summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2021-01-20 13:34:23 -0600
committerRobert Speicher <rspeicher@gmail.com>2021-01-20 13:34:23 -0600
commit6438df3a1e0fb944485cebf07976160184697d72 (patch)
tree00b09bfd170e77ae9391b1a2f5a93ef6839f2597
parent42bcd54d971da7ef2854b896a7b34f4ef8601067 (diff)
downloadgitlab-ce-13.8.0-rc42.tar.gz
Add latest changes from gitlab-org/gitlab@13-8-stable-eev13.8.0-rc42
-rw-r--r--.eslintrc.yml12
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--.gitlab/CODEOWNERS14
-rw-r--r--.gitlab/ci/dev-fixtures.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml15
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml3
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/graphql.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/pages.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml119
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml104
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml8
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml30
-rw-r--r--.gitlab/issue_templates/Acceptance Testing.md2
-rw-r--r--.gitlab/issue_templates/Design Sprint.md203
-rw-r--r--.gitlab/issue_templates/Feature proposal.md9
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md1
-rw-r--r--.gitlab/merge_request_templates/New End To End Test.md1
-rw-r--r--.haml-lint_todo.yml1
-rw-r--r--.prettierrc1
-rw-r--r--.rubocop.yml13
-rw-r--r--.rubocop_manual_todo.yml316
-rw-r--r--.rubocop_todo.yml396
-rw-r--r--CHANGELOG.md40
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile53
-rw-r--r--Gemfile.lock339
-rw-r--r--Guardfile4
-rw-r--r--app/assets/images/board-intro.svg1
-rw-r--r--app/assets/javascripts/access_tokens/index.js2
-rw-r--r--app/assets/javascripts/activities.js6
-rw-r--r--app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue10
-rw-r--r--app/assets/javascripts/add_context_commits_modal/store/actions.js14
-rw-r--r--app/assets/javascripts/add_context_commits_modal/utils.js2
-rw-r--r--app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js2
-rw-r--r--app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue2
-rw-r--r--app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue2
-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/statistics_panel/store/getters.js4
-rw-r--r--app/assets/javascripts/admin/users/components/user_avatar.vue53
-rw-r--r--app/assets/javascripts/admin/users/components/users_table.vue10
-rw-r--r--app/assets/javascripts/admin/users/constants.js1
-rw-r--r--app/assets/javascripts/admin/users/index.js4
-rw-r--r--app/assets/javascripts/alert_handler.js4
-rw-r--r--app/assets/javascripts/alert_management/components/alert_details.vue26
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_empty_state.vue52
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue6
-rw-r--r--app/assets/javascripts/alert_management/components/alert_metrics.vue2
-rw-r--r--app/assets/javascripts/alert_management/components/alert_status.vue4
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue4
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue2
-rw-r--r--app/assets/javascripts/alert_management/details.js12
-rw-r--r--app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql4
-rw-r--r--app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql2
-rw-r--r--app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.mutation.graphql17
-rw-r--r--app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql36
-rw-r--r--app/assets/javascripts/alert_management/list.js12
-rw-r--r--app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue16
-rw-r--r--app/assets/javascripts/alerts_service_settings/index.js2
-rw-r--r--app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue22
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue4
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue140
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue41
-rw-r--r--app/assets/javascripts/alerts_settings/constants.js10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql.js2
-rw-r--r--app/assets/javascripts/alerts_settings/index.js18
-rw-r--r--app/assets/javascripts/alerts_settings/utils/cache_updates.js4
-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.vue8
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue4
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/utils.js2
-rw-r--r--app/assets/javascripts/analytics/product_analytics/activity_charts_bundle.js8
-rw-r--r--app/assets/javascripts/api.js87
-rw-r--r--app/assets/javascripts/api/api_utils.js5
-rw-r--r--app/assets/javascripts/api/constants.js1
-rw-r--r--app/assets/javascripts/api/groups_api.js22
-rw-r--r--app/assets/javascripts/api/projects_api.js27
-rw-r--r--app/assets/javascripts/api/user_api.js66
-rw-r--r--app/assets/javascripts/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql5
-rw-r--r--app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql7
-rw-r--r--app/assets/javascripts/artifacts_settings/index.js32
-rw-r--r--app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue99
-rw-r--r--app/assets/javascripts/authentication/u2f/authenticate.js6
-rw-r--r--app/assets/javascripts/authentication/u2f/register.js4
-rw-r--r--app/assets/javascripts/authentication/webauthn/authenticate.js4
-rw-r--r--app/assets/javascripts/authentication/webauthn/register.js4
-rw-r--r--app/assets/javascripts/awards_handler.js45
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue20
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue2
-rw-r--r--app/assets/javascripts/badges/store/actions.js20
-rw-r--r--app/assets/javascripts/badges/store/mutations.js10
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue6
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js20
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js20
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js14
-rw-r--r--app/assets/javascripts/batch_comments/utils.js4
-rw-r--r--app/assets/javascripts/behaviors/autosize.js2
-rw-r--r--app/assets/javascripts/behaviors/bind_in_out.js2
-rw-r--r--app/assets/javascripts/behaviors/copy_to_clipboard.js2
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js2
-rw-r--r--app/assets/javascripts/behaviors/load_startup_css.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/copy_as_gfm.js12
-rw-r--r--app/assets/javascripts/behaviors/markdown/highlight_current_user.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/inline_diff.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/inline_html.js6
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/code_block.js6
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/emoji.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/image.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/playable.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/reference.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_cell.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/paste_markdown_table.js13
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_math.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js8
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_metrics.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/schema.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/serializer.js4
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js40
-rw-r--r--app/assets/javascripts/behaviors/quick_submit.js2
-rw-r--r--app/assets/javascripts/behaviors/requires_input.js2
-rw-r--r--app/assets/javascripts/behaviors/secret_values.js4
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/keybindings.js8
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js8
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js2
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js4
-rw-r--r--app/assets/javascripts/blob/3d_viewer/index.js4
-rw-r--r--app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js4
-rw-r--r--app/assets/javascripts/blob/blob_file_dropzone.js14
-rw-r--r--app/assets/javascripts/blob/blob_line_permalink_updater.js6
-rw-r--r--app/assets/javascripts/blob/components/blob_content_error.vue2
-rw-r--r--app/assets/javascripts/blob/components/blob_header_default_actions.vue5
-rw-r--r--app/assets/javascripts/blob/file_template_mediator.js45
-rw-r--r--app/assets/javascripts/blob/notebook/notebook_viewer.vue6
-rw-r--r--app/assets/javascripts/blob/openapi/index.js2
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue6
-rw-r--r--app/assets/javascripts/blob/sketch/index.js6
-rw-r--r--app/assets/javascripts/blob/stl_viewer.js4
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js2
-rw-r--r--app/assets/javascripts/blob/template_selector.js8
-rw-r--r--app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js29
-rw-r--r--app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/dockerfile_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/gitignore_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/license_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/type_selector.js4
-rw-r--r--app/assets/javascripts/blob/viewer/index.js10
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js2
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js8
-rw-r--r--app/assets/javascripts/boards/boards_util.js50
-rw-r--r--app/assets/javascripts/boards/components/board_assignee_dropdown.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_card_layout.vue20
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue81
-rw-r--r--app/assets/javascripts/boards/components/board_column_deprecated.vue105
-rw-r--r--app/assets/javascripts/boards/components/board_column_new.vue82
-rw-r--r--app/assets/javascripts/boards/components/board_configuration_options.vue35
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue27
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue149
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue480
-rw-r--r--app/assets/javascripts/boards/components/board_list_deprecated.vue443
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue159
-rw-r--r--app/assets/javascripts/boards/components/board_list_header_deprecated.vue340
-rw-r--r--app/assets/javascripts/boards/components/board_list_header_new.vue359
-rw-r--r--app/assets/javascripts/boards/components/board_list_new.vue239
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue84
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue_deprecated.vue136
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue_new.vue129
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js6
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue6
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue50
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue245
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue28
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue48
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.vue6
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue14
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js2
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue193
-rw-r--r--app/assets/javascripts/boards/components/project_select_deprecated.vue145
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_editable_item.vue39
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue6
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue171
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue12
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue18
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue2
-rw-r--r--app/assets/javascripts/boards/components/sidebar/remove_issue.vue10
-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/board.mutation.graphql11
-rw-r--r--app/assets/javascripts/boards/graphql/board_create.mutation.graphql9
-rw-r--r--app/assets/javascripts/boards/graphql/board_destroy.mutation.graphql7
-rw-r--r--app/assets/javascripts/boards/graphql/board_update.mutation.graphql9
-rw-r--r--app/assets/javascripts/boards/graphql/group_projects.query.graphql17
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql8
-rw-r--r--app/assets/javascripts/boards/index.js46
-rw-r--r--app/assets/javascripts/boards/mixins/sortable_default_options.js2
-rw-r--r--app/assets/javascripts/boards/models/issue.js2
-rw-r--r--app/assets/javascripts/boards/models/list.js4
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js9
-rw-r--r--app/assets/javascripts/boards/stores/actions.js103
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js145
-rw-r--r--app/assets/javascripts/boards/stores/getters.js18
-rw-r--r--app/assets/javascripts/boards/stores/modal_store.js10
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js4
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js40
-rw-r--r--app/assets/javascripts/boards/stores/state.js8
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js2
-rw-r--r--app/assets/javascripts/breadcrumb.js12
-rw-r--r--app/assets/javascripts/broadcast_notification.js2
-rw-r--r--app/assets/javascripts/build_artifacts.js10
-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.vue10
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/index.js2
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js21
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue2
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue2
-rw-r--r--app/assets/javascripts/ci_variable_list/store/actions.js8
-rw-r--r--app/assets/javascripts/ci_variable_list/store/getters.js4
-rw-r--r--app/assets/javascripts/ci_variable_list/store/utils.js8
-rw-r--r--app/assets/javascripts/clone_panel.js2
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js28
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue2
-rw-r--r--app/assets/javascripts/clusters/components/fluentd_output_settings.vue2
-rw-r--r--app/assets/javascripts/clusters/forms/stores/index.js2
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js6
-rw-r--r--app/assets/javascripts/clusters/stores/new_cluster/index.js2
-rw-r--r--app/assets/javascripts/clusters_list/components/ancestor_notice.vue35
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue12
-rw-r--r--app/assets/javascripts/clusters_list/load_clusters.js2
-rw-r--r--app/assets/javascripts/clusters_list/store/actions.js8
-rw-r--r--app/assets/javascripts/clusters_list/store/index.js2
-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/utils/index.js4
-rw-r--r--app/assets/javascripts/commit/image_file.js20
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js2
-rw-r--r--app/assets/javascripts/commit_merge_requests.js4
-rw-r--r--app/assets/javascripts/commits.js5
-rw-r--r--app/assets/javascripts/commons/bootstrap.js8
-rw-r--r--app/assets/javascripts/commons/nav/user_merge_requests.js32
-rw-r--r--app/assets/javascripts/compare_autocomplete.js10
-rw-r--r--app/assets/javascripts/confidential_merge_request/components/project_form_group.vue4
-rw-r--r--app/assets/javascripts/confirm_danger_modal.js2
-rw-r--r--app/assets/javascripts/confirm_modal.js2
-rw-r--r--app/assets/javascripts/contextual_sidebar.js5
-rw-r--r--app/assets/javascripts/contributors/components/contributors.vue12
-rw-r--r--app/assets/javascripts/contributors/stores/actions.js4
-rw-r--r--app/assets/javascripts/contributors/stores/getters.js4
-rw-r--r--app/assets/javascripts/contributors/utils.js4
-rw-r--r--app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue8
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/index.js2
-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.js4
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/state.js2
-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_machine_type_dropdown.vue4
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue10
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue4
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js24
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/index.js18
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/store/actions.js89
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/store/getters.js6
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster_namespace/index.js2
-rw-r--r--app/assets/javascripts/create_cluster/init_create_cluster.js14
-rw-r--r--app/assets/javascripts/create_cluster/store/cluster_dropdown/actions.js6
-rw-r--r--app/assets/javascripts/create_item_dropdown.js4
-rw-r--r--app/assets/javascripts/create_label.js18
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js8
-rw-r--r--app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue6
-rw-r--r--app/assets/javascripts/custom_metrics/constants.js4
-rw-r--r--app/assets/javascripts/cycle_analytics/components/total_time_component.vue4
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js6
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_service.js4
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_store.js10
-rw-r--r--app/assets/javascripts/deploy_freeze/store/actions.js2
-rw-r--r--app/assets/javascripts/deploy_freeze/store/index.js2
-rw-r--r--app/assets/javascripts/deploy_freeze/store/mutations.js4
-rw-r--r--app/assets/javascripts/deploy_keys/components/app.vue4
-rw-r--r--app/assets/javascripts/deploy_keys/components/key.vue2
-rw-r--r--app/assets/javascripts/deploy_keys/service/index.js6
-rw-r--r--app/assets/javascripts/deploy_keys/store/index.js2
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js43
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js17
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js16
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js2
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/index.js2
-rw-r--r--app/assets/javascripts/design_management/components/design_destroyer.vue19
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue6
-rw-r--r--app/assets/javascripts/design_management/components/design_presentation.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue20
-rw-r--r--app/assets/javascripts/design_management/components/design_todo_button.vue23
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/design_navigation.vue2
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/index.vue18
-rw-r--r--app/assets/javascripts/design_management/components/upload/design_version_dropdown.vue2
-rw-r--r--app/assets/javascripts/design_management/graphql.js4
-rw-r--r--app/assets/javascripts/design_management/mixins/all_designs.js2
-rw-r--r--app/assets/javascripts/design_management/mixins/all_versions.js4
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue62
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue27
-rw-r--r--app/assets/javascripts/design_management/router/routes.js8
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js28
-rw-r--r--app/assets/javascripts/design_management/utils/design_management_utils.js36
-rw-r--r--app/assets/javascripts/design_management/utils/error_messages.js4
-rw-r--r--app/assets/javascripts/diff.js8
-rw-r--r--app/assets/javascripts/diffs/components/app.vue74
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue11
-rw-r--r--app/assets/javascripts/diffs/components/compare_dropdown_layout.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue27
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue9
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue11
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue268
-rw-r--r--app/assets/javascripts/diffs/components/diff_row_utils.js26
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue39
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue7
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue6
-rw-r--r--app/assets/javascripts/diffs/components/no_changes.vue42
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue30
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue8
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue2
-rw-r--r--app/assets/javascripts/diffs/constants.js6
-rw-r--r--app/assets/javascripts/diffs/index.js11
-rw-r--r--app/assets/javascripts/diffs/store/actions.js65
-rw-r--r--app/assets/javascripts/diffs/store/getters.js68
-rw-r--r--app/assets/javascripts/diffs/store/getters_versions_dropdowns.js28
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js2
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js2
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js57
-rw-r--r--app/assets/javascripts/diffs/store/utils.js97
-rw-r--r--app/assets/javascripts/diffs/utils/diff_file.js15
-rw-r--r--app/assets/javascripts/diffs/utils/file_reviews.js61
-rw-r--r--app/assets/javascripts/diffs/utils/merge_request.js20
-rw-r--r--app/assets/javascripts/diffs/utils/uuids.js4
-rw-r--r--app/assets/javascripts/diffs/workers/tree_worker.js2
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_collection.js2
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_form.js8
-rw-r--r--app/assets/javascripts/droplab/drop_down.js4
-rw-r--r--app/assets/javascripts/droplab/drop_lab.js10
-rw-r--r--app/assets/javascripts/droplab/hook_button.js4
-rw-r--r--app/assets/javascripts/droplab/hook_input.js4
-rw-r--r--app/assets/javascripts/droplab/keyboard.js2
-rw-r--r--app/assets/javascripts/droplab/plugins/ajax.js4
-rw-r--r--app/assets/javascripts/droplab/plugins/ajax_filter.js8
-rw-r--r--app/assets/javascripts/droplab/plugins/filter.js10
-rw-r--r--app/assets/javascripts/droplab/plugins/input_setter.js2
-rw-r--r--app/assets/javascripts/droplab/utils.js7
-rw-r--r--app/assets/javascripts/dropzone_input.js36
-rw-r--r--app/assets/javascripts/due_date_select.js20
-rw-r--r--app/assets/javascripts/editor/constants.js9
-rw-r--r--app/assets/javascripts/editor/editor_lite.js28
-rw-r--r--app/assets/javascripts/editor/editor_lite_extension_base.js11
-rw-r--r--app/assets/javascripts/editor/editor_markdown_ext.js97
-rw-r--r--app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js38
-rw-r--r--app/assets/javascripts/editor/extensions/editor_file_template_ext.js (renamed from app/assets/javascripts/editor/editor_file_template_ext.js)0
-rw-r--r--app/assets/javascripts/editor/extensions/editor_lite_extension_base.js11
-rw-r--r--app/assets/javascripts/editor/extensions/editor_markdown_ext.js97
-rw-r--r--app/assets/javascripts/editor/utils.js2
-rw-r--r--app/assets/javascripts/emoji/index.js27
-rw-r--r--app/assets/javascripts/emoji/no_emoji_validator.js2
-rw-r--r--app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js4
-rw-r--r--app/assets/javascripts/emoji/support/unicode_support_map.js8
-rw-r--r--app/assets/javascripts/environments/components/canary_ingress.vue109
-rw-r--r--app/assets/javascripts/environments/components/canary_update_modal.vue133
-rw-r--r--app/assets/javascripts/environments/components/container.vue12
-rw-r--r--app/assets/javascripts/environments/components/deploy_board.vue216
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue2
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue16
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue40
-rw-r--r--app/assets/javascripts/environments/constants.js40
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js3
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue12
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql5
-rw-r--r--app/assets/javascripts/environments/index.js3
-rw-r--r--app/assets/javascripts/environments/mixins/canary_callout_mixin.js26
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js10
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js26
-rw-r--r--app/assets/javascripts/environments/stores/helpers.js21
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue4
-rw-r--r--app/assets/javascripts/error_tracking/components/stacktrace_entry.vue4
-rw-r--r--app/assets/javascripts/error_tracking/store/actions.js2
-rw-r--r--app/assets/javascripts/error_tracking/store/details/actions.js2
-rw-r--r--app/assets/javascripts/error_tracking/store/details/getters.js2
-rw-r--r--app/assets/javascripts/error_tracking/store/list/mutations.js4
-rw-r--r--app/assets/javascripts/error_tracking/utils.js4
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/actions.js2
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/getters.js8
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/mutations.js2
-rw-r--r--app/assets/javascripts/error_tracking_settings/utils.js2
-rw-r--r--app/assets/javascripts/experimental_flags.js2
-rw-r--r--app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue14
-rw-r--r--app/assets/javascripts/feature_flags/components/edit_feature_flag.vue26
-rw-r--r--app/assets/javascripts/feature_flags/components/environments_dropdown.vue17
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags_tab.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags_table.vue33
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue40
-rw-r--r--app/assets/javascripts/feature_flags/components/new_feature_flag.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy.vue8
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy_parameters.vue2
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/actions.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/index.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/helpers.js34
-rw-r--r--app/assets/javascripts/feature_flags/store/index/actions.js6
-rw-r--r--app/assets/javascripts/feature_flags/store/index/index.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/index/mutations.js11
-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_flags/utils.js2
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight.js2
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_helper.js2
-rw-r--r--app/assets/javascripts/file_pickers.js2
-rw-r--r--app/assets/javascripts/files_comment_button.js4
-rw-r--r--app/assets/javascripts/filterable_list.js2
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js11
-rw-r--r--app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue6
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_ajax_filter.js2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js4
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_utils.js12
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown.js6
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js28
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js21
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js9
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js2
-rw-r--r--app/assets/javascripts/filtered_search/stores/recent_searches_store.js2
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js10
-rw-r--r--app/assets/javascripts/flash.js10
-rw-r--r--app/assets/javascripts/fly_out_nav.js22
-rw-r--r--app/assets/javascripts/frequent_items/components/app.vue2
-rw-r--r--app/assets/javascripts/frequent_items/index.js2
-rw-r--r--app/assets/javascripts/frequent_items/store/actions.js10
-rw-r--r--app/assets/javascripts/frequent_items/store/getters.js2
-rw-r--r--app/assets/javascripts/frequent_items/store/mutations.js2
-rw-r--r--app/assets/javascripts/frequent_items/utils.js8
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js51
-rw-r--r--app/assets/javascripts/gl_field_errors.js8
-rw-r--r--app/assets/javascripts/gl_form.js11
-rw-r--r--app/assets/javascripts/gpg_badges.js2
-rw-r--r--app/assets/javascripts/grafana_integration/store/actions.js2
-rw-r--r--app/assets/javascripts/grafana_integration/store/index.js2
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql (renamed from app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql)0
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql (renamed from app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql)0
-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.graphql36
-rw-r--r--app/assets/javascripts/graphql_shared/utils.js2
-rw-r--r--app/assets/javascripts/group.js14
-rw-r--r--app/assets/javascripts/group_settings/components/shared_runners_form.vue2
-rw-r--r--app/assets/javascripts/groups/components/app.vue20
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue2
-rw-r--r--app/assets/javascripts/groups/components/visibility_level_dropdown.vue2
-rw-r--r--app/assets/javascripts/groups/groups_filterable_list.js5
-rw-r--r--app/assets/javascripts/groups/init_invite_members_banner.js2
-rw-r--r--app/assets/javascripts/groups/members/components/app.vue4
-rw-r--r--app/assets/javascripts/groups/members/index.js2
-rw-r--r--app/assets/javascripts/groups/members/utils.js2
-rw-r--r--app/assets/javascripts/groups/store/groups_store.js12
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js6
-rw-r--r--app/assets/javascripts/groups_select.js6
-rw-r--r--app/assets/javascripts/helpers/event_hub_factory.js4
-rw-r--r--app/assets/javascripts/helpers/help_page_helper.js21
-rw-r--r--app/assets/javascripts/helpers/monitor_helper.js4
-rw-r--r--app/assets/javascripts/helpers/startup_css_helper.js6
-rw-r--r--app/assets/javascripts/ide/commit_icon.js2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue1
-rw-r--r--app/assets/javascripts/ide/components/file_templates/bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/file_templates/dropdown.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_sidebar_nav.vue2
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown.vue4
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue14
-rw-r--r--app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue6
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue42
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue2
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue19
-rw-r--r--app/assets/javascripts/ide/constants.js3
-rw-r--r--app/assets/javascripts/ide/ide_router.js10
-rw-r--r--app/assets/javascripts/ide/index.js4
-rw-r--r--app/assets/javascripts/ide/lib/common/disposable.js4
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js4
-rw-r--r--app/assets/javascripts/ide/lib/create_diff.js16
-rw-r--r--app/assets/javascripts/ide/lib/create_file_diff.js10
-rw-r--r--app/assets/javascripts/ide/lib/decorations/controller.js2
-rw-r--r--app/assets/javascripts/ide/lib/diff/controller.js6
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff.js2
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff_worker.js2
-rw-r--r--app/assets/javascripts/ide/lib/editor.js12
-rw-r--r--app/assets/javascripts/ide/lib/editor_options.js4
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/parser.js13
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js12
-rw-r--r--app/assets/javascripts/ide/lib/errors.js14
-rw-r--r--app/assets/javascripts/ide/lib/files.js21
-rw-r--r--app/assets/javascripts/ide/lib/languages/hcl.js14
-rw-r--r--app/assets/javascripts/ide/lib/languages/vue.js8
-rw-r--r--app/assets/javascripts/ide/lib/mirror.js26
-rw-r--r--app/assets/javascripts/ide/services/index.js11
-rw-r--r--app/assets/javascripts/ide/services/terminals.js2
-rw-r--r--app/assets/javascripts/ide/stores/actions.js17
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js47
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js18
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js15
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js4
-rw-r--r--app/assets/javascripts/ide/stores/extend.js2
-rw-r--r--app/assets/javascripts/ide/stores/getters.js66
-rw-r--r--app/assets/javascripts/ide/stores/modules/branches/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/branches/mutations.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js41
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/getters.js10
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/setup.js15
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/getters.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/getters.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutations.js10
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/utils.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js4
-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.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/getters.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/messages.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/utils.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js12
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js46
-rw-r--r--app/assets/javascripts/ide/stores/mutations/tree.js2
-rw-r--r--app/assets/javascripts/ide/stores/plugins/terminal.js2
-rw-r--r--app/assets/javascripts/ide/stores/plugins/terminal_sync.js20
-rw-r--r--app/assets/javascripts/ide/stores/utils.js34
-rw-r--r--app/assets/javascripts/ide/sync_router_and_store.js8
-rw-r--r--app/assets/javascripts/ide/utils.js33
-rw-r--r--app/assets/javascripts/image_diff/helpers/badge_helper.js2
-rw-r--r--app/assets/javascripts/image_diff/init_discussion_tab.js2
-rw-r--r--app/assets/javascripts/image_diff/replaced_image_diff.js4
-rw-r--r--app/assets/javascripts/image_diff/view_types.js2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js8
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js6
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue19
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/actions.js14
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/getters.js24
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/mutations.js22
-rw-r--r--app/assets/javascripts/import_entities/import_projects/utils.js6
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue4
-rw-r--r--app/assets/javascripts/incidents/list.js6
-rw-r--r--app/assets/javascripts/init_changes_dropdown.js2
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue5
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue4
-rw-r--r--app/assets/javascripts/integrations/edit/components/override_dropdown.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/store/getters.js4
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js7
-rw-r--r--app/assets/javascripts/invite_member/init_invite_member_modal.js2
-rw-r--r--app/assets/javascripts/invite_member/init_invite_member_trigger.js2
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue59
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue7
-rw-r--r--app/assets/javascripts/invite_members/components/members_token_select.vue37
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js4
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_trigger.js2
-rw-r--r--app/assets/javascripts/issuable/auto_width_dropdown_select.js5
-rw-r--r--app/assets/javascripts/issuable_bulk_update_actions.js4
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar.js8
-rw-r--r--app/assets/javascripts/issuable_context.js2
-rw-r--r--app/assets/javascripts/issuable_form.js20
-rw-r--r--app/assets/javascripts/issuable_index.js6
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue2
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_edit_form.vue3
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/app.vue2
-rw-r--r--app/assets/javascripts/issuable_suggestions/index.js2
-rw-r--r--app/assets/javascripts/issue.js10
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue18
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue10
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue12
-rw-r--r--app/assets/javascripts/issue_show/incident.js17
-rw-r--r--app/assets/javascripts/issue_show/issue.js2
-rw-r--r--app/assets/javascripts/issue_show/utils/parse_data.js2
-rw-r--r--app/assets/javascripts/issues_list/components/issuable.vue4
-rw-r--r--app/assets/javascripts/issues_list/components/issuables_list_app.vue8
-rw-r--r--app/assets/javascripts/issues_list/index.js2
-rw-r--r--app/assets/javascripts/jira_connect/api.js33
-rw-r--r--app/assets/javascripts/jira_connect/components/app.vue57
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list.vue88
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list_item.vue42
-rw-r--r--app/assets/javascripts/jira_connect/constants.js1
-rw-r--r--app/assets/javascripts/jira_connect/index.js97
-rw-r--r--app/assets/javascripts/jira_connect/store/index.js9
-rw-r--r--app/assets/javascripts/jira_connect/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/jira_connect/store/mutations.js7
-rw-r--r--app/assets/javascripts/jira_connect/store/state.js3
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_form.vue4
-rw-r--r--app/assets/javascripts/jira_import/utils/cache_update.js2
-rw-r--r--app/assets/javascripts/jira_import/utils/jira_import_utils.js14
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue10
-rw-r--r--app/assets/javascripts/jobs/components/log/line.vue4
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue5
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue5
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue2
-rw-r--r--app/assets/javascripts/jobs/store/actions.js8
-rw-r--r--app/assets/javascripts/jobs/store/getters.js24
-rw-r--r--app/assets/javascripts/jobs/store/utils.js4
-rw-r--r--app/assets/javascripts/label_manager.js2
-rw-r--r--app/assets/javascripts/labels_select.js35
-rw-r--r--app/assets/javascripts/lazy_loader.js10
-rw-r--r--app/assets/javascripts/lib/chrome_84_icon_fix.js4
-rw-r--r--app/assets/javascripts/lib/dompurify.js8
-rw-r--r--app/assets/javascripts/lib/graphql.js4
-rw-r--r--app/assets/javascripts/lib/utils/ajax_cache.js2
-rw-r--r--app/assets/javascripts/lib/utils/apollo_startup_js_link.js16
-rw-r--r--app/assets/javascripts/lib/utils/autosave.js4
-rw-r--r--app/assets/javascripts/lib/utils/axios_startup_calls.js8
-rw-r--r--app/assets/javascripts/lib/utils/axios_utils.js10
-rw-r--r--app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js2
-rw-r--r--app/assets/javascripts/lib/utils/chart_utils.js4
-rw-r--r--app/assets/javascripts/lib/utils/color_utils.js4
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js168
-rw-r--r--app/assets/javascripts/lib/utils/css_utils.js2
-rw-r--r--app/assets/javascripts/lib/utils/datetime_range.js18
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js129
-rw-r--r--app/assets/javascripts/lib/utils/dom_utils.js6
-rw-r--r--app/assets/javascripts/lib/utils/favicon.js30
-rw-r--r--app/assets/javascripts/lib/utils/favicon_ci.js16
-rw-r--r--app/assets/javascripts/lib/utils/forms.js12
-rw-r--r--app/assets/javascripts/lib/utils/grammar.js6
-rw-r--r--app/assets/javascripts/lib/utils/headers.js3
-rw-r--r--app/assets/javascripts/lib/utils/icon_utils.js6
-rw-r--r--app/assets/javascripts/lib/utils/notify.js2
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js2
-rw-r--r--app/assets/javascripts/lib/utils/poll.js4
-rw-r--r--app/assets/javascripts/lib/utils/poll_until_complete.js2
-rw-r--r--app/assets/javascripts/lib/utils/set.js2
-rw-r--r--app/assets/javascripts/lib/utils/simple_poll.js2
-rw-r--r--app/assets/javascripts/lib/utils/sticky.js2
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js16
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js28
-rw-r--r--app/assets/javascripts/lib/utils/type_utility.js2
-rw-r--r--app/assets/javascripts/lib/utils/unit_format/formatter_factory.js4
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js16
-rw-r--r--app/assets/javascripts/lib/utils/users_cache.js8
-rw-r--r--app/assets/javascripts/line_highlighter.js42
-rw-r--r--app/assets/javascripts/locale/ensure_single_line.js2
-rw-r--r--app/assets/javascripts/locale/index.js4
-rw-r--r--app/assets/javascripts/locale/sprintf.js2
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue8
-rw-r--r--app/assets/javascripts/logs/components/log_advanced_filters.vue2
-rw-r--r--app/assets/javascripts/logs/logs_tracking_helper.js2
-rw-r--r--app/assets/javascripts/logs/stores/actions.js8
-rw-r--r--app/assets/javascripts/logs/stores/getters.js4
-rw-r--r--app/assets/javascripts/logs/utils.js2
-rw-r--r--app/assets/javascripts/main.js22
-rw-r--r--app/assets/javascripts/manual_ordering.js2
-rw-r--r--app/assets/javascripts/member_expiration_date.js8
-rw-r--r--app/assets/javascripts/members.js10
-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/invite_action_buttons.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue4
-rw-r--r--app/assets/javascripts/members/components/avatars/user_avatar.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.vue24
-rw-r--r--app/assets/javascripts/members/components/modals/leave_modal.vue4
-rw-r--r--app/assets/javascripts/members/components/table/member_source.vue2
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue43
-rw-r--r--app/assets/javascripts/members/constants.js2
-rw-r--r--app/assets/javascripts/members/store/index.js2
-rw-r--r--app/assets/javascripts/members/store/utils.js3
-rw-r--r--app/assets/javascripts/members/utils.js12
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.js33
-rw-r--r--app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js2
-rw-r--r--app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js2
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_store.js28
-rw-r--r--app/assets/javascripts/merge_request.js34
-rw-r--r--app/assets/javascripts/merge_request/components/status_box.vue69
-rw-r--r--app/assets/javascripts/merge_request/eventhub.js3
-rw-r--r--app/assets/javascripts/merge_request_tabs.js18
-rw-r--r--app/assets/javascripts/milestone.js2
-rw-r--r--app/assets/javascripts/milestone_select.js14
-rw-r--r--app/assets/javascripts/milestones/components/milestone_combobox.vue2
-rw-r--r--app/assets/javascripts/milestones/stores/actions.js16
-rw-r--r--app/assets/javascripts/milestones/stores/mutations.js2
-rw-r--r--app/assets/javascripts/mini_pipeline_graph_dropdown.js8
-rw-r--r--app/assets/javascripts/mirrors/mirror_repos.js2
-rw-r--r--app/assets/javascripts/mirrors/ssh_mirror.js12
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget.vue26
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget_form.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/annotations.js4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/anomaly.vue23
-rw-r--r--app/assets/javascripts/monitoring/components/charts/bar.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/column.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/heatmap.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/options.js12
-rw-r--r--app/assets/javascripts/monitoring/components/charts/stacked_column.vue10
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue8
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue12
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue10
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/embed_group.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/metric_embed.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/empty_state.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/variables/dropdown_field.vue2
-rw-r--r--app/assets/javascripts/monitoring/csv_export.js14
-rw-r--r--app/assets/javascripts/monitoring/requests/index.js14
-rw-r--r--app/assets/javascripts/monitoring/services/alerts_service.js10
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js54
-rw-r--r--app/assets/javascripts/monitoring/stores/embed_group/getters.js2
-rw-r--r--app/assets/javascripts/monitoring/stores/getters.js38
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js16
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js28
-rw-r--r--app/assets/javascripts/monitoring/stores/variable_mapping.js18
-rw-r--r--app/assets/javascripts/monitoring/utils.js24
-rw-r--r--app/assets/javascripts/monitoring/validators.js6
-rw-r--r--app/assets/javascripts/mr_notes/init_notes.js2
-rw-r--r--app/assets/javascripts/mr_notes/stores/getters.js2
-rw-r--r--app/assets/javascripts/mr_popover/components/mr_popover.vue2
-rw-r--r--app/assets/javascripts/mr_popover/index.js4
-rw-r--r--app/assets/javascripts/namespace_select.js2
-rw-r--r--app/assets/javascripts/network/branch_graph.js8
-rw-r--r--app/assets/javascripts/new_branch_form.js6
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue4
-rw-r--r--app/assets/javascripts/notebook/cells/output/index.vue5
-rw-r--r--app/assets/javascripts/notebook/cells/output/latex.vue45
-rw-r--r--app/assets/javascripts/notes.js68
-rw-r--r--app/assets/javascripts/notes/components/comment_field_layout.vue69
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue81
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_actions.vue19
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue6
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue38
-rw-r--r--app/assets/javascripts/notes/components/email_participants_warning.vue70
-rw-r--r--app/assets/javascripts/notes/components/multiline_comment_form.vue7
-rw-r--r--app/assets/javascripts/notes/components/multiline_comment_utils.js10
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue4
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue16
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue96
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue4
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue2
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue4
-rw-r--r--app/assets/javascripts/notes/components/timeline_toggle.vue1
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue4
-rw-r--r--app/assets/javascripts/notes/discussion_filters.js4
-rw-r--r--app/assets/javascripts/notes/mixins/diff_line_note_form.js6
-rw-r--r--app/assets/javascripts/notes/mixins/discussion_navigation.js2
-rw-r--r--app/assets/javascripts/notes/mixins/issuable_state.js11
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js2
-rw-r--r--app/assets/javascripts/notes/sort_discussions.js2
-rw-r--r--app/assets/javascripts/notes/stores/actions.js41
-rw-r--r--app/assets/javascripts/notes/stores/collapse_utils.js4
-rw-r--r--app/assets/javascripts/notes/stores/getters.js96
-rw-r--r--app/assets/javascripts/notes/stores/modules/index.js2
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js24
-rw-r--r--app/assets/javascripts/notes/stores/utils.js14
-rw-r--r--app/assets/javascripts/notes/utils.js2
-rw-r--r--app/assets/javascripts/notifications_dropdown.js10
-rw-r--r--app/assets/javascripts/onboarding_issues/index.js4
-rw-r--r--app/assets/javascripts/operation_settings/store/actions.js2
-rw-r--r--app/assets/javascripts/operation_settings/store/index.js2
-rw-r--r--app/assets/javascripts/packages/details/components/package_files.vue8
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list.vue8
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue14
-rw-r--r--app/assets/javascripts/packages/list/components/packages_sort.vue8
-rw-r--r--app/assets/javascripts/packages/list/stores/getters.js4
-rw-r--r--app/assets/javascripts/packages/list/utils.js3
-rw-r--r--app/assets/javascripts/packages/shared/components/package_tags.vue2
-rw-r--r--app/assets/javascripts/packages/shared/utils.js6
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/bundle.js20
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue9
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js14
-rw-r--r--app/assets/javascripts/pages/admin/admin.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.js2
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue4
-rw-r--r--app/assets/javascripts/pages/admin/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/users/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/users/new/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue2
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js2
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js1
-rw-r--r--app/assets/javascripts/pages/groups/new/group_path_validator.js6
-rw-r--r--app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/shared/group_tabs.js4
-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.vue99
-rw-r--r--app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js4
-rw-r--r--app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js85
-rw-r--r--app/assets/javascripts/pages/profiles/index.js2
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/edit/mount_search_settings.js12
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue6
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue6
-rw-r--r--app/assets/javascripts/pages/projects/init_form.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js4
-rw-r--r--app/assets/javascripts/pages/projects/jobs/index/index.js4
-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/labels/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js12
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js17
-rw-r--r--app/assets/javascripts/pages/projects/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pages_domains/form.js6
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js6
-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/target_branch_dropdown.js8
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js12
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/charts/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/init_pipelines.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/new/index.js22
-rw-r--r--app/assets/javascripts/pages/projects/project.js30
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue6
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue97
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/external.js2
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/tags/index/index.js7
-rw-r--r--app/assets/javascripts/pages/search/show/refresh_counts.js2
-rw-r--r--app/assets/javascripts/pages/search/show/search.js13
-rw-r--r--app/assets/javascripts/pages/sessions/new/length_validator.js2
-rw-r--r--app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js4
-rw-r--r--app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js2
-rw-r--r--app/assets/javascripts/pages/sessions/new/username_validator.js6
-rw-r--r--app/assets/javascripts/pages/shared/mount_badge_settings.js2
-rw-r--r--app/assets/javascripts/pages/shared/wikis/wikis.js34
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js29
-rw-r--r--app/assets/javascripts/pages/users/index.js6
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js20
-rw-r--r--app/assets/javascripts/pdf/index.vue4
-rw-r--r--app/assets/javascripts/pdf/page/index.vue2
-rw-r--r--app/assets/javascripts/performance/utils.js2
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue6
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue2
-rw-r--r--app/assets/javascripts/performance_bar/index.js29
-rw-r--r--app/assets/javascripts/performance_bar/performance_bar_log.js6
-rw-r--r--app/assets/javascripts/performance_bar/services/performance_bar_service.js2
-rw-r--r--app/assets/javascripts/performance_bar/stores/performance_bar_store.js6
-rw-r--r--app/assets/javascripts/persistent_user_callout.js6
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js2
-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.vue53
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue18
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue40
-rw-r--r--app/assets/javascripts/pipeline_editor/components/text_editor.vue34
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue68
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql2
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql2
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql6
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js4
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js25
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue164
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue29
-rw-r--r--app/assets/javascripts/pipeline_new/utils/format_refs.js2
-rw-r--r--app/assets/javascripts/pipelines.js2
-rw-r--r--app/assets/javascripts/pipelines/components/dag/dag.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/dag/dag_graph.vue18
-rw-r--r--app/assets/javascripts/pipelines/components/dag/drawing_utils.js4
-rw-r--r--app/assets/javascripts/pipelines/components/dag/interactions.js28
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue78
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue16
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue15
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue41
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/utils.js12
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js97
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue140
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue86
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/main_graph_wrapper.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/parsing_utils.js24
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/drawing_utils.js96
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue114
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue54
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue68
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue52
-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_row.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/stage.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/unwrapping_utils.js33
-rw-r--r--app/assets/javascripts/pipelines/graphql/fragments/linked_pipelines.fragment.graphql17
-rw-r--r--app/assets/javascripts/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql34
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_details.query.graphql65
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql20
-rw-r--r--app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js2
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js6
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js19
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_graph.js4
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_header.js2
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_mediator.js2
-rw-r--r--app/assets/javascripts/pipelines/stores/pipeline_store.js27
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/getters.js10
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/index.js2
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/utils.js2
-rw-r--r--app/assets/javascripts/pipelines/utils.js32
-rw-r--r--app/assets/javascripts/popovers/components/popovers.vue10
-rw-r--r--app/assets/javascripts/popovers/index.js6
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue4
-rw-r--r--app/assets/javascripts/profile/add_ssh_key_validation.js2
-rw-r--r--app/assets/javascripts/profile/gl_crop.js8
-rw-r--r--app/assets/javascripts/profile/preferences/profile_preferences_bundle.js2
-rw-r--r--app/assets/javascripts/profile/profile.js10
-rw-r--r--app/assets/javascripts/project_find_file.js16
-rw-r--r--app/assets/javascripts/project_select.js10
-rw-r--r--app/assets/javascripts/project_select_combo_button.js18
-rw-r--r--app/assets/javascripts/project_visibility.js2
-rw-r--r--app/assets/javascripts/projects/commit/components/branches_dropdown.vue94
-rw-r--r--app/assets/javascripts/projects/commit/components/form_modal.vue137
-rw-r--r--app/assets/javascripts/projects/commit/components/form_trigger.vue32
-rw-r--r--app/assets/javascripts/projects/commit/constants.js33
-rw-r--r--app/assets/javascripts/projects/commit/event_hub.js3
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_modal.js55
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_trigger.js20
-rw-r--r--app/assets/javascripts/projects/commit/store/actions.js36
-rw-r--r--app/assets/javascripts/projects/commit/store/getters.js5
-rw-r--r--app/assets/javascripts/projects/commit/store/index.js19
-rw-r--r--app/assets/javascripts/projects/commit/store/mutation_types.js6
-rw-r--r--app/assets/javascripts/projects/commit/store/mutations.js25
-rw-r--r--app/assets/javascripts/projects/commit/store/state.js13
-rw-r--r--app/assets/javascripts/projects/commit_box/info/init_details_button.js4
-rw-r--r--app/assets/javascripts/projects/commit_box/info/load_branches.js2
-rw-r--r--app/assets/javascripts/projects/commits/components/author_select.vue2
-rw-r--r--app/assets/javascripts/projects/commits/index.js2
-rw-r--r--app/assets/javascripts/projects/commits/store/actions.js2
-rw-r--r--app/assets/javascripts/projects/default_project_templates.js4
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue24
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue2
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/illustrations/blank-project.svg36
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/illustrations/ci-cd-project.svg96
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/illustrations/create-from-template.svg67
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/illustrations/import-project.svg133
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/index.js2
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue233
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue151
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue41
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue176
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue46
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue8
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql1
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js102
-rw-r--r--app/assets/javascripts/projects/project_new.js17
-rw-r--r--app/assets/javascripts/projects/settings/access_dropdown.js34
-rw-r--r--app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue2
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue6
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue11
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue7
-rw-r--r--app/assets/javascripts/prometheus_alerts/components/reset_key.vue2
-rw-r--r--app/assets/javascripts/prometheus_metrics/custom_metrics.js12
-rw-r--r--app/assets/javascripts/prometheus_metrics/prometheus_metrics.js8
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_create.js4
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js4
-rw-r--r--app/assets/javascripts/read_more.js4
-rw-r--r--app/assets/javascripts/ref/components/ref_results_section.vue2
-rw-r--r--app/assets/javascripts/ref/components/ref_selector.vue6
-rw-r--r--app/assets/javascripts/ref/stores/actions.js12
-rw-r--r--app/assets/javascripts/ref/stores/mutations.js4
-rw-r--r--app/assets/javascripts/ref_select_dropdown.js2
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue2
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/details_header.vue60
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue4
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue5
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue4
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue2
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue4
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/image_list.vue6
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue23
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue8
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue12
-rw-r--r--app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue81
-rw-r--r--app/assets/javascripts/registry/explorer/constants/details.js21
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/fragments/container_repository.fragment.graphql11
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/index.js1
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql26
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql5
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/queries/get_group_container_repositories.query.graphql23
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/queries/get_project_container_repositories.query.graphql23
-rw-r--r--app/assets/javascripts/registry/explorer/index.js30
-rw-r--r--app/assets/javascripts/registry/explorer/pages/details.vue15
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue138
-rw-r--r--app/assets/javascripts/registry/settings/components/expiration_input.vue4
-rw-r--r--app/assets/javascripts/registry/settings/components/expiration_toggle.vue2
-rw-r--r--app/assets/javascripts/registry/settings/components/registry_settings_app.vue2
-rw-r--r--app/assets/javascripts/registry/settings/components/settings_form.vue16
-rw-r--r--app/assets/javascripts/registry/settings/constants.js4
-rw-r--r--app/assets/javascripts/registry/settings/graphql/utils/cache_update.js4
-rw-r--r--app/assets/javascripts/registry/settings/utils.js10
-rw-r--r--app/assets/javascripts/related_issues/components/related_issuable_input.vue6
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue6
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_root.vue6
-rw-r--r--app/assets/javascripts/related_issues/index.js2
-rw-r--r--app/assets/javascripts/related_issues/stores/related_issues_store.js2
-rw-r--r--app/assets/javascripts/related_merge_requests/index.js2
-rw-r--r--app/assets/javascripts/related_merge_requests/store/actions.js2
-rw-r--r--app/assets/javascripts/releases/components/release_block_assets.vue6
-rw-r--r--app/assets/javascripts/releases/components/release_block_milestone_info.vue6
-rw-r--r--app/assets/javascripts/releases/components/releases_sort.vue6
-rw-r--r--app/assets/javascripts/releases/constants.js2
-rw-r--r--app/assets/javascripts/releases/mount_edit.js2
-rw-r--r--app/assets/javascripts/releases/mount_index.js2
-rw-r--r--app/assets/javascripts/releases/mount_new.js2
-rw-r--r--app/assets/javascripts/releases/mount_show.js2
-rw-r--r--app/assets/javascripts/releases/stores/getters.js2
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/actions.js14
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/getters.js16
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/index.js2
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/mutations.js4
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/actions.js2
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/index.js2
-rw-r--r--app/assets/javascripts/releases/util.js30
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/getters.js14
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/index.js4
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/actions.js4
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/getters.js8
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/index.js4
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js2
-rw-r--r--app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js2
-rw-r--r--app/assets/javascripts/reports/components/grouped_issues_list.vue2
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue20
-rw-r--r--app/assets/javascripts/reports/components/issues_list.vue2
-rw-r--r--app/assets/javascripts/reports/components/modal.vue74
-rw-r--r--app/assets/javascripts/reports/components/modal_open_name.vue51
-rw-r--r--app/assets/javascripts/reports/components/report_item.vue2
-rw-r--r--app/assets/javascripts/reports/components/report_link.vue10
-rw-r--r--app/assets/javascripts/reports/components/test_issue_body.vue8
-rw-r--r--app/assets/javascripts/reports/store/actions.js9
-rw-r--r--app/assets/javascripts/reports/store/getters.js2
-rw-r--r--app/assets/javascripts/reports/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/reports/store/mutations.js18
-rw-r--r--app/assets/javascripts/reports/store/state.js1
-rw-r--r--app/assets/javascripts/reports/store/utils.js12
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue4
-rw-r--r--app/assets/javascripts/repository/components/directory_download_links.vue2
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue10
-rw-r--r--app/assets/javascripts/repository/components/table/parent_row.vue6
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue2
-rw-r--r--app/assets/javascripts/repository/graphql.js4
-rw-r--r--app/assets/javascripts/repository/log_tree.js8
-rw-r--r--app/assets/javascripts/repository/queries/project_path.query.graphql2
-rw-r--r--app/assets/javascripts/repository/router.js2
-rw-r--r--app/assets/javascripts/repository/utils/commit.js2
-rw-r--r--app/assets/javascripts/repository/utils/dom.js4
-rw-r--r--app/assets/javascripts/repository/utils/readme.js6
-rw-r--r--app/assets/javascripts/rest_api.js15
-rw-r--r--app/assets/javascripts/right_sidebar.js42
-rw-r--r--app/assets/javascripts/search/highlight_blob_search_result.js4
-rw-r--r--app/assets/javascripts/search/sidebar/index.js2
-rw-r--r--app/assets/javascripts/search/store/actions.js4
-rw-r--r--app/assets/javascripts/search/store/index.js2
-rw-r--r--app/assets/javascripts/search/topbar/index.js4
-rw-r--r--app/assets/javascripts/search_autocomplete.js8
-rw-r--r--app/assets/javascripts/search_settings/components/search_settings.vue129
-rw-r--r--app/assets/javascripts/search_settings/constants.js11
-rw-r--r--app/assets/javascripts/search_settings/index.js23
-rw-r--r--app/assets/javascripts/self_monitor/store/actions.js18
-rw-r--r--app/assets/javascripts/self_monitor/store/index.js2
-rw-r--r--app/assets/javascripts/sentry_error_stack_trace/index.js2
-rw-r--r--app/assets/javascripts/serverless/components/area.vue8
-rw-r--r--app/assets/javascripts/serverless/store/actions.js18
-rw-r--r--app/assets/javascripts/serverless/store/getters.js4
-rw-r--r--app/assets/javascripts/serverless/utils.js8
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue9
-rw-r--r--app/assets/javascripts/set_status_modal/utils.js4
-rw-r--r--app/assets/javascripts/settings_panels.js11
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue43
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue12
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue17
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewers.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue18
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue11
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue21
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js4
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js2
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js40
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js6
-rw-r--r--app/assets/javascripts/sidebar/utils.js2
-rw-r--r--app/assets/javascripts/single_file_diff.js11
-rw-r--r--app/assets/javascripts/smart_interval.js6
-rw-r--r--app/assets/javascripts/snippet/collapsible_input.js8
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue6
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_edit.vue6
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_view.vue14
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue11
-rw-r--r--app/assets/javascripts/snippets/mixins/snippets.js2
-rw-r--r--app/assets/javascripts/snippets/utils/blob.js12
-rw-r--r--app/assets/javascripts/star.js5
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/index.js4
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/resolvers/file.js2
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js2
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js4
-rw-r--r--app/assets/javascripts/static_site_editor/image_repository.js6
-rw-r--r--app/assets/javascripts/static_site_editor/index.js2
-rw-r--r--app/assets/javascripts/static_site_editor/pages/home.vue2
-rw-r--r--app/assets/javascripts/static_site_editor/services/formatter.js6
-rw-r--r--app/assets/javascripts/static_site_editor/services/front_matterify.js2
-rw-r--r--app/assets/javascripts/static_site_editor/services/image_service.js4
-rw-r--r--app/assets/javascripts/static_site_editor/services/load_source_content.js2
-rw-r--r--app/assets/javascripts/static_site_editor/services/parse_source_file.js4
-rw-r--r--app/assets/javascripts/static_site_editor/services/renderers/render_image.js10
-rw-r--r--app/assets/javascripts/static_site_editor/services/submit_content_changes.js2
-rw-r--r--app/assets/javascripts/static_site_editor/services/templater.js10
-rw-r--r--app/assets/javascripts/task_list.js2
-rw-r--r--app/assets/javascripts/terminal/terminal.js6
-rw-r--r--app/assets/javascripts/terraform/components/terraform_list.vue2
-rw-r--r--app/assets/javascripts/test_utils/simulate_input.js2
-rw-r--r--app/assets/javascripts/toggle_buttons.js2
-rw-r--r--app/assets/javascripts/tooltips/components/tooltips.vue20
-rw-r--r--app/assets/javascripts/tooltips/index.js32
-rw-r--r--app/assets/javascripts/tracking.js6
-rw-r--r--app/assets/javascripts/tree.js8
-rw-r--r--app/assets/javascripts/ui_development_kit.js8
-rw-r--r--app/assets/javascripts/usage_ping_consent.js2
-rw-r--r--app/assets/javascripts/user_callout.js2
-rw-r--r--app/assets/javascripts/user_lists/components/user_list_form.vue2
-rw-r--r--app/assets/javascripts/user_lists/store/edit/actions.js4
-rw-r--r--app/assets/javascripts/user_lists/store/edit/index.js2
-rw-r--r--app/assets/javascripts/user_lists/store/new/actions.js2
-rw-r--r--app/assets/javascripts/user_lists/store/new/index.js2
-rw-r--r--app/assets/javascripts/user_lists/store/show/actions.js4
-rw-r--r--app/assets/javascripts/user_lists/store/show/index.js2
-rw-r--r--app/assets/javascripts/user_lists/store/show/mutations.js4
-rw-r--r--app/assets/javascripts/user_lists/store/utils.js7
-rw-r--r--app/assets/javascripts/user_popovers.js8
-rw-r--r--app/assets/javascripts/users_select/index.js86
-rw-r--r--app/assets/javascripts/vue_alerts.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue164
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue19
-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_merged.vue4
-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.vue110
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue457
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue31
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql41
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/getters.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/index.js15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js7
-rw-r--r--app/assets/javascripts/vue_shared/components/actions_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_modal.vue4
-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/download_viewer.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/deployment_instance.vue91
-rw-r--r--app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue121
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_container.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/editor_lite.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/index.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js11
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js12
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue4
-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/gfm_autocomplete.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js69
-rw-r--r--app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue34
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue30
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/navigation_tabs.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/ordered_layout.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/pikaday.vue57
-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.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/metadata_item.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/title_area.vue40
-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.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js16
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js8
-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/renderers/render_identifier_instance_text.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/select2_select.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.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/labels_select_root.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/split_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/tabs/tabs.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/timezone_dropdown.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue2
-rw-r--r--app/assets/javascripts/vue_shared/constants.js5
-rw-r--r--app/assets/javascripts/vue_shared/directives/autofocusonshow.js4
-rw-r--r--app/assets/javascripts/vue_shared/directives/validation.js12
-rw-r--r--app/assets/javascripts/vue_shared/gl_feature_flags_plugin.js2
-rw-r--r--app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/security_summary.vue4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/constants.js9
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/getters.js22
-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/secret_detection/actions.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/utils.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/utils.js39
-rw-r--r--app/assets/javascripts/vue_shared/translate.js2
-rw-r--r--app/assets/javascripts/vuex_shared/bindings.js2
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue5
-rw-r--r--app/assets/javascripts/whats_new/index.js2
-rw-r--r--app/assets/javascripts/whats_new/utils/get_drawer_body_height.js2
-rw-r--r--app/assets/javascripts/whats_new/utils/notification.js4
-rw-r--r--app/assets/javascripts/zen_mode.js26
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss2
-rw-r--r--app/assets/stylesheets/components/avatar.scss6
-rw-r--r--app/assets/stylesheets/components/deployment_instance.scss91
-rw-r--r--app/assets/stylesheets/components/whats_new.scss2
-rw-r--r--app/assets/stylesheets/framework/blank.scss4
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss6
-rw-r--r--app/assets/stylesheets/framework/diffs.scss6
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss13
-rw-r--r--app/assets/stylesheets/framework/header.scss4
-rw-r--r--app/assets/stylesheets/framework/highlight.scss3
-rw-r--r--app/assets/stylesheets/framework/mixins.scss4
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss13
-rw-r--r--app/assets/stylesheets/framework/variables.scss6
-rw-r--r--app/assets/stylesheets/highlight/common.scss46
-rw-r--r--app/assets/stylesheets/highlight/conflict_colors.scss119
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss6
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss2
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss2
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss2
-rw-r--r--app/assets/stylesheets/highlight/themes/white.scss2
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss15
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss5
-rw-r--r--app/assets/stylesheets/page_bundles/_pipeline_mixins.scss7
-rw-r--r--app/assets/stylesheets/page_bundles/environments.scss89
-rw-r--r--app/assets/stylesheets/page_bundles/error_tracking_index.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/incident_management_list.scss153
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss28
-rw-r--r--app/assets/stylesheets/page_bundles/merge_conflicts.scss180
-rw-r--r--app/assets/stylesheets/page_bundles/oncall_schedules.scss18
-rw-r--r--app/assets/stylesheets/page_bundles/wiki.scss5
-rw-r--r--app/assets/stylesheets/pages/editor.scss1
-rw-r--r--app/assets/stylesheets/pages/incident_management_list.scss150
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss20
-rw-r--r--app/assets/stylesheets/pages/note_form.scss8
-rw-r--r--app/assets/stylesheets/pages/registry.scss8
-rw-r--r--app/assets/stylesheets/pages/settings.scss2
-rw-r--r--app/assets/stylesheets/pages/settings_ci_cd.scss4
-rw-r--r--app/assets/stylesheets/pages/tree.scss1
-rw-r--r--app/assets/stylesheets/pages/trials.scss8
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss4
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss4
-rw-r--r--app/assets/stylesheets/themes/_dark.scss14
-rw-r--r--app/assets/stylesheets/utilities.scss13
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/admin/dev_ops_report_controller.rb8
-rw-r--r--app/controllers/admin/projects_controller.rb4
-rw-r--r--app/controllers/application_controller.rb30
-rw-r--r--app/controllers/concerns/invisible_captcha_on_signup.rb4
-rw-r--r--app/controllers/concerns/issuable_actions.rb1
-rw-r--r--app/controllers/concerns/redis_tracking.rb2
-rw-r--r--app/controllers/concerns/show_inherited_labels_checker.rb11
-rw-r--r--app/controllers/concerns/spammable_actions.rb25
-rw-r--r--app/controllers/dashboard/snippets_controller.rb1
-rw-r--r--app/controllers/explore/projects_controller.rb7
-rw-r--r--app/controllers/groups/group_members_controller.rb4
-rw-r--r--app/controllers/groups/labels_controller.rb3
-rw-r--r--app/controllers/groups/settings/packages_and_registries_controller.rb14
-rw-r--r--app/controllers/import/bulk_imports_controller.rb35
-rw-r--r--app/controllers/jira_connect/app_descriptor_controller.rb41
-rw-r--r--app/controllers/jira_connect/subscriptions_controller.rb3
-rw-r--r--app/controllers/metrics_controller.rb10
-rw-r--r--app/controllers/projects/blob_controller.rb3
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb2
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb5
-rw-r--r--app/controllers/projects/environments_controller.rb3
-rw-r--r--app/controllers/projects/feature_flags_controller.rb10
-rw-r--r--app/controllers/projects/incident_management/pager_duty_incidents_controller.rb2
-rw-r--r--app/controllers/projects/labels_controller.rb3
-rw-r--r--app/controllers/projects/mattermosts_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb16
-rw-r--r--app/controllers/projects/merge_requests_controller.rb14
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb1
-rw-r--r--app/controllers/projects/pipelines/tests_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb39
-rw-r--r--app/controllers/projects/project_members_controller.rb13
-rw-r--r--app/controllers/projects/usage_ping_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb6
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb11
-rw-r--r--app/controllers/users_controller.rb6
-rw-r--r--app/enums/.keep0
-rw-r--r--app/experiments/application_experiment.rb6
-rw-r--r--app/finders/alert_management/alerts_finder.rb2
-rw-r--r--app/finders/autocomplete/group_finder.rb3
-rw-r--r--app/finders/autocomplete/project_finder.rb3
-rw-r--r--app/finders/ci/pipelines_for_merge_request_finder.rb18
-rw-r--r--app/finders/concerns/finder_methods.rb2
-rw-r--r--app/finders/concerns/packages/finder_helper.rb29
-rw-r--r--app/finders/concerns/time_frame_filter.rb2
-rw-r--r--app/finders/deployments_finder.rb4
-rw-r--r--app/finders/issuable_finder.rb8
-rw-r--r--app/finders/issuable_finder/params.rb33
-rw-r--r--app/finders/merge_requests_finder.rb4
-rw-r--r--app/finders/packages/debian/distributions_finder.rb52
-rw-r--r--app/finders/packages/group_packages_finder.rb8
-rw-r--r--app/finders/packages/maven/package_finder.rb16
-rw-r--r--app/finders/packages/nuget/package_finder.rb35
-rw-r--r--app/finders/packages/packages_finder.rb8
-rw-r--r--app/finders/projects_finder.rb2
-rw-r--r--app/finders/template_finder.rb1
-rw-r--r--app/finders/users_finder.rb7
-rw-r--r--app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb4
-rw-r--r--app/graphql/mutations/alert_management/base.rb10
-rw-r--r--app/graphql/mutations/alert_management/http_integration/create.rb19
-rw-r--r--app/graphql/mutations/alert_management/http_integration/destroy.rb2
-rw-r--r--app/graphql/mutations/alert_management/http_integration/http_integration_base.rb2
-rw-r--r--app/graphql/mutations/alert_management/http_integration/reset_token.rb2
-rw-r--r--app/graphql/mutations/alert_management/http_integration/update.rb6
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb6
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb2
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb2
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/update.rb6
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb2
-rw-r--r--app/graphql/mutations/award_emojis/base.rb4
-rw-r--r--app/graphql/mutations/boards/destroy.rb4
-rw-r--r--app/graphql/mutations/boards/issues/issue_move_list.rb14
-rw-r--r--app/graphql/mutations/boards/lists/base.rb4
-rw-r--r--app/graphql/mutations/boards/lists/create.rb4
-rw-r--r--app/graphql/mutations/boards/lists/update.rb6
-rw-r--r--app/graphql/mutations/boards/update.rb2
-rw-r--r--app/graphql/mutations/branches/create.rb8
-rw-r--r--app/graphql/mutations/ci/base.rb22
-rw-r--r--app/graphql/mutations/ci/ci_cd_settings_update.rb29
-rw-r--r--app/graphql/mutations/ci/pipeline/base.rb24
-rw-r--r--app/graphql/mutations/ci/pipeline/cancel.rb24
-rw-r--r--app/graphql/mutations/ci/pipeline/destroy.rb24
-rw-r--r--app/graphql/mutations/ci/pipeline/retry.rb29
-rw-r--r--app/graphql/mutations/ci/pipeline_cancel.rb22
-rw-r--r--app/graphql/mutations/ci/pipeline_destroy.rb22
-rw-r--r--app/graphql/mutations/ci/pipeline_retry.rb27
-rw-r--r--app/graphql/mutations/commits/create.rb10
-rw-r--r--app/graphql/mutations/concerns/mutations/authorizes_project.rb17
-rw-r--r--app/graphql/mutations/concerns/mutations/finds_project.rb11
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_namespace.rb15
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb4
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_subscription.rb2
-rw-r--r--app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb2
-rw-r--r--app/graphql/mutations/container_expiration_policies/update.rb4
-rw-r--r--app/graphql/mutations/container_repositories/destroy_tags.rb2
-rw-r--r--app/graphql/mutations/custom_emoji/create.rb8
-rw-r--r--app/graphql/mutations/design_management/base.rb4
-rw-r--r--app/graphql/mutations/design_management/delete.rb4
-rw-r--r--app/graphql/mutations/design_management/move.rb8
-rw-r--r--app/graphql/mutations/design_management/upload.rb4
-rw-r--r--app/graphql/mutations/discussions/toggle_resolve.rb6
-rw-r--r--app/graphql/mutations/environments/canary_ingress/update.rb4
-rw-r--r--app/graphql/mutations/issues/base.rb6
-rw-r--r--app/graphql/mutations/issues/create.rb18
-rw-r--r--app/graphql/mutations/issues/move.rb2
-rw-r--r--app/graphql/mutations/issues/set_due_date.rb2
-rw-r--r--app/graphql/mutations/issues/set_locked.rb2
-rw-r--r--app/graphql/mutations/issues/update.rb8
-rw-r--r--app/graphql/mutations/jira_import/import_users.rb4
-rw-r--r--app/graphql/mutations/jira_import/start.rb10
-rw-r--r--app/graphql/mutations/labels/create.rb8
-rw-r--r--app/graphql/mutations/merge_requests/base.rb6
-rw-r--r--app/graphql/mutations/merge_requests/create.rb4
-rw-r--r--app/graphql/mutations/merge_requests/update.rb2
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/create.rb14
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/delete.rb2
-rw-r--r--app/graphql/mutations/namespace/package_settings/update.rb54
-rw-r--r--app/graphql/mutations/notes/base.rb2
-rw-r--r--app/graphql/mutations/notes/create/base.rb2
-rw-r--r--app/graphql/mutations/notes/create/note.rb2
-rw-r--r--app/graphql/mutations/notes/destroy.rb2
-rw-r--r--app/graphql/mutations/notes/reposition_image_diff_note.rb2
-rw-r--r--app/graphql/mutations/notes/update/base.rb2
-rw-r--r--app/graphql/mutations/releases/base.rb2
-rw-r--r--app/graphql/mutations/releases/create.rb12
-rw-r--r--app/graphql/mutations/releases/update.rb16
-rw-r--r--app/graphql/mutations/snippets/base.rb2
-rw-r--r--app/graphql/mutations/snippets/create.rb14
-rw-r--r--app/graphql/mutations/snippets/destroy.rb2
-rw-r--r--app/graphql/mutations/snippets/mark_as_spam.rb2
-rw-r--r--app/graphql/mutations/snippets/update.rb10
-rw-r--r--app/graphql/mutations/terraform/state/base.rb2
-rw-r--r--app/graphql/mutations/todos/create.rb4
-rw-r--r--app/graphql/mutations/todos/mark_all_done.rb4
-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.rb6
-rw-r--r--app/graphql/queries/container_registry/get_container_repositories.query.graphql60
-rw-r--r--app/graphql/queries/pipelines/get_pipeline_details.query.graphql101
-rw-r--r--app/graphql/queries/snippet/snippet.query.graphql5
-rw-r--r--app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb6
-rw-r--r--app/graphql/resolvers/alert_management/alert_resolver.rb10
-rw-r--r--app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb2
-rw-r--r--app/graphql/resolvers/board_list_issues_resolver.rb2
-rw-r--r--app/graphql/resolvers/board_lists_resolver.rb4
-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.rb74
-rw-r--r--app/graphql/resolvers/ci/jobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/runner_setup_resolver.rb8
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb32
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb6
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb3
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb6
-rw-r--r--app/graphql/resolvers/concerns/resolves_snippets.rb4
-rw-r--r--app/graphql/resolvers/concerns/time_frame_arguments.rb2
-rw-r--r--app/graphql/resolvers/container_repositories_resolver.rb2
-rw-r--r--app/graphql/resolvers/design_management/design_at_version_resolver.rb2
-rw-r--r--app/graphql/resolvers/design_management/design_resolver.rb4
-rw-r--r--app/graphql/resolvers/design_management/designs_resolver.rb4
-rw-r--r--app/graphql/resolvers/design_management/version/design_at_version_resolver.rb6
-rw-r--r--app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb4
-rw-r--r--app/graphql/resolvers/design_management/version_in_collection_resolver.rb4
-rw-r--r--app/graphql/resolvers/design_management/version_resolver.rb2
-rw-r--r--app/graphql/resolvers/design_management/versions_resolver.rb4
-rw-r--r--app/graphql/resolvers/echo_resolver.rb2
-rw-r--r--app/graphql/resolvers/environments_resolver.rb6
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb2
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb2
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb4
-rw-r--r--app/graphql/resolvers/full_path_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_members_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_milestones_resolver.rb2
-rw-r--r--app/graphql/resolvers/issues_resolver.rb14
-rw-r--r--app/graphql/resolvers/members_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_request_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb16
-rw-r--r--app/graphql/resolvers/metrics/dashboard_resolver.rb2
-rw-r--r--app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb4
-rw-r--r--app/graphql/resolvers/milestones_resolver.rb10
-rw-r--r--app/graphql/resolvers/namespace_projects_resolver.rb6
-rw-r--r--app/graphql/resolvers/package_details_resolver.rb18
-rw-r--r--app/graphql/resolvers/packages_resolver.rb2
-rw-r--r--app/graphql/resolvers/project_members_resolver.rb2
-rw-r--r--app/graphql/resolvers/project_milestones_resolver.rb2
-rw-r--r--app/graphql/resolvers/project_pipeline_resolver.rb2
-rw-r--r--app/graphql/resolvers/projects/jira_projects_resolver.rb7
-rw-r--r--app/graphql/resolvers/projects/services_resolver.rb4
-rw-r--r--app/graphql/resolvers/projects_resolver.rb10
-rw-r--r--app/graphql/resolvers/release_milestones_resolver.rb13
-rw-r--r--app/graphql/resolvers/release_resolver.rb2
-rw-r--r--app/graphql/resolvers/releases_resolver.rb2
-rw-r--r--app/graphql/resolvers/snippets/blobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/snippets_resolver.rb8
-rw-r--r--app/graphql/resolvers/todo_resolver.rb12
-rw-r--r--app/graphql/resolvers/tree_resolver.rb6
-rw-r--r--app/graphql/resolvers/user_resolver.rb4
-rw-r--r--app/graphql/resolvers/user_starred_projects_resolver.rb2
-rw-r--r--app/graphql/resolvers/users/snippets_resolver.rb2
-rw-r--r--app/graphql/resolvers/users_resolver.rb20
-rw-r--r--app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb4
-rw-r--r--app/graphql/types/alert_management/domain_filter_enum.rb2
-rw-r--r--app/graphql/types/base_enum.rb19
-rw-r--r--app/graphql/types/board_type.rb8
-rw-r--r--app/graphql/types/ci/build_need_type.rb14
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb4
-rw-r--r--app/graphql/types/ci/config/config_type.rb2
-rw-r--r--app/graphql/types/ci/config/group_type.rb2
-rw-r--r--app/graphql/types/ci/config/job_restriction_type.rb15
-rw-r--r--app/graphql/types/ci/config/job_type.rb33
-rw-r--r--app/graphql/types/ci/config/stage_type.rb2
-rw-r--r--app/graphql/types/ci/job_type.rb6
-rw-r--r--app/graphql/types/ci/stage_type.rb33
-rw-r--r--app/graphql/types/data_visualization_palette/color_enum.rb14
-rw-r--r--app/graphql/types/data_visualization_palette/weight_enum.rb14
-rw-r--r--app/graphql/types/issue_type.rb7
-rw-r--r--app/graphql/types/merge_request_type.rb18
-rw-r--r--app/graphql/types/mutation_type.rb8
-rw-r--r--app/graphql/types/namespace/package_settings_type.rb14
-rw-r--r--app/graphql/types/namespace_type.rb5
-rw-r--r--app/graphql/types/notes/note_type.rb7
-rw-r--r--app/graphql/types/package_type.rb16
-rw-r--r--app/graphql/types/package_type_enum.rb15
-rw-r--r--app/graphql/types/packages/composer/details_type.rb16
-rw-r--r--app/graphql/types/packages/composer/json_type.rb18
-rw-r--r--app/graphql/types/packages/composer/metadatum_type.rb17
-rw-r--r--app/graphql/types/packages/package_tag_type.rb16
-rw-r--r--app/graphql/types/packages/package_type.rb27
-rw-r--r--app/graphql/types/packages/package_type_enum.rb17
-rw-r--r--app/graphql/types/project_type.rb9
-rw-r--r--app/graphql/types/query_type.rb5
-rw-r--r--app/graphql/types/release_type.rb3
-rw-r--r--app/graphql/types/repository_type.rb2
-rw-r--r--app/helpers/application_helper.rb12
-rw-r--r--app/helpers/application_settings_helper.rb4
-rw-r--r--app/helpers/blob_helper.rb23
-rw-r--r--app/helpers/ci/pipelines_helper.rb4
-rw-r--r--app/helpers/ci/triggers_helper.rb15
-rw-r--r--app/helpers/commits_helper.rb12
-rw-r--r--app/helpers/dashboard_helper.rb4
-rw-r--r--app/helpers/emails_helper.rb23
-rw-r--r--app/helpers/graph_helper.rb6
-rw-r--r--app/helpers/groups/group_members_helper.rb80
-rw-r--r--app/helpers/groups_helper.rb1
-rw-r--r--app/helpers/invite_members_helper.rb30
-rw-r--r--app/helpers/issuables_helper.rb3
-rw-r--r--app/helpers/jira_connect_helper.rb13
-rw-r--r--app/helpers/merge_requests_helper.rb30
-rw-r--r--app/helpers/page_layout_helper.rb2
-rw-r--r--app/helpers/preferences_helper.rb2
-rw-r--r--app/helpers/projects/alert_management_helper.rb2
-rw-r--r--app/helpers/projects/project_members_helper.rb29
-rw-r--r--app/helpers/projects_helper.rb8
-rw-r--r--app/helpers/services_helper.rb8
-rw-r--r--app/helpers/startup_css_helper.rb7
-rw-r--r--app/helpers/tab_helper.rb3
-rw-r--r--app/helpers/triggers_helper.rb15
-rw-r--r--app/helpers/users_helper.rb2
-rw-r--r--app/helpers/visibility_level_helper.rb110
-rw-r--r--app/helpers/web_ide_button_helper.rb4
-rw-r--r--app/mailers/emails/issues.rb2
-rw-r--r--app/mailers/emails/members.rb19
-rw-r--r--app/mailers/emails/merge_requests.rb2
-rw-r--r--app/mailers/emails/pipelines.rb15
-rw-r--r--app/mailers/previews/devise_mailer_preview.rb2
-rw-r--r--app/models/alert_management/http_integration.rb4
-rw-r--r--app/models/application_record.rb5
-rw-r--r--app/models/application_setting.rb46
-rw-r--r--app/models/application_setting_implementation.rb6
-rw-r--r--app/models/audit_event.rb3
-rw-r--r--app/models/audit_event_archived.rb10
-rw-r--r--app/models/audit_event_partitioned.rb14
-rw-r--r--app/models/authentication_event.rb8
-rw-r--r--app/models/blob_viewer/gitlab_ci_yml.rb4
-rw-r--r--app/models/ci/bridge.rb14
-rw-r--r--app/models/ci/build.rb56
-rw-r--r--app/models/ci/build_need.rb2
-rw-r--r--app/models/ci/build_runner_session.rb4
-rw-r--r--app/models/ci/commit_with_pipeline.rb38
-rw-r--r--app/models/ci/group.rb24
-rw-r--r--app/models/ci/job_artifact.rb10
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/ci/ref.rb7
-rw-r--r--app/models/clusters/applications/cert_manager.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.rb2
-rw-r--r--app/models/commit.rb8
-rw-r--r--app/models/commit_status.rb12
-rw-r--r--app/models/commit_with_pipeline.rb2
-rw-r--r--app/models/concerns/boards/listable.rb52
-rw-r--r--app/models/concerns/bulk_insert_safe.rb4
-rw-r--r--app/models/concerns/ci/artifactable.rb3
-rw-r--r--app/models/concerns/each_batch.rb16
-rw-r--r--app/models/concerns/enums/ci/commit_status.rb36
-rw-r--r--app/models/concerns/enums/commit_status.rb35
-rw-r--r--app/models/concerns/enums/vulnerability.rb46
-rw-r--r--app/models/concerns/issuable.rb11
-rw-r--r--app/models/concerns/issue_available_features.rb5
-rw-r--r--app/models/concerns/milestoneable.rb2
-rw-r--r--app/models/concerns/noteable.rb21
-rw-r--r--app/models/concerns/packages/debian/architecture.rb25
-rw-r--r--app/models/concerns/packages/debian/distribution.rb115
-rw-r--r--app/models/concerns/repositories/can_housekeep_repository.rb25
-rw-r--r--app/models/cycle_analytics/level_base.rb74
-rw-r--r--app/models/cycle_analytics/project_level.rb21
-rw-r--r--app/models/cycle_analytics/project_level_stage_adapter.rb44
-rw-r--r--app/models/deployment.rb17
-rw-r--r--app/models/diff_note.rb4
-rw-r--r--app/models/experiment.rb4
-rw-r--r--app/models/gpg_key.rb2
-rw-r--r--app/models/group.rb3
-rw-r--r--app/models/issue.rb4
-rw-r--r--app/models/list.rb36
-rw-r--r--app/models/member.rb2
-rw-r--r--app/models/members/group_member.rb12
-rw-r--r--app/models/merge_request.rb33
-rw-r--r--app/models/milestone.rb1
-rw-r--r--app/models/namespace.rb11
-rw-r--r--app/models/namespace/package_setting.rb28
-rw-r--r--app/models/namespace/root_storage_statistics.rb2
-rw-r--r--app/models/namespace_onboarding_action.rb27
-rw-r--r--app/models/onboarding_progress.rb65
-rw-r--r--app/models/packages/conan/file_metadatum.rb4
-rw-r--r--app/models/packages/debian.rb9
-rw-r--r--app/models/packages/debian/file_metadatum.rb56
-rw-r--r--app/models/packages/debian/group_architecture.rb9
-rw-r--r--app/models/packages/debian/group_distribution.rb9
-rw-r--r--app/models/packages/debian/project_architecture.rb9
-rw-r--r--app/models/packages/debian/project_distribution.rb9
-rw-r--r--app/models/packages/dependency.rb2
-rw-r--r--app/models/packages/event.rb28
-rw-r--r--app/models/packages/package.rb7
-rw-r--r--app/models/packages/package_file.rb9
-rw-r--r--app/models/pages_domain.rb4
-rw-r--r--app/models/plan.rb2
-rw-r--r--app/models/project.rb71
-rw-r--r--app/models/project_feature_usage.rb4
-rw-r--r--app/models/project_pages_metadatum.rb3
-rw-r--r--app/models/project_services/alerts_service.rb86
-rw-r--r--app/models/project_services/alerts_service_data.rb14
-rw-r--r--app/models/project_services/datadog_service.rb8
-rw-r--r--app/models/project_services/jira_service.rb10
-rw-r--r--app/models/project_services/mattermost_slash_commands_service.rb2
-rw-r--r--app/models/project_services/slack_slash_commands_service.rb2
-rw-r--r--app/models/protectable_dropdown.rb2
-rw-r--r--app/models/release.rb2
-rw-r--r--app/models/remote_mirror.rb2
-rw-r--r--app/models/repository.rb21
-rw-r--r--app/models/service.rb8
-rw-r--r--app/models/snippet.rb18
-rw-r--r--app/models/snippet_repository.rb1
-rw-r--r--app/models/snippet_repository_storage_move.rb6
-rw-r--r--app/models/terraform/state.rb9
-rw-r--r--app/models/user.rb19
-rw-r--r--app/models/user_preference.rb2
-rw-r--r--app/models/wiki.rb1
-rw-r--r--app/policies/analytics/instance_statistics/measurement_policy.rb9
-rw-r--r--app/policies/ci/build_policy.rb11
-rw-r--r--app/policies/global_policy.rb1
-rw-r--r--app/policies/group_member_policy.rb6
-rw-r--r--app/policies/group_policy.rb5
-rw-r--r--app/policies/namespace/package_setting_policy.rb5
-rw-r--r--app/policies/namespace_policy.rb2
-rw-r--r--app/policies/packages/composer/metadatum_policy.rb8
-rw-r--r--app/policies/packages/tag_policy.rb6
-rw-r--r--app/policies/project_policy.rb9
-rw-r--r--app/presenters/board_presenter.rb5
-rw-r--r--app/presenters/ci/build_runner_presenter.rb21
-rw-r--r--app/presenters/packages/composer/packages_presenter.rb30
-rw-r--r--app/presenters/packages/nuget/service_index_presenter.rb104
-rw-r--r--app/serializers/build_details_entity.rb2
-rw-r--r--app/serializers/diffs_metadata_entity.rb22
-rw-r--r--app/serializers/environment_entity.rb5
-rw-r--r--app/serializers/group_analytics_stage_entity.rb16
-rw-r--r--app/serializers/group_analytics_stage_serializer.rb5
-rw-r--r--app/serializers/issuable_sidebar_basic_entity.rb4
-rw-r--r--app/serializers/issue_entity.rb4
-rw-r--r--app/serializers/member_entity.rb54
-rw-r--r--app/serializers/member_serializer.rb5
-rw-r--r--app/serializers/member_user_entity.rb28
-rw-r--r--app/serializers/merge_request_poll_cached_widget_entity.rb10
-rw-r--r--app/serializers/merge_request_poll_widget_entity.rb6
-rw-r--r--app/serializers/merge_request_widget_entity.rb10
-rw-r--r--app/serializers/merge_requests/pipeline_entity.rb10
-rw-r--r--app/serializers/pipeline_details_entity.rb4
-rw-r--r--app/services/alert_management/http_integrations/create_service.rb13
-rw-r--r--app/services/alert_management/sync_alert_service_data_service.rb56
-rw-r--r--app/services/boards/base_items_list_service.rb128
-rw-r--r--app/services/boards/issues/list_service.rb111
-rw-r--r--app/services/bulk_create_integration_service.rb4
-rw-r--r--app/services/ci/create_downstream_pipeline_service.rb4
-rw-r--r--app/services/ci/create_pipeline_service.rb16
-rw-r--r--app/services/ci/create_web_ide_terminal_service.rb2
-rw-r--r--app/services/ci/destroy_expired_job_artifacts_service.rb57
-rw-r--r--app/services/ci/pipeline_artifacts/coverage_report_service.rb32
-rw-r--r--app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb52
-rw-r--r--app/services/ci/pipeline_trigger_service.rb8
-rw-r--r--app/services/ci/pipelines/create_artifact_service.rb32
-rw-r--r--app/services/ci/play_build_service.rb4
-rw-r--r--app/services/ci/process_build_service.rb21
-rw-r--r--app/services/ci/register_job_service.rb4
-rw-r--r--app/services/ci/retry_build_service.rb6
-rw-r--r--app/services/ci/retry_pipeline_service.rb2
-rw-r--r--app/services/ci/test_failure_history_service.rb1
-rw-r--r--app/services/ci/update_build_state_service.rb2
-rw-r--r--app/services/concerns/schedule_bulk_repository_shard_moves_methods.rb53
-rw-r--r--app/services/concerns/update_repository_storage_methods.rb114
-rw-r--r--app/services/container_expiration_policies/cleanup_service.rb23
-rw-r--r--app/services/draft_notes/base_service.rb4
-rw-r--r--app/services/draft_notes/create_service.rb4
-rw-r--r--app/services/draft_notes/publish_service.rb1
-rw-r--r--app/services/feature_flags/base_service.rb15
-rw-r--r--app/services/git/branch_push_service.rb4
-rw-r--r--app/services/groups/create_service.rb1
-rw-r--r--app/services/groups/destroy_service.rb23
-rw-r--r--app/services/ide/base_config_service.rb2
-rw-r--r--app/services/incident_management/pager_duty/process_webhook_service.rb13
-rw-r--r--app/services/issuable/bulk_update_service.rb2
-rw-r--r--app/services/issuable/export_csv/base_service.rb38
-rw-r--r--app/services/issuable_base_service.rb4
-rw-r--r--app/services/issues/clone_service.rb2
-rw-r--r--app/services/issues/close_service.rb7
-rw-r--r--app/services/issues/export_csv_service.rb26
-rw-r--r--app/services/jira_connect/sync_service.rb2
-rw-r--r--app/services/jira_connect_subscriptions/create_service.rb2
-rw-r--r--app/services/labels/create_service.rb2
-rw-r--r--app/services/members/create_service.rb3
-rw-r--r--app/services/merge_requests/after_create_service.rb3
-rw-r--r--app/services/merge_requests/base_service.rb4
-rw-r--r--app/services/merge_requests/cleanup_refs_service.rb2
-rw-r--r--app/services/merge_requests/close_service.rb3
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb3
-rw-r--r--app/services/merge_requests/export_csv_service.rb20
-rw-r--r--app/services/merge_requests/merge_service.rb4
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb16
-rw-r--r--app/services/merge_requests/post_merge_service.rb3
-rw-r--r--app/services/merge_requests/reopen_service.rb3
-rw-r--r--app/services/merge_requests/update_service.rb34
-rw-r--r--app/services/namespaces/package_settings/update_service.rb40
-rw-r--r--app/services/notes/create_service.rb5
-rw-r--r--app/services/notes/destroy_service.rb5
-rw-r--r--app/services/notes/update_service.rb5
-rw-r--r--app/services/notification_service.rb10
-rw-r--r--app/services/onboarding_progress_service.rb6
-rw-r--r--app/services/packages/create_event_service.rb16
-rw-r--r--app/services/packages/debian/create_package_file_service.rb36
-rw-r--r--app/services/packages/debian/extract_metadata_service.rb85
-rw-r--r--app/services/packages/debian/get_or_create_incoming_service.rb11
-rw-r--r--app/services/packages/maven/find_or_create_package_service.rb23
-rw-r--r--app/services/packages/nuget/search_service.rb110
-rw-r--r--app/services/pages/migrate_legacy_storage_to_deployment_service.rb58
-rw-r--r--app/services/pages/zip_directory_service.rb49
-rw-r--r--app/services/post_receive_service.rb2
-rw-r--r--app/services/projects/after_import_service.rb4
-rw-r--r--app/services/projects/container_repository/cleanup_tags_service.rb57
-rw-r--r--app/services/projects/container_repository/gitlab/delete_tags_service.rb4
-rw-r--r--app/services/projects/fork_service.rb6
-rw-r--r--app/services/projects/housekeeping_service.rb107
-rw-r--r--app/services/projects/schedule_bulk_repository_shard_moves_service.rb38
-rw-r--r--app/services/projects/transfer_service.rb9
-rw-r--r--app/services/projects/unlink_fork_service.rb13
-rw-r--r--app/services/projects/update_pages_service.rb41
-rw-r--r--app/services/projects/update_repository_storage_service.rb120
-rw-r--r--app/services/projects/update_service.rb5
-rw-r--r--app/services/repositories/housekeeping_service.rb106
-rw-r--r--app/services/resource_events/change_state_service.rb2
-rw-r--r--app/services/serverless/associate_domain_service.rb2
-rw-r--r--app/services/service_desk_settings/update_service.rb4
-rw-r--r--app/services/snippets/schedule_bulk_repository_shard_moves_service.rb31
-rw-r--r--app/services/snippets/update_repository_storage_service.rb21
-rw-r--r--app/services/todo_service.rb4
-rw-r--r--app/services/web_hook_service.rb4
-rw-r--r--app/uploaders/packages/debian/distribution_release_file_uploader.rb27
-rw-r--r--app/uploaders/packages/package_file_uploader.rb4
-rw-r--r--app/validators/feature_flag_strategies_validator.rb6
-rw-r--r--app/validators/json_schemas/debian_fields.json9
-rw-r--r--app/validators/json_schemas/http_integration_payload_attribute_mapping.json3
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml4
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml1
-rw-r--r--app/views/admin/application_settings/_ip_limits.html.haml7
-rw-r--r--app/views/admin/application_settings/_signup.html.haml2
-rw-r--r--app/views/admin/application_settings/_spam.html.haml8
-rw-r--r--app/views/admin/application_settings/_usage.html.haml2
-rw-r--r--app/views/admin/application_settings/reporting.html.haml2
-rw-r--r--app/views/admin/background_jobs/show.html.haml2
-rw-r--r--app/views/admin/dev_ops_report/_report.html.haml2
-rw-r--r--app/views/admin/dev_ops_report/show.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml10
-rw-r--r--app/views/admin/hooks/_form.html.haml65
-rw-r--r--app/views/admin/jobs/index.html.haml2
-rw-r--r--app/views/admin/runners/index.html.haml26
-rw-r--r--app/views/admin/runners/show.html.haml32
-rw-r--r--app/views/admin/system_info/show.html.haml28
-rw-r--r--app/views/admin/users/_admin_notes.html.haml2
-rw-r--r--app/views/admin/users/index.html.haml3
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml24
-rw-r--r--app/views/ci/runner/_how_to_setup_runner_automatically.html.haml15
-rw-r--r--app/views/ci/variables/_index.html.haml2
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml1
-rw-r--r--app/views/clusters/clusters/new.html.haml1
-rw-r--r--app/views/dashboard/todos/index.html.haml2
-rw-r--r--app/views/devise/shared/_footer.html.haml8
-rw-r--r--app/views/devise/shared/_signup_box.html.haml2
-rw-r--r--app/views/doorkeeper/authorizations/new.html.haml4
-rw-r--r--app/views/events/event/_push.html.haml2
-rw-r--r--app/views/explore/projects/_projects.html.haml2
-rw-r--r--app/views/groups/_invite_members_modal.html.haml2
-rw-r--r--app/views/groups/edit.html.haml4
-rw-r--r--app/views/groups/group_members/index.html.haml192
-rw-r--r--app/views/groups/registry/repositories/index.html.haml33
-rw-r--r--app/views/groups/runners/_group_runners.html.haml13
-rw-r--r--app/views/groups/runners/_index.html.haml4
-rw-r--r--app/views/groups/settings/_two_factor_auth.html.haml2
-rw-r--r--app/views/groups/settings/ci_cd/_auto_devops_form.html.haml4
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml6
-rw-r--r--app/views/groups/settings/packages_and_registries/index.html.haml5
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml25
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--app/views/layouts/_startup_css.haml2
-rw-r--r--app/views/layouts/_startup_css_activation.haml2
-rw-r--r--app/views/layouts/devise.html.haml10
-rw-r--r--app/views/layouts/devise_empty.html.haml11
-rw-r--r--app/views/layouts/header/_default.html.haml33
-rw-r--r--app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/header/_new_dropdown.haml4
-rw-r--r--app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/jira_connect.html.haml5
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml10
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml4
-rw-r--r--app/views/notify/_issuable_csv_export.html.haml2
-rw-r--r--app/views/notify/issue_due_email.html.haml2
-rw-r--r--app/views/notify/issue_due_email.text.erb2
-rw-r--r--app/views/notify/issues_csv_email.text.erb2
-rw-r--r--app/views/notify/member_expiration_date_updated_email.html.haml6
-rw-r--r--app/views/notify/member_expiration_date_updated_email.text.erb5
-rw-r--r--app/views/notify/merge_requests_csv_email.text.erb2
-rw-r--r--app/views/notify/pipeline_failed_email.html.haml2
-rw-r--r--app/views/notify/pipeline_failed_email.text.erb2
-rw-r--r--app/views/notify/pipeline_fixed_email.html.haml2
-rw-r--r--app/views/notify/pipeline_fixed_email.text.erb2
-rw-r--r--app/views/notify/pipeline_success_email.html.haml2
-rw-r--r--app/views/notify/pipeline_success_email.text.erb2
-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/profiles/chat_names/index.html.haml2
-rw-r--r--app/views/profiles/show.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/_codes.html.haml17
-rw-r--r--app/views/profiles/two_factor_auths/create.html.haml4
-rw-r--r--app/views/projects/_export.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml2
-rw-r--r--app/views/projects/_invite_members_modal.html.haml2
-rw-r--r--app/views/projects/_service_desk_settings.html.haml6
-rw-r--r--app/views/projects/_visibility_modal.html.haml4
-rw-r--r--app/views/projects/alert_management/index.html.haml1
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml3
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml6
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml4
-rw-r--r--app/views/projects/branches/_branch.html.haml2
-rw-r--r--app/views/projects/branches/new.html.haml9
-rw-r--r--app/views/projects/ci/builds/_build.html.haml12
-rw-r--r--app/views/projects/ci/lints/show.html.haml2
-rw-r--r--app/views/projects/ci/pipeline_editor/show.html.haml8
-rw-r--r--app/views/projects/commit/_change.html.haml40
-rw-r--r--app/views/projects/commit/_commit_box.html.haml2
-rw-r--r--app/views/projects/commit/_commit_modal.html.haml26
-rw-r--r--app/views/projects/commit/show.html.haml4
-rw-r--r--app/views/projects/edit.html.haml17
-rw-r--r--app/views/projects/environments/_metrics_button.html.haml2
-rw-r--r--app/views/projects/incidents/index.html.haml1
-rw-r--r--app/views/projects/issues/_design_management.html.haml2
-rw-r--r--app/views/projects/issues/import_csv/_button.html.haml2
-rw-r--r--app/views/projects/jobs/index.html.haml5
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml6
-rw-r--r--app/views/projects/merge_requests/show.html.haml5
-rw-r--r--app/views/projects/mirrors/_instructions.html.haml4
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml10
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml4
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/pages/_destroy.haml6
-rw-r--r--app/views/projects/pages/_use.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml2
-rw-r--r--app/views/projects/pipelines/_info.html.haml14
-rw-r--r--app/views/projects/pipelines/charts.html.haml10
-rw-r--r--app/views/projects/pipelines/index.html.haml2
-rw-r--r--app/views/projects/pipelines/show.html.haml3
-rw-r--r--app/views/projects/project_members/_groups.html.haml17
-rw-r--r--app/views/projects/project_members/_team.html.haml22
-rw-r--r--app/views/projects/project_members/index.html.haml121
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml13
-rw-r--r--app/views/projects/protected_branches/shared/_index.html.haml13
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml17
-rw-r--r--app/views/projects/protected_tags/shared/_index.html.haml12
-rw-r--r--app/views/projects/protected_tags/shared/_tags_list.html.haml6
-rw-r--r--app/views/projects/registry/repositories/index.html.haml37
-rw-r--r--app/views/projects/runners/_group_runners.html.haml29
-rw-r--r--app/views/projects/runners/_index.html.haml3
-rw-r--r--app/views/projects/runners/_runner.html.haml2
-rw-r--r--app/views/projects/runners/_shared_runners.html.haml7
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml12
-rw-r--r--app/views/projects/runners/edit.html.haml2
-rw-r--r--app/views/projects/services/_form.html.haml6
-rw-r--r--app/views/projects/services/alerts/_help.html.haml1
-rw-r--r--app/views/projects/services/alerts/_top.html.haml8
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml8
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml19
-rw-r--r--app/views/projects/settings/operations/_alert_management.html.haml1
-rw-r--r--app/views/projects/show.html.haml2
-rw-r--r--app/views/projects/snippets/verify.html.haml2
-rw-r--r--app/views/projects/tracings/_tracing_button.html.haml2
-rw-r--r--app/views/shared/_recaptcha_form.html.haml5
-rw-r--r--app/views/shared/_search_settings.html.haml2
-rw-r--r--app/views/shared/_zen.html.haml4
-rw-r--r--app/views/shared/deploy_tokens/_index.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_revoke_modal.html.haml6
-rw-r--r--app/views/shared/empty_states/_snippets.html.haml4
-rw-r--r--app/views/shared/empty_states/_wikis.html.haml6
-rw-r--r--app/views/shared/integrations/_index.html.haml3
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml12
-rw-r--r--app/views/shared/issuable/form/_branch_chooser.html.haml19
-rw-r--r--app/views/shared/members/_badge.html.haml2
-rw-r--r--app/views/shared/members/_invite_member.html.haml4
-rw-r--r--app/views/shared/members/_member.html.haml3
-rw-r--r--app/views/shared/members/tab_pane/_form_item.html.haml (renamed from app/views/groups/group_members/tab_pane/_form_item.html.haml)0
-rw-r--r--app/views/shared/members/tab_pane/_header.html.haml (renamed from app/views/groups/group_members/tab_pane/_header.html.haml)0
-rw-r--r--app/views/shared/members/tab_pane/_title.html.haml (renamed from app/views/groups/group_members/tab_pane/_title.html.haml)0
-rw-r--r--app/views/shared/milestones/_header.html.haml7
-rw-r--r--app/views/shared/milestones/_milestone.html.haml5
-rw-r--r--app/views/shared/promotions/_promote_servicedesk.html.haml6
-rw-r--r--app/views/shared/runners/_form.html.haml6
-rw-r--r--app/views/shared/runners/_runner_description.html.haml14
-rw-r--r--app/views/shared/runners/_shared_runners_description.html.haml4
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml4
-rw-r--r--app/views/shared/wikis/_form.html.haml10
-rw-r--r--app/views/shared/wikis/_sidebar.html.haml18
-rw-r--r--app/views/shared/wikis/diff.html.haml11
-rw-r--r--app/views/shared/wikis/edit.html.haml19
-rw-r--r--app/views/shared/wikis/history.html.haml11
-rw-r--r--app/views/shared/wikis/pages.html.haml6
-rw-r--r--app/views/shared/wikis/show.html.haml2
-rw-r--r--app/views/sherlock/transactions/show.html.haml4
-rw-r--r--app/views/snippets/verify.html.haml2
-rw-r--r--app/workers/all_queues.yml78
-rw-r--r--app/workers/bulk_import_worker.rb53
-rw-r--r--app/workers/bulk_imports/entity_worker.rb23
-rw-r--r--app/workers/ci/daily_build_group_report_results_worker.rb2
-rw-r--r--app/workers/ci/pipeline_artifacts/coverage_report_worker.rb20
-rw-r--r--app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb23
-rw-r--r--app/workers/ci/pipelines/create_artifact_worker.rb18
-rw-r--r--app/workers/concerns/update_repository_storage_worker.rb42
-rw-r--r--app/workers/container_expiration_policies/cleanup_container_repository_worker.rb27
-rw-r--r--app/workers/experiments/record_conversion_event_worker.rb18
-rw-r--r--app/workers/expire_build_artifacts_worker.rb4
-rw-r--r--app/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker.rb15
-rw-r--r--app/workers/gitlab_performance_bar_stats_worker.rb3
-rw-r--r--app/workers/gitlab_usage_ping_worker.rb2
-rw-r--r--app/workers/issuable_export_csv_worker.rb56
-rw-r--r--app/workers/jira_connect/sync_branch_worker.rb3
-rw-r--r--app/workers/jira_connect/sync_deployments_worker.rb29
-rw-r--r--app/workers/jira_connect/sync_feature_flags_worker.rb24
-rw-r--r--app/workers/jira_connect/sync_merge_request_worker.rb3
-rw-r--r--app/workers/namespaces/onboarding_pipeline_created_worker.rb20
-rw-r--r--app/workers/object_pool/join_worker.rb2
-rw-r--r--app/workers/project_update_repository_storage_worker.rb32
-rw-r--r--app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb13
-rw-r--r--app/workers/snippet_update_repository_storage_worker.rb23
-rw-r--r--changelogs/unreleased/10io-fix-graphql-container-repository-tag-size-type.yml5
-rw-r--r--changelogs/unreleased/10io-use-empty-string-when-sending-local-file.yml5
-rw-r--r--changelogs/unreleased/13019-improve-error-messages-when-adding-namespaces-in-jira-connect-app.yml5
-rw-r--r--changelogs/unreleased/18816-forward-an-e-mail-to-an-existing-issue-as-a-new-comment.yml5
-rw-r--r--changelogs/unreleased/205578-enable-collect_package_events_redis-feature.yml5
-rw-r--r--changelogs/unreleased/211962-allow-group-owners-to-bypass-sso-enforce.yml5
-rw-r--r--changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml5
-rw-r--r--changelogs/unreleased/215309-improve-the-error-message-username-has-already-been-taken-on-user-.yml5
-rw-r--r--changelogs/unreleased/21686_persist_squash_commit_sha.yml5
-rw-r--r--changelogs/unreleased/21686_show_merge_request_for_squashed_commits.yml5
-rw-r--r--changelogs/unreleased/218624-roadmaps-conf-filter.yml5
-rw-r--r--changelogs/unreleased/218997-fj-add-snippet-repository-moves-api-endpoints.yml5
-rw-r--r--changelogs/unreleased/222970-207742-fix-500-webhooks-urls-not-encoded.yml5
-rw-r--r--changelogs/unreleased/223853-create-specialized-worker-for-refreshing-project-authorizations-du.yml6
-rw-r--r--changelogs/unreleased/224698-fe-operations.yml5
-rw-r--r--changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-in-app-assets-javascripts-vue.yml5
-rw-r--r--changelogs/unreleased/230728-nav-tabs-migration.yml5
-rw-r--r--changelogs/unreleased/231073-apply-gitlab-ui-button-styles-to-buttons-in-ee-app-views-projects-.yml5
-rw-r--r--changelogs/unreleased/23109-add-wiki-edit-button.yml5
-rw-r--r--changelogs/unreleased/231217-yo-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/23308-allow-commits-to-fork-from-maintainers.yml5
-rw-r--r--changelogs/unreleased/233423-fix-ide-commit-to-new-branch-errors.yml5
-rw-r--r--changelogs/unreleased/233658-migrate-alert-on-new-branch-page.yml5
-rw-r--r--changelogs/unreleased/23531-change-needs-failure-message.yml5
-rw-r--r--changelogs/unreleased/238854-fix-copy-sha-in-add-previous-commits-modal-doesnt-copy.yml5
-rw-r--r--changelogs/unreleased/241267-swap-audit-events-migration.yml5
-rw-r--r--changelogs/unreleased/24163-add-admin-filter-to-user-api.yml5
-rw-r--r--changelogs/unreleased/243857-matrix-job-status-allow-failure.yml5
-rw-r--r--changelogs/unreleased/244274-boards-migrate-deleteboard-board_store-function-to-vuex-action.yml5
-rw-r--r--changelogs/unreleased/247184-instument-file-by-file-mrs.yml5
-rw-r--r--changelogs/unreleased/247477-fix-double-render-errors-in-rescue-from.yml5
-rw-r--r--changelogs/unreleased/247936-fix-cut-off-file-blame-line-number.yml5
-rw-r--r--changelogs/unreleased/250659-allow-users-to-use-production-stage-end-event.yml5
-rw-r--r--changelogs/unreleased/250681_dont_unlink_forks_after_visibility_change.yml5
-rw-r--r--changelogs/unreleased/250681_fix_incorrect_validation_for_forked_projects.yml5
-rw-r--r--changelogs/unreleased/254325-remove-stages-from-dast-template.yml5
-rw-r--r--changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml5
-rw-r--r--changelogs/unreleased/256035-empty-changes-tab-on-merge-requests-should-not-show-file-browser-a.yml5
-rw-r--r--changelogs/unreleased/258206-remove-gitpod-feature-flag.yml5
-rw-r--r--changelogs/unreleased/262394-show-status-of-snippet-author.yml5
-rw-r--r--changelogs/unreleased/262857-creation-rotation-graphql.yml5
-rw-r--r--changelogs/unreleased/262860-create-shifts-table.yml5
-rw-r--r--changelogs/unreleased/263364-child-form-elements-should-be-indented.yml5
-rw-r--r--changelogs/unreleased/263408-improve-delete-snippet-test.yml5
-rw-r--r--changelogs/unreleased/270059-feature-flag-rollout-of-ci_pipeline_editor_page.yml5
-rw-r--r--changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml5
-rw-r--r--changelogs/unreleased/273544-add-group-mr-approval-settings-api.yml5
-rw-r--r--changelogs/unreleased/273555-move-time-tracker-help-state-to-the-sidebar-component.yml5
-rw-r--r--changelogs/unreleased/273657-remove-opsgenie-integration.yml6
-rw-r--r--changelogs/unreleased/276018-provisoned-accounts-welcome-email.yml5
-rw-r--r--changelogs/unreleased/276882-maven-dupe-fix.yml6
-rw-r--r--changelogs/unreleased/276882-package-maven-dupe-settings.yml5
-rw-r--r--changelogs/unreleased/276882-use-package-settings-maven.yml5
-rw-r--r--changelogs/unreleased/276900-use-the-expiration_policy_cleanup_status-to-report-the-cleanup-pol.yml5
-rw-r--r--changelogs/unreleased/276917-remove-default_merge_ref_for_diffs-feature-flag.yml6
-rw-r--r--changelogs/unreleased/276965-allow-basic-auth-for-generic-packages.yml5
-rw-r--r--changelogs/unreleased/277030-fix-error-tracking-mobile-layout.yml5
-rw-r--r--changelogs/unreleased/277134_populate_finding_uuid_values_for_vulnerability_feedback.yml6
-rw-r--r--changelogs/unreleased/278469-docs-feedback-hard-to-understand-code-coverage-colouring.yml6
-rw-r--r--changelogs/unreleased/280535-fix-mr-analytics-query-error.yml5
-rw-r--r--changelogs/unreleased/280545-improve-container-registry-client.yml5
-rw-r--r--changelogs/unreleased/280847-reduce-lcp-in-container-registry-index-page.yml5
-rw-r--r--changelogs/unreleased/281688-database-query-timeout-for-expired-job-artifacts.yml5
-rw-r--r--changelogs/unreleased/281824-convert-project-members-list-view-from-haml-to-vue-setup-tabs.yml5
-rw-r--r--changelogs/unreleased/281912_remove_jira_connect_full_namespace_sync_feature_flag.yml6
-rw-r--r--changelogs/unreleased/282299-grouping-swimlanes-choice-should-persist-after-board-has-been-edit.yml5
-rw-r--r--changelogs/unreleased/282458_remove_default_update_sequence_id_from_jira_connect_workers.yml5
-rw-r--r--changelogs/unreleased/283874-followup-to-mr-47253.yml5
-rw-r--r--changelogs/unreleased/283875_remove_reset_integrations_feature_flag.yml5
-rw-r--r--changelogs/unreleased/284640-fix-newline-in-custom-server-hook-renders-improperly.yml5
-rw-r--r--changelogs/unreleased/284686-fix-the-maven-packages-finder.yml5
-rw-r--r--changelogs/unreleased/285112-reduce-table-column-layout-shift.yml5
-rw-r--r--changelogs/unreleased/285334-maven-cross-group-sort.yml6
-rw-r--r--changelogs/unreleased/285467-package-registry-graphql-api.yml5
-rw-r--r--changelogs/unreleased/285509-global-breadcrumb-on-container-girestry-explorer.yml5
-rw-r--r--changelogs/unreleased/285634-Fix-confusion-button-text-when-importing-from-github.yml5
-rw-r--r--changelogs/unreleased/287636-auto-assign-author.yml5
-rw-r--r--changelogs/unreleased/287762-fix-multiple-vulnerabilities-requests.yml5
-rw-r--r--changelogs/unreleased/288325-wiki-avatar.yml5
-rw-r--r--changelogs/unreleased/288327-wiki-edit-automatically-focus-on-the-title-field.yml5
-rw-r--r--changelogs/unreleased/288329-wiki-submit-btn.yml5
-rw-r--r--changelogs/unreleased/288812-cleanup-policies-hard-limit-the-number-of-tags-to-delete.yml5
-rw-r--r--changelogs/unreleased/288812-properly-catch-tags-delete-errors-and-mark-repository-as-cleanup-u.yml5
-rw-r--r--changelogs/unreleased/289803-enable-ci_rules_variables.yml5
-rw-r--r--changelogs/unreleased/289972-remove-users-show-json-completely.yml5
-rw-r--r--changelogs/unreleased/290008-fix-background-migration-arguments.yml5
-rw-r--r--changelogs/unreleased/290008-remove-duplicate-services.yml5
-rw-r--r--changelogs/unreleased/290288-composer-cache-prep.yml5
-rw-r--r--changelogs/unreleased/290715-has_external_wiki_trigger.yml5
-rw-r--r--changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml5
-rw-r--r--changelogs/unreleased/291027-extend-diffs_metadata-with-project-and-user-names.yml5
-rw-r--r--changelogs/unreleased/292017-fj-fix-bug-when-cloning-snippet-different-from-master.yml5
-rw-r--r--changelogs/unreleased/292039-limit-rendering-of-commit-messages.yml5
-rw-r--r--changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml5
-rw-r--r--changelogs/unreleased/292498-webide-switch-before-closing.yml5
-rw-r--r--changelogs/unreleased/292516-daily-updates-for-devops-adoption.yml5
-rw-r--r--changelogs/unreleased/292517-enlarge-timeline-view-btn.yml5
-rw-r--r--changelogs/unreleased/292603-compliance-aggregated-usage-ping-metric.yml5
-rw-r--r--changelogs/unreleased/292658-include-keyword-for-cilint-graphql.yml5
-rw-r--r--changelogs/unreleased/292679-add-users-request-specs.yml5
-rw-r--r--changelogs/unreleased/292680-refactor-users_controller_spec-rb-ssh_keys.yml5
-rw-r--r--changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-2.yml5
-rw-r--r--changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-3.yml5
-rw-r--r--changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request.yml5
-rw-r--r--changelogs/unreleased/292827-track-action-metrics-for-a-merge-request.yml5
-rw-r--r--changelogs/unreleased/292902-move-to-createboard-mutation-instead-of-rest-api-call-updateboard.yml6
-rw-r--r--changelogs/unreleased/293679_introduce_dismissal_reason_for_vulnerability_feedback.yml5
-rw-r--r--changelogs/unreleased/293803-fix-jobs-admin-is-missing-CI-status-styles.yml5
-rw-r--r--changelogs/unreleased/293927-package-event-counts-are-not-aggregated-correctly.yml5
-rw-r--r--changelogs/unreleased/293967-refactor-users_controller_spec-gpg_keys.yml5
-rw-r--r--changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml5
-rw-r--r--changelogs/unreleased/294202-updated-at.yml5
-rw-r--r--changelogs/unreleased/294422-follow-up-from-fire-webhook-when-updating-or-removing-a-group-memb.yml5
-rw-r--r--changelogs/unreleased/295263-fork-icon-shrinks-if-branch-name-is-very-long.yml5
-rw-r--r--changelogs/unreleased/295494-fix-runner-admin-is-missing-ci-status-styles.yml5
-rw-r--r--changelogs/unreleased/295625-include-a-test-to-check-if-users-user-is-redirected-to-users-show.yml5
-rw-r--r--changelogs/unreleased/296380-update-docker-from-19-03-to-20-10-on-ci-cd-of-gitlab.yml5
-rw-r--r--changelogs/unreleased/296606-use-gl-badge-in-pipeline-url-component.yml5
-rw-r--r--changelogs/unreleased/296842-invalidate-reviewer-counter-on-create.yml5
-rw-r--r--changelogs/unreleased/296842-review-requests-counter-cache-invalidation.yml5
-rw-r--r--changelogs/unreleased/297007-add-back-milestones-to-incidents.yml5
-rw-r--r--changelogs/unreleased/297011-add-additional-aliases-for-reviewer-quick-commands.yml5
-rw-r--r--changelogs/unreleased/297503-cablett-remove-index.yml5
-rw-r--r--changelogs/unreleased/297569-inline-code-coverage-visualization-not-displaying-in-inline-mr-dif.yml5
-rw-r--r--changelogs/unreleased/298884-fix-broken-foss.yml5
-rw-r--r--changelogs/unreleased/30390-duplicate-group-label.yml5
-rw-r--r--changelogs/unreleased/30477-vfazio-alert-transfer-error.yml5
-rw-r--r--changelogs/unreleased/31343-remove-more-unnecessary-freeze.yml5
-rw-r--r--changelogs/unreleased/31343-remove-unneccessary-freeze.yml5
-rw-r--r--changelogs/unreleased/36423-nuget-group-level-project-api.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_index-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_revoke_modal-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsintrascations_show-html-haml.yml5
-rw-r--r--changelogs/unreleased/Fix-alignment-of-protected-tag-labels-on-mobile.yml5
-rw-r--r--changelogs/unreleased/Fix-long-deploy-token-name-overflows-revocation-modal.yml5
-rw-r--r--changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml5
-rw-r--r--changelogs/unreleased/ab-drop-tmp-index.yml5
-rw-r--r--changelogs/unreleased/add-api-command-to-delete-pending-invitation.yml5
-rw-r--r--changelogs/unreleased/add-flutter-cicd-template.yml5
-rw-r--r--changelogs/unreleased/add-icons.yml5
-rw-r--r--changelogs/unreleased/add-terraform-state-api-usage-tracking.yml5
-rw-r--r--changelogs/unreleased/add-user-id-to-user-webhook-data.yml5
-rw-r--r--changelogs/unreleased/add_access_request_endpoint.yml5
-rw-r--r--changelogs/unreleased/add_annotation_to_cilium_network_policies.yml5
-rw-r--r--changelogs/unreleased/add_boards_url.yml5
-rw-r--r--changelogs/unreleased/add_codeowners_supersede_for_web_ide.yml5
-rw-r--r--changelogs/unreleased/ajk-297358-fix-preloaded-pagination.yml5
-rw-r--r--changelogs/unreleased/ajk-ci-job-needs-type.yml5
-rw-r--r--changelogs/unreleased/ajk-gql-ci-performance-improvements.yml5
-rw-r--r--changelogs/unreleased/ajk-gql-merge-request-reviewers.yml5
-rw-r--r--changelogs/unreleased/ajk-group-member-policy-fix.yml5
-rw-r--r--changelogs/unreleased/align-admin-notes-label-to-the-left.yml5
-rw-r--r--changelogs/unreleased/allow-custom-rate-limiting-response.yml5
-rw-r--r--changelogs/unreleased/andr3-remove-sidebar-toggle-reviewers.yml5
-rw-r--r--changelogs/unreleased/aqualls-okr-autodevops.yml5
-rw-r--r--changelogs/unreleased/aqualls-okr-protected-branches.yml5
-rw-r--r--changelogs/unreleased/aqualls-okr-protected-tags.yml5
-rw-r--r--changelogs/unreleased/astoicescu-remove-limit-of-features-on-billing-page.yml5
-rw-r--r--changelogs/unreleased/board_api.yml5
-rw-r--r--changelogs/unreleased/cablett-issue-due.yml5
-rw-r--r--changelogs/unreleased/cc-verbiage-sast-in-core.yml5
-rw-r--r--changelogs/unreleased/change-clusters-helm-major-version-default-to-3.yml5
-rw-r--r--changelogs/unreleased/chore-disable-admin-mode-in-lib.yml5
-rw-r--r--changelogs/unreleased/chore-disable-admin-mode-remains.yml5
-rw-r--r--changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml5
-rw-r--r--changelogs/unreleased/ci-pipeline-artifacts-removal-cleanup.yml6
-rw-r--r--changelogs/unreleased/ci-project-config-path-variable.yml5
-rw-r--r--changelogs/unreleased/ci-setting-prevent-user-defined-ci-variables.yml5
-rw-r--r--changelogs/unreleased/dblessing_ldap_rake_db_create_fix.yml5
-rw-r--r--changelogs/unreleased/dblessing_redirect_deprecated_profile_paths.yml5
-rw-r--r--changelogs/unreleased/debian_distribution_architectures.yml5
-rw-r--r--changelogs/unreleased/debian_distributions.yml5
-rw-r--r--changelogs/unreleased/debian_file_metadatum.yml5
-rw-r--r--changelogs/unreleased/debian_package_file_upload.yml5
-rw-r--r--changelogs/unreleased/default-enable-set-user-availability-status.yml5
-rw-r--r--changelogs/unreleased/default-enabled-reviewer-approval-rules.yml5
-rw-r--r--changelogs/unreleased/deprecate-prometheus-listen-address.yml5
-rw-r--r--changelogs/unreleased/disable-pipelines-explore.yml5
-rw-r--r--changelogs/unreleased/display-artifacts-dropdown-on-mr-widget.yml5
-rw-r--r--changelogs/unreleased/doc-218997-fj-add-doc-for-snippet-api-repository-moves.yml5
-rw-r--r--changelogs/unreleased/docs-geo-update-patroni-support.yml6
-rw-r--r--changelogs/unreleased/docs-make-patroni-recommended.yml5
-rw-r--r--changelogs/unreleased/drop-tmp-index-on-emails-again.yml5
-rw-r--r--changelogs/unreleased/dz-5-minute-prod-app-ci-template.yml5
-rw-r--r--changelogs/unreleased/eb-fix-cobertura-empty-sources.yml5
-rw-r--r--changelogs/unreleased/eb-remove-test-failure-history-flag.yml5
-rw-r--r--changelogs/unreleased/epic-5076-spec-controllers-jwks_controller_spec-rb.yml5
-rw-r--r--changelogs/unreleased/epic-5076-spec-controllers-runner_setup_controller_spec-rb.yml5
-rw-r--r--changelogs/unreleased/epic_boards_epic_list.yml5
-rw-r--r--changelogs/unreleased/epic_boards_graphql_lists.yml5
-rw-r--r--changelogs/unreleased/eread-improve-badges-ui-text.yml5
-rw-r--r--changelogs/unreleased/eread-improve-service-desk-ui-text.yml5
-rw-r--r--changelogs/unreleased/expose-resolved_at-via-api.yml5
-rw-r--r--changelogs/unreleased/extend-ci-minutes-reset-window.yml5
-rw-r--r--changelogs/unreleased/feat-flag-copy-change.yml5
-rw-r--r--changelogs/unreleased/feature-visibility-mismatch-warning.yml5
-rw-r--r--changelogs/unreleased/ff-enable-ci-vis-by_-default.yml5
-rw-r--r--changelogs/unreleased/fix-500-settings-when-repository-does-not-exist.yml5
-rw-r--r--changelogs/unreleased/fix-abuse-reports-contains-html.yml5
-rw-r--r--changelogs/unreleased/fix-admin-project-overview-badge-alignment.yml5
-rw-r--r--changelogs/unreleased/fix-brand_new_project_guidelines.yml5
-rw-r--r--changelogs/unreleased/fix-casing-of-ci-lint-on-jobs-page.yml5
-rw-r--r--changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml5
-rw-r--r--changelogs/unreleased/fix-identicon-dark-mode.yml5
-rw-r--r--changelogs/unreleased/fix-overflowing-branch-name-on-profile.yml5
-rw-r--r--changelogs/unreleased/fix-padding-of-user-admin-search-bar.yml5
-rw-r--r--changelogs/unreleased/fix-secret-detection-template.yml5
-rw-r--r--changelogs/unreleased/fj-fix-n-plus-one-in-dashboard-snippets.yml5
-rw-r--r--changelogs/unreleased/fj-forbid-push-when-snippet-read-only.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-bulk-import-entity-worker.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-fix-bulk-import-graphql-extractor.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-limit-extractors-loaders-to-one.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-update-max-import-size-default-value.yml5
-rw-r--r--changelogs/unreleased/gitaly-client-identity.yml5
-rw-r--r--changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml5
-rw-r--r--changelogs/unreleased/id-bump-grape-helpers.yml5
-rw-r--r--changelogs/unreleased/id-bump-net-ldap.yml5
-rw-r--r--changelogs/unreleased/id-mark-optional_code_owners_sections-as-default.yml5
-rw-r--r--changelogs/unreleased/id-update-factory-bot.yml5
-rw-r--r--changelogs/unreleased/invisible-captcha-as-application-setting.yml5
-rw-r--r--changelogs/unreleased/jdb-juptyer-notebooks-latex-support.yml5
-rw-r--r--changelogs/unreleased/jivanvl-keep-latest-artifact-project-level.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-graphql-pipeline-analytics.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-total-duration-ci-cd-analytics.yml5
-rw-r--r--changelogs/unreleased/jv-ci-refspec-sha.yml5
-rw-r--r--changelogs/unreleased/keep_n_int.yml5
-rw-r--r--changelogs/unreleased/ld-add-calls-gitaly-to-fields.yml6
-rw-r--r--changelogs/unreleased/ld-fix-typo-on-designs-lfs-notice.yml5
-rw-r--r--changelogs/unreleased/lm-add-new-jobs-fields-graphql.yml5
-rw-r--r--changelogs/unreleased/lm-expose-errors-linter.yml5
-rw-r--r--changelogs/unreleased/lm-manual-bridge-support.yml5
-rw-r--r--changelogs/unreleased/lm-update-regex-group-ame.yml5
-rw-r--r--changelogs/unreleased/lm-update-w-connections-graphql.yml5
-rw-r--r--changelogs/unreleased/lmca-kotlin-native.yml5
-rw-r--r--changelogs/unreleased/lower-allocations-nav.yml5
-rw-r--r--changelogs/unreleased/lower-explore-pages.yml5
-rw-r--r--changelogs/unreleased/maintenance-fast-mersenne-twister.yml5
-rw-r--r--changelogs/unreleased/make-todo-filter-sort-input-full-width-on-mobile.yml5
-rw-r--r--changelogs/unreleased/mattkasa-downloadable-artifacts.yml5
-rw-r--r--changelogs/unreleased/mc-backstage-create-artifact-expiry-backfill-migration.yml5
-rw-r--r--changelogs/unreleased/mc-feature-associate-restarted-pipeline-triggerer.yml5
-rw-r--r--changelogs/unreleased/mjang-MR-approval-instance-level.yml5
-rw-r--r--changelogs/unreleased/mk-add-repo-checksum-task.yml5
-rw-r--r--changelogs/unreleased/mk-bump-workhorse.yml5
-rw-r--r--changelogs/unreleased/mk-configurable-sampling-intervals.yml5
-rw-r--r--changelogs/unreleased/mk-remove-extra-space.yml5
-rw-r--r--changelogs/unreleased/mo-refactor-pipeline-artifact-coverage.yml5
-rw-r--r--changelogs/unreleased/move_deployment_boards_to_core.yml5
-rw-r--r--changelogs/unreleased/mw-remove-column-compliance-frameworks-group_id.yml5
-rw-r--r--changelogs/unreleased/mw-replace-dropdown-input-fa-color-with-gray-500.yml5
-rw-r--r--changelogs/unreleased/nfriend-fix-release-milestone-order.yml5
-rw-r--r--changelogs/unreleased/nfriend-remove-pagination-from-deployment-frequency-api.yml5
-rw-r--r--changelogs/unreleased/oauth-pkce.yml5
-rw-r--r--changelogs/unreleased/optimize-release-page-markdown-rendering.yml5
-rw-r--r--changelogs/unreleased/override-mix-blend-mode-tertiary-buttons-dark-mode.yml5
-rw-r--r--changelogs/unreleased/pages-migration-task.yml5
-rw-r--r--changelogs/unreleased/pb-handle-git-errors-cleanup-refs.yml5
-rw-r--r--changelogs/unreleased/pb-keep-latest-artifact-setting-ui.yml5
-rw-r--r--changelogs/unreleased/peterhegman-hide-mobile-actions-field-with-no-buttons.yml5
-rw-r--r--changelogs/unreleased/ph-285635-suggestionAppliedResolvedStatus.yml5
-rw-r--r--changelogs/unreleased/ph-290850-mrStatusBoxPoll.yml5
-rw-r--r--changelogs/unreleased/pipeline-error-message.yml5
-rw-r--r--changelogs/unreleased/pipeline-status-conciseness.yml5
-rw-r--r--changelogs/unreleased/ps-step-3-use-ide-files-change-to-update-clientside-preview.yml5
-rw-r--r--changelogs/unreleased/puma-nakayoshi_fork.yml5
-rw-r--r--changelogs/unreleased/qmnguyen0711-731-add-ratelimit-headers-to-rackattack-responses.yml5
-rw-r--r--changelogs/unreleased/remove-ci_pipelines_for_merge_request_finder_new_cte-feature-flag.yml5
-rw-r--r--changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml5
-rw-r--r--changelogs/unreleased/remove-group-release-filter.yml5
-rw-r--r--changelogs/unreleased/remove-tmp-emails-index.yml5
-rw-r--r--changelogs/unreleased/rename-backlog-list-to-open-in-backend.yml5
-rw-r--r--changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml5
-rw-r--r--changelogs/unreleased/secret-detection-no-run-on-tag.yml5
-rw-r--r--changelogs/unreleased/security-workhorse-prometheus.yml5
-rw-r--r--changelogs/unreleased/selhorn-cleanup-uistrings-okr.yml5
-rw-r--r--changelogs/unreleased/selhorn-runner-lowercase-2.yml5
-rw-r--r--changelogs/unreleased/selhorn-runner-settings-okr.yml5
-rw-r--r--changelogs/unreleased/sh-accelerate-s3-copy.yml5
-rw-r--r--changelogs/unreleased/sh-cache-license-data.yml5
-rw-r--r--changelogs/unreleased/sh-disable-rebase-on-conflicts.yml5
-rw-r--r--changelogs/unreleased/sh-fix-nplus-one-graphql-group-issues.yml5
-rw-r--r--changelogs/unreleased/sh-quick-action-rebase.yml5
-rw-r--r--changelogs/unreleased/sh-rebase-quick-action-feedback.yml5
-rw-r--r--changelogs/unreleased/sh-remove-lfs-chunked-encoding-feature-flag.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-grape-1-5-0.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-webrick-1-6-1.yml5
-rw-r--r--changelogs/unreleased/shl-267553-remove-pat-creation-api-feature-flag.yml5
-rw-r--r--changelogs/unreleased/ss-copy-clipboard-email.yml5
-rw-r--r--changelogs/unreleased/state-lock-delete-validation.yml5
-rw-r--r--changelogs/unreleased/strip-newline-from-commit-description-on-project-overview.yml5
-rw-r--r--changelogs/unreleased/sy-remove-alerts-service.yml5
-rw-r--r--changelogs/unreleased/terraform-0-14-cache.yml5
-rw-r--r--changelogs/unreleased/tr-metric-image-delete.yml5
-rw-r--r--changelogs/unreleased/track-ci-template-usage-by-default.yml5
-rw-r--r--changelogs/unreleased/unify-nuget-auth-1.yml6
-rw-r--r--changelogs/unreleased/unify-nuget-auth-2.yml6
-rw-r--r--changelogs/unreleased/update-cluster-applications-to-0-37-0.yml5
-rw-r--r--changelogs/unreleased/update-dotnet-pj-archive.yml5
-rw-r--r--changelogs/unreleased/update-express-pj-archive.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-24-0.yml5
-rw-r--r--changelogs/unreleased/update-knative-for-helm-3.yml5
-rw-r--r--changelogs/unreleased/update-puma-to-v-5.yml5
-rw-r--r--changelogs/unreleased/update-rails-pj-archive.yml5
-rw-r--r--changelogs/unreleased/update-toast-position-set-status.yml5
-rw-r--r--changelogs/unreleased/upgrade-codequality-0-85-19.yml5
-rw-r--r--changelogs/unreleased/use-dynamic-import-for-gapi.yml5
-rw-r--r--changelogs/unreleased/use-git-packages-from-buster-on-build-qa-image.yml5
-rw-r--r--changelogs/unreleased/versionless-package-api-option.yml5
-rw-r--r--changelogs/unreleased/webide-markdown-center.yml5
-rw-r--r--changelogs/unreleased/wiki-header-spacing.yml5
-rw-r--r--changelogs/unreleased/yo-align-no-schedules.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge-ci.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge-runners.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-feature-highlight.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-jaegar.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-members.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-07160.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-19353.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-32789.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-49524.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-52337.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-63367.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-66129.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-67232.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-74981.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-80251.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-88070.yml5
-rw-r--r--changelogs/unreleased/yo-move-issue-gl-button.yml5
-rw-r--r--changelogs/unreleased/yo-remove-footer-members-list.yml5
-rw-r--r--config/application.rb13
-rw-r--r--config/feature_categories.yml4
-rw-r--r--config/feature_flags/development/cd_skipped_deployment_status.yml7
-rw-r--r--config/feature_flags/development/ci_allow_failure_with_exit_codes.yml2
-rw-r--r--config/feature_flags/development/ci_bridge_dependency_variables.yml7
-rw-r--r--config/feature_flags/development/ci_config_visualization_tab.yml2
-rw-r--r--config/feature_flags/development/ci_include_multiple_files_from_project.yml8
-rw-r--r--config/feature_flags/development/ci_pipeline_editor_page.yml2
-rw-r--r--config/feature_flags/development/ci_pipeline_open_merge_requests.yml3
-rw-r--r--config/feature_flags/development/ci_pipelines_for_merge_request_finder_new_cte.yml8
-rw-r--r--config/feature_flags/development/ci_rules_variables.yml2
-rw-r--r--config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml8
-rw-r--r--config/feature_flags/development/collect_package_events_redis.yml2
-rw-r--r--config/feature_flags/development/coverage_fuzzing_mr_widget.yml8
-rw-r--r--config/feature_flags/development/devops_adoption_feature.yml4
-rw-r--r--config/feature_flags/development/diff_check_with_paths_changed_rpc.yml8
-rw-r--r--config/feature_flags/development/drag_comment_selection.yml8
-rw-r--r--config/feature_flags/development/feature_flags_legacy_read_only.yml8
-rw-r--r--config/feature_flags/development/feature_flags_legacy_read_only_override.yml8
-rw-r--r--config/feature_flags/development/github_import_pull_request_reviews.yml8
-rw-r--r--config/feature_flags/development/gitpod.yml8
-rw-r--r--config/feature_flags/development/gl_tooltips.yml8
-rw-r--r--config/feature_flags/development/graphql_logging.yml4
-rw-r--r--config/feature_flags/development/graphql_pipeline_analytics.yml8
-rw-r--r--config/feature_flags/development/group_members_filtered_search.yml8
-rw-r--r--config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml8
-rw-r--r--config/feature_flags/development/invisible_captcha.yml8
-rw-r--r--config/feature_flags/development/jira_connect_full_namespace_sync.yml7
-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/lfs_chunked_encoding.yml8
-rw-r--r--config/feature_flags/development/merge_orchestration_service.yml8
-rw-r--r--config/feature_flags/development/merge_ref_auto_sync.yml8
-rw-r--r--config/feature_flags/development/merge_ref_auto_sync_lock.yml8
-rw-r--r--config/feature_flags/development/mr_commit_neighbor_nav.yml8
-rw-r--r--config/feature_flags/development/multiple_todos.yml8
-rw-r--r--config/feature_flags/development/new_jira_connect_ui.yml8
-rw-r--r--config/feature_flags/development/new_project_level_vsa_backend.yml8
-rw-r--r--config/feature_flags/development/non_public_artifacts.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_migration_mark_as_not_deployed.yml8
-rw-r--r--config/feature_flags/development/pat_creation_api_for_admin.yml7
-rw-r--r--config/feature_flags/development/reset_integrations.yml8
-rw-r--r--config/feature_flags/development/restrict_access_to_build_debug_mode.yml8
-rw-r--r--config/feature_flags/development/reviewer_approval_rules.yml2
-rw-r--r--config/feature_flags/development/s3_multithreaded_uploads.yml8
-rw-r--r--config/feature_flags/development/search_settings_in_page.yml8
-rw-r--r--config/feature_flags/development/security_on_demand_scans_site_validation.yml2
-rw-r--r--config/feature_flags/development/service_desk_custom_address.yml8
-rw-r--r--config/feature_flags/development/set_user_availability_status.yml2
-rw-r--r--config/feature_flags/development/show_inherited_labels.yml8
-rw-r--r--config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml8
-rw-r--r--config/feature_flags/development/sourcegraph.yml8
-rw-r--r--config/feature_flags/development/startup_css.yml8
-rw-r--r--config/feature_flags/development/suggestions_custom_commit.yml8
-rw-r--r--config/feature_flags/development/test_failure_history.yml8
-rw-r--r--config/feature_flags/development/track_unique_wiki_page_views.yml2
-rw-r--r--config/feature_flags/development/unified_diff_components.yml2
-rw-r--r--config/feature_flags/development/upload_middleware_jwt_params_handler.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_mr_diffs.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_mr_single_file_diffs.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_close_mr.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_create_mr.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_create_mr_comment.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_create_multiline_mr_comment.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_create_review_note.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_edit_mr_comment.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_edit_multiline_mr_comment.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_merge_mr.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_publish_review.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_remove_mr_comment.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_remove_multiline_mr_comment.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_reopen_mr.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_single_file_diffs.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_full_code_quality_report_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_group_code_coverage_visit_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_metrics_report_widget_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_web_performance_widget_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alerts_total_unique_counts.yml8
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incidents_total_unique_counts.yml8
-rw-r--r--config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml8
-rw-r--r--config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml8
-rw-r--r--config/feature_flags/development/value_stream_analytics_extended_form.yml8
-rw-r--r--config/feature_flags/development/variable_inside_variable.yml8
-rw-r--r--config/feature_flags/development/variables_in_include_section_ci.yml8
-rw-r--r--config/feature_flags/development/vue_2fa_recovery_codes.yml8
-rw-r--r--config/feature_flags/development/vue_group_members_list.yml8
-rw-r--r--config/feature_flags/development/widget_visibility_polling.yml8
-rw-r--r--config/feature_flags/development/wiki.yml2
-rw-r--r--config/feature_flags/development/wiki_front_matter.yml6
-rw-r--r--config/feature_flags/experiment/ci_syntax_templates_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/customize_homepage_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/default_to_issues_board_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_empty_group_version_a_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_version_b_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/null_hypothesis.yml1
-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/explore_pipeline_status.yml8
-rw-r--r--config/feature_flags/ops/scalability_ci_fetch_sha.yml8
-rw-r--r--config/gitlab.yml.example14
-rw-r--r--config/helpers/is_eslint.js2
-rw-r--r--config/helpers/vendor_dll_hash.js10
-rw-r--r--config/initializers/0_inject_feature_flags.rb39
-rw-r--r--config/initializers/1_settings.rb17
-rw-r--r--config/initializers/8_devise.rb2
-rw-r--r--config/initializers/carrierwave_patch.rb19
-rw-r--r--config/initializers/grape_patch.rb31
-rw-r--r--config/initializers/postgres_partitioning.rb2
-rw-r--r--config/initializers/trusted_proxies.rb2
-rw-r--r--config/karma.config.js12
-rw-r--r--config/known_invalid_graphql_queries.yml5
-rw-r--r--config/locales/en.yml1
-rw-r--r--config/metrics/counts_28d/deployments.yml15
-rw-r--r--config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml16
-rw-r--r--config/metrics/counts_all/deployments.yml15
-rw-r--r--config/metrics/license/recorded_at.yml16
-rw-r--r--config/metrics/license/uuid.yml17
-rw-r--r--config/metrics/schema.json66
-rw-r--r--config/metrics/settings/database_adapter.yml14
-rw-r--r--config/plugins/monaco_webpack.js2
-rw-r--r--config/puma.example.development.rb10
-rw-r--r--config/puma.rb.example12
-rw-r--r--config/puma_actioncable.example.development.rb10
-rw-r--r--config/routes.rb15
-rw-r--r--config/routes/group.rb2
-rw-r--r--config/routes/import.rb1
-rw-r--r--config/sidekiq_queues.yml10
-rw-r--r--config/webpack.config.js18
-rw-r--r--danger/frozen_string/Dangerfile29
-rw-r--r--danger/product_analytics/Dangerfile48
-rw-r--r--danger/product_intelligence/Dangerfile48
-rw-r--r--danger/roulette/Dangerfile7
-rw-r--r--danger/specs/Dangerfile17
-rw-r--r--data/whats_new/202009300001_13_04.yml2
-rw-r--r--data/whats_new/202012160001_13_07.yml51
-rw-r--r--db/fixtures/development/03_project.rb1
-rw-r--r--db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb2
-rw-r--r--db/migrate/20190402150158_backport_enterprise_schema.rb8
-rw-r--r--db/migrate/20190709220143_add_index_to_issues_relative_position.rb2
-rw-r--r--db/migrate/20190716144222_create_analytics_cycle_analytics_project_stages.rb13
-rw-r--r--db/migrate/20190729062536_create_analytics_cycle_analytics_group_stages.rb13
-rw-r--r--db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb7
-rw-r--r--db/migrate/20191118182722_add_index_to_environments_on_project_id_state_environment_type.rb4
-rw-r--r--db/migrate/20191121161018_add_project_id_name_version_package_type_index_to_packages_packages.rb2
-rw-r--r--db/migrate/20191129144631_add_index_to_resource_group_id.rb2
-rw-r--r--db/migrate/20191214175727_add_indexes_to_deployments_on_project_id_and_ref.rb2
-rw-r--r--db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb2
-rw-r--r--db/migrate/20200117112554_update_project_index_to_import_failures.rb4
-rw-r--r--db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb4
-rw-r--r--db/migrate/20200528054112_add_index_to_package_name.rb2
-rw-r--r--db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb4
-rw-r--r--db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb2
-rw-r--r--db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb2
-rw-r--r--db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb4
-rw-r--r--db/migrate/20201112215132_swap_partitioned_audit_events.rb15
-rw-r--r--db/migrate/20201204105300_create_packages_debian_file_metadata.rb29
-rw-r--r--db/migrate/20201204110700_create_packages_debian_project_distributions.rb62
-rw-r--r--db/migrate/20201204110800_create_packages_debian_group_distributions.rb62
-rw-r--r--db/migrate/20201204111000_create_packages_debian_project_architectures.rb38
-rw-r--r--db/migrate/20201204111100_create_packages_debian_group_architectures.rb38
-rw-r--r--db/migrate/20201204193952_keep_latest_artifact_project_level.rb19
-rw-r--r--db/migrate/20201208210209_create_incident_management_oncall_shifts.rb35
-rw-r--r--db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb26
-rw-r--r--db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb19
-rw-r--r--db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb17
-rw-r--r--db/migrate/20201214032220_add_has_external_wiki_trigger.rb52
-rw-r--r--db/migrate/20201214111858_add_container_registry_cleanup_tags_service_max_list_size_to_application_settings.rb11
-rw-r--r--db/migrate/20201214112752_add_app_settings_container_reg_cleanup_tags_service_max_list_size_constraint.rb19
-rw-r--r--db/migrate/20201214184020_add_epic_board_list.rb33
-rw-r--r--db/migrate/20201215205404_create_namespace_package_settings.rb25
-rw-r--r--db/migrate/20201216151616_add_squash_commit_sha_index.rb22
-rw-r--r--db/migrate/20201216154457_add_devops_adoption_snapshot_range_end.rb11
-rw-r--r--db/migrate/20201217070530_add_group_merge_request_approval_settings.rb24
-rw-r--r--db/migrate/20201217132603_create_elastic_reindexing_subtasks.rb56
-rw-r--r--db/migrate/20201221124036_add_devops_snapshot_index.rb19
-rw-r--r--db/migrate/20201221213415_change_clusters_helm_major_version_default_to_3.rb9
-rw-r--r--db/migrate/20201223114050_add_restrict_user_defined_variables_to_project_settings.rb19
-rw-r--r--db/migrate/20201224144948_migrate_coverage_report_worker.rb15
-rw-r--r--db/migrate/20201228184500_add_dismissal_reason_into_vulnerability_feedback_table.rb13
-rw-r--r--db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb9
-rw-r--r--db/migrate/20201230161206_add_rate_limiting_response_text_to_application_settings.rb12
-rw-r--r--db/migrate/20201230180202_create_onboarding_progress.rb36
-rw-r--r--db/migrate/20210101110640_set_limit_for_rate_limiting_response_text.rb16
-rw-r--r--db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb19
-rw-r--r--db/migrate/20210104163218_add_epic_board_position_index.rb18
-rw-r--r--db/migrate/20210106153021_drop_tmp_index_on_emails.rb20
-rw-r--r--db/migrate/20210108161039_update_max_import_size_default.rb9
-rw-r--r--db/migrate/20210112084512_drop_tmp_index_on_emails_again.rb18
-rw-r--r--db/migrate/20210114033715_remove_group_id_title_index.rb20
-rw-r--r--db/post_migrate/20190402224749_schedule_merge_request_assignees_migration_progress_check.rb2
-rw-r--r--db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb4
-rw-r--r--db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb6
-rw-r--r--db/post_migrate/20191030223057_backfill_version_author_and_created_at.rb2
-rw-r--r--db/post_migrate/20191104142124_nullify_users_role.rb2
-rw-r--r--db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb2
-rw-r--r--db/post_migrate/20200217225719_schedule_migrate_security_scans.rb2
-rw-r--r--db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb135
-rw-r--r--db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb21
-rw-r--r--db/post_migrate/20201207165956_remove_duplicate_services.rb14
-rw-r--r--db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb38
-rw-r--r--db/post_migrate/20201211090634_schedule_populate_finding_uuid_for_vulnerability_feedback.rb25
-rw-r--r--db/post_migrate/20201216185336_add_devops_adoption_snapshot_not_null.rb31
-rw-r--r--db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb21
-rw-r--r--db/post_migrate/20210105103649_delete_column_group_id_on_compliance_framework.rb9
-rw-r--r--db/post_migrate/20210107194543_remove_alerts_service_records.rb19
-rw-r--r--db/post_migrate/20210112143418_remove_duplicate_services2.rb29
-rw-r--r--db/schema_migrations/202007162342591
-rw-r--r--db/schema_migrations/202007162345181
-rw-r--r--db/schema_migrations/202011122151321
-rw-r--r--db/schema_migrations/202012041053001
-rw-r--r--db/schema_migrations/202012041107001
-rw-r--r--db/schema_migrations/202012041108001
-rw-r--r--db/schema_migrations/202012041110001
-rw-r--r--db/schema_migrations/202012041111001
-rw-r--r--db/schema_migrations/202012041939521
-rw-r--r--db/schema_migrations/202012071659561
-rw-r--r--db/schema_migrations/202012081751171
-rw-r--r--db/schema_migrations/202012082102091
-rw-r--r--db/schema_migrations/202012091639581
-rw-r--r--db/schema_migrations/202012091935511
-rw-r--r--db/schema_migrations/202012110906341
-rw-r--r--db/schema_migrations/202012140000001
-rw-r--r--db/schema_migrations/202012140322201
-rw-r--r--db/schema_migrations/202012141118581
-rw-r--r--db/schema_migrations/202012141127521
-rw-r--r--db/schema_migrations/202012141840201
-rw-r--r--db/schema_migrations/202012152054041
-rw-r--r--db/schema_migrations/202012161516161
-rw-r--r--db/schema_migrations/202012161544571
-rw-r--r--db/schema_migrations/202012161853361
-rw-r--r--db/schema_migrations/202012170705301
-rw-r--r--db/schema_migrations/202012171326031
-rw-r--r--db/schema_migrations/202012211240361
-rw-r--r--db/schema_migrations/202012212134151
-rw-r--r--db/schema_migrations/202012230122311
-rw-r--r--db/schema_migrations/202012231140501
-rw-r--r--db/schema_migrations/202012241449481
-rw-r--r--db/schema_migrations/202012281845001
-rw-r--r--db/schema_migrations/202012291059481
-rw-r--r--db/schema_migrations/202012301612061
-rw-r--r--db/schema_migrations/202012301802021
-rw-r--r--db/schema_migrations/202101011106401
-rw-r--r--db/schema_migrations/202101021641211
-rw-r--r--db/schema_migrations/202101041632181
-rw-r--r--db/schema_migrations/202101051036491
-rw-r--r--db/schema_migrations/202101061530211
-rw-r--r--db/schema_migrations/202101071945431
-rw-r--r--db/schema_migrations/202101081610391
-rw-r--r--db/schema_migrations/202101120845121
-rw-r--r--db/schema_migrations/202101121434181
-rw-r--r--db/schema_migrations/202101140337151
-rw-r--r--db/structure.sql474
-rw-r--r--doc/.vale/gitlab/Acronyms.yml2
-rw-r--r--doc/.vale/gitlab/Admin.yml2
-rw-r--r--doc/.vale/gitlab/AlertBoxStyle.yml7
-rw-r--r--doc/.vale/gitlab/British.yml2
-rw-r--r--doc/.vale/gitlab/CurlStringsQuoted.yml4
-rw-r--r--doc/.vale/gitlab/FutureTense.yml3
-rw-r--r--doc/.vale/gitlab/OxfordComma.yml3
-rw-r--r--doc/.vale/gitlab/ReferenceLinks.yml2
-rw-r--r--doc/.vale/gitlab/SentenceSpacing.yml5
-rw-r--r--doc/.vale/gitlab/Spelling.yml3
-rw-r--r--doc/.vale/gitlab/SubstitutionSuggestions.yml6
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml4
-rw-r--r--doc/.vale/gitlab/Substitutions.yml4
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt2
-rw-r--r--doc/administration/audit_events.md2
-rw-r--r--doc/administration/auth/jwt.md2
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/ldap/index.md6
-rw-r--r--doc/administration/compliance.md28
-rw-r--r--doc/administration/geo/disaster_recovery/index.md75
-rw-r--r--doc/administration/geo/index.md6
-rw-r--r--doc/administration/geo/replication/configuration.md5
-rw-r--r--doc/administration/geo/setup/database.md171
-rw-r--r--doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.pngbin21779 -> 0 bytes
-rw-r--r--doc/administration/gitaly/index.md20
-rw-r--r--doc/administration/gitaly/praefect.md13
-rw-r--r--doc/administration/housekeeping.md17
-rw-r--r--doc/administration/incoming_email.md2
-rw-r--r--doc/administration/index.md41
-rw-r--r--doc/administration/integration/plantuml.md12
-rw-r--r--doc/administration/job_logs.md4
-rw-r--r--doc/administration/monitoring/performance/index.md11
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_exporter.md24
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md1
-rw-r--r--doc/administration/nfs.md7
-rw-r--r--doc/administration/object_storage.md10
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md2
-rw-r--r--doc/administration/operations/moving_repositories.md6
-rw-r--r--doc/administration/packages/container_registry.md55
-rw-r--r--doc/administration/pages/index.md89
-rw-r--r--doc/administration/pages/source.md38
-rw-r--r--doc/administration/postgresql/pgbouncer.md11
-rw-r--r--doc/administration/postgresql/replication_and_failover.md1186
-rw-r--r--doc/administration/raketasks/check.md58
-rw-r--r--doc/administration/raketasks/github_import.md2
-rw-r--r--doc/administration/raketasks/storage.md4
-rw-r--r--doc/administration/reference_architectures/10k_users.md198
-rw-r--r--doc/administration/reference_architectures/1k_users.md3
-rw-r--r--doc/administration/reference_architectures/25k_users.md198
-rw-r--r--doc/administration/reference_architectures/2k_users.md13
-rw-r--r--doc/administration/reference_architectures/3k_users.md241
-rw-r--r--doc/administration/reference_architectures/50k_users.md198
-rw-r--r--doc/administration/reference_architectures/5k_users.md228
-rw-r--r--doc/administration/reference_architectures/index.md8
-rw-r--r--doc/administration/reference_architectures/troubleshooting.md44
-rw-r--r--doc/administration/repository_storage_paths.md6
-rw-r--r--doc/administration/terraform_state.md7
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md38
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md8
-rw-r--r--doc/administration/troubleshooting/postgresql.md14
-rw-r--r--doc/administration/troubleshooting/tracing_correlation_id.md2
-rw-r--r--doc/administration/uploads.md60
-rw-r--r--doc/api/README.md73
-rw-r--r--doc/api/api_resources.md1
-rw-r--r--doc/api/appearance.md4
-rw-r--r--doc/api/audit_events.md4
-rw-r--r--doc/api/avatar.md2
-rw-r--r--doc/api/boards.md2
-rw-r--r--doc/api/container_registry.md9
-rw-r--r--doc/api/deploy_keys.md6
-rw-r--r--doc/api/deployments.md2
-rw-r--r--doc/api/discussions.md3
-rw-r--r--doc/api/epic_links.md2
-rw-r--r--doc/api/epics.md41
-rw-r--r--doc/api/features.md4
-rw-r--r--doc/api/graphql/img/users_query_example_v13_8.pngbin0 -> 200017 bytes
-rw-r--r--doc/api/graphql/index.md4
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql3359
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json6326
-rw-r--r--doc/api/graphql/reference/index.md529
-rw-r--r--doc/api/graphql/users_example.md109
-rw-r--r--doc/api/group_boards.md22
-rw-r--r--doc/api/group_import_export.md2
-rw-r--r--doc/api/groups.md26
-rw-r--r--doc/api/import.md2
-rw-r--r--doc/api/invitations.md24
-rw-r--r--doc/api/issues.md61
-rw-r--r--doc/api/job_artifacts.md8
-rw-r--r--doc/api/members.md6
-rw-r--r--doc/api/merge_requests.md484
-rw-r--r--doc/api/notes.md4
-rw-r--r--doc/api/oauth2.md126
-rw-r--r--doc/api/openapi/openapi.yaml54
-rw-r--r--doc/api/openapi/v4/access_requests.yaml381
-rw-r--r--doc/api/packages.md10
-rw-r--r--doc/api/personal_access_tokens.md5
-rw-r--r--doc/api/project_import_export.md2
-rw-r--r--doc/api/project_level_variables.md6
-rw-r--r--doc/api/project_repository_storage_moves.md3
-rw-r--r--doc/api/projects.md82
-rw-r--r--doc/api/releases/index.md26
-rw-r--r--doc/api/releases/links.md10
-rw-r--r--doc/api/scim.md10
-rw-r--r--doc/api/search.md16
-rw-r--r--doc/api/services.md6
-rw-r--r--doc/api/settings.md10
-rw-r--r--doc/api/snippet_repository_storage_moves.md293
-rw-r--r--doc/api/users.md35
-rw-r--r--doc/architecture/blueprints/cloud_native_gitlab_pages/index.md4
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md24
-rw-r--r--doc/ci/README.md14
-rw-r--r--doc/ci/caching/index.md31
-rw-r--r--doc/ci/cloud_deployment/index.md19
-rw-r--r--doc/ci/docker/using_docker_build.md97
-rw-r--r--doc/ci/docker/using_docker_images.md255
-rw-r--r--doc/ci/docker/using_kaniko.md35
-rw-r--r--doc/ci/environments/deployment_safety.md72
-rw-r--r--doc/ci/environments/incremental_rollouts.md14
-rw-r--r--doc/ci/environments/index.md107
-rw-r--r--doc/ci/environments/protected_environments.md14
-rw-r--r--doc/ci/examples/README.md42
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md5
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md17
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md58
-rw-r--r--doc/ci/examples/deployment/README.md6
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md36
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md5
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md6
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md6
-rw-r--r--doc/ci/examples/semantic-release.md2
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md10
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-new.pngbin6602 -> 0 bytes
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.pngbin25235 -> 0 bytes
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.pngbin15794 -> 0 bytes
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.pngbin32253 -> 0 bytes
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.pngbin57203 -> 0 bytes
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md397
-rw-r--r--doc/ci/img/environments_available.pngbin8582 -> 0 bytes
-rw-r--r--doc/ci/img/environments_available_13_7.pngbin0 -> 29124 bytes
-rw-r--r--doc/ci/introduction/index.md4
-rw-r--r--doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.pngbin0 -> 15697 bytes
-rw-r--r--doc/ci/merge_request_pipelines/index.md4
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md4
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md10
-rw-r--r--doc/ci/multi_project_pipelines.md3
-rw-r--r--doc/ci/pipeline_editor/img/ci_config_visualization_hover_v13_7.png (renamed from doc/ci/yaml/img/ci_config_visualization_hover_v13_7.png)bin19870 -> 19870 bytes
-rw-r--r--doc/ci/pipeline_editor/img/ci_config_visualization_v13_7.png (renamed from doc/ci/yaml/img/ci_config_visualization_v13_7.png)bin18585 -> 18585 bytes
-rw-r--r--doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.pngbin0 -> 18744 bytes
-rw-r--r--doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.pngbin0 -> 20402 bytes
-rw-r--r--doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.pngbin0 -> 10399 bytes
-rw-r--r--doc/ci/pipeline_editor/index.md133
-rw-r--r--doc/ci/pipelines/img/job_artifacts_merge_request.pngbin0 -> 40817 bytes
-rw-r--r--doc/ci/pipelines/index.md23
-rw-r--r--doc/ci/pipelines/job_artifacts.md25
-rw-r--r--doc/ci/pipelines/schedules.md2
-rw-r--r--doc/ci/quick_start/README.md2
-rw-r--r--doc/ci/review_apps/index.md22
-rw-r--r--doc/ci/runners/README.md18
-rw-r--r--doc/ci/unit_test_reports.md27
-rw-r--r--doc/ci/variables/README.md61
-rw-r--r--doc/ci/variables/deprecated_variables.md36
-rw-r--r--doc/ci/variables/predefined_variables.md240
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md1
-rw-r--r--doc/ci/yaml/README.md217
-rw-r--r--doc/ci/yaml/gitlab_ci_yaml.md2
-rw-r--r--doc/ci/yaml/visualization.md52
-rw-r--r--doc/development/README.md9
-rw-r--r--doc/development/adding_database_indexes.md31
-rw-r--r--doc/development/agent/identity.md4
-rw-r--r--doc/development/agent/local.md44
-rw-r--r--doc/development/api_graphql_styleguide.md7
-rw-r--r--doc/development/changelog.md4
-rw-r--r--doc/development/cicd/templates.md20
-rw-r--r--doc/development/code_review.md17
-rw-r--r--doc/development/contributing/style_guides.md6
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md35
-rw-r--r--doc/development/database_review.md4
-rw-r--r--doc/development/documentation/feature_flags.md8
-rw-r--r--doc/development/documentation/index.md18
-rw-r--r--doc/development/documentation/styleguide/index.md77
-rw-r--r--doc/development/documentation/testing.md12
-rw-r--r--doc/development/elasticsearch.md48
-rw-r--r--doc/development/event_tracking/backend.md6
-rw-r--r--doc/development/event_tracking/frontend.md6
-rw-r--r--doc/development/event_tracking/index.md6
-rw-r--r--doc/development/experiment_guide/index.md33
-rw-r--r--doc/development/fe_guide/dependencies.md7
-rw-r--r--doc/development/fe_guide/editor_lite.md9
-rw-r--r--doc/development/fe_guide/event_tracking.md6
-rw-r--r--doc/development/fe_guide/graphql.md5
-rw-r--r--doc/development/fe_guide/icons.md7
-rw-r--r--doc/development/fe_guide/performance.md4
-rw-r--r--doc/development/fe_guide/style/javascript.md2
-rw-r--r--doc/development/fe_guide/style/vue.md84
-rw-r--r--doc/development/fe_guide/vue.md107
-rw-r--r--doc/development/feature_categorization/index.md2
-rw-r--r--doc/development/feature_flags/controls.md1
-rw-r--r--doc/development/feature_flags/development.md12
-rw-r--r--doc/development/feature_flags/index.md58
-rw-r--r--doc/development/feature_flags/process.md27
-rw-r--r--doc/development/foreign_keys.md2
-rw-r--r--doc/development/geo/framework.md261
-rw-r--r--doc/development/gitaly.md44
-rw-r--r--doc/development/go_guide/index.md9
-rw-r--r--doc/development/gotchas.md2
-rw-r--r--doc/development/img/snowplow_flow.pngbin16589 -> 6029 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_annotation.pngbin0 -> 13544 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_debug_1.pngbin0 -> 41296 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_debug_2.pngbin0 -> 37361 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_debug_3.pngbin0 -> 51282 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_filters.pngbin0 -> 10648 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_metrics.pngbin0 -> 38776 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_time_customization.pngbin0 -> 20025 bytes
-rw-r--r--doc/development/img/stage_group_dashboards_time_filter.pngbin0 -> 22641 bytes
-rw-r--r--doc/development/instrumentation.md2
-rw-r--r--doc/development/integrations/codesandbox.md10
-rw-r--r--doc/development/integrations/jenkins.md2
-rw-r--r--doc/development/integrations/jira_connect.md21
-rw-r--r--doc/development/internal_api.md19
-rw-r--r--doc/development/iterating_tables_in_batches.md25
-rw-r--r--doc/development/migration_style_guide.md6
-rw-r--r--doc/development/new_fe_guide/development/accessibility.md2
-rw-r--r--doc/development/packages.md18
-rw-r--r--doc/development/pipelines.md113
-rw-r--r--doc/development/product_analytics/event_dictionary.md6
-rw-r--r--doc/development/product_analytics/index.md11
-rw-r--r--doc/development/product_analytics/snowplow.md616
-rw-r--r--doc/development/product_analytics/usage_ping.md1059
-rw-r--r--doc/development/profiling.md89
-rw-r--r--doc/development/query_performance.md2
-rw-r--r--doc/development/secure_coding_guidelines.md2
-rw-r--r--doc/development/sidekiq_style_guide.md2
-rw-r--r--doc/development/snowplow.md623
-rw-r--r--doc/development/stage_group_dashboards.md148
-rw-r--r--doc/development/telemetry/event_dictionary.md4
-rw-r--r--doc/development/telemetry/index.md4
-rw-r--r--doc/development/telemetry/snowplow.md4
-rw-r--r--doc/development/telemetry/usage_ping.md4
-rw-r--r--doc/development/testing_guide/best_practices.md35
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md82
-rw-r--r--doc/development/testing_guide/frontend_testing.md47
-rw-r--r--doc/development/testing_guide/testing_levels.md6
-rw-r--r--doc/development/usage_ping.md1151
-rw-r--r--doc/development/usage_ping/metrics_dictionary.md73
-rw-r--r--doc/gitlab-basics/create-branch.md2
-rw-r--r--doc/gitlab-basics/create-project.md2
-rw-r--r--doc/gitlab-basics/start-using-git.md11
-rw-r--r--doc/install/README.md24
-rw-r--r--doc/install/aws/index.md33
-rw-r--r--doc/install/google_cloud_platform/index.md2
-rw-r--r--doc/install/installation.md49
-rw-r--r--doc/install/requirements.md15
-rw-r--r--doc/integration/bitbucket.md7
-rw-r--r--doc/integration/elasticsearch.md41
-rw-r--r--doc/integration/github.md2
-rw-r--r--doc/integration/gitlab.md19
-rw-r--r--doc/integration/gitpod.md35
-rw-r--r--doc/integration/jira_development_panel.md11
-rw-r--r--doc/integration/vault.md16
-rw-r--r--doc/operations/feature_flags.md8
-rw-r--r--doc/operations/incident_management/alert_integrations.md13
-rw-r--r--doc/operations/incident_management/img/incident_metrics_tab_v13_8.pngbin0 -> 19907 bytes
-rw-r--r--doc/operations/incident_management/img/metric_image_url_dialog_v13_8.pngbin0 -> 15876 bytes
-rw-r--r--doc/operations/incident_management/incidents.md18
-rw-r--r--doc/public_access/img/project_visibility_confirmation_v12_6.pngbin33696 -> 0 bytes
-rw-r--r--doc/public_access/public_access.md10
-rw-r--r--doc/push_rules/push_rules.md36
-rw-r--r--doc/raketasks/README.md2
-rw-r--r--doc/raketasks/backup_restore.md34
-rw-r--r--doc/raketasks/migrate_snippets.md2
-rw-r--r--doc/security/rack_attack.md6
-rw-r--r--doc/security/webhooks.md2
-rw-r--r--doc/subscriptions/gitlab_com/index.md53
-rw-r--r--doc/subscriptions/index.md4
-rw-r--r--doc/subscriptions/self_managed/index.md67
-rw-r--r--doc/system_hooks/system_hooks.md4
-rw-r--r--doc/telemetry/index.md4
-rw-r--r--doc/telemetry/snowplow.md4
-rw-r--r--doc/topics/autodevops/index.md16
-rw-r--r--doc/topics/autodevops/quick_start_guide.md49
-rw-r--r--doc/topics/autodevops/upgrading_auto_deploy_dependencies.md4
-rw-r--r--doc/topics/git/lfs/index.md2
-rw-r--r--doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md4
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md5
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md2
-rw-r--r--doc/topics/git/partial_clone.md2
-rw-r--r--doc/topics/gitlab_flow.md2
-rw-r--r--doc/topics/web_application_firewall/index.md97
-rw-r--r--doc/topics/web_application_firewall/quick_start_guide.md258
-rw-r--r--doc/university/training/topics/getting_started.md2
-rw-r--r--doc/university/training/topics/unstage.md2
-rw-r--r--doc/update/README.md2
-rw-r--r--doc/update/mysql_to_postgresql.md4
-rw-r--r--doc/update/patch_versions.md4
-rw-r--r--doc/update/restore_after_failure.md4
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md4
-rw-r--r--doc/update/upgrading_from_source.md4
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md4
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md18
-rw-r--r--doc/user/admin_area/analytics/user_cohorts.md29
-rw-r--r--doc/user/admin_area/img/license_admin_area.pngbin27826 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/license_upload.pngbin10043 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/license_upload_v13_8.pngbin0 -> 32860 bytes
-rw-r--r--doc/user/admin_area/license.md30
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md14
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md8
-rw-r--r--doc/user/admin_area/settings/index.md2
-rw-r--r--doc/user/admin_area/settings/project_integration_management.md16
-rw-r--r--doc/user/admin_area/settings/protected_paths.md6
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md7
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md65
-rw-r--r--doc/user/analytics/ci_cd_analytics.md33
-rw-r--r--doc/user/analytics/img/deployment_frequency_chart_v13_8.pngbin0 -> 40919 bytes
-rw-r--r--doc/user/analytics/img/pipelines_duration_chart.png (renamed from doc/ci/pipelines/img/pipelines_duration_chart.png)bin10587 -> 10587 bytes
-rw-r--r--doc/user/analytics/img/pipelines_success_chart.png (renamed from doc/ci/pipelines/img/pipelines_success_chart.png)bin23249 -> 23249 bytes
-rw-r--r--doc/user/analytics/index.md2
-rw-r--r--doc/user/application_security/api_fuzzing/index.md1
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md4
-rw-r--r--doc/user/application_security/dast/index.md221
-rw-r--r--doc/user/application_security/dependency_scanning/index.md15
-rw-r--r--doc/user/application_security/sast/analyzers.md24
-rw-r--r--doc/user/application_security/sast/index.md27
-rw-r--r--doc/user/application_security/secret_detection/index.md1
-rw-r--r--doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.pngbin86032 -> 31816 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md3
-rw-r--r--doc/user/application_security/vulnerabilities/severities.md70
-rw-r--r--doc/user/clusters/agent/index.md16
-rw-r--r--doc/user/clusters/agent/runner.md452
-rw-r--r--doc/user/clusters/applications.md17
-rw-r--r--doc/user/compliance/license_compliance/index.md2
-rw-r--r--doc/user/discussions/img/threads_resolved.pngbin3976 -> 0 bytes
-rw-r--r--doc/user/discussions/index.md21
-rw-r--r--doc/user/gitlab_com/index.md34
-rw-r--r--doc/user/group/import/img/bulk_imports_v13_8.pngbin0 -> 61983 bytes
-rw-r--r--doc/user/group/import/img/import_panel_v13_8.pngbin0 -> 107428 bytes
-rw-r--r--doc/user/group/import/img/new_group_navigation_v13_8.pngbin0 -> 39500 bytes
-rw-r--r--doc/user/group/import/index.md91
-rw-r--r--doc/user/group/index.md37
-rw-r--r--doc/user/group/iterations/index.md16
-rw-r--r--doc/user/group/roadmap/img/roadmap_filters_v13_7.pngbin21615 -> 0 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_filters_v13_8.pngbin0 -> 20766 bytes
-rw-r--r--doc/user/group/roadmap/index.md3
-rw-r--r--doc/user/group/saml_sso/group_managed_accounts.md4
-rw-r--r--doc/user/group/saml_sso/index.md14
-rw-r--r--doc/user/group/saml_sso/scim_setup.md6
-rw-r--r--doc/user/group/settings/import_export.md2
-rw-r--r--doc/user/group/subgroups/img/group_members_filter_v12_6.pngbin6381 -> 0 bytes
-rw-r--r--doc/user/group/subgroups/index.md2
-rw-r--r--doc/user/group/value_stream_analytics/index.md9
-rw-r--r--doc/user/infrastructure/img/terraform_list_view_actions_v13_8.pngbin0 -> 36949 bytes
-rw-r--r--doc/user/infrastructure/img/terraform_list_view_v13_5.pngbin13849 -> 0 bytes
-rw-r--r--doc/user/infrastructure/img/terraform_list_view_v13_8.pngbin0 -> 74877 bytes
-rw-r--r--doc/user/infrastructure/index.md69
-rw-r--r--doc/user/infrastructure/mr_integration.md8
-rw-r--r--doc/user/infrastructure/terraform_state.md79
-rw-r--r--doc/user/packages/composer_repository/index.md18
-rw-r--r--doc/user/packages/conan_repository/index.md18
-rw-r--r--doc/user/packages/container_registry/index.md19
-rw-r--r--doc/user/packages/dependency_proxy/index.md3
-rw-r--r--doc/user/packages/generic_packages/index.md27
-rw-r--r--doc/user/packages/npm_registry/index.md36
-rw-r--r--doc/user/packages/nuget_repository/index.md109
-rw-r--r--doc/user/packages/pypi_repository/index.md17
-rw-r--r--doc/user/packages/workflows/project_registry.md2
-rw-r--r--doc/user/permissions.md5
-rw-r--r--doc/user/profile/account/two_factor_authentication.md41
-rw-r--r--doc/user/profile/index.md27
-rw-r--r--doc/user/profile/notifications.md4
-rw-r--r--doc/user/profile/personal_access_tokens.md2
-rw-r--r--doc/user/project/canary_deployments.md7
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md1
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md2
-rw-r--r--doc/user/project/clusters/index.md20
-rw-r--r--doc/user/project/clusters/protect/container_host_security/index.md59
-rw-r--r--doc/user/project/clusters/protect/container_host_security/quick_start_guide.md81
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md70
-rw-r--r--doc/user/project/clusters/protect/container_network_security/quick_start_guide.md153
-rw-r--r--doc/user/project/clusters/protect/index.md29
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png (renamed from doc/topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png)bin51416 -> 51416 bytes
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png (renamed from doc/topics/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png)bin44243 -> 44243 bytes
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png (renamed from doc/topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png)bin54688 -> 54688 bytes
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/index.md103
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md265
-rw-r--r--doc/user/project/clusters/runbooks/index.md2
-rw-r--r--doc/user/project/clusters/securing.md155
-rw-r--r--doc/user/project/clusters/serverless/index.md1
-rw-r--r--doc/user/project/code_owners.md46
-rw-r--r--doc/user/project/deploy_boards.md21
-rw-r--r--doc/user/project/deploy_keys/index.md10
-rw-r--r--doc/user/project/deploy_tokens/img/deploy_tokens_ui.pngbin101571 -> 35336 bytes
-rw-r--r--doc/user/project/deploy_tokens/index.md14
-rw-r--r--doc/user/project/description_templates.md2
-rw-r--r--doc/user/project/img/canary_weight.pngbin52101 -> 14559 bytes
-rw-r--r--doc/user/project/img/description_templates_issue_settings.pngbin11103 -> 9315 bytes
-rw-r--r--doc/user/project/img/optional_code_owners_sections_v13_8.pngbin0 -> 104264 bytes
-rw-r--r--doc/user/project/img/protected_branches_deploy_keys_v13_5.pngbin46325 -> 16142 bytes
-rw-r--r--doc/user/project/img/service_desk_custom_email_address_v13_0.pngbin50234 -> 0 bytes
-rw-r--r--doc/user/project/img/service_desk_enabled.pngbin19003 -> 0 bytes
-rw-r--r--doc/user/project/import/github.md2
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md2
-rw-r--r--doc/user/project/integrations/img/webhooks_ssl.pngbin58529 -> 0 bytes
-rw-r--r--doc/user/project/integrations/jira_integrations.md2
-rw-r--r--doc/user/project/integrations/prometheus.md1
-rw-r--r--doc/user/project/integrations/webhooks.md153
-rw-r--r--doc/user/project/issue_board.md27
-rw-r--r--doc/user/project/issues/confidential_issues.md47
-rw-r--r--doc/user/project/issues/crosslinking_issues.md11
-rw-r--r--doc/user/project/issues/csv_export.md2
-rw-r--r--doc/user/project/issues/due_dates.md23
-rw-r--r--doc/user/project/issues/img/due_dates_issues_index_page.pngbin19302 -> 0 bytes
-rw-r--r--doc/user/project/issues/index.md51
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md8
-rw-r--r--doc/user/project/issues/managing_issues.md75
-rw-r--r--doc/user/project/labels.md6
-rw-r--r--doc/user/project/members/img/access_requests_management.pngbin10436 -> 0 bytes
-rw-r--r--doc/user/project/members/img/access_requests_management_13_8.pngbin0 -> 21685 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_accept.pngbin16878 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_accept_13_8.pngbin0 -> 18139 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_ready.pngbin28171 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_ready_13_8.pngbin0 -> 28850 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_search.pngbin29628 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_search_13_8.pngbin0 -> 29293 bytes
-rw-r--r--doc/user/project/members/img/add_user_give_permissions.pngbin36619 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_give_permissions_13_8.pngbin0 -> 69132 bytes
-rw-r--r--doc/user/project/members/img/add_user_import_members_from_another_project.pngbin25333 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_import_members_from_another_project_13_8.pngbin0 -> 35191 bytes
-rw-r--r--doc/user/project/members/img/add_user_imported_members.pngbin25398 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_imported_members_13_8.pngbin0 -> 47167 bytes
-rw-r--r--doc/user/project/members/img/add_user_list_members.pngbin16916 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_list_members_13_8.pngbin0 -> 39827 bytes
-rw-r--r--doc/user/project/members/img/add_user_search_people.pngbin25368 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_search_people_13_8.pngbin0 -> 28335 bytes
-rw-r--r--doc/user/project/members/img/other_group_sees_shared_project_v13_6.pngbin291848 -> 0 bytes
-rw-r--r--doc/user/project/members/img/other_group_sees_shared_project_v13_8.pngbin0 -> 52192 bytes
-rw-r--r--doc/user/project/members/img/project_groups_tab_13_8.pngbin0 -> 65200 bytes
-rw-r--r--doc/user/project/members/img/project_members.pngbin36955 -> 0 bytes
-rw-r--r--doc/user/project/members/img/project_members_13_8.pngbin0 -> 34744 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups_tab_v13_6.pngbin378257 -> 0 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups_tab_v13_8.pngbin0 -> 62368 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups_v13_6.pngbin395958 -> 0 bytes
-rw-r--r--doc/user/project/members/index.md20
-rw-r--r--doc/user/project/members/share_project_with_groups.md11
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md8
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md2
-rw-r--r--doc/user/project/merge_requests/code_quality.md99
-rw-r--r--doc/user/project/merge_requests/getting_started.md56
-rw-r--r--doc/user/project/merge_requests/img/code_quality_host_bound_sequential.pngbin0 -> 12345 bytes
-rw-r--r--doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.pngbin0 -> 42245 bytes
-rw-r--r--doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.pngbin0 -> 38840 bytes
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md2
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md2
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md2
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md24
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md4
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/index.md18
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md8
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md11
-rw-r--r--doc/user/project/pages/getting_started/pages_ci_cd_template.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_forked_sample_project.md4
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md6
-rw-r--r--doc/user/project/pages/getting_started_part_one.md32
-rw-r--r--doc/user/project/pages/index.md12
-rw-r--r--doc/user/project/pages/introduction.md44
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md14
-rw-r--r--doc/user/project/pages/pages_access_control.md16
-rw-r--r--doc/user/project/quick_actions.md14
-rw-r--r--doc/user/project/releases/index.md11
-rw-r--r--doc/user/project/repository/forking_workflow.md4
-rw-r--r--doc/user/project/repository/index.md18
-rw-r--r--doc/user/project/repository/repository_mirroring.md146
-rw-r--r--doc/user/project/repository/web_editor.md2
-rw-r--r--doc/user/project/requirements/index.md54
-rw-r--r--doc/user/project/service_desk.md224
-rw-r--r--doc/user/project/settings/import_export.md2
-rw-r--r--doc/user/project/settings/index.md4
-rw-r--r--doc/user/project/settings/project_access_tokens.md18
-rw-r--r--doc/user/project/web_ide/index.md39
-rw-r--r--doc/user/project/wiki/index.md8
-rw-r--r--doc/user/search/advanced_search_syntax.md7
-rw-r--r--doc/user/search/img/project_search_general_settings_v13_8.pngbin0 -> 47120 bytes
-rw-r--r--doc/user/search/index.md98
-rw-r--r--doc/user/snippets.md34
-rw-r--r--doc/user/todos.md2
-rw-r--r--doc/user/usage_quotas.md1
-rw-r--r--fixtures/lib/gitlab/graphql/queries/author.fragment.graphql4
-rw-r--r--fixtures/lib/gitlab/graphql/queries/bad.fragment.graphql4
-rw-r--r--fixtures/lib/gitlab/graphql/queries/bad_argument.graphql5
-rw-r--r--fixtures/lib/gitlab/graphql/queries/client.query.graphql3
-rw-r--r--fixtures/lib/gitlab/graphql/queries/client_unused_fragment.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/connection.query.graphql9
-rw-r--r--fixtures/lib/gitlab/graphql/queries/deeply/nested/bad_import.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/deeply/nested/query.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/duplicate_imports.graphql10
-rw-r--r--fixtures/lib/gitlab/graphql/queries/ee/author.fragment.graphql5
-rw-r--r--fixtures/lib/gitlab/graphql/queries/ee_else_ce.import.graphql9
-rw-r--r--fixtures/lib/gitlab/graphql/queries/missing_argument.graphql8
-rw-r--r--fixtures/lib/gitlab/graphql/queries/mixed_client.query.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/mixed_client_invalid.query.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/mixed_client_skipped_argument.graphql11
-rw-r--r--fixtures/lib/gitlab/graphql/queries/mixed_client_unused_fragment.graphql11
-rw-r--r--fixtures/lib/gitlab/graphql/queries/post.fragment.graphql8
-rw-r--r--fixtures/lib/gitlab/graphql/queries/post_by_slug.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.graphql9
-rw-r--r--fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.misspelled.graphql9
-rw-r--r--fixtures/lib/gitlab/graphql/queries/syntax-error.graphql5
-rw-r--r--fixtures/lib/gitlab/graphql/queries/thingy.fragment.graphql3
-rw-r--r--fixtures/lib/gitlab/graphql/queries/transitive_bad_import.fragment.graphql6
-rw-r--r--fixtures/lib/gitlab/graphql/queries/transitive_bad_import.graphql9
-rw-r--r--fixtures/lib/gitlab/graphql/queries/typedefs.graphql3
-rw-r--r--fixtures/lib/gitlab/graphql/queries/unused_import.graphql8
-rw-r--r--fixtures/lib/gitlab/graphql/queries/wrong_field.graphql7
-rw-r--r--fixtures/lib/gitlab/graphql/queries/wrong_field.import.graphql7
-rw-r--r--jest.config.base.js10
-rw-r--r--jest.config.js2
-rw-r--r--lib/api/api.rb3
-rw-r--r--lib/api/api_guard.rb13
-rw-r--r--lib/api/boards.rb4
-rw-r--r--lib/api/boards_responses.rb14
-rw-r--r--lib/api/ci/runner.rb1
-rw-r--r--lib/api/concerns/packages/nuget_endpoints.rb63
-rw-r--r--lib/api/debian_project_packages.rb5
-rw-r--r--lib/api/entities/basic_repository_storage_move.rb13
-rw-r--r--lib/api/entities/basic_snippet.rb18
-rw-r--r--lib/api/entities/board.rb2
-rw-r--r--lib/api/entities/note.rb1
-rw-r--r--lib/api/entities/project.rb1
-rw-r--r--lib/api/entities/project_repository_storage_move.rb7
-rw-r--r--lib/api/entities/release.rb7
-rw-r--r--lib/api/entities/snippet.rb12
-rw-r--r--lib/api/entities/snippet_repository_storage_move.rb9
-rw-r--r--lib/api/generic_packages.rb8
-rw-r--r--lib/api/group_boards.rb34
-rw-r--r--lib/api/group_packages.rb4
-rw-r--r--lib/api/helpers.rb16
-rw-r--r--lib/api/helpers/authentication.rb73
-rw-r--r--lib/api/helpers/merge_requests_helpers.rb12
-rw-r--r--lib/api/helpers/packages/basic_auth_helpers.rb13
-rw-r--r--lib/api/helpers/pagination.rb4
-rw-r--r--lib/api/helpers/projects_helpers.rb4
-rw-r--r--lib/api/helpers/services_helpers.rb2
-rw-r--r--lib/api/internal/base.rb1
-rw-r--r--lib/api/invitations.rb18
-rw-r--r--lib/api/job_artifacts.rb7
-rw-r--r--lib/api/jobs.rb21
-rw-r--r--lib/api/lint.rb5
-rw-r--r--lib/api/maven_packages.rb6
-rw-r--r--lib/api/nuget_group_packages.rb58
-rw-r--r--lib/api/nuget_project_packages.rb68
-rw-r--r--lib/api/project_packages.rb4
-rw-r--r--lib/api/project_templates.rb4
-rw-r--r--lib/api/projects.rb4
-rw-r--r--lib/api/settings.rb1
-rw-r--r--lib/api/snippet_repository_storage_moves.rb110
-rw-r--r--lib/api/templates.rb3
-rw-r--r--lib/api/terraform/state.rb2
-rw-r--r--lib/api/usage_data.rb2
-rw-r--r--lib/api/user_counts.rb4
-rw-r--r--lib/api/users.rb3
-rw-r--r--lib/atlassian/jira_connect/client.rb73
-rw-r--r--lib/atlassian/jira_connect/serializers/build_entity.rb6
-rw-r--r--lib/atlassian/jira_connect/serializers/deployment_entity.rb90
-rw-r--r--lib/atlassian/jira_connect/serializers/environment_entity.rb39
-rw-r--r--lib/atlassian/jira_connect/serializers/feature_flag_entity.rb83
-rw-r--r--lib/atlassian/jira_connect/serializers/pipeline_entity.rb31
-rw-r--r--lib/backup/repositories.rb39
-rw-r--r--lib/banzai/filter/ascii_doc_sanitization_filter.rb38
-rw-r--r--lib/banzai/filter/asset_proxy_filter.rb10
-rw-r--r--lib/banzai/filter/base_sanitization_filter.rb34
-rw-r--r--lib/banzai/filter/broadcast_message_sanitization_filter.rb10
-rw-r--r--lib/banzai/filter/sanitization_filter.rb22
-rw-r--r--lib/banzai/filter/truncate_source_filter.rb13
-rw-r--r--lib/banzai/pipeline/description_pipeline.rb4
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb1
-rw-r--r--lib/bulk_imports/common/extractors/graphql_extractor.rb12
-rw-r--r--lib/bulk_imports/importers/group_importer.rb14
-rw-r--r--lib/bulk_imports/importers/groups_importer.rb36
-rw-r--r--lib/bulk_imports/pipeline.rb20
-rw-r--r--lib/bulk_imports/pipeline/runner.rb30
-rw-r--r--lib/container_registry/client.rb43
-rw-r--r--lib/declarative_enum.rb105
-rw-r--r--lib/expand_variables.rb6
-rw-r--r--lib/feature/shared.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/default_stages.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events.rb9
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production.rb38
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb38
-rw-r--r--lib/gitlab/analytics/unique_visits.rb2
-rw-r--r--lib/gitlab/api_authentication/builder.rb18
-rw-r--r--lib/gitlab/api_authentication/sent_through_builder.rb19
-rw-r--r--lib/gitlab/api_authentication/token_locator.rb37
-rw-r--r--lib/gitlab/api_authentication/token_resolver.rb87
-rw-r--r--lib/gitlab/api_authentication/token_type_builder.rb18
-rw-r--r--lib/gitlab/application_context.rb2
-rw-r--r--lib/gitlab/auth/auth_finders.rb18
-rw-r--r--lib/gitlab/auth/ldap/config.rb13
-rw-r--r--lib/gitlab/auth/request_authenticator.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_artifact_expiry_date.rb57
-rw-r--r--lib/gitlab/background_migration/copy_column_using_background_migration_job.rb64
-rw-r--r--lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb128
-rw-r--r--lib/gitlab/background_migration/remove_duplicate_services.rb58
-rw-r--r--lib/gitlab/checks/diff_check.rb58
-rw-r--r--lib/gitlab/ci/config.rb7
-rw-r--r--lib/gitlab/ci/config/entry/artifacts.rb3
-rw-r--r--lib/gitlab/ci/config/external/context.rb5
-rw-r--r--lib/gitlab/ci/config/external/file/local.rb3
-rw-r--r--lib/gitlab/ci/config/external/file/project.rb3
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb32
-rw-r--r--lib/gitlab/ci/features.rb12
-rw-r--r--lib/gitlab/ci/lint.rb8
-rw-r--r--lib/gitlab/ci/parsers.rb4
-rw-r--r--lib/gitlab/ci/parsers/coverage/cobertura.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb29
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed.rb7
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed_block.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/template_usage.rb32
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/abilities.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb2
-rw-r--r--lib/gitlab/ci/reports/test_failure_history.rb2
-rw-r--r--lib/gitlab/ci/status/group/factory.rb4
-rw-r--r--lib/gitlab/ci/syntax_templates/Artifacts example.gitlab-ci.yml52
-rw-r--r--lib/gitlab/ci/syntax_templates/Before_script and after_script example.gitlab-ci.yml36
-rw-r--r--lib/gitlab/ci/syntax_templates/Manual jobs example.gitlab-ci.yml53
-rw-r--r--lib/gitlab/ci/syntax_templates/Multi-stage pipeline example.gitlab-ci.yml33
-rw-r--r--lib/gitlab/ci/syntax_templates/Variables example.gitlab-ci.yml47
-rw-r--r--lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml84
-rw-r--r--lib/gitlab/ci/templates/Flutter.gitlab-ci.yml29
-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/Security/DAST.latest.gitlab-ci.yml43
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml29
-rw-r--r--lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Terraform.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/variables/collection/sorted.rb77
-rw-r--r--lib/gitlab/ci/yaml_processor.rb6
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb4
-rw-r--r--lib/gitlab/composer/version_index.rb47
-rw-r--r--lib/gitlab/conflict/file.rb29
-rw-r--r--lib/gitlab/cycle_analytics/base_event_fetcher.rb79
-rw-r--r--lib/gitlab/cycle_analytics/base_query.rb54
-rw-r--r--lib/gitlab/cycle_analytics/base_stage.rb83
-rw-r--r--lib/gitlab/cycle_analytics/builds_event_helper.rb36
-rw-r--r--lib/gitlab/cycle_analytics/code_event_fetcher.rb31
-rw-r--r--lib/gitlab/cycle_analytics/code_helper.rb11
-rw-r--r--lib/gitlab/cycle_analytics/code_stage.rb33
-rw-r--r--lib/gitlab/cycle_analytics/event_fetcher.rb11
-rw-r--r--lib/gitlab/cycle_analytics/issue_event_fetcher.rb29
-rw-r--r--lib/gitlab/cycle_analytics/issue_helper.rb25
-rw-r--r--lib/gitlab/cycle_analytics/issue_stage.rb34
-rw-r--r--lib/gitlab/cycle_analytics/permissions.rb2
-rw-r--r--lib/gitlab/cycle_analytics/plan_event_fetcher.rb29
-rw-r--r--lib/gitlab/cycle_analytics/plan_helper.rb26
-rw-r--r--lib/gitlab/cycle_analytics/plan_stage.rb34
-rw-r--r--lib/gitlab/cycle_analytics/production_event_fetcher.rb30
-rw-r--r--lib/gitlab/cycle_analytics/production_helper.rb13
-rw-r--r--lib/gitlab/cycle_analytics/review_event_fetcher.rb30
-rw-r--r--lib/gitlab/cycle_analytics/review_helper.rb11
-rw-r--r--lib/gitlab/cycle_analytics/review_stage.rb33
-rw-r--r--lib/gitlab/cycle_analytics/stage.rb11
-rw-r--r--lib/gitlab/cycle_analytics/staging_event_fetcher.rb10
-rw-r--r--lib/gitlab/cycle_analytics/staging_stage.rb33
-rw-r--r--lib/gitlab/cycle_analytics/test_event_fetcher.rb10
-rw-r--r--lib/gitlab/cycle_analytics/test_helper.rb21
-rw-r--r--lib/gitlab/cycle_analytics/test_stage.rb33
-rw-r--r--lib/gitlab/danger/base_linter.rb5
-rw-r--r--lib/gitlab/danger/changelog.rb4
-rw-r--r--lib/gitlab/danger/commit_linter.rb12
-rw-r--r--lib/gitlab/danger/helper.rb10
-rw-r--r--lib/gitlab/danger/merge_request_linter.rb8
-rw-r--r--lib/gitlab/danger/roulette.rb16
-rw-r--r--lib/gitlab/danger/teammate.rb4
-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/database/median.rb149
-rw-r--r--lib/gitlab/database/migration_helpers.rb175
-rw-r--r--lib/gitlab/database/migrations/background_migration_helpers.rb10
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb2
-rw-r--r--lib/gitlab/database/postgres_hll/batch_distinct_counter.rb62
-rw-r--r--lib/gitlab/database/postgres_hll/buckets.rb77
-rw-r--r--lib/gitlab/database/reindexing.rb6
-rw-r--r--lib/gitlab/database/reindexing/coordinator.rb38
-rw-r--r--lib/gitlab/database/reindexing/grafana_notifier.rb72
-rw-r--r--lib/gitlab/database/reindexing/reindex_action.rb20
-rw-r--r--lib/gitlab/database_importers/self_monitoring/project/create_service.rb12
-rw-r--r--lib/gitlab/diff/line.rb4
-rw-r--r--lib/gitlab/diff/position.rb7
-rw-r--r--lib/gitlab/email/handler.rb1
-rw-r--r--lib/gitlab/email/handler/create_note_on_issuable_handler.rb81
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb2
-rw-r--r--lib/gitlab/error_tracking.rb39
-rw-r--r--lib/gitlab/experimentation.rb18
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb7
-rw-r--r--lib/gitlab/experimentation/experiment.rb20
-rw-r--r--lib/gitlab/faraday.rb7
-rw-r--r--lib/gitlab/faraday/error_callback.rb44
-rw-r--r--lib/gitlab/git/changed_path.rb18
-rw-r--r--lib/gitlab/git/diff_collection.rb2
-rw-r--r--lib/gitlab/git/repository.rb4
-rw-r--r--lib/gitlab/git/wiki_page_version.rb7
-rw-r--r--lib/gitlab/git_access_snippet.rb19
-rw-r--r--lib/gitlab/gitaly_client.rb4
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb5
-rw-r--r--lib/gitlab/github_import/importer/repository_importer.rb2
-rw-r--r--lib/gitlab/gitpod.rb26
-rw-r--r--lib/gitlab/gon_helper.rb5
-rw-r--r--lib/gitlab/graphql/batch_key.rb39
-rw-r--r--lib/gitlab/graphql/lazy.rb8
-rw-r--r--lib/gitlab/graphql/pagination/keyset/connection.rb17
-rw-r--r--lib/gitlab/graphql/pagination/keyset/query_builder.rb5
-rw-r--r--lib/gitlab/graphql/queries.rb286
-rw-r--r--lib/gitlab/hashed_storage/rake_helper.rb32
-rw-r--r--lib/gitlab/jira/http_client.rb6
-rw-r--r--lib/gitlab/kubernetes/cilium_network_policy.rb8
-rw-r--r--lib/gitlab/kubernetes/kubectl_cmd.rb2
-rw-r--r--lib/gitlab/kubernetes/pod_cmd.rb15
-rw-r--r--lib/gitlab/metrics/samplers/action_cable_sampler.rb4
-rw-r--r--lib/gitlab/metrics/samplers/base_sampler.rb12
-rw-r--r--lib/gitlab/metrics/samplers/database_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/puma_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/threads_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb2
-rw-r--r--lib/gitlab/metrics/system.rb14
-rw-r--r--lib/gitlab/middleware/multipart.rb124
-rw-r--r--lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb22
-rw-r--r--lib/gitlab/project_template.rb3
-rw-r--r--lib/gitlab/prometheus/internal.rb28
-rw-r--r--lib/gitlab/quick_actions/issue_actions.rb3
-rw-r--r--lib/gitlab/quick_actions/issue_and_merge_request_actions.rb2
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb183
-rw-r--r--lib/gitlab/rack_attack.rb60
-rw-r--r--lib/gitlab/sourcegraph.rb3
-rw-r--r--lib/gitlab/template/base_template.rb7
-rw-r--r--lib/gitlab/template/dockerfile_template.rb5
-rw-r--r--lib/gitlab/template/gitlab_ci_syntax_yml_template.rb29
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb5
-rw-r--r--lib/gitlab/template/metrics_dashboard_template.rb5
-rw-r--r--lib/gitlab/throttle.rb6
-rw-r--r--lib/gitlab/tracking.rb4
-rw-r--r--lib/gitlab/tracking/standard_context.rb41
-rw-r--r--lib/gitlab/url_builder.rb10
-rw-r--r--lib/gitlab/usage/metric.rb43
-rw-r--r--lib/gitlab/usage/metric_definition.rb86
-rw-r--r--lib/gitlab/usage_data_counters.rb2
-rw-r--r--lib/gitlab/usage_data_counters/aggregated_metrics/common.yml5
-rw-r--r--lib/gitlab/usage_data_counters/ci_template_unique_counter.rb37
-rw-r--r--lib/gitlab/usage_data_counters/counter_events/guest_package_events.yml34
-rw-r--r--lib/gitlab/usage_data_counters/counter_events/package_events.yml46
-rw-r--r--lib/gitlab/usage_data_counters/editor_unique_counter.rb2
-rw-r--r--lib/gitlab/usage_data_counters/guest_package_event_counter.rb11
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb31
-rw-r--r--lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb2
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml143
-rw-r--r--lib/gitlab/usage_data_counters/known_events/package_events.yml308
-rw-r--r--lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb95
-rw-r--r--lib/gitlab/usage_data_counters/package_event_counter.rb11
-rw-r--r--lib/gitlab/usage_data_counters/track_unique_events.rb4
-rw-r--r--lib/gitlab/utils.rb12
-rw-r--r--lib/gitlab/utils/usage_data.rb10
-rw-r--r--lib/gitlab/uuid.rb5
-rw-r--r--lib/gitlab/visibility_level.rb8
-rw-r--r--lib/gitlab/webpack/manifest.rb4
-rw-r--r--lib/gitlab_danger.rb2
-rw-r--r--lib/release_highlights/validator.rb54
-rw-r--r--lib/release_highlights/validator/entry.rb74
-rw-r--r--lib/tasks/gitlab/git.rake34
-rw-r--r--lib/tasks/gitlab/graphql.rake42
-rw-r--r--lib/tasks/gitlab/packages/events.rake34
-rw-r--r--lib/tasks/gitlab/pages.rake35
-rw-r--r--lib/tasks/gitlab/storage.rake15
-rw-r--r--lib/uploaded_file.rb32
-rw-r--r--locale/am_ET/gitlab.po1775
-rw-r--r--locale/ar_SA/gitlab.po1795
-rw-r--r--locale/as_IN/gitlab.po1775
-rw-r--r--locale/az_AZ/gitlab.po1775
-rw-r--r--locale/ba_RU/gitlab.po1770
-rw-r--r--locale/bg/gitlab.po1775
-rw-r--r--locale/bn_BD/gitlab.po1775
-rw-r--r--locale/bn_IN/gitlab.po1775
-rw-r--r--locale/bs_BA/gitlab.po1780
-rw-r--r--locale/ca_ES/gitlab.po1775
-rw-r--r--locale/cs_CZ/gitlab.po1785
-rw-r--r--locale/cy_GB/gitlab.po1795
-rw-r--r--locale/da_DK/gitlab.po1775
-rw-r--r--locale/de/gitlab.po1821
-rw-r--r--locale/el_GR/gitlab.po1775
-rw-r--r--locale/eo/gitlab.po1775
-rw-r--r--locale/es/gitlab.po1871
-rw-r--r--locale/et_EE/gitlab.po1775
-rw-r--r--locale/fa_IR/gitlab.po1775
-rw-r--r--locale/fi_FI/gitlab.po1775
-rw-r--r--locale/fil_PH/gitlab.po1775
-rw-r--r--locale/fr/gitlab.po1811
-rw-r--r--locale/gitlab.pot1458
-rw-r--r--locale/gl_ES/gitlab.po1775
-rw-r--r--locale/he_IL/gitlab.po1785
-rw-r--r--locale/hi_IN/gitlab.po1775
-rw-r--r--locale/hr_HR/gitlab.po1780
-rw-r--r--locale/hu_HU/gitlab.po1775
-rw-r--r--locale/id_ID/gitlab.po1770
-rw-r--r--locale/ig_NG/gitlab.po1770
-rw-r--r--locale/is_IS/gitlab.po1775
-rw-r--r--locale/it/gitlab.po1775
-rw-r--r--locale/ja/gitlab.po2814
-rw-r--r--locale/ka_GE/gitlab.po1775
-rw-r--r--locale/kab/gitlab.po1775
-rw-r--r--locale/ko/gitlab.po1964
-rw-r--r--locale/ku_TR/gitlab.po1775
-rw-r--r--locale/ky_KG/gitlab.po1775
-rw-r--r--locale/lt_LT/gitlab.po1785
-rw-r--r--locale/mk_MK/gitlab.po1775
-rw-r--r--locale/mn_MN/gitlab.po1775
-rw-r--r--locale/nb_NO/gitlab.po1825
-rw-r--r--locale/nl_NL/gitlab.po1775
-rw-r--r--locale/pa_IN/gitlab.po1775
-rw-r--r--locale/pl_PL/gitlab.po1791
-rw-r--r--locale/pt_BR/gitlab.po1841
-rw-r--r--locale/pt_PT/gitlab.po1795
-rw-r--r--locale/ro_RO/gitlab.po1780
-rw-r--r--locale/ru/gitlab.po2495
-rw-r--r--locale/si_LK/gitlab.po1775
-rw-r--r--locale/sk_SK/gitlab.po1785
-rw-r--r--locale/sl_SI/gitlab.po1785
-rw-r--r--locale/sq_AL/gitlab.po1775
-rw-r--r--locale/sr_CS/gitlab.po1780
-rw-r--r--locale/sr_SP/gitlab.po1780
-rw-r--r--locale/sv_SE/gitlab.po1775
-rw-r--r--locale/sw_KE/gitlab.po1775
-rw-r--r--locale/tr_TR/gitlab.po1935
-rw-r--r--locale/uk/gitlab.po1889
-rw-r--r--locale/ur_PK/gitlab.po1775
-rw-r--r--locale/uz_UZ/gitlab.po1775
-rw-r--r--locale/vi_VN/gitlab.po1770
-rw-r--r--locale/zh_CN/gitlab.po5404
-rw-r--r--locale/zh_HK/gitlab.po1774
-rw-r--r--locale/zh_TW/gitlab.po1790
-rw-r--r--package.json24
-rw-r--r--qa/Dockerfile14
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/Gemfile.lock16
-rw-r--r--qa/qa.rb5
-rw-r--r--qa/qa/fixtures/kubernetes_agent/agentk-config.yaml.erb3
-rw-r--r--qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb95
-rw-r--r--qa/qa/fixtures/kubernetes_agent/galatic-empire-manifest.yaml15
-rw-r--r--qa/qa/fixtures/web_ide/README.md0
-rw-r--r--qa/qa/fixtures/web_ide/dk.pngbin0 -> 1062 bytes
-rw-r--r--qa/qa/fixtures/web_ide/logo_sample.svg27
-rw-r--r--qa/qa/fixtures/web_ide/text_file.txt1
-rw-r--r--qa/qa/flow/sign_up.rb47
-rw-r--r--qa/qa/page/admin/settings/component/sign_up_restrictions.rb6
-rw-r--r--qa/qa/page/base.rb44
-rw-r--r--qa/qa/page/component/snippet.rb42
-rw-r--r--qa/qa/page/project/job/show.rb2
-rw-r--r--qa/qa/page/project/members.rb2
-rw-r--r--qa/qa/page/project/pipeline/show.rb2
-rw-r--r--qa/qa/page/project/settings/advanced.rb1
-rw-r--r--qa/qa/page/project/web_ide/edit.rb49
-rw-r--r--qa/qa/resource/clusters/agent.rb54
-rw-r--r--qa/qa/resource/clusters/agent_token.rb49
-rw-r--r--qa/qa/resource/protected_branch.rb2
-rw-r--r--qa/qa/runtime/env.rb4
-rw-r--r--qa/qa/runtime/feature.rb2
-rw-r--r--qa/qa/scenario/test/integration/ssh_tunnel.rb13
-rw-r--r--qa/qa/service/kubernetes_cluster.rb8
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb43
-rw-r--r--qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb34
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb75
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb89
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb94
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb45
-rw-r--r--qa/qa/support/page/logging.rb6
-rw-r--r--qa/spec/spec_helper.rb5
-rw-r--r--rubocop/cop/lint/last_keyword_argument.rb26
-rw-r--r--rubocop/cop/rspec/expect_gitlab_tracking.rb2
-rw-r--r--rubocop/cop/rspec/web_mock_enable.rb39
-rw-r--r--rubocop/rubocop.rb2
-rwxr-xr-xscripts/api/cancel_pipeline.rb (renamed from scripts/api/cancel_pipeline)0
-rwxr-xr-xscripts/api/download_job_artifact.rb (renamed from scripts/api/download_job_artifact)0
-rwxr-xr-xscripts/api/get_job_id.rb (renamed from scripts/api/get_job_id)0
-rwxr-xr-xscripts/api/play_job60
-rwxr-xr-xscripts/api/play_job.rb63
-rw-r--r--scripts/frontend/block_dependencies.js4
-rwxr-xr-xscripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js2
-rw-r--r--scripts/frontend/extract_gettext_all.js2
-rwxr-xr-xscripts/frontend/file_test_coverage.js16
-rw-r--r--scripts/frontend/frontend_script_utils.js9
-rw-r--r--scripts/frontend/merge_coverage_frontend.js8
-rw-r--r--scripts/frontend/prettier.js16
-rw-r--r--scripts/frontend/stylelint/stylelint-duplicate-selectors.js4
-rw-r--r--scripts/frontend/stylelint/stylelint-utility-classes.js4
-rw-r--r--scripts/frontend/stylelint/stylelint-utility-map.js4
-rw-r--r--scripts/frontend/stylelint/stylelint-utils.js4
-rwxr-xr-xscripts/frontend/webpack_dev_server.js6
-rwxr-xr-xscripts/gitaly-test-build2
-rwxr-xr-xscripts/gitaly-test-spawn1
-rw-r--r--scripts/gitaly_test.rb10
-rwxr-xr-xscripts/perf/gc/collect_gc_stats.rb97
-rwxr-xr-xscripts/perf/gc/print_gc_stats.rb69
-rwxr-xr-xscripts/review_apps/automated_cleanup.rb10
-rw-r--r--scripts/rspec_helpers.sh10
-rw-r--r--scripts/utils.sh4
-rwxr-xr-xscripts/validate_migration_schema119
-rwxr-xr-xscripts/verify-tff-mapping4
-rw-r--r--spec/controllers/admin/dev_ops_report_controller_spec.rb6
-rw-r--r--spec/controllers/admin/projects_controller_spec.rb30
-rw-r--r--spec/controllers/application_controller_spec.rb43
-rw-r--r--spec/controllers/concerns/redis_tracking_spec.rb2
-rw-r--r--spec/controllers/concerns/spammable_actions_spec.rb198
-rw-r--r--spec/controllers/dashboard/projects_controller_spec.rb9
-rw-r--r--spec/controllers/dashboard/snippets_controller_spec.rb19
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb2
-rw-r--r--spec/controllers/groups/labels_controller_spec.rb41
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb36
-rw-r--r--spec/controllers/jwks_controller_spec.rb36
-rw-r--r--spec/controllers/metrics_controller_spec.rb75
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb76
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb6
-rw-r--r--spec/controllers/projects/feature_flags_controller_spec.rb418
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb24
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb34
-rw-r--r--spec/controllers/projects/labels_controller_spec.rb44
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb74
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb66
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb133
-rw-r--r--spec/controllers/projects_controller_spec.rb25
-rw-r--r--spec/controllers/registrations_controller_spec.rb8
-rw-r--r--spec/controllers/repositories/git_http_controller_spec.rb2
-rw-r--r--spec/controllers/runner_setup_controller_spec.rb21
-rw-r--r--spec/controllers/users_controller_spec.rb925
-rw-r--r--spec/db/schema_spec.rb2
-rw-r--r--spec/factories/alerts_service_data.rb8
-rw-r--r--spec/factories/boards.rb4
-rw-r--r--spec/factories/ci/builds.rb8
-rw-r--r--spec/factories/ci_platform_metrics.rb2
-rw-r--r--spec/factories/namespace_onboarding_actions.rb8
-rw-r--r--spec/factories/namespace_package_settings.rb14
-rw-r--r--spec/factories/onboarding_progresses.rb7
-rw-r--r--spec/factories/packages.rb22
-rw-r--r--spec/factories/packages/debian/distribution.rb25
-rw-r--r--spec/factories/packages/debian/file_metadatum.rb60
-rw-r--r--spec/factories/packages/debian/group_architecture.rb9
-rw-r--r--spec/factories/packages/debian/project_architecture.rb9
-rw-r--r--spec/factories/packages/package_file.rb91
-rw-r--r--spec/factories/project_group_links.rb2
-rw-r--r--spec/factories/project_members.rb4
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/factories/services.rb18
-rw-r--r--spec/factories/usage_data.rb4
-rw-r--r--spec/factories_spec.rb2
-rw-r--r--spec/features/admin/admin_groups_spec.rb1
-rw-r--r--spec/features/admin/admin_runners_spec.rb6
-rw-r--r--spec/features/admin/admin_settings_spec.rb31
-rw-r--r--spec/features/alert_management/user_filters_alerts_by_status_spec.rb1
-rw-r--r--spec/features/alert_management/user_searches_alerts_spec.rb1
-rw-r--r--spec/features/alert_management/user_updates_alert_status_spec.rb1
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb6
-rw-r--r--spec/features/dashboard/projects_spec.rb2
-rw-r--r--spec/features/groups/board_spec.rb11
-rw-r--r--spec/features/groups/import_export/connect_instance_spec.rb2
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb1
-rw-r--r--spec/features/groups/members/manage_members_spec.rb28
-rw-r--r--spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb1
-rw-r--r--spec/features/groups/members/master_manages_access_requests_spec.rb1
-rw-r--r--spec/features/groups/members/sort_members_spec.rb196
-rw-r--r--spec/features/groups/settings/ci_cd_spec.rb2
-rw-r--r--spec/features/groups/settings/packages_and_registries_spec.rb59
-rw-r--r--spec/features/incidents/incident_details_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb163
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb358
-rw-r--r--spec/features/issues/issue_state_spec.rb10
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb1
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb4
-rw-r--r--spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb2
-rw-r--r--spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb3
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb1
-rw-r--r--spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb9
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb22
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb46
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb10
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb4
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb3
-rw-r--r--spec/features/merge_request/user_uses_quick_actions_spec.rb1
-rw-r--r--spec/features/projects/ci/lint_spec.rb4
-rw-r--r--spec/features/projects/commit/user_reverts_commit_spec.rb38
-rw-r--r--spec/features/projects/environments_pod_logs_spec.rb2
-rw-r--r--spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb36
-rw-r--r--spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb117
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb56
-rw-r--r--spec/features/projects/issues/design_management/user_uploads_designs_spec.rb2
-rw-r--r--spec/features/projects/issues/email_participants_spec.rb34
-rw-r--r--spec/features/projects/jobs/permissions_spec.rb57
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb2
-rw-r--r--spec/features/projects/members/group_members_spec.rb55
-rw-r--r--spec/features/projects/members/groups_with_access_list_spec.rb17
-rw-r--r--spec/features/projects/members/invite_group_spec.rb10
-rw-r--r--spec/features/projects/members/list_spec.rb5
-rw-r--r--spec/features/projects/members/master_manages_access_requests_spec.rb1
-rw-r--r--spec/features/projects/members/tabs_spec.rb73
-rw-r--r--spec/features/projects/releases/user_creates_release_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_alerts_spec.rb74
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/user_manages_project_members_spec.rb6
-rw-r--r--spec/features/projects/snippets/user_deletes_snippet_spec.rb4
-rw-r--r--spec/features/promotion_spec.rb2
-rw-r--r--spec/features/protected_tags_spec.rb2
-rw-r--r--spec/features/runners_spec.rb34
-rw-r--r--spec/features/security/dashboard_access_spec.rb2
-rw-r--r--spec/features/security/profile_access_spec.rb12
-rw-r--r--spec/features/users/login_spec.rb67
-rw-r--r--spec/features/users/signup_spec.rb6
-rw-r--r--spec/finders/alert_management/alerts_finder_spec.rb6
-rw-r--r--spec/finders/ci/daily_build_group_report_results_finder_spec.rb6
-rw-r--r--spec/finders/ci/pipelines_for_merge_request_finder_spec.rb18
-rw-r--r--spec/finders/cluster_ancestors_finder_spec.rb12
-rw-r--r--spec/finders/concerns/packages/finder_helper_spec.rb161
-rw-r--r--spec/finders/group_projects_finder_spec.rb38
-rw-r--r--spec/finders/groups_finder_spec.rb23
-rw-r--r--spec/finders/issues_finder_spec.rb176
-rw-r--r--spec/finders/merge_requests_finder_spec.rb55
-rw-r--r--spec/finders/packages/debian/distributions_finder_spec.rb28
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb8
-rw-r--r--spec/finders/packages/maven/package_finder_spec.rb80
-rw-r--r--spec/finders/packages/nuget/package_finder_spec.rb119
-rw-r--r--spec/finders/packages/packages_finder_spec.rb6
-rw-r--r--spec/finders/projects_finder_spec.rb4
-rw-r--r--spec/finders/snippets_finder_spec.rb36
-rw-r--r--spec/finders/template_finder_spec.rb2
-rw-r--r--spec/finders/users_finder_spec.rb27
-rw-r--r--spec/fixtures/api/schemas/entities/discussion.json1
-rw-r--r--spec/fixtures/api/schemas/entities/member.json66
-rw-r--r--spec/fixtures/api/schemas/entities/member_user.json22
-rw-r--r--spec/fixtures/api/schemas/environment.json6
-rw-r--r--spec/fixtures/api/schemas/graphql/namespace/package_settings.json12
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_composer_details.json12
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_details.json36
-rw-r--r--spec/fixtures/api/schemas/group_member.json89
-rw-r--r--spec/fixtures/api/schemas/group_members.json6
-rw-r--r--spec/fixtures/api/schemas/members.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/notes.json1
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_move.json20
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_moves.json6
-rw-r--r--spec/fixtures/api/schemas/rollout_status.json52
-rw-r--r--spec/fixtures/emails/valid_note_on_issuable.eml24
-rw-r--r--spec/fixtures/whats_new/blank.yml9
-rw-r--r--spec/fixtures/whats_new/invalid.yml20
-rw-r--r--spec/fixtures/whats_new/valid.yml20
-rw-r--r--spec/frontend/__helpers__/README.md5
-rw-r--r--spec/frontend/__helpers__/backoff_helper.js33
-rw-r--r--spec/frontend/__helpers__/class_spec_helper.js (renamed from spec/frontend/helpers/class_spec_helper.js)0
-rw-r--r--spec/frontend/__helpers__/class_spec_helper_spec.js (renamed from spec/frontend/helpers/class_spec_helper_spec.js)0
-rw-r--r--spec/frontend/__helpers__/datetime_helpers.js6
-rw-r--r--spec/frontend/__helpers__/dom_events_helper.js8
-rw-r--r--spec/frontend/__helpers__/dom_shims/README.md (renamed from spec/frontend/helpers/dom_shims/README.md)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/create_object_url.js (renamed from spec/frontend/helpers/dom_shims/create_object_url.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/element_scroll_by.js (renamed from spec/frontend/helpers/dom_shims/element_scroll_by.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/element_scroll_into_view.js (renamed from spec/frontend/helpers/dom_shims/element_scroll_into_view.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/element_scroll_to.js (renamed from spec/frontend/helpers/dom_shims/element_scroll_to.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/form_element.js (renamed from spec/frontend/helpers/dom_shims/form_element.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/get_client_rects.js (renamed from spec/frontend/helpers/dom_shims/get_client_rects.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/get_client_rects_spec.js (renamed from spec/frontend/helpers/dom_shims/get_client_rects_spec.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/image_element_properties.js (renamed from spec/frontend/helpers/dom_shims/image_element_properties.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/index.js (renamed from spec/frontend/helpers/dom_shims/index.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/inner_text.js (renamed from spec/frontend/helpers/dom_shims/inner_text.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/range.js (renamed from spec/frontend/helpers/dom_shims/range.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/scroll_by.js (renamed from spec/frontend/helpers/dom_shims/scroll_by.js)0
-rw-r--r--spec/frontend/__helpers__/dom_shims/size_properties.js19
-rw-r--r--spec/frontend/__helpers__/dom_shims/window_scroll_to.js (renamed from spec/frontend/helpers/dom_shims/window_scroll_to.js)0
-rw-r--r--spec/frontend/__helpers__/emoji.js88
-rw-r--r--spec/frontend/__helpers__/experimentation_helper.js (renamed from spec/frontend/helpers/experimentation_helper.js)0
-rw-r--r--spec/frontend/__helpers__/fake_date.js49
-rw-r--r--spec/frontend/__helpers__/fake_date_spec.js (renamed from spec/frontend/helpers/fake_date_spec.js)0
-rw-r--r--spec/frontend/__helpers__/fake_request_animation_frame.js12
-rw-r--r--spec/frontend/__helpers__/filtered_search_spec_helper.js (renamed from spec/frontend/helpers/filtered_search_spec_helper.js)0
-rw-r--r--spec/frontend/__helpers__/fixtures.js38
-rw-r--r--spec/frontend/__helpers__/init_vue_mr_page_helper.js (renamed from spec/frontend/helpers/init_vue_mr_page_helper.js)0
-rw-r--r--spec/frontend/__helpers__/jest_helpers.js22
-rw-r--r--spec/frontend/__helpers__/jquery.js (renamed from spec/frontend/helpers/jquery.js)0
-rw-r--r--spec/frontend/__helpers__/keep_alive_component_helper.js (renamed from spec/frontend/helpers/keep_alive_component_helper.js)0
-rw-r--r--spec/frontend/__helpers__/keep_alive_component_helper_spec.js (renamed from spec/frontend/helpers/keep_alive_component_helper_spec.js)0
-rw-r--r--spec/frontend/__helpers__/local_storage_helper.js49
-rw-r--r--spec/frontend/__helpers__/local_storage_helper_spec.js (renamed from spec/frontend/helpers/local_storage_helper_spec.js)0
-rw-r--r--spec/frontend/__helpers__/locale_helper.js9
-rw-r--r--spec/frontend/__helpers__/mock_apollo_helper.js (renamed from spec/frontend/helpers/mock_apollo_helper.js)0
-rw-r--r--spec/frontend/__helpers__/mock_dom_observer.js (renamed from spec/frontend/helpers/mock_dom_observer.js)0
-rw-r--r--spec/frontend/__helpers__/mock_window_location_helper.js43
-rw-r--r--spec/frontend/__helpers__/set_timeout_promise_helper.js4
-rw-r--r--spec/frontend/__helpers__/set_window_location_helper.js (renamed from spec/frontend/helpers/set_window_location_helper.js)0
-rw-r--r--spec/frontend/__helpers__/set_window_location_helper_spec.js40
-rw-r--r--spec/frontend/__helpers__/stub_children.js3
-rw-r--r--spec/frontend/__helpers__/stub_component.js (renamed from spec/frontend/helpers/stub_component.js)0
-rw-r--r--spec/frontend/__helpers__/stub_transition.js8
-rw-r--r--spec/frontend/__helpers__/test_constants.js (renamed from spec/frontend/helpers/test_constants.js)0
-rw-r--r--spec/frontend/__helpers__/text_helper.js18
-rw-r--r--spec/frontend/__helpers__/timeout.js59
-rw-r--r--spec/frontend/__helpers__/tracking_helper.js25
-rw-r--r--spec/frontend/__helpers__/user_mock_data_helper.js29
-rw-r--r--spec/frontend/__helpers__/vue_mock_directive.js25
-rw-r--r--spec/frontend/__helpers__/vue_mount_component_helper.js (renamed from spec/frontend/helpers/vue_mount_component_helper.js)0
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper.js53
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper_spec.js (renamed from spec/frontend/helpers/vue_test_utils_helper_spec.js)0
-rw-r--r--spec/frontend/__helpers__/vuex_action_helper.js128
-rw-r--r--spec/frontend/__helpers__/vuex_action_helper_spec.js174
-rw-r--r--spec/frontend/__helpers__/wait_for_promises.js1
-rw-r--r--spec/frontend/__helpers__/wait_for_text.js (renamed from spec/frontend/helpers/wait_for_text.js)0
-rw-r--r--spec/frontend/__helpers__/wait_using_real_timer.js7
-rw-r--r--spec/frontend/__helpers__/web_worker_mock.js (renamed from spec/frontend/helpers/web_worker_mock.js)0
-rw-r--r--spec/frontend/__mocks__/@gitlab/ui.js6
-rw-r--r--spec/frontend/__mocks__/lodash/debounce.js2
-rw-r--r--spec/frontend/__mocks__/lodash/defer.js5
-rw-r--r--spec/frontend/__mocks__/lodash/throttle.js2
-rw-r--r--spec/frontend/activities_spec.js10
-rw-r--r--spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap1
-rw-r--r--spec/frontend/add_context_commits_modal/store/actions_spec.js26
-rw-r--r--spec/frontend/admin/statistics_panel/components/app_spec.js2
-rw-r--r--spec/frontend/admin/statistics_panel/store/actions_spec.js10
-rw-r--r--spec/frontend/admin/users/components/user_avatar_spec.js63
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js9
-rw-r--r--spec/frontend/admin/users/mock_data.js5
-rw-r--r--spec/frontend/alert_handler_spec.js2
-rw-r--r--spec/frontend/alert_management/components/alert_details_spec.js13
-rw-r--r--spec/frontend/alert_management/components/alert_management_empty_state_spec.js12
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js94
-rw-r--r--spec/frontend/alert_management/components/alert_status_spec.js2
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js18
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js2
-rw-r--r--spec/frontend/alert_management/mocks/alerts_provide_config.json4
-rw-r--r--spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js49
-rw-r--r--spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap121
-rw-r--r--spec/frontend/alerts_settings/alert_mapping_builder_spec.js10
-rw-r--r--spec/frontend/alerts_settings/alerts_integrations_list_spec.js6
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_spec.js43
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js17
-rw-r--r--spec/frontend/alerts_settings/util.js6
-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.js2
-rw-r--r--spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js2
-rw-r--r--spec/frontend/analytics/instance_statistics/components/users_chart_spec.js2
-rw-r--r--spec/frontend/api/api_utils_spec.js35
-rw-r--r--spec/frontend/api_spec.js194
-rw-r--r--spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap29
-rw-r--r--spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js88
-rw-r--r--spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js6
-rw-r--r--spec/frontend/authentication/u2f/authenticate_spec.js9
-rw-r--r--spec/frontend/authentication/u2f/register_spec.js7
-rw-r--r--spec/frontend/awards_handler_spec.js14
-rw-r--r--spec/frontend/badges/components/badge_form_spec.js6
-rw-r--r--spec/frontend/badges/components/badge_list_row_spec.js8
-rw-r--r--spec/frontend/badges/components/badge_list_spec.js12
-rw-r--r--spec/frontend/badges/components/badge_spec.js12
-rw-r--r--spec/frontend/badges/store/actions_spec.js77
-rw-r--r--spec/frontend/batch_comments/components/diff_file_drafts_spec.js16
-rw-r--r--spec/frontend/batch_comments/components/draft_note_spec.js6
-rw-r--r--spec/frontend/batch_comments/components/drafts_count_spec.js2
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js2
-rw-r--r--spec/frontend/batch_comments/components/publish_button_spec.js2
-rw-r--r--spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js26
-rw-r--r--spec/frontend/behaviors/autosize_spec.js2
-rw-r--r--spec/frontend/behaviors/bind_in_out_spec.js2
-rw-r--r--spec/frontend/behaviors/copy_as_gfm_spec.js10
-rw-r--r--spec/frontend/behaviors/gl_emoji_spec.js2
-rw-r--r--spec/frontend/behaviors/load_startup_css_spec.js2
-rw-r--r--spec/frontend/behaviors/markdown/paste_markdown_table_spec.js10
-rw-r--r--spec/frontend/behaviors/quick_submit_spec.js2
-rw-r--r--spec/frontend/behaviors/requires_input_spec.js24
-rw-r--r--spec/frontend/behaviors/secret_values_spec.js22
-rw-r--r--spec/frontend/behaviors/shortcuts/keybindings_spec.js2
-rw-r--r--spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js36
-rw-r--r--spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js14
-rw-r--r--spec/frontend/blob/components/blob_content_error_spec.js4
-rw-r--r--spec/frontend/blob/components/blob_edit_content_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_edit_header_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_header_filepath_spec.js14
-rw-r--r--spec/frontend/blob/components/blob_header_spec.js2
-rw-r--r--spec/frontend/blob/pipeline_tour_success_modal_spec.js15
-rw-r--r--spec/frontend/blob/sketch/index_spec.js6
-rw-r--r--spec/frontend/blob/utils_spec.js2
-rw-r--r--spec/frontend/blob/viewer/index_spec.js10
-rw-r--r--spec/frontend/blob_edit/edit_blob_spec.js10
-rw-r--r--spec/frontend/boards/board_list_deprecated_spec.js275
-rw-r--r--spec/frontend/boards/board_list_helper.js2
-rw-r--r--spec/frontend/boards/board_list_new_spec.js268
-rw-r--r--spec/frontend/boards/board_list_spec.js346
-rw-r--r--spec/frontend/boards/board_new_issue_deprecated_spec.js203
-rw-r--r--spec/frontend/boards/board_new_issue_spec.js203
-rw-r--r--spec/frontend/boards/boards_store_spec.js32
-rw-r--r--spec/frontend/boards/components/board_assignee_dropdown_spec.js15
-rw-r--r--spec/frontend/boards/components/board_card_layout_spec.js70
-rw-r--r--spec/frontend/boards/components/board_card_spec.js7
-rw-r--r--spec/frontend/boards/components/board_column_deprecated_spec.js94
-rw-r--r--spec/frontend/boards/components/board_column_new_spec.js69
-rw-r--r--spec/frontend/boards/components/board_column_spec.js49
-rw-r--r--spec/frontend/boards/components/board_configuration_options_spec.js49
-rw-r--r--spec/frontend/boards/components/board_content_spec.js18
-rw-r--r--spec/frontend/boards/components/board_form_spec.js216
-rw-r--r--spec/frontend/boards/components/board_list_header_deprecated_spec.js165
-rw-r--r--spec/frontend/boards/components/board_list_header_new_spec.js187
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js136
-rw-r--r--spec/frontend/boards/components/board_new_issue_new_spec.js115
-rw-r--r--spec/frontend/boards/components/board_new_issue_spec.js115
-rw-r--r--spec/frontend/boards/components/boards_selector_spec.js8
-rw-r--r--spec/frontend/boards/components/issue_count_spec.js2
-rw-r--r--spec/frontend/boards/components/issue_due_date_spec.js2
-rw-r--r--spec/frontend/boards/components/issue_time_estimate_deprecated_spec.js64
-rw-r--r--spec/frontend/boards/components/issue_time_estimate_spec.js54
-rw-r--r--spec/frontend/boards/components/sidebar/board_editable_item_spec.js25
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js182
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js18
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js2
-rw-r--r--spec/frontend/boards/components/sidebar/remove_issue_spec.js2
-rw-r--r--spec/frontend/boards/issue_card_deprecated_spec.js332
-rw-r--r--spec/frontend/boards/issue_card_inner_spec.js372
-rw-r--r--spec/frontend/boards/issue_card_spec.js342
-rw-r--r--spec/frontend/boards/list_spec.js4
-rw-r--r--spec/frontend/boards/mock_data.js36
-rw-r--r--spec/frontend/boards/project_select_deprecated_spec.js261
-rw-r--r--spec/frontend/boards/project_select_spec.js154
-rw-r--r--spec/frontend/boards/stores/actions_spec.js307
-rw-r--r--spec/frontend/boards/stores/getters_spec.js6
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js100
-rw-r--r--spec/frontend/branches/branches_delete_modal_spec.js2
-rw-r--r--spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js23
-rw-r--r--spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js21
-rw-r--r--spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js8
-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_settings_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_table_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/store/actions_spec.js20
-rw-r--r--spec/frontend/clusters/clusters_bundle_spec.js2
-rw-r--r--spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap186
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js2
-rw-r--r--spec/frontend/clusters/components/applications_spec.js10
-rw-r--r--spec/frontend/clusters/components/fluentd_output_settings_spec.js12
-rw-r--r--spec/frontend/clusters/components/uninstall_application_button_spec.js2
-rw-r--r--spec/frontend/clusters/services/application_state_machine_spec.js18
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js23
-rw-r--r--spec/frontend/clusters_list/components/ancestor_notice_spec.js4
-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/code_navigation/store/actions_spec.js14
-rw-r--r--spec/frontend/collapsed_sidebar_todo_spec.js14
-rw-r--r--spec/frontend/commit/commit_pipeline_status_component_spec.js4
-rw-r--r--spec/frontend/commit/pipelines/pipelines_spec.js30
-rw-r--r--spec/frontend/commits_spec.js4
-rw-r--r--spec/frontend/commons/nav/user_merge_requests_spec.js25
-rw-r--r--spec/frontend/confirm_modal_spec.js14
-rw-r--r--spec/frontend/contributors/store/actions_spec.js4
-rw-r--r--spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js39
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js5
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/getters_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js2
-rw-r--r--spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js47
-rw-r--r--spec/frontend/create_cluster/gke_cluster/helpers.js8
-rw-r--r--spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js12
-rw-r--r--spec/frontend/create_cluster/gke_cluster_namespace/gke_cluster_namespace_spec.js4
-rw-r--r--spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js2
-rw-r--r--spec/frontend/create_item_dropdown_spec.js17
-rw-r--r--spec/frontend/create_merge_request_dropdown_spec.js4
-rw-r--r--spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js170
-rw-r--r--spec/frontend/cycle_analytics/limit_warning_component_spec.js2
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js7
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js2
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js2
-rw-r--r--spec/frontend/deploy_keys/components/app_spec.js20
-rw-r--r--spec/frontend/deploy_keys/components/key_spec.js13
-rw-r--r--spec/frontend/deploy_keys/components/keys_panel_spec.js11
-rw-r--r--spec/frontend/deprecated_jquery_dropdown_spec.js9
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js24
-rw-r--r--spec/frontend/design_management/components/design_notes/design_reply_form_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js6
-rw-r--r--spec/frontend/design_management/components/design_presentation_spec.js42
-rw-r--r--spec/frontend/design_management/components/design_scaler_spec.js2
-rw-r--r--spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap6
-rw-r--r--spec/frontend/design_management/components/toolbar/index_spec.js2
-rw-r--r--spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap2
-rw-r--r--spec/frontend/design_management/components/upload/design_version_dropdown_spec.js4
-rw-r--r--spec/frontend/design_management/pages/index_spec.js284
-rw-r--r--spec/frontend/design_management/router_spec.js4
-rw-r--r--spec/frontend/design_management/utils/error_messages_spec.js4
-rw-r--r--spec/frontend/diffs/components/app_spec.js388
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js14
-rw-r--r--spec/frontend/diffs/components/compare_dropdown_layout_spec.js2
-rw-r--r--spec/frontend/diffs/components/compare_versions_spec.js92
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js9
-rw-r--r--spec/frontend/diffs/components/diff_expansion_cell_spec.js53
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js35
-rw-r--r--spec/frontend/diffs/components/diff_file_spec.js28
-rw-r--r--spec/frontend/diffs/components/diff_gutter_avatars_spec.js4
-rw-r--r--spec/frontend/diffs/components/diff_line_note_form_spec.js41
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js101
-rw-r--r--spec/frontend/diffs/components/diff_row_utils_spec.js16
-rw-r--r--spec/frontend/diffs/components/diff_stats_spec.js6
-rw-r--r--spec/frontend/diffs/components/diff_view_spec.js83
-rw-r--r--spec/frontend/diffs/components/file_row_stats_spec.js24
-rw-r--r--spec/frontend/diffs/components/hidden_files_warning_spec.js6
-rw-r--r--spec/frontend/diffs/components/image_diff_overlay_spec.js24
-rw-r--r--spec/frontend/diffs/components/no_changes_spec.js75
-rw-r--r--spec/frontend/diffs/components/parallel_diff_table_row_spec.js14
-rw-r--r--spec/frontend/diffs/components/settings_dropdown_spec.js16
-rw-r--r--spec/frontend/diffs/components/tree_list_spec.js16
-rw-r--r--spec/frontend/diffs/store/actions_spec.js123
-rw-r--r--spec/frontend/diffs/store/getters_spec.js33
-rw-r--r--spec/frontend/diffs/store/getters_versions_dropdowns_spec.js10
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js17
-rw-r--r--spec/frontend/diffs/store/utils_spec.js79
-rw-r--r--spec/frontend/diffs/utils/diff_file_spec.js30
-rw-r--r--spec/frontend/diffs/utils/file_reviews_spec.js146
-rw-r--r--spec/frontend/diffs/utils/merge_request_spec.js31
-rw-r--r--spec/frontend/diffs/utils/uuids_spec.js2
-rw-r--r--spec/frontend/dirty_submit/dirty_submit_collection_spec.js6
-rw-r--r--spec/frontend/dirty_submit/dirty_submit_form_spec.js8
-rw-r--r--spec/frontend/droplab/drop_down_spec.js8
-rw-r--r--spec/frontend/droplab/plugins/ajax_filter_spec.js12
-rw-r--r--spec/frontend/editor/editor_ci_schema_ext_spec.js107
-rw-r--r--spec/frontend/editor/editor_lite_extension_base_spec.js4
-rw-r--r--spec/frontend/editor/editor_lite_spec.js14
-rw-r--r--spec/frontend/editor/editor_markdown_ext_spec.js4
-rw-r--r--spec/frontend/emoji/emoji_spec.js14
-rw-r--r--spec/frontend/environment.js4
-rw-r--r--spec/frontend/environments/canary_ingress_spec.js102
-rw-r--r--spec/frontend/environments/canary_update_modal_spec.js126
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js139
-rw-r--r--spec/frontend/environments/environment_actions_spec.js4
-rw-r--r--spec/frontend/environments/environment_monitoring_spec.js3
-rw-r--r--spec/frontend/environments/environment_table_spec.js128
-rw-r--r--spec/frontend/environments/environment_terminal_button_spec.js2
-rw-r--r--spec/frontend/environments/environments_app_spec.js32
-rw-r--r--spec/frontend/environments/environments_folder_view_spec.js59
-rw-r--r--spec/frontend/environments/environments_store_spec.js56
-rw-r--r--spec/frontend/environments/folder/environments_folder_view_spec.js4
-rw-r--r--spec/frontend/environments/mock_data.js41
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js6
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_actions_spec.js24
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js20
-rw-r--r--spec/frontend/error_tracking/store/actions_spec.js4
-rw-r--r--spec/frontend/error_tracking/store/details/actions_spec.js6
-rw-r--r--spec/frontend/error_tracking/store/list/actions_spec.js19
-rw-r--r--spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js16
-rw-r--r--spec/frontend/error_tracking_settings/store/actions_spec.js22
-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.js2
-rw-r--r--spec/frontend/feature_flags/components/environments_dropdown_spec.js15
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_spec.js20
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_table_spec.js23
-rw-r--r--spec/frontend/feature_flags/components/form_spec.js11
-rw-r--r--spec/frontend/feature_flags/components/new_environments_dropdown_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategy_parameters_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/user_lists_table_spec.js2
-rw-r--r--spec/frontend/feature_flags/store/edit/actions_spec.js24
-rw-r--r--spec/frontend/feature_flags/store/index/actions_spec.js58
-rw-r--r--spec/frontend/feature_flags/store/index/mutations_spec.js8
-rw-r--r--spec/frontend/feature_flags/store/new/actions_spec.js12
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_helper_spec.js4
-rw-r--r--spec/frontend/filterable_list_spec.js2
-rw-r--r--spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js13
-rw-r--r--spec/frontend/filtered_search/dropdown_utils_spec.js2
-rw-r--r--spec/frontend/filtered_search/filtered_search_manager_spec.js28
-rw-r--r--spec/frontend/filtered_search/filtered_search_token_keys_spec.js2
-rw-r--r--spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js4
-rw-r--r--spec/frontend/filtered_search/issues_filtered_search_token_keys_spec.js25
-rw-r--r--spec/frontend/filtered_search/recent_searches_root_spec.js2
-rw-r--r--spec/frontend/filtered_search/services/recent_searches_service_spec.js20
-rw-r--r--spec/frontend/filtered_search/visual_token_value_spec.js38
-rw-r--r--spec/frontend/fixtures/static/create_item_dropdown.html29
-rw-r--r--spec/frontend/fixtures/static/deprecated_jquery_dropdown.html12
-rw-r--r--spec/frontend/fixtures/static/line_highlighter.html100
-rw-r--r--spec/frontend/fixtures/static/project_select_combo_button.html6
-rw-r--r--spec/frontend/flash_spec.js2
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js14
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_item_spec.js2
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_search_input_spec.js4
-rw-r--r--spec/frontend/frequent_items/store/actions_spec.js28
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js41
-rw-r--r--spec/frontend/gl_field_errors_spec.js32
-rw-r--r--spec/frontend/gl_form_spec.js24
-rw-r--r--spec/frontend/gpg_badges_spec.js10
-rw-r--r--spec/frontend/group_settings/components/shared_runners_form_spec.js2
-rw-r--r--spec/frontend/groups/components/app_spec.js13
-rw-r--r--spec/frontend/groups/components/group_item_spec.js8
-rw-r--r--spec/frontend/groups/components/invite_members_banner_spec.js10
-rw-r--r--spec/frontend/groups/components/item_stats_spec.js2
-rw-r--r--spec/frontend/groups/components/visibility_level_dropdown_spec.js9
-rw-r--r--spec/frontend/groups/members/components/app_spec.js22
-rw-r--r--spec/frontend/helpers/README.md3
-rw-r--r--spec/frontend/helpers/backoff_helper.js33
-rw-r--r--spec/frontend/helpers/dom_events_helper.js8
-rw-r--r--spec/frontend/helpers/dom_shims/size_properties.js19
-rw-r--r--spec/frontend/helpers/emoji.js88
-rw-r--r--spec/frontend/helpers/event_hub_factory_spec.js10
-rw-r--r--spec/frontend/helpers/fake_date.js49
-rw-r--r--spec/frontend/helpers/fake_request_animation_frame.js12
-rw-r--r--spec/frontend/helpers/fixtures.js38
-rw-r--r--spec/frontend/helpers/help_page_helper_spec.js29
-rw-r--r--spec/frontend/helpers/jest_helpers.js22
-rw-r--r--spec/frontend/helpers/local_storage_helper.js49
-rw-r--r--spec/frontend/helpers/locale_helper.js9
-rw-r--r--spec/frontend/helpers/mock_window_location_helper.js43
-rw-r--r--spec/frontend/helpers/monitor_helper_spec.js6
-rw-r--r--spec/frontend/helpers/set_timeout_promise_helper.js4
-rw-r--r--spec/frontend/helpers/set_window_location_helper_spec.js40
-rw-r--r--spec/frontend/helpers/startup_css_helper_spec.js19
-rw-r--r--spec/frontend/helpers/stub_children.js3
-rw-r--r--spec/frontend/helpers/text_helper.js18
-rw-r--r--spec/frontend/helpers/timeout.js59
-rw-r--r--spec/frontend/helpers/tracking_helper.js25
-rw-r--r--spec/frontend/helpers/user_mock_data_helper.js34
-rw-r--r--spec/frontend/helpers/vue_mock_directive.js25
-rw-r--r--spec/frontend/helpers/vue_test_utils_helper.js53
-rw-r--r--spec/frontend/helpers/vuex_action_helper.js128
-rw-r--r--spec/frontend/helpers/vuex_action_helper_spec.js174
-rw-r--r--spec/frontend/helpers/wait_for_promises.js1
-rw-r--r--spec/frontend/helpers/wait_using_real_timer.js7
-rw-r--r--spec/frontend/ide/components/activity_bar_spec.js4
-rw-r--r--spec/frontend/ide/components/branches/search_list_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/actions_spec.js6
-rw-r--r--spec/frontend/ide/components/commit_sidebar/empty_state_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_item_spec.js10
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/message_field_spec.js16
-rw-r--r--spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js14
-rw-r--r--spec/frontend/ide/components/commit_sidebar/radio_group_spec.js14
-rw-r--r--spec/frontend/ide/components/commit_sidebar/success_message_spec.js4
-rw-r--r--spec/frontend/ide/components/error_message_spec.js4
-rw-r--r--spec/frontend/ide/components/file_row_extra_spec.js35
-rw-r--r--spec/frontend/ide/components/file_templates/bar_spec.js11
-rw-r--r--spec/frontend/ide/components/file_templates/dropdown_spec.js8
-rw-r--r--spec/frontend/ide/components/ide_review_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_sidebar_nav_spec.js7
-rw-r--r--spec/frontend/ide/components/ide_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_status_bar_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_status_mr_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_tree_list_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_tree_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/detail/description_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/detail/scroll_button_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/detail_spec.js6
-rw-r--r--spec/frontend/ide/components/jobs/item_spec.js4
-rw-r--r--spec/frontend/ide/components/jobs/list_spec.js4
-rw-r--r--spec/frontend/ide/components/jobs/stage_spec.js7
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js12
-rw-r--r--spec/frontend/ide/components/nav_dropdown_button_spec.js8
-rw-r--r--spec/frontend/ide/components/nav_dropdown_spec.js6
-rw-r--r--spec/frontend/ide/components/new_dropdown/button_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.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/upload_spec.js10
-rw-r--r--spec/frontend/ide/components/panes/collapsible_sidebar_spec.js4
-rw-r--r--spec/frontend/ide/components/panes/right_spec.js2
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js22
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js54
-rw-r--r--spec/frontend/ide/components/repo_commit_section_spec.js28
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js68
-rw-r--r--spec/frontend/ide/components/repo_tabs_spec.js2
-rw-r--r--spec/frontend/ide/components/resizable_panel_spec.js2
-rw-r--r--spec/frontend/ide/components/shared/tokened_input_spec.js6
-rw-r--r--spec/frontend/ide/components/terminal/session_spec.js4
-rw-r--r--spec/frontend/ide/components/terminal/terminal_controls_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/terminal_spec.js57
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js2
-rw-r--r--spec/frontend/ide/file_helpers.js2
-rw-r--r--spec/frontend/ide/helpers.js11
-rw-r--r--spec/frontend/ide/ide_router_extension_spec.js4
-rw-r--r--spec/frontend/ide/ide_router_spec.js2
-rw-r--r--spec/frontend/ide/lib/common/model_spec.js2
-rw-r--r--spec/frontend/ide/lib/create_diff_spec.js8
-rw-r--r--spec/frontend/ide/lib/create_file_diff_spec.js14
-rw-r--r--spec/frontend/ide/lib/diff/controller_spec.js4
-rw-r--r--spec/frontend/ide/lib/editor_spec.js2
-rw-r--r--spec/frontend/ide/lib/editorconfig/parser_spec.js6
-rw-r--r--spec/frontend/ide/lib/errors_spec.js2
-rw-r--r--spec/frontend/ide/lib/files_spec.js11
-rw-r--r--spec/frontend/ide/lib/languages/hcl_spec.js36
-rw-r--r--spec/frontend/ide/lib/mirror_spec.js4
-rw-r--r--spec/frontend/ide/services/index_spec.js33
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js38
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js38
-rw-r--r--spec/frontend/ide/stores/actions/project_spec.js30
-rw-r--r--spec/frontend/ide/stores/actions/tree_spec.js29
-rw-r--r--spec/frontend/ide/stores/actions_spec.js90
-rw-r--r--spec/frontend/ide/stores/extend_spec.js4
-rw-r--r--spec/frontend/ide/stores/getters_spec.js2
-rw-r--r--spec/frontend/ide/stores/integration_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/branches/actions_spec.js12
-rw-r--r--spec/frontend/ide/stores/modules/branches/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/clientside/actions_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/commit/actions_spec.js95
-rw-r--r--spec/frontend/ide/stores/modules/commit/getters_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/editor/setup_spec.js11
-rw-r--r--spec/frontend/ide/stores/modules/file_templates/actions_spec.js22
-rw-r--r--spec/frontend/ide/stores/modules/merge_requests/actions_spec.js16
-rw-r--r--spec/frontend/ide/stores/modules/pane/actions_spec.js12
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/actions_spec.js48
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js8
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js4
-rw-r--r--spec/frontend/ide/stores/plugins/terminal_sync_spec.js9
-rw-r--r--spec/frontend/ide/sync_router_and_store_spec.js4
-rw-r--r--spec/frontend/ide/utils_spec.js2
-rw-r--r--spec/frontend/image_diff/helpers/comment_indicator_helper_spec.js2
-rw-r--r--spec/frontend/image_diff/helpers/utils_helper_spec.js2
-rw-r--r--spec/frontend/image_diff/image_diff_spec.js2
-rw-r--r--spec/frontend/image_diff/init_discussion_tab_spec.js4
-rw-r--r--spec/frontend/image_diff/replaced_image_diff_spec.js18
-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.js2
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js8
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js18
-rw-r--r--spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js29
-rw-r--r--spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js2
-rw-r--r--spec/frontend/import_entities/import_projects/store/actions_spec.js2
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js14
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap1
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap1
-rw-r--r--spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js13
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js251
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js2
-rw-r--r--spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js8
-rw-r--r--spec/frontend/integrations/edit/components/trigger_fields_spec.js2
-rw-r--r--spec/frontend/invite_member/components/invite_member_modal_spec.js10
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js227
-rw-r--r--spec/frontend/invite_members/components/members_token_select_spec.js39
-rw-r--r--spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js17
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js7
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_list_spec.js7
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js4
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js9
-rw-r--r--spec/frontend/issuable_show/components/issuable_body_spec.js7
-rw-r--r--spec/frontend/issuable_show/components/issuable_edit_form_spec.js2
-rw-r--r--spec/frontend/issuable_show/components/issuable_header_spec.js2
-rw-r--r--spec/frontend/issuable_show/components/issuable_show_root_spec.js2
-rw-r--r--spec/frontend/issuable_spec.js2
-rw-r--r--spec/frontend/issuable_suggestions/components/app_spec.js14
-rw-r--r--spec/frontend/issuable_suggestions/components/item_spec.js2
-rw-r--r--spec/frontend/issuable_suggestions/mock_data.js2
-rw-r--r--spec/frontend/issue_show/components/app_spec.js12
-rw-r--r--spec/frontend/issue_show/components/description_spec.js2
-rw-r--r--spec/frontend/issue_show/components/edit_actions_spec.js12
-rw-r--r--spec/frontend/issue_show/components/fields/description_spec.js4
-rw-r--r--spec/frontend/issue_show/components/form_spec.js2
-rw-r--r--spec/frontend/issue_show/components/header_actions_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.js75
-rw-r--r--spec/frontend/issue_show/components/pinned_links_spec.js14
-rw-r--r--spec/frontend/issue_show/issue_spec.js2
-rw-r--r--spec/frontend/issue_spec.js2
-rw-r--r--spec/frontend/issues_list/components/issuable_spec.js16
-rw-r--r--spec/frontend/issues_list/components/issuables_list_app_spec.js16
-rw-r--r--spec/frontend/jira_connect/api_spec.js107
-rw-r--r--spec/frontend/jira_connect/components/app_spec.js80
-rw-r--r--spec/frontend/jira_connect/components/groups_list_item_spec.js46
-rw-r--r--spec/frontend/jira_connect/components/groups_list_spec.js71
-rw-r--r--spec/frontend/jira_connect/mock_data.js15
-rw-r--r--spec/frontend/jira_connect/store/mutations_spec.js18
-rw-r--r--spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap164
-rw-r--r--spec/frontend/jira_import/components/jira_import_form_spec.js2
-rw-r--r--spec/frontend/jira_import/components/jira_import_progress_spec.js2
-rw-r--r--spec/frontend/jira_import/components/jira_import_setup_spec.js2
-rw-r--r--spec/frontend/jobs/components/artifacts_block_spec.js4
-rw-r--r--spec/frontend/jobs/components/commit_block_spec.js2
-rw-r--r--spec/frontend/jobs/components/empty_state_spec.js14
-rw-r--r--spec/frontend/jobs/components/erased_block_spec.js2
-rw-r--r--spec/frontend/jobs/components/job_app_spec.js22
-rw-r--r--spec/frontend/jobs/components/job_container_item_spec.js2
-rw-r--r--spec/frontend/jobs/components/job_log_controllers_spec.js2
-rw-r--r--spec/frontend/jobs/components/job_sidebar_details_container_spec.js9
-rw-r--r--spec/frontend/jobs/components/jobs_container_spec.js2
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js5
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js6
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js8
-rw-r--r--spec/frontend/jobs/components/sidebar_spec.js2
-rw-r--r--spec/frontend/jobs/components/stages_dropdown_spec.js2
-rw-r--r--spec/frontend/jobs/components/stuck_block_spec.js2
-rw-r--r--spec/frontend/jobs/components/trigger_block_spec.js4
-rw-r--r--spec/frontend/jobs/store/actions_spec.js56
-rw-r--r--spec/frontend/jobs/store/helpers.js2
-rw-r--r--spec/frontend/lazy_loader_spec.js6
-rw-r--r--spec/frontend/lib/dompurify_spec.js10
-rw-r--r--spec/frontend/lib/utils/ajax_cache_spec.js8
-rw-r--r--spec/frontend/lib/utils/apollo_startup_js_link_spec.js72
-rw-r--r--spec/frontend/lib/utils/chart_utils_spec.js6
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js140
-rw-r--r--spec/frontend/lib/utils/datetime_range_spec.js2
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js168
-rw-r--r--spec/frontend/lib/utils/dom_utils_spec.js4
-rw-r--r--spec/frontend/lib/utils/favicon_ci_spec.js50
-rw-r--r--spec/frontend/lib/utils/favicon_spec.js39
-rw-r--r--spec/frontend/lib/utils/forms_spec.js8
-rw-r--r--spec/frontend/lib/utils/highlight_spec.js4
-rw-r--r--spec/frontend/lib/utils/icon_utils_spec.js12
-rw-r--r--spec/frontend/lib/utils/mock_data.js3
-rw-r--r--spec/frontend/lib/utils/poll_spec.js20
-rw-r--r--spec/frontend/lib/utils/poll_until_complete_spec.js2
-rw-r--r--spec/frontend/lib/utils/text_utility_spec.js4
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js18
-rw-r--r--spec/frontend/lib/utils/users_cache_spec.js60
-rw-r--r--spec/frontend/line_highlighter_spec.js9
-rw-r--r--spec/frontend/logs/components/environment_logs_spec.js12
-rw-r--r--spec/frontend/logs/components/log_advanced_filters_spec.js6
-rw-r--r--spec/frontend/logs/components/log_control_buttons_spec.js2
-rw-r--r--spec/frontend/logs/components/log_simple_filters_spec.js2
-rw-r--r--spec/frontend/logs/stores/actions_spec.js2
-rw-r--r--spec/frontend/logs/stores/mutations_spec.js2
-rw-r--r--spec/frontend/matchers.js9
-rw-r--r--spec/frontend/matchers_spec.js4
-rw-r--r--spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js4
-rw-r--r--spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/resend_invite_button_spec.js8
-rw-r--r--spec/frontend/members/components/action_buttons/user_action_buttons_spec.js4
-rw-r--r--spec/frontend/members/components/avatars/user_avatar_spec.js2
-rw-r--r--spec/frontend/members/components/filter_sort/filter_sort_container_spec.js2
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js7
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js8
-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.js2
-rw-r--r--spec/frontend/members/components/table/created_at_spec.js2
-rw-r--r--spec/frontend/members/components/table/expiration_datepicker_spec.js10
-rw-r--r--spec/frontend/members/components/table/expires_at_spec.js4
-rw-r--r--spec/frontend/members/components/table/member_avatar_spec.js2
-rw-r--r--spec/frontend/members/components/table/member_source_spec.js6
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js51
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js8
-rw-r--r--spec/frontend/members/mock_data.js2
-rw-r--r--spec/frontend/members/utils_spec.js2
-rw-r--r--spec/frontend/merge_request/components/status_box_spec.js81
-rw-r--r--spec/frontend/merge_request_spec.js18
-rw-r--r--spec/frontend/merge_request_tabs_spec.js5
-rw-r--r--spec/frontend/milestones/milestone_combobox_spec.js126
-rw-r--r--spec/frontend/mini_pipeline_graph_dropdown_spec.js6
-rw-r--r--spec/frontend/mocks/ce/lib/utils/axios_utils.js14
-rw-r--r--spec/frontend/mocks/mocks_helper.js6
-rw-r--r--spec/frontend/mocks/mocks_helper_spec.js10
-rw-r--r--spec/frontend/monitoring/alert_widget_spec.js29
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap1
-rw-r--r--spec/frontend/monitoring/components/alert_widget_form_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/annotations_spec.js6
-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.js4
-rw-r--r--spec/frontend/monitoring/components/charts/gauge_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/options_spec.js12
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js6
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js22
-rw-r--r--spec/frontend/monitoring/components/dashboard_actions_menu_spec.js8
-rw-r--r--spec/frontend/monitoring/components/dashboard_header_spec.js12
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js12
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js38
-rw-r--r--spec/frontend/monitoring/components/dashboards_dropdown_spec.js22
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js52
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js75
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js4
-rw-r--r--spec/frontend/monitoring/components/graph_group_spec.js2
-rw-r--r--spec/frontend/monitoring/components/group_empty_state_spec.js2
-rw-r--r--spec/frontend/monitoring/components/links_section_spec.js2
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js4
-rw-r--r--spec/frontend/monitoring/components/variables/dropdown_field_spec.js11
-rw-r--r--spec/frontend/monitoring/fixture_data.js4
-rw-r--r--spec/frontend/monitoring/graph_data.js4
-rw-r--r--spec/frontend/monitoring/mock_data.js3
-rw-r--r--spec/frontend/monitoring/requests/index_spec.js20
-rw-r--r--spec/frontend/monitoring/router_spec.js14
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js44
-rw-r--r--spec/frontend/monitoring/store/getters_spec.js2
-rw-r--r--spec/frontend/monitoring/store/mutations_spec.js7
-rw-r--r--spec/frontend/monitoring/store/utils_spec.js26
-rw-r--r--spec/frontend/monitoring/store_utils.js8
-rw-r--r--spec/frontend/monitoring/utils_spec.js6
-rw-r--r--spec/frontend/mr_popover/index_spec.js2
-rw-r--r--spec/frontend/new_branch_spec.js6
-rw-r--r--spec/frontend/notebook/cells/code_spec.js6
-rw-r--r--spec/frontend/notebook/cells/output/index_spec.js54
-rw-r--r--spec/frontend/notebook/cells/output/latex_spec.js40
-rw-r--r--spec/frontend/notebook/cells/prompt_spec.js4
-rw-r--r--spec/frontend/notebook/index_spec.js6
-rw-r--r--spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap21
-rw-r--r--spec/frontend/notes/components/comment_field_layout_spec.js137
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js15
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js10
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js33
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_filter_note_spec.js10
-rw-r--r--spec/frontend/notes/components/discussion_filter_spec.js26
-rw-r--r--spec/frontend/notes/components/discussion_jump_to_next_button_spec.js43
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js5
-rw-r--r--spec/frontend/notes/components/discussion_resolve_button_spec.js2
-rw-r--r--spec/frontend/notes/components/email_participants_warning_spec.js70
-rw-r--r--spec/frontend/notes/components/multiline_comment_form_spec.js89
-rw-r--r--spec/frontend/notes/components/multiline_comment_utils_spec.js4
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js28
-rw-r--r--spec/frontend/notes/components/note_attachment_spec.js2
-rw-r--r--spec/frontend/notes/components/note_awards_list_spec.js8
-rw-r--r--spec/frontend/notes/components/note_body_spec.js2
-rw-r--r--spec/frontend/notes/components/note_form_spec.js86
-rw-r--r--spec/frontend/notes/components/note_header_spec.js4
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js80
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js4
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js44
-rw-r--r--spec/frontend/notes/components/toggle_replies_widget_spec.js2
-rw-r--r--spec/frontend/notes/helpers.js2
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js2
-rw-r--r--spec/frontend/notes/old_notes_spec.js74
-rw-r--r--spec/frontend/notes/stores/actions_spec.js130
-rw-r--r--spec/frontend/notes/stores/getters_spec.js25
-rw-r--r--spec/frontend/notes/stores/mutation_spec.js8
-rw-r--r--spec/frontend/oauth_remember_me_spec.js6
-rw-r--r--spec/frontend/operation_settings/components/metrics_settings_spec.js1
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap8
-rw-r--r--spec/frontend/packages/details/components/additional_metadata_spec.js4
-rw-r--r--spec/frontend/packages/details/components/conan_installation_spec.js12
-rw-r--r--spec/frontend/packages/details/components/maven_installation_spec.js18
-rw-r--r--spec/frontend/packages/details/components/npm_installation_spec.js24
-rw-r--r--spec/frontend/packages/details/components/nuget_installation_spec.js12
-rw-r--r--spec/frontend/packages/details/components/package_files_spec.js1
-rw-r--r--spec/frontend/packages/details/components/package_history_spec.js10
-rw-r--r--spec/frontend/packages/details/store/actions_spec.js20
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap16
-rw-r--r--spec/frontend/packages/list/components/packages_sort_spec.js2
-rw-r--r--spec/frontend/packages/list/stores/actions_spec.js34
-rw-r--r--spec/frontend/packages/shared/components/package_path_spec.js8
-rw-r--r--spec/frontend/packages/shared/components/package_tags_spec.js12
-rw-r--r--spec/frontend/packages/shared/utils_spec.js2
-rw-r--r--spec/frontend/pager_spec.js12
-rw-r--r--spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js4
-rw-r--r--spec/frontend/pages/admin/application_settings/account_and_limits_spec.js2
-rw-r--r--spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js12
-rw-r--r--spec/frontend/pages/admin/users/components/delete_user_modal_spec.js6
-rw-r--r--spec/frontend/pages/admin/users/new/index_spec.js4
-rw-r--r--spec/frontend/pages/dashboard/todos/index/todos_spec.js8
-rw-r--r--spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js2
-rw-r--r--spec/frontend/pages/labels/components/promote_label_modal_spec.js12
-rw-r--r--spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js12
-rw-r--r--spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js120
-rw-r--r--spec/frontend/pages/profiles/show/emoji_menu_spec.js4
-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.js4
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js19
-rw-r--r--spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap1
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js4
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js14
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js29
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js49
-rw-r--r--spec/frontend/pages/search/show/refresh_counts_spec.js7
-rw-r--r--spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js6
-rw-r--r--spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js2
-rw-r--r--spec/frontend/pdf/index_spec.js6
-rw-r--r--spec/frontend/pdf/page_spec.js2
-rw-r--r--spec/frontend/performance_bar/components/detailed_metric_spec.js8
-rw-r--r--spec/frontend/performance_bar/index_spec.js11
-rw-r--r--spec/frontend/performance_bar/stores/performance_bar_store_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_form_spec.js4
-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.js33
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js81
-rw-r--r--spec/frontend/pipeline_editor/components/text_editor_spec.js67
-rw-r--r--spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js91
-rw-r--r--spec/frontend/pipeline_editor/graphql/__snapshots__/resolvers_spec.js.snap4
-rw-r--r--spec/frontend/pipeline_editor/graphql/resolvers_spec.js6
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js129
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js235
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js31
-rw-r--r--spec/frontend/pipelines/blank_state_spec.js2
-rw-r--r--spec/frontend/pipelines/components/dag/dag_annotations_spec.js6
-rw-r--r--spec/frontend/pipelines/components/dag/dag_graph_spec.js26
-rw-r--r--spec/frontend/pipelines/components/dag/dag_spec.js2
-rw-r--r--spec/frontend/pipelines/components/dag/parsing_utils_spec.js5
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js6
-rw-r--r--spec/frontend/pipelines/empty_state_spec.js105
-rw-r--r--spec/frontend/pipelines/graph/action_component_spec.js6
-rw-r--r--spec/frontend/pipelines/graph/graph_component_legacy_spec.js80
-rw-r--r--spec/frontend/pipelines/graph/graph_component_spec.js45
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/job_item_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/mock_data.js76
-rw-r--r--spec/frontend/pipelines/graph/stage_column_component_legacy_spec.js7
-rw-r--r--spec/frontend/pipelines/graph/stage_column_component_spec.js66
-rw-r--r--spec/frontend/pipelines/nav_controls_spec.js2
-rw-r--r--spec/frontend/pipelines/pipeline_graph/mock_data.js10
-rw-r--r--spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js18
-rw-r--r--spec/frontend/pipelines/pipeline_graph/utils_spec.js44
-rw-r--r--spec/frontend/pipelines/pipeline_url_spec.js2
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js28
-rw-r--r--spec/frontend/pipelines/pipelines_artifacts_spec.js16
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js98
-rw-r--r--spec/frontend/pipelines/pipelines_store_spec.js5
-rw-r--r--spec/frontend/pipelines/pipelines_table_row_spec.js21
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js2
-rw-r--r--spec/frontend/pipelines/shared/links_layer_spec.js99
-rw-r--r--spec/frontend/pipelines/stage_spec.js77
-rw-r--r--spec/frontend/pipelines/stores/pipeline_store_spec.js4
-rw-r--r--spec/frontend/pipelines/test_reports/stores/actions_spec.js22
-rw-r--r--spec/frontend/pipelines/test_reports/stores/getters_spec.js4
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js2
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js6
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_spec.js2
-rw-r--r--spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js2
-rw-r--r--spec/frontend/pipelines/unwrapping_utils_spec.js26
-rw-r--r--spec/frontend/profile/account/components/delete_account_modal_spec.js20
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js2
-rw-r--r--spec/frontend/project_find_file_spec.js11
-rw-r--r--spec/frontend/projects/commit/components/branches_dropdown_spec.js166
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js155
-rw-r--r--spec/frontend/projects/commit/components/form_trigger_spec.js44
-rw-r--r--spec/frontend/projects/commit/mock_data.js27
-rw-r--r--spec/frontend/projects/commit/store/actions_spec.js111
-rw-r--r--spec/frontend/projects/commit/store/getters_spec.js21
-rw-r--r--spec/frontend/projects/commit/store/mutations_spec.js57
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js26
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap1
-rw-r--r--spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap67
-rw-r--r--spec/frontend/projects/components/shared/delete_button_spec.js16
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/app_spec.js24
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/legacy_container_spec.js2
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js2
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap27
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap27
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap9
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js72
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js134
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js39
-rw-r--r--spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js78
-rw-r--r--spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js30
-rw-r--r--spec/frontend/projects/pipelines/charts/mock_data.js16
-rw-r--r--spec/frontend/projects/project_import_gitlab_project_spec.js2
-rw-r--r--spec/frontend/projects/project_new_spec.js7
-rw-r--r--spec/frontend/projects/projects_filterable_list_spec.js2
-rw-r--r--spec/frontend/projects/settings/access_dropdown_spec.js10
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js4
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js4
-rw-r--r--spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js8
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js13
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js24
-rw-r--r--spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap87
-rw-r--r--spec/frontend/registry/explorer/components/delete_button_spec.js2
-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.js2
-rw-r--r--spec/frontend/registry/explorer/components/details_page/details_header_spec.js121
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js6
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js24
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js6
-rw-r--r--spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap2
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js21
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_spec.js20
-rw-r--r--spec/frontend/registry/explorer/components/list_page/registry_header_spec.js7
-rw-r--r--spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js93
-rw-r--r--spec/frontend/registry/explorer/mock_data.js32
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js27
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js100
-rw-r--r--spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap4
-rw-r--r--spec/frontend/registry/settings/components/expiration_dropdown_spec.js7
-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.js4
-rw-r--r--spec/frontend/registry/settings/mock_data.js2
-rw-r--r--spec/frontend/registry/settings/utils_spec.js5
-rw-r--r--spec/frontend/related_merge_requests/components/related_merge_requests_spec.js7
-rw-r--r--spec/frontend/related_merge_requests/store/actions_spec.js12
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap48
-rw-r--r--spec/frontend/releases/components/app_edit_new_spec.js6
-rw-r--r--spec/frontend/releases/components/app_index_spec.js34
-rw-r--r--spec/frontend/releases/components/app_show_spec.js2
-rw-r--r--spec/frontend/releases/components/asset_links_form_spec.js6
-rw-r--r--spec/frontend/releases/components/issuable_stats_spec.js2
-rw-r--r--spec/frontend/releases/components/release_block_assets_spec.js14
-rw-r--r--spec/frontend/releases/components/release_block_milestone_info_spec.js32
-rw-r--r--spec/frontend/releases/components/releases_pagination_graphql_spec.js4
-rw-r--r--spec/frontend/releases/components/releases_pagination_rest_spec.js2
-rw-r--r--spec/frontend/releases/components/releases_pagination_spec.js2
-rw-r--r--spec/frontend/releases/components/tag_field_new_spec.js2
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js4
-rw-r--r--spec/frontend/releases/stores/modules/list/helpers.js2
-rw-r--r--spec/frontend/reports/accessibility_report/store/actions_spec.js12
-rw-r--r--spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js12
-rw-r--r--spec/frontend/reports/codequality_report/store/actions_spec.js12
-rw-r--r--spec/frontend/reports/codequality_report/store/utils/codequality_comparison_spec.js6
-rw-r--r--spec/frontend/reports/components/grouped_issues_list_spec.js6
-rw-r--r--spec/frontend/reports/components/grouped_test_reports_app_spec.js70
-rw-r--r--spec/frontend/reports/components/issue_status_icon_spec.js2
-rw-r--r--spec/frontend/reports/components/modal_open_name_spec.js47
-rw-r--r--spec/frontend/reports/components/modal_spec.js57
-rw-r--r--spec/frontend/reports/components/report_link_spec.js2
-rw-r--r--spec/frontend/reports/components/report_section_spec.js18
-rw-r--r--spec/frontend/reports/components/test_issue_body_spec.js4
-rw-r--r--spec/frontend/reports/store/actions_spec.js30
-rw-r--r--spec/frontend/reports/store/mutations_spec.js27
-rw-r--r--spec/frontend/repository/components/breadcrumbs_spec.js16
-rw-r--r--spec/frontend/repository/components/directory_download_links_spec.js5
-rw-r--r--spec/frontend/repository/components/last_commit_spec.js10
-rw-r--r--spec/frontend/repository/utils/dom_spec.js2
-rw-r--r--spec/frontend/right_sidebar_spec.js6
-rw-r--r--spec/frontend/search/index_spec.js2
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js2
-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.js2
-rw-r--r--spec/frontend/search/topbar/components/searchable_dropdown_spec.js4
-rw-r--r--spec/frontend/search_autocomplete_spec.js10
-rw-r--r--spec/frontend/search_settings/components/search_settings_spec.js106
-rw-r--r--spec/frontend/search_settings/index_spec.js36
-rw-r--r--spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap1
-rw-r--r--spec/frontend/self_monitor/components/self_monitor_form_spec.js5
-rw-r--r--spec/frontend/self_monitor/store/actions_spec.js20
-rw-r--r--spec/frontend/sentry/sentry_config_spec.js4
-rw-r--r--spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js5
-rw-r--r--spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap2
-rw-r--r--spec/frontend/serverless/components/area_spec.js4
-rw-r--r--spec/frontend/serverless/components/function_row_spec.js2
-rw-r--r--spec/frontend/serverless/components/missing_prometheus_spec.js2
-rw-r--r--spec/frontend/serverless/components/pod_box_spec.js2
-rw-r--r--spec/frontend/serverless/components/url_spec.js2
-rw-r--r--spec/frontend/serverless/mock_data.js5
-rw-r--r--spec/frontend/serverless/store/actions_spec.js12
-rw-r--r--spec/frontend/serverless/utils.js6
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js24
-rw-r--r--spec/frontend/shared/popover_spec.js20
-rw-r--r--spec/frontend/shortcuts_spec.js6
-rw-r--r--spec/frontend/sidebar/assignee_title_spec.js2
-rw-r--r--spec/frontend/sidebar/assignees_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js7
-rw-r--r--spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js2
-rw-r--r--spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js22
-rw-r--r--spec/frontend/sidebar/components/severity/severity_spec.js2
-rw-r--r--spec/frontend/sidebar/components/severity/sidebar_severity_spec.js22
-rw-r--r--spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js12
-rw-r--r--spec/frontend/sidebar/confidential/edit_form_spec.js2
-rw-r--r--spec/frontend/sidebar/lock/edit_form_buttons_spec.js2
-rw-r--r--spec/frontend/sidebar/lock/edit_form_spec.js2
-rw-r--r--spec/frontend/sidebar/lock/issuable_lock_form_spec.js4
-rw-r--r--spec/frontend/sidebar/participants_spec.js2
-rw-r--r--spec/frontend/sidebar/reviewer_title_spec.js23
-rw-r--r--spec/frontend/sidebar/reviewers_spec.js2
-rw-r--r--spec/frontend/sidebar/sidebar_assignees_spec.js2
-rw-r--r--spec/frontend/sidebar/sidebar_mediator_spec.js2
-rw-r--r--spec/frontend/sidebar/sidebar_move_issue_spec.js18
-rw-r--r--spec/frontend/sidebar/sidebar_store_spec.js2
-rw-r--r--spec/frontend/sidebar/subscriptions_spec.js2
-rw-r--r--spec/frontend/sidebar/todo_spec.js7
-rw-r--r--spec/frontend/snippet/collapsible_input_spec.js12
-rw-r--r--spec/frontend/snippets/components/edit_spec.js14
-rw-r--r--spec/frontend/snippets/components/embed_dropdown_spec.js2
-rw-r--r--spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js22
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js39
-rw-r--r--spec/frontend/snippets/components/snippet_visibility_edit_spec.js2
-rw-r--r--spec/frontend/snippets/utils/blob_spec.js2
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js67
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_controls_spec.js2
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/file_spec.js2
-rw-r--r--spec/frontend/static_site_editor/services/load_source_content_spec.js2
-rw-r--r--spec/frontend/static_site_editor/services/submit_content_changes_spec.js2
-rw-r--r--spec/frontend/syntax_highlight_spec.js2
-rw-r--r--spec/frontend/task_list_spec.js4
-rw-r--r--spec/frontend/terraform/components/states_table_actions_spec.js2
-rw-r--r--spec/frontend/terraform/components/terraform_list_spec.js2
-rw-r--r--spec/frontend/test_setup.js27
-rw-r--r--spec/frontend/toggle_buttons_spec.js2
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js12
-rw-r--r--spec/frontend/tooltips/index_spec.js8
-rw-r--r--spec/frontend/tracking_spec.js2
-rw-r--r--spec/frontend/transfer_edit_spec.js38
-rw-r--r--spec/frontend/user_lists/components/add_user_modal_spec.js2
-rw-r--r--spec/frontend/user_lists/components/edit_user_list_spec.js4
-rw-r--r--spec/frontend/user_lists/components/new_user_list_spec.js4
-rw-r--r--spec/frontend/user_lists/components/user_list_spec.js16
-rw-r--r--spec/frontend/user_lists/store/show/mutations_spec.js6
-rw-r--r--spec/frontend/user_popovers_spec.js4
-rw-r--r--spec/frontend/version_check_image_spec.js4
-rw-r--r--spec/frontend/vue_alerts_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js39
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js50
-rw-r--r--spec/frontend/vue_mr_widget/components/artifacts_list_spec.js20
-rw-r--r--spec/frontend/vue_mr_widget/components/mock_data.js14
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js16
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js4
-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.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js20
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js268
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/review_app_link_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap183
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js421
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js64
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js3
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js11
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js47
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/mock_data.js24
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js444
-rw-r--r--spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js14
-rw-r--r--spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/actions_button_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/alert_details_table_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/awards_list_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/ci_badge_link_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/clipboard_button_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/color_picker/color_picker_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/commit_spec.js13
-rw-r--r--spec/frontend/vue_shared/components/confirm_modal_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js103
-rw-r--r--spec/frontend/vue_shared/components/deployment_instance/mock_data.js144
-rw-r--r--spec/frontend/vue_shared/components/deprecated_modal_2_spec.js258
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/dismissible_container_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/editor_lite_spec.js42
-rw-r--r--spec/frontend/vue_shared/components/expand_button_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/file_finder/index_spec.js30
-rw-r--r--spec/frontend/vue_shared/components/file_finder/item_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/file_tree_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js51
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js13
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper.js4
-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.js13
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap13
-rw-r--r--spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js83
-rw-r--r--spec/frontend/vue_shared/components/gl_countdown_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/gl_modal_vuex_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_assignees_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_milestone_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js2
-rw-r--r--spec/frontend/vue_shared/components/local_storage_sync_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestions_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/navigation_tabs_spec.js82
-rw-r--r--spec/frontend/vue_shared/components/notes/noteable_warning_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/ordered_layout_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js19
-rw-r--r--spec/frontend/vue_shared/components/pagination_links_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/pikaday_spec.js45
-rw-r--r--spec/frontend/vue_shared/components/project_avatar/default_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/registry/details_row_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/list_item_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/registry/metadata_item_spec.js23
-rw-r--r--spec/frontend/vue_shared/components/registry/title_area_spec.js42
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js2
-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_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js8
-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_identifier_paragraph_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/security_reports/help_icon_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/security_reports/security_summary_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/sidebar/date_picker_spec.js35
-rw-r--r--spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js32
-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_value_collapsed_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js30
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/getters_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/slot_switch_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/split_button_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/stacked_progress_bar_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/table_pagination_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/tabs/tab_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js11
-rw-r--r--spec/frontend/vue_shared/directives/tooltip_spec.js8
-rw-r--r--spec/frontend/vue_shared/directives/validation_spec.js6
-rw-r--r--spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js2
-rw-r--r--spec/frontend/vue_shared/security_reports/mock_data.js75
-rw-r--r--spec/frontend/vue_shared/security_reports/security_reports_app_spec.js22
-rw-r--r--spec/frontend/vue_shared/security_reports/store/getters_spec.js2
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js16
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js16
-rw-r--r--spec/frontend/vue_shared/security_reports/utils_spec.js7
-rw-r--r--spec/frontend/vuex_shared/modules/modal/actions_spec.js8
-rw-r--r--spec/frontend/whats_new/components/app_spec.js4
-rw-r--r--spec/frontend/wikis_spec.js222
-rw-r--r--spec/frontend/zen_mode_spec.js5
-rw-r--r--spec/frontend_integration/ide/helpers/ide_helper.js66
-rw-r--r--spec/frontend_integration/ide/helpers/start.js14
-rw-r--r--spec/frontend_integration/ide/ide_integration_spec.js25
-rw-r--r--spec/frontend_integration/ide/user_opens_file_spec.js4
-rw-r--r--spec/frontend_integration/test_helpers/factories/commit_id.js4
-rw-r--r--spec/frontend_integration/test_helpers/fixtures.js6
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/index.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/404.js4
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/ci.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/graphql.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/index.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/projects.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/repository.js20
-rw-r--r--spec/frontend_integration/test_helpers/setup/index.js1
-rw-r--r--spec/frontend_integration/test_helpers/setup/setup_testing_library.js3
-rw-r--r--spec/frontend_integration/test_helpers/snapshot_serializer.js2
-rw-r--r--spec/frontend_integration/test_helpers/utils/obj_spec.js6
-rw-r--r--spec/graphql/mutations/namespace/package_settings/update_spec.rb98
-rw-r--r--spec/graphql/mutations/releases/create_spec.rb7
-rw-r--r--spec/graphql/mutations/releases/update_spec.rb7
-rw-r--r--spec/graphql/resolvers/ci/config_resolver_spec.rb29
-rw-r--r--spec/graphql/resolvers/ci/jobs_resolver_spec.rb3
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/package_details_resolver_spec.rb21
-rw-r--r--spec/graphql/resolvers/projects_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/release_milestones_resolver_spec.rb23
-rw-r--r--spec/graphql/resolvers/user_notes_count_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/users_resolver_spec.rb26
-rw-r--r--spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb44
-rw-r--r--spec/graphql/types/base_enum_spec.rb70
-rw-r--r--spec/graphql/types/board_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/config/job_restriction_type_spec.rb13
-rw-r--r--spec/graphql/types/ci/config/job_type_spec.rb9
-rw-r--r--spec/graphql/types/ci/job_type_spec.rb1
-rw-r--r--spec/graphql/types/issue_type_spec.rb3
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb14
-rw-r--r--spec/graphql/types/namespace/package_settings_type_spec.rb17
-rw-r--r--spec/graphql/types/notes/note_type_spec.rb1
-rw-r--r--spec/graphql/types/package_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/composer/details_type_spec.rb23
-rw-r--r--spec/graphql/types/packages/composer/json_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/composer/metadatum_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/package_type_enum_spec.rb (renamed from spec/graphql/types/package_type_enum_spec.rb)0
-rw-r--r--spec/graphql/types/packages/package_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/tag_type_spec.rb15
-rw-r--r--spec/graphql/types/project_type_spec.rb2
-rw-r--r--spec/graphql/types/projects/service_type_spec.rb2
-rw-r--r--spec/graphql/types/query_type_spec.rb6
-rw-r--r--spec/graphql/types/repository_type_spec.rb2
-rw-r--r--spec/helpers/blob_helper_spec.rb11
-rw-r--r--spec/helpers/ci/pipelines_helper_spec.rb19
-rw-r--r--spec/helpers/ci/triggers_helper_spec.rb31
-rw-r--r--spec/helpers/commits_helper_spec.rb33
-rw-r--r--spec/helpers/dashboard_helper_spec.rb6
-rw-r--r--spec/helpers/graph_helper_spec.rb12
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb12
-rw-r--r--spec/helpers/invite_members_helper_spec.rb65
-rw-r--r--spec/helpers/jira_connect_helper_spec.rb15
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb33
-rw-r--r--spec/helpers/projects/project_members_helper_spec.rb145
-rw-r--r--spec/helpers/projects_helper_spec.rb29
-rw-r--r--spec/helpers/services_helper_spec.rb50
-rw-r--r--spec/helpers/tree_helper_spec.rb3
-rw-r--r--spec/helpers/users_helper_spec.rb6
-rw-r--r--spec/helpers/visibility_level_helper_spec.rb38
-rw-r--r--spec/initializers/carrierwave_patch_spec.rb97
-rw-r--r--spec/javascripts/fly_out_nav_browser_spec.js9
-rw-r--r--spec/javascripts/lib/utils/browser_spec.js106
-rw-r--r--spec/javascripts/matchers.js7
-rw-r--r--spec/javascripts/test_bundle.js20
-rw-r--r--spec/javascripts/test_constants.js2
-rw-r--r--spec/lib/api/entities/snippet_repository_storage_move_spec.rb25
-rw-r--r--spec/lib/api/helpers/authentication_spec.rb207
-rw-r--r--spec/lib/api/helpers_spec.rb47
-rw-r--r--spec/lib/atlassian/jira_connect/client_spec.rb300
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/build_entity_spec.rb4
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/deployment_entity_spec.rb95
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb85
-rw-r--r--spec/lib/banzai/filter/asset_proxy_filter_spec.rb10
-rw-r--r--spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb12
-rw-r--r--spec/lib/banzai/filter/reference_redactor_filter_spec.rb31
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb24
-rw-r--r--spec/lib/banzai/filter/truncate_source_filter_spec.rb31
-rw-r--r--spec/lib/banzai/pipeline/description_pipeline_spec.rb2
-rw-r--r--spec/lib/banzai/pipeline/gfm_pipeline_spec.rb4
-rw-r--r--spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb8
-rw-r--r--spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb7
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb16
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb10
-rw-r--r--spec/lib/bulk_imports/importers/group_importer_spec.rb5
-rw-r--r--spec/lib/bulk_imports/importers/groups_importer_spec.rb36
-rw-r--r--spec/lib/bulk_imports/pipeline_spec.rb14
-rw-r--r--spec/lib/constraints/admin_constrainer_spec.rb2
-rw-r--r--spec/lib/container_registry/client_spec.rb100
-rw-r--r--spec/lib/declarative_enum_spec.rb147
-rw-r--r--spec/lib/expand_variables_spec.rb37
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production_spec.rb7
-rw-r--r--spec/lib/gitlab/api_authentication/builder_spec.rb76
-rw-r--r--spec/lib/gitlab/api_authentication/sent_through_builder_spec.rb17
-rw-r--r--spec/lib/gitlab/api_authentication/token_locator_spec.rb55
-rw-r--r--spec/lib/gitlab/api_authentication/token_resolver_spec.rb117
-rw-r--r--spec/lib/gitlab/api_authentication/token_type_builder_spec.rb16
-rw-r--r--spec/lib/gitlab/asset_proxy_spec.rb4
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb58
-rw-r--r--spec/lib/gitlab/auth/current_user_mode_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/ldap/config_spec.rb22
-rw-r--r--spec/lib/gitlab/auth/request_authenticator_spec.rb5
-rw-r--r--spec/lib/gitlab/auth_spec.rb5
-rw-r--r--spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb82
-rw-r--r--spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb91
-rw-r--r--spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb113
-rw-r--r--spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb121
-rw-r--r--spec/lib/gitlab/checks/diff_check_spec.rb97
-rw-r--r--spec/lib/gitlab/ci/config/entry/artifacts_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/config/entry/variables_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb126
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb24
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/build_spec.rb114
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/reports/test_failure_history_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/status/group/factory_spec.rb5
-rw-r--r--spec/lib/gitlab/ci/syntax_templates_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb49
-rw-r--r--spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sorted_spec.rb251
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb34
-rw-r--r--spec/lib/gitlab/composer/version_index_spec.rb49
-rw-r--r--spec/lib/gitlab/config/entry/composable_hash_spec.rb2
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb32
-rw-r--r--spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb49
-rw-r--r--spec/lib/gitlab/cycle_analytics/code_event_fetcher_spec.rb13
-rw-r--r--spec/lib/gitlab/cycle_analytics/code_stage_spec.rb129
-rw-r--r--spec/lib/gitlab/cycle_analytics/events_spec.rb182
-rw-r--r--spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb9
-rw-r--r--spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb136
-rw-r--r--spec/lib/gitlab/cycle_analytics/plan_event_fetcher_spec.rb17
-rw-r--r--spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb116
-rw-r--r--spec/lib/gitlab/cycle_analytics/production_event_fetcher_spec.rb9
-rw-r--r--spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb9
-rw-r--r--spec/lib/gitlab/cycle_analytics/review_stage_spec.rb90
-rw-r--r--spec/lib/gitlab/cycle_analytics/staging_event_fetcher_spec.rb13
-rw-r--r--spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb99
-rw-r--r--spec/lib/gitlab/cycle_analytics/test_event_fetcher_spec.rb13
-rw-r--r--spec/lib/gitlab/cycle_analytics/test_stage_spec.rb57
-rw-r--r--spec/lib/gitlab/danger/base_linter_spec.rb53
-rw-r--r--spec/lib/gitlab/danger/changelog_spec.rb71
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb56
-rw-r--r--spec/lib/gitlab/danger/roulette_spec.rb63
-rw-r--r--spec/lib/gitlab/danger/teammate_spec.rb8
-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.rb1
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb1
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb190
-rw-r--r--spec/lib/gitlab/database/partitioning/partition_creator_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning/replace_table_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb139
-rw-r--r--spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb83
-rw-r--r--spec/lib/gitlab/database/postgres_hll/buckets_spec.rb33
-rw-r--r--spec/lib/gitlab/database/reindexing/coordinator_spec.rb82
-rw-r--r--spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb139
-rw-r--r--spec/lib/gitlab/database/reindexing/index_selection_spec.rb2
-rw-r--r--spec/lib/gitlab/database/reindexing/reindex_action_spec.rb112
-rw-r--r--spec/lib/gitlab/database/reindexing_spec.rb9
-rw-r--r--spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb30
-rw-r--r--spec/lib/gitlab/diff/position_spec.rb58
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb234
-rw-r--r--spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb61
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb10
-rw-r--r--spec/lib/gitlab/email/handler_spec.rb5
-rw-r--r--spec/lib/gitlab/error_tracking_spec.rb21
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb10
-rw-r--r--spec/lib/gitlab/experimentation/experiment_spec.rb6
-rw-r--r--spec/lib/gitlab/experimentation_spec.rb2
-rw-r--r--spec/lib/gitlab/faraday/error_callback_spec.rb59
-rw-r--r--spec/lib/gitlab/git/changed_path_spec.rb29
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb2
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb31
-rw-r--r--spec/lib/gitlab/git/wiki_page_version_spec.rb28
-rw-r--r--spec/lib/gitlab/git_access_snippet_spec.rb89
-rw-r--r--spec/lib/gitlab/git_access_spec.rb60
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb6
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb5
-rw-r--r--spec/lib/gitlab/github_import/importer/repository_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/gitpod_spec.rb73
-rw-r--r--spec/lib/gitlab/graphql/batch_key_spec.rb78
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb41
-rw-r--r--spec/lib/gitlab/graphql/queries_spec.rb343
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml4
-rw-r--r--spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb24
-rw-r--r--spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb5
-rw-r--r--spec/lib/gitlab/kubernetes/pod_cmd_spec.rb14
-rw-r--r--spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb10
-rw-r--r--spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb10
-rw-r--r--spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb10
-rw-r--r--spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb12
-rw-r--r--spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb10
-rw-r--r--spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/system_spec.rb34
-rw-r--r--spec/lib/gitlab/middleware/multipart/handler_for_jwt_params_spec.rb53
-rw-r--r--spec/lib/gitlab/middleware/multipart_spec.rb198
-rw-r--r--spec/lib/gitlab/middleware/multipart_with_handler_for_jwt_params_spec.rb202
-rw-r--r--spec/lib/gitlab/middleware/multipart_with_handler_spec.rb196
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb6
-rw-r--r--spec/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled_spec.rb1
-rw-r--r--spec/lib/gitlab/project_template_spec.rb1
-rw-r--r--spec/lib/gitlab/prometheus/internal_spec.rb48
-rw-r--r--spec/lib/gitlab/rack_attack_spec.rb212
-rw-r--r--spec/lib/gitlab/search_results_spec.rb39
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb2
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb9
-rw-r--r--spec/lib/gitlab/template/gitlab_ci_syntax_yml_template_spec.rb17
-rw-r--r--spec/lib/gitlab/throttle_spec.rb28
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb55
-rw-r--r--spec/lib/gitlab/tracking_spec.rb43
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/usage/metric_definition_spec.rb123
-rw-r--r--spec/lib/gitlab/usage/metric_spec.rb29
-rw-r--r--spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb31
-rw-r--r--spec/lib/gitlab/usage_data_counters/guest_package_event_counter_spec.rb31
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb156
-rw-r--r--spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb151
-rw-r--r--spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb31
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb6
-rw-r--r--spec/lib/gitlab/user_access_spec.rb32
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb112
-rw-r--r--spec/lib/gitlab/utils_spec.rb17
-rw-r--r--spec/lib/gitlab/uuid_spec.rb19
-rw-r--r--spec/lib/gitlab/visibility_level_spec.rb48
-rw-r--r--spec/lib/release_highlights/validator/entry_spec.rb87
-rw-r--r--spec/lib/release_highlights/validator_spec.rb85
-rw-r--r--spec/lib/uploaded_file_spec.rb194
-rw-r--r--spec/mailers/emails/merge_requests_spec.rb2
-rw-r--r--spec/mailers/emails/pipelines_spec.rb32
-rw-r--r--spec/mailers/notify_spec.rb86
-rw-r--r--spec/migrations/20210112143418_remove_duplicate_services2_spec.rb52
-rw-r--r--spec/migrations/add_has_external_wiki_trigger_spec.rb128
-rw-r--r--spec/migrations/remove_alerts_service_records_spec.rb30
-rw-r--r--spec/migrations/remove_duplicate_labels_from_groups_spec.rb227
-rw-r--r--spec/migrations/schedule_populate_finding_uuid_for_vulnerability_feedback_spec.rb37
-rw-r--r--spec/models/alert_management/http_integration_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb39
-rw-r--r--spec/models/audit_event_archived_spec.rb52
-rw-r--r--spec/models/audit_event_partitioned_spec.rb52
-rw-r--r--spec/models/ci/bridge_spec.rb12
-rw-r--r--spec/models/ci/build_need_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb249
-rw-r--r--spec/models/ci/commit_with_pipeline_spec.rb124
-rw-r--r--spec/models/ci/group_spec.rb12
-rw-r--r--spec/models/ci/job_artifact_spec.rb33
-rw-r--r--spec/models/ci/ref_spec.rb60
-rw-r--r--spec/models/clusters/applications/knative_spec.rb6
-rw-r--r--spec/models/commit_spec.rb13
-rw-r--r--spec/models/commit_status_spec.rb19
-rw-r--r--spec/models/commit_with_pipeline_spec.rb124
-rw-r--r--spec/models/concerns/ci/artifactable_spec.rb19
-rw-r--r--spec/models/concerns/each_batch_spec.rb16
-rw-r--r--spec/models/concerns/milestoneable_spec.rb4
-rw-r--r--spec/models/concerns/noteable_spec.rb104
-rw-r--r--spec/models/cycle_analytics/code_spec.rb73
-rw-r--r--spec/models/cycle_analytics/issue_spec.rb46
-rw-r--r--spec/models/cycle_analytics/plan_spec.rb52
-rw-r--r--spec/models/cycle_analytics/project_level_spec.rb34
-rw-r--r--spec/models/cycle_analytics/project_level_stage_adapter_spec.rb38
-rw-r--r--spec/models/cycle_analytics/review_spec.rb34
-rw-r--r--spec/models/cycle_analytics/staging_spec.rb56
-rw-r--r--spec/models/cycle_analytics/test_spec.rb73
-rw-r--r--spec/models/deployment_spec.rb50
-rw-r--r--spec/models/experiment_spec.rb58
-rw-r--r--spec/models/group_spec.rb20
-rw-r--r--spec/models/list_spec.rb67
-rw-r--r--spec/models/members/group_member_spec.rb12
-rw-r--r--spec/models/merge_request_spec.rb148
-rw-r--r--spec/models/namespace/package_setting_spec.rb81
-rw-r--r--spec/models/namespace_onboarding_action_spec.rb53
-rw-r--r--spec/models/namespace_spec.rb23
-rw-r--r--spec/models/onboarding_progress_spec.rb107
-rw-r--r--spec/models/packages/debian/file_metadatum_spec.rb91
-rw-r--r--spec/models/packages/debian/group_architecture_spec.rb7
-rw-r--r--spec/models/packages/debian/group_distribution_spec.rb7
-rw-r--r--spec/models/packages/debian/project_architecture_spec.rb7
-rw-r--r--spec/models/packages/debian/project_distribution_spec.rb7
-rw-r--r--spec/models/packages/package_file_spec.rb1
-rw-r--r--spec/models/packages/package_spec.rb24
-rw-r--r--spec/models/project_import_state_spec.rb2
-rw-r--r--spec/models/project_pages_metadatum_spec.rb21
-rw-r--r--spec/models/project_services/alerts_service_spec.rb110
-rw-r--r--spec/models/project_services/jira_service_spec.rb53
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb4
-rw-r--r--spec/models/project_spec.rb310
-rw-r--r--spec/models/project_wiki_spec.rb6
-rw-r--r--spec/models/protectable_dropdown_spec.rb32
-rw-r--r--spec/models/release_highlight_spec.rb2
-rw-r--r--spec/models/release_spec.rb12
-rw-r--r--spec/models/repository_spec.rb18
-rw-r--r--spec/models/snippet_repository_storage_move_spec.rb2
-rw-r--r--spec/models/snippet_spec.rb86
-rw-r--r--spec/models/terraform/state_spec.rb16
-rw-r--r--spec/models/user_spec.rb20
-rw-r--r--spec/policies/group_member_policy_spec.rb65
-rw-r--r--spec/policies/namespace_policy_spec.rb2
-rw-r--r--spec/policies/project_policy_spec.rb42
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb28
-rw-r--r--spec/presenters/packages/nuget/service_index_presenter_spec.rb55
-rw-r--r--spec/rack_servers/puma_spec.rb2
-rw-r--r--spec/rack_servers/unicorn_spec.rb2
-rw-r--r--spec/requests/api/api_spec.rb2
-rw-r--r--spec/requests/api/boards_spec.rb11
-rw-r--r--spec/requests/api/ci/runner/jobs_put_spec.rb27
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb6
-rw-r--r--spec/requests/api/debian_project_packages_spec.rb7
-rw-r--r--spec/requests/api/generic_packages_spec.rb189
-rw-r--r--spec/requests/api/graphql/ci/ci_cd_setting_spec.rb10
-rw-r--r--spec/requests/api/graphql/ci/config_spec.rb304
-rw-r--r--spec/requests/api/graphql/ci/jobs_spec.rb155
-rw-r--r--spec/requests/api/graphql/ci/pipelines_spec.rb112
-rw-r--r--spec/requests/api/graphql/group/group_members_spec.rb16
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb16
-rw-r--r--spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb58
-rw-r--r--spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb142
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb22
-rw-r--r--spec/requests/api/graphql/mutations/releases/update_spec.rb10
-rw-r--r--spec/requests/api/graphql/namespace/package_settings_spec.rb33
-rw-r--r--spec/requests/api/graphql/packages/package_composer_details_spec.rb39
-rw-r--r--spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb34
-rw-r--r--spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb26
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb72
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb155
-rw-r--r--spec/requests/api/graphql/project/project_members_spec.rb9
-rw-r--r--spec/requests/api/graphql/project/release_spec.rb33
-rw-r--r--spec/requests/api/graphql/project_query_spec.rb66
-rw-r--r--spec/requests/api/graphql/user/starred_projects_query_spec.rb24
-rw-r--r--spec/requests/api/graphql/users_spec.rb46
-rw-r--r--spec/requests/api/group_packages_spec.rb4
-rw-r--r--spec/requests/api/invitations_spec.rb84
-rw-r--r--spec/requests/api/jobs_spec.rb141
-rw-r--r--spec/requests/api/labels_spec.rb27
-rw-r--r--spec/requests/api/lint_spec.rb4
-rw-r--r--spec/requests/api/maven_packages_spec.rb50
-rw-r--r--spec/requests/api/merge_requests_spec.rb139
-rw-r--r--spec/requests/api/nuget_group_packages_spec.rb122
-rw-r--r--spec/requests/api/nuget_project_packages_spec.rb384
-rw-r--r--spec/requests/api/project_packages_spec.rb4
-rw-r--r--spec/requests/api/project_repository_storage_moves_spec.rb220
-rw-r--r--spec/requests/api/project_templates_spec.rb17
-rw-r--r--spec/requests/api/projects_spec.rb38
-rw-r--r--spec/requests/api/releases_spec.rb35
-rw-r--r--spec/requests/api/snippet_repository_storage_moves_spec.rb12
-rw-r--r--spec/requests/api/terraform/state_spec.rb37
-rw-r--r--spec/requests/api/todos_spec.rb2
-rw-r--r--spec/requests/api/users_spec.rb184
-rw-r--r--spec/requests/jwks_controller_spec.rb36
-rw-r--r--spec/requests/lfs_http_spec.rb16
-rw-r--r--spec/requests/profiles/notifications_controller_spec.rb2
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb134
-rw-r--r--spec/requests/projects/incident_management/pagerduty_incidents_spec.rb2
-rw-r--r--spec/requests/rack_attack_global_spec.rb82
-rw-r--r--spec/requests/runner_setup_controller_spec.rb21
-rw-r--r--spec/requests/users_controller_spec.rb833
-rw-r--r--spec/routing/notifications_routing_spec.rb8
-rw-r--r--spec/routing/project_routing_spec.rb24
-rw-r--r--spec/routing/routing_spec.rb92
-rw-r--r--spec/rubocop/cop/active_record_association_reload_spec.rb2
-rw-r--r--spec/rubocop/cop/api/base_spec.rb2
-rw-r--r--spec/rubocop/cop/avoid_becomes_spec.rb2
-rw-r--r--spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb2
-rw-r--r--spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb2
-rw-r--r--spec/rubocop/cop/avoid_return_from_blocks_spec.rb2
-rw-r--r--spec/rubocop/cop/avoid_route_redirect_leading_slash_spec.rb2
-rw-r--r--spec/rubocop/cop/ban_catch_throw_spec.rb2
-rw-r--r--spec/rubocop/cop/code_reuse/finder_spec.rb2
-rw-r--r--spec/rubocop/cop/code_reuse/presenter_spec.rb2
-rw-r--r--spec/rubocop/cop/code_reuse/serializer_spec.rb2
-rw-r--r--spec/rubocop/cop/code_reuse/service_class_spec.rb2
-rw-r--r--spec/rubocop/cop/code_reuse/worker_spec.rb2
-rw-r--r--spec/rubocop/cop/default_scope_spec.rb2
-rw-r--r--spec/rubocop/cop/destroy_all_spec.rb2
-rw-r--r--spec/rubocop/cop/filename_length_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/bulk_insert_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/change_timezone_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/except_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/httparty_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/intersect_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/json_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/predicate_memoization_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/rails_logger_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/union_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/authorize_types_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/descriptions_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/gid_expected_type_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/id_type_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/json_type_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/resolver_type_spec.rb2
-rw-r--r--spec/rubocop/cop/group_public_or_visible_to_user_spec.rb2
-rw-r--r--spec/rubocop/cop/ignored_columns_spec.rb2
-rw-r--r--spec/rubocop/cop/include_sidekiq_worker_spec.rb2
-rw-r--r--spec/rubocop/cop/inject_enterprise_edition_module_spec.rb2
-rw-r--r--spec/rubocop/cop/lint/last_keyword_argument_spec.rb29
-rw-r--r--spec/rubocop/cop/migration/add_column_with_default_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_concurrent_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_reference_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_timestamps_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/datetime_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/drop_table_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/hash_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/prevent_strings_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/remove_column_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/remove_concurrent_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/remove_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/safer_boolean_column_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/timestamps_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/update_column_in_batches_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/with_lock_retries_disallowed_method_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/with_lock_retries_with_change_spec.rb2
-rw-r--r--spec/rubocop/cop/performance/ar_count_each_spec.rb2
-rw-r--r--spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb2
-rw-r--r--spec/rubocop/cop/performance/readlines_each_spec.rb2
-rw-r--r--spec/rubocop/cop/prefer_class_methods_over_module_spec.rb2
-rw-r--r--spec/rubocop/cop/project_path_helper_spec.rb2
-rw-r--r--spec/rubocop/cop/put_group_routes_under_scope_spec.rb2
-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.rb2
-rw-r--r--spec/rubocop/cop/qa/element_with_pattern_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/any_instance_of_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/be_success_matcher_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/env_assignment_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/timecop_freeze_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/timecop_travel_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/top_level_describe_path_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/web_mock_enable_spec.rb22
-rw-r--r--spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb2
-rw-r--r--spec/rubocop/cop/safe_params_spec.rb2
-rw-r--r--spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb2
-rw-r--r--spec/rubocop/cop/scalability/cron_worker_context_spec.rb2
-rw-r--r--spec/rubocop/cop/scalability/file_uploads_spec.rb2
-rw-r--r--spec/rubocop/cop/scalability/idempotent_worker_spec.rb2
-rw-r--r--spec/rubocop/cop/sidekiq_options_queue_spec.rb2
-rw-r--r--spec/rubocop/cop/static_translation_definition_spec.rb2
-rw-r--r--spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb2
-rw-r--r--spec/rubocop/cop/usage_data/large_table_spec.rb2
-rw-r--r--spec/rubocop/qa_helpers_spec.rb2
-rw-r--r--spec/serializers/analytics_stage_serializer_spec.rb56
-rw-r--r--spec/serializers/build_details_entity_spec.rb39
-rw-r--r--spec/serializers/deploy_key_entity_spec.rb8
-rw-r--r--spec/serializers/diffs_metadata_entity_spec.rb1
-rw-r--r--spec/serializers/environment_entity_spec.rb22
-rw-r--r--spec/serializers/member_entity_spec.rb71
-rw-r--r--spec/serializers/member_serializer_spec.rb32
-rw-r--r--spec/serializers/member_user_entity_spec.rb38
-rw-r--r--spec/serializers/merge_request_poll_cached_widget_entity_spec.rb12
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb11
-rw-r--r--spec/serializers/merge_requests/pipeline_entity_spec.rb4
-rw-r--r--spec/serializers/pipeline_details_entity_spec.rb2
-rw-r--r--spec/serializers/runner_entity_spec.rb2
-rw-r--r--spec/services/alert_management/alerts/todo/create_service_spec.rb4
-rw-r--r--spec/services/alert_management/sync_alert_service_data_service_spec.rb55
-rw-r--r--spec/services/ci/build_report_result_service_spec.rb6
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb47
-rw-r--r--spec/services/ci/create_pipeline_service/dry_run_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb73
-rw-r--r--spec/services/ci/destroy_expired_job_artifacts_service_spec.rb76
-rw-r--r--spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb58
-rw-r--r--spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb81
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_delayed_and_needs_test.yml41
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_manual_and_needs_test.yml40
-rw-r--r--spec/services/ci/pipeline_trigger_service_spec.rb14
-rw-r--r--spec/services/ci/pipelines/create_artifact_service_spec.rb58
-rw-r--r--spec/services/ci/play_build_service_spec.rb25
-rw-r--r--spec/services/ci/process_build_service_spec.rb40
-rw-r--r--spec/services/ci/retry_build_service_spec.rb16
-rw-r--r--spec/services/ci/retry_pipeline_service_spec.rb22
-rw-r--r--spec/services/ci/test_failure_history_service_spec.rb21
-rw-r--r--spec/services/ci/update_build_state_service_spec.rb21
-rw-r--r--spec/services/container_expiration_policies/cleanup_service_spec.rb43
-rw-r--r--spec/services/draft_notes/create_service_spec.rb17
-rw-r--r--spec/services/draft_notes/publish_service_spec.rb22
-rw-r--r--spec/services/feature_flags/create_service_spec.rb24
-rw-r--r--spec/services/feature_flags/update_service_spec.rb24
-rw-r--r--spec/services/git/branch_push_service_spec.rb4
-rw-r--r--spec/services/groups/create_service_spec.rb8
-rw-r--r--spec/services/groups/destroy_service_spec.rb111
-rw-r--r--spec/services/incident_management/pager_duty/process_webhook_service_spec.rb2
-rw-r--r--spec/services/issuable/bulk_update_service_spec.rb51
-rw-r--r--spec/services/issues/close_service_spec.rb27
-rw-r--r--spec/services/issues/export_csv_service_spec.rb4
-rw-r--r--spec/services/jira_connect/sync_service_spec.rb4
-rw-r--r--spec/services/jira_connect_subscriptions/create_service_spec.rb12
-rw-r--r--spec/services/members/create_service_spec.rb51
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb22
-rw-r--r--spec/services/merge_requests/cleanup_refs_service_spec.rb20
-rw-r--r--spec/services/merge_requests/close_service_spec.rb9
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb3
-rw-r--r--spec/services/merge_requests/create_service_spec.rb6
-rw-r--r--spec/services/merge_requests/export_csv_service_spec.rb4
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb30
-rw-r--r--spec/services/merge_requests/mergeability_check_service_spec.rb49
-rw-r--r--spec/services/merge_requests/post_merge_service_spec.rb9
-rw-r--r--spec/services/merge_requests/reopen_service_spec.rb9
-rw-r--r--spec/services/merge_requests/update_service_spec.rb29
-rw-r--r--spec/services/namespaces/package_settings/update_service_spec.rb102
-rw-r--r--spec/services/notes/create_service_spec.rb30
-rw-r--r--spec/services/notes/destroy_service_spec.rb8
-rw-r--r--spec/services/notes/quick_actions_service_spec.rb8
-rw-r--r--spec/services/notes/update_service_spec.rb14
-rw-r--r--spec/services/notification_service_spec.rb12
-rw-r--r--spec/services/onboarding_progress_service_spec.rb36
-rw-r--r--spec/services/packages/create_event_service_spec.rb25
-rw-r--r--spec/services/packages/debian/create_package_file_service_spec.rb106
-rw-r--r--spec/services/packages/debian/extract_metadata_service_spec.rb59
-rw-r--r--spec/services/packages/debian/get_or_create_incoming_service_spec.rb36
-rw-r--r--spec/services/packages/maven/find_or_create_package_service_spec.rb54
-rw-r--r--spec/services/packages/nuget/search_service_spec.rb150
-rw-r--r--spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb118
-rw-r--r--spec/services/pages/zip_directory_service_spec.rb28
-rw-r--r--spec/services/post_receive_service_spec.rb11
-rw-r--r--spec/services/projects/after_import_service_spec.rb6
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb116
-rw-r--r--spec/services/projects/container_repository/delete_tags_service_spec.rb4
-rw-r--r--spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb17
-rw-r--r--spec/services/projects/fork_service_spec.rb18
-rw-r--r--spec/services/projects/housekeeping_service_spec.rb134
-rw-r--r--spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb43
-rw-r--r--spec/services/projects/update_pages_service_spec.rb13
-rw-r--r--spec/services/projects/update_service_spec.rb43
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb212
-rw-r--r--spec/services/repositories/housekeeping_service_spec.rb14
-rw-r--r--spec/services/resource_events/change_state_service_spec.rb9
-rw-r--r--spec/services/service_desk_settings/update_service_spec.rb13
-rw-r--r--spec/services/snippets/schedule_bulk_repository_shard_moves_service_spec.rb12
-rw-r--r--spec/services/snippets/update_repository_storage_service_spec.rb137
-rw-r--r--spec/services/todo_service_spec.rb258
-rw-r--r--spec/services/users/update_service_spec.rb2
-rw-r--r--spec/services/web_hook_service_spec.rb9
-rw-r--r--spec/spec_helper.rb42
-rw-r--r--spec/support/atlassian/jira_connect/schemata.rb337
-rw-r--r--spec/support/capybara.rb2
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast.yml3
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml15
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast_excluded_analyzers.yml14
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_includes.yml26
-rw-r--r--spec/support/helpers/database/database_helpers.rb15
-rw-r--r--spec/support/helpers/database/partitioning_helpers.rb96
-rw-r--r--spec/support/helpers/database/table_schema_helpers.rb149
-rw-r--r--spec/support/helpers/database/trigger_helpers.rb68
-rw-r--r--spec/support/helpers/database_helpers.rb13
-rw-r--r--spec/support/helpers/graphql_helpers.rb42
-rw-r--r--spec/support/helpers/multipart_helpers.rb20
-rw-r--r--spec/support/helpers/partitioning_helpers.rb94
-rw-r--r--spec/support/helpers/rack_attack_spec_helpers.rb21
-rw-r--r--spec/support/helpers/stub_experiments.rb8
-rw-r--r--spec/support/helpers/stub_feature_flags.rb4
-rw-r--r--spec/support/helpers/table_schema_helpers.rb112
-rw-r--r--spec/support/helpers/test_env.rb9
-rw-r--r--spec/support/helpers/trigger_helpers.rb66
-rw-r--r--spec/support/matchers/be_sorted.rb71
-rw-r--r--spec/support/matchers/be_valid_json.rb16
-rw-r--r--spec/support/matchers/schema_matcher.rb10
-rw-r--r--spec/support/rspec.rb4
-rw-r--r--spec/support/shared_contexts/email_shared_context.rb245
-rw-r--r--spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb48
-rw-r--r--spec/support/shared_contexts/finders/users_finder_shared_contexts.rb1
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb1
-rw-r--r--spec/support/shared_contexts/policies/group_policy_shared_context.rb25
-rw-r--r--spec/support/shared_contexts/read_ci_configuration_shared_context.rb8
-rw-r--r--spec/support/shared_contexts/requests/api/nuget_packages_shared_context.rb10
-rw-r--r--spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/controllers/unique_hll_events_examples.rb2
-rw-r--r--spec/support/shared_examples/features/file_uploads_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb10
-rw-r--r--spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb52
-rw-r--r--spec/support/shared_examples/finders/packages/debian/distributions_finder_shared_examples.rb79
-rw-r--r--spec/support/shared_examples/finders/packages_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/graphql/projects/merge_request_n_plus_one_query_examples.rb6
-rw-r--r--spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/base_stage_shared_examples.rb74
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/default_query_config_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/metrics/sampler_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/models/boards/listable_shared_examples.rb97
-rw-r--r--spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb45
-rw-r--r--spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb45
-rw-r--r--spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb48
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb225
-rw-r--r--spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb92
-rw-r--r--spec/support/shared_examples/requests/api/boards_shared_examples.rb33
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb69
-rw-r--r--spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb146
-rw-r--r--spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb58
-rw-r--r--spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb219
-rw-r--r--spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/requests/releases_shared_examples.rb61
-rw-r--r--spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb84
-rw-r--r--spec/support/shared_examples/routing/legacy_path_redirect_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/serializers/pipeline_artifacts_shared_example.rb21
-rw-r--r--spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb80
-rw-r--r--spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb65
-rw-r--r--spec/support/shared_examples/services/merge_request_shared_examples.rb15
-rw-r--r--spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/services/onboarding_progress_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb42
-rw-r--r--spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb118
-rw-r--r--spec/support/shared_examples/services/schedule_bulk_repository_shard_moves_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/workers/schedule_bulk_repository_shard_moves_shared_examples.rb30
-rw-r--r--spec/support/shared_examples/workers/update_repository_move_shared_examples.rb39
-rw-r--r--spec/support_specs/matchers/be_sorted_spec.rb33
-rw-r--r--spec/tasks/gitlab/git_rake_spec.rb34
-rw-r--r--spec/tasks/gitlab/packages/events_rake_spec.rb4
-rw-r--r--spec/tasks/gitlab/pages_rake_spec.rb67
-rw-r--r--spec/tooling/lib/tooling/kubernetes_client_spec.rb176
-rw-r--r--spec/tooling/lib/tooling/test_file_finder_spec.rb175
-rw-r--r--spec/uploaders/packages/debian/distribution_release_file_uploader_spec.rb52
-rw-r--r--spec/uploaders/packages/package_file_uploader_spec.rb71
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb111
-rw-r--r--spec/views/notify/pipeline_failed_email.html.haml_spec.rb2
-rw-r--r--spec/views/notify/pipeline_failed_email.text.erb_spec.rb2
-rw-r--r--spec/views/notify/pipeline_fixed_email.html.haml_spec.rb2
-rw-r--r--spec/views/notify/pipeline_fixed_email.text.erb_spec.rb2
-rw-r--r--spec/views/notify/pipeline_success_email.html.haml_spec.rb2
-rw-r--r--spec/views/notify/pipeline_success_email.text.erb_spec.rb2
-rw-r--r--spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb4
-rw-r--r--spec/views/projects/settings/operations/show.html.haml_spec.rb51
-rw-r--r--spec/views/shared/wikis/_sidebar.html.haml_spec.rb24
-rw-r--r--spec/workers/bulk_import_worker_spec.rb71
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb39
-rw-r--r--spec/workers/ci/pipeline_artifacts/coverage_report_worker_spec.rb32
-rw-r--r--spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb36
-rw-r--r--spec/workers/ci/pipelines/create_artifact_worker_spec.rb32
-rw-r--r--spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb82
-rw-r--r--spec/workers/experiments/record_conversion_event_worker_spec.rb35
-rw-r--r--spec/workers/expire_build_artifacts_worker_spec.rb4
-rw-r--r--spec/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker_spec.rb16
-rw-r--r--spec/workers/gitlab_performance_bar_stats_worker_spec.rb2
-rw-r--r--spec/workers/group_destroy_worker_spec.rb6
-rw-r--r--spec/workers/jira_connect/sync_branch_worker_spec.rb89
-rw-r--r--spec/workers/jira_connect/sync_deployments_worker_spec.rb60
-rw-r--r--spec/workers/jira_connect/sync_feature_flags_worker_spec.rb60
-rw-r--r--spec/workers/jira_connect/sync_merge_request_worker_spec.rb47
-rw-r--r--spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb32
-rw-r--r--spec/workers/namespaces/onboarding_user_added_worker_spec.rb10
-rw-r--r--spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb29
-rw-r--r--spec/workers/project_update_repository_storage_worker_spec.rb42
-rw-r--r--spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb12
-rw-r--r--spec/workers/snippet_update_repository_storage_worker_spec.rb15
-rw-r--r--tmp/.gitignore7
-rw-r--r--tooling/lib/tooling/helm3_client.rb6
-rw-r--r--tooling/lib/tooling/kubernetes_client.rb45
-rw-r--r--tooling/lib/tooling/test_file_finder.rb94
-rw-r--r--tooling/overcommit/Gemfile2
-rw-r--r--tooling/overcommit/Gemfile.lock4
-rw-r--r--vendor/assets/javascripts/jquery.scrollTo.js210
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/C++.gitignore0
-rw-r--r--[l---------]vendor/gitignore/Clojure.gitignore15
-rw-r--r--[l---------]vendor/gitignore/Fortran.gitignore33
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/Java.gitignore0
-rw-r--r--[l---------]vendor/gitignore/Kotlin.gitignore24
-rw-r--r--vendor/project_templates/dotnetcore.tar.gzbin7027 -> 4924 bytes
-rw-r--r--vendor/project_templates/express.tar.gzbin16098 -> 17921 bytes
-rw-r--r--vendor/project_templates/rails.tar.gzbin25668 -> 27308 bytes
-rw-r--r--workhorse/.gitlab-ci.yml4
-rw-r--r--workhorse/CHANGELOG12
-rw-r--r--workhorse/Makefile18
-rw-r--r--workhorse/PROCESS.md1
-rw-r--r--workhorse/VERSION2
-rwxr-xr-xworkhorse/_support/fmt.sh25
-rwxr-xr-xworkhorse/_support/validate-formatting.sh9
-rw-r--r--workhorse/cmd/gitlab-resize-image/main.go9
-rw-r--r--workhorse/cmd/gitlab-resize-image/png/reader.go86
-rw-r--r--workhorse/cmd/gitlab-resize-image/png/reader_test.go97
-rw-r--r--workhorse/internal/api/api.go4
-rw-r--r--workhorse/internal/badgateway/roundtripper.go10
-rw-r--r--workhorse/internal/git/archive.go5
-rw-r--r--workhorse/internal/git/diff.go6
-rw-r--r--workhorse/internal/git/format-patch.go6
-rw-r--r--workhorse/internal/git/git-http.go4
-rw-r--r--workhorse/internal/git/snapshot.go3
-rw-r--r--workhorse/internal/helper/helpers.go20
-rw-r--r--workhorse/internal/helper/helpers_test.go116
-rw-r--r--workhorse/internal/helper/raven.go2
-rw-r--r--workhorse/internal/imageresizer/image_resizer.go22
-rw-r--r--workhorse/internal/log/logging.go88
-rw-r--r--workhorse/internal/log/logging_test.go157
-rw-r--r--workhorse/internal/redis/keywatcher.go11
-rw-r--r--workhorse/internal/rejectmethods/middleware_test.go2
-rw-r--r--workhorse/internal/sendurl/sendurl.go4
-rw-r--r--workhorse/testdata/image_bad_iccp.pngbin0 -> 10696 bytes
-rw-r--r--workhorse/testdata/image_stripped_iccp.pngbin0 -> 2029 bytes
-rw-r--r--yarn.lock224
5476 files changed, 180933 insertions, 77009 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 1e6df6f5a77..a764f749785 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -43,6 +43,18 @@ rules:
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
overrides:
- files:
- '**/spec/**/*'
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5e54f9cde35..b41d7bcd34f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -64,7 +64,7 @@ variables:
BUILD_ASSETS_IMAGE: "false"
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
ELASTIC_URL: "http://elastic:changeme@elasticsearch:9200"
- DOCKER_VERSION: "19.03.0"
+ DOCKER_VERSION: "20.10.1"
CACHE_CLASSES: "true"
# Preparing custom clone path to reduce space used by all random forks
@@ -110,3 +110,4 @@ include:
- local: .gitlab/ci/notify.gitlab-ci.yml
- local: .gitlab/ci/dast.gitlab-ci.yml
- local: .gitlab/ci/workhorse.gitlab-ci.yml
+ - local: .gitlab/ci/graphql.gitlab-ci.yml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 70d9dbc9ad7..df81d05eec1 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -250,10 +250,10 @@ Dangerfile @gl-quality/eng-prod
/ee/spec/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
/doc/user/project/code_owners.md @reprazent @kerrizor @garyh
-[Product Analytics]
-/ee/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product_analytics/engineers
-/ee/lib/ee/gitlab/usage_data.rb @gitlab-org/growth/product_analytics/engineers
-/lib/gitlab/grafana_embed_usage_data.rb @gitlab-org/growth/product_analytics/engineers
-/lib/gitlab/usage_data.rb @gitlab-org/growth/product_analytics/engineers
-/lib/gitlab/cycle_analytics/usage_data.rb @gitlab-org/growth/product_analytics/engineers
-/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product_analytics/engineers
+[Product Intelligence]
+/ee/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product-intelligence/engineers
+/ee/lib/ee/gitlab/usage_data.rb @gitlab-org/growth/product-intelligence/engineers
+/lib/gitlab/grafana_embed_usage_data.rb @gitlab-org/growth/product-intelligence/engineers
+/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
diff --git a/.gitlab/ci/dev-fixtures.gitlab-ci.yml b/.gitlab/ci/dev-fixtures.gitlab-ci.yml
index c19dce7e4a9..1848283f921 100644
--- a/.gitlab/ci/dev-fixtures.gitlab-ci.yml
+++ b/.gitlab/ci/dev-fixtures.gitlab-ci.yml
@@ -15,7 +15,6 @@
# SEED_NESTED_GROUPS: "false" # requires network connection
.run-dev-fixtures-script: &run-dev-fixtures-script
- - run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn"
- run_timed_command "RAILS_ENV=test bundle exec rake db:seed_fu"
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index d6dc709a11a..955f44c6216 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -43,7 +43,7 @@ docs-lint markdown:
- .default-retry
- .docs:rules:docs-lint
# When updating the image version here, update it in /scripts/lint-doc.sh too.
- image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.12-vale-2.6.1-markdownlint-0.24.0"
+ image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.12-vale-2.8.0-markdownlint-0.26.0"
stage: test
needs: []
script:
@@ -84,16 +84,3 @@ ui-docs-links lint:
needs: []
script:
- bundle exec haml-lint -i DocumentationLinks
-
-graphql-reference-verify:
- extends:
- - .default-retry
- - .rails-cache
- - .default-before_script
- - .docs:rules:graphql-reference-verify
- - .use-pg11
- stage: test
- needs: ["setup-test-env"]
- script:
- - bundle exec rake gitlab:graphql:check_docs
- - bundle exec rake gitlab:graphql:check_schema
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 0b921309ced..c87305cab18 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -103,7 +103,6 @@ update-yarn-cache:
WEBPACK_VENDOR_DLL: "true"
script:
- run_timed_command "gem install knapsack --no-document"
- - run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn"
- source ./scripts/rspec_helpers.sh
- rspec_paralellized_job "--tag frontend_fixture"
@@ -236,6 +235,8 @@ coverage-frontend:
- *yarn-install
script:
- run_timed_command "yarn node scripts/frontend/merge_coverage_frontend.js"
+ # Removing the individual coverage results, as we just merged them.
+ - rm -r coverage-frontend/jest-*
coverage: '/^Statements\s*:\s*?(\d+(?:\.\d+)?)%/'
artifacts:
name: coverage-frontend
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 0fafd5869d9..355607c17ac 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -112,7 +112,7 @@
.use-kaniko:
image:
- name: gcr.io/kaniko-project/executor:debug-v0.20.0
+ name: gcr.io/kaniko-project/executor:debug-v1.3.0
entrypoint: [""]
before_script:
- source scripts/utils.sh
diff --git a/.gitlab/ci/graphql.gitlab-ci.yml b/.gitlab/ci/graphql.gitlab-ci.yml
new file mode 100644
index 00000000000..4aff0ef6306
--- /dev/null
+++ b/.gitlab/ci/graphql.gitlab-ci.yml
@@ -0,0 +1,14 @@
+graphql-verify:
+ variables:
+ SETUP_DB: "false"
+ extends:
+ - .default-retry
+ - .rails-cache
+ - .default-before_script
+ - .graphql:rules:graphql-verify
+ stage: test
+ needs: []
+ script:
+ - bundle exec rake gitlab:graphql:validate
+ - bundle exec rake gitlab:graphql:check_docs
+ - bundle exec rake gitlab:graphql:check_schema
diff --git a/.gitlab/ci/pages.gitlab-ci.yml b/.gitlab/ci/pages.gitlab-ci.yml
index a66e0d88db3..4961bd508d3 100644
--- a/.gitlab/ci/pages.gitlab-ci.yml
+++ b/.gitlab/ci/pages.gitlab-ci.yml
@@ -14,7 +14,6 @@ pages:
- mv coverage/ public/coverage-ruby/ || true
- mv coverage-frontend/ public/coverage-frontend/ || true
- mv coverage-javascript/ public/coverage-javascript/ || true
- - mv webpack-report/ public/webpack-report/ || true
- cp .public/assets/application-*.css public/application.css || true
- cp .public/assets/application-*.css.gz public/application.css.gz || true
artifacts:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 2818b6be176..7f8dfa900ca 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -10,7 +10,6 @@
# Only install knapsack after bundle install! Otherwise oddly some native
# gems could not be found under some circumstance. No idea why, hours wasted.
- run_timed_command "gem install knapsack --no-document"
- - run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn"
- source ./scripts/rspec_helpers.sh
@@ -150,20 +149,35 @@ setup-test-env:
script:
- run_timed_command "bundle exec ruby -I. -e 'require \"config/environment\"; TestEnv.init'"
- run_timed_command "scripts/gitaly-test-build" # Do not use 'bundle exec' here
- - rm tmp/tests/gitaly/.ruby-bundle # This file prevents gems from being installed even if vendor/gitaly-ruby is missing
artifacts:
expire_in: 7d
paths:
- config/secrets.yml
- - tmp/tests/gitaly
- - tmp/tests/gitlab-elasticsearch-indexer
- - tmp/tests/gitlab-shell
- - tmp/tests/gitlab-test-fork
- - tmp/tests/gitlab-test-fork_bare
- - tmp/tests/gitlab-test
- - tmp/tests/gitlab-workhorse
- - tmp/tests/repositories
- - tmp/tests/second_storage
+ - tmp/tests/gitaly/config.toml
+ - tmp/tests/gitaly/gitaly
+ - tmp/tests/gitaly/gitaly2.config.toml
+ - tmp/tests/gitaly/gitaly-git2go
+ - tmp/tests/gitaly/gitaly-hooks
+ - tmp/tests/gitaly/gitaly-lfs-smudge
+ - tmp/tests/gitaly/gitaly-ssh
+ - tmp/tests/gitaly/internal/
+ - tmp/tests/gitaly/internal_sockets/
+ - tmp/tests/gitaly/Makefile
+ - tmp/tests/gitaly/praefect
+ - tmp/tests/gitaly/praefect.config.toml
+ - tmp/tests/gitaly/ruby/
+ - tmp/tests/gitlab-elasticsearch-indexer/bin/gitlab-elasticsearch-indexer
+ - tmp/tests/gitlab-shell/
+ - tmp/tests/gitlab-test-fork/
+ - tmp/tests/gitlab-test-fork_bare/
+ - tmp/tests/gitlab-test/
+ - tmp/tests/gitlab-workhorse/gitlab-zip-metadata
+ - tmp/tests/gitlab-workhorse/gitlab-zip-cat
+ - tmp/tests/gitlab-workhorse/gitlab-workhorse
+ - tmp/tests/gitlab-workhorse/gitlab-resize-image
+ - tmp/tests/gitlab-workhorse/config.toml
+ - tmp/tests/repositories/
+ - tmp/tests/second_storage/
when: always
update-rails-cache:
@@ -286,6 +300,16 @@ rspec system pg11 minimal:
- .minimal-rspec-tests
- .rails:rules:ee-and-foss-system:minimal
+# Dedicated job to test DB library code against PG12.
+# Note that these are already tested against PG11 in the `rspec unit pg11` / `rspec-ee unit pg11` jobs.
+rspec db-library-code pg12:
+ extends:
+ - .rspec-base-pg12
+ - .rails:rules:ee-and-foss-db-library-code
+ script:
+ - *base-script
+ - rspec_simple_job "-- spec/lib/gitlab/database/ spec/support/helpers/database/ ee/spec/lib/gitlab/database/ ee/spec/lib/ee/gitlab/database_spec.rb"
+
rspec fast_spec_helper:
extends:
- .rspec-base-pg11
@@ -311,6 +335,14 @@ db:check-schema:
script:
- source scripts/schema_changed.sh
+db:check-migrations:
+ extends:
+ - .db-job-base
+ - .rails:rules:ee-and-foss-mr-with-migration
+ script:
+ - scripts/validate_migration_schema
+ allow_failure: true
+
db:migrate-from-v12.10.0:
extends: .db-job-base
variables:
@@ -376,6 +408,38 @@ db:backup_and_restore:
rules:
- changes: ["lib/backup/**/*"]
+rspec:deprecations:
+ extends:
+ - .default-retry
+ - .default-before_script
+ - .static-analysis-cache
+ - .rails:rules:deprecations
+ 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:
+ - rspec migration pg11
+ - rspec unit pg11
+ - rspec integration pg11
+ - rspec system pg11
+ - rspec-ee migration pg11
+ - rspec-ee unit pg11
+ - rspec-ee integration pg11
+ - rspec-ee system pg11
+ - rspec-ee unit pg11 geo
+ - rspec-ee integration pg11 geo
+ - rspec-ee system pg11 geo
+ variables:
+ SETUP_DB: "false"
+ script:
+ - run_timed_command "bundle exec rubocop --only Lint/LastKeywordArgument --parallel"
+ artifacts:
+ expire_in: 31d
+ when: always
+ paths:
+ - deprecations/
+
rspec:coverage:
extends:
- .coverage-base
@@ -549,33 +613,36 @@ rspec-ee unit pg11 geo:
- .rails:rules:ee-only-unit
- .rspec-ee-unit-geo-parallel
-rspec-ee unit pg11 geo minimal:
- extends:
- - rspec-ee unit pg11 geo
- - .minimal-rspec-tests
- - .rails:rules:ee-only-unit:minimal
+# FIXME: Temporarily disable geo minimal rspec jobs https://gitlab.com/gitlab-org/gitlab/-/issues/294212
+#rspec-ee unit pg11 geo minimal:
+# extends:
+# - rspec-ee unit pg11 geo
+# - .minimal-rspec-tests
+# - .rails:rules:ee-only-unit:minimal
rspec-ee integration pg11 geo:
extends:
- .rspec-ee-base-geo-pg11
- .rails:rules:ee-only-integration
-rspec-ee integration pg11 geo minimal:
- extends:
- - rspec-ee integration pg11 geo
- - .minimal-rspec-tests
- - .rails:rules:ee-only-integration:minimal
+# FIXME: Temporarily disable geo minimal rspec jobs https://gitlab.com/gitlab-org/gitlab/-/issues/294212
+#rspec-ee integration pg11 geo minimal:
+# extends:
+# - rspec-ee integration pg11 geo
+# - .minimal-rspec-tests
+# - .rails:rules:ee-only-integration:minimal
rspec-ee system pg11 geo:
extends:
- .rspec-ee-base-geo-pg11
- .rails:rules:ee-only-system
-rspec-ee system pg11 geo minimal:
- extends:
- - rspec-ee system pg11 geo
- - .minimal-rspec-tests
- - .rails:rules:ee-only-system:minimal
+# FIXME: Temporarily disable geo minimal rspec jobs https://gitlab.com/gitlab-org/gitlab/-/issues/294212
+#rspec-ee system pg11 geo minimal:
+# extends:
+# - rspec-ee system pg11 geo
+# - .minimal-rspec-tests
+# - .rails:rules:ee-only-system:minimal
db:rollback geo:
extends:
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 85aec070557..77ada89aa6a 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -4,9 +4,9 @@
# - template: Security/Dependency-Scanning.gitlab-ci.yml
# - template: Security/DAST.gitlab-ci.yml
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
+# We need to duplicate this job's definition because the rules
+# defined in the extended jobs rely on local YAML anchors
+# (`*if-default-refs`)
code_quality:
extends:
- .default-retry
@@ -36,9 +36,9 @@ code_quality:
- gl-code-quality-report.json # GitLab-specific
expire_in: 1 week # GitLab-specific
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
+# We need to duplicate this job's definition because the rules
+# defined in the extended jobs rely on local YAML anchors
+# (`*if-default-refs`)
.sast:
extends:
- .default-retry
@@ -89,74 +89,58 @@ secrets-sast:
sast: gl-secret-detection-report.json
expire_in: 1 week # GitLab-specific
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
-dependency_scanning:
+# We need to duplicate this job's definition because the rules
+# defined in the extended jobs rely on local YAML anchors
+# (`*if-default-refs`)
+.dependency_scanning:
extends:
- .default-retry
- .reports:rules:dependency_scanning
- - .use-docker-in-docker
stage: test
needs: []
variables:
DS_MAJOR_VERSION: 2
- DS_EXCLUDED_PATHS: "qa/qa/ee/fixtures/secure_premade_reports,spec,ee/spec" # GitLab-specific
- script:
- - |
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
- function propagate_env_vars() {
- CURRENT_ENV=$(printenv)
-
- for VAR_NAME; do
- echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
- done
- }
- - |
- docker run \
- $(propagate_env_vars \
- DS_ANALYZER_IMAGES \
- DS_ANALYZER_IMAGE_PREFIX \
- DS_ANALYZER_IMAGE_TAG \
- DS_DEFAULT_ANALYZERS \
- DS_EXCLUDED_PATHS \
- DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- DS_PULL_ANALYZER_IMAGE_TIMEOUT \
- DS_RUN_ANALYZER_TIMEOUT \
- DS_PYTHON_VERSION \
- DS_PIP_VERSION \
- DS_PIP_DEPENDENCY_PATH \
- GEMNASIUM_DB_LOCAL_PATH \
- GEMNASIUM_DB_REMOTE_URL \
- GEMNASIUM_DB_REF_NAME \
- PIP_INDEX_URL \
- PIP_EXTRA_INDEX_URL \
- PIP_REQUIREMENTS_FILE \
- MAVEN_CLI_OPTS \
- BUNDLER_AUDIT_UPDATE_DISABLED \
- BUNDLER_AUDIT_ADVISORY_DB_URL \
- BUNDLER_AUDIT_ADVISORY_DB_REF_NAME \
- ) \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_MAJOR_VERSION" /code
- # Post-processing: This will be an after_script once this job will use the Dependency Scanning CI template
- - apk add jq
- # Lower execa severity based on https://gitlab.com/gitlab-org/gitlab/-/issues/223859#note_452922390
- - jq '(.vulnerabilities[] | select (.cve == "yarn.lock:execa:gemnasium:05cfa2e8-2d0c-42c1-8894-638e2f12ff3d")).severity = "Medium"' gl-dependency-scanning-report.json > temp.json && mv temp.json gl-dependency-scanning-report.json
+ DS_EXCLUDED_PATHS: "qa/qa/ee/fixtures/secure_premade_reports, spec, ee/spec" # GitLab-specific
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
artifacts:
paths:
- gl-dependency-scanning-report.json # GitLab-specific
reports:
dependency_scanning: gl-dependency-scanning-report.json
expire_in: 1 week # GitLab-specific
+ script:
+ - /analyzer run
+
+dependency_scanning gemnasium:
+ extends: .dependency_scanning
+ image:
+ name: "$SECURE_ANALYZERS_PREFIX/gemnasium:$DS_MAJOR_VERSION"
+ before_script:
+ # git-lfs is needed for auto-remediation
+ - apk add git-lfs
+ after_script:
+ # Post-processing
+ - apk add jq
+ # Lower execa severity based on https://gitlab.com/gitlab-org/gitlab/-/issues/223859#note_452922390
+ - jq '(.vulnerabilities[] | select (.cve == "yarn.lock:execa:gemnasium:05cfa2e8-2d0c-42c1-8894-638e2f12ff3d")).severity = "Medium"' gl-dependency-scanning-report.json > temp.json && mv temp.json gl-dependency-scanning-report.json
+
+dependency_scanning bundler-audit:
+ extends: .dependency_scanning
+ image:
+ name: "$SECURE_ANALYZERS_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
+
+dependency_scanning retire-js:
+ extends: .dependency_scanning
+ image:
+ name: "$SECURE_ANALYZERS_PREFIX/retire.js:$DS_MAJOR_VERSION"
+
+dependency_scanning gemnasium-python:
+ extends: .dependency_scanning
+ image:
+ name: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
-# The job below analysis dependencies for malicous behavior
+# Analyze dependencies for malicious behavior
+# See https://gitlab.com/gitlab-com/gl-security/security-research/package-hunter
package_hunter:
extends:
- .reports:schedule-dast
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index f1bd173ff6d..b7d9f18dcb4 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -38,7 +38,7 @@ review-build-cng:
- BUILD_TRIGGER_TOKEN=$REVIEW_APPS_BUILD_TRIGGER_TOKEN ./scripts/trigger-build cng
# When the job is manual, review-deploy is also manual and we don't want people
# to have to manually start the jobs in sequence, so we do it for them.
- - '[ -z $CI_JOB_MANUAL ] || scripts/api/play_job --job-name "review-deploy"'
+ - '[ -z $CI_JOB_MANUAL ] || scripts/api/play_job.rb --job-name "review-deploy"'
.review-workflow-base:
extends:
@@ -48,7 +48,7 @@ review-build-cng:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
REVIEW_APPS_DOMAIN: "temp.gitlab-review.app" # FIXME: using temporary domain
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
- GITLAB_HELM_CHART_REF: "v4.3.0"
+ GITLAB_HELM_CHART_REF: "v4.6.3"
environment:
name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
@@ -78,8 +78,8 @@ review-deploy:
- disable_sign_ups || (delete_release && exit 1)
# When the job is manual, review-qa-smoke is also manual and we don't want people
# to have to manually start the jobs in sequence, so we do it for them.
- - '[ -z $CI_JOB_MANUAL ] || scripts/api/play_job --job-name "review-qa-smoke"'
- - '[ -z $CI_JOB_MANUAL ] || scripts/api/play_job --job-name "review-performance"'
+ - '[ -z $CI_JOB_MANUAL ] || scripts/api/play_job.rb --job-name "review-qa-smoke"'
+ - '[ -z $CI_JOB_MANUAL ] || scripts/api/play_job.rb --job-name "review-performance"'
after_script:
# Run seed-dast-test-data.sh only when DAST_RUN is set to true. This is to pupulate review app with data for DAST scan.
# Set DAST_RUN to true when jobs are manually scheduled.
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 159defc83c3..5e8cdf0daaf 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -155,9 +155,15 @@
- "{,ee/}{,spec/}lib/{,ee/}gitlab/database{,_spec}.rb"
- "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration/**/*"
- "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration{,_spec}.rb"
+ - "{,ee/}spec/support/helpers/database/**/*"
- "config/prometheus/common_metrics.yml" # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer
- "{,ee/}app/models/project_statistics.rb" # Used to calculate sizes in migration specs
+.db-library-patterns: &db-library-patterns
+ - "{,ee/}{,spec/}lib/{,ee/}gitlab/database/**/*"
+ - "{,ee/}{,spec/}lib/{,ee/}gitlab/database{,_spec}.rb"
+ - "{,ee/}spec/support/helpers/database/**/*"
+
.backstage-patterns: &backstage-patterns
- "Dangerfile"
- "danger/**/*"
@@ -349,7 +355,11 @@
changes: *docs-patterns
when: on_success
-.docs:rules:graphql-reference-verify:
+##################
+# GraphQL rules #
+##################
+
+.graphql:rules:graphql-verify:
rules:
- <<: *if-not-ee
when: never
@@ -507,6 +517,12 @@
- <<: *if-merge-request
changes: *db-patterns
+.rails:rules:ee-and-foss-mr-with-migration:
+ rules:
+ - <<: *if-merge-request
+ changes: *db-patterns
+ - <<: *if-merge-request-title-run-all-rspec
+
.rails:rules:ee-and-foss-unit:
rules:
- changes: *backend-patterns
@@ -765,6 +781,11 @@
- <<: *if-merge-request-title-as-if-foss
changes: *code-backstage-patterns
+.rails:rules:ee-and-foss-db-library-code:
+ rules:
+ - changes: *db-library-patterns
+ - <<: *if-merge-request-title-run-all-rspec
+
.rails:rules:ee-mr-and-master-only:
rules:
- <<: *if-not-ee
@@ -825,6 +846,13 @@
- <<: *if-merge-request
changes: *code-backstage-patterns
+.rails:rules:deprecations:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-master-schedule-nightly
+ - <<: *if-merge-request-title-run-all-rspec
+
.rails:rules:rspec-coverage:
rules:
- <<: *if-not-ee
diff --git a/.gitlab/issue_templates/Acceptance Testing.md b/.gitlab/issue_templates/Acceptance Testing.md
index 5a6c35f28ad..52896382554 100644
--- a/.gitlab/issue_templates/Acceptance Testing.md
+++ b/.gitlab/issue_templates/Acceptance Testing.md
@@ -27,7 +27,7 @@ Then leave running while monitoring and performing some testing through web, api
- [ ] [Inspect logs in ELK](https://log.gitlab.net/app/kibana)
- [ ] [Check for errors in GitLab Dev Sentry](https://sentry.gitlab.net/gitlab/devgitlaborg/?query=is%3Aunresolved)
-## 2. Staging Trial
+## 3. Staging Trial
#### Check Staging Server Versions
- [ ] GitLab: https://staging.gitlab.com/help
diff --git a/.gitlab/issue_templates/Design Sprint.md b/.gitlab/issue_templates/Design Sprint.md
new file mode 100644
index 00000000000..787c4469b88
--- /dev/null
+++ b/.gitlab/issue_templates/Design Sprint.md
@@ -0,0 +1,203 @@
+<!-- Title: Design Sprint -->
+
+## Design Sprint Focus
+* [ ] Have you [determined that a Design Sprint is appropriate for this project](#anchor-tag-to-handbook-page)?
+<!-- What is the focus of the [Design Sprint](https://about.gitlab.com/handbook/product/product-processes/#design-sprint)? What problem area will you be solving for and who is the target user? -->
+
+## Objectives
+
+<!-- Try to describe the objectives of the Sprint in detail. eg "We want to introduce a new feature but we are unsure that we are thinking about the solution from the customer's perspective and through the Sprint we want to rethink the solution, prototype it and validate it with our customers" or "We are unhappy with the direction of one of our categories and we want to explore new directions with different stakeholders, reach to one solution and test it with users" or "Among the team we have different visions for a specific category and we want to work towards a solution we all support and test it with users". -->
+
+## Outputs
+
+- [ ] A User testing flow.
+- [ ] A Prototype to be tested with users.
+- [ ] User testing analysis.
+- [ ] (If the solution is viable) An epic or issue that describes the direction in details and the next steps
+- [ ] Necessary updates to the Handbook.
+
+## Design Sprint Details
+
+| Start | End |
+| ------ | ------ |
+| YYYY-MM-DD | YYYY-MM-DD |
+| TT:TT PST | TT:TT PST |
+
+
+### WHEN
+
+**Start date:**
+
+**End date:**
+
+**Reference time zone:**
+
+### WHERE
+
+**Zoom link:**
+
+### WHO
+
+ - `Name` `gitlab handle` - Facilitator
+ - `Name` `gitlab handle` - Decider (usually the Product Manager)
+ - `Name` `gitlab handle` - Co-decider (optional)
+ - `Name` `gitlab handle` - Sprint team member
+ - `Name` `gitlab handle` - Sprint team member
+ - `Name` `gitlab handle` - Sprint team member
+ - `Name` `gitlab handle` - Sprint team member
+ - `Name` `gitlab handle` - Sprint team member
+ - `Name` `gitlab handle` - Sprint team member
+ - `Name` `gitlab handle` - Co-facilitator (optional)
+
+## Tools
+Here is the list of tools for the Sprint preparation, collaboration and documentation. Prior to the Sprint make sure you have access to all of the following:
+
+* **GitLab**<br/>
+Each Sprint day outcomes and material will be documented in a separate issue under the Design Sprint epic.
+
+* **Mural** (You can join as anonymous but we need to be able to identify input against names, so please create an account beforehand.<br/>
+We will use Mural for most of the Sprint collaboration. Some of the things we will do in Mural:
+ * Create artifacts like affinity diagrams from participants' input
+ * Use post-its to comment on each other's points and to add notes
+ * Vote on ideas and solutions
+ * Create the first draft of the prototype.
+The Mural link to the collaboration project will be provided in the issue before the start of the Design Sprint.
+
+* **Video and/or screen recording tool** (Loom, Quicktime, Zoom or another tool you are using).<br/>
+As part of the pre-Sprint homework, you will be asked to record a short Lightning Walkthrough video. You can use any tool you feel comfortable with as long as it can capture your screen, mouse pointer and your audio.
+
+* **A4/Letter sized paper (preferably white blank), Sharpies/Pens** (please don't use a pencil because it doesn't create enough contrast for photos).<br/>
+Day 2 of the sprint involves some (async) ideation via sketching so you will need a writing utensil (Sharpies are preferred because they force you to draw at a lower fidelity because the small details aren't necessary at this point) and some paper. This is the most fun part of the Sprint where you get into a design thinking mindset and can appeal to your creative self. Don't worry, it's not about artistry, it's about ideas and collaboration.
+
+* **Camera (phone or other) or scanner**<br/>
+You will need to upload sketches as images for the facilitator to prepare the material before the next sync meeting. You can take a photo with your phone or use a scanner if available.
+
+* **Post-it notes (Optional)**<br/>
+If you enjoy taking notes using post-it notes make sure you have available some of them as well. The upside is that they will make you feel more like you are in a workshop and will help the ideas flow (I find that typing is distracting while ideating). The downside is that you will have to digitalise the ones you want to share with the team in Mural.
+
+## Artefacts & Pre-Read Material
+
+<!-- If there is material that will be useful for the participants to read before the Design Sprint add here. -->
+
+### Handbook pages
+<!-- Add a link to the category vision from the handbook -->
+
+### Competitor resources
+<!-- Add any solutions by competitors that are relevant to the Design Sprint topic and could be used as source of inspiration. -->
+
+
+### Articles on Design Sprints
+ * [The Design Sprint](https://www.gv.com/sprint/)
+ * [The Ultimate Guide To Remote Design Sprints](https://drive.google.com/file/d/16bwrAqHVf8qxovd87Q7LdzqwAgy7a6Rx/view?usp=sharing)
+
+## Asyncronus tasks
+
+### Design Sprint preparation
+
+<!-- Replace the roles with GitLab handles to assign to specific participants -->
+
+- [ ] Finalise participant list - `decider` and `facilitator`
+- [ ] Create [participation form](https://docs.google.com/forms/d/e/1FAIpQLSc0_BNltvRW8yXXaJd8sIKzgDmrSGqILMfkoCJrAj6sFcsMcg/viewform?usp=sf_link) and send to participants (**deadline**: [date]) - `facilitator`
+- [ ] Promote this issue to an epic - `facilitator`
+- [ ] Create issues under the epic for the pre-workshop tasks: Expert interviews ([example](https://gitlab.com/groups/gitlab-org/configure/-/epics/3#note_332412524)), Lightning walkthroughs and How might we.. notetaking assignment ([example](https://gitlab.com/gitlab-org/configure/general/-/issues/52)), Voting How might we... notes assignment ([example](https://gitlab.com/gitlab-org/configure/general/-/issues/54)) - `facilitator`
+- [ ] Create sync meetings in calendar and invite all participants (**deadline**: [date]) - `decider` or `facilitator`
+- [ ] Block 2 hours for Sprint activities in calendar for the Sprint week - `all participants`
+- [ ] Prepare material and tools (eg. presentation templates, Google folders, Instructions videos etc) and Mural board from the [Mural template ](https://app.mural.co/invitation/mural/gitlab2474/1586990879319?sender=jmandell0210&key=03c25e92-9a43-4a3d-8907-6f0c3b094ab8) - facilitator
+- [ ] Finalize Agenda - `facilitator`
+- [ ] Run a test with material and tools - `facilitator`
+- [ ] Start user recruiting for prototype user testing (EOD 1) - `facilitator` or `decider`
+
+### Pre-Sprint activities (Homework exercises)
+
+Each exercise should be explained and documented in a separate issue. You can use the example issues above as templates.
+
+- [ ] Fill form and submit (**deadline**: [date]) - `all participants except the facilitator`
+- [ ] Expert interview analysis - `facilitator`
+- [ ] Lightning walkthrough videos (**deadline**: [date]) - `all participants except the facilitator`
+- [ ] How might we... notetaking assignment (**deadline**: [date]) - `all participants except the facilitator`
+- [ ] Voting How might we... notes assignment (**deadline**: [date]) - `all participants except the facilitator`
+- [ ] Add all required material to the Mural board (**deadline**: [date]) - `facilitator`
+
+### During Sprint activities
+
+- [ ] Organise user testing sessions - `facilitator` or `decider`
+- [ ] Create the Prototype to be tested and task list (End of Day 3) - `Product designer` or `Front end developer`
+- [ ] Run user testing sessions - `facilitator` or `decider`
+
+### Post-Sprint activities
+
+- [ ] Create a feedback issue for the Design Sprint - `facilitator` or `decider`
+- [ ] Analyse user testing results - `facilitator` or `decider`
+- [ ] Create report and share with the Design Sprint participants and wider team - `facilitator` or `decider`
+
+## Personas
+
+Deciding which persona we are focusing on will be part of the Day 1 discussions in the workshop. The personas we are going to consider are:
+
+<!-- Choose which personas could be target users so that you choose from this list during the Sprint. Personas are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/
+
+* [Cameron (Compliance Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#cameron-compliance-manager)
+* [Parker (Product Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#parker-product-manager)
+* [Delaney (Development Team Lead)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
+* [Presley (Product Designer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#presley-product-designer)
+* [Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sasha-software-developer)
+* [Devon (DevOps Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#devon-devops-engineer)
+* [Sidney (Systems Administrator)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sidney-systems-administrator)
+* [Sam (Security Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sam-security-analyst)
+* [Rachel (Release Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#rachel-release-manager)
+* [Alex (Security Operations Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#alex-security-operations-engineer)
+* [Simone (Software Engineer in Test)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#simone-software-engineer-in-test)
+* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
+* [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer)
+* [Dana (Data Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#dana-data-analyst)
+* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
+-->
+
+## Agenda
+### Day 1
+
+ | Activity | Duration | Tool | Description |
+|---|---|---|---|
+| Warm-up exercise | 5 mins | Mural | Write 1 post-it answering the questions: <br/>"My name is…"<br/>"My role is…"<br/>“Something about myself you may not know is…â€<br/>"My wish for this workshop is…" |
+| Summarise the async activities & complete Map | 20 mins | Mural | The Map is intended to show the focus of the Sprint and doesn't need to be complete or detailed. Steps:<br/> Go through the Map and the top voted How might we’s tree as a warm-up/reminder. <br/> • Make appropriate adjustments and additions to the map based on the reviews from the team. <br/> • Add the most voted HMWs to the most relevant area on the Map. If a HMW can go to more than one place, add it to the most left area. |
+| Long term goals/Deciding the Sprint goal | 15 mins | Mural | • Long term goal: Everyone spends 5 minutes in silence and writes one (max 2) long term goal post-it note for the Sprint. (5 mins ) <br/> • One by one everyone will read their goal aloud to the team. (5 mins) <br/> Everyone besides the decider will vote on the goal of the Sprint (1 dot). (4 minutes) <br/> The decider then makes the final decision on the long term goal of the Sprint. (1 min) |
+ | Sprint questions | 20 mins | Mural | • Referencing the Long Term goal, everyone will write 2-3 post-it note Sprint questions for the biggest challenges they think might stop us from achieving our long term goal (what might hold us back or hinder us from achieving this goal). The questions should start with “Can we...†(similarly to the HMW). (7 mins) <br/> • One by one everyone will read their Sprint questions aloud to the team. (5 mins) <br/> • Everyone (including the decider) votes on the top 3 questions they think we should focus on as Sprint challenges (3 dots). (5 mins) <br/> • Separate the 3 most voted questions and keep them on the side. (1 min) <br/> • Finally, the decider chooses one Sprint question that will be the question we will focus on more during the Sprint by placing a green smiley sticker on it. (1 min) <br/> • Move the long term goal and the Sprint questions to the dedicated Mural space, highlighting the ultimate Sprint question that the decider chose. (1 min) |
+| Recap day. <br/> Short intro to next day and share the video with the next day exercise instructions. | 5 mins | Mural, Zoom | Summarise activities of the day and decisions. Brief walkthrough of the next day's activities and wrap up the day. |
+
+### Day 2
+ | Activity | Duration | Tool | Description |
+|---|---|---|---|
+| Summary of Day 1 outcomes | 5 mins | Mural | Go through the previous day's activities, the Long term goal and the top voted Sprint questions, highlighting the ultimate Sprint question, and summarise the concept solution sketching homework exercise. |
+| Concept gallery review | 20 mins | Mural | • Everyone takes some time to read through and look at every aspect of each of the sketches in the Concept Gallery. The concept sketches are anonymous to avoid bias (15 mins). <br/> • The team will then vote on their favorite concepts and/or components of a concept via the red dots. When they see something that interests them and they think it will help solve the long term goal/challenges they can add one or more dots. They can use as many red dots as they want. Be frivolous when adding dots but if you really like or think something is important, add more to draw attention to it (5 mins).<br/> Note: If anyone has any questions about a concept sketch create a red sticky and write that question down placing it under the concept sketches. |
+| Speed critique | 5 mins | Mural | • The facilitator walks through each of the concepts, briefly summarizing each concept (to the best of their ability) with a focus on the areas that have been dotted. <br/> • During this time the facilitator will also try to answer any of the red post-it questions. <br/> • When the facilitator believes they’ve reached the end of their summary for that concept, ask the team if there was a concept that was voted on but not discussed or if the point of the red dot vote was missed in the discussion.
+| Straw Poll | ~15 mins | Mural | • All the participants, besides the Decider, vote using the larger green dot by adding their initials to it and placing it on the concept sketch they believe is the best one that will best fulfill the long term goal and challenges of this sprint and is worthy of being prototyped (2 mins) <br/> • Each participant will create a post-it note that explains their reasoning for choosing the concept. (5 mins) <br/> • Each participant will then get 1 minute to read through their post-it and attempt to sell their preferred concept to the Decider and the other participants. (5-10 mins) |
+| Super Vote (The Decider) | 10 mins | Mural | • The Decider makes their final decision of which of the concepts is the one to move forward with. <br/> • The decider can discuss their thought process and any questions with the rest of the participants. <br/> • They will get 2 green smiley stickers to vote with. Placing one on the concept they want to move forward with and the second, optional smiley, can be used to mark any other area of any other concept they think should also be incorporated into the prototype. |
+
+
+### Day 3
+ | Activity | Duration | Tool | Description |
+|---|---|---|---|
+| User test flow | 25 mins | Mural | • Each participant writes (on separate post-its) 6 steps/actions that represent a step of a flow (you can think of a high-level prototype flow) from start to finish. Place them in the appropriate location on the User Test section. (10 mins) <br/> • Each participant takes 1 minute to walk the team through their flows one-by-one (5-10 mins total). Note: It's best to have the Decider go last. <br/> • Voting: All the Sprint participants get one red dot (the Decider gets 2) to vote on the flow row they think is the best foundation for the prototype. <br/> • After everyone has voted the Decider will vote on the row they think is best with one dot using the second dot to, optionally, vote on an element of another flow they think should be incorporated into the prototype. (5 mins) <br/> • If the second dot is used copy the specific sticky into the main flow voted by the Decider. |
+| Storyboard | 45 mins | Mural | • Copy the winning flow from the User Test Flow exercise to the Storyboard/Prototype section placing each individual post-it note into its own container. <br/> • Look at the sketch concepts and move over any relevant screens that fulfill the needs of the sticky note in that container. You can move the entire concept or screen capture cut/paste parts of concepts. Note: Don’t add any unnecessary details or ideas that aren’t needed for the end result prototype <br/> • Fill in the details that are required for each step described in the sticky. |
+| Recap day | 5 mins | Mural, Zoom | Summarise activities of the day and decisions. Brief walkthrough of the next day's activities and wrap up the day. |
+
+### Day 4
+ | Activity | Duration | Tool | Description |
+|---|---|---|---|
+| Validate Prototype | 30 mins | Mural | • Go through the Prototype created by the Product designer or Front end developer and discuss any inaccuracies or missing content. |
+| Wrap up the Sprint | 15 mins | Zoom, GitLab | • Recap the Sprint and discuss next steps. Create user testing issues. |
+
+### Day 5
+ | Activity | Duration | Tool | Description |
+|---|---|---|---|
+| Prototype testing with 5 users | ~45 mins | Figma or code/Zoom | • Test the prototype with users. |
+
+## Ground Rules
+* Honor the Facilitator's directions. They're the guide for the entire process.
+* Minimise distractions: During the week you will need to dedicate some hours to the Sprint for async tasks and sync video conferences. During this time we recommend blocking time in your calendar and having devices or apps with notifications turned off during that time.
+* All opinions are valid and are equally important, however, the Decider has the ultimate, final decision.
+* Everyone is an active participant in a sync activity (with the exception of the Observers).
+* One conversation at a time.
+* Document as much as you can: We should have concrete outputs to share with broader team. Also interesting ideas or fixes should be documented to be transferred in issues for our backlog.
+* Stick to scheduled breaks during sync calls. The Facilitator will guide each session and set break times.
+* The Sprint is one of the few chances we get to work so closely together. Have fun!
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 5ab46bfa26f..66450c37a22 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -77,6 +77,15 @@ Please list the test areas (unit, integration and end-to-end) that needs to be a
See the test engineering planning process and reach out to your counterpart Software Engineer in Test for assistance: https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-planning -->
+### Available Tier
+
+<!-- This section should be used for setting the appropriate tier that this feature will belong to. Pricing can be found here: https://about.gitlab.com/pricing/
+
+* Free
+* Premium/Silver
+* Ultimate/Gold
+-->
+
### What does success look like, and how can we measure that?
<!--
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index 840ef4c6337..3de004b0319 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -9,6 +9,7 @@ Set the title to: `Description of the original issue`
## Prior to starting the security release work
- [ ] Read the [security process for developers] if you are not familiar with it.
+ - Verify if the issue you're working on `gitlab-org/gitlab` is confidential, if it's public fix should be placed on GitLab canonical and no backports are required.
- [ ] Mark this [issue as related] to the Security Release Tracking Issue. You can find it on the topic of the `#releases` Slack channel.
- Fill out the [Links section](#links):
- [ ] Next to **Issue on GitLab**, add a link to the `gitlab-org/gitlab` issue that describes the security vulnerability.
diff --git a/.gitlab/merge_request_templates/New End To End Test.md b/.gitlab/merge_request_templates/New End To End Test.md
index 9bd7f11d4a5..c38c3ce340a 100644
--- a/.gitlab/merge_request_templates/New End To End Test.md
+++ b/.gitlab/merge_request_templates/New End To End Test.md
@@ -11,6 +11,7 @@ Please link to the respective test case in the testcases project
- [ ] Follow the end-to-end tests [style guide](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html) and [best practices](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html).
- [ ] Use the appropriate [RSpec metadata tag(s)](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/rspec_metadata_tests.html#rspec-metadata-for-end-to-end-tests).
- [ ] Ensure that a created resource is removed after test execution.
+- [ ] Ensure that no [transient bugs](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#transient-bugs) are hidden accidentally due to the usage of `waits` and `reloads`.
- [ ] Verify the tags to ensure it runs on the desired test environments.
- [ ] If this MR has a dependency on another MR, such as a GitLab QA MR, specify the order in which the MRs should be merged.
- [ ] (If applicable) Create a follow-up issue to document [the special setup](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/running_tests_that_require_special_setup.html) necessary to run the test: ISSUE_LINK
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index c83d5420a4d..bb546632335 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -364,7 +364,6 @@ linters:
- 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
- 'ee/app/views/shared/issuable/_filter_weight.html.haml'
- 'ee/app/views/shared/members/ee/_ldap_tag.html.haml'
- - 'ee/app/views/shared/members/ee/_override_member_buttons.html.haml'
- 'ee/app/views/shared/members/ee/_sso_badge.html.haml'
- 'ee/app/views/shared/milestones/_burndown.html.haml'
- 'ee/app/views/shared/milestones/_weight.html.haml'
diff --git a/.prettierrc b/.prettierrc
index 5e2863a11f6..ace0e29d59b 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"printWidth": 100,
"singleQuote": true,
+ "arrowParens": "always",
"trailingComma": "all"
}
diff --git a/.rubocop.yml b/.rubocop.yml
index b133ecbcf93..4a0cd9579e6 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -48,6 +48,11 @@ Cop/StaticTranslationDefinition:
- 'spec/**/*'
- 'ee/spec/**/*'
+InternalAffairs/DeprecateCopHelper:
+ Enabled: true
+ Include:
+ - spec/rubocop/**/*.rb
+
Lint/LastKeywordArgument:
Enabled: true
Safe: false
@@ -321,6 +326,14 @@ RSpec/TimecopTravel:
- 'ee/spec/**/*.rb'
- 'qa/spec/**/*.rb'
+RSpec/WebMockEnable:
+ Enabled: true
+ Include:
+ - 'spec/**/*.rb'
+ - 'ee/spec/**/*.rb'
+ Exclude:
+ - 'spec/support/webmock.rb'
+
Naming/PredicateName:
Enabled: true
Exclude:
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 2ffbef850d0..cdf7f79412b 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -1,3 +1,15 @@
+---
+# This file is not meant to store permanent exclusions.
+# - for permanent lists, place them in the .rubocop.yml.
+# - for short (less than 15 lines line) temporary lists, place them in the .rubocop_todo.yml file (run auto-generation).
+#
+# Purpose of this file:
+# - show long exclusion lists that are hidden in generic auto-generation of .rubocop_todo.yml.
+# - provide an 'in-flight' list of exclusions being worked on when qualifying as a long list
+# as mentioned above.
+# - guidelines for use found in
+# https://docs.gitlab.com/ee/development/contributing/style_guides.html#resolving-rubocop-exceptions.
+
FactoryBot/InlineAssociation:
Exclude:
- 'ee/spec/factories/analytics/cycle_analytics/group_stages.rb'
@@ -17,24 +29,109 @@ FactoryBot/InlineAssociation:
- 'spec/factories/uploads.rb'
- 'spec/factories/wiki_pages.rb'
-Graphql/IDType:
- Exclude:
- - 'ee/app/graphql/ee/mutations/issues/update.rb'
- - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
- - 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/design_resolver.rb'
- - 'app/graphql/resolvers/design_management/designs_resolver.rb'
- - 'app/graphql/resolvers/design_management/version/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_in_collection_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_resolver.rb'
- - 'app/graphql/resolvers/design_management/versions_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
- - 'app/graphql/resolvers/user_merge_requests_resolver.rb'
-
-Gitlab/PolicyRuleBoolean:
+InternalAffairs/DeprecateCopHelper:
Exclude:
- - 'ee/app/policies/ee/identity_provider_policy.rb'
+ - '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'
+ - 'spec/rubocop/cop/migration/drop_table_spec.rb'
+ - 'spec/rubocop/cop/migration/hash_index_spec.rb'
+ - 'spec/rubocop/cop/migration/datetime_spec.rb'
+ - 'spec/rubocop/cop/migration/add_column_with_default_spec.rb'
+ - 'spec/rubocop/cop/migration/prevent_strings_spec.rb'
+ - 'spec/rubocop/cop/migration/add_timestamps_spec.rb'
+ - 'spec/rubocop/cop/migration/add_concurrent_index_spec.rb'
+ - 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
+ - 'spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb'
+ - 'spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb'
+ - 'spec/rubocop/cop/migration/schedule_async_spec.rb'
+ - 'spec/rubocop/cop/migration/timestamps_spec.rb'
+ - 'spec/rubocop/cop/migration/remove_concurrent_index_spec.rb'
+ - 'spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb'
+ - 'spec/rubocop/cop/migration/with_lock_retries_disallowed_method_spec.rb'
+ - 'spec/rubocop/cop/migration/add_reference_spec.rb'
+ - 'spec/rubocop/cop/migration/remove_column_spec.rb'
+ - 'spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb'
+ - 'spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb'
+ - 'spec/rubocop/cop/migration/with_lock_retries_with_change_spec.rb'
+ - 'spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb'
+ - 'spec/rubocop/cop/avoid_return_from_blocks_spec.rb'
+ - 'spec/rubocop/cop/avoid_route_redirect_leading_slash_spec.rb'
+ - 'spec/rubocop/cop/put_group_routes_under_scope_spec.rb'
+ - 'spec/rubocop/cop/sidekiq_options_queue_spec.rb'
+ - 'spec/rubocop/cop/ignored_columns_spec.rb'
+ - 'spec/rubocop/cop/prefer_class_methods_over_module_spec.rb'
Rails/SaveBang:
Exclude:
@@ -204,7 +301,6 @@ Rails/SaveBang:
- 'spec/controllers/projects_controller_spec.rb'
- 'spec/controllers/sent_notifications_controller_spec.rb'
- 'spec/controllers/sessions_controller_spec.rb'
- - 'spec/controllers/users_controller_spec.rb'
- 'spec/factories_spec.rb'
- 'spec/features/admin/admin_appearance_spec.rb'
- 'spec/features/admin/admin_labels_spec.rb'
@@ -406,6 +502,7 @@ Rails/SaveBang:
- 'spec/requests/api/labels_spec.rb'
- 'spec/requests/api/project_import_spec.rb'
- 'spec/requests/projects/cycle_analytics_events_spec.rb'
+ - 'spec/requests/users_controller_spec.rb'
Rails/TimeZone:
Enabled: true
@@ -669,128 +766,6 @@ RSpec/TimecopTravel:
Graphql/Descriptions:
Exclude:
- - 'app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb'
- - 'app/graphql/mutations/alert_management/base.rb'
- - 'app/graphql/mutations/alert_management/http_integration/create.rb'
- - 'app/graphql/mutations/alert_management/http_integration/destroy.rb'
- - 'app/graphql/mutations/alert_management/http_integration/http_integration_base.rb'
- - 'app/graphql/mutations/alert_management/http_integration/reset_token.rb'
- - 'app/graphql/mutations/alert_management/http_integration/update.rb'
- - 'app/graphql/mutations/alert_management/prometheus_integration/create.rb'
- - 'app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb'
- - 'app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb'
- - 'app/graphql/mutations/alert_management/prometheus_integration/update.rb'
- - 'app/graphql/mutations/alert_management/update_alert_status.rb'
- - 'app/graphql/mutations/award_emojis/base.rb'
- - 'app/graphql/mutations/boards/destroy.rb'
- - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
- - 'app/graphql/mutations/boards/lists/base.rb'
- - 'app/graphql/mutations/boards/lists/create.rb'
- - 'app/graphql/mutations/boards/lists/update.rb'
- - 'app/graphql/mutations/branches/create.rb'
- - 'app/graphql/mutations/ci/base.rb'
- - 'app/graphql/mutations/ci/pipeline_retry.rb'
- - 'app/graphql/mutations/commits/create.rb'
- - 'app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb'
- - 'app/graphql/mutations/concerns/mutations/resolves_subscription.rb'
- - 'app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb'
- - 'app/graphql/mutations/container_expiration_policies/update.rb'
- - 'app/graphql/mutations/container_repositories/destroy_tags.rb'
- - 'app/graphql/mutations/custom_emoji/create.rb'
- - 'app/graphql/mutations/design_management/base.rb'
- - 'app/graphql/mutations/design_management/delete.rb'
- - 'app/graphql/mutations/design_management/move.rb'
- - 'app/graphql/mutations/design_management/upload.rb'
- - 'app/graphql/mutations/discussions/toggle_resolve.rb'
- - 'app/graphql/mutations/environments/canary_ingress/update.rb'
- - 'app/graphql/mutations/issues/base.rb'
- - 'app/graphql/mutations/issues/create.rb'
- - 'app/graphql/mutations/issues/move.rb'
- - 'app/graphql/mutations/issues/set_due_date.rb'
- - 'app/graphql/mutations/issues/set_locked.rb'
- - 'app/graphql/mutations/issues/update.rb'
- - 'app/graphql/mutations/jira_import/import_users.rb'
- - 'app/graphql/mutations/jira_import/start.rb'
- - 'app/graphql/mutations/labels/create.rb'
- - 'app/graphql/mutations/merge_requests/base.rb'
- - 'app/graphql/mutations/merge_requests/create.rb'
- - 'app/graphql/mutations/metrics/dashboard/annotations/create.rb'
- - 'app/graphql/mutations/metrics/dashboard/annotations/delete.rb'
- - 'app/graphql/mutations/notes/base.rb'
- - 'app/graphql/mutations/notes/create/base.rb'
- - 'app/graphql/mutations/notes/create/note.rb'
- - 'app/graphql/mutations/notes/destroy.rb'
- - 'app/graphql/mutations/notes/reposition_image_diff_note.rb'
- - 'app/graphql/mutations/notes/update/base.rb'
- - 'app/graphql/mutations/releases/base.rb'
- - 'app/graphql/mutations/releases/create.rb'
- - 'app/graphql/mutations/releases/update.rb'
- - 'app/graphql/mutations/snippets/base.rb'
- - 'app/graphql/mutations/snippets/create.rb'
- - 'app/graphql/mutations/snippets/destroy.rb'
- - 'app/graphql/mutations/snippets/mark_as_spam.rb'
- - 'app/graphql/mutations/snippets/update.rb'
- - 'app/graphql/mutations/terraform/state/base.rb'
- - 'app/graphql/mutations/todos/create.rb'
- - 'app/graphql/mutations/todos/mark_all_done.rb'
- - 'app/graphql/mutations/todos/mark_done.rb'
- - 'app/graphql/mutations/todos/restore.rb'
- - 'app/graphql/mutations/todos/restore_many.rb'
- - 'app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb'
- - 'app/graphql/resolvers/alert_management/alert_resolver.rb'
- - 'app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb'
- - 'app/graphql/resolvers/board_list_issues_resolver.rb'
- - 'app/graphql/resolvers/board_lists_resolver.rb'
- - 'app/graphql/resolvers/board_resolver.rb'
- - 'app/graphql/resolvers/boards_resolver.rb'
- - 'app/graphql/resolvers/ci/config_resolver.rb'
- - 'app/graphql/resolvers/ci/jobs_resolver.rb'
- - 'app/graphql/resolvers/ci/runner_setup_resolver.rb'
- - 'app/graphql/resolvers/concerns/issue_resolver_arguments.rb'
- - 'app/graphql/resolvers/concerns/resolves_pipelines.rb'
- - 'app/graphql/resolvers/concerns/resolves_snippets.rb'
- - 'app/graphql/resolvers/concerns/time_frame_arguments.rb'
- - 'app/graphql/resolvers/container_repositories_resolver.rb'
- - 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/design_resolver.rb'
- - 'app/graphql/resolvers/design_management/designs_resolver.rb'
- - 'app/graphql/resolvers/design_management/version/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_in_collection_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_resolver.rb'
- - 'app/graphql/resolvers/design_management/versions_resolver.rb'
- - 'app/graphql/resolvers/echo_resolver.rb'
- - 'app/graphql/resolvers/environments_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb'
- - 'app/graphql/resolvers/full_path_resolver.rb'
- - 'app/graphql/resolvers/group_members_resolver.rb'
- - 'app/graphql/resolvers/group_milestones_resolver.rb'
- - 'app/graphql/resolvers/issues_resolver.rb'
- - 'app/graphql/resolvers/members_resolver.rb'
- - 'app/graphql/resolvers/merge_request_resolver.rb'
- - 'app/graphql/resolvers/merge_requests_resolver.rb'
- - 'app/graphql/resolvers/metrics/dashboard_resolver.rb'
- - 'app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb'
- - 'app/graphql/resolvers/milestones_resolver.rb'
- - 'app/graphql/resolvers/namespace_projects_resolver.rb'
- - 'app/graphql/resolvers/project_members_resolver.rb'
- - 'app/graphql/resolvers/project_milestones_resolver.rb'
- - 'app/graphql/resolvers/project_pipeline_resolver.rb'
- - 'app/graphql/resolvers/projects/jira_projects_resolver.rb'
- - 'app/graphql/resolvers/projects/services_resolver.rb'
- - 'app/graphql/resolvers/projects_resolver.rb'
- - 'app/graphql/resolvers/release_resolver.rb'
- - 'app/graphql/resolvers/releases_resolver.rb'
- - 'app/graphql/resolvers/snippets/blobs_resolver.rb'
- - 'app/graphql/resolvers/snippets_resolver.rb'
- - 'app/graphql/resolvers/todo_resolver.rb'
- - 'app/graphql/resolvers/tree_resolver.rb'
- - 'app/graphql/resolvers/user_resolver.rb'
- - 'app/graphql/resolvers/user_starred_projects_resolver.rb'
- - 'app/graphql/resolvers/users/snippets_resolver.rb'
- - 'app/graphql/resolvers/users_resolver.rb'
- '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'
@@ -906,12 +881,6 @@ Graphql/Descriptions:
- 'app/graphql/types/tree/tree_type.rb'
- 'app/graphql/types/user_status_type.rb'
- 'app/graphql/types/user_type.rb'
- - 'ee/app/graphql/ee/mutations/boards/issues/issue_move_list.rb'
- - 'ee/app/graphql/ee/mutations/boards/lists/create.rb'
- - 'ee/app/graphql/ee/mutations/issues/create.rb'
- - 'ee/app/graphql/ee/mutations/issues/update.rb'
- - 'ee/app/graphql/ee/resolvers/issues_resolver.rb'
- - 'ee/app/graphql/ee/resolvers/namespace_projects_resolver.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'
@@ -923,61 +892,6 @@ Graphql/Descriptions:
- '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/mutations/admin/analytics/devops_adoption/segments/delete.rb'
- - 'ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/mixins.rb'
- - 'ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/update.rb'
- - 'ee/app/graphql/mutations/boards/lists/update_limit_metrics.rb'
- - 'ee/app/graphql/mutations/boards/update.rb'
- - 'ee/app/graphql/mutations/boards/update_epic_user_preferences.rb'
- - 'ee/app/graphql/mutations/compliance_management/frameworks/destroy.rb'
- - 'ee/app/graphql/mutations/compliance_management/frameworks/update.rb'
- - 'ee/app/graphql/mutations/clusters/agent_tokens/create.rb'
- - 'ee/app/graphql/mutations/clusters/agent_tokens/delete.rb'
- - 'ee/app/graphql/mutations/clusters/agents/create.rb'
- - 'ee/app/graphql/mutations/clusters/agents/delete.rb'
- - 'ee/app/graphql/mutations/concerns/mutations/shared_epic_arguments.rb'
- - 'ee/app/graphql/mutations/epic_tree/reorder.rb'
- - 'ee/app/graphql/mutations/epics/add_issue.rb'
- - 'ee/app/graphql/mutations/epics/base.rb'
- - 'ee/app/graphql/mutations/epics/create.rb'
- - 'ee/app/graphql/mutations/epics/set_subscription.rb'
- - 'ee/app/graphql/mutations/epics/update.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/create.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/destroy.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/oncall_schedule_base.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/update.rb'
- - 'ee/app/graphql/mutations/instance_security_dashboard/add_project.rb'
- - 'ee/app/graphql/mutations/instance_security_dashboard/remove_project.rb'
- - 'ee/app/graphql/mutations/issues/common_ee_mutation_arguments.rb'
- - 'ee/app/graphql/mutations/issues/promote_to_epic.rb'
- - 'ee/app/graphql/mutations/issues/set_weight.rb'
- - 'ee/app/graphql/mutations/iterations/create.rb'
- - 'ee/app/graphql/mutations/namespaces/base.rb'
- - 'ee/app/graphql/mutations/quality_management/test_cases/create.rb'
- - 'ee/app/graphql/mutations/requirements_management/base_requirement.rb'
- - 'ee/app/graphql/mutations/requirements_management/update_requirement.rb'
- - 'ee/app/graphql/mutations/security/ci_configuration/configure_sast.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/confirm.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/dismiss.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/resolve.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/revert_to_detected.rb'
- - 'ee/app/graphql/resolvers/board_groupings/epics_resolver.rb'
- - 'ee/app/graphql/resolvers/boards/epic_boards_resolver.rb'
- - 'ee/app/graphql/resolvers/ci/code_coverage_activities_resolver.rb'
- - 'ee/app/graphql/resolvers/clusters/agents_resolver.rb'
- - 'ee/app/graphql/resolvers/dast_site_profile_resolver.rb'
- - 'ee/app/graphql/resolvers/dast_site_validation_resolver.rb'
- - 'ee/app/graphql/resolvers/epics_resolver.rb'
- - 'ee/app/graphql/resolvers/geo/registries_resolver.rb'
- - 'ee/app/graphql/resolvers/requirements_management/requirements_resolver.rb'
- - 'ee/app/graphql/resolvers/requirements_management/test_reports_resolver.rb'
- - 'ee/app/graphql/resolvers/timelog_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities/issue_links_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities_count_per_day_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities_grade_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities_history_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerability_severities_count_resolver.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'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 293c8fccf33..d60ab9b2fcc 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,49 +1,77 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2020-10-29 17:35:37 UTC using RuboCop version 0.89.1.
+# on 2021-01-11 15:49:32 UTC using RuboCop version 0.91.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
-# Offense count: 310
+# Offense count: 313
# Cop supports --auto-correct.
Capybara/CurrentPathExpectation:
Enabled: false
-# Offense count: 210
+# Offense count: 218
Capybara/VisibilityMatcher:
Enabled: false
-# Offense count: 1903
+# Offense count: 1
+Gitlab/PolicyRuleBoolean:
+ Exclude:
+ - 'ee/app/policies/ee/identity_provider_policy.rb'
+
+# Offense count: 5
+Graphql/IDType:
+ Exclude:
+ - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
+
+# Offense count: 2054
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
Enabled: false
-# Offense count: 49
+# Offense count: 11
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyleAlignWith, Severity.
+# SupportedStylesAlignWith: start_of_line, begin
+Layout/BeginEndAlignment:
+ Exclude:
+ - 'app/controllers/groups/shared_projects_controller.rb'
+ - 'app/workers/concerns/reactive_cacheable_worker.rb'
+ - 'ee/app/services/security/token_revocation_service.rb'
+ - 'ee/lib/gitlab/analytics/cycle_analytics/summary/group/deploy.rb'
+ - 'ee/lib/gitlab/ci/config/entry/vault/secret.rb'
+ - 'lib/api/internal/base.rb'
+ - 'lib/atlassian/jira_connect/serializers/build_entity.rb'
+ - 'lib/gitlab/ci/jwt.rb'
+ - 'lib/gitlab/external_authorization/client.rb'
+ - 'lib/gitlab/phabricator_import/project_creator.rb'
+ - 'scripts/gitaly_test.rb'
+
+# Offense count: 52
# Cop supports --auto-correct.
# Configuration parameters: AllowAliasSyntax, AllowedMethods.
# AllowedMethods: alias_method, public, protected, private
Layout/EmptyLinesAroundAttributeAccessor:
Enabled: false
-# Offense count: 610
+# Offense count: 721
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
Layout/FirstArrayElementIndentation:
Enabled: false
-# Offense count: 1535
+# Offense count: 1592
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_braces
Layout/FirstHashElementIndentation:
Enabled: false
-# Offense count: 2754
+# Offense count: 3019
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
@@ -52,33 +80,47 @@ Layout/FirstHashElementIndentation:
Layout/HashAlignment:
Enabled: false
-# Offense count: 64
+# Offense count: 73
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 1313
-# Offense count: 118
+# Offense count: 163
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented
Layout/MultilineOperationIndentation:
Enabled: false
-# Offense count: 52
+# Offense count: 11
+# Cop supports --auto-correct.
+Layout/RescueEnsureAlignment:
+ Exclude:
+ - 'app/models/blob_viewer/dependency_manager.rb'
+ - 'app/models/project.rb'
+ - 'app/services/prometheus/proxy_service.rb'
+ - 'app/workers/concerns/reactive_cacheable_worker.rb'
+ - 'app/workers/delete_stored_files_worker.rb'
+ - 'config/initializers/1_settings.rb'
+ - 'config/initializers/trusted_proxies.rb'
+ - 'lib/api/internal/base.rb'
+ - 'lib/gitlab/highlight.rb'
+
+# Offense count: 53
# Cop supports --auto-correct.
Layout/SpaceAroundMethodCallOperator:
Enabled: false
-# Offense count: 790
+# Offense count: 725
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_no_space, require_space
Layout/SpaceInLambdaLiteral:
Enabled: false
-# Offense count: 1110
+# Offense count: 218
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
@@ -86,7 +128,7 @@ Layout/SpaceInLambdaLiteral:
Layout/SpaceInsideBlockBraces:
Enabled: false
-# Offense count: 501
+# Offense count: 559
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: space, no_space
@@ -96,7 +138,6 @@ Layout/SpaceInsideParens:
# Offense count: 18
Lint/BinaryOperatorWithIdenticalOperands:
Exclude:
- - 'app/finders/concerns/time_frame_filter.rb'
- 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- 'spec/helpers/visibility_level_helper_spec.rb'
- 'spec/lib/gitlab/conan_token_spec.rb'
@@ -110,6 +151,10 @@ Lint/BinaryOperatorWithIdenticalOperands:
- 'spec/models/repository_spec.rb'
- 'spec/models/ssh_host_key_spec.rb'
+# Offense count: 83
+Lint/ConstantDefinitionInBlock:
+ Enabled: false
+
# Offense count: 9
# Cop supports --auto-correct.
Lint/DeprecatedOpenSSLConstant:
@@ -118,7 +163,6 @@ Lint/DeprecatedOpenSSLConstant:
- 'ee/lib/gitlab/geo/oauth/logout_state.rb'
- 'lib/gitlab/conan_token.rb'
- 'lib/gitlab/gitaly_client.rb'
- - 'lib/gitlab/kubernetes/helm/certificate.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'
@@ -126,11 +170,25 @@ Lint/DeprecatedOpenSSLConstant:
- 'spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb'
# Offense count: 1
-Lint/FloatComparison:
+Lint/DuplicateRequire:
+ Exclude:
+ - 'ee/spec/lib/gitlab/auth/group_saml/user_spec.rb'
+
+# Offense count: 2
+# Configuration parameters: AllowComments.
+Lint/EmptyFile:
Exclude:
- - 'ee/app/models/ee/namespace.rb'
+ - 'db/seeds.rb'
+ - 'ee/db/geo/seeds.rb'
-# Offense count: 157
+# Offense count: 8
+# Cop supports --auto-correct.
+Lint/IdentityComparison:
+ Exclude:
+ - 'spec/lib/gitlab/danger/weightage/maintainers_spec.rb'
+ - 'spec/lib/gitlab/danger/weightage/reviewers_spec.rb'
+
+# Offense count: 184
# Configuration parameters: MaximumRangeSize.
Lint/MissingCopEnableDirective:
Enabled: false
@@ -153,13 +211,7 @@ Lint/MixedRegexpCaptureTypes:
- 'lib/gitlab/slash_commands/issue_new.rb'
- 'lib/gitlab/slash_commands/run.rb'
-# Offense count: 1
-# Cop supports --auto-correct.
-Lint/NonDeterministicRequireOrder:
- Exclude:
- - 'rubocop/rubocop.rb'
-
-# Offense count: 118
+# Offense count: 141
# Cop supports --auto-correct.
Lint/RedundantCopDisableDirective:
Enabled: false
@@ -169,12 +221,6 @@ Lint/SelfAssignment:
Exclude:
- 'spec/lib/gitlab/search_context/builder_spec.rb'
-# Offense count: 1
-# Cop supports --auto-correct.
-Lint/SendWithMixinArgument:
- Exclude:
- - 'config/initializers/trusted_proxies.rb'
-
# Offense count: 3
Lint/StructNewOverride:
Exclude:
@@ -187,20 +233,63 @@ Lint/UnreachableLoop:
Exclude:
- 'qa/qa/runtime/feature.rb'
-# Offense count: 5
-# Configuration parameters: IgnoredMethods.
+# Offense count: 22
+# Cop supports --auto-correct.
+# Configuration parameters: AllowComments.
+Lint/UselessMethodDefinition:
+ Enabled: false
+
+# Offense count: 7
+# Configuration parameters: IgnoredMethods, Max.
Metrics/AbcSize:
- Max: 59
+ Exclude:
+ - 'app/helpers/issuables_helper.rb'
+ - 'app/services/merge_requests/build_service.rb'
+ - 'app/services/projects/create_service.rb'
+ - 'lib/api/helpers.rb'
+ - 'lib/gitlab/lograge/custom_options.rb'
+ - 'lib/gitlab/rack_attack.rb'
+ - 'qa/qa/resource/repository/push.rb'
-# Offense count: 13
-# Configuration parameters: IgnoredMethods.
+# Offense count: 15
+# Configuration parameters: IgnoredMethods, Max.
Metrics/CyclomaticComplexity:
- Max: 25
+ Exclude:
+ - 'app/services/projects/create_service.rb'
+ - 'app/services/system_hooks_service.rb'
+ - 'ee/app/controllers/ee/groups_controller.rb'
+ - 'ee/app/helpers/ee/groups_helper.rb'
+ - 'ee/lib/security/ci_configuration/sast_build_actions.rb'
+ - 'lib/banzai/filter/abstract_reference_filter.rb'
+ - 'lib/declarative_policy/runner.rb'
+ - 'lib/gitlab/conflict/file.rb'
+ - 'lib/gitlab/danger/roulette.rb'
+ - 'lib/gitlab/diff/parser.rb'
+ - 'lib/gitlab/rack_attack.rb'
+ - 'lib/gitlab/sidekiq_cluster/cli.rb'
+ - 'lib/gitlab/utils/merge_hash.rb'
+ - 'lib/kramdown/parser/atlassian_document_format.rb'
+ - 'spec/support/cycle_analytics_helpers/test_generation.rb'
-# Offense count: 13
-# Configuration parameters: IgnoredMethods.
+# Offense count: 15
+# Configuration parameters: IgnoredMethods, Max.
Metrics/PerceivedComplexity:
- Max: 25
+ Exclude:
+ - 'app/helpers/submodule_helper.rb'
+ - 'app/helpers/tab_helper.rb'
+ - 'app/services/projects/create_service.rb'
+ - 'ee/app/controllers/ee/groups_controller.rb'
+ - 'ee/app/helpers/ee/groups_helper.rb'
+ - 'ee/lib/security/ci_configuration/sast_build_actions.rb'
+ - 'lib/banzai/filter/abstract_reference_filter.rb'
+ - 'lib/banzai/renderer.rb'
+ - 'lib/declarative_policy/runner.rb'
+ - 'lib/gitlab/conflict/file.rb'
+ - 'lib/gitlab/danger/roulette.rb'
+ - 'lib/gitlab/rack_attack.rb'
+ - 'lib/gitlab/sidekiq_cluster/cli.rb'
+ - 'lib/gitlab/utils/merge_hash.rb'
+ - 'spec/support/cycle_analytics_helpers/test_generation.rb'
# Offense count: 1
# Cop supports --auto-correct.
@@ -208,7 +297,7 @@ Migration/DepartmentName:
Exclude:
- 'app/models/commit.rb'
-# Offense count: 171
+# Offense count: 184
# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, Regex, IgnoreExecutableScripts, AllowedAcronyms.
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
Naming/FileName:
@@ -225,7 +314,7 @@ Naming/HeredocDelimiterCase:
- 'spec/support/helpers/repo_helpers.rb'
- 'spec/support/helpers/seed_repo.rb'
-# Offense count: 263
+# Offense count: 308
# Configuration parameters: ForbiddenDelimiters.
# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
Naming/HeredocDelimiterNaming:
@@ -239,7 +328,7 @@ Naming/MethodParameterName:
- 'lib/gitlab/diff/inline_diff.rb'
- 'spec/support/helpers/key_generator_helper.rb'
-# Offense count: 191
+# Offense count: 206
# Cop supports --auto-correct.
# Configuration parameters: PreferredName.
Naming/RescuedExceptionsVariableName:
@@ -251,12 +340,22 @@ Performance/AncestorsInclude:
Exclude:
- 'lib/gitlab/ci/config/extendable/entry.rb'
+# Offense count: 39
+# Cop supports --auto-correct.
+Performance/BlockGivenWithExplicitBlock:
+ Enabled: false
+
# Offense count: 28
# Configuration parameters: MinSize.
Performance/CollectionLiteralInLoop:
Enabled: false
-# Offense count: 19
+# Offense count: 37
+# Cop supports --auto-correct.
+Performance/ConstantRegexp:
+ Enabled: false
+
+# Offense count: 18
# Cop supports --auto-correct.
Performance/Count:
Exclude:
@@ -267,10 +366,9 @@ Performance/Count:
- 'spec/lib/gitlab/conflict/file_spec.rb'
- 'spec/lib/gitlab/git/tree_spec.rb'
- 'spec/models/ci/build_spec.rb'
- - 'spec/support/matchers/exceed_query_limit.rb'
- 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
-# Offense count: 15
+# Offense count: 14
# Cop supports --auto-correct.
# Configuration parameters: SafeMultiline.
Performance/DeletePrefix:
@@ -283,14 +381,13 @@ Performance/DeletePrefix:
- 'lib/gitlab/gfm/uploads_rewriter.rb'
- 'lib/gitlab/git/ref.rb'
- 'lib/gitlab/project_template.rb'
- - 'lib/gitlab/repo_path.rb'
- 'lib/gitlab/setup_helper.rb'
- 'lib/gitlab/time_tracking_formatter.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/lib/gitlab/gfm/uploads_rewriter_spec.rb'
- 'spec/support/helpers/test_env.rb'
-# Offense count: 6
+# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: SafeMultiline.
Performance/DeleteSuffix:
@@ -299,7 +396,6 @@ Performance/DeleteSuffix:
- 'app/workers/concerns/application_worker.rb'
- 'ee/app/models/geo/upload_registry.rb'
- 'ee/app/workers/geo/file_download_dispatch_worker/attachment_job_finder.rb'
- - 'lib/gitlab/repo_path.rb'
- 'lib/sentry/client/issue.rb'
# Offense count: 13
@@ -313,7 +409,11 @@ Performance/Detect:
- 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/models/event_spec.rb'
-# Offense count: 19
+# Offense count: 116
+Performance/MethodObjectAsBlock:
+ Enabled: false
+
+# Offense count: 18
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect.
Performance/StringInclude:
@@ -330,23 +430,30 @@ Performance/StringInclude:
- 'qa/qa/ee/page/merge_request/show.rb'
- 'qa/qa/specs/runner.rb'
- 'spec/features/projects/jobs_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
-# Offense count: 9
+# Offense count: 18
# Cop supports --auto-correct.
Performance/Sum:
Exclude:
+ - 'app/controllers/projects/pipelines/tests_controller.rb'
- 'app/models/application_setting_implementation.rb'
- 'app/models/ci/pipeline.rb'
+ - 'app/services/issues/export_csv_service.rb'
- 'ee/spec/lib/gitlab/elastic/bulk_indexer_spec.rb'
+ - 'lib/api/entities/issuable_time_stats.rb'
+ - 'lib/container_registry/tag.rb'
- 'lib/declarative_policy/rule.rb'
- 'lib/declarative_policy/runner.rb'
+ - 'lib/gitlab/ci/reports/test_suite_comparer.rb'
+ - 'lib/gitlab/diff/file.rb'
- 'lib/gitlab/sherlock/transaction.rb'
- 'lib/gitlab/usage_data.rb'
+ - 'lib/peek/views/detailed_view.rb'
+ - 'spec/models/namespace/root_storage_statistics_spec.rb'
-# Offense count: 13879
+# Offense count: 14717
# Configuration parameters: Prefixes.
# Prefixes: when, with, without
RSpec/ContextWording:
@@ -359,65 +466,50 @@ RSpec/EmptyExampleGroup:
- 'ee/spec/services/personal_access_tokens/revoke_invalid_tokens_spec.rb'
- 'spec/services/projects/prometheus/alerts/notify_service_spec.rb'
-# Offense count: 1310
+# Offense count: 1365
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: method_call, block
RSpec/ExpectChange:
Enabled: false
-RSpec/ExpectGitlabTracking:
- Exclude:
- - 'ee/spec/requests/api/visual_review_discussions_spec.rb'
- - 'ee/spec/services/epics/issue_promote_service_spec.rb'
- - 'spec/controllers/groups/registry/repositories_controller_spec.rb'
- - 'spec/controllers/projects/registry/repositories_controller_spec.rb'
- - 'spec/controllers/projects/registry/tags_controller_spec.rb'
- - 'spec/controllers/projects/settings/operations_controller_spec.rb'
- - 'spec/lib/api/helpers_spec.rb'
- - 'spec/requests/api/project_container_repositories_spec.rb'
- - 'spec/support/shared_examples/controllers/trackable_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/discussions_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/packages_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/tracking_shared_examples.rb'
-
-# Offense count: 888
+# Offense count: 889
RSpec/ExpectInHook:
Enabled: false
-# Offense count: 15945
+# Offense count: 16403
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
Max: 40
-# Offense count: 2297
+# Offense count: 2352
# Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
# SupportedStyles: inflected, explicit
RSpec/PredicateMatcher:
Enabled: false
-# Offense count: 98
+# Offense count: 112
RSpec/RepeatedExampleGroupBody:
Enabled: false
-# Offense count: 213
+# Offense count: 219
RSpec/RepeatedExampleGroupDescription:
Enabled: false
-# Offense count: 636
+# Offense count: 655
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: and_return, block
RSpec/ReturnFromStub:
Enabled: false
-# Offense count: 574
+# Offense count: 596
# Cop supports --auto-correct.
RSpec/ScatteredLet:
Enabled: false
-# Offense count: 4
+# Offense count: 6
RSpec/ScatteredSetup:
Exclude:
- 'spec/requests/api/jobs_spec.rb'
@@ -429,7 +521,7 @@ RSpec/VariableDefinition:
Exclude:
- 'spec/initializers/mail_encoding_patch_spec.rb'
-# Offense count: 25
+# Offense count: 24
# Configuration parameters: EnforcedStyle, IgnoredPatterns.
# SupportedStyles: snake_case, camelCase
RSpec/VariableName:
@@ -437,13 +529,12 @@ RSpec/VariableName:
- 'spec/features/projects/import_export/import_file_spec.rb'
- 'spec/features/task_lists_spec.rb'
- 'spec/initializers/mail_encoding_patch_spec.rb'
- - 'spec/lib/gitlab/experimentation_spec.rb'
- 'spec/models/board_spec.rb'
- 'spec/support/shared_contexts/url_shared_context.rb'
- 'spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb'
- 'spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb'
-# Offense count: 27
+# Offense count: 25
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
@@ -472,25 +563,25 @@ Rails/BelongsTo:
- 'app/models/deployment.rb'
- 'app/models/environment.rb'
-# Offense count: 84
+# Offense count: 90
# Configuration parameters: Database, Include.
# SupportedDatabases: mysql, postgresql
# Include: db/migrate/*.rb
Rails/BulkChangeTable:
Enabled: false
-# Offense count: 151
+# Offense count: 153
# Cop supports --auto-correct.
Rails/ContentTag:
Enabled: false
-# Offense count: 270
+# Offense count: 300
# Configuration parameters: Include.
# Include: db/migrate/*.rb
Rails/CreateTableWithTimestamps:
Enabled: false
-# Offense count: 323
+# Offense count: 347
# Configuration parameters: EnforcedStyle.
# SupportedStyles: slashes, arguments
Rails/FilePath:
@@ -512,13 +603,13 @@ Rails/FindById:
- 'spec/finders/concerns/finder_methods_spec.rb'
- 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
-# Offense count: 329
+# Offense count: 346
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Enabled: false
-# Offense count: 507
+# Offense count: 539
# Configuration parameters: Include.
# Include: app/helpers/**/*.rb
Rails/HelperInstanceVariable:
@@ -542,7 +633,7 @@ Rails/IndexBy:
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
- 'lib/gitlab/language_detection.rb'
-# Offense count: 44
+# Offense count: 45
# Cop supports --auto-correct.
Rails/IndexWith:
Enabled: false
@@ -552,7 +643,7 @@ Rails/Inquiry:
Exclude:
- 'spec/helpers/labels_helper_spec.rb'
-# Offense count: 112
+# Offense count: 115
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/InverseOf:
@@ -580,33 +671,34 @@ Rails/MailerName:
Exclude:
- 'app/mailers/notify.rb'
-# Offense count: 48
+# Offense count: 51
# Cop supports --auto-correct.
Rails/NegateInclude:
Enabled: false
-# Offense count: 41
+# Offense count: 44
# Cop supports --auto-correct.
Rails/Pick:
Enabled: false
-# Offense count: 113
+# Offense count: 110
# Cop supports --auto-correct.
Rails/Pluck:
Enabled: false
-# Offense count: 38
+# Offense count: 39
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: **/Rakefile, **/*.rake
Rails/RakeEnvironment:
Enabled: false
-# Offense count: 52
+# Offense count: 58
# Cop supports --auto-correct.
Rails/RedundantForeignKey:
Enabled: false
+# Offense count: 1
Rails/RenderInline:
Exclude:
- 'ee/app/controllers/sitemap_controller.rb'
@@ -621,18 +713,23 @@ Rails/ShortI18n:
- 'app/uploaders/content_type_whitelist.rb'
- 'spec/views/shared/runners/show.html.haml_spec.rb'
-# Offense count: 1043
+# Offense count: 1080
# Configuration parameters: ForbiddenMethods, AllowedMethods.
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
Rails/SkipsModelValidations:
Enabled: false
-# Offense count: 202
+# Offense count: 251
# Cop supports --auto-correct.
Rails/SquishedSQLHeredocs:
Enabled: false
-# Offense count: 37
+# Offense count: 45
+# Cop supports --auto-correct.
+Rails/WhereEquals:
+ Enabled: false
+
+# Offense count: 40
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: exists, where
@@ -661,13 +758,12 @@ Security/YAMLLoad:
Style/AccessorGrouping:
Enabled: false
-# Offense count: 13
+# Offense count: 12
# Cop supports --auto-correct.
Style/ArrayCoercion:
Exclude:
- 'app/controllers/admin/ci/variables_controller.rb'
- 'app/controllers/groups/variables_controller.rb'
- - 'app/controllers/import/bulk_imports_controller.rb'
- 'app/controllers/projects/variables_controller.rb'
- 'db/migrate/20190620105427_change_null_private_profile_to_false.rb'
- 'db/post_migrate/20190812070645_migrate_private_profile_nulls.rb'
@@ -679,7 +775,7 @@ Style/ArrayCoercion:
- 'ee/lib/ee/banzai/pipeline/gfm_pipeline.rb'
- 'spec/support/helpers/lfs_http_helpers.rb'
-# Offense count: 176
+# Offense count: 183
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: percent_q, bare_percent
@@ -693,11 +789,27 @@ Style/BisectedAttrAccessor:
- 'lib/system_check/base_check.rb'
- 'qa/qa/resource/api_fabricator.rb'
-# Offense count: 37
+# Offense count: 36
# Cop supports --auto-correct.
Style/CaseLikeIf:
Enabled: false
+# Offense count: 15
+Style/CombinableLoops:
+ Exclude:
+ - 'app/models/application_setting.rb'
+ - 'ee/db/fixtures/development/30_customizable_cycle_analytics.rb'
+ - 'ee/lib/gitlab/audit/events/preloader.rb'
+ - 'ee/spec/finders/snippets_finder_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/remove_duplicate_cs_findings_spec.rb'
+ - 'rubocop/code_reuse_helpers.rb'
+ - 'spec/features/merge_request/user_suggests_changes_on_diff_spec.rb'
+ - 'spec/finders/packages/group_packages_finder_spec.rb'
+ - 'spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb'
+ - 'spec/migrations/cleanup_optimistic_locking_nulls_spec.rb'
+ - 'spec/requests/api/members_spec.rb'
+ - 'spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb'
+
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
@@ -723,7 +835,7 @@ Style/EachWithObject:
Style/EmptyElse:
Enabled: false
-# Offense count: 193
+# Offense count: 197
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, expanded
@@ -737,94 +849,99 @@ Style/ExpandPathArguments:
- 'cable/config.ru'
- 'config.ru'
-# Offense count: 118
+# Offense count: 116
# Cop supports --auto-correct.
Style/ExplicitBlockArgument:
Enabled: false
-# Offense count: 521
+# Offense count: 555
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: format, sprintf, percent
Style/FormatString:
Enabled: false
-# Offense count: 48
+# Offense count: 61
# Cop supports --auto-correct.
Style/GlobalStdStream:
Enabled: false
-# Offense count: 835
+# Offense count: 879
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Enabled: false
-# Offense count: 93
+# Offense count: 56
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: braces, no_braces
Style/HashAsLastArrayItem:
Enabled: false
-# Offense count: 55
+# Offense count: 66
# Cop supports --auto-correct.
Style/HashEachMethods:
Enabled: false
-# Offense count: 30
+# Offense count: 33
# Configuration parameters: AllowIfModifier.
Style/IfInsideElse:
Enabled: false
-# Offense count: 1798
+# Offense count: 1888
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Enabled: false
-# Offense count: 447
+# Offense count: 68
+# Cop supports --auto-correct.
+Style/KeywordParametersOrder:
+ Enabled: false
+
+# Offense count: 431
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: line_count_dependent, lambda, literal
Style/Lambda:
Enabled: false
-# Offense count: 18
+# Offense count: 20
Style/MissingRespondToMissing:
Enabled: false
-# Offense count: 32
+# Offense count: 35
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength.
# SupportedStyles: skip_modifier_ifs, always
Style/Next:
Enabled: false
-# Offense count: 95
+# Offense count: 98
# Cop supports --auto-correct.
# Configuration parameters: EnforcedOctalStyle.
# SupportedOctalStyles: zero_with_o, zero_only
Style/NumericLiteralPrefix:
Enabled: false
-# Offense count: 132
+# Offense count: 135
# Cop supports --auto-correct.
Style/ParallelAssignment:
Enabled: false
-# Offense count: 2473
+# Offense count: 2601
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
Enabled: false
-# Offense count: 246
+# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, exploded
Style/RaiseArgs:
Enabled: false
-# Offense count: 66
+# Offense count: 65
# Cop supports --auto-correct.
Style/RedundantAssignment:
Enabled: false
@@ -846,91 +963,102 @@ Style/RedundantFetchBlock:
Style/RedundantFileExtensionInRequire:
Enabled: false
-# Offense count: 260
+# Offense count: 220
# Cop supports --auto-correct.
Style/RedundantFreeze:
Enabled: false
-# Offense count: 167
+# Offense count: 182
# Cop supports --auto-correct.
Style/RedundantInterpolation:
Enabled: false
-# Offense count: 11
+# Offense count: 8
# Cop supports --auto-correct.
Style/RedundantRegexpCharacterClass:
Exclude:
- 'app/models/concerns/taskable.rb'
- - 'ee/lib/ee/gitlab/path_regex.rb'
- 'lib/gitlab/authorized_keys.rb'
- 'lib/gitlab/fogbugz_import/repository.rb'
- - 'lib/gitlab/prometheus/internal.rb'
- 'lib/gitlab/quick_actions/substitution_definition.rb'
- 'lib/gitlab/regex.rb'
- 'spec/features/merge_request/user_views_open_merge_request_spec.rb'
- 'spec/tasks/gitlab/usage_data_rake_spec.rb'
-# Offense count: 250
+# Offense count: 270
# Cop supports --auto-correct.
Style/RedundantRegexpEscape:
Enabled: false
-# Offense count: 868
+# Offense count: 920
# Cop supports --auto-correct.
Style/RedundantSelf:
Enabled: false
-# Offense count: 179
+# Offense count: 2
+# Cop supports --auto-correct.
+Style/RedundantSelfAssignment:
+ Exclude:
+ - 'app/models/concerns/issuable.rb'
+ - 'spec/db/schema_spec.rb'
+
+# Offense count: 196
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
Enabled: false
-# Offense count: 49
+# Offense count: 50
# Cop supports --auto-correct.
Style/RescueModifier:
Enabled: false
-# Offense count: 329
+# Offense count: 346
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
Enabled: false
-# Offense count: 104
+# Offense count: 115
# Cop supports --auto-correct.
Style/SingleArgumentDig:
Enabled: false
-# Offense count: 47
+# Offense count: 45
# Cop supports --auto-correct.
Style/SlicingWithRange:
Enabled: false
-# Offense count: 109
+# Offense count: 61
+# Configuration parameters: AllowModifier.
+Style/SoleNestedConditional:
+ Enabled: false
+
+# Offense count: 121
# Cop supports --auto-correct.
# Configuration parameters: .
# SupportedStyles: use_perl_names, use_english_names
Style/SpecialGlobalVars:
EnforcedStyle: use_perl_names
-# Offense count: 516
+# Offense count: 545
# Cop supports --auto-correct.
Style/StringConcatenation:
Enabled: false
-# Offense count: 103
+# Offense count: 108
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Enabled: false
-# Offense count: 276
+# Offense count: 292
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.
# IgnoredMethods: respond_to, define_method
Style/SymbolProc:
Enabled: false
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f14f7fa6325..3b6780c7797 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -504,6 +504,26 @@ entry.
- Update GitLab Workhorse to v8.57.0.
+## 13.6.5 (2021-01-13)
+
+### Security (1 change)
+
+- Deny implicit flow for confidential apps.
+
+
+## 13.6.4 (2021-01-07)
+
+### Security (7 changes)
+
+- Forbid public cache for private repos.
+- Deny implicit flow for confidential apps.
+- Update NuGet regular expression to protect against ReDoS.
+- Fix regular expression backtracking issue in package name validation.
+- Upgrade GitLab Pages to 1.30.2.
+- Update trusted OAuth applications to set them as confidential.
+- Upgrade Workhorse to 8.54.2.
+
+
## 13.6.3 (2020-12-10)
### Fixed (5 changes)
@@ -1062,6 +1082,26 @@ entry.
- Change wording on the project remove fork page. !47878
+## 13.5.7 (2021-01-13)
+
+### Security (1 change)
+
+- Deny implicit flow for confidential apps.
+
+
+## 13.5.6 (2021-01-07)
+
+### Security (7 changes)
+
+- Forbid public cache for private repos.
+- Deny implicit flow for confidential apps.
+- Update NuGet regular expression to protect against ReDoS.
+- Fix regular expression backtracking issue in package name validation.
+- Upgrade GitLab Pages to 1.28.2.
+- Update trusted OAuth applications to set them as confidential.
+- Upgrade Workhorse to 8.51.2.
+
+
## 13.5.5 (2020-12-07)
### Security (10 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 1fabcd61c9c..7fb9791df63 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.7.4 \ No newline at end of file
+64625df11e8add7e64cce44a47984512e5f42d72
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index d6ef99820ff..44726955203 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-13.7.0
+13.8.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index d9a01d25342..04f6473099c 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.14.0
+13.15.0
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index 8aa8b5f68bd..8c20f999400 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.58.2
+8.59.0
diff --git a/Gemfile b/Gemfile
index 49d0841be3c..c7ed1cd4d71 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,9 +4,6 @@ gem 'rails', '~> 6.0.3.1'
gem 'bootsnap', '~> 1.4.6'
-# Improves copy-on-write performance for MRI
-gem 'nakayoshi_fork', '~> 0.0.4'
-
# Responders respond_to and respond_with
gem 'responders', '~> 3.0'
@@ -19,10 +16,10 @@ gem 'default_value_for', '~> 3.3.0'
gem 'pg', '~> 1.1'
gem 'rugged', '~> 0.28'
-gem 'grape-path-helpers', '~> 1.5'
+gem 'grape-path-helpers', '~> 1.6.1'
gem 'faraday', '~> 1.0'
-gem 'marginalia', '~> 1.9.0'
+gem 'marginalia', '~> 1.10.0'
# Authentication libraries
gem 'devise', '~> 4.7.2'
@@ -57,7 +54,7 @@ gem 'gssapi', group: :kerberos
# Spam and anti-bot protection
gem 'recaptcha', '~> 4.11', require: 'recaptcha/rails'
gem 'akismet', '~> 3.0'
-gem 'invisible_captcha', '~> 0.12.1'
+gem 'invisible_captcha', '~> 1.1.0'
# Two-factor authentication
gem 'devise-two-factor', '~> 3.1.0'
@@ -81,12 +78,10 @@ gem 'gpgme', '~> 2.0.19'
# GitLab fork with several improvements to original library. For full list of changes
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
gem 'gitlab_omniauth-ldap', '~> 2.1.1', require: 'omniauth-ldap'
-gem 'net-ldap'
+gem 'net-ldap', '~> 0.16.3'
# API
-# Locked at Grape v1.4.0 until https://github.com/ruby-grape/grape/pull/2088 is merged
-# Remove config/initializers/grape_patch.rb
-gem 'grape', '= 1.4.0'
+gem 'grape', '~> 1.5.1'
gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.6', require: 'rack/cors'
@@ -115,7 +110,7 @@ gem 'carrierwave', '~> 1.3'
gem 'mini_magick', '~> 4.10.1'
# for backups
-gem 'fog-aws', '~> 3.7'
+gem 'fog-aws', '~> 3.8'
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
# Also see config/initializers/fog_core_patch.rb.
gem 'fog-core', '= 2.1.0'
@@ -145,7 +140,7 @@ gem 'aws-sdk-s3', '~> 1'
gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
# Markdown and HTML processing
-gem 'html-pipeline', '~> 2.12'
+gem 'html-pipeline', '~> 2.13.2'
gem 'deckar01-task_list', '2.3.1'
gem 'gitlab-markup', '~> 1.7.1'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
@@ -163,7 +158,7 @@ gem 'asciidoctor-kroki', '~> 0.2.2', require: false
gem 'rouge', '~> 3.26.0'
gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 4.2.0'
-gem 'nokogiri', '~> 1.10.9'
+gem 'nokogiri', '~> 1.11.1'
gem 'escape_utils', '~> 1.1'
# Calendar rendering
@@ -184,15 +179,15 @@ group :unicorn do
end
group :puma do
- gem 'gitlab-puma', '~> 4.3.3.gitlab.2', require: false
- gem 'gitlab-puma_worker_killer', '~> 0.1.1.gitlab.1', require: false
+ gem 'puma', '~> 5.1.1', require: false
+ gem 'puma_worker_killer', '~> 0.3.1', require: false
end
# State machine
-gem 'state_machines-activerecord', '~> 0.6.0'
+gem 'state_machines-activerecord', '~> 0.8.0'
# Issue tags
-gem 'acts-as-taggable-on', '~> 6.0'
+gem 'acts-as-taggable-on', '~> 7.0'
# Background jobs
gem 'sidekiq', '~> 5.2.7'
@@ -242,7 +237,7 @@ gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false
gem 'hipchat', '~> 1.5.0'
# Jira integration
-gem 'jira-ruby', '~> 2.0.0'
+gem 'jira-ruby', '~> 2.1.4'
gem 'atlassian-jwt', '~> 0.2.0'
# Flowdock integration
@@ -255,7 +250,7 @@ gem 'slack-messenger', '~> 2.3.4'
gem 'hangouts-chat', '~> 0.0.5'
# Asana integration
-gem 'asana', '0.10.2'
+gem 'asana', '~> 0.10.3'
# FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1'
@@ -306,12 +301,12 @@ gem 'rack-attack', '~> 6.3.0'
gem 'sentry-raven', '~> 3.0'
# PostgreSQL query parsing
-gem 'gitlab-pg_query', '~> 1.3', require: 'pg_query'
+gem 'pg_query', '~> 1.3.0'
gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
-gem 'gitlab-labkit', '0.13.3'
+gem 'gitlab-labkit', '0.14.0'
# I18n
gem 'ruby_parser', '~> 3.15', require: false
@@ -331,6 +326,7 @@ gem 'snowplow-tracker', '~> 0.6.1'
# Metrics
group :metrics do
gem 'method_source', '~> 1.0', require: false
+ gem 'webrick', '~> 1.6.1', require: false
# Prometheus
gem 'prometheus-client-mmap', '~> 0.12.0'
@@ -353,14 +349,15 @@ end
group :development, :test do
gem 'deprecation_toolkit', '~> 1.5.1', require: false
gem 'bullet', '~> 6.1.0'
- gem 'pry-byebug', '~> 3.9.0', platform: :mri
+ gem 'gitlab-pry-byebug', platform: :mri, require: ['pry-byebug', 'pry-byebug/pry_remote_ext']
gem 'pry-rails', '~> 0.3.9'
+ gem 'pry-remote'
gem 'awesome_print', require: false
gem 'database_cleaner', '~> 1.7.0'
- gem 'factory_bot_rails', '~> 5.1.0'
- gem 'rspec-rails', '~> 4.0.0'
+ gem 'factory_bot_rails', '~> 6.1.0'
+ gem 'rspec-rails', '~> 4.0.1'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.11.0'
@@ -371,7 +368,7 @@ group :development, :test do
gem 'spring', '~> 2.1.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 5.3.0', require: false
+ gem 'gitlab-styles', '~> 6.0.0', require: false
gem 'scss_lint', '~> 0.59.0', require: false
gem 'haml_lint', '~> 0.36.0', require: false
@@ -409,7 +406,7 @@ group :test do
gem 'rspec_profiling', '~> 0.0.6'
gem 'rspec-parameterized', require: false
- gem 'capybara', '~> 3.33.0'
+ gem 'capybara', '~> 3.34.0'
gem 'capybara-screenshot', '~> 1.0.22'
gem 'selenium-webdriver', '~> 3.142'
@@ -465,7 +462,7 @@ group :ed25519 do
end
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 13.7.0.pre.rc1'
+gem 'gitaly', '~> 13.8.0.pre.rc2'
gem 'grpc', '~> 1.30.2'
@@ -478,7 +475,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.4'
+gem 'gitlab-experiment', '~> 0.4.5'
# Structured logging
gem 'lograge', '~> 0.5'
diff --git a/Gemfile.lock b/Gemfile.lock
index 1cd90080fd8..b370024b95b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -5,66 +5,66 @@ GEM
abstract_type (0.0.7)
acme-client (2.0.6)
faraday (>= 0.17, < 2.0.0)
- actioncable (6.0.3.3)
- actionpack (= 6.0.3.3)
+ actioncable (6.0.3.4)
+ actionpack (= 6.0.3.4)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.3.3)
- actionpack (= 6.0.3.3)
- activejob (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- activestorage (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ actionmailbox (6.0.3.4)
+ actionpack (= 6.0.3.4)
+ activejob (= 6.0.3.4)
+ activerecord (= 6.0.3.4)
+ activestorage (= 6.0.3.4)
+ activesupport (= 6.0.3.4)
mail (>= 2.7.1)
- actionmailer (6.0.3.3)
- actionpack (= 6.0.3.3)
- actionview (= 6.0.3.3)
- activejob (= 6.0.3.3)
+ actionmailer (6.0.3.4)
+ actionpack (= 6.0.3.4)
+ actionview (= 6.0.3.4)
+ activejob (= 6.0.3.4)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.3.3)
- actionview (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ actionpack (6.0.3.4)
+ actionview (= 6.0.3.4)
+ activesupport (= 6.0.3.4)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.0.3.3)
- actionpack (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- activestorage (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ actiontext (6.0.3.4)
+ actionpack (= 6.0.3.4)
+ activerecord (= 6.0.3.4)
+ activestorage (= 6.0.3.4)
+ activesupport (= 6.0.3.4)
nokogiri (>= 1.8.5)
- actionview (6.0.3.3)
- activesupport (= 6.0.3.3)
+ actionview (6.0.3.4)
+ activesupport (= 6.0.3.4)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.0.3.3)
- activesupport (= 6.0.3.3)
+ activejob (6.0.3.4)
+ activesupport (= 6.0.3.4)
globalid (>= 0.3.6)
- activemodel (6.0.3.3)
- activesupport (= 6.0.3.3)
- activerecord (6.0.3.3)
- activemodel (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ activemodel (6.0.3.4)
+ activesupport (= 6.0.3.4)
+ activerecord (6.0.3.4)
+ activemodel (= 6.0.3.4)
+ activesupport (= 6.0.3.4)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
- activestorage (6.0.3.3)
- actionpack (= 6.0.3.3)
- activejob (= 6.0.3.3)
- activerecord (= 6.0.3.3)
+ activestorage (6.0.3.4)
+ actionpack (= 6.0.3.4)
+ activejob (= 6.0.3.4)
+ activerecord (= 6.0.3.4)
marcel (~> 0.3.1)
- activesupport (6.0.3.3)
+ activesupport (6.0.3.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
- acts-as-taggable-on (6.5.0)
- activerecord (>= 5.0, < 6.1)
+ acts-as-taggable-on (7.0.0)
+ activerecord (>= 5.0, < 6.2)
adamantium (0.2.0)
ice_nine (~> 0.11.0)
memoizable (~> 0.4.0)
@@ -76,7 +76,7 @@ GEM
apollo_upload_server (2.0.2)
graphql (>= 1.8)
rails (>= 4.2)
- asana (0.10.2)
+ asana (0.10.3)
faraday (~> 1.0)
faraday_middleware (~> 1.0)
faraday_middleware-multi_json (~> 0.0)
@@ -115,13 +115,14 @@ GEM
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.1)
aws-eventstream (~> 1, >= 1.0.2)
- azure-storage-blob (2.0.0)
+ azure-storage-blob (2.0.1)
azure-storage-common (~> 2.0)
- nokogiri (~> 1.10.4)
- azure-storage-common (2.0.1)
+ nokogiri (~> 1.11.0.rc2)
+ azure-storage-common (2.0.2)
faraday (~> 1.0)
faraday_middleware (~> 1.0.0.rc1)
- nokogiri (~> 1.10.4)
+ net-http-persistent (~> 4.0)
+ nokogiri (~> 1.11.0.rc2)
babosa (1.0.2)
base32 (0.3.2)
batch-loader (1.4.0)
@@ -151,7 +152,7 @@ GEM
bundler (>= 1.2.0, < 3)
thor (~> 0.18)
byebug (11.1.3)
- capybara (3.33.0)
+ capybara (3.34.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
@@ -228,17 +229,16 @@ GEM
activerecord (>= 3.2.0, < 6.1)
deprecation_toolkit (1.5.1)
activesupport (>= 4.2)
- derailed_benchmarks (1.7.0)
+ derailed_benchmarks (1.8.1)
benchmark-ips (~> 2)
get_process_mem (~> 0)
heapy (~> 0)
memory_profiler (~> 0)
- mini_histogram (~> 0)
+ mini_histogram (>= 0.2.1)
rack (>= 1)
rake (> 10, < 14)
ruby-statistics (>= 2.1)
thor (>= 0.19, < 2)
- unicode_plot (>= 0.0.4, < 1.0.0)
device_detector (1.0.0)
devise (4.7.3)
bcrypt (~> 3.0)
@@ -252,7 +252,7 @@ GEM
devise (~> 4.0)
railties (< 6.1)
rotp (~> 2.0)
- diff-lcs (1.3)
+ diff-lcs (1.4.4)
diff_match_patch (0.1.0)
diffy (3.3.0)
discordrb-webhooks-blackst0ne (3.3.0)
@@ -265,21 +265,19 @@ GEM
doorkeeper-openid_connect (1.7.4)
doorkeeper (>= 5.2, < 5.5)
json-jwt (>= 1.11.0)
- dry-configurable (0.11.5)
+ dry-configurable (0.12.0)
concurrent-ruby (~> 1.0)
- dry-core (~> 0.4, >= 0.4.7)
- dry-equalizer (~> 0.2)
+ dry-core (~> 0.5, >= 0.5.0)
dry-container (0.7.2)
concurrent-ruby (~> 1.0)
dry-configurable (~> 0.1, >= 0.1.3)
- dry-core (0.4.9)
+ dry-core (0.5.0)
concurrent-ruby (~> 1.0)
dry-equalizer (0.3.0)
dry-inflector (0.2.0)
- dry-logic (1.0.6)
+ dry-logic (1.1.0)
concurrent-ruby (~> 1.0)
- dry-core (~> 0.2)
- dry-equalizer (~> 0.2)
+ dry-core (~> 0.5, >= 0.5)
dry-types (1.4.0)
concurrent-ruby (~> 1.0)
dry-container (~> 0.3)
@@ -309,7 +307,6 @@ GEM
launchy (~> 2.1)
mail (~> 2.7)
encryptor (3.0.0)
- enumerable-statistics (2.0.1)
equalizer (0.0.11)
erubi (1.9.0)
escape_utils (1.2.1)
@@ -321,11 +318,11 @@ GEM
expression_parser (0.9.0)
extended-markdown-filter (0.6.0)
html-pipeline (~> 2.0)
- factory_bot (5.1.0)
- activesupport (>= 4.2.0)
- factory_bot_rails (5.1.0)
- factory_bot (~> 5.1.0)
- railties (>= 4.2.0)
+ factory_bot (6.1.0)
+ activesupport (>= 5.0.0)
+ factory_bot_rails (6.1.0)
+ factory_bot (~> 6.1.0)
+ railties (>= 5.0.0)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.7)
@@ -363,7 +360,7 @@ GEM
fog-json
ipaddress (~> 0.8)
xml-simple (~> 1.1)
- fog-aws (3.7.0)
+ fog-aws (3.8.0)
fog-core (~> 2.1)
fog-json (~> 1.1)
fog-xml (~> 0.1)
@@ -420,12 +417,12 @@ GEM
rails (>= 3.2.0)
git (1.7.0)
rchardet (~> 1.8)
- gitaly (13.7.0.pre.rc1)
+ gitaly (13.8.0.pre.rc2)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-experiment (0.4.4)
+ gitlab-experiment (0.4.5)
activesupport (>= 3.0)
scientist (~> 1.5, >= 1.5.0)
gitlab-fog-azure-rm (1.0.0)
@@ -435,9 +432,9 @@ GEM
fog-json (~> 1.2.0)
mime-types
ms_rest_azure (~> 0.12.0)
- gitlab-labkit (0.13.3)
- actionpack (>= 5.0.0, < 6.1.0)
- activesupport (>= 5.0.0, < 6.1.0)
+ gitlab-labkit (0.14.0)
+ actionpack (>= 5.0.0, < 7.0.0)
+ activesupport (>= 5.0.0, < 7.0.0)
gitlab-pg_query (~> 1.3)
grpc (~> 1.19)
jaeger-client (~> 1.1)
@@ -447,19 +444,17 @@ GEM
gitlab-mail_room (0.0.8)
gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1)
- gitlab-pg_query (1.3.0)
- gitlab-puma (4.3.5.gitlab.3)
- nio4r (~> 2.0)
- gitlab-puma_worker_killer (0.1.1.gitlab.1)
- get_process_mem (~> 0.2)
- gitlab-puma (>= 2.7, < 5)
+ gitlab-pg_query (1.3.1)
+ gitlab-pry-byebug (3.9.0)
+ byebug (~> 11.0)
+ pry (~> 0.13.0)
gitlab-sidekiq-fetcher (0.5.2)
sidekiq (~> 5)
- gitlab-styles (5.3.0)
- rubocop (~> 0.89.1)
- rubocop-gitlab-security (~> 0.1.0)
- rubocop-performance (~> 1.8.1)
- rubocop-rails (~> 2.8)
+ gitlab-styles (6.0.0)
+ rubocop (~> 0.91.1)
+ rubocop-gitlab-security (~> 0.1.1)
+ rubocop-performance (~> 1.9.2)
+ rubocop-rails (~> 2.9)
rubocop-rspec (~> 1.44)
gitlab_chronic_duration (0.10.6.2)
numerizer (~> 0.2)
@@ -497,7 +492,7 @@ GEM
signet (~> 0.14)
gpgme (2.0.20)
mini_portile2 (~> 2.3)
- grape (1.4.0)
+ grape (1.5.1)
activesupport
builder
dry-types (>= 1.1)
@@ -507,10 +502,11 @@ GEM
grape-entity (0.7.1)
activesupport (>= 4.0)
multi_json (>= 1.3.2)
- grape-path-helpers (1.5.0)
+ grape-path-helpers (1.6.1)
activesupport
grape (~> 1.3)
rake (> 12)
+ ruby2_keywords (~> 0.0.2)
grape_logging (1.8.3)
grape
rack
@@ -573,11 +569,12 @@ GEM
hashie (>= 3.0)
health_check (3.0.0)
railties (>= 5.0)
- heapy (0.1.4)
+ heapy (0.2.0)
+ thor
hipchat (1.5.2)
httparty
mimemagic
- html-pipeline (2.12.2)
+ html-pipeline (2.13.2)
activesupport (>= 2)
nokogiri (>= 1.4)
html2text (0.2.0)
@@ -598,18 +595,18 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.8.5)
+ i18n (1.8.7)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
ice_nine (0.11.2)
- invisible_captcha (0.12.1)
- rails (>= 3.2.0)
+ invisible_captcha (1.1.0)
+ rails (>= 4.2)
ipaddress (0.8.3)
jaeger-client (1.1.0)
opentracing (~> 0.3)
thrift
- jira-ruby (2.0.0)
+ jira-ruby (2.1.4)
activesupport
atlassian-jwt
multipart-post
@@ -686,7 +683,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.7.0)
+ loofah (2.8.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
@@ -695,7 +692,7 @@ GEM
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
- marginalia (1.9.0)
+ marginalia (1.10.0)
actionpack (>= 2.3)
activerecord (>= 2.3)
memoist (0.16.2)
@@ -707,10 +704,10 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2020.0512)
mimemagic (0.3.5)
- mini_histogram (0.1.3)
+ mini_histogram (0.3.1)
mini_magick (4.10.1)
mini_mime (1.0.2)
- mini_portile2 (2.4.0)
+ mini_portile2 (2.5.0)
minitest (5.11.3)
ms_rest (0.7.6)
concurrent-ruby (~> 1.0)
@@ -730,17 +727,19 @@ GEM
ruby2_keywords (~> 0.0.1)
mustermann-grape (1.0.1)
mustermann (>= 1.0.0)
- nakayoshi_fork (0.0.4)
nap (1.1.0)
nenv (0.3.0)
- net-ldap (0.16.2)
+ net-http-persistent (4.0.0)
+ connection_pool (~> 2.2)
+ net-ldap (0.16.3)
net-ntp (2.1.3)
net-ssh (6.0.0)
netrc (0.11.0)
nio4r (2.5.4)
no_proxy_fix (0.1.2)
- nokogiri (1.10.10)
- mini_portile2 (~> 2.4.0)
+ nokogiri (1.11.1)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
nokogumbo (2.0.2)
nokogiri (~> 1.8, >= 1.8.4)
notiffany (0.1.3)
@@ -840,13 +839,14 @@ GEM
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (1.1.1)
- parallel (1.19.2)
- parser (2.7.2.0)
+ parallel (1.20.1)
+ parser (3.0.0.0)
ast (~> 2.4.1)
parslet (1.8.2)
peek (1.1.0)
railties (>= 4.0.0)
pg (1.2.3)
+ pg_query (1.3.0)
png_quantizator (0.2.1)
po_to_json (1.0.1)
json (>= 1.6.0)
@@ -866,14 +866,20 @@ GEM
pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
- pry-byebug (3.9.0)
- byebug (~> 11.0)
- pry (~> 0.13.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
+ pry-remote (0.1.8)
+ pry (~> 0.9)
+ slop (~> 3.0)
public_suffix (4.0.6)
+ puma (5.1.1)
+ nio4r (~> 2.0)
+ puma_worker_killer (0.3.1)
+ get_process_mem (~> 0.2)
+ puma (>= 2.7)
pyu-ruby-sasl (0.0.3.3)
raabro (1.1.6)
+ racc (1.5.2)
rack (2.2.3)
rack-accept (0.4.5)
rack (>= 0.4)
@@ -894,20 +900,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.2)
- rails (6.0.3.3)
- actioncable (= 6.0.3.3)
- actionmailbox (= 6.0.3.3)
- actionmailer (= 6.0.3.3)
- actionpack (= 6.0.3.3)
- actiontext (= 6.0.3.3)
- actionview (= 6.0.3.3)
- activejob (= 6.0.3.3)
- activemodel (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- activestorage (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ rails (6.0.3.4)
+ actioncable (= 6.0.3.4)
+ actionmailbox (= 6.0.3.4)
+ actionmailer (= 6.0.3.4)
+ actionpack (= 6.0.3.4)
+ actiontext (= 6.0.3.4)
+ actionview (= 6.0.3.4)
+ activejob (= 6.0.3.4)
+ activemodel (= 6.0.3.4)
+ activerecord (= 6.0.3.4)
+ activestorage (= 6.0.3.4)
+ activesupport (= 6.0.3.4)
bundler (>= 1.3.0)
- railties (= 6.0.3.3)
+ railties (= 6.0.3.4)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -921,15 +927,15 @@ GEM
rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 7)
- railties (6.0.3.3)
- actionpack (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ railties (6.0.3.4)
+ actionpack (= 6.0.3.4)
+ activesupport (= 6.0.3.4)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
raindrops (0.19.1)
- rake (13.0.1)
+ rake (13.0.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
@@ -989,25 +995,25 @@ GEM
chunky_png
rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2)
- rspec (3.9.0)
- rspec-core (~> 3.9.0)
- rspec-expectations (~> 3.9.0)
- rspec-mocks (~> 3.9.0)
- rspec-core (3.9.1)
- rspec-support (~> 3.9.1)
- rspec-expectations (3.9.1)
+ rspec (3.10.0)
+ rspec-core (~> 3.10.0)
+ rspec-expectations (~> 3.10.0)
+ rspec-mocks (~> 3.10.0)
+ rspec-core (3.10.0)
+ rspec-support (~> 3.10.0)
+ rspec-expectations (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.9.0)
- rspec-mocks (3.9.1)
+ rspec-support (~> 3.10.0)
+ rspec-mocks (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.9.0)
+ rspec-support (~> 3.10.0)
rspec-parameterized (0.4.2)
binding_ninja (>= 0.2.3)
parser
proc_to_ast
rspec (>= 2.13, < 4)
unparser
- rspec-rails (4.0.0)
+ rspec-rails (4.0.1)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
@@ -1017,7 +1023,7 @@ GEM
rspec-support (~> 3.9)
rspec-retry (0.6.1)
rspec-core (> 3.3)
- rspec-support (3.9.2)
+ rspec-support (3.10.0)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
rspec_profiling (0.0.6)
@@ -1025,26 +1031,26 @@ GEM
pg
rails
sqlite3
- rubocop (0.89.1)
+ rubocop (0.91.1)
parallel (~> 1.10)
parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
- rubocop-ast (>= 0.3.0, < 1.0)
+ rubocop-ast (>= 0.4.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.8.0)
parser (>= 2.7.1.5)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
- rubocop-performance (1.8.1)
- rubocop (>= 0.87.0)
+ rubocop-performance (1.9.2)
+ rubocop (>= 0.90.0, < 2.0)
rubocop-ast (>= 0.4.0)
- rubocop-rails (2.8.1)
+ rubocop-rails (2.9.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.87.0)
+ rubocop (>= 0.90.0, < 2.0)
rubocop-rspec (1.44.1)
rubocop (~> 0.87)
rubocop-ast (>= 0.7.1)
@@ -1053,7 +1059,7 @@ GEM
ruby-fogbugz (0.2.1)
crack (~> 0.4)
ruby-prof (1.3.1)
- ruby-progressbar (1.10.1)
+ ruby-progressbar (1.11.0)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
ruby-statistics (2.1.2)
@@ -1127,6 +1133,7 @@ GEM
simplecov-html (0.12.2)
sixarm_ruby_unaccent (1.2.0)
slack-messenger (2.3.4)
+ slop (3.6.0)
snowplow-tracker (0.6.1)
contracts (~> 0.7, <= 0.11)
spring (2.1.1)
@@ -1143,12 +1150,12 @@ GEM
sshkey (2.0.0)
stackprof (0.2.15)
state_machines (0.5.0)
- state_machines-activemodel (0.7.1)
- activemodel (>= 4.1)
+ state_machines-activemodel (0.8.0)
+ activemodel (>= 5.1)
state_machines (>= 0.5.0)
- state_machines-activerecord (0.6.0)
- activerecord (>= 4.1)
- state_machines-activemodel (>= 0.5.0)
+ state_machines-activerecord (0.8.0)
+ activerecord (>= 5.1)
+ state_machines-activemodel (>= 0.8.0)
swd (1.1.2)
activesupport (>= 3)
attr_required (>= 0.0.5)
@@ -1185,7 +1192,7 @@ GEM
truncato (0.7.11)
htmlentities (~> 4.3.1)
nokogiri (>= 1.7.0, <= 2.0)
- tzinfo (1.2.8)
+ tzinfo (1.2.9)
thread_safe (~> 0.1)
u2f (0.2.1)
uber (0.1.0)
@@ -1193,8 +1200,6 @@ GEM
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
- unicode_plot (0.0.4)
- enumerable-statistics (>= 2.0.1)
unicode_utils (1.4.0)
unicorn (5.5.5)
kgio (~> 2.6)
@@ -1247,6 +1252,7 @@ GEM
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
+ webrick (1.6.1)
websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
@@ -1259,7 +1265,7 @@ GEM
xpath (3.2.0)
nokogiri (~> 1.8)
yajl-ruby (1.4.1)
- zeitwerk (2.4.1)
+ zeitwerk (2.4.2)
PLATFORMS
ruby
@@ -1268,11 +1274,11 @@ DEPENDENCIES
RedCloth (~> 4.3.2)
acme-client (~> 2.0, >= 2.0.6)
activerecord-explain-analyze (~> 0.1)
- acts-as-taggable-on (~> 6.0)
+ acts-as-taggable-on (~> 7.0)
addressable (~> 2.7)
akismet (~> 3.0)
apollo_upload_server (~> 2.0.2)
- asana (= 0.10.2)
+ asana (~> 0.10.3)
asciidoctor (~> 2.0.10)
asciidoctor-include-ext (~> 0.3.1)
asciidoctor-kroki (~> 0.2.2)
@@ -1297,7 +1303,7 @@ DEPENDENCIES
browser (~> 4.2)
bullet (~> 6.1.0)
bundler-audit (~> 0.6.1)
- capybara (~> 3.33.0)
+ capybara (~> 3.34.0)
capybara-screenshot (~> 1.0.22)
carrierwave (~> 1.3)
charlock_holmes (~> 0.7.7)
@@ -1329,7 +1335,7 @@ DEPENDENCIES
email_spec (~> 2.2.0)
erubi (~> 1.9.0)
escape_utils (~> 1.1)
- factory_bot_rails (~> 5.1.0)
+ factory_bot_rails (~> 6.1.0)
faraday (~> 1.0)
faraday_middleware-aws-sigv4 (~> 0.3.0)
fast_blank
@@ -1339,7 +1345,7 @@ DEPENDENCIES
flipper-active_support_cache_store (~> 0.17.1)
flowdock (~> 0.7)
fog-aliyun (~> 0.3)
- fog-aws (~> 3.7)
+ fog-aws (~> 3.8)
fog-core (= 2.1.0)
fog-google (~> 1.12)
fog-local (~> 0.6)
@@ -1351,30 +1357,28 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 13.7.0.pre.rc1)
+ gitaly (~> 13.8.0.pre.rc2)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-experiment (~> 0.4.4)
+ gitlab-experiment (~> 0.4.5)
gitlab-fog-azure-rm (~> 1.0)
- gitlab-labkit (= 0.13.3)
+ gitlab-labkit (= 0.14.0)
gitlab-license (~> 1.0)
gitlab-mail_room (~> 0.0.8)
gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1)
- gitlab-pg_query (~> 1.3)
- gitlab-puma (~> 4.3.3.gitlab.2)
- gitlab-puma_worker_killer (~> 0.1.1.gitlab.1)
+ gitlab-pry-byebug
gitlab-sidekiq-fetcher (= 0.5.2)
- gitlab-styles (~> 5.3.0)
+ gitlab-styles (~> 6.0.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
google-api-client (~> 0.33)
google-protobuf (~> 3.12)
gpgme (~> 2.0.19)
- grape (= 1.4.0)
+ grape (~> 1.5.1)
grape-entity (~> 0.7.1)
- grape-path-helpers (~> 1.5)
+ grape-path-helpers (~> 1.6.1)
grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10)
graphlient (~> 0.4.0)
@@ -1390,13 +1394,13 @@ DEPENDENCIES
hashie-forbidden_attributes
health_check (~> 3.0)
hipchat (~> 1.5.0)
- html-pipeline (~> 2.12)
+ html-pipeline (~> 2.13.2)
html2text
httparty (~> 0.16.4)
icalendar
- invisible_captcha (~> 0.12.1)
+ invisible_captcha (~> 1.1.0)
ipaddress (~> 0.8.3)
- jira-ruby (~> 2.0.0)
+ jira-ruby (~> 2.1.4)
js_regex (~> 3.4)
json (~> 2.3.0)
json-schema (~> 2.8.0)
@@ -1414,18 +1418,17 @@ DEPENDENCIES
loofah (~> 2.2)
lru_redux
mail (= 2.7.1)
- marginalia (~> 1.9.0)
+ marginalia (~> 1.10.0)
memory_profiler (~> 0.9)
method_source (~> 1.0)
mimemagic (~> 0.3.2)
mini_magick (~> 4.10.1)
minitest (~> 5.11.0)
multi_json (~> 1.14.1)
- nakayoshi_fork (~> 0.0.4)
- net-ldap
+ net-ldap (~> 0.16.3)
net-ntp
net-ssh (~> 6.0)
- nokogiri (~> 1.10.9)
+ nokogiri (~> 1.11.1)
oauth2 (~> 1.4)
octokit (~> 4.15)
oj (~> 3.10.6)
@@ -1451,11 +1454,14 @@ DEPENDENCIES
parallel (~> 1.19)
peek (~> 1.1)
pg (~> 1.1)
+ pg_query (~> 1.3.0)
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 0.12.0)
- pry-byebug (~> 3.9.0)
pry-rails (~> 0.3.9)
+ pry-remote
+ puma (~> 5.1.1)
+ puma_worker_killer (~> 0.3.1)
rack (~> 2.2.3)
rack-attack (~> 6.3.0)
rack-cors (~> 1.0.6)
@@ -1481,7 +1487,7 @@ DEPENDENCIES
rouge (~> 3.26.0)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
- rspec-rails (~> 4.0.0)
+ rspec-rails (~> 4.0.1)
rspec-retry (~> 0.6.1)
rspec_junit_formatter
rspec_profiling (~> 0.0.6)
@@ -1511,7 +1517,7 @@ DEPENDENCIES
sprockets (~> 3.7.0)
sshkey (~> 2.0)
stackprof (~> 0.2.15)
- state_machines-activerecord (~> 0.6.0)
+ state_machines-activerecord (~> 0.8.0)
sys-filesystem (~> 1.1.6)
terser (= 1.0.2)
test-prof (~> 0.12.0)
@@ -1530,6 +1536,7 @@ DEPENDENCIES
vmstat (~> 2.3.0)
webauthn (~> 2.3)
webmock (~> 3.9.1)
+ webrick (~> 1.6.1)
wikicloth (= 0.8.1)
yajl-ruby (~> 1.4.1)
diff --git a/Guardfile b/Guardfile
index baaa52bd204..1d9ec406c1d 100644
--- a/Guardfile
+++ b/Guardfile
@@ -6,7 +6,7 @@ require "guard/rspec/dsl"
cmd = ENV['GUARD_CMD'] || (ENV['SPRING'] ? 'spring rspec' : 'bundle exec rspec')
-directories %w(app ee lib spec)
+directories %w(app ee lib rubocop tooling spec)
rspec_context_for = proc do |context_path|
OpenStruct.new(to_s: "spec").tap do |rspec|
@@ -42,6 +42,8 @@ guard_setup = proc do |context_path|
# Ruby files
watch(%r{^#{context_path}(lib/.+)\.rb$}) { |m| rspec.spec.call(m[1]) }
+ watch(%r{^#{context_path}(rubocop/.+)\.rb$}) { |m| rspec.spec.call(m[1]) }
+ watch(%r{^#{context_path}(tooling/.+)\.rb$}) { |m| rspec.spec.call(m[1]) }
# Rails files
rails = rails_context_for.call(context_path, %w(erb haml slim))
diff --git a/app/assets/images/board-intro.svg b/app/assets/images/board-intro.svg
new file mode 100644
index 00000000000..8f04077d598
--- /dev/null
+++ b/app/assets/images/board-intro.svg
@@ -0,0 +1 @@
+<svg width="566" height="213" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 .5h166c2.467 0 4.5 2.084 4.5 4.695v202.61c0 2.611-2.033 4.695-4.5 4.695H5c-2.467 0-4.5-2.084-4.5-4.695V5.195C.5 2.584 2.533.5 5 .5z" fill="#F2F2F2" stroke="#DFDFDF"/><g filter="url(#filter0_i)"><path d="M366 0H200c-2.761 0-5 2.326-5 5.195v202.61c0 2.869 2.239 5.195 5 5.195h166c2.761 0 5-2.326 5-5.195V5.195C371 2.325 368.761 0 366 0z" fill="#F2F2F2"/></g><path d="M200 .5h166c2.467 0 4.5 2.084 4.5 4.695v202.61c0 2.611-2.033 4.695-4.5 4.695H200c-2.467 0-4.5-2.084-4.5-4.695V5.195C195.5 2.584 197.533.5 200 .5z" stroke="#DFDFDF"/><path d="M395 .5h166c2.467 0 4.5 2.084 4.5 4.695v202.61c0 2.611-2.033 4.695-4.5 4.695H395c-2.467 0-4.5-2.084-4.5-4.695V5.195C390.5 2.584 392.533.5 395 .5z" fill="#F2F2F2" stroke="#DFDFDF"/><rect x="210" y="15.585" width="40" height="13.507" rx="6.754" fill="#D9534F"/><path d="M17.73 20.826c0-.456.047-.897.14-1.323.103-.427.261-.805.476-1.135.215-.34.495-.606.84-.8.346-.204.765-.306 1.26-.306s.915.102 1.26.306c.346.194.625.46.84.8.215.33.369.708.462 1.135.103.426.154.867.154 1.323 0 .437-.051.863-.154 1.28a3.397 3.397 0 01-.462 1.106c-.215.33-.494.596-.84.8-.345.194-.765.29-1.26.29s-.915-.096-1.26-.29a2.507 2.507 0 01-.84-.8 3.64 3.64 0 01-.476-1.106 5.845 5.845 0 01-.14-1.28zm-2.198 0c0 .757.112 1.465.336 2.124.224.65.546 1.217.966 1.702.42.485.933.868 1.54 1.149.616.272 1.307.407 2.072.407.775 0 1.465-.135 2.072-.407a4.528 4.528 0 001.54-1.15c.42-.484.742-1.051.966-1.701a6.56 6.56 0 00.336-2.124c0-.776-.112-1.493-.336-2.153a5.228 5.228 0 00-.966-1.745 4.444 4.444 0 00-1.54-1.164c-.607-.281-1.297-.422-2.072-.422-.765 0-1.456.14-2.072.422-.607.281-1.12.67-1.54 1.164a5.228 5.228 0 00-.966 1.745 6.655 6.655 0 00-.336 2.153zm14.775 3.797c-.318 0-.588-.068-.812-.204a1.694 1.694 0 01-.546-.524 2.674 2.674 0 01-.294-.77 4.761 4.761 0 010-1.79c.056-.29.149-.548.28-.77.14-.224.317-.403.532-.539.224-.145.499-.218.826-.218.317 0 .583.073.798.218.224.136.406.32.546.553.14.223.238.48.294.77.065.292.098.588.098.888 0 .3-.028.597-.084.888-.056.29-.154.547-.294.77-.131.214-.308.388-.532.524-.215.136-.486.204-.812.204zm-3.654-6.168V28.61h1.988v-3.564h.028c.242.368.55.65.924.843.382.184.798.277 1.246.277.532 0 .994-.107 1.386-.32.401-.214.732-.5.994-.859.27-.358.471-.77.602-1.236.13-.465.196-.95.196-1.455 0-.533-.066-1.042-.196-1.527a3.803 3.803 0 00-.602-1.295 3.065 3.065 0 00-1.022-.887c-.411-.223-.901-.334-1.47-.334-.448 0-.859.092-1.232.276-.374.184-.682.48-.924.887h-.028v-.96h-1.89zm13.43 2.953H36.85c.01-.145.038-.31.084-.495.056-.184.145-.358.266-.523.13-.165.299-.3.504-.407.215-.117.48-.175.798-.175.486 0 .845.136 1.078.407.243.272.41.67.504 1.193zm-3.234 1.31h5.222a5.512 5.512 0 00-.14-1.674 4.097 4.097 0 00-.644-1.425 3.121 3.121 0 00-1.12-.99c-.457-.252-.994-.378-1.61-.378-.55 0-1.054.102-1.512.306a3.528 3.528 0 00-1.162.844 3.63 3.63 0 00-.756 1.25 4.539 4.539 0 00-.266 1.572c0 .582.084 1.115.252 1.6.178.485.425.902.742 1.25.318.35.705.621 1.162.815.458.184.97.277 1.54.277.822 0 1.522-.194 2.1-.582.579-.388 1.008-1.033 1.288-1.935h-1.75c-.065.233-.242.456-.532.67-.29.203-.634.305-1.036.305-.56 0-.99-.15-1.288-.451-.298-.3-.462-.786-.49-1.455zm6.401-4.263v7.52h1.988v-3.942c0-.766.122-1.314.364-1.643.243-.34.635-.51 1.176-.51.476 0 .808.156.994.466.187.3.28.762.28 1.382v4.248h1.988V21.35a5.85 5.85 0 00-.126-1.266 2.34 2.34 0 00-.406-.974 1.868 1.868 0 00-.812-.626c-.336-.155-.77-.233-1.302-.233-.42 0-.83.102-1.232.306-.401.194-.728.51-.98.946h-.042v-1.048h-1.89z" fill="#2E2E2E"/><g filter="url(#filter1_d)"><path d="M352 46.756H214c-2.209 0-4 1.86-4 4.156v30.132c0 2.295 1.791 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156V50.912c0-2.295-1.791-4.156-4-4.156z" fill="#fff"/><path d="M352 46.756H214c-2.209 0-4 1.86-4 4.156v30.132c0 2.295 1.791 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156V50.912c0-2.295-1.791-4.156-4-4.156z" stroke="#D6D6D6"/></g><path d="M332 57.146H222v6.234h110v-6.234zM300 68.576h-78v6.234h78v-6.234z" fill="#D8D8D8"/><g filter="url(#filter2_d)"><path d="M157 98.707H19c-2.21 0-4 1.861-4 4.156v30.132c0 2.295 1.79 4.156 4 4.156h138c2.209 0 4-1.861 4-4.156v-30.132c0-2.295-1.791-4.156-4-4.156z" fill="#fff"/><path d="M157 98.707H19c-2.21 0-4 1.861-4 4.156v30.132c0 2.295 1.79 4.156 4 4.156h138c2.209 0 4-1.861 4-4.156v-30.132c0-2.295-1.791-4.156-4-4.156z" stroke="#D6D6D6"/></g><path d="M137 109.098H27v6.234h110v-6.234zM105 120.527H27v6.234h78v-6.234z" fill="#D8D8D8"/><g filter="url(#filter3_d)"><path d="M352 96.63H214c-2.209 0-4 1.86-4 4.155v30.132c0 2.295 1.791 4.156 4 4.156h138c2.209 0 4-1.861 4-4.156v-30.132c0-2.295-1.791-4.156-4-4.156z" fill="#fff"/><path d="M352 96.63H214c-2.209 0-4 1.86-4 4.155v30.132c0 2.295 1.791 4.156 4 4.156h138c2.209 0 4-1.861 4-4.156v-30.132c0-2.295-1.791-4.156-4-4.156z" stroke="#D6D6D6"/></g><path d="M316 107.02h-94v6.234h94v-6.234zM292 118.449h-70v6.234h70v-6.234z" fill="#D8D8D8"/><g filter="url(#filter4_d)"><path d="M157 46.756H19c-2.21 0-4 1.86-4 4.156v30.132c0 2.295 1.79 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156V50.912c0-2.295-1.791-4.156-4-4.156z" fill="#fff"/><path d="M157 46.756H19c-2.21 0-4 1.86-4 4.156v30.132c0 2.295 1.79 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156V50.912c0-2.295-1.791-4.156-4-4.156z" stroke="#D6D6D6"/></g><path d="M121 57.146H27v6.234h94v-6.234zM97 68.576H27v6.234h70v-6.234z" fill="#D8D8D8"/><g filter="url(#filter5_d)"><path d="M157 148.581H19c-2.21 0-4 1.86-4 4.156v30.131c0 2.296 1.79 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156v-30.131c0-2.296-1.791-4.156-4-4.156z" fill="#fff"/><path d="M157 148.581H19c-2.21 0-4 1.86-4 4.156v30.131c0 2.296 1.79 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156v-30.131c0-2.296-1.791-4.156-4-4.156z" stroke="#D6D6D6"/></g><path d="M145 158.971H27v6.234h118v-6.234zM121 170.4H27v6.234h94V170.4z" fill="#D8D8D8"/><path d="M547 46.756H409c-2.209 0-4 1.86-4 4.156v30.132c0 2.295 1.791 4.156 4 4.156h138c2.209 0 4-1.86 4-4.156V50.912c0-2.295-1.791-4.156-4-4.156z" fill="#fff" stroke="#D6D6D6" stroke-dasharray="4 2"/><path d="M414.63 19.08h2.128a4.299 4.299 0 00-.476-1.6 3.726 3.726 0 00-.966-1.163 4.003 4.003 0 00-1.316-.728 4.796 4.796 0 00-1.554-.247c-.765 0-1.456.14-2.072.422-.607.281-1.12.67-1.54 1.164a5.228 5.228 0 00-.966 1.745 6.655 6.655 0 00-.336 2.153c0 .757.112 1.465.336 2.124.224.65.546 1.217.966 1.702.42.485.933.868 1.54 1.149.616.272 1.307.407 2.072.407.616 0 1.181-.097 1.694-.29a3.909 3.909 0 001.344-.844c.383-.369.691-.815.924-1.339.233-.523.378-1.11.434-1.76h-2.128c-.084.699-.317 1.261-.7 1.688-.373.427-.896.64-1.568.64-.495 0-.915-.097-1.26-.291a2.512 2.512 0 01-.84-.8 3.64 3.64 0 01-.476-1.106 5.863 5.863 0 01-.14-1.28c0-.456.047-.897.14-1.323.103-.427.261-.805.476-1.135.215-.34.495-.606.84-.8.345-.204.765-.306 1.26-.306.271 0 .527.049.77.146.252.087.476.213.672.378.196.165.359.359.49.582.131.213.215.45.252.713zm3.559-3.49v10.386h1.988V15.59h-1.988zm5.317 6.633c0-.3.028-.597.084-.888.056-.29.15-.548.28-.77a1.64 1.64 0 01.546-.539c.224-.145.504-.218.84-.218.336 0 .616.073.84.218.234.136.416.315.546.538.14.223.238.48.294.771a4.684 4.684 0 010 1.775 2.387 2.387 0 01-.294.77c-.13.224-.312.403-.546.54-.224.135-.504.203-.84.203-.336 0-.616-.068-.84-.204a1.64 1.64 0 01-.546-.538 2.62 2.62 0 01-.28-.771 4.685 4.685 0 01-.084-.887zm-1.988 0c0 .6.089 1.144.266 1.629.178.485.43.902.756 1.25.327.34.719.602 1.176.786.458.184.971.277 1.54.277.57 0 1.083-.092 1.54-.277a3.307 3.307 0 001.19-.785c.327-.35.579-.766.756-1.251a4.701 4.701 0 00.266-1.63c0-.6-.088-1.144-.266-1.629a3.45 3.45 0 00-.756-1.25 3.22 3.22 0 00-1.19-.8 3.904 3.904 0 00-1.54-.291c-.569 0-1.082.096-1.54.29a3.259 3.259 0 00-1.176.8c-.326.34-.578.757-.756 1.252a4.725 4.725 0 00-.266 1.629zm10.323 1.309h-1.89c.019.504.126.926.322 1.265.205.33.462.597.77.8.317.204.677.35 1.078.437a5.777 5.777 0 002.436 0 2.909 2.909 0 001.064-.422c.308-.204.555-.47.742-.8.196-.34.294-.757.294-1.251 0-.35-.065-.64-.196-.873a1.747 1.747 0 00-.518-.596 2.611 2.611 0 00-.742-.393 7.729 7.729 0 00-.84-.247c-.28-.068-.555-.131-.826-.19a8.052 8.052 0 01-.728-.189 1.609 1.609 0 01-.504-.29.575.575 0 01-.196-.451.54.54 0 01.112-.364.724.724 0 01.266-.218c.112-.049.233-.078.364-.087.131-.02.252-.03.364-.03.355 0 .663.073.924.219.261.135.406.402.434.8h1.89c-.037-.466-.154-.849-.35-1.15a2.225 2.225 0 00-.714-.741 2.95 2.95 0 00-.994-.393 5.617 5.617 0 00-2.282 0 2.885 2.885 0 00-1.008.378 2.046 2.046 0 00-.728.727c-.177.31-.266.708-.266 1.193 0 .33.065.611.196.844.131.223.303.412.518.567.215.146.457.267.728.364.28.087.565.165.854.233.709.155 1.26.31 1.652.465.401.155.602.388.602.698 0 .184-.042.34-.126.466a1.053 1.053 0 01-.322.29 1.658 1.658 0 01-.42.16 2.265 2.265 0 01-1.008-.028 1.546 1.546 0 01-.476-.219 1.383 1.383 0 01-.35-.392 1.266 1.266 0 01-.126-.582zm10.851-2.124h-3.234c.01-.145.038-.31.084-.495.056-.184.145-.358.266-.523.131-.165.299-.3.504-.407.215-.117.481-.175.798-.175.486 0 .845.136 1.078.407.243.272.411.67.504 1.193zm-3.234 1.31h5.222a5.478 5.478 0 00-.14-1.674 4.077 4.077 0 00-.644-1.425 3.112 3.112 0 00-1.12-.99c-.457-.252-.994-.378-1.61-.378-.55 0-1.054.102-1.512.306a3.532 3.532 0 00-1.162.844c-.326.349-.578.766-.756 1.25a4.548 4.548 0 00-.266 1.572c0 .582.084 1.115.252 1.6.178.485.425.902.742 1.25.318.35.705.621 1.162.815.458.184.971.277 1.54.277.822 0 1.522-.194 2.1-.582.579-.388 1.008-1.033 1.288-1.935h-1.75c-.065.233-.242.456-.532.67-.289.203-.634.305-1.036.305-.56 0-.989-.15-1.288-.451-.298-.3-.462-.786-.49-1.455zm11.54-.524c0 .31-.028.61-.084.901-.056.291-.15.553-.28.786a1.521 1.521 0 01-.532.538c-.215.136-.486.204-.812.204a1.51 1.51 0 01-.798-.204 2 2 0 01-.546-.553 2.622 2.622 0 01-.308-.785 3.933 3.933 0 01-.098-.873c0-.31.028-.606.084-.887.065-.291.163-.548.294-.771a1.64 1.64 0 01.546-.538c.224-.136.499-.204.826-.204.326 0 .597.068.812.204.214.135.387.315.518.538.14.213.238.465.294.756.056.281.084.577.084.888zm.028 2.822v.96h1.89V15.59h-1.988v3.782h-.028a2.106 2.106 0 00-.924-.83 2.66 2.66 0 00-1.218-.29c-.532 0-.999.111-1.4.334-.402.213-.738.5-1.008.858a4.032 4.032 0 00-.602 1.251c-.131.466-.196.95-.196 1.455 0 .524.065 1.028.196 1.513.14.485.34.916.602 1.294.27.369.611.665 1.022.888.41.213.886.32 1.428.32.476 0 .9-.088 1.274-.262.382-.184.69-.48.924-.887h.028z" fill="#2E2E2E"/><path d="M340.093 89.04a.976.976 0 00-1.398.22 1.065 1.065 0 00.212 1.452l1.186-1.673zm85.907.836l-11.413 1.82 7.224 9.36L426 89.876zm-85.395 2.116a.975.975 0 001.394-.243 1.066 1.066 0 00-.233-1.45l-1.161 1.693zm5.465 1.342a.978.978 0 00-1.382.312 1.064 1.064 0 00.3 1.436l1.082-1.748zm2.533 4.049a.98.98 0 001.367-.375 1.062 1.062 0 00-.36-1.42l-1.007 1.795zm5.555.775a.982.982 0 00-1.343.459c-.249.512-.052 1.137.441 1.396l.902-1.855zm2.941 3.746c.505.232 1.095-.005 1.319-.53.223-.525-.005-1.138-.51-1.37l-.809 1.9zm5.608.104c-.52-.195-1.093.084-1.281.624-.188.539.081 1.135.601 1.33l.68-1.954zm3.356 3.332c.529.163 1.086-.151 1.242-.702.157-.551-.146-1.128-.675-1.291l-.567 1.993zm5.57-.676c-.54-.118-1.071.241-1.185.802-.114.562.232 1.113.772 1.231l.413-2.033zm3.788 2.803c.547.081 1.053-.314 1.13-.882.078-.568-.303-1.094-.85-1.175l-.28 2.057zm5.405-1.537c-.552-.031-1.023.409-1.052.981-.029.574.394 1.063.946 1.094l.106-2.075zm4.164 2.15c.552-.011.991-.485.98-1.058-.011-.575-.467-1.031-1.019-1.02l.039 2.078zm5.093-2.424c-.549.063-.945.577-.884 1.147.061.571.556.981 1.105.918l-.221-2.065zm4.447 1.414c.543-.105.902-.647.801-1.211-.101-.564-.623-.937-1.166-.832l.365 2.043zm4.642-3.252c-.531.155-.842.728-.694 1.28.149.553.701.876 1.233.721l-.539-2.001zm4.601.664c.521-.192.793-.786.608-1.327a.991.991 0 00-1.277-.632l.669 1.959zm4.128-3.961c-.503.235-.728.85-.502 1.374a.986.986 0 001.322.522l-.82-1.896zm4.641-.036a1.06 1.06 0 00.421-1.403.982.982 0 00-1.35-.438l.929 1.841zm3.552-4.497c-.47.301-.616.941-.326 1.43a.98.98 0 001.377.338l-1.051-1.768zm4.602-.647c.454-.327.568-.974.254-1.446a.978.978 0 00-1.392-.263l1.138 1.709zm3.031-4.903a1.067 1.067 0 00-.171 1.459.975.975 0 001.404.177l-1.233-1.636zm-84.82.274c.527.404 1.094.832 1.698 1.28l1.161-1.692c-.594-.44-1.152-.862-1.673-1.26l-1.186 1.672zm6.081 4.37a96.649 96.649 0 003.615 2.3l1.007-1.795a93.481 93.481 0 01-3.54-2.253l-1.082 1.748zm8.268 4.931a80.434 80.434 0 003.843 1.891l.809-1.9a79.08 79.08 0 01-3.75-1.846l-.902 1.855zm8.771 3.949c1.309.492 2.655.953 4.036 1.378l.567-1.993a67.852 67.852 0 01-3.923-1.339l-.68 1.954zm9.193 2.735c1.373.302 2.773.56 4.201.77l.28-2.057a59.56 59.56 0 01-4.068-.746l-.413 2.033zm9.5 1.308c1.402.077 2.826.104 4.27.075l-.039-2.078a55.27 55.27 0 01-4.125-.072l-.106 2.075zm9.584-.284a56.47 56.47 0 004.226-.651l-.365-2.043a54.612 54.612 0 01-4.082.629l.221 2.065zm9.407-1.902a59.941 59.941 0 004.062-1.337l-.669-1.959a57.797 57.797 0 01-3.932 1.295l.539 2.001zm9.01-3.402a70.301 70.301 0 003.821-1.932l-.929-1.84a66.75 66.75 0 01-3.712 1.876l.82 1.896zm8.424-4.661a81.532 81.532 0 003.551-2.415l-1.138-1.71a79.562 79.562 0 01-3.464 2.357l1.051 1.768z" fill="#5398AD"/><path d="M216.724 19.523v6.984h1.884v-6.984h2.568V17.94h-7.02v1.584h2.568zm5.436 3.888c0-.248.024-.492.072-.732.048-.24.128-.452.24-.636.12-.184.276-.332.468-.444.192-.12.432-.18.72-.18s.528.06.72.18c.2.112.356.26.468.444.12.184.204.396.252.636a3.723 3.723 0 010 1.464 1.925 1.925 0 01-.252.636 1.25 1.25 0 01-.468.444c-.192.112-.432.168-.72.168s-.528-.056-.72-.168a1.382 1.382 0 01-.468-.444 2.095 2.095 0 01-.24-.636 3.723 3.723 0 01-.072-.732zm-1.704 0c0 .496.076.944.228 1.344.152.4.368.744.648 1.032.28.28.616.496 1.008.648.392.152.832.228 1.32.228.488 0 .928-.076 1.32-.228.4-.152.74-.368 1.02-.648.28-.288.496-.632.648-1.032.152-.4.228-.848.228-1.344a3.76 3.76 0 00-.228-1.344 2.836 2.836 0 00-.648-1.032 2.776 2.776 0 00-1.02-.66 3.465 3.465 0 00-1.32-.24c-.488 0-.928.08-1.32.24a2.836 2.836 0 00-1.656 1.692 3.76 3.76 0 00-.228 1.344zm15.272-.024c0 .256-.024.504-.072.744-.048.24-.128.456-.24.648a1.277 1.277 0 01-.456.444c-.184.112-.416.168-.696.168-.264 0-.492-.056-.684-.168a1.692 1.692 0 01-.468-.456 2.123 2.123 0 01-.264-.648 3.16 3.16 0 01-.084-.72c0-.256.024-.5.072-.732.056-.24.14-.452.252-.636.12-.184.276-.332.468-.444.192-.112.428-.168.708-.168.28 0 .512.056.696.168.184.112.332.26.444.444.12.176.204.384.252.624.048.232.072.476.072.732zm.024 2.328v.792h1.62V17.94h-1.704v3.12h-.024a1.784 1.784 0 00-.792-.684 2.35 2.35 0 00-1.044-.24c-.456 0-.856.092-1.2.276a2.57 2.57 0 00-.864.708c-.224.296-.396.64-.516 1.032a4.264 4.264 0 00-.168 1.2c0 .432.056.848.168 1.248.12.4.292.756.516 1.068.232.304.524.548.876.732.352.176.76.264 1.224.264.408 0 .772-.072 1.092-.216.328-.152.592-.396.792-.732h.024zm4.42-2.304c0-.248.024-.492.072-.732.048-.24.128-.452.24-.636.12-.184.276-.332.468-.444.192-.12.432-.18.72-.18s.528.06.72.18c.2.112.356.26.468.444.12.184.204.396.252.636a3.723 3.723 0 010 1.464 1.925 1.925 0 01-.252.636 1.25 1.25 0 01-.468.444c-.192.112-.432.168-.72.168s-.528-.056-.72-.168a1.382 1.382 0 01-.468-.444 2.095 2.095 0 01-.24-.636 3.723 3.723 0 01-.072-.732zm-1.704 0c0 .496.076.944.228 1.344.152.4.368.744.648 1.032.28.28.616.496 1.008.648.392.152.832.228 1.32.228.488 0 .928-.076 1.32-.228.4-.152.74-.368 1.02-.648.28-.288.496-.632.648-1.032.152-.4.228-.848.228-1.344a3.76 3.76 0 00-.228-1.344 2.836 2.836 0 00-.648-1.032 2.776 2.776 0 00-1.02-.66 3.465 3.465 0 00-1.32-.24c-.488 0-.928.08-1.32.24a2.836 2.836 0 00-1.656 1.692 3.76 3.76 0 00-.228 1.344z" fill="#fff"/><defs><filter id="filter0_i" x="195" y="0" width="176" height="213" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/><feOffset dy="3"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix values="0 0 0 0 0.85098 0 0 0 0 0.32549 0 0 0 0 0.309804 0 0 0 1 0"/><feBlend in2="shape" result="effect1_innerShadow"/></filter><filter id="filter1_d" x="208.5" y="46.256" width="149" height="41.444" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1"/><feGaussianBlur stdDeviation=".5"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0791084 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><filter id="filter2_d" x="13.5" y="98.207" width="149" height="41.444" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1"/><feGaussianBlur stdDeviation=".5"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0791084 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><filter id="filter3_d" x="208.5" y="96.129" width="149" height="41.444" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1"/><feGaussianBlur stdDeviation=".5"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0791084 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><filter id="filter4_d" x="13.5" y="46.256" width="149" height="41.444" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1"/><feGaussianBlur stdDeviation=".5"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0791084 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><filter id="filter5_d" x="13.5" y="148.081" width="149" height="41.444" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1"/><feGaussianBlur stdDeviation=".5"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0791084 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter></defs></svg>
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index 319144193f1..b4353af30d5 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import ExpiresAtField from './components/expires_at_field.vue';
-const getInputAttrs = el => {
+const getInputAttrs = (el) => {
const input = el.querySelector('input');
return {
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index 05de970e387..6b9f46dcfb6 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -9,9 +9,9 @@ export default class Activities {
constructor(container = '') {
this.container = container;
- Pager.init(20, true, false, data => data, this.updateTooltips, this.container);
+ Pager.init(20, true, false, (data) => data, this.updateTooltips, this.container);
- $('.event-filter-link').on('click', e => {
+ $('.event-filter-link').on('click', (e) => {
e.preventDefault();
this.toggleFilter(e.currentTarget);
this.reloadActivities();
@@ -24,7 +24,7 @@ export default class Activities {
reloadActivities() {
$('.content_list').html('');
- Pager.init(20, true, false, data => data, this.updateTooltips, this.container);
+ Pager.init(20, true, false, (data) => data, this.updateTooltips, this.container);
}
toggleFilter(sender) {
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 cb9aa50fa68..c58ded3f1f5 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
@@ -61,14 +61,14 @@ export default {
},
},
selectedCommitsCount() {
- return this.selectedCommits.filter(selectedCommit => selectedCommit.isSelected).length;
+ return this.selectedCommits.filter((selectedCommit) => selectedCommit.isSelected).length;
},
shouldPurge() {
return this.selectedCommitsCount !== this.selectedCommits.length;
},
uniqueCommits() {
return this.selectedCommits.filter(
- selectedCommit =>
+ (selectedCommit) =>
selectedCommit.isSelected &&
findCommitIndex(this.contextCommits, selectedCommit.short_id) === -1,
);
@@ -126,7 +126,7 @@ export default {
this.focusSearch();
if (this.shouldPurge) {
this.setSelectedCommits(
- [...this.commits, ...this.selectedCommits].filter(commit => commit.isSelected),
+ [...this.commits, ...this.selectedCommits].filter((commit) => commit.isSelected),
);
}
}
@@ -178,7 +178,7 @@ export default {
this.setCommits({ commits: tempCommits });
this.setSelectedCommits([
...tempSelectedCommits,
- ...tempCommits.filter(commit => commit.isSelected),
+ ...tempCommits.filter((commit) => commit.isSelected),
]);
},
handleCreateContextCommits() {
@@ -186,7 +186,7 @@ export default {
return Promise.all([
this.createContextCommits({ commits: this.uniqueCommits }),
this.removeContextCommits(),
- ]).then(values => {
+ ]).then((values) => {
if (values[0] || values[1]) {
window.location.reload();
}
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 d23955182b2..1bf54b159ee 100644
--- a/app/assets/javascripts/add_context_commits_modal/store/actions.js
+++ b/app/assets/javascripts/add_context_commits_modal/store/actions.js
@@ -27,10 +27,10 @@ export const searchCommits = ({ dispatch, commit, state }, searchText) => {
return axios
.get(state.contextCommitsPath, params)
.then(({ data }) => {
- let commits = data.map(o => ({ ...o, isSelected: false }));
- commits = commits.map(c => {
+ let commits = data.map((o) => ({ ...o, isSelected: false }));
+ commits = commits.map((c) => {
const isPresent = state.selectedCommits.find(
- selectedCommit => selectedCommit.short_id === c.short_id && selectedCommit.isSelected,
+ (selectedCommit) => selectedCommit.short_id === c.short_id && selectedCommit.isSelected,
);
if (isPresent) {
return { ...c, isSelected: true };
@@ -50,7 +50,7 @@ export const searchCommits = ({ dispatch, commit, state }, searchText) => {
export const setCommits = ({ commit }, { commits: data, silentAddition = false }) => {
let commits = _.uniqBy(data, 'short_id');
- commits = _.orderBy(data, c => new Date(c.committed_date), ['desc']);
+ commits = _.orderBy(data, (c) => new Date(c.committed_date), ['desc']);
if (silentAddition) {
commit(types.SET_COMMITS_SILENT, commits);
} else {
@@ -60,7 +60,7 @@ export const setCommits = ({ commit }, { commits: data, silentAddition = false }
export const createContextCommits = ({ state }, { commits, forceReload = false }) =>
Api.createContextCommits(state.projectId, state.mergeRequestIid, {
- commits: commits.map(commit => commit.short_id),
+ commits: commits.map((commit) => commit.short_id),
})
.then(() => {
if (forceReload) {
@@ -81,7 +81,7 @@ export const fetchContextCommits = ({ dispatch, commit, state }) => {
commit(types.FETCH_CONTEXT_COMMITS);
return Api.allContextCommits(state.projectId, state.mergeRequestIid)
.then(({ data }) => {
- const contextCommits = data.map(o => ({ ...o, isSelected: true }));
+ const contextCommits = data.map((o) => ({ ...o, isSelected: true }));
dispatch('setContextCommits', contextCommits);
dispatch('setCommits', {
commits: [...state.commits, ...contextCommits],
@@ -121,7 +121,7 @@ export const setSelectedCommits = ({ commit }, selected) => {
let selectedCommits = _.uniqBy(selected, 'short_id');
selectedCommits = _.orderBy(
selectedCommits,
- selectedCommit => new Date(selectedCommit.committed_date),
+ (selectedCommit) => new Date(selectedCommit.committed_date),
['desc'],
);
commit(types.SET_SELECTED_COMMITS, selectedCommits);
diff --git a/app/assets/javascripts/add_context_commits_modal/utils.js b/app/assets/javascripts/add_context_commits_modal/utils.js
index 3495ee17cd3..114913b1893 100644
--- a/app/assets/javascripts/add_context_commits_modal/utils.js
+++ b/app/assets/javascripts/add_context_commits_modal/utils.js
@@ -1,5 +1,5 @@
export const findCommitIndex = (commits, commitShortId) => {
- return commits.findIndex(commit => commit.short_id === commitShortId);
+ return commits.findIndex((commit) => commit.short_id === commitShortId);
};
export const setCommitStatus = (commits, commitIndex, selected) => {
diff --git a/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js b/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js
index f89533aeb1d..a357d5d2f1f 100644
--- a/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js
+++ b/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js
@@ -1,7 +1,7 @@
import PayloadPreviewer from '~/pages/admin/application_settings/payload_previewer';
export default () => {
- Array.from(document.querySelectorAll('.js-payload-preview-trigger')).forEach(trigger => {
+ Array.from(document.querySelectorAll('.js-payload-preview-trigger')).forEach((trigger) => {
new PayloadPreviewer(trigger).init();
});
};
diff --git a/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue b/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue
index bc2d96832fa..5da38495010 100644
--- a/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue
+++ b/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue
@@ -36,7 +36,7 @@ export default {
)
"
>
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="docsLink" target="_blank">{{ content }}</gl-link>
</template>
<template #strong="{ content }"
diff --git a/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue b/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue
index 316827e1b07..c0ad814172d 100644
--- a/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue
+++ b/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue
@@ -35,7 +35,7 @@ export default {
)
"
>
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="docsLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/admin/statistics_panel/index.js b/app/assets/javascripts/admin/statistics_panel/index.js
index 39112e3ddc0..8c49fffe630 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 (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 dd04e492388..149540c4222 100644
--- a/app/assets/javascripts/admin/statistics_panel/store/actions.js
+++ b/app/assets/javascripts/admin/statistics_panel/store/actions.js
@@ -13,7 +13,7 @@ export const fetchStatistics = ({ dispatch }) => {
.then(({ data }) => {
dispatch('receiveStatisticsSuccess', convertObjectPropsToCamelCase(data, { deep: true }));
})
- .catch(error => dispatch('receiveStatisticsError', error));
+ .catch((error) => dispatch('receiveStatisticsError', error));
};
export const receiveStatisticsSuccess = ({ commit }, statistics) =>
diff --git a/app/assets/javascripts/admin/statistics_panel/store/getters.js b/app/assets/javascripts/admin/statistics_panel/store/getters.js
index 1c1868b5bca..7ad1b0445ac 100644
--- a/app/assets/javascripts/admin/statistics_panel/store/getters.js
+++ b/app/assets/javascripts/admin/statistics_panel/store/getters.js
@@ -3,8 +3,8 @@
* and returns an array of the following form:
* [{ key: "forks", label: "Forks", value: 50 }]
*/
-export const getStatistics = state => labels =>
- Object.keys(labels).map(key => {
+export const getStatistics = (state) => (labels) =>
+ Object.keys(labels).map((key) => {
const result = {
key,
label: labels[key],
diff --git a/app/assets/javascripts/admin/users/components/user_avatar.vue b/app/assets/javascripts/admin/users/components/user_avatar.vue
new file mode 100644
index 00000000000..4f79c4fd451
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/user_avatar.vue
@@ -0,0 +1,53 @@
+<script>
+import { GlAvatarLink, GlAvatarLabeled, GlBadge } from '@gitlab/ui';
+import { USER_AVATAR_SIZE } from '../constants';
+
+export default {
+ components: {
+ GlAvatarLink,
+ GlAvatarLabeled,
+ GlBadge,
+ },
+ props: {
+ user: {
+ type: Object,
+ required: true,
+ },
+ adminUserPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ adminUserHref() {
+ return this.adminUserPath.replace('id', this.user.username);
+ },
+ },
+ USER_AVATAR_SIZE,
+};
+</script>
+
+<template>
+ <gl-avatar-link
+ v-if="user"
+ class="js-user-link"
+ :href="adminUserHref"
+ :data-user-id="user.id"
+ :data-username="user.username"
+ >
+ <gl-avatar-labeled
+ :size="$options.USER_AVATAR_SIZE"
+ :src="user.avatarUrl"
+ :label="user.name"
+ :sub-label="user.email"
+ >
+ <template #meta>
+ <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
+ }}</gl-badge>
+ </div>
+ </template>
+ </gl-avatar-labeled>
+ </gl-avatar-link>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue
index a2d68972519..15e31935a4c 100644
--- a/app/assets/javascripts/admin/users/components/users_table.vue
+++ b/app/assets/javascripts/admin/users/components/users_table.vue
@@ -1,14 +1,16 @@
<script>
import { GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
+import UserAvatar from './user_avatar.vue';
const DEFAULT_TH_CLASSES =
'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!';
-const thWidthClass = width => `gl-w-${width}p ${DEFAULT_TH_CLASSES}`;
+const thWidthClass = (width) => `gl-w-${width}p ${DEFAULT_TH_CLASSES}`;
export default {
components: {
GlTable,
+ UserAvatar,
},
props: {
users: {
@@ -58,6 +60,10 @@ export default {
:empty-text="s__('AdminUsers|No users found')"
show-empty
stacked="md"
- />
+ >
+ <template #cell(name)="{ item: user }">
+ <UserAvatar :user="user" :admin-user-path="paths.adminUser" />
+ </template>
+ </gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/admin/users/constants.js b/app/assets/javascripts/admin/users/constants.js
new file mode 100644
index 00000000000..675fcf00c39
--- /dev/null
+++ b/app/assets/javascripts/admin/users/constants.js
@@ -0,0 +1 @@
+export const USER_AVATAR_SIZE = 32;
diff --git a/app/assets/javascripts/admin/users/index.js b/app/assets/javascripts/admin/users/index.js
index 21780ee9984..f35b57c4e1a 100644
--- a/app/assets/javascripts/admin/users/index.js
+++ b/app/assets/javascripts/admin/users/index.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import AdminUsersApp from './components/app.vue';
-export default function(el = document.querySelector('#js-admin-users-app')) {
+export default function (el = document.querySelector('#js-admin-users-app')) {
if (!el) {
return false;
}
@@ -11,7 +11,7 @@ export default function(el = document.querySelector('#js-admin-users-app')) {
return new Vue({
el,
- render: createElement =>
+ render: (createElement) =>
createElement(AdminUsersApp, {
props: {
users: convertObjectPropsToCamelCase(JSON.parse(users), { deep: true }),
diff --git a/app/assets/javascripts/alert_handler.js b/app/assets/javascripts/alert_handler.js
index 26b0142f6a2..3c867f196d6 100644
--- a/app/assets/javascripts/alert_handler.js
+++ b/app/assets/javascripts/alert_handler.js
@@ -8,9 +8,9 @@ export default function initAlertHandler() {
const DISMISS_LABEL = '[aria-label="Dismiss"]';
const DISMISS_CLASS = '.gl-alert-dismiss';
- DISMISSIBLE_SELECTORS.forEach(selector => {
+ DISMISSIBLE_SELECTORS.forEach((selector) => {
const elements = document.querySelectorAll(selector);
- elements.forEach(element => {
+ elements.forEach((element) => {
const button = element.querySelector(DISMISS_LABEL) || element.querySelector(DISMISS_CLASS);
if (!button) {
return;
diff --git a/app/assets/javascripts/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue
index 1f3fdd5eef2..895c6e76019 100644
--- a/app/assets/javascripts/alert_management/components/alert_details.vue
+++ b/app/assets/javascripts/alert_management/components/alert_details.vue
@@ -140,7 +140,7 @@ export default {
},
currentTabIndex: {
get() {
- return this.$options.tabsConfig.findIndex(tab => tab.id === this.activeTab);
+ return this.$options.tabsConfig.findIndex((tab) => tab.id === this.activeTab);
},
set(tabIdx) {
const tabId = this.$options.tabsConfig[tabIdx].id;
@@ -194,15 +194,21 @@ export default {
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 => {
+ .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;
});
diff --git a/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue b/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue
index c5ff2dc0d11..9b0e5090a75 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue
@@ -6,20 +6,11 @@ import alertsHelpUrlQuery from '../graphql/queries/alert_help_url.query.graphql'
export default {
i18n: {
emptyState: {
- opsgenie: {
- title: s__('AlertManagement|Opsgenie is enabled'),
- info: s__(
- 'AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie.',
- ),
- buttonText: s__('AlertManagement|View alerts in Opsgenie'),
- },
- gitlab: {
- title: s__('AlertManagement|Surface alerts in GitLab'),
- info: s__(
- 'AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents.',
- ),
- buttonText: s__('AlertManagement|Authorize external service'),
- },
+ title: s__('AlertManagement|Surface alerts in GitLab'),
+ info: s__(
+ 'AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents.',
+ ),
+ buttonText: s__('AlertManagement|Authorize external service'),
},
moreInformation: s__('AlertManagement|More information'),
},
@@ -33,46 +24,27 @@ export default {
query: alertsHelpUrlQuery,
},
},
- inject: [
- 'enableAlertManagementPath',
- 'userCanEnableAlertManagement',
- 'emptyAlertSvgPath',
- 'opsgenieMvcEnabled',
- 'opsgenieMvcTargetUrl',
- ],
+ inject: ['enableAlertManagementPath', 'userCanEnableAlertManagement', 'emptyAlertSvgPath'],
data() {
return {
alertsHelpUrl: '',
};
},
- computed: {
- emptyState() {
- return {
- ...(this.opsgenieMvcEnabled
- ? this.$options.i18n.emptyState.opsgenie
- : this.$options.i18n.emptyState.gitlab),
- link: this.opsgenieMvcEnabled ? this.opsgenieMvcTargetUrl : this.enableAlertManagementPath,
- };
- },
- alertsCanBeEnabled() {
- return this.userCanEnableAlertManagement || this.opsgenieMvcEnabled;
- },
- },
};
</script>
<template>
<div>
- <gl-empty-state :title="emptyState.title" :svg-path="emptyAlertSvgPath">
+ <gl-empty-state :title="$options.i18n.emptyState.title" :svg-path="emptyAlertSvgPath">
<template #description>
<div class="gl-display-block">
- <span>{{ emptyState.info }}</span>
- <gl-link v-if="!opsgenieMvcEnabled" :href="alertsHelpUrl" target="_blank">
+ <span>{{ $options.i18n.emptyState.info }}</span>
+ <gl-link :href="alertsHelpUrl" target="_blank">
{{ $options.i18n.moreInformation }}
</gl-link>
</div>
- <div v-if="alertsCanBeEnabled" class="gl-display-block center gl-pt-4">
- <gl-button category="primary" variant="success" :href="emptyState.link">
- {{ emptyState.buttonText }}
+ <div v-if="userCanEnableAlertManagement" class="gl-display-block center gl-pt-4">
+ <gl-button category="primary" variant="success" :href="enableAlertManagementPath">
+ {{ $options.i18n.emptyState.buttonText }}
</gl-button>
</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 f287b425826..2bad15faa85 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -23,7 +23,7 @@ import {
} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
-import getAlerts from '../graphql/queries/get_alerts.query.graphql';
+import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql';
import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
import {
ALERTS_STATUS_TABS,
@@ -119,7 +119,7 @@ export default {
apollo: {
alerts: {
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
- query: getAlerts,
+ query: getAlertsQuery,
variables() {
return {
searchTerm: this.searchTerm,
@@ -138,7 +138,7 @@ export default {
data.project || {};
const now = new Date();
- const listWithData = list.map(alert => {
+ const listWithData = list.map((alert) => {
const then = new Date(alert.startedAt);
const diff = now - then;
diff --git a/app/assets/javascripts/alert_management/components/alert_metrics.vue b/app/assets/javascripts/alert_management/components/alert_metrics.vue
index 8a6490ecd5c..dd4faa03c00 100644
--- a/app/assets/javascripts/alert_management/components/alert_metrics.vue
+++ b/app/assets/javascripts/alert_management/components/alert_metrics.vue
@@ -33,7 +33,7 @@ export default {
});
this.metricEmbedComponent = MetricEmbed;
})
- .catch(e => Sentry.captureException(e));
+ .catch((e) => Sentry.captureException(e));
}
},
};
diff --git a/app/assets/javascripts/alert_management/components/alert_status.vue b/app/assets/javascripts/alert_management/components/alert_status.vue
index 3083a85cbd9..2afdeb8b6fd 100644
--- a/app/assets/javascripts/alert_management/components/alert_status.vue
+++ b/app/assets/javascripts/alert_management/components/alert_status.vue
@@ -3,7 +3,7 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { s__ } from '~/locale';
import Tracking from '~/tracking';
import { trackAlertStatusUpdateOptions } from '../constants';
-import updateAlertStatusMutation from '../graphql/mutations/update_alert_status.mutation.graphql';
+import updateAlertStatusMutation from '~/graphql_shared/mutations/update_alert_status.mutation.graphql';
export default {
i18n: {
@@ -57,7 +57,7 @@ export default {
projectPath: this.projectPath,
},
})
- .then(resp => {
+ .then((resp) => {
this.trackStatusUpdate(status);
const errors = resp.data?.updateAlertStatus?.errors || [];
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
index 3af68d42ddf..2a999b908f9 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
+++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
@@ -92,7 +92,7 @@ export default {
},
sortedUsers() {
return this.users
- .map(user => ({ ...user, active: this.isActive(user.username) }))
+ .map((user) => ({ ...user, active: this.isActive(user.username) }))
.sort((a, b) => (a.active === b.active ? 0 : a.active ? -1 : 1)); // eslint-disable-line no-nested-ternary
},
dropdownClass() {
@@ -192,7 +192,7 @@ export default {
</script>
<template>
- <div class="block alert-assignees ">
+ <div class="block alert-assignees">
<div ref="assignees" class="sidebar-collapsed-icon" @click="$emit('toggle-sidebar')">
<gl-icon name="user" :size="14" />
<gl-loading-icon v-if="isUpdating" />
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
index 84d54466a10..485395bcac2 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
+++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
@@ -115,7 +115,7 @@ export default {
variables: this.getAlertQueryVariables,
});
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.project.alertManagementAlerts.nodes[0].todos.nodes = [];
});
diff --git a/app/assets/javascripts/alert_management/details.js b/app/assets/javascripts/alert_management/details.js
index cbbdecae390..4217b702d0a 100644
--- a/app/assets/javascripts/alert_management/details.js
+++ b/app/assets/javascripts/alert_management/details.js
@@ -9,7 +9,7 @@ import createRouter from './router';
Vue.use(VueApollo);
-export default selector => {
+export default (selector) => {
const domEl = document.querySelector(selector);
const { alertId, projectPath, projectIssuesPath, projectId } = domEl.dataset;
const router = createRouter();
@@ -18,7 +18,7 @@ export default selector => {
Mutation: {
toggleSidebarStatus: (_, __, { cache }) => {
const sourceData = cache.readQuery({ query: sidebarStatusQuery });
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.sidebarStatus = !draftData.sidebarStatus;
});
@@ -30,7 +30,7 @@ export default selector => {
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(resolvers, {
cacheConfig: {
- dataIdFromObject: object => {
+ dataIdFromObject: (object) => {
// eslint-disable-next-line no-underscore-dangle
if (object.__typename === 'AlertManagementAlert') {
return object.iid;
@@ -51,6 +51,9 @@ export default selector => {
// eslint-disable-next-line no-new
new Vue({
el: selector,
+ components: {
+ AlertDetails,
+ },
provide: {
projectPath,
alertId,
@@ -58,9 +61,6 @@ export default selector => {
projectId,
},
apolloProvider,
- components: {
- AlertDetails,
- },
router,
render(createElement) {
return createElement('alert-details', {});
diff --git a/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql
index 406dfe97ce0..9a9ae369519 100644
--- a/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql
+++ b/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql
@@ -1,5 +1,5 @@
-#import "./list_item.fragment.graphql"
-#import "./alert_note.fragment.graphql"
+#import "~/graphql_shared/fragments/alert.fragment.graphql"
+#import "~/graphql_shared/fragments/alert_note.fragment.graphql"
fragment AlertDetailItem on AlertManagementAlert {
...AlertListItem
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql b/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql
index 5008bfa5e1b..63d952a4857 100644
--- a/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql
+++ b/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql
@@ -1,4 +1,4 @@
-#import "../fragments/alert_note.fragment.graphql"
+#import "~/graphql_shared/fragments/alert_note.fragment.graphql"
mutation alertSetAssignees($projectPath: ID!, $assigneeUsernames: [String!]!, $iid: String!) {
alertSetAssignees(
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.mutation.graphql b/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.mutation.graphql
deleted file mode 100644
index ba1e607bc10..00000000000
--- a/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.mutation.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-#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/alert_management/graphql/queries/get_alerts.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql
deleted file mode 100644
index bc7e51a2e90..00000000000
--- a/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql
+++ /dev/null
@@ -1,36 +0,0 @@
-#import "../fragments/list_item.fragment.graphql"
-
-query getAlerts(
- $projectPath: ID!
- $statuses: [AlertManagementStatus!]
- $sort: AlertManagementAlertSort
- $firstPageSize: Int
- $lastPageSize: Int
- $prevPageCursor: String = ""
- $nextPageCursor: String = ""
- $searchTerm: String = ""
- $assigneeUsername: String = ""
-) {
- project(fullPath: $projectPath) {
- alertManagementAlerts(
- search: $searchTerm
- assigneeUsername: $assigneeUsername
- statuses: $statuses
- sort: $sort
- first: $firstPageSize
- last: $lastPageSize
- after: $nextPageCursor
- before: $prevPageCursor
- ) {
- nodes {
- ...AlertListItem
- }
- pageInfo {
- hasNextPage
- endCursor
- hasPreviousPage
- startCursor
- }
- }
- }
-}
diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js
index e34450204fb..b484841ed2c 100644
--- a/app/assets/javascripts/alert_management/list.js
+++ b/app/assets/javascripts/alert_management/list.js
@@ -17,12 +17,10 @@ export default () => {
emptyAlertSvgPath,
populatingAlertsHelpUrl,
alertsHelpUrl,
- opsgenieMvcTargetUrl,
textQuery,
assigneeUsernameQuery,
alertManagementEnabled,
userCanEnableAlertManagement,
- opsgenieMvcEnabled,
} = domEl.dataset;
const apolloProvider = new VueApollo({
@@ -30,7 +28,7 @@ export default () => {
{},
{
cacheConfig: {
- dataIdFromObject: object => {
+ dataIdFromObject: (object) => {
// eslint-disable-next-line no-underscore-dangle
if (object.__typename === 'AlertManagementAlert') {
return object.iid;
@@ -50,6 +48,9 @@ export default () => {
return new Vue({
el: selector,
+ components: {
+ AlertManagementList,
+ },
provide: {
projectPath,
textQuery,
@@ -57,15 +58,10 @@ export default () => {
enableAlertManagementPath,
populatingAlertsHelpUrl,
emptyAlertSvgPath,
- opsgenieMvcTargetUrl,
alertManagementEnabled: parseBoolean(alertManagementEnabled),
userCanEnableAlertManagement: parseBoolean(userCanEnableAlertManagement),
- opsgenieMvcEnabled: parseBoolean(opsgenieMvcEnabled),
},
apolloProvider,
- components: {
- AlertManagementList,
- },
render(createElement) {
return createElement('alert-management-list');
},
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
index f2394ce385f..c0e93d315a4 100644
--- a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
+++ b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
@@ -91,25 +91,11 @@ export default {
];
},
},
- watch: {
- activated() {
- this.updateIcon();
- },
- },
methods: {
- updateIcon() {
- return document.querySelectorAll('.js-service-active-status').forEach(icon => {
- if (icon.dataset.value === this.activated.toString()) {
- icon.classList.remove('d-none');
- } else {
- icon.classList.add('d-none');
- }
- });
- },
resetKey() {
return axios
.put(this.formPath, { service: { token: '' } })
- .then(res => {
+ .then((res) => {
this.authorizationKey = res.data.token;
})
.catch(() => {
diff --git a/app/assets/javascripts/alerts_service_settings/index.js b/app/assets/javascripts/alerts_service_settings/index.js
index fe83ced2ee7..ddba966ffb3 100644
--- a/app/assets/javascripts/alerts_service_settings/index.js
+++ b/app/assets/javascripts/alerts_service_settings/index.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertsServiceForm from './components/alerts_service_form.vue';
-export default el => {
+export default (el) => {
if (!el) {
return null;
}
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 f6474efcc1f..c52e9f5c264 100644
--- a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
+++ b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
@@ -40,6 +40,11 @@ export default {
directives: {
GlTooltip,
},
+ inject: {
+ gitlabAlertFields: {
+ default: gitlabFieldsMock,
+ },
+ },
props: {
payloadFields: {
type: Array,
@@ -57,16 +62,11 @@ export default {
gitlabFields: this.gitlabAlertFields,
};
},
- inject: {
- gitlabAlertFields: {
- default: gitlabFieldsMock,
- },
- },
computed: {
mappingData() {
- return this.gitlabFields.map(gitlabField => {
+ return this.gitlabFields.map((gitlabField) => {
const mappingFields = this.payloadFields.filter(({ type }) =>
- type.some(t => gitlabField.compatibleTypes.includes(t)),
+ type.some((t) => gitlabField.compatibleTypes.includes(t)),
);
const foundMapping = this.mapping.find(
@@ -88,26 +88,26 @@ export default {
},
methods: {
setMapping(gitlabKey, mappingKey, valueKey) {
- const fieldIndex = this.gitlabFields.findIndex(field => field.name === gitlabKey);
+ const fieldIndex = this.gitlabFields.findIndex((field) => field.name === gitlabKey);
const updatedField = { ...this.gitlabFields[fieldIndex], ...{ [valueKey]: mappingKey } };
Vue.set(this.gitlabFields, fieldIndex, updatedField);
},
setSearchTerm(search = '', searchFieldKey, gitlabKey) {
- const fieldIndex = this.gitlabFields.findIndex(field => field.name === gitlabKey);
+ const fieldIndex = this.gitlabFields.findIndex((field) => field.name === gitlabKey);
const updatedField = { ...this.gitlabFields[fieldIndex], ...{ [searchFieldKey]: search } };
Vue.set(this.gitlabFields, fieldIndex, updatedField);
},
filterFields(searchTerm = '', fields) {
const search = searchTerm.toLowerCase();
- return fields.filter(field => field.label.toLowerCase().includes(search));
+ return fields.filter((field) => field.label.toLowerCase().includes(search));
},
isSelected(fieldValue, mapping) {
return fieldValue === mapping;
},
selectedValue(name) {
return (
- this.payloadFields.find(item => item.name === name)?.label ||
+ this.payloadFields.find((item) => item.name === name)?.label ||
this.$options.i18n.makeSelection
);
},
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
index cf16750dbf8..6cfb4601192 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -97,8 +97,8 @@ export default {
};
},
mounted() {
- const callback = entries => {
- const isVisible = entries.some(entry => entry.isIntersecting);
+ const callback = (entries) => {
+ const isVisible = entries.some((entry) => entry.isIntersecting);
if (isVisible) {
this.trackPageViews();
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 b2be563522a..1ae7f826ce6 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
@@ -18,14 +18,11 @@ 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 service from '../services';
import {
- integrationTypesNew,
+ integrationTypes,
JSON_VALIDATE_DELAY,
targetPrometheusUrlPlaceholder,
- targetOpsgenieUrlPlaceholder,
typeSet,
- sectionHash,
} from '../constants';
// 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)
@@ -91,20 +88,13 @@ export const i18n = {
'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
),
},
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- opsgenie: {
- label: s__('AlertSettings|2. Add link to your Opsgenie alert list'),
- info: s__(
- 'AlertSettings|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature.',
- ),
- },
},
};
export default {
+ integrationTypes,
placeholders: {
prometheus: targetPrometheusUrlPlaceholder,
- opsgenie: targetOpsgenieUrlPlaceholder,
},
JSON_VALIDATE_DELAY,
typeSet,
@@ -127,6 +117,7 @@ export default {
directives: {
GlModal: GlModalDirective,
},
+ mixins: [glFeatureFlagsMixin()],
inject: {
generic: {
default: {},
@@ -134,12 +125,7 @@ export default {
prometheus: {
default: {},
},
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- opsgenie: {
- default: {},
- },
},
- mixins: [glFeatureFlagsMixin()],
props: {
loading: {
type: Boolean,
@@ -149,12 +135,6 @@ export default {
type: Boolean,
required: true,
},
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- canManageOpsgenie: {
- type: Boolean,
- required: false,
- default: false,
- },
},
apollo: {
currentIntegration: {
@@ -163,7 +143,7 @@ export default {
},
data() {
return {
- selectedIntegration: integrationTypesNew[0].value,
+ selectedIntegration: integrationTypes[0].value,
active: false,
formVisible: false,
integrationTestPayload: {
@@ -174,8 +154,6 @@ export default {
customMapping: null,
parsingPayload: false,
currentIntegration: null,
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- isManagingOpsgenie: false,
};
},
computed: {
@@ -185,32 +163,12 @@ export default {
jsonIsValid() {
return this.integrationTestPayload.error === null;
},
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- disabledIntegrations() {
- const options = [];
- if (this.opsgenie.active) {
- options.push(typeSet.http, typeSet.prometheus);
- } else if (!this.canManageOpsgenie) {
- options.push(typeSet.opsgenie);
- }
-
- return options;
- },
- options() {
- return integrationTypesNew.map(el => ({
- ...el,
- disabled: this.disabledIntegrations.includes(el.value),
- }));
- },
selectedIntegrationType() {
switch (this.selectedIntegration) {
case typeSet.http:
return this.generic;
case typeSet.prometheus:
return this.prometheus;
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- case typeSet.opsgenie:
- return this.opsgenie;
default:
return {};
}
@@ -285,49 +243,17 @@ export default {
},
methods: {
integrationTypeSelect() {
- if (this.selectedIntegration === integrationTypesNew[0].value) {
+ if (this.selectedIntegration === integrationTypes[0].value) {
this.formVisible = false;
} else {
this.formVisible = true;
}
-
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- if (this.canManageOpsgenie && this.selectedIntegration === typeSet.opsgenie) {
- this.isManagingOpsgenie = true;
- this.active = this.opsgenie.active;
- this.integrationForm.apiUrl = this.opsgenie.opsgenieMvcTargetUrl;
- } else {
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- this.isManagingOpsgenie = false;
- }
- },
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- submitWithOpsgenie() {
- return service
- .updateGenericActive({
- endpoint: this.opsgenie.formPath,
- params: {
- service: {
- opsgenie_mvc_target_url: this.integrationForm.apiUrl,
- opsgenie_mvc_enabled: this.active,
- },
- },
- })
- .then(() => {
- window.location.hash = sectionHash;
- window.location.reload();
- });
},
submitWithTestPayload() {
this.$emit('set-test-alert-payload', this.testAlertPayload);
this.submit();
},
submit() {
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- if (this.isManagingOpsgenie) {
- return this.submitWithOpsgenie();
- }
-
const { name, apiUrl } = this.integrationForm;
const variables =
this.selectedIntegration === typeSet.http
@@ -343,7 +269,7 @@ export default {
return this.$emit('create-new-integration', integrationPayload);
},
reset() {
- this.selectedIntegration = integrationTypesNew[0].value;
+ this.selectedIntegration = integrationTypes[0].value;
this.integrationTypeSelect();
if (this.currentIntegration) {
@@ -360,9 +286,6 @@ export default {
error: null,
};
this.active = false;
-
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- this.isManagingOpsgenie = false;
},
resetAuthKey() {
if (!this.currentIntegration) {
@@ -390,10 +313,10 @@ export default {
// TODO: replace with real BE mutation when ready;
this.parsingPayload = true;
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => resolve(mockedCustomMapping), 1000);
})
- .then(res => {
+ .then((res) => {
const mapping = { ...res };
delete mapping.storedMapping;
this.customMapping = res;
@@ -408,7 +331,7 @@ export default {
},
getIntegrationMapping() {
// TODO: replace with real BE mutation when ready;
- return Promise.resolve(mockedCustomMapping).then(res => {
+ return Promise.resolve(mockedCustomMapping).then((res) => {
this.customMapping = res;
this.integrationTestPayload.json = res?.samplePayload.body;
});
@@ -428,8 +351,8 @@ export default {
<gl-form-select
v-model="selectedIntegration"
:disabled="isSelectDisabled"
- :class="{ 'gl-bg-gray-100!': isSelectDisabled }"
- :options="options"
+ class="mw-100"
+ :options="$options.integrationTypes"
@change="integrationTypeSelect"
/>
@@ -441,37 +364,7 @@ export default {
</div>
</gl-form-group>
<gl-collapse v-model="formVisible" class="gl-mt-3">
- <!-- TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657 -->
- <div v-if="isManagingOpsgenie">
- <gl-form-group
- id="integration-webhook"
- :label="$options.i18n.integrationFormSteps.opsgenie.label"
- label-for="integration-webhook"
- >
- <span class="gl-my-4">
- {{ $options.i18n.integrationFormSteps.opsgenie.info }}
- </span>
-
- <gl-toggle
- v-model="active"
- :is-loading="loading"
- :label="__('Active')"
- class="gl-my-4 gl-font-weight-normal"
- />
-
- <gl-form-input
- id="opsgenie-opsgenieMvcTargetUrl"
- v-model="integrationForm.apiUrl"
- type="text"
- :placeholder="$options.placeholders.opsgenie"
- />
-
- <span class="gl-text-gray-400 gl-my-1">
- {{ $options.i18n.integrationFormSteps.prometheusFormUrl.help }}
- </span>
- </gl-form-group>
- </div>
- <div v-else>
+ <div>
<gl-form-group
id="name-integration"
:label="$options.i18n.integrationFormSteps.step2.label"
@@ -661,9 +554,7 @@ export default {
data-testid="integration-form-submit"
>{{ s__('AlertSettings|Save integration') }}
</gl-button>
- <!-- TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657 -->
<gl-button
- v-if="!isManagingOpsgenie"
data-testid="integration-test-and-submit"
:disabled="isSubmitTestPayloadDisabled"
category="secondary"
@@ -672,12 +563,7 @@ export default {
@click="submitWithTestPayload"
>{{ s__('AlertSettings|Save and test payload') }}</gl-button
>
- <gl-button
- type="reset"
- class="js-no-auto-disable"
- :class="{ 'gl-ml-3': isManagingOpsgenie }"
- >{{ __('Cancel') }}</gl-button
- >
+ <gl-button type="reset" class="js-no-auto-disable">{{ __('Cancel') }}</gl-button>
</div>
</gl-collapse>
</gl-form>
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 a55e63c3bc0..d0cac066ffa 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -1,5 +1,4 @@
<script>
-import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import { fetchPolicies } from '~/lib/graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
@@ -41,10 +40,6 @@ export default {
),
},
components: {
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- GlAlert,
- GlLink,
- GlSprintf,
IntegrationsList,
AlertSettingsForm,
},
@@ -55,10 +50,6 @@ export default {
prometheus: {
default: {},
},
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- opsgenie: {
- default: {},
- },
projectPath: {
default: '',
},
@@ -105,13 +96,6 @@ export default {
canAddIntegration() {
return this.multiIntegrations || this.integrations?.list?.length < 2;
},
- canManageOpsgenie() {
- return (
- this.opsgenie.active ||
- this.integrations?.list?.every(({ active }) => active === false) ||
- this.integrations?.list?.length === 0
- );
- },
},
methods: {
createNewIntegration({ type, variables }) {
@@ -243,7 +227,9 @@ export default {
});
},
editIntegration({ id }) {
- const currentIntegration = this.integrations.list.find(integration => integration.id === id);
+ const currentIntegration = this.integrations.list.find(
+ (integration) => integration.id === id,
+ );
this.$apollo.mutate({
mutation: updateCurrentIntergrationMutation,
variables: {
@@ -317,27 +303,7 @@ export default {
<template>
<div>
- <!-- TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657 -->
- <gl-alert v-if="opsgenie.active" :dismissible="false" variant="tip">
- <gl-sprintf
- :message="
- s__(
- 'AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link
- class="gl-display-inline-block"
- href="https://gitlab.com/gitlab-org/gitlab/-/issues/273657"
- target="_blank"
- >{{ content }}</gl-link
- >
- </template>
- </gl-sprintf>
- </gl-alert>
<integrations-list
- v-else
:integrations="integrations.list"
:loading="loading"
@edit-integration="editIntegration"
@@ -346,7 +312,6 @@ export default {
<alert-settings-form
:loading="isUpdating"
:can-add-integration="canAddIntegration"
- :can-manage-opsgenie="canManageOpsgenie"
@create-new-integration="createNewIntegration"
@update-integration="updateIntegration"
@reset-token="resetToken"
diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js
index e30dc2ad553..ecd7c921b2f 100644
--- a/app/assets/javascripts/alerts_settings/constants.js
+++ b/app/assets/javascripts/alerts_settings/constants.js
@@ -40,22 +40,15 @@ export const i18n = {
integration: s__('AlertSettings|Integration'),
};
-// TODO: Delete as part of old form removal in 13.6
export const integrationTypes = [
+ { value: '', text: s__('AlertSettings|Select integration type') },
{ value: 'HTTP', text: s__('AlertSettings|HTTP Endpoint') },
{ value: 'PROMETHEUS', text: s__('AlertSettings|External Prometheus') },
- { value: 'OPSGENIE', text: s__('AlertSettings|Opsgenie') },
-];
-
-export const integrationTypesNew = [
- { value: '', text: s__('AlertSettings|Select integration type') },
- ...integrationTypes,
];
export const typeSet = {
http: 'HTTP',
prometheus: 'PROMETHEUS',
- opsgenie: 'OPSGENIE',
};
export const integrationToDeleteDefault = { id: null, name: '' };
@@ -63,7 +56,6 @@ export const integrationToDeleteDefault = { id: null, name: '' };
export const JSON_VALIDATE_DELAY = 250;
export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/';
-export const targetOpsgenieUrlPlaceholder = 'https://app.opsgenie.com/alert/list/';
export const sectionHash = 'js-alert-management-settings';
diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js
index 02c2def87fa..3dbfa69a8e9 100644
--- a/app/assets/javascripts/alerts_settings/graphql.js
+++ b/app/assets/javascripts/alerts_settings/graphql.js
@@ -14,7 +14,7 @@ const resolvers = {
{ cache },
) => {
const sourceData = cache.readQuery({ query: getCurrentIntegrationQuery });
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
if (id === null) {
// eslint-disable-next-line no-param-reassign
draftData.currentIntegration = null;
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 41b19a675c5..85858956987 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -11,7 +11,7 @@ apolloProvider.clients.defaultClient.cache.writeData({
});
Vue.use(GlToast);
-export default el => {
+export default (el) => {
if (!el) {
return null;
}
@@ -29,16 +29,15 @@ export default el => {
formPath,
authorizationKey,
url,
- opsgenieMvcAvailable,
- opsgenieMvcFormPath,
- opsgenieMvcEnabled,
- opsgenieMvcTargetUrl,
projectPath,
multiIntegrations,
} = el.dataset;
return new Vue({
el,
+ components: {
+ AlertSettingsWrapper,
+ },
provide: {
prometheus: {
active: parseBoolean(prometheusActivated),
@@ -56,19 +55,10 @@ export default el => {
token: authorizationKey,
url,
},
- opsgenie: {
- formPath: opsgenieMvcFormPath,
- active: parseBoolean(opsgenieMvcEnabled),
- opsgenieMvcTargetUrl,
- opsgenieMvcIsAvailable: parseBoolean(opsgenieMvcAvailable),
- },
projectPath,
multiIntegrations: parseBoolean(multiIntegrations),
},
apolloProvider,
- components: {
- AlertSettingsWrapper,
- },
render(createElement) {
return createElement('alert-settings-wrapper');
},
diff --git a/app/assets/javascripts/alerts_settings/utils/cache_updates.js b/app/assets/javascripts/alerts_settings/utils/cache_updates.js
index 18054b29fe9..758f3eb6dd4 100644
--- a/app/assets/javascripts/alerts_settings/utils/cache_updates.js
+++ b/app/assets/javascripts/alerts_settings/utils/cache_updates.js
@@ -14,7 +14,7 @@ const deleteIntegrationFromStore = (store, query, { httpIntegrationDestroy }, va
variables,
});
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.project.alertManagementIntegrations.nodes = draftData.project.alertManagementIntegrations.nodes.filter(
({ id }) => id !== integration.id,
@@ -45,7 +45,7 @@ const addIntegrationToStore = (
variables,
});
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.project.alertManagementIntegrations.nodes = [
integration,
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 a9bd1bb2f41..620f38bd50f 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
@@ -60,13 +60,13 @@ export default {
return Object.values(this.errors);
},
isLoading() {
- return some(this.$apollo.queries, query => query?.loading);
+ return some(this.$apollo.queries, (query) => query?.loading);
},
allQueriesFailed() {
- return every(this.errorMessages, message => message.length);
+ return every(this.errorMessages, (message) => message.length);
},
hasLoadingErrors() {
- return some(this.errorMessages, message => message.length);
+ return some(this.errorMessages, (message) => message.length);
},
errorMessage() {
// show the generic loading message if all requests fail
@@ -179,7 +179,7 @@ export default {
};
},
})
- .catch(error => this.handleError({ identifier, error, message: errorMessage }));
+ .catch((error) => this.handleError({ identifier, error, message: errorMessage }));
},
},
};
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 e8e35c22fe1..46cc05fc124 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
@@ -11,7 +11,7 @@ import latestGroupsQuery from '../graphql/queries/groups.query.graphql';
import latestProjectsQuery from '../graphql/queries/projects.query.graphql';
import { getAverageByMonth } from '../utils';
-const sortByDate = data => sortBy(data, item => new Date(item[0]).getTime());
+const sortByDate = (data) => sortBy(data, (item) => new Date(item[0]).getTime());
const averageAndSortData = (data = [], maxDataPoints) => {
const averaged = getAverageByMonth(
@@ -148,7 +148,7 @@ export default {
name: this.$options.i18n.xAxisTitle,
type: 'category',
axisLabel: {
- formatter: value => {
+ formatter: (value) => {
return formatDateAsMonth(value);
},
},
@@ -189,7 +189,7 @@ export default {
.fetchMore({
variables: { first: this.totalDataPoints, after: pageInfo.endCursor },
updateQuery: (previousResult, { fetchMoreResult }) => {
- const results = produce(fetchMoreResult, newData => {
+ const results = produce(fetchMoreResult, (newData) => {
// eslint-disable-next-line no-param-reassign
newData[dataKey].nodes = [
...previousResult[dataKey].nodes,
@@ -199,7 +199,7 @@ export default {
return results;
},
})
- .catch(error => {
+ .catch((error) => {
this.handleError({ error, message: errorMessage, dataKey });
});
}
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 a4a1d40b70b..03462113630 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue
@@ -10,7 +10,7 @@ import { formatDateAsMonth } from '~/lib/utils/datetime_utility';
import usersQuery from '../graphql/queries/users.query.graphql';
import { getAverageByMonth } from '../utils';
-const sortByDate = data => sortBy(data, item => new Date(item[0]).getTime());
+const sortByDate = (data) => sortBy(data, (item) => new Date(item[0]).getTime());
export default {
name: 'UsersChart',
@@ -106,7 +106,7 @@ export default {
.fetchMore({
variables: { first: this.totalDataPoints, after: this.pageInfo.endCursor },
updateQuery: (previousResult, { fetchMoreResult }) => {
- return produce(fetchMoreResult, newUsers => {
+ return produce(fetchMoreResult, (newUsers) => {
// eslint-disable-next-line no-param-reassign
newUsers.users.nodes = [...previousResult.users.nodes, ...newUsers.users.nodes];
});
diff --git a/app/assets/javascripts/analytics/instance_statistics/utils.js b/app/assets/javascripts/analytics/instance_statistics/utils.js
index e1fa5d155a2..396962ffad6 100644
--- a/app/assets/javascripts/analytics/instance_statistics/utils.js
+++ b/app/assets/javascripts/analytics/instance_statistics/utils.js
@@ -29,7 +29,7 @@ export function getAverageByMonth(items = [], options = {}) {
return { ...memo, [month]: { sum: count, recordCount: 1 } };
}, {});
- return Object.keys(itemsMap).map(month => {
+ return Object.keys(itemsMap).map((month) => {
const { sum, recordCount } = itemsMap[month];
const avg = sum / recordCount;
if (shouldRound) {
diff --git a/app/assets/javascripts/analytics/product_analytics/activity_charts_bundle.js b/app/assets/javascripts/analytics/product_analytics/activity_charts_bundle.js
index d1f4b537b11..91cb48e181b 100644
--- a/app/assets/javascripts/analytics/product_analytics/activity_charts_bundle.js
+++ b/app/assets/javascripts/analytics/product_analytics/activity_charts_bundle.js
@@ -8,18 +8,18 @@ export default () => {
return false;
}
- return containers.forEach(container => {
+ return containers.forEach((container) => {
const { chartData } = container.dataset;
const formattedData = JSON.parse(chartData);
return new Vue({
el: container,
- provide: {
- formattedData,
- },
components: {
ActivityChart,
},
+ provide: {
+ formattedData,
+ },
render(createElement) {
return createElement('activity-chart');
},
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 8daccae3467..0a3db8ad3a6 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -5,6 +5,12 @@ import { __ } from '~/locale';
const DEFAULT_PER_PAGE = 20;
+/**
+ * Slow deprecation Notice: Please rather use for new calls
+ * or during refactors /rest_api as this is doing named exports
+ * which support treeshaking
+ */
+
const Api = {
DEFAULT_PER_PAGE,
groupsPath: '/api/:version/groups.json',
@@ -13,6 +19,7 @@ const Api = {
groupMilestonesPath: '/api/:version/groups/:id/milestones',
subgroupsPath: '/api/:version/groups/:id/subgroups',
namespacesPath: '/api/:version/namespaces.json',
+ groupInvitationsPath: '/api/:version/groups/:id/invitations',
groupPackagesPath: '/api/:version/groups/:id/packages',
projectPackagesPath: '/api/:version/projects/:id/packages',
projectPackagePath: '/api/:version/projects/:id/packages/:package_id',
@@ -23,6 +30,7 @@ const Api = {
projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectFileSchemaPath: '/:namespace_path/:project_path/-/schema/:ref/:filename',
projectUsersPath: '/api/:version/projects/:id/users',
+ projectInvitationsPath: '/api/:version/projects/:id/invitations',
projectMembersPath: '/api/:version/projects/:id/members',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
@@ -127,12 +135,18 @@ const Api = {
});
},
- inviteGroupMember(id, data) {
+ addGroupMembersByUserId(id, data) {
const url = Api.buildUrl(this.groupMembersPath).replace(':id', encodeURIComponent(id));
return axios.post(url, data);
},
+ inviteGroupMembersByEmail(id, data) {
+ const url = Api.buildUrl(this.groupInvitationsPath).replace(':id', encodeURIComponent(id));
+
+ return axios.post(url, data);
+ },
+
groupMilestones(id, options) {
const url = Api.buildUrl(this.groupMilestonesPath).replace(':id', encodeURIComponent(id));
@@ -144,7 +158,10 @@ const Api = {
});
},
- // Return groups list. Filtered by query
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getGroups` method in `~/rest_api` instead.
+ */
groups(query, options, callback = () => {}) {
const url = Api.buildUrl(Api.groupsPath);
return axios
@@ -180,7 +197,10 @@ const Api = {
.then(({ data }) => callback(data));
},
- // Return projects list. Filtered by query
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getProjects` method in `~/rest_api` instead.
+ */
projects(query, options, callback = () => {}) {
const url = Api.buildUrl(Api.projectsPath);
const defaults = {
@@ -217,12 +237,18 @@ const Api = {
.then(({ data }) => data);
},
- inviteProjectMembers(id, data) {
+ addProjectMembersByUserId(id, data) {
const url = Api.buildUrl(this.projectMembersPath).replace(':id', encodeURIComponent(id));
return axios.post(url, data);
},
+ inviteProjectMembersByEmail(id, data) {
+ const url = Api.buildUrl(this.projectInvitationsPath).replace(':id', encodeURIComponent(id));
+
+ return axios.post(url, data);
+ },
+
// Return single project
project(projectPath) {
const url = Api.buildUrl(Api.projectPath).replace(':id', encodeURIComponent(projectPath));
@@ -374,8 +400,8 @@ const Api = {
.post(url, {
label: data,
})
- .then(res => callback(res.data))
- .catch(e => callback(e.response.data));
+ .then((res) => callback(res.data))
+ .catch((e) => callback(e.response.data));
},
// Return group projects list. Filtered by query
@@ -389,10 +415,12 @@ const Api = {
.get(url, {
params: { ...defaults, ...options },
})
- .then(({ data }) => callback(data))
+ .then(({ data }) => (callback ? callback(data) : data))
.catch(() => {
flash(__('Something went wrong while fetching projects'));
- callback();
+ if (callback) {
+ callback();
+ }
});
},
@@ -414,10 +442,10 @@ const Api = {
});
},
- applySuggestion(id) {
+ applySuggestion(id, message) {
const url = Api.buildUrl(Api.applySuggestionPath).replace(':id', encodeURIComponent(id));
- return axios.put(url);
+ return axios.put(url, { commit_message: message });
},
applySuggestionBatch(ids) {
@@ -429,7 +457,7 @@ const Api = {
commitPipelines(projectId, sha) {
const encodedProjectId = projectId
.split('/')
- .map(fragment => encodeURIComponent(fragment))
+ .map((fragment) => encodeURIComponent(fragment))
.join('/');
const url = Api.buildUrl(Api.commitPipelinesPath)
@@ -453,7 +481,7 @@ const Api = {
.replace(':type', type)
.replace(':key', encodeURIComponent(key));
- return axios.get(url, { params: options }).then(res => {
+ return axios.get(url, { params: options }).then((res) => {
if (callback) callback(res.data);
return res;
@@ -465,7 +493,7 @@ const Api = {
.replace(':id', encodeURIComponent(id))
.replace(':type', type);
- return axios.get(url, { params }).then(res => {
+ return axios.get(url, { params }).then((res) => {
if (callback) callback(res.data);
return res;
@@ -505,6 +533,10 @@ const Api = {
.replace(':namespace_path', namespacePath);
},
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getUsers` method in `~/rest_api` instead.
+ */
users(query, options) {
const url = Api.buildUrl(this.usersPath);
return axios.get(url, {
@@ -516,6 +548,10 @@ const Api = {
});
},
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getUser` method in `~/rest_api` instead.
+ */
user(id, options) {
const url = Api.buildUrl(this.userPath).replace(':id', encodeURIComponent(id));
return axios.get(url, {
@@ -523,11 +559,19 @@ const Api = {
});
},
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getUserCounts` method in `~/rest_api` instead.
+ */
userCounts() {
const url = Api.buildUrl(this.userCountsPath);
return axios.get(url);
},
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getUserStatus` method in `~/rest_api` instead.
+ */
userStatus(id, options) {
const url = Api.buildUrl(this.userStatusPath).replace(':id', encodeURIComponent(id));
return axios.get(url, {
@@ -535,6 +579,10 @@ const Api = {
});
},
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `getUserProjects` method in `~/rest_api` instead.
+ */
userProjects(userId, query, options, callback) {
const url = Api.buildUrl(Api.userProjectsPath).replace(':id', userId);
const defaults = {
@@ -570,6 +618,10 @@ const Api = {
});
},
+ /**
+ * @deprecated This method will be removed soon. Use the
+ * `updateUserStatus` method in `~/rest_api` instead.
+ */
postUserStatus({ emoji, message, availability }) {
const url = Api.buildUrl(this.userPostStatusPath);
@@ -834,11 +886,18 @@ const Api = {
page: 1,
};
+ const passedOptions = options;
+
+ // calling search API with empty string will not return results
+ if (!passedOptions.search) {
+ passedOptions.search = undefined;
+ }
+
return axios
.get(url, {
params: {
...defaults,
- ...options,
+ ...passedOptions,
},
})
.then(({ data, headers }) => {
diff --git a/app/assets/javascripts/api/api_utils.js b/app/assets/javascripts/api/api_utils.js
new file mode 100644
index 00000000000..42eb5e7aaf3
--- /dev/null
+++ b/app/assets/javascripts/api/api_utils.js
@@ -0,0 +1,5 @@
+import { joinPaths } from '../lib/utils/url_utility';
+
+export function buildApiUrl(url) {
+ return joinPaths('/', gon.relative_url_root || '', url.replace(':version', gon.api_version));
+}
diff --git a/app/assets/javascripts/api/constants.js b/app/assets/javascripts/api/constants.js
new file mode 100644
index 00000000000..b6c720a85f3
--- /dev/null
+++ b/app/assets/javascripts/api/constants.js
@@ -0,0 +1 @@
+export const DEFAULT_PER_PAGE = 20;
diff --git a/app/assets/javascripts/api/groups_api.js b/app/assets/javascripts/api/groups_api.js
new file mode 100644
index 00000000000..d4ba46656e6
--- /dev/null
+++ b/app/assets/javascripts/api/groups_api.js
@@ -0,0 +1,22 @@
+import axios from '../lib/utils/axios_utils';
+import { buildApiUrl } from './api_utils';
+import { DEFAULT_PER_PAGE } from './constants';
+
+const GROUPS_PATH = '/api/:version/groups.json';
+
+export function getGroups(query, options, callback = () => {}) {
+ const url = buildApiUrl(GROUPS_PATH);
+ return axios
+ .get(url, {
+ params: {
+ search: query,
+ per_page: DEFAULT_PER_PAGE,
+ ...options,
+ },
+ })
+ .then(({ data }) => {
+ callback(data);
+
+ return data;
+ });
+}
diff --git a/app/assets/javascripts/api/projects_api.js b/app/assets/javascripts/api/projects_api.js
new file mode 100644
index 00000000000..d9a2467cff3
--- /dev/null
+++ b/app/assets/javascripts/api/projects_api.js
@@ -0,0 +1,27 @@
+import axios from '../lib/utils/axios_utils';
+import { buildApiUrl } from './api_utils';
+import { DEFAULT_PER_PAGE } from './constants';
+
+const PROJECTS_PATH = '/api/:version/projects.json';
+
+export function getProjects(query, options, callback = () => {}) {
+ const url = buildApiUrl(PROJECTS_PATH);
+ const defaults = {
+ search: query,
+ per_page: DEFAULT_PER_PAGE,
+ simple: true,
+ };
+
+ if (gon.current_user_id) {
+ defaults.membership = true;
+ }
+
+ return axios
+ .get(url, {
+ params: Object.assign(defaults, options),
+ })
+ .then(({ data, headers }) => {
+ callback(data);
+ return { data, headers };
+ });
+}
diff --git a/app/assets/javascripts/api/user_api.js b/app/assets/javascripts/api/user_api.js
new file mode 100644
index 00000000000..e5983ec3c58
--- /dev/null
+++ b/app/assets/javascripts/api/user_api.js
@@ -0,0 +1,66 @@
+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';
+const USER_PATH = '/api/:version/users/:id';
+const USER_STATUS_PATH = '/api/:version/users/:id/status';
+const USER_PROJECTS_PATH = '/api/:version/users/:id/projects';
+const USER_POST_STATUS_PATH = '/api/:version/user/status';
+
+export function getUsers(query, options) {
+ const url = buildApiUrl(USERS_PATH);
+ return axios.get(url, {
+ params: {
+ search: query,
+ per_page: DEFAULT_PER_PAGE,
+ ...options,
+ },
+ });
+}
+
+export function getUser(id, options) {
+ const url = buildApiUrl(USER_PATH).replace(':id', encodeURIComponent(id));
+ return axios.get(url, {
+ params: options,
+ });
+}
+
+export function getUserCounts() {
+ const url = buildApiUrl(USER_COUNTS_PATH);
+ return axios.get(url);
+}
+
+export function getUserStatus(id, options) {
+ const url = buildApiUrl(USER_STATUS_PATH).replace(':id', encodeURIComponent(id));
+ return axios.get(url, {
+ params: options,
+ });
+}
+
+export function getUserProjects(userId, query, options, callback) {
+ const url = buildApiUrl(USER_PROJECTS_PATH).replace(':id', userId);
+ const defaults = {
+ search: query,
+ per_page: DEFAULT_PER_PAGE,
+ };
+ return axios
+ .get(url, {
+ params: { ...defaults, ...options },
+ })
+ .then(({ data }) => callback(data))
+ .catch(() => flash(__('Something went wrong while fetching projects')));
+}
+
+export function updateUserStatus({ emoji, message, availability }) {
+ const url = buildApiUrl(USER_POST_STATUS_PATH);
+
+ return axios.put(url, {
+ emoji,
+ message,
+ availability,
+ });
+}
diff --git a/app/assets/javascripts/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql b/app/assets/javascripts/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql
new file mode 100644
index 00000000000..d50fd665c16
--- /dev/null
+++ b/app/assets/javascripts/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql
@@ -0,0 +1,5 @@
+mutation updateKeepLatestArtifactProjectSetting($fullPath: ID!, $keepLatestArtifact: Boolean!) {
+ ciCdSettingsUpdate(input: { fullPath: $fullPath, keepLatestArtifact: $keepLatestArtifact }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql b/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql
new file mode 100644
index 00000000000..7486512c57c
--- /dev/null
+++ b/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql
@@ -0,0 +1,7 @@
+query getKeepLatestArtifactProjectSetting($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ ciCdSettings {
+ keepLatestArtifact
+ }
+ }
+}
diff --git a/app/assets/javascripts/artifacts_settings/index.js b/app/assets/javascripts/artifacts_settings/index.js
new file mode 100644
index 00000000000..d99d2be81cf
--- /dev/null
+++ b/app/assets/javascripts/artifacts_settings/index.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import KeepLatestArtifactCheckbox from '~/artifacts_settings/keep_latest_artifact_checkbox.vue';
+
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default (containerId = 'js-artifacts-settings-app') => {
+ const containerEl = document.getElementById(containerId);
+
+ if (!containerEl) {
+ return false;
+ }
+
+ const { fullPath, helpPagePath } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ apolloProvider,
+ provide: {
+ fullPath,
+ helpPagePath,
+ },
+ render(createElement) {
+ return createElement(KeepLatestArtifactCheckbox);
+ },
+ });
+};
diff --git a/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue b/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue
new file mode 100644
index 00000000000..5684033f3af
--- /dev/null
+++ b/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue
@@ -0,0 +1,99 @@
+<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.');
+
+export default {
+ components: {
+ GlAlert,
+ GlFormCheckbox,
+ GlLink,
+ },
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ helpPagePath: {
+ default: '',
+ },
+ },
+ apollo: {
+ keepLatestArtifact: {
+ query: GetKeepLatestArtifactProjectSetting,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ };
+ },
+ update(data) {
+ return data.project?.ciCdSettings?.keepLatestArtifact;
+ },
+ error() {
+ this.reportError(FETCH_ERROR);
+ },
+ },
+ },
+ data() {
+ return {
+ keepLatestArtifact: true,
+ errorMessage: '',
+ isAlertDismissed: false,
+ };
+ },
+ computed: {
+ shouldShowAlert() {
+ return this.errorMessage && !this.isAlertDismissed;
+ },
+ },
+ methods: {
+ reportError(error) {
+ this.errorMessage = error;
+ this.isAlertDismissed = false;
+ },
+ async updateSetting(checked) {
+ try {
+ const { data } = await this.$apollo.mutate({
+ mutation: UpdateKeepLatestArtifactProjectSetting,
+ variables: {
+ fullPath: this.fullPath,
+ keepLatestArtifact: checked,
+ },
+ });
+
+ if (data.ciCdSettingsUpdate.errors.length) {
+ this.reportError(UPDATE_ERROR);
+ }
+ } catch (error) {
+ this.reportError(UPDATE_ERROR);
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert
+ v-if="shouldShowAlert"
+ class="gl-mb-5"
+ variant="danger"
+ @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>
+ </div>
+</template>
diff --git a/app/assets/javascripts/authentication/u2f/authenticate.js b/app/assets/javascripts/authentication/u2f/authenticate.js
index f9b5ca3e5b4..f5217e9c9be 100644
--- a/app/assets/javascripts/authentication/u2f/authenticate.js
+++ b/app/assets/javascripts/authentication/u2f/authenticate.js
@@ -37,7 +37,7 @@ export default class U2FAuthenticate {
// Note: The server library fixes this behaviour in (unreleased) version 1.0.0.
// This can be removed once we upgrade.
// https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4
- this.signRequests = u2fParams.sign_requests.map(request => omit(request, 'challenge'));
+ this.signRequests = u2fParams.sign_requests.map((request) => omit(request, 'challenge'));
this.templates = {
inProgress: '#js-authenticate-token-2fa-in-progress',
@@ -48,7 +48,7 @@ export default class U2FAuthenticate {
start() {
return importU2FLibrary()
- .then(utils => {
+ .then((utils) => {
this.u2fUtils = utils;
this.renderInProgress();
})
@@ -60,7 +60,7 @@ export default class U2FAuthenticate {
this.appId,
this.challenge,
this.signRequests,
- response => {
+ (response) => {
if (response.errorCode) {
const error = new U2FError(response.errorCode, 'authenticate');
return this.renderError(error);
diff --git a/app/assets/javascripts/authentication/u2f/register.js b/app/assets/javascripts/authentication/u2f/register.js
index 9773a9185f8..52940e1c305 100644
--- a/app/assets/javascripts/authentication/u2f/register.js
+++ b/app/assets/javascripts/authentication/u2f/register.js
@@ -34,7 +34,7 @@ export default class U2FRegister {
start() {
return importU2FLibrary()
- .then(utils => {
+ .then((utils) => {
this.u2fUtils = utils;
this.renderSetup();
})
@@ -46,7 +46,7 @@ export default class U2FRegister {
this.appId,
this.registerRequests,
this.signRequests,
- response => {
+ (response) => {
if (response.errorCode) {
const error = new U2FError(response.errorCode, 'register');
return this.renderError(error);
diff --git a/app/assets/javascripts/authentication/webauthn/authenticate.js b/app/assets/javascripts/authentication/webauthn/authenticate.js
index 42c4c2b63bd..47cb7a40f76 100644
--- a/app/assets/javascripts/authentication/webauthn/authenticate.js
+++ b/app/assets/javascripts/authentication/webauthn/authenticate.js
@@ -39,11 +39,11 @@ export default class WebAuthnAuthenticate {
authenticate() {
navigator.credentials
.get({ publicKey: this.webauthnParams })
- .then(resp => {
+ .then((resp) => {
const convertedResponse = convertGetResponse(resp);
this.renderAuthenticated(JSON.stringify(convertedResponse));
})
- .catch(err => {
+ .catch((err) => {
this.flow.renderError(new WebAuthnError(err, 'authenticate'));
});
}
diff --git a/app/assets/javascripts/authentication/webauthn/register.js b/app/assets/javascripts/authentication/webauthn/register.js
index 06e4ffd6f3e..62ebf85abe4 100644
--- a/app/assets/javascripts/authentication/webauthn/register.js
+++ b/app/assets/javascripts/authentication/webauthn/register.js
@@ -39,8 +39,8 @@ export default class WebAuthnRegister {
.create({
publicKey: this.webauthnOptions,
})
- .then(cred => this.renderRegistered(JSON.stringify(convertCreateResponse(cred))))
- .catch(err => this.flow.renderError(new WebAuthnError(err, 'register')));
+ .then((cred) => this.renderRegistered(JSON.stringify(convertCreateResponse(cred))))
+ .catch((err) => this.flow.renderError(new WebAuthnError(err, 'register')));
}
renderSetup() {
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index d937060536a..22717a3f84c 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -56,13 +56,13 @@ export class AwardsHandler {
}
},
);
- this.registerEventListener('on', $parentEl, 'click', this.toggleButtonSelector, e => {
+ this.registerEventListener('on', $parentEl, 'click', this.toggleButtonSelector, (e) => {
e.stopPropagation();
e.preventDefault();
this.showEmojiMenu($(e.currentTarget));
});
- this.registerEventListener('on', $('html'), 'click', e => {
+ this.registerEventListener('on', $('html'), 'click', (e) => {
const $target = $(e.target);
if (!$target.closest(`.${this.menuClass}`).length) {
$('.js-awards-block.current').removeClass('current');
@@ -74,7 +74,7 @@ export class AwardsHandler {
});
const emojiButtonSelector = `.js-awards-block .js-emoji-btn, .${this.menuClass} .js-emoji-btn`;
- this.registerEventListener('on', $parentEl, 'click', emojiButtonSelector, e => {
+ this.registerEventListener('on', $parentEl, 'click', emojiButtonSelector, (e) => {
e.preventDefault();
const $target = $(e.currentTarget);
const $glEmojiElement = $target.find('gl-emoji');
@@ -98,10 +98,7 @@ export class AwardsHandler {
showEmojiMenu($addBtn) {
if ($addBtn.hasClass('js-note-emoji')) {
- $addBtn
- .closest('.note')
- .find('.js-awards-block')
- .addClass('current');
+ $addBtn.closest('.note').find('.js-awards-block').addClass('current');
} else {
$addBtn.closest('.js-awards-block').addClass('current');
}
@@ -193,7 +190,7 @@ export class AwardsHandler {
(promiseChain, categoryNameKey) =>
promiseChain.then(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
const emojisInCategory = categoryMap[categoryNameKey];
const categoryMarkup = this.renderCategory(
categoryLabelMap[categoryNameKey],
@@ -216,7 +213,7 @@ export class AwardsHandler {
menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish'));
}
})
- .catch(err => {
+ .catch((err) => {
emojiContentElement.insertAdjacentHTML(
'beforeend',
'<p>We encountered an error while adding the remaining categories</p>',
@@ -233,7 +230,7 @@ export class AwardsHandler {
<ul class="clearfix emoji-menu-list ${opts.menuListClass || ''}">
${emojiList
.map(
- emojiName => `
+ (emojiName) => `
<li class="emoji-menu-list-item">
<button class="emoji-menu-btn text-center js-emoji-btn" type="button">
${this.emoji.glEmojiTag(emojiName, {
@@ -466,7 +463,7 @@ export class AwardsHandler {
const className = 'pulse animated once short';
$emoji.addClass(className);
- this.registerEventListener('on', $emoji, animationEndEventString, e => {
+ this.registerEventListener('on', $emoji, animationEndEventString, (e) => {
$(e.currentTarget).removeClass(className);
});
}
@@ -518,7 +515,7 @@ export class AwardsHandler {
this.frequentlyUsedEmojis ||
(() => {
const frequentlyUsedEmojis = uniq((Cookies.get('frequently_used_emojis') || '').split(','));
- this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter(inputName =>
+ this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter((inputName) =>
this.emoji.isEmojiNameValid(inputName),
);
@@ -530,15 +527,13 @@ export class AwardsHandler {
setupSearch() {
const $search = $('.js-emoji-menu-search');
- this.registerEventListener('on', $search, 'input', e => {
- const term = $(e.target)
- .val()
- .trim();
+ this.registerEventListener('on', $search, 'input', (e) => {
+ const term = $(e.target).val().trim();
this.searchEmojis(term);
});
const $menu = $(`.${this.menuClass}`);
- this.registerEventListener('on', $menu, transitionEndEventString, e => {
+ this.registerEventListener('on', $menu, transitionEndEventString, (e) => {
if (e.target === e.currentTarget) {
// Clear the search
this.searchEmojis('');
@@ -556,17 +551,11 @@ export class AwardsHandler {
// Generate a search result block
const h5 = $('<h5 class="emoji-search-title"/>').text('Search results');
const foundEmojis = this.findMatchingEmojiElements(term).show();
- const ul = $('<ul>')
- .addClass('emoji-menu-list emoji-menu-search')
- .append(foundEmojis);
+ const ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis);
$('.emoji-menu-content ul, .emoji-menu-content h5').hide();
- $('.emoji-menu-content')
- .append(h5)
- .append(ul);
+ $('.emoji-menu-content').append(h5).append(ul);
} else {
- $('.emoji-menu-content')
- .children()
- .show();
+ $('.emoji-menu-content').children().show();
}
}
@@ -594,7 +583,7 @@ export class AwardsHandler {
}
hideMenuElement($emojiMenu) {
- $emojiMenu.on(transitionEndEventString, e => {
+ $emojiMenu.on(transitionEndEventString, (e) => {
if (e.currentTarget === e.target) {
// eslint-disable-next-line @gitlab/no-global-event-off
$emojiMenu.removeClass(IS_RENDERED).off(transitionEndEventString);
@@ -605,7 +594,7 @@ export class AwardsHandler {
}
destroy() {
- this.eventListeners.forEach(entry => {
+ this.eventListeners.forEach((entry) => {
entry.element.off.call(entry.element, ...entry.args);
});
$(`.${this.menuClass}`).remove();
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 0a8479519f1..9e09f527a39 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -48,10 +48,10 @@ export default {
},
helpText() {
const placeholders = ['project_path', 'project_id', 'default_branch', 'commit_sha']
- .map(placeholder => `<code>%{${placeholder}}</code>`)
+ .map((placeholder) => `<code>%{${placeholder}}</code>`)
.join(', ');
return sprintf(
- s__('Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}'),
+ s__('Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}'),
{
docsLinkEnd: '</a>',
docsLinkStart: `<a href="${escape(this.docsUrl)}">`,
@@ -105,13 +105,13 @@ export default {
badgeImageUrlExample() {
const exampleUrl =
'https://example.gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg';
- return sprintf(s__('Badges|e.g. %{exampleUrl}'), {
+ return sprintf(s__('Badges|Example: %{exampleUrl}'), {
exampleUrl,
});
},
badgeLinkUrlExample() {
const exampleUrl = 'https://example.gitlab.com/%{project_path}';
- return sprintf(s__('Badges|e.g. %{exampleUrl}'), {
+ return sprintf(s__('Badges|Example: %{exampleUrl}'), {
exampleUrl,
});
},
@@ -134,10 +134,10 @@ export default {
if (this.isEditing) {
return this.saveBadge()
.then(() => {
- createFlash(s__('Badges|The badge was saved.'), 'notice');
+ createFlash(s__('Badges|Badge saved.'), 'notice');
this.wasValidated = false;
})
- .catch(error => {
+ .catch((error) => {
createFlash(
s__('Badges|Saving the badge failed, please check the entered URLs and try again.'),
);
@@ -147,10 +147,10 @@ export default {
return this.addBadge()
.then(() => {
- createFlash(s__('Badges|A new badge was added.'), 'notice');
+ createFlash(s__('Badges|New badge added.'), 'notice');
this.wasValidated = false;
})
- .catch(error => {
+ .catch((error) => {
createFlash(
s__('Badges|Adding the badge failed, please check the entered URLs and try again.'),
);
@@ -183,7 +183,7 @@ export default {
required
@input="debouncedPreview"
/>
- <div class="invalid-feedback">{{ s__('Badges|Please fill in a valid URL') }}</div>
+ <div class="invalid-feedback">{{ s__('Badges|Enter a valid URL') }}</div>
<span class="form-text text-muted">{{ badgeLinkUrlExample }}</span>
</div>
@@ -198,7 +198,7 @@ export default {
required
@input="debouncedPreview"
/>
- <div class="invalid-feedback">{{ s__('Badges|Please fill in a valid URL') }}</div>
+ <div class="invalid-feedback">{{ s__('Badges|Enter a valid URL') }}</div>
<span class="form-text text-muted">{{ badgeImageUrlExample }}</span>
</div>
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index 19781783100..73c63a72b1c 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -42,7 +42,7 @@ export default {
.then(() => {
createFlash(s__('Badges|The badge was deleted.'), 'notice');
})
- .catch(error => {
+ .catch((error) => {
createFlash(s__('Badges|Deleting the badge failed, please try again.'));
throw error;
});
diff --git a/app/assets/javascripts/badges/store/actions.js b/app/assets/javascripts/badges/store/actions.js
index 806c2423e7e..3377f6c0996 100644
--- a/app/assets/javascripts/badges/store/actions.js
+++ b/app/assets/javascripts/badges/store/actions.js
@@ -2,7 +2,7 @@ import axios from '~/lib/utils/axios_utils';
import types from './mutation_types';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-export const transformBackendBadge = badge => ({
+export const transformBackendBadge = (badge) => ({
...convertObjectPropsToCamelCase(badge, true),
isDeleting: false,
});
@@ -27,11 +27,11 @@ export default {
image_url: newBadge.imageUrl,
link_url: newBadge.linkUrl,
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveNewBadgeError');
throw error;
})
- .then(res => {
+ .then((res) => {
dispatch('receiveNewBadge', transformBackendBadge(res.data));
});
},
@@ -50,7 +50,7 @@ export default {
const endpoint = `${state.apiEndpointUrl}/${badgeId}`;
return axios
.delete(endpoint)
- .catch(error => {
+ .catch((error) => {
dispatch('receiveDeleteBadgeError', badgeId);
throw error;
})
@@ -78,11 +78,11 @@ export default {
const endpoint = state.apiEndpointUrl;
return axios
.get(endpoint)
- .catch(error => {
+ .catch((error) => {
dispatch('receiveLoadBadgesError');
throw error;
})
- .then(res => {
+ .then((res) => {
dispatch('receiveLoadBadges', res.data.map(transformBackendBadge));
});
},
@@ -113,11 +113,11 @@ export default {
const renderEndpoint = `${state.apiEndpointUrl}/render?${parameters}`;
return axios
.get(renderEndpoint)
- .catch(error => {
+ .catch((error) => {
dispatch('receiveRenderedBadgeError');
throw error;
})
- .then(res => {
+ .then((res) => {
dispatch('receiveRenderedBadge', transformBackendBadge(res.data));
});
},
@@ -142,11 +142,11 @@ export default {
image_url: badge.imageUrl,
link_url: badge.linkUrl,
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveUpdatedBadgeError');
throw error;
})
- .then(res => {
+ .then((res) => {
dispatch('receiveUpdatedBadge', transformBackendBadge(res.data));
});
},
diff --git a/app/assets/javascripts/badges/store/mutations.js b/app/assets/javascripts/badges/store/mutations.js
index bd84e68c00f..3f4689aeb17 100644
--- a/app/assets/javascripts/badges/store/mutations.js
+++ b/app/assets/javascripts/badges/store/mutations.js
@@ -1,7 +1,7 @@
import types from './mutation_types';
import { PROJECT_BADGE } from '../constants';
-const reorderBadges = badges =>
+const reorderBadges = (badges) =>
badges.sort((a, b) => {
if (a.kind !== b.kind) {
return a.kind === PROJECT_BADGE ? 1 : -1;
@@ -31,7 +31,7 @@ export default {
},
[types.RECEIVE_UPDATED_BADGE](state, updatedBadge) {
- const badges = state.badges.map(badge => {
+ const badges = state.badges.map((badge) => {
if (badge.id === updatedBadge.id) {
return updatedBadge;
}
@@ -77,13 +77,13 @@ export default {
},
[types.RECEIVE_DELETE_BADGE](state, badgeId) {
- const badges = state.badges.filter(badge => badge.id !== badgeId);
+ const badges = state.badges.filter((badge) => badge.id !== badgeId);
Object.assign(state, {
badges,
});
},
[types.RECEIVE_DELETE_BADGE_ERROR](state, badgeId) {
- const badges = state.badges.map(badge => {
+ const badges = state.badges.map((badge) => {
if (badge.id === badgeId) {
return {
...badge,
@@ -98,7 +98,7 @@ export default {
});
},
[types.REQUEST_DELETE_BADGE](state, badgeId) {
- const badges = state.badges.map(badge => {
+ const badges = state.badges.map((badge) => {
if (badge.id === badgeId) {
return {
...badge,
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index dca6d90fbcb..3e93168f0e2 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -47,7 +47,7 @@ export default {
}
return sprintf(__("%{authorsName}'s thread"), {
- authorsName: this.discussion.notes.find(note => !note.system).author.name,
+ authorsName: this.discussion.notes.find((note) => !note.system).author.name,
});
},
linePosition() {
@@ -98,9 +98,7 @@ export default {
{{ titleText }}
</span>
<template v-if="showLinePosition">
- <template v-if="!glFeatures.multilineComments"
- >:{{ linePosition }}</template
- >
+ <template v-if="!glFeatures.multilineComments">:{{ linePosition }}</template>
<template v-else-if="startLineNumber === endLineNumber">
:<span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span>
</template>
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 ebd821125fb..a29409c52ae 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
@@ -11,8 +11,8 @@ export const saveDraft = ({ dispatch }, draft) =>
export const addDraftToDiscussion = ({ commit }, { endpoint, data }) =>
service
.addDraftToDiscussion(endpoint, data)
- .then(res => res.data)
- .then(res => {
+ .then((res) => res.data)
+ .then((res) => {
commit(types.ADD_NEW_DRAFT, res);
return res;
})
@@ -23,8 +23,8 @@ export const addDraftToDiscussion = ({ commit }, { endpoint, data }) =>
export const createNewDraft = ({ commit }, { endpoint, data }) =>
service
.createNewDraft(endpoint, data)
- .then(res => res.data)
- .then(res => {
+ .then((res) => res.data)
+ .then((res) => {
commit(types.ADD_NEW_DRAFT, res);
return res;
})
@@ -43,8 +43,8 @@ export const deleteDraft = ({ commit, getters }, draft) =>
export const fetchDrafts = ({ commit, getters }) =>
service
.fetchDrafts(getters.getNotesData.draftsPath)
- .then(res => res.data)
- .then(data => commit(types.SET_BATCH_COMMENTS_DRAFTS, data))
+ .then((res) => res.data)
+ .then((data) => commit(types.SET_BATCH_COMMENTS_DRAFTS, data))
.catch(() => flash(__('An error occurred while fetching pending comments')));
export const publishSingleDraft = ({ commit, dispatch, getters }, draftId) => {
@@ -86,8 +86,8 @@ export const updateDraft = (
resolveDiscussion,
position: JSON.stringify(position),
})
- .then(res => res.data)
- .then(data => commit(types.RECEIVE_DRAFT_UPDATE_SUCCESS, data))
+ .then((res) => res.data)
+ .then((data) => commit(types.RECEIVE_DRAFT_UPDATE_SUCCESS, data))
.then(callback)
.catch(() => flash(__('An error occurred while updating the comment')));
@@ -116,8 +116,8 @@ export const scrollToDraft = ({ dispatch, rootGetters }, draft) => {
export const expandAllDiscussions = ({ dispatch, state }) =>
state.drafts
- .filter(draft => draft.discussion_id)
- .forEach(draft => {
+ .filter((draft) => draft.discussion_id)
+ .forEach((draft) => {
dispatch('expandDiscussion', { discussionId: draft.discussion_id }, { root: true });
});
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js
index 22ae6c2e970..df5214ea7ab 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js
@@ -1,12 +1,12 @@
import { parallelLineKey, showDraftOnSide } from '../../../utils';
-export const draftsCount = state => state.drafts.length;
+export const draftsCount = (state) => state.drafts.length;
export const getNotesData = (state, getters, rootState, rootGetters) => rootGetters.getNotesData;
-export const hasDrafts = state => state.drafts.length > 0;
+export const hasDrafts = (state) => state.drafts.length > 0;
-export const draftsPerDiscussionId = state =>
+export const draftsPerDiscussionId = (state) =>
state.drafts.reduce((acc, draft) => {
if (draft.discussion_id) {
acc[draft.discussion_id] = draft;
@@ -15,7 +15,7 @@ export const draftsPerDiscussionId = state =>
return acc;
}, {});
-export const draftsPerFileHashAndLine = state =>
+export const draftsPerFileHashAndLine = (state) =>
state.drafts.reduce((acc, draft) => {
if (draft.file_hash) {
if (!acc[draft.file_hash]) {
@@ -55,10 +55,10 @@ export const hasParallelDraftRight = (state, getters) => (diffFileSha, line) =>
return draftsForFile ? Boolean(draftsForFile[rkey]) : false;
};
-export const shouldRenderDraftRowInDiscussion = (state, getters) => discussionId =>
+export const shouldRenderDraftRowInDiscussion = (state, getters) => (discussionId) =>
typeof getters.draftsPerDiscussionId[discussionId] !== 'undefined';
-export const draftForDiscussion = (state, getters) => discussionId =>
+export const draftForDiscussion = (state, getters) => (discussionId) =>
getters.draftsPerDiscussionId[discussionId] || {};
export const draftForLine = (state, getters) => (diffFileSha, line, side = null) => {
@@ -75,10 +75,10 @@ export const draftForLine = (state, getters) => (diffFileSha, line, side = null)
return {};
};
-export const draftsForFile = state => diffFileSha =>
- state.drafts.filter(draft => draft.file_hash === diffFileSha);
+export const draftsForFile = (state) => (diffFileSha) =>
+ state.drafts.filter((draft) => draft.file_hash === diffFileSha);
-export const isPublishingDraft = state => draftId =>
+export const isPublishingDraft = (state) => (draftId) =>
state.currentlyPublishingDrafts.indexOf(draftId) !== -1;
-export const sortedDrafts = state => [...state.drafts].sort((a, b) => a.id > b.id);
+export const sortedDrafts = (state) => [...state.drafts].sort((a, b) => a.id > b.id);
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js
index 731f4b6d12a..dabfe864575 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js
@@ -1,6 +1,6 @@
import * as types from './mutation_types';
-const processDraft = draft => ({
+const processDraft = (draft) => ({
...draft,
isDraft: true,
});
@@ -11,7 +11,7 @@ export default {
},
[types.DELETE_DRAFT](state, draftId) {
- state.drafts = state.drafts.filter(draft => draft.id !== draftId);
+ state.drafts = state.drafts.filter((draft) => draft.id !== draftId);
},
[types.SET_BATCH_COMMENTS_DRAFTS](state, drafts) {
@@ -23,13 +23,13 @@ export default {
},
[types.RECEIVE_PUBLISH_DRAFT_SUCCESS](state, draftId) {
state.currentlyPublishingDrafts = state.currentlyPublishingDrafts.filter(
- publishingDraftId => publishingDraftId !== draftId,
+ (publishingDraftId) => publishingDraftId !== draftId,
);
- state.drafts = state.drafts.filter(d => d.id !== draftId);
+ state.drafts = state.drafts.filter((d) => d.id !== draftId);
},
[types.RECEIVE_PUBLISH_DRAFT_ERROR](state, draftId) {
state.currentlyPublishingDrafts = state.currentlyPublishingDrafts.filter(
- publishingDraftId => publishingDraftId !== draftId,
+ (publishingDraftId) => publishingDraftId !== draftId,
);
},
@@ -44,14 +44,14 @@ export default {
state.isPublishing = false;
},
[types.RECEIVE_DRAFT_UPDATE_SUCCESS](state, data) {
- const index = state.drafts.findIndex(draft => draft.id === data.id);
+ const index = state.drafts.findIndex((draft) => draft.id === data.id);
if (index >= 0) {
state.drafts.splice(index, 1, processDraft(data));
}
},
[types.TOGGLE_RESOLVE_DISCUSSION](state, draftId) {
- state.drafts = state.drafts.map(draft => {
+ state.drafts = state.drafts.map((draft) => {
if (draft.id === draftId) {
return {
...draft,
diff --git a/app/assets/javascripts/batch_comments/utils.js b/app/assets/javascripts/batch_comments/utils.js
index cf4f7af0ebb..387e7e4a610 100644
--- a/app/assets/javascripts/batch_comments/utils.js
+++ b/app/assets/javascripts/batch_comments/utils.js
@@ -1,11 +1,11 @@
import { getFormData } from '~/diffs/store/utils';
-export const getDraftReplyFormData = data => ({
+export const getDraftReplyFormData = (data) => ({
endpoint: data.notesData.draftsPath,
data,
});
-export const getDraftFormData = params => ({
+export const getDraftFormData = (params) => ({
endpoint: params.notesData.draftsPath,
data: getFormData(params),
});
diff --git a/app/assets/javascripts/behaviors/autosize.js b/app/assets/javascripts/behaviors/autosize.js
index 3e9d77cdf6b..a5404539c17 100644
--- a/app/assets/javascripts/behaviors/autosize.js
+++ b/app/assets/javascripts/behaviors/autosize.js
@@ -8,6 +8,6 @@ document.addEventListener('DOMContentLoaded', () => {
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/bind_in_out.js b/app/assets/javascripts/behaviors/bind_in_out.js
index 886f127b06b..2c5a3994ade 100644
--- a/app/assets/javascripts/behaviors/bind_in_out.js
+++ b/app/assets/javascripts/behaviors/bind_in_out.js
@@ -30,7 +30,7 @@ class BindInOut {
static initAll() {
const ins = document.querySelectorAll('*[data-bind-in]');
- return [].map.call(ins, anIn => BindInOut.init(anIn));
+ return [].map.call(ins, (anIn) => BindInOut.init(anIn));
}
static init(anIn, anOut) {
diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js
index e822072d669..1176fa6628d 100644
--- a/app/assets/javascripts/behaviors/copy_to_clipboard.js
+++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js
@@ -58,7 +58,7 @@ export default function initCopyToClipboard() {
* the last minute to deconstruct this JSON hash and set the `text/plain` and `text/x-gfm` copy
* data types to the intended values.
*/
- $(document).on('copy', 'body > textarea[readonly]', e => {
+ $(document).on('copy', 'body > textarea[readonly]', (e) => {
const { clipboardData } = e.originalEvent;
if (!clipboardData) return;
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
index 16373b523b2..1fa37999d62 100644
--- a/app/assets/javascripts/behaviors/gl_emoji.js
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -32,7 +32,7 @@ class GlEmoji extends HTMLElement {
const isEmojiUnicode =
this.childNodes &&
- Array.prototype.every.call(this.childNodes, childNode => childNode.nodeType === 3);
+ Array.prototype.every.call(this.childNodes, (childNode) => childNode.nodeType === 3);
if (
emojiUnicode &&
diff --git a/app/assets/javascripts/behaviors/load_startup_css.js b/app/assets/javascripts/behaviors/load_startup_css.js
index 1d7bf716475..dbe9ff8b6e7 100644
--- a/app/assets/javascripts/behaviors/load_startup_css.js
+++ b/app/assets/javascripts/behaviors/load_startup_css.js
@@ -8,7 +8,7 @@ export const loadStartupCSS = () => {
() => {
document
.querySelectorAll('link[media=print]')
- .forEach(x => x.dispatchEvent(new Event('load')));
+ .forEach((x) => x.dispatchEvent(new Event('load')));
},
{ once: true },
);
diff --git a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
index ce5b63df19c..9a8af79210e 100644
--- a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
@@ -10,10 +10,10 @@ export class CopyAsGFM {
const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent);
if (isIOS) return;
- $(document).on('copy', '.md', e => {
+ $(document).on('copy', '.md', (e) => {
CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection);
});
- $(document).on('copy', 'pre.code.highlight, table.code td.line_content', e => {
+ $(document).on('copy', 'pre.code.highlight, table.code td.line_content', (e) => {
CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformCodeSelection);
});
$(document).on('paste', '.js-gfm-input', CopyAsGFM.pasteGFM);
@@ -42,7 +42,7 @@ export class CopyAsGFM {
clipboardData.setData('text/x-gfm-html', html);
CopyAsGFM.nodeToGFM(el)
- .then(res => {
+ .then((res) => {
clipboardData.setData('text/x-gfm', res);
})
.catch(() => {
@@ -71,7 +71,7 @@ export class CopyAsGFM {
const div = document.createElement('div');
div.innerHTML = gfmHtml;
CopyAsGFM.nodeToGFM(div)
- .then(transformedGfm => {
+ .then((transformedGfm) => {
CopyAsGFM.insertPastedText(e.target, text, transformedGfm);
})
.catch(() => {});
@@ -79,7 +79,7 @@ export class CopyAsGFM {
}
static insertPastedText(target, text, gfm) {
- insertText(target, textBefore => {
+ insertText(target, (textBefore) => {
// If the text before the cursor contains an odd number of backticks,
// we are either inside an inline code span that starts with 1 backtick
// or a code block that starts with 3 backticks.
@@ -125,7 +125,7 @@ export class CopyAsGFM {
let lineSelector = '.line';
if (target) {
- const lineClass = ['left-side', 'right-side'].filter(name =>
+ const lineClass = ['left-side', 'right-side'].filter((name) =>
target.classList.contains(name),
)[0];
if (lineClass) {
diff --git a/app/assets/javascripts/behaviors/markdown/highlight_current_user.js b/app/assets/javascripts/behaviors/markdown/highlight_current_user.js
index 6208b3f0032..0fac278573e 100644
--- a/app/assets/javascripts/behaviors/markdown/highlight_current_user.js
+++ b/app/assets/javascripts/behaviors/markdown/highlight_current_user.js
@@ -9,7 +9,7 @@ export default function highlightCurrentUser(elements) {
return;
}
- elements.forEach(element => {
+ elements.forEach((element) => {
if (parseInt(element.dataset.user, 10) === currentUserId) {
element.classList.add('current-user');
}
diff --git a/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js b/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js
index ce425e80cd3..7f1506cd5d9 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/inline_diff.js
@@ -19,7 +19,7 @@ export default class InlineDiff extends Mark {
{ tag: 'span.idiff.addition', attrs: { addition: true } },
{ tag: 'span.idiff.deletion', attrs: { addition: false } },
],
- toDOM: node => [
+ toDOM: (node) => [
'span',
{ class: `idiff left right ${node.attrs.addition ? 'addition' : 'deletion'}` },
0,
diff --git a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
index f8465111959..556e6f7df1c 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
@@ -19,14 +19,14 @@ export default class InlineHTML extends Mark {
parseDOM: [
{
tag: 'sup, sub, kbd, q, samp, var',
- getAttrs: el => ({ tag: el.nodeName.toLowerCase() }),
+ getAttrs: (el) => ({ tag: el.nodeName.toLowerCase() }),
},
{
tag: 'abbr',
- getAttrs: el => ({ tag: 'abbr', title: el.getAttribute('title') }),
+ getAttrs: (el) => ({ tag: 'abbr', title: el.getAttribute('title') }),
},
],
- toDOM: node => [node.attrs.tag, { title: node.attrs.title }, 0],
+ toDOM: (node) => [node.attrs.tag, { title: node.attrs.title }, 0],
};
}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
index 1e0c05eff08..cd90d67c60d 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
@@ -25,7 +25,7 @@ export default class CodeBlock extends BaseCodeBlock {
{
tag: 'pre.code.highlight',
preserveWhitespace: 'full',
- getAttrs: el => {
+ getAttrs: (el) => {
const lang = el.getAttribute('lang');
if (!lang || lang === '') return {};
@@ -62,13 +62,13 @@ export default class CodeBlock extends BaseCodeBlock {
tag: '.md-suggestion-diff',
preserveWhitespace: 'full',
getContent: (el, schema) =>
- [...el.querySelectorAll('.line_content.new span')].map(span =>
+ [...el.querySelectorAll('.line_content.new span')].map((span) =>
schema.text(span.innerText),
),
attrs: { lang: 'suggestion' },
},
],
- toDOM: node => ['pre', { class: 'code highlight', lang: node.attrs.lang }, ['code', 0]],
+ toDOM: (node) => ['pre', { class: 'code highlight', lang: node.attrs.lang }, ['code', 0]],
};
}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/emoji.js b/app/assets/javascripts/behaviors/markdown/nodes/emoji.js
index a7cc3e828f5..367a06ad3c1 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/emoji.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/emoji.js
@@ -20,14 +20,14 @@ export default class Emoji extends Node {
parseDOM: [
{
tag: 'gl-emoji',
- getAttrs: el => ({
+ getAttrs: (el) => ({
name: el.dataset.name,
title: el.getAttribute('title'),
moji: el.textContent,
}),
},
],
- toDOM: node => [
+ toDOM: (node) => [
'gl-emoji',
{ 'data-name': node.attrs.name, title: node.attrs.title },
node.attrs.moji,
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/image.js b/app/assets/javascripts/behaviors/markdown/nodes/image.js
index b1983eebe15..76746528e72 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/image.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/image.js
@@ -30,7 +30,7 @@ export default class Image extends BaseImage {
// Matches HTML generated by Banzai::Filter::ImageLazyLoadFilter
{
tag: 'img[src]',
- getAttrs: el => {
+ getAttrs: (el) => {
const imageSrc = el.src;
const imageUrl =
imageSrc && imageSrc !== placeholderImage ? imageSrc : el.dataset.src || '';
@@ -43,7 +43,7 @@ export default class Image extends BaseImage {
},
},
],
- toDOM: node => ['img', node.attrs],
+ toDOM: (node) => ['img', node.attrs],
};
}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/playable.js b/app/assets/javascripts/behaviors/markdown/nodes/playable.js
index 9a2c9c3c9b0..9cbd95a7bd8 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/playable.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/playable.js
@@ -42,11 +42,11 @@ export default class Playable extends Node {
},
{
tag: `${this.mediaType}[src]`,
- getAttrs: el => ({ src: el.src, alt: el.dataset.title }),
+ getAttrs: (el) => ({ src: el.src, alt: el.dataset.title }),
},
];
- const toDOM = node => [
+ const toDOM = (node) => [
this.mediaType,
{
src: node.attrs.src,
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/reference.js b/app/assets/javascripts/behaviors/markdown/nodes/reference.js
index aa724798da6..dd82ea58ea5 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/reference.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/reference.js
@@ -25,7 +25,7 @@ export default class Reference extends Node {
{
tag: 'a.gfm:not([data-link=true])',
priority: HIGHER_PARSE_RULE_PRIORITY,
- getAttrs: el => ({
+ getAttrs: (el) => ({
className: el.className,
referenceType: el.dataset.referenceType,
originalText: el.dataset.original,
@@ -34,7 +34,7 @@ export default class Reference extends Node {
}),
},
],
- toDOM: node => [
+ toDOM: (node) => [
'a',
{
class: node.attrs.className,
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js b/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js
index c63bfe10e39..ebb66cd4da5 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_cell.js
@@ -19,13 +19,13 @@ export default class TableCell extends Node {
parseDOM: [
{
tag: 'td, th',
- getAttrs: el => ({
+ getAttrs: (el) => ({
header: el.tagName === 'TH',
align: el.getAttribute('align') || el.style.textAlign,
}),
},
],
- toDOM: node => [node.attrs.header ? 'th' : 'td', { align: node.attrs.align }, 0],
+ toDOM: (node) => [node.attrs.header ? 'th' : 'td', { align: node.attrs.align }, 0],
};
}
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
index 7bb56b4c406..56c2b17286d 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
@@ -23,7 +23,7 @@ export default class TaskListItem extends Node {
{
priority: HIGHER_PARSE_RULE_PRIORITY,
tag: 'li.task-list-item',
- getAttrs: el => {
+ getAttrs: (el) => {
const checkbox = el.querySelector('input[type=checkbox].task-list-item-checkbox');
return { done: checkbox && checkbox.checked };
},
diff --git a/app/assets/javascripts/behaviors/markdown/paste_markdown_table.js b/app/assets/javascripts/behaviors/markdown/paste_markdown_table.js
index 278dd857ab8..46582867d05 100644
--- a/app/assets/javascripts/behaviors/markdown/paste_markdown_table.js
+++ b/app/assets/javascripts/behaviors/markdown/paste_markdown_table.js
@@ -1,4 +1,5 @@
-const maxColumnWidth = (rows, columnIndex) => Math.max(...rows.map(row => row[columnIndex].length));
+const maxColumnWidth = (rows, columnIndex) =>
+ Math.max(...rows.map((row) => row[columnIndex].length));
export default class PasteMarkdownTable {
constructor(clipboardData) {
@@ -16,7 +17,7 @@ export default class PasteMarkdownTable {
this.calculateColumnWidths();
const markdownRows = this.rows.map(
- row =>
+ (row) =>
// | Name | Title | Email Address |
// |--------------|-------|----------------|
// | Jane Atler | CEO | jane@acme.com |
@@ -66,7 +67,7 @@ export default class PasteMarkdownTable {
return false;
}
- this.rows = splitRows.map(row => row.split('\t'));
+ this.rows = splitRows.map((row) => row.split('\t'));
this.normalizeRows();
// Check that the max number of columns in the HTML matches the number of
@@ -81,10 +82,10 @@ export default class PasteMarkdownTable {
// Ensure each row has the same number of columns
normalizeRows() {
- const rowLengths = this.rows.map(row => row.length);
+ const rowLengths = this.rows.map((row) => row.length);
const maxLength = Math.max(...rowLengths);
- this.rows.forEach(row => {
+ this.rows.forEach((row) => {
while (row.length < maxLength) {
row.push('');
}
@@ -101,7 +102,7 @@ export default class PasteMarkdownTable {
const textColumnCount = this.rows[0].length;
let htmlColumnCount = 0;
- this.doc.querySelectorAll('table tr').forEach(row => {
+ this.doc.querySelectorAll('table tr').forEach((row) => {
htmlColumnCount = Math.max(row.cells.length, htmlColumnCount);
});
diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
index 30783562da9..f34fec4d449 100644
--- a/app/assets/javascripts/behaviors/markdown/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -35,7 +35,7 @@ const RENDER_FLASH_MSG = sprintf(
// Wait for the browser to reflow the layout. Reflowing SVG takes time.
// This has to wrap the inner function, otherwise IE/Edge throw "invalid calling object".
-const waitForReflow = fn => {
+const waitForReflow = (fn) => {
window.requestAnimationFrame(fn);
};
@@ -122,7 +122,7 @@ class SafeMathRenderer {
render() {
// Replace math blocks with a placeholder so they aren't rendered twice
- this.elements.forEach(el => {
+ this.elements.forEach((el) => {
const placeholder = document.createElement('span');
placeholder.style.display = 'none';
placeholder.setAttribute('data-math-style', el.getAttribute('data-math-style'));
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index 602f156dbf0..479782a1f1f 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -29,7 +29,7 @@ let mermaidModule = {};
function importMermaidModule() {
return import(/* webpackChunkName: 'mermaid' */ 'mermaid')
- .then(mermaid => {
+ .then((mermaid) => {
let theme = 'neutral';
const ideDarkThemes = ['dark', 'solarized-dark', 'monokai'];
@@ -59,7 +59,7 @@ function importMermaidModule() {
return mermaid;
})
- .catch(err => {
+ .catch((err) => {
flash(sprintf(__("Can't load mermaid module: %{err}"), { err }));
// eslint-disable-next-line no-console
console.error(err);
@@ -77,7 +77,7 @@ function fixElementSource(el) {
}
function renderMermaidEl(el) {
- mermaidModule.init(undefined, el, id => {
+ mermaidModule.init(undefined, el, (id) => {
const source = el.textContent;
const svg = document.getElementById(id);
@@ -170,7 +170,7 @@ function renderMermaids($els) {
elsProcessingMap.set(el, requestId);
});
})
- .catch(err => {
+ .catch((err) => {
flash(sprintf(__('Encountered an error while rendering: %{err}'), { err }));
// eslint-disable-next-line no-console
console.error(err);
diff --git a/app/assets/javascripts/behaviors/markdown/render_metrics.js b/app/assets/javascripts/behaviors/markdown/render_metrics.js
index 37cbce46b6f..e7a2a6ce47c 100644
--- a/app/assets/javascripts/behaviors/markdown/render_metrics.js
+++ b/app/assets/javascripts/behaviors/markdown/render_metrics.js
@@ -9,7 +9,7 @@ export default function renderMetrics(elements) {
const wrapperList = [];
- elements.forEach(element => {
+ elements.forEach((element) => {
let wrapper;
const { previousElementSibling } = element;
const isFirstElementInGroup = !previousElementSibling?.urls;
@@ -33,7 +33,7 @@ export default function renderMetrics(elements) {
).then(({ default: EmbedGroup }) => {
const EmbedGroupComponent = Vue.extend(EmbedGroup);
- wrapperList.forEach(wrapper => {
+ wrapperList.forEach((wrapper) => {
// eslint-disable-next-line no-new
new EmbedGroupComponent({
el: wrapper,
diff --git a/app/assets/javascripts/behaviors/markdown/schema.js b/app/assets/javascripts/behaviors/markdown/schema.js
index 163182ab778..8bea24584cc 100644
--- a/app/assets/javascripts/behaviors/markdown/schema.js
+++ b/app/assets/javascripts/behaviors/markdown/schema.js
@@ -2,7 +2,7 @@ import { Schema } from 'prosemirror-model';
import editorExtensions from './editor_extensions';
const nodes = editorExtensions
- .filter(extension => extension.type === 'node')
+ .filter((extension) => extension.type === 'node')
.reduce(
(ns, { name, schema }) => ({
...ns,
@@ -12,7 +12,7 @@ const nodes = editorExtensions
);
const marks = editorExtensions
- .filter(extension => extension.type === 'mark')
+ .filter((extension) => extension.type === 'mark')
.reduce(
(ms, { name, schema }) => ({
...ms,
diff --git a/app/assets/javascripts/behaviors/markdown/serializer.js b/app/assets/javascripts/behaviors/markdown/serializer.js
index 70dbd8bd206..b4adf1a413f 100644
--- a/app/assets/javascripts/behaviors/markdown/serializer.js
+++ b/app/assets/javascripts/behaviors/markdown/serializer.js
@@ -2,7 +2,7 @@ import { MarkdownSerializer } from 'prosemirror-markdown';
import editorExtensions from './editor_extensions';
const nodes = editorExtensions
- .filter(extension => extension.type === 'node')
+ .filter((extension) => extension.type === 'node')
.reduce(
(ns, { name, toMarkdown }) => ({
...ns,
@@ -12,7 +12,7 @@ const nodes = editorExtensions
);
const marks = editorExtensions
- .filter(extension => extension.type === 'mark')
+ .filter((extension) => extension.type === 'mark')
.reduce(
(ms, { name, toMarkdown }) => ({
...ms,
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 84bf22586a9..def1c567cd5 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -23,7 +23,7 @@ MarkdownPreview.prototype.emptyMessage = __('Nothing to preview.');
MarkdownPreview.prototype.ajaxCache = {};
-MarkdownPreview.prototype.showPreview = function($form) {
+MarkdownPreview.prototype.showPreview = function ($form) {
const preview = $form.find('.js-md-preview');
const url = preview.data('url');
if (preview.hasClass('md-preview-loading')) {
@@ -41,7 +41,7 @@ MarkdownPreview.prototype.showPreview = function($form) {
this.hideReferencedUsers($form);
} else {
preview.addClass('md-preview-loading').text(__('Loading...'));
- this.fetchMarkdownPreview(mdText, url, response => {
+ this.fetchMarkdownPreview(mdText, url, (response) => {
let body;
if (response.body.length > 0) {
({ body } = response);
@@ -60,7 +60,7 @@ MarkdownPreview.prototype.showPreview = function($form) {
}
};
-MarkdownPreview.prototype.fetchMarkdownPreview = function(text, url, success) {
+MarkdownPreview.prototype.fetchMarkdownPreview = function (text, url, success) {
if (!url) {
return;
}
@@ -82,11 +82,11 @@ MarkdownPreview.prototype.fetchMarkdownPreview = function(text, url, success) {
.catch(() => flash(__('An error occurred while fetching markdown preview')));
};
-MarkdownPreview.prototype.hideReferencedUsers = function($form) {
+MarkdownPreview.prototype.hideReferencedUsers = function ($form) {
$form.find('.referenced-users').hide();
};
-MarkdownPreview.prototype.renderReferencedUsers = function(users, $form) {
+MarkdownPreview.prototype.renderReferencedUsers = function (users, $form) {
const referencedUsers = $form.find('.referenced-users');
if (referencedUsers.length) {
if (users.length >= this.referenceThreshold) {
@@ -98,11 +98,11 @@ MarkdownPreview.prototype.renderReferencedUsers = function(users, $form) {
}
};
-MarkdownPreview.prototype.hideReferencedCommands = function($form) {
+MarkdownPreview.prototype.hideReferencedCommands = function ($form) {
$form.find('.referenced-commands').hide();
};
-MarkdownPreview.prototype.renderReferencedCommands = function(commands, $form) {
+MarkdownPreview.prototype.renderReferencedCommands = function (commands, $form) {
const referencedCommands = $form.find('.referenced-commands');
if (commands.length > 0) {
referencedCommands.html(commands);
@@ -120,7 +120,7 @@ const writeButtonSelector = '.js-md-write-button';
lastTextareaPreviewed = null;
const markdownToolbar = $('.md-header-toolbar');
-$.fn.setupMarkdownPreview = function() {
+$.fn.setupMarkdownPreview = function () {
const $form = $(this);
$form.find('textarea.markdown-area').on('input', () => {
markdownPreview.hideReferencedUsers($form);
@@ -136,14 +136,8 @@ $(document).on('markdown-preview:show', (e, $form) => {
lastTextareaHeight = lastTextareaPreviewed.height();
// toggle tabs
- $form
- .find(writeButtonSelector)
- .parent()
- .removeClass('active');
- $form
- .find(previewButtonSelector)
- .parent()
- .addClass('active');
+ $form.find(writeButtonSelector).parent().removeClass('active');
+ $form.find(previewButtonSelector).parent().addClass('active');
// toggle content
$form.find('.md-write-holder').hide();
@@ -163,14 +157,8 @@ $(document).on('markdown-preview:hide', (e, $form) => {
}
// toggle tabs
- $form
- .find(writeButtonSelector)
- .parent()
- .addClass('active');
- $form
- .find(previewButtonSelector)
- .parent()
- .removeClass('active');
+ $form.find(writeButtonSelector).parent().addClass('active');
+ $form.find(previewButtonSelector).parent().removeClass('active');
// toggle content
$form.find('.md-write-holder').show();
@@ -194,13 +182,13 @@ $(document).on('markdown-preview:toggle', (e, keyboardEvent) => {
}
});
-$(document).on('click', previewButtonSelector, function(e) {
+$(document).on('click', previewButtonSelector, function (e) {
e.preventDefault();
const $form = $(this).closest('form');
$(document).triggerHandler('markdown-preview:show', [$form]);
});
-$(document).on('click', writeButtonSelector, function(e) {
+$(document).on('click', writeButtonSelector, function (e) {
e.preventDefault();
const $form = $(this).closest('form');
$(document).triggerHandler('markdown-preview:hide', [$form]);
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index 907cfc06e28..68e831252d6 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -30,7 +30,7 @@ function keyCodeIs(e, keyCode) {
return e.keyCode === keyCode;
}
-$(document).on('keydown.quick_submit', '.js-quick-submit', e => {
+$(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
// Enter
if (!keyCodeIs(e, 13)) {
return;
diff --git a/app/assets/javascripts/behaviors/requires_input.js b/app/assets/javascripts/behaviors/requires_input.js
index 2fa3f4fc789..b1227fb3533 100644
--- a/app/assets/javascripts/behaviors/requires_input.js
+++ b/app/assets/javascripts/behaviors/requires_input.js
@@ -23,7 +23,7 @@ $.fn.requiresInput = function requiresInput() {
function requireInput() {
// Collect the input values of *all* required fields
- const values = Array.from($(fieldSelector, $form)).map(field => field.value);
+ const values = Array.from($(fieldSelector, $form)).map((field) => field.value);
// Disable the button if any required fields are empty
if (values.length && values.some(isEmpty)) {
diff --git a/app/assets/javascripts/behaviors/secret_values.js b/app/assets/javascripts/behaviors/secret_values.js
index 5b92608d536..2f1951c97f9 100644
--- a/app/assets/javascripts/behaviors/secret_values.js
+++ b/app/assets/javascripts/behaviors/secret_values.js
@@ -30,12 +30,12 @@ export default class SecretValues {
updateDom(isRevealed) {
const values = this.container.querySelectorAll(this.valueSelector);
- values.forEach(value => {
+ values.forEach((value) => {
value.classList.toggle('hide', !isRevealed);
});
const placeholders = this.container.querySelectorAll(this.placeholderSelector);
- placeholders.forEach(placeholder => {
+ placeholders.forEach((placeholder) => {
placeholder.classList.toggle('hide', isRevealed);
});
diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
index bbcc40ab9fe..10832583783 100644
--- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js
+++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
@@ -49,10 +49,10 @@ export const keybindingGroups = [
// For each keybinding object, add a `customKeys` property populated with the
// user's custom keybindings (if the command has been customized).
// `customKeys` will be `undefined` if the command hasn't been customized.
- .map(group => {
+ .map((group) => {
return {
...group,
- keybindings: group.keybindings.map(binding => ({
+ keybindings: group.keybindings.map((binding) => ({
...binding,
customKeys: customizations[binding.command],
})),
@@ -66,7 +66,7 @@ export const keybindingGroups = [
* @example
* { "globalShortcuts.togglePerformanceBar": ["p e r f"] }
*/
-const commandToKeys = flatten(keybindingGroups.map(group => group.keybindings)).reduce(
+const commandToKeys = flatten(keybindingGroups.map((group) => group.keybindings)).reduce(
(acc, binding) => {
acc[binding.command] = binding.customKeys || binding.defaultKeys;
return acc;
@@ -87,7 +87,7 @@ const commandToKeys = flatten(keybindingGroups.map(group => group.keybindings)).
*
* Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), handler);
*/
-export const keysFor = command => {
+export const keysFor = (command) => {
if (shouldDisableShortcuts()) {
return [];
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index c0f67923191..50d2399b312 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -98,9 +98,7 @@ export default class Shortcuts {
});
// eslint-disable-next-line @gitlab/no-global-event-off
- $('.js-shortcuts-modal-trigger')
- .off('click')
- .on('click', this.onToggleHelp);
+ $('.js-shortcuts-modal-trigger').off('click').on('click', this.onToggleHelp);
if (shouldDisableShortcuts()) {
disableShortcuts();
@@ -199,7 +197,7 @@ export default class Shortcuts {
$textarea.data(LOCAL_MOUSETRAP_DATA_KEY, localMousetrap);
toolbarBtnToShortcutsMap.forEach((keyboardShortcuts, $toolbarBtn) => {
- localMousetrap.bind(keyboardShortcuts, e => {
+ localMousetrap.bind(keyboardShortcuts, (e) => {
e.preventDefault();
handler($toolbarBtn);
@@ -233,7 +231,7 @@ export default class Shortcuts {
const localMousetrap = $textarea.data(LOCAL_MOUSETRAP_DATA_KEY);
if (localMousetrap) {
- getToolbarBtnToShortcutsMap($textarea).forEach(keyboardShortcuts => {
+ getToolbarBtnToShortcutsMap($textarea).forEach((keyboardShortcuts) => {
localMousetrap.unbind(keyboardShortcuts);
});
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js
index c35a073b291..11b4fcd4e1c 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js
@@ -53,7 +53,7 @@ export default class ShortcutsBlob extends Shortcuts {
shortcircuitPermalinkButton() {
const button = this.options.fileBlobPermalinkUrlElement;
- const handleButton = e => {
+ const handleButton = (e) => {
if (!eventHasModifierKeys(e)) {
e.preventDefault();
this.moveToFilePermalink();
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index 5a5a67334d3..5e8ddeb6af7 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -39,7 +39,7 @@ export default class ShortcutsIssuable extends Shortcuts {
// ... Or come from a message
if (!foundMessage) {
if (documentFragment.originalNodes) {
- documentFragment.originalNodes.forEach(e => {
+ documentFragment.originalNodes.forEach((e) => {
let node = e;
do {
// Text nodes don't define the `matches` method
@@ -62,7 +62,7 @@ export default class ShortcutsIssuable extends Shortcuts {
const blockquoteEl = document.createElement('blockquote');
blockquoteEl.appendChild(el);
CopyAsGFM.nodeToGFM(blockquoteEl)
- .then(text => {
+ .then((text) => {
if (text.trim() === '') {
return false;
}
diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js
index 2d4f45cc365..94397d70384 100644
--- a/app/assets/javascripts/blob/3d_viewer/index.js
+++ b/app/assets/javascripts/blob/3d_viewer/index.js
@@ -68,7 +68,7 @@ export default class Renderer {
}
loadFile() {
- this.loader.load(this.container.dataset.endpoint, geo => {
+ this.loader.load(this.container.dataset.endpoint, (geo) => {
const obj = new MeshObject(geo);
this.objects.push(obj);
@@ -99,7 +99,7 @@ export default class Renderer {
}
changeObjectMaterials(type) {
- this.objects.forEach(obj => {
+ this.objects.forEach((obj) => {
obj.changeMaterial(type);
});
}
diff --git a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
index 5b781947d55..ebe2c2b3bb8 100644
--- a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
+++ b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
@@ -28,7 +28,7 @@ class BalsamiqViewer {
.then(({ data }) => {
this.renderFile(data);
})
- .catch(e => {
+ .catch((e) => {
throw new Error(e);
});
}
@@ -39,7 +39,7 @@ class BalsamiqViewer {
this.initDatabase(fileBuffer);
const previews = this.getPreviews();
- previews.forEach(preview => {
+ previews.forEach((preview) => {
const renderedPreview = this.renderPreview(preview);
container.appendChild(renderedPreview);
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js
index e8772b7240a..19bad64155d 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js
@@ -43,16 +43,14 @@ export default class BlobFileDropzone {
previewsContainer: '.dropzone-previews',
headers: csrf.headers,
init() {
- this.on('processing', function() {
+ this.on('processing', function () {
this.options.url = form.attr('action');
});
this.on('addedfile', () => {
toggleLoading(submitButton, submitButtonLoadingIcon, false);
dropzoneMessage.addClass(HIDDEN_CLASS);
- $('.dropzone-alerts')
- .html('')
- .hide();
+ $('.dropzone-alerts').html('').hide();
});
this.on('removedfile', () => {
toggleLoading(submitButton, submitButtonLoadingIcon, false);
@@ -62,7 +60,7 @@ export default class BlobFileDropzone {
$('#modal-upload-blob').modal('hide');
visitUrl(response.filePath);
});
- this.on('maxfilesexceeded', function(file) {
+ this.on('maxfilesexceeded', function (file) {
dropzoneMessage.addClass(HIDDEN_CLASS);
this.removeFile(file);
});
@@ -74,9 +72,7 @@ export default class BlobFileDropzone {
},
// Override behavior of adding error underneath preview
error(file, errorMessage) {
- const stripped = $('<div/>')
- .html(errorMessage)
- .text();
+ const stripped = $('<div/>').html(errorMessage).text();
$('.dropzone-alerts')
.html(sprintf(__('Error uploading file: %{stripped}'), { stripped }))
.show();
@@ -84,7 +80,7 @@ export default class BlobFileDropzone {
},
});
- submitButton.on('click', e => {
+ submitButton.on('click', (e) => {
e.preventDefault();
e.stopPropagation();
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
diff --git a/app/assets/javascripts/blob/blob_line_permalink_updater.js b/app/assets/javascripts/blob/blob_line_permalink_updater.js
index 62f0a56ed75..11089b299c5 100644
--- a/app/assets/javascripts/blob/blob_line_permalink_updater.js
+++ b/app/assets/javascripts/blob/blob_line_permalink_updater.js
@@ -2,12 +2,12 @@ import { getLocationHash } from '../lib/utils/url_utility';
const lineNumberRe = /^L[0-9]+/;
-const updateLineNumbersOnBlobPermalinks = linksToUpdate => {
+const updateLineNumbersOnBlobPermalinks = (linksToUpdate) => {
const hash = getLocationHash();
if (hash && lineNumberRe.test(hash)) {
const hashUrlString = `#${hash}`;
- [].concat(Array.prototype.slice.call(linksToUpdate)).forEach(permalinkButton => {
+ [].concat(Array.prototype.slice.call(linksToUpdate)).forEach((permalinkButton) => {
const baseHref =
permalinkButton.getAttribute('data-original-href') ||
(() => {
@@ -28,7 +28,7 @@ function BlobLinePermalinkUpdater(blobContentHolder, lineNumberSelector, element
}, 0);
};
- blobContentHolder.addEventListener('click', e => {
+ blobContentHolder.addEventListener('click', (e) => {
if (e.target.matches(lineNumberSelector)) {
updateBlameAndBlobPermalinkCb();
}
diff --git a/app/assets/javascripts/blob/components/blob_content_error.vue b/app/assets/javascripts/blob/components/blob_content_error.vue
index 7344b9cdff5..4c5d9831237 100644
--- a/app/assets/javascripts/blob/components/blob_content_error.vue
+++ b/app/assets/javascripts/blob/components/blob_content_error.vue
@@ -25,7 +25,7 @@ export default {
},
renderErrorReason() {
const defaultReasonPath = Object.keys(BLOB_RENDER_ERRORS.REASONS).find(
- reason => BLOB_RENDER_ERRORS.REASONS[reason].id === this.viewerError,
+ (reason) => BLOB_RENDER_ERRORS.REASONS[reason].id === this.viewerError,
);
const defaultReason = BLOB_RENDER_ERRORS.REASONS[defaultReasonPath].text;
return this.notStoredExternally
diff --git a/app/assets/javascripts/blob/components/blob_header_default_actions.vue b/app/assets/javascripts/blob/components/blob_header_default_actions.vue
index 6eddec31166..b9f2c5b42e4 100644
--- a/app/assets/javascripts/blob/components/blob_header_default_actions.vue
+++ b/app/assets/javascripts/blob/components/blob_header_default_actions.vue
@@ -16,6 +16,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['blobHash'],
props: {
rawPath: {
type: String,
@@ -32,7 +33,6 @@ export default {
default: false,
},
},
- inject: ['blobHash'],
computed: {
downloadUrl() {
return `${this.rawPath}?inline=false`;
@@ -50,7 +50,7 @@ export default {
};
</script>
<template>
- <gl-button-group>
+ <gl-button-group data-qa-selector="default_actions_container">
<gl-button
v-if="!hasRenderError"
v-gl-tooltip.hover
@@ -59,6 +59,7 @@ export default {
:disabled="copyDisabled"
:data-clipboard-target="getBlobHashTarget"
data-testid="copyContentsButton"
+ data-qa-selector="copy_contents_button"
icon="copy-to-clipboard"
category="primary"
variant="default"
diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js
index 8f64bda1ba6..c35f9934004 100644
--- a/app/assets/javascripts/blob/file_template_mediator.js
+++ b/app/assets/javascripts/blob/file_template_mediator.js
@@ -9,6 +9,7 @@ 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 DockerfileSelector from './template_selectors/dockerfile_selector';
import GitignoreSelector from './template_selectors/gitignore_selector';
import LicenseSelector from './template_selectors/license_selector';
@@ -33,24 +34,30 @@ export default class FileTemplateMediator {
this.templateSelectors = [
GitignoreSelector,
BlobCiYamlSelector,
+ BlobCiSyntaxYamlSelector,
MetricsDashboardSelector,
DockerfileSelector,
LicenseSelector,
- ].map(TemplateSelectorClass => new TemplateSelectorClass({ mediator: this }));
+ ].map((TemplateSelectorClass) => new TemplateSelectorClass({ mediator: this }));
}
initTemplateTypeSelector() {
this.typeSelector = new FileTemplateTypeSelector({
mediator: this,
- dropdownData: this.templateSelectors.map(templateSelector => {
- const cfg = templateSelector.config;
-
- return {
- name: cfg.name,
- key: cfg.key,
- id: cfg.key,
- };
- }),
+ dropdownData: this.templateSelectors
+ .map((templateSelector) => {
+ const cfg = templateSelector.config;
+
+ return {
+ name: cfg.name,
+ key: cfg.key,
+ id: cfg.key,
+ };
+ })
+ .reduce(
+ (acc, current) => (acc.find((item) => item.id === current.id) ? acc : [...acc, current]),
+ [],
+ ),
});
}
@@ -92,7 +99,7 @@ export default class FileTemplateMediator {
}
listenForPreviewMode() {
- this.$navLinks.on('click', 'a', e => {
+ this.$navLinks.on('click', 'a', (e) => {
const urlPieces = e.target.href.split('#');
const hash = urlPieces[1];
if (hash === 'preview') {
@@ -108,7 +115,7 @@ export default class FileTemplateMediator {
e.preventDefault();
}
- this.templateSelectors.forEach(selector => {
+ this.templateSelectors.forEach((selector) => {
if (selector.config.key === item.key) {
selector.show();
} else {
@@ -131,7 +138,7 @@ export default class FileTemplateMediator {
selector.renderLoading();
this.fetchFileTemplate(selector.config.type, query, data)
- .then(file => {
+ .then((file) => {
this.setEditorContent(file);
this.setFilename(name);
selector.renderLoaded();
@@ -150,12 +157,12 @@ export default class FileTemplateMediator {
initPopover(suggestCommitChanges);
}
})
- .catch(err => new Flash(`An error occurred while fetching the template: ${err}`));
+ .catch((err) => new Flash(`An error occurred while fetching the template: ${err}`));
}
displayMatchedTemplateSelector() {
const currentInput = this.getFilename();
- this.templateSelectors.forEach(selector => {
+ this.templateSelectors.forEach((selector) => {
const match = selector.config.pattern.test(currentInput);
if (match) {
@@ -167,8 +174,8 @@ export default class FileTemplateMediator {
}
fetchFileTemplate(type, query, data = {}) {
- return new Promise(resolve => {
- const resolveFile = file => resolve(file);
+ return new Promise((resolve) => {
+ const resolveFile = (file) => resolve(file);
Api.projectTemplate(this.projectId, type, query, data, resolveFile);
});
@@ -187,7 +194,7 @@ export default class FileTemplateMediator {
}
findTemplateSelectorByKey(key) {
- return this.templateSelectors.find(selector => selector.config.key === key);
+ return this.templateSelectors.find((selector) => selector.config.key === key);
}
hideTemplateSelectorMenu() {
@@ -243,6 +250,6 @@ export default class FileTemplateMediator {
}
getSelected() {
- return this.templateSelectors.find(selector => selector.selected);
+ return this.templateSelectors.find((selector) => selector.selected);
}
}
diff --git a/app/assets/javascripts/blob/notebook/notebook_viewer.vue b/app/assets/javascripts/blob/notebook/notebook_viewer.vue
index ea33d621d47..02f93e14219 100644
--- a/app/assets/javascripts/blob/notebook/notebook_viewer.vue
+++ b/app/assets/javascripts/blob/notebook/notebook_viewer.vue
@@ -45,12 +45,12 @@ export default {
loadFile() {
axios
.get(this.endpoint)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
this.json = data;
this.loading = false;
})
- .catch(e => {
+ .catch((e) => {
if (e.status !== 200) {
this.loadError = true;
}
diff --git a/app/assets/javascripts/blob/openapi/index.js b/app/assets/javascripts/blob/openapi/index.js
index 12cc2be8246..e6dc463f764 100644
--- a/app/assets/javascripts/blob/openapi/index.js
+++ b/app/assets/javascripts/blob/openapi/index.js
@@ -12,7 +12,7 @@ export default () => {
dom_id: '#js-openapi-viewer',
});
})
- .catch(error => {
+ .catch((error) => {
flash(__('Something went wrong while initializing the OpenAPI viewer'));
throw error;
});
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index 02a522dda9d..fdaa4b082f7 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -98,7 +98,7 @@ export default {
</template>
<p>
<gl-sprintf :message="$options.i18n.bodyMessage">
- <template #codeQualityLink="{content}">
+ <template #codeQualityLink="{ content }">
<gl-link :href="codeQualityLink" target="_blank" class="font-size-inherit">{{
content
}}</gl-link>
@@ -106,12 +106,12 @@ export default {
</gl-sprintf>
</p>
<gl-sprintf :message="$options.i18n.helpMessage">
- <template #beginnerLink="{content}">
+ <template #beginnerLink="{ content }">
<gl-link :href="$options.beginnerLink" target="_blank">
{{ content }}
</gl-link>
</template>
- <template #exampleLink="{content}">
+ <template #exampleLink="{ content }">
<gl-link :href="exampleLink" target="_blank">
{{ content }}
</gl-link>
diff --git a/app/assets/javascripts/blob/sketch/index.js b/app/assets/javascripts/blob/sketch/index.js
index 767e205fcaa..d257810da65 100644
--- a/app/assets/javascripts/blob/sketch/index.js
+++ b/app/assets/javascripts/blob/sketch/index.js
@@ -12,9 +12,9 @@ export default class SketchLoader {
load() {
return this.getZipFile()
- .then(data => JSZip.loadAsync(data))
- .then(asyncResult => asyncResult.files['previews/preview.png'].async('uint8array'))
- .then(content => {
+ .then((data) => JSZip.loadAsync(data))
+ .then((asyncResult) => asyncResult.files['previews/preview.png'].async('uint8array'))
+ .then((content) => {
const url = window.URL || window.webkitURL;
const blob = new Blob([new Uint8Array(content)], {
type: 'image/png',
diff --git a/app/assets/javascripts/blob/stl_viewer.js b/app/assets/javascripts/blob/stl_viewer.js
index f129b6e631e..339906adc34 100644
--- a/app/assets/javascripts/blob/stl_viewer.js
+++ b/app/assets/javascripts/blob/stl_viewer.js
@@ -3,8 +3,8 @@ import Renderer from './3d_viewer';
export default () => {
const viewer = new Renderer(document.getElementById('js-stl-viewer'));
- [].slice.call(document.querySelectorAll('.js-material-changer')).forEach(el => {
- el.addEventListener('click', e => {
+ [].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => {
+ el.addEventListener('click', (e) => {
const { target } = e;
e.preventDefault();
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
index 55edb852ee6..d0dd80932cc 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import Popover from './components/popover.vue';
-export default el =>
+export default (el) =>
new Vue({
el,
render(createElement) {
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js
index ae9bb3455f0..9fa70ce3c62 100644
--- a/app/assets/javascripts/blob/template_selector.js
+++ b/app/assets/javascripts/blob/template_selector.js
@@ -26,12 +26,12 @@ export default class TemplateSelector {
data,
filterable: true,
selectable: true,
- toggleLabel: item => item.name,
+ toggleLabel: (item) => item.name,
search: {
fields: ['name'],
},
- clicked: options => this.onDropdownClicked(options),
- text: item => item.name,
+ clicked: (options) => this.onDropdownClicked(options),
+ text: (item) => item.name,
});
}
@@ -46,7 +46,7 @@ export default class TemplateSelector {
}
listenForFilenameInput() {
- return this.$filenameInput.on('keyup blur', e => this.renderMatchedDropdown(e));
+ return this.$filenameInput.on('keyup blur', (e) => this.renderMatchedDropdown(e));
}
renderMatchedDropdown() {
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
new file mode 100644
index 00000000000..9370e170571
--- /dev/null
+++ b/app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js
@@ -0,0 +1,29 @@
+import FileTemplateSelector from '../file_template_selector';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+
+export default class BlobCiSyntaxYamlSelector extends FileTemplateSelector {
+ constructor({ mediator }) {
+ super(mediator);
+ this.config = {
+ key: 'gitlab-ci-yaml',
+ name: '.gitlab-ci.yml',
+ pattern: /(.gitlab-ci.yml)/,
+ type: 'gitlab_ci_syntax_ymls',
+ dropdown: '.js-gitlab-ci-syntax-yml-selector',
+ wrapper: '.js-gitlab-ci-syntax-yml-selector-wrap',
+ };
+ }
+
+ initDropdown() {
+ initDeprecatedJQueryDropdown(this.$dropdown, {
+ data: this.$dropdown.data('data'),
+ filterable: true,
+ selectable: true,
+ search: {
+ fields: ['name'],
+ },
+ clicked: (options) => this.reportSelectionName(options),
+ text: (item) => item.name,
+ });
+ }
+}
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 3a4e86fe572..3879a6c5742 100644
--- a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
@@ -23,8 +23,8 @@ export default class BlobCiYamlSelector extends FileTemplateSelector {
search: {
fields: ['name'],
},
- clicked: options => this.reportSelectionName(options),
- text: item => item.name,
+ clicked: (options) => this.reportSelectionName(options),
+ text: (item) => item.name,
});
}
}
diff --git a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
index 3cb4bb83930..5d976c5acdb 100644
--- a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
@@ -24,8 +24,8 @@ export default class DockerfileSelector extends FileTemplateSelector {
search: {
fields: ['name'],
},
- clicked: options => this.reportSelectionName(options),
- text: item => item.name,
+ clicked: (options) => this.reportSelectionName(options),
+ text: (item) => item.name,
});
}
}
diff --git a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
index 1721230dcb7..1bb1cbb74de 100644
--- a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
@@ -22,8 +22,8 @@ export default class BlobGitignoreSelector extends FileTemplateSelector {
search: {
fields: ['name'],
},
- clicked: options => this.reportSelectionName(options),
- text: item => item.name,
+ clicked: (options) => this.reportSelectionName(options),
+ text: (item) => item.name,
});
}
}
diff --git a/app/assets/javascripts/blob/template_selectors/license_selector.js b/app/assets/javascripts/blob/template_selectors/license_selector.js
index dafde82b1e0..affa20997e9 100644
--- a/app/assets/javascripts/blob/template_selectors/license_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/license_selector.js
@@ -22,7 +22,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
search: {
fields: ['name'],
},
- clicked: options => {
+ clicked: (options) => {
const { e } = options;
const el = options.$el;
const query = options.selectedObj;
@@ -39,7 +39,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
data,
});
},
- text: item => item.name,
+ text: (item) => item.name,
});
}
}
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 9e698bfea5d..42adab05ce3 100644
--- a/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
@@ -22,8 +22,8 @@ export default class MetricsDashboardSelector extends FileTemplateSelector {
search: {
fields: ['name'],
},
- clicked: options => this.reportSelectionName(options),
- text: item => item.name,
+ clicked: (options) => this.reportSelectionName(options),
+ text: (item) => item.name,
});
}
}
diff --git a/app/assets/javascripts/blob/template_selectors/type_selector.js b/app/assets/javascripts/blob/template_selectors/type_selector.js
index 01625911815..f74f7535d99 100644
--- a/app/assets/javascripts/blob/template_selectors/type_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/type_selector.js
@@ -17,8 +17,8 @@ export default class FileTemplateTypeSelector extends FileTemplateSelector {
data: this.config.dropdownData,
filterable: false,
selectable: true,
- clicked: options => this.mediator.selectTemplateTypeOptions(options),
- text: item => item.name,
+ clicked: (options) => this.mediator.selectTemplateTypeOptions(options),
+ text: (item) => item.name,
});
}
}
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 01350acad0c..4e6ec20ec64 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -7,7 +7,7 @@ import eventHub from '../../notes/event_hub';
import { __ } from '~/locale';
import { fixTitle } from '~/tooltips';
-const loadRichBlobViewer = type => {
+const loadRichBlobViewer = (type) => {
switch (type) {
case 'balsamiq':
return import(/* webpackChunkName: 'balsamiq_viewer' */ '../balsamiq_viewer');
@@ -30,8 +30,8 @@ export const handleBlobRichViewer = (viewer, type) => {
if (!viewer || !type) return;
loadRichBlobViewer(type)
- .then(module => module?.default(viewer))
- .catch(error => {
+ .then((module) => module?.default(viewer))
+ .catch((error) => {
Flash(__('Error loading file viewer.'));
throw error;
});
@@ -84,7 +84,7 @@ export default class BlobViewer {
initBindings() {
if (this.switcherBtns.length) {
- Array.from(this.switcherBtns).forEach(el => {
+ Array.from(this.switcherBtns).forEach((el) => {
el.addEventListener('click', this.switchViewHandler.bind(this));
});
}
@@ -155,7 +155,7 @@ export default class BlobViewer {
this.toggleCopyButtonState();
BlobViewer.loadViewer(newViewer)
- .then(viewer => {
+ .then((viewer) => {
$(viewer).renderGFM();
this.$fileHolder.trigger('highlight:line');
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index 678044687a9..7c2217a59e9 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -75,7 +75,7 @@ export default () => {
});
initPopovers();
})
- .catch(e => createFlash(e));
+ .catch((e) => createFlash(e));
cancelLink.on('click', () => {
window.onbeforeunload = null;
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 1bc51aa1d6f..c7f66a357f3 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -5,7 +5,7 @@ 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/editor_file_template_ext';
+import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
import { insertFinalNewline } from '~/lib/utils/text_utility';
export default class EditBlob {
@@ -16,12 +16,12 @@ export default class EditBlob {
this.configureMonacoEditor();
if (this.options.isMarkdown) {
- import('~/editor/editor_markdown_ext')
+ import('~/editor/extensions/editor_markdown_ext')
.then(({ EditorMarkdownExtension: MarkdownExtension } = {}) => {
this.editor.use(new MarkdownExtension());
addEditorMarkdownListeners(this.editor);
})
- .catch(e => createFlash(`${BLOB_EDITOR_ERROR}: ${e}`));
+ .catch((e) => createFlash(`${BLOB_EDITOR_ERROR}: ${e}`));
}
this.initModePanesAndLinks();
@@ -66,7 +66,7 @@ export default class EditBlob {
initModePanesAndLinks() {
this.$editModePanes = $('.js-edit-mode-pane');
this.$editModeLinks = $('.js-edit-mode a');
- this.$editModeLinks.on('click', e => this.editModeLinkClickHandler(e));
+ this.$editModeLinks.on('click', (e) => this.editModeLinkClickHandler(e));
}
editModeLinkClickHandler(e) {
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index e5ff41dab74..965d3571f42 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,5 +1,4 @@
import { sortBy } from 'lodash';
-import axios from '~/lib/utils/axios_utils';
import { ListType } from './constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
@@ -42,14 +41,14 @@ export function formatListIssues(listIssues) {
const listData = listIssues.nodes.reduce((map, list) => {
listIssuesCount = list.issues.count;
- let sortedIssues = list.issues.edges.map(issueNode => ({
+ let sortedIssues = list.issues.edges.map((issueNode) => ({
...issueNode.node,
}));
sortedIssues = sortBy(sortedIssues, 'relativePosition');
return {
...map,
- [list.id]: sortedIssues.map(i => {
+ [list.id]: sortedIssues.map((i) => {
const id = getIdFromGraphQLId(i.id);
const listIssue = {
@@ -83,49 +82,64 @@ export function fullBoardId(boardId) {
return `gid://gitlab/Board/${boardId}`;
}
+export function fullIterationId(id) {
+ return `gid://gitlab/Iteration/${id}`;
+}
+
+export function fullUserId(id) {
+ return `gid://gitlab/User/${id}`;
+}
+
+export function fullMilestoneId(id) {
+ return `gid://gitlab/Milestone/${id}`;
+}
+
export function fullLabelId(label) {
- if (label.project_id !== null) {
+ if (label.project_id && label.project_id !== null) {
return `gid://gitlab/ProjectLabel/${label.id}`;
}
return `gid://gitlab/GroupLabel/${label.id}`;
}
+export function formatIssueInput(issueInput, boardConfig) {
+ const { labelIds = [], assigneeIds = [] } = issueInput;
+ const { labels, assigneeId, milestoneId } = boardConfig;
+
+ return {
+ milestoneId: milestoneId ? fullMilestoneId(milestoneId) : null,
+ ...issueInput,
+ labelIds: [...labelIds, ...(labels?.map((l) => fullLabelId(l)) || [])],
+ assigneeIds: [...assigneeIds, ...(assigneeId ? [fullUserId(assigneeId)] : [])],
+ };
+}
+
export function moveIssueListHelper(issue, fromList, toList) {
const updatedIssue = issue;
if (
toList.listType === ListType.label &&
- !updatedIssue.labels.find(label => label.id === toList.label.id)
+ !updatedIssue.labels.find((label) => label.id === toList.label.id)
) {
updatedIssue.labels.push(toList.label);
}
if (fromList?.label && fromList.listType === ListType.label) {
- updatedIssue.labels = updatedIssue.labels.filter(label => fromList.label.id !== label.id);
+ updatedIssue.labels = updatedIssue.labels.filter((label) => fromList.label.id !== label.id);
}
if (
toList.listType === ListType.assignee &&
- !updatedIssue.assignees.find(assignee => assignee.id === toList.assignee.id)
+ !updatedIssue.assignees.find((assignee) => assignee.id === toList.assignee.id)
) {
updatedIssue.assignees.push(toList.assignee);
}
if (fromList?.assignee && fromList.listType === ListType.assignee) {
updatedIssue.assignees = updatedIssue.assignees.filter(
- assignee => assignee.id !== fromList.assignee.id,
+ (assignee) => assignee.id !== fromList.assignee.id,
);
}
return updatedIssue;
}
-export function getBoardsPath(endpoint, board) {
- const path = `${endpoint}${board.id ? `/${board.id}` : ''}.json`;
-
- if (board.id) {
- return axios.put(path, { board });
- }
- return axios.post(path, { board });
-}
-
export function isListDraggable(list) {
return list.listType !== ListType.backlog && list.listType !== ListType.closed;
}
@@ -141,6 +155,6 @@ export default {
formatListIssues,
fullBoardId,
fullLabelId,
- getBoardsPath,
+ fullIterationId,
isListDraggable,
};
diff --git a/app/assets/javascripts/boards/components/board_assignee_dropdown.vue b/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
index 1469efae5a6..5d381f9a570 100644
--- a/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
+++ b/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
@@ -119,7 +119,7 @@ export default {
this.selected = this.selected.concat(name);
},
unselect(name) {
- this.selected = this.selected.filter(user => user.username !== name);
+ this.selected = this.selected.filter((user) => user.username !== name);
},
saveAssignees() {
this.setAssignees(this.selectedUserNames);
diff --git a/app/assets/javascripts/boards/components/board_card_layout.vue b/app/assets/javascripts/boards/components/board_card_layout.vue
index f796acd2303..0a2301394c1 100644
--- a/app/assets/javascripts/boards/components/board_card_layout.vue
+++ b/app/assets/javascripts/boards/components/board_card_layout.vue
@@ -1,12 +1,17 @@
<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 { ISSUABLE } from '~/boards/constants';
export default {
- name: 'BoardsIssueCard',
+ name: 'BoardCardLayout',
components: {
- IssueCardInner,
+ IssueCardInner: gon.features?.graphqlBoardLists ? IssueCardInner : IssueCardInnerDeprecated,
},
+ mixins: [glFeatureFlagMixin()],
props: {
list: {
type: Object,
@@ -41,11 +46,13 @@ export default {
};
},
computed: {
+ ...mapGetters(['isSwimlanesOn']),
multiSelectVisible() {
- return this.multiSelect.list.findIndex(issue => issue.id === this.issue.id) > -1;
+ return this.multiSelect.list.findIndex((issue) => issue.id === this.issue.id) > -1;
},
},
methods: {
+ ...mapActions(['setActiveId']),
mouseDown() {
this.showDetail = true;
},
@@ -56,6 +63,11 @@ 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) {
+ this.setActiveId({ id: this.issue.id, sidebarType: ISSUABLE });
+ return;
+ }
+
const isMultiSelect = e.ctrlKey || e.metaKey;
if (this.showDetail || isMultiSelect) {
@@ -80,7 +92,7 @@ export default {
:data-issue-iid="issue.iid"
:data-issue-path="issue.referencePath"
data-testid="board_card"
- class="board-card p-3 rounded"
+ class="board-card gl-p-5 gl-rounded-base"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event)"
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index 753e6941c43..9f0eef844f6 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -1,16 +1,19 @@
<script>
-// This component is being replaced in favor of './board_column_new.vue' for GraphQL boards
-import Sortable from 'sortablejs';
+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 boardsStore from '../stores/boards_store';
-import { getBoardSortableDefaultOptions, sortableEnd } from '../mixins/sortable_default_options';
+import { isListDraggable } from '../boards_util';
export default {
components: {
BoardListHeader,
BoardList,
},
+ inject: {
+ boardId: {
+ default: '',
+ },
+ },
props: {
list: {
type: Object,
@@ -27,58 +30,27 @@ export default {
default: false,
},
},
- inject: {
- boardId: {
- default: '',
- },
- },
- data() {
- return {
- detailIssue: boardsStore.detail,
- filter: boardsStore.filter,
- };
- },
computed: {
+ ...mapState(['filterParams']),
+ ...mapGetters(['getIssuesByList']),
listIssues() {
- return this.list.issues;
+ return this.getIssuesByList(this.list.id);
+ },
+ isListDraggable() {
+ return isListDraggable(this.list);
},
},
watch: {
- filter: {
+ filterParams: {
handler() {
- this.list.page = 1;
- this.list.getIssues(true).catch(() => {
- // TODO: handle request error
- });
+ this.fetchIssuesForList({ listId: this.list.id });
},
deep: true,
+ immediate: true,
},
},
- mounted() {
- const instance = this;
-
- const sortableOptions = getBoardSortableDefaultOptions({
- disabled: this.disabled,
- group: 'boards',
- draggable: '.is-draggable',
- handle: '.js-board-handle',
- onEnd(e) {
- sortableEnd();
-
- const sortable = this;
-
- if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) {
- const order = sortable.toArray();
- const list = boardsStore.findList('id', parseInt(e.item.dataset.id, 10));
-
- instance.$nextTick(() => {
- boardsStore.moveList(list, order);
- });
- }
- },
- });
-
- Sortable.create(this.$el.parentNode, sortableOptions);
+ methods: {
+ ...mapActions(['fetchIssuesForList']),
},
};
</script>
@@ -86,20 +58,25 @@ export default {
<template>
<div
:class="{
- 'is-draggable': !list.preset,
- 'is-expandable': list.isExpandable,
- 'is-collapsed': !list.isExpanded,
- 'board-type-assignee': list.type === 'assignee',
+ 'is-draggable': isListDraggable,
+ 'is-collapsed': list.collapsed,
+ 'board-type-assignee': list.listType === 'assignee',
}"
:data-id="list.id"
- class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal"
+ class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal is-expandable"
data-qa-selector="board_list"
>
<div
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
>
<board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
- <board-list ref="board-list" :disabled="disabled" :issues="listIssues" :list="list" />
+ <board-list
+ ref="board-list"
+ :disabled="disabled"
+ :issues="listIssues"
+ :list="list"
+ :can-admin-list="canAdminList"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_column_deprecated.vue b/app/assets/javascripts/boards/components/board_column_deprecated.vue
new file mode 100644
index 00000000000..35688efceb4
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_column_deprecated.vue
@@ -0,0 +1,105 @@
+<script>
+// 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';
+
+export default {
+ components: {
+ BoardListHeader,
+ BoardList,
+ },
+ inject: {
+ boardId: {
+ default: '',
+ },
+ },
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ required: true,
+ },
+ canAdminList: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ detailIssue: boardsStore.detail,
+ filter: boardsStore.filter,
+ };
+ },
+ computed: {
+ listIssues() {
+ return this.list.issues;
+ },
+ },
+ watch: {
+ filter: {
+ handler() {
+ this.list.page = 1;
+ this.list.getIssues(true).catch(() => {
+ // TODO: handle request error
+ });
+ },
+ deep: true,
+ },
+ },
+ mounted() {
+ const instance = this;
+
+ const sortableOptions = getBoardSortableDefaultOptions({
+ disabled: this.disabled,
+ group: 'boards',
+ draggable: '.is-draggable',
+ handle: '.js-board-handle',
+ onEnd(e) {
+ sortableEnd();
+
+ const sortable = this;
+
+ if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) {
+ const order = sortable.toArray();
+ const list = boardsStore.findList('id', parseInt(e.item.dataset.id, 10));
+
+ instance.$nextTick(() => {
+ boardsStore.moveList(list, order);
+ });
+ }
+ },
+ });
+
+ Sortable.create(this.$el.parentNode, sortableOptions);
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{
+ 'is-draggable': !list.preset,
+ 'is-expandable': list.isExpandable,
+ 'is-collapsed': !list.isExpanded,
+ 'board-type-assignee': list.type === 'assignee',
+ }"
+ :data-id="list.id"
+ class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal"
+ data-qa-selector="board_list"
+ >
+ <div
+ class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
+ >
+ <board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
+ <board-list ref="board-list" :disabled="disabled" :issues="listIssues" :list="list" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_column_new.vue b/app/assets/javascripts/boards/components/board_column_new.vue
deleted file mode 100644
index 7839f45c48b..00000000000
--- a/app/assets/javascripts/boards/components/board_column_new.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<script>
-import { mapGetters, mapActions, mapState } from 'vuex';
-import BoardListHeader from 'ee_else_ce/boards/components/board_list_header_new.vue';
-import BoardList from './board_list_new.vue';
-import { isListDraggable } from '../boards_util';
-
-export default {
- components: {
- BoardListHeader,
- BoardList,
- },
- props: {
- list: {
- type: Object,
- default: () => ({}),
- required: false,
- },
- disabled: {
- type: Boolean,
- required: true,
- },
- canAdminList: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- inject: {
- boardId: {
- default: '',
- },
- },
- computed: {
- ...mapState(['filterParams']),
- ...mapGetters(['getIssuesByList']),
- listIssues() {
- return this.getIssuesByList(this.list.id);
- },
- isListDraggable() {
- return isListDraggable(this.list);
- },
- },
- watch: {
- filterParams: {
- handler() {
- this.fetchIssuesForList({ listId: this.list.id });
- },
- deep: true,
- immediate: true,
- },
- },
- methods: {
- ...mapActions(['fetchIssuesForList']),
- },
-};
-</script>
-
-<template>
- <div
- :class="{
- 'is-draggable': isListDraggable,
- 'is-collapsed': list.collapsed,
- 'board-type-assignee': list.listType === 'assignee',
- }"
- :data-id="list.id"
- class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal is-expandable"
- data-qa-selector="board_list"
- >
- <div
- class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
- >
- <board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
- <board-list
- ref="board-list"
- :disabled="disabled"
- :issues="listIssues"
- :list="list"
- :can-admin-list="canAdminList"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_configuration_options.vue b/app/assets/javascripts/boards/components/board_configuration_options.vue
index 99d1e4a2611..b8ee930a8c9 100644
--- a/app/assets/javascripts/boards/components/board_configuration_options.vue
+++ b/app/assets/javascripts/boards/components/board_configuration_options.vue
@@ -6,36 +6,13 @@ export default {
GlFormCheckbox,
},
props: {
- currentBoard: {
- type: Object,
- required: true,
- },
- board: {
- type: Object,
+ hideBacklogList: {
+ type: Boolean,
required: true,
},
- isNewForm: {
+ hideClosedList: {
type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- const { hide_backlog_list: hideBacklogList, hide_closed_list: hideClosedList } = this.isNewForm
- ? this.board
- : this.currentBoard;
-
- return {
- hideClosedList,
- hideBacklogList,
- };
- },
- methods: {
- changeClosedList(checked) {
- this.board.hideClosedList = !checked;
- },
- changeBacklogList(checked) {
- this.board.hideBacklogList = !checked;
+ required: true,
},
},
};
@@ -52,13 +29,13 @@ export default {
<gl-form-checkbox
:checked="!hideBacklogList"
data-testid="backlog-list-checkbox"
- @change="changeBacklogList"
+ @change="$emit('update:hideBacklogList', !hideBacklogList)"
>{{ __('Show the Open list') }}
</gl-form-checkbox>
<gl-form-checkbox
:checked="!hideClosedList"
data-testid="closed-list-checkbox"
- @change="changeClosedList"
+ @change="$emit('update:hideClosedList', !hideClosedList)"
>{{ __('Show the Closed list') }}
</gl-form-checkbox>
</div>
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index b366aa6fdb3..19254343208 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -3,15 +3,15 @@ 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 BoardColumnNew from './board_column_new.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';
export default {
components: {
- BoardColumn: gon.features?.graphqlBoardLists ? BoardColumnNew : BoardColumn,
+ BoardColumn: gon.features?.graphqlBoardLists ? BoardColumn : BoardColumnDeprecated,
BoardContentSidebar: () => import('ee_component/boards/components/board_content_sidebar.vue'),
EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'),
GlAlert,
@@ -20,7 +20,8 @@ export default {
props: {
lists: {
type: Array,
- required: true,
+ required: false,
+ default: () => [],
},
canAdminList: {
type: Boolean,
@@ -53,7 +54,7 @@ export default {
fallbackOnBody: false,
group: 'boards-list',
tag: 'div',
- value: this.lists,
+ value: this.boardListsToUse,
};
return this.canDragColumns ? options : {};
@@ -108,14 +109,14 @@ export default {
/>
</component>
- <template v-else>
- <epics-swimlanes
- ref="swimlanes"
- :lists="boardListsToUse"
- :can-admin-list="canAdminList"
- :disabled="disabled"
- />
- <board-content-sidebar />
- </template>
+ <epics-swimlanes
+ v-else
+ ref="swimlanes"
+ :lists="boardListsToUse"
+ :can-admin-list="canAdminList"
+ :disabled="disabled"
+ />
+
+ <board-content-sidebar v-if="isSwimlanesOn || glFeatures.graphqlBoardLists" />
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index dab934352ca..c701ecd3040 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -1,20 +1,24 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { pick } from 'lodash';
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 { fullBoardId, getBoardsPath } from '../boards_util';
+import { fullLabelId, fullBoardId } from '../boards_util';
import BoardConfigurationOptions from './board_configuration_options.vue';
-import createBoardMutation from '../graphql/board.mutation.graphql';
+import updateBoardMutation from '../graphql/board_update.mutation.graphql';
+import createBoardMutation from '../graphql/board_create.mutation.graphql';
+import destroyBoardMutation from '../graphql/board_destroy.mutation.graphql';
const boardDefaults = {
id: false,
name: '',
labels: [],
milestone_id: undefined,
+ iteration_id: undefined,
assignee: {},
assignee_id: undefined,
weight: null,
@@ -46,6 +50,14 @@ export default {
GlModal,
BoardConfigurationOptions,
},
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ rootPath: {
+ default: '',
+ },
+ },
props: {
canAdminBoard: {
type: Boolean,
@@ -89,11 +101,6 @@ export default {
required: true,
},
},
- inject: {
- endpoints: {
- default: {},
- },
- },
data() {
return {
board: { ...boardDefaults, ...this.currentBoard },
@@ -154,14 +161,44 @@ export default {
text: this.$options.i18n.cancelButtonText,
};
},
- boardPayload() {
- const { assignee, milestone, labels } = this.board;
- return {
- ...this.board,
- assignee_id: assignee?.id,
- milestone_id: milestone?.id,
- label_ids: labels.length ? labels.map(b => b.id) : [''],
+ currentMutation() {
+ return this.board.id ? updateBoardMutation : createBoardMutation;
+ },
+ mutationVariables() {
+ const { board } = this;
+ /* eslint-disable @gitlab/require-i18n-strings */
+ let baseMutationVariables = {
+ name: board.name,
+ hideBacklogList: board.hide_backlog_list,
+ hideClosedList: board.hide_closed_list,
};
+
+ if (this.scopedIssueBoardFeatureEnabled) {
+ baseMutationVariables = {
+ ...baseMutationVariables,
+ weight: board.weight,
+ assigneeId: board.assignee?.id ? convertToGraphQLId('User', board.assignee.id) : null,
+ milestoneId:
+ board.milestone?.id || board.milestone?.id === 0
+ ? convertToGraphQLId('Milestone', board.milestone.id)
+ : null,
+ labelIds: board.labels.map(fullLabelId),
+ iterationId: board.iteration_id
+ ? convertToGraphQLId('Iteration', board.iteration_id)
+ : null,
+ };
+ }
+ /* eslint-enable @gitlab/require-i18n-strings */
+ return board.id
+ ? {
+ ...baseMutationVariables,
+ id: fullBoardId(board.id),
+ }
+ : {
+ ...baseMutationVariables,
+ projectPath: this.projectId ? this.fullPath : null,
+ groupPath: this.groupId ? this.fullPath : null,
+ };
},
},
mounted() {
@@ -171,55 +208,51 @@ export default {
}
},
methods: {
- callBoardMutation(id) {
- return this.$apollo.mutate({
- mutation: createBoardMutation,
- variables: {
- ...pick(this.boardPayload, ['hideClosedList', 'hideBacklogList']),
- id,
- },
- });
+ setIteration(iterationId) {
+ this.board.iteration_id = iterationId;
},
- async updateBoard() {
- const responses = await Promise.all([
- // Remove unnecessary REST API call when https://gitlab.com/gitlab-org/gitlab/-/issues/282299#note_462996301 is resolved
- getBoardsPath(this.endpoints.boardsEndpoint, this.boardPayload),
- this.callBoardMutation(fullBoardId(this.boardPayload.id)),
- ]);
+ async createOrUpdateBoard() {
+ const response = await this.$apollo.mutate({
+ mutation: this.currentMutation,
+ variables: { input: this.mutationVariables },
+ });
- return responses[0].data;
- },
- async createBoard() {
- // TODO: change this to use `createBoard` mutation https://gitlab.com/gitlab-org/gitlab/-/issues/292466 is resolved
- const boardData = await getBoardsPath(this.endpoints.boardsEndpoint, this.boardPayload);
- this.callBoardMutation(fullBoardId(boardData.data.id));
+ if (!this.board.id) {
+ return response.data.createBoard.board.webPath;
+ }
- return boardData.data || boardData;
+ const path = response.data.updateBoard.board.webPath;
+ const param = getParameterByName('group_by')
+ ? `?group_by=${getParameterByName('group_by')}`
+ : '';
+ return `${path}${param}`;
},
- submit() {
+ async submit() {
if (this.board.name.length === 0) return;
this.isLoading = true;
if (this.isDeleteForm) {
- boardsStore
- .deleteBoard(this.currentBoard)
- .then(() => {
- this.isLoading = false;
- visitUrl(boardsStore.rootPath);
- })
- .catch(() => {
- Flash(this.$options.i18n.deleteErrorMessage);
- this.isLoading = false;
+ try {
+ await this.$apollo.mutate({
+ mutation: destroyBoardMutation,
+ variables: {
+ id: fullBoardId(this.board.id),
+ },
});
+ visitUrl(this.rootPath);
+ } catch {
+ Flash(this.$options.i18n.deleteErrorMessage);
+ } finally {
+ this.isLoading = false;
+ }
} else {
- const boardAction = this.boardPayload.id ? this.updateBoard : this.createBoard;
- boardAction()
- .then(data => {
- visitUrl(data.board_path);
- })
- .catch(() => {
- Flash(this.$options.i18n.saveErrorMessage);
- this.isLoading = false;
- });
+ try {
+ const url = await this.createOrUpdateBoard();
+ visitUrl(url);
+ } catch {
+ Flash(this.$options.i18n.saveErrorMessage);
+ } finally {
+ this.isLoading = false;
+ }
}
},
cancel() {
@@ -273,9 +306,8 @@ export default {
</div>
<board-configuration-options
- :is-new-form="isNewForm"
- :board="board"
- :current-board="currentBoard"
+ :hide-backlog-list.sync="board.hide_backlog_list"
+ :hide-closed-list.sync="board.hide_closed_list"
/>
<board-scope
@@ -289,6 +321,7 @@ export default {
:project-id="projectId"
:group-id="groupId"
:weights="weights"
+ @set-iteration="setIteration"
/>
</form>
</gl-modal>
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 1f87b563e73..b6e4d0980fa 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -1,27 +1,24 @@
<script>
-import { Sortable, MultiDrag } from 'sortablejs';
+import Draggable from 'vuedraggable';
+import { mapActions, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
-import boardNewIssue from './board_new_issue.vue';
-import boardCard from './board_card.vue';
+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 boardsStore from '../stores/boards_store';
import { sprintf, __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import {
- getBoardSortableDefaultOptions,
- sortableStart,
- sortableEnd,
-} from '../mixins/sortable_default_options';
-
-// This component is being replaced in favor of './board_list_new.vue' for GraphQL boards
-
-Sortable.mount(new MultiDrag());
export default {
name: 'BoardList',
+ i18n: {
+ loadingIssues: __('Loading issues'),
+ loadingMoreissues: __('Loading more issues'),
+ showingAllIssues: __('Showing all issues'),
+ },
components: {
- boardCard,
- boardNewIssue,
+ BoardCard,
+ BoardNewIssue,
GlLoadingIcon,
},
props: {
@@ -37,55 +34,67 @@ export default {
type: Array,
required: true,
},
+ canAdminList: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
scrollOffset: 250,
- filters: boardsStore.state.filters,
showCount: false,
showIssueForm: false,
};
},
computed: {
+ ...mapState(['pageInfoByListId', 'listsFlags']),
paginatedIssueText() {
return sprintf(__('Showing %{pageSize} of %{total} issues'), {
- pageSize: this.list.issues.length,
- total: this.list.issuesSize,
+ pageSize: this.issues.length,
+ total: this.list.issuesCount,
});
},
issuesSizeExceedsMax() {
- return this.list.maxIssueCount > 0 && this.list.issuesSize > this.list.maxIssueCount;
+ return this.list.maxIssueCount > 0 && this.list.issuesCount > this.list.maxIssueCount;
+ },
+ hasNextPage() {
+ return this.pageInfoByListId[this.list.id].hasNextPage;
},
loading() {
- return this.list.loading;
+ return this.listsFlags[this.list.id]?.isLoading;
+ },
+ loadingMore() {
+ return this.listsFlags[this.list.id]?.isLoadingMore;
+ },
+ listRef() {
+ // When list is draggable, the reference to the list needs to be accessed differently
+ return this.canAdminList ? this.$refs.list.$el : this.$refs.list;
+ },
+ showingAllIssues() {
+ return this.issues.length === this.list.issuesCount;
+ },
+ treeRootWrapper() {
+ return this.canAdminList ? Draggable : 'ul';
+ },
+ treeRootOptions() {
+ const options = {
+ ...defaultSortableConfig,
+ fallbackOnBody: false,
+ group: 'board-list',
+ tag: 'ul',
+ 'ghost-class': 'board-card-drag-active',
+ 'data-list-id': this.list.id,
+ value: this.issues,
+ };
+
+ return this.canAdminList ? options : {};
},
},
watch: {
- filters: {
- handler() {
- this.list.loadingMore = false;
- this.$refs.list.scrollTop = 0;
- },
- deep: true,
- },
issues() {
this.$nextTick(() => {
- if (
- this.scrollHeight() <= this.listHeight() &&
- this.list.issuesSize > this.list.issues.length &&
- this.list.isExpanded
- ) {
- this.list.page += 1;
- this.list.getIssues(false).catch(() => {
- // TODO: handle request error
- });
- }
-
- if (this.scrollHeight() > Math.ceil(this.listHeight())) {
- this.showCount = true;
- } else {
- this.showCount = false;
- }
+ this.showCount = this.scrollHeight() > Math.ceil(this.listHeight());
});
},
},
@@ -94,315 +103,90 @@ export default {
eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
},
mounted() {
- // TODO: Use Draggable in ./board_list_new.vue to drag & drop issue
- // https://gitlab.com/gitlab-org/gitlab/-/issues/218164
- const multiSelectOpts = {
- multiDrag: true,
- selectedClass: 'js-multi-select',
- animation: 500,
- };
-
- const options = getBoardSortableDefaultOptions({
- scroll: true,
- disabled: this.disabled,
- filter: '.board-list-count, .is-disabled',
- dataIdAttr: 'data-issue-id',
- removeCloneOnHide: false,
- ...multiSelectOpts,
- group: {
- name: 'issues',
- /**
- * Dynamically determine between which containers
- * items can be moved or copied as
- * Assignee lists (EE feature) require this behavior
- */
- pull: (to, from, dragEl, e) => {
- // As per Sortable's docs, `to` should provide
- // reference to exact sortable container on which
- // we're trying to drag element, but either it is
- // a library's bug or our markup structure is too complex
- // that `to` never points to correct container
- // See https://github.com/RubaXa/Sortable/issues/1037
- //
- // So we use `e.target` which is always accurate about
- // which element we're currently dragging our card upon
- // So from there, we can get reference to actual container
- // and thus the container type to enable Copy or Move
- if (e.target) {
- const containerEl =
- e.target.closest('.js-board-list') || e.target.querySelector('.js-board-list');
- const toBoardType = containerEl.dataset.boardType;
- const cloneActions = {
- label: ['milestone', 'assignee'],
- assignee: ['milestone', 'label'],
- milestone: ['label', 'assignee'],
- };
-
- if (toBoardType) {
- const fromBoardType = this.list.type;
- // For each list we check if the destination list is
- // a the list were we should clone the issue
- const shouldClone = Object.entries(cloneActions).some(
- entry => fromBoardType === entry[0] && entry[1].includes(toBoardType),
- );
-
- if (shouldClone) {
- return 'clone';
- }
- }
- }
-
- return true;
- },
- revertClone: true,
- },
- onStart: e => {
- const card = this.$refs.issue[e.oldIndex];
-
- card.showDetail = false;
-
- const { list } = card;
-
- const issue = list.findIssue(Number(e.item.dataset.issueId));
-
- boardsStore.startMoving(list, issue);
-
- this.$root.$emit('bv::hide::tooltip');
-
- sortableStart();
- },
- onAdd: e => {
- const { items = [], newIndicies = [] } = e;
- if (items.length) {
- // Not using e.newIndex here instead taking a min of all
- // the newIndicies. Basically we have to find that during
- // a drop what is the index we're going to start putting
- // all the dropped elements from.
- const newIndex = Math.min(...newIndicies.map(obj => obj.index).filter(i => i !== -1));
- const issues = items.map(item =>
- boardsStore.moving.list.findIssue(Number(item.dataset.issueId)),
- );
-
- boardsStore.moveMultipleIssuesToList({
- listFrom: boardsStore.moving.list,
- listTo: this.list,
- issues,
- newIndex,
- });
- } else {
- boardsStore.moveIssueToList(
- boardsStore.moving.list,
- this.list,
- boardsStore.moving.issue,
- e.newIndex,
- );
- this.$nextTick(() => {
- e.item.remove();
- });
- }
- },
- onUpdate: e => {
- const sortedArray = this.sortable.toArray().filter(id => id !== '-1');
-
- const { items = [], newIndicies = [], oldIndicies = [] } = e;
- if (items.length) {
- const newIndex = Math.min(...newIndicies.map(obj => obj.index));
- const issues = items.map(item =>
- boardsStore.moving.list.findIssue(Number(item.dataset.issueId)),
- );
- boardsStore.moveMultipleIssuesInList({
- list: this.list,
- issues,
- oldIndicies: oldIndicies.map(obj => obj.index),
- newIndex,
- idArray: sortedArray,
- });
- e.items.forEach(el => {
- Sortable.utils.deselect(el);
- });
- boardsStore.clearMultiSelect();
- return;
- }
-
- boardsStore.moveIssueInList(
- this.list,
- boardsStore.moving.issue,
- e.oldIndex,
- e.newIndex,
- sortedArray,
- );
- },
- onEnd: e => {
- const { items = [], clones = [], to } = e;
-
- // This is not a multi select operation
- if (!items.length && !clones.length) {
- sortableEnd();
- return;
- }
-
- let toList;
- if (to) {
- const containerEl = to.closest('.js-board-list');
- toList = boardsStore.findList('id', Number(containerEl.dataset.board), '');
- }
-
- /**
- * onEnd is called irrespective if the cards were moved in the
- * same list or the other list. Don't remove items if it's same list.
- */
- const isSameList = toList && toList.id === this.list.id;
- if (toList && !isSameList && boardsStore.shouldRemoveIssue(this.list, toList)) {
- const issues = items.map(item => this.list.findIssue(Number(item.dataset.issueId)));
- if (
- issues.filter(Boolean).length &&
- !boardsStore.issuesAreContiguous(this.list, issues)
- ) {
- const indexes = [];
- const ids = this.list.issues.map(i => i.id);
- issues.forEach(issue => {
- const index = ids.indexOf(issue.id);
- if (index > -1) {
- indexes.push(index);
- }
- });
-
- // Descending sort because splice would cause index discrepancy otherwise
- const sortedIndexes = indexes.sort((a, b) => (a < b ? 1 : -1));
-
- sortedIndexes.forEach(i => {
- /**
- * **setTimeout and splice each element one-by-one in a loop
- * is intended.**
- *
- * The problem here is all the indexes are in the list but are
- * non-contiguous. Due to that, when we splice all the indexes,
- * at once, Vue -- during a re-render -- is unable to find reference
- * nodes and the entire app crashes.
- *
- * If the indexes are contiguous, this piece of code is not
- * executed. If it is, this is a possible regression. Only when
- * issue indexes are far apart, this logic should ever kick in.
- */
- setTimeout(() => {
- this.list.issues.splice(i, 1);
- }, 0);
- });
- }
- }
-
- if (!toList) {
- createFlash(__('Something went wrong while performing the action.'));
- }
-
- if (!isSameList) {
- boardsStore.clearMultiSelect();
-
- // Since Vue's list does not re-render the same keyed item, we'll
- // remove `multi-select` class to express it's unselected
- if (clones && clones.length) {
- clones.forEach(el => el.classList.remove('multi-select'));
- }
-
- // Due to some bug which I am unable to figure out
- // Sortable does not deselect some pending items from the
- // source list.
- // We'll just do it forcefully here.
- Array.from(document.querySelectorAll('.js-multi-select') || []).forEach(item => {
- Sortable.utils.deselect(item);
- });
-
- /**
- * SortableJS leaves all the moving items "as is" on the DOM.
- * Vue picks up and rehydrates the DOM, but we need to explicity
- * remove the "trash" items from the DOM.
- *
- * This is in parity to the logic on single item move from a list/in
- * a list. For reference, look at the implementation of onAdd method.
- */
- this.$nextTick(() => {
- if (items && items.length) {
- items.forEach(item => {
- item.remove();
- });
- }
- });
- }
- sortableEnd();
- },
- onMove(e) {
- return !e.related.classList.contains('board-list-count');
- },
- onSelect(e) {
- const {
- item: { classList },
- } = e;
-
- if (
- classList &&
- classList.contains('js-multi-select') &&
- !classList.contains('multi-select')
- ) {
- Sortable.utils.deselect(e.item);
- }
- },
- onDeselect: e => {
- const {
- item: { dataset, classList },
- } = e;
-
- if (
- classList &&
- classList.contains('multi-select') &&
- !classList.contains('js-multi-select')
- ) {
- const issue = this.list.findIssue(Number(dataset.issueId));
- boardsStore.toggleMultiSelect(issue);
- }
- },
- });
-
- this.sortable = Sortable.create(this.$refs.list, options);
-
// Scroll event on list to load more
- this.$refs.list.addEventListener('scroll', this.onScroll);
+ this.listRef.addEventListener('scroll', this.onScroll);
},
beforeDestroy() {
eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
eventHub.$off(`scroll-board-list-${this.list.id}`, this.scrollToTop);
- this.$refs.list.removeEventListener('scroll', this.onScroll);
+ this.listRef.removeEventListener('scroll', this.onScroll);
},
methods: {
+ ...mapActions(['fetchIssuesForList', 'moveIssue']),
listHeight() {
- return this.$refs.list.getBoundingClientRect().height;
+ return this.listRef.getBoundingClientRect().height;
},
scrollHeight() {
- return this.$refs.list.scrollHeight;
+ return this.listRef.scrollHeight;
},
scrollTop() {
- return this.$refs.list.scrollTop + this.listHeight();
+ return this.listRef.scrollTop + this.listHeight();
},
scrollToTop() {
- this.$refs.list.scrollTop = 0;
+ this.listRef.scrollTop = 0;
},
loadNextPage() {
- const getIssues = this.list.nextPage();
- const loadingDone = () => {
- this.list.loadingMore = false;
- };
-
- if (getIssues) {
- this.list.loadingMore = true;
- getIssues.then(loadingDone).catch(loadingDone);
- }
+ this.fetchIssuesForList({ listId: this.list.id, fetchNext: true });
},
toggleForm() {
this.showIssueForm = !this.showIssueForm;
},
onScroll() {
- if (!this.list.loadingMore && this.scrollTop() > this.scrollHeight() - this.scrollOffset) {
- this.loadNextPage();
+ window.requestAnimationFrame(() => {
+ if (
+ !this.loadingMore &&
+ this.scrollTop() > this.scrollHeight() - this.scrollOffset &&
+ this.hasNextPage
+ ) {
+ this.loadNextPage();
+ }
+ });
+ },
+ handleDragOnStart() {
+ sortableStart();
+ },
+ handleDragOnEnd(params) {
+ sortableEnd();
+ const { newIndex, oldIndex, from, to, item } = params;
+ const { issueId, issueIid, issuePath } = item.dataset;
+ const { children } = to;
+ let moveBeforeId;
+ let moveAfterId;
+
+ const getIssueId = (el) => Number(el.dataset.issueId);
+
+ // If issue is being moved within the same list
+ if (from === to) {
+ if (newIndex > oldIndex && children.length > 1) {
+ // If issue is being moved down we look for the issue that ends up before
+ moveBeforeId = getIssueId(children[newIndex]);
+ } else if (newIndex < oldIndex && children.length > 1) {
+ // If issue is being moved up we look for the issue that ends up after
+ moveAfterId = getIssueId(children[newIndex]);
+ } else {
+ // If issue remains in the same list at the same position we do nothing
+ return;
+ }
+ } else {
+ // We look for the issue that ends up before the moved issue if it exists
+ if (children[newIndex - 1]) {
+ moveBeforeId = getIssueId(children[newIndex - 1]);
+ }
+ // We look for the issue that ends up after the moved issue if it exists
+ if (children[newIndex]) {
+ moveAfterId = getIssueId(children[newIndex]);
+ }
}
+
+ this.moveIssue({
+ issueId,
+ issueIid,
+ issuePath,
+ fromListId: from.dataset.listId,
+ toListId: to.dataset.listId,
+ moveBeforeId,
+ moveAfterId,
+ });
},
},
};
@@ -410,21 +194,31 @@ export default {
<template>
<div
- :class="{ 'd-none': !list.isExpanded, 'd-flex flex-column': list.isExpanded }"
- class="board-list-component position-relative h-100"
+ v-show="!list.collapsed"
+ class="board-list-component gl-relative gl-h-full gl-display-flex gl-flex-direction-column"
data-qa-selector="board_list_cards_area"
>
- <div v-if="loading" class="board-list-loading text-center" :aria-label="__('Loading issues')">
+ <div
+ v-if="loading"
+ class="gl-mt-4 gl-text-center"
+ :aria-label="$options.i18n.loadingIssues"
+ data-testid="board_list_loading"
+ >
<gl-loading-icon />
</div>
- <board-new-issue v-if="list.type !== 'closed' && showIssueForm" :list="list" />
- <ul
+ <board-new-issue v-if="list.listType !== 'closed' && showIssueForm" :list="list" />
+ <component
+ :is="treeRootWrapper"
v-show="!loading"
ref="list"
+ v-bind="treeRootOptions"
:data-board="list.id"
- :data-board-type="list.type"
- :class="{ 'is-smaller': showIssueForm, 'bg-danger-100': issuesSizeExceedsMax }"
- class="board-list w-100 h-100 list-unstyled mb-0 p-1 js-board-list"
+ :data-board-type="list.listType"
+ :class="{ 'bg-danger-100': issuesSizeExceedsMax }"
+ class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2 js-board-list"
+ data-testid="tree-root-wrapper"
+ @start="handleDragOnStart"
+ @end="handleDragOnEnd"
>
<board-card
v-for="(issue, index) in issues"
@@ -435,11 +229,11 @@ export default {
:issue="issue"
:disabled="disabled"
/>
- <li v-if="showCount" class="board-list-count text-center" data-issue-id="-1">
- <gl-loading-icon v-show="list.loadingMore" label="Loading more issues" />
- <span v-if="list.issues.length === list.issuesSize">{{ __('Showing all issues') }}</span>
+ <li v-if="showCount" class="board-list-count gl-text-center" data-issue-id="-1">
+ <gl-loading-icon v-if="loadingMore" :label="$options.i18n.loadingMoreissues" />
+ <span v-if="showingAllIssues">{{ $options.i18n.showingAllIssues }}</span>
<span v-else>{{ paginatedIssueText }}</span>
</li>
- </ul>
+ </component>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_list_deprecated.vue b/app/assets/javascripts/boards/components/board_list_deprecated.vue
new file mode 100644
index 00000000000..24900346bda
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_list_deprecated.vue
@@ -0,0 +1,443 @@
+<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 { deprecatedCreateFlash as createFlash } from '~/flash';
+import {
+ getBoardSortableDefaultOptions,
+ sortableStart,
+ sortableEnd,
+} from '../mixins/sortable_default_options';
+
+// This component is being replaced in favor of './board_list.vue' for GraphQL boards
+
+Sortable.mount(new MultiDrag());
+
+export default {
+ name: 'BoardList',
+ components: {
+ boardCard,
+ boardNewIssue,
+ GlLoadingIcon,
+ },
+ props: {
+ disabled: {
+ type: Boolean,
+ required: true,
+ },
+ list: {
+ type: Object,
+ required: true,
+ },
+ issues: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ scrollOffset: 250,
+ filters: boardsStore.state.filters,
+ showCount: false,
+ showIssueForm: false,
+ };
+ },
+ computed: {
+ paginatedIssueText() {
+ return sprintf(__('Showing %{pageSize} of %{total} issues'), {
+ pageSize: this.list.issues.length,
+ total: this.list.issuesSize,
+ });
+ },
+ issuesSizeExceedsMax() {
+ return this.list.maxIssueCount > 0 && this.list.issuesSize > this.list.maxIssueCount;
+ },
+ loading() {
+ return this.list.loading;
+ },
+ },
+ watch: {
+ filters: {
+ handler() {
+ this.list.loadingMore = false;
+ this.$refs.list.scrollTop = 0;
+ },
+ deep: true,
+ },
+ issues() {
+ this.$nextTick(() => {
+ if (
+ this.scrollHeight() <= this.listHeight() &&
+ this.list.issuesSize > this.list.issues.length &&
+ this.list.isExpanded
+ ) {
+ this.list.page += 1;
+ this.list.getIssues(false).catch(() => {
+ // TODO: handle request error
+ });
+ }
+
+ if (this.scrollHeight() > Math.ceil(this.listHeight())) {
+ this.showCount = true;
+ } else {
+ this.showCount = false;
+ }
+ });
+ },
+ },
+ created() {
+ eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
+ eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
+ },
+ mounted() {
+ const multiSelectOpts = {
+ multiDrag: true,
+ selectedClass: 'js-multi-select',
+ animation: 500,
+ };
+
+ const options = getBoardSortableDefaultOptions({
+ scroll: true,
+ disabled: this.disabled,
+ filter: '.board-list-count, .is-disabled',
+ dataIdAttr: 'data-issue-id',
+ removeCloneOnHide: false,
+ ...multiSelectOpts,
+ group: {
+ name: 'issues',
+ /**
+ * Dynamically determine between which containers
+ * items can be moved or copied as
+ * Assignee lists (EE feature) require this behavior
+ */
+ pull: (to, from, dragEl, e) => {
+ // As per Sortable's docs, `to` should provide
+ // reference to exact sortable container on which
+ // we're trying to drag element, but either it is
+ // a library's bug or our markup structure is too complex
+ // that `to` never points to correct container
+ // See https://github.com/RubaXa/Sortable/issues/1037
+ //
+ // So we use `e.target` which is always accurate about
+ // which element we're currently dragging our card upon
+ // So from there, we can get reference to actual container
+ // and thus the container type to enable Copy or Move
+ if (e.target) {
+ const containerEl =
+ e.target.closest('.js-board-list') || e.target.querySelector('.js-board-list');
+ const toBoardType = containerEl.dataset.boardType;
+ const cloneActions = {
+ label: ['milestone', 'assignee'],
+ assignee: ['milestone', 'label'],
+ milestone: ['label', 'assignee'],
+ };
+
+ if (toBoardType) {
+ const fromBoardType = this.list.type;
+ // For each list we check if the destination list is
+ // a the list were we should clone the issue
+ const shouldClone = Object.entries(cloneActions).some(
+ (entry) => fromBoardType === entry[0] && entry[1].includes(toBoardType),
+ );
+
+ if (shouldClone) {
+ return 'clone';
+ }
+ }
+ }
+
+ return true;
+ },
+ revertClone: true,
+ },
+ onStart: (e) => {
+ const card = this.$refs.issue[e.oldIndex];
+
+ card.showDetail = false;
+
+ const { list } = card;
+
+ const issue = list.findIssue(Number(e.item.dataset.issueId));
+
+ boardsStore.startMoving(list, issue);
+
+ this.$root.$emit('bv::hide::tooltip');
+
+ sortableStart();
+ },
+ onAdd: (e) => {
+ const { items = [], newIndicies = [] } = e;
+ if (items.length) {
+ // Not using e.newIndex here instead taking a min of all
+ // the newIndicies. Basically we have to find that during
+ // a drop what is the index we're going to start putting
+ // all the dropped elements from.
+ const newIndex = Math.min(...newIndicies.map((obj) => obj.index).filter((i) => i !== -1));
+ const issues = items.map((item) =>
+ boardsStore.moving.list.findIssue(Number(item.dataset.issueId)),
+ );
+
+ boardsStore.moveMultipleIssuesToList({
+ listFrom: boardsStore.moving.list,
+ listTo: this.list,
+ issues,
+ newIndex,
+ });
+ } else {
+ boardsStore.moveIssueToList(
+ boardsStore.moving.list,
+ this.list,
+ boardsStore.moving.issue,
+ e.newIndex,
+ );
+ this.$nextTick(() => {
+ e.item.remove();
+ });
+ }
+ },
+ onUpdate: (e) => {
+ const sortedArray = this.sortable.toArray().filter((id) => id !== '-1');
+
+ const { items = [], newIndicies = [], oldIndicies = [] } = e;
+ if (items.length) {
+ const newIndex = Math.min(...newIndicies.map((obj) => obj.index));
+ const issues = items.map((item) =>
+ boardsStore.moving.list.findIssue(Number(item.dataset.issueId)),
+ );
+ boardsStore.moveMultipleIssuesInList({
+ list: this.list,
+ issues,
+ oldIndicies: oldIndicies.map((obj) => obj.index),
+ newIndex,
+ idArray: sortedArray,
+ });
+ e.items.forEach((el) => {
+ Sortable.utils.deselect(el);
+ });
+ boardsStore.clearMultiSelect();
+ return;
+ }
+
+ boardsStore.moveIssueInList(
+ this.list,
+ boardsStore.moving.issue,
+ e.oldIndex,
+ e.newIndex,
+ sortedArray,
+ );
+ },
+ onEnd: (e) => {
+ const { items = [], clones = [], to } = e;
+
+ // This is not a multi select operation
+ if (!items.length && !clones.length) {
+ sortableEnd();
+ return;
+ }
+
+ let toList;
+ if (to) {
+ const containerEl = to.closest('.js-board-list');
+ toList = boardsStore.findList('id', Number(containerEl.dataset.board));
+ }
+
+ /**
+ * onEnd is called irrespective if the cards were moved in the
+ * same list or the other list. Don't remove items if it's same list.
+ */
+ const isSameList = toList && toList.id === this.list.id;
+ if (toList && !isSameList && boardsStore.shouldRemoveIssue(this.list, toList)) {
+ const issues = items.map((item) => this.list.findIssue(Number(item.dataset.issueId)));
+ if (
+ issues.filter(Boolean).length &&
+ !boardsStore.issuesAreContiguous(this.list, issues)
+ ) {
+ const indexes = [];
+ const ids = this.list.issues.map((i) => i.id);
+ issues.forEach((issue) => {
+ const index = ids.indexOf(issue.id);
+ if (index > -1) {
+ indexes.push(index);
+ }
+ });
+
+ // Descending sort because splice would cause index discrepancy otherwise
+ const sortedIndexes = indexes.sort((a, b) => (a < b ? 1 : -1));
+
+ sortedIndexes.forEach((i) => {
+ /**
+ * **setTimeout and splice each element one-by-one in a loop
+ * is intended.**
+ *
+ * The problem here is all the indexes are in the list but are
+ * non-contiguous. Due to that, when we splice all the indexes,
+ * at once, Vue -- during a re-render -- is unable to find reference
+ * nodes and the entire app crashes.
+ *
+ * If the indexes are contiguous, this piece of code is not
+ * executed. If it is, this is a possible regression. Only when
+ * issue indexes are far apart, this logic should ever kick in.
+ */
+ setTimeout(() => {
+ this.list.issues.splice(i, 1);
+ }, 0);
+ });
+ }
+ }
+
+ if (!toList) {
+ createFlash(__('Something went wrong while performing the action.'));
+ }
+
+ if (!isSameList) {
+ boardsStore.clearMultiSelect();
+
+ // Since Vue's list does not re-render the same keyed item, we'll
+ // remove `multi-select` class to express it's unselected
+ if (clones && clones.length) {
+ clones.forEach((el) => el.classList.remove('multi-select'));
+ }
+
+ // Due to some bug which I am unable to figure out
+ // Sortable does not deselect some pending items from the
+ // source list.
+ // We'll just do it forcefully here.
+ Array.from(document.querySelectorAll('.js-multi-select') || []).forEach((item) => {
+ Sortable.utils.deselect(item);
+ });
+
+ /**
+ * SortableJS leaves all the moving items "as is" on the DOM.
+ * Vue picks up and rehydrates the DOM, but we need to explicity
+ * remove the "trash" items from the DOM.
+ *
+ * This is in parity to the logic on single item move from a list/in
+ * a list. For reference, look at the implementation of onAdd method.
+ */
+ this.$nextTick(() => {
+ if (items && items.length) {
+ items.forEach((item) => {
+ item.remove();
+ });
+ }
+ });
+ }
+ sortableEnd();
+ },
+ onMove(e) {
+ return !e.related.classList.contains('board-list-count');
+ },
+ onSelect(e) {
+ const {
+ item: { classList },
+ } = e;
+
+ if (
+ classList &&
+ classList.contains('js-multi-select') &&
+ !classList.contains('multi-select')
+ ) {
+ Sortable.utils.deselect(e.item);
+ }
+ },
+ onDeselect: (e) => {
+ const {
+ item: { dataset, classList },
+ } = e;
+
+ if (
+ classList &&
+ classList.contains('multi-select') &&
+ !classList.contains('js-multi-select')
+ ) {
+ const issue = this.list.findIssue(Number(dataset.issueId));
+ boardsStore.toggleMultiSelect(issue);
+ }
+ },
+ });
+
+ this.sortable = Sortable.create(this.$refs.list, options);
+
+ // Scroll event on list to load more
+ this.$refs.list.addEventListener('scroll', this.onScroll);
+ },
+ beforeDestroy() {
+ eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
+ eventHub.$off(`scroll-board-list-${this.list.id}`, this.scrollToTop);
+ this.$refs.list.removeEventListener('scroll', this.onScroll);
+ },
+ methods: {
+ listHeight() {
+ return this.$refs.list.getBoundingClientRect().height;
+ },
+ scrollHeight() {
+ return this.$refs.list.scrollHeight;
+ },
+ scrollTop() {
+ return this.$refs.list.scrollTop + this.listHeight();
+ },
+ scrollToTop() {
+ this.$refs.list.scrollTop = 0;
+ },
+ loadNextPage() {
+ const getIssues = this.list.nextPage();
+ const loadingDone = () => {
+ this.list.loadingMore = false;
+ };
+
+ if (getIssues) {
+ this.list.loadingMore = true;
+ getIssues.then(loadingDone).catch(loadingDone);
+ }
+ },
+ toggleForm() {
+ this.showIssueForm = !this.showIssueForm;
+ },
+ onScroll() {
+ if (!this.list.loadingMore && this.scrollTop() > this.scrollHeight() - this.scrollOffset) {
+ this.loadNextPage();
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{ 'd-none': !list.isExpanded, 'd-flex flex-column': list.isExpanded }"
+ class="board-list-component position-relative h-100"
+ data-qa-selector="board_list_cards_area"
+ >
+ <div v-if="loading" class="board-list-loading text-center" :aria-label="__('Loading issues')">
+ <gl-loading-icon />
+ </div>
+ <board-new-issue v-if="list.type !== 'closed' && showIssueForm" :list="list" />
+ <ul
+ v-show="!loading"
+ ref="list"
+ :data-board="list.id"
+ :data-board-type="list.type"
+ :class="{ 'is-smaller': showIssueForm, 'bg-danger-100': issuesSizeExceedsMax }"
+ class="board-list w-100 h-100 list-unstyled mb-0 p-1 js-board-list"
+ >
+ <board-card
+ v-for="(issue, index) in issues"
+ ref="issue"
+ :key="issue.id"
+ :index="index"
+ :list="list"
+ :issue="issue"
+ :disabled="disabled"
+ />
+ <li v-if="showCount" class="board-list-count text-center" data-issue-id="-1">
+ <gl-loading-icon v-show="list.loadingMore" label="Loading more issues" />
+ <span v-if="list.issues.length === list.issuesSize">{{ __('Showing all issues') }}</span>
+ <span v-else>{{ paginatedIssueText }}</span>
+ </li>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 3db5c2e0830..06f39eceb08 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -9,16 +9,22 @@ import {
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
-import { n__, s__ } from '~/locale';
+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 { inactiveId, LIST, ListType } from '../constants';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import { isListDraggable } from '~/boards/boards_util';
export default {
+ i18n: {
+ newIssue: __('New issue'),
+ listSettings: __('List settings'),
+ expand: s__('Boards|Expand'),
+ collapse: s__('Boards|Collapse'),
+ },
components: {
GlButtonGroup,
GlButton,
@@ -31,6 +37,20 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: {
+ boardId: {
+ default: '',
+ },
+ weightFeatureAvailable: {
+ default: false,
+ },
+ scopedLabelsAvailable: {
+ default: false,
+ },
+ currentUserId: {
+ default: null,
+ },
+ },
props: {
list: {
type: Object,
@@ -47,61 +67,53 @@ export default {
default: false,
},
},
- inject: {
- boardId: {
- default: '',
- },
- },
- data() {
- return {
- weightFeatureAvailable: false,
- };
- },
computed: {
...mapState(['activeId']),
isLoggedIn() {
- return Boolean(gon.current_user_id);
+ return Boolean(this.currentUserId);
},
listType() {
- return this.list.type;
+ return this.list.listType;
},
listAssignee() {
return this.list?.assignee?.username || '';
},
listTitle() {
- return this.list?.label?.description || this.list.title || '';
+ return this.list?.label?.description || this.list?.assignee?.name || this.list.title || '';
},
showListHeaderButton() {
return !this.disabled && this.listType !== ListType.closed;
},
showMilestoneListDetails() {
return (
- this.list.type === 'milestone' &&
+ this.listType === ListType.milestone &&
this.list.milestone &&
- (this.list.isExpanded || !this.isSwimlanesHeader)
+ (!this.list.collapsed || !this.isSwimlanesHeader)
);
},
showAssigneeListDetails() {
- return this.list.type === 'assignee' && (this.list.isExpanded || !this.isSwimlanesHeader);
+ return (
+ this.listType === ListType.assignee && (!this.list.collapsed || !this.isSwimlanesHeader)
+ );
},
issuesCount() {
- return this.list.issuesSize;
+ return this.list.issuesCount;
},
issuesTooltipLabel() {
return n__(`%d issue`, `%d issues`, this.issuesCount);
},
chevronTooltip() {
- return this.list.isExpanded ? s__('Boards|Collapse') : s__('Boards|Expand');
+ return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse;
},
chevronIcon() {
- return this.list.isExpanded ? 'chevron-right' : 'chevron-down';
+ return this.list.collapsed ? 'chevron-down' : 'chevron-right';
},
isNewIssueShown() {
return this.listType === ListType.backlog || this.showListHeaderButton;
},
isSettingsShown() {
return (
- this.listType !== ListType.backlog && this.showListHeaderButton && this.list.isExpanded
+ this.listType !== ListType.backlog && this.showListHeaderButton && !this.list.collapsed
);
},
uniqueKey() {
@@ -111,9 +123,15 @@ export default {
collapsedTooltipTitle() {
return this.listTitle || this.listAssignee;
},
+ headerStyle() {
+ return { borderTopColor: this.list?.label?.color };
+ },
+ userCanDrag() {
+ return !this.disabled && isListDraggable(this.list);
+ },
},
methods: {
- ...mapActions(['setActiveId']),
+ ...mapActions(['updateList', 'setActiveId']),
openSidebarSettings() {
if (this.activeId === inactiveId) {
sidebarEventHub.$emit('sidebar.closeAll');
@@ -122,14 +140,14 @@ export default {
this.setActiveId({ id: this.list.id, sidebarType: LIST });
},
showScopedLabels(label) {
- return boardsStore.scopedLabels.enabled && isScopedLabel(label);
+ return this.scopedLabelsAvailable && isScopedLabel(label);
},
showNewIssueForm() {
eventHub.$emit(`toggle-issue-form-${this.list.id}`);
},
toggleExpanded() {
- this.list.isExpanded = !this.list.isExpanded;
+ this.list.collapsed = !this.list.collapsed;
if (!this.isLoggedIn) {
this.addToLocalStorage();
@@ -143,11 +161,11 @@ export default {
},
addToLocalStorage() {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
- localStorage.setItem(`${this.uniqueKey}.expanded`, this.list.isExpanded);
+ localStorage.setItem(`${this.uniqueKey}.expanded`, !this.list.collapsed);
}
},
updateListFunction() {
- this.list.update();
+ this.updateList({ listId: this.list.id, collapsed: this.list.collapsed });
},
},
};
@@ -157,26 +175,25 @@ export default {
<header
:class="{
'has-border': list.label && list.label.color,
- 'gl-h-full': !list.isExpanded,
+ 'gl-h-full': list.collapsed,
'board-inner gl-rounded-top-left-base gl-rounded-top-right-base': isSwimlanesHeader,
}"
- :style="{ borderTopColor: list.label && list.label.color ? list.label.color : null }"
+ :style="headerStyle"
class="board-header gl-relative"
data-qa-selector="board_list_header"
data-testid="board-list-header"
>
<h3
:class="{
- 'user-can-drag': !disabled && !list.preset,
- 'gl-py-3 gl-h-full': !list.isExpanded && !isSwimlanesHeader,
- 'gl-border-b-0': !list.isExpanded || isSwimlanesHeader,
- 'gl-py-2': !list.isExpanded && isSwimlanesHeader,
- 'gl-flex-direction-column': !list.isExpanded,
+ 'user-can-drag': userCanDrag,
+ 'gl-py-3 gl-h-full': list.collapsed && !isSwimlanesHeader,
+ 'gl-border-b-0': list.collapsed || isSwimlanesHeader,
+ 'gl-py-2': list.collapsed && isSwimlanesHeader,
+ 'gl-flex-direction-column': list.collapsed,
}"
class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
>
<gl-button
- v-if="list.isExpandable"
v-gl-tooltip.hover
:aria-label="chevronTooltip"
:title="chevronTooltip"
@@ -186,14 +203,14 @@ export default {
size="small"
@click="toggleExpanded"
/>
- <!-- The following is only true in EE and if it is a milestone -->
+ <!-- EE start -->
<span
v-if="showMilestoneListDetails"
aria-hidden="true"
class="milestone-icon"
:class="{
- 'gl-mt-3 gl-rotate-90': !list.isExpanded,
- 'gl-mr-2': list.isExpanded,
+ 'gl-mt-3 gl-rotate-90': list.collapsed,
+ 'gl-mr-2': !list.collapsed,
}"
>
<gl-icon name="timer" />
@@ -201,90 +218,95 @@ export default {
<a
v-if="showAssigneeListDetails"
- :href="list.assignee.path"
+ :href="list.assignee.webUrl"
class="user-avatar-link js-no-trigger"
:class="{
- 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ 'gl-mt-3 gl-rotate-90': list.collapsed,
}"
>
<img
v-gl-tooltip.hover.bottom
:title="listAssignee"
:alt="list.assignee.name"
- :src="list.assignee.avatar"
+ :src="list.assignee.avatarUrl"
class="avatar s20"
height="20"
width="20"
/>
</a>
+ <!-- EE end -->
<div
class="board-title-text"
:class="{
- 'gl-display-none': !list.isExpanded && isSwimlanesHeader,
- 'gl-flex-grow-0 gl-my-3 gl-mx-0': !list.isExpanded,
- 'gl-flex-grow-1': list.isExpanded,
+ 'gl-display-none': list.collapsed && isSwimlanesHeader,
+ 'gl-flex-grow-0 gl-my-3 gl-mx-0': list.collapsed,
+ 'gl-flex-grow-1': !list.collapsed,
}"
>
+ <!-- EE start -->
<span
- v-if="list.type !== 'label'"
+ v-if="listType !== 'label'"
v-gl-tooltip.hover
:class="{
- 'gl-display-block': !list.isExpanded || list.type === 'milestone',
+ 'gl-display-block': list.collapsed || listType === 'milestone',
}"
:title="listTitle"
class="board-title-main-text gl-text-truncate"
>
- {{ list.title }}
+ {{ listTitle }}
</span>
<span
- v-if="list.type === 'assignee'"
+ v-if="listType === 'assignee'"
+ v-show="!list.collapsed"
class="gl-ml-2 gl-font-weight-normal gl-text-gray-500"
- :class="{ 'gl-display-none': !list.isExpanded }"
>
@{{ listAssignee }}
</span>
+ <!-- EE end -->
<gl-label
- v-if="list.type === 'label'"
+ v-if="listType === 'label'"
v-gl-tooltip.hover.bottom
:background-color="list.label.color"
:description="list.label.description"
:scoped="showScopedLabels(list.label)"
- :size="!list.isExpanded ? 'sm' : ''"
+ :size="list.collapsed ? 'sm' : ''"
:title="list.label.title"
/>
</div>
+ <!-- EE start -->
<span
- v-if="isSwimlanesHeader && !list.isExpanded"
+ v-if="isSwimlanesHeader && list.collapsed"
ref="collapsedInfo"
aria-hidden="true"
- class="board-header-collapsed-info-icon gl-mt-2 gl-cursor-pointer gl-text-gray-500"
+ class="board-header-collapsed-info-icon gl-cursor-pointer gl-text-gray-500"
>
<gl-icon name="information" />
</span>
- <gl-tooltip v-if="isSwimlanesHeader && !list.isExpanded" :target="() => $refs.collapsedInfo">
+ <gl-tooltip v-if="isSwimlanesHeader && list.collapsed" :target="() => $refs.collapsedInfo">
<div class="gl-font-weight-bold gl-pb-2">{{ collapsedTooltipTitle }}</div>
<div v-if="list.maxIssueCount !== 0">
- &#8226;
+ •
<gl-sprintf :message="__('%{issuesSize} with a limit of %{maxIssueCount}')">
<template #issuesSize>{{ issuesTooltipLabel }}</template>
<template #maxIssueCount>{{ list.maxIssueCount }}</template>
</gl-sprintf>
</div>
- <div v-else>&#8226; {{ issuesTooltipLabel }}</div>
+ <div v-else>• {{ issuesTooltipLabel }}</div>
<div v-if="weightFeatureAvailable">
- &#8226;
+ •
<gl-sprintf :message="__('%{totalWeight} total weight')">
<template #totalWeight>{{ list.totalWeight }}</template>
</gl-sprintf>
</div>
</gl-tooltip>
+ <!-- EE end -->
<div
- class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag text-secondary"
+ class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag gl-text-gray-500"
:class="{
- 'gl-display-none!': !list.isExpanded && isSwimlanesHeader,
- 'gl-p-0': !list.isExpanded,
+ 'gl-display-none!': list.collapsed && isSwimlanesHeader,
+ 'gl-p-0': list.collapsed,
}"
>
<span class="gl-display-inline-flex">
@@ -293,7 +315,7 @@ export default {
<gl-icon class="gl-mr-2" name="issues" />
<issue-count :issues-size="issuesCount" :max-issue-count="list.maxIssueCount" />
</span>
- <!-- The following is only true in EE. -->
+ <!-- EE start -->
<template v-if="weightFeatureAvailable">
<gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" />
<span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3">
@@ -301,6 +323,7 @@ export default {
{{ list.totalWeight }}
</span>
</template>
+ <!-- EE end -->
</span>
</div>
<gl-button-group
@@ -309,13 +332,11 @@ export default {
>
<gl-button
v-if="isNewIssueShown"
+ v-show="!list.collapsed"
ref="newIssueBtn"
v-gl-tooltip.hover
- :class="{
- 'gl-display-none': !list.isExpanded,
- }"
- :aria-label="__('New issue')"
- :title="__('New issue')"
+ :aria-label="$options.i18n.newIssue"
+ :title="$options.i18n.newIssue"
class="issue-count-badge-add-button no-drag"
icon="plus"
@click="showNewIssueForm"
@@ -325,13 +346,13 @@ export default {
v-if="isSettingsShown"
ref="settingsBtn"
v-gl-tooltip.hover
- :aria-label="__('List settings')"
+ :aria-label="$options.i18n.listSettings"
class="no-drag js-board-settings-button"
- :title="__('List settings')"
+ :title="$options.i18n.listSettings"
icon="settings"
@click="openSidebarSettings"
/>
- <gl-tooltip :target="() => $refs.settingsBtn">{{ __('List settings') }}</gl-tooltip>
+ <gl-tooltip :target="() => $refs.settingsBtn">{{ $options.i18n.listSettings }}</gl-tooltip>
</gl-button-group>
</h3>
</header>
diff --git a/app/assets/javascripts/boards/components/board_list_header_deprecated.vue b/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
new file mode 100644
index 00000000000..21147f1616c
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
@@ -0,0 +1,340 @@
+<script>
+import { mapActions, mapState } from 'vuex';
+import {
+ GlButton,
+ GlButtonGroup,
+ GlLabel,
+ GlTooltip,
+ GlIcon,
+ GlSprintf,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+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 { inactiveId, LIST, ListType } from '../constants';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+
+// This component is being replaced in favor of './board_list_header.vue' for GraphQL boards
+
+export default {
+ components: {
+ GlButtonGroup,
+ GlButton,
+ GlLabel,
+ GlTooltip,
+ GlIcon,
+ GlSprintf,
+ IssueCount,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ inject: {
+ boardId: {
+ default: '',
+ },
+ },
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ required: true,
+ },
+ isSwimlanesHeader: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ weightFeatureAvailable: false,
+ };
+ },
+ computed: {
+ ...mapState(['activeId']),
+ isLoggedIn() {
+ return Boolean(gon.current_user_id);
+ },
+ listType() {
+ return this.list.type;
+ },
+ listAssignee() {
+ return this.list?.assignee?.username || '';
+ },
+ listTitle() {
+ return this.list?.label?.description || this.list.title || '';
+ },
+ showListHeaderButton() {
+ return !this.disabled && this.listType !== ListType.closed;
+ },
+ showMilestoneListDetails() {
+ return (
+ this.list.type === 'milestone' &&
+ this.list.milestone &&
+ (this.list.isExpanded || !this.isSwimlanesHeader)
+ );
+ },
+ showAssigneeListDetails() {
+ return this.list.type === 'assignee' && (this.list.isExpanded || !this.isSwimlanesHeader);
+ },
+ issuesCount() {
+ return this.list.issuesSize;
+ },
+ issuesTooltipLabel() {
+ return n__(`%d issue`, `%d issues`, this.issuesCount);
+ },
+ chevronTooltip() {
+ return this.list.isExpanded ? s__('Boards|Collapse') : s__('Boards|Expand');
+ },
+ chevronIcon() {
+ return this.list.isExpanded ? 'chevron-right' : 'chevron-down';
+ },
+ isNewIssueShown() {
+ return this.listType === ListType.backlog || this.showListHeaderButton;
+ },
+ isSettingsShown() {
+ return (
+ this.listType !== ListType.backlog && this.showListHeaderButton && this.list.isExpanded
+ );
+ },
+ uniqueKey() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `boards.${this.boardId}.${this.listType}.${this.list.id}`;
+ },
+ collapsedTooltipTitle() {
+ return this.listTitle || this.listAssignee;
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveId']),
+ openSidebarSettings() {
+ if (this.activeId === inactiveId) {
+ sidebarEventHub.$emit('sidebar.closeAll');
+ }
+
+ this.setActiveId({ id: this.list.id, sidebarType: LIST });
+ },
+ showScopedLabels(label) {
+ return boardsStore.scopedLabels.enabled && isScopedLabel(label);
+ },
+
+ showNewIssueForm() {
+ eventHub.$emit(`toggle-issue-form-${this.list.id}`);
+ },
+ toggleExpanded() {
+ this.list.isExpanded = !this.list.isExpanded;
+
+ if (!this.isLoggedIn) {
+ this.addToLocalStorage();
+ } else {
+ this.updateListFunction();
+ }
+
+ // 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');
+ },
+ addToLocalStorage() {
+ if (AccessorUtilities.isLocalStorageAccessSafe()) {
+ localStorage.setItem(`${this.uniqueKey}.expanded`, this.list.isExpanded);
+ }
+ },
+ updateListFunction() {
+ this.list.update();
+ },
+ },
+};
+</script>
+
+<template>
+ <header
+ :class="{
+ 'has-border': list.label && list.label.color,
+ 'gl-h-full': !list.isExpanded,
+ 'board-inner gl-rounded-top-left-base gl-rounded-top-right-base': isSwimlanesHeader,
+ }"
+ :style="{ borderTopColor: list.label && list.label.color ? list.label.color : null }"
+ class="board-header gl-relative"
+ data-qa-selector="board_list_header"
+ data-testid="board-list-header"
+ >
+ <h3
+ :class="{
+ 'user-can-drag': !disabled && !list.preset,
+ 'gl-py-3 gl-h-full': !list.isExpanded && !isSwimlanesHeader,
+ 'gl-border-b-0': !list.isExpanded || isSwimlanesHeader,
+ 'gl-py-2': !list.isExpanded && isSwimlanesHeader,
+ 'gl-flex-direction-column': !list.isExpanded,
+ }"
+ class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
+ >
+ <gl-button
+ v-if="list.isExpandable"
+ v-gl-tooltip.hover
+ :aria-label="chevronTooltip"
+ :title="chevronTooltip"
+ :icon="chevronIcon"
+ class="board-title-caret no-drag gl-cursor-pointer"
+ category="tertiary"
+ size="small"
+ @click="toggleExpanded"
+ />
+ <!-- The following is only true in EE and if it is a milestone -->
+ <span
+ v-if="showMilestoneListDetails"
+ aria-hidden="true"
+ class="milestone-icon"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ 'gl-mr-2': list.isExpanded,
+ }"
+ >
+ <gl-icon name="timer" />
+ </span>
+
+ <a
+ v-if="showAssigneeListDetails"
+ :href="list.assignee.path"
+ class="user-avatar-link js-no-trigger"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ }"
+ >
+ <img
+ v-gl-tooltip.hover.bottom
+ :title="listAssignee"
+ :alt="list.assignee.name"
+ :src="list.assignee.avatar"
+ class="avatar s20"
+ height="20"
+ width="20"
+ />
+ </a>
+ <div
+ class="board-title-text"
+ :class="{
+ 'gl-display-none': !list.isExpanded && isSwimlanesHeader,
+ 'gl-flex-grow-0 gl-my-3 gl-mx-0': !list.isExpanded,
+ 'gl-flex-grow-1': list.isExpanded,
+ }"
+ >
+ <span
+ v-if="list.type !== 'label'"
+ v-gl-tooltip.hover
+ :class="{
+ 'gl-display-block': !list.isExpanded || list.type === 'milestone',
+ }"
+ :title="listTitle"
+ class="board-title-main-text gl-text-truncate"
+ >
+ {{ list.title }}
+ </span>
+ <span
+ v-if="list.type === 'assignee'"
+ class="gl-ml-2 gl-font-weight-normal gl-text-gray-500"
+ :class="{ 'gl-display-none': !list.isExpanded }"
+ >
+ @{{ listAssignee }}
+ </span>
+ <gl-label
+ v-if="list.type === 'label'"
+ v-gl-tooltip.hover.bottom
+ :background-color="list.label.color"
+ :description="list.label.description"
+ :scoped="showScopedLabels(list.label)"
+ :size="!list.isExpanded ? 'sm' : ''"
+ :title="list.label.title"
+ />
+ </div>
+
+ <span
+ v-if="isSwimlanesHeader && !list.isExpanded"
+ ref="collapsedInfo"
+ aria-hidden="true"
+ class="board-header-collapsed-info-icon gl-mt-2 gl-cursor-pointer gl-text-gray-500"
+ >
+ <gl-icon name="information" />
+ </span>
+ <gl-tooltip v-if="isSwimlanesHeader && !list.isExpanded" :target="() => $refs.collapsedInfo">
+ <div class="gl-font-weight-bold gl-pb-2">{{ collapsedTooltipTitle }}</div>
+ <div v-if="list.maxIssueCount !== 0">
+ &#8226;
+ <gl-sprintf :message="__('%{issuesSize} with a limit of %{maxIssueCount}')">
+ <template #issuesSize>{{ issuesTooltipLabel }}</template>
+ <template #maxIssueCount>{{ list.maxIssueCount }}</template>
+ </gl-sprintf>
+ </div>
+ <div v-else>&#8226; {{ issuesTooltipLabel }}</div>
+ <div v-if="weightFeatureAvailable">
+ &#8226;
+ <gl-sprintf :message="__('%{totalWeight} total weight')">
+ <template #totalWeight>{{ list.totalWeight }}</template>
+ </gl-sprintf>
+ </div>
+ </gl-tooltip>
+
+ <div
+ class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag text-secondary"
+ :class="{
+ 'gl-display-none!': !list.isExpanded && isSwimlanesHeader,
+ 'gl-p-0': !list.isExpanded,
+ }"
+ >
+ <span class="gl-display-inline-flex">
+ <gl-tooltip :target="() => $refs.issueCount" :title="issuesTooltipLabel" />
+ <span ref="issueCount" class="issue-count-badge-count">
+ <gl-icon class="gl-mr-2" name="issues" />
+ <issue-count :issues-size="issuesCount" :max-issue-count="list.maxIssueCount" />
+ </span>
+ <!-- The following is only true in EE. -->
+ <template v-if="weightFeatureAvailable">
+ <gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" />
+ <span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3">
+ <gl-icon class="gl-mr-2" name="weight" />
+ {{ list.totalWeight }}
+ </span>
+ </template>
+ </span>
+ </div>
+ <gl-button-group
+ v-if="isNewIssueShown || isSettingsShown"
+ class="board-list-button-group pl-2"
+ >
+ <gl-button
+ v-if="isNewIssueShown"
+ ref="newIssueBtn"
+ v-gl-tooltip.hover
+ :class="{
+ 'gl-display-none': !list.isExpanded,
+ }"
+ :aria-label="__('New issue')"
+ :title="__('New issue')"
+ class="issue-count-badge-add-button no-drag"
+ icon="plus"
+ @click="showNewIssueForm"
+ />
+
+ <gl-button
+ v-if="isSettingsShown"
+ ref="settingsBtn"
+ v-gl-tooltip.hover
+ :aria-label="__('List settings')"
+ class="no-drag js-board-settings-button"
+ :title="__('List settings')"
+ icon="settings"
+ @click="openSidebarSettings"
+ />
+ <gl-tooltip :target="() => $refs.settingsBtn">{{ __('List settings') }}</gl-tooltip>
+ </gl-button-group>
+ </h3>
+ </header>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_list_header_new.vue b/app/assets/javascripts/boards/components/board_list_header_new.vue
deleted file mode 100644
index 44eb2aa34c2..00000000000
--- a/app/assets/javascripts/boards/components/board_list_header_new.vue
+++ /dev/null
@@ -1,359 +0,0 @@
-<script>
-import { mapActions, mapState } from 'vuex';
-import {
- GlButton,
- GlButtonGroup,
- GlLabel,
- GlTooltip,
- GlIcon,
- GlSprintf,
- GlTooltipDirective,
-} from '@gitlab/ui';
-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 { inactiveId, LIST, ListType } from '../constants';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import { isListDraggable } from '~/boards/boards_util';
-
-export default {
- i18n: {
- newIssue: __('New issue'),
- listSettings: __('List settings'),
- expand: s__('Boards|Expand'),
- collapse: s__('Boards|Collapse'),
- },
- components: {
- GlButtonGroup,
- GlButton,
- GlLabel,
- GlTooltip,
- GlIcon,
- GlSprintf,
- IssueCount,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- list: {
- type: Object,
- default: () => ({}),
- required: false,
- },
- disabled: {
- type: Boolean,
- required: true,
- },
- isSwimlanesHeader: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- inject: {
- boardId: {
- default: '',
- },
- weightFeatureAvailable: {
- default: false,
- },
- scopedLabelsAvailable: {
- default: false,
- },
- currentUserId: {
- default: null,
- },
- },
- computed: {
- ...mapState(['activeId']),
- isLoggedIn() {
- return Boolean(this.currentUserId);
- },
- listType() {
- return this.list.listType;
- },
- listAssignee() {
- return this.list?.assignee?.username || '';
- },
- listTitle() {
- return this.list?.label?.description || this.list?.assignee?.name || this.list.title || '';
- },
- showListHeaderButton() {
- return !this.disabled && this.listType !== ListType.closed;
- },
- showMilestoneListDetails() {
- return (
- this.listType === ListType.milestone &&
- this.list.milestone &&
- (!this.list.collapsed || !this.isSwimlanesHeader)
- );
- },
- showAssigneeListDetails() {
- return (
- this.listType === ListType.assignee && (!this.list.collapsed || !this.isSwimlanesHeader)
- );
- },
- issuesCount() {
- return this.list.issuesCount;
- },
- issuesTooltipLabel() {
- return n__(`%d issue`, `%d issues`, this.issuesCount);
- },
- chevronTooltip() {
- return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse;
- },
- chevronIcon() {
- return this.list.collapsed ? 'chevron-down' : 'chevron-right';
- },
- isNewIssueShown() {
- return this.listType === ListType.backlog || this.showListHeaderButton;
- },
- isSettingsShown() {
- return (
- this.listType !== ListType.backlog && this.showListHeaderButton && !this.list.collapsed
- );
- },
- uniqueKey() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `boards.${this.boardId}.${this.listType}.${this.list.id}`;
- },
- collapsedTooltipTitle() {
- return this.listTitle || this.listAssignee;
- },
- headerStyle() {
- return { borderTopColor: this.list?.label?.color };
- },
- userCanDrag() {
- return !this.disabled && isListDraggable(this.list);
- },
- },
- methods: {
- ...mapActions(['updateList', 'setActiveId']),
- openSidebarSettings() {
- if (this.activeId === inactiveId) {
- sidebarEventHub.$emit('sidebar.closeAll');
- }
-
- this.setActiveId({ id: this.list.id, sidebarType: LIST });
- },
- showScopedLabels(label) {
- return this.scopedLabelsAvailable && isScopedLabel(label);
- },
-
- showNewIssueForm() {
- eventHub.$emit(`toggle-issue-form-${this.list.id}`);
- },
- toggleExpanded() {
- this.list.collapsed = !this.list.collapsed;
-
- if (!this.isLoggedIn) {
- this.addToLocalStorage();
- } else {
- this.updateListFunction();
- }
-
- // 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');
- },
- addToLocalStorage() {
- if (AccessorUtilities.isLocalStorageAccessSafe()) {
- localStorage.setItem(`${this.uniqueKey}.expanded`, !this.list.collapsed);
- }
- },
- updateListFunction() {
- this.updateList({ listId: this.list.id, collapsed: this.list.collapsed });
- },
- },
-};
-</script>
-
-<template>
- <header
- :class="{
- 'has-border': list.label && list.label.color,
- 'gl-h-full': list.collapsed,
- 'board-inner gl-rounded-top-left-base gl-rounded-top-right-base': isSwimlanesHeader,
- }"
- :style="headerStyle"
- class="board-header gl-relative"
- data-qa-selector="board_list_header"
- data-testid="board-list-header"
- >
- <h3
- :class="{
- 'user-can-drag': userCanDrag,
- 'gl-py-3 gl-h-full': list.collapsed && !isSwimlanesHeader,
- 'gl-border-b-0': list.collapsed || isSwimlanesHeader,
- 'gl-py-2': list.collapsed && isSwimlanesHeader,
- 'gl-flex-direction-column': list.collapsed,
- }"
- class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
- >
- <gl-button
- v-gl-tooltip.hover
- :aria-label="chevronTooltip"
- :title="chevronTooltip"
- :icon="chevronIcon"
- class="board-title-caret no-drag gl-cursor-pointer"
- category="tertiary"
- size="small"
- @click="toggleExpanded"
- />
- <!-- EE start -->
- <span
- v-if="showMilestoneListDetails"
- aria-hidden="true"
- class="milestone-icon"
- :class="{
- 'gl-mt-3 gl-rotate-90': list.collapsed,
- 'gl-mr-2': !list.collapsed,
- }"
- >
- <gl-icon name="timer" />
- </span>
-
- <a
- v-if="showAssigneeListDetails"
- :href="list.assignee.webUrl"
- class="user-avatar-link js-no-trigger"
- :class="{
- 'gl-mt-3 gl-rotate-90': list.collapsed,
- }"
- >
- <img
- v-gl-tooltip.hover.bottom
- :title="listAssignee"
- :alt="list.assignee.name"
- :src="list.assignee.avatarUrl"
- class="avatar s20"
- height="20"
- width="20"
- />
- </a>
- <!-- EE end -->
- <div
- class="board-title-text"
- :class="{
- 'gl-display-none': list.collapsed && isSwimlanesHeader,
- 'gl-flex-grow-0 gl-my-3 gl-mx-0': list.collapsed,
- 'gl-flex-grow-1': !list.collapsed,
- }"
- >
- <!-- EE start -->
- <span
- v-if="listType !== 'label'"
- v-gl-tooltip.hover
- :class="{
- 'gl-display-block': list.collapsed || listType === 'milestone',
- }"
- :title="listTitle"
- class="board-title-main-text gl-text-truncate"
- >
- {{ listTitle }}
- </span>
- <span
- v-if="listType === 'assignee'"
- v-show="!list.collapsed"
- class="gl-ml-2 gl-font-weight-normal gl-text-gray-500"
- >
- @{{ listAssignee }}
- </span>
- <!-- EE end -->
- <gl-label
- v-if="listType === 'label'"
- v-gl-tooltip.hover.bottom
- :background-color="list.label.color"
- :description="list.label.description"
- :scoped="showScopedLabels(list.label)"
- :size="list.collapsed ? 'sm' : ''"
- :title="list.label.title"
- />
- </div>
-
- <!-- EE start -->
- <span
- v-if="isSwimlanesHeader && list.collapsed"
- ref="collapsedInfo"
- aria-hidden="true"
- class="board-header-collapsed-info-icon gl-cursor-pointer gl-text-gray-500"
- >
- <gl-icon name="information" />
- </span>
- <gl-tooltip v-if="isSwimlanesHeader && list.collapsed" :target="() => $refs.collapsedInfo">
- <div class="gl-font-weight-bold gl-pb-2">{{ collapsedTooltipTitle }}</div>
- <div v-if="list.maxIssueCount !== 0">
- •
- <gl-sprintf :message="__('%{issuesSize} with a limit of %{maxIssueCount}')">
- <template #issuesSize>{{ issuesTooltipLabel }}</template>
- <template #maxIssueCount>{{ list.maxIssueCount }}</template>
- </gl-sprintf>
- </div>
- <div v-else>• {{ issuesTooltipLabel }}</div>
- <div v-if="weightFeatureAvailable">
- •
- <gl-sprintf :message="__('%{totalWeight} total weight')">
- <template #totalWeight>{{ list.totalWeight }}</template>
- </gl-sprintf>
- </div>
- </gl-tooltip>
- <!-- EE end -->
-
- <div
- class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag gl-text-gray-500"
- :class="{
- 'gl-display-none!': list.collapsed && isSwimlanesHeader,
- 'gl-p-0': list.collapsed,
- }"
- >
- <span class="gl-display-inline-flex">
- <gl-tooltip :target="() => $refs.issueCount" :title="issuesTooltipLabel" />
- <span ref="issueCount" class="issue-count-badge-count">
- <gl-icon class="gl-mr-2" name="issues" />
- <issue-count :issues-size="issuesCount" :max-issue-count="list.maxIssueCount" />
- </span>
- <!-- EE start -->
- <template v-if="weightFeatureAvailable">
- <gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" />
- <span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3">
- <gl-icon class="gl-mr-2" name="weight" />
- {{ list.totalWeight }}
- </span>
- </template>
- <!-- EE end -->
- </span>
- </div>
- <gl-button-group
- v-if="isNewIssueShown || isSettingsShown"
- class="board-list-button-group pl-2"
- >
- <gl-button
- v-if="isNewIssueShown"
- v-show="!list.collapsed"
- ref="newIssueBtn"
- v-gl-tooltip.hover
- :aria-label="$options.i18n.newIssue"
- :title="$options.i18n.newIssue"
- class="issue-count-badge-add-button no-drag"
- icon="plus"
- @click="showNewIssueForm"
- />
-
- <gl-button
- v-if="isSettingsShown"
- ref="settingsBtn"
- v-gl-tooltip.hover
- :aria-label="$options.i18n.listSettings"
- class="no-drag js-board-settings-button"
- :title="$options.i18n.listSettings"
- icon="settings"
- @click="openSidebarSettings"
- />
- <gl-tooltip :target="() => $refs.settingsBtn">{{ $options.i18n.listSettings }}</gl-tooltip>
- </gl-button-group>
- </h3>
- </header>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_list_new.vue b/app/assets/javascripts/boards/components/board_list_new.vue
deleted file mode 100644
index 92a381a8f57..00000000000
--- a/app/assets/javascripts/boards/components/board_list_new.vue
+++ /dev/null
@@ -1,239 +0,0 @@
-<script>
-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_new.vue';
-import BoardCard from './board_card.vue';
-import eventHub from '../eventhub';
-import { sprintf, __ } from '~/locale';
-
-export default {
- name: 'BoardList',
- i18n: {
- loadingIssues: __('Loading issues'),
- loadingMoreissues: __('Loading more issues'),
- showingAllIssues: __('Showing all issues'),
- },
- components: {
- BoardCard,
- BoardNewIssue,
- GlLoadingIcon,
- },
- props: {
- disabled: {
- type: Boolean,
- required: true,
- },
- list: {
- type: Object,
- required: true,
- },
- issues: {
- type: Array,
- required: true,
- },
- canAdminList: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- scrollOffset: 250,
- showCount: false,
- showIssueForm: false,
- };
- },
- computed: {
- ...mapState(['pageInfoByListId', 'listsFlags']),
- paginatedIssueText() {
- return sprintf(__('Showing %{pageSize} of %{total} issues'), {
- pageSize: this.issues.length,
- total: this.list.issuesCount,
- });
- },
- issuesSizeExceedsMax() {
- return this.list.maxIssueCount > 0 && this.list.issuesCount > this.list.maxIssueCount;
- },
- hasNextPage() {
- return this.pageInfoByListId[this.list.id].hasNextPage;
- },
- loading() {
- return this.listsFlags[this.list.id]?.isLoading;
- },
- loadingMore() {
- return this.listsFlags[this.list.id]?.isLoadingMore;
- },
- listRef() {
- // When list is draggable, the reference to the list needs to be accessed differently
- return this.canAdminList ? this.$refs.list.$el : this.$refs.list;
- },
- showingAllIssues() {
- return this.issues.length === this.list.issuesCount;
- },
- treeRootWrapper() {
- return this.canAdminList ? Draggable : 'ul';
- },
- treeRootOptions() {
- const options = {
- ...defaultSortableConfig,
- fallbackOnBody: false,
- group: 'board-list',
- tag: 'ul',
- 'ghost-class': 'board-card-drag-active',
- 'data-list-id': this.list.id,
- value: this.issues,
- };
-
- return this.canAdminList ? options : {};
- },
- },
- watch: {
- issues() {
- this.$nextTick(() => {
- this.showCount = this.scrollHeight() > Math.ceil(this.listHeight());
- });
- },
- },
- created() {
- eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
- eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
- },
- mounted() {
- // Scroll event on list to load more
- this.listRef.addEventListener('scroll', this.onScroll);
- },
- beforeDestroy() {
- eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
- eventHub.$off(`scroll-board-list-${this.list.id}`, this.scrollToTop);
- this.listRef.removeEventListener('scroll', this.onScroll);
- },
- methods: {
- ...mapActions(['fetchIssuesForList', 'moveIssue']),
- listHeight() {
- return this.listRef.getBoundingClientRect().height;
- },
- scrollHeight() {
- return this.listRef.scrollHeight;
- },
- scrollTop() {
- return this.listRef.scrollTop + this.listHeight();
- },
- scrollToTop() {
- this.listRef.scrollTop = 0;
- },
- loadNextPage() {
- this.fetchIssuesForList({ listId: this.list.id, fetchNext: true });
- },
- toggleForm() {
- this.showIssueForm = !this.showIssueForm;
- },
- onScroll() {
- window.requestAnimationFrame(() => {
- if (
- !this.loadingMore &&
- this.scrollTop() > this.scrollHeight() - this.scrollOffset &&
- this.hasNextPage
- ) {
- this.loadNextPage();
- }
- });
- },
- handleDragOnStart() {
- sortableStart();
- },
- handleDragOnEnd(params) {
- sortableEnd();
- const { newIndex, oldIndex, from, to, item } = params;
- const { issueId, issueIid, issuePath } = item.dataset;
- const { children } = to;
- let moveBeforeId;
- let moveAfterId;
-
- const getIssueId = el => Number(el.dataset.issueId);
-
- // If issue is being moved within the same list
- if (from === to) {
- if (newIndex > oldIndex && children.length > 1) {
- // If issue is being moved down we look for the issue that ends up before
- moveBeforeId = getIssueId(children[newIndex]);
- } else if (newIndex < oldIndex && children.length > 1) {
- // If issue is being moved up we look for the issue that ends up after
- moveAfterId = getIssueId(children[newIndex]);
- } else {
- // If issue remains in the same list at the same position we do nothing
- return;
- }
- } else {
- // We look for the issue that ends up before the moved issue if it exists
- if (children[newIndex - 1]) {
- moveBeforeId = getIssueId(children[newIndex - 1]);
- }
- // We look for the issue that ends up after the moved issue if it exists
- if (children[newIndex]) {
- moveAfterId = getIssueId(children[newIndex]);
- }
- }
-
- this.moveIssue({
- issueId,
- issueIid,
- issuePath,
- fromListId: from.dataset.listId,
- toListId: to.dataset.listId,
- moveBeforeId,
- moveAfterId,
- });
- },
- },
-};
-</script>
-
-<template>
- <div
- v-show="!list.collapsed"
- class="board-list-component gl-relative gl-h-full gl-display-flex gl-flex-direction-column"
- data-qa-selector="board_list_cards_area"
- >
- <div
- v-if="loading"
- class="gl-mt-4 gl-text-center"
- :aria-label="$options.i18n.loadingIssues"
- data-testid="board_list_loading"
- >
- <gl-loading-icon />
- </div>
- <board-new-issue v-if="list.listType !== 'closed' && showIssueForm" :list="list" />
- <component
- :is="treeRootWrapper"
- v-show="!loading"
- ref="list"
- v-bind="treeRootOptions"
- :data-board="list.id"
- :data-board-type="list.listType"
- :class="{ 'bg-danger-100': issuesSizeExceedsMax }"
- class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2 js-board-list"
- data-testid="tree-root-wrapper"
- @start="handleDragOnStart"
- @end="handleDragOnEnd"
- >
- <board-card
- v-for="(issue, index) in issues"
- ref="issue"
- :key="issue.id"
- :index="index"
- :list="list"
- :issue="issue"
- :disabled="disabled"
- />
- <li v-if="showCount" class="board-list-count gl-text-center" data-issue-id="-1">
- <gl-loading-icon v-if="loadingMore" :label="$options.i18n.loadingMoreissues" />
- <span v-if="showingAllIssues">{{ $options.i18n.showingAllIssues }}</span>
- <span v-else>{{ paginatedIssueText }}</span>
- </li>
- </component>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index a9e6d768656..14d28643046 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,94 +1,85 @@
<script>
+import { mapActions, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
import { getMilestone } from 'ee_else_ce/boards/boards_util';
-import ListIssue from 'ee_else_ce/boards/models/issue';
import eventHub from '../eventhub';
import ProjectSelect from './project_select.vue';
-import boardsStore from '../stores/boards_store';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-// This component is being replaced in favor of './board_new_issue_new.vue' for GraphQL boards
+import { __ } from '~/locale';
export default {
name: 'BoardNewIssue',
+ i18n: {
+ submit: __('Submit issue'),
+ cancel: __('Cancel'),
+ },
components: {
ProjectSelect,
GlButton,
},
mixins: [glFeatureFlagMixin()],
+ inject: ['groupId', 'weightFeatureAvailable', 'boardWeight'],
props: {
list: {
type: Object,
required: true,
},
},
- inject: ['groupId'],
data() {
return {
title: '',
- error: false,
- selectedProject: {},
};
},
computed: {
+ ...mapState(['selectedProject']),
disabled() {
if (this.groupId) {
return this.title === '' || !this.selectedProject.name;
}
return this.title === '';
},
+ inputFieldId() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `${this.list.id}-title`;
+ },
},
mounted() {
this.$refs.input.focus();
eventHub.$on('setSelectedProject', this.setSelectedProject);
},
methods: {
+ ...mapActions(['addListNewIssue']),
submit(e) {
e.preventDefault();
- if (this.title.trim() === '') return Promise.resolve();
-
- this.error = false;
const labels = this.list.label ? [this.list.label] : [];
const assignees = this.list.assignee ? [this.list.assignee] : [];
const milestone = getMilestone(this.list);
- const { weightFeatureAvailable } = boardsStore;
- const { weight } = weightFeatureAvailable ? boardsStore.state.currentBoard : {};
+ const weight = this.weightFeatureAvailable ? this.boardWeight : undefined;
- const issue = new ListIssue({
- title: this.title,
- labels,
- subscribed: true,
- assignees,
- milestone,
- project_id: this.selectedProject.id,
- weight,
- });
+ const { title } = this;
eventHub.$emit(`scroll-board-list-${this.list.id}`);
- this.cancel();
- return this.list
- .newIssue(issue)
- .then(() => {
- boardsStore.setIssueDetail(issue);
- boardsStore.setListDetail(this.list);
- })
- .catch(() => {
- this.list.removeIssue(issue);
-
- // Show error message
- this.error = true;
- });
+ return this.addListNewIssue({
+ issueInput: {
+ title,
+ labelIds: labels?.map((l) => l.id),
+ assigneeIds: assignees?.map((a) => a?.id),
+ milestoneId: milestone?.id,
+ projectPath: this.selectedProject.fullPath,
+ weight: weight >= 0 ? weight : null,
+ },
+ list: this.list,
+ }).then(() => {
+ this.reset();
+ });
},
- cancel() {
+ reset() {
this.title = '';
eventHub.$emit(`toggle-issue-form-${this.list.id}`);
},
- setSelectedProject(selectedProject) {
- this.selectedProject = selectedProject;
- },
},
};
</script>
@@ -96,13 +87,10 @@ export default {
<template>
<div class="board-new-issue-form">
<div class="board-card position-relative p-3 rounded">
- <form @submit="submit($event)">
- <div v-if="error" class="flash-container">
- <div class="flash-alert">{{ __('An error occurred. Please try again.') }}</div>
- </div>
- <label :for="list.id + '-title'" class="label-bold">{{ __('Title') }}</label>
+ <form ref="submitForm" @submit="submit">
+ <label :for="inputFieldId" class="label-bold">{{ __('Title') }}</label>
<input
- :id="list.id + '-title'"
+ :id="inputFieldId"
ref="input"
v-model="title"
class="form-control"
@@ -119,16 +107,18 @@ export default {
variant="success"
category="primary"
type="submit"
- >{{ __('Submit issue') }}</gl-button
>
+ {{ $options.i18n.submit }}
+ </gl-button>
<gl-button
ref="cancelButton"
class="float-right"
type="button"
variant="default"
- @click="cancel"
- >{{ __('Cancel') }}</gl-button
+ @click="reset"
>
+ {{ $options.i18n.cancel }}
+ </gl-button>
</div>
</form>
</div>
diff --git a/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue b/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
new file mode 100644
index 00000000000..4fc58742783
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
@@ -0,0 +1,136 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { getMilestone } from 'ee_else_ce/boards/boards_util';
+import ListIssue from 'ee_else_ce/boards/models/issue';
+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';
+
+// This component is being replaced in favor of './board_new_issue.vue' for GraphQL boards
+
+export default {
+ name: 'BoardNewIssue',
+ components: {
+ ProjectSelect,
+ GlButton,
+ },
+ mixins: [glFeatureFlagMixin()],
+ inject: ['groupId'],
+ props: {
+ list: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ title: '',
+ error: false,
+ selectedProject: {},
+ };
+ },
+ computed: {
+ disabled() {
+ if (this.groupId) {
+ return this.title === '' || !this.selectedProject.name;
+ }
+ return this.title === '';
+ },
+ },
+ mounted() {
+ this.$refs.input.focus();
+ eventHub.$on('setSelectedProject', this.setSelectedProject);
+ },
+ methods: {
+ submit(e) {
+ e.preventDefault();
+ if (this.title.trim() === '') return Promise.resolve();
+
+ this.error = false;
+
+ const labels = this.list.label ? [this.list.label] : [];
+ const assignees = this.list.assignee ? [this.list.assignee] : [];
+ const milestone = getMilestone(this.list);
+
+ const { weightFeatureAvailable } = boardsStore;
+ const { weight } = weightFeatureAvailable ? boardsStore.state.currentBoard : {};
+
+ const issue = new ListIssue({
+ title: this.title,
+ labels,
+ subscribed: true,
+ assignees,
+ milestone,
+ project_id: this.selectedProject.id,
+ weight,
+ });
+
+ eventHub.$emit(`scroll-board-list-${this.list.id}`);
+ this.cancel();
+
+ return this.list
+ .newIssue(issue)
+ .then(() => {
+ boardsStore.setIssueDetail(issue);
+ boardsStore.setListDetail(this.list);
+ })
+ .catch(() => {
+ this.list.removeIssue(issue);
+
+ // Show error message
+ this.error = true;
+ });
+ },
+ cancel() {
+ this.title = '';
+ eventHub.$emit(`toggle-issue-form-${this.list.id}`);
+ },
+ setSelectedProject(selectedProject) {
+ this.selectedProject = selectedProject;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="board-new-issue-form">
+ <div class="board-card position-relative p-3 rounded">
+ <form @submit="submit($event)">
+ <div v-if="error" class="flash-container">
+ <div class="flash-alert">{{ __('An error occurred. Please try again.') }}</div>
+ </div>
+ <label :for="list.id + '-title'" class="label-bold">{{ __('Title') }}</label>
+ <input
+ :id="list.id + '-title'"
+ ref="input"
+ v-model="title"
+ class="form-control"
+ type="text"
+ name="issue_title"
+ autocomplete="off"
+ />
+ <project-select v-if="groupId" :group-id="groupId" :list="list" />
+ <div class="clearfix gl-mt-3">
+ <gl-button
+ ref="submitButton"
+ :disabled="disabled"
+ class="float-left js-no-auto-disable"
+ variant="success"
+ category="primary"
+ type="submit"
+ >{{ __('Submit issue') }}</gl-button
+ >
+ <gl-button
+ ref="cancelButton"
+ class="float-right"
+ type="button"
+ variant="default"
+ @click="cancel"
+ >{{ __('Cancel') }}</gl-button
+ >
+ </div>
+ </form>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_new_issue_new.vue b/app/assets/javascripts/boards/components/board_new_issue_new.vue
deleted file mode 100644
index 969c84ddb59..00000000000
--- a/app/assets/javascripts/boards/components/board_new_issue_new.vue
+++ /dev/null
@@ -1,129 +0,0 @@
-<script>
-import { mapActions } from 'vuex';
-import { GlButton } from '@gitlab/ui';
-import { getMilestone } from 'ee_else_ce/boards/boards_util';
-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',
- i18n: {
- submit: __('Submit issue'),
- cancel: __('Cancel'),
- },
- components: {
- ProjectSelect,
- GlButton,
- },
- mixins: [glFeatureFlagMixin()],
- props: {
- list: {
- type: Object,
- required: true,
- },
- },
- inject: ['groupId', 'weightFeatureAvailable', 'boardWeight'],
- data() {
- return {
- title: '',
- selectedProject: {},
- };
- },
- computed: {
- disabled() {
- if (this.groupId) {
- return this.title === '' || !this.selectedProject.name;
- }
- return this.title === '';
- },
- inputFieldId() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `${this.list.id}-title`;
- },
- },
- mounted() {
- this.$refs.input.focus();
- eventHub.$on('setSelectedProject', this.setSelectedProject);
- },
- methods: {
- ...mapActions(['addListNewIssue']),
- submit(e) {
- e.preventDefault();
-
- const labels = this.list.label ? [this.list.label] : [];
- const assignees = this.list.assignee ? [this.list.assignee] : [];
- const milestone = getMilestone(this.list);
-
- const weight = this.weightFeatureAvailable ? this.boardWeight : undefined;
-
- const { title } = this;
-
- eventHub.$emit(`scroll-board-list-${this.list.id}`);
-
- return this.addListNewIssue({
- issueInput: {
- title,
- labelIds: labels?.map(l => l.id),
- assigneeIds: assignees?.map(a => a?.id),
- milestoneId: milestone?.id,
- projectPath: this.selectedProject.path,
- weight: weight >= 0 ? weight : null,
- },
- list: this.list,
- }).then(() => {
- this.reset();
- });
- },
- reset() {
- this.title = '';
- eventHub.$emit(`toggle-issue-form-${this.list.id}`);
- },
- setSelectedProject(selectedProject) {
- this.selectedProject = selectedProject;
- },
- },
-};
-</script>
-
-<template>
- <div class="board-new-issue-form">
- <div class="board-card position-relative p-3 rounded">
- <form ref="submitForm" @submit="submit">
- <label :for="inputFieldId" class="label-bold">{{ __('Title') }}</label>
- <input
- :id="inputFieldId"
- ref="input"
- v-model="title"
- class="form-control"
- type="text"
- name="issue_title"
- autocomplete="off"
- />
- <project-select v-if="groupId" :group-id="groupId" :list="list" />
- <div class="clearfix gl-mt-3">
- <gl-button
- ref="submitButton"
- :disabled="disabled"
- class="float-left js-no-auto-disable"
- variant="success"
- category="primary"
- type="submit"
- >
- {{ $options.i18n.submit }}
- </gl-button>
- <gl-button
- ref="cancelButton"
- class="float-right"
- type="button"
- variant="default"
- @click="reset"
- >
- {{ $options.i18n.cancel }}
- </gl-button>
- </div>
- </form>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index 60db8fefe82..f362fc60bd3 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -116,7 +116,7 @@ export default {
v-if="isWipLimitsOn"
:max-issue-count="activeList.maxIssueCount"
/>
- <div v-if="canAdminList && !activeList.preset && activeList.id" class="gl-m-4">
+ <div v-if="canAdminList && !activeList.preset && activeList.id" class="gl-mt-4">
<gl-button
variant="danger"
category="secondary"
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index d26f15c1723..bf3dc5c608f 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -68,7 +68,7 @@ export default Vue.extend({
: __('Label');
},
selectedLabels() {
- return this.hasLabels ? this.issue.labels.map(l => l.title).join(',') : '';
+ return this.hasLabels ? this.issue.labels.map((l) => l.title).join(',') : '';
},
},
watch: {
@@ -82,9 +82,7 @@ export default Vue.extend({
});
$('.js-issue-board-sidebar', this.$el).each((i, el) => {
- $(el)
- .data('deprecatedJQueryDropdown')
- .clearMenu();
+ $(el).data('deprecatedJQueryDropdown').clearMenu();
});
}
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 4f23c38d0f7..fcd1c3fdceb 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -118,7 +118,7 @@ export default {
return this.state.currentPage;
},
filteredBoards() {
- return this.boards.filter(board =>
+ return this.boards.filter((board) =>
board.name.toLowerCase().includes(this.filterTerm.toLowerCase()),
);
},
@@ -181,10 +181,10 @@ export default {
this.loadingRecentBoards = true;
boardsStore
.recentBoards()
- .then(res => {
+ .then((res) => {
this.recentBoards = res.data;
})
- .catch(err => {
+ .catch((err) => {
/**
* If user is unauthorized we'd still want to resolve the
* request to display all boards.
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index ddd20ff281c..457d0d4dcd6 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -1,6 +1,6 @@
<script>
import { sortBy } from 'lodash';
-import { mapState } from 'vuex';
+import { mapActions, mapState } from 'vuex';
import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
import { sprintf, __, n__ } from '~/locale';
@@ -8,9 +8,10 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
-import boardsStore from '../stores/boards_store';
+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: {
@@ -26,6 +27,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [issueCardInner],
+ inject: ['groupId', 'rootPath', 'scopedLabelsAvailable'],
props: {
issue: {
type: Object,
@@ -42,7 +44,6 @@ export default {
default: false,
},
},
- inject: ['groupId', 'rootPath'],
data() {
return {
limitBeforeCounter: 2,
@@ -52,6 +53,16 @@ export default {
},
computed: {
...mapState(['isShowingLabels']),
+ cappedAssignees() {
+ // e.g. maxRender is 4,
+ // Render up to all 4 assignees if there are only 4 assigness
+ // Otherwise render up to the limitBeforeCounter
+ if (this.issue.assignees.length <= this.maxRender) {
+ return this.issue.assignees.slice(0, this.maxRender);
+ }
+
+ return this.issue.assignees.slice(0, this.limitBeforeCounter);
+ },
numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter;
},
@@ -98,19 +109,10 @@ export default {
},
},
methods: {
+ ...mapActions(['performSearch']),
isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter;
},
- shouldRenderAssignee(index) {
- // Eg. maxRender is 4,
- // Render up to all 4 assignees if there are only 4 assigness
- // Otherwise render up to the limitBeforeCounter
- if (this.issue.assignees.length <= this.maxRender) {
- return index < this.maxRender;
- }
-
- return index < this.limitBeforeCounter;
- },
assigneeUrl(assignee) {
if (!assignee) return '';
return `${this.rootPath}${assignee.username}`;
@@ -118,6 +120,9 @@ export default {
avatarUrlTitle(assignee) {
return sprintf(__(`Avatar for %{assigneeName}`), { assigneeName: assignee.name });
},
+ avatarUrl(assignee) {
+ return assignee.avatarUrl || assignee.avatar || gon.default_avatar_url;
+ },
showLabel(label) {
if (!label.id) return false;
return true;
@@ -133,13 +138,19 @@ export default {
},
filterByLabel(label) {
if (!this.updateFilters) return;
- const labelTitle = encodeURIComponent(label.title);
- const filter = `label_name[]=${labelTitle}`;
+ const filterPath = window.location.search ? `${window.location.search}&` : '?';
+ const filter = `label_name[]=${encodeURIComponent(label.title)}`;
- boardsStore.toggleFilter(filter);
+ if (!filterPath.includes(filter)) {
+ updateHistory({
+ url: `${filterPath}${filter}`,
+ });
+ this.performSearch();
+ eventHub.$emit('updateTokens');
+ }
},
showScopedLabel(label) {
- return boardsStore.scopedLabels.enabled && isScopedLabel(label);
+ return this.scopedLabelsAvailable && isScopedLabel(label);
},
},
};
@@ -222,12 +233,11 @@ export default {
</div>
<div class="board-card-assignee gl-display-flex">
<user-avatar-link
- v-for="(assignee, index) in issue.assignees"
- v-if="shouldRenderAssignee(index)"
+ v-for="assignee in cappedAssignees"
:key="assignee.id"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
- :img-src="assignee.avatarUrl || assignee.avatar || assignee.avatar_url"
+ :img-src="avatarUrl(assignee)"
:img-size="24"
class="js-no-trigger"
tooltip-placement="bottom"
diff --git a/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue b/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
new file mode 100644
index 00000000000..75cf1f0b9e1
--- /dev/null
+++ b/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
@@ -0,0 +1,245 @@
+<script>
+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 { 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 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: {
+ GlLabel,
+ GlIcon,
+ UserAvatarLink,
+ TooltipOnTruncate,
+ IssueDueDate,
+ IssueTimeEstimate,
+ IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [issueCardInner],
+ inject: ['groupId', 'rootPath'],
+ props: {
+ issue: {
+ type: Object,
+ required: true,
+ },
+ list: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ updateFilters: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ limitBeforeCounter: 2,
+ maxRender: 3,
+ maxCounter: 99,
+ };
+ },
+ computed: {
+ ...mapState(['isShowingLabels']),
+ numberOverLimit() {
+ return this.issue.assignees.length - this.limitBeforeCounter;
+ },
+ assigneeCounterTooltip() {
+ const { numberOverLimit, maxCounter } = this;
+ const count = numberOverLimit > maxCounter ? maxCounter : numberOverLimit;
+ return sprintf(__('%{count} more assignees'), { count });
+ },
+ assigneeCounterLabel() {
+ if (this.numberOverLimit > this.maxCounter) {
+ return `${this.maxCounter}+`;
+ }
+
+ return `+${this.numberOverLimit}`;
+ },
+ shouldRenderCounter() {
+ if (this.issue.assignees.length <= this.maxRender) {
+ return false;
+ }
+
+ return this.issue.assignees.length > this.numberOverLimit;
+ },
+ issueId() {
+ if (this.issue.iid) {
+ return `#${this.issue.iid}`;
+ }
+ return false;
+ },
+ showLabelFooter() {
+ return this.isShowingLabels && this.issue.labels.find(this.showLabel);
+ },
+ issueReferencePath() {
+ const { referencePath, groupId } = this.issue;
+ return !groupId ? referencePath.split('#')[0] : null;
+ },
+ orderedLabels() {
+ return sortBy(this.issue.labels.filter(this.isNonListLabel), 'title');
+ },
+ blockedLabel() {
+ if (this.issue.blockedByCount) {
+ return n__(`Blocked by %d issue`, `Blocked by %d issues`, this.issue.blockedByCount);
+ }
+ return __('Blocked issue');
+ },
+ },
+ methods: {
+ isIndexLessThanlimit(index) {
+ return index < this.limitBeforeCounter;
+ },
+ shouldRenderAssignee(index) {
+ // Eg. maxRender is 4,
+ // Render up to all 4 assignees if there are only 4 assigness
+ // Otherwise render up to the limitBeforeCounter
+ if (this.issue.assignees.length <= this.maxRender) {
+ return index < this.maxRender;
+ }
+
+ return index < this.limitBeforeCounter;
+ },
+ assigneeUrl(assignee) {
+ if (!assignee) return '';
+ return `${this.rootPath}${assignee.username}`;
+ },
+ avatarUrlTitle(assignee) {
+ return sprintf(__(`Avatar for %{assigneeName}`), { assigneeName: assignee.name });
+ },
+ showLabel(label) {
+ if (!label.id) return false;
+ return true;
+ },
+ isNonListLabel(label) {
+ return label.id && !(this.list.type === 'label' && this.list.title === label.title);
+ },
+ filterByLabel(label) {
+ if (!this.updateFilters) return;
+ const labelTitle = encodeURIComponent(label.title);
+ const filter = `label_name[]=${labelTitle}`;
+
+ boardsStore.toggleFilter(filter);
+ },
+ showScopedLabel(label) {
+ return boardsStore.scopedLabels.enabled && isScopedLabel(label);
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <div class="gl-display-flex" dir="auto">
+ <h4 class="board-card-title gl-mb-0 gl-mt-0">
+ <gl-icon
+ v-if="issue.blocked"
+ v-gl-tooltip
+ name="issue-block"
+ :title="blockedLabel"
+ class="issue-blocked-icon gl-mr-2"
+ :aria-label="blockedLabel"
+ data-testid="issue-blocked-icon"
+ />
+ <gl-icon
+ v-if="issue.confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ class="confidential-icon gl-mr-2"
+ :aria-label="__('Confidential')"
+ />
+ <a
+ :href="issue.path || issue.webUrl || ''"
+ :title="issue.title"
+ class="js-no-trigger"
+ @mousemove.stop
+ >{{ issue.title }}</a
+ >
+ </h4>
+ </div>
+ <div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-display-flex gl-flex-wrap">
+ <template v-for="label in orderedLabels">
+ <gl-label
+ :key="label.id"
+ :background-color="label.color"
+ :title="label.title"
+ :description="label.description"
+ size="sm"
+ :scoped="showScopedLabel(label)"
+ @click="filterByLabel(label)"
+ />
+ </template>
+ </div>
+ <div
+ class="board-card-footer gl-display-flex gl-justify-content-space-between gl-align-items-flex-end"
+ >
+ <div
+ class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden js-board-card-number-container"
+ >
+ <span
+ v-if="issue.referencePath"
+ class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3"
+ >
+ <tooltip-on-truncate
+ v-if="issueReferencePath"
+ :title="issueReferencePath"
+ placement="bottom"
+ class="board-issue-path gl-text-truncate gl-font-weight-bold"
+ >{{ issueReferencePath }}</tooltip-on-truncate
+ >
+ #{{ issue.iid }}
+ </span>
+ <span class="board-info-items gl-mt-3 gl-display-inline-block">
+ <issue-due-date
+ v-if="issue.dueDate"
+ :date="issue.dueDate"
+ :closed="issue.closed || Boolean(issue.closedAt)"
+ />
+ <issue-time-estimate v-if="issue.timeEstimate" :estimate="issue.timeEstimate" />
+ <issue-card-weight
+ v-if="validIssueWeight"
+ :weight="issue.weight"
+ @click="filterByWeight(issue.weight)"
+ />
+ </span>
+ </div>
+ <div class="board-card-assignee gl-display-flex">
+ <user-avatar-link
+ v-for="(assignee, index) in issue.assignees"
+ v-if="shouldRenderAssignee(index)"
+ :key="assignee.id"
+ :link-href="assigneeUrl(assignee)"
+ :img-alt="avatarUrlTitle(assignee)"
+ :img-src="assignee.avatarUrl || assignee.avatar || assignee.avatar_url"
+ :img-size="24"
+ class="js-no-trigger"
+ tooltip-placement="bottom"
+ >
+ <span class="js-assignee-tooltip">
+ <span class="gl-font-weight-bold gl-display-block">{{ __('Assignee') }}</span>
+ {{ assignee.name }}
+ <span class="text-white-50">@{{ assignee.username }}</span>
+ </span>
+ </user-avatar-link>
+ <span
+ v-if="shouldRenderCounter"
+ v-gl-tooltip
+ :title="assigneeCounterTooltip"
+ class="avatar-counter"
+ data-placement="bottom"
+ >{{ assigneeCounterLabel }}</span
+ >
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index fe56833016e..f6b00b695da 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -1,30 +1,34 @@
<script>
import { GlTooltip, GlIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
-import boardsStore from '../stores/boards_store';
export default {
+ i18n: {
+ timeEstimate: __('Time estimate'),
+ },
components: {
GlIcon,
GlTooltip,
},
+ inject: ['timeTrackingLimitToHours'],
props: {
estimate: {
type: Number,
required: true,
},
},
- data() {
- return {
- limitToHours: boardsStore.timeTracking.limitToHours,
- };
- },
computed: {
title() {
- return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }), true);
+ return stringifyTime(
+ parseSeconds(this.estimate, { limitToHours: this.timeTrackingLimitToHours }),
+ true,
+ );
},
timeEstimate() {
- return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }));
+ return stringifyTime(
+ parseSeconds(this.estimate, { limitToHours: this.timeTrackingLimitToHours }),
+ );
},
},
};
@@ -33,16 +37,16 @@ export default {
<template>
<span>
<span ref="issueTimeEstimate" class="board-card-info card-number">
- <gl-icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{
- timeEstimate
- }}</time>
+ <gl-icon name="hourglass" class="board-card-info-icon" />
+ <time class="board-card-info-text">{{ timeEstimate }}</time>
</span>
<gl-tooltip
:target="() => $refs.issueTimeEstimate"
placement="bottom"
class="js-issue-time-estimate"
>
- <span class="bold d-block">{{ __('Time estimate') }}</span> {{ title }}
+ <span class="gl-font-weight-bold gl-display-block">{{ $options.i18n.timeEstimate }}</span>
+ {{ title }}
</gl-tooltip>
</span>
</template>
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue b/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
new file mode 100644
index 00000000000..fe56833016e
--- /dev/null
+++ b/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
@@ -0,0 +1,48 @@
+<script>
+import { GlTooltip, GlIcon } from '@gitlab/ui';
+import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
+import boardsStore from '../stores/boards_store';
+
+export default {
+ components: {
+ GlIcon,
+ GlTooltip,
+ },
+ props: {
+ estimate: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ limitToHours: boardsStore.timeTracking.limitToHours,
+ };
+ },
+ computed: {
+ title() {
+ return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }), true);
+ },
+ timeEstimate() {
+ return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }));
+ },
+ },
+};
+</script>
+
+<template>
+ <span>
+ <span ref="issueTimeEstimate" class="board-card-info card-number">
+ <gl-icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{
+ timeEstimate
+ }}</time>
+ </span>
+ <gl-tooltip
+ :target="() => $refs.issueTimeEstimate"
+ placement="bottom"
+ class="js-issue-time-estimate"
+ >
+ <span class="bold d-block">{{ __('Time estimate') }}</span> {{ title }}
+ </gl-tooltip>
+ </span>
+</template>
diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue
index d28a03da97f..10c29977cae 100644
--- a/app/assets/javascripts/boards/components/modal/footer.vue
+++ b/app/assets/javascripts/boards/components/modal/footer.vue
@@ -40,21 +40,21 @@ export default {
const firstListIndex = 1;
const list = this.modal.selectedList || this.state.lists[firstListIndex];
const selectedIssues = ModalStore.getSelectedIssues();
- const issueIds = selectedIssues.map(issue => issue.id);
+ const issueIds = selectedIssues.map((issue) => issue.id);
const req = this.buildUpdateRequest(list);
// Post the data to the backend
boardsStore.bulkUpdate(issueIds, req).catch(() => {
Flash(__('Failed to update issues, please try again.'));
- selectedIssues.forEach(issue => {
+ selectedIssues.forEach((issue) => {
list.removeIssue(issue);
list.issuesSize -= 1;
});
});
// Add the issues on the frontend
- selectedIssues.forEach(issue => {
+ selectedIssues.forEach((issue) => {
list.addIssue(issue);
list.issuesSize += 1;
});
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
index 817b3bdddb0..84d687a46b9 100644
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -65,9 +65,7 @@ export default {
this.loading = false;
};
- this.loadIssues()
- .then(loadingDone)
- .catch(loadingDone);
+ this.loadIssues().then(loadingDone).catch(loadingDone);
} else if (!this.showAddIssuesModal) {
this.issues = [];
this.selectedIssues = [];
@@ -83,9 +81,7 @@ export default {
this.filterLoading = false;
};
- this.loadIssues(true)
- .then(loadingDone)
- .catch(loadingDone);
+ this.loadIssues(true).then(loadingDone).catch(loadingDone);
}
},
deep: true,
@@ -104,13 +100,13 @@ export default {
page: this.page,
per: this.perPage,
})
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
if (clearIssues) {
this.issues = [];
}
- data.issues.forEach(issueObj => {
+ data.issues.forEach((issueObj) => {
const issue = new ListIssue(issueObj);
const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
issue.selected = Boolean(foundSelectedIssue);
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js
index d1011c24977..2bc54155163 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
@@ -40,7 +40,7 @@ $(document)
});
export default function initNewListDropdown() {
- $('.js-new-board-list').each(function() {
+ $('.js-new-board-list').each(function () {
const $dropdownToggle = $(this);
const $dropdown = $dropdownToggle.closest('.dropdown');
new CreateLabelDropdown(
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index 9c90938fc52..04699d0d3a4 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -1,120 +1,141 @@
<script>
-import $ from 'jquery';
-import { escape } from 'lodash';
-import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-import eventHub from '../eventhub';
-import Api from '../../api';
+import { mapActions, mapState } from 'vuex';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { s__ } from '~/locale';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { ListType } from '../constants';
export default {
- name: 'BoardProjectSelect',
+ name: 'ProjectSelect',
+ i18n: {
+ headerTitle: s__(`BoardNewIssue|Projects`),
+ dropdownText: s__(`BoardNewIssue|Select a project`),
+ searchPlaceholder: s__(`BoardNewIssue|Search projects`),
+ emptySearchResult: s__(`BoardNewIssue|No matching results`),
+ },
+ defaultFetchOptions: {
+ with_issues_enabled: true,
+ with_shared: false,
+ include_subgroups: true,
+ order_by: 'similarity',
+ },
components: {
- GlIcon,
+ GlIntersectionObserver,
GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlSearchBoxByType,
},
+ inject: ['groupId'],
props: {
list: {
type: Object,
required: true,
},
},
- inject: ['groupId'],
data() {
return {
- loading: true,
+ initialLoading: true,
selectedProject: {},
+ searchTerm: '',
};
},
computed: {
+ ...mapState(['groupProjects', 'groupProjectsFlags']),
selectedProjectName() {
- return this.selectedProject.name || __('Select a project');
+ return this.selectedProject.name || this.$options.i18n.dropdownText;
+ },
+ fetchOptions() {
+ const additionalAttrs = {};
+ if (this.list.type && this.list.type !== ListType.backlog) {
+ additionalAttrs.min_access_level = featureAccessLevel.EVERYONE;
+ }
+
+ return {
+ ...this.$options.defaultFetchOptions,
+ ...additionalAttrs,
+ };
+ },
+ isFetchResultEmpty() {
+ return this.groupProjects.length === 0;
+ },
+ hasNextPage() {
+ return this.groupProjectsFlags.pageInfo?.hasNextPage;
+ },
+ },
+ watch: {
+ searchTerm() {
+ this.fetchGroupProjects({ search: this.searchTerm });
},
},
mounted() {
- initDeprecatedJQueryDropdown($(this.$refs.projectsDropdown), {
- filterable: true,
- filterRemote: true,
- search: {
- fields: ['name_with_namespace'],
- },
- clicked: ({ $el, e }) => {
- e.preventDefault();
- this.selectedProject = {
- id: $el.data('project-id'),
- name: $el.data('project-name'),
- path: $el.data('project-path'),
- };
- eventHub.$emit('setSelectedProject', this.selectedProject);
- },
- selectable: true,
- data: (term, callback) => {
- this.loading = true;
- const additionalAttrs = {};
+ this.fetchGroupProjects({});
- if ((this.list.type || this.list.listType) !== ListType.backlog) {
- additionalAttrs.min_access_level = featureAccessLevel.EVERYONE;
- }
-
- return Api.groupProjects(
- this.groupId,
- term,
- {
- with_issues_enabled: true,
- with_shared: false,
- include_subgroups: true,
- order_by: 'similarity',
- ...additionalAttrs,
- },
- projects => {
- this.loading = false;
- callback(projects);
- },
- );
- },
- renderRow(project) {
- return `
- <li>
- <a href='#' class='dropdown-menu-link'
- data-project-id="${project.id}"
- data-project-name="${project.name}"
- data-project-name-with-namespace="${project.name_with_namespace}"
- data-project-path="${project.path_with_namespace}"
- >
- ${escape(project.name_with_namespace)}
- </a>
- </li>
- `;
- },
- text: project => project.name_with_namespace,
- });
+ this.initialLoading = false;
+ },
+ methods: {
+ ...mapActions(['fetchGroupProjects', 'setSelectedProject']),
+ selectProject(projectId) {
+ this.selectedProject = this.groupProjects.find((project) => project.id === projectId);
+ this.setSelectedProject(this.selectedProject);
+ },
+ loadMoreProjects() {
+ this.fetchGroupProjects({ search: this.searchTerm, fetchNext: true });
+ },
},
};
</script>
<template>
<div>
- <label class="label-bold gl-mt-3">{{ __('Project') }}</label>
- <div ref="projectsDropdown" class="dropdown dropdown-projects">
- <button
- class="dropdown-menu-toggle wide"
- type="button"
- data-toggle="dropdown"
- aria-expanded="false"
+ <label class="gl-font-weight-bold gl-mt-3" data-testid="header-label">{{
+ $options.i18n.headerTitle
+ }}</label>
+ <gl-dropdown
+ data-testid="project-select-dropdown"
+ :text="selectedProjectName"
+ :header-text="$options.i18n.headerTitle"
+ block
+ menu-class="gl-w-full!"
+ :loading="initialLoading"
+ >
+ <gl-search-box-by-type
+ v-model.trim="searchTerm"
+ debounce="250"
+ :placeholder="$options.i18n.searchPlaceholder"
+ />
+ <gl-dropdown-item
+ v-for="project in groupProjects"
+ v-show="!groupProjectsFlags.isLoading"
+ :key="project.id"
+ :name="project.name"
+ @click="selectProject(project.id)"
+ >
+ {{ project.nameWithNamespace }}
+ </gl-dropdown-item>
+ <gl-dropdown-text
+ v-show="groupProjectsFlags.isLoading"
+ data-testid="dropdown-text-loading-icon"
+ >
+ <gl-loading-icon class="gl-mx-auto" />
+ </gl-dropdown-text>
+ <gl-dropdown-text
+ v-if="isFetchResultEmpty && !groupProjectsFlags.isLoading"
+ data-testid="empty-result-message"
>
- {{ selectedProjectName }} <gl-icon name="chevron-down" class="dropdown-menu-toggle-icon" />
- </button>
- <div class="dropdown-menu dropdown-menu-selectable dropdown-menu-full-width">
- <div class="dropdown-title">{{ __('Projects') }}</div>
- <div class="dropdown-input">
- <input class="dropdown-input-field" type="search" :placeholder="__('Search projects')" />
- <gl-icon name="search" class="dropdown-input-search" data-hidden="true" />
- </div>
- <div class="dropdown-content"></div>
- <div class="dropdown-loading"><gl-loading-icon /></div>
- </div>
- </div>
+ <span class="gl-text-gray-500">{{ $options.i18n.emptySearchResult }}</span>
+ </gl-dropdown-text>
+ <gl-intersection-observer v-if="hasNextPage" @appear="loadMoreProjects">
+ <gl-loading-icon v-if="groupProjectsFlags.isLoadingMore" size="md" />
+ </gl-intersection-observer>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/project_select_deprecated.vue b/app/assets/javascripts/boards/components/project_select_deprecated.vue
new file mode 100644
index 00000000000..a043dc575ca
--- /dev/null
+++ b/app/assets/javascripts/boards/components/project_select_deprecated.vue
@@ -0,0 +1,145 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ 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 { ListType } from '../constants';
+
+export default {
+ name: 'ProjectSelect',
+ i18n: {
+ headerTitle: s__(`BoardNewIssue|Projects`),
+ dropdownText: s__(`BoardNewIssue|Select a project`),
+ searchPlaceholder: s__(`BoardNewIssue|Search projects`),
+ emptySearchResult: s__(`BoardNewIssue|No matching results`),
+ },
+ defaultFetchOptions: {
+ with_issues_enabled: true,
+ with_shared: false,
+ include_subgroups: true,
+ order_by: 'similarity',
+ },
+ components: {
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlSearchBoxByType,
+ },
+ inject: ['groupId'],
+ props: {
+ list: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ initialLoading: true,
+ isFetching: false,
+ projects: [],
+ selectedProject: {},
+ searchTerm: '',
+ };
+ },
+ computed: {
+ selectedProjectName() {
+ return this.selectedProject.name || this.$options.i18n.dropdownText;
+ },
+ fetchOptions() {
+ const additionalAttrs = {};
+ if (this.list.type && this.list.type !== ListType.backlog) {
+ additionalAttrs.min_access_level = featureAccessLevel.EVERYONE;
+ }
+
+ return {
+ ...this.$options.defaultFetchOptions,
+ ...additionalAttrs,
+ };
+ },
+ isFetchResultEmpty() {
+ return this.projects.length === 0;
+ },
+ },
+ watch: {
+ searchTerm() {
+ this.fetchProjects();
+ },
+ },
+ async mounted() {
+ await this.fetchProjects();
+
+ this.initialLoading = false;
+ },
+ methods: {
+ async fetchProjects() {
+ this.isFetching = true;
+ try {
+ const projects = await Api.groupProjects(this.groupId, this.searchTerm, this.fetchOptions);
+
+ this.projects = projects.map((project) => {
+ return {
+ id: project.id,
+ name: project.name,
+ namespacedName: project.name_with_namespace,
+ path: project.path_with_namespace,
+ };
+ });
+ } catch (err) {
+ /* Handled in Api.groupProjects */
+ } finally {
+ this.isFetching = false;
+ }
+ },
+ selectProject(projectId) {
+ this.selectedProject = this.projects.find((project) => project.id === projectId);
+
+ eventHub.$emit('setSelectedProject', this.selectedProject);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <label class="gl-font-weight-bold gl-mt-3" data-testid="header-label">{{
+ $options.i18n.headerTitle
+ }}</label>
+ <gl-dropdown
+ data-testid="project-select-dropdown"
+ :text="selectedProjectName"
+ :header-text="$options.i18n.headerTitle"
+ block
+ menu-class="gl-w-full!"
+ :loading="initialLoading"
+ >
+ <gl-search-box-by-type
+ v-model.trim="searchTerm"
+ debounce="250"
+ :placeholder="$options.i18n.searchPlaceholder"
+ />
+ <gl-dropdown-item
+ v-for="project in projects"
+ v-show="!isFetching"
+ :key="project.id"
+ :name="project.name"
+ @click="selectProject(project.id)"
+ >
+ {{ project.namespacedName }}
+ </gl-dropdown-item>
+ <gl-dropdown-text v-show="isFetching" data-testid="dropdown-text-loading-icon">
+ <gl-loading-icon class="gl-mx-auto" />
+ </gl-dropdown-text>
+ <gl-dropdown-text v-if="isFetchResultEmpty && !isFetching" data-testid="empty-result-message">
+ <span class="gl-text-gray-500">{{ $options.i18n.emptySearchResult }}</span>
+ </gl-dropdown-text>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
index ce267be6d45..61863bbe2a9 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
@@ -3,6 +3,7 @@ import { GlButton, GlLoadingIcon } from '@gitlab/ui';
export default {
components: { GlButton, GlLoadingIcon },
+ inject: ['canUpdate'],
props: {
title: {
type: String,
@@ -14,20 +15,41 @@ export default {
required: false,
default: false,
},
+ toggleHeader: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ handleOffClick: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
- inject: ['canUpdate'],
data() {
return {
edit: false,
};
},
+ computed: {
+ showHeader() {
+ if (!this.toggleHeader) {
+ return true;
+ }
+
+ return !this.edit;
+ },
+ },
destroyed() {
window.removeEventListener('click', this.collapseWhenOffClick);
},
methods: {
collapseWhenOffClick({ target }) {
if (!this.$el.contains(target)) {
- this.collapse();
+ this.$emit('off-click');
+ if (this.handleOffClick) {
+ this.collapse();
+ }
}
},
expand() {
@@ -63,21 +85,26 @@ export default {
<template>
<div>
- <div class="gl-display-flex gl-justify-content-space-between gl-mb-3">
+ <header
+ v-show="showHeader"
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-flex-start gl-mb-3"
+ >
<span class="gl-vertical-align-middle">
- <span data-testid="title">{{ title }}</span>
+ <slot name="title">
+ <span data-testid="title">{{ title }}</span>
+ </slot>
<gl-loading-icon v-if="loading" inline class="gl-ml-2" />
</span>
<gl-button
v-if="canUpdate"
variant="link"
- class="gl-text-gray-900! js-sidebar-dropdown-toggle"
+ class="gl-text-gray-900! gl-ml-5 js-sidebar-dropdown-toggle"
data-testid="edit-button"
@click="toggle"
>
{{ __('Edit') }}
</gl-button>
- </div>
+ </header>
<div v-show="!edit" class="gl-text-gray-500" data-testid="collapsed-content">
<slot name="collapsed">{{ __('None') }}</slot>
</div>
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 904ceaed1b3..4a664d5beef 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
@@ -18,16 +18,16 @@ export default {
};
},
computed: {
- ...mapGetters({ issue: 'activeIssue', projectPathForActiveIssue: 'projectPathForActiveIssue' }),
+ ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
hasDueDate() {
- return this.issue.dueDate != null;
+ return this.activeIssue.dueDate != null;
},
parsedDueDate() {
if (!this.hasDueDate) {
return null;
}
- return parsePikadayDate(this.issue.dueDate);
+ return parsePikadayDate(this.activeIssue.dueDate);
},
formattedDueDate() {
if (!this.hasDueDate) {
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
new file mode 100644
index 00000000000..d0e641daf5c
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
@@ -0,0 +1,171 @@
+<script>
+import { mapGetters, mapActions } from 'vuex';
+import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
+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 { __ } from '~/locale';
+
+export default {
+ components: {
+ GlForm,
+ GlAlert,
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ BoardEditableItem,
+ },
+ directives: {
+ autofocusonshow,
+ },
+ data() {
+ return {
+ title: '',
+ loading: false,
+ showChangesAlert: false,
+ };
+ },
+ computed: {
+ ...mapGetters({ issue: 'activeIssue' }),
+ pendingChangesStorageKey() {
+ return this.getPendingChangesKey(this.issue);
+ },
+ projectPath() {
+ const referencePath = this.issue.referencePath || '';
+ return referencePath.slice(0, referencePath.indexOf('#'));
+ },
+ validationState() {
+ return Boolean(this.title);
+ },
+ },
+ watch: {
+ issue: {
+ handler(updatedIssue, formerIssue) {
+ if (formerIssue?.title !== this.title) {
+ localStorage.setItem(this.getPendingChangesKey(formerIssue), this.title);
+ }
+
+ this.title = updatedIssue.title;
+ this.setPendingState();
+ },
+ immediate: true,
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveIssueTitle']),
+ getPendingChangesKey(issue) {
+ if (!issue) {
+ return '';
+ }
+
+ return joinPaths(
+ window.location.pathname.slice(1),
+ String(issue.id),
+ 'issue-title-pending-changes',
+ );
+ },
+ async setPendingState() {
+ const pendingChanges = localStorage.getItem(this.pendingChangesStorageKey);
+
+ if (pendingChanges) {
+ this.title = pendingChanges;
+ this.showChangesAlert = true;
+ await this.$nextTick();
+ this.$refs.sidebarItem.expand();
+ } else {
+ this.showChangesAlert = false;
+ }
+ },
+ cancel() {
+ this.title = this.issue.title;
+ this.$refs.sidebarItem.collapse();
+ this.showChangesAlert = false;
+ localStorage.removeItem(this.pendingChangesStorageKey);
+ },
+ async setTitle() {
+ this.$refs.sidebarItem.collapse();
+
+ if (!this.title || this.title === this.issue.title) {
+ return;
+ }
+
+ try {
+ this.loading = true;
+ await this.setActiveIssueTitle({ title: this.title, projectPath: this.projectPath });
+ localStorage.removeItem(this.pendingChangesStorageKey);
+ this.showChangesAlert = false;
+ } catch (e) {
+ this.title = this.issue.title;
+ createFlash({ message: this.$options.i18n.updateTitleError });
+ } finally {
+ this.loading = false;
+ }
+ },
+ handleOffClick() {
+ if (this.title !== this.issue.title) {
+ this.showChangesAlert = true;
+ localStorage.setItem(this.pendingChangesStorageKey, this.title);
+ } else {
+ this.$refs.sidebarItem.collapse();
+ }
+ },
+ },
+ i18n: {
+ issueTitlePlaceholder: __('Issue title'),
+ submitButton: __('Save changes'),
+ cancelButton: __('Cancel'),
+ updateTitleError: __('An error occurred when updating the issue title'),
+ invalidFeedback: __('An issue title is required'),
+ reviewYourChanges: __('Changes to the title have not been saved'),
+ },
+};
+</script>
+
+<template>
+ <board-editable-item
+ ref="sidebarItem"
+ toggle-header
+ :loading="loading"
+ :handle-off-click="false"
+ @off-click="handleOffClick"
+ >
+ <template #title>
+ <span class="gl-font-weight-bold" data-testid="issue-title">{{ issue.title }}</span>
+ </template>
+ <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>
+
+ <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>
+ </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 6a407bd6ba6..dcf769e6fe5 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
@@ -14,18 +14,18 @@ export default {
LabelsSelect,
GlLabel,
},
+ inject: ['labelsFetchPath', 'labelsManagePath', 'labelsFilterBasePath'],
data() {
return {
loading: false,
};
},
- inject: ['labelsFetchPath', 'labelsManagePath', 'labelsFilterBasePath'],
computed: {
...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
selectedLabels() {
const { labels = [] } = this.activeIssue;
- return labels.map(label => ({
+ return labels.map((label) => ({
...label,
id: getIdFromGraphQLId(label.id),
}));
@@ -33,7 +33,7 @@ export default {
issueLabels() {
const { labels = [] } = this.activeIssue;
- return labels.map(label => ({
+ return labels.map((label) => ({
...label,
scoped: isScopedLabel(label),
}));
@@ -46,10 +46,10 @@ export default {
this.$refs.sidebarItem.collapse();
try {
- const addLabelIds = payload.filter(label => label.set).map(label => label.id);
+ const addLabelIds = payload.filter((label) => label.set).map((label) => label.id);
const removeLabelIds = this.selectedLabels
- .filter(label => !payload.find(selected => selected.id === label.id))
- .map(label => label.id);
+ .filter((label) => !payload.find((selected) => selected.id === label.id))
+ .map((label) => label.id);
const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveIssueLabels(input);
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 78c3f8acc62..144a81f009b 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
@@ -50,7 +50,7 @@ export default {
},
update(data) {
const edges = data?.group?.milestones?.edges ?? [];
- return edges.map(item => item.node);
+ return edges.map((item) => item.node);
},
error() {
createFlash({ message: this.$options.i18n.fetchMilestonesError });
@@ -58,20 +58,20 @@ export default {
},
},
computed: {
- ...mapGetters({ issue: 'activeIssue' }),
+ ...mapGetters(['activeIssue']),
hasMilestone() {
- return this.issue.milestone !== null;
+ return this.activeIssue.milestone !== null;
},
groupFullPath() {
- const { referencePath = '' } = this.issue;
+ const { referencePath = '' } = this.activeIssue;
return referencePath.slice(0, referencePath.indexOf('/'));
},
projectPath() {
- const { referencePath = '' } = this.issue;
+ const { referencePath = '' } = this.activeIssue;
return referencePath.slice(0, referencePath.indexOf('#'));
},
dropdownText() {
- return this.issue.milestone?.title ?? this.$options.i18n.noMilestone;
+ return this.activeIssue.milestone?.title ?? this.$options.i18n.noMilestone;
},
},
mounted() {
@@ -120,7 +120,7 @@ export default {
@close="edit = false"
>
<template v-if="hasMilestone" #collapsed>
- <strong class="gl-text-gray-900">{{ issue.milestone.title }}</strong>
+ <strong class="gl-text-gray-900">{{ activeIssue.milestone.title }}</strong>
</template>
<template>
<gl-dropdown
@@ -133,7 +133,7 @@ export default {
<gl-dropdown-item
data-testid="no-milestone-item"
:is-check-item="true"
- :is-checked="!issue.milestone"
+ :is-checked="!activeIssue.milestone"
@click="setMilestone(null)"
>
{{ $options.i18n.noMilestone }}
@@ -145,7 +145,7 @@ export default {
v-for="milestone in milestones"
:key="milestone.id"
:is-check-item="true"
- :is-checked="issue.milestone && milestone.id === issue.milestone.id"
+ :is-checked="activeIssue.milestone && milestone.id === activeIssue.milestone.id"
data-testid="milestone-item"
@click="setMilestone(milestone.id)"
>
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 ed069cea630..4aa8d2f55e4 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
@@ -15,7 +15,7 @@ export default {
),
},
updateSubscribedErrorMessage: s__(
- 'IssueBoards|An error occurred while setting notifications status.',
+ 'IssueBoards|An error occurred while setting notifications status. Please try again.',
),
},
components: {
diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.vue b/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
index 4e5a6609042..8d65f3240c8 100644
--- a/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
+++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
@@ -42,13 +42,13 @@ export default {
axios.patch(this.updateUrl, data).catch(() => {
Flash(__('Failed to remove issue from board, please try again.'));
- lists.forEach(list => {
+ lists.forEach((list) => {
list.addIssue(issue);
});
});
// Remove from the frontend store
- lists.forEach(list => {
+ lists.forEach((list) => {
list.removeIssue(issue);
});
@@ -58,9 +58,11 @@ export default {
* Build the default patch request.
*/
buildPatchRequest(issue, lists) {
- const listLabelIds = lists.map(list => list.label.id);
+ const listLabelIds = lists.map((list) => list.label.id);
- const labelIds = issue.labels.map(label => label.id).filter(id => !listLabelIds.includes(id));
+ const labelIds = issue.labels
+ .map((label) => label.id)
+ .filter((id) => !listLabelIds.includes(id));
return {
label_ids: labelIds,
diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js
index 1667dcc9f2e..94b35aadaf1 100644
--- a/app/assets/javascripts/boards/filtered_search_boards.js
+++ b/app/assets/javascripts/boards/filtered_search_boards.js
@@ -23,8 +23,8 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
// Issue boards is slightly different, we handle all the requests async
// instead or reloading the page, we just re-fire the list ajax requests
this.isHandledAsync = true;
- this.cantEdit = cantEdit.filter(i => typeof i === 'string');
- this.cantEditWithValue = cantEdit.filter(i => typeof i === 'object');
+ this.cantEdit = cantEdit.filter((i) => typeof i === 'string');
+ this.cantEditWithValue = cantEdit.filter((i) => typeof i === 'object');
if (vuexstore.getters.shouldUseGraphQL && vuexstore.state.boardConfig) {
const boardConfigPath = transformBoardConfig(vuexstore.state.boardConfig);
@@ -55,7 +55,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
const tokens = FilteredSearchContainer.container.querySelectorAll('.js-visual-token');
// Remove all the tokens as they will be replaced by the search manager
- [].forEach.call(tokens, el => {
+ [].forEach.call(tokens, (el) => {
el.parentNode.removeChild(el);
});
@@ -75,7 +75,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
if (this.cantEdit.includes(tokenName)) return false;
return (
this.cantEditWithValue.findIndex(
- token => token.name === tokenName && token.value === tokenValue,
+ (token) => token.name === tokenName && token.value === tokenValue,
) === -1
);
}
diff --git a/app/assets/javascripts/boards/filters/due_date_filters.js b/app/assets/javascripts/boards/filters/due_date_filters.js
index 9eaa0cd227d..c35dedde71b 100644
--- a/app/assets/javascripts/boards/filters/due_date_filters.js
+++ b/app/assets/javascripts/boards/filters/due_date_filters.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import dateFormat from 'dateformat';
-Vue.filter('due-date', value => {
+Vue.filter('due-date', (value) => {
const date = new Date(value);
return dateFormat(date, 'mmm d, yyyy', true);
});
diff --git a/app/assets/javascripts/boards/graphql/board.mutation.graphql b/app/assets/javascripts/boards/graphql/board.mutation.graphql
deleted file mode 100644
index ef2b81a7939..00000000000
--- a/app/assets/javascripts/boards/graphql/board.mutation.graphql
+++ /dev/null
@@ -1,11 +0,0 @@
-mutation UpdateBoard($id: ID!, $hideClosedList: Boolean, $hideBacklogList: Boolean) {
- updateBoard(
- input: { id: $id, hideClosedList: $hideClosedList, hideBacklogList: $hideBacklogList }
- ) {
- board {
- id
- hideClosedList
- hideBacklogList
- }
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/board_create.mutation.graphql b/app/assets/javascripts/boards/graphql/board_create.mutation.graphql
new file mode 100644
index 00000000000..b3ea79d6443
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/board_create.mutation.graphql
@@ -0,0 +1,9 @@
+mutation createBoard($input: CreateBoardInput!) {
+ createBoard(input: $input) {
+ board {
+ id
+ webPath
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/board_destroy.mutation.graphql b/app/assets/javascripts/boards/graphql/board_destroy.mutation.graphql
new file mode 100644
index 00000000000..d4b928749de
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/board_destroy.mutation.graphql
@@ -0,0 +1,7 @@
+mutation destroyBoard($id: BoardID!) {
+ destroyBoard(input: { id: $id }) {
+ board {
+ id
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/board_update.mutation.graphql b/app/assets/javascripts/boards/graphql/board_update.mutation.graphql
new file mode 100644
index 00000000000..3abe09079c7
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/board_update.mutation.graphql
@@ -0,0 +1,9 @@
+mutation UpdateBoard($input: UpdateBoardInput!) {
+ updateBoard(input: $input) {
+ board {
+ id
+ webPath
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/group_projects.query.graphql b/app/assets/javascripts/boards/graphql/group_projects.query.graphql
new file mode 100644
index 00000000000..1afa6e48547
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/group_projects.query.graphql
@@ -0,0 +1,17 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getGroupProjects($fullPath: ID!, $search: String, $after: String) {
+ group(fullPath: $fullPath) {
+ projects(search: $search, after: $after, first: 100) {
+ nodes {
+ id
+ name
+ fullPath
+ nameWithNamespace
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
new file mode 100644
index 00000000000..62e6c1352a6
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
@@ -0,0 +1,8 @@
+mutation issueSetTitle($input: UpdateIssueInput!) {
+ updateIssue(input: $input) {
+ issue {
+ title
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 64a4f246735..ef70a094f7c 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -55,7 +55,7 @@ export default () => {
const $boardApp = document.getElementById('board-app');
// check for browser back and trigger a hard reload to circumvent browser caching.
- window.addEventListener('pageshow', event => {
+ window.addEventListener('pageshow', (event) => {
const isNavTypeBackForward =
window.performance && window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD;
@@ -68,8 +68,10 @@ export default () => {
issueBoardsApp.$destroy(true);
}
- boardsStore.create();
- boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours);
+ if (!gon?.features?.graphqlBoardLists) {
+ boardsStore.create();
+ boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours);
+ }
issueBoardsApp = new Vue({
el: $boardApp,
@@ -117,16 +119,9 @@ export default () => {
},
},
created() {
- const endpoints = {
- boardsEndpoint: this.boardsEndpoint,
- recentBoardsEndpoint: this.recentBoardsEndpoint,
- listsEndpoint: this.listsEndpoint,
- bulkUpdatePath: this.bulkUpdatePath,
+ this.setInitialBoardData({
boardId: $boardApp.dataset.boardId,
fullPath: $boardApp.dataset.fullPath,
- };
- this.setInitialBoardData({
- ...endpoints,
boardType: this.parent,
disabled: this.disabled,
boardConfig: {
@@ -134,14 +129,23 @@ export default () => {
milestoneTitle: $boardApp.dataset.boardMilestoneTitle || '',
iterationId: parseInt($boardApp.dataset.boardIterationId, 10),
iterationTitle: $boardApp.dataset.boardIterationTitle || '',
+ assigneeId: $boardApp.dataset.boardAssigneeId,
assigneeUsername: $boardApp.dataset.boardAssigneeUsername,
- labels: $boardApp.dataset.labels ? JSON.parse($boardApp.dataset.labels || []) : [],
+ labels: $boardApp.dataset.labels ? JSON.parse($boardApp.dataset.labels) : [],
+ labelIds: $boardApp.dataset.labelIds ? JSON.parse($boardApp.dataset.labelIds) : [],
weight: $boardApp.dataset.boardWeight
? parseInt($boardApp.dataset.boardWeight, 10)
: null,
},
});
- boardsStore.setEndpoints(endpoints);
+ boardsStore.setEndpoints({
+ boardsEndpoint: this.boardsEndpoint,
+ recentBoardsEndpoint: this.recentBoardsEndpoint,
+ listsEndpoint: this.listsEndpoint,
+ bulkUpdatePath: this.bulkUpdatePath,
+ boardId: $boardApp.dataset.boardId,
+ fullPath: $boardApp.dataset.fullPath,
+ });
boardsStore.rootPath = this.boardsEndpoint;
eventHub.$on('updateTokens', this.updateTokens);
@@ -174,9 +178,9 @@ export default () => {
initialBoardLoad() {
boardsStore
.all()
- .then(res => res.data)
- .then(lists => {
- lists.forEach(list => boardsStore.addList(list));
+ .then((res) => res.data)
+ .then((lists) => {
+ lists.forEach((list) => boardsStore.addList(list));
this.loading = false;
})
.catch(() => {
@@ -194,8 +198,8 @@ export default () => {
setEpicFetchingState(newIssue, true);
boardsStore
.getIssueInfo(sidebarInfoEndpoint)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
const {
subscribed,
totalTimeSpent,
@@ -305,7 +309,7 @@ export default () => {
if (!this.store) {
return true;
}
- return !this.store.lists.filter(list => !list.preset).length;
+ return !this.store.lists.filter((list) => !list.preset).length;
},
},
methods: {
@@ -335,7 +339,7 @@ export default () => {
}
mountMultipleBoardsSwitcher({
- boardsEndpoint: $boardApp.dataset.boardsEndpoint,
- recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
+ fullPath: $boardApp.dataset.fullPath,
+ rootPath: $boardApp.dataset.boardsEndpoint,
});
};
diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js b/app/assets/javascripts/boards/mixins/sortable_default_options.js
index f02c92e4230..a95d749d71c 100644
--- a/app/assets/javascripts/boards/mixins/sortable_default_options.js
+++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js
@@ -24,7 +24,7 @@ export function getBoardSortableDefaultOptions(obj) {
onEnd: sortableEnd,
};
- Object.keys(obj).forEach(key => {
+ Object.keys(obj).forEach((key) => {
defaultSortOptions[key] = obj[key];
});
return defaultSortOptions;
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index 822e6d62ab3..1e77326ba9c 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -70,7 +70,7 @@ class ListIssue {
}
getLists() {
- return boardsStore.state.lists.filter(list => list.findIssue(this.id));
+ return boardsStore.state.lists.filter((list) => list.findIssue(this.id));
}
updateData(newData) {
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index 09f5d5b4dd8..be02ac7b889 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -35,7 +35,7 @@ class List {
constructor(obj) {
this.id = obj.id;
this.position = obj.position;
- this.title = (obj.list_type || obj.listType) === 'backlog' ? __('Open') : obj.title;
+ this.title = obj.title;
this.type = obj.list_type || obj.listType;
const typeInfo = this.getTypeInfo(this.type);
@@ -134,7 +134,7 @@ class List {
updateMultipleIssues(issues, listFrom, moveBeforeId, moveAfterId) {
boardsStore
.moveMultipleIssues({
- ids: issues.map(issue => issue.id),
+ ids: issues.map((issue) => issue.id),
fromListId: listFrom.id,
toListId: this.id,
moveBeforeId,
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
index df65ebb7526..738c8fb927e 100644
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
@@ -10,7 +10,7 @@ const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
-export default (endpoints = {}) => {
+export default (params = {}) => {
const boardsSwitcherElement = document.getElementById('js-multiple-boards-switcher');
return new Vue({
el: boardsSwitcherElement,
@@ -18,6 +18,10 @@ export default (endpoints = {}) => {
BoardsSelector,
},
apolloProvider,
+ provide: {
+ fullPath: params.fullPath,
+ rootPath: params.rootPath,
+ },
data() {
const { dataset } = boardsSwitcherElement;
@@ -35,9 +39,6 @@ export default (endpoints = {}) => {
return { boardsSelectorProps };
},
- provide: {
- endpoints,
- },
render(createElement) {
return createElement(BoardsSelector, {
props: this.boardsSelectorProps,
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 59b97eba9fe..1d34f21798a 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -12,6 +12,8 @@ import {
fullBoardId,
formatListsPageInfo,
formatIssue,
+ formatIssueInput,
+ updateListPosition,
} from '../boards_util';
import createFlash from '~/flash';
import { __ } from '~/locale';
@@ -27,6 +29,8 @@ import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql
import issueSetDueDateMutation from '../graphql/issue_set_due_date.mutation.graphql';
import issueSetSubscriptionMutation from '../graphql/issue_set_subscription.mutation.graphql';
import issueSetMilestoneMutation from '../graphql/issue_set_milestone.mutation.graphql';
+import issueSetTitleMutation from '../graphql/issue_set_title.mutation.graphql';
+import groupProjectsQuery from '../graphql/group_projects.query.graphql';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
@@ -78,8 +82,7 @@ export default {
},
fetchLists: ({ commit, state, dispatch }) => {
- const { endpoints, boardType, filterParams } = state;
- const { fullPath, boardId } = endpoints;
+ const { boardType, filterParams, fullPath, boardId } = state;
const variables = {
fullPath,
@@ -98,7 +101,7 @@ export default {
const { lists, hideBacklogList } = data[boardType]?.board;
commit(types.RECEIVE_BOARD_LISTS_SUCCESS, formatBoardLists(lists));
// Backlog list needs to be created if it doesn't exist and it's not hidden
- if (!lists.nodes.find(l => l.listType === ListType.backlog) && !hideBacklogList) {
+ if (!lists.nodes.find((l) => l.listType === ListType.backlog) && !hideBacklogList) {
dispatch('createList', { backlog: true });
}
})
@@ -106,7 +109,7 @@ export default {
},
createList: ({ state, commit, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => {
- const { boardId } = state.endpoints;
+ const { boardId } = state;
gqlClient
.mutate({
@@ -131,12 +134,11 @@ export default {
},
addList: ({ commit }, list) => {
- commit(types.RECEIVE_ADD_LIST_SUCCESS, list);
+ commit(types.RECEIVE_ADD_LIST_SUCCESS, updateListPosition(list));
},
fetchLabels: ({ state, commit }, searchTerm) => {
- const { endpoints, boardType } = state;
- const { fullPath } = endpoints;
+ const { fullPath, boardType } = state;
const variables = {
fullPath,
@@ -214,11 +216,17 @@ export default {
listId,
},
})
- .then(({ data: { destroyBoardList: { errors } } }) => {
- if (errors.length > 0) {
- commit(types.REMOVE_LIST_FAILURE, listsBackup);
- }
- })
+ .then(
+ ({
+ data: {
+ destroyBoardList: { errors },
+ },
+ }) => {
+ if (errors.length > 0) {
+ commit(types.REMOVE_LIST_FAILURE, listsBackup);
+ }
+ },
+ )
.catch(() => {
commit(types.REMOVE_LIST_FAILURE, listsBackup);
});
@@ -227,8 +235,7 @@ export default {
fetchIssuesForList: ({ state, commit }, { listId, fetchNext = false }) => {
commit(types.REQUEST_ISSUES_FOR_LIST, { listId, fetchNext });
- const { endpoints, boardType, filterParams } = state;
- const { fullPath, boardId } = endpoints;
+ const { fullPath, boardId, boardType, filterParams } = state;
const variables = {
fullPath,
@@ -271,7 +278,7 @@ export default {
const originalIndex = fromList.indexOf(Number(issueId));
commit(types.MOVE_ISSUE, { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId });
- const { boardId } = state.endpoints;
+ const { boardId } = state;
const [fullProjectPath] = issuePath.split(/[#]/);
gqlClient
@@ -356,10 +363,13 @@ export default {
},
createNewIssue: ({ commit, state }, issueInput) => {
- const input = issueInput;
- const { boardType, endpoints } = state;
+ const { boardConfig } = state;
+
+ const input = formatIssueInput(issueInput, boardConfig);
+
+ const { boardType, fullPath } = state;
if (boardType === BoardType.project) {
- input.projectPath = endpoints.fullPath;
+ input.projectPath = fullPath;
}
return gqlClient
@@ -387,7 +397,7 @@ export default {
commit(types.ADD_ISSUE_TO_LIST, { list, issue, position: 0 });
dispatch('createNewIssue', issueInput)
- .then(res => {
+ .then((res) => {
commit(types.ADD_ISSUE_TO_LIST, {
list,
issue: formatIssue({ ...res, id: getIdFromGraphQLId(res.id) }),
@@ -469,6 +479,61 @@ export default {
});
},
+ setActiveIssueTitle: async ({ commit, getters }, input) => {
+ const { activeIssue } = getters;
+ const { data } = await gqlClient.mutate({
+ mutation: issueSetTitleMutation,
+ variables: {
+ input: {
+ iid: String(activeIssue.iid),
+ projectPath: input.projectPath,
+ title: input.title,
+ },
+ },
+ });
+
+ if (data.updateIssue?.errors?.length > 0) {
+ throw new Error(data.updateIssue.errors);
+ }
+
+ commit(types.UPDATE_ISSUE_BY_ID, {
+ issueId: activeIssue.id,
+ prop: 'title',
+ value: data.updateIssue.issue.title,
+ });
+ },
+
+ fetchGroupProjects: ({ commit, state }, { search = '', fetchNext = false }) => {
+ commit(types.REQUEST_GROUP_PROJECTS, fetchNext);
+
+ const { fullPath } = state;
+
+ const variables = {
+ fullPath,
+ search: search !== '' ? search : undefined,
+ after: fetchNext ? state.groupProjectsFlags.pageInfo.endCursor : undefined,
+ };
+
+ return gqlClient
+ .query({
+ query: groupProjectsQuery,
+ variables,
+ })
+ .then(({ data }) => {
+ const { projects } = data.group;
+ commit(types.RECEIVE_GROUP_PROJECTS_SUCCESS, {
+ projects: projects.nodes,
+ pageInfo: projects.pageInfo,
+ fetchNext,
+ });
+ })
+ .catch(() => commit(types.RECEIVE_GROUP_PROJECTS_FAILURE));
+ },
+
+ setSelectedProject: ({ commit }, project) => {
+ commit(types.SET_SELECTED_PROJECT, project);
+ },
+
fetchBacklog: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 36702b6ca5f..f59530ddf8f 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -101,7 +101,7 @@ const boardsStore = {
},
new(listObj) {
const list = this.addList(listObj);
- const backlogList = this.findList('type', 'backlog', 'backlog');
+ const backlogList = this.findList('type', 'backlog');
list
.save()
@@ -124,7 +124,7 @@ const boardsStore = {
},
findIssueLabel(issue, findLabel) {
- return issue.labels.find(label => label.id === findLabel.id);
+ return issue.labels.find((label) => label.id === findLabel.id);
},
goToNextPage(list) {
@@ -182,15 +182,15 @@ const boardsStore = {
}
},
findListIssue(list, id) {
- return list.issues.find(issue => issue.id === id);
+ return list.issues.find((issue) => issue.id === id);
},
- removeList(id, type = 'blank') {
- const list = this.findList('id', id, type);
+ removeList(id) {
+ const list = this.findList('id', id);
if (!list) return;
- this.state.lists = this.state.lists.filter(list => list.id !== id);
+ this.state.lists = this.state.lists.filter((list) => list.id !== id);
},
moveList(listFrom, orderLists) {
orderLists.forEach((id, i) => {
@@ -205,7 +205,7 @@ const boardsStore = {
let moveBeforeId = null;
let moveAfterId = null;
- const listHasIssues = issues.every(issue => list.findIssue(issue.id));
+ const listHasIssues = issues.every((issue) => list.findIssue(issue.id));
if (!listHasIssues) {
if (newIndex !== undefined) {
@@ -223,21 +223,21 @@ const boardsStore = {
}
if (list.label) {
- issues.forEach(issue => issue.addLabel(list.label));
+ issues.forEach((issue) => issue.addLabel(list.label));
}
if (list.assignee) {
if (listFrom && listFrom.type === 'assignee') {
- issues.forEach(issue => issue.removeAssignee(listFrom.assignee));
+ issues.forEach((issue) => issue.removeAssignee(listFrom.assignee));
}
- issues.forEach(issue => issue.addAssignee(list.assignee));
+ issues.forEach((issue) => issue.addAssignee(list.assignee));
}
if (IS_EE && list.milestone) {
if (listFrom && listFrom.type === 'milestone') {
- issues.forEach(issue => issue.removeMilestone(listFrom.milestone));
+ issues.forEach((issue) => issue.removeMilestone(listFrom.milestone));
}
- issues.forEach(issue => issue.addMilestone(list.milestone));
+ issues.forEach((issue) => issue.addMilestone(list.milestone));
}
if (listFrom) {
@@ -249,7 +249,7 @@ const boardsStore = {
},
removeListIssues(list, removeIssue) {
- list.issues = list.issues.filter(issue => {
+ list.issues = list.issues.filter((issue) => {
const matchesRemove = removeIssue.id === issue.id;
if (matchesRemove) {
@@ -261,9 +261,9 @@ const boardsStore = {
});
},
removeListMultipleIssues(list, removeIssues) {
- const ids = removeIssues.map(issue => issue.id);
+ const ids = removeIssues.map((issue) => issue.id);
- list.issues = list.issues.filter(issue => {
+ list.issues = list.issues.filter((issue) => {
const matchesRemove = ids.includes(issue.id);
if (matchesRemove) {
@@ -289,9 +289,9 @@ const boardsStore = {
},
moveMultipleIssuesToList({ listFrom, listTo, issues, newIndex }) {
- const issueTo = issues.map(issue => listTo.findIssue(issue.id));
- const issueLists = issues.map(issue => issue.getLists()).flat();
- const listLabels = issueLists.map(list => list.label);
+ const issueTo = issues.map((issue) => listTo.findIssue(issue.id));
+ const issueLists = issues.map((issue) => issue.getLists()).flat();
+ const listLabels = issueLists.map((list) => list.label);
const hasMoveableIssues = issueTo.filter(Boolean).length > 0;
if (!hasMoveableIssues) {
@@ -299,30 +299,30 @@ const boardsStore = {
if (
listTo.type === ListType.assignee &&
listFrom.type === ListType.assignee &&
- issues.some(issue => issue.findAssignee(listTo.assignee))
+ issues.some((issue) => issue.findAssignee(listTo.assignee))
) {
- const targetIssues = issues.map(issue => listTo.findIssue(issue.id));
- targetIssues.forEach(targetIssue => targetIssue.removeAssignee(listFrom.assignee));
+ const targetIssues = issues.map((issue) => listTo.findIssue(issue.id));
+ targetIssues.forEach((targetIssue) => targetIssue.removeAssignee(listFrom.assignee));
} else if (listTo.type === 'milestone') {
- const currentMilestones = issues.map(issue => issue.milestone);
+ const currentMilestones = issues.map((issue) => issue.milestone);
const currentLists = this.state.lists
- .filter(list => list.type === 'milestone' && list.id !== listTo.id)
- .filter(list =>
- list.issues.some(listIssue => issues.some(issue => listIssue.id === issue.id)),
+ .filter((list) => list.type === 'milestone' && list.id !== listTo.id)
+ .filter((list) =>
+ list.issues.some((listIssue) => issues.some((issue) => listIssue.id === issue.id)),
);
- issues.forEach(issue => {
- currentMilestones.forEach(milestone => {
+ issues.forEach((issue) => {
+ currentMilestones.forEach((milestone) => {
issue.removeMilestone(milestone);
});
});
- issues.forEach(issue => {
+ issues.forEach((issue) => {
issue.addMilestone(listTo.milestone);
});
- currentLists.forEach(currentList => {
- issues.forEach(issue => {
+ currentLists.forEach((currentList) => {
+ issues.forEach((issue) => {
currentList.removeIssue(issue);
});
});
@@ -334,36 +334,36 @@ const boardsStore = {
}
} else {
listTo.updateMultipleIssues(issues, listFrom);
- issues.forEach(issue => {
+ issues.forEach((issue) => {
issue.removeLabel(listFrom.label);
});
}
if (listTo.type === ListType.closed && listFrom.type !== ListType.backlog) {
- issueLists.forEach(list => {
- issues.forEach(issue => {
+ issueLists.forEach((list) => {
+ issues.forEach((issue) => {
list.removeIssue(issue);
});
});
- issues.forEach(issue => {
+ issues.forEach((issue) => {
issue.removeLabels(listLabels);
});
} else if (listTo.type === ListType.backlog && listFrom.type === ListType.assignee) {
- issues.forEach(issue => {
+ issues.forEach((issue) => {
issue.removeAssignee(listFrom.assignee);
});
- issueLists.forEach(list => {
- issues.forEach(issue => {
+ issueLists.forEach((list) => {
+ issues.forEach((issue) => {
list.removeIssue(issue);
});
});
} else if (listTo.type === ListType.backlog && listFrom.type === ListType.milestone) {
- issues.forEach(issue => {
+ issues.forEach((issue) => {
issue.removeMilestone(listFrom.milestone);
});
- issueLists.forEach(list => {
- issues.forEach(issue => {
+ issueLists.forEach((list) => {
+ issues.forEach((issue) => {
list.removeIssue(issue);
});
});
@@ -380,8 +380,8 @@ const boardsStore = {
if (issues.length === 1) return true;
// Create list of ids for issues involved.
- const listIssueIds = list.issues.map(issue => issue.id);
- const movedIssueIds = issues.map(issue => issue.id);
+ const listIssueIds = list.issues.map((issue) => issue.id);
+ const movedIssueIds = issues.map((issue) => issue.id);
// Check if moved issue IDs is sub-array
// of source list issue IDs (i.e. contiguous selection).
@@ -391,7 +391,7 @@ const boardsStore = {
moveIssueToList(listFrom, listTo, issue, newIndex) {
const issueTo = listTo.findIssue(issue.id);
const issueLists = issue.getLists();
- const listLabels = issueLists.map(listIssue => listIssue.label);
+ const listLabels = issueLists.map((listIssue) => listIssue.label);
if (!issueTo) {
// Check if target list assignee is already present in this issue
@@ -405,12 +405,12 @@ const boardsStore = {
} else if (listTo.type === 'milestone') {
const currentMilestone = issue.milestone;
const currentLists = this.state.lists
- .filter(list => list.type === 'milestone' && list.id !== listTo.id)
- .filter(list => list.issues.some(listIssue => issue.id === listIssue.id));
+ .filter((list) => list.type === 'milestone' && list.id !== listTo.id)
+ .filter((list) => list.issues.some((listIssue) => issue.id === listIssue.id));
issue.removeMilestone(currentMilestone);
issue.addMilestone(listTo.milestone);
- currentLists.forEach(currentList => currentList.removeIssue(issue));
+ currentLists.forEach((currentList) => currentList.removeIssue(issue));
listTo.addIssue(issue, listFrom, newIndex);
} else {
// Add to new lists issues if it doesn't already exist
@@ -422,7 +422,7 @@ const boardsStore = {
}
if (listTo.type === 'closed' && listFrom.type !== 'backlog') {
- issueLists.forEach(list => {
+ issueLists.forEach((list) => {
list.removeIssue(issue);
});
issue.removeLabels(listLabels);
@@ -461,18 +461,11 @@ const boardsStore = {
moveAfterId: afterId,
});
},
- findList(key, val, type = 'label') {
- const filteredList = this.state.lists.filter(list => {
- const byType = type
- ? list.type === type || list.type === 'assignee' || list.type === 'milestone'
- : true;
-
- return list[key] === val && byType;
- });
- return filteredList[0];
+ findList(key, val) {
+ return this.state.lists.find((list) => list[key] === val);
},
findListByLabelId(id) {
- return this.state.lists.find(list => list.type === 'label' && list.label.id === id);
+ return this.state.lists.find((list) => list.type === 'label' && list.label.id === id);
},
toggleFilter(filter) {
@@ -589,8 +582,8 @@ const boardsStore = {
}
return this.createList(entity.id, entityType)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
list.id = data.id;
list.type = data.list_type;
list.position = data.position;
@@ -607,7 +600,7 @@ const boardsStore = {
};
if (list.label && data.label_name) {
- data.label_name = data.label_name.filter(label => label !== list.label.title);
+ data.label_name = data.label_name.filter((label) => label !== list.label.title);
}
if (emptyIssues) {
@@ -615,8 +608,8 @@ const boardsStore = {
}
return this.getIssuesForList(list.id, data)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
list.loading = false;
list.issuesSize = data.size;
@@ -624,7 +617,7 @@ const boardsStore = {
list.issues = [];
}
- data.issues.forEach(issueObj => {
+ data.issues.forEach((issueObj) => {
list.addIssue(new ListIssue(issueObj));
});
@@ -634,7 +627,7 @@ const boardsStore = {
getIssuesForList(id, filter = {}) {
const data = { id };
- Object.keys(filter).forEach(key => {
+ Object.keys(filter).forEach((key) => {
data[key] = filter[key];
});
@@ -670,13 +663,13 @@ const boardsStore = {
},
moveListMultipleIssues({ list, issues, oldIndicies, newIndex, moveBeforeId, moveAfterId }) {
- oldIndicies.reverse().forEach(index => {
+ oldIndicies.reverse().forEach((index) => {
list.issues.splice(index, 1);
});
list.issues.splice(newIndex, 0, ...issues);
return this.moveMultipleIssues({
- ids: issues.map(issue => issue.id),
+ ids: issues.map((issue) => issue.id),
fromListId: null,
toListId: null,
moveBeforeId,
@@ -703,8 +696,8 @@ const boardsStore = {
}
return this.newIssue(list.id, issue)
- .then(res => res.data)
- .then(data => list.onNewIssueResponse(issue, data));
+ .then((res) => res.data)
+ .then((data) => list.onNewIssueResponse(issue, data));
},
getBacklog(data) {
@@ -717,7 +710,7 @@ const boardsStore = {
},
removeIssueLabel(issue, removeLabel) {
if (removeLabel) {
- issue.labels = issue.labels.filter(label => removeLabel.id !== label.id);
+ issue.labels = issue.labels.filter((label) => removeLabel.id !== label.id);
}
},
@@ -753,16 +746,12 @@ const boardsStore = {
return axios.get(this.state.endpoints.recentBoardsEndpoint);
},
- deleteBoard({ id }) {
- return axios.delete(this.generateBoardsPath(id));
- },
-
setCurrentBoard(board) {
this.state.currentBoard = board;
},
toggleMultiSelect(issue) {
- const selectedIssueIds = this.multiSelect.list.map(issue => issue.id);
+ const selectedIssueIds = this.multiSelect.list.map((issue) => issue.id);
const index = selectedIssueIds.indexOf(issue.id);
if (index === -1) {
@@ -777,12 +766,12 @@ const boardsStore = {
},
removeIssueAssignee(issue, removeAssignee) {
if (removeAssignee) {
- issue.assignees = issue.assignees.filter(assignee => assignee.id !== removeAssignee.id);
+ issue.assignees = issue.assignees.filter((assignee) => assignee.id !== removeAssignee.id);
}
},
findIssueAssignee(issue, findAssignee) {
- return issue.assignees.find(assignee => assignee.id === findAssignee.id);
+ return issue.assignees.find((assignee) => assignee.id === findAssignee.id);
},
clearMultiSelect() {
@@ -837,11 +826,11 @@ const boardsStore = {
}
if (obj.labels) {
- issue.labels = obj.labels.map(label => new ListLabel(label));
+ issue.labels = obj.labels.map((label) => new ListLabel(label));
}
if (obj.assignees) {
- issue.assignees = obj.assignees.map(a => new ListAssignee(a));
+ issue.assignees = obj.assignees.map((a) => new ListAssignee(a));
}
},
addIssueLabel(issue, label) {
diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js
index ca6887b6f45..d72b5c6fb8e 100644
--- a/app/assets/javascripts/boards/stores/getters.js
+++ b/app/assets/javascripts/boards/stores/getters.js
@@ -2,18 +2,18 @@ import { find } from 'lodash';
import { inactiveId } from '../constants';
export default {
- isSidebarOpen: state => state.activeId !== inactiveId,
+ isSidebarOpen: (state) => state.activeId !== inactiveId,
isSwimlanesOn: () => false,
- getIssueById: state => id => {
+ getIssueById: (state) => (id) => {
return state.issues[id] || {};
},
- getIssuesByList: (state, getters) => listId => {
+ getIssuesByList: (state, getters) => (listId) => {
const listIssueIds = state.issuesByListId[listId] || [];
- return listIssueIds.map(id => getters.getIssueById(id));
+ return listIssueIds.map((id) => getters.getIssueById(id));
},
- activeIssue: state => {
+ activeIssue: (state) => {
return state.issues[state.activeId] || {};
},
@@ -22,12 +22,12 @@ export default {
return referencePath.slice(0, referencePath.indexOf('#'));
},
- getListByLabelId: state => labelId => {
- return find(state.boardLists, l => l.label?.id === labelId);
+ getListByLabelId: (state) => (labelId) => {
+ return find(state.boardLists, (l) => l.label?.id === labelId);
},
- getListByTitle: state => title => {
- return find(state.boardLists, l => l.title === title);
+ getListByTitle: (state) => (title) => {
+ return find(state.boardLists, (l) => l.title === title);
},
shouldUseGraphQL: () => {
diff --git a/app/assets/javascripts/boards/stores/modal_store.js b/app/assets/javascripts/boards/stores/modal_store.js
index b7228bf7bf5..8a8fa61361c 100644
--- a/app/assets/javascripts/boards/stores/modal_store.js
+++ b/app/assets/javascripts/boards/stores/modal_store.js
@@ -40,7 +40,7 @@ class ModalStore {
toggleAll() {
const select = this.selectedCount() !== this.store.issues.length;
- this.store.issues.forEach(issue => {
+ this.store.issues.forEach((issue) => {
const issueUpdate = issue;
if (issueUpdate.selected !== select) {
@@ -56,7 +56,7 @@ class ModalStore {
}
getSelectedIssues() {
- return this.store.selectedIssues.filter(issue => issue.selected);
+ return this.store.selectedIssues.filter((issue) => issue.selected);
}
addSelectedIssue(issue) {
@@ -70,13 +70,13 @@ class ModalStore {
removeSelectedIssue(issue, forcePurge = false) {
if (this.store.activeTab === 'all' || forcePurge) {
this.store.selectedIssues = this.store.selectedIssues.filter(
- fIssue => fIssue.id !== issue.id,
+ (fIssue) => fIssue.id !== issue.id,
);
}
}
purgeUnselectedIssues() {
- this.store.selectedIssues.forEach(issue => {
+ this.store.selectedIssues.forEach((issue) => {
if (!issue.selected) {
this.removeSelectedIssue(issue, true);
}
@@ -88,7 +88,7 @@ class ModalStore {
}
findSelectedIssue(issue) {
- return this.store.selectedIssues.filter(filteredIssue => filteredIssue.id === issue.id)[0];
+ return this.store.selectedIssues.filter((filteredIssue) => filteredIssue.id === issue.id)[0];
}
}
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index 2b2c2bee51c..4697f39498a 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -36,3 +36,7 @@ export const SET_ACTIVE_ID = 'SET_ACTIVE_ID';
export const UPDATE_ISSUE_BY_ID = 'UPDATE_ISSUE_BY_ID';
export const SET_ASSIGNEE_LOADING = 'SET_ASSIGNEE_LOADING';
export const RESET_ISSUES = 'RESET_ISSUES';
+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';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 8c4e514710f..6c79b22d308 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -32,8 +32,9 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter
export default {
[mutationTypes.SET_INITIAL_BOARD_DATA](state, data) {
- const { boardType, disabled, boardConfig, ...endpoints } = data;
- state.endpoints = endpoints;
+ const { boardType, disabled, boardId, fullPath, boardConfig } = data;
+ state.boardId = boardId;
+ state.fullPath = fullPath;
state.boardType = boardType;
state.disabled = disabled;
state.boardConfig = boardConfig;
@@ -43,7 +44,7 @@ export default {
state.boardLists = lists;
},
- [mutationTypes.RECEIVE_BOARD_LISTS_FAILURE]: state => {
+ [mutationTypes.RECEIVE_BOARD_LISTS_FAILURE]: (state) => {
state.error = s__(
'Boards|An error occurred while fetching the board lists. Please reload the page.',
);
@@ -58,15 +59,15 @@ export default {
state.filterParams = filterParams;
},
- [mutationTypes.CREATE_LIST_FAILURE]: state => {
+ [mutationTypes.CREATE_LIST_FAILURE]: (state) => {
state.error = s__('Boards|An error occurred while creating the list. Please try again.');
},
- [mutationTypes.RECEIVE_LABELS_FAILURE]: state => {
+ [mutationTypes.RECEIVE_LABELS_FAILURE]: (state) => {
state.error = s__('Boards|An error occurred while fetching labels. Please reload the page.');
},
- [mutationTypes.GENERATE_DEFAULT_LISTS_FAILURE]: state => {
+ [mutationTypes.GENERATE_DEFAULT_LISTS_FAILURE]: (state) => {
state.error = s__('Boards|An error occurred while generating lists. Please reload the page.');
},
@@ -128,8 +129,8 @@ export default {
Vue.set(state.listsFlags, listId, { isLoading: false, isLoadingMore: false });
},
- [mutationTypes.RESET_ISSUES]: state => {
- Object.keys(state.issuesByListId).forEach(listId => {
+ [mutationTypes.RESET_ISSUES]: (state) => {
+ Object.keys(state.issuesByListId).forEach((listId) => {
Vue.set(state.issuesByListId, listId, []);
});
},
@@ -205,7 +206,7 @@ export default {
notImplemented();
},
- [mutationTypes.CREATE_ISSUE_FAILURE]: state => {
+ [mutationTypes.CREATE_ISSUE_FAILURE]: (state) => {
state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
},
@@ -236,4 +237,25 @@ export default {
[mutationTypes.TOGGLE_EMPTY_STATE]: () => {
notImplemented();
},
+
+ [mutationTypes.REQUEST_GROUP_PROJECTS]: (state, fetchNext) => {
+ Vue.set(state, 'groupProjectsFlags', {
+ [fetchNext ? 'isLoadingMore' : 'isLoading']: true,
+ pageInfo: state.groupProjectsFlags.pageInfo,
+ });
+ },
+
+ [mutationTypes.RECEIVE_GROUP_PROJECTS_SUCCESS]: (state, { projects, pageInfo, fetchNext }) => {
+ Vue.set(state, 'groupProjects', fetchNext ? [...state.groupProjects, ...projects] : projects);
+ Vue.set(state, 'groupProjectsFlags', { isLoading: false, isLoadingMore: false, pageInfo });
+ },
+
+ [mutationTypes.RECEIVE_GROUP_PROJECTS_FAILURE]: (state) => {
+ state.error = s__('Boards|An error occurred while fetching group projects. Please try again.');
+ Vue.set(state, 'groupProjectsFlags', { isLoading: false, isLoadingMore: false });
+ },
+
+ [mutationTypes.SET_SELECTED_PROJECT]: (state, project) => {
+ state.selectedProject = project;
+ },
};
diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js
index 573e98e56e0..aba7da373cf 100644
--- a/app/assets/javascripts/boards/stores/state.js
+++ b/app/assets/javascripts/boards/stores/state.js
@@ -1,7 +1,6 @@
import { inactiveId } from '~/boards/constants';
export default () => ({
- endpoints: {},
boardType: null,
disabled: false,
isShowingLabels: true,
@@ -15,6 +14,13 @@ export default () => ({
issues: {},
filterParams: {},
boardConfig: {},
+ groupProjects: [],
+ groupProjectsFlags: {
+ isLoading: false,
+ isLoadingMore: false,
+ pageInfo: {},
+ },
+ selectedProject: {},
error: undefined,
// TODO: remove after ce/ee split of board_content.vue
isShowingEpicsSwimlanes: false,
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
index 89e9d3fcb62..a577bdca082 100644
--- a/app/assets/javascripts/branches/divergence_graph.js
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -21,7 +21,7 @@ export function createGraphVueApp(el, data, maxCommits) {
});
}
-export default endpoint => {
+export default (endpoint) => {
const names = [...document.querySelectorAll('.js-branch-item')].map(
({ dataset }) => dataset.name,
);
diff --git a/app/assets/javascripts/breadcrumb.js b/app/assets/javascripts/breadcrumb.js
index ff7f734f998..b8b8a0b2867 100644
--- a/app/assets/javascripts/breadcrumb.js
+++ b/app/assets/javascripts/breadcrumb.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { hide } from '~/tooltips';
-export const addTooltipToEl = el => {
+export const addTooltipToEl = (el) => {
const textEl = el.querySelector('.js-breadcrumb-item-text');
if (textEl && textEl.scrollWidth > textEl.offsetWidth) {
@@ -16,14 +16,14 @@ export default () => {
if (breadcrumbs) {
const topLevelLinks = [...breadcrumbs.children]
- .filter(el => !el.classList.contains('dropdown'))
- .map(el => el.querySelector('a'))
- .filter(el => el);
+ .filter((el) => !el.classList.contains('dropdown'))
+ .map((el) => el.querySelector('a'))
+ .filter((el) => el);
const $expander = $('.js-breadcrumbs-collapsed-expander');
- topLevelLinks.forEach(el => addTooltipToEl(el));
+ topLevelLinks.forEach((el) => addTooltipToEl(el));
- $expander.closest('.dropdown').on('show.bs.dropdown hide.bs.dropdown', e => {
+ $expander.closest('.dropdown').on('show.bs.dropdown hide.bs.dropdown', (e) => {
const $el = $('.js-breadcrumbs-collapsed-expander', e.currentTarget);
$el.toggleClass('open');
diff --git a/app/assets/javascripts/broadcast_notification.js b/app/assets/javascripts/broadcast_notification.js
index 97da6fa34da..2cf2e922f68 100644
--- a/app/assets/javascripts/broadcast_notification.js
+++ b/app/assets/javascripts/broadcast_notification.js
@@ -15,5 +15,5 @@ const handleOnDismiss = ({ currentTarget }) => {
export default () => {
document
.querySelectorAll('.js-dismiss-current-broadcast-notification')
- .forEach(dismissButton => dismissButton.addEventListener('click', handleOnDismiss));
+ .forEach((dismissButton) => dismissButton.addEventListener('click', handleOnDismiss));
};
diff --git a/app/assets/javascripts/build_artifacts.js b/app/assets/javascripts/build_artifacts.js
index 8324c649538..42e0f8b37bd 100644
--- a/app/assets/javascripts/build_artifacts.js
+++ b/app/assets/javascripts/build_artifacts.js
@@ -14,17 +14,17 @@ export default class BuildArtifacts {
// eslint-disable-next-line class-methods-use-this
disablePropagation() {
- $('.top-block').on('click', '.download', e => {
+ $('.top-block').on('click', '.download', (e) => {
e.stopPropagation();
});
- return $('.tree-holder').on('click', 'tr[data-link] a', e => {
+ return $('.tree-holder').on('click', 'tr[data-link] a', (e) => {
e.stopImmediatePropagation();
});
}
// eslint-disable-next-line class-methods-use-this
setupEntryClick() {
- return $('.tree-holder').on('click', 'tr[data-link]', function() {
+ return $('.tree-holder').on('click', 'tr[data-link]', function () {
visitUrl(this.dataset.link, parseBoolean(this.dataset.externalLink));
});
}
@@ -41,12 +41,12 @@ export default class BuildArtifacts {
// We want the tooltip to show if you hover anywhere on the row
// But be placed below and in the middle of the file name
$('.js-artifact-tree-row')
- .on('mouseenter', e => {
+ .on('mouseenter', (e) => {
const $el = $(e.currentTarget).find('.js-artifact-tree-tooltip');
show($el);
})
- .on('mouseleave', e => {
+ .on('mouseleave', (e) => {
const $el = $(e.currentTarget).find('.js-artifact-tree-tooltip');
hide($el);
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint.vue b/app/assets/javascripts/ci_lint/components/ci_lint.vue
index 731ed2ddd01..fc47fe8c333 100644
--- a/app/assets/javascripts/ci_lint/components/ci_lint.vue
+++ b/app/assets/javascripts/ci_lint/components/ci_lint.vue
@@ -111,7 +111,7 @@ export default {
<gl-form-checkbox v-model="dryRun"
>{{ __('Simulate a pipeline created for the default branch') }}
<gl-link :href="pipelineSimulationHelpPagePath" target="_blank"
- ><gl-icon class="gl-text-blue-600" name="question-o"/></gl-link
+ ><gl-icon class="gl-text-blue-600" name="question-o" /></gl-link
></gl-form-checkbox>
</div>
<gl-button data-testid="ci-lint-clear" @click="clear">{{ __('Clear') }}</gl-button>
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 ad07052a298..b84c188cd08 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
@@ -61,7 +61,7 @@ export default {
class="triggers-list"
responsive
>
- <template #cell(token)="{item}">
+ <template #cell(token)="{ item }">
{{ item.token }}
<clipboard-button
v-if="item.hasTokenExposed"
@@ -82,7 +82,7 @@ export default {
</gl-badge>
</div>
</template>
- <template #cell(description)="{item}">
+ <template #cell(description)="{ item }">
<tooltip-on-truncate
:title="item.description"
truncate-target="child"
@@ -92,7 +92,7 @@ export default {
<div class="gl-flex-fill-1 gl-text-truncate">{{ item.description }}</div>
</tooltip-on-truncate>
</template>
- <template #cell(owner)="{item}">
+ <template #cell(owner)="{ item }">
<span class="trigger-owner sr-only">{{ item.owner.name }}</span>
<user-avatar-link
v-if="item.owner"
@@ -102,11 +102,11 @@ export default {
:img-alt="item.owner.name"
/>
</template>
- <template #cell(lastUsed)="{item}">
+ <template #cell(lastUsed)="{ item }">
<time-ago-tooltip v-if="item.lastUsed" :time="item.lastUsed" />
<span v-else>{{ __('Never') }}</span>
</template>
- <template #cell(actions)="{item}">
+ <template #cell(actions)="{ item }">
<gl-button
:title="s__('Pipelines|Edit')"
icon="pencil"
diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/index.js b/app/assets/javascripts/ci_settings_pipeline_triggers/index.js
index 182d5ca5ffb..dc79bbb4d97 100644
--- a/app/assets/javascripts/ci_settings_pipeline_triggers/index.js
+++ b/app/assets/javascripts/ci_settings_pipeline_triggers/index.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import TriggersList from './components/triggers_list.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-const parseJsonArray = triggers => {
+const parseJsonArray = (triggers) => {
try {
return convertObjectPropsToCamelCase(JSON.parse(triggers), { deep: true });
} catch {
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 cb1935c863d..aa4d311527e 100644
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
@@ -81,17 +81,17 @@ export default class VariableList {
this.initRow(rowEl);
});
- this.$container.on('click', '.js-row-remove-button', e => {
+ this.$container.on('click', '.js-row-remove-button', (e) => {
e.preventDefault();
this.removeRow($(e.currentTarget).closest('.js-row'));
});
const inputSelector = Object.keys(this.inputMap)
- .map(name => this.inputMap[name].selector)
+ .map((name) => this.inputMap[name].selector)
.join(',');
// Remove any empty rows except the last row
- this.$container.on('blur', inputSelector, e => {
+ this.$container.on('blur', inputSelector, (e) => {
const $row = $(e.currentTarget).closest('.js-row');
if ($row.is(':not(:last-child)') && !this.checkIfRowTouched($row)) {
@@ -99,7 +99,7 @@ export default class VariableList {
}
});
- this.$container.on('input trigger-change', inputSelector, e => {
+ this.$container.on('input trigger-change', inputSelector, (e) => {
// Always make sure there is an empty last row
const $lastRow = this.$container.find('.js-row').last();
@@ -149,7 +149,7 @@ export default class VariableList {
$rowClone.removeAttr('data-is-persisted');
// Reset the inputs to their defaults
- Object.keys(this.inputMap).forEach(name => {
+ Object.keys(this.inputMap).forEach((name) => {
const entry = this.inputMap[name];
$rowClone.find(entry.selector).val(entry.default);
});
@@ -184,7 +184,7 @@ export default class VariableList {
}
checkIfRowTouched($row) {
- return Object.keys(this.inputMap).some(name => {
+ return Object.keys(this.inputMap).some((name) => {
// Row should not qualify as touched if only switches have been touched
if (['protected', 'masked'].includes(name)) return false;
@@ -223,14 +223,11 @@ export default class VariableList {
getAllData() {
// Ignore the last empty row because we don't want to try persist
// a blank variable and run into validation problems.
- const validRows = this.$container
- .find('.js-row')
- .toArray()
- .slice(0, -1);
+ const validRows = this.$container.find('.js-row').toArray().slice(0, -1);
- return validRows.map(rowEl => {
+ return validRows.map((rowEl) => {
const resultant = {};
- Object.keys(this.inputMap).forEach(name => {
+ Object.keys(this.inputMap).forEach((name) => {
const entry = this.inputMap[name];
const $input = $(rowEl).find(entry.selector);
if ($input.length) {
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue b/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
index 83e9717041f..104d6672015 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
@@ -33,7 +33,7 @@ export default {
},
filteredResults() {
const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.joinedEnvironments.filter(resultString =>
+ return this.joinedEnvironments.filter((resultString) =>
resultString.toLowerCase().includes(lowerCasedSearchTerm),
);
},
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
index 07278bb442c..47b2745af08 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
@@ -69,7 +69,7 @@ export default {
},
fields() {
if (this.isGroup) {
- return this.$options.fields.filter(field => field.key !== 'environment_scope');
+ return this.$options.fields.filter((field) => field.key !== 'environment_scope');
}
return this.$options.fields;
},
diff --git a/app/assets/javascripts/ci_variable_list/store/actions.js b/app/assets/javascripts/ci_variable_list/store/actions.js
index e3e9dac0a79..ac595fa0045 100644
--- a/app/assets/javascripts/ci_variable_list/store/actions.js
+++ b/app/assets/javascripts/ci_variable_list/store/actions.js
@@ -47,7 +47,7 @@ export const addVariable = ({ state, dispatch }) => {
dispatch('receiveAddVariableSuccess');
dispatch('fetchVariables');
})
- .catch(error => {
+ .catch((error) => {
createFlash(error.response.data[0]);
dispatch('receiveAddVariableError', error);
});
@@ -77,7 +77,7 @@ export const updateVariable = ({ state, dispatch }) => {
dispatch('receiveUpdateVariableSuccess');
dispatch('fetchVariables');
})
- .catch(error => {
+ .catch((error) => {
createFlash(error.response.data[0]);
dispatch('receiveUpdateVariableError', error);
});
@@ -132,7 +132,7 @@ export const deleteVariable = ({ dispatch, state }) => {
dispatch('receiveDeleteVariableSuccess');
dispatch('fetchVariables');
})
- .catch(error => {
+ .catch((error) => {
createFlash(error.response.data[0]);
dispatch('receiveDeleteVariableError', error);
});
@@ -150,7 +150,7 @@ export const fetchEnvironments = ({ dispatch, state }) => {
dispatch('requestEnvironments');
return Api.environments(state.projectId)
- .then(res => {
+ .then((res) => {
dispatch('receiveEnvironmentsSuccess', prepareEnvironments(res.data));
})
.catch(() => {
diff --git a/app/assets/javascripts/ci_variable_list/store/getters.js b/app/assets/javascripts/ci_variable_list/store/getters.js
index 619ad54cad6..6570f455541 100644
--- a/app/assets/javascripts/ci_variable_list/store/getters.js
+++ b/app/assets/javascripts/ci_variable_list/store/getters.js
@@ -1,6 +1,6 @@
import { uniq } from 'lodash';
-export const joinedEnvironments = state => {
- const scopesFromVariables = (state.variables || []).map(variable => variable.environment_scope);
+export const joinedEnvironments = (state) => {
+ const scopesFromVariables = (state.variables || []).map((variable) => variable.environment_scope);
return uniq(state.environments.concat(scopesFromVariables)).sort();
};
diff --git a/app/assets/javascripts/ci_variable_list/store/utils.js b/app/assets/javascripts/ci_variable_list/store/utils.js
index f04530359e7..d9ca460a8e1 100644
--- a/app/assets/javascripts/ci_variable_list/store/utils.js
+++ b/app/assets/javascripts/ci_variable_list/store/utils.js
@@ -1,12 +1,12 @@
import { cloneDeep } from 'lodash';
import { displayText, types } from '../constants';
-const variableTypeHandler = type =>
+const variableTypeHandler = (type) =>
type === displayText.variableText ? types.variableType : types.fileType;
-export const prepareDataForDisplay = variables => {
+export const prepareDataForDisplay = (variables) => {
const variablesToDisplay = [];
- variables.forEach(variable => {
+ variables.forEach((variable) => {
const variableCopy = variable;
if (variableCopy.variable_type === types.variableType) {
variableCopy.variable_type = displayText.variableText;
@@ -42,4 +42,4 @@ export const prepareDataForApi = (variable, destroy = false) => {
return variableCopy;
};
-export const prepareEnvironments = environments => environments.map(e => e.name);
+export const prepareEnvironments = (environments) => environments.map((e) => e.name);
diff --git a/app/assets/javascripts/clone_panel.js b/app/assets/javascripts/clone_panel.js
index 362e6c5c5ce..00bf54e1478 100644
--- a/app/assets/javascripts/clone_panel.js
+++ b/app/assets/javascripts/clone_panel.js
@@ -14,7 +14,7 @@ export default function initClonePanel() {
$(`a:contains('${selectedCloneOption}')`, $cloneOptions).addClass('is-active');
}
- $('a', $cloneOptions).on('click', e => {
+ $('a', $cloneOptions).on('click', (e) => {
e.preventDefault();
const $this = $(e.currentTarget);
const url = $this.attr('href');
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index a533a1a78e8..eb2128b2856 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -128,7 +128,7 @@ export default class Clusters {
this.initPolling(
'fetchClusterEnvironments',
- data => this.handleClusterEnvironmentsSuccess(data),
+ (data) => this.handleClusterEnvironmentsSuccess(data),
() => this.handleEnvironmentsPollError(),
);
}
@@ -139,7 +139,7 @@ export default class Clusters {
if (statusPath && !this.environments) {
this.initPolling(
'fetchClusterStatus',
- data => this.handleClusterStatusSuccess(data),
+ (data) => this.handleClusterStatusSuccess(data),
() => this.handlePollError(),
);
}
@@ -248,15 +248,15 @@ export default class Clusters {
addListeners() {
eventHub.$on('installApplication', this.installApplication);
- eventHub.$on('updateApplication', data => this.updateApplication(data));
- eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
- eventHub.$on('setKnativeDomain', data => this.setKnativeDomain(data));
- eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
- eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data));
- eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data));
- eventHub.$on('setIngressModSecurityMode', data => this.setIngressModSecurityMode(data));
- eventHub.$on('resetIngressModSecurityChanges', id => this.resetIngressModSecurityChanges(id));
- eventHub.$on('setFluentdSettings', data => this.setFluentdSettings(data));
+ eventHub.$on('updateApplication', (data) => this.updateApplication(data));
+ eventHub.$on('saveKnativeDomain', (data) => this.saveKnativeDomain(data));
+ eventHub.$on('setKnativeDomain', (data) => this.setKnativeDomain(data));
+ eventHub.$on('uninstallApplication', (data) => this.uninstallApplication(data));
+ eventHub.$on('setCrossplaneProviderStack', (data) => this.setCrossplaneProviderStack(data));
+ eventHub.$on('setIngressModSecurityEnabled', (data) => this.setIngressModSecurityEnabled(data));
+ eventHub.$on('setIngressModSecurityMode', (data) => this.setIngressModSecurityMode(data));
+ eventHub.$on('resetIngressModSecurityChanges', (id) => this.resetIngressModSecurityChanges(id));
+ eventHub.$on('setFluentdSettings', (data) => this.setFluentdSettings(data));
// Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
@@ -343,12 +343,12 @@ export default class Clusters {
checkForNewInstalls(prevApplicationMap, newApplicationMap) {
const appTitles = Object.keys(newApplicationMap)
.filter(
- appId =>
+ (appId) =>
newApplicationMap[appId].status === APPLICATION_STATUS.INSTALLED &&
prevApplicationMap[appId].status !== APPLICATION_STATUS.INSTALLED &&
prevApplicationMap[appId].status !== null,
)
- .map(appId => newApplicationMap[appId].title);
+ .map((appId) => newApplicationMap[appId].title);
if (appTitles.length > 0) {
const text = sprintf(
@@ -450,7 +450,7 @@ export default class Clusters {
);
});
})
- .catch(error => this.store.updateAppProperty(appId, 'validationError', error));
+ .catch((error) => this.store.updateAppProperty(appId, 'validationError', error));
}
static validateInstallation(appId, params) {
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index fdffaa24d03..e096a29ce7f 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -461,7 +461,7 @@ export default {
)
"
>
- <template #code="{content}">
+ <template #code="{ content }">
<code>{{ content }}</code>
</template>
<template #link="{ content }">
diff --git a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
index b37fc3894f8..84a39874000 100644
--- a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
+++ b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
@@ -127,7 +127,7 @@ export default {
});
},
updateCurrentServerSideSettings(settings) {
- Object.keys(settings).forEach(key => {
+ Object.keys(settings).forEach((key) => {
if (this.currentServerSideSettings[key] === null) {
this.currentServerSideSettings[key] = this[key];
}
diff --git a/app/assets/javascripts/clusters/forms/stores/index.js b/app/assets/javascripts/clusters/forms/stores/index.js
index ae082c07f26..87f1c05fdf9 100644
--- a/app/assets/javascripts/clusters/forms/stores/index.js
+++ b/app/assets/javascripts/clusters/forms/stores/index.js
@@ -4,7 +4,7 @@ import state from './state';
Vue.use(Vuex);
-export const createStore = initialState =>
+export const createStore = (initialState) =>
new Vuex.Store({
state: state(initialState),
});
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 88505eac3a9..5de487308c5 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -17,7 +17,7 @@ import {
} from '../constants';
import transitionApplicationState from '../services/application_state_machine';
-const isApplicationInstalled = appStatus => APPLICATION_INSTALLED_STATUSES.includes(appStatus);
+const isApplicationInstalled = (appStatus) => APPLICATION_INSTALLED_STATUSES.includes(appStatus);
const applicationInitialState = {
status: null,
@@ -195,7 +195,7 @@ export default class ClusterStore {
this.state.status = serverState.status;
this.state.statusReason = serverState.status_reason;
- serverState.applications.forEach(serverAppEntry => {
+ serverState.applications.forEach((serverAppEntry) => {
const {
name: appId,
status,
@@ -284,7 +284,7 @@ export default class ClusterStore {
}
updateEnvironments(environments = []) {
- this.state.environments = environments.map(environment => ({
+ this.state.environments = environments.map((environment) => ({
name: environment.name,
project: environment.project,
environmentPath: environment.environment_path,
diff --git a/app/assets/javascripts/clusters/stores/new_cluster/index.js b/app/assets/javascripts/clusters/stores/new_cluster/index.js
index ae082c07f26..87f1c05fdf9 100644
--- a/app/assets/javascripts/clusters/stores/new_cluster/index.js
+++ b/app/assets/javascripts/clusters/stores/new_cluster/index.js
@@ -4,7 +4,7 @@ import state from './state';
Vue.use(Vuex);
-export const createStore = initialState =>
+export const createStore = (initialState) =>
new Vuex.Store({
state: state(initialState),
});
diff --git a/app/assets/javascripts/clusters_list/components/ancestor_notice.vue b/app/assets/javascripts/clusters_list/components/ancestor_notice.vue
index 7954fc61785..b241aa34283 100644
--- a/app/assets/javascripts/clusters_list/components/ancestor_notice.vue
+++ b/app/assets/javascripts/clusters_list/components/ancestor_notice.vue
@@ -1,11 +1,12 @@
<script>
-import { GlLink, GlSprintf } from '@gitlab/ui';
+import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
import { mapState } from 'vuex';
export default {
components: {
GlLink,
GlSprintf,
+ GlAlert,
},
computed: {
...mapState(['ancestorHelperPath', 'hasAncestorClusters']),
@@ -14,21 +15,19 @@ export default {
</script>
<template>
- <div v-if="hasAncestorClusters" class="bs-callout bs-callout-info">
- <p>
- <gl-sprintf
- :message="
- s__(
- '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}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link :href="ancestorHelperPath">
- <strong>{{ content }}</strong>
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
+ <gl-alert v-if="hasAncestorClusters" variant="info" :dismissible="false" class="gl-my-4">
+ <gl-sprintf
+ :message="
+ s__(
+ '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}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="ancestorHelperPath">
+ <strong>{{ content }}</strong>
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index 08fd7db40a1..53eec5c8a0d 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -79,7 +79,7 @@ export default {
{
key: 'cluster_type',
label: __('Cluster level'),
- formatter: value => CLUSTER_TYPES[value],
+ formatter: (value) => CLUSTER_TYPES[value],
},
];
},
@@ -254,9 +254,7 @@ export default {
<template #freeSpacePercentage>{{
totalCpuAndUsage(item.nodes).freeSpacePercentage
}}</template>
- <template #percentSymbol
- >%</template
- >
+ <template #percentSymbol>%</template>
</gl-sprintf>
</span>
@@ -277,9 +275,7 @@ export default {
<template #freeSpacePercentage>{{
totalMemoryAndUsage(item.nodes).freeSpacePercentage
}}</template>
- <template #percentSymbol
- >%</template
- >
+ <template #percentSymbol>%</template>
</gl-sprintf>
</span>
@@ -293,7 +289,7 @@ export default {
/>
</template>
- <template #cell(cluster_type)="{value}">
+ <template #cell(cluster_type)="{ value }">
<gl-badge variant="muted">
{{ value }}
</gl-badge>
diff --git a/app/assets/javascripts/clusters_list/load_clusters.js b/app/assets/javascripts/clusters_list/load_clusters.js
index 98bc5880898..01430230879 100644
--- a/app/assets/javascripts/clusters_list/load_clusters.js
+++ b/app/assets/javascripts/clusters_list/load_clusters.js
@@ -1,7 +1,7 @@
import Clusters from './components/clusters.vue';
import { createStore } from './store';
-export default Vue => {
+export default (Vue) => {
const el = document.querySelector('#js-clusters-list-app');
if (!el) {
diff --git a/app/assets/javascripts/clusters_list/store/actions.js b/app/assets/javascripts/clusters_list/store/actions.js
index 1be82988db0..97ed0a7ab37 100644
--- a/app/assets/javascripts/clusters_list/store/actions.js
+++ b/app/assets/javascripts/clusters_list/store/actions.js
@@ -13,11 +13,11 @@ const allNodesPresent = (clusters, retryCount) => {
They may fail for reasons GitLab cannot control.
MAX_REQUESTS will ensure this poll stops at some point.
*/
- return retryCount > MAX_REQUESTS || clusters.every(cluster => cluster.nodes != null);
+ return retryCount > MAX_REQUESTS || clusters.every((cluster) => cluster.nodes != null);
};
export const reportSentryError = (_store, { error, tag }) => {
- Sentry.withScope(scope => {
+ Sentry.withScope((scope) => {
scope.setTag('javascript_clusters_list', tag);
Sentry.captureException(error);
});
@@ -30,7 +30,7 @@ export const fetchClusters = ({ state, commit, dispatch }) => {
const poll = new Poll({
resource: {
- fetchClusters: paginatedEndPoint => axios.get(paginatedEndPoint),
+ fetchClusters: (paginatedEndPoint) => axios.get(paginatedEndPoint),
},
data: `${state.endpoint}?page=${state.page}`,
method: 'fetchClusters',
@@ -59,7 +59,7 @@ export const fetchClusters = ({ state, commit, dispatch }) => {
dispatch('reportSentryError', { error, tag: 'fetchClustersSuccessCallback' });
}
},
- errorCallback: response => {
+ errorCallback: (response) => {
poll.stop();
commit(types.SET_LOADING_CLUSTERS, false);
diff --git a/app/assets/javascripts/clusters_list/store/index.js b/app/assets/javascripts/clusters_list/store/index.js
index c472d2f354c..47e17b3624b 100644
--- a/app/assets/javascripts/clusters_list/store/index.js
+++ b/app/assets/javascripts/clusters_list/store/index.js
@@ -6,7 +6,7 @@ import * as actions from './actions';
Vue.use(Vuex);
-export const createStore = initialState =>
+export const createStore = (initialState) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/code_navigation/index.js b/app/assets/javascripts/code_navigation/index.js
index fa5835245bc..38b3467dc33 100644
--- a/app/assets/javascripts/code_navigation/index.js
+++ b/app/assets/javascripts/code_navigation/index.js
@@ -3,7 +3,7 @@ import Vuex from 'vuex';
import createStore from './store';
import App from './components/app.vue';
-export default initialData => {
+export default (initialData) => {
const el = document.getElementById('js-code-navigation');
if (!el) return null;
diff --git a/app/assets/javascripts/code_navigation/store/actions.js b/app/assets/javascripts/code_navigation/store/actions.js
index 9a472ca014f..fb77a70de0b 100644
--- a/app/assets/javascripts/code_navigation/store/actions.js
+++ b/app/assets/javascripts/code_navigation/store/actions.js
@@ -34,7 +34,7 @@ export default {
},
showBlobInteractionZones({ state }, path) {
if (state.data && state.data[path]) {
- Object.values(state.data[path]).forEach(d => addInteractionClass(path, d));
+ Object.values(state.data[path]).forEach((d) => addInteractionClass(path, d));
}
},
showDefinition({ commit, state }, { target: el }) {
diff --git a/app/assets/javascripts/code_navigation/utils/index.js b/app/assets/javascripts/code_navigation/utils/index.js
index bb33bc556af..6c078891ed4 100644
--- a/app/assets/javascripts/code_navigation/utils/index.js
+++ b/app/assets/javascripts/code_navigation/utils/index.js
@@ -1,7 +1,7 @@
export const cachedData = new Map();
export const getCurrentHoverElement = () => cachedData.get('current');
-export const setCurrentHoverElement = el => cachedData.set('current', el);
+export const setCurrentHoverElement = (el) => cachedData.set('current', el);
export const addInteractionClass = (path, d) => {
const lineNumber = d.start_line + 1;
@@ -10,7 +10,7 @@ export const addInteractionClass = (path, d) => {
.querySelectorAll(`.blob-content #LC${lineNumber}, .line_content:not(.old) #LC${lineNumber}`);
if (!lines?.length) return;
- lines.forEach(line => {
+ lines.forEach((line) => {
let charCount = 0;
const el = [...line.childNodes].find(({ textContent }) => {
if (charCount === d.start_char) return true;
diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js
index b70f8d6e736..5f24a3c370a 100644
--- a/app/assets/javascripts/commit/image_file.js
+++ b/app/assets/javascripts/commit/image_file.js
@@ -28,7 +28,7 @@ export default class ImageFile {
initViewModes() {
const viewMode = viewModes[0];
$('.view-modes', this.file).removeClass('gl-display-none');
- $('.view-modes-menu', this.file).on('click', 'li', event => {
+ $('.view-modes-menu', this.file).on('click', 'li', (event) => {
if (!$(event.currentTarget).hasClass('active')) {
return this.activateViewMode(event.currentTarget.className);
}
@@ -56,15 +56,15 @@ export default class ImageFile {
let dragging = false;
const $body = $('body');
const $offsetEl = $el.parent();
- const dragStart = function() {
+ const dragStart = function () {
dragging = true;
$body.css('user-select', 'none');
};
- const dragStop = function() {
+ const dragStop = function () {
dragging = false;
$body.css('user-select', '');
};
- const dragMove = function(e) {
+ const dragMove = function (e) {
const moveX = e.pageX || e.touches[0].pageX;
const left = moveX - ($offsetEl.offset().left + padding);
if (!dragging) return;
@@ -73,11 +73,7 @@ export default class ImageFile {
};
// eslint-disable-next-line @gitlab/no-global-event-off
- $el
- .off('mousedown')
- .off('touchstart')
- .on('mousedown', dragStart)
- .on('touchstart', dragStart);
+ $el.off('mousedown').off('touchstart').on('mousedown', dragStart).on('touchstart', dragStart);
// eslint-disable-next-line @gitlab/no-global-event-off
$body
@@ -109,9 +105,9 @@ export default class ImageFile {
}
views = {
- 'two-up': function() {
+ 'two-up': function () {
return $('.two-up.view .wrap', this.file).each((index, wrap) => {
- $('img', wrap).each(function() {
+ $('img', wrap).each(function () {
const currentWidth = $(this).width();
if (currentWidth > availWidth / 2) {
return $(this).width(availWidth / 2);
@@ -157,7 +153,7 @@ export default class ImageFile {
});
});
},
- 'onion-skin': function() {
+ 'onion-skin': function () {
let maxHeight, maxWidth;
maxWidth = 0;
maxHeight = 0;
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index c8168afbcb0..24033634aad 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -21,7 +21,7 @@ export default () => {
if (pipelineTableViewEl) {
// Update MR and Commits tabs
- pipelineTableViewEl.addEventListener('update-pipelines-count', event => {
+ pipelineTableViewEl.addEventListener('update-pipelines-count', (event) => {
if (
event.detail.pipelines &&
event.detail.pipelines.count &&
diff --git a/app/assets/javascripts/commit_merge_requests.js b/app/assets/javascripts/commit_merge_requests.js
index 3cdb1587a3b..e382356841c 100644
--- a/app/assets/javascripts/commit_merge_requests.js
+++ b/app/assets/javascripts/commit_merge_requests.js
@@ -50,7 +50,7 @@ export function createContent(mergeRequests) {
if (mergeRequests.length === 0) {
$content.text(s__('Commits|No related merge requests found'));
} else {
- mergeRequests.forEach(mergeRequest => {
+ mergeRequests.forEach((mergeRequest) => {
const $header = createHeader($content.children().length, mergeRequests.length);
const $item = createItem(mergeRequest);
$content.append($header);
@@ -66,7 +66,7 @@ export function fetchCommitMergeRequests() {
axios
.get($container.data('projectCommitPath'))
- .then(response => {
+ .then((response) => {
const $content = createContent(response.data);
$container.html($content);
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index b18c109937d..f82bea134a3 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -85,10 +85,7 @@ export default class CommitsList {
// Update commits count in the previous commits header.
commitsCount += Number(
- $(processedData)
- .nextUntil('li.js-commit-header')
- .first()
- .find('li.commit').length,
+ $(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length,
);
$commitsHeadersLast
diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js
index 2a1244149ff..f750c62103e 100644
--- a/app/assets/javascripts/commons/bootstrap.js
+++ b/app/assets/javascripts/commons/bootstrap.js
@@ -13,14 +13,10 @@ import 'bootstrap/js/dist/tab';
// custom jQuery functions
$.fn.extend({
disable() {
- return $(this)
- .prop('disabled', true)
- .addClass('disabled');
+ return $(this).prop('disabled', true).addClass('disabled');
},
enable() {
- return $(this)
- .prop('disabled', false)
- .removeClass('disabled');
+ return $(this).prop('disabled', false).removeClass('disabled');
},
});
diff --git a/app/assets/javascripts/commons/nav/user_merge_requests.js b/app/assets/javascripts/commons/nav/user_merge_requests.js
index 8e694cca6a1..84ab728274f 100644
--- a/app/assets/javascripts/commons/nav/user_merge_requests.js
+++ b/app/assets/javascripts/commons/nav/user_merge_requests.js
@@ -1,4 +1,4 @@
-import Api from '~/api';
+import { getUserCounts } from '~/rest_api';
let channel;
@@ -11,7 +11,17 @@ function broadcastCount(newCount) {
}
function updateUserMergeRequestCounts(newCount) {
- const mergeRequestsCountEl = document.querySelector('.merge-requests-count');
+ const mergeRequestsCountEl = document.querySelector('.js-assigned-mr-count');
+ mergeRequestsCountEl.textContent = newCount.toLocaleString();
+}
+
+function updateReviewerMergeRequestCounts(newCount) {
+ const mergeRequestsCountEl = document.querySelector('.js-reviewer-mr-count');
+ mergeRequestsCountEl.textContent = newCount.toLocaleString();
+}
+
+function updateMergeRequestCounts(newCount) {
+ const mergeRequestsCountEl = document.querySelector('.js-merge-requests-count');
mergeRequestsCountEl.textContent = newCount.toLocaleString();
mergeRequestsCountEl.classList.toggle('hidden', Number(newCount) === 0);
}
@@ -20,14 +30,18 @@ function updateUserMergeRequestCounts(newCount) {
* Refresh user counts (and broadcast if open)
*/
export function refreshUserMergeRequestCounts() {
- return Api.userCounts()
+ return getUserCounts()
.then(({ data }) => {
- const count = data.merge_requests;
+ const assignedMergeRequests = data.assigned_merge_requests;
+ const reviewerMergeRequests = data.review_requested_merge_requests;
+ const fullCount = assignedMergeRequests + reviewerMergeRequests;
- updateUserMergeRequestCounts(count);
- broadcastCount(count);
+ updateUserMergeRequestCounts(assignedMergeRequests);
+ updateReviewerMergeRequestCounts(reviewerMergeRequests);
+ updateMergeRequestCounts(fullCount);
+ broadcastCount(fullCount);
})
- .catch(ex => {
+ .catch((ex) => {
console.error(ex); // eslint-disable-line no-console
});
}
@@ -59,8 +73,8 @@ export function openUserCountsBroadcast() {
const currentUserId = typeof gon !== 'undefined' && gon && gon.current_user_id;
if (currentUserId) {
channel = new BroadcastChannel(`mr_count_channel_${currentUserId}`);
- channel.onmessage = ev => {
- updateUserMergeRequestCounts(ev.data);
+ channel.onmessage = (ev) => {
+ updateMergeRequestCounts(ev.data);
};
}
}
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js
index 1c1f0664885..82384434e8f 100644
--- a/app/assets/javascripts/compare_autocomplete.js
+++ b/app/assets/javascripts/compare_autocomplete.js
@@ -9,7 +9,7 @@ import { fixTitle } from '~/tooltips';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default function initCompareAutocomplete(limitTo = null, clickHandler = () => {}) {
- $('.js-compare-dropdown').each(function() {
+ $('.js-compare-dropdown').each(function () {
const $dropdown = $(this);
const selected = $dropdown.data('selected');
const $dropdownContainer = $dropdown.closest('.dropdown');
@@ -51,9 +51,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
.text(ref)
.attr('data-ref', ref);
if (ref.header != null) {
- return $('<li />')
- .addClass('dropdown-header')
- .text(ref.header);
+ return $('<li />').addClass('dropdown-header').text(ref.header);
}
return $('<li />').append(link);
},
@@ -65,7 +63,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
},
clicked: () => clickHandler($dropdown),
});
- $filterInput.on('keyup', e => {
+ $filterInput.on('keyup', (e) => {
const keyCode = e.keyCode || e.which;
if (keyCode !== 13) return;
const text = $filterInput.val();
@@ -74,7 +72,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
$dropdownContainer.removeClass('open');
});
- $dropdownContainer.on('click', '.dropdown-content a', e => {
+ $dropdownContainer.on('click', '.dropdown-content a', (e) => {
$dropdown.prop('title', e.target.text.replace(/_+?/g, '-'));
if ($dropdown.hasClass('has-tooltip')) {
fixTitle($dropdown);
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 3a6707bc573..58fe022b794 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
@@ -61,7 +61,7 @@ export default {
}
},
normalizeProjectData(data) {
- return data.map(p => ({
+ return data.map((p) => ({
id: p.id,
name: p.name_with_namespace,
pathWithNamespace: p.path_with_namespace,
@@ -78,7 +78,7 @@ export default {
this.projects = this.normalizeProjectData(data);
this.selectProject(this.projects[0]);
})
- .catch(e => {
+ .catch((e) => {
createFlash(__('Error fetching forked projects. Please try again.'));
throw e;
});
diff --git a/app/assets/javascripts/confirm_danger_modal.js b/app/assets/javascripts/confirm_danger_modal.js
index 4f7bc829b0c..5b9e70e3c09 100644
--- a/app/assets/javascripts/confirm_danger_modal.js
+++ b/app/assets/javascripts/confirm_danger_modal.js
@@ -47,7 +47,7 @@ function getModal($btn) {
}
export default function initConfirmDangerModal() {
- $(document).on('click', '.js-confirm-danger', e => {
+ $(document).on('click', '.js-confirm-danger', (e) => {
const $btn = $(e.target);
const checkFieldName = $btn.data('checkFieldName');
const checkFieldCompareValue = $btn.data('checkCompareValue');
diff --git a/app/assets/javascripts/confirm_modal.js b/app/assets/javascripts/confirm_modal.js
index bf2ea3ce38a..7a42b192b8a 100644
--- a/app/assets/javascripts/confirm_modal.js
+++ b/app/assets/javascripts/confirm_modal.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import ConfirmModal from '~/vue_shared/components/confirm_modal.vue';
-const mountConfirmModal = optionalProps =>
+const mountConfirmModal = (optionalProps) =>
new Vue({
render(h) {
return h(ConfirmModal, {
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index 41988f321e5..f7d24c70864 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -43,7 +43,10 @@ export default class ContextualSidebar {
$(document).trigger('content.resize');
});
- $(window).on('resize', debounce(() => this.render(), 100));
+ $(window).on(
+ 'resize',
+ debounce(() => this.render(), 100),
+ );
}
// See documentation: https://design.gitlab.com/regions/navigation#contextual-navigation
diff --git a/app/assets/javascripts/contributors/components/contributors.vue b/app/assets/javascripts/contributors/components/contributors.vue
index 3de1b2f0707..86580aa170b 100644
--- a/app/assets/javascripts/contributors/components/contributors.vue
+++ b/app/assets/javascripts/contributors/components/contributors.vue
@@ -39,7 +39,7 @@ export default {
...mapGetters(['showChart', 'parsedData']),
masterChartData() {
const data = {};
- this.xAxisRange.forEach(date => {
+ this.xAxisRange.forEach((date) => {
data[date] = this.parsedData.total[date] || 0;
});
return [
@@ -67,7 +67,7 @@ export default {
const maxNumberOfIndividualContributorsCharts = 100;
return Object.keys(this.parsedData.byAuthorEmail)
- .map(email => {
+ .map((email) => {
const author = this.parsedData.byAuthorEmail[email];
return {
name: author.name,
@@ -76,7 +76,7 @@ export default {
dates: [
{
name: __('Commits'),
- data: this.xAxisRange.map(date => [date, author.dates[date] || 0]),
+ data: this.xAxisRange.map((date) => [date, author.dates[date] || 0]),
},
],
};
@@ -101,7 +101,7 @@ export default {
},
individualChartYAxisMax() {
return this.individualChartsData.reduce((acc, item) => {
- const values = item.dates[0].data.map(value => value[1]);
+ const values = item.dates[0].data.map((value) => value[1]);
return Math.max(acc, ...values);
}, 0);
},
@@ -150,7 +150,7 @@ export default {
},
setSvg(name) {
return getSvgIconPathContent(name)
- .then(path => {
+ .then((path) => {
if (path) {
this.$set(this.svgs, name, `path://${path}`);
}
@@ -177,7 +177,7 @@ export default {
this.individualCharts.push(chart);
},
setIndividualChartsZoom(options) {
- this.charts.forEach(chart =>
+ this.charts.forEach((chart) =>
chart.setOption(
{
dataZoom: {
diff --git a/app/assets/javascripts/contributors/stores/actions.js b/app/assets/javascripts/contributors/stores/actions.js
index f941c5aa944..72aae3af692 100644
--- a/app/assets/javascripts/contributors/stores/actions.js
+++ b/app/assets/javascripts/contributors/stores/actions.js
@@ -8,8 +8,8 @@ export const fetchChartData = ({ commit }, endpoint) => {
return service
.fetchChartData(endpoint)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
commit(types.SET_CHART_DATA, data);
commit(types.SET_LOADING_STATE, false);
})
diff --git a/app/assets/javascripts/contributors/stores/getters.js b/app/assets/javascripts/contributors/stores/getters.js
index 9022179d6c7..45b569066f8 100644
--- a/app/assets/javascripts/contributors/stores/getters.js
+++ b/app/assets/javascripts/contributors/stores/getters.js
@@ -1,6 +1,6 @@
-export const showChart = state => Boolean(!state.loading && state.chartData);
+export const showChart = (state) => Boolean(!state.loading && state.chartData);
-export const parsedData = state => {
+export const parsedData = (state) => {
const byAuthorEmail = {};
const total = {};
diff --git a/app/assets/javascripts/contributors/utils.js b/app/assets/javascripts/contributors/utils.js
index 7d8932ce495..fa3f8154dfe 100644
--- a/app/assets/javascripts/contributors/utils.js
+++ b/app/assets/javascripts/contributors/utils.js
@@ -9,7 +9,7 @@ import { getMonthNames } from '~/lib/utils/datetime_utility';
* xAxisLabelFormatter('02-12-2019') will return 'Feb'
* xAxisLabelFormatter('07-12-2019') will return 'Jul'
*/
-export const xAxisLabelFormatter = val => {
+export const xAxisLabelFormatter = (val) => {
const date = new Date(val);
const month = date.getUTCMonth();
const year = date.getUTCFullYear();
@@ -21,7 +21,7 @@ export const xAxisLabelFormatter = val => {
* @param {Date}
* @returns {String} - formatted value
*/
-export const dateFormatter = date => {
+export const dateFormatter = (date) => {
const year = date.getUTCFullYear();
const month = date.getUTCMonth();
const day = date.getUTCDate();
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 1e3a19b9da1..7f4c3635119 100644
--- a/app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue
@@ -6,9 +6,9 @@ import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_searc
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-const toArray = value => (isNil(value) ? [] : [].concat(value));
-const itemsProp = (items, prop) => items.map(item => item[prop]);
-const defaultSearchFn = (searchQuery, labelProp) => item =>
+const toArray = (value) => (isNil(value) ? [] : [].concat(value));
+const itemsProp = (items, prop) => items.map((item) => item[prop]);
+const defaultSearchFn = (searchQuery, labelProp) => (item) =>
item[labelProp].toLowerCase().indexOf(searchQuery) > -1;
export default {
@@ -135,7 +135,7 @@ export default {
const valueList = toArray(this.value);
const items = this.getItemsOrEmptyList();
- return items.filter(item => valueList.some(value => item[valueProp] === value));
+ return items.filter((item) => valueList.some((value) => item[valueProp] === value));
},
selectedItemsLabels() {
return itemsProp(this.selectedItems, this.labelProperty).join(', ');
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/index.js b/app/assets/javascripts/create_cluster/eks_cluster/index.js
index 6d1034b4a72..38b7eefd15b 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/index.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/index.js
@@ -6,7 +6,7 @@ import createStore from './store';
Vue.use(Vuex);
-export default el => {
+export default (el) => {
const {
gitlabManagedClusterHelpPath,
namespacePerEnvironmentHelpPath,
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 58568b5dedb..c2b59191997 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
@@ -37,7 +37,7 @@ export const fetchVpcs = ({ region }) => {
.describeVpcs()
.promise()
.then(({ Vpcs: vpcs }) =>
- vpcs.map(vpc => ({
+ vpcs.map((vpc) => ({
value: vpc.VpcId,
name: lookupVpcName(vpc),
})),
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 b182d4dff13..55576efd3b8 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
@@ -5,7 +5,7 @@ import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-const getErrorMessage = data => {
+const getErrorMessage = (data) => {
const errorKey = Object.keys(data)[0];
return data[errorKey][0];
@@ -42,7 +42,7 @@ export const createRole = ({ dispatch, state: { createRolePath } }, payload) =>
dispatch('createRoleSuccess', awsData);
})
- .catch(error => {
+ .catch((error) => {
let message = error;
if (error?.response?.data?.message) {
message = error.response.data.message;
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/state.js b/app/assets/javascripts/create_cluster/eks_cluster/store/state.js
index c957eca1f7a..c906ddf9011 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/state.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/state.js
@@ -1,6 +1,6 @@
import { KUBERNETES_VERSIONS } from '../constants';
-const kubernetesVersion = KUBERNETES_VERSIONS.find(version => version.default).value;
+const kubernetesVersion = KUBERNETES_VERSIONS.find((version) => version.default).value;
export default () => ({
createRolePath: null,
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 3b91ce63744..f9d0d86e381 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
@@ -42,13 +42,13 @@ export default {
return [];
}
- return this.items.filter(item => item.name.toLowerCase().indexOf(this.searchQuery) > -1);
+ return this.items.filter((item) => item.name.toLowerCase().indexOf(this.searchQuery) > -1);
},
},
methods: {
fetchSuccessHandler() {
if (this.defaultValue) {
- const itemToSelect = this.items.find(item => item.name === this.defaultValue);
+ const itemToSelect = this.items.find((item) => item.name === this.defaultValue);
if (itemToSelect) {
this.setItem(itemToSelect.name);
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue
index d6deda25752..6b18455bfcc 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue
@@ -57,9 +57,7 @@ export default {
if (this.hasZone) {
this.isLoading = true;
- this.fetchMachineTypes()
- .then(this.fetchSuccessHandler)
- .catch(this.fetchFailureHandler);
+ this.fetchMachineTypes().then(this.fetchSuccessHandler).catch(this.fetchFailureHandler);
}
},
},
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 522fef423af..acbc4d1b3bc 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
@@ -99,16 +99,14 @@ export default {
created() {
this.isLoading = true;
- this.fetchProjects()
- .then(this.fetchSuccessHandler)
- .catch(this.fetchFailureHandler);
+ this.fetchProjects().then(this.fetchSuccessHandler).catch(this.fetchFailureHandler);
},
methods: {
...mapActions(['fetchProjects', 'setIsValidatingProjectBilling', 'validateProjectBilling']),
...mapActions({ setItem: 'setProject' }),
fetchSuccessHandler() {
if (this.defaultValue) {
- const projectToSelect = this.items.find(item => item.projectId === this.defaultValue);
+ const projectToSelect = this.items.find((item) => item.projectId === this.defaultValue);
if (projectToSelect) {
this.setItem(projectToSelect);
@@ -175,9 +173,7 @@ export default {
<gl-sprintf :message="helpText">
<template #linkToBilling="{ content }">
<gl-link
- :href="
- 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral'
- "
+ :href="'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral'"
target="_blank"
>{{ content }} <gl-icon name="external-link"
/></gl-link>
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue
index b60a5be2e63..daab42c7e60 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue
@@ -46,9 +46,7 @@ export default {
if (!isValidating && this.projectHasBillingEnabled) {
this.isLoading = true;
- this.fetchZones()
- .then(this.fetchSuccessHandler)
- .catch(this.fetchFailureHandler);
+ this.fetchZones().then(this.fetchSuccessHandler).catch(this.fetchFailureHandler);
}
},
},
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js b/app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js
new file mode 100644
index 00000000000..b5f92fed8eb
--- /dev/null
+++ b/app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js
@@ -0,0 +1,24 @@
+// This is a helper module to lazily import the google APIs for the GKE cluster
+// integration without introducing an indirect global dependency on an
+// initialized window.gapi object.
+export default () => {
+ if (window.gapiPromise === undefined) {
+ // first time loading the module
+ window.gapiPromise = new Promise((resolve, reject) => {
+ // this callback is set as a query param to script.src URL
+ window.onGapiLoad = () => {
+ resolve(window.gapi);
+ };
+
+ const script = document.createElement('script');
+ // do not use script.onload, because gapi continues to load after the initial script load
+ script.type = 'text/javascript';
+ script.async = true;
+ script.src = 'https://apis.google.com/js/api.js?onload=onGapiLoad';
+ script.onerror = reject;
+ document.head.appendChild(script);
+ });
+ }
+
+ return window.gapiPromise;
+};
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/index.js b/app/assets/javascripts/create_cluster/gke_cluster/index.js
index b9316353072..c02173fc510 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/index.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/index.js
@@ -1,10 +1,10 @@
-/* global gapi */
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 GkeSubmitButton from './components/gke_submit_button.vue';
+import gapiLoader from './gapi_loader';
import store from './store';
@@ -22,7 +22,7 @@ const mountComponent = (entryPoint, component, componentName, extraProps = {}) =
components: {
[componentName]: component,
},
- render: createElement =>
+ render: (createElement) =>
createElement(componentName, {
props: {
fieldName: hiddenInput.getAttribute('name'),
@@ -63,7 +63,7 @@ const gkeDropdownErrorHandler = () => {
Flash(CONSTANTS.GCP_API_ERROR);
};
-const initializeGapiClient = () => {
+const initializeGapiClient = (gapi) => () => {
const el = document.querySelector('.js-gke-cluster-creation');
if (!el) return false;
@@ -86,13 +86,9 @@ const initializeGapiClient = () => {
.catch(gkeDropdownErrorHandler);
};
-const initGkeDropdowns = () => {
- if (!gapi) {
- gkeDropdownErrorHandler();
- return false;
- }
-
- return gapi.load('client', initializeGapiClient);
-};
+const initGkeDropdowns = () =>
+ gapiLoader()
+ .then((gapi) => gapi.load('client', initializeGapiClient(gapi)))
+ .catch(gkeDropdownErrorHandler);
export default initGkeDropdowns;
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 f0c41d1d230..8977053297a 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
@@ -1,19 +1,19 @@
-/* global gapi */
import * as types from './mutation_types';
+import gapiLoader from '../gapi_loader';
const gapiResourceListRequest = ({ resource, params, commit, mutation, payloadKey }) =>
new Promise((resolve, reject) => {
const request = resource.list(params);
return request.then(
- resp => {
+ (resp) => {
const { result } = resp;
commit(mutation, result[payloadKey]);
resolve();
},
- resp => {
+ (resp) => {
reject(resp);
},
);
@@ -36,57 +36,64 @@ export const setIsValidatingProjectBilling = ({ commit }, isValidatingProjectBil
};
export const fetchProjects = ({ commit }) =>
- gapiResourceListRequest({
- resource: gapi.client.cloudresourcemanager.projects,
- params: {},
- commit,
- mutation: types.SET_PROJECTS,
- payloadKey: 'projects',
- });
+ gapiLoader().then((gapi) =>
+ gapiResourceListRequest({
+ resource: gapi.client.cloudresourcemanager.projects,
+ params: {},
+ commit,
+ mutation: types.SET_PROJECTS,
+ payloadKey: 'projects',
+ }),
+ );
export const validateProjectBilling = ({ dispatch, commit, state }) =>
- new Promise((resolve, reject) => {
- const request = gapi.client.cloudbilling.projects.getBillingInfo({
- name: `projects/${state.selectedProject.projectId}`,
- });
+ gapiLoader()
+ .then((gapi) => {
+ const request = gapi.client.cloudbilling.projects.getBillingInfo({
+ name: `projects/${state.selectedProject.projectId}`,
+ });
- commit(types.SET_ZONE, '');
- commit(types.SET_MACHINE_TYPE, '');
+ commit(types.SET_ZONE, '');
+ commit(types.SET_MACHINE_TYPE, '');
- return request.then(
- resp => {
+ return request;
+ })
+ .then(
+ (resp) => {
const { billingEnabled } = resp.result;
commit(types.SET_PROJECT_BILLING_STATUS, Boolean(billingEnabled));
dispatch('setIsValidatingProjectBilling', false);
- resolve();
},
- resp => {
+ (errorResp) => {
dispatch('setIsValidatingProjectBilling', false);
- reject(resp);
+ return errorResp;
},
);
- });
export const fetchZones = ({ commit, state }) =>
- gapiResourceListRequest({
- resource: gapi.client.compute.zones,
- params: {
- project: state.selectedProject.projectId,
- },
- commit,
- mutation: types.SET_ZONES,
- payloadKey: 'items',
- });
+ gapiLoader().then((gapi) =>
+ gapiResourceListRequest({
+ resource: gapi.client.compute.zones,
+ params: {
+ project: state.selectedProject.projectId,
+ },
+ commit,
+ mutation: types.SET_ZONES,
+ payloadKey: 'items',
+ }),
+ );
export const fetchMachineTypes = ({ commit, state }) =>
- gapiResourceListRequest({
- resource: gapi.client.compute.machineTypes,
- params: {
- project: state.selectedProject.projectId,
- zone: state.selectedZone,
- },
- commit,
- mutation: types.SET_MACHINE_TYPES,
- payloadKey: 'items',
- });
+ gapiLoader().then((gapi) =>
+ gapiResourceListRequest({
+ resource: gapi.client.compute.machineTypes,
+ params: {
+ project: state.selectedProject.projectId,
+ zone: state.selectedZone,
+ },
+ commit,
+ mutation: types.SET_MACHINE_TYPES,
+ payloadKey: 'items',
+ }),
+ );
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js b/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js
index 4d4cd223832..99f8393ffdb 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js
@@ -1,5 +1,5 @@
-export const hasProject = state => Boolean(state.selectedProject.projectId);
-export const hasZone = state => Boolean(state.selectedZone);
-export const hasMachineType = state => Boolean(state.selectedMachineType);
+export const hasProject = (state) => Boolean(state.selectedProject.projectId);
+export const hasZone = (state) => Boolean(state.selectedZone);
+export const hasMachineType = (state) => Boolean(state.selectedMachineType);
export const hasValidData = (state, getters) =>
Boolean(state.projectHasBillingEnabled) && getters.hasZone && getters.hasMachineType;
diff --git a/app/assets/javascripts/create_cluster/gke_cluster_namespace/index.js b/app/assets/javascripts/create_cluster/gke_cluster_namespace/index.js
index 0ec4d8807b0..2b3dfb99328 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster_namespace/index.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster_namespace/index.js
@@ -12,7 +12,7 @@ const setDisabled = (el, isDisabled) => {
}
};
-const setState = glManagedCheckbox => {
+const setState = (glManagedCheckbox) => {
const glManaged = document.querySelector('.js-namespace-prefixed');
const selfManaged = document.querySelector('.js-namespace');
diff --git a/app/assets/javascripts/create_cluster/init_create_cluster.js b/app/assets/javascripts/create_cluster/init_create_cluster.js
index 2b09771d772..f97da3d55db 100644
--- a/app/assets/javascripts/create_cluster/init_create_cluster.js
+++ b/app/assets/javascripts/create_cluster/init_create_cluster.js
@@ -4,11 +4,11 @@ import PersistentUserCallout from '~/persistent_user_callout';
const newClusterViews = [':clusters:new', ':clusters:create_gcp', ':clusters:create_user'];
-const isProjectLevelCluster = page => page.startsWith('project:clusters');
+const isProjectLevelCluster = (page) => page.startsWith('project:clusters');
-export default document => {
+export default (document) => {
const { page } = document.body.dataset;
- const isNewClusterView = newClusterViews.some(view => page.endsWith(view));
+ const isNewClusterView = newClusterViews.some((view) => page.endsWith(view));
if (!isNewClusterView) {
return;
@@ -19,6 +19,10 @@ export default document => {
initGkeDropdowns();
+ if (isProjectLevelCluster(page)) {
+ initGkeNamespace();
+ }
+
import(/* webpackChunkName: 'eks_cluster' */ '~/create_cluster/eks_cluster')
.then(({ default: initCreateEKSCluster }) => {
const el = document.querySelector('.js-create-eks-cluster-form-container');
@@ -28,8 +32,4 @@ export default document => {
}
})
.catch(() => {});
-
- if (isProjectLevelCluster(page)) {
- initGkeNamespace();
- }
};
diff --git a/app/assets/javascripts/create_cluster/store/cluster_dropdown/actions.js b/app/assets/javascripts/create_cluster/store/cluster_dropdown/actions.js
index 5d250b2e29e..669b0dcc732 100644
--- a/app/assets/javascripts/create_cluster/store/cluster_dropdown/actions.js
+++ b/app/assets/javascripts/create_cluster/store/cluster_dropdown/actions.js
@@ -1,6 +1,6 @@
import * as types from './mutation_types';
-export default fetchItems => ({
+export default (fetchItems) => ({
requestItems: ({ commit }) => commit(types.REQUEST_ITEMS),
receiveItemsSuccess: ({ commit }, payload) => commit(types.RECEIVE_ITEMS_SUCCESS, payload),
receiveItemsError: ({ commit }, payload) => commit(types.RECEIVE_ITEMS_ERROR, payload),
@@ -8,7 +8,7 @@ export default fetchItems => ({
dispatch('requestItems');
return fetchItems(payload)
- .then(items => dispatch('receiveItemsSuccess', { items }))
- .catch(error => dispatch('receiveItemsError', { error }));
+ .then((items) => dispatch('receiveItemsSuccess', { items }))
+ .catch((error) => dispatch('receiveItemsError', { error }));
},
});
diff --git a/app/assets/javascripts/create_item_dropdown.js b/app/assets/javascripts/create_item_dropdown.js
index 75e8523adfa..1472adf458b 100644
--- a/app/assets/javascripts/create_item_dropdown.js
+++ b/app/assets/javascripts/create_item_dropdown.js
@@ -47,7 +47,7 @@ export default class CreateItemDropdown {
return escape(item.id);
},
onFilter: this.toggleCreateNewButton.bind(this),
- clicked: options => {
+ clicked: (options) => {
options.e.preventDefault();
this.onSelect();
},
@@ -79,7 +79,7 @@ export default class CreateItemDropdown {
this.getDataOption(term, (data = []) => {
// Ensure the selected item isn't already in the data to avoid duplicates
const alreadyHasSelectedItem =
- this.selectedItem && data.some(item => item.id === this.selectedItem.id);
+ this.selectedItem && data.some((item) => item.id === this.selectedItem.id);
let uniqueData = data;
if (!alreadyHasSelectedItem) {
diff --git a/app/assets/javascripts/create_label.js b/app/assets/javascripts/create_label.js
index 0d53efe8689..07fe2c7e01f 100644
--- a/app/assets/javascripts/create_label.js
+++ b/app/assets/javascripts/create_label.js
@@ -46,7 +46,7 @@ export default class CreateLabelDropdown {
addBinding() {
const self = this;
- this.$colorSuggestions.on('click', function(e) {
+ this.$colorSuggestions.on('click', function (e) {
const $this = $(this);
self.addColorValue(e, $this);
});
@@ -56,7 +56,7 @@ export default class CreateLabelDropdown {
this.$dropdownBack.on('click', this.resetForm.bind(this));
- this.$cancelButton.on('click', e => {
+ this.$cancelButton.on('click', (e) => {
e.preventDefault();
e.stopPropagation();
@@ -72,10 +72,7 @@ export default class CreateLabelDropdown {
e.stopPropagation();
this.$newColorField.val($this.data('color')).trigger('change');
- this.$colorPreview
- .css('background-color', $this.data('color'))
- .parent()
- .addClass('is-active');
+ this.$colorPreview.css('background-color', $this.data('color')).parent().addClass('is-active');
}
enableLabelCreateButton() {
@@ -94,10 +91,7 @@ export default class CreateLabelDropdown {
this.$addList.prop('checked', this.addListDefault);
- this.$colorPreview
- .css('background-color', '')
- .parent()
- .removeClass('is-active');
+ this.$colorPreview.css('background-color', '').parent().removeClass('is-active');
}
saveLabel(e) {
@@ -111,7 +105,7 @@ export default class CreateLabelDropdown {
title: this.$newLabelField.val(),
color: this.$newColorField.val(),
},
- label => {
+ (label) => {
this.$newLabelCreateButton.enable();
if (label.message) {
@@ -121,7 +115,7 @@ export default class CreateLabelDropdown {
errors = label.message;
} else {
errors = Object.keys(label.message)
- .map(key => `${humanize(key)} ${label.message[key].join(', ')}`)
+ .map((key) => `${humanize(key)} ${label.message[key].join(', ')}`)
.join('<br/>');
}
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index 49091f5f140..aaaa7055799 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -191,7 +191,7 @@ export default class CreateMergeRequestDropdown {
static findByValue(objects, ref, returnFirstMatch = false) {
if (!objects || !objects.length) return false;
if (objects.indexOf(ref) > -1) return ref;
- if (returnFirstMatch) return objects.find(item => new RegExp(`^${ref}`).test(item));
+ if (returnFirstMatch) return objects.find((item) => new RegExp(`^${ref}`).test(item));
return false;
}
@@ -356,7 +356,7 @@ export default class CreateMergeRequestDropdown {
event.preventDefault();
if (isConfidentialIssue() && !event.target.classList.contains('js-create-target')) {
- this.droplab.hooks.forEach(hook => hook.list.toggle());
+ this.droplab.hooks.forEach((hook) => hook.list.toggle());
return;
}
@@ -404,8 +404,8 @@ export default class CreateMergeRequestDropdown {
const inputClasses = ['gl-field-error-outline', 'gl-field-success-outline'];
const messageClasses = ['text-muted', 'text-danger', 'text-success'];
- inputClasses.forEach(cssClass => input.classList.remove(cssClass));
- messageClasses.forEach(cssClass => message.classList.remove(cssClass));
+ inputClasses.forEach((cssClass) => input.classList.remove(cssClass));
+ messageClasses.forEach((cssClass) => message.classList.remove(cssClass));
message.style.display = 'none';
}
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 6f8455e4bcf..f3fa28dc2f3 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
@@ -22,7 +22,7 @@ let cancelTokenSource;
function backOffRequest(makeRequestCallback) {
return backOff((next, stop) => {
makeRequestCallback()
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.OK) {
stop(resp);
} else {
@@ -32,7 +32,7 @@ function backOffRequest(makeRequestCallback) {
// If the request is cancelled by axios
// then consider it as noop so that its not
// caught by subsequent catches
- .catch(thrown => (axios.isCancel(thrown) ? undefined : stop(thrown)));
+ .catch((thrown) => (axios.isCancel(thrown) ? undefined : stop(thrown)));
}, VALIDATION_REQUEST_TIMEOUT);
}
@@ -144,7 +144,7 @@ export default {
// as well.
cancelTokenSource = axiosCancelToken.source();
this.requestValidation(this.query, cancelTokenSource.token)
- .then(res => {
+ .then((res) => {
const response = res.data;
const { valid, error } = response.query;
if (response.success) {
diff --git a/app/assets/javascripts/custom_metrics/constants.js b/app/assets/javascripts/custom_metrics/constants.js
index 2526445fdf9..cd2ac6d8390 100644
--- a/app/assets/javascripts/custom_metrics/constants.js
+++ b/app/assets/javascripts/custom_metrics/constants.js
@@ -4,9 +4,9 @@ export const queryTypes = {
system: 'system',
};
-export const formDataValidator = val => {
+export const formDataValidator = (val) => {
const fieldNames = Object.keys(val);
const requiredFields = ['title', 'query', 'yLabel', 'unit', 'group', 'legend'];
- return requiredFields.every(name => fieldNames.includes(name));
+ return requiredFields.every((name) => fieldNames.includes(name));
};
diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.vue b/app/assets/javascripts/cycle_analytics/components/total_time_component.vue
index b93a7d3c4f9..f52438ca2cb 100644
--- a/app/assets/javascripts/cycle_analytics/components/total_time_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.vue
@@ -30,8 +30,6 @@ export default {
{{ time.seconds }} <span> {{ s__('Time|s') }} </span>
</template>
</template>
- <template v-else>
- --
- </template>
+ <template v-else> -- </template>
</span>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index 70ebe91a3b2..bd5a6cc40c4 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -78,7 +78,7 @@ export default () => {
$dropdown
.find('li a')
.off('click')
- .on('click', e => {
+ .on('click', (e) => {
e.preventDefault();
const $target = $(e.currentTarget);
this.startDate = $target.data('value');
@@ -94,7 +94,7 @@ export default () => {
this.service
.fetchCycleAnalyticsData(fetchOptions)
- .then(response => {
+ .then((response) => {
this.store.setCycleAnalyticsData(response);
this.selectDefaultStage();
this.initDropdown();
@@ -128,7 +128,7 @@ export default () => {
startDate: this.startDate,
projectIds: this.selectedProjectIds,
})
- .then(response => {
+ .then((response) => {
this.isEmptyStage = !response.events.length;
this.store.setStageEvents(response.events, stage);
this.isLoadingStage = false;
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
index babbfe93082..d7fcda24352 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
@@ -17,7 +17,7 @@ export default class CycleAnalyticsService {
'cycle_analytics[project_ids]': projectIds,
},
})
- .then(x => x.data);
+ .then((x) => x.data);
}
fetchStageData(options) {
@@ -30,6 +30,6 @@ export default class CycleAnalyticsService {
'cycle_analytics[project_ids]': projectIds,
},
})
- .then(x => x.data);
+ .then((x) => x.data);
}
}
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
index 3a160d0532c..7b04494892e 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
@@ -42,11 +42,11 @@ export default {
newData.stages = data.stats || [];
newData.summary = data.summary || [];
- newData.summary.forEach(item => {
+ newData.summary.forEach((item) => {
item.value = item.value || '-';
});
- newData.stages.forEach(item => {
+ newData.stages.forEach((item) => {
const stageSlug = dasherize(item.name.toLowerCase());
item.active = false;
item.isUserAllowed = data.permissions[stageSlug];
@@ -64,7 +64,7 @@ export default {
this.state.hasError = state;
},
deactivateAllStages() {
- this.state.stages.forEach(stage => {
+ this.state.stages.forEach((stage) => {
stage.active = false;
});
},
@@ -78,7 +78,7 @@ export default {
decorateEvents(events, stage) {
const newEvents = [];
- events.forEach(item => {
+ events.forEach((item) => {
if (!item) return;
const eventItem = { ...DEFAULT_EVENT_OBJECTS[stage.slug], ...item };
@@ -107,6 +107,6 @@ export default {
return newEvents;
},
currentActiveStage() {
- return this.state.stages.find(stage => stage.active);
+ return this.state.stages.find((stage) => stage.active);
},
};
diff --git a/app/assets/javascripts/deploy_freeze/store/actions.js b/app/assets/javascripts/deploy_freeze/store/actions.js
index 2fbbba5a128..9a75c3cad2f 100644
--- a/app/assets/javascripts/deploy_freeze/store/actions.js
+++ b/app/assets/javascripts/deploy_freeze/store/actions.js
@@ -28,7 +28,7 @@ export const addFreezePeriod = ({ state, dispatch, commit }) => {
commit(types.RESET_MODAL);
dispatch('fetchFreezePeriods');
})
- .catch(error => {
+ .catch((error) => {
createFlash(__('Error: Unable to create deploy freeze'));
dispatch('receiveAddFreezePeriodError', error);
});
diff --git a/app/assets/javascripts/deploy_freeze/store/index.js b/app/assets/javascripts/deploy_freeze/store/index.js
index ca7ea8c783c..2da7ed31a13 100644
--- a/app/assets/javascripts/deploy_freeze/store/index.js
+++ b/app/assets/javascripts/deploy_freeze/store/index.js
@@ -6,7 +6,7 @@ import createState from './state';
Vue.use(Vuex);
-export default initialState =>
+export default (initialState) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/deploy_freeze/store/mutations.js b/app/assets/javascripts/deploy_freeze/store/mutations.js
index 89ce1dc5428..3b34f3950e6 100644
--- a/app/assets/javascripts/deploy_freeze/store/mutations.js
+++ b/app/assets/javascripts/deploy_freeze/store/mutations.js
@@ -4,7 +4,7 @@ import * as types from './mutation_types';
const formatTimezoneName = (freezePeriod, timezoneList) =>
convertObjectPropsToCamelCase({
...freezePeriod,
- cron_timezone: timezoneList.find(tz => tz.identifier === freezePeriod.cron_timezone)?.name,
+ cron_timezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)?.name,
});
export default {
@@ -14,7 +14,7 @@ export default {
[types.RECEIVE_FREEZE_PERIODS_SUCCESS](state, freezePeriods) {
state.isLoading = false;
- state.freezePeriods = freezePeriods.map(freezePeriod =>
+ state.freezePeriods = freezePeriods.map((freezePeriod) =>
formatTimezoneName(freezePeriod, state.timezoneData),
);
},
diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue
index 0ac16e6b6a0..92e80d15902 100644
--- a/app/assets/javascripts/deploy_keys/components/app.vue
+++ b/app/assets/javascripts/deploy_keys/components/app.vue
@@ -39,7 +39,7 @@ export default {
},
computed: {
tabs() {
- return Object.keys(this.$options.scopes).map(scope => {
+ return Object.keys(this.$options.scopes).map((scope) => {
const count = Array.isArray(this.keys[scope]) ? this.keys[scope].length : null;
return {
@@ -81,7 +81,7 @@ export default {
return this.service
.getKeys()
- .then(data => {
+ .then((data) => {
this.isLoading = false;
this.store.keys = data;
})
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue
index 16eee094108..3ddaba7abcc 100644
--- a/app/assets/javascripts/deploy_keys/components/key.vue
+++ b/app/assets/javascripts/deploy_keys/components/key.vue
@@ -48,7 +48,7 @@ export default {
if (this.projectId !== null) {
const indexOfCurrentProject = projects.findIndex(
- project =>
+ (project) =>
project &&
project.project &&
project.project.id &&
diff --git a/app/assets/javascripts/deploy_keys/service/index.js b/app/assets/javascripts/deploy_keys/service/index.js
index 10333752936..2837fc8ed88 100644
--- a/app/assets/javascripts/deploy_keys/service/index.js
+++ b/app/assets/javascripts/deploy_keys/service/index.js
@@ -6,14 +6,14 @@ export default class DeployKeysService {
}
getKeys() {
- return axios.get(this.endpoint).then(response => response.data);
+ return axios.get(this.endpoint).then((response) => response.data);
}
enableKey(id) {
- return axios.put(`${this.endpoint}/${id}/enable`).then(response => response.data);
+ return axios.put(`${this.endpoint}/${id}/enable`).then((response) => response.data);
}
disableKey(id) {
- return axios.put(`${this.endpoint}/${id}/disable`).then(response => response.data);
+ return axios.put(`${this.endpoint}/${id}/disable`).then((response) => response.data);
}
}
diff --git a/app/assets/javascripts/deploy_keys/store/index.js b/app/assets/javascripts/deploy_keys/store/index.js
index a350bc99a70..dcd77e921cd 100644
--- a/app/assets/javascripts/deploy_keys/store/index.js
+++ b/app/assets/javascripts/deploy_keys/store/index.js
@@ -4,6 +4,6 @@ export default class DeployKeysStore {
}
isEnabled(id) {
- return this.keys.enabled_keys.some(key => key.id === id);
+ return this.keys.enabled_keys.some((key) => key.id === id);
}
}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
index fe57dd2dc8f..99351231520 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
@@ -68,7 +68,7 @@ export class GitLabDropdown {
this.remote = new GitLabDropdownRemote(this.options.data, {
dataType: this.options.dataType,
beforeSend: this.toggleLoading.bind(this),
- success: data => {
+ success: (data) => {
this.fullData = data;
this.parseData(this.fullData);
this.focusTextInput();
@@ -113,7 +113,7 @@ export class GitLabDropdown {
return $(selector, this.dropdown);
},
data: () => this.fullData,
- callback: data => {
+ callback: (data) => {
this.parseData(data);
if (this.filterInput.val() !== '') {
selector = SELECTABLE_CLASSES;
@@ -123,10 +123,7 @@ export class GitLabDropdown {
if ($(this.el).is('input')) {
currentIndex = -1;
} else {
- $(selector, this.dropdown)
- .first()
- .find('a')
- .addClass('is-focused');
+ $(selector, this.dropdown).first().find('a').addClass('is-focused');
currentIndex = 0;
}
}
@@ -138,13 +135,13 @@ export class GitLabDropdown {
this.dropdown.on('hidden.bs.dropdown', this.hidden);
$(this.el).on('update.label', this.updateLabel);
this.dropdown.on('click', '.dropdown-menu, .dropdown-menu-close', this.shouldPropagate);
- this.dropdown.on('keyup', e => {
+ this.dropdown.on('keyup', (e) => {
// Escape key
if (e.which === 27) {
return $('.dropdown-menu-close', this.dropdown).trigger('click');
}
});
- this.dropdown.on('blur', 'a', e => {
+ this.dropdown.on('blur', 'a', (e) => {
let $dropdownMenu;
let $relatedTarget;
if (e.relatedTarget != null) {
@@ -156,7 +153,7 @@ export class GitLabDropdown {
}
});
if (this.dropdown.find('.dropdown-toggle-page').length) {
- this.dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on('click', e => {
+ this.dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on('click', (e) => {
e.preventDefault();
e.stopPropagation();
return this.togglePage();
@@ -167,7 +164,7 @@ export class GitLabDropdown {
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = '.dropdown-page-one .dropdown-content a';
}
- this.dropdown.on('click', selector, e => {
+ this.dropdown.on('click', selector, (e) => {
const $el = $(e.currentTarget);
const selected = self.rowClicked($el);
const selectedObj = selected ? selected[0] : null;
@@ -224,7 +221,7 @@ export class GitLabDropdown {
else if (isObject(data)) {
html = [];
- Object.keys(data).forEach(name => {
+ Object.keys(data).forEach((name) => {
groupData = data[name];
html.push(
this.renderItem(
@@ -235,7 +232,7 @@ export class GitLabDropdown {
name,
),
);
- this.renderData(groupData, name).map(item => html.push(item));
+ this.renderData(groupData, name).map((item) => html.push(item));
});
} else {
// Render each row
@@ -274,7 +271,7 @@ export class GitLabDropdown {
filteredFullData() {
return this.fullData.filter(
- r =>
+ (r) =>
typeof r === 'object' &&
!Object.prototype.hasOwnProperty.call(r, 'beforeDivider') &&
!Object.prototype.hasOwnProperty.call(r, 'header'),
@@ -392,7 +389,7 @@ export class GitLabDropdown {
...this.options,
icon: this.icon,
highlight: this.highlight,
- highlightText: text => this.highlightTextMatches(text, this.filterInput.val()),
+ highlightText: (text) => this.highlightTextMatches(text, this.filterInput.val()),
highlightTemplate: this.highlightTemplate.bind(this),
parent,
},
@@ -493,10 +490,7 @@ export class GitLabDropdown {
if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) {
this.dropdown.find(`.${ACTIVE_CLASS}`).removeClass(ACTIVE_CLASS);
if (!isInput) {
- this.dropdown
- .parent()
- .find(`input[name='${fieldName}']`)
- .remove();
+ this.dropdown.parent().find(`input[name='${fieldName}']`).remove();
}
}
if (field && field.length && value == null) {
@@ -536,16 +530,13 @@ export class GitLabDropdown {
$(`input[name="${fieldName}"]`).remove();
}
- const $input = $('<input>')
- .attr('type', 'hidden')
- .attr('name', fieldName)
- .val(value);
+ const $input = $('<input>').attr('type', 'hidden').attr('name', fieldName).val(value);
if (this.options.inputId != null) {
$input.attr('id', this.options.inputId);
}
if (this.options.multiSelect) {
- Object.keys(selectedObject).forEach(attribute => {
+ Object.keys(selectedObject).forEach((attribute) => {
$input.attr(`data-${attribute}`, selectedObject[attribute]);
});
}
@@ -586,7 +577,7 @@ export class GitLabDropdown {
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = `.dropdown-page-one ${selector}`;
}
- return $('body').on('keydown', e => {
+ return $('body').on('keydown', (e) => {
let $listItems;
let PREV_INDEX;
const currentKeyCode = e.which;
@@ -678,9 +669,7 @@ export class GitLabDropdown {
toggleText = this.options.updateLabel;
}
- return $(this.el)
- .find('.dropdown-toggle-text')
- .text(toggleText);
+ return $(this.el).find('.dropdown-toggle-text').text(toggleText);
}
// eslint-disable-next-line class-methods-use-this
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 89ffb5f5f79..ab9fb1ec332 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
@@ -18,19 +18,16 @@ export class GitLabDropdownFilter {
this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true;
const $inputContainer = this.input.parent();
const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
- $clearButton.on('click', e => {
+ $clearButton.on('click', (e) => {
// Clear click
e.preventDefault();
e.stopPropagation();
- return this.input
- .val('')
- .trigger('input')
- .focus();
+ return this.input.val('').trigger('input').focus();
});
// Key events
timeout = '';
this.input
- .on('keydown', e => {
+ .on('keydown', (e) => {
const keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
@@ -49,7 +46,7 @@ export class GitLabDropdownFilter {
return (timeout = setTimeout(() => {
$inputContainer.parent().addClass('is-loading');
- return this.options.query(this.input.val(), data => {
+ return this.options.query(this.input.val(), (data) => {
$inputContainer.parent().removeClass('is-loading');
return this.options.callback(data);
});
@@ -97,13 +94,13 @@ export class GitLabDropdownFilter {
// }
else if (isObject(data)) {
results = {};
- Object.keys(data).forEach(key => {
+ Object.keys(data).forEach((key) => {
group = data[key];
tmp = fuzzaldrinPlus.filter(group, searchText, {
key: this.options.keys,
});
if (tmp.length) {
- results[key] = tmp.map(item => item);
+ results[key] = tmp.map((item) => item);
}
});
}
@@ -113,7 +110,7 @@ export class GitLabDropdownFilter {
const elements = this.options.elements();
if (searchText) {
// eslint-disable-next-line func-names
- elements.each(function() {
+ elements.each(function () {
const $el = $(this);
const matches = fuzzaldrinPlus.match($el.text().trim(), searchText);
if (!$el.is('.dropdown-header')) {
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js
index d857071d05f..61d3e5fbf38 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js
@@ -5,24 +5,21 @@ export class GitLabDropdownInput {
this.fieldName = this.options.fieldName || 'field-name';
const $inputContainer = this.input.parent();
const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
- $clearButton.on('click', e => {
+ $clearButton.on('click', (e) => {
// Clear click
e.preventDefault();
e.stopPropagation();
- return this.input
- .val('')
- .trigger('input')
- .focus();
+ return this.input.val('').trigger('input').focus();
});
this.input
- .on('keydown', e => {
+ .on('keydown', (e) => {
const keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
}
})
- .on('input', e => {
+ .on('input', (e) => {
let val = e.currentTarget.value || this.options.inputFieldName;
val = val
.split(' ')
@@ -31,10 +28,7 @@ export class GitLabDropdownInput {
.toLowerCase() // replace non alphanumeric
.replace(/(-)\1+/g, '-'); // replace repeated dashes
this.cb(this.options.fieldName, val, {}, true);
- this.input
- .closest('.dropdown')
- .find('.dropdown-toggle-text')
- .text(val);
+ this.input.closest('.dropdown').find('.dropdown-toggle-text').text(val);
});
}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js
index 1f6a2e1f646..ae5d3298b62 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js
@@ -15,7 +15,7 @@ export class GitLabDropdownRemote {
if (this.options.beforeSend) {
this.options.beforeSend();
}
- return this.dataEndpoint('', data => {
+ return this.dataEndpoint('', (data) => {
// Fetch the data by calling the data function
if (this.options.success) {
this.options.success(data);
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/index.js b/app/assets/javascripts/deprecated_jquery_dropdown/index.js
index 90e7f15b5b7..6a3d2026192 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/index.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/index.js
@@ -3,7 +3,7 @@ import { GitLabDropdown } from './gl_dropdown';
export default function initDeprecatedJQueryDropdown($el, opts) {
// eslint-disable-next-line func-names
- return $el.each(function() {
+ return $el.each(function () {
if (!$.data(this, 'deprecatedJQueryDropdown')) {
$.data(this, 'deprecatedJQueryDropdown', new GitLabDropdown(this, opts));
}
diff --git a/app/assets/javascripts/design_management/components/design_destroyer.vue b/app/assets/javascripts/design_management/components/design_destroyer.vue
index 5d32bfd4a73..01f9cac456d 100644
--- a/app/assets/javascripts/design_management/components/design_destroyer.vue
+++ b/app/assets/javascripts/design_management/components/design_destroyer.vue
@@ -8,12 +8,6 @@ export default {
components: {
ApolloMutation,
},
- props: {
- filenames: {
- type: Array,
- required: true,
- },
- },
inject: {
projectPath: {
default: '',
@@ -23,6 +17,12 @@ export default {
defaut: '',
},
},
+ props: {
+ filenames: {
+ type: Array,
+ required: true,
+ },
+ },
computed: {
projectQueryBody() {
return {
@@ -32,12 +32,7 @@ export default {
},
},
methods: {
- updateStoreAfterDelete(
- store,
- {
- data: { designManagementDelete },
- },
- ) {
+ updateStoreAfterDelete(store, { data: { designManagementDelete } }) {
updateStoreAfterDesignsDelete(
store,
designManagementDelete,
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 6aab4bf423e..ea4d5d7b570 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
@@ -171,7 +171,7 @@ export default {
this.$emit('resolve-discussion-error', data.errors[0]);
}
})
- .catch(err => {
+ .catch((err) => {
this.$emit('resolve-discussion-error', err);
})
.finally(() => {
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 7aaac58a1ce..0cc89440754 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
@@ -2,6 +2,7 @@
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';
export default {
name: 'DesignReplyForm',
@@ -60,6 +61,9 @@ export default {
? s__('DesignManagement|Comment')
: s__('DesignManagement|Save comment');
},
+ markdownDocsPath() {
+ return helpPagePath('user/markdown');
+ },
},
mounted() {
this.focusInput();
@@ -89,7 +93,7 @@ export default {
:can-attach-file="false"
:enable-autocomplete="true"
:textarea-value="value"
- markdown-docs-path="/help/user/markdown"
+ :markdown-docs-path="markdownDocsPath"
class="bordered-box"
>
<template #textarea>
diff --git a/app/assets/javascripts/design_management/components/design_presentation.vue b/app/assets/javascripts/design_management/components/design_presentation.vue
index c4d904e0d91..a760adf8b14 100644
--- a/app/assets/javascripts/design_management/components/design_presentation.vue
+++ b/app/assets/javascripts/design_management/components/design_presentation.vue
@@ -58,7 +58,7 @@ export default {
},
computed: {
discussionStartingNotes() {
- return this.discussions.map(discussion => ({
+ return this.discussions.map((discussion) => ({
...discussion.notes[0],
index: discussion.index,
}));
diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue
index 41dcec38abe..50b12fd739b 100644
--- a/app/assets/javascripts/design_management/components/design_sidebar.vue
+++ b/app/assets/javascripts/design_management/components/design_sidebar.vue
@@ -21,6 +21,14 @@ export default {
DesignTodoButton,
},
mixins: [glFeatureFlagsMixin()],
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ issueIid: {
+ default: '',
+ },
+ },
props: {
design: {
type: Object,
@@ -41,14 +49,6 @@ export default {
discussionWithOpenForm: '',
};
},
- inject: {
- projectPath: {
- default: '',
- },
- issueIid: {
- default: '',
- },
- },
computed: {
discussions() {
return extractDiscussions(this.design.discussions);
@@ -63,10 +63,10 @@ export default {
return extractParticipants(this.issue.participants.nodes);
},
resolvedDiscussions() {
- return this.discussions.filter(discussion => discussion.resolved);
+ return this.discussions.filter((discussion) => discussion.resolved);
},
unresolvedDiscussions() {
- return this.discussions.filter(discussion => !discussion.resolved);
+ return this.discussions.filter((discussion) => !discussion.resolved);
},
resolvedCommentsToggleIcon() {
return this.resolvedDiscussionsExpanded ? 'chevron-down' : 'chevron-right';
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 aff4f348d15..db14db79989 100644
--- a/app/assets/javascripts/design_management/components/design_todo_button.vue
+++ b/app/assets/javascripts/design_management/components/design_todo_button.vue
@@ -13,12 +13,6 @@ export default {
TodoButton,
},
mixins: [allVersionsMixin],
- props: {
- design: {
- type: Object,
- required: true,
- },
- },
inject: {
projectPath: {
default: '',
@@ -27,6 +21,12 @@ export default {
default: '',
},
},
+ props: {
+ design: {
+ type: Object,
+ required: true,
+ },
+ },
data() {
return {
todoLoading: false,
@@ -95,7 +95,7 @@ export default {
.then(() => {
this.incrementGlobalTodoCount();
})
- .catch(err => {
+ .catch((err) => {
this.$emit('error', Error(CREATE_DESIGN_TODO_ERROR));
throw err;
})
@@ -116,12 +116,7 @@ export default {
variables: {
id,
},
- update(
- store,
- {
- data: { todoMarkDone },
- },
- ) {
+ update(store, { data: { todoMarkDone } }) {
const todoMarkDoneFirstError = (todoMarkDone.errors || [])[0];
if (todoMarkDoneFirstError) {
this.$emit('error', Error(todoMarkDoneFirstError));
@@ -138,7 +133,7 @@ export default {
.then(() => {
this.decrementGlobalTodoCount();
})
- .catch(err => {
+ .catch((err) => {
this.$emit('error', Error(DELETE_DESIGN_TODO_ERROR));
throw err;
})
diff --git a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
index 4edc2e410c7..6091a3183ac 100644
--- a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
@@ -26,7 +26,7 @@ export default {
return this.designs.length;
},
currentIndex() {
- return this.designs.findIndex(design => design.filename === this.id);
+ return this.designs.findIndex((design) => design.filename === this.id);
},
paginationText() {
return sprintf(s__('DesignManagement|%{current_design} of %{designs_count}'), {
diff --git a/app/assets/javascripts/design_management/components/toolbar/index.vue b/app/assets/javascripts/design_management/components/toolbar/index.vue
index 4caee863df8..3509a701984 100644
--- a/app/assets/javascripts/design_management/components/toolbar/index.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/index.vue
@@ -18,6 +18,14 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [timeagoMixin],
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ issueIid: {
+ default: '',
+ },
+ },
props: {
id: {
type: String,
@@ -58,14 +66,6 @@ export default {
},
};
},
- inject: {
- projectPath: {
- default: '',
- },
- issueIid: {
- default: '',
- },
- },
apollo: {
permissions: {
query: permissionsQuery,
@@ -75,7 +75,7 @@ export default {
iid: this.issueIid,
};
},
- update: data => data.project.issue.userPermissions,
+ update: (data) => data.project.issue.userPermissions,
},
},
computed: {
diff --git a/app/assets/javascripts/design_management/components/upload/design_version_dropdown.vue b/app/assets/javascripts/design_management/components/upload/design_version_dropdown.vue
index 4a1be7b720a..750f16bbe57 100644
--- a/app/assets/javascripts/design_management/components/upload/design_version_dropdown.vue
+++ b/app/assets/javascripts/design_management/components/upload/design_version_dropdown.vue
@@ -19,7 +19,7 @@ export default {
if (!this.queryVersion) return 0;
const idx = this.allVersions.findIndex(
- version => this.findVersionId(version.id) === this.queryVersion,
+ (version) => this.findVersionId(version.id) === this.queryVersion,
);
// if the currentVersionId isn't a valid version (i.e. not in allVersions)
diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js
index d1fe977b969..b7aba315168 100644
--- a/app/assets/javascripts/design_management/graphql.js
+++ b/app/assets/javascripts/design_management/graphql.js
@@ -19,7 +19,7 @@ const resolvers = {
updateActiveDiscussion: (_, { id = null, source }, { cache }) => {
const sourceData = cache.readQuery({ query: activeDiscussionQuery });
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.activeDiscussion = {
__typename: 'ActiveDiscussion',
@@ -74,7 +74,7 @@ const defaultClient = createDefaultClient(
// Should be removed as soon as https://gitlab.com/gitlab-org/gitlab/issues/13495 is resolved
{
cacheConfig: {
- dataIdFromObject: object => {
+ dataIdFromObject: (object) => {
// eslint-disable-next-line no-underscore-dangle, @gitlab/require-i18n-strings
if (object.__typename === 'Design') {
return object.id && object.image ? `${object.id}-${object.image}` : uniqueId();
diff --git a/app/assets/javascripts/design_management/mixins/all_designs.js b/app/assets/javascripts/design_management/mixins/all_designs.js
index 466f61e21fa..4783382d563 100644
--- a/app/assets/javascripts/design_management/mixins/all_designs.js
+++ b/app/assets/javascripts/design_management/mixins/all_designs.js
@@ -17,7 +17,7 @@ export default {
atVersion: this.designsVersion,
};
},
- update: data => {
+ update: (data) => {
const designNodes = propertyOf(data)([
'project',
'issue',
diff --git a/app/assets/javascripts/design_management/mixins/all_versions.js b/app/assets/javascripts/design_management/mixins/all_versions.js
index 07cd0fc92bd..42cef35a08e 100644
--- a/app/assets/javascripts/design_management/mixins/all_versions.js
+++ b/app/assets/javascripts/design_management/mixins/all_versions.js
@@ -12,7 +12,7 @@ export default {
atVersion: null,
};
},
- update: data => data.project.issue.designCollection.versions.nodes,
+ update: (data) => data.project.issue.designCollection.versions.nodes,
},
},
inject: {
@@ -28,7 +28,7 @@ export default {
return (
this.$route.query.version &&
this.allVersions &&
- this.allVersions.some(version => version.id.endsWith(this.$route.query.version))
+ this.allVersions.some((version) => version.id.endsWith(this.$route.query.version))
);
},
designsVersion() {
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index fb86568c304..492ed2e8719 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -57,6 +57,27 @@ export default {
DesignSidebar,
},
mixins: [allVersionsMixin, glFeatureFlagsMixin()],
+ beforeRouteUpdate(to, from, next) {
+ // reset scale when the active design changes
+ this.scale = DEFAULT_SCALE;
+ next();
+ },
+ beforeRouteEnter(to, from, next) {
+ const pageEl = getPageLayoutElement();
+ if (pageEl) {
+ pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
+ }
+
+ next();
+ },
+ beforeRouteLeave(to, from, next) {
+ const pageEl = getPageLayoutElement();
+ if (pageEl) {
+ pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
+ }
+
+ next();
+ },
props: {
id: {
type: String,
@@ -81,7 +102,7 @@ export default {
variables() {
return this.designVariables;
},
- update: data => extractDesign(data),
+ update: (data) => extractDesign(data),
result(res) {
this.onDesignQueryResult(res);
},
@@ -139,7 +160,7 @@ export default {
return Boolean(this.annotationCoordinates);
},
resolvedDiscussions() {
- return this.discussions.filter(discussion => discussion.resolved);
+ return this.discussions.filter((discussion) => discussion.resolved);
},
},
watch: {
@@ -161,18 +182,8 @@ export default {
beforeDestroy() {
Mousetrap.unbind('esc', this.closeDesign);
},
- beforeRouteUpdate(to, from, next) {
- // reset scale when the active design changes
- this.scale = DEFAULT_SCALE;
- next();
- },
methods: {
- addImageDiffNoteToStore(
- store,
- {
- data: { createImageDiffNote },
- },
- ) {
+ addImageDiffNoteToStore(store, { data: { createImageDiffNote } }) {
updateStoreAfterAddImageDiffNote(
store,
createImageDiffNote,
@@ -180,12 +191,7 @@ export default {
this.designVariables,
);
},
- updateImageDiffNoteInStore(
- store,
- {
- data: { repositionImageDiffNote },
- },
- ) {
+ updateImageDiffNoteInStore(store, { data: { repositionImageDiffNote } }) {
return updateStoreAfterRepositionImageDiffNote(
store,
repositionImageDiffNote,
@@ -213,7 +219,7 @@ export default {
update: this.updateImageDiffNoteInStore,
};
- return this.$apollo.mutate(mutationPayload).catch(e => this.onUpdateImageDiffNoteError(e));
+ return this.$apollo.mutate(mutationPayload).catch((e) => this.onUpdateImageDiffNoteError(e));
},
onDesignQueryResult({ data, loading }) {
// On the initial load with cache-and-network policy data is undefined while loading is true
@@ -306,22 +312,6 @@ export default {
this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded;
},
},
- beforeRouteEnter(to, from, next) {
- const pageEl = getPageLayoutElement();
- if (pageEl) {
- pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- }
-
- next();
- },
- beforeRouteLeave(to, from, next) {
- const pageEl = getPageLayoutElement();
- if (pageEl) {
- pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- }
-
- next();
- },
createImageDiffNoteMutation,
DESIGNS_ROUTE_NAME,
};
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index ea404692840..5c82a7331b6 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -69,9 +69,13 @@ export default {
iid: this.issueIid,
};
},
- update: data => data.project.issue.userPermissions,
+ update: (data) => data.project.issue.userPermissions,
},
},
+ beforeRouteUpdate(to, from, next) {
+ this.selectedDesigns = [];
+ next();
+ },
data() {
return {
permissions: {
@@ -184,15 +188,10 @@ export default {
return this.$apollo
.mutate(mutationPayload)
- .then(res => this.onUploadDesignDone(res))
+ .then((res) => this.onUploadDesignDone(res))
.catch(() => this.onUploadDesignError());
},
- afterUploadDesign(
- store,
- {
- data: { designManagementUpload },
- },
- ) {
+ afterUploadDesign(store, { data: { designManagementUpload } }) {
updateStoreAfterUploadDesign(store, designManagementUpload, this.projectQueryBody);
},
onUploadDesignDone(res) {
@@ -213,7 +212,7 @@ export default {
this.trackUploadDesign(res);
},
trackUploadDesign(res) {
- (res?.data?.designManagementUpload?.designs || []).forEach(design => {
+ (res?.data?.designManagementUpload?.designs || []).forEach((design) => {
if (design.event === 'CREATION') {
trackDesignCreate();
} else if (design.event === 'MODIFICATION') {
@@ -227,7 +226,7 @@ export default {
},
changeSelectedDesigns(filename) {
if (this.isDesignSelected(filename)) {
- this.selectedDesigns = this.selectedDesigns.filter(design => design !== filename);
+ this.selectedDesigns = this.selectedDesigns.filter((design) => design !== filename);
} else {
this.selectedDesigns.push(filename);
}
@@ -236,14 +235,14 @@ export default {
if (this.hasSelectedDesigns) {
this.selectedDesigns = [];
} else {
- this.selectedDesigns = this.designs.map(design => design.filename);
+ this.selectedDesigns = this.designs.map((design) => design.filename);
}
},
isDesignSelected(filename) {
return this.selectedDesigns.includes(filename);
},
isDesignToBeSaved(filename) {
- return this.filesToBeSaved.some(file => file.name === filename);
+ return this.filesToBeSaved.some((file) => file.name === filename);
},
canSelectDesign(filename) {
return this.isLatestVersion && this.canCreateDesign && !this.isDesignToBeSaved(filename);
@@ -329,10 +328,6 @@ export default {
this.reorderedDesigns = designs;
},
},
- beforeRouteUpdate(to, from, next) {
- this.selectedDesigns = [];
- next();
- },
dragOptions: {
animation: 200,
ghostClass: 'gl-visibility-hidden',
diff --git a/app/assets/javascripts/design_management/router/routes.js b/app/assets/javascripts/design_management/router/routes.js
index d888b856611..1b07d8aeb76 100644
--- a/app/assets/javascripts/design_management/router/routes.js
+++ b/app/assets/javascripts/design_management/router/routes.js
@@ -13,13 +13,7 @@ export default [
name: DESIGN_ROUTE_NAME,
path: '/designs/:id',
component: DesignDetail,
- beforeEnter(
- {
- params: { id },
- },
- _,
- next,
- ) {
+ beforeEnter({ params: { id } }, _, next) {
if (typeof id === 'string') {
next();
}
diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index 5bd0288d037..0c4ee0bf012 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -11,14 +11,14 @@ import {
designDeletionError,
} from './error_messages';
-const designsOf = data => data.project.issue.designCollection.designs;
+const designsOf = (data) => data.project.issue.designCollection.designs;
const deleteDesignsFromStore = (store, query, selectedDesigns) => {
const sourceData = store.readQuery(query);
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
const changedDesigns = designsOf(sourceData).nodes.filter(
- design => !selectedDesigns.includes(design.filename),
+ (design) => !selectedDesigns.includes(design.filename),
);
designsOf(draftData).nodes = [...changedDesigns];
});
@@ -40,7 +40,7 @@ const addNewVersionToStore = (store, query, version) => {
if (!version) return;
const sourceData = store.readQuery(query);
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.project.issue.designCollection.versions.nodes = [
version,
@@ -74,14 +74,14 @@ const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) =
},
};
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
const design = extractDesign(draftData);
design.notesCount += 1;
design.discussions.nodes = [...design.discussions.nodes, newDiscussion];
if (
!design.issue.participants.nodes.some(
- participant => participant.username === createImageDiffNote.note.author.username,
+ (participant) => participant.username === createImageDiffNote.note.author.username,
)
) {
design.issue.participants.nodes = [
@@ -107,7 +107,7 @@ const updateImageDiffNoteInStore = (store, repositionImageDiffNote, query, varia
variables,
});
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
const design = extractDesign(draftData);
const discussion = extractCurrentDiscussion(
design.discussions,
@@ -130,18 +130,18 @@ const updateImageDiffNoteInStore = (store, repositionImageDiffNote, query, varia
const addNewDesignToStore = (store, designManagementUpload, query) => {
const sourceData = store.readQuery(query);
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
const currentDesigns = extractDesigns(draftData);
const difference = differenceBy(designManagementUpload.designs, currentDesigns, 'filename');
const newDesigns = currentDesigns
- .map(design => {
- return designManagementUpload.designs.find(d => d.filename === design.filename) || design;
+ .map((design) => {
+ return designManagementUpload.designs.find((d) => d.filename === design.filename) || design;
})
.concat(difference);
let newVersionNode;
- const findNewVersions = designManagementUpload.designs.find(design => design.versions);
+ const findNewVersions = designManagementUpload.designs.find((design) => design.versions);
if (findNewVersions) {
const findNewVersionsNodes = findNewVersions.versions.nodes;
@@ -181,7 +181,7 @@ const addNewDesignToStore = (store, designManagementUpload, query) => {
const moveDesignInStore = (store, designManagementMove, query) => {
const sourceData = store.readQuery(query);
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
// eslint-disable-next-line no-param-reassign
draftData.project.issue.designCollection.designs =
designManagementMove.designCollection.designs;
@@ -199,7 +199,7 @@ export const addPendingTodoToStore = (store, pendingTodo, query, queryVariables)
variables: queryVariables,
});
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
const design = extractDesign(draftData);
const existingTodos = design.currentUserTodos?.nodes || [];
const newTodoNodes = [...existingTodos, { ...pendingTodo, __typename: 'Todo' }];
@@ -226,7 +226,7 @@ export const deletePendingTodoFromStore = (store, todoMarkDone, query, queryVari
const {
todo: { id: todoId },
} = todoMarkDone;
- const data = produce(sourceData, draftData => {
+ const data = produce(sourceData, (draftData) => {
const design = extractDesign(draftData);
const existingTodos = design.currentUserTodos?.nodes || [];
diff --git a/app/assets/javascripts/design_management/utils/design_management_utils.js b/app/assets/javascripts/design_management/utils/design_management_utils.js
index a905230811c..05b220801f2 100644
--- a/app/assets/javascripts/design_management/utils/design_management_utils.js
+++ b/app/assets/javascripts/design_management/utils/design_management_utils.js
@@ -10,7 +10,7 @@ export const isValidDesignFile = ({ type }) =>
* @param {Array} discussions
*/
-export const extractDiscussions = discussions =>
+export const extractDiscussions = (discussions) =>
discussions.nodes.map((discussion, index) => ({
...discussion,
index: index + 1,
@@ -24,27 +24,27 @@ export const extractDiscussions = discussions =>
*/
export const extractCurrentDiscussion = (discussions, id) =>
- discussions.nodes.find(discussion => discussion.id === id);
+ discussions.nodes.find((discussion) => discussion.id === id);
-export const findVersionId = id => (id.match('::Version/(.+$)') || [])[1];
+export const findVersionId = (id) => (id.match('::Version/(.+$)') || [])[1];
-export const findNoteId = id => (id.match('DiffNote/(.+$)') || [])[1];
+export const findNoteId = (id) => (id.match('DiffNote/(.+$)') || [])[1];
-export const findIssueId = id => (id.match('Issue/(.+$)') || [])[1];
+export const findIssueId = (id) => (id.match('Issue/(.+$)') || [])[1];
-export const findDesignId = id => (id.match('Design/(.+$)') || [])[1];
+export const findDesignId = (id) => (id.match('Design/(.+$)') || [])[1];
-export const extractDesigns = data => data.project.issue.designCollection.designs.nodes;
+export const extractDesigns = (data) => data.project.issue.designCollection.designs.nodes;
-export const extractDesign = data => (extractDesigns(data) || [])[0];
+export const extractDesign = (data) => (extractDesigns(data) || [])[0];
-export const toDiffNoteGid = noteId => `gid://gitlab/DiffNote/${noteId}`;
+export const toDiffNoteGid = (noteId) => `gid://gitlab/DiffNote/${noteId}`;
/**
* Return the note ID from a URL hash parameter
* @param {String} urlHash URL hash, including `#` prefix
*/
-export const extractDesignNoteId = urlHash => {
+export const extractDesignNoteId = (urlHash) => {
const [, noteId] = urlHash.match('#note_([0-9]+$)') || [];
return noteId || null;
};
@@ -53,8 +53,8 @@ export const extractDesignNoteId = urlHash => {
* Generates optimistic response for a design upload mutation
* @param {Array<File>} files
*/
-export const designUploadOptimisticResponse = files => {
- const designs = files.map(file => ({
+export const designUploadOptimisticResponse = (files) => {
+ const designs = files.map((file) => ({
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'Design',
@@ -128,7 +128,7 @@ export const repositionImageDiffNoteOptimisticResponse = (note, { position }) =>
* Generates optimistic response for a design upload mutation
* @param {Array} designs
*/
-export const moveDesignOptimisticResponse = designs => ({
+export const moveDesignOptimisticResponse = (designs) => ({
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'Mutation',
@@ -145,13 +145,13 @@ export const moveDesignOptimisticResponse = designs => ({
},
});
-const normalizeAuthor = author => ({
+const normalizeAuthor = (author) => ({
...author,
web_url: author.webUrl,
avatar_url: author.avatarUrl,
});
-export const extractParticipants = users => users.map(node => normalizeAuthor(node));
+export const extractParticipants = (users) => users.map((node) => normalizeAuthor(node));
export const getPageLayoutElement = () => document.querySelector('.layout-page');
@@ -160,14 +160,14 @@ export const getPageLayoutElement = () => document.querySelector('.layout-page')
* Example of todoDeletePath: /delete/1234
* @param {String} todoDeletePath delete_path from REST API response
*/
-export const extractTodoIdFromDeletePath = todoDeletePath =>
+export const extractTodoIdFromDeletePath = (todoDeletePath) =>
(todoDeletePath.match('todos/([0-9]+$)') || [])[1];
-const createTodoGid = todoId => {
+const createTodoGid = (todoId) => {
return `gid://gitlab/Todo/${todoId}`;
};
-export const createPendingTodo = todoId => {
+export const createPendingTodo = (todoId) => {
return {
__typename: 'Todo', // eslint-disable-line @gitlab/require-i18n-strings
id: createTodoGid(todoId),
diff --git a/app/assets/javascripts/design_management/utils/error_messages.js b/app/assets/javascripts/design_management/utils/error_messages.js
index bd21d711462..cb4bb6e26a8 100644
--- a/app/assets/javascripts/design_management/utils/error_messages.js
+++ b/app/assets/javascripts/design_management/utils/error_messages.js
@@ -54,7 +54,7 @@ export const TOGGLE_TODO_ERROR = __('Failed to toggle To-Do for the design.');
const MAX_SKIPPED_FILES_LISTINGS = 5;
-const oneDesignSkippedMessage = filename =>
+const oneDesignSkippedMessage = (filename) =>
`${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${sprintf(s__('DesignManagement|%{filename} did not change.'), {
filename,
})}`;
@@ -64,7 +64,7 @@ const oneDesignSkippedMessage = filename =>
* files were skipped.
* @param {Array<{ filename }>} skippedFiles
*/
-const someDesignsSkippedMessage = skippedFiles => {
+const someDesignsSkippedMessage = (skippedFiles) => {
const designsSkippedMessage = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
'Some of the designs you tried uploading did not change:',
)}`;
diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js
index 9497ea7bb4f..c4e86638e9d 100644
--- a/app/assets/javascripts/diff.js
+++ b/app/assets/javascripts/diff.js
@@ -24,9 +24,7 @@ export default class Diff {
if (!tab || (tab && tab.dataset && tab.dataset.isLocked !== ''))
FilesCommentButton.init($diffFile);
- const firstFile = $('.files')
- .first()
- .get(0);
+ const firstFile = $('.files').first().get(0);
const canCreateNote = firstFile && firstFile.hasAttribute('data-can-create-note');
$diffFile.each((index, file) => initImageDiffHelper.initImageDiff(file, canCreateNote));
@@ -119,7 +117,7 @@ export default class Diff {
table.removeClass('left-side-selected right-side-selected');
- const lineClass = ['left-side', 'right-side'].filter(name => line.hasClass(name))[0];
+ const lineClass = ['left-side', 'right-side'].filter((name) => line.hasClass(name))[0];
if (lineClass) {
table.addClass(`${lineClass}-selected`);
}
@@ -134,7 +132,7 @@ export default class Diff {
if (children.length !== 2) {
return [0, 0];
}
- return children.map(elm => parseInt($(elm).data('linenumber'), 10) || 0);
+ return children.map((elm) => parseInt($(elm).data('linenumber'), 10) || 0);
}
// eslint-disable-next-line class-methods-use-this
highlightSelectedLine() {
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 7827c78b658..32822fe1fe8 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -124,6 +124,16 @@ export default {
required: false,
default: false,
},
+ defaultSuggestionCommitMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ mrReviews: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
data() {
const treeWidth =
@@ -136,19 +146,17 @@ export default {
},
computed: {
...mapState({
- isLoading: state => state.diffs.isLoading,
- isBatchLoading: state => state.diffs.isBatchLoading,
- diffFiles: state => state.diffs.diffFiles,
- diffViewType: state => state.diffs.diffViewType,
- mergeRequestDiffs: state => state.diffs.mergeRequestDiffs,
- mergeRequestDiff: state => state.diffs.mergeRequestDiff,
- commit: state => state.diffs.commit,
- renderOverflowWarning: state => state.diffs.renderOverflowWarning,
- numTotalFiles: state => state.diffs.realSize,
- numVisibleFiles: state => state.diffs.size,
- plainDiffPath: state => state.diffs.plainDiffPath,
- emailPatchPath: state => state.diffs.emailPatchPath,
- retrievingBatches: state => state.diffs.retrievingBatches,
+ isLoading: (state) => state.diffs.isLoading,
+ isBatchLoading: (state) => state.diffs.isBatchLoading,
+ diffFiles: (state) => state.diffs.diffFiles,
+ diffViewType: (state) => state.diffs.diffViewType,
+ commit: (state) => state.diffs.commit,
+ renderOverflowWarning: (state) => state.diffs.renderOverflowWarning,
+ numTotalFiles: (state) => state.diffs.realSize,
+ numVisibleFiles: (state) => state.diffs.size,
+ plainDiffPath: (state) => state.diffs.plainDiffPath,
+ emailPatchPath: (state) => state.diffs.emailPatchPath,
+ retrievingBatches: (state) => state.diffs.retrievingBatches,
}),
...mapState('diffs', [
'showTreeList',
@@ -161,7 +169,12 @@ export default {
'hasConflicts',
'viewDiffsFileByFile',
]),
- ...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']),
+ ...mapGetters('diffs', [
+ 'whichCollapsedTypes',
+ 'isParallelView',
+ 'currentDiffIndex',
+ 'fileReviews',
+ ]),
...mapGetters(['isNotesFetched', 'getNoteableData']),
diffs() {
if (!this.viewDiffsFileByFile) {
@@ -176,17 +189,16 @@ export default {
return this.currentUser.can_fork === true && this.currentUser.can_create_merge_request;
},
renderDiffFiles() {
- return (
- this.diffFiles.length > 0 ||
- (this.startVersion &&
- this.startVersion.version_index === this.mergeRequestDiff.version_index)
- );
+ return this.diffFiles.length > 0;
+ },
+ renderFileTree() {
+ return this.renderDiffFiles && this.showTreeList;
},
hideFileStats() {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
isLimitedContainer() {
- return !this.showTreeList && !this.isParallelView && !this.isFluidLayout;
+ return !this.renderFileTree && !this.isParallelView && !this.isFluidLayout;
},
isDiffHead() {
return parseBoolean(getParameterByName('diff_head'));
@@ -249,7 +261,7 @@ export default {
this.adjustView();
},
isLoading: 'adjustView',
- showTreeList: 'adjustView',
+ renderFileTree: 'adjustView',
},
mounted() {
this.setBaseConfig({
@@ -261,6 +273,8 @@ export default {
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
viewDiffsFileByFile: fileByFile(this.fileByFileUserPreference),
+ defaultSuggestionCommitMessage: this.defaultSuggestionCommitMessage,
+ mrReviews: this.mrReviews || {},
});
if (this.shouldShow) {
@@ -270,12 +284,7 @@ export default {
const id = window?.location?.hash;
if (id && id.indexOf('#note') !== 0) {
- this.setHighlightedRow(
- id
- .split('diff-content')
- .pop()
- .slice(1),
- );
+ this.setHighlightedRow(id.split('diff-content').pop().slice(1));
}
},
beforeCreate() {
@@ -393,10 +402,7 @@ export default {
},
setDiscussions() {
requestIdleCallback(
- () =>
- this.assignDiscussionsToDiff()
- .then(this.$nextTick)
- .then(this.startTaskList),
+ () => this.assignDiscussionsToDiff().then(this.$nextTick).then(this.startTaskList),
{ timeout: 1000 },
);
},
@@ -425,7 +431,7 @@ export default {
}
});
- if (this.commit && this.glFeatures.mrCommitNeighborNav) {
+ if (this.commit) {
Mousetrap.bind('c', () => this.moveToNeighboringCommit({ direction: 'next' }));
Mousetrap.bind('x', () => this.moveToNeighboringCommit({ direction: 'previous' }));
}
@@ -464,7 +470,6 @@ export default {
<div v-if="isLoading || !isTreeLoaded" class="loading"><gl-loading-icon size="lg" /></div>
<div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane">
<compare-versions
- :merge-request-diffs="mergeRequestDiffs"
:is-limited-container="isLimitedContainer"
:diff-files-count-text="numTotalFiles"
/>
@@ -492,7 +497,7 @@ export default {
class="files d-flex gl-mt-2"
>
<div
- v-if="showTreeList"
+ v-if="renderFileTree"
:style="{ width: `${treeWidth}px` }"
class="diff-tree-list js-diff-tree-list px-3 pr-md-0"
>
@@ -519,6 +524,7 @@ export default {
v-for="(file, index) in diffs"
:key="file.newPath"
:file="file"
+ :reviewed="fileReviews[index]"
:is-first-file="index === 0"
:is-last-file="index === diffs.length - 1"
:help-page-path="helpPagePath"
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index a548354f257..af19f90ee77 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -6,7 +6,7 @@ import { GlButtonGroup, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
@@ -39,7 +39,7 @@ import { setUrlParams } from '../../lib/utils/url_utility';
export default {
components: {
UserAvatarLink,
- ClipboardButton,
+ ModalCopyButton,
TimeAgoTooltip,
CommitPipelineStatus,
GlButtonGroup,
@@ -142,16 +142,13 @@ export default {
data-testid="commit-sha-short-id"
v-text="commit.short_id"
/>
- <clipboard-button
+ <modal-copy-button
:text="commit.id"
:title="__('Copy commit SHA')"
class="input-group-text"
/>
</gl-button-group>
- <div
- v-if="hasNeighborCommits && glFeatures.mrCommitNeighborNav"
- class="commit-nav-buttons ml-3"
- >
+ <div v-if="hasNeighborCommits" class="commit-nav-buttons ml-3">
<gl-button-group>
<gl-button
:href="previousCommitUrl"
diff --git a/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue b/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
index da34a7ee19b..2c249f71091 100644
--- a/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
+++ b/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
@@ -16,7 +16,7 @@ export default {
},
computed: {
selectedVersionName() {
- return this.versions.find(x => x.selected)?.versionName || '';
+ return this.versions.find((x) => x.selected)?.versionName || '';
},
},
};
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index f3cc359a679..489278fd6ef 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -22,10 +22,6 @@ export default {
GlTooltip: GlTooltipDirective,
},
props: {
- mergeRequestDiffs: {
- type: Array,
- required: true,
- },
isLimitedContainer: {
type: Boolean,
required: false,
@@ -44,6 +40,7 @@ export default {
'diffCompareDropdownSourceVersions',
]),
...mapState('diffs', [
+ 'diffFiles',
'commit',
'showTreeList',
'startVersion',
@@ -51,12 +48,15 @@ export default {
'addedLines',
'removedLines',
]),
- showDropdowns() {
- return !this.commit && this.mergeRequestDiffs.length;
- },
toggleFileBrowserTitle() {
return this.showTreeList ? __('Hide file browser') : __('Show file browser');
},
+ hasChanges() {
+ return this.diffFiles.length > 0;
+ },
+ hasSourceVersions() {
+ return this.diffCompareDropdownSourceVersions.length > 0;
+ },
},
created() {
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
@@ -82,6 +82,7 @@ export default {
}"
>
<gl-button
+ v-if="hasChanges"
v-gl-tooltip.hover
variant="default"
icon="file-tree"
@@ -90,8 +91,12 @@ export default {
:selected="showTreeList"
@click="setShowTreeList({ showTreeList: !showTreeList })"
/>
+ <div v-if="commit">
+ {{ __('Viewing commit') }}
+ <gl-link :href="commit.commit_url" class="monospace">{{ commit.short_id }}</gl-link>
+ </div>
<gl-sprintf
- v-if="showDropdowns"
+ v-else-if="hasSourceVersions"
class="d-flex align-items-center compare-versions-container"
:message="s__('MergeRequest|Compare %{target} and %{source}')"
>
@@ -109,11 +114,7 @@ export default {
/>
</template>
</gl-sprintf>
- <div v-else-if="commit">
- {{ __('Viewing commit') }}
- <gl-link :href="commit.commit_url" class="monospace">{{ commit.short_id }}</gl-link>
- </div>
- <div class="inline-parallel-buttons d-none d-md-flex ml-auto">
+ <div v-if="hasChanges" class="inline-parallel-buttons d-none d-md-flex ml-auto">
<diff-stats
:diff-files-count-text="diffFilesCountText"
:added-lines="addedLines"
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index f938ea368d8..f4e2571dd09 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -50,7 +50,7 @@ export default {
},
computed: {
...mapState({
- projectPath: state => state.diffs.projectPath,
+ projectPath: (state) => state.diffs.projectPath,
}),
...mapGetters('diffs', [
'isInlineView',
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 2401e12e4f6..2d1a7237122 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -13,7 +13,7 @@ const EXPAND_DOWN = 2;
const lineNumberByViewType = (viewType, diffLine) => {
const numberGetters = {
- [INLINE_DIFF_VIEW_TYPE]: line => line?.new_line,
+ [INLINE_DIFF_VIEW_TYPE]: (line) => line?.new_line,
};
const numberGetter = numberGetters[viewType];
return numberGetter && numberGetter(diffLine);
@@ -56,7 +56,7 @@ export default {
},
computed: {
...mapState({
- diffFiles: state => state.diffs.diffFiles,
+ diffFiles: (state) => state.diffs.diffFiles,
}),
canExpandUp() {
return !this.isBottom;
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index ed94cabe124..e613b684345 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -37,6 +37,11 @@ export default {
type: Object,
required: true,
},
+ reviewed: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
isFirstFile: {
type: Boolean,
required: false,
@@ -134,7 +139,7 @@ export default {
return !this.isCollapsed || this.automaticallyCollapsed;
},
showWarning() {
- return this.isCollapsed && (this.automaticallyCollapsed && !this.viewDiffsFileByFile);
+ return this.isCollapsed && this.automaticallyCollapsed && !this.viewDiffsFileByFile;
},
showContent() {
return !this.isCollapsed && !this.isFileTooLarge;
@@ -205,7 +210,7 @@ export default {
await this.$nextTick();
- eventsForThisFile.forEach(event => {
+ eventsForThisFile.forEach((event) => {
eventHub.$emit(event);
});
},
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index 439319f487c..f62b31734c5 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -29,7 +29,7 @@ export default {
return this.discussions.reduce((acc, note) => acc.concat(note.notes), []);
},
notesInGutter() {
- return this.allDiscussions.slice(0, COUNT_OF_AVATARS_IN_GUTTER).map(n => ({
+ return this.allDiscussions.slice(0, COUNT_OF_AVATARS_IN_GUTTER).map((n) => ({
note: n.note,
author: n.author,
}));
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 172a2bdde7d..463b7f5cff4 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -56,10 +56,11 @@ export default {
},
computed: {
...mapState({
- noteableData: state => state.notes.noteableData,
- diffViewType: state => state.diffs.diffViewType,
+ diffViewType: ({ diffs }) => diffs.diffViewType,
+ showSuggestPopover: ({ diffs }) => diffs.showSuggestPopover,
+ noteableData: ({ notes }) => notes.noteableData,
+ selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition,
}),
- ...mapState('diffs', ['showSuggestPopover']),
...mapGetters('diffs', ['getDiffFileByHash', 'diffLines']),
...mapGetters([
'isLoggedIn',
@@ -126,6 +127,10 @@ export default {
this.initAutoSave(this.noteableData, keys);
}
+
+ if (this.selectedCommentPosition) {
+ this.commentLineStart = this.selectedCommentPosition.start;
+ }
},
methods: {
...mapActions('diffs', [
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index c0719e2a7d9..db03da966c3 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -1,7 +1,16 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import { CONTEXT_LINE_CLASS_NAME, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
+import {
+ CONTEXT_LINE_CLASS_NAME,
+ PARALLEL_DIFF_VIEW_TYPE,
+ CONFLICT_MARKER_OUR,
+ CONFLICT_MARKER_THEIR,
+ CONFLICT_OUR,
+ 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';
@@ -14,6 +23,7 @@ export default {
GlTooltip: GlTooltipDirective,
SafeHtml,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
fileHash: {
type: String,
@@ -37,6 +47,15 @@ export default {
required: false,
default: false,
},
+ index: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ dragging: false,
+ };
},
computed: {
...mapGetters('diffs', ['fileLineCoverage']),
@@ -44,26 +63,40 @@ export default {
...mapState({
isHighlighted(state) {
const line = this.line.left?.line_code ? this.line.left : this.line.right;
- return utils.isHighlighted(state, line, this.isCommented);
+ return utils.isHighlighted(state, line, false);
},
}),
classNameMap() {
return {
[CONTEXT_LINE_CLASS_NAME]: this.line.isContextLineLeft,
- [PARALLEL_DIFF_VIEW_TYPE]: true,
+ [PARALLEL_DIFF_VIEW_TYPE]: !this.inline,
+ commented: this.isCommented,
};
},
parallelViewLeftLineType() {
- return utils.parallelViewLeftLineType(this.line, this.isHighlighted);
+ return utils.parallelViewLeftLineType(this.line, this.isHighlighted || this.isCommented);
},
- coverageState() {
+ coverageStateLeft() {
+ if (!this.inline || !this.line.left) return {};
+ return this.fileLineCoverage(this.filePath, this.line.left.new_line);
+ },
+ coverageStateRight() {
+ if (!this.line.right) return {};
return this.fileLineCoverage(this.filePath, this.line.right.new_line);
},
classNameMapCellLeft() {
- return utils.classNameMapCell(this.line.left, this.isHighlighted, this.isLoggedIn);
+ return utils.classNameMapCell({
+ line: this.line.left,
+ hll: this.isHighlighted || this.isCommented,
+ isLoggedIn: this.isLoggedIn,
+ });
},
classNameMapCellRight() {
- return utils.classNameMapCell(this.line.right, this.isHighlighted, this.isLoggedIn);
+ return utils.classNameMapCell({
+ line: this.line.right,
+ hll: this.isHighlighted || this.isCommented,
+ isLoggedIn: this.isLoggedIn,
+ });
},
addCommentTooltipLeft() {
return utils.addCommentTooltip(this.line.left);
@@ -71,6 +104,12 @@ export default {
addCommentTooltipRight() {
return utils.addCommentTooltip(this.line.right);
},
+ emptyCellRightClassMap() {
+ return { conflict_their: this.line.left?.type === CONFLICT_OUR };
+ },
+ emptyCellLeftClassMap() {
+ return { conflict_our: this.line.right?.type === CONFLICT_THEIR };
+ },
shouldRenderCommentButton() {
return (
this.isLoggedIn &&
@@ -80,6 +119,9 @@ export default {
!this.line.hasDiscussionsRight
);
},
+ isLeftConflictMarker() {
+ return [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(this.line.left?.type);
+ },
},
mounted() {
this.scrollToLineIfNeededParallel(this.line);
@@ -98,7 +140,9 @@ export default {
const table = line.closest('.diff-table');
table.classList.remove('left-side-selected', 'right-side-selected');
- const [lineClass] = ['left-side', 'right-side'].filter(name => line.classList.contains(name));
+ const [lineClass] = ['left-side', 'right-side'].filter((name) =>
+ line.classList.contains(name),
+ );
if (lineClass) {
table.classList.add(`${lineClass}-selected`);
@@ -107,37 +151,75 @@ export default {
handleCommentButton(line) {
this.showCommentForm({ lineCode: line.line_code, fileHash: this.fileHash });
},
+ conflictText(line) {
+ return line.type === CONFLICT_MARKER_THEIR
+ ? this.$options.THEIR_CHANGES
+ : this.$options.OUR_CHANGES;
+ },
+ onDragEnd() {
+ this.dragging = false;
+ if (!this.glFeatures.dragCommentSelection) return;
+
+ this.$emit('stopdragging');
+ },
+ onDragEnter(line, index) {
+ if (!this.glFeatures.dragCommentSelection) return;
+
+ this.$emit('enterdragging', { ...line, index });
+ },
+ onDragStart(line) {
+ this.$root.$emit('bv::hide::tooltip');
+ this.dragging = true;
+ this.$emit('startdragging', line);
+ },
},
+ OUR_CHANGES: 'HEAD//our changes',
+ THEIR_CHANGES: 'origin//their changes',
+ CONFLICT_MARKER,
+ CONFLICT_MARKER_THEIR,
+ CONFLICT_OUR,
+ CONFLICT_THEIR,
};
</script>
<template>
<div :class="classNameMap" class="diff-grid-row diff-tr line_holder">
- <div class="diff-grid-left left-side">
- <template v-if="line.left">
+ <div
+ data-testid="left-side"
+ class="diff-grid-left left-side"
+ @dragover.prevent
+ @dragenter="onDragEnter(line.left, index)"
+ @dragend="onDragEnd"
+ >
+ <template v-if="line.left && line.left.type !== $options.CONFLICT_MARKER">
<div
:class="classNameMapCellLeft"
data-testid="leftLineNumber"
- class="diff-td diff-line-num old_line"
+ class="diff-td diff-line-num"
>
- <span
- v-if="shouldRenderCommentButton"
- v-gl-tooltip
- data-testid="leftCommentButton"
- class="add-diff-note tooltip-wrapper"
- :title="addCommentTooltipLeft"
- >
- <button
- type="button"
- class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
- :disabled="line.left.commentsDisabled"
- @click="handleCommentButton(line.left)"
+ <template v-if="!isLeftConflictMarker">
+ <span
+ v-if="shouldRenderCommentButton"
+ v-gl-tooltip
+ data-testid="leftCommentButton"
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltipLeft"
>
- <gl-icon :size="12" name="comment" />
- </button>
- </span>
+ <button
+ :draggable="glFeatures.dragCommentSelection"
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :class="{ 'gl-cursor-grab': dragging }"
+ :disabled="line.left.commentsDisabled"
+ @click="handleCommentButton(line.left)"
+ @dragstart="onDragStart({ ...line.left, index })"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ </template>
<a
- v-if="line.left.old_line"
+ v-if="line.left.old_line && line.left.type !== $options.CONFLICT_THEIR"
:data-linenumber="line.left.old_line"
:href="line.lineHrefOld"
@click="setHighlightedRow(line.lineCode)"
@@ -157,52 +239,87 @@ export default {
"
/>
</div>
- <div v-if="inline" :class="classNameMapCellLeft" class="diff-td diff-line-num old_line">
+ <div v-if="inline" :class="classNameMapCellLeft" class="diff-td diff-line-num">
<a
- v-if="line.left.new_line"
+ v-if="line.left.new_line && line.left.type !== $options.CONFLICT_OUR"
:data-linenumber="line.left.new_line"
:href="line.lineHrefOld"
@click="setHighlightedRow(line.lineCode)"
>
</a>
</div>
- <div :class="parallelViewLeftLineType" class="diff-td line-coverage left-side"></div>
+ <div
+ v-gl-tooltip.hover
+ :title="coverageStateLeft.text"
+ :class="[...parallelViewLeftLineType, coverageStateLeft.class]"
+ class="diff-td line-coverage left-side"
+ ></div>
<div
:id="line.left.line_code"
:key="line.left.line_code"
- v-safe-html="line.left.rich_text"
- :class="parallelViewLeftLineType"
- class="diff-td line_content with-coverage parallel left-side"
+ :class="[parallelViewLeftLineType, { parallel: !inline }]"
+ class="diff-td line_content with-coverage left-side"
data-testid="leftContent"
@mousedown="handleParallelLineMouseDown"
- ></div>
+ >
+ <strong v-if="isLeftConflictMarker">{{ conflictText(line.left) }}</strong>
+ <span v-else v-safe-html="line.left.rich_text"></span>
+ </div>
</template>
- <template v-else>
- <div data-testid="leftEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div>
- <div v-if="inline" class="diff-td diff-line-num old_line empty-cell"></div>
- <div class="diff-td line-coverage left-side empty-cell"></div>
- <div class="diff-td line_content with-coverage parallel left-side empty-cell"></div>
+ <template v-else-if="!inline || (line.left && line.left.type === $options.CONFLICT_MARKER)">
+ <div
+ data-testid="leftEmptyCell"
+ class="diff-td diff-line-num old_line empty-cell"
+ :class="emptyCellLeftClassMap"
+ >
+ &nbsp;
+ </div>
+ <div
+ v-if="inline"
+ class="diff-td diff-line-num old_line empty-cell"
+ :class="emptyCellLeftClassMap"
+ ></div>
+ <div
+ class="diff-td line-coverage left-side empty-cell"
+ :class="emptyCellLeftClassMap"
+ ></div>
+ <div
+ class="diff-td line_content with-coverage left-side empty-cell"
+ :class="[emptyCellLeftClassMap, { parallel: !inline }]"
+ ></div>
</template>
</div>
- <div v-if="!inline" class="diff-grid-right right-side">
+ <div
+ v-if="!inline"
+ data-testid="right-side"
+ class="diff-grid-right right-side"
+ @dragover.prevent
+ @dragenter="onDragEnter(line.right, index)"
+ @dragend="onDragEnd"
+ >
<template v-if="line.right">
<div :class="classNameMapCellRight" class="diff-td diff-line-num new_line">
- <span
- v-if="shouldRenderCommentButton"
- v-gl-tooltip
- data-testid="rightCommentButton"
- class="add-diff-note tooltip-wrapper"
- :title="addCommentTooltipRight"
- >
- <button
- type="button"
- class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
- :disabled="line.right.commentsDisabled"
- @click="handleCommentButton(line.right)"
+ <template v-if="line.right.type !== $options.CONFLICT_MARKER_THEIR">
+ <span
+ v-if="shouldRenderCommentButton"
+ v-gl-tooltip
+ data-testid="rightCommentButton"
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltipRight"
>
- <gl-icon :size="12" name="comment" />
- </button>
- </span>
+ <button
+ :draggable="glFeatures.dragCommentSelection"
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :class="{ 'gl-cursor-grab': dragging }"
+ :disabled="line.right.commentsDisabled"
+ @click="handleCommentButton(line.right)"
+ @dragstart="onDragStart({ ...line.right, index })"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ </template>
<a
v-if="line.right.new_line"
:data-linenumber="line.right.new_line"
@@ -226,8 +343,12 @@ export default {
</div>
<div
v-gl-tooltip.hover
- :title="coverageState.text"
- :class="[line.right.type, coverageState.class, { hll: isHighlighted }]"
+ :title="coverageStateRight.text"
+ :class="[
+ line.right.type,
+ coverageStateRight.class,
+ { hll: isHighlighted, hll: isCommented },
+ ]"
class="diff-td line-coverage right-side"
></div>
<div
@@ -238,17 +359,38 @@ export default {
line.right.type,
{
hll: isHighlighted,
+ hll: isCommented,
+ parallel: !inline,
},
]"
- class="diff-td line_content with-coverage parallel right-side"
+ class="diff-td line_content with-coverage right-side"
@mousedown="handleParallelLineMouseDown"
- ></div>
+ >
+ <strong v-if="line.right.type === $options.CONFLICT_MARKER_THEIR">{{
+ conflictText(line.right)
+ }}</strong>
+ <span v-else v-safe-html="line.right.rich_text"></span>
+ </div>
</template>
<template v-else>
- <div data-testid="rightEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div>
- <div class="diff-td diff-line-num old_line empty-cell"></div>
- <div class="diff-td line-coverage right-side empty-cell"></div>
- <div class="diff-td line_content with-coverage parallel right-side empty-cell"></div>
+ <div
+ data-testid="rightEmptyCell"
+ class="diff-td diff-line-num old_line empty-cell"
+ :class="emptyCellRightClassMap"
+ ></div>
+ <div
+ v-if="inline"
+ class="diff-td diff-line-num old_line empty-cell"
+ :class="emptyCellRightClassMap"
+ ></div>
+ <div
+ class="diff-td line-coverage right-side empty-cell"
+ :class="emptyCellRightClassMap"
+ ></div>
+ <div
+ class="diff-td line_content with-coverage right-side empty-cell"
+ :class="[emptyCellRightClassMap, { parallel: !inline }]"
+ ></div>
</template>
</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js
index d5491d3cd56..7606c39ad37 100644
--- a/app/assets/javascripts/diffs/components/diff_row_utils.js
+++ b/app/assets/javascripts/diffs/components/diff_row_utils.js
@@ -15,27 +15,27 @@ export const isHighlighted = (state, line, isCommented) => {
return lineCode ? lineCode === state.diffs.highlightedRow : false;
};
-export const isContextLine = type => type === CONTEXT_LINE_TYPE;
+export const isContextLine = (type) => type === CONTEXT_LINE_TYPE;
-export const isMatchLine = type => type === MATCH_LINE_TYPE;
+export const isMatchLine = (type) => type === MATCH_LINE_TYPE;
-export const isMetaLine = type =>
+export const isMetaLine = (type) =>
[OLD_NO_NEW_LINE_TYPE, NEW_NO_NEW_LINE_TYPE, EMPTY_CELL_TYPE].includes(type);
export const shouldRenderCommentButton = (isLoggedIn, isCommentButtonRendered) => {
return isCommentButtonRendered && isLoggedIn;
};
-export const hasDiscussions = line => line?.discussions?.length > 0;
+export const hasDiscussions = (line) => line?.discussions?.length > 0;
-export const lineHref = line => `#${line?.line_code || ''}`;
+export const lineHref = (line) => `#${line?.line_code || ''}`;
-export const lineCode = line => {
+export const lineCode = (line) => {
if (!line) return undefined;
return line.line_code || line.left?.line_code || line.right?.line_code;
};
-export const classNameMapCell = (line, hll, isLoggedIn, isHover) => {
+export const classNameMapCell = ({ line, hll, isLoggedIn, isHover }) => {
if (!line) return [];
const { type } = line;
@@ -44,15 +44,19 @@ export const classNameMapCell = (line, hll, isLoggedIn, isHover) => {
{
hll,
[LINE_HOVER_CLASS_NAME]: isLoggedIn && isHover && !isContextLine(type) && !isMetaLine(type),
+ old_line: line.type === 'old',
+ new_line: line.type === 'new',
},
];
};
-export const addCommentTooltip = line => {
+export const addCommentTooltip = (line) => {
let tooltip;
if (!line) return tooltip;
- tooltip = __('Add a comment to this line');
+ tooltip = gon.drag_comment_selection
+ ? __('Add a comment to this line or drag for multiple lines')
+ : __('Add a comment to this line');
const brokenSymlinks = line.commentsDisabled;
if (brokenSymlinks) {
@@ -84,7 +88,7 @@ export const shouldShowCommentButton = (hover, context, meta, discussions) => {
return hover && !context && !meta && !discussions;
};
-export const mapParallel = content => line => {
+export const mapParallel = (content) => (line) => {
let { left, right } = line;
// Dicussions/Comments
@@ -137,7 +141,7 @@ export const mapParallel = content => line => {
};
// TODO: Delete this function when unifiedDiffComponents FF is removed
-export const mapInline = content => line => {
+export const mapInline = (content) => (line) => {
// Discussions/Comments
const renderCommentRow = line.hasForm || (line.discussions?.length && line.discussionsExpanded);
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 84429f62a1c..79800f835f4 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -1,5 +1,5 @@
<script>
-import { mapGetters, mapState } from 'vuex';
+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';
@@ -35,6 +35,12 @@ export default {
default: false,
},
},
+ data() {
+ return {
+ dragStart: null,
+ updatedLineRange: null,
+ };
+ },
computed: {
...mapGetters('diffs', ['commitId']),
...mapState({
@@ -52,12 +58,39 @@ export default {
},
},
methods: {
+ ...mapActions(['setSelectedCommentPosition']),
+ ...mapActions('diffs', ['showCommentForm']),
showCommentLeft(line) {
return !this.inline || line.left;
},
showCommentRight(line) {
return !this.inline || (line.right && !line.left);
},
+ onStartDragging(line) {
+ this.dragStart = line;
+ },
+ onDragOver(line) {
+ if (line.chunk !== this.dragStart.chunk) return;
+
+ let start = this.dragStart;
+ let end = line;
+
+ if (this.dragStart.index >= line.index) {
+ start = line;
+ end = this.dragStart;
+ }
+
+ this.updatedLineRange = { start, end };
+
+ this.setSelectedCommentPosition(this.updatedLineRange);
+ },
+ onStopDragging() {
+ this.showCommentForm({
+ lineCode: this.updatedLineRange?.end?.line_code,
+ fileHash: this.diffFile.file_hash,
+ });
+ this.dragStart = null;
+ },
},
userColorScheme: window.gon.user_color_scheme,
};
@@ -94,6 +127,10 @@ export default {
:is-bottom="index + 1 === diffLinesLength"
:is-commented="index >= commentedLines.startLine && index <= commentedLines.endLine"
:inline="inline"
+ :index="index"
+ @enterdragging="onDragOver"
+ @startdragging="onStartDragging"
+ @stopdragging="onStopDragging"
/>
<div
v-if="line.renderCommentRow"
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 2d8ffb047ca..014b1ebe54b 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -72,7 +72,12 @@ export default {
return this.fileLineCoverage(this.filePath, this.line.new_line);
},
classNameMapCell() {
- return classNameMapCell(this.line, this.isHighlighted, this.isLoggedIn, this.isHover);
+ return classNameMapCell({
+ line: this.line,
+ hll: this.isHighlighted,
+ isLoggedIn: this.isLoggedIn,
+ isHover: this.isHover,
+ });
},
addCommentTooltip() {
return addCommentTooltip(this.line);
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index 05f5461054f..28485a2fdac 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -58,9 +58,9 @@ export default {
class="code diff-wrap-lines js-syntax-highlight text-file js-diff-inline-view"
>
<colgroup>
- <col style="width: 50px;" />
- <col style="width: 50px;" />
- <col style="width: 8px;" />
+ <col style="width: 50px" />
+ <col style="width: 50px" />
+ <col style="width: 8px" />
<col />
</colgroup>
<tbody>
diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue
index a640dcb0a90..e0fdbf6ac3a 100644
--- a/app/assets/javascripts/diffs/components/no_changes.vue
+++ b/app/assets/javascripts/diffs/components/no_changes.vue
@@ -14,7 +14,31 @@ export default {
},
},
computed: {
+ ...mapGetters('diffs', [
+ 'diffCompareDropdownTargetVersions',
+ 'diffCompareDropdownSourceVersions',
+ ]),
...mapGetters(['getNoteableData']),
+ selectedSourceVersion() {
+ return this.diffCompareDropdownSourceVersions.find((x) => x.selected);
+ },
+ sourceName() {
+ if (!this.selectedSourceVersion || this.selectedSourceVersion.isLatestVersion) {
+ return this.getNoteableData.source_branch;
+ }
+
+ return this.selectedSourceVersion.versionName;
+ },
+ selectedTargetVersion() {
+ return this.diffCompareDropdownTargetVersions.find((x) => x.selected);
+ },
+ targetName() {
+ if (!this.selectedTargetVersion || this.selectedTargetVersion.version_index < 0) {
+ return this.getNoteableData.target_branch;
+ }
+
+ return this.selectedTargetVersion.versionName || '';
+ },
},
};
</script>
@@ -26,14 +50,16 @@ export default {
</div>
<div class="col-12">
<div class="text-content text-center">
- <gl-sprintf :message="__('No changes between %{sourceBranch} and %{targetBranch}')">
- <template #sourceBranch>
- <span class="ref-name">{{ getNoteableData.source_branch }}</span>
- </template>
- <template #targetBranch>
- <span class="ref-name">{{ getNoteableData.target_branch }}</span>
- </template>
- </gl-sprintf>
+ <div data-testid="no-changes-message">
+ <gl-sprintf :message="__('No changes between %{source} and %{target}')">
+ <template #source>
+ <span class="ref-name">{{ sourceName }}</span>
+ </template>
+ <template #target>
+ <span class="ref-name">{{ targetName }}</span>
+ </template>
+ </gl-sprintf>
+ </div>
<div class="text-center">
<gl-button :href="getNoteableData.new_blob_path" variant="success" category="primary">{{
__('Create commit')
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 13cd0651ff2..47eecef2385 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -68,20 +68,20 @@ export default {
return this.fileLineCoverage(this.filePath, this.line.right.new_line);
},
classNameMapCellLeft() {
- return utils.classNameMapCell(
- this.line.left,
- this.isHighlighted,
- this.isLoggedIn,
- this.isLeftHover,
- );
+ return utils.classNameMapCell({
+ line: this.line.left,
+ hll: this.isHighlighted,
+ isLoggedIn: this.isLoggedIn,
+ isHover: this.isLeftHover,
+ });
},
classNameMapCellRight() {
- return utils.classNameMapCell(
- this.line.right,
- this.isHighlighted,
- this.isLoggedIn,
- this.isRightHover,
- );
+ return utils.classNameMapCell({
+ line: this.line.right,
+ hll: this.isHighlighted,
+ isLoggedIn: this.isLoggedIn,
+ isHover: this.isRightHover,
+ });
},
addCommentTooltipLeft() {
return utils.addCommentTooltip(this.line.left);
@@ -112,8 +112,8 @@ export default {
mounted() {
this.scrollToLineIfNeededParallel(this.line);
this.unwatchShouldShowCommentButton = this.$watch(
- vm => [vm.shouldShowCommentButtonLeft, vm.shouldShowCommentButtonRight].join(),
- newVal => {
+ (vm) => [vm.shouldShowCommentButtonLeft, vm.shouldShowCommentButtonRight].join(),
+ (newVal) => {
if (newVal) {
this.isCommentButtonRendered = true;
this.unwatchShouldShowCommentButton();
@@ -150,7 +150,7 @@ export default {
const table = line.closest('table');
table.removeClass('left-side-selected right-side-selected');
- const [lineClass] = ['left-side', 'right-side'].filter(name => line.hasClass(name));
+ const [lineClass] = ['left-side', 'right-side'].filter((name) => line.hasClass(name));
if (lineClass) {
table.addClass(`${lineClass}-selected`);
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index 67b599fe163..21e0bf18dbf 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -57,11 +57,11 @@ export default {
class="code diff-wrap-lines js-syntax-highlight text-file"
>
<colgroup>
- <col style="width: 50px;" />
- <col style="width: 8px;" />
+ <col style="width: 50px" />
+ <col style="width: 8px" />
<col />
- <col style="width: 50px;" />
- <col style="width: 8px;" />
+ <col style="width: 50px" />
+ <col style="width: 8px" />
<col />
</colgroup>
<tbody>
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index d03d450b12d..1a258695fa0 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -35,7 +35,7 @@ export default {
}
return this.allBlobs.reduce((acc, folder) => {
- const tree = folder.tree.filter(f => f.path.toLowerCase().indexOf(search) >= 0);
+ const tree = folder.tree.filter((f) => f.path.toLowerCase().indexOf(search) >= 0);
if (tree.length) {
return acc.concat({
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 07e27bd8e47..7080348ee7d 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -109,3 +109,9 @@ export const EVT_PERF_MARK_FILE_TREE_END = 'mr:diffs:perf:fileTreeEnd';
export const EVT_PERF_MARK_DIFF_FILES_START = 'mr:diffs:perf:filesStart';
export const EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN = 'mr:diffs:perf:firstFileShown';
export const EVT_PERF_MARK_DIFF_FILES_END = 'mr:diffs:perf:filesEnd';
+
+export const CONFLICT_OUR = 'conflict_our';
+export const CONFLICT_THEIR = 'conflict_their';
+export const CONFLICT_MARKER = 'conflict_marker';
+export const CONFLICT_MARKER_OUR = 'conflict_marker_our';
+export const CONFLICT_MARKER_THEIR = 'conflict_marker_their';
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 587220488be..4e0720c645a 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -5,6 +5,10 @@ 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';
export default function initDiffsApp(store) {
@@ -79,11 +83,12 @@ export default function initDiffsApp(store) {
showSuggestPopover: parseBoolean(dataset.showSuggestPopover),
showWhitespaceDefault: parseBoolean(dataset.showWhitespaceDefault),
viewDiffsFileByFile: parseBoolean(dataset.fileByFileDefault),
+ defaultSuggestionCommitMessage: dataset.defaultSuggestionCommitMessage,
};
},
computed: {
...mapState({
- activeTab: state => state.page.activeTab,
+ activeTab: (state) => state.page.activeTab,
}),
},
created() {
@@ -102,6 +107,8 @@ export default function initDiffsApp(store) {
...mapActions('diffs', ['setRenderTreeList', 'setShowWhitespace']),
},
render(createElement) {
+ const { mrPath } = getDerivedMergeRequestInformation({ endpoint: this.endpoint });
+
return createElement('diffs-app', {
props: {
endpoint: this.endpoint,
@@ -117,6 +124,8 @@ export default function initDiffsApp(store) {
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
fileByFileUserPreference: this.viewDiffsFileByFile,
+ defaultSuggestionCommitMessage: this.defaultSuggestionCommitMessage,
+ mrReviews: getReviewsForMergeRequest(mrPath),
},
});
},
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 5b410051705..e95e9ac3ee4 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -50,6 +50,8 @@ import {
} from '../constants';
import { diffViewerModes } from '~/ide/constants';
import { isCollapsed } from '../utils/diff_file';
+import { getDerivedMergeRequestInformation } from '../utils/merge_request';
+import { markFileReview, setReviewsForMergeRequest } from '../utils/file_reviews';
export const setBaseConfig = ({ commit }, options) => {
const {
@@ -60,7 +62,9 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ defaultSuggestionCommitMessage,
viewDiffsFileByFile,
+ mrReviews,
} = options;
commit(types.SET_BASE_CONFIG, {
endpoint,
@@ -70,7 +74,9 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ defaultSuggestionCommitMessage,
viewDiffsFileByFile,
+ mrReviews,
});
};
@@ -123,7 +129,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
// We need to check that the currentDiffFileId points to a file that exists
if (
state.currentDiffFileId &&
- !state.diffFiles.some(f => f.file_hash === state.currentDiffFileId) &&
+ !state.diffFiles.some((f) => f.file_hash === state.currentDiffFileId) &&
!isNoteLink
) {
commit(types.VIEW_DIFF_FILE, state.diffFiles[0].file_hash);
@@ -131,11 +137,11 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
if (state.diffFiles?.length) {
// eslint-disable-next-line promise/catch-or-return,promise/no-nesting
- import('~/code_navigation').then(m =>
+ import('~/code_navigation').then((m) =>
m.default({
blobs: state.diffFiles
- .filter(f => f.code_navigation_path)
- .map(f => ({
+ .filter((f) => f.code_navigation_path)
+ .map((f) => ({
path: f.new_path,
codeNavigationPath: f.code_navigation_path,
})),
@@ -157,7 +163,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
return pagination.next_page;
})
- .then(nextPage => nextPage && getBatch(nextPage))
+ .then((nextPage) => nextPage && getBatch(nextPage))
.catch(() => commit(types.SET_RETRIEVING_BATCHES, false));
return getBatch()
@@ -207,7 +213,7 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
export const fetchCoverageFiles = ({ commit, state }) => {
const coveragePoll = new Poll({
resource: {
- getCoverageReports: endpoint => axios.get(endpoint),
+ getCoverageReports: (endpoint) => axios.get(endpoint),
},
data: state.endpointCoverage,
method: 'getCoverageReports',
@@ -242,8 +248,8 @@ export const assignDiscussionsToDiff = (
const hash = getLocationHash();
discussions
- .filter(discussion => discussion.diff_discussion)
- .forEach(discussion => {
+ .filter((discussion) => discussion.diff_discussion)
+ .forEach((discussion) => {
commit(types.SET_LINE_DISCUSSIONS_FOR_FILE, {
discussion,
diffPositionByLineCode,
@@ -270,10 +276,10 @@ export const toggleLineDiscussions = ({ commit }, options) => {
};
export const renderFileForDiscussionId = ({ commit, rootState, state }, discussionId) => {
- const discussion = rootState.notes.discussions.find(d => d.id === discussionId);
+ const discussion = rootState.notes.discussions.find((d) => d.id === discussionId);
if (discussion && discussion.diff_file) {
- const file = state.diffFiles.find(f => f.file_hash === discussion.diff_file.file_hash);
+ const file = state.diffFiles.find((f) => f.file_hash === discussion.diff_file.file_hash);
if (file) {
if (!file.renderIt) {
@@ -299,11 +305,12 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi
export const startRenderDiffsQueue = ({ state, commit }) => {
const checkItem = () =>
- new Promise(resolve => {
+ new Promise((resolve) => {
const nextFile = state.diffFiles.find(
- file =>
+ (file) =>
!file.renderIt &&
- (file.viewer && (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text)),
+ file.viewer &&
+ (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text),
);
if (nextFile) {
@@ -357,7 +364,7 @@ export const loadMoreLines = ({ commit }, options) => {
params.from_merge_request = true;
- return axios.get(endpoint, { params }).then(res => {
+ return axios.get(endpoint, { params }).then((res) => {
const contextLines = res.data || [];
commit(types.ADD_CONTEXT_LINES, {
@@ -398,7 +405,7 @@ export const loadCollapsedDiff = ({ commit, getters, state }, file) =>
w: state.showWhitespace ? '0' : '1',
},
})
- .then(res => {
+ .then((res) => {
commit(types.ADD_COLLAPSED_DIFFS, {
file,
data: res.data,
@@ -421,7 +428,7 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
const shouldCloseAll = getters.diffHasAllExpandedDiscussions(diff);
const shouldExpandAll = getters.diffHasAllCollapsedDiscussions(diff);
- discussions.forEach(discussion => {
+ discussions.forEach((discussion) => {
const data = { discussionId: discussion.id };
if (shouldCloseAll) {
@@ -435,13 +442,13 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
export const toggleFileDiscussionWrappers = ({ commit }, diff) => {
const discussionWrappersExpanded = allDiscussionWrappersExpanded(diff);
const lineCodesWithDiscussions = new Set();
- const lineHasDiscussion = line => Boolean(line?.discussions.length);
- const registerDiscussionLine = line => lineCodesWithDiscussions.add(line.line_code);
+ const lineHasDiscussion = (line) => Boolean(line?.discussions.length);
+ const registerDiscussionLine = (line) => lineCodesWithDiscussions.add(line.line_code);
diff[INLINE_DIFF_LINES_KEY].filter(lineHasDiscussion).forEach(registerDiscussionLine);
if (lineCodesWithDiscussions.size) {
- Array.from(lineCodesWithDiscussions).forEach(lineCode => {
+ Array.from(lineCodesWithDiscussions).forEach((lineCode) => {
commit(types.TOGGLE_LINE_DISCUSSIONS, {
fileHash: diff.file_hash,
expanded: !discussionWrappersExpanded,
@@ -459,8 +466,8 @@ export const saveDiffDiscussion = ({ state, dispatch }, { note, formData }) => {
});
return dispatch('saveNote', postData, { root: true })
- .then(result => dispatch('updateDiscussion', result.discussion, { root: true }))
- .then(discussion => dispatch('assignDiscussionsToDiff', [discussion]))
+ .then((result) => dispatch('updateDiscussion', result.discussion, { root: true }))
+ .then((discussion) => dispatch('assignDiscussionsToDiff', [discussion]))
.then(() => dispatch('updateResolvableDiscussionsCounts', null, { root: true }))
.then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.file_hash))
.catch(() => createFlash(s__('MergeRequests|Saving the comment failed')));
@@ -560,7 +567,7 @@ export const setExpandedDiffLines = ({ commit }, { file, data }) => {
});
commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
- const idleCb = t => {
+ const idleCb = (t) => {
const startIndex = index;
while (
@@ -608,7 +615,7 @@ export const fetchFullDiff = ({ commit, dispatch }, file) =>
.catch(() => dispatch('receiveFullDiffError', file.file_path));
export const toggleFullDiff = ({ dispatch, commit, getters, state }, filePath) => {
- const file = state.diffFiles.find(f => f.file_path === filePath);
+ const file = state.diffFiles.find((f) => f.file_path === filePath);
commit(types.REQUEST_FULL_DIFF, filePath);
@@ -719,7 +726,7 @@ export const setCurrentDiffFileIdFromNote = ({ commit, state, rootGetters }, not
const fileHash = rootGetters.getDiscussion(note.discussion_id).diff_file?.file_hash;
- if (fileHash && state.diffFiles.some(f => f.file_hash === fileHash)) {
+ if (fileHash && state.diffFiles.some((f) => f.file_hash === fileHash)) {
commit(types.VIEW_DIFF_FILE, fileHash);
}
};
@@ -741,3 +748,13 @@ export const setFileByFile = ({ commit }, { fileByFile }) => {
mergeUrlParams({ [DIFF_FILE_BY_FILE_COOKIE_NAME]: fileViewMode }, window.location.href),
);
};
+
+export function reviewFile({ commit, state, getters }, { file, reviewed = true }) {
+ const { mrPath } = getDerivedMergeRequestInformation({ endpoint: file.load_collapsed_diff_url });
+ const reviews = setReviewsForMergeRequest(
+ mrPath,
+ markFileReview(getters.fileReviews(state), file, reviewed),
+ );
+
+ 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 baf54188932..a167b6d4694 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,5 +1,6 @@
import { __, n__ } from '~/locale';
import { parallelizeDiffLines } from './utils';
+import { isFileReviewed } from '../utils/file_reviews';
import {
PARALLEL_DIFF_VIEW_TYPE,
INLINE_DIFF_VIEW_TYPE,
@@ -8,13 +9,13 @@ import {
export * from './getters_versions_dropdowns';
-export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW_TYPE;
+export const isParallelView = (state) => state.diffViewType === PARALLEL_DIFF_VIEW_TYPE;
-export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE;
+export const isInlineView = (state) => state.diffViewType === INLINE_DIFF_VIEW_TYPE;
-export const whichCollapsedTypes = state => {
- const automatic = state.diffFiles.some(file => file.viewer?.automaticallyCollapsed);
- const manual = state.diffFiles.some(file => file.viewer?.manuallyCollapsed);
+export const whichCollapsedTypes = (state) => {
+ const automatic = state.diffFiles.some((file) => file.viewer?.automaticallyCollapsed);
+ const manual = state.diffFiles.some((file) => file.viewer?.manuallyCollapsed);
return {
any: automatic || manual,
@@ -23,18 +24,18 @@ export const whichCollapsedTypes = state => {
};
};
-export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null);
+export const commitId = (state) => (state.commit && state.commit.id ? state.commit.id : null);
/**
* Checks if the diff has all discussions expanded
* @param {Object} diff
* @returns {Boolean}
*/
-export const diffHasAllExpandedDiscussions = (state, getters) => diff => {
+export const diffHasAllExpandedDiscussions = (state, getters) => (diff) => {
const discussions = getters.getDiffFileDiscussions(diff);
return (
- (discussions && discussions.length && discussions.every(discussion => discussion.expanded)) ||
+ (discussions && discussions.length && discussions.every((discussion) => discussion.expanded)) ||
false
);
};
@@ -44,11 +45,13 @@ export const diffHasAllExpandedDiscussions = (state, getters) => diff => {
* @param {Object} diff
* @returns {Boolean}
*/
-export const diffHasAllCollapsedDiscussions = (state, getters) => diff => {
+export const diffHasAllCollapsedDiscussions = (state, getters) => (diff) => {
const discussions = getters.getDiffFileDiscussions(diff);
return (
- (discussions && discussions.length && discussions.every(discussion => !discussion.expanded)) ||
+ (discussions &&
+ discussions.length &&
+ discussions.every((discussion) => !discussion.expanded)) ||
false
);
};
@@ -58,9 +61,9 @@ export const diffHasAllCollapsedDiscussions = (state, getters) => diff => {
* @param {Object} diff
* @returns {Boolean}
*/
-export const diffHasExpandedDiscussions = () => diff => {
- return diff[INLINE_DIFF_LINES_KEY].filter(l => l.discussions.length >= 1).some(
- l => l.discussionsExpanded,
+export const diffHasExpandedDiscussions = () => (diff) => {
+ return diff[INLINE_DIFF_LINES_KEY].filter((l) => l.discussions.length >= 1).some(
+ (l) => l.discussionsExpanded,
);
};
@@ -69,8 +72,8 @@ export const diffHasExpandedDiscussions = () => diff => {
* @param {Boolean} diff
* @returns {Boolean}
*/
-export const diffHasDiscussions = () => diff => {
- return diff[INLINE_DIFF_LINES_KEY].some(l => l.discussions.length >= 1);
+export const diffHasDiscussions = () => (diff) => {
+ return diff[INLINE_DIFF_LINES_KEY].some((l) => l.discussions.length >= 1);
};
/**
@@ -78,22 +81,22 @@ export const diffHasDiscussions = () => diff => {
* @param {Object} diff
* @returns {Array}
*/
-export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) => diff =>
+export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) => (diff) =>
rootGetters.discussions.filter(
- discussion => discussion.diff_discussion && discussion.diff_file.file_hash === diff.file_hash,
+ (discussion) => discussion.diff_discussion && discussion.diff_file.file_hash === diff.file_hash,
) || [];
-export const getDiffFileByHash = state => fileHash =>
- state.diffFiles.find(file => file.file_hash === fileHash);
+export const getDiffFileByHash = (state) => (fileHash) =>
+ state.diffFiles.find((file) => file.file_hash === fileHash);
-export const flatBlobsList = state =>
- Object.values(state.treeEntries).filter(f => f.type === 'blob');
+export const flatBlobsList = (state) =>
+ Object.values(state.treeEntries).filter((f) => f.type === 'blob');
export const allBlobs = (state, getters) =>
getters.flatBlobsList.reduce((acc, file) => {
const { parentPath } = file;
- if (parentPath && !acc.some(f => f.path === parentPath)) {
+ if (parentPath && !acc.some((f) => f.path === parentPath)) {
acc.push({
path: parentPath,
isHeader: true,
@@ -101,13 +104,13 @@ export const allBlobs = (state, getters) =>
});
}
- acc.find(f => f.path === parentPath).tree.push(file);
+ acc.find((f) => f.path === parentPath).tree.push(file);
return acc;
}, []);
-export const getCommentFormForDiffFile = state => fileHash =>
- state.commentForms.find(form => form.fileHash === fileHash);
+export const getCommentFormForDiffFile = (state) => (fileHash) =>
+ state.commentForms.find((form) => form.fileHash === fileHash);
/**
* Returns the test coverage hits for a specific line of a given file
@@ -115,7 +118,7 @@ export const getCommentFormForDiffFile = state => fileHash =>
* @param {number} line
* @returns {number}
*/
-export const fileLineCoverage = state => (file, line) => {
+export const fileLineCoverage = (state) => (file, line) => {
if (!state.coverageFiles.files) return {};
const fileCoverage = state.coverageFiles.files[file];
if (!fileCoverage) return {};
@@ -136,10 +139,13 @@ export const fileLineCoverage = state => (file, line) => {
* Returns index of a currently selected diff in diffFiles
* @returns {number}
*/
-export const currentDiffIndex = state =>
- Math.max(0, state.diffFiles.findIndex(diff => diff.file_hash === state.currentDiffFileId));
+export const currentDiffIndex = (state) =>
+ Math.max(
+ 0,
+ state.diffFiles.findIndex((diff) => diff.file_hash === state.currentDiffFileId),
+ );
-export const diffLines = state => (file, unifiedDiffComponents) => {
+export const diffLines = (state) => (file, unifiedDiffComponents) => {
if (!unifiedDiffComponents && state.diffViewType === INLINE_DIFF_VIEW_TYPE) {
return null;
}
@@ -149,3 +155,7 @@ export const diffLines = state => (file, unifiedDiffComponents) => {
state.diffViewType === INLINE_DIFF_VIEW_TYPE,
);
};
+
+export function fileReviews(state) {
+ return state.diffFiles.map((file) => isFileReviewed(state.mrReviews, file));
+}
diff --git a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
index 135b1c61ef5..3f33b0c900e 100644
--- a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
+++ b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
@@ -2,10 +2,10 @@ import { __, n__, sprintf } from '~/locale';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import { DIFF_COMPARE_BASE_VERSION_INDEX, DIFF_COMPARE_HEAD_VERSION_INDEX } from '../constants';
-export const selectedTargetIndex = state =>
+export const selectedTargetIndex = (state) =>
state.startVersion?.version_index || DIFF_COMPARE_BASE_VERSION_INDEX;
-export const selectedSourceIndex = state => state.mergeRequestDiff.version_index;
+export const selectedSourceIndex = (state) => state.mergeRequestDiff.version_index;
export const diffCompareDropdownTargetVersions = (state, getters) => {
// startVersion only exists if the user has selected a version other
@@ -40,7 +40,7 @@ export const diffCompareDropdownTargetVersions = (state, getters) => {
selected: isHeadSelected,
};
// Appended properties here are to make the compare_dropdown_layout easier to reason about
- const formatVersion = v => {
+ const formatVersion = (v) => {
return {
href: v.compare_path,
versionName: sprintf(__(`version %{versionIndex}`), { versionIndex: v.version_index }),
@@ -53,19 +53,23 @@ export const diffCompareDropdownTargetVersions = (state, getters) => {
...state.mergeRequestDiffs.slice(1).map(formatVersion),
baseVersion,
state.mergeRequestDiff.head_version_path && headVersion,
- ].filter(a => a);
+ ].filter((a) => a);
};
export const diffCompareDropdownSourceVersions = (state, getters) => {
// Appended properties here are to make the compare_dropdown_layout easier to reason about
- return state.mergeRequestDiffs.map((v, i) => ({
- ...v,
- href: v.version_path,
- commitsText: n__(`%d commit,`, `%d commits,`, v.commits_count),
- versionName:
- i === 0
+ return state.mergeRequestDiffs.map((v, i) => {
+ const isLatestVersion = i === 0;
+
+ return {
+ ...v,
+ href: v.version_path,
+ commitsText: n__(`%d commit,`, `%d commits,`, v.commits_count),
+ isLatestVersion,
+ versionName: isLatestVersion
? __('latest version')
: sprintf(__(`version %{versionIndex}`), { versionIndex: v.version_index }),
- selected: v.version_index === getters.selectedSourceIndex,
- }));
+ selected: v.version_index === getters.selectedSourceIndex,
+ };
+ });
};
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index c331e52c887..aa89c74cef0 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -45,4 +45,6 @@ export default () => ({
fileFinderVisible: false,
dismissEndpoint: '',
showSuggestPopover: true,
+ defaultSuggestionCommitMessage: '',
+ mrReviews: {},
});
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 30097239aaa..4641731c4b6 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -7,6 +7,8 @@ export const SET_DIFF_METADATA = 'SET_DIFF_METADATA';
export const SET_DIFF_DATA_BATCH = 'SET_DIFF_DATA_BATCH';
export const SET_DIFF_FILES = 'SET_DIFF_FILES';
+export const SET_MR_FILE_REVIEWS = 'SET_MR_FILE_REVIEWS';
+
export const SET_DIFF_VIEW_TYPE = 'SET_DIFF_VIEW_TYPE';
export const SET_COVERAGE_DATA = 'SET_COVERAGE_DATA';
export const SET_MERGE_REQUEST_DIFFS = 'SET_MERGE_REQUEST_DIFFS';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 19122c3096f..06f0f2c3dfb 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -36,7 +36,9 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ defaultSuggestionCommitMessage,
viewDiffsFileByFile,
+ mrReviews,
} = options;
Object.assign(state, {
endpoint,
@@ -46,7 +48,9 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ defaultSuggestionCommitMessage,
viewDiffsFileByFile,
+ mrReviews,
});
},
@@ -103,11 +107,11 @@ export default {
},
[types.TOGGLE_LINE_HAS_FORM](state, { lineCode, fileHash, hasForm }) {
- const diffFile = state.diffFiles.find(f => f.file_hash === fileHash);
+ const diffFile = state.diffFiles.find((f) => f.file_hash === fileHash);
if (!diffFile) return;
- diffFile[INLINE_DIFF_LINES_KEY].find(l => l.line_code === lineCode).hasForm = hasForm;
+ diffFile[INLINE_DIFF_LINES_KEY].find((l) => l.line_code === lineCode).hasForm = hasForm;
},
[types.ADD_CONTEXT_LINES](state, options) {
@@ -123,7 +127,7 @@ export default {
bottom,
isExpandDown,
nextLineNumbers,
- ).map(line => {
+ ).map((line) => {
const lineCode =
line.type === 'match'
? `${fileHash}_${line.meta_data.old_pos}_${line.meta_data.new_pos}_match`
@@ -147,8 +151,8 @@ export default {
[types.ADD_COLLAPSED_DIFFS](state, { file, data }) {
const files = prepareDiffData({ diff: data });
- const [newFileData] = files.filter(f => f.file_hash === file.file_hash);
- const selectedFile = state.diffFiles.find(f => f.file_hash === file.file_hash);
+ const [newFileData] = files.filter((f) => f.file_hash === file.file_hash);
+ const selectedFile = state.diffFiles.find((f) => f.file_hash === file.file_hash);
Object.assign(selectedFile, { ...newFileData });
},
@@ -157,9 +161,9 @@ export default {
const discussionLineCodes = [discussion.line_code, ...(discussion.line_codes || [])];
const fileHash = discussion.diff_file.file_hash;
- const lineCheck = line =>
+ const lineCheck = (line) =>
discussionLineCodes.some(
- discussionLineCode =>
+ (discussionLineCode) =>
line.line_code === discussionLineCode &&
isDiscussionApplicableToLine({
discussion,
@@ -177,26 +181,26 @@ export default {
: [],
});
- const setDiscussionsExpanded = line => {
+ const setDiscussionsExpanded = (line) => {
const isLineNoteTargeted =
line.discussions &&
line.discussions.some(
- disc => disc.notes && disc.notes.find(note => hash === `note_${note.id}`),
+ (disc) => disc.notes && disc.notes.find((note) => hash === `note_${note.id}`),
);
return {
...line,
discussionsExpanded:
line.discussions && line.discussions.length
- ? line.discussions.some(disc => !disc.resolved) || isLineNoteTargeted
+ ? line.discussions.some((disc) => !disc.resolved) || isLineNoteTargeted
: false,
};
};
- state.diffFiles.forEach(file => {
+ state.diffFiles.forEach((file) => {
if (file.file_hash === fileHash) {
if (file[INLINE_DIFF_LINES_KEY].length) {
- file[INLINE_DIFF_LINES_KEY].forEach(line => {
+ file[INLINE_DIFF_LINES_KEY].forEach((line) => {
Object.assign(
line,
setDiscussionsExpanded(lineCheck(line) ? mapDiscussions(line) : line),
@@ -206,7 +210,7 @@ export default {
if (!file[INLINE_DIFF_LINES_KEY].length) {
const newDiscussions = (file.discussions || [])
- .filter(d => d.id !== discussion.id)
+ .filter((d) => d.id !== discussion.id)
.concat(discussion);
Object.assign(file, {
@@ -218,26 +222,26 @@ export default {
},
[types.REMOVE_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, lineCode }) {
- const selectedFile = state.diffFiles.find(f => f.file_hash === fileHash);
+ const selectedFile = state.diffFiles.find((f) => f.file_hash === fileHash);
if (selectedFile) {
- updateLineInFile(selectedFile, lineCode, line =>
+ updateLineInFile(selectedFile, lineCode, (line) =>
Object.assign(line, {
- discussions: line.discussions.filter(discussion => discussion.notes.length),
+ discussions: line.discussions.filter((discussion) => discussion.notes.length),
}),
);
if (selectedFile.discussions && selectedFile.discussions.length) {
selectedFile.discussions = selectedFile.discussions.filter(
- discussion => discussion.notes.length,
+ (discussion) => discussion.notes.length,
);
}
}
},
[types.TOGGLE_LINE_DISCUSSIONS](state, { fileHash, lineCode, expanded }) {
- const selectedFile = state.diffFiles.find(f => f.file_hash === fileHash);
+ const selectedFile = state.diffFiles.find((f) => f.file_hash === fileHash);
- updateLineInFile(selectedFile, lineCode, line => {
+ updateLineInFile(selectedFile, lineCode, (line) => {
Object.assign(line, { discussionsExpanded: expanded });
});
},
@@ -260,7 +264,7 @@ export default {
[types.UPDATE_DIFF_FILE_COMMENT_FORM](state, formData) {
const { fileHash } = formData;
- state.commentForms = state.commentForms.map(form => {
+ state.commentForms = state.commentForms.map((form) => {
if (form.fileHash === fileHash) {
return {
...formData,
@@ -271,7 +275,7 @@ export default {
});
},
[types.CLOSE_DIFF_FILE_COMMENT_FORM](state, fileHash) {
- state.commentForms = state.commentForms.filter(form => form.fileHash !== fileHash);
+ state.commentForms = state.commentForms.filter((form) => form.fileHash !== fileHash);
},
[types.SET_HIGHLIGHTED_ROW](state, lineCode) {
state.highlightedRow = lineCode;
@@ -311,7 +315,7 @@ export default {
state,
{ filePath, collapsed, trigger = DIFF_FILE_AUTOMATIC_COLLAPSE },
) {
- const file = state.diffFiles.find(f => f.file_path === filePath);
+ const file = state.diffFiles.find((f) => f.file_path === filePath);
if (file && file.viewer) {
if (trigger === DIFF_FILE_MANUAL_COLLAPSE) {
@@ -328,17 +332,17 @@ export default {
}
},
[types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
- const file = state.diffFiles.find(f => f.file_path === filePath);
+ const file = state.diffFiles.find((f) => f.file_path === filePath);
file[INLINE_DIFF_LINES_KEY] = lines;
},
[types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, line }) {
- const file = state.diffFiles.find(f => f.file_path === filePath);
+ const file = state.diffFiles.find((f) => f.file_path === filePath);
file[INLINE_DIFF_LINES_KEY].push(line);
},
[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, filePath) {
- const file = state.diffFiles.find(f => f.file_path === filePath);
+ const file = state.diffFiles.find((f) => f.file_path === filePath);
file.renderingLines = !file.renderingLines;
},
@@ -353,4 +357,7 @@ export default {
[types.SET_FILE_BY_FILE](state, fileByFile) {
state.viewDiffsFileByFile = fileByFile;
},
+ [types.SET_MR_FILE_REVIEWS](state, newReviews) {
+ state.mrReviews = newReviews;
+ },
};
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 1839df12c96..c52da558be2 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -15,13 +15,23 @@ import {
INLINE_DIFF_LINES_KEY,
SHOW_WHITESPACE,
NO_SHOW_WHITESPACE,
+ CONFLICT_OUR,
+ CONFLICT_THEIR,
+ CONFLICT_MARKER,
+ CONFLICT_MARKER_OUR,
+ CONFLICT_MARKER_THEIR,
} from '../constants';
import { prepareRawDiffFile } from '../utils/diff_file';
-export const isAdded = line => ['new', 'new-nonewline'].includes(line.type);
-export const isRemoved = line => ['old', 'old-nonewline'].includes(line.type);
-export const isUnchanged = line => !line.type;
-export const isMeta = line => ['match', 'new-nonewline', 'old-nonewline'].includes(line.type);
+export const isAdded = (line) => ['new', 'new-nonewline'].includes(line.type);
+export const isRemoved = (line) => ['old', 'old-nonewline'].includes(line.type);
+export const isUnchanged = (line) => !line.type;
+export const isMeta = (line) => ['match', 'new-nonewline', 'old-nonewline'].includes(line.type);
+export const isConflictMarker = (line) =>
+ [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(line.type);
+export const isConflictSeperator = (line) => line.type === CONFLICT_MARKER;
+export const isConflictOur = (line) => line.type === CONFLICT_OUR;
+export const isConflictTheir = (line) => line.type === CONFLICT_THEIR;
/**
* Pass in the inline diff lines array which gets converted
@@ -42,12 +52,22 @@ export const isMeta = line => ['match', 'new-nonewline', 'old-nonewline'].includ
export const parallelizeDiffLines = (diffLines, inline) => {
let freeRightIndex = null;
+ let conflictStartIndex = -1;
const lines = [];
+ // `chunk` is used for dragging to select diff lines
+ // we are restricting commenting to only lines that appear between
+ // "expansion rows". Here equal chunks are lines grouped together
+ // inbetween expansion rows.
+ let chunk = 0;
+
for (let i = 0, diffLinesLength = diffLines.length, index = 0; i < diffLinesLength; i += 1) {
const line = diffLines[i];
+ line.chunk = chunk;
+
+ if (isMeta(line)) chunk += 1;
- if (isRemoved(line) || inline) {
+ if (isRemoved(line) || isConflictOur(line) || inline) {
lines.push({
[LINE_POSITION_LEFT]: line,
[LINE_POSITION_RIGHT]: null,
@@ -58,7 +78,7 @@ export const parallelizeDiffLines = (diffLines, inline) => {
freeRightIndex = index;
}
index += 1;
- } else if (isAdded(line)) {
+ } else if (isAdded(line) || isConflictTheir(line)) {
if (freeRightIndex !== null) {
// If an old line came before this without a line on the right, this
// line can be put to the right of it.
@@ -77,15 +97,28 @@ export const parallelizeDiffLines = (diffLines, inline) => {
freeRightIndex = null;
index += 1;
}
- } else if (isMeta(line) || isUnchanged(line)) {
- // line in the right panel is the same as in the left one
- lines.push({
- [LINE_POSITION_LEFT]: line,
- [LINE_POSITION_RIGHT]: line,
- });
+ } else if (
+ isMeta(line) ||
+ isUnchanged(line) ||
+ isConflictMarker(line) ||
+ (isConflictSeperator(line) && inline)
+ ) {
+ if (conflictStartIndex <= 0) {
+ // line in the right panel is the same as in the left one
+ lines.push({
+ [LINE_POSITION_LEFT]: line,
+ [LINE_POSITION_RIGHT]: !inline && line,
+ });
- freeRightIndex = null;
- index += 1;
+ if (!inline && isConflictMarker(line)) {
+ conflictStartIndex = index;
+ }
+ freeRightIndex = null;
+ index += 1;
+ } else {
+ lines[conflictStartIndex][LINE_POSITION_RIGHT] = line;
+ conflictStartIndex = -1;
+ }
}
}
@@ -93,10 +126,10 @@ export const parallelizeDiffLines = (diffLines, inline) => {
};
export function findDiffFile(files, match, matchKey = 'file_hash') {
- return files.find(file => file[matchKey] === match);
+ return files.find((file) => file[matchKey] === match);
}
-export const getReversePosition = linePosition => {
+export const getReversePosition = (linePosition) => {
if (linePosition === LINE_POSITION_RIGHT) {
return LINE_POSITION_LEFT;
}
@@ -173,7 +206,7 @@ export const findIndexInInlineLines = (lines, lineNumbers) => {
const { oldLineNumber, newLineNumber } = lineNumbers;
return lines.findIndex(
- line => line.old_line === oldLineNumber && line.new_line === newLineNumber,
+ (line) => line.old_line === oldLineNumber && line.new_line === newLineNumber,
);
};
@@ -346,7 +379,7 @@ export function prepareLineForRenamedFile({ line, diffFile, index = 0 }) {
function prepareDiffFileLines(file) {
const inlineLines = file[INLINE_DIFF_LINES_KEY];
- inlineLines.forEach(line => prepareLine(line, file)); // WARNING: In-Place Mutations!
+ inlineLines.forEach((line) => prepareLine(line, file)); // WARNING: In-Place Mutations!
Object.assign(file, {
inlineLinesCount: inlineLines.length,
@@ -400,7 +433,7 @@ export function getDiffPositionByLineCode(diffFiles) {
let lines = [];
lines = diffFiles.reduce((acc, diffFile) => {
- diffFile[INLINE_DIFF_LINES_KEY].forEach(line => {
+ diffFile[INLINE_DIFF_LINES_KEY].forEach((line) => {
acc.push({ file: diffFile, line });
});
@@ -447,21 +480,21 @@ export function isDiscussionApplicableToLine({ discussion, diffPosition, latestD
...(discussion.positions || []),
];
- const removeLineRange = position => {
+ const removeLineRange = (position) => {
const { line_range: pNotUsed, ...positionNoLineRange } = position;
return positionNoLineRange;
};
return discussionPositions
.map(removeLineRange)
- .some(position => isEqual(position, diffPositionCopy));
+ .some((position) => isEqual(position, diffPositionCopy));
}
// eslint-disable-next-line
return latestDiff && discussion.active && line_code === discussion.line_code;
}
-export const getLowestSingleFolder = folder => {
+export const getLowestSingleFolder = (folder) => {
const getFolder = (blob, start = []) =>
blob.tree.reduce(
(acc, file) => {
@@ -493,8 +526,8 @@ export const getLowestSingleFolder = folder => {
};
};
-export const flattenTree = tree => {
- const flatten = blobTree =>
+export const flattenTree = (tree) => {
+ const flatten = (blobTree) =>
blobTree.reduce((acc, file) => {
const blob = file;
let treeToFlatten = blob.tree;
@@ -516,7 +549,7 @@ export const flattenTree = tree => {
return flatten(tree);
};
-export const generateTreeList = files => {
+export const generateTreeList = (files) => {
const { treeEntries, tree } = files.reduce(
(acc, file) => {
const split = file.new_path.split('/');
@@ -566,8 +599,8 @@ export const generateTreeList = files => {
return { treeEntries, tree: flattenTree(tree) };
};
-export const getDiffMode = diffFile => {
- const diffModeKey = Object.keys(diffModes).find(key => diffFile[`${key}_file`]);
+export const getDiffMode = (diffFile) => {
+ const diffModeKey = Object.keys(diffModes).find((key) => diffFile[`${key}_file`]);
return (
diffModes[diffModeKey] ||
(diffFile.viewer &&
@@ -615,11 +648,11 @@ export const convertExpandLines = ({
return lines;
};
-export const idleCallback = cb => requestIdleCallback(cb);
+export const idleCallback = (cb) => requestIdleCallback(cb);
function getLinesFromFileByLineCode(file, lineCode) {
const inlineLines = file[INLINE_DIFF_LINES_KEY];
- const matchesCode = line => line.line_code === lineCode;
+ const matchesCode = (line) => line.line_code === lineCode;
return inlineLines.filter(matchesCode);
}
@@ -628,15 +661,15 @@ export const updateLineInFile = (selectedFile, lineCode, updateFn) => {
getLinesFromFileByLineCode(selectedFile, lineCode).forEach(updateFn);
};
-export const allDiscussionWrappersExpanded = diff => {
+export const allDiscussionWrappersExpanded = (diff) => {
let discussionsExpanded = true;
- const changeExpandedResult = line => {
+ const changeExpandedResult = (line) => {
if (line && line.discussions.length) {
discussionsExpanded = discussionsExpanded && line.discussionsExpanded;
}
};
- diff[INLINE_DIFF_LINES_KEY].forEach(line => {
+ diff[INLINE_DIFF_LINES_KEY].forEach((line) => {
changeExpandedResult(line);
});
diff --git a/app/assets/javascripts/diffs/utils/diff_file.js b/app/assets/javascripts/diffs/utils/diff_file.js
index 69d0e49e501..ce0398e75fc 100644
--- a/app/assets/javascripts/diffs/utils/diff_file.js
+++ b/app/assets/javascripts/diffs/utils/diff_file.js
@@ -4,11 +4,12 @@ import {
DIFF_FILE_MANUAL_COLLAPSE,
DIFF_FILE_AUTOMATIC_COLLAPSE,
} from '../constants';
+import { getDerivedMergeRequestInformation } from './merge_request';
import { uuids } from './uuids';
function fileSymlinkInformation(file, fileList) {
- const duplicates = fileList.filter(iteratedFile => iteratedFile.file_hash === file.file_hash);
- const includesSymlink = duplicates.some(iteratedFile => {
+ const duplicates = fileList.filter((iteratedFile) => iteratedFile.file_hash === file.file_hash);
+ const includesSymlink = duplicates.some((iteratedFile) => {
return [iteratedFile.a_mode, iteratedFile.b_mode].includes(DIFF_FILE_SYMLINK_MODE);
});
const brokenSymlinkScenario = duplicates.length > 1 && includesSymlink;
@@ -34,8 +35,12 @@ function collapsed(file) {
}
function identifier(file) {
+ const { userOrGroup, project, id } = getDerivedMergeRequestInformation({
+ endpoint: file.load_collapsed_diff_url,
+ });
+
return uuids({
- seeds: [file.file_identifier_hash, file.blob?.id],
+ seeds: [userOrGroup, project, id, file.file_identifier_hash, file.blob?.id],
})[0];
}
@@ -48,10 +53,10 @@ export function prepareRawDiffFile({ file, allFiles, meta = false }) {
},
};
- // It's possible, but not confirmed, that `content_sha` isn't available sometimes
+ // It's possible, but not confirmed, that `blob.id` isn't available sometimes
// See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49506#note_464692057
// We don't want duplicate IDs if that's the case, so we just don't assign an ID
- if (!meta && file.blob?.id) {
+ if (!meta && file.blob?.id && file.load_collapsed_diff_url) {
additionalProperties.id = identifier(file);
}
diff --git a/app/assets/javascripts/diffs/utils/file_reviews.js b/app/assets/javascripts/diffs/utils/file_reviews.js
new file mode 100644
index 00000000000..0047955643a
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/file_reviews.js
@@ -0,0 +1,61 @@
+function getFileReviewsKey(mrPath) {
+ return `${mrPath}-file-reviews`;
+}
+
+export function getReviewsForMergeRequest(mrPath) {
+ const reviewsForMr = localStorage.getItem(getFileReviewsKey(mrPath));
+ let reviews = {};
+
+ if (reviewsForMr) {
+ try {
+ reviews = JSON.parse(reviewsForMr);
+ } catch (err) {
+ reviews = {};
+ }
+ }
+
+ return reviews;
+}
+
+export function setReviewsForMergeRequest(mrPath, reviews) {
+ localStorage.setItem(getFileReviewsKey(mrPath), JSON.stringify(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;
+ let fileReviews;
+
+ if (reviewable(file)) {
+ fileReviews = new Set([...(usableReviews[file.file_identifier_hash] || [])]);
+
+ if (reviewed) {
+ fileReviews.add(file.id);
+ } else {
+ fileReviews.delete(file.id);
+ }
+
+ updatedReviews = {
+ ...usableReviews,
+ [file.file_identifier_hash]: Array.from(fileReviews),
+ };
+
+ if (updatedReviews[file.file_identifier_hash].length === 0) {
+ delete updatedReviews[file.file_identifier_hash];
+ }
+ }
+
+ return updatedReviews;
+}
diff --git a/app/assets/javascripts/diffs/utils/merge_request.js b/app/assets/javascripts/diffs/utils/merge_request.js
new file mode 100644
index 00000000000..edb4304f558
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/merge_request.js
@@ -0,0 +1,20 @@
+const endpointRE = /^(\/?(.+?)\/(.+?)\/-\/merge_requests\/(\d+)).*$/i;
+
+export function getDerivedMergeRequestInformation({ endpoint } = {}) {
+ let mrPath;
+ let userOrGroup;
+ let project;
+ let id;
+ const matches = endpointRE.exec(endpoint);
+
+ if (matches) {
+ [, mrPath, userOrGroup, project, id] = matches;
+ }
+
+ return {
+ mrPath,
+ userOrGroup,
+ project,
+ id,
+ };
+}
diff --git a/app/assets/javascripts/diffs/utils/uuids.js b/app/assets/javascripts/diffs/utils/uuids.js
index 12448350e62..1fe5f9f6499 100644
--- a/app/assets/javascripts/diffs/utils/uuids.js
+++ b/app/assets/javascripts/diffs/utils/uuids.js
@@ -11,7 +11,7 @@
* @typedef {String} UUIDv4
*/
-import MersenneTwister from 'mersenne-twister';
+import { MersenneTwister } from 'fast-mersenne-twister';
import stringHash from 'string-hash';
import { isString } from 'lodash';
import { v4 } from 'uuid';
@@ -49,7 +49,7 @@ function randomValuesForUuid(prng) {
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
- view.setUint32(0, prng.random_int());
+ view.setUint32(0, prng.randomNumber());
randomValues.push(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3));
}
diff --git a/app/assets/javascripts/diffs/workers/tree_worker.js b/app/assets/javascripts/diffs/workers/tree_worker.js
index 415c463fd19..2fa1934439e 100644
--- a/app/assets/javascripts/diffs/workers/tree_worker.js
+++ b/app/assets/javascripts/diffs/workers/tree_worker.js
@@ -2,7 +2,7 @@ import { sortTree } from '~/ide/stores/utils';
import { generateTreeList } from '../store/utils';
// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', e => {
+self.addEventListener('message', (e) => {
const { data } = e;
if (data === undefined) {
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_collection.js b/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
index 42b051b2270..4886125d4ac 100644
--- a/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
@@ -6,7 +6,7 @@ class DirtySubmitCollection {
this.dirtySubmits = [];
- this.forms.forEach(form => this.dirtySubmits.push(new DirtySubmitForm(form)));
+ this.forms.forEach((form) => this.dirtySubmits.push(new DirtySubmitForm(form)));
}
}
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_form.js b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
index 903c31cb0d1..54fd5f91194 100644
--- a/app/assets/javascripts/dirty_submit/dirty_submit_form.js
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
@@ -22,10 +22,10 @@ class DirtySubmitForm {
registerListeners() {
const getThrottledHandlerForInput = memoize(() =>
- throttle(event => this.updateDirtyInput(event), DirtySubmitForm.THROTTLE_DURATION),
+ throttle((event) => this.updateDirtyInput(event), DirtySubmitForm.THROTTLE_DURATION),
);
- const throttledUpdateDirtyInput = event => {
+ const throttledUpdateDirtyInput = (event) => {
const throttledHandler = getThrottledHandlerForInput(event.target.name);
throttledHandler(event);
};
@@ -33,7 +33,7 @@ class DirtySubmitForm {
this.form.addEventListener('input', throttledUpdateDirtyInput);
this.form.addEventListener('change', throttledUpdateDirtyInput);
$(this.form).on('change.select2', throttledUpdateDirtyInput);
- this.form.addEventListener('submit', event => this.formSubmit(event));
+ this.form.addEventListener('submit', (event) => this.formSubmit(event));
}
updateDirtyInput(event) {
@@ -58,7 +58,7 @@ class DirtySubmitForm {
toggleSubmission() {
this.isDisabled = this.dirtyInputs.length === 0;
- this.submits.forEach(element => {
+ this.submits.forEach((element) => {
element.disabled = this.isDisabled;
});
}
diff --git a/app/assets/javascripts/droplab/drop_down.js b/app/assets/javascripts/droplab/drop_down.js
index 31d32fb5060..f4a0b3ed727 100644
--- a/app/assets/javascripts/droplab/drop_down.js
+++ b/app/assets/javascripts/droplab/drop_down.js
@@ -68,7 +68,7 @@ class DropDown {
removeSelectedClasses() {
const items = this.items || this.getItems();
- items.forEach(item => item.classList.remove(SELECTED_CLASS));
+ items.forEach((item) => item.classList.remove(SELECTED_CLASS));
}
addEvents() {
@@ -162,7 +162,7 @@ class DropDown {
static setImagesSrc(template) {
const images = [...template.querySelectorAll('img[data-src]')];
- images.forEach(image => {
+ images.forEach((image) => {
const img = image;
img.src = img.getAttribute('data-src');
diff --git a/app/assets/javascripts/droplab/drop_lab.js b/app/assets/javascripts/droplab/drop_lab.js
index 33c05404493..537a05aebb9 100644
--- a/app/assets/javascripts/droplab/drop_lab.js
+++ b/app/assets/javascripts/droplab/drop_lab.js
@@ -28,7 +28,7 @@ class DropLab {
}
destroy() {
- this.hooks.forEach(hook => hook.destroy());
+ this.hooks.forEach((hook) => hook.destroy());
this.hooks = [];
this.removeEvents();
}
@@ -51,7 +51,7 @@ class DropLab {
}
processData(trigger, data, methodName) {
- this.hooks.forEach(hook => {
+ this.hooks.forEach((hook) => {
if (Array.isArray(trigger)) hook.list[methodName](trigger);
if (hook.trigger.id === trigger) hook.list[methodName](data);
@@ -70,7 +70,7 @@ class DropLab {
if (utils.isDropDownParts(thisTag, this.hooks)) return;
if (utils.isDropDownParts(e.target, this.hooks)) return;
- this.hooks.forEach(hook => hook.list.hide());
+ this.hooks.forEach((hook) => hook.list.hide());
}
removeEvents() {
@@ -115,7 +115,7 @@ class DropLab {
}
addHooks(hooks, plugins, config) {
- hooks.forEach(hook => this.addHook(hook, null, plugins, config));
+ hooks.forEach((hook) => this.addHook(hook, null, plugins, config));
return this;
}
@@ -147,7 +147,7 @@ class DropLab {
this.fireReady();
- this.queuedData.forEach(data => this.addData(data));
+ this.queuedData.forEach((data) => this.addData(data));
this.queuedData = [];
return this;
diff --git a/app/assets/javascripts/droplab/hook_button.js b/app/assets/javascripts/droplab/hook_button.js
index af45eba74e7..c58d0052251 100644
--- a/app/assets/javascripts/droplab/hook_button.js
+++ b/app/assets/javascripts/droplab/hook_button.js
@@ -14,7 +14,7 @@ class HookButton extends Hook {
}
addPlugins() {
- this.plugins.forEach(plugin => plugin.init(this));
+ this.plugins.forEach((plugin) => plugin.init(this));
}
clicked(e) {
@@ -44,7 +44,7 @@ class HookButton extends Hook {
}
removePlugins() {
- this.plugins.forEach(plugin => plugin.destroy());
+ this.plugins.forEach((plugin) => plugin.destroy());
}
destroy() {
diff --git a/app/assets/javascripts/droplab/hook_input.js b/app/assets/javascripts/droplab/hook_input.js
index 19131a64f2c..c523dae347f 100644
--- a/app/assets/javascripts/droplab/hook_input.js
+++ b/app/assets/javascripts/droplab/hook_input.js
@@ -14,7 +14,7 @@ class HookInput extends Hook {
}
addPlugins() {
- this.plugins.forEach(plugin => plugin.init(this));
+ this.plugins.forEach((plugin) => plugin.init(this));
}
addEvents() {
@@ -101,7 +101,7 @@ class HookInput extends Hook {
}
removePlugins() {
- this.plugins.forEach(plugin => plugin.destroy());
+ this.plugins.forEach((plugin) => plugin.destroy());
}
destroy() {
diff --git a/app/assets/javascripts/droplab/keyboard.js b/app/assets/javascripts/droplab/keyboard.js
index 40837ffdf8f..fe1ea2fa6b0 100644
--- a/app/assets/javascripts/droplab/keyboard.js
+++ b/app/assets/javascripts/droplab/keyboard.js
@@ -2,7 +2,7 @@
import { ACTIVE_CLASS } from './constants';
-const Keyboard = function() {
+const Keyboard = function () {
var currentKey;
var currentFocus;
var isUpArrow = false;
diff --git a/app/assets/javascripts/droplab/plugins/ajax.js b/app/assets/javascripts/droplab/plugins/ajax.js
index 48b2a90c459..77d60454d1a 100644
--- a/app/assets/javascripts/droplab/plugins/ajax.js
+++ b/app/assets/javascripts/droplab/plugins/ajax.js
@@ -43,10 +43,10 @@ const Ajax = {
return AjaxCache.retrieve(config.endpoint)
.then(self.preprocessing.bind(null, config))
- .then(data => self._loadData(data, config, self))
+ .then((data) => self._loadData(data, config, self))
.catch(config.onError);
},
- destroy: function() {
+ destroy: function () {
this.destroyed = true;
},
};
diff --git a/app/assets/javascripts/droplab/plugins/ajax_filter.js b/app/assets/javascripts/droplab/plugins/ajax_filter.js
index 66a52548417..ac4d44adc17 100644
--- a/app/assets/javascripts/droplab/plugins/ajax_filter.js
+++ b/app/assets/javascripts/droplab/plugins/ajax_filter.js
@@ -2,7 +2,7 @@
import AjaxCache from '../../lib/utils/ajax_cache';
const AjaxFilter = {
- init: function(hook) {
+ init: function (hook) {
this.destroyed = false;
this.hook = hook;
this.notLoading();
@@ -63,7 +63,7 @@ const AjaxFilter = {
params[config.searchKey] = searchValue;
var url = config.endpoint + this.buildParams(params);
return AjaxCache.retrieve(url)
- .then(data => {
+ .then((data) => {
this._loadData(data, config);
if (config.onLoadingFinished) {
config.onLoadingFinished(data);
@@ -93,9 +93,9 @@ const AjaxFilter = {
list.currentIndex = 0;
},
- buildParams: function(params) {
+ buildParams: function (params) {
if (!params) return '';
- var paramsArray = Object.keys(params).map(function(param) {
+ var paramsArray = Object.keys(params).map(function (param) {
return param + '=' + (params[param] || '');
});
return '?' + paramsArray.join('&');
diff --git a/app/assets/javascripts/droplab/plugins/filter.js b/app/assets/javascripts/droplab/plugins/filter.js
index 6f1dc252d24..06391668928 100644
--- a/app/assets/javascripts/droplab/plugins/filter.js
+++ b/app/assets/javascripts/droplab/plugins/filter.js
@@ -1,7 +1,7 @@
/* eslint-disable */
const Filter = {
- keydown: function(e) {
+ keydown: function (e) {
if (this.destroyed) return;
var hiddenCount = 0;
@@ -21,22 +21,22 @@ const Filter = {
if (config && config.filterFunction && typeof config.filterFunction === 'function') {
filterFunction = config.filterFunction;
} else {
- filterFunction = function(o) {
+ filterFunction = function (o) {
// cheap string search
o.droplab_hidden = o[config.template].toLowerCase().indexOf(value) === -1;
return o;
};
}
- dataHiddenCount = data.filter(function(o) {
+ dataHiddenCount = data.filter(function (o) {
return !o.droplab_hidden;
}).length;
- matches = data.map(function(o) {
+ matches = data.map(function (o) {
return filterFunction(o, value);
});
- hiddenCount = matches.filter(function(o) {
+ hiddenCount = matches.filter(function (o) {
return !o.droplab_hidden;
}).length;
diff --git a/app/assets/javascripts/droplab/plugins/input_setter.js b/app/assets/javascripts/droplab/plugins/input_setter.js
index 6cfc738a1e3..148d9a35b81 100644
--- a/app/assets/javascripts/droplab/plugins/input_setter.js
+++ b/app/assets/javascripts/droplab/plugins/input_setter.js
@@ -27,7 +27,7 @@ const InputSetter = {
if (!Array.isArray(this.config)) this.config = [this.config];
- this.config.forEach(config => this.setInput(config, selectedItem));
+ this.config.forEach((config) => this.setInput(config, selectedItem));
},
setInput(config, selectedItem) {
diff --git a/app/assets/javascripts/droplab/utils.js b/app/assets/javascripts/droplab/utils.js
index df3c5c2132a..d7f49bf19d8 100644
--- a/app/assets/javascripts/droplab/utils.js
+++ b/app/assets/javascripts/droplab/utils.js
@@ -5,12 +5,7 @@ import { DATA_TRIGGER, DATA_DROPDOWN, TEMPLATE_REGEX } from './constants';
const utils = {
toCamelCase(attr) {
- return this.camelize(
- attr
- .split('-')
- .slice(1)
- .join(' '),
- );
+ return this.camelize(attr.split('-').slice(1).join(' '));
},
template(templateString, data) {
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index 69961d2e07a..d7aacfbce60 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -46,7 +46,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
let uploadFile;
formTextarea.wrap('<div class="div-dropzone"></div>');
- formTextarea.on('paste', event => handlePaste(event));
+ formTextarea.on('paste', (event) => handlePaste(event));
// Add dropzone area to the form.
const $mdArea = formTextarea.closest('.md-area');
@@ -139,7 +139,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
// removeAllFiles(true) stops uploading files (if any)
// and remove them from dropzone files queue.
- $cancelButton.on('click', e => {
+ $cancelButton.on('click', (e) => {
e.preventDefault();
e.stopPropagation();
Dropzone.forElement($formDropzone.get(0)).removeAllFiles(true);
@@ -149,7 +149,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
// clear dropzone files queue, change status of failed files to undefined,
// and add that files to the dropzone files queue again.
// addFile() adds file to dropzone files queue and upload it.
- $retryLink.on('click', e => {
+ $retryLink.on('click', (e) => {
const dropzoneInstance = Dropzone.forElement(
e.target.closest('.js-main-target-form').querySelector('.div-dropzone'),
);
@@ -161,7 +161,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
// uploading of files that are being uploaded at the moment.
dropzoneInstance.removeAllFiles(true);
- failedFiles.map(failedFile => {
+ failedFiles.map((failedFile) => {
const file = failedFile;
if (file.status === Dropzone.ERROR) {
@@ -173,7 +173,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
});
});
// eslint-disable-next-line consistent-return
- handlePaste = event => {
+ handlePaste = (event) => {
const pasteEvent = event.originalEvent;
const { clipboardData } = pasteEvent;
if (clipboardData && clipboardData.items) {
@@ -198,7 +198,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
}
};
- isImage = data => {
+ isImage = (data) => {
let i = 0;
while (i < data.clipboardData.items.length) {
const item = data.clipboardData.items[i];
@@ -219,12 +219,8 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const caretStart = textarea.selectionStart;
const caretEnd = textarea.selectionEnd;
const textEnd = $(child).val().length;
- const beforeSelection = $(child)
- .val()
- .substring(0, caretStart);
- const afterSelection = $(child)
- .val()
- .substring(caretEnd, textEnd);
+ const beforeSelection = $(child).val().substring(0, caretStart);
+ const afterSelection = $(child).val().substring(caretEnd, textEnd);
$(child).val(beforeSelection + formattedText + afterSelection);
textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
textarea.style.height = `${textarea.scrollHeight}px`;
@@ -232,7 +228,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
return formTextarea.trigger('input');
};
- addFileToForm = path => {
+ addFileToForm = (path) => {
$(form).append(`<input type="hidden" name="files[]" value="${escape(path)}">`);
};
@@ -240,7 +236,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const closeSpinner = () => $uploadingProgressContainer.addClass('hide');
- const showError = message => {
+ const showError = (message) => {
$uploadingErrorContainer.removeClass('hide');
$uploadingErrorMessage.html(message);
};
@@ -273,15 +269,16 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
insertToTextArea(filename, md);
closeSpinner();
})
- .catch(e => {
+ .catch((e) => {
showError(e.response.data.message);
closeSpinner();
});
};
updateAttachingMessage = (files, messageContainer) => {
- const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued')
- .length;
+ const filesCount = files.filter(
+ (file) => file.status === 'uploading' || file.status === 'queued',
+ ).length;
const attachingMessage = n__('Attaching a file', 'Attaching %d files', filesCount);
messageContainer.text(`${attachingMessage} -`);
@@ -289,10 +286,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
form.find('.markdown-selector').click(function onMarkdownClick(e) {
e.preventDefault();
- $(this)
- .closest('.gfm-form')
- .find('.div-dropzone')
- .click();
+ $(this).closest('.gfm-form').find('.div-dropzone').click();
formTextarea.focus();
});
diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js
index ffb5232ca75..c311e1b561c 100644
--- a/app/assets/javascripts/due_date_select.js
+++ b/app/assets/javascripts/due_date_select.js
@@ -55,9 +55,9 @@ class DueDateSelect {
field: $dueDateInput.get(0),
theme: 'gitlab-theme',
format: 'yyyy-mm-dd',
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
- onSelect: dateText => {
+ parse: (dateString) => parsePikadayDate(dateString),
+ toString: (date) => pikadayToString(date),
+ onSelect: (dateText) => {
$dueDateInput.val(calendar.toString(dateText));
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
@@ -76,7 +76,7 @@ class DueDateSelect {
}
initRemoveDueDate() {
- this.$block.on('click', '.js-remove-due-date', e => {
+ this.$block.on('click', '.js-remove-due-date', (e) => {
const calendar = this.$datePicker.data('pikaday');
e.preventDefault();
@@ -103,7 +103,7 @@ class DueDateSelect {
if (this.rawSelectedDate.length) {
// Construct Date object manually to avoid buggy dateString support within Date constructor
- const dateArray = this.rawSelectedDate.split('-').map(v => parseInt(v, 10));
+ const dateArray = this.rawSelectedDate.split('-').map((v) => parseInt(v, 10));
const dateObj = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
this.displayedDate = dateFormat(dateObj, 'mmm d, yyyy');
} else {
@@ -182,8 +182,8 @@ export default class DueDateSelectors {
theme: 'gitlab-theme animate-picker',
format: 'yyyy-mm-dd',
container: $datePicker.parent().get(0),
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
+ parse: (dateString) => parsePikadayDate(dateString),
+ toString: (date) => pikadayToString(date),
onSelect(dateText) {
$datePicker.val(calendar.toString(dateText));
},
@@ -195,11 +195,9 @@ export default class DueDateSelectors {
$datePicker.data('pikaday', calendar);
});
- $('.js-clear-due-date,.js-clear-start-date').on('click', e => {
+ $('.js-clear-due-date,.js-clear-start-date').on('click', (e) => {
e.preventDefault();
- const calendar = $(e.target)
- .siblings('.datepicker')
- .data('pikaday');
+ const calendar = $(e.target).siblings('.datepicker').data('pikaday');
calendar.setDate(null);
});
}
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js
index d6f87872bde..8d1a3d17c6e 100644
--- a/app/assets/javascripts/editor/constants.js
+++ b/app/assets/javascripts/editor/constants.js
@@ -10,3 +10,12 @@ export const CONTENT_UPDATE_DEBOUNCE = 250;
export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = __(
'Editor Lite instance is required to set up an extension.',
);
+
+//
+// EXTENSIONS' CONSTANTS
+//
+
+// For CI config schemas the filename must match
+// '*.gitlab-ci.yml' regardless of project configuration.
+// https://gitlab.com/gitlab-org/gitlab/-/issues/293641
+export const EXTENSION_CI_SCHEMA_FILE_NAME_MATCH = '.gitlab-ci.yml';
diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js
index 2bd1cdc84d0..1808f968b8c 100644
--- a/app/assets/javascripts/editor/editor_lite.js
+++ b/app/assets/javascripts/editor/editor_lite.js
@@ -24,7 +24,7 @@ export default class EditorLite {
static setupMonacoTheme() {
const themeName = window.gon?.user_color_scheme || DEFAULT_THEME;
- const theme = themes.find(t => t.name === themeName);
+ const theme = themes.find((t) => t.name === themeName);
if (theme) monacoEditor.defineTheme(themeName, theme.data);
monacoEditor.setTheme(theme ? themeName : DEFAULT_THEME);
}
@@ -35,7 +35,7 @@ export default class EditorLite {
const ext = `.${path.split('.').pop()}`;
const language = monacoLanguages
.getLanguages()
- .find(lang => lang.extensions.indexOf(ext) !== -1);
+ .find((lang) => lang.extensions.indexOf(ext) !== -1);
const id = language ? language.id : 'plaintext';
monacoEditor.setModelLanguage(model, id);
}
@@ -51,7 +51,7 @@ export default class EditorLite {
const promises = [];
const extensionsArray = typeof extensions === 'string' ? extensions.split(',') : extensions;
- extensionsArray.forEach(ext => {
+ extensionsArray.forEach((ext) => {
const prefix = ext.includes('/') ? '' : 'editor/';
const trimmedExt = ext.replace(/^\//, '').trim();
EditorLite.pushToImportsArray(promises, `~/${prefix}${trimmedExt}`);
@@ -66,7 +66,7 @@ export default class EditorLite {
}
const isClassInstance = source.constructor.prototype !== Object.prototype;
const sanitizedSource = isClassInstance ? source.constructor.prototype : source;
- Object.getOwnPropertyNames(sanitizedSource).forEach(prop => {
+ Object.getOwnPropertyNames(sanitizedSource).forEach((prop) => {
if (prop !== 'constructor') {
Object.assign(inst, { [prop]: source[prop] });
}
@@ -110,17 +110,17 @@ export default class EditorLite {
});
instance.setModel(model);
instance.onDidDispose(() => {
- const index = this.instances.findIndex(inst => inst === instance);
+ 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);
+ instance.updateModelLanguage = (path) => EditorLite.updateModelLanguage(path, instance);
+ instance.use = (args) => this.use(args, instance);
EditorLite.loadExtensions(extensions, instance)
- .then(modules => {
+ .then((modules) => {
if (modules) {
- modules.forEach(module => {
+ modules.forEach((module) => {
instance.use(module.default);
});
}
@@ -128,7 +128,7 @@ export default class EditorLite {
.then(() => {
el.dispatchEvent(new Event('editor-ready'));
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
@@ -137,20 +137,20 @@ export default class EditorLite {
}
dispose() {
- this.instances.forEach(instance => instance.dispose());
+ this.instances.forEach((instance) => instance.dispose());
}
use(exts = [], instance = null) {
const extensions = Array.isArray(exts) ? exts : [exts];
- const initExtensions = inst => {
- extensions.forEach(extension => {
+ const initExtensions = (inst) => {
+ extensions.forEach((extension) => {
EditorLite.mixIntoInstance(extension, inst);
});
};
if (instance) {
initExtensions(instance);
} else {
- this.instances.forEach(inst => {
+ this.instances.forEach((inst) => {
initExtensions(inst);
});
}
diff --git a/app/assets/javascripts/editor/editor_lite_extension_base.js b/app/assets/javascripts/editor/editor_lite_extension_base.js
deleted file mode 100644
index b8d87fa4969..00000000000
--- a/app/assets/javascripts/editor/editor_lite_extension_base.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from './constants';
-
-export class EditorLiteExtension {
- constructor({ instance, ...options } = {}) {
- if (instance) {
- Object.assign(instance, options);
- } else if (Object.entries(options).length) {
- throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
- }
- }
-}
diff --git a/app/assets/javascripts/editor/editor_markdown_ext.js b/app/assets/javascripts/editor/editor_markdown_ext.js
deleted file mode 100644
index 19e0037c175..00000000000
--- a/app/assets/javascripts/editor/editor_markdown_ext.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { EditorLiteExtension } from './editor_lite_extension_base';
-
-export class EditorMarkdownExtension extends EditorLiteExtension {
- getSelectedText(selection = this.getSelection()) {
- const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
- const valArray = this.getValue().split('\n');
- let text = '';
- if (startLineNumber === endLineNumber) {
- text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
- } else {
- const startLineText = valArray[startLineNumber - 1].slice(startColumn - 1);
- const endLineText = valArray[endLineNumber - 1].slice(0, endColumn - 1);
-
- for (let i = startLineNumber, k = endLineNumber - 1; i < k; i += 1) {
- text += `${valArray[i]}`;
- if (i !== k - 1) text += `\n`;
- }
- text = text
- ? [startLineText, text, endLineText].join('\n')
- : [startLineText, endLineText].join('\n');
- }
- return text;
- }
-
- replaceSelectedText(text, select = undefined) {
- const forceMoveMarkers = !select;
- this.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
- }
-
- moveCursor(dx = 0, dy = 0) {
- const pos = this.getPosition();
- pos.column += dx;
- pos.lineNumber += dy;
- this.setPosition(pos);
- }
-
- /**
- * Adjust existing selection to select text within the original selection.
- * - If `selectedText` is not supplied, we fetch selected text with
- *
- * ALGORITHM:
- *
- * MULTI-LINE SELECTION
- * 1. Find line that contains `toSelect` text.
- * 2. Using the index of this line and the position of `toSelect` text in it,
- * construct:
- * * newStartLineNumber
- * * newStartColumn
- *
- * SINGLE-LINE SELECTION
- * 1. Use `startLineNumber` from the current selection as `newStartLineNumber`
- * 2. Find the position of `toSelect` text in it to get `newStartColumn`
- *
- * 3. `newEndLineNumber` — Since this method is supposed to be used with
- * markdown decorators that are pretty short, the `newEndLineNumber` is
- * suggested to be assumed the same as the startLine.
- * 4. `newEndColumn` — pretty obvious
- * 5. Adjust the start and end positions of the current selection
- * 6. Re-set selection on the instance
- *
- * @param {string} toSelect - New text to select within current selection.
- * @param {string} selectedText - Currently selected text. It's just a
- * shortcut: If it's not supplied, we fetch selected text from the instance
- */
- selectWithinSelection(toSelect, selectedText) {
- const currentSelection = this.getSelection();
- if (currentSelection.isEmpty() || !toSelect) {
- return;
- }
- const text = selectedText || this.getSelectedText(currentSelection);
- let lineShift;
- let newStartLineNumber;
- let newStartColumn;
-
- const textLines = text.split('\n');
-
- if (textLines.length > 1) {
- // Multi-line selection
- lineShift = textLines.findIndex(line => line.indexOf(toSelect) !== -1);
- newStartLineNumber = currentSelection.startLineNumber + lineShift;
- newStartColumn = textLines[lineShift].indexOf(toSelect) + 1;
- } else {
- // Single-line selection
- newStartLineNumber = currentSelection.startLineNumber;
- newStartColumn = currentSelection.startColumn + text.indexOf(toSelect);
- }
-
- const newEndLineNumber = newStartLineNumber;
- const newEndColumn = newStartColumn + toSelect.length;
-
- const newSelection = currentSelection
- .setStartPosition(newStartLineNumber, newStartColumn)
- .setEndPosition(newEndLineNumber, newEndColumn);
-
- this.setSelection(newSelection);
- }
-}
diff --git a/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
new file mode 100644
index 00000000000..eb47c20912e
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
@@ -0,0 +1,38 @@
+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';
+
+export class CiSchemaExtension extends EditorLiteExtension {
+ /**
+ * Registers a syntax schema to the editor based on project
+ * identifier and commit.
+ *
+ * The schema is added to the file that is currently edited
+ * in the editor.
+ *
+ * @param {Object} opts
+ * @param {String} opts.projectNamespace
+ * @param {String} opts.projectPath
+ * @param {String?} opts.ref - Current ref. Defaults to master
+ */
+ registerCiSchema({ projectNamespace, projectPath, ref = 'master' } = {}) {
+ const ciSchemaPath = Api.buildUrl(Api.projectFileSchemaPath)
+ .replace(':namespace_path', projectNamespace)
+ .replace(':project_path', projectPath)
+ .replace(':ref', ref)
+ .replace(':filename', EXTENSION_CI_SCHEMA_FILE_NAME_MATCH);
+ // In order for workers loaded from `data://` as the
+ // ones loaded by monaco editor, we use absolute URLs
+ // to fetch schema files, hence the `gon.gitlab_url`
+ // reference. This prevents error:
+ // "Failed to execute 'fetch' on 'WorkerGlobalScope'"
+ const absoluteSchemaUrl = gon.gitlab_url + ciSchemaPath;
+ const modelFileName = this.getModel().uri.path.split('/').pop();
+
+ registerSchema({
+ uri: absoluteSchemaUrl,
+ fileMatch: [modelFileName],
+ });
+ }
+}
diff --git a/app/assets/javascripts/editor/editor_file_template_ext.js b/app/assets/javascripts/editor/extensions/editor_file_template_ext.js
index f5474318447..f5474318447 100644
--- a/app/assets/javascripts/editor/editor_file_template_ext.js
+++ b/app/assets/javascripts/editor/extensions/editor_file_template_ext.js
diff --git a/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js b/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
new file mode 100644
index 00000000000..8d350068973
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
@@ -0,0 +1,11 @@
+import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from '../constants';
+
+export class EditorLiteExtension {
+ constructor({ instance, ...options } = {}) {
+ if (instance) {
+ Object.assign(instance, options);
+ } else if (Object.entries(options).length) {
+ throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
+ }
+ }
+}
diff --git a/app/assets/javascripts/editor/extensions/editor_markdown_ext.js b/app/assets/javascripts/editor/extensions/editor_markdown_ext.js
new file mode 100644
index 00000000000..2ce003753f7
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/editor_markdown_ext.js
@@ -0,0 +1,97 @@
+import { EditorLiteExtension } from './editor_lite_extension_base';
+
+export class EditorMarkdownExtension extends EditorLiteExtension {
+ getSelectedText(selection = this.getSelection()) {
+ const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
+ const valArray = this.getValue().split('\n');
+ let text = '';
+ if (startLineNumber === endLineNumber) {
+ text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
+ } else {
+ const startLineText = valArray[startLineNumber - 1].slice(startColumn - 1);
+ const endLineText = valArray[endLineNumber - 1].slice(0, endColumn - 1);
+
+ for (let i = startLineNumber, k = endLineNumber - 1; i < k; i += 1) {
+ text += `${valArray[i]}`;
+ if (i !== k - 1) text += `\n`;
+ }
+ text = text
+ ? [startLineText, text, endLineText].join('\n')
+ : [startLineText, endLineText].join('\n');
+ }
+ return text;
+ }
+
+ replaceSelectedText(text, select = undefined) {
+ const forceMoveMarkers = !select;
+ this.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
+ }
+
+ moveCursor(dx = 0, dy = 0) {
+ const pos = this.getPosition();
+ pos.column += dx;
+ pos.lineNumber += dy;
+ this.setPosition(pos);
+ }
+
+ /**
+ * Adjust existing selection to select text within the original selection.
+ * - If `selectedText` is not supplied, we fetch selected text with
+ *
+ * ALGORITHM:
+ *
+ * MULTI-LINE SELECTION
+ * 1. Find line that contains `toSelect` text.
+ * 2. Using the index of this line and the position of `toSelect` text in it,
+ * construct:
+ * * newStartLineNumber
+ * * newStartColumn
+ *
+ * SINGLE-LINE SELECTION
+ * 1. Use `startLineNumber` from the current selection as `newStartLineNumber`
+ * 2. Find the position of `toSelect` text in it to get `newStartColumn`
+ *
+ * 3. `newEndLineNumber` — Since this method is supposed to be used with
+ * markdown decorators that are pretty short, the `newEndLineNumber` is
+ * suggested to be assumed the same as the startLine.
+ * 4. `newEndColumn` — pretty obvious
+ * 5. Adjust the start and end positions of the current selection
+ * 6. Re-set selection on the instance
+ *
+ * @param {string} toSelect - New text to select within current selection.
+ * @param {string} selectedText - Currently selected text. It's just a
+ * shortcut: If it's not supplied, we fetch selected text from the instance
+ */
+ selectWithinSelection(toSelect, selectedText) {
+ const currentSelection = this.getSelection();
+ if (currentSelection.isEmpty() || !toSelect) {
+ return;
+ }
+ const text = selectedText || this.getSelectedText(currentSelection);
+ let lineShift;
+ let newStartLineNumber;
+ let newStartColumn;
+
+ const textLines = text.split('\n');
+
+ if (textLines.length > 1) {
+ // Multi-line selection
+ lineShift = textLines.findIndex((line) => line.indexOf(toSelect) !== -1);
+ newStartLineNumber = currentSelection.startLineNumber + lineShift;
+ newStartColumn = textLines[lineShift].indexOf(toSelect) + 1;
+ } else {
+ // Single-line selection
+ newStartLineNumber = currentSelection.startLineNumber;
+ newStartColumn = currentSelection.startColumn + text.indexOf(toSelect);
+ }
+
+ const newEndLineNumber = newStartLineNumber;
+ const newEndColumn = newStartColumn + toSelect.length;
+
+ const newSelection = currentSelection
+ .setStartPosition(newStartLineNumber, newStartColumn)
+ .setEndPosition(newEndLineNumber, newEndColumn);
+
+ this.setSelection(newSelection);
+ }
+}
diff --git a/app/assets/javascripts/editor/utils.js b/app/assets/javascripts/editor/utils.js
index d8b6396b671..af4473413f4 100644
--- a/app/assets/javascripts/editor/utils.js
+++ b/app/assets/javascripts/editor/utils.js
@@ -1,4 +1,4 @@
-export const clearDomElement = el => {
+export const clearDomElement = (el) => {
if (!el || !el.firstChild) return;
while (el.firstChild) {
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index 4a56843c0b5..fa1024a74a4 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -35,7 +35,7 @@ async function prepareEmojiMap() {
validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)];
- Object.keys(emojiMap).forEach(name => {
+ Object.keys(emojiMap).forEach((name) => {
emojiMap[name].aliases = [];
emojiMap[name].name = name;
});
@@ -122,23 +122,23 @@ const searchMatchers = {
const searchPredicates = {
// Search by name
- name: (matcher, query) => emoji => {
+ 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 => {
+ 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 => {
+ 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 => {
+ unicode: (matcher, query) => (emoji) => {
return [{ emoji, field: emoji.e, success: emoji.e === query }];
},
};
@@ -196,18 +196,18 @@ export function searchEmoji(query, opts) {
}
const matcher = searchMatchers[match] || searchMatchers.exact;
- const predicates = fields.map(f => searchPredicates[f](matcher, query));
+ const predicates = fields.map((f) => searchPredicates[f](matcher, query));
const results = Object.values(emojiMap)
- .flatMap(emoji => predicates.flatMap(predicate => predicate(emoji)))
- .filter(r => r.success);
+ .flatMap((emoji) => predicates.flatMap((predicate) => predicate(emoji)))
+ .filter((r) => r.success);
// Fallback to question mark for unknown emojis
if (fallback && results.length === 0) {
return raw ? [{ emoji: fallbackEmoji }] : [fallbackEmoji];
}
- return raw ? results : results.map(r => r.emoji);
+ return raw ? results : results.map((r) => r.emoji);
}
let emojiCategoryMap;
@@ -223,7 +223,7 @@ export function getEmojiCategoryMap() {
symbols: [],
flags: [],
};
- Object.keys(emojiMap).forEach(name => {
+ Object.keys(emojiMap).forEach((name) => {
const emoji = emojiMap[name];
if (emojiCategoryMap[emoji.c]) {
emojiCategoryMap[emoji.c].push(name);
@@ -242,8 +242,9 @@ export function getEmojiInfo(query) {
export function emojiFallbackImageSrc(inputName) {
const { name } = getEmojiInfo(inputName);
- return `${gon.asset_host || ''}${gon.relative_url_root ||
- ''}/-/emojis/${EMOJI_VERSION}/${name}.png`;
+ return `${gon.asset_host || ''}${
+ gon.relative_url_root || ''
+ }/-/emojis/${EMOJI_VERSION}/${name}.png`;
}
export function emojiImageTag(name, src) {
diff --git a/app/assets/javascripts/emoji/no_emoji_validator.js b/app/assets/javascripts/emoji/no_emoji_validator.js
index edef868619a..85c8204225a 100644
--- a/app/assets/javascripts/emoji/no_emoji_validator.js
+++ b/app/assets/javascripts/emoji/no_emoji_validator.js
@@ -9,7 +9,7 @@ export default class NoEmojiValidator extends InputValidator {
const container = opts.container || '';
this.noEmojiEmelents = document.querySelectorAll(`${container} .js-block-emoji`);
- this.noEmojiEmelents.forEach(element =>
+ this.noEmojiEmelents.forEach((element) =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
diff --git a/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js b/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
index c5f9fcf6358..cf9794e6a87 100644
--- a/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
+++ b/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
@@ -33,7 +33,7 @@ const tone5 = 127999; // parseInt('1F3FF', 16)
function isSkinToneComboEmoji(emojiUnicode) {
return (
emojiUnicode.length > 2 &&
- Array.from(emojiUnicode).some(char => {
+ Array.from(emojiUnicode).some((char) => {
const cp = char.codePointAt(0);
return cp >= tone1 && cp <= tone5;
})
@@ -60,7 +60,7 @@ const personEndCodePoint = 128105; // parseInt('1F469', 16)
function isPersonZwjEmoji(emojiUnicode) {
let hasPersonEmoji = false;
let hasZwj = false;
- Array.from(emojiUnicode).forEach(character => {
+ Array.from(emojiUnicode).forEach((character) => {
const cp = character.codePointAt(0);
if (cp === zwj) {
hasZwj = true;
diff --git a/app/assets/javascripts/emoji/support/unicode_support_map.js b/app/assets/javascripts/emoji/support/unicode_support_map.js
index 651169391fe..fe3bc75f9fd 100644
--- a/app/assets/javascripts/emoji/support/unicode_support_map.js
+++ b/app/assets/javascripts/emoji/support/unicode_support_map.js
@@ -89,9 +89,9 @@ function generateUnicodeSupportMap(testMap) {
ctx.font = `${fontSize}px "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`;
// Write each emoji to the canvas vertically
let writeIndex = 0;
- testMapKeys.forEach(testKey => {
+ testMapKeys.forEach((testKey) => {
const testEntry = testMap[testKey];
- [].concat(testEntry).forEach(emojiUnicode => {
+ [].concat(testEntry).forEach((emojiUnicode) => {
ctx.fillText(emojiUnicode, 0, writeIndex * fontSize + fontSize / 2);
writeIndex += 1;
});
@@ -100,11 +100,11 @@ function generateUnicodeSupportMap(testMap) {
// Read from the canvas
const resultMap = {};
let readIndex = 0;
- testMapKeys.forEach(testKey => {
+ testMapKeys.forEach((testKey) => {
const testEntry = testMap[testKey];
// This needs to be a `reduce` instead of `every` because we need to
// keep the `readIndex` in sync from the writes by running all entries
- const isTestSatisfied = [].concat(testEntry).reduce(isSatisfied => {
+ const isTestSatisfied = [].concat(testEntry).reduce((isSatisfied) => {
// Sample along the vertical-middle for a couple of characters
const imageData = ctx.getImageData(0, readIndex * fontSize + fontSize / 2, 2 * fontSize, 1)
.data;
diff --git a/app/assets/javascripts/environments/components/canary_ingress.vue b/app/assets/javascripts/environments/components/canary_ingress.vue
new file mode 100644
index 00000000000..f8cdbb96bc2
--- /dev/null
+++ b/app/assets/javascripts/environments/components/canary_ingress.vue
@@ -0,0 +1,109 @@
+<script>
+import { uniqueId } from 'lodash';
+import { GlDropdown, GlDropdownItem, GlModalDirective as GlModal } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { CANARY_UPDATE_MODAL } from '../constants';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ directives: {
+ GlModal,
+ },
+ props: {
+ canaryIngress: {
+ required: true,
+ type: Object,
+ },
+ },
+ ingressOptions: Array(100 / 5 + 1)
+ .fill(0)
+ .map((_, i) => i * 5),
+
+ translations: {
+ stableLabel: s__('CanaryIngress|Stable'),
+ canaryLabel: s__('CanaryIngress|Canary'),
+ },
+
+ CANARY_UPDATE_MODAL,
+
+ css: {
+ label: [
+ 'gl-font-base',
+ 'gl-font-weight-normal',
+ 'gl-line-height-normal',
+ 'gl-inset-border-1-gray-200',
+ 'gl-py-3',
+ 'gl-px-4',
+ 'gl-mb-0',
+ ],
+ },
+ computed: {
+ stableWeightId() {
+ return uniqueId('stable-weight-');
+ },
+ canaryWeightId() {
+ return uniqueId('canary-weight-');
+ },
+ stableWeight() {
+ return (100 - this.canaryIngress.canary_weight).toString();
+ },
+ canaryWeight() {
+ return this.canaryIngress.canary_weight.toString();
+ },
+ },
+ methods: {
+ changeCanary(weight) {
+ this.$emit('change', weight);
+ },
+ changeStable(weight) {
+ this.$emit('change', 100 - weight);
+ },
+ },
+};
+</script>
+<template>
+ <section class="gl-display-flex gl-bg-white gl-m-3">
+ <div class="gl-display-flex gl-flex-direction-column">
+ <label :for="stableWeightId" :class="$options.css.label" class="gl-rounded-top-left-base">
+ {{ $options.translations.stableLabel }}
+ </label>
+ <gl-dropdown
+ :id="stableWeightId"
+ :text="stableWeight"
+ data-testid="stable-weight"
+ class="gl-w-full"
+ toggle-class="gl-rounded-top-left-none! gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
+ >
+ <gl-dropdown-item
+ v-for="option in $options.ingressOptions"
+ :key="option"
+ v-gl-modal="$options.CANARY_UPDATE_MODAL"
+ @click="changeStable(option)"
+ >{{ option }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ <div class="gl-display-flex gl-display-flex gl-flex-direction-column">
+ <label :for="canaryWeightId" :class="$options.css.label" class="gl-rounded-top-right-base">{{
+ $options.translations.canaryLabel
+ }}</label>
+ <gl-dropdown
+ :id="canaryWeightId"
+ :text="canaryWeight"
+ data-testid="canary-weight"
+ toggle-class="gl-rounded-top-left-none! gl-rounded-top-right-none! gl-rounded-bottom-left-none! gl-border-l-none!"
+ >
+ <gl-dropdown-item
+ v-for="option in $options.ingressOptions"
+ :key="option"
+ v-gl-modal="$options.CANARY_UPDATE_MODAL"
+ @click="changeCanary(option)"
+ >{{ option }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/environments/components/canary_update_modal.vue b/app/assets/javascripts/environments/components/canary_update_modal.vue
new file mode 100644
index 00000000000..fc63d6272c8
--- /dev/null
+++ b/app/assets/javascripts/environments/components/canary_update_modal.vue
@@ -0,0 +1,133 @@
+<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';
+
+export default {
+ components: {
+ GlAlert,
+ GlModal,
+ GlSprintf,
+ },
+ props: {
+ environment: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ weight: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ visible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ translations: {
+ title: s__('CanaryIngress|Change the ratio of canary deployments?'),
+ ratioChange: s__(
+ 'CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:',
+ ),
+ stableWeight: s__('CanaryIngress|%{boldStart}Stable:%{boldEnd} %{stable}'),
+ canaryWeight: s__('CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}'),
+ deploymentWarning: s__(
+ 'CanaryIngress|Doing so will set a deployment change in progress. This temporarily blocks any further configuration until the deployment is finished.',
+ ),
+ },
+ modal: {
+ modalId: CANARY_UPDATE_MODAL,
+ actionPrimary: {
+ text: s__('CanaryIngress|Change ratio'),
+ attributes: [{ variant: 'info' }],
+ },
+ actionCancel: { text: __('Cancel') },
+ static: true,
+ },
+ data() {
+ return { error: '', dismissed: true };
+ },
+ computed: {
+ stableWeight() {
+ return (100 - this.weight).toString();
+ },
+ canaryWeight() {
+ return this.weight.toString();
+ },
+ hasError() {
+ return Boolean(this.error);
+ },
+ environmentName() {
+ return this.environment?.name ?? '';
+ },
+ },
+ methods: {
+ submitCanaryChange() {
+ return this.$apollo
+ .mutate({
+ mutation: updateCanaryIngress,
+ variables: {
+ input: {
+ id: this.environment.global_id,
+ weight: this.weight,
+ },
+ },
+ })
+ .then(
+ ({
+ data: {
+ environmentsCanaryIngressUpdate: {
+ errors: [error],
+ },
+ },
+ }) => {
+ this.error = error;
+ },
+ )
+ .catch(() => {
+ this.error = __('Something went wrong. Please try again later');
+ });
+ },
+ dismiss() {
+ this.error = '';
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-alert v-if="hasError" variant="danger" @dismiss="dismiss">{{ error }}</gl-alert>
+ <gl-modal v-bind="$options.modal" :visible="visible" @primary="submitCanaryChange">
+ <template #modal-title>{{ $options.translations.title }}</template>
+ <template #default>
+ <p>
+ <gl-sprintf :message="$options.translations.ratioChange">
+ <template #environment>{{ environmentName }}</template>
+ </gl-sprintf>
+ </p>
+ <ul class="gl-list-style-none gl-p-0">
+ <li>
+ <gl-sprintf :message="$options.translations.stableWeight">
+ <template #bold="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ <template #stable>{{ stableWeight }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf :message="$options.translations.canaryWeight">
+ <template #bold="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ <template #canary>{{ canaryWeight }}</template>
+ </gl-sprintf>
+ </li>
+ </ul>
+ <p>{{ $options.translations.deploymentWarning }}</p>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index e7697f14802..c6b34fecbb7 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -10,11 +10,6 @@ export default {
GlLoadingIcon,
},
props: {
- canaryDeploymentFeatureId: {
- type: String,
- required: false,
- default: null,
- },
isLoading: {
type: Boolean,
required: true,
@@ -46,11 +41,6 @@ export default {
required: false,
default: '',
},
- showCanaryDeploymentCallout: {
- type: Boolean,
- required: false,
- default: false,
- },
userCalloutsPath: {
type: String,
required: false,
@@ -75,8 +65,6 @@ export default {
<environment-table
:environments="environments"
:can-read-environment="canReadEnvironment"
- :canary-deployment-feature-id="canaryDeploymentFeatureId"
- :show-canary-deployment-callout="showCanaryDeploymentCallout"
:user-callouts-path="userCalloutsPath"
:lock-promotion-svg-path="lockPromotionSvgPath"
:help-canary-deployments-path="helpCanaryDeploymentsPath"
diff --git a/app/assets/javascripts/environments/components/deploy_board.vue b/app/assets/javascripts/environments/components/deploy_board.vue
new file mode 100644
index 00000000000..07cb968d8d3
--- /dev/null
+++ b/app/assets/javascripts/environments/components/deploy_board.vue
@@ -0,0 +1,216 @@
+<script>
+/* eslint-disable @gitlab/vue-require-i18n-strings */
+/**
+ * Renders a deploy board.
+ *
+ * A deploy board is composed by:
+ * - Information area with percentage of completion.
+ * - Instances with status.
+ * - Button Actions.
+ * [Mockup](https://gitlab.com/gitlab-org/gitlab-foss/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png)
+ */
+import { isEmpty } from 'lodash';
+import {
+ GlIcon,
+ GlLoadingIcon,
+ GlLink,
+ GlTooltip,
+ 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 { n__ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { STATUS_MAP, CANARY_STATUS } from '../constants';
+import CanaryIngress from './canary_ingress.vue';
+
+export default {
+ components: {
+ instanceComponent,
+ CanaryIngress,
+ GlIcon,
+ GlLoadingIcon,
+ GlLink,
+ GlTooltip,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ deployBoardData: {
+ type: Object,
+ required: true,
+ },
+ deployBoardsHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ isLoading: {
+ type: Boolean,
+ required: true,
+ },
+ isEmpty: {
+ type: Boolean,
+ required: true,
+ },
+ logsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ canRenderDeployBoard() {
+ return !this.isEmpty && !isEmpty(this.deployBoardData);
+ },
+ canRenderEmptyState() {
+ return this.isEmpty;
+ },
+ canRenderCanaryWeight() {
+ return (
+ this.glFeatures.canaryIngressWeightControl && !isEmpty(this.deployBoardData.canary_ingress)
+ );
+ },
+ instanceCount() {
+ const { instances } = this.deployBoardData;
+
+ return Array.isArray(instances) ? instances.length : 0;
+ },
+ instanceIsCompletedCount() {
+ const completionPercentage = this.deployBoardData.completion / 100;
+ const completionCount = Math.floor(completionPercentage * this.instanceCount);
+
+ return Number.isNaN(completionCount) ? 0 : completionCount;
+ },
+ instanceIsCompletedText() {
+ const title = n__('instance completed', 'instances completed', this.instanceIsCompletedCount);
+
+ return `${this.instanceIsCompletedCount} ${title}`;
+ },
+ instanceTitle() {
+ return n__('Instance', 'Instances', this.instanceCount);
+ },
+ deployBoardSvg() {
+ return deployBoardSvg;
+ },
+ deployBoardActions() {
+ return this.deployBoardData.rollback_url || this.deployBoardData.abort_url;
+ },
+ statuses() {
+ // Canary is not a pod status but it needs to be in the legend.
+ // Hence adding it here.
+ return {
+ ...STATUS_MAP,
+ CANARY_STATUS,
+ };
+ },
+ },
+ methods: {
+ changeCanaryWeight(weight) {
+ this.$emit('changeCanaryWeight', weight);
+ },
+ },
+};
+</script>
+<template>
+ <div class="js-deploy-board deploy-board">
+ <gl-loading-icon v-if="isLoading" class="loading-icon" />
+ <template v-else>
+ <div v-if="canRenderDeployBoard" class="deploy-board-information gl-p-5">
+ <div class="deploy-board-information gl-w-full">
+ <section class="deploy-board-status">
+ <span v-gl-tooltip :title="instanceIsCompletedText">
+ <span ref="percentage" class="gl-text-center text-plain gl-font-lg"
+ >{{ deployBoardData.completion }}%</span
+ >
+ <span class="text text-center text-secondary">{{ __('Complete') }}</span>
+ </span>
+ </section>
+
+ <section class="deploy-board-instances">
+ <div class="gl-font-base text-secondary">
+ <span class="deploy-board-instances-text"
+ >{{ instanceTitle }} ({{ instanceCount }})</span
+ >
+ <span ref="legend-icon" data-testid="legend-tooltip-target">
+ <gl-icon class="gl-text-blue-500 gl-ml-2" name="question" />
+ </span>
+ <gl-tooltip :target="() => $refs['legend-icon']" boundary="#content-body">
+ <div class="deploy-board-legend gl-display-flex gl-flex-direction-column">
+ <div
+ v-for="status in statuses"
+ :key="status.text"
+ class="gl-display-flex gl-align-items-center"
+ >
+ <instance-component :status="status.class" :stable="status.stable" />
+ <span class="legend-text gl-ml-3">{{ status.text }}</span>
+ </div>
+ </div>
+ </gl-tooltip>
+ </div>
+
+ <div class="deploy-board-instances-container d-flex flex-wrap flex-row">
+ <template v-for="(instance, i) in deployBoardData.instances">
+ <instance-component
+ :key="i"
+ :status="instance.status"
+ :tooltip-text="instance.tooltip"
+ :pod-name="instance.pod_name"
+ :logs-path="logsPath"
+ :stable="instance.stable"
+ />
+ </template>
+ </div>
+ </section>
+
+ <canary-ingress
+ v-if="canRenderCanaryWeight"
+ class="deploy-board-canary-ingress"
+ :canary-ingress="deployBoardData.canary_ingress"
+ @change="changeCanaryWeight"
+ />
+
+ <section v-if="deployBoardActions" class="deploy-board-actions">
+ <gl-link
+ v-if="deployBoardData.rollback_url"
+ :href="deployBoardData.rollback_url"
+ class="btn"
+ data-method="post"
+ rel="nofollow"
+ >{{ __('Rollback') }}</gl-link
+ >
+ <gl-link
+ v-if="deployBoardData.abort_url"
+ :href="deployBoardData.abort_url"
+ class="btn btn-danger btn-inverted"
+ data-method="post"
+ rel="nofollow"
+ >{{ __('Abort') }}</gl-link
+ >
+ </section>
+ </div>
+ </div>
+
+ <div v-if="canRenderEmptyState" class="deploy-board-empty">
+ <section v-safe-html="deployBoardSvg" class="deploy-board-empty-state-svg"></section>
+
+ <section class="deploy-board-empty-state-text">
+ <span class="deploy-board-empty-state-title d-flex">{{
+ __('Kubernetes deployment not found')
+ }}</span>
+ <span>
+ To see deployment progress for your environments, make sure you are deploying to
+ <code>$KUBE_NAMESPACE</code> and annotating with
+ <code>app.gitlab.com/app=$CI_PROJECT_PATH_SLUG</code>
+ and
+ <code>app.gitlab.com/env=$CI_ENVIRONMENT_SLUG</code>.
+ </span>
+ </section>
+ </div>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 347828888dc..1724cc692bd 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -226,7 +226,7 @@ export default {
{ deep: true },
);
const combinedActions = (manualActions || []).concat(scheduledActions || []);
- return combinedActions.map(action => ({
+ return combinedActions.map((action) => ({
...action,
name: action.name,
}));
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 32528e6c6ea..48edde82ce7 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -55,7 +55,7 @@ export default {
retryUrl: this.retryUrl,
isLastDeployment: this.isLastDeployment,
});
- eventHub.$on('rollbackEnvironment', environment => {
+ eventHub.$on('rollbackEnvironment', (environment) => {
if (environment.id === this.environment.id) {
this.isLoading = true;
}
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index b6a7cce36e9..6f68c6e864a 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -39,11 +39,6 @@ export default {
type: String,
required: true,
},
- canaryDeploymentFeatureId: {
- type: String,
- required: false,
- default: '',
- },
canCreateEnvironment: {
type: Boolean,
required: true,
@@ -75,11 +70,6 @@ export default {
required: false,
default: '',
},
- showCanaryDeploymentCallout: {
- type: Boolean,
- required: false,
- default: false,
- },
userCalloutsPath: {
type: String,
required: false,
@@ -116,7 +106,7 @@ export default {
this.service
.getFolderContent(folder.folder_path)
- .then(response => this.store.setfolderContent(folder, response.data.environments))
+ .then((response) => this.store.setfolderContent(folder, response.data.environments))
.then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false))
.catch(() => {
Flash(s__('Environments|An error occurred while fetching the environments.'));
@@ -130,7 +120,7 @@ export default {
// We need to verify if any folder is open to also update it
const openFolders = this.store.getOpenFolders();
if (openFolders.length) {
- openFolders.forEach(folder => this.fetchChildEnvironments(folder));
+ openFolders.forEach((folder) => this.fetchChildEnvironments(folder));
}
},
},
@@ -205,8 +195,6 @@ export default {
:environments="state.environments"
:pagination="state.paginationInformation"
:can-read-environment="canReadEnvironment"
- :canary-deployment-feature-id="canaryDeploymentFeatureId"
- :show-canary-deployment-callout="showCanaryDeploymentCallout"
:user-callouts-path="userCalloutsPath"
:lock-promotion-svg-path="lockPromotionSvgPath"
:help-canary-deployments-path="helpCanaryDeploymentsPath"
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index d13c7204285..bbb56ca6f26 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -6,16 +6,16 @@ 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';
export default {
components: {
EnvironmentItem,
GlLoadingIcon,
- DeployBoard: () => import('ee_component/environments/components/deploy_board_component.vue'),
- CanaryDeploymentCallout: () =>
- import('ee_component/environments/components/canary_deployment_callout.vue'),
+ DeployBoard,
EnvironmentAlert: () => import('ee_component/environments/components/environment_alert.vue'),
- CanaryUpdateModal: () => import('ee_component/environments/components/canary_update_modal.vue'),
+ CanaryUpdateModal,
},
props: {
environments: {
@@ -33,11 +33,6 @@ export default {
required: false,
default: false,
},
- canaryDeploymentFeatureId: {
- type: String,
- required: false,
- default: '',
- },
helpCanaryDeploymentsPath: {
type: String,
required: false,
@@ -48,11 +43,6 @@ export default {
required: false,
default: '',
},
- showCanaryDeploymentCallout: {
- type: Boolean,
- required: false,
- default: false,
- },
userCalloutsPath: {
type: String,
required: false,
@@ -67,7 +57,7 @@ export default {
},
computed: {
sortedEnvironments() {
- return this.sortEnvironments(this.environments).map(env =>
+ return this.sortEnvironments(this.environments).map((env) =>
this.shouldRenderFolderContent(env)
? { ...env, children: this.sortEnvironments(env.children) }
: env,
@@ -121,9 +111,6 @@ export default {
shouldRenderFolderContent(env) {
return env.isFolder && env.isOpen && env.children && env.children.length > 0;
},
- shouldShowCanaryCallout(env) {
- return env.showCanaryCallout && this.showCanaryDeploymentCallout;
- },
shouldRenderAlert(env) {
return env?.has_opened_alert;
},
@@ -144,11 +131,11 @@ export default {
* 5. Put folders first.
*/
return flow(
- sortBy(env => (env.isFolder ? env.folderName : env.name)),
+ sortBy((env) => (env.isFolder ? env.folderName : env.name)),
reverse,
- sortBy(env => (env.last_deployment ? env.last_deployment.created_at : '0000')),
+ sortBy((env) => (env.last_deployment ? env.last_deployment.created_at : '0000')),
reverse,
- sortBy(env => (env.isFolder ? -1 : 1)),
+ sortBy((env) => (env.isFolder ? -1 : 1)),
)(environments);
},
changeCanaryWeight(model, weight) {
@@ -241,17 +228,6 @@ export default {
</div>
</template>
</template>
-
- <template v-if="shouldShowCanaryCallout(model)">
- <canary-deployment-callout
- :key="`canary-promo-${i}`"
- :canary-deployment-feature-id="canaryDeploymentFeatureId"
- :user-callouts-path="userCalloutsPath"
- :lock-promotion-svg-path="lockPromotionSvgPath"
- :help-canary-deployments-path="helpCanaryDeploymentsPath"
- :data-js-canary-promo-key="i"
- />
- </template>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/environments/constants.js b/app/assets/javascripts/environments/constants.js
new file mode 100644
index 00000000000..6d427bef4e6
--- /dev/null
+++ b/app/assets/javascripts/environments/constants.js
@@ -0,0 +1,40 @@
+import { __ } from '~/locale';
+
+// These statuses are based on how the backend defines pod phases here
+// lib/gitlab/kubernetes/pod.rb
+
+export const STATUS_MAP = {
+ succeeded: {
+ class: 'succeeded',
+ text: __('Succeeded'),
+ stable: true,
+ },
+ running: {
+ class: 'running',
+ text: __('Running'),
+ stable: true,
+ },
+ failed: {
+ class: 'failed',
+ text: __('Failed'),
+ stable: true,
+ },
+ pending: {
+ class: 'pending',
+ text: __('Pending'),
+ stable: true,
+ },
+ unknown: {
+ class: 'unknown',
+ text: __('Unknown'),
+ stable: true,
+ },
+};
+
+export const CANARY_STATUS = {
+ class: 'canary-icon',
+ text: __('Canary'),
+ stable: false,
+};
+
+export const CANARY_UPDATE_MODAL = 'confirm-canary-change';
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index 6c547c3713a..e4726412f99 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -1,6 +1,5 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import canaryCalloutMixin from '../mixins/canary_callout_mixin';
import environmentsFolderApp from './environments_folder_view.vue';
import { parseBoolean } from '../../lib/utils/common_utils';
import Translate from '../../vue_shared/translate';
@@ -21,7 +20,6 @@ export default () => {
components: {
environmentsFolderApp,
},
- mixins: [canaryCalloutMixin],
apolloProvider,
provide: {
projectPath: el.dataset.projectPath,
@@ -43,7 +41,6 @@ export default () => {
folderName: this.folderName,
cssContainerClass: this.cssContainerClass,
canReadEnvironment: this.canReadEnvironment,
- ...this.canaryCalloutProps,
},
});
},
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index 25f5483c58b..dbb60fa4622 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -34,16 +34,6 @@ export default {
type: Boolean,
required: true,
},
- canaryDeploymentFeatureId: {
- type: String,
- required: false,
- default: '',
- },
- showCanaryDeploymentCallout: {
- type: Boolean,
- required: false,
- default: false,
- },
userCalloutsPath: {
type: String,
required: false,
@@ -98,8 +88,6 @@ export default {
:environments="state.environments"
:pagination="state.paginationInformation"
:can-read-environment="canReadEnvironment"
- :canary-deployment-feature-id="canaryDeploymentFeatureId"
- :show-canary-deployment-callout="showCanaryDeploymentCallout"
:user-callouts-path="userCalloutsPath"
:lock-promotion-svg-path="lockPromotionSvgPath"
:help-canary-deployments-path="helpCanaryDeploymentsPath"
diff --git a/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql
new file mode 100644
index 00000000000..04ea5cbcaef
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql
@@ -0,0 +1,5 @@
+mutation($input: EnvironmentsCanaryIngressUpdateInput!) {
+ environmentsCanaryIngressUpdate(input: $input) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index 8e8af3f32f7..4d734a457ab 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -1,6 +1,5 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import canaryCalloutMixin from './mixins/canary_callout_mixin';
import environmentsComponent from './components/environments_app.vue';
import { parseBoolean } from '../lib/utils/common_utils';
import Translate from '../vue_shared/translate';
@@ -20,7 +19,6 @@ export default () => {
components: {
environmentsComponent,
},
- mixins: [canaryCalloutMixin],
apolloProvider,
provide: {
projectPath: el.dataset.projectPath,
@@ -46,7 +44,6 @@ export default () => {
deployBoardsHelpPath: this.deployBoardsHelpPath,
canCreateEnvironment: this.canCreateEnvironment,
canReadEnvironment: this.canReadEnvironment,
- ...this.canaryCalloutProps,
},
});
},
diff --git a/app/assets/javascripts/environments/mixins/canary_callout_mixin.js b/app/assets/javascripts/environments/mixins/canary_callout_mixin.js
deleted file mode 100644
index e9f1a144cb3..00000000000
--- a/app/assets/javascripts/environments/mixins/canary_callout_mixin.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { parseBoolean } from '~/lib/utils/common_utils';
-
-export default {
- data() {
- const data = this.$options.el.dataset;
-
- return {
- canaryDeploymentFeatureId: data.environmentsDataCanaryDeploymentFeatureId,
- showCanaryDeploymentCallout: parseBoolean(data.environmentsDataShowCanaryDeploymentCallout),
- userCalloutsPath: data.environmentsDataUserCalloutsPath,
- lockPromotionSvgPath: data.environmentsDataLockPromotionSvgPath,
- helpCanaryDeploymentsPath: data.environmentsDataHelpCanaryDeploymentsPath,
- };
- },
- computed: {
- canaryCalloutProps() {
- return {
- canaryDeploymentFeatureId: this.canaryDeploymentFeatureId,
- showCanaryDeploymentCallout: this.showCanaryDeploymentCallout,
- userCalloutsPath: this.userCalloutsPath,
- lockPromotionSvgPath: this.lockPromotionSvgPath,
- helpCanaryDeploymentsPath: this.helpCanaryDeploymentsPath,
- };
- },
- },
-};
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 9b0301bba07..15a00c11ee6 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -3,7 +3,7 @@
*/
import { isEqual, isFunction, omitBy } from 'lodash';
import Visibility from 'visibilityjs';
-import EnvironmentsStore from 'ee_else_ce/environments/stores/environments_store';
+import EnvironmentsStore from '../stores/environments_store';
import Poll from '../../lib/utils/poll';
import { getParameterByName } from '../../lib/utils/common_utils';
import { s__ } from '../../locale';
@@ -64,7 +64,7 @@ export default {
},
filterNilValues(obj) {
- return omitBy(obj, value => value === undefined || value === null);
+ return omitBy(obj, (value) => value === undefined || value === null);
},
/**
@@ -80,7 +80,7 @@ export default {
// fetch new data
return this.service
.fetchEnvironments(this.requestData)
- .then(response => {
+ .then((response) => {
this.successCallback(response);
this.poll.enable({ data: this.requestData, response });
})
@@ -107,7 +107,7 @@ export default {
this.service
.postAction(endpoint)
.then(() => this.fetchEnvironments())
- .catch(err => {
+ .catch((err) => {
this.isLoading = false;
Flash(isFunction(errorMessage) ? errorMessage(err.response.data) : errorMessage);
});
@@ -219,7 +219,7 @@ export default {
data: this.requestData,
successCallback: this.successCallback,
errorCallback: this.errorCallback,
- notificationCallback: isMakingRequest => {
+ notificationCallback: (isMakingRequest) => {
this.isMakingRequest = isMakingRequest;
},
});
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index 1992e753255..8911885e920 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -1,4 +1,4 @@
-import { setDeployBoard } from 'ee_else_ce/environments/stores/helpers';
+import { setDeployBoard } from './helpers';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
/**
@@ -46,9 +46,9 @@ export default class EnvironmentsStore {
* @returns {Array}
*/
storeEnvironments(environments = []) {
- const filteredEnvironments = environments.map(env => {
+ const filteredEnvironments = environments.map((env) => {
const oldEnvironmentState =
- this.state.environments.find(element => {
+ this.state.environments.find((element) => {
if (env.latest) {
return element.id === env.latest.id;
}
@@ -135,12 +135,22 @@ export default class EnvironmentsStore {
/**
* Toggles deploy board visibility for the provided environment ID.
- * Currently only works on EE.
*
* @param {Object} environment
* @return {Array}
*/
- toggleDeployBoard() {
+ toggleDeployBoard(environmentID) {
+ const environments = this.state.environments.slice();
+
+ this.state.environments = environments.map((env) => {
+ let updated = { ...env };
+
+ if (env.id === environmentID) {
+ updated = { ...updated, isDeployBoardVisible: !env.isDeployBoardVisible };
+ }
+ return updated;
+ });
+
return this.state.environments;
}
@@ -163,7 +173,7 @@ export default class EnvironmentsStore {
* @return {Object}
*/
setfolderContent(folder, environments) {
- const updatedEnvironments = environments.map(env => {
+ const updatedEnvironments = environments.map((env) => {
let updated = env;
if (env.latest) {
@@ -192,7 +202,7 @@ export default class EnvironmentsStore {
updateEnvironmentProp(environment, prop, newValue) {
const { environments } = this.state;
- const updatedEnvironments = environments.map(env => {
+ const updatedEnvironments = environments.map((env) => {
const updateEnv = { ...env };
if (env.id === environment.id) {
updateEnv[prop] = newValue;
@@ -207,6 +217,6 @@ export default class EnvironmentsStore {
getOpenFolders() {
const { environments } = this.state;
- return environments.filter(env => env.isFolder && env.isOpen);
+ return environments.filter((env) => env.isFolder && env.isOpen);
}
}
diff --git a/app/assets/javascripts/environments/stores/helpers.js b/app/assets/javascripts/environments/stores/helpers.js
index eb47ba29412..89457da0614 100644
--- a/app/assets/javascripts/environments/stores/helpers.js
+++ b/app/assets/javascripts/environments/stores/helpers.js
@@ -1,7 +1,22 @@
/**
- * Deploy boards are EE only.
- *
* @param {Object} environment
* @returns {Object}
*/
-export const setDeployBoard = (oldEnvironmentState, environment) => environment;
+export const setDeployBoard = (oldEnvironmentState, environment) => {
+ let parsedEnvironment = environment;
+ if (environment.size === 1 && environment.rollout_status) {
+ parsedEnvironment = {
+ ...environment,
+ hasDeployBoard: true,
+ isDeployBoardVisible:
+ oldEnvironmentState.isDeployBoardVisible === false
+ ? oldEnvironmentState.isDeployBoardVisible
+ : true,
+ deployBoardData:
+ environment.rollout_status.status === 'found' ? environment.rollout_status : {},
+ isLoadingDeployBoard: environment.rollout_status.status === 'loading',
+ isEmptyDeployBoard: environment.rollout_status.status === 'not_found',
+ };
+ }
+ return parsedEnvironment;
+};
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 8272260705b..e21c6b62b91 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -87,7 +87,7 @@ export default {
};
},
pollInterval: 2000,
- update: data => data.project.sentryErrors.detailedError,
+ update: (data) => data.project.sentryErrors.detailedError,
error: () => createFlash(__('Failed to load error details from Sentry.')),
result(res) {
if (res.data.project?.sentryErrors?.detailedError) {
@@ -213,7 +213,7 @@ export default {
this.errorStatus === errorStatus.RESOLVED ? errorStatus.UNRESOLVED : errorStatus.RESOLVED;
// eslint-disable-next-line promise/catch-or-return
- this.updateResolveStatus({ endpoint: this.issueUpdatePath, status }).then(res => {
+ this.updateResolveStatus({ endpoint: this.issueUpdatePath, status }).then((res) => {
this.closedIssueId = res.closed_issue_iid;
if (this.closedIssueId) {
this.isAlertVisible = true;
diff --git a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
index c3471346a63..dd320676e98 100644
--- a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
+++ b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
@@ -100,7 +100,7 @@ export default {
/>
<gl-sprintf v-if="errorFn" :message="__('%{spanStart}in%{spanEnd} %{errorFn}')">
- <template #span="{content}">
+ <template #span="{ content }">
<span class="gl-text-gray-200">{{ content }}&nbsp;</span>
</template>
<template #errorFn>
@@ -109,7 +109,7 @@ export default {
</gl-sprintf>
<gl-sprintf :message="__('%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}')">
- <template #span="{content}">
+ <template #span="{ content }">
<span class="gl-text-gray-200">{{ content }}&nbsp;</span>
</template>
<template #errorLine>
diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js
index b52405248d8..8f1e7e0b959 100644
--- a/app/assets/javascripts/error_tracking/store/actions.js
+++ b/app/assets/javascripts/error_tracking/store/actions.js
@@ -11,7 +11,7 @@ export const setStatus = ({ commit }, status) => {
export const updateStatus = ({ commit }, { endpoint, redirectUrl, status }) =>
service
.updateErrorStatus(endpoint, status)
- .then(resp => {
+ .then((resp) => {
commit(types.SET_ERROR_STATUS, status);
if (redirectUrl) visitUrl(redirectUrl);
diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js
index df5be5224a7..394dec938cf 100644
--- a/app/assets/javascripts/error_tracking/store/details/actions.js
+++ b/app/assets/javascripts/error_tracking/store/details/actions.js
@@ -6,7 +6,7 @@ import { __ } from '~/locale';
let stackTracePoll;
-const stopPolling = poll => {
+const stopPolling = (poll) => {
if (poll) poll.stop();
};
diff --git a/app/assets/javascripts/error_tracking/store/details/getters.js b/app/assets/javascripts/error_tracking/store/details/getters.js
index a3b31436c81..4e159b3931f 100644
--- a/app/assets/javascripts/error_tracking/store/details/getters.js
+++ b/app/assets/javascripts/error_tracking/store/details/getters.js
@@ -1,4 +1,4 @@
-export const stacktrace = state =>
+export const stacktrace = (state) =>
state.stacktraceData.stack_trace_entries
? state.stacktraceData.stack_trace_entries.reverse()
: [];
diff --git a/app/assets/javascripts/error_tracking/store/list/mutations.js b/app/assets/javascripts/error_tracking/store/list/mutations.js
index be0cd4de78d..84a62fa9024 100644
--- a/app/assets/javascripts/error_tracking/store/list/mutations.js
+++ b/app/assets/javascripts/error_tracking/store/list/mutations.js
@@ -17,7 +17,7 @@ export default {
return;
}
// remove any existing item, then add it to the start of the list
- const recentSearches = state.recentSearches.filter(s => s !== searchTerm);
+ const recentSearches = state.recentSearches.filter((s) => s !== searchTerm);
recentSearches.unshift(searchTerm);
// only keep the last 5
state.recentSearches = recentSearches.slice(0, 5);
@@ -60,7 +60,7 @@ export default {
state.endpoint = endpoint;
},
[types.REMOVE_IGNORED_RESOLVED_ERRORS](state, error) {
- state.errors = state.errors.filter(err => err.id !== error);
+ state.errors = state.errors.filter((err) => err.id !== error);
},
[types.SET_STATUS_FILTER](state, query) {
state.statusFilter = query;
diff --git a/app/assets/javascripts/error_tracking/utils.js b/app/assets/javascripts/error_tracking/utils.js
index 5b705cc5510..aeed5450022 100644
--- a/app/assets/javascripts/error_tracking/utils.js
+++ b/app/assets/javascripts/error_tracking/utils.js
@@ -4,7 +4,7 @@
* Tracks snowplow event when User clicks on error link to Sentry
* @param {String} externalUrl that will be send as a property for the event
*/
-export const trackClickErrorLinkToSentryOptions = url => ({
+export const trackClickErrorLinkToSentryOptions = (url) => ({
category: 'Error Tracking',
action: 'click_error_link_to_sentry',
label: 'Error Link',
@@ -30,7 +30,7 @@ export const trackErrorDetailsViewsOptions = {
/**
* Tracks snowplow event when error status is updated
*/
-export const trackErrorStatusUpdateOptions = status => ({
+export const trackErrorStatusUpdateOptions = (status) => ({
category: 'Error Tracking',
action: `update_${status}_status`,
});
diff --git a/app/assets/javascripts/error_tracking_settings/store/actions.js b/app/assets/javascripts/error_tracking_settings/store/actions.js
index 27433178c8e..2821798f82d 100644
--- a/app/assets/javascripts/error_tracking_settings/store/actions.js
+++ b/app/assets/javascripts/error_tracking_settings/store/actions.js
@@ -63,7 +63,7 @@ export const updateSettings = ({ dispatch, state }) => {
.then(() => {
refreshCurrentPage();
})
- .catch(err => {
+ .catch((err) => {
dispatch('receiveSettingsError', err);
});
};
diff --git a/app/assets/javascripts/error_tracking_settings/store/getters.js b/app/assets/javascripts/error_tracking_settings/store/getters.js
index a02a4310ab9..30828778574 100644
--- a/app/assets/javascripts/error_tracking_settings/store/getters.js
+++ b/app/assets/javascripts/error_tracking_settings/store/getters.js
@@ -2,12 +2,12 @@ import { isMatch } from 'lodash';
import { __, s__, sprintf } from '~/locale';
import { getDisplayName } from '../utils';
-export const hasProjects = state => Boolean(state.projects) && state.projects.length > 0;
+export const hasProjects = (state) => Boolean(state.projects) && state.projects.length > 0;
export const isProjectInvalid = (state, getters) =>
Boolean(state.selectedProject) &&
getters.hasProjects &&
- !state.projects.some(project => isMatch(state.selectedProject, project));
+ !state.projects.some((project) => isMatch(state.selectedProject, project));
export const dropdownLabel = (state, getters) => {
if (state.selectedProject !== null) {
@@ -19,7 +19,7 @@ export const dropdownLabel = (state, getters) => {
return s__('ErrorTracking|Select project');
};
-export const invalidProjectLabel = state => {
+export const invalidProjectLabel = (state) => {
if (state.selectedProject) {
return sprintf(
__('Project "%{name}" is no longer available. Select another project to continue.'),
@@ -31,7 +31,7 @@ export const invalidProjectLabel = state => {
return '';
};
-export const projectSelectionLabel = state => {
+export const projectSelectionLabel = (state) => {
if (state.token) {
return s__(
"ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown.",
diff --git a/app/assets/javascripts/error_tracking_settings/store/mutations.js b/app/assets/javascripts/error_tracking_settings/store/mutations.js
index e1986eb694b..1fc028093c1 100644
--- a/app/assets/javascripts/error_tracking_settings/store/mutations.js
+++ b/app/assets/javascripts/error_tracking_settings/store/mutations.js
@@ -12,7 +12,7 @@ export default {
.map(convertObjectPropsToCamelCase)
// The `pick` strips out extra properties returned from Sentry.
// Such properties could be problematic later, e.g. when checking whether `projects` contains `selectedProject`
- .map(project => pick(project, projectKeys));
+ .map((project) => pick(project, projectKeys));
},
[types.RESET_CONNECT](state) {
state.connectSuccessful = false;
diff --git a/app/assets/javascripts/error_tracking_settings/utils.js b/app/assets/javascripts/error_tracking_settings/utils.js
index 9a09702a030..5d18ac8e802 100644
--- a/app/assets/javascripts/error_tracking_settings/utils.js
+++ b/app/assets/javascripts/error_tracking_settings/utils.js
@@ -13,4 +13,4 @@ export const transformFrontendSettings = ({ apiHost, enabled, token, selectedPro
return { api_host: apiHost || null, enabled, token: token || null, project };
};
-export const getDisplayName = project => `${project.organizationName} | ${project.slug}`;
+export const getDisplayName = (project) => `${project.organizationName} | ${project.slug}`;
diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js
index 42b3fb8c6da..1d60847147b 100644
--- a/app/assets/javascripts/experimental_flags.js
+++ b/app/assets/javascripts/experimental_flags.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import Cookies from 'js-cookie';
export default () => {
- $('.js-experiment-feature-toggle').on('change', e => {
+ $('.js-experiment-feature-toggle').on('change', (e) => {
const el = e.target;
Cookies.set(el.name, el.value, {
diff --git a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
index 5953a4fbad8..5fcca11e695 100644
--- a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
+++ b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
@@ -31,6 +31,13 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: [
+ 'projectName',
+ 'featureFlagsHelpPagePath',
+ 'unleashApiUrl',
+ 'featureFlagsClientExampleHelpPagePath',
+ 'featureFlagsClientLibrariesHelpPagePath',
+ ],
props: {
instanceId: {
@@ -55,13 +62,6 @@ export default {
required: true,
},
},
- inject: [
- 'projectName',
- 'featureFlagsHelpPagePath',
- 'unleashApiUrl',
- 'featureFlagsClientExampleHelpPagePath',
- 'featureFlagsClientLibrariesHelpPagePath',
- ],
translations: {
cancelActionLabel: __('Close'),
modalTitle: s__('FeatureFlags|Configure feature flags'),
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 b89e9723606..210212fa900 100644
--- a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
@@ -30,9 +30,6 @@ export default {
};
},
translations: {
- legacyFlagAlert: s__(
- 'FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag.',
- ),
legacyReadOnlyFlagAlert: s__(
'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.',
),
@@ -59,18 +56,6 @@ export default {
deprecated() {
return this.version === LEGACY_FLAG;
},
- deprecatedAndEditable() {
- return this.deprecated && !this.hasLegacyReadOnlyFlags;
- },
- deprecatedAndReadOnly() {
- return this.deprecated && this.hasLegacyReadOnlyFlags;
- },
- hasLegacyReadOnlyFlags() {
- return (
- this.glFeatures.featureFlagsLegacyReadOnly &&
- !this.glFeatures.featureFlagsLegacyReadOnlyOverride
- );
- },
},
created() {
return this.fetchFeatureFlag();
@@ -91,12 +76,9 @@ export default {
<gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" />
<template v-else-if="!isLoading && !hasError">
- <gl-alert v-if="deprecatedAndEditable" variant="warning" :dismissible="false" class="gl-my-5">
- {{ $options.translations.legacyFlagAlert }}
- </gl-alert>
- <gl-alert v-if="deprecatedAndReadOnly" variant="warning" :dismissible="false" class="gl-my-5">
- {{ $options.translations.legacyReadOnlyFlagAlert }}
- </gl-alert>
+ <gl-alert v-if="deprecated" variant="warning" :dismissible="false" class="gl-my-5">{{
+ $options.translations.legacyReadOnlyFlagAlert
+ }}</gl-alert>
<div class="gl-display-flex gl-align-items-center gl-mb-4 gl-mt-4">
<gl-toggle
:value="active"
@@ -122,7 +104,7 @@ export default {
:submit-text="__('Save changes')"
:active="active"
:version="version"
- @handleSubmit="data => updateFeatureFlag(data)"
+ @handleSubmit="(data) => updateFeatureFlag(data)"
/>
</template>
</div>
diff --git a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
index 3caf536b6a2..88f1e692f5f 100644
--- a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
@@ -1,6 +1,6 @@
<script>
import { debounce } from 'lodash';
-import { GlDeprecatedButton, GlSearchBoxByType } from '@gitlab/ui';
+import { GlButton, GlSearchBoxByType } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
@@ -28,9 +28,10 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
export default {
name: 'EnvironmentsSearchableInput',
components: {
- GlDeprecatedButton,
+ GlButton,
GlSearchBoxByType,
},
+ inject: ['environmentsEndpoint'],
props: {
value: {
type: String,
@@ -53,7 +54,6 @@ export default {
required: false,
},
},
- inject: ['environmentsEndpoint'],
data() {
return {
environmentSearch: this.value,
@@ -159,19 +159,20 @@ export default {
<div class="dropdown-content">
<ul v-if="results.length">
<li v-for="(result, i) in results" :key="i">
- <gl-deprecated-button class="btn-transparent" @click="selectEnvironment(result)">{{
+ <gl-button category="tertiary" @click="selectEnvironment(result)">{{
result
- }}</gl-deprecated-button>
+ }}</gl-button>
</li>
</ul>
<div v-else-if="!results.length" class="text-secondary gl-p-3">
{{ __('No matching results') }}
</div>
<div v-if="shouldRenderCreateButton" class="dropdown-footer">
- <gl-deprecated-button
- class="js-create-button btn-blank dropdown-item"
+ <gl-button
+ category="tertiary"
+ class="js-create-button dropdown-item"
@click="createClicked"
- >{{ composedCreateButtonLabel }}</gl-deprecated-button
+ >{{ composedCreateButtonLabel }}</gl-button
>
</div>
</div>
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags.vue b/app/assets/javascripts/feature_flags/components/feature_flags.vue
index fe327a98605..ddeefd7b827 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags.vue
@@ -133,7 +133,7 @@ export default {
},
updateFeatureFlagOptions(parameters) {
const queryString = Object.keys(parameters)
- .map(parameter => {
+ .map((parameter) => {
const value = parameters[parameter];
return `${parameter}=${encodeURIComponent(value)}`;
})
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 0539b5ff832..24b0b54d1be 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
@@ -3,6 +3,7 @@ import { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab } from '@g
export default {
components: { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab },
+ inject: ['errorStateSvgPath', 'featureFlagsHelpPagePath'],
props: {
title: {
required: true,
@@ -46,7 +47,6 @@ export default {
type: String,
},
},
- inject: ['errorStateSvgPath', 'featureFlagsHelpPagePath'],
computed: {
itemCount() {
return this.count ?? 0;
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 ba46bab2df0..f3b199b5aca 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
@@ -17,13 +17,13 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagMixin()],
+ inject: ['csrfToken'],
props: {
featureFlags: {
type: Array,
required: true,
},
},
- inject: ['csrfToken'],
data() {
return {
deleteFeatureFlagUrl: null,
@@ -31,19 +31,12 @@ export default {
};
},
translations: {
- legacyFlagAlert: s__('FeatureFlags|Flag becomes read only soon'),
legacyFlagReadOnlyAlert: s__('FeatureFlags|Flag is read-only'),
},
computed: {
permissions() {
return this.glFeatures.featureFlagPermissions;
},
- isLegacyReadOnlyFlagsEnabled() {
- return (
- this.glFeatures.featureFlagsLegacyReadOnly &&
- !this.glFeatures.featureFlagsLegacyReadOnlyOverride
- );
- },
modalTitle() {
return sprintf(s__('FeatureFlags|Delete %{name}?'), {
name: this.deleteFeatureFlagName,
@@ -57,18 +50,13 @@ export default {
modalId() {
return 'delete-feature-flag';
},
- legacyFlagToolTipText() {
- const { legacyFlagReadOnlyAlert, legacyFlagAlert } = this.$options.translations;
-
- return this.isLegacyReadOnlyFlagsEnabled ? legacyFlagReadOnlyAlert : legacyFlagAlert;
- },
},
methods: {
isLegacyFlag(flag) {
return flag.version !== NEW_VERSION_FLAG;
},
statusToggleDisabled(flag) {
- return this.isLegacyReadOnlyFlagsEnabled && flag.version === LEGACY_FLAG;
+ return flag.version === LEGACY_FLAG;
},
scopeTooltipText(scope) {
return !scope.active
@@ -100,7 +88,7 @@ export default {
return featureFlag.iid ? `^${featureFlag.iid}` : '';
},
canDeleteFlag(flag) {
- return !this.permissions || (flag.scopes || []).every(scope => scope.can_update);
+ return !this.permissions || (flag.scopes || []).every((scope) => scope.can_update);
},
setDeleteModalData(featureFlag) {
this.deleteFeatureFlagUrl = featureFlag.destroy_path;
@@ -123,9 +111,7 @@ export default {
<template>
<div class="table-holder js-feature-flag-table">
<div class="gl-responsive-table-row table-row-header" role="row">
- <div class="table-section section-10">
- {{ s__('FeatureFlags|ID') }}
- </div>
+ <div class="table-section section-10">{{ s__('FeatureFlags|ID') }}</div>
<div class="table-section section-10" role="columnheader">
{{ s__('FeatureFlags|Status') }}
</div>
@@ -161,9 +147,8 @@ export default {
v-else-if="featureFlag.active"
variant="success"
data-testid="feature-flag-status-badge"
+ >{{ s__('FeatureFlags|Active') }}</gl-badge
>
- {{ s__('FeatureFlags|Active') }}
- </gl-badge>
<gl-badge v-else variant="danger">{{ s__('FeatureFlags|Inactive') }}</gl-badge>
</div>
</div>
@@ -179,7 +164,7 @@ export default {
</div>
<gl-icon
v-if="isLegacyFlag(featureFlag)"
- v-gl-tooltip.hover="legacyFlagToolTipText"
+ v-gl-tooltip.hover="$options.translations.legacyFlagReadOnlyAlert"
class="gl-ml-3"
name="information-o"
/>
@@ -205,9 +190,8 @@ export default {
:variant="badgeVariant(scope)"
:data-qa-selector="`feature-flag-scope-${badgeVariant(scope)}-badge`"
class="gl-mr-3 gl-mt-2"
+ >{{ badgeText(scope) }}</gl-badge
>
- {{ badgeText(scope) }}
- </gl-badge>
</template>
<template v-else>
<gl-badge
@@ -216,9 +200,8 @@ export default {
data-testid="strategy-badge"
variant="info"
class="gl-mr-3 gl-mt-2"
+ >{{ strategyBadgeText(strategy) }}</gl-badge
>
- {{ strategyBadgeText(strategy) }}
- </gl-badge>
</template>
</div>
</div>
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index 12856b79f63..253661ece1f 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -46,6 +46,11 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [featureFlagsMixin()],
+ inject: {
+ featureFlagIssuesEndpoint: {
+ default: '',
+ },
+ },
props: {
active: {
type: Boolean,
@@ -86,11 +91,6 @@ export default {
default: LEGACY_FLAG,
},
},
- inject: {
- featureFlagIssuesEndpoint: {
- default: '',
- },
- },
translations: {
allEnvironmentsText: s__('FeatureFlags|* (All Environments)'),
@@ -117,7 +117,7 @@ export default {
formDescription: this.description,
// operate on a clone to avoid mutating props
- formScopes: this.scopes.map(s => ({ ...s })),
+ formScopes: this.scopes.map((s) => ({ ...s })),
formStrategies: cloneDeep(this.strategies),
newScope: '',
@@ -125,13 +125,13 @@ export default {
},
computed: {
filteredScopes() {
- return this.formScopes.filter(scope => !scope.shouldBeDestroyed);
+ return this.formScopes.filter((scope) => !scope.shouldBeDestroyed);
},
filteredStrategies() {
- return this.formStrategies.filter(s => !s.shouldBeDestroyed);
+ return this.formStrategies.filter((s) => !s.shouldBeDestroyed);
},
canUpdateFlag() {
- return !this.permissionsFlag || (this.formScopes || []).every(scope => scope.canUpdate);
+ return !this.permissionsFlag || (this.formScopes || []).every((scope) => scope.canUpdate);
},
permissionsFlag() {
return this.glFeatures.featureFlagPermissions;
@@ -143,11 +143,7 @@ export default {
return this.featureFlagIssuesEndpoint.length > 0;
},
readOnly() {
- return (
- this.glFeatures.featureFlagsLegacyReadOnly &&
- !this.glFeatures.featureFlagsLegacyReadOnlyOverride &&
- this.version === LEGACY_FLAG
- );
+ return this.version === LEGACY_FLAG;
},
},
methods: {
@@ -167,7 +163,7 @@ export default {
if (isNumber(s.id)) {
Vue.set(s, 'shouldBeDestroyed', true);
} else {
- this.formStrategies = this.formStrategies.filter(strategy => strategy !== s);
+ this.formStrategies = this.formStrategies.filter((strategy) => strategy !== s);
}
},
@@ -188,7 +184,7 @@ export default {
*/
removeScope(scope) {
if (isString(scope.id) && scope.id.startsWith(INTERNAL_ID_PREFIX)) {
- this.formScopes = this.formScopes.filter(s => s !== scope);
+ this.formScopes = this.formScopes.filter((s) => s !== scope);
} else {
Vue.set(scope, 'shouldBeDestroyed', true);
}
@@ -387,9 +383,9 @@ export default {
class="col-12"
:value="scope.environmentScope"
:disabled="!canUpdateScope(scope) || scope.environmentScope !== ''"
- @selectEnvironment="env => (scope.environmentScope = env)"
- @createClicked="env => (scope.environmentScope = env)"
- @clearInput="env => (scope.environmentScope = '')"
+ @selectEnvironment="(env) => (scope.environmentScope = env)"
+ @createClicked="(env) => (scope.environmentScope = env)"
+ @clearInput="(env) => (scope.environmentScope = '')"
/>
<gl-badge v-if="permissionsFlag && scope.protected" variant="success">
@@ -406,7 +402,7 @@ export default {
<toggle-button
:value="scope.active"
:disabled-input="!active || !canUpdateScope(scope)"
- @change="status => (scope.active = status)"
+ @change="(status) => (scope.active = status)"
/>
</div>
</div>
@@ -524,8 +520,8 @@ export default {
<environments-dropdown
class="js-new-scope-name col-12"
:value="newScope"
- @selectEnvironment="env => createNewScope({ environmentScope: env })"
- @createClicked="env => createNewScope({ environmentScope: env })"
+ @selectEnvironment="(env) => createNewScope({ environmentScope: env })"
+ @createClicked="(env) => createNewScope({ environmentScope: env })"
/>
</div>
</div>
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 e6949d8028b..529fefd7e45 100644
--- a/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
@@ -71,7 +71,7 @@ export default {
:scopes="scopes"
:strategies="strategies"
:version="version"
- @handleSubmit="data => createFeatureFlag(data)"
+ @handleSubmit="(data) => createFeatureFlag(data)"
/>
</div>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/strategy.vue b/app/assets/javascripts/feature_flags/components/strategy.vue
index ce03248381c..9593bcf6487 100644
--- a/app/assets/javascripts/feature_flags/components/strategy.vue
+++ b/app/assets/javascripts/feature_flags/components/strategy.vue
@@ -83,7 +83,7 @@ export default {
);
},
filteredEnvironments() {
- return this.environments.filter(e => !e.shouldBeDestroyed);
+ return this.environments.filter((e) => !e.shouldBeDestroyed);
},
isPercentUserRollout() {
return this.formStrategy.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT;
@@ -91,7 +91,9 @@ export default {
},
methods: {
addEnvironment(environment) {
- const allEnvironmentsScope = this.environments.find(scope => scope.environmentScope === '*');
+ const allEnvironmentsScope = this.environments.find(
+ (scope) => scope.environmentScope === '*',
+ );
if (allEnvironmentsScope) {
allEnvironmentsScope.shouldBeDestroyed = true;
}
@@ -113,7 +115,7 @@ export default {
if (isNumber(environment.id)) {
Vue.set(environment, 'shouldBeDestroyed', true);
} else {
- this.environments = this.environments.filter(e => e !== environment);
+ this.environments = this.environments.filter((e) => e !== environment);
}
if (this.filteredEnvironments.length === 0) {
this.environments.push({ environmentScope: '*' });
diff --git a/app/assets/javascripts/feature_flags/components/strategy_parameters.vue b/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
index b6e06880315..a22f081bb92 100644
--- a/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
+++ b/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
@@ -30,7 +30,7 @@ export default {
},
computed: {
strategyComponent() {
- return STRATEGIES[(this.strategy?.name)];
+ return STRATEGIES[this.strategy?.name];
},
},
methods: {
diff --git a/app/assets/javascripts/feature_flags/store/edit/actions.js b/app/assets/javascripts/feature_flags/store/edit/actions.js
index 3678c2f7788..c4515e07a00 100644
--- a/app/assets/javascripts/feature_flags/store/edit/actions.js
+++ b/app/assets/javascripts/feature_flags/store/edit/actions.js
@@ -29,7 +29,7 @@ export const updateFeatureFlag = ({ state, dispatch }, params) => {
dispatch('receiveUpdateFeatureFlagSuccess');
visitUrl(state.path);
})
- .catch(error => dispatch('receiveUpdateFeatureFlagError', error.response.data));
+ .catch((error) => dispatch('receiveUpdateFeatureFlagError', error.response.data));
};
export const requestUpdateFeatureFlag = ({ commit }) => commit(types.REQUEST_UPDATE_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 81edc791924..65ea61c3025 100644
--- a/app/assets/javascripts/feature_flags/store/edit/index.js
+++ b/app/assets/javascripts/feature_flags/store/edit/index.js
@@ -4,7 +4,7 @@ import state from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default data =>
+export default (data) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
index d4587713fed..a834524df6c 100644
--- a/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
@@ -1,14 +1,14 @@
import Api from '~/api';
import * as types from './mutation_types';
-const getErrorMessages = error => [].concat(error?.response?.data?.message ?? error.message);
+const getErrorMessages = (error) => [].concat(error?.response?.data?.message ?? error.message);
export const fetchUserLists = ({ commit, state: { filter, projectId } }) => {
commit(types.FETCH_USER_LISTS);
return Api.searchFeatureFlagUserLists(projectId, filter)
.then(({ data }) => commit(types.RECEIVE_USER_LISTS_SUCCESS, data))
- .catch(error => commit(types.RECEIVE_USER_LISTS_ERROR, getErrorMessages(error)));
+ .catch((error) => commit(types.RECEIVE_USER_LISTS_ERROR, getErrorMessages(error)));
};
export const setFilter = ({ commit, dispatch }, filter) => {
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 d25b574981f..5f2726770d5 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
@@ -3,7 +3,7 @@ import mutations from './mutations';
import * as actions from './actions';
import * as getters from './getters';
-export default data => ({
+export default (data) => ({
state: state(data),
actions,
getters,
diff --git a/app/assets/javascripts/feature_flags/store/helpers.js b/app/assets/javascripts/feature_flags/store/helpers.js
index d42e5c504db..2fa20e25f4e 100644
--- a/app/assets/javascripts/feature_flags/store/helpers.js
+++ b/app/assets/javascripts/feature_flags/store/helpers.js
@@ -17,16 +17,16 @@ import {
* objects that is easier/nicer to bind to in Vue.
* @param {Array} scopesFromRails An array of scope objects fetched from the API
*/
-export const mapToScopesViewModel = scopesFromRails =>
- (scopesFromRails || []).map(s => {
+export const mapToScopesViewModel = (scopesFromRails) =>
+ (scopesFromRails || []).map((s) => {
const percentStrategy = (s.strategies || []).find(
- strat => strat.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ (strat) => strat.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
);
const rolloutPercentage = fetchPercentageParams(percentStrategy) || DEFAULT_PERCENT_ROLLOUT;
const userStrategy = (s.strategies || []).find(
- strat => strat.name === ROLLOUT_STRATEGY_USER_ID,
+ (strat) => strat.name === ROLLOUT_STRATEGY_USER_ID,
);
const rolloutStrategy =
@@ -36,7 +36,7 @@ export const mapToScopesViewModel = scopesFromRails =>
const rolloutUserIds = (fetchUserIdParams(userStrategy) || '')
.split(',')
- .filter(id => id)
+ .filter((id) => id)
.join(', ');
return {
@@ -59,8 +59,8 @@ export const mapToScopesViewModel = scopesFromRails =>
* the shape that the Rails API expects.
* @param {Array} scopesFromVue An array of scope objects from the Vue component
*/
-export const mapFromScopesViewModel = params => {
- const scopes = (params.scopes || []).map(s => {
+export const mapFromScopesViewModel = (params) => {
+ const scopes = (params.scopes || []).map((s) => {
const parameters = {};
if (s.rolloutStrategy === ROLLOUT_STRATEGY_PERCENT_ROLLOUT) {
parameters.groupId = PERCENT_ROLLOUT_GROUP_ID;
@@ -145,32 +145,32 @@ export const createNewEnvironmentScope = (overrides = {}, featureFlagPermissions
return newScope;
};
-const mapStrategyScopesToRails = scopes =>
+const mapStrategyScopesToRails = (scopes) =>
scopes.length === 0
? [{ environment_scope: '*' }]
- : scopes.map(s => ({
+ : scopes.map((s) => ({
id: s.id,
_destroy: s.shouldBeDestroyed,
environment_scope: s.environmentScope,
}));
-const mapStrategyScopesToView = scopes =>
- scopes.map(s => ({
+const mapStrategyScopesToView = (scopes) =>
+ scopes.map((s) => ({
id: s.id,
// eslint-disable-next-line no-underscore-dangle
shouldBeDestroyed: Boolean(s._destroy),
environmentScope: s.environment_scope,
}));
-const mapStrategiesParametersToViewModel = params => {
+const mapStrategiesParametersToViewModel = (params) => {
if (params.userIds) {
return { ...params, userIds: params.userIds.split(',').join(', ') };
}
return params;
};
-export const mapStrategiesToViewModel = strategiesFromRails =>
- (strategiesFromRails || []).map(s => ({
+export const mapStrategiesToViewModel = (strategiesFromRails) =>
+ (strategiesFromRails || []).map((s) => ({
id: s.id,
name: s.name,
parameters: mapStrategiesParametersToViewModel(s.parameters),
@@ -180,14 +180,14 @@ export const mapStrategiesToViewModel = strategiesFromRails =>
scopes: mapStrategyScopesToView(s.scopes),
}));
-const mapStrategiesParametersToRails = params => {
+const mapStrategiesParametersToRails = (params) => {
if (params.userIds) {
return { ...params, userIds: params.userIds.replace(/\s*,\s*/g, ',') };
}
return params;
};
-const mapStrategyToRails = strategy => {
+const mapStrategyToRails = (strategy) => {
const mappedStrategy = {
id: strategy.id,
name: strategy.name,
@@ -202,7 +202,7 @@ const mapStrategyToRails = strategy => {
return mappedStrategy;
};
-export const mapStrategiesToRails = params => ({
+export const mapStrategiesToRails = (params) => ({
operations_feature_flag: {
name: params.name,
description: params.description,
diff --git a/app/assets/javascripts/feature_flags/store/index/actions.js b/app/assets/javascripts/feature_flags/store/index/actions.js
index a8c1a72c016..6b6b3d55e16 100644
--- a/app/assets/javascripts/feature_flags/store/index/actions.js
+++ b/app/assets/javascripts/feature_flags/store/index/actions.js
@@ -12,7 +12,7 @@ export const fetchFeatureFlags = ({ state, dispatch }) => {
.get(state.endpoint, {
params: state.options,
})
- .then(response =>
+ .then((response) =>
dispatch('receiveFeatureFlagsSuccess', {
data: response.data || {},
headers: response.headers,
@@ -46,7 +46,7 @@ export const toggleFeatureFlag = ({ dispatch }, flag) => {
.put(flag.update_path, {
operations_feature_flag: flag,
})
- .then(response => dispatch('receiveUpdateFeatureFlagSuccess', response.data))
+ .then((response) => dispatch('receiveUpdateFeatureFlagSuccess', response.data))
.catch(() => dispatch('receiveUpdateFeatureFlagError', flag.id));
};
@@ -62,7 +62,7 @@ export const deleteUserList = ({ state, dispatch }, list) => {
return Api.deleteFeatureFlagUserList(state.projectId, list.iid)
.then(() => dispatch('fetchUserLists'))
- .catch(error =>
+ .catch((error) =>
dispatch('receiveDeleteUserListError', {
list,
error: error?.response?.data ?? error,
diff --git a/app/assets/javascripts/feature_flags/store/index/index.js b/app/assets/javascripts/feature_flags/store/index/index.js
index f737e0517fc..76495a33232 100644
--- a/app/assets/javascripts/feature_flags/store/index/index.js
+++ b/app/assets/javascripts/feature_flags/store/index/index.js
@@ -3,7 +3,7 @@ import state from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default data =>
+export default (data) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/feature_flags/store/index/mutations.js b/app/assets/javascripts/feature_flags/store/index/mutations.js
index bdc23e66214..910b2ec42d4 100644
--- a/app/assets/javascripts/feature_flags/store/index/mutations.js
+++ b/app/assets/javascripts/feature_flags/store/index/mutations.js
@@ -4,7 +4,7 @@ import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../../constants';
import { mapToScopesViewModel } from '../helpers';
-const mapFlag = flag => ({ ...flag, scopes: mapToScopesViewModel(flag.scopes || []) });
+const mapFlag = (flag) => ({ ...flag, scopes: mapToScopesViewModel(flag.scopes || []) });
const updateFlag = (state, flag) => {
const index = state[FEATURE_FLAG_SCOPE].findIndex(({ id }) => id === flag.id);
@@ -74,12 +74,7 @@ export default {
state.isRotating = true;
state.hasRotateError = false;
},
- [types.RECEIVE_ROTATE_INSTANCE_ID_SUCCESS](
- state,
- {
- data: { token },
- },
- ) {
+ [types.RECEIVE_ROTATE_INSTANCE_ID_SUCCESS](state, { data: { token } }) {
state.isRotating = false;
state.instanceId = token;
state.hasRotateError = false;
@@ -99,7 +94,7 @@ export default {
updateFlag(state, { ...flag, active: !flag.active });
},
[types.REQUEST_DELETE_USER_LIST](state, list) {
- state.userLists = state.userLists.filter(l => l !== list);
+ state.userLists = state.userLists.filter((l) => l !== list);
},
[types.RECEIVE_DELETE_USER_LIST_ERROR](state, { error, list }) {
state.isLoading = false;
diff --git a/app/assets/javascripts/feature_flags/store/new/actions.js b/app/assets/javascripts/feature_flags/store/new/actions.js
index e21c128cd39..6d595603819 100644
--- a/app/assets/javascripts/feature_flags/store/new/actions.js
+++ b/app/assets/javascripts/feature_flags/store/new/actions.js
@@ -27,7 +27,7 @@ export const createFeatureFlag = ({ state, dispatch }, params) => {
dispatch('receiveCreateFeatureFlagSuccess');
visitUrl(state.path);
})
- .catch(error => dispatch('receiveCreateFeatureFlagError', error.response.data));
+ .catch((error) => dispatch('receiveCreateFeatureFlagError', error.response.data));
};
export const requestCreateFeatureFlag = ({ commit }) => commit(types.REQUEST_CREATE_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 81edc791924..65ea61c3025 100644
--- a/app/assets/javascripts/feature_flags/store/new/index.js
+++ b/app/assets/javascripts/feature_flags/store/new/index.js
@@ -4,7 +4,7 @@ import state from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default data =>
+export default (data) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/feature_flags/utils.js b/app/assets/javascripts/feature_flags/utils.js
index 24c570657e6..e77cb8406cc 100644
--- a/app/assets/javascripts/feature_flags/utils.js
+++ b/app/assets/javascripts/feature_flags/utils.js
@@ -48,7 +48,7 @@ const badgeTextByType = {
const scopeName = ({ environment_scope: scope }) =>
scope === ALL_ENVIRONMENTS_NAME ? s__('FeatureFlags|All Environments') : scope;
-export const labelForStrategy = strategy => {
+export const labelForStrategy = (strategy) => {
const { name, parameters } = badgeTextByType[strategy.name];
if (parameters) {
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js
index be55e6923c6..2da9aadd2b1 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight.js
@@ -31,7 +31,7 @@ export function setupFeatureHighlightPopover(id, debounceTimeout = 300) {
.removeAttr('disabled');
}
-const getPriority = e => parseInt(e.dataset.highlightPriority, 10) || 0;
+const getPriority = (e) => parseInt(e.dataset.highlightPriority, 10) || 0;
export function findHighestPriorityFeature() {
let priorityFeature;
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
index cfadfb26db2..fabc905d756 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
@@ -5,7 +5,7 @@ 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 const getSelector = (highlightId) => `.js-feature-highlight[data-highlight=${highlightId}]`;
export function dismiss(highlightId) {
axios
diff --git a/app/assets/javascripts/file_pickers.js b/app/assets/javascripts/file_pickers.js
index 956a4954afb..fa5a5f14adb 100644
--- a/app/assets/javascripts/file_pickers.js
+++ b/app/assets/javascripts/file_pickers.js
@@ -1,7 +1,7 @@
export default function initFilePickers() {
const filePickers = document.querySelectorAll('.js-filepicker');
- filePickers.forEach(filePicker => {
+ filePickers.forEach((filePicker) => {
const button = filePicker.querySelector('.js-filepicker-button');
button.addEventListener('click', () => {
diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js
index aad5647c045..0d7a475eb8e 100644
--- a/app/assets/javascripts/files_comment_button.js
+++ b/app/assets/javascripts/files_comment_button.js
@@ -33,8 +33,8 @@ export default {
if (this.userCanCreateNote) {
$diffFile
- .on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
- .on('mouseleave', LINE_COLUMN_CLASSES, e => this.hideButton(this.isParallelView, e));
+ .on('mouseover', LINE_COLUMN_CLASSES, (e) => this.showButton(this.isParallelView, e))
+ .on('mouseleave', LINE_COLUMN_CLASSES, (e) => this.hideButton(this.isParallelView, e));
}
},
diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js
index eabf3b0846e..a8670caf5b2 100644
--- a/app/assets/javascripts/filterable_list.js
+++ b/app/assets/javascripts/filterable_list.js
@@ -72,7 +72,7 @@ export default class FilterableList {
.get(this.getFilterEndpoint(), {
params,
})
- .then(res => {
+ .then((res) => {
this.onFilterSuccess(res, params);
this.onFilterComplete();
})
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
index 77491d1556b..588bd534224 100644
--- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -50,7 +50,7 @@ export default class AvailableDropdownMappings {
},
};
- supportedTokens.forEach(type => {
+ supportedTokens.forEach((type) => {
if (availableMappings[type]) {
allowedMappings[type] = availableMappings[type];
}
@@ -99,7 +99,7 @@ export default class AvailableDropdownMappings {
// The DropdownNonUser class is hardcoded to look for and display a
// "title" property, so we need to add this property to each release object
- preprocessing: releases => releases.map(r => ({ ...r, title: r.tag })),
+ preprocessing: (releases) => releases.map((r) => ({ ...r, title: r.tag })),
},
element: this.container.querySelector('#js-dropdown-release'),
},
@@ -162,7 +162,7 @@ export default class AvailableDropdownMappings {
extraArguments: {
endpoint: this.getEnvironmentsEndpoint(),
symbol: '',
- preprocessing: data => data.map(env => ({ title: env })),
+ preprocessing: (data) => data.map((env) => ({ title: env })),
},
element: this.container.querySelector('#js-dropdown-environment'),
},
@@ -200,8 +200,9 @@ export default class AvailableDropdownMappings {
}
getMergeRequestTargetBranchesEndpoint() {
- const endpoint = `${gon.relative_url_root ||
- ''}/autocomplete/merge_request_target_branches.json`;
+ const endpoint = `${
+ gon.relative_url_root || ''
+ }/autocomplete/merge_request_target_branches.json`;
const params = {
group_id: this.getGroupId(),
diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
index 0c4abc14494..4c2f55fd174 100644
--- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
+++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
@@ -28,16 +28,16 @@ export default {
* fix by ignoring non-string recents while in Epic page.
*/
compatibleItems() {
- return this.items.filter(item => typeof item === 'string');
+ return this.items.filter((item) => typeof item === 'string');
},
processedItems() {
- return this.compatibleItems.map(item => {
+ return this.compatibleItems.map((item) => {
const { tokens, searchToken } = FilteredSearchTokenizer.processTokens(
item,
this.allowedKeys,
);
- const resultantTokens = tokens.map(token => ({
+ const resultantTokens = tokens.map((token) => ({
prefix: `${token.key}:`,
operator: token.operator,
suffix: `${token.symbol}${token.value}`,
diff --git a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
index 30f412e590f..2c0c3024d38 100644
--- a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
+++ b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
@@ -33,7 +33,7 @@ export default class DropdownAjaxFilter extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e, selected => {
+ super.itemClicked(e, (selected) => {
const title = selected.querySelector('.dropdown-light-content').innerText.trim();
return DropdownUtils.getEscapedText(title);
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index 1e3679b9e3c..001030b5f5f 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -53,7 +53,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e, selected => {
+ super.itemClicked(e, (selected) => {
const name = selected.querySelector('.js-data-value').innerText.trim();
return DropdownUtils.getEscapedText(name);
});
@@ -69,7 +69,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
// Replace empty gl-emoji tag to real content
const dropdownItems = [...this.dropdown.querySelectorAll('.filter-dropdown-item')];
- dropdownItems.forEach(dropdownItem => {
+ dropdownItems.forEach((dropdownItem) => {
const valueElement = dropdownItem.querySelector('.js-data-value');
if (valueElement !== null) {
const name = valueElement.innerText;
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js
index 4f10b6ba9c3..1180f8683a1 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
@@ -83,7 +83,7 @@ export default class DropdownHint extends FilteredSearchDropdown {
const dropdownData = this.tokenKeys
.get()
- .map(tokenKey => ({
+ .map((tokenKey) => ({
icon: `${gon.sprite_icons}#${tokenKey.icon}`,
hint: tokenKey.key,
tag: `:${tokenKey.tag}`,
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index bfa9f4a57ca..11261debeda 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
@@ -30,7 +30,7 @@ export default class DropdownNonUser extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e, selected => {
+ super.itemClicked(e, (selected) => {
const title = selected.querySelector('.js-data-value').innerText.trim();
return `${this.symbol}${DropdownUtils.getEscapedText(title)}`;
});
diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js
index 43de86b09ee..22c98f360ed 100644
--- a/app/assets/javascripts/filtered_search/dropdown_utils.js
+++ b/app/assets/javascripts/filtered_search/dropdown_utils.js
@@ -61,7 +61,7 @@ export default class DropdownUtils {
const { lastToken, tokens } = FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
const lastKey = lastToken.key || lastToken || '';
const allowMultiple = item.type === 'array';
- const itemInExistingTokens = tokens.some(t => t.key === item.hint);
+ const itemInExistingTokens = tokens.some((t) => t.key === item.hint);
const isSearchItem = updatedItem.hint === 'search';
if (isSearchItem) {
@@ -77,7 +77,7 @@ export default class DropdownUtils {
const tokenName = last(split[0].split(' '));
const match = isSearchItem
- ? allowedKeys.some(key => key.startsWith(tokenName.toLowerCase()))
+ ? allowedKeys.some((key) => key.startsWith(tokenName.toLowerCase()))
: updatedItem.hint.indexOf(tokenName.toLowerCase()) === -1;
updatedItem.droplab_hidden = tokenName ? match : false;
@@ -129,12 +129,12 @@ export default class DropdownUtils {
const values = [];
if (untilInput) {
- const inputIndex = tokens.findIndex(t => t.classList.contains('input-token'));
+ const inputIndex = tokens.findIndex((t) => t.classList.contains('input-token'));
// Add one to include input-token to the tokens array
tokens.splice(inputIndex + 1);
}
- tokens.forEach(token => {
+ tokens.forEach((token) => {
if (token.classList.contains('js-visual-token')) {
const name = token.querySelector('.name');
const operatorContainer = token.querySelector('.operator');
@@ -176,7 +176,7 @@ export default class DropdownUtils {
}
});
- return values.map(value => value.trim()).join(' ');
+ return values.map((value) => value.trim()).join(' ');
}
static getSearchInput(filteredSearchInput) {
@@ -192,7 +192,7 @@ export default class DropdownUtils {
// Replace all spaces inside quote marks with underscores
// (will continue to match entire string until an end quote is found if any)
// This helps with matching the beginning & end of a token:key
- inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, str =>
+ inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, (str) =>
str.replace(/\s/g, '_'),
);
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
index 8626e1a3d18..7434cc4c5d1 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
@@ -28,7 +28,7 @@ export default class FilteredSearchDropdown {
}
getCurrentHook() {
- return this.droplab.hooks.filter(h => h.id === this.hookId)[0] || null;
+ return this.droplab.hooks.filter((h) => h.id === this.hookId)[0] || null;
}
itemClicked(e, getValueFunction) {
@@ -134,7 +134,7 @@ export default class FilteredSearchDropdown {
if (!data) return;
- const results = data.map(o => {
+ const results = data.map((o) => {
const updated = o;
updated.droplab_hidden = false;
return updated;
@@ -157,7 +157,7 @@ export default class FilteredSearchDropdown {
// Iterate over all the static dropdown values,
// then hide `None` and `Any` items.
- Array.from(dropdownEl.querySelectorAll('li[data-value]')).forEach(itemEl => {
+ Array.from(dropdownEl.querySelectorAll('li[data-value]')).forEach((itemEl) => {
const {
dataset: { value },
} = itemEl;
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 d446e32394b..3c630c26bc7 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -23,7 +23,7 @@ export default class FilteredSearchDropdownManager {
isGroupDecendent,
filteredSearchTokenKeys,
}) {
- const removeTrailingSlash = url => url.replace(/\/$/, '');
+ const removeTrailingSlash = (url) => url.replace(/\/$/, '');
this.container = FilteredSearchContainer.container;
this.runnerTagsEndpoint = removeTrailingSlash(runnerTagsEndpoint);
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 921d686bb28..11b2eb839ce 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -90,14 +90,14 @@ export default class FilteredSearchManager {
// Fetch recent searches from localStorage
this.fetchingRecentSearchesPromise = this.recentSearchesService
.fetch()
- .catch(error => {
+ .catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
// eslint-disable-next-line no-new
new Flash(__('An error occurred while parsing recent searches'));
// Gracefully fail to empty array
return [];
})
- .then(searches => {
+ .then((searches) => {
if (!searches) {
return;
}
@@ -169,7 +169,7 @@ export default class FilteredSearchManager {
if (this.stateFilters) {
this.searchStateWrapper = this.searchState.bind(this);
- this.applyToStateFilters(filterEl => {
+ this.applyToStateFilters((filterEl) => {
filterEl.addEventListener('click', this.searchStateWrapper);
});
}
@@ -177,14 +177,14 @@ export default class FilteredSearchManager {
unbindStateEvents() {
if (this.stateFilters) {
- this.applyToStateFilters(filterEl => {
+ this.applyToStateFilters((filterEl) => {
filterEl.removeEventListener('click', this.searchStateWrapper);
});
}
}
applyToStateFilters(callback) {
- this.stateFilters.querySelectorAll('a[data-state]').forEach(filterEl => {
+ this.stateFilters.querySelectorAll('a[data-state]').forEach((filterEl) => {
if (this.states.indexOf(filterEl.dataset.state) > -1) {
callback(filterEl);
}
@@ -263,7 +263,7 @@ export default class FilteredSearchManager {
let backspaceCount = 0;
// closure for keeping track of the number of backspace keystrokes
- return e => {
+ return (e) => {
// 8 = Backspace Key
// 46 = Delete Key
// Handled by respective backspace-combination check functions
@@ -447,7 +447,7 @@ export default class FilteredSearchManager {
const removeElements = [];
- [].forEach.call(this.tokensContainer.children, t => {
+ [].forEach.call(this.tokensContainer.children, (t) => {
let canClearToken = t.classList.contains('js-visual-token');
if (canClearToken) {
@@ -460,7 +460,7 @@ export default class FilteredSearchManager {
}
});
- removeElements.forEach(el => {
+ removeElements.forEach((el) => {
el.parentElement.removeChild(el);
});
@@ -488,7 +488,7 @@ export default class FilteredSearchManager {
const { isLastVisualTokenValid } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (isLastVisualTokenValid) {
- tokens.forEach(t => {
+ tokens.forEach((t) => {
input.value = input.value.replace(`${t.key}:${t.operator}${t.symbol}${t.value}`, '');
FilteredSearchVisualTokens.addFilterVisualToken(
@@ -585,7 +585,7 @@ export default class FilteredSearchManager {
*/
const notKeyValueRegex = new RegExp(/not\[(\w+)\]\[?\]?=(.*)/);
- return params.map(query => {
+ return params.map((query) => {
// Check if there are matches for `not` operator
const matches = query.match(notKeyValueRegex);
if (matches && matches.length === 3) {
@@ -624,7 +624,7 @@ export default class FilteredSearchManager {
const usernameParams = this.getUsernameParams();
let hasFilteredSearch = false;
- params.forEach(p => {
+ params.forEach((p) => {
const split = p.split('=');
const keyParam = decodeURIComponent(split[0]);
const value = split[1];
@@ -746,7 +746,7 @@ export default class FilteredSearchManager {
paths.push(`state=${currentState}`);
}
- tokens.forEach(token => {
+ tokens.forEach((token) => {
const condition = this.filteredSearchTokenKeys.searchByConditionKeyValue(
token.key,
token.operator,
@@ -795,7 +795,7 @@ export default class FilteredSearchManager {
if (searchToken) {
const sanitized = searchToken
.split(' ')
- .map(t => encodeURIComponent(t))
+ .map((t) => encodeURIComponent(t))
.join('+');
paths.push(`search=${sanitized}`);
}
@@ -817,7 +817,7 @@ export default class FilteredSearchManager {
const usernamesById = {};
try {
const attribute = this.filteredSearchInput.getAttribute('data-username-params');
- JSON.parse(attribute).forEach(user => {
+ JSON.parse(attribute).forEach((user) => {
usernamesById[user.id] = user.username;
});
} catch (e) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index 89fc8047b65..6216ab5401d 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -14,7 +14,7 @@ export default class FilteredSearchTokenKeys {
}
getKeys() {
- return this.tokenKeys.map(i => i.key);
+ return this.tokenKeys.map((i) => i.key);
}
getAlternatives() {
@@ -36,16 +36,16 @@ export default class FilteredSearchTokenKeys {
}
searchByKey(key) {
- return this.tokenKeys.find(tokenKey => tokenKey.key === key) || null;
+ return this.tokenKeys.find((tokenKey) => tokenKey.key === key) || null;
}
searchBySymbol(symbol) {
- return this.tokenKeys.find(tokenKey => tokenKey.symbol === symbol) || null;
+ return this.tokenKeys.find((tokenKey) => tokenKey.symbol === symbol) || null;
}
searchByKeyParam(keyParam) {
return (
- this.tokenKeysWithAlternative.find(tokenKey => {
+ this.tokenKeysWithAlternative.find((tokenKey) => {
let tokenKeyParam = tokenKey.key;
// Replace hyphen with underscore to compare keyParam with tokenKeyParam
@@ -62,13 +62,13 @@ export default class FilteredSearchTokenKeys {
}
searchByConditionUrl(url) {
- return this.conditions.find(condition => condition.url === url) || null;
+ return this.conditions.find((condition) => condition.url === url) || null;
}
searchByConditionKeyValue(key, operator, value) {
return (
this.conditions.find(
- condition =>
+ (condition) =>
condition.tokenKey === key &&
condition.operator === operator &&
condition.value.toLowerCase() === value.toLowerCase(),
@@ -93,4 +93,13 @@ export default class FilteredSearchTokenKeys {
this.tokenKeys.push(confidentialToken);
this.tokenKeysWithAlternative.push(confidentialToken);
}
+
+ removeTokensForKeys(...keys) {
+ const keysSet = new Set(keys);
+
+ this.tokenKeys = this.tokenKeys.filter(({ key }) => !keysSet.has(key));
+ this.tokenKeysWithAlternative = this.tokenKeysWithAlternative.filter(
+ ({ key }) => !keysSet.has(key),
+ );
+ }
}
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 f0951f6b177..4e594dfa910 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -8,7 +8,7 @@ export default class FilteredSearchVisualTokens {
static getOperatorToken(value) {
let token = null;
- FilteredSearchVisualTokens.permissibleOperatorValues.forEach(operatorToken => {
+ FilteredSearchVisualTokens.permissibleOperatorValues.forEach((operatorToken) => {
if (value.startsWith(operatorToken)) {
token = operatorToken;
}
@@ -20,7 +20,7 @@ export default class FilteredSearchVisualTokens {
static getValueToken(value) {
let newValue = value;
- FilteredSearchVisualTokens.permissibleOperatorValues.forEach(operatorToken => {
+ FilteredSearchVisualTokens.permissibleOperatorValues.forEach((operatorToken) => {
if (value.startsWith(operatorToken)) {
newValue = value.slice(operatorToken.length);
}
@@ -48,7 +48,7 @@ export default class FilteredSearchVisualTokens {
const otherTokens = FilteredSearchContainer.container.querySelectorAll(
'.js-visual-token .selectable.selected',
);
- [].forEach.call(otherTokens, t => t.classList.remove('selected'));
+ [].forEach.call(otherTokens, (t) => t.classList.remove('selected'));
}
static selectToken(tokenButton, forceSelection = false) {
@@ -193,7 +193,8 @@ export default class FilteredSearchVisualTokens {
});
} else if (
!isLastVisualTokenValid &&
- (lastVisualToken && !lastVisualToken.querySelector('.operator'))
+ lastVisualToken &&
+ !lastVisualToken.querySelector('.operator')
) {
const tokensContainer = FilteredSearchContainer.container.querySelector('.tokens-container');
tokensContainer.removeChild(lastVisualToken);
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 f9388e9c5d8..46867b184c8 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
@@ -150,7 +150,7 @@ export const conditions = flattenDeep(
tokenKey: 'my-reaction',
value: __('Any'),
},
- ].map(condition => {
+ ].map((condition) => {
const [keyPart, valuePart] = condition.url.split('=');
const hasBrackets = keyPart.includes('[]');
diff --git a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js
index 423f123f71c..ca0a58137b1 100644
--- a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js
+++ b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js
@@ -19,7 +19,7 @@ class RecentSearchesStore {
}
setRecentSearches(searches = []) {
- const trimmedSearches = searches.map(search =>
+ const trimmedSearches = searches.map((search) =>
typeof search === 'string' ? search.trim() : search,
);
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index f73646da6d1..0d36126943b 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -40,7 +40,7 @@ export default class VisualTokenValue {
return (
UsersCache.retrieve(username)
- .then(user => {
+ .then((user) => {
if (!user) {
return;
}
@@ -68,9 +68,9 @@ export default class VisualTokenValue {
);
return AjaxCache.retrieve(labelsEndpointWithParams)
- .then(labels => {
+ .then((labels) => {
const matchingLabel = (labels || []).find(
- label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
+ (label) => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
);
if (!matchingLabel) {
@@ -96,8 +96,8 @@ export default class VisualTokenValue {
);
return AjaxCache.retrieve(epicsEndpointWithParams)
- .then(epics => {
- const matchingEpic = (epics || []).find(epic => epic.id === Number(tokenValue));
+ .then((epics) => {
+ const matchingEpic = (epics || []).find((epic) => epic.id === Number(tokenValue));
if (!matchingEpic) {
return;
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index 1d5f09a265b..d14af53746e 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -34,7 +34,7 @@ const hideFlash = (flashEl, fadeTransition = true) => {
if (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
};
-const createAction = config => `
+const createAction = (config) => `
<a
href="${config.href || '#'}"
class="flash-action"
@@ -69,7 +69,7 @@ const removeFlashClickListener = (flashEl, fadeTransition) => {
* @param {String} message Flash message text
* @param {String} type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
* @param {Object} parent Reference to parent element under which Flash needs to appear
- * @param {Object} actonConfig Map of config to show action on banner
+ * @param {Object} actionConfig Map of config to show action on banner
* @param {String} href URL to which action config should point to (default: '#')
* @param {String} title Title of action
* @param {Function} clickHandler Method to call when action is clicked on
@@ -97,7 +97,7 @@ const deprecatedCreateFlash = function deprecatedCreateFlash(
if (actionConfig.clickHandler) {
flashEl
.querySelector('.flash-action')
- .addEventListener('click', e => actionConfig.clickHandler(e));
+ .addEventListener('click', (e) => actionConfig.clickHandler(e));
}
}
@@ -119,7 +119,7 @@ const deprecatedCreateFlash = function deprecatedCreateFlash(
* @param {String} options.message Flash message text
* @param {String} options.type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
* @param {Object} options.parent Reference to parent element under which Flash needs to appear
- * @param {Object} options.actonConfig Map of config to show action on banner
+ * @param {Object} options.actionConfig Map of config to show action on banner
* @param {String} href URL to which action config should point to (default: '#')
* @param {String} title Title of action
* @param {Function} clickHandler Method to call when action is clicked on
@@ -151,7 +151,7 @@ const createFlash = function createFlash({
if (actionConfig.clickHandler) {
flashEl
.querySelector('.flash-action')
- .addEventListener('click', e => actionConfig.clickHandler(e));
+ .addEventListener('click', (e) => actionConfig.clickHandler(e));
}
}
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index b9ce0851585..5df0ac37812 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -12,7 +12,7 @@ let sidebar;
export const mousePos = [];
-export const setSidebar = el => {
+export const setSidebar = (el) => {
sidebar = el;
};
export const getOpenMenu = () => currentOpenMenu;
@@ -32,7 +32,7 @@ const setHeaderHeight = () => {
export const isSidebarCollapsed = () =>
sidebar && sidebar.classList.contains(SIDEBAR_COLLAPSED_CLASS);
-export const canShowActiveSubItems = el => {
+export const canShowActiveSubItems = (el) => {
if (el.classList.contains('active') && !isSidebarCollapsed()) {
return false;
}
@@ -71,7 +71,7 @@ export const calculateTop = (boundingRect, outerHeight) => {
: boundingRect.top;
};
-export const hideMenu = el => {
+export const hideMenu = (el) => {
if (!el) return;
const parentEl = el.parentNode;
@@ -112,7 +112,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
}
};
-export const showSubLevelItems = el => {
+export const showSubLevelItems = (el) => {
const subItems = el.querySelector('.sidebar-sub-level-items');
const isIconOnly = subItems && subItems.classList.contains('is-fly-out-only');
@@ -139,7 +139,7 @@ export const mouseEnterTopItems = (el, timeout = getHideSubItemsInterval()) => {
}, timeout);
};
-export const mouseLeaveTopItem = el => {
+export const mouseLeaveTopItem = (el) => {
const subItems = el.querySelector('.sidebar-sub-level-items');
if (
@@ -152,7 +152,7 @@ export const mouseLeaveTopItem = el => {
el.classList.remove(IS_OVER_CLASS);
};
-export const documentMouseMove = e => {
+export const documentMouseMove = (e) => {
mousePos.push({
x: e.clientX,
y: e.clientY,
@@ -161,7 +161,7 @@ export const documentMouseMove = e => {
if (mousePos.length > 6) mousePos.shift();
};
-export const subItemsMouseLeave = relatedTarget => {
+export const subItemsMouseLeave = (relatedTarget) => {
clearTimeout(timeoutId);
if (relatedTarget && !relatedTarget.closest(`.${IS_OVER_CLASS}`)) {
@@ -189,15 +189,15 @@ export default () => {
requestIdleCallback(setHeaderHeight);
- items.forEach(el => {
+ items.forEach((el) => {
const subItems = el.querySelector('.sidebar-sub-level-items');
if (subItems) {
- subItems.addEventListener('mouseleave', e => subItemsMouseLeave(e.relatedTarget));
+ subItems.addEventListener('mouseleave', (e) => subItemsMouseLeave(e.relatedTarget));
}
- el.addEventListener('mouseenter', e => mouseEnterTopItems(e.currentTarget));
- el.addEventListener('mouseleave', e => mouseLeaveTopItem(e.currentTarget));
+ el.addEventListener('mouseenter', (e) => mouseEnterTopItems(e.currentTarget));
+ el.addEventListener('mouseleave', (e) => mouseLeaveTopItem(e.currentTarget));
});
document.addEventListener('mousemove', documentMouseMove);
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue
index c4f61b839e4..68cc8645813 100644
--- a/app/assets/javascripts/frequent_items/components/app.vue
+++ b/app/assets/javascripts/frequent_items/components/app.vue
@@ -77,7 +77,7 @@ export default {
// Check if item already exists in list
const itemMatchIndex = storedFrequentItems.findIndex(
- frequentItem => frequentItem.id === item.id,
+ (frequentItem) => frequentItem.id === item.id,
);
if (itemMatchIndex > -1) {
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index 639562bf961..cef8be37a40 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -18,7 +18,7 @@ const frequentItemDropdowns = [
];
export default function initFrequentItemDropdowns() {
- frequentItemDropdowns.forEach(dropdown => {
+ frequentItemDropdowns.forEach((dropdown) => {
const { namespace, key } = dropdown;
const el = document.getElementById(`js-${namespace}-dropdown`);
const navEl = document.getElementById(`nav-${namespace}-dropdown`);
diff --git a/app/assets/javascripts/frequent_items/store/actions.js b/app/assets/javascripts/frequent_items/store/actions.js
index d4756e2ea6a..f4156487625 100644
--- a/app/assets/javascripts/frequent_items/store/actions.js
+++ b/app/assets/javascripts/frequent_items/store/actions.js
@@ -1,7 +1,7 @@
-import Api from '~/api';
import AccessorUtilities from '~/lib/utils/accessor';
import * as types from './mutation_types';
import { getTopFrequentItems } from '../utils';
+import { getGroups, getProjects } from '~/rest_api';
export const setNamespace = ({ commit }, namespace) => {
commit(types.SET_NAMESPACE, namespace);
@@ -54,12 +54,16 @@ export const fetchSearchedItems = ({ state, dispatch }, searchQuery) => {
membership: Boolean(gon.current_user_id),
};
+ let searchFunction;
if (state.namespace === 'projects') {
+ searchFunction = getProjects;
params.order_by = 'last_activity_at';
+ } else {
+ searchFunction = getGroups;
}
- return Api[state.namespace](searchQuery, params)
- .then(results => {
+ return searchFunction(searchQuery, params)
+ .then((results) => {
dispatch('receiveSearchedItemsSuccess', results);
})
.catch(() => {
diff --git a/app/assets/javascripts/frequent_items/store/getters.js b/app/assets/javascripts/frequent_items/store/getters.js
index 36cc9020d8d..e52678dbec2 100644
--- a/app/assets/javascripts/frequent_items/store/getters.js
+++ b/app/assets/javascripts/frequent_items/store/getters.js
@@ -1 +1 @@
-export const hasSearchQuery = state => state.searchQuery !== '';
+export const hasSearchQuery = (state) => state.searchQuery !== '';
diff --git a/app/assets/javascripts/frequent_items/store/mutations.js b/app/assets/javascripts/frequent_items/store/mutations.js
index 78ccef7f253..eee00243867 100644
--- a/app/assets/javascripts/frequent_items/store/mutations.js
+++ b/app/assets/javascripts/frequent_items/store/mutations.js
@@ -50,7 +50,7 @@ export default {
[types.RECEIVE_SEARCHED_ITEMS_SUCCESS](state, results) {
const rawItems = results.data ? results.data : results; // Api.groups returns array, Api.projects returns object
Object.assign(state, {
- items: rawItems.map(rawItem => ({
+ items: rawItems.map((rawItem) => ({
id: rawItem.id,
name: rawItem.name,
namespace: rawItem.name_with_namespace || rawItem.full_name,
diff --git a/app/assets/javascripts/frequent_items/utils.js b/app/assets/javascripts/frequent_items/utils.js
index 954d426c86c..63fe0ef20b0 100644
--- a/app/assets/javascripts/frequent_items/utils.js
+++ b/app/assets/javascripts/frequent_items/utils.js
@@ -5,7 +5,7 @@ import { FREQUENT_ITEMS, HOUR_IN_MS } from './constants';
export const isMobile = () => ['md', 'sm', 'xs'].includes(bp.getBreakpointSize());
-export const getTopFrequentItems = items => {
+export const getTopFrequentItems = (items) => {
if (!items) {
return [];
}
@@ -13,7 +13,7 @@ export const getTopFrequentItems = items => {
? FREQUENT_ITEMS.LIST_COUNT_MOBILE
: FREQUENT_ITEMS.LIST_COUNT_DESKTOP;
- const frequentItems = items.filter(item => item.frequency >= FREQUENT_ITEMS.ELIGIBLE_FREQUENCY);
+ const frequentItems = items.filter((item) => item.frequency >= FREQUENT_ITEMS.ELIGIBLE_FREQUENCY);
if (!frequentItems || frequentItems.length === 0) {
return [];
@@ -45,9 +45,9 @@ export const updateExistingFrequentItem = (frequentItem, item) => {
};
};
-export const sanitizeItem = item => {
+export const sanitizeItem = (item) => {
// Only sanitize if the key exists on the item
- const maybeSanitize = key => {
+ const maybeSanitize = (key) => {
if (!Object.prototype.hasOwnProperty.call(item, key)) {
return {};
}
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index dcb27434a07..cf9ff87f25e 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -15,7 +15,7 @@ function sanitize(str) {
}
export function membersBeforeSave(members) {
- return members.map(member => {
+ return members.map((member) => {
const GROUP_TYPE = 'Group';
let title = '';
@@ -103,6 +103,7 @@ class GfmAutoComplete {
at: '/',
alias: 'commands',
searchKey: 'search',
+ limit: 100,
skipSpecialCharacterTest: true,
skipMarkdownCharacterTest: true,
data: GfmAutoComplete.defaultLoadingData,
@@ -156,7 +157,7 @@ class GfmAutoComplete {
...this.getDefaultCallbacks(),
beforeSave(commands) {
if (GfmAutoComplete.isLoading(commands)) return commands;
- return $.map(commands, c => {
+ return $.map(commands, (c) => {
let search = c.name;
if (c.aliases.length > 0) {
search = `${search} ${c.aliases.join(' ')}`;
@@ -237,7 +238,7 @@ class GfmAutoComplete {
});
// return to the form atwho wants
- return results.map(name => ({ name }));
+ return results.map((name) => ({ name }));
},
},
});
@@ -285,13 +286,10 @@ class GfmAutoComplete {
...this.getDefaultCallbacks(),
beforeSave: membersBeforeSave,
matcher(flag, subtext) {
- const subtextNodes = subtext
- .split(/\n+/g)
- .pop()
- .split(GfmAutoComplete.regexSubtext);
+ const subtextNodes = subtext.split(/\n+/g).pop().split(GfmAutoComplete.regexSubtext);
// Check if @ is followed by '/assign', '/reassign', '/unassign' or '/cc' commands.
- command = subtextNodes.find(node => {
+ command = subtextNodes.find((node) => {
if (Object.values(MEMBER_COMMAND).includes(node)) {
return node;
}
@@ -301,7 +299,7 @@ class GfmAutoComplete {
// Cache assignees list for easier filtering later
assignees =
SidebarMediator.singleton?.store?.assignees?.map(
- assignee => `${assignee.username} ${assignee.name}`,
+ (assignee) => `${assignee.username} ${assignee.name}`,
) || [];
const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers);
@@ -319,10 +317,10 @@ class GfmAutoComplete {
if (command === MEMBER_COMMAND.ASSIGN) {
// Only include members which are not assigned to Issuable currently
- return data.filter(member => !assignees.includes(member.search));
+ return data.filter((member) => !assignees.includes(member.search));
} else if (command === MEMBER_COMMAND.UNASSIGN) {
// Only include members which are assigned to Issuable currently
- return data.filter(member => assignees.includes(member.search));
+ return data.filter((member) => assignees.includes(member.search));
}
return data;
@@ -349,7 +347,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(issues) {
- return $.map(issues, i => {
+ return $.map(issues, (i) => {
if (i.title == null) {
return i;
}
@@ -383,7 +381,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(milestones) {
- return $.map(milestones, m => {
+ return $.map(milestones, (m) => {
if (m.title == null) {
return m;
}
@@ -416,7 +414,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(merges) {
- return $.map(merges, m => {
+ return $.map(merges, (m) => {
if (m.title == null) {
return m;
}
@@ -457,7 +455,7 @@ class GfmAutoComplete {
...this.getDefaultCallbacks(),
beforeSave(merges) {
if (GfmAutoComplete.isLoading(merges)) return merges;
- return $.map(merges, m => ({
+ return $.map(merges, (m) => ({
title: sanitize(m.title),
color: m.color,
search: m.title,
@@ -465,13 +463,10 @@ class GfmAutoComplete {
}));
},
matcher(flag, subtext) {
- const subtextNodes = subtext
- .split(/\n+/g)
- .pop()
- .split(GfmAutoComplete.regexSubtext);
+ const subtextNodes = subtext.split(/\n+/g).pop().split(GfmAutoComplete.regexSubtext);
// Check if ~ is followed by '/label', '/relabel' or '/unlabel' commands.
- command = subtextNodes.find(node => {
+ command = subtextNodes.find((node) => {
if (
node === LABEL_COMMAND.LABEL ||
node === LABEL_COMMAND.RELABEL ||
@@ -492,7 +487,7 @@ class GfmAutoComplete {
return null;
}
const lastCandidate = subtext.split(flag).pop();
- if (labels.find(label => label.title.startsWith(lastCandidate))) {
+ if (labels.find((label) => label.title.startsWith(lastCandidate))) {
return lastCandidate;
}
} else {
@@ -519,10 +514,10 @@ class GfmAutoComplete {
// because we want to return all the labels (unfiltered) for that command.
if (command === LABEL_COMMAND.LABEL) {
// Return labels with set: undefined.
- return data.filter(label => !label.set);
+ return data.filter((label) => !label.set);
} else if (command === LABEL_COMMAND.UNLABEL) {
// Return labels with set: true.
- return data.filter(label => label.set);
+ return data.filter((label) => label.set);
}
return data;
@@ -549,7 +544,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(snippets) {
- return $.map(snippets, m => {
+ return $.map(snippets, (m) => {
if (m.title == null) {
return m;
}
@@ -654,7 +649,7 @@ class GfmAutoComplete {
this.loadEmojiData($input, at).catch(() => {});
} else if (dataSource) {
AjaxCache.retrieve(dataSource, true)
- .then(data => {
+ .then((data) => {
this.loadData($input, at, data);
})
.catch(() => {
@@ -696,11 +691,11 @@ class GfmAutoComplete {
}
lookup[key].push({ kind, emoji });
};
- Object.values(emojis).forEach(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));
+ emoji.aliases.forEach((a) => add(a, 'alias', emoji));
});
this.emojiLookup = lookup;
@@ -772,7 +767,7 @@ GfmAutoComplete.atTypeMap = {
};
GfmAutoComplete.typesWithBackendFiltering = ['vulnerabilities'];
-GfmAutoComplete.isTypeWithBackendFiltering = type =>
+GfmAutoComplete.isTypeWithBackendFiltering = (type) =>
GfmAutoComplete.typesWithBackendFiltering.includes(GfmAutoComplete.atTypeMap[type]);
function findEmoji(name) {
diff --git a/app/assets/javascripts/gl_field_errors.js b/app/assets/javascripts/gl_field_errors.js
index ad79483d5ec..eec7a138ea7 100644
--- a/app/assets/javascripts/gl_field_errors.js
+++ b/app/assets/javascripts/gl_field_errors.js
@@ -16,14 +16,14 @@ export default class GlFieldErrors {
initValidators() {
// register selectors here as needed
const validateSelectors = [':text', ':password', '[type=email]', '[type=url]', '[type=number]']
- .map(selector => `input${selector}`)
+ .map((selector) => `input${selector}`)
.join(',');
this.state.inputs = this.form
.find(validateSelectors)
.toArray()
- .filter(input => !input.classList.contains(customValidationFlag))
- .map(input => new GlFieldError({ input, formErrors: this }));
+ .filter((input) => !input.classList.contains(customValidationFlag))
+ .map((input) => new GlFieldError({ input, formErrors: this }));
this.form.on('submit', GlFieldErrors.catchInvalidFormSubmit);
}
@@ -45,7 +45,7 @@ export default class GlFieldErrors {
/* Public method for triggering validity updates manually */
updateFormValidityState() {
- this.state.inputs.forEach(field => {
+ this.state.inputs.forEach((field) => {
if (field.state.submitted) {
field.updateValidity();
}
diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js
index 4a3755f39cc..3e777c2dc09 100644
--- a/app/assets/javascripts/gl_form.js
+++ b/app/assets/javascripts/gl_form.js
@@ -20,7 +20,7 @@ export default class GLForm {
// Disable autocomplete for keywords which do not have dataSources available
const dataSources = (gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources) || {};
- Object.keys(this.enableGFM).forEach(item => {
+ Object.keys(this.enableGFM).forEach((item) => {
if (item !== 'emojis' && !dataSources[item]) {
this.enableGFM[item] = false;
}
@@ -67,6 +67,7 @@ export default class GLForm {
addMarkdownListeners(this.form);
this.form.show();
if (this.isAutosizeable) this.setupAutosize();
+ if (this.textarea.data('autofocus') === true) this.textarea.focus();
}
setupAutosize() {
@@ -108,14 +109,10 @@ export default class GLForm {
addEventListeners() {
this.textarea.on('focus', function focusTextArea() {
- $(this)
- .closest('.md-area')
- .addClass('is-focused');
+ $(this).closest('.md-area').addClass('is-focused');
});
this.textarea.on('blur', function blurTextArea() {
- $(this)
- .closest('.md-area')
- .removeClass('is-focused');
+ $(this).closest('.md-area').removeClass('is-focused');
});
}
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index e0f64c8e843..3a8ae56bb8f 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -28,7 +28,7 @@ export default class GpgBadges {
return axios
.get(endpoint, { params })
.then(({ data }) => {
- data.signatures.forEach(signature => {
+ data.signatures.forEach((signature) => {
badges.filter(`[data-commit-sha="${signature.commit_sha}"]`).replaceWith(signature.html);
});
})
diff --git a/app/assets/javascripts/grafana_integration/store/actions.js b/app/assets/javascripts/grafana_integration/store/actions.js
index d28e59925d4..436f92eae84 100644
--- a/app/assets/javascripts/grafana_integration/store/actions.js
+++ b/app/assets/javascripts/grafana_integration/store/actions.js
@@ -24,7 +24,7 @@ export const updateGrafanaIntegration = ({ state, dispatch }) =>
},
})
.then(() => dispatch('receiveGrafanaIntegrationUpdateSuccess'))
- .catch(error => dispatch('receiveGrafanaIntegrationUpdateError', error));
+ .catch((error) => dispatch('receiveGrafanaIntegrationUpdateError', error));
export const receiveGrafanaIntegrationUpdateSuccess = () => {
/**
diff --git a/app/assets/javascripts/grafana_integration/store/index.js b/app/assets/javascripts/grafana_integration/store/index.js
index e96bb1e8aad..e3dcfd31a83 100644
--- a/app/assets/javascripts/grafana_integration/store/index.js
+++ b/app/assets/javascripts/grafana_integration/store/index.js
@@ -6,7 +6,7 @@ import mutations from './mutations';
Vue.use(Vuex);
-export const createStore = initialState =>
+export const createStore = (initialState) =>
new Vuex.Store({
state: createState(initialState),
actions,
diff --git a/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
index 62119177887..62119177887 100644
--- a/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
diff --git a/app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql
index 74b425717a0..74b425717a0 100644
--- a/app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql
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
new file mode 100644
index 00000000000..42dc388c9d1
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/mutations/update_alert_status.mutation.graphql
@@ -0,0 +1,17 @@
+#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
new file mode 100644
index 00000000000..e94758ef60e
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
@@ -0,0 +1,36 @@
+#import "~/graphql_shared/fragments/alert.fragment.graphql"
+
+query getAlerts(
+ $projectPath: ID!
+ $statuses: [AlertManagementStatus!]
+ $sort: AlertManagementAlertSort
+ $firstPageSize: Int
+ $lastPageSize: Int
+ $prevPageCursor: String = ""
+ $nextPageCursor: String = ""
+ $searchTerm: String = ""
+ $assigneeUsername: String = ""
+) {
+ project(fullPath: $projectPath) {
+ alertManagementAlerts(
+ search: $searchTerm
+ assigneeUsername: $assigneeUsername
+ statuses: $statuses
+ sort: $sort
+ first: $firstPageSize
+ last: $lastPageSize
+ after: $nextPageCursor
+ before: $prevPageCursor
+ ) {
+ nodes {
+ ...AlertListItem
+ }
+ pageInfo {
+ hasNextPage
+ endCursor
+ hasPreviousPage
+ startCursor
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/graphql_shared/utils.js b/app/assets/javascripts/graphql_shared/utils.js
index 813e21b6ce9..4715bbc94f6 100644
--- a/app/assets/javascripts/graphql_shared/utils.js
+++ b/app/assets/javascripts/graphql_shared/utils.js
@@ -51,4 +51,4 @@ export const convertToGraphQLId = (type, id) => {
* @param {Array} ids An array of id values
* @returns {Array}
*/
-export const convertToGraphQLIds = (type, ids) => ids.map(id => convertToGraphQLId(type, id));
+export const convertToGraphQLIds = (type, ids) => ids.map((id) => convertToGraphQLId(type, id));
diff --git a/app/assets/javascripts/group.js b/app/assets/javascripts/group.js
index a840e995860..6878635b288 100644
--- a/app/assets/javascripts/group.js
+++ b/app/assets/javascripts/group.js
@@ -12,7 +12,7 @@ export default class Group {
this.resetHandler = this.reset.bind(this);
this.updateGroupPathSlugHandler = this.updateGroupPathSlug.bind(this);
- this.groupNames.forEach(groupName => {
+ this.groupNames.forEach((groupName) => {
if (groupName.value === '') {
groupName.addEventListener('keyup', this.updateHandler);
@@ -22,7 +22,7 @@ export default class Group {
}
});
- this.groupPaths.forEach(groupPath => {
+ this.groupPaths.forEach((groupPath) => {
groupPath.addEventListener('keydown', this.resetHandler);
});
}
@@ -30,21 +30,21 @@ export default class Group {
update({ currentTarget: { value: updatedValue } }) {
const slug = slugify(updatedValue);
- this.groupNames.forEach(element => {
+ this.groupNames.forEach((element) => {
element.value = updatedValue;
});
- this.groupPaths.forEach(element => {
+ this.groupPaths.forEach((element) => {
element.value = slug;
});
}
reset() {
- this.groupNames.forEach(groupName => {
+ this.groupNames.forEach((groupName) => {
groupName.removeEventListener('keyup', this.updateHandler);
groupName.removeEventListener('blur', this.checkPathHandler);
});
- this.groupPaths.forEach(groupPath => {
+ this.groupPaths.forEach((groupPath) => {
groupPath.removeEventListener('keydown', this.resetHandler);
});
}
@@ -59,7 +59,7 @@ export default class Group {
if (exists && suggests.length) {
const [suggestedSlug] = suggests;
- this.groupPaths.forEach(element => {
+ this.groupPaths.forEach((element) => {
element.value = suggestedSlug;
});
} else if (exists && !suggests.length) {
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 e396521ce7c..d6ed08a9407 100644
--- a/app/assets/javascripts/group_settings/components/shared_runners_form.vue
+++ b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
@@ -82,7 +82,7 @@ export default {
.then(() => {
this.isLoading = false;
})
- .catch(error => {
+ .catch((error) => {
const message = [
error.response?.data?.error || __('An error occurred while updating configuration.'),
ERROR_MESSAGE,
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index e057012a246..4f26bab8bd3 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -1,8 +1,6 @@
<script>
/* global Flash */
-import $ from 'jquery';
-import 'vendor/jquery.scrollTo';
import { GlLoadingIcon, GlModal } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
import { HIDDEN_CLASS } from '~/lib/utils/constants';
@@ -108,7 +106,7 @@ export default {
fetchGroups({ parentId, page, filterGroupsBy, sortBy, archived, updatePagination }) {
return this.service
.getGroups(parentId, page, filterGroupsBy, sortBy, archived)
- .then(res => {
+ .then((res) => {
if (updatePagination) {
this.updatePagination(res.headers);
}
@@ -116,7 +114,7 @@ export default {
})
.catch(() => {
this.isLoading = false;
- $.scrollTo(0);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
Flash(COMMON_STR.FAILURE);
});
@@ -135,7 +133,7 @@ export default {
sortBy,
archived,
updatePagination: true,
- }).then(res => {
+ }).then((res) => {
this.isLoading = false;
this.updateGroups(res, Boolean(filterGroupsBy));
});
@@ -149,9 +147,9 @@ export default {
sortBy,
archived,
updatePagination: true,
- }).then(res => {
+ }).then((res) => {
this.isLoading = false;
- $.scrollTo(0);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
const currentPath = mergeUrlParams({ page }, window.location.href);
window.history.replaceState(
@@ -173,7 +171,7 @@ export default {
this.fetchGroups({
parentId: parentGroup.id,
})
- .then(res => {
+ .then((res) => {
this.store.setGroupChildren(parentGroup, res);
})
.catch(() => {
@@ -194,12 +192,12 @@ export default {
this.targetGroup.isBeingRemoved = true;
this.service
.leaveGroup(this.targetGroup.leavePath)
- .then(res => {
- $.scrollTo(0);
+ .then((res) => {
+ window.scrollTo({ top: 0, behavior: 'smooth' });
this.store.removeGroup(this.targetGroup, this.targetParentGroup);
this.$toast.show(res.data.notice);
})
- .catch(err => {
+ .catch((err) => {
let message = COMMON_STR.FAILURE;
if (err.status === 403) {
message = COMMON_STR.LEAVE_FORBIDDEN;
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index ef58b93c049..d65ad974c73 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -126,7 +126,7 @@ export default {
/>
<div
:class="{ 'd-sm-flex': !group.isChildrenLoading }"
- class="avatar-container rect-avatar s32 d-none flex-grow-0 flex-shrink-0 "
+ class="avatar-container rect-avatar s32 d-none flex-grow-0 flex-shrink-0"
>
<a :href="group.relativePath" class="no-expand">
<img
diff --git a/app/assets/javascripts/groups/components/visibility_level_dropdown.vue b/app/assets/javascripts/groups/components/visibility_level_dropdown.vue
index ff0f8c3ff46..0933045fc38 100644
--- a/app/assets/javascripts/groups/components/visibility_level_dropdown.vue
+++ b/app/assets/javascripts/groups/components/visibility_level_dropdown.vue
@@ -23,7 +23,7 @@ export default {
},
methods: {
getDefaultOption() {
- return this.visibilityLevelOptions.find(option => option.level === this.defaultLevel);
+ return this.visibilityLevelOptions.find((option) => option.level === this.defaultLevel);
},
onClick(option) {
this.selectedOption = option;
diff --git a/app/assets/javascripts/groups/groups_filterable_list.js b/app/assets/javascripts/groups/groups_filterable_list.js
index 693519729ac..c33ad8b6ecb 100644
--- a/app/assets/javascripts/groups/groups_filterable_list.js
+++ b/app/assets/javascripts/groups/groups_filterable_list.js
@@ -65,10 +65,7 @@ export default class GroupFilterableList extends FilterableList {
setDefaultFilterOption() {
const defaultOption = $.trim(
- this.$dropdown
- .find('.dropdown-menu li.js-filter-sort-order a')
- .first()
- .text(),
+ this.$dropdown.find('.dropdown-menu li.js-filter-sort-order a').first().text(),
);
this.$dropdown.find('.dropdown-label').text(defaultOption);
}
diff --git a/app/assets/javascripts/groups/init_invite_members_banner.js b/app/assets/javascripts/groups/init_invite_members_banner.js
index c7967827917..2052dd6ac8c 100644
--- a/app/assets/javascripts/groups/init_invite_members_banner.js
+++ b/app/assets/javascripts/groups/init_invite_members_banner.js
@@ -18,6 +18,6 @@ export default function initInviteMembersBanner() {
isDismissedKey,
trackLabel,
},
- render: createElement => createElement(InviteMembersBanner),
+ render: (createElement) => createElement(InviteMembersBanner),
});
}
diff --git a/app/assets/javascripts/groups/members/components/app.vue b/app/assets/javascripts/groups/members/components/app.vue
index f6f3a955813..34a2c67fa9f 100644
--- a/app/assets/javascripts/groups/members/components/app.vue
+++ b/app/assets/javascripts/groups/members/components/app.vue
@@ -5,12 +5,10 @@ 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';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'GroupMembersApp',
components: { MembersTable, FilterSortContainer, GlAlert },
- mixins: [glFeatureFlagsMixin()],
computed: {
...mapState(['showError', 'errorMessage']),
},
@@ -36,7 +34,7 @@ export default {
<gl-alert v-if="showError" ref="errorAlert" variant="danger" @dismiss="hideError">{{
errorMessage
}}</gl-alert>
- <filter-sort-container v-if="glFeatures.groupMembersFilteredSearch" />
+ <filter-sort-container />
<members-table />
</div>
</template>
diff --git a/app/assets/javascripts/groups/members/index.js b/app/assets/javascripts/groups/members/index.js
index 9ce0e3c1179..3ec874b8d36 100644
--- a/app/assets/javascripts/groups/members/index.js
+++ b/app/assets/javascripts/groups/members/index.js
@@ -38,6 +38,6 @@ export const initGroupMembersApp = (
el,
components: { App },
store,
- render: createElement => createElement('app'),
+ render: (createElement) => createElement('app'),
});
};
diff --git a/app/assets/javascripts/groups/members/utils.js b/app/assets/javascripts/groups/members/utils.js
index 2d584556bbc..4fcf348b69f 100644
--- a/app/assets/javascripts/groups/members/utils.js
+++ b/app/assets/javascripts/groups/members/utils.js
@@ -7,7 +7,7 @@ import {
GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME,
} from './constants';
-export const parseDataAttributes = el => {
+export const parseDataAttributes = (el) => {
const { members, groupId, memberPath, canManageMembers } = el.dataset;
return {
diff --git a/app/assets/javascripts/groups/store/groups_store.js b/app/assets/javascripts/groups/store/groups_store.js
index b6cea38e87f..6cf70f4052e 100644
--- a/app/assets/javascripts/groups/store/groups_store.js
+++ b/app/assets/javascripts/groups/store/groups_store.js
@@ -12,15 +12,15 @@ export default class GroupsStore {
setGroups(rawGroups) {
if (rawGroups && rawGroups.length) {
- this.state.groups = rawGroups.map(rawGroup => this.formatGroupItem(rawGroup));
+ this.state.groups = rawGroups.map((rawGroup) => this.formatGroupItem(rawGroup));
} else {
this.state.groups = [];
}
}
setSearchedGroups(rawGroups) {
- const formatGroups = groups =>
- groups.map(group => {
+ const formatGroups = (groups) =>
+ groups.map((group) => {
const formattedGroup = this.formatGroupItem(group);
if (formattedGroup.children && formattedGroup.children.length) {
formattedGroup.children = formatGroups(formattedGroup.children);
@@ -37,7 +37,7 @@ export default class GroupsStore {
setGroupChildren(parentGroup, children) {
const updatedParentGroup = parentGroup;
- updatedParentGroup.children = children.map(rawChild => this.formatGroupItem(rawChild));
+ updatedParentGroup.children = children.map((rawChild) => this.formatGroupItem(rawChild));
updatedParentGroup.isOpen = true;
updatedParentGroup.isChildrenLoading = false;
}
@@ -103,9 +103,9 @@ export default class GroupsStore {
removeGroup(group, parentGroup) {
const updatedParentGroup = parentGroup;
if (updatedParentGroup.children && updatedParentGroup.children.length) {
- updatedParentGroup.children = parentGroup.children.filter(child => group.id !== child.id);
+ updatedParentGroup.children = parentGroup.children.filter((child) => group.id !== child.id);
} else {
- this.state.groups = this.state.groups.filter(child => group.id !== child.id);
+ this.state.groups = this.state.groups.filter((child) => group.id !== child.id);
}
}
}
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
index cefd803c631..59cc779d2ae 100644
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ b/app/assets/javascripts/groups/transfer_dropdown.js
@@ -20,11 +20,11 @@ export default class TransferDropdown {
initDeprecatedJQueryDropdown(this.groupDropdown, {
selectable: true,
filterable: true,
- toggleLabel: item => item.text,
+ toggleLabel: (item) => item.text,
search: { fields: ['text'] },
data: extraOptions.concat(this.data),
- text: item => item.text,
- clicked: options => {
+ text: (item) => item.text,
+ clicked: (options) => {
const { e } = options;
e.preventDefault();
this.assignSelected(options.selectedObj);
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 29af8c77d25..c65fff432d0 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -6,11 +6,11 @@ import { normalizeHeaders } from './lib/utils/common_utils';
import { __ } from '~/locale';
import { loadCSSFile } from './lib/utils/css_utils';
-const fetchGroups = params => {
+const fetchGroups = (params) => {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
- .then(res => {
+ .then((res) => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
@@ -67,7 +67,7 @@ const groupsSelect = () => {
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
- const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
+ const results = groups.filter((group) => skipGroups.indexOf(group.id) === -1);
return {
results,
diff --git a/app/assets/javascripts/helpers/event_hub_factory.js b/app/assets/javascripts/helpers/event_hub_factory.js
index a9c301e3a93..62af67d3ef3 100644
--- a/app/assets/javascripts/helpers/event_hub_factory.js
+++ b/app/assets/javascripts/helpers/event_hub_factory.js
@@ -45,7 +45,7 @@ class EventHub {
$off(type, handler) {
const handlers = this.$_all.get(type) || [];
- const newHandlers = handler ? handlers.filter(x => x !== handler) : [];
+ const newHandlers = handler ? handlers.filter((x) => x !== handler) : [];
if (newHandlers.length) {
this.$_all.set(type, newHandlers);
@@ -77,7 +77,7 @@ class EventHub {
$emit(type, ...args) {
const handlers = this.$_all.get(type) || [];
- handlers.forEach(handler => {
+ handlers.forEach((handler) => {
handler(...args);
});
}
diff --git a/app/assets/javascripts/helpers/help_page_helper.js b/app/assets/javascripts/helpers/help_page_helper.js
new file mode 100644
index 00000000000..0e824548646
--- /dev/null
+++ b/app/assets/javascripts/helpers/help_page_helper.js
@@ -0,0 +1,21 @@
+import { joinPaths, setUrlFragment } from '~/lib/utils/url_utility';
+
+const HELP_PAGE_URL_ROOT = '/help/';
+
+/**
+ * Generate link to a GitLab documentation page.
+ *
+ * This is designed to mirror the Ruby `help_page_path` helper function, so that
+ * the two can be used interchangeably.
+ * @param {String} path - Path to doc file relative to the doc/ directory in the GitLab repository.
+ * Optionally, including `.md` or `.html` prefix
+ * @param {String} options.anchor - Name of the anchor to scroll to on the documentation page.
+ */
+export const helpPagePath = (path, { anchor = '' } = {}) => {
+ let helpPath = joinPaths(gon.relative_url_root || '/', HELP_PAGE_URL_ROOT, path);
+ if (anchor) {
+ helpPath = setUrlFragment(helpPath, anchor);
+ }
+
+ return helpPath;
+};
diff --git a/app/assets/javascripts/helpers/monitor_helper.js b/app/assets/javascripts/helpers/monitor_helper.js
index 5e345321013..7c6a6d6a433 100644
--- a/app/assets/javascripts/helpers/monitor_helper.js
+++ b/app/assets/javascripts/helpers/monitor_helper.js
@@ -38,7 +38,7 @@ const templatedLabel = (queryLabel, metricAttributes) => {
* @example
* multiMetricLabel('', {__name__: "up", app: "prometheus"}) -> "__name__: up, app: prometheus"
*/
-const multiMetricLabel = metricAttributes => {
+const multiMetricLabel = (metricAttributes) => {
return Object.entries(metricAttributes)
.map(([templateVar, label]) => `${templateVar}: ${label}`)
.join(', ');
@@ -64,7 +64,7 @@ export const getSeriesLabel = (queryLabel, metricAttributes) => {
* @returns {Array} The formatted values
*/
export const makeDataSeries = (queryResults, defaultConfig) =>
- queryResults.map(result => {
+ queryResults.map((result) => {
return {
...defaultConfig,
data: result.values,
diff --git a/app/assets/javascripts/helpers/startup_css_helper.js b/app/assets/javascripts/helpers/startup_css_helper.js
index d41a6209898..6e19979721c 100644
--- a/app/assets/javascripts/helpers/startup_css_helper.js
+++ b/app/assets/javascripts/helpers/startup_css_helper.js
@@ -22,14 +22,14 @@ const handleStartupEvents = () => {
/* For `waitForCSSLoaded` methods, see docs.gitlab.com/ee/development/fe_guide/performance.html#important-considerations */
export const waitForCSSLoaded = (action = () => {}) => {
- if (!gon?.features?.startupCss || allLinksLoaded()) {
- return new Promise(resolve => {
+ if (allLinksLoaded()) {
+ return new Promise((resolve) => {
action();
resolve();
});
}
- return new Promise(resolve => {
+ return new Promise((resolve) => {
document.addEventListener(CSS_LOADED_EVENT, resolve, { once: true });
document.addEventListener(STARTUP_LINK_LOADED_EVENT, handleStartupEvents);
}).then(action);
diff --git a/app/assets/javascripts/ide/commit_icon.js b/app/assets/javascripts/ide/commit_icon.js
index 4984b5bb91d..70ee9cff22b 100644
--- a/app/assets/javascripts/ide/commit_icon.js
+++ b/app/assets/javascripts/ide/commit_icon.js
@@ -1,6 +1,6 @@
import { commitItemIconMap } from './constants';
-export default file => {
+export default (file) => {
if (file.deleted) {
return commitItemIconMap.deleted;
} else if (file.tempFile && !file.prevPath) {
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 123e0aba959..4192a002486 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -63,7 +63,7 @@ export default {
return this.openPendingTab({
file: this.file,
keyPrefix: this.keyPrefix,
- }).then(changeViewer => {
+ }).then((changeViewer) => {
if (changeViewer) {
this.updateViewer(viewerTypes.diff);
}
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 aed7b792902..91cce44382c 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -74,6 +74,7 @@ export default {
<input
:placeholder="placeholderBranchName"
:value="newBranchName"
+ data-testid="ide-new-branch-name"
type="text"
class="form-control monospace"
@input="updateBranchName($event.target.value)"
diff --git a/app/assets/javascripts/ide/components/file_templates/bar.vue b/app/assets/javascripts/ide/components/file_templates/bar.vue
index 88dca2f0556..bd4c4f18141 100644
--- a/app/assets/javascripts/ide/components/file_templates/bar.vue
+++ b/app/assets/javascripts/ide/components/file_templates/bar.vue
@@ -29,7 +29,7 @@ export default {
'undoFileTemplate',
]),
setInitialType() {
- const initialTemplateType = this.templateTypes.find(t => t.name === this.activeFile.name);
+ const initialTemplateType = this.templateTypes.find((t) => t.name === this.activeFile.name);
if (initialTemplateType) {
this.setSelectedTemplateType(initialTemplateType);
diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
index 5d5b66a6444..772dab3fed3 100644
--- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue
+++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
@@ -44,7 +44,7 @@ export default {
computed: {
...mapState('fileTemplates', ['templates', 'isLoading']),
outputData() {
- return (this.isAsyncData ? this.templates : this.data).filter(t => {
+ return (this.isAsyncData ? this.templates : this.data).filter((t) => {
if (!this.searchable) return true;
return t.name.toLowerCase().indexOf(this.search.toLowerCase()) >= 0;
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index f8568f46cd6..aac899fde0d 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -73,7 +73,7 @@ export default {
},
},
mounted() {
- window.onbeforeunload = e => this.onBeforeUnload(e);
+ window.onbeforeunload = (e) => this.onBeforeUnload(e);
if (this.themeName)
document.querySelector('.navbar-gitlab').classList.add(`theme-${this.themeName}`);
diff --git a/app/assets/javascripts/ide/components/ide_sidebar_nav.vue b/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
index 966c36d6e71..9dbed0ace40 100644
--- a/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
+++ b/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
@@ -37,7 +37,7 @@ export default {
},
methods: {
isActiveTab(tab) {
- return this.isOpen && tab.views.some(view => view.name === this.currentView);
+ return this.isOpen && tab.views.some((view) => view.name === this.currentView);
},
buttonClasses(tab) {
return [
diff --git a/app/assets/javascripts/ide/components/nav_dropdown.vue b/app/assets/javascripts/ide/components/nav_dropdown.vue
index 8cea8655461..6ff77e556c0 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown.vue
@@ -31,9 +31,7 @@ export default {
},
removeDropdownListeners() {
// eslint-disable-next-line @gitlab/no-global-event-off
- $(this.$refs.dropdown)
- .off('show.bs.dropdown')
- .off('hide.bs.dropdown');
+ $(this.$refs.dropdown).off('show.bs.dropdown').off('hide.bs.dropdown');
},
showDropdown() {
this.isVisibleDropdown = true;
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index 4a9a2a57acd..5704129c10f 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -25,23 +25,24 @@ export default {
},
methods: {
createFile(target, file) {
- const { name } = file;
+ const { name, type: mimeType } = file;
const encodedContent = target.result.split('base64,')[1];
const rawContent = encodedContent ? atob(encodedContent) : '';
- const isText = isTextFile({ content: rawContent, mimeType: file.type, name });
+ const isText = isTextFile({ content: rawContent, mimeType, name });
- const emitCreateEvent = content =>
+ const emitCreateEvent = (content) =>
this.$emit('create', {
name: `${this.path ? `${this.path}/` : ''}${name}`,
type: 'blob',
content,
rawPath: !isText ? URL.createObjectURL(file) : '',
+ mimeType,
});
if (isText) {
const reader = new FileReader();
- reader.addEventListener('load', e => emitCreateEvent(e.target.result), { once: true });
+ reader.addEventListener('load', (e) => emitCreateEvent(e.target.result), { once: true });
reader.readAsText(file);
} else {
emitCreateEvent(rawContent);
@@ -50,11 +51,11 @@ export default {
readFile(file) {
const reader = new FileReader();
- reader.addEventListener('load', e => this.createFile(e.target, file), { once: true });
+ reader.addEventListener('load', (e) => this.createFile(e.target, file), { once: true });
reader.readAsDataURL(file);
},
openFile() {
- Array.from(this.$refs.fileUpload.files).forEach(file => this.readFile(file));
+ Array.from(this.$refs.fileUpload.files).forEach((file) => this.readFile(file));
},
startFileUpload() {
this.$refs.fileUpload.click();
@@ -80,6 +81,7 @@ export default {
type="file"
class="hidden"
multiple
+ data-qa-selector="file_upload_field"
@change="openFile"
/>
</div>
diff --git a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
index 87019c3b2a5..6f42ae48cc9 100644
--- a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
+++ b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
@@ -35,13 +35,13 @@ export default {
return `${this.side}Pane`;
},
tabs() {
- return this.extensionTabs.filter(tab => tab.show);
+ return this.extensionTabs.filter((tab) => tab.show);
},
tabViews() {
- return this.tabs.map(tab => tab.views).flat();
+ return this.tabs.map((tab) => tab.views).flat();
},
aliveTabViews() {
- return this.tabViews.filter(view => this.isAliveView(view.name));
+ return this.tabViews.filter((view) => this.isAliveView(view.name));
},
},
methods: {
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index f65b1201d94..4c2a369226e 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -1,12 +1,13 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { isEmpty } from 'lodash';
+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 { packageJsonPath } from '../../constants';
+import { packageJsonPath, LIVE_PREVIEW_DEBOUNCE } from '../../constants';
import { createPathWithExt } from '../../utils';
+import eventHub from '../../eventhub';
export default {
components: {
@@ -61,13 +62,10 @@ export default {
};
},
},
- watch: {
- entries: {
- deep: true,
- handler: 'update',
- },
- },
mounted() {
+ this.onFilesChangeCallback = debounce(() => this.update(), LIVE_PREVIEW_DEBOUNCE);
+ eventHub.$on('ide.files.change', this.onFilesChangeCallback);
+
this.loading = true;
return this.loadFileContent(packageJsonPath)
@@ -78,17 +76,19 @@ export default {
.then(() => this.initPreview());
},
beforeDestroy() {
+ // Setting sandpackReady = false protects us form a phantom `update()` being called when `debounce` finishes.
+ this.sandpackReady = false;
+ eventHub.$off('ide.files.change', this.onFilesChangeCallback);
+
if (!isEmpty(this.manager)) {
this.manager.listener();
}
+
this.manager = {};
if (this.listener) {
this.listener();
}
-
- clearTimeout(this.timeout);
- this.timeout = null;
},
methods: {
...mapActions(['getFileData', 'getRawFileData']),
@@ -108,7 +108,7 @@ export default {
.then(() => {
this.initManager();
- this.listener = listen(e => {
+ this.listener = listen((e) => {
switch (e.type) {
case 'done':
this.sandpackReady = true;
@@ -122,25 +122,21 @@ export default {
update() {
if (!this.sandpackReady) return;
- clearTimeout(this.timeout);
-
- this.timeout = setTimeout(() => {
- if (isEmpty(this.manager)) {
- this.initPreview();
+ if (isEmpty(this.manager)) {
+ this.initPreview();
- return;
- }
+ return;
+ }
- this.manager.updatePreview(this.sandboxOpts);
- }, 250);
+ this.manager.updatePreview(this.sandboxOpts);
},
initManager() {
const { codesandboxBundlerUrl: bundlerURL } = this;
const settings = {
fileResolver: {
- isFile: p => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
- readFile: p => this.loadFileContent(createPathWithExt(p)).then(content => content),
+ isFile: (p) => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
+ readFile: (p) => this.loadFileContent(createPathWithExt(p)).then((content) => content),
},
...(bundlerURL ? { bundlerURL } : {}),
};
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 60710251fef..8986359427f 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -31,7 +31,7 @@ export default {
},
},
mounted() {
- this.listener = listen(e => {
+ this.listener = listen((e) => {
switch (e.type) {
case 'urlchange':
this.onUrlChange(e);
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index dfd25feed08..8092ef3bce6 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -41,12 +41,12 @@ export default {
file,
keyPrefix: file.staged ? stageKeys.staged : stageKeys.unstaged,
})
- .then(changeViewer => {
+ .then((changeViewer) => {
if (changeViewer) {
this.updateViewer('diff');
}
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
},
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index 1f029612c29..a9c05f2e1ac 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -74,8 +74,11 @@ export default {
fileEditor() {
return getFileEditorOrDefault(this.fileEditors, this.file.path);
},
+ isBinaryFile() {
+ return !isTextFile(this.file);
+ },
shouldHideEditor() {
- return this.file && !this.file.loading && !isTextFile(this.file);
+ return this.file && !this.file.loading && this.isBinaryFile;
},
showContentViewer() {
return (
@@ -216,7 +219,7 @@ export default {
.then(() => {
this.createEditorInstance();
})
- .catch(err => {
+ .catch((err) => {
flash(
__('Error setting up editor. Please try again.'),
'alert',
@@ -244,6 +247,10 @@ export default {
);
},
createEditorInstance() {
+ if (this.isBinaryFile) {
+ return;
+ }
+
this.editor.dispose();
this.$nextTick(() => {
@@ -274,7 +281,7 @@ export default {
this.model.updateOptions(this.rules);
- this.model.onChange(model => {
+ this.model.onChange((model) => {
const { file } = model;
if (!file.active) return;
@@ -322,7 +329,7 @@ export default {
}
},
fetchEditorconfigRules() {
- return getRulesWithTraversal(this.file.path, path => {
+ return getRulesWithTraversal(this.file.path, (path) => {
const entry = this.entries[path];
if (!entry) return Promise.resolve(null);
@@ -332,7 +339,7 @@ export default {
return this.getFileData({ path: entry.path, makeFileActive: false }).then(() =>
this.getRawFileData({ path: entry.path }),
);
- }).then(rules => {
+ }).then((rules) => {
this.rules = mapRulesToMonaco(rules);
});
},
@@ -346,7 +353,7 @@ export default {
event.preventDefault();
event.stopImmediatePropagation();
- return readFileAsDataURL(file).then(content => {
+ return readFileAsDataURL(file).then((content) => {
const parentPath = getPathParent(this.file.path);
const path = `${parentPath ? `${parentPath}/` : ''}${file.name}`;
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index bdb11e6b004..e5618466395 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -97,3 +97,6 @@ export const packageJsonPath = 'package.json';
export const SIDE_LEFT = 'left';
export const SIDE_RIGHT = 'right';
+
+// Live Preview feature
+export const LIVE_PREVIEW_DEBOUNCE = 2000;
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index b9ebacef7e1..0e6775d87f1 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -39,7 +39,7 @@ const EmptyRouterComponent = {
},
};
-export const createRouter = store => {
+export const createRouter = (store) => {
const router = new IdeRouter({
mode: 'history',
base: joinPaths(gon.relative_url_root || '', '/-/ide/'),
@@ -54,11 +54,11 @@ export const createRouter = store => {
},
{
path: ':targetmode(edit|tree|blob)/:branchid+/',
- redirect: to => joinPaths(to.path, '/-/'),
+ redirect: (to) => joinPaths(to.path, '/-/'),
},
{
path: ':targetmode(edit|tree|blob)',
- redirect: to => joinPaths(to.path, '/master/-/'),
+ redirect: (to) => joinPaths(to.path, '/master/-/'),
},
{
path: 'merge_requests/:mrid',
@@ -66,7 +66,7 @@ export const createRouter = store => {
},
{
path: '',
- redirect: to => joinPaths(to.path, '/edit/master/-/'),
+ redirect: (to) => joinPaths(to.path, '/edit/master/-/'),
},
],
},
@@ -110,7 +110,7 @@ export const createRouter = store => {
});
}
})
- .catch(e => {
+ .catch((e) => {
flash(
__('Error while loading the project data. Please try again.'),
'alert',
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 62f49ba56b1..af408c06556 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -63,6 +63,10 @@ export function initIde(el, options = {}) {
codesandboxBundlerUrl: el.dataset.codesandboxBundlerUrl,
});
},
+ beforeDestroy() {
+ // This helps tests do Singleton cleanups which we don't really have responsibility to know about here.
+ this.$emit('destroy');
+ },
methods: {
...mapActions(['setEmptyStateSvgs', 'setLinks', 'setInitialData']),
},
diff --git a/app/assets/javascripts/ide/lib/common/disposable.js b/app/assets/javascripts/ide/lib/common/disposable.js
index 84b29bdb600..c5d0773c9a2 100644
--- a/app/assets/javascripts/ide/lib/common/disposable.js
+++ b/app/assets/javascripts/ide/lib/common/disposable.js
@@ -4,11 +4,11 @@ export default class Disposable {
}
add(...disposers) {
- disposers.forEach(disposer => this.disposers.add(disposer));
+ disposers.forEach((disposer) => this.disposers.add(disposer));
}
dispose() {
- this.disposers.forEach(disposer => disposer.dispose());
+ this.disposers.forEach((disposer) => disposer.dispose());
this.disposers.clear();
}
}
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 2471b3627ce..4969875439e 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -75,7 +75,7 @@ export default class Model {
}
onChange(cb) {
- this.events.add(this.disposable.add(this.model.onDidChangeContent(e => cb(this, e))));
+ this.events.add(this.disposable.add(this.model.onDidChangeContent((e) => cb(this, e))));
}
onDispose(cb) {
@@ -121,7 +121,7 @@ export default class Model {
dispose() {
if (!this.model.isDisposed()) this.applyCustomOptions();
- this.events.forEach(cb => {
+ this.events.forEach((cb) => {
if (typeof cb === 'function') cb();
});
diff --git a/app/assets/javascripts/ide/lib/create_diff.js b/app/assets/javascripts/ide/lib/create_diff.js
index 3e915afdbcb..51d4967fb23 100644
--- a/app/assets/javascripts/ide/lib/create_diff.js
+++ b/app/assets/javascripts/ide/lib/create_diff.js
@@ -32,8 +32,8 @@ const filesWithChanges = ({ stagedFiles = [], changedFiles = [], entries = {} })
// We need to clean "move" actions, because we can only support 100% similarity moves at the moment.
// This is because the previous file's content might not be loaded.
Object.values(changes)
- .filter(change => change.action === commitActionTypes.move)
- .forEach(change => {
+ .filter((change) => change.action === commitActionTypes.move)
+ .forEach((change) => {
const prev = changes[change.file.prevPath];
if (!prev) {
@@ -51,14 +51,14 @@ const filesWithChanges = ({ stagedFiles = [], changedFiles = [], entries = {} })
// Next, we need to add deleted directories by looking at the parents
Object.values(changes)
- .filter(change => change.action === commitActionTypes.delete && change.file.parentPath)
+ .filter((change) => change.action === commitActionTypes.delete && change.file.parentPath)
.forEach(({ file }) => {
// Do nothing if we've already visited this directory.
if (changes[file.parentPath]) {
return;
}
- getDeletedParents(entries, file).forEach(parent => {
+ getDeletedParents(entries, file).forEach((parent) => {
changes[parent.path] = { action: commitActionTypes.delete, file: parent };
});
});
@@ -66,13 +66,15 @@ const filesWithChanges = ({ stagedFiles = [], changedFiles = [], entries = {} })
return Object.values(changes);
};
-const createDiff = state => {
+const createDiff = (state) => {
const changes = filesWithChanges(state);
- const toDelete = changes.filter(x => x.action === commitActionTypes.delete).map(x => x.file.path);
+ const toDelete = changes
+ .filter((x) => x.action === commitActionTypes.delete)
+ .map((x) => x.file.path);
const patch = changes
- .filter(x => x.action !== commitActionTypes.delete)
+ .filter((x) => x.action !== commitActionTypes.delete)
.map(({ file, action }) => createFileDiff(file, action))
.join('');
diff --git a/app/assets/javascripts/ide/lib/create_file_diff.js b/app/assets/javascripts/ide/lib/create_file_diff.js
index 5ae4993321c..b417b4765d8 100644
--- a/app/assets/javascripts/ide/lib/create_file_diff.js
+++ b/app/assets/javascripts/ide/lib/create_file_diff.js
@@ -12,13 +12,13 @@ const NEW_LINE = '\n';
*
* - Removes "=======" separator added at the beginning
*/
-const cleanTwoFilesPatch = text => text.replace(/^(=+\s*)/, '');
+const cleanTwoFilesPatch = (text) => text.replace(/^(=+\s*)/, '');
-const endsWithNewLine = val => !val || val[val.length - 1] === NEW_LINE;
+const endsWithNewLine = (val) => !val || val[val.length - 1] === NEW_LINE;
-const addEndingNewLine = val => (endsWithNewLine(val) ? val : val + NEW_LINE);
+const addEndingNewLine = (val) => (endsWithNewLine(val) ? val : val + NEW_LINE);
-const removeEndingNewLine = val => (endsWithNewLine(val) ? val.substr(0, val.length - 1) : val);
+const removeEndingNewLine = (val) => (endsWithNewLine(val) ? val.substr(0, val.length - 1) : val);
const diffHead = (prevPath, newPath = '') =>
`diff --git "a/${prevPath}" "b/${newPath || prevPath}"`;
@@ -37,7 +37,7 @@ const createDiffBody = (path, content, isCreate) => {
const chunkHead = isCreate ? `@@ -0,0 +1,${lines.length} @@` : `@@ -1,${lines.length} +0,0 @@`;
const chunk = lines
- .map(line => `${prefix}${line}`)
+ .map((line) => `${prefix}${line}`)
.concat(!hasNewLine ? [NO_NEW_LINE] : [])
.join(NEW_LINE);
diff --git a/app/assets/javascripts/ide/lib/decorations/controller.js b/app/assets/javascripts/ide/lib/decorations/controller.js
index 13d477bb2cf..b5d3eb10952 100644
--- a/app/assets/javascripts/ide/lib/decorations/controller.js
+++ b/app/assets/javascripts/ide/lib/decorations/controller.js
@@ -11,7 +11,7 @@ export default class DecorationsController {
const modelDecorations = this.decorations.get(model.url);
const decorations = [];
- modelDecorations.forEach(val => decorations.push(...val));
+ modelDecorations.forEach((val) => decorations.push(...val));
return decorations;
}
diff --git a/app/assets/javascripts/ide/lib/diff/controller.js b/app/assets/javascripts/ide/lib/diff/controller.js
index 35fcda6a6c5..3efe692be13 100644
--- a/app/assets/javascripts/ide/lib/diff/controller.js
+++ b/app/assets/javascripts/ide/lib/diff/controller.js
@@ -3,7 +3,7 @@ import { throttle } from 'lodash';
import DirtyDiffWorker from './diff_worker';
import Disposable from '../common/disposable';
-export const getDiffChangeType = change => {
+export const getDiffChangeType = (change) => {
if (change.modified) {
return 'modified';
} else if (change.added) {
@@ -15,7 +15,7 @@ export const getDiffChangeType = change => {
return '';
};
-export const getDecorator = change => ({
+export const getDecorator = (change) => ({
range: new Range(change.lineNumber, 1, change.endLineNumber, 1),
options: {
isWholeLine: true,
@@ -71,7 +71,7 @@ export default class DirtyDiffController {
}
decorate({ data }) {
- const decorations = data.changes.map(change => getDecorator(change));
+ const decorations = data.changes.map((change) => getDecorator(change));
const model = this.modelManager.getModel(data.path);
this.decorationsController.addDecorations(model, 'dirtyDiff', decorations);
}
diff --git a/app/assets/javascripts/ide/lib/diff/diff.js b/app/assets/javascripts/ide/lib/diff/diff.js
index 62ec798b372..5a6401f56ec 100644
--- a/app/assets/javascripts/ide/lib/diff/diff.js
+++ b/app/assets/javascripts/ide/lib/diff/diff.js
@@ -11,7 +11,7 @@ export const computeDiff = (originalContent, newContent) => {
let lineNumber = 1;
return changes.reduce((acc, change) => {
- const findOnLine = acc.find(c => c.lineNumber === lineNumber);
+ const findOnLine = acc.find((c) => c.lineNumber === lineNumber);
if (findOnLine) {
Object.assign(findOnLine, change, {
diff --git a/app/assets/javascripts/ide/lib/diff/diff_worker.js b/app/assets/javascripts/ide/lib/diff/diff_worker.js
index 77416a8de9d..78b2eab6399 100644
--- a/app/assets/javascripts/ide/lib/diff/diff_worker.js
+++ b/app/assets/javascripts/ide/lib/diff/diff_worker.js
@@ -1,7 +1,7 @@
import { computeDiff } from './diff';
// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', e => {
+self.addEventListener('message', (e) => {
const { data } = e;
// eslint-disable-next-line no-restricted-globals
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index 493dedcd89a..4fad0c09ce7 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -12,7 +12,7 @@ import { clearDomElement } from '~/editor/utils';
import { registerLanguages } from '../utils';
function setupThemes() {
- themes.forEach(theme => {
+ themes.forEach((theme) => {
monacoEditor.defineTheme(theme.name, theme.data);
});
}
@@ -108,7 +108,7 @@ export default class Editor {
this.instance.updateOptions(
editorOptions.reduce((acc, obj) => {
- Object.keys(obj).forEach(key => {
+ Object.keys(obj).forEach((key) => {
Object.assign(acc, {
[key]: obj[key](model),
});
@@ -177,7 +177,7 @@ export default class Editor {
onPositionChange(cb) {
if (!this.instance.onDidChangeCursorPosition) return;
- this.disposable.add(this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)));
+ this.disposable.add(this.instance.onDidChangeCursorPosition((e) => cb(this.instance, e)));
}
updateDiffView() {
@@ -213,14 +213,14 @@ export default class Editor {
addCommands() {
const { store } = this;
- const getKeyCode = key => {
+ const getKeyCode = (key) => {
const monacoKeyMod = key.indexOf('KEY_') === 0;
return monacoKeyMod ? KeyCode[key] : KeyMod[key];
};
- keymap.forEach(command => {
- const keybindings = command.bindings.map(binding => {
+ keymap.forEach((command) => {
+ const keybindings = command.bindings.map((binding) => {
const keys = binding.split('+');
// eslint-disable-next-line no-bitwise
diff --git a/app/assets/javascripts/ide/lib/editor_options.js b/app/assets/javascripts/ide/lib/editor_options.js
index f182a1ec50e..9f2a9a8cf4a 100644
--- a/app/assets/javascripts/ide/lib/editor_options.js
+++ b/app/assets/javascripts/ide/lib/editor_options.js
@@ -31,7 +31,7 @@ export const defaultModelOptions = {
export const editorOptions = [
{
- readOnly: model => Boolean(model.file.file_lock),
- quickSuggestions: model => !(model.language === 'markdown'),
+ readOnly: (model) => Boolean(model.file.file_lock),
+ quickSuggestions: (model) => !(model.language === 'markdown'),
},
];
diff --git a/app/assets/javascripts/ide/lib/editorconfig/parser.js b/app/assets/javascripts/ide/lib/editorconfig/parser.js
index 1597e4a8bfa..2adc643a15b 100644
--- a/app/assets/javascripts/ide/lib/editorconfig/parser.js
+++ b/app/assets/javascripts/ide/lib/editorconfig/parser.js
@@ -2,7 +2,7 @@ import { parseString } from 'editorconfig/src/lib/ini';
import minimatch from 'minimatch';
import { getPathParents } from '../../utils';
-const dirname = path => path.replace(/\.editorconfig$/, '');
+const dirname = (path) => path.replace(/\.editorconfig$/, '');
function isRootConfig(config) {
return config.some(([pattern, rules]) => !pattern && rules?.root === 'true');
@@ -44,11 +44,16 @@ function getRulesWithConfigs(filePath, configFiles = [], rules = {}) {
export function getRulesWithTraversal(filePath, getFileContent) {
const editorconfigPaths = [
- ...getPathParents(filePath).map(x => `${x}/.editorconfig`),
+ ...getPathParents(filePath).map((x) => `${x}/.editorconfig`),
'.editorconfig',
];
return Promise.all(
- editorconfigPaths.map(path => getFileContent(path).then(content => ({ path, content }))),
- ).then(results => getRulesWithConfigs(filePath, results.filter(x => x.content)));
+ editorconfigPaths.map((path) => getFileContent(path).then((content) => ({ path, content }))),
+ ).then((results) =>
+ getRulesWithConfigs(
+ filePath,
+ results.filter((x) => x.content),
+ ),
+ );
}
diff --git a/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js b/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js
index f9d5579511a..25ffa9a15be 100644
--- a/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js
+++ b/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js
@@ -1,23 +1,23 @@
import { isBoolean, isNumber } from 'lodash';
-const map = (key, validValues) => value =>
+const map = (key, validValues) => (value) =>
value in validValues ? { [key]: validValues[value] } : {};
-const bool = key => value => (isBoolean(value) ? { [key]: value } : {});
+const bool = (key) => (value) => (isBoolean(value) ? { [key]: value } : {});
-const int = (key, isValid) => value =>
+const int = (key, isValid) => (value) =>
isNumber(value) && isValid(value) ? { [key]: Math.trunc(value) } : {};
const rulesMapper = {
indent_style: map('insertSpaces', { tab: false, space: true }),
- indent_size: int('tabSize', n => n > 0),
- tab_width: int('tabSize', n => n > 0),
+ indent_size: int('tabSize', (n) => n > 0),
+ tab_width: int('tabSize', (n) => n > 0),
trim_trailing_whitespace: bool('trimTrailingWhitespace'),
end_of_line: map('endOfLine', { crlf: 1, lf: 0 }),
insert_final_newline: bool('insertFinalNewline'),
};
-const parseValue = x => {
+const parseValue = (x) => {
let value = typeof x === 'string' ? x.toLowerCase() : x;
if (/^[0-9.-]+$/.test(value)) value = Number(value);
if (value === 'true') value = true;
diff --git a/app/assets/javascripts/ide/lib/errors.js b/app/assets/javascripts/ide/lib/errors.js
index e62d9d1e77f..f975034a872 100644
--- a/app/assets/javascripts/ide/lib/errors.js
+++ b/app/assets/javascripts/ide/lib/errors.js
@@ -6,17 +6,17 @@ const CODEOWNERS_REGEX = /Push.*protected branches.*CODEOWNERS/;
const BRANCH_CHANGED_REGEX = /changed.*since.*start.*edit/;
const BRANCH_ALREADY_EXISTS = /branch.*already.*exists/;
-const createNewBranchAndCommit = store =>
+const createNewBranchAndCommit = (store) =>
store
.dispatch('commit/updateCommitAction', consts.COMMIT_TO_NEW_BRANCH)
.then(() => store.dispatch('commit/commitChanges'));
-export const createUnexpectedCommitError = message => ({
+export const createUnexpectedCommitError = (message) => ({
title: __('Unexpected error'),
messageHTML: escape(message) || __('Could not commit. An unexpected error occurred.'),
});
-export const createCodeownersCommitError = message => ({
+export const createCodeownersCommitError = (message) => ({
title: __('CODEOWNERS rule violation'),
messageHTML: escape(message),
primaryAction: {
@@ -25,7 +25,7 @@ export const createCodeownersCommitError = message => ({
},
});
-export const createBranchChangedCommitError = message => ({
+export const createBranchChangedCommitError = (message) => ({
title: __('Branch changed'),
messageHTML: `${escape(message)}<br/><br/>${__('Would you like to create a new branch?')}`,
primaryAction: {
@@ -34,19 +34,19 @@ export const createBranchChangedCommitError = message => ({
},
});
-export const branchAlreadyExistsCommitError = message => ({
+export const branchAlreadyExistsCommitError = (message) => ({
title: __('Branch already exists'),
messageHTML: `${escape(message)}<br/><br/>${__(
'Would you like to try auto-generating a branch name?',
)}`,
primaryAction: {
text: __('Create new branch'),
- callback: store =>
+ callback: (store) =>
store.dispatch('commit/addSuffixToBranchName').then(() => createNewBranchAndCommit(store)),
},
});
-export const parseCommitError = e => {
+export const parseCommitError = (e) => {
const { message } = e?.response?.data || {};
if (!message) {
diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js
index 789e09fa8f2..3fdf012bbb2 100644
--- a/app/assets/javascripts/ide/lib/files.js
+++ b/app/assets/javascripts/ide/lib/files.js
@@ -1,6 +1,6 @@
import { decorateData, sortTree } from '../stores/utils';
-export const splitParent = path => {
+export const splitParent = (path) => {
const idx = path.lastIndexOf('/');
return {
@@ -11,8 +11,20 @@ export const splitParent = path => {
/**
* Create file objects from a list of file paths.
+ *
+ * @param {Array} options.data Array of blob paths to parse and create a file tree from.
+ * @param {Boolean} options.tempFile Web IDE flag for whether this is a "new" file or not.
+ * @param {String} options.content Content to initialize the new blob with.
+ * @param {String} options.rawPath Raw path used for the new blob.
+ * @param {Object} options.blobData Extra values to initialize each blob with.
*/
-export const decorateFiles = ({ data, tempFile = false, content = '', rawPath = '' }) => {
+export const decorateFiles = ({
+ data,
+ tempFile = false,
+ content = '',
+ rawPath = '',
+ blobData = {},
+}) => {
const treeList = [];
const entries = {};
@@ -20,7 +32,7 @@ export const decorateFiles = ({ data, tempFile = false, content = '', rawPath =
let file;
let parentPath;
- const insertParent = path => {
+ const insertParent = (path) => {
if (!path) {
return null;
} else if (entries[path]) {
@@ -55,7 +67,7 @@ export const decorateFiles = ({ data, tempFile = false, content = '', rawPath =
return tree;
};
- data.forEach(path => {
+ data.forEach((path) => {
const { parent, name } = splitParent(path);
const fileFolder = parent && insertParent(parent);
@@ -73,6 +85,7 @@ export const decorateFiles = ({ data, tempFile = false, content = '', rawPath =
content,
rawPath,
parentPath,
+ ...blobData,
});
Object.assign(entries, {
diff --git a/app/assets/javascripts/ide/lib/languages/hcl.js b/app/assets/javascripts/ide/lib/languages/hcl.js
index 4539719b1f2..bbb2ca66f33 100644
--- a/app/assets/javascripts/ide/lib/languages/hcl.js
+++ b/app/assets/javascripts/ide/lib/languages/hcl.js
@@ -11,7 +11,11 @@ const conf = {
lineComment: '//',
blockComment: ['/*', '*/'],
},
- brackets: [['{', '}'], ['[', ']'], ['(', ')']],
+ brackets: [
+ ['{', '}'],
+ ['[', ']'],
+ ['(', ')'],
+ ],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
@@ -140,7 +144,7 @@ const language = {
],
heredocBody: [
[
- /^([\w\-]+)$/,
+ /([\w\-]+)$/,
{
cases: {
'$1==$S2': [
@@ -161,7 +165,11 @@ const language = {
[/\/\/.*$/, 'comment'],
[/#.*$/, 'comment'],
],
- comment: [[/[^\/*]+/, 'comment'], [/\*\//, 'comment', '@pop'], [/[\/*]/, 'comment']],
+ comment: [
+ [/[^\/*]+/, 'comment'],
+ [/\*\//, 'comment', '@pop'],
+ [/[\/*]/, 'comment'],
+ ],
string: [
[/\$\{/, { token: 'delimiter', next: '@stringExpression' }],
[/[^\\"\$]+/, 'string'],
diff --git a/app/assets/javascripts/ide/lib/languages/vue.js b/app/assets/javascripts/ide/lib/languages/vue.js
index b9ff5c5d776..f2f81307981 100644
--- a/app/assets/javascripts/ide/lib/languages/vue.js
+++ b/app/assets/javascripts/ide/lib/languages/vue.js
@@ -37,7 +37,13 @@ const conf = {
blockComment: ['{{!--', '--}}'],
},
- brackets: [['<!--', '-->'], ['<', '>'], ['{{', '}}'], ['{', '}'], ['(', ')']],
+ brackets: [
+ ['<!--', '-->'],
+ ['<', '>'],
+ ['{{', '}}'],
+ ['{', '}'],
+ ['(', ')'],
+ ],
autoClosingPairs: [
{ open: '{', close: '}' },
diff --git a/app/assets/javascripts/ide/lib/mirror.js b/app/assets/javascripts/ide/lib/mirror.js
index a516c28ad7a..6f9cfec9465 100644
--- a/app/assets/javascripts/ide/lib/mirror.js
+++ b/app/assets/javascripts/ide/lib/mirror.js
@@ -12,23 +12,23 @@ export const MSG_CONNECTION_ERROR = __('Could not connect to Web IDE file mirror
const noop = () => {};
export const SERVICE_DELAY = 8000;
-const cancellableWait = time => {
+const cancellableWait = (time) => {
let timeoutId = 0;
const cancel = () => clearTimeout(timeoutId);
- const promise = new Promise(resolve => {
+ const promise = new Promise((resolve) => {
timeoutId = setTimeout(resolve, time);
});
return [promise, cancel];
};
-const isErrorResponse = error => error && error.code !== 0;
+const isErrorResponse = (error) => error && error.code !== 0;
-const isErrorPayload = payload => payload && payload.status_code !== 200;
+const isErrorPayload = (payload) => payload && payload.status_code !== 200;
-const getErrorFromResponse = data => {
+const getErrorFromResponse = (data) => {
if (isErrorResponse(data.error)) {
return { message: data.error.Message };
} else if (isErrorPayload(data.payload)) {
@@ -38,9 +38,9 @@ const getErrorFromResponse = data => {
return null;
};
-const getFullPath = path => mergeUrlParams({ service: SERVICE_NAME }, getWebSocketUrl(path));
+const getFullPath = (path) => mergeUrlParams({ service: SERVICE_NAME }, getWebSocketUrl(path));
-const createWebSocket = fullPath =>
+const createWebSocket = (fullPath) =>
new Promise((resolve, reject) => {
const socket = new WebSocket(fullPath, [PROTOCOL]);
const resetCallbacks = () => {
@@ -59,7 +59,7 @@ const createWebSocket = fullPath =>
};
});
-export const canConnect = ({ services = [] }) => services.some(name => name === SERVICE_NAME);
+export const canConnect = ({ services = [] }) => services.some((name) => name === SERVICE_NAME);
export const createMirror = () => {
let socket = null;
@@ -71,23 +71,23 @@ export const createMirror = () => {
cancelHandler = noop;
};
- const onCancelConnect = fn => {
+ const onCancelConnect = (fn) => {
cancelHandler = fn;
};
- const receiveMessage = ev => {
+ const receiveMessage = (ev) => {
const handle = nextMessageHandler;
nextMessageHandler = noop;
handle(JSON.parse(ev.data));
};
- const onNextMessage = fn => {
+ const onNextMessage = (fn) => {
nextMessageHandler = fn;
};
const waitForNextMessage = () =>
new Promise((resolve, reject) => {
- onNextMessage(data => {
+ onNextMessage((data) => {
const err = getErrorFromResponse(data);
if (err) {
@@ -133,7 +133,7 @@ export const createMirror = () => {
return wait
.then(() => createWebSocket(fullPath))
- .then(newSocket => {
+ .then((newSocket) => {
socket = newSocket;
socket.onmessage = receiveMessage;
});
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index 70a6a6b423d..2264d63c737 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -4,9 +4,9 @@ import Api from '~/api';
import getUserPermissions from '../queries/getUserPermissions.query.graphql';
import { query } from './gql';
-const fetchApiProjectData = projectPath => Api.project(projectPath).then(({ data }) => data);
+const fetchApiProjectData = (projectPath) => Api.project(projectPath).then(({ data }) => data);
-const fetchGqlProjectData = projectPath =>
+const fetchGqlProjectData = (projectPath) =>
query({
query: getUserPermissions,
variables: { projectPath },
@@ -27,9 +27,12 @@ export default {
return Promise.resolve(file.raw);
}
+ const options = file.binary ? { responseType: 'arraybuffer' } : {};
+
return axios
.get(file.rawPath, {
- transformResponse: [f => f],
+ transformResponse: [(f) => f],
+ ...options,
})
.then(({ data }) => data);
},
@@ -51,7 +54,7 @@ export default {
escapeFileUrl(filePath),
),
{
- transformResponse: [f => f],
+ transformResponse: [(f) => f],
},
)
.then(({ data }) => data);
diff --git a/app/assets/javascripts/ide/services/terminals.js b/app/assets/javascripts/ide/services/terminals.js
index 17b4329037d..ea54733baa4 100644
--- a/app/assets/javascripts/ide/services/terminals.js
+++ b/app/assets/javascripts/ide/services/terminals.js
@@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
-export const baseUrl = projectPath => `/${projectPath}/ide_terminals`;
+export const baseUrl = (projectPath) => `/${projectPath}/ide_terminals`;
export const checkConfig = (projectPath, branch) =>
axios.post(`${baseUrl(projectPath)}/check_config`, {
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 710256b6377..d62dfc35d15 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -20,7 +20,7 @@ export const redirectToUrl = (self, url) => visitUrl(url);
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const discardAllChanges = ({ state, commit, dispatch }) => {
- state.changedFiles.forEach(file => dispatch('restoreOriginalFile', file.path));
+ state.changedFiles.forEach((file) => dispatch('restoreOriginalFile', file.path));
commit(types.REMOVE_ALL_CHANGES_FILES);
};
@@ -31,7 +31,7 @@ export const setResizingStatus = ({ commit }, resizing) => {
export const createTempEntry = (
{ state, commit, dispatch, getters },
- { name, type, content = '', rawPath = '', openFile = true, makeFileActive = true },
+ { name, type, content = '', rawPath = '', openFile = true, makeFileActive = true, mimeType = '' },
) => {
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
@@ -56,6 +56,9 @@ export const createTempEntry = (
tempFile: true,
content,
rawPath,
+ blobData: {
+ mimeType,
+ },
});
const { file, parentPath } = data;
@@ -103,7 +106,7 @@ export const stageAllChanges = ({ state, commit, dispatch, getters }) => {
commit(types.SET_LAST_COMMIT_MSG, '');
- state.changedFiles.forEach(file =>
+ state.changedFiles.forEach((file) =>
commit(types.STAGE_CHANGE, { path: file.path, diffInfo: getters.getDiffInfo(file.path) }),
);
@@ -120,7 +123,7 @@ export const stageAllChanges = ({ state, commit, dispatch, getters }) => {
export const unstageAllChanges = ({ state, commit, dispatch, getters }) => {
const openFile = state.openFiles[0];
- state.stagedFiles.forEach(file =>
+ state.stagedFiles.forEach((file) =>
commit(types.UNSTAGE_CHANGE, { path: file.path, diffInfo: getters.getDiffInfo(file.path) }),
);
@@ -191,7 +194,7 @@ export const deleteEntry = ({ commit, dispatch, state }, path) => {
if (entry.opened) dispatch('closeFile', entry);
if (isTree) {
- entry.tree.forEach(f => dispatch('deleteEntry', f.path));
+ entry.tree.forEach((f) => dispatch('deleteEntry', f.path));
}
commit(types.DELETE_ENTRY, path);
@@ -218,7 +221,7 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name,
commit(types.RENAME_ENTRY, { path, name, parentPath });
if (entry.type === 'tree') {
- state.entries[newPath].tree.forEach(f => {
+ state.entries[newPath].tree.forEach((f) => {
dispatch('renameEntry', {
path: f.path,
name: f.name,
@@ -277,7 +280,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force =
commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
resolve(data);
})
- .catch(e => {
+ .catch((e) => {
if (e.response.status === 404) {
reject(e);
} else {
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 8b43c7238fd..42668dec63a 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -10,22 +10,15 @@ import eventHub from '../../eventhub';
import service from '../../services';
import * as types from '../mutation_types';
import { setPageTitleForFile } from '../utils';
-import { viewerTypes, stageKeys } from '../../constants';
+import { viewerTypes, stageKeys, commitActionTypes } from '../../constants';
export const closeFile = ({ commit, state, dispatch, getters }, file) => {
const { path } = file;
- const indexOfClosedFile = state.openFiles.findIndex(f => f.key === file.key);
+ const indexOfClosedFile = state.openFiles.findIndex((f) => f.key === file.key);
const fileWasActive = file.active;
- if (file.pending) {
- commit(types.REMOVE_PENDING_TAB, file);
- } else {
- commit(types.TOGGLE_FILE_OPEN, path);
- commit(types.SET_FILE_ACTIVE, { path, active: false });
- }
-
- if (state.openFiles.length > 0 && fileWasActive) {
- const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
+ if (state.openFiles.length > 1 && fileWasActive) {
+ const nextIndexToOpen = indexOfClosedFile === 0 ? 1 : indexOfClosedFile - 1;
const nextFileToOpen = state.openFiles[nextIndexToOpen];
if (nextFileToOpen.pending) {
@@ -35,14 +28,22 @@ export const closeFile = ({ commit, state, dispatch, getters }, file) => {
keyPrefix: nextFileToOpen.staged ? 'staged' : 'unstaged',
});
} else {
+ dispatch('setFileActive', nextFileToOpen.path);
dispatch('router/push', getters.getUrlForPath(nextFileToOpen.path), { root: true });
}
- } else if (!state.openFiles.length) {
+ } else if (state.openFiles.length === 1) {
dispatch('router/push', `/project/${state.currentProjectId}/tree/${state.currentBranchId}/`, {
root: true,
});
}
+ if (file.pending) {
+ commit(types.REMOVE_PENDING_TAB, file);
+ } else {
+ commit(types.TOGGLE_FILE_OPEN, path);
+ commit(types.SET_FILE_ACTIVE, { path, active: false });
+ }
+
eventHub.$emit(`editor.update.model.dispose.${file.key}`);
};
@@ -108,7 +109,7 @@ export const getFileData = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the file.'),
- action: payload =>
+ action: (payload) =>
dispatch('getFileData', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
actionPayload: { path, makeFileActive },
@@ -125,13 +126,13 @@ export const setFileMrChange = ({ commit }, { file, mrChange }) => {
export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) => {
const file = state.entries[path];
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
const fileDeletedAndReadded = getters.isFileDeletedAndReadded(path);
commit(types.TOGGLE_LOADING, { entry: file, forceValue: true });
return service
.getRawFileData(fileDeletedAndReadded ? stagedFile : file)
- .then(raw => {
+ .then((raw) => {
if (!(file.tempFile && !file.prevPath && !fileDeletedAndReadded))
commit(types.SET_FILE_RAW_DATA, { file, raw, fileDeletedAndReadded });
@@ -139,7 +140,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
const baseSha =
(getters.currentMergeRequest && getters.currentMergeRequest.baseCommitSha) || '';
- return service.getBaseRawFileData(file, state.currentProjectId, baseSha).then(baseRaw => {
+ return service.getBaseRawFileData(file, state.currentProjectId, baseSha).then((baseRaw) => {
commit(types.SET_FILE_BASE_RAW_DATA, {
file,
baseRaw,
@@ -149,10 +150,10 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
}
return raw;
})
- .catch(e => {
+ .catch((e) => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the file content.'),
- action: payload =>
+ action: (payload) =>
dispatch('getRawFileData', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
actionPayload: { path },
@@ -164,7 +165,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
});
};
-export const changeFileContent = ({ commit, state, getters }, { path, content }) => {
+export const changeFileContent = ({ commit, dispatch, state, getters }, { path, content }) => {
const file = state.entries[path];
// It's possible for monaco to hit a race condition where it tries to update renamed files.
@@ -178,13 +179,15 @@ export const changeFileContent = ({ commit, state, getters }, { path, content })
content,
});
- const indexOfChangedFile = state.changedFiles.findIndex(f => f.path === path);
+ const indexOfChangedFile = state.changedFiles.findIndex((f) => f.path === path);
if (file.changed && indexOfChangedFile === -1) {
commit(types.STAGE_CHANGE, { path, diffInfo: getters.getDiffInfo(path) });
} else if (!file.changed && !file.tempFile && indexOfChangedFile !== -1) {
commit(types.REMOVE_FILE_FROM_CHANGED, path);
}
+
+ dispatch('triggerFilesChange', { type: commitActionTypes.update, path });
};
export const restoreOriginalFile = ({ dispatch, state, commit }, path) => {
@@ -225,7 +228,7 @@ export const discardFileChanges = ({ dispatch, state, commit, getters }, path) =
.then(() => {
dispatch('router/push', getters.getUrlForPath(file.path), { root: true });
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
}
@@ -275,7 +278,7 @@ export const unstageChange = ({ commit, dispatch, getters }, path) => {
export const openPendingTab = ({ commit, dispatch, getters, state }, { file, keyPrefix }) => {
if (getters.activeFile && getters.activeFile.key === `${keyPrefix}-${file.key}`) return false;
- state.openFiles.forEach(f => eventHub.$emit(`editor.update.model.dispose.${f.key}`));
+ state.openFiles.forEach((f) => eventHub.$emit(`editor.update.model.dispose.${f.key}`));
commit(types.ADD_PENDING_TAB, { file, keyPrefix });
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 547665b49c6..8215cba7ccf 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -33,7 +33,7 @@ export const getMergeRequestsForBranch = (
commit(types.SET_CURRENT_MERGE_REQUEST, `${currentMR.iid}`);
}
})
- .catch(e => {
+ .catch((e) => {
flash(
__(`Error fetching merge requests for ${branchId}`),
'alert',
@@ -66,7 +66,7 @@ export const getMergeRequestData = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request.'),
- action: payload =>
+ action: (payload) =>
dispatch('getMergeRequestData', payload).then(() =>
dispatch('setErrorMessage', null),
),
@@ -99,7 +99,7 @@ export const getMergeRequestChanges = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request changes.'),
- action: payload =>
+ action: (payload) =>
dispatch('getMergeRequestChanges', payload).then(() =>
dispatch('setErrorMessage', null),
),
@@ -121,8 +121,8 @@ export const getMergeRequestVersions = (
if (!state.projects[projectId].mergeRequests[mergeRequestId].versions.length || force) {
service
.getProjectMergeRequestVersions(targetProjectId || projectId, mergeRequestId)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
commit(types.SET_MERGE_REQUEST_VERSIONS, {
projectPath: projectId,
mergeRequestId,
@@ -133,7 +133,7 @@ export const getMergeRequestVersions = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request version data.'),
- action: payload =>
+ action: (payload) =>
dispatch('getMergeRequestVersions', payload).then(() =>
dispatch('setErrorMessage', null),
),
@@ -156,7 +156,7 @@ export const openMergeRequest = (
targetProjectId,
mergeRequestId,
})
- .then(mr => {
+ .then((mr) => {
dispatch('setCurrentBranchId', mr.source_branch);
return dispatch('getBranchData', {
@@ -186,7 +186,7 @@ export const openMergeRequest = (
mergeRequestId,
}),
)
- .then(mrChanges => {
+ .then((mrChanges) => {
if (mrChanges.changes.length) {
dispatch('updateActivityBarView', leftSidebarViews.review.name);
}
@@ -210,7 +210,7 @@ export const openMergeRequest = (
}
});
})
- .catch(e => {
+ .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 51e9bf6a84c..27f6848f1d6 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -11,8 +11,8 @@ export const getProjectData = ({ commit, state }, { namespace, projectId, force
commit(types.TOGGLE_LOADING, { entry: state });
service
.getProjectData(namespace, projectId)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
commit(types.TOGGLE_LOADING, { entry: state });
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
@@ -44,8 +44,9 @@ export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {})
commit: data.commit,
});
})
- .catch(() => {
+ .catch((e) => {
flash(__('Error loading last commit.'), 'alert', document, null, false, true);
+ throw e;
});
export const createNewBranchFromDefault = ({ state, dispatch, getters }, branch) =>
@@ -61,7 +62,7 @@ export const createNewBranchFromDefault = ({ state, dispatch, getters }, branch)
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred creating the new branch.'),
- action: payload => dispatch('createNewBranchFromDefault', payload),
+ action: (payload) => dispatch('createNewBranchFromDefault', payload),
actionText: __('Please try again'),
actionPayload: branch,
});
@@ -76,7 +77,7 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => {
},
false,
),
- action: payload => dispatch('createNewBranchFromDefault', payload),
+ action: (payload) => dispatch('createNewBranchFromDefault', payload),
actionText: __('Create branch'),
actionPayload: branchId,
});
@@ -102,7 +103,7 @@ export const loadFile = ({ dispatch, state }, { basePath }) => {
if (basePath) {
const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
const treeEntryKey = Object.keys(state.entries).find(
- key => key === path && !state.entries[key].pending,
+ (key) => key === path && !state.entries[key].pending,
);
const treeEntry = state.entries[treeEntryKey];
@@ -144,7 +145,7 @@ export const loadBranch = ({ dispatch, getters, state }, { projectId, branchId }
ref: branch.commit.id,
});
})
- .catch(err => {
+ .catch((err) => {
dispatch('showBranchNotFoundError', branchId);
throw err;
});
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 23a5e26bc1c..150dfcb2726 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -87,10 +87,10 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) => {
resolve();
})
- .catch(e => {
+ .catch((e) => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading all the files.'),
- action: actionPayload =>
+ action: (actionPayload) =>
dispatch('getFiles', actionPayload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
actionPayload: { projectId, branchId },
diff --git a/app/assets/javascripts/ide/stores/extend.js b/app/assets/javascripts/ide/stores/extend.js
index 1c1636cf6ca..b2777ec89ff 100644
--- a/app/assets/javascripts/ide/stores/extend.js
+++ b/app/assets/javascripts/ide/stores/extend.js
@@ -8,7 +8,7 @@ const plugins = () => [
export default (store, el) => {
// plugins is actually an array of plugin factories, so we have to create first then call
- plugins().forEach(plugin => plugin(el)(store));
+ plugins().forEach((plugin) => plugin(el)(store));
return store;
};
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 500ce9f32d5..59e8d37a92a 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -9,19 +9,19 @@ import {
import { addNumericSuffix } from '~/ide/utils';
import Api from '~/api';
-export const activeFile = state => state.openFiles.find(file => file.active) || null;
+export const activeFile = (state) => state.openFiles.find((file) => file.active) || null;
-export const addedFiles = state => state.changedFiles.filter(f => f.tempFile);
+export const addedFiles = (state) => state.changedFiles.filter((f) => f.tempFile);
-export const modifiedFiles = state => state.changedFiles.filter(f => !f.tempFile);
+export const modifiedFiles = (state) => state.changedFiles.filter((f) => !f.tempFile);
-export const projectsWithTrees = state =>
- Object.keys(state.projects).map(projectId => {
+export const projectsWithTrees = (state) =>
+ Object.keys(state.projects).map((projectId) => {
const project = state.projects[projectId];
return {
...project,
- branches: Object.keys(project.branches).map(branchId => {
+ branches: Object.keys(project.branches).map((branchId) => {
const branch = project.branches[branchId];
return {
@@ -32,7 +32,7 @@ export const projectsWithTrees = state =>
};
});
-export const currentMergeRequest = state => {
+export const currentMergeRequest = (state) => {
if (
state.projects[state.currentProjectId] &&
state.projects[state.currentProjectId].mergeRequests
@@ -42,19 +42,19 @@ export const currentMergeRequest = state => {
return null;
};
-export const findProject = state => projectId => state.projects[projectId];
+export const findProject = (state) => (projectId) => state.projects[projectId];
export const currentProject = (state, getters) => getters.findProject(state.currentProjectId);
-export const emptyRepo = state =>
+export const emptyRepo = (state) =>
state.projects[state.currentProjectId] && state.projects[state.currentProjectId].empty_repo;
-export const currentTree = state =>
+export const currentTree = (state) =>
state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
-export const hasMergeRequest = state => Boolean(state.currentMergeRequestId);
+export const hasMergeRequest = (state) => Boolean(state.currentMergeRequestId);
-export const allBlobs = state =>
+export const allBlobs = (state) =>
Object.keys(state.entries)
.reduce((acc, key) => {
const entry = state.entries[key];
@@ -67,35 +67,35 @@ export const allBlobs = state =>
}, [])
.sort((a, b) => b.lastOpenedAt - a.lastOpenedAt);
-export const getChangedFile = state => path => state.changedFiles.find(f => f.path === path);
-export const getStagedFile = state => path => state.stagedFiles.find(f => f.path === path);
-export const getOpenFile = state => path => state.openFiles.find(f => f.path === path);
+export const getChangedFile = (state) => (path) => state.changedFiles.find((f) => f.path === path);
+export const getStagedFile = (state) => (path) => state.stagedFiles.find((f) => f.path === path);
+export const getOpenFile = (state) => (path) => state.openFiles.find((f) => f.path === path);
-export const lastOpenedFile = state =>
+export const lastOpenedFile = (state) =>
[...state.changedFiles, ...state.stagedFiles].sort((a, b) => b.lastOpenedAt - a.lastOpenedAt)[0];
-export const isEditModeActive = state => state.currentActivityView === leftSidebarViews.edit.name;
-export const isCommitModeActive = state =>
+export const isEditModeActive = (state) => state.currentActivityView === leftSidebarViews.edit.name;
+export const isCommitModeActive = (state) =>
state.currentActivityView === leftSidebarViews.commit.name;
-export const isReviewModeActive = state =>
+export const isReviewModeActive = (state) =>
state.currentActivityView === leftSidebarViews.review.name;
-export const someUncommittedChanges = state =>
+export const someUncommittedChanges = (state) =>
Boolean(state.changedFiles.length || state.stagedFiles.length);
-export const getChangesInFolder = state => path => {
- const changedFilesCount = state.changedFiles.filter(f => filePathMatches(f.path, path)).length;
+export const getChangesInFolder = (state) => (path) => {
+ const changedFilesCount = state.changedFiles.filter((f) => filePathMatches(f.path, path)).length;
const stagedFilesCount = state.stagedFiles.filter(
- f => filePathMatches(f.path, path) && !getChangedFile(state)(f.path),
+ (f) => filePathMatches(f.path, path) && !getChangedFile(state)(f.path),
).length;
return changedFilesCount + stagedFilesCount;
};
-export const getUnstagedFilesCountForPath = state => path =>
+export const getUnstagedFilesCountForPath = (state) => (path) =>
getChangesCountForFiles(state.changedFiles, path);
-export const getStagedFilesCountForPath = state => path =>
+export const getStagedFilesCountForPath = (state) => (path) =>
getChangesCountForFiles(state.stagedFiles, path);
export const lastCommit = (state, getters) => {
@@ -115,7 +115,7 @@ export const currentBranch = (state, getters) =>
export const branchName = (_state, getters) => getters.currentBranch && getters.currentBranch.name;
-export const packageJson = state => state.entries[packageJsonPath];
+export const packageJson = (state) => state.entries[packageJsonPath];
export const isOnDefaultBranch = (_state, getters) =>
getters.currentProject && getters.currentProject.default_branch === getters.branchName;
@@ -124,14 +124,14 @@ export const canPushToBranch = (_state, getters) => {
return Boolean(getters.currentBranch ? getters.currentBranch.can_push : getters.canPushCode);
};
-export const isFileDeletedAndReadded = (state, getters) => path => {
+export const isFileDeletedAndReadded = (state, getters) => (path) => {
const stagedFile = getters.getStagedFile(path);
const file = state.entries[path];
return Boolean(stagedFile && stagedFile.deleted && file.tempFile);
};
// checks if any diff exists in the staged or unstaged changes for this path
-export const getDiffInfo = (state, getters) => path => {
+export const getDiffInfo = (state, getters) => (path) => {
const stagedFile = getters.getStagedFile(path);
const file = state.entries[path];
const renamed = file.prevPath ? file.path !== file.prevPath : false;
@@ -149,7 +149,7 @@ export const getDiffInfo = (state, getters) => path => {
};
};
-export const findProjectPermissions = (state, getters) => projectId =>
+export const findProjectPermissions = (state, getters) => (projectId) =>
getters.findProject(projectId)?.userPermissions || {};
export const canReadMergeRequests = (state, getters) =>
@@ -161,10 +161,10 @@ export const canCreateMergeRequests = (state, getters) =>
export const canPushCode = (state, getters) =>
Boolean(getters.findProjectPermissions(state.currentProjectId)[PERMISSION_PUSH_CODE]);
-export const entryExists = state => path =>
+export const entryExists = (state) => (path) =>
Boolean(state.entries[path] && !state.entries[path].deleted);
-export const getAvailableFileName = (state, getters) => path => {
+export const getAvailableFileName = (state, getters) => (path) => {
let newPath = path;
while (getters.entryExists(newPath)) {
@@ -174,10 +174,10 @@ export const getAvailableFileName = (state, getters) => path => {
return newPath;
};
-export const getUrlForPath = state => path =>
+export const getUrlForPath = (state) => (path) =>
`/project/${state.currentProjectId}/tree/${state.currentBranchId}/-/${path}/`;
-export const getJsonSchemaForPath = (state, getters) => path => {
+export const getJsonSchemaForPath = (state, getters) => (path) => {
const [namespace, ...project] = state.currentProjectId.split('/');
return {
uri:
diff --git a/app/assets/javascripts/ide/stores/modules/branches/actions.js b/app/assets/javascripts/ide/stores/modules/branches/actions.js
index c46289f77e2..74a4cd9848b 100644
--- a/app/assets/javascripts/ide/stores/modules/branches/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/branches/actions.js
@@ -8,7 +8,7 @@ export const receiveBranchesError = ({ commit, dispatch }, { search }) => {
'setErrorMessage',
{
text: __('Error loading branches.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchBranches', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/branches/mutations.js b/app/assets/javascripts/ide/stores/modules/branches/mutations.js
index 0a455f4500f..3883e1cc905 100644
--- a/app/assets/javascripts/ide/stores/modules/branches/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/branches/mutations.js
@@ -9,7 +9,7 @@ export default {
},
[types.RECEIVE_BRANCHES_SUCCESS](state, data) {
state.isLoading = false;
- state.branches = data.map(branch => ({
+ state.branches = data.map((branch) => ({
name: branch.name,
committedDate: branch.commit.committed_date,
}));
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index e0d2028d2e1..29b9a8a9521 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -78,8 +78,8 @@ export const updateFilesAfterCommit = ({ commit, dispatch, rootState, rootGetter
{ root: true },
);
- rootState.stagedFiles.forEach(file => {
- const changedFile = rootState.changedFiles.find(f => f.path === file.path);
+ rootState.stagedFiles.forEach((file) => {
+ const changedFile = rootState.changedFiles.find((f) => f.path === file.path);
commit(
rootTypes.UPDATE_FILE_AFTER_COMMIT,
@@ -133,7 +133,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
return service.commit(rootState.currentProjectId, payload);
})
- .catch(e => {
+ .catch((e) => {
commit(types.UPDATE_LOADING, false);
commit(types.SET_ERROR, parseCommitError(e));
@@ -193,37 +193,36 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
},
{ root: true },
)
- .then(changeViewer => {
+ .then((changeViewer) => {
if (changeViewer) {
dispatch('updateViewer', 'diff', { root: true });
}
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
} else {
dispatch('updateActivityBarView', leftSidebarViews.edit.name, { root: true });
dispatch('updateViewer', 'editor', { root: true });
-
- if (rootGetters.activeFile) {
- dispatch(
- 'router/push',
- `/project/${rootState.currentProjectId}/blob/${branchName}/-/${rootGetters.activeFile.path}`,
- { root: true },
- );
- }
}
})
.then(() => dispatch('updateCommitAction', consts.COMMIT_TO_CURRENT_BRANCH))
- .then(() =>
- dispatch(
+ .then(() => {
+ if (newBranch) {
+ const path = rootGetters.activeFile ? rootGetters.activeFile.path : '';
+
+ return dispatch(
+ 'router/push',
+ `/project/${rootState.currentProjectId}/blob/${branchName}/-/${path}`,
+ { root: true },
+ );
+ }
+
+ return dispatch(
'refreshLastCommitData',
- {
- projectId: rootState.currentProjectId,
- branchId: rootState.currentBranchId,
- },
+ { projectId: rootState.currentProjectId, branchId: branchName },
{ root: true },
- ),
- );
+ );
+ });
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
index 416ca88d6c9..2301cf23f9f 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -11,7 +11,7 @@ const createTranslatedTextForFiles = (files, text) => {
});
};
-export const discardDraftButtonDisabled = state =>
+export const discardDraftButtonDisabled = (state) =>
state.commitMessage === '' || state.submitCommitLoading;
// Note: If changing the structure of the placeholder branch name, please also
@@ -37,18 +37,18 @@ export const preBuiltCommitMessage = (state, _, rootState) => {
if (state.commitMessage) return state.commitMessage;
const files = rootState.stagedFiles.length ? rootState.stagedFiles : rootState.changedFiles;
- const modifiedFiles = files.filter(f => !f.deleted);
- const deletedFiles = files.filter(f => f.deleted);
+ const modifiedFiles = files.filter((f) => !f.deleted);
+ const deletedFiles = files.filter((f) => f.deleted);
return [
createTranslatedTextForFiles(modifiedFiles, __('Update')),
createTranslatedTextForFiles(deletedFiles, __('Deleted')),
]
- .filter(t => t)
+ .filter((t) => t)
.join('\n');
};
-export const isCreatingNewBranch = state => state.commitAction === consts.COMMIT_TO_NEW_BRANCH;
+export const isCreatingNewBranch = (state) => state.commitAction === consts.COMMIT_TO_NEW_BRANCH;
export const shouldHideNewMrOption = (_state, getters, _rootState, rootGetters) =>
!getters.isCreatingNewBranch &&
diff --git a/app/assets/javascripts/ide/stores/modules/editor/setup.js b/app/assets/javascripts/ide/stores/modules/editor/setup.js
index c5a613c6baa..9f3163aa6f5 100644
--- a/app/assets/javascripts/ide/stores/modules/editor/setup.js
+++ b/app/assets/javascripts/ide/stores/modules/editor/setup.js
@@ -1,18 +1,23 @@
import eventHub from '~/ide/eventhub';
import { commitActionTypes } from '~/ide/constants';
-const removeUnusedFileEditors = store => {
+const removeUnusedFileEditors = (store) => {
Object.keys(store.state.editor.fileEditors)
- .filter(path => !store.state.entries[path])
- .forEach(path => store.dispatch('editor/removeFileEditor', path));
+ .filter((path) => !store.state.entries[path])
+ .forEach((path) => store.dispatch('editor/removeFileEditor', path));
};
-export const setupFileEditorsSync = store => {
+export const setupFileEditorsSync = (store) => {
eventHub.$on('ide.files.change', ({ type, ...payload } = {}) => {
+ // Do nothing on file update because the file tree itself hasn't changed.
+ if (type === commitActionTypes.update) {
+ return;
+ }
+
if (type === commitActionTypes.move) {
store.dispatch('editor/renameFileEditor', payload);
} else {
- // The files have changed, but the specific change is not known.
+ // The file tree has changed, but the specific change is not known.
removeUnusedFileEditors(store);
}
});
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 6b2c929cd44..6800f824da0 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
@@ -68,7 +68,7 @@ export const receiveTemplateError = ({ dispatch }, template) => {
'setErrorMessage',
{
text: __('Error loading template.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchTemplateTypes', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
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 4a407aea557..0613fe9b12b 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
@@ -24,6 +24,6 @@ export const templateTypes = () => [
},
];
-export const showFileTemplatesBar = (_, getters, rootState) => name =>
- getters.templateTypes.find(t => t.name === name) &&
+export const showFileTemplatesBar = (_, getters, rootState) => (name) =>
+ getters.templateTypes.find((t) => t.name === name) &&
rootState.currentActivityView === leftSidebarViews.edit.name;
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 6a1a0de033e..299f7a883d2 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
@@ -9,7 +9,7 @@ export const receiveMergeRequestsError = ({ commit, dispatch }, { type, search }
'setErrorMessage',
{
text: __('Error loading merge requests.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchMergeRequests', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js b/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js
index 7576b2477d1..eae64ad80c3 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js
@@ -9,7 +9,7 @@ export default {
},
[types.RECEIVE_MERGE_REQUESTS_SUCCESS](state, data) {
state.isLoading = false;
- state.mergeRequests = data.map(mergeRequest => ({
+ state.mergeRequests = data.map((mergeRequest) => ({
id: mergeRequest.id,
iid: mergeRequest.iid,
title: mergeRequest.title,
diff --git a/app/assets/javascripts/ide/stores/modules/pane/getters.js b/app/assets/javascripts/ide/stores/modules/pane/getters.js
index ce597329df1..66d23c8ebdc 100644
--- a/app/assets/javascripts/ide/stores/modules/pane/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pane/getters.js
@@ -1,2 +1,2 @@
-export const isAliveView = state => view =>
+export const isAliveView = (state) => (view) =>
state.keepAliveViews[view] || (state.isOpen && state.currentView === view);
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
index 99bd08ee876..2c2034d76d0 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -47,7 +47,7 @@ export const receiveLatestPipelineSuccess = ({ rootGetters, commit }, { pipeline
if (pipelines && pipelines.length) {
const lastCommitHash = rootGetters.lastCommit && rootGetters.lastCommit.id;
- lastCommitPipeline = pipelines.find(pipeline => pipeline.commit.id === lastCommitHash);
+ lastCommitPipeline = pipelines.find((pipeline) => pipeline.commit.id === lastCommitHash);
}
commit(types.RECEIVE_LASTEST_PIPELINE_SUCCESS, lastCommitPipeline);
@@ -63,7 +63,7 @@ export const fetchLatestPipeline = ({ dispatch, rootGetters }) => {
method: 'lastCommitPipelines',
data: { getters: rootGetters },
successCallback: ({ data }) => dispatch('receiveLatestPipelineSuccess', data),
- errorCallback: err => dispatch('receiveLatestPipelineError', err),
+ errorCallback: (err) => dispatch('receiveLatestPipelineError', err),
});
if (!Visibility.hidden()) {
@@ -85,7 +85,7 @@ export const receiveJobsError = ({ commit, dispatch }, stage) => {
'setErrorMessage',
{
text: __('An error occurred while loading the pipelines jobs.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchJobs', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
index eb3cc027494..051159a0fd5 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
@@ -1,22 +1,23 @@
import { states } from './constants';
-export const hasLatestPipeline = state => !state.isLoadingPipeline && Boolean(state.latestPipeline);
+export const hasLatestPipeline = (state) =>
+ !state.isLoadingPipeline && Boolean(state.latestPipeline);
-export const pipelineFailed = state =>
+export const pipelineFailed = (state) =>
state.latestPipeline && state.latestPipeline.details.status.text === states.failed;
-export const failedStages = state =>
+export const failedStages = (state) =>
state.stages
- .filter(stage => stage.status.text.toLowerCase() === states.failed)
- .map(stage => ({
+ .filter((stage) => stage.status.text.toLowerCase() === states.failed)
+ .map((stage) => ({
...stage,
- jobs: stage.jobs.filter(job => job.status.text.toLowerCase() === states.failed),
+ jobs: stage.jobs.filter((job) => job.status.text.toLowerCase() === states.failed),
}));
-export const failedJobsCount = state =>
+export const failedJobsCount = (state) =>
state.stages.reduce(
- (acc, stage) => acc + stage.jobs.filter(j => j.status.text === states.failed).length,
+ (acc, stage) => acc + stage.jobs.filter((j) => j.status.text === states.failed).length,
0,
);
-export const jobsCount = state => state.stages.reduce((acc, stage) => acc + stage.jobs.length, 0);
+export const jobsCount = (state) => state.stages.reduce((acc, stage) => acc + stage.jobs.length, 0);
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
index 3a3cb4a7cb2..09006df7e94 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
@@ -23,7 +23,7 @@ export default {
yamlError: pipeline.yaml_errors,
};
state.stages = pipeline.details.stages.map((stage, i) => {
- const foundStage = state.stages.find(s => s.id === i);
+ const foundStage = state.stages.find((s) => s.id === i);
return {
id: i,
dropdownPath: stage.dropdown_path,
@@ -39,26 +39,26 @@ export default {
}
},
[types.REQUEST_JOBS](state, id) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isLoading: stage.id === id ? true : stage.isLoading,
}));
},
[types.RECEIVE_JOBS_ERROR](state, id) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isLoading: stage.id === id ? false : stage.isLoading,
}));
},
[types.RECEIVE_JOBS_SUCCESS](state, { id, data }) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isLoading: stage.id === id ? false : stage.isLoading,
jobs: stage.id === id ? data.latest_statuses.map(normalizeJob) : stage.jobs,
}));
},
[types.TOGGLE_STAGE_COLLAPSE](state, id) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isCollapsed: stage.id === id ? !stage.isCollapsed : stage.isCollapsed,
}));
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
index 95716e0a0c6..ded00196ab7 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
@@ -1,4 +1,4 @@
-export const normalizeJob = job => ({
+export const normalizeJob = (job) => ({
id: job.id,
name: job.name,
status: job.status,
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 43b6650b241..b2c1ddd877c 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
@@ -36,7 +36,7 @@ export const fetchConfigCheck = ({ dispatch, rootState, rootGetters }) => {
.then(() => {
dispatch('receiveConfigCheckSuccess');
})
- .catch(e => {
+ .catch((e) => {
dispatch('receiveConfigCheckError', e);
});
};
@@ -92,7 +92,7 @@ export const fetchRunnersCheck = ({ dispatch, rootGetters }, options = {}) => {
.then(({ data }) => {
dispatch('receiveRunnersCheckSuccess', data);
})
- .catch(e => {
+ .catch((e) => {
dispatch('receiveRunnersCheckError', e);
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
index f20f7fc9cd6..aa460859b4c 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
@@ -45,7 +45,7 @@ export const startSession = ({ state, dispatch, rootGetters, rootState }) => {
.then(({ data }) => {
dispatch('receiveStartSessionSuccess', data);
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveStartSessionError', error);
});
};
@@ -73,7 +73,7 @@ export const stopSession = ({ state, dispatch }) => {
.then(() => {
dispatch('receiveStopSessionSuccess');
})
- .catch(err => {
+ .catch((err) => {
dispatch('receiveStopSessionError', err);
});
};
@@ -103,7 +103,7 @@ export const restartSession = ({ state, dispatch, rootState }) => {
.then(({ data }) => {
dispatch('receiveStartSessionSuccess', data);
})
- .catch(error => {
+ .catch((error) => {
const responseStatus = error.response && error.response.status;
// We may have removed the build, in this case we'll just create a new session
if (
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 d715d555aa9..3ab1817e662 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
@@ -58,7 +58,7 @@ export const fetchSessionStatus = ({ dispatch, state }) => {
.then(({ data }) => {
dispatch('receiveSessionStatusSuccess', data);
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveSessionStatusError', error);
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/getters.js b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
index b29d391845d..fb9a1a2fa39 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
@@ -1,11 +1,11 @@
-export const allCheck = state => {
+export const allCheck = (state) => {
const checks = Object.values(state.checks);
- if (checks.some(check => check.isLoading)) {
+ if (checks.some((check) => check.isLoading)) {
return { isLoading: true };
}
- const invalidCheck = checks.find(check => !check.isValid);
+ const invalidCheck = checks.find((check) => !check.isValid);
const isValid = !invalidCheck;
const message = !invalidCheck ? '' : invalidCheck.message;
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/messages.js b/app/assets/javascripts/ide/stores/modules/terminal/messages.js
index bf35ce0f0bc..967ba80cd2c 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/messages.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/messages.js
@@ -46,7 +46,7 @@ export const configCheckError = (status, helpUrl) => {
return UNEXPECTED_ERROR_CONFIG;
};
-export const runnersCheckEmpty = helpUrl =>
+export const runnersCheckEmpty = (helpUrl) =>
sprintf(
EMPTY_RUNNERS,
{
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/utils.js b/app/assets/javascripts/ide/stores/modules/terminal/utils.js
index c30136b5277..1f4bca9f50a 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/utils.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/utils.js
@@ -1,5 +1,5 @@
import { STARTING, PENDING, RUNNING } from './constants';
-export const isStartingStatus = status => status === STARTING || status === PENDING;
-export const isRunningStatus = status => status === RUNNING;
-export const isEndingStatus = status => !isStartingStatus(status) && !isRunningStatus(status);
+export const isStartingStatus = (status) => status === STARTING || status === PENDING;
+export const isRunningStatus = (status) => status === RUNNING;
+export const isEndingStatus = (status) => !isStartingStatus(status) && !isRunningStatus(status);
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 2fee6b4e974..006800f58c2 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
@@ -9,7 +9,7 @@ export const upload = ({ rootState, commit }) => {
.then(() => {
commit(types.SET_SUCCESS);
})
- .catch(err => {
+ .catch((err) => {
commit(types.SET_ERROR, err);
});
};
@@ -34,7 +34,7 @@ export const start = ({ rootState, commit }) => {
.then(() => {
commit(types.SET_SUCCESS);
})
- .catch(err => {
+ .catch((err) => {
commit(types.SET_ERROR, err);
throw err;
});
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 460d3ced381..6ed6798a5b6 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -61,7 +61,7 @@ export default {
});
} else {
const tree = entry.tree.filter(
- f => foundEntry.tree.find(e => e.path === f.path) === undefined,
+ (f) => foundEntry.tree.find((e) => e.path === f.path) === undefined,
);
Object.assign(foundEntry, {
tree: sortTree(foundEntry.tree.concat(tree)),
@@ -72,7 +72,7 @@ export default {
}, []);
const currentTree = state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
- const foundEntry = currentTree.tree.find(e => e.path === data.treeList[0].path);
+ const foundEntry = currentTree.tree.find((e) => e.path === data.treeList[0].path);
if (!foundEntry) {
Object.assign(currentTree, {
@@ -125,7 +125,7 @@ export default {
});
},
[types.UPDATE_FILE_AFTER_COMMIT](state, { file, lastCommit }) {
- const changedFile = state.changedFiles.find(f => f.path === file.path);
+ const changedFile = state.changedFiles.find((f) => f.path === file.path);
const { prevPath } = file;
Object.assign(state.entries[file.path], {
@@ -172,7 +172,7 @@ export default {
entry.deleted = true;
if (parent) {
- parent.tree = parent.tree.filter(f => f.path !== entry.path);
+ parent.tree = parent.tree.filter((f) => f.path !== entry.path);
}
if (entry.type === 'blob') {
@@ -181,8 +181,8 @@ export default {
// changed and staged. Otherwise, we'd need to somehow evaluate the difference between
// changed and HEAD.
// https://gitlab.com/gitlab-org/create-stage/-/issues/12669
- state.changedFiles = state.changedFiles.filter(f => f.path !== path);
- state.stagedFiles = state.stagedFiles.filter(f => f.path !== path);
+ state.changedFiles = state.changedFiles.filter((f) => f.path !== path);
+ state.stagedFiles = state.stagedFiles.filter((f) => f.path !== path);
} else {
state.changedFiles = state.changedFiles.concat(entry);
}
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index 61a55d45128..4446971d5d6 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -12,7 +12,7 @@ export default {
if (active && !state.entries[path].pending) {
Object.assign(state, {
- openFiles: state.openFiles.map(f =>
+ openFiles: state.openFiles.map((f) =>
Object.assign(f, { active: f.pending ? false : f.active }),
),
});
@@ -28,21 +28,21 @@ export default {
if (entry.opened) {
Object.assign(state, {
- openFiles: state.openFiles.filter(f => f.path !== path).concat(state.entries[path]),
+ openFiles: state.openFiles.filter((f) => f.path !== path).concat(state.entries[path]),
});
} else {
Object.assign(state, {
- openFiles: state.openFiles.filter(f => f.key !== entry.key),
+ openFiles: state.openFiles.filter((f) => f.key !== entry.key),
});
}
},
[types.SET_FILE_DATA](state, { data, file }) {
const stateEntry = state.entries[file.path];
- const stagedFile = state.stagedFiles.find(f => f.path === file.path);
- const openFile = state.openFiles.find(f => f.path === file.path);
- const changedFile = state.changedFiles.find(f => f.path === file.path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === file.path);
+ const openFile = state.openFiles.find((f) => f.path === file.path);
+ const changedFile = state.changedFiles.find((f) => f.path === file.path);
- [stateEntry, stagedFile, openFile, changedFile].forEach(f => {
+ [stateEntry, stagedFile, openFile, changedFile].forEach((f) => {
if (f) {
Object.assign(
f,
@@ -57,10 +57,10 @@ export default {
},
[types.SET_FILE_RAW_DATA](state, { file, raw, fileDeletedAndReadded = false }) {
const openPendingFile = state.openFiles.find(
- f =>
+ (f) =>
f.path === file.path && f.pending && !(f.tempFile && !f.prevPath && !fileDeletedAndReadded),
);
- const stagedFile = state.stagedFiles.find(f => f.path === file.path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === file.path);
if (file.tempFile && file.content === '' && !fileDeletedAndReadded) {
Object.assign(state.entries[file.path], { content: raw });
@@ -86,7 +86,7 @@ export default {
});
},
[types.UPDATE_FILE_CONTENT](state, { path, content }) {
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
const rawContent = stagedFile ? stagedFile.content : state.entries[path].raw;
const changed = content !== rawContent;
@@ -112,7 +112,7 @@ export default {
});
},
[types.DISCARD_FILE_CHANGES](state, path) {
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
const entry = state.entries[path];
const { deleted } = entry;
@@ -137,14 +137,14 @@ export default {
},
[types.REMOVE_FILE_FROM_CHANGED](state, path) {
Object.assign(state, {
- changedFiles: state.changedFiles.filter(f => f.path !== path),
+ changedFiles: state.changedFiles.filter((f) => f.path !== path),
});
},
[types.STAGE_CHANGE](state, { path, diffInfo }) {
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
Object.assign(state, {
- changedFiles: state.changedFiles.filter(f => f.path !== path),
+ changedFiles: state.changedFiles.filter((f) => f.path !== path),
entries: Object.assign(state.entries, {
[path]: Object.assign(state.entries[path], {
staged: diffInfo.exists,
@@ -162,12 +162,12 @@ export default {
}
if (!diffInfo.exists) {
- state.stagedFiles = state.stagedFiles.filter(f => f.path !== path);
+ state.stagedFiles = state.stagedFiles.filter((f) => f.path !== path);
}
},
[types.UNSTAGE_CHANGE](state, { path, diffInfo }) {
- const changedFile = state.changedFiles.find(f => f.path === path);
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const changedFile = state.changedFiles.find((f) => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
if (!changedFile && stagedFile) {
Object.assign(state.entries[path], {
@@ -182,11 +182,11 @@ export default {
}
if (!diffInfo.exists) {
- state.changedFiles = state.changedFiles.filter(f => f.path !== path);
+ state.changedFiles = state.changedFiles.filter((f) => f.path !== path);
}
Object.assign(state, {
- stagedFiles: state.stagedFiles.filter(f => f.path !== path),
+ stagedFiles: state.stagedFiles.filter((f) => f.path !== path),
entries: Object.assign(state.entries, {
[path]: Object.assign(state.entries[path], {
staged: false,
@@ -206,7 +206,7 @@ export default {
state.entries[file.path].opened = false;
state.entries[file.path].active = false;
state.entries[file.path].lastOpenedAt = new Date().getTime();
- state.openFiles.forEach(f =>
+ state.openFiles.forEach((f) =>
Object.assign(f, {
opened: false,
active: false,
@@ -224,13 +224,13 @@ export default {
},
[types.REMOVE_PENDING_TAB](state, file) {
Object.assign(state, {
- openFiles: state.openFiles.filter(f => f.key !== file.key),
+ openFiles: state.openFiles.filter((f) => f.key !== file.key),
});
},
[types.REMOVE_FILE_FROM_STAGED_AND_CHANGED](state, file) {
Object.assign(state, {
- changedFiles: state.changedFiles.filter(f => f.key !== file.key),
- stagedFiles: state.stagedFiles.filter(f => f.key !== file.key),
+ changedFiles: state.changedFiles.filter((f) => f.key !== file.key),
+ stagedFiles: state.stagedFiles.filter((f) => f.key !== file.key),
});
Object.assign(state.entries[file.path], {
diff --git a/app/assets/javascripts/ide/stores/mutations/tree.js b/app/assets/javascripts/ide/stores/mutations/tree.js
index cce43a99bd9..c38002bd4e0 100644
--- a/app/assets/javascripts/ide/stores/mutations/tree.js
+++ b/app/assets/javascripts/ide/stores/mutations/tree.js
@@ -45,7 +45,7 @@ export default {
? state.entries[entry.parentPath]
: state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
- if (!parent.tree.find(f => f.path === path)) {
+ if (!parent.tree.find((f) => f.path === path)) {
parent.tree = sortTree(parent.tree.concat(entry));
}
},
diff --git a/app/assets/javascripts/ide/stores/plugins/terminal.js b/app/assets/javascripts/ide/stores/plugins/terminal.js
index 66539c7bd4f..94139d5bdf0 100644
--- a/app/assets/javascripts/ide/stores/plugins/terminal.js
+++ b/app/assets/javascripts/ide/stores/plugins/terminal.js
@@ -11,7 +11,7 @@ function getPathsFromData(el) {
}
export default function createTerminalPlugin(el) {
- return store => {
+ return (store) => {
store.registerModule('terminal', terminalModule());
store.dispatch('terminal/setPaths', getPathsFromData(el));
diff --git a/app/assets/javascripts/ide/stores/plugins/terminal_sync.js b/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
index c60bba4293a..d925a5f7567 100644
--- a/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
+++ b/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
@@ -1,5 +1,6 @@
import { debounce } from 'lodash';
import eventHub from '~/ide/eventhub';
+import { commitActionTypes } from '~/ide/constants';
import terminalSyncModule from '../modules/terminal_sync';
import { isEndingStatus, isRunningStatus } from '../modules/terminal/utils';
@@ -12,23 +13,32 @@ const UPLOAD_DEBOUNCE = 200;
* - Listens for file change event to control upload.
*/
export default function createMirrorPlugin() {
- return store => {
+ return (store) => {
store.registerModule('terminalSync', terminalSyncModule());
const upload = debounce(() => {
store.dispatch(`terminalSync/upload`);
}, UPLOAD_DEBOUNCE);
+ const onFilesChange = (payload) => {
+ // Do nothing on a file update since we only want to trigger manually on "save".
+ if (payload?.type === commitActionTypes.update) {
+ return;
+ }
+
+ upload();
+ };
+
const stop = () => {
store.dispatch(`terminalSync/stop`);
- eventHub.$off('ide.files.change', upload);
+ eventHub.$off('ide.files.change', onFilesChange);
};
const start = () => {
store
.dispatch(`terminalSync/start`)
.then(() => {
- eventHub.$on('ide.files.change', upload);
+ eventHub.$on('ide.files.change', onFilesChange);
})
.catch(() => {
// error is handled in store
@@ -36,8 +46,8 @@ export default function createMirrorPlugin() {
};
store.watch(
- x => x.terminal && x.terminal.session && x.terminal.session.status,
- val => {
+ (x) => x.terminal && x.terminal.session && x.terminal.session.status,
+ (val) => {
if (isRunningStatus(val)) {
start();
} else if (isEndingStatus(val)) {
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 96f3caf1e98..04eacf271b8 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -31,9 +31,10 @@ export const dataStructure = () => ({
mrChange: null,
deleted: false,
prevPath: undefined,
+ mimeType: '',
});
-export const decorateData = entity => {
+export const decorateData = (entity) => {
const {
id,
type,
@@ -47,6 +48,7 @@ export const decorateData = entity => {
rawPath = '',
file_lock,
parentPath = '',
+ mimeType = '',
} = entity;
return Object.assign(dataStructure(), {
@@ -63,10 +65,11 @@ export const decorateData = entity => {
rawPath,
file_lock,
parentPath,
+ mimeType,
});
};
-export const setPageTitle = title => {
+export const setPageTitle = (title) => {
document.title = title;
};
@@ -75,7 +78,7 @@ export const setPageTitleForFile = (state, file) => {
setPageTitle(title);
};
-export const commitActionForFile = file => {
+export const commitActionForFile = (file) => {
if (file.prevPath) {
return commitActionTypes.move;
} else if (file.deleted) {
@@ -87,7 +90,7 @@ export const commitActionForFile = file => {
return commitActionTypes.update;
};
-export const getCommitFiles = stagedFiles =>
+export const getCommitFiles = (stagedFiles) =>
stagedFiles.reduce((acc, file) => {
if (file.type === 'tree') return acc;
@@ -106,7 +109,7 @@ export const createCommitPayload = ({
}) => ({
branch,
commit_message: state.commitMessage || getters.preBuiltCommitMessage,
- actions: getCommitFiles(rootState.stagedFiles).map(f => {
+ actions: getCommitFiles(rootState.stagedFiles).map((f) => {
const isBlob = isBlobUrl(f.rawPath);
const content = isBlob ? btoa(f.content) : f.content;
@@ -136,9 +139,9 @@ const sortTreesByTypeAndName = (a, b) => {
return 0;
};
-export const sortTree = sortedTree =>
+export const sortTree = (sortedTree) =>
sortedTree
- .map(entity =>
+ .map((entity) =>
Object.assign(entity, {
tree: entity.tree.length ? sortTree(entity.tree) : [],
}),
@@ -148,7 +151,7 @@ export const sortTree = sortedTree =>
export const filePathMatches = (filePath, path) => filePath.indexOf(`${path}/`) === 0;
export const getChangesCountForFiles = (files, path) =>
- files.filter(f => filePathMatches(f.path, path)).length;
+ files.filter((f) => filePathMatches(f.path, path)).length;
export const mergeTrees = (fromTree, toTree) => {
if (!fromTree || !fromTree.length) {
@@ -159,7 +162,7 @@ export const mergeTrees = (fromTree, toTree) => {
if (!n) {
return t;
}
- const existingTreeNode = t.find(el => el.path === n.path);
+ const existingTreeNode = t.find((el) => el.path === n.path);
if (existingTreeNode && n.tree.length > 0) {
existingTreeNode.opened = true;
@@ -180,7 +183,7 @@ export const mergeTrees = (fromTree, toTree) => {
export const swapInStateArray = (state, arr, key, entryPath) =>
Object.assign(state, {
- [arr]: state[arr].map(f => (f.key === key ? state.entries[entryPath] : f)),
+ [arr]: state[arr].map((f) => (f.key === key ? state.entries[entryPath] : f)),
});
export const getEntryOrRoot = (state, path) =>
@@ -213,12 +216,12 @@ export const removeFromParentTree = (state, oldKey, parentPath) => {
};
export const updateFileCollections = (state, key, entryPath) => {
- ['openFiles', 'changedFiles', 'stagedFiles'].forEach(fileCollection => {
+ ['openFiles', 'changedFiles', 'stagedFiles'].forEach((fileCollection) => {
swapInStateArray(state, fileCollection, key, entryPath);
});
};
-export const cleanTrailingSlash = path => path.replace(/\/$/, '');
+export const cleanTrailingSlash = (path) => path.replace(/\/$/, '');
export const pathsAreEqual = (a, b) => {
const cleanA = a ? cleanTrailingSlash(a) : '';
@@ -251,12 +254,7 @@ export function extractMarkdownImagesFromEntries(mdFile, entries) {
const imageContent = entries[imagePath]?.content || entries[imagePath]?.raw;
if (!isAbsolute(path) && imageContent) {
- const ext = path.includes('.')
- ? path
- .split('.')
- .pop()
- .trim()
- : 'jpeg';
+ const ext = path.includes('.') ? path.split('.').pop().trim() : 'jpeg';
const src = `data:image/${ext};base64,${imageContent}`;
i += 1;
const key = `{{${prefix}${i}}}`;
diff --git a/app/assets/javascripts/ide/sync_router_and_store.js b/app/assets/javascripts/ide/sync_router_and_store.js
index b33bcbb94ea..d73ac93dc1d 100644
--- a/app/assets/javascripts/ide/sync_router_and_store.js
+++ b/app/assets/javascripts/ide/sync_router_and_store.js
@@ -21,8 +21,8 @@ export const syncRouterAndStore = (router, store) => {
// sync store to router
disposables.push(
store.watch(
- state => state.router.fullPath,
- fullPath => {
+ (state) => state.router.fullPath,
+ (fullPath) => {
if (currentPath === fullPath) {
return;
}
@@ -36,7 +36,7 @@ export const syncRouterAndStore = (router, store) => {
// sync router to store
disposables.push(
- router.afterEach(to => {
+ router.afterEach((to) => {
if (currentPath === to.fullPath) {
return;
}
@@ -47,7 +47,7 @@ export const syncRouterAndStore = (router, store) => {
);
const unsync = () => {
- disposables.forEach(fn => fn());
+ disposables.forEach((fn) => fn());
};
return unsync;
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 43276f32322..8eb2d17b876 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -3,17 +3,17 @@ import { flatten, isString } from 'lodash';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
-const toLowerCase = x => x.toLowerCase();
+const toLowerCase = (x) => x.toLowerCase();
const monacoLanguages = languages.getLanguages();
const monacoExtensions = new Set(
- flatten(monacoLanguages.map(lang => lang.extensions?.map(toLowerCase) || [])),
+ flatten(monacoLanguages.map((lang) => lang.extensions?.map(toLowerCase) || [])),
);
const monacoMimetypes = new Set(
- flatten(monacoLanguages.map(lang => lang.mimetypes?.map(toLowerCase) || [])),
+ flatten(monacoLanguages.map((lang) => lang.mimetypes?.map(toLowerCase) || [])),
);
const monacoFilenames = new Set(
- flatten(monacoLanguages.map(lang => lang.filenames?.map(toLowerCase) || [])),
+ flatten(monacoLanguages.map((lang) => lang.filenames?.map(toLowerCase) || [])),
);
const KNOWN_TYPES = [
@@ -44,7 +44,7 @@ const KNOWN_TYPES = [
];
export function isTextFile({ name, raw, content, mimeType = '' }) {
- const knownType = KNOWN_TYPES.find(type => type.isMatch(mimeType, name));
+ const knownType = KNOWN_TYPES.find((type) => type.isMatch(mimeType, name));
if (knownType) return knownType.isText;
// does the string contain ascii characters only (ranges from space to tilde, tabs and new lines)
@@ -56,20 +56,20 @@ export function isTextFile({ name, raw, content, mimeType = '' }) {
return isString(fileContents) && (fileContents === '' || asciiRegex.test(fileContents));
}
-export const createPathWithExt = p => {
+export const createPathWithExt = (p) => {
const ext = p.lastIndexOf('.') >= 0 ? p.substring(p.lastIndexOf('.') + 1) : '';
return `${p.substring(1, p.lastIndexOf('.') + 1 || p.length)}${ext || '.js'}`;
};
-export const trimPathComponents = path =>
+export const trimPathComponents = (path) =>
path
.split('/')
- .map(s => s.trim())
+ .map((s) => s.trim())
.join('/');
export function registerLanguages(def, ...defs) {
- defs.forEach(lang => registerLanguages(lang));
+ defs.forEach((lang) => registerLanguages(lang));
const languageId = def.id;
@@ -80,7 +80,7 @@ export function registerLanguages(def, ...defs) {
export function registerSchema(schema) {
const defaults = [languages.json.jsonDefaults, languages.yaml.yamlDefaults];
- defaults.forEach(d =>
+ defaults.forEach((d) =>
d.setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true,
@@ -91,7 +91,7 @@ export function registerSchema(schema) {
);
}
-export const otherSide = side => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);
+export const otherSide = (side) => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);
export function trimTrailingWhitespace(content) {
return content.replace(/[^\S\r\n]+$/gm, '');
@@ -125,9 +125,9 @@ export function getPathParent(path) {
* @param {File} file
*/
export function readFileAsDataURL(file) {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
const reader = new FileReader();
- reader.addEventListener('load', e => resolve(e.target.result), { once: true });
+ reader.addEventListener('load', (e) => resolve(e.target.result), { once: true });
reader.readAsDataURL(file);
});
}
@@ -154,12 +154,7 @@ export function getFileEOL(content = '') {
*/
export function addNumericSuffix(filename, randomize = false) {
return filename.replace(/([ _-]?)(\d*)(\..+?$|$)/, (_, before, number, after) => {
- const n = randomize
- ? Math.random()
- .toString()
- .substring(2, 7)
- .slice(-5)
- : Number(number) + 1;
+ const n = randomize ? Math.random().toString().substring(2, 7).slice(-5) : Number(number) + 1;
return `${before || '-'}${n}${after}`;
});
}
diff --git a/app/assets/javascripts/image_diff/helpers/badge_helper.js b/app/assets/javascripts/image_diff/helpers/badge_helper.js
index 229e0a62c51..8ee72235a23 100644
--- a/app/assets/javascripts/image_diff/helpers/badge_helper.js
+++ b/app/assets/javascripts/image_diff/helpers/badge_helper.js
@@ -3,7 +3,7 @@ import { spriteIcon } from '~/lib/utils/common_utils';
export function createImageBadge(noteId, { x, y }, classNames = []) {
const buttonEl = document.createElement('button');
const classList = classNames.concat(['js-image-badge']);
- classList.forEach(className => buttonEl.classList.add(className));
+ classList.forEach((className) => buttonEl.classList.add(className));
buttonEl.setAttribute('type', 'button');
buttonEl.setAttribute('disabled', true);
buttonEl.dataset.noteId = noteId;
diff --git a/app/assets/javascripts/image_diff/init_discussion_tab.js b/app/assets/javascripts/image_diff/init_discussion_tab.js
index 54ff2858206..4e0c5a6d916 100644
--- a/app/assets/javascripts/image_diff/init_discussion_tab.js
+++ b/app/assets/javascripts/image_diff/init_discussion_tab.js
@@ -7,7 +7,7 @@ export default () => {
const renderCommentBadge = true;
const diffFileEls = document.querySelectorAll('.timeline-content .diff-file.js-image-file');
- [...diffFileEls].forEach(diffFileEl =>
+ [...diffFileEls].forEach((diffFileEl) =>
initImageDiffHelper.initImageDiff(diffFileEl, canCreateNote, renderCommentBadge),
);
};
diff --git a/app/assets/javascripts/image_diff/replaced_image_diff.js b/app/assets/javascripts/image_diff/replaced_image_diff.js
index 8d9e65155d8..2df15e5e1a5 100644
--- a/app/assets/javascripts/image_diff/replaced_image_diff.js
+++ b/app/assets/javascripts/image_diff/replaced_image_diff.js
@@ -26,7 +26,7 @@ export default class ReplacedImageDiff extends ImageDiff {
this.imageEls = {};
const viewTypeNames = Object.getOwnPropertyNames(viewTypes);
- viewTypeNames.forEach(viewType => {
+ viewTypeNames.forEach((viewType) => {
this.imageEls[viewType] = this.imageFrameEls[viewType].querySelector('img');
});
}
@@ -62,7 +62,7 @@ export default class ReplacedImageDiff extends ImageDiff {
// Clear existing badges on new view
const existingBadges = this.imageFrameEl.querySelectorAll('.badge');
- [...existingBadges].map(badge => badge.remove());
+ [...existingBadges].map((badge) => badge.remove());
// Remove existing references to old view image badges
this.imageBadges = [];
diff --git a/app/assets/javascripts/image_diff/view_types.js b/app/assets/javascripts/image_diff/view_types.js
index 1a5123de220..f08b29e468c 100644
--- a/app/assets/javascripts/image_diff/view_types.js
+++ b/app/assets/javascripts/image_diff/view_types.js
@@ -5,5 +5,5 @@ export const viewTypes = {
};
export function isValidViewType(validate) {
- return Boolean(Object.getOwnPropertyNames(viewTypes).find(viewType => viewType === validate));
+ return Boolean(Object.getOwnPropertyNames(viewTypes).find((viewType) => viewType === validate));
}
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 153c58b556e..80e2e73f420 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
@@ -7,7 +7,7 @@ import setNewNameMutation from '../graphql/mutations/set_new_name.mutation.graph
import importGroupMutation from '../graphql/mutations/import_group.mutation.graphql';
import ImportTableRow from './import_table_row.vue';
-const mapApolloMutations = mutations =>
+const mapApolloMutations = (mutations) =>
Object.fromEntries(
Object.entries(mutations).map(([key, mutation]) => [
key,
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue
index 07603d89f0f..1707ab10c89 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue
@@ -35,7 +35,7 @@ export default {
select2Options() {
return {
- data: this.availableNamespaces.map(namespace => ({
+ data: this.availableNamespaces.map((namespace) => ({
id: namespace.full_path,
text: namespace.full_path,
})),
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 4fcaa1b55fc..8f2d488d661 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
@@ -23,7 +23,7 @@ export function createResolvers({ endpoints }) {
} = await client.query({ query: availableNamespacesQuery });
return axios.get(endpoints.status).then(({ data }) => {
- return data.importable_data.map(group => ({
+ return data.importable_data.map((group) => ({
__typename: clientTypenames.BulkImportSourceGroup,
...group,
status: STATUSES.NONE,
@@ -37,7 +37,7 @@ export function createResolvers({ endpoints }) {
availableNamespaces: () =>
axios.get(endpoints.availableNamespaces).then(({ data }) =>
- data.map(namespace => ({
+ data.map((namespace) => ({
__typename: clientTypenames.AvailableNamespace,
...namespace,
})),
@@ -45,14 +45,14 @@ export function createResolvers({ endpoints }) {
},
Mutation: {
setTargetNamespace(_, { targetNamespace, sourceGroupId }, { client }) {
- new SourceGroupsManager({ client }).updateById(sourceGroupId, sourceGroup => {
+ new SourceGroupsManager({ client }).updateById(sourceGroupId, (sourceGroup) => {
// eslint-disable-next-line no-param-reassign
sourceGroup.import_target.target_namespace = targetNamespace;
});
},
setNewName(_, { newName, sourceGroupId }, { client }) {
- new SourceGroupsManager({ client }).updateById(sourceGroupId, sourceGroup => {
+ new SourceGroupsManager({ client }).updateById(sourceGroupId, (sourceGroup) => {
// eslint-disable-next-line no-param-reassign
sourceGroup.import_target.new_name = newName;
});
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 f752ecc8cd6..047b04fe7d6 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
@@ -37,7 +37,7 @@ export class SourceGroupsManager {
}
setImportStatus(group, status) {
- this.update(group, sourceGroup => {
+ this.update(group, (sourceGroup) => {
// eslint-disable-next-line no-param-reassign
sourceGroup.status = status;
});
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 5d2922b0ba8..41dd25b9150 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
@@ -5,7 +5,7 @@ import bulkImportSourceGroupsQuery from '../queries/bulk_import_source_groups.qu
import { STATUSES } from '../../../constants';
import { SourceGroupsManager } from './source_groups_manager';
-const groupId = i => `group${i}`;
+const groupId = (i) => `group${i}`;
function generateGroupsQuery(groups) {
return gql`{
@@ -46,14 +46,14 @@ export class StatusPoller {
const { bulkImportSourceGroups } = this.client.readQuery({
query: bulkImportSourceGroupsQuery,
});
- const groupsInProgress = bulkImportSourceGroups.filter(g => g.status === STATUSES.STARTED);
+ 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 => {
+ completedGroups.forEach((group) => {
this.groupManager.setImportStatus(group, STATUSES.FINISHED);
});
}
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 2b6b8b765a2..192d6e056cd 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
@@ -35,6 +35,7 @@ export default {
...mapGetters([
'isLoading',
'isImportingAnyRepo',
+ 'importingRepoCount',
'hasImportableRepos',
'hasIncompatibleRepos',
'importAllCount',
@@ -60,13 +61,17 @@ export default {
},
importAllButtonText() {
- return this.hasIncompatibleRepos
- ? n__(
- 'Import %d compatible repository',
- 'Import %d compatible repositories',
- this.importAllCount,
- )
- : n__('Import %d repository', 'Import %d repositories', this.importAllCount);
+ if (this.isImportingAnyRepo) {
+ return n__('Importing %d repository', 'Importing %d repositories', this.importingRepoCount);
+ }
+
+ if (this.hasIncompatibleRepos)
+ return n__(
+ 'Import %d compatible repository',
+ 'Import %d compatible repositories',
+ this.importAllCount,
+ );
+ return n__('Import %d repository', 'Import %d repositories', this.importAllCount);
},
emptyStateText() {
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 7b7afd13c55..a8217ff1033 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/actions.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/actions.js
@@ -12,9 +12,9 @@ import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
let eTagPoll;
-const hasRedirectInError = e => e?.response?.data?.error?.redirect;
-const redirectToUrlInError = e => visitUrl(e.response.data.error.redirect);
-const tooManyRequests = e => e.response.status === httpStatusCodes.TOO_MANY_REQUESTS;
+const hasRedirectInError = (e) => e?.response?.data?.error?.redirect;
+const redirectToUrlInError = (e) => visitUrl(e.response.data.error.redirect);
+const tooManyRequests = (e) => e.response.status === httpStatusCodes.TOO_MANY_REQUESTS;
const pathWithParams = ({ path, ...params }) => {
const filteredParams = Object.fromEntries(
Object.entries(params).filter(([, value]) => value !== ''),
@@ -47,7 +47,7 @@ const importAll = ({ state, dispatch }) => {
return Promise.all(
state.repositories
.filter(isProjectImportable)
- .map(r => dispatch('fetchImport', r.importSource.id)),
+ .map((r) => dispatch('fetchImport', r.importSource.id)),
);
};
@@ -69,7 +69,7 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit })
.then(({ data }) => {
commit(types.RECEIVE_REPOS_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true }));
})
- .catch(e => {
+ .catch((e) => {
commit(types.SET_PAGE, nextPage - 1);
if (hasRedirectInError(e)) {
@@ -114,7 +114,7 @@ const fetchImportFactory = (importPath = isRequired()) => ({ state, commit, gett
repoId,
});
})
- .catch(e => {
+ .catch((e) => {
const serverErrorMessage = e?.response?.data?.errors;
const flashMessage = serverErrorMessage
? sprintf(
@@ -145,7 +145,7 @@ export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, d
method: 'fetchJobs',
successCallback: ({ data }) =>
commit(types.RECEIVE_JOBS_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })),
- errorCallback: e => {
+ errorCallback: (e) => {
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else {
diff --git a/app/assets/javascripts/import_entities/import_projects/store/getters.js b/app/assets/javascripts/import_entities/import_projects/store/getters.js
index 31e22b50554..ef01a67ec94 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/getters.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/getters.js
@@ -1,27 +1,23 @@
-import { STATUSES } from '../../constants';
-import { isProjectImportable, isIncompatible } from '../utils';
+import { isProjectImportable, isIncompatible, isImporting } from '../utils';
-export const isLoading = state => state.isLoadingRepos || state.isLoadingNamespaces;
+export const isLoading = (state) => state.isLoadingRepos || state.isLoadingNamespaces;
-export const isImportingAnyRepo = state =>
- state.repositories.some(repo =>
- [STATUSES.SCHEDULING, STATUSES.SCHEDULED, STATUSES.STARTED].includes(
- repo.importedProject?.importStatus,
- ),
- );
+export const importingRepoCount = (state) => state.repositories.filter(isImporting).length;
-export const hasIncompatibleRepos = state => state.repositories.some(isIncompatible);
+export const isImportingAnyRepo = (state) => state.repositories.some(isImporting);
-export const hasImportableRepos = state => state.repositories.some(isProjectImportable);
+export const hasIncompatibleRepos = (state) => state.repositories.some(isIncompatible);
-export const importAllCount = state => state.repositories.filter(isProjectImportable).length;
+export const hasImportableRepos = (state) => state.repositories.some(isProjectImportable);
-export const getImportTarget = state => repoId => {
+export const importAllCount = (state) => state.repositories.filter(isProjectImportable).length;
+
+export const getImportTarget = (state) => (repoId) => {
if (state.customImportTargets[repoId]) {
return state.customImportTargets[repoId];
}
- const repo = state.repositories.find(r => r.importSource.id === repoId);
+ const repo = state.repositories.find((r) => r.importSource.id === repoId);
return {
newName: repo.importSource.sanitizedName,
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 3d718a6a386..1a96508bd48 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/mutations.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/mutations.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import * as types from './mutation_types';
import { STATUSES } from '../../constants';
-const makeNewImportedProject = importedProject => ({
+const makeNewImportedProject = (importedProject) => ({
importSource: {
id: importedProject.id,
fullName: importedProject.importSource,
@@ -12,15 +12,15 @@ const makeNewImportedProject = importedProject => ({
importedProject,
});
-const makeNewIncompatibleProject = project => ({
+const makeNewIncompatibleProject = (project) => ({
importSource: { ...project, incompatible: true },
importedProject: null,
});
const processLegacyEntries = ({ newRepositories, existingRepositories, factory }) => {
const newEntries = [];
- newRepositories.forEach(project => {
- const existingProject = existingRepositories.find(p => p.importSource.id === project.id);
+ newRepositories.forEach((project) => {
+ const existingProject = existingRepositories.find((p) => p.importSource.id === project.id);
const importedProjectShape = factory(project);
if (existingProject) {
@@ -66,7 +66,7 @@ export default {
state.repositories = [
...newImportedProjects,
...state.repositories,
- ...repositories.providerRepos.map(project => ({
+ ...repositories.providerRepos.map((project) => ({
importSource: project,
importedProject: null,
})),
@@ -91,7 +91,7 @@ export default {
},
[types.REQUEST_IMPORT](state, { repoId, importTarget }) {
- const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
+ const existingRepo = state.repositories.find((r) => r.importSource.id === repoId);
existingRepo.importedProject = {
importStatus: STATUSES.SCHEDULING,
fullPath: `/${importTarget.targetNamespace}/${importTarget.newName}`,
@@ -99,18 +99,18 @@ export default {
},
[types.RECEIVE_IMPORT_SUCCESS](state, { importedProject, repoId }) {
- const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
+ const existingRepo = state.repositories.find((r) => r.importSource.id === repoId);
existingRepo.importedProject = importedProject;
},
[types.RECEIVE_IMPORT_ERROR](state, repoId) {
- const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
+ const existingRepo = state.repositories.find((r) => r.importSource.id === repoId);
existingRepo.importedProject = null;
},
[types.RECEIVE_JOBS_SUCCESS](state, updatedProjects) {
- updatedProjects.forEach(updatedProject => {
- const repo = state.repositories.find(p => p.importedProject?.id === updatedProject.id);
+ updatedProjects.forEach((updatedProject) => {
+ const repo = state.repositories.find((p) => p.importedProject?.id === updatedProject.id);
if (repo?.importedProject) {
repo.importedProject.importStatus = updatedProject.importStatus;
}
@@ -131,7 +131,7 @@ export default {
},
[types.SET_IMPORT_TARGET](state, { repoId, importTarget }) {
- const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
+ const existingRepo = state.repositories.find((r) => r.importSource.id === repoId);
if (
importTarget.targetNamespace === state.defaultTargetNamespace &&
diff --git a/app/assets/javascripts/import_entities/import_projects/utils.js b/app/assets/javascripts/import_entities/import_projects/utils.js
index 0610117e09b..38bd529321a 100644
--- a/app/assets/javascripts/import_entities/import_projects/utils.js
+++ b/app/assets/javascripts/import_entities/import_projects/utils.js
@@ -11,3 +11,9 @@ export function getImportStatus(project) {
export function isProjectImportable(project) {
return !isIncompatible(project) && getImportStatus(project) === STATUSES.NONE;
}
+
+export function isImporting(repo) {
+ return [STATUSES.SCHEDULING, STATUSES.SCHEDULED, STATUSES.STARTED].includes(
+ repo.importedProject?.importStatus,
+ );
+}
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 0e3839deaf5..7d44a28b4bb 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -265,9 +265,7 @@ export default {
if (field?.sortKey) {
sortKey = field.sortKey;
} else {
- sortKey = convertToSnakeCase(sortBy)
- .replace(/_.*/, '')
- .toUpperCase();
+ sortKey = convertToSnakeCase(sortBy).replace(/_.*/, '').toUpperCase();
}
this.pagination = initialPaginationState;
diff --git a/app/assets/javascripts/incidents/list.js b/app/assets/javascripts/incidents/list.js
index 6f87fbbe775..8644ff3a249 100644
--- a/app/assets/javascripts/incidents/list.js
+++ b/app/assets/javascripts/incidents/list.js
@@ -29,6 +29,9 @@ export default () => {
return new Vue({
el: selector,
+ components: {
+ IncidentsList,
+ },
provide: {
projectPath,
incidentTemplateName,
@@ -43,9 +46,6 @@ export default () => {
slaFeatureAvailable: parseBoolean(slaFeatureAvailable),
},
apolloProvider,
- components: {
- IncidentsList,
- },
render(createElement) {
return createElement('incidents-list');
},
diff --git a/app/assets/javascripts/init_changes_dropdown.js b/app/assets/javascripts/init_changes_dropdown.js
index c0dc6ce07b1..22667d8ae88 100644
--- a/app/assets/javascripts/init_changes_dropdown.js
+++ b/app/assets/javascripts/init_changes_dropdown.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import { stickyMonitor } from './lib/utils/sticky';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-export default stickyTop => {
+export default (stickyTop) => {
stickyMonitor(document.querySelector('.js-diff-files-changed'), stickyTop);
initDeprecatedJQueryDropdown($('.js-diff-stats-dropdown'), {
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index 9dde1ed1055..f568f7e6d3d 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -92,7 +92,7 @@ export default {
return isEmpty(this.value) && this.required;
},
options() {
- return this.choices.map(choice => {
+ return this.choices.map((choice) => {
return {
value: choice[1],
text: choice[0],
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index c6f8ba8dcb2..ac8a64d5f3b 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -59,9 +59,6 @@ export default {
showReset() {
return this.isInstanceOrGroupLevel && this.propsSource.resetPath;
},
- saveButtonKey() {
- return `save-button-${this.isDisabled}`;
- },
},
methods: {
...mapActions([
@@ -120,7 +117,6 @@ export default {
<div v-if="isEditable" class="footer-block row-content-block">
<template v-if="isInstanceOrGroupLevel">
<gl-button
- :key="saveButtonKey"
v-gl-modal.confirmSaveIntegration
category="primary"
variant="success"
@@ -134,7 +130,6 @@ export default {
</template>
<gl-button
v-else
- :key="saveButtonKey"
category="primary"
variant="success"
type="submit"
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 123d794912a..bc005aa16e9 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
@@ -91,6 +91,8 @@ export default {
<gl-form-group
v-show="showEnableComments"
:label="s__('Integrations|Comment settings:')"
+ label-for="service[comment_on_event_enabled]"
+ class="gl-pl-6"
data-testid="comment-settings"
>
<input
@@ -106,6 +108,8 @@ export default {
<gl-form-group
v-show="showEnableComments && enableComments"
:label="s__('Integrations|Comment detail:')"
+ label-for="service[comment_detail]"
+ class="gl-pl-9"
data-testid="comment-detail"
>
<input name="service[comment_detail]" type="hidden" :value="commentDetail" />
diff --git a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
index c31dada8d2f..4e2c37ac7f3 100644
--- a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
+++ b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
@@ -40,7 +40,7 @@ export default {
},
data() {
return {
- selected: dropdownOptions.find(x => x.value === this.override),
+ selected: dropdownOptions.find((x) => x.value === this.override),
};
},
computed: {
diff --git a/app/assets/javascripts/integrations/edit/store/getters.js b/app/assets/javascripts/integrations/edit/store/getters.js
index 310d970c73e..39e14de2d0d 100644
--- a/app/assets/javascripts/integrations/edit/store/getters.js
+++ b/app/assets/javascripts/integrations/edit/store/getters.js
@@ -1,6 +1,6 @@
-export const isInheriting = state => (state.defaultState === null ? false : !state.override);
+export const isInheriting = (state) => (state.defaultState === null ? false : !state.override);
-export const isDisabled = state => state.isSaving || state.isTesting || state.isResetting;
+export const isDisabled = (state) => state.isSaving || state.isTesting || state.isResetting;
export const propsSource = (state, getters) =>
getters.isInheriting ? state.defaultState : state.customState;
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index 14d6f133d27..861655a6a64 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -1,4 +1,5 @@
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';
@@ -22,7 +23,7 @@ export default class IntegrationSettingsForm {
document.querySelector('.js-vue-integration-settings'),
document.querySelector('.js-vue-default-integration-settings'),
);
- eventHub.$on('toggle', active => {
+ eventHub.$on('toggle', (active) => {
this.formActive = active;
this.toggleServiceState();
});
@@ -43,7 +44,9 @@ export default class IntegrationSettingsForm {
const formValid = this.$form.get(0).checkValidity() || this.formActive === false;
if (formValid) {
- this.$form.submit();
+ delay(() => {
+ this.$form.trigger('submit');
+ }, 100);
} else {
eventHub.$emit('validateForm');
this.vue.$store.dispatch('setIsSaving', false);
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 7d60d78d3d9..901e3e315ee 100644
--- a/app/assets/javascripts/invite_member/init_invite_member_modal.js
+++ b/app/assets/javascripts/invite_member/init_invite_member_modal.js
@@ -16,6 +16,6 @@ export default function initInviteMembersModal() {
return new Vue({
el,
provide: { membersPath },
- render: createElement => createElement(InviteMemberModal),
+ render: (createElement) => createElement(InviteMemberModal),
});
}
diff --git a/app/assets/javascripts/invite_member/init_invite_member_trigger.js b/app/assets/javascripts/invite_member/init_invite_member_trigger.js
index a5f904b87a6..5e763e4f47d 100644
--- a/app/assets/javascripts/invite_member/init_invite_member_trigger.js
+++ b/app/assets/javascripts/invite_member/init_invite_member_trigger.js
@@ -11,6 +11,6 @@ export default function initInviteMembersTrigger() {
return new Vue({
el,
provide: { ...el.dataset },
- render: createElement => createElement(InviteMemberTrigger),
+ render: (createElement) => createElement(InviteMemberTrigger),
});
}
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 b55ef77ae5d..a92289ca8c1 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -9,6 +9,7 @@ import {
GlButton,
GlFormInput,
} from '@gitlab/ui';
+import { partition, isString } from 'lodash';
import eventHub from '../event_hub';
import { s__, __, sprintf } from '~/locale';
import Api from '~/api';
@@ -58,7 +59,7 @@ export default {
visible: true,
modalId: 'invite-members-modal',
selectedAccessLevel: this.defaultAccessLevel,
- newUsersToInvite: '',
+ newUsersToInvite: [],
selectedDate: undefined,
};
},
@@ -79,13 +80,12 @@ export default {
return {
onComplete: () => {
this.selectedAccessLevel = this.defaultAccessLevel;
- this.newUsersToInvite = '';
+ this.newUsersToInvite = [];
},
};
},
- postData() {
+ basePostData() {
return {
- user_id: this.newUsersToInvite,
access_level: this.selectedAccessLevel,
expires_at: this.selectedDate,
format: 'json',
@@ -93,7 +93,7 @@ export default {
},
selectedRoleName() {
return Object.keys(this.accessLevels).find(
- key => this.accessLevels[key] === Number(this.selectedAccessLevel),
+ (key) => this.accessLevels[key] === Number(this.selectedAccessLevel),
);
},
},
@@ -101,6 +101,17 @@ export default {
eventHub.$on('openModal', this.openModal);
},
methods: {
+ partitionNewUsersToInvite() {
+ const [usersToInviteByEmail, usersToAddById] = partition(
+ this.newUsersToInvite,
+ (user) => isString(user.id) && user.id.includes('user-defined-token'),
+ );
+
+ return [
+ usersToInviteByEmail.map((user) => user.name).join(','),
+ usersToAddById.map((user) => user.id).join(','),
+ ];
+ },
openModal() {
this.$root.$emit('bv::show::modal', this.modalId);
},
@@ -108,7 +119,7 @@ export default {
this.$root.$emit('bv::hide::modal', this.modalId);
},
sendInvite() {
- this.submitForm(this.postData);
+ this.submitForm();
this.closeModal();
},
cancelInvite() {
@@ -120,15 +131,33 @@ export default {
changeSelectedItem(item) {
this.selectedAccessLevel = item;
},
- submitForm(formData) {
- if (this.isProject) {
- return Api.inviteProjectMembers(this.id, formData)
- .then(this.showToastMessageSuccess)
- .catch(this.showToastMessageError);
+ submitForm() {
+ const [usersToInviteByEmail, usersToAddById] = this.partitionNewUsersToInvite();
+ const promises = [];
+
+ if (usersToInviteByEmail !== '') {
+ const apiInviteByEmail = this.isProject
+ ? Api.inviteProjectMembersByEmail.bind(Api)
+ : Api.inviteGroupMembersByEmail.bind(Api);
+
+ promises.push(apiInviteByEmail(this.id, this.inviteByEmailPostData(usersToInviteByEmail)));
}
- return Api.inviteGroupMember(this.id, formData)
- .then(this.showToastMessageSuccess)
- .catch(this.showToastMessageError);
+
+ if (usersToAddById !== '') {
+ const apiAddByUserId = this.isProject
+ ? Api.addProjectMembersByUserId.bind(Api)
+ : Api.addGroupMembersByUserId.bind(Api);
+
+ promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
+ }
+
+ Promise.all(promises).then(this.showToastMessageSuccess).catch(this.showToastMessageError);
+ },
+ inviteByEmailPostData(usersToInviteByEmail) {
+ return { ...this.basePostData, email: usersToInviteByEmail };
+ },
+ addByUserIdPostData(usersToAddById) {
+ return { ...this.basePostData, user_id: usersToAddById };
},
showToastMessageSuccess() {
this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
@@ -195,7 +224,7 @@ export default {
<div class="gl-mt-2">
<gl-sprintf :message="$options.labels.readMoreText">
- <template #link="{content}">
+ <template #link="{ content }">
<gl-link :href="helpLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index d133e3655e3..eb97c458f88 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -19,6 +19,11 @@ export default {
required: false,
default: '',
},
+ classes: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
methods: {
openModal() {
@@ -29,7 +34,7 @@ export default {
</script>
<template>
- <gl-link @click="openModal">
+ <gl-link :class="classes" @click="openModal">
<div v-if="icon" class="nav-icon-container">
<gl-icon :size="16" :name="icon" />
</div>
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 aed2e5e3236..627d4ab2771 100644
--- a/app/assets/javascripts/invite_members/components/members_token_select.vue
+++ b/app/assets/javascripts/invite_members/components/members_token_select.vue
@@ -1,14 +1,16 @@
<script>
import { debounce } from 'lodash';
-import { GlTokenSelector, GlAvatar, GlAvatarLabeled } from '@gitlab/ui';
+import { GlTokenSelector, GlAvatar, GlAvatarLabeled, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
import { USER_SEARCH_DELAY } from '../constants';
-import Api from '~/api';
+import { getUsers } from '~/rest_api';
export default {
components: {
GlTokenSelector,
GlAvatar,
GlAvatarLabeled,
+ GlSprintf,
},
props: {
placeholder: {
@@ -32,12 +34,10 @@ export default {
};
},
computed: {
- newUsersToInvite() {
- return this.selectedTokens
- .map(obj => {
- return obj.id;
- })
- .join(',');
+ emailIsValid() {
+ const regex = /.+@/;
+
+ return this.query.match(regex) !== null;
},
placeholderText() {
if (this.selectedTokens.length === 0) {
@@ -54,9 +54,9 @@ export default {
this.retrieveUsers(query);
},
retrieveUsers: debounce(function debouncedRetrieveUsers() {
- return Api.users(this.query, this.$options.queryOptions)
- .then(response => {
- this.users = response.data.map(token => ({
+ return getUsers(this.query, this.$options.queryOptions)
+ .then((response) => {
+ this.users = response.data.map((token) => ({
id: token.id,
name: token.name,
username: token.username,
@@ -69,7 +69,7 @@ export default {
});
}, USER_SEARCH_DELAY),
handleInput() {
- this.$emit('input', this.newUsersToInvite);
+ this.$emit('input', this.selectedTokens);
},
handleBlur() {
this.hideDropdownWithNoItems = false;
@@ -86,6 +86,9 @@ export default {
},
},
queryOptions: { exclude_internal: true, active: true },
+ i18n: {
+ inviteTextMessage: __('Invite "%{email}" by email'),
+ },
};
</script>
@@ -94,7 +97,7 @@ export default {
v-model="selectedTokens"
:dropdown-items="users"
:loading="loading"
- :allow-user-defined-tokens="false"
+ :allow-user-defined-tokens="emailIsValid"
:hide-dropdown-with-no-items="hideDropdownWithNoItems"
:placeholder="placeholderText"
:aria-labelledby="ariaLabelledby"
@@ -116,5 +119,13 @@ export default {
:sub-label="dropdownItem.username"
/>
</template>
+
+ <template #user-defined-token-content="{ inputText: email }">
+ <gl-sprintf :message="$options.i18n.inviteTextMessage">
+ <template #email>
+ <span>{{ email }}</span>
+ </template>
+ </gl-sprintf>
+ </template>
</gl-token-selector>
</template>
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 db957ecacfd..74c374018de 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
+import { parseBoolean } from '~/lib/utils/common_utils';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
Vue.use(GlToast);
@@ -13,10 +14,11 @@ export default function initInviteMembersModal() {
return new Vue({
el,
- render: createElement =>
+ render: (createElement) =>
createElement(InviteMembersModal, {
props: {
...el.dataset,
+ isProject: parseBoolean(el.dataset.isProject),
accessLevels: JSON.parse(el.dataset.accessLevels),
},
}),
diff --git a/app/assets/javascripts/invite_members/init_invite_members_trigger.js b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
index bee4f1c0f72..a7b95960995 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_trigger.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
@@ -10,7 +10,7 @@ export default function initInviteMembersTrigger() {
return new Vue({
el,
- render: createElement =>
+ render: (createElement) =>
createElement(InviteMembersTrigger, {
props: {
...el.dataset,
diff --git a/app/assets/javascripts/issuable/auto_width_dropdown_select.js b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
index 12f03873958..243d82f55aa 100644
--- a/app/assets/javascripts/issuable/auto_width_dropdown_select.js
+++ b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
@@ -37,10 +37,7 @@ class AutoWidthDropdownSelect {
// We have to look at the parent because
// `offsetParent` on a `display: none;` is `null`
- const offsetParentWidth = $(this)
- .parent()
- .offsetParent()
- .width();
+ const offsetParentWidth = $(this).parent().offsetParent().width();
// Reset any width to let it naturally flow
$dropdown.css('width', 'auto');
if ($dropdown.outerWidth(false) > offsetParentWidth) {
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js
index 6ba21cd7869..8bb76edbd47 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_actions.js
@@ -101,7 +101,7 @@ export default {
// Collect unique label IDs for all checked issues
this.getElement('.selected-issuable:checked').each((i, el) => {
issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels');
- issuableLabels.forEach(labelId => {
+ issuableLabels.forEach((labelId) => {
// Store unique IDs
if (uniqueIds.indexOf(labelId) === -1) {
uniqueIds.push(labelId);
@@ -113,7 +113,7 @@ export default {
// Add uniqueIds to add it as argument for _.intersection
labelIds.unshift(uniqueIds);
// Return IDs that are present but not in all selected issueables
- return uniqueIds.filter(x => !intersection.apply(this, labelIds).includes(x));
+ return uniqueIds.filter((x) => !intersection.apply(this, labelIds).includes(x));
},
getElement(selector) {
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js
index 7d9cefbe66a..b9daa16874a 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js
@@ -39,9 +39,9 @@ export default class IssuableBulkUpdateSidebar {
}
bindEvents() {
- this.$bulkUpdateEnableBtn.on('click', e => this.toggleBulkEdit(e, true));
- this.$bulkEditCancelBtn.on('click', e => this.toggleBulkEdit(e, false));
- this.$checkAllContainer.on('click', e => this.selectAll(e));
+ this.$bulkUpdateEnableBtn.on('click', (e) => this.toggleBulkEdit(e, true));
+ this.$bulkEditCancelBtn.on('click', (e) => this.toggleBulkEdit(e, false));
+ this.$checkAllContainer.on('click', (e) => this.selectAll(e));
this.$issuesList.on('change', () => this.updateFormState());
this.$bulkEditSubmitBtn.on('click', () => this.prepForSubmit());
this.$checkAllContainer.on('click', () => this.updateFormState());
@@ -159,7 +159,7 @@ export default class IssuableBulkUpdateSidebar {
const $checkedIssues = $('.selected-issuable:checked');
if ($checkedIssues.length > 0) {
- return $.map($checkedIssues, value => $(value).data('id'));
+ return $.map($checkedIssues, (value) => $(value).data('id'));
}
return [];
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
index 2072e41514d..6fcff90b608 100644
--- a/app/assets/javascripts/issuable_context.js
+++ b/app/assets/javascripts/issuable_context.js
@@ -31,7 +31,7 @@ export default class IssuableContext {
});
$(document)
.off('click', '.issuable-sidebar .dropdown-content a')
- .on('click', '.issuable-sidebar .dropdown-content a', e => e.preventDefault());
+ .on('click', '.issuable-sidebar .dropdown-content a', (e) => e.preventDefault());
$(document)
.off('click', '.edit-link')
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index 791b5fef699..a8fd7aaecdf 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -52,12 +52,12 @@ export default class IssuableForm {
/* eslint-disable @gitlab/require-i18n-strings */
this.wipRegex = new RegExp(
'^\\s*(' + // Line start, then any amount of leading whitespace
- 'draft\\s-\\s' + // Draft_-_ where "_" are *exactly* one whitespace
- '|\\[(draft|wip)\\]\\s*' + // [Draft] or [WIP] and any following whitespace
- '|(draft|wip):\\s*' + // Draft: or WIP: and any following whitespace
- '|(draft|wip)\\s+' + // Draft_ or WIP_ where "_" is at least one whitespace
- '|\\(draft\\)\\s*' + // (Draft) and any following whitespace
- ')+' + // At least one repeated match of the preceding parenthetical
+ 'draft\\s-\\s' + // Draft_-_ where "_" are *exactly* one whitespace
+ '|\\[(draft|wip)\\]\\s*' + // [Draft] or [WIP] and any following whitespace
+ '|(draft|wip):\\s*' + // Draft: or WIP: and any following whitespace
+ '|(draft|wip)\\s+' + // Draft_ or WIP_ where "_" is at least one whitespace
+ '|\\(draft\\)\\s*' + // (Draft) and any following whitespace
+ ')+' + // At least one repeated match of the preceding parenthetical
'\\s*', // Any amount of trailing whitespace
'i', // Match any case(s)
);
@@ -89,9 +89,9 @@ export default class IssuableForm {
theme: 'gitlab-theme animate-picker',
format: 'yyyy-mm-dd',
container: $issuableDueDate.parent().get(0),
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
- onSelect: dateText => $issuableDueDate.val(calendar.toString(dateText)),
+ parse: (dateString) => parsePikadayDate(dateString),
+ toString: (date) => pikadayToString(date),
+ onSelect: (dateText) => $issuableDueDate.val(calendar.toString(dateText)),
firstDay: gon.first_day_of_week,
});
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
@@ -202,7 +202,7 @@ export default class IssuableForm {
results(data) {
return {
// `data` keys are translated so we can't just access them with a string based key
- results: data[Object.keys(data)[0]].map(name => ({
+ results: data[Object.keys(data)[0]].map((name) => ({
id: name,
text: name,
})),
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index e888e481fe5..4f31d26ab5d 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -13,7 +13,7 @@ export default class IssuableIndex {
static resetIncomingEmailToken() {
const $resetToken = $('.incoming-email-token-reset');
- $resetToken.on('click', e => {
+ $resetToken.on('click', (e) => {
e.preventDefault();
$resetToken.text(s__('EmailToken|resetting...'));
@@ -21,9 +21,7 @@ export default class IssuableIndex {
axios
.put($resetToken.attr('href'))
.then(({ data }) => {
- $('#issuable_email')
- .val(data.new_address)
- .focus();
+ $('#issuable_email').val(data.new_address).focus();
$resetToken.text(s__('EmailToken|reset it'));
})
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 b2312c55f01..c5475a34d3c 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -200,7 +200,7 @@ export default {
this.checkedIssuables[this.issuableId(issuable)].checked = value;
},
handleAllIssuablesCheckedInput(value) {
- Object.keys(this.checkedIssuables).forEach(issuableId => {
+ Object.keys(this.checkedIssuables).forEach((issuableId) => {
this.checkedIssuables[issuableId].checked = value;
});
},
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 93e4db8b99c..830a740ff78 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
@@ -141,8 +141,7 @@ export default {
:data-supports-quick-actions="enableAutocomplete"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
- class="note-textarea js-gfm-input js-autosize markdown-area
- qa-description-textarea"
+ class="note-textarea js-gfm-input js-autosize markdown-area qa-description-textarea"
dir="auto"
@keydown="handleKeydown($event, 'description')"
></textarea>
diff --git a/app/assets/javascripts/issuable_suggestions/components/app.vue b/app/assets/javascripts/issuable_suggestions/components/app.vue
index 8a9a880e7ee..ac5f04147d3 100644
--- a/app/assets/javascripts/issuable_suggestions/components/app.vue
+++ b/app/assets/javascripts/issuable_suggestions/components/app.vue
@@ -29,7 +29,7 @@ export default {
skip() {
return this.isSearchEmpty;
},
- update: data => data.project.issues.edges.map(({ node }) => node),
+ update: (data) => data.project.issues.edges.map(({ node }) => node),
variables() {
return {
fullPath: this.projectPath,
diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js
index 40916c9d27f..9949527106b 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 () {
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 5d2880c3c10..91912c684ad 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -23,7 +23,7 @@ export default class Issue {
}
// Listen to state changes in the Vue app
- document.addEventListener('issuable_vue_app:change', event => {
+ document.addEventListener('issuable_vue_app:change', (event) => {
this.updateTopState(event.detail.isClosed, event.detail.data);
});
}
@@ -54,11 +54,7 @@ export default class Issue {
$(document).trigger('issuable:change', isClosed);
let numProjectIssues = Number(
- projectIssuesCounter
- .first()
- .text()
- .trim()
- .replace(/[^\d]/, ''),
+ projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''),
);
numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1;
projectIssuesCounter.text(addDelimiter(numProjectIssues));
@@ -84,7 +80,7 @@ export default class Issue {
alertMovedFromServiceDeskWarning.show();
}
- alertMovedFromServiceDeskWarning.on('click', '.js-close', e => {
+ alertMovedFromServiceDeskWarning.on('click', '.js-close', (e) => {
e.preventDefault();
e.stopImmediatePropagation();
alertMovedFromServiceDeskWarning.remove();
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 61e5db0970a..d569ad573a2 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -250,7 +250,7 @@ export default {
this.poll = new Poll({
resource: this.service,
method: 'getData',
- successCallback: res => this.store.updateState(res.data),
+ successCallback: (res) => this.store.updateState(res.data),
errorCallback(err) {
throw new Error(err);
},
@@ -294,8 +294,8 @@ export default {
updateStoreState() {
return this.service
.getData()
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
this.store.updateState(data);
})
.catch(() => {
@@ -320,7 +320,7 @@ export default {
requestTemplatesAndShowForm() {
return this.service
.loadTemplates(this.issuableTemplateNamesPath)
- .then(res => {
+ .then((res) => {
this.updateAndShowForm(res.data);
})
.catch(() => {
@@ -345,9 +345,9 @@ export default {
updateIssuable() {
return this.service
.updateIssuable(this.store.formState)
- .then(res => res.data)
- .then(data => this.checkForSpam(data))
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => this.checkForSpam(data))
+ .then((data) => {
if (!window.location.pathname.includes(data.web_url)) {
visitUrl(data.web_url);
}
@@ -384,8 +384,8 @@ export default {
deleteIssuable(payload) {
return this.service
.deleteIssuable(payload)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
// Stop the poll so we don't get 404's with the issuable not existing
this.poll.stop();
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 0de0060615b..8d417e32d62 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -1,12 +1,13 @@
<script>
import updateMixin from '../../mixins/update';
-import markdownField from '../../../vue_shared/components/markdown/field.vue';
+import markdownField from '~/vue_shared/components/markdown/field.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
markdownField,
},
- mixins: [updateMixin],
+ mixins: [glFeatureFlagsMixin(), updateMixin],
props: {
formState: {
type: Object,
@@ -52,10 +53,9 @@ export default {
id="issue-description"
ref="textarea"
v-model="formState.description"
- class="note-textarea js-gfm-input js-autosize markdown-area
- qa-description-textarea"
+ class="note-textarea js-gfm-input js-autosize markdown-area qa-description-textarea"
dir="auto"
- data-supports-quick-actions="true"
+ :data-supports-quick-actions="!glFeatures.tributeAutocomplete"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@keydown.meta.enter="updateIssuable"
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 ea6e03404e7..71299381aae 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -34,7 +34,7 @@ export default {
mounted() {
// Create the editor for the template
const editor = document.querySelector('.detail-page-description .note-textarea') || {};
- editor.setValue = val => {
+ editor.setValue = (val) => {
this.formState.description = val;
};
editor.getValue = () => this.formState.description;
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 c593fa33973..f9f06c3ad5a 100644
--- a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
+++ b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
@@ -6,7 +6,6 @@ import createFlash from '~/flash';
import { s__ } from '~/locale';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import Tracking from '~/tracking';
-
import getAlert from './graphql/queries/get_alert.graphql';
import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
@@ -17,8 +16,9 @@ export default {
GlTab,
GlTabs,
HighlightBar,
+ MetricsTab: () => import('ee_component/issue_show/components/incidents/metrics_tab.vue'),
},
- inject: ['fullPath', 'iid'],
+ inject: ['fullPath', 'iid', 'uploadMetricsFeatureAvailable'],
apollo: {
alert: {
query: getAlert,
@@ -67,7 +67,13 @@ export default {
<highlight-bar :alert="alert" />
<description-component v-bind="$attrs" />
</gl-tab>
- <gl-tab v-if="alert" class="alert-management-details" :title="s__('Incident|Alert details')">
+ <metrics-tab v-if="uploadMetricsFeatureAvailable" data-testid="metrics-tab" />
+ <gl-tab
+ v-if="alert"
+ class="alert-management-details"
+ :title="s__('Incident|Alert details')"
+ data-testid="alert-details-tab"
+ >
<alert-details-table :alert="alert" :loading="loading" />
</gl-tab>
</gl-tabs>
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
index 618fb551f28..ccac38811b5 100644
--- a/app/assets/javascripts/issue_show/incident.js
+++ b/app/assets/javascripts/issue_show/incident.js
@@ -12,7 +12,17 @@ export default function initIssuableApp(issuableData = {}) {
defaultClient: createDefaultClient(),
});
- const { iid, projectNamespace, projectPath, slaFeatureAvailable } = issuableData;
+ const {
+ canUpdate,
+ iid,
+ projectNamespace,
+ projectPath,
+ projectId,
+ slaFeatureAvailable,
+ uploadMetricsFeatureAvailable,
+ } = issuableData;
+
+ const fullPath = `${projectNamespace}/${projectPath}`;
return new Vue({
el: document.getElementById('js-issuable-app'),
@@ -21,9 +31,12 @@ export default function initIssuableApp(issuableData = {}) {
issuableApp,
},
provide: {
- fullPath: `${projectNamespace}/${projectPath}`,
+ canUpdate,
+ fullPath,
iid,
+ projectId,
slaFeatureAvailable: parseBoolean(slaFeatureAvailable),
+ uploadMetricsFeatureAvailable: parseBoolean(uploadMetricsFeatureAvailable),
},
render(createElement) {
return createElement('issuable-app', {
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
index 8260460828b..83fd1355f26 100644
--- a/app/assets/javascripts/issue_show/issue.js
+++ b/app/assets/javascripts/issue_show/issue.js
@@ -57,6 +57,6 @@ export function initIssueHeaderActions(store) {
reportAbusePath: el.dataset.reportAbusePath,
submitAsSpamPath: el.dataset.submitAsSpamPath,
},
- render: createElement => createElement(HeaderActions),
+ render: (createElement) => createElement(HeaderActions),
});
}
diff --git a/app/assets/javascripts/issue_show/utils/parse_data.js b/app/assets/javascripts/issue_show/utils/parse_data.js
index 12f38005366..d5e7d2a8807 100644
--- a/app/assets/javascripts/issue_show/utils/parse_data.js
+++ b/app/assets/javascripts/issue_show/utils/parse_data.js
@@ -4,7 +4,7 @@ import { sanitize } from '~/lib/dompurify';
// We currently load + parse the data from the issue app and related merge request
let cachedParsedData;
-export const parseIssuableData = el => {
+export const parseIssuableData = (el) => {
try {
if (cachedParsedData) return cachedParsedData;
diff --git a/app/assets/javascripts/issues_list/components/issuable.vue b/app/assets/javascripts/issues_list/components/issuable.vue
index 16f8e67cde0..3965fd6b0c7 100644
--- a/app/assets/javascripts/issues_list/components/issuable.vue
+++ b/app/assets/javascripts/issues_list/components/issuable.vue
@@ -37,7 +37,6 @@ export default {
openedAgoJira: __('opened %{timeAgoString} by %{user} in Jira'),
openedAgoServiceDesk: __('opened %{timeAgoString} by %{email} via %{user}'),
},
- inject: ['scopedLabelsAvailable'],
components: {
IssueAssignees,
GlLink,
@@ -51,6 +50,7 @@ export default {
GlTooltip,
SafeHtml,
},
+ inject: ['scopedLabelsAvailable'],
props: {
issuable: {
type: Object,
@@ -110,7 +110,7 @@ export default {
return getDayDifference(new Date(this.issuable.created_at), new Date()) < 1;
},
labelIdsString() {
- return JSON.stringify(this.issuable.labels.map(l => l.id));
+ return JSON.stringify(this.issuable.labels.map((l) => l.id));
},
milestoneDueDate() {
const { due_date: dueDate } = this.issuable.milestone || {};
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 0ce2bcc1cce..eda8bc2b61f 100644
--- a/app/assets/javascripts/issues_list/components/issuables_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
@@ -208,7 +208,7 @@ export default {
},
mounted() {
if (this.canBulkEdit) {
- this.unsubscribeToggleBulkEdit = issueableEventHub.$on('issuables:toggleBulkEdit', val => {
+ this.unsubscribeToggleBulkEdit = issueableEventHub.$on('issuables:toggleBulkEdit', (val) => {
this.isBulkEditing = val;
});
}
@@ -223,7 +223,7 @@ export default {
return Boolean(this.selection[issuableId]);
},
setSelection(ids) {
- ids.forEach(id => {
+ ids.forEach((id) => {
this.select(id, true);
});
},
@@ -254,7 +254,7 @@ export default {
per_page: this.itemsPerPage,
},
})
- .then(response => {
+ .then((response) => {
this.loading = false;
this.issuables = response.data;
this.totalItems = Number(response.headers['x-total']);
@@ -335,7 +335,7 @@ export default {
handleFilter(filters) {
let search = null;
- filters.forEach(filter => {
+ filters.forEach((filter) => {
if (typeof filter === 'string') {
search = filter;
}
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 5ef86536865..42e97766b95 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -40,7 +40,7 @@ function mountIssuablesListApp() {
return;
}
- document.querySelectorAll('.js-issuables-list').forEach(el => {
+ document.querySelectorAll('.js-issuables-list').forEach((el) => {
const { canBulkEdit, emptyStateMeta = {}, scopedLabelsAvailable, ...data } = el.dataset;
return new Vue({
diff --git a/app/assets/javascripts/jira_connect/api.js b/app/assets/javascripts/jira_connect/api.js
new file mode 100644
index 00000000000..d689a2d1962
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/api.js
@@ -0,0 +1,33 @@
+import axios from 'axios';
+
+const getJwt = async () => {
+ return AP.context.getToken();
+};
+
+export const addSubscription = async (addPath, namespace) => {
+ const jwt = await getJwt();
+
+ return axios.post(addPath, {
+ jwt,
+ namespace_path: namespace,
+ });
+};
+
+export const removeSubscription = async (removePath) => {
+ const jwt = await getJwt();
+
+ return axios.delete(removePath, {
+ params: {
+ jwt,
+ },
+ });
+};
+
+export const fetchGroups = async (groupsPath, { page, perPage }) => {
+ return axios.get(groupsPath, {
+ params: {
+ page,
+ per_page: perPage,
+ },
+ });
+};
diff --git a/app/assets/javascripts/jira_connect/components/app.vue b/app/assets/javascripts/jira_connect/components/app.vue
index 490bf2fdd66..f5bf30f4488 100644
--- a/app/assets/javascripts/jira_connect/components/app.vue
+++ b/app/assets/javascripts/jira_connect/components/app.vue
@@ -1,16 +1,63 @@
<script>
+import { mapState } from 'vuex';
+import { GlAlert, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import GroupsList from './groups_list.vue';
+
export default {
name: 'JiraConnectApp',
+ components: {
+ GlAlert,
+ GlButton,
+ GlModal,
+ GroupsList,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ mixins: [glFeatureFlagsMixin()],
computed: {
- state() {
- return this.$root.$data.state || {};
+ ...mapState(['errorMessage']),
+ showNewUI() {
+ return this.glFeatures.newJiraConnectUi;
},
- error() {
- return this.state.error;
+ },
+ modal: {
+ cancelProps: {
+ text: __('Cancel'),
},
},
};
</script>
+
<template>
- <div></div>
+ <div>
+ <gl-alert v-if="errorMessage" class="gl-mb-6" variant="danger" :dismissible="false">
+ {{ errorMessage }}
+ </gl-alert>
+
+ <h1>GitLab for Jira Configuration</h1>
+
+ <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"
+ >
+ <h3 data-testid="new-jira-connect-ui-heading">{{ s__('Integrations|Linked namespaces') }}</h3>
+ <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>
+ </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
new file mode 100644
index 00000000000..eeddd32addc
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/components/groups_list.vue
@@ -0,0 +1,88 @@
+<script>
+import { GlTabs, GlTab, GlLoadingIcon, GlPagination } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import { fetchGroups } from '~/jira_connect/api';
+import { defaultPerPage } from '~/jira_connect/constants';
+import GroupsListItem from './groups_list_item.vue';
+
+export default {
+ components: {
+ GlTabs,
+ GlTab,
+ GlLoadingIcon,
+ GlPagination,
+ GroupsListItem,
+ },
+ inject: {
+ groupsPath: {
+ default: '',
+ },
+ },
+ data() {
+ return {
+ groups: [],
+ isLoading: false,
+ page: 1,
+ perPage: defaultPerPage,
+ totalItems: 0,
+ };
+ },
+ mounted() {
+ this.loadGroups();
+ },
+ methods: {
+ loadGroups() {
+ this.isLoading = true;
+
+ fetchGroups(this.groupsPath, {
+ page: this.page,
+ perPage: this.perPage,
+ })
+ .then((response) => {
+ const { page, total } = parseIntPagination(normalizeHeaders(response.headers));
+ this.page = page;
+ this.totalItems = total;
+ this.groups = response.data;
+ })
+ .catch(() => {
+ // eslint-disable-next-line no-alert
+ alert(s__('Integrations|Failed to load namespaces. Please try again.'));
+ })
+ .finally(() => {
+ this.isLoading = false;
+ });
+ },
+ },
+};
+</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 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>
+</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
new file mode 100644
index 00000000000..15e37ab3cb0
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlIcon, GlAvatar } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ GlAvatar,
+ },
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <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">
+ <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">
+ <div class="gl-min-w-0 gl-flex-grow-1 flex-shrink-1">
+ <div class="gl-display-flex gl-align-items-center gl-flex-wrap">
+ <span
+ class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold"
+ data-testid="group-list-item-name"
+ >
+ {{ group.full_name }}
+ </span>
+ </div>
+ <div v-if="group.description" data-testid="group-list-item-description">
+ <p class="gl-mt-2! gl-mb-0 gl-text-gray-600" v-text="group.description"></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/jira_connect/constants.js b/app/assets/javascripts/jira_connect/constants.js
new file mode 100644
index 00000000000..2b3be5cd5cd
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/constants.js
@@ -0,0 +1 @@
+export const defaultPerPage = 10;
diff --git a/app/assets/javascripts/jira_connect/index.js b/app/assets/javascripts/jira_connect/index.js
index e7aa4c437bb..dc2a77f4e0c 100644
--- a/app/assets/javascripts/jira_connect/index.js
+++ b/app/assets/javascripts/jira_connect/index.js
@@ -1,18 +1,21 @@
import Vue from 'vue';
+import Vuex from 'vuex';
import $ from 'jquery';
-import App from './components/app.vue';
-
-const store = {
- state: {
- error: '',
- },
- setErrorMessage(errorMessage) {
- this.state.error = errorMessage;
- },
-};
+import setConfigs from '@gitlab/ui/dist/config';
+import Translate from '~/vue_shared/translate';
+import GlFeatureFlagsPlugin from '~/vue_shared/gl_feature_flags_plugin';
+
+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 necessary form handlers for the Jira Connect app
+ * Initialize form handlers for the Jira Connect app
*/
const initJiraFormHandlers = () => {
const reqComplete = () => {
@@ -20,53 +23,40 @@ const initJiraFormHandlers = () => {
};
const reqFailed = (res, fallbackErrorMessage) => {
- const { responseJSON: { error = fallbackErrorMessage } = {} } = res || {};
+ const { error = fallbackErrorMessage } = res || {};
- store.setErrorMessage(error);
- // eslint-disable-next-line no-alert
- alert(error);
+ store.commit(SET_ERROR_MESSAGE, error);
};
- AP.getLocation(location => {
- $('.js-jira-connect-sign-in').each(function updateSignInLink() {
- const updatedLink = `${$(this).attr('href')}?return_to=${location}`;
- $(this).attr('href', updatedLink);
+ 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);
+ });
});
- });
+ }
$('#add-subscription-form').on('submit', function onAddSubscriptionForm(e) {
- const actionUrl = $(this).attr('action');
+ const addPath = $(this).attr('action');
+ const namespace = $('#namespace-input').val();
+
e.preventDefault();
- AP.context.getToken(token => {
- // eslint-disable-next-line no-jquery/no-ajax
- $.post(actionUrl, {
- jwt: token,
- namespace_path: $('#namespace-input').val(),
- format: 'json',
- })
- .done(reqComplete)
- .fail(err => reqFailed(err, 'Failed to add namespace. Please try again.'));
- });
+ addSubscription(addPath, namespace)
+ .then(reqComplete)
+ .catch((err) => reqFailed(err.response.data, 'Failed to add namespace. Please try again.'));
});
$('.remove-subscription').on('click', function onRemoveSubscriptionClick(e) {
- const href = $(this).attr('href');
+ const removePath = $(this).attr('href');
e.preventDefault();
- AP.context.getToken(token => {
- // eslint-disable-next-line no-jquery/no-ajax
- $.ajax({
- url: href,
- method: 'DELETE',
- data: {
- jwt: token,
- format: 'json',
- },
- })
- .done(reqComplete)
- .fail(err => reqFailed(err, 'Failed to remove namespace. Please try again.'));
- });
+ removeSubscription(removePath)
+ .then(reqComplete)
+ .catch((err) =>
+ reqFailed(err.response.data, 'Failed to remove namespace. Please try again.'),
+ );
});
};
@@ -75,13 +65,24 @@ function initJiraConnect() {
initJiraFormHandlers();
+ if (!el) {
+ return null;
+ }
+
+ setConfigs();
+ Vue.use(Translate);
+ Vue.use(GlFeatureFlagsPlugin);
+
+ const { groupsPath } = el.dataset;
+
return new Vue({
el,
- data: {
- state: store.state,
+ store,
+ provide: {
+ groupsPath,
},
render(createElement) {
- return createElement(App, {});
+ return createElement(JiraConnectApp);
},
});
}
diff --git a/app/assets/javascripts/jira_connect/store/index.js b/app/assets/javascripts/jira_connect/store/index.js
new file mode 100644
index 00000000000..aa7e14269a4
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/store/index.js
@@ -0,0 +1,9 @@
+import Vuex from 'vuex';
+import mutations from './mutations';
+import state from './state';
+
+export default () =>
+ new Vuex.Store({
+ state,
+ mutations,
+ });
diff --git a/app/assets/javascripts/jira_connect/store/mutation_types.js b/app/assets/javascripts/jira_connect/store/mutation_types.js
new file mode 100644
index 00000000000..7f6ff1256bb
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/store/mutation_types.js
@@ -0,0 +1 @@
+export const SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE';
diff --git a/app/assets/javascripts/jira_connect/store/mutations.js b/app/assets/javascripts/jira_connect/store/mutations.js
new file mode 100644
index 00000000000..c3acd07f89f
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/store/mutations.js
@@ -0,0 +1,7 @@
+import { SET_ERROR_MESSAGE } from './mutation_types';
+
+export default {
+ [SET_ERROR_MESSAGE](state, errorMessage) {
+ state.errorMessage = errorMessage;
+ },
+};
diff --git a/app/assets/javascripts/jira_connect/store/state.js b/app/assets/javascripts/jira_connect/store/state.js
new file mode 100644
index 00000000000..079b8350770
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/store/state.js
@@ -0,0 +1,3 @@
+export default () => ({
+ errorMessage: undefined,
+});
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 4a1bca110fd..ab475c3c85a 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_form.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue
@@ -118,7 +118,7 @@ export default {
this.getJiraUserMapping();
this.searchUsers()
- .then(data => {
+ .then((data) => {
this.initialUsers = data;
})
.catch(() => {});
@@ -219,7 +219,7 @@ export default {
}
},
updateMapping(jiraAccountId, gitlabId, gitlabUsername) {
- this.userMappings = this.userMappings.map(userMapping =>
+ this.userMappings = this.userMappings.map((userMapping) =>
userMapping.jiraAccountId === jiraAccountId
? {
...userMapping,
diff --git a/app/assets/javascripts/jira_import/utils/cache_update.js b/app/assets/javascripts/jira_import/utils/cache_update.js
index 65b2e459f03..db7dbb7353f 100644
--- a/app/assets/javascripts/jira_import/utils/cache_update.js
+++ b/app/assets/javascripts/jira_import/utils/cache_update.js
@@ -20,7 +20,7 @@ export const addInProgressImportToStore = (store, jiraImportStart, fullPath) =>
store.writeQuery({
...queryDetails,
- data: produce(sourceData, draftData => {
+ data: produce(sourceData, (draftData) => {
draftData.project.jiraImportStatus = IMPORT_STATE.SCHEDULED; // eslint-disable-line no-param-reassign
// eslint-disable-next-line no-param-reassign
draftData.project.jiraImports.nodes = [
diff --git a/app/assets/javascripts/jira_import/utils/jira_import_utils.js b/app/assets/javascripts/jira_import/utils/jira_import_utils.js
index edd6fad4aac..4e3b5b2fbde 100644
--- a/app/assets/javascripts/jira_import/utils/jira_import_utils.js
+++ b/app/assets/javascripts/jira_import/utils/jira_import_utils.js
@@ -9,10 +9,10 @@ export const IMPORT_STATE = {
STARTED: 'started',
};
-export const isInProgress = state =>
+export const isInProgress = (state) =>
state === IMPORT_STATE.SCHEDULED || state === IMPORT_STATE.STARTED;
-export const isFinished = state => state === IMPORT_STATE.FINISHED;
+export const isFinished = (state) => state === IMPORT_STATE.FINISHED;
/**
* Converts the list of Jira projects into a format consumable by GlFormSelect.
@@ -22,7 +22,7 @@ export const isFinished = state => state === IMPORT_STATE.FINISHED;
* @param {string} projects[].name - Jira project name
* @returns {Object[]} - List of Jira projects in a format consumable by GlFormSelect
*/
-export const extractJiraProjectsOptions = projects =>
+export const extractJiraProjectsOptions = (projects) =>
projects.map(({ key, name }) => ({ text: `${name} (${key})`, value: key }));
/**
@@ -32,10 +32,10 @@ export const extractJiraProjectsOptions = projects =>
* @param {string} jiraImports[].jiraProjectKey - Jira project key
* @returns {string} - A label title
*/
-const calculateJiraImportLabelTitle = jiraImports => {
+const calculateJiraImportLabelTitle = (jiraImports) => {
const mostRecentJiraProjectKey = last(jiraImports)?.jiraProjectKey;
const jiraProjectImportCount = jiraImports.filter(
- jiraImport => jiraImport.jiraProjectKey === mostRecentJiraProjectKey,
+ (jiraImport) => jiraImport.jiraProjectKey === mostRecentJiraProjectKey,
).length;
return `jira-import::${mostRecentJiraProjectKey}-${jiraProjectImportCount}`;
};
@@ -50,7 +50,7 @@ const calculateJiraImportLabelTitle = jiraImports => {
* @returns {string} - The label color associated with the given labelTitle
*/
const calculateJiraImportLabelColor = (labelTitle, labels) =>
- labels.find(label => label.title === labelTitle)?.color;
+ labels.find((label) => label.title === labelTitle)?.color;
/**
* Calculates the label for the most recent Jira import.
@@ -91,7 +91,7 @@ export const shouldShowFinishedAlert = (labelTitle, importStatus) => {
*
* @param {string} labelTitle - Jira import label, for checking localStorage
*/
-export const setFinishedAlertHideMap = labelTitle => {
+export const setFinishedAlertHideMap = (labelTitle) => {
const finishedAlertHideMap =
JSON.parse(localStorage.getItem(JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY)) || {};
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 30093224631..b0ba6ce52d1 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -134,7 +134,7 @@ export default {
if (isEmpty(oldVal) && !isEmpty(newVal.pipeline)) {
const stages = this.job.pipeline.details.stages || [];
- const defaultStage = stages.find(stage => stage && stage.name === this.selectedStage);
+ const defaultStage = stages.find((stage) => stage && stage.name === this.selectedStage);
if (defaultStage) {
this.fetchJobsForStage(defaultStage);
diff --git a/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue b/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue
index 5ce9d08035d..e83ed6c6332 100644
--- a/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue
+++ b/app/assets/javascripts/jobs/components/job_retry_forward_deployment_modal.vue
@@ -11,6 +11,11 @@ export default {
i18n: {
...JOB_RETRY_FORWARD_DEPLOYMENT_MODAL,
},
+ inject: {
+ retryOutdatedJobDocsUrl: {
+ default: '',
+ },
+ },
props: {
modalId: {
type: String,
@@ -21,11 +26,6 @@ export default {
required: true,
},
},
- inject: {
- retryOutdatedJobDocsUrl: {
- default: '',
- },
- },
data() {
return {
primaryProps: {
diff --git a/app/assets/javascripts/jobs/components/log/line.vue b/app/assets/javascripts/jobs/components/log/line.vue
index 87af387ca91..2d9714cd06b 100644
--- a/app/assets/javascripts/jobs/components/log/line.vue
+++ b/app/assets/javascripts/jobs/components/log/line.vue
@@ -18,7 +18,7 @@ export default {
render(h, { props }) {
const { line, path } = props;
- const chars = line.content.map(content => {
+ const chars = line.content.map((content) => {
return h(
'span',
{
@@ -26,7 +26,7 @@ export default {
},
// Simple "tokenization": Split text in chunks of text
// which alternate between text and urls.
- content.text.split(linkRegex).map(chunk => {
+ content.text.split(linkRegex).map((chunk) => {
// Return normal string for non-links
if (!chunk.match(linkRegex)) {
return chunk;
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index bf1930c9a37..24276cbe60a 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -93,7 +93,10 @@ export default {
this.secretValue = '';
},
deleteVariable(id) {
- this.variables.splice(this.variables.findIndex(el => el.id === id), 1);
+ this.variables.splice(
+ this.variables.findIndex((el) => el.id === id),
+ 1,
+ );
},
},
};
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index aeae9f26ed3..7d4fe0a0680 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -48,7 +48,10 @@ export default {
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
<span class="font-weight-bold">{{ s__('Job|Pipeline') }}</span>
- <gl-link :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
+ <gl-link
+ :href="pipeline.path"
+ class="js-pipeline-path link-commit"
+ data-qa-selector="pipeline_path"
>#{{ pipeline.id }}</gl-link
>
<template v-if="hasRef">
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index 3cb5e63fd36..1d46dd8cea4 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -27,7 +27,7 @@ export default {
return this.showVariableValues ? __('Hide values') : __('Reveal values');
},
hasValues() {
- return this.trigger.variables.some(v => v.value);
+ return this.trigger.variables.some((v) => v.value);
},
},
methods: {
diff --git a/app/assets/javascripts/jobs/store/actions.js b/app/assets/javascripts/jobs/store/actions.js
index e3ded725168..e76a3693db9 100644
--- a/app/assets/javascripts/jobs/store/actions.js
+++ b/app/assets/javascripts/jobs/store/actions.js
@@ -2,7 +2,7 @@ import Visibility from 'visibilityjs';
import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
-import { setFaviconOverlay, resetFavicon } from '~/lib/utils/common_utils';
+import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
import {
@@ -173,7 +173,7 @@ export const fetchTrace = ({ dispatch, state }) =>
dispatch('startPollingTrace');
}
})
- .catch(e =>
+ .catch((e) =>
e.response.status === httpStatusCodes.FORBIDDEN
? dispatch('receiveTraceUnauthorizedError')
: dispatch('receiveTraceError'),
@@ -229,7 +229,7 @@ export const fetchJobsForStage = ({ dispatch }, stage = {}) => {
},
})
.then(({ data }) => {
- const retriedJobs = data.retried.map(job => ({ ...job, retried: true }));
+ const retriedJobs = data.retried.map((job) => ({ ...job, retried: true }));
const jobs = data.latest_statuses.concat(retriedJobs);
dispatch('receiveJobsForStageSuccess', jobs);
@@ -244,7 +244,7 @@ export const receiveJobsForStageError = ({ commit }) => {
};
export const triggerManualJob = ({ state }, variables) => {
- const parsedVariables = variables.map(variable => {
+ const parsedVariables = variables.map((variable) => {
const copyVar = { ...variable };
delete copyVar.id;
return copyVar;
diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js
index 8c2d1dd8ab2..30a4a247dc4 100644
--- a/app/assets/javascripts/jobs/store/getters.js
+++ b/app/assets/javascripts/jobs/store/getters.js
@@ -1,37 +1,37 @@
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.started : state.job.created_at);
-export const hasForwardDeploymentFailure = state =>
+export const hasForwardDeploymentFailure = (state) =>
state?.job?.failure_reason === 'forward_deployment_failure';
-export const hasUnmetPrerequisitesFailure = state =>
+export const hasUnmetPrerequisitesFailure = (state) =>
state?.job?.failure_reason === 'unmet_prerequisites';
-export const shouldRenderCalloutMessage = state =>
+export const shouldRenderCalloutMessage = (state) =>
!isEmpty(state.job.status) && !isEmpty(state.job.callout_message);
/**
* When job has not started the key will be null
* When job started the key will be a string with a date.
*/
-export const shouldRenderTriggeredLabel = state => isString(state.job.started);
+export const shouldRenderTriggeredLabel = (state) => isString(state.job.started);
-export const hasEnvironment = state => !isEmpty(state.job.deployment_status);
+export const hasEnvironment = (state) => !isEmpty(state.job.deployment_status);
/**
* Checks if it the job has trace.
* Used to check if it should render the job log or the empty state
* @returns {Boolean}
*/
-export const hasTrace = state =>
+export const hasTrace = (state) =>
state.job.has_trace || (!isEmpty(state.job.status) && state.job.status.group === 'running');
-export const emptyStateIllustration = state =>
+export const emptyStateIllustration = (state) =>
(state.job && state.job.status && state.job.status.illustration) || {};
-export const emptyStateAction = state =>
+export const emptyStateAction = (state) =>
(state.job && state.job.status && state.job.status.action) || null;
/**
@@ -40,12 +40,12 @@ export const emptyStateAction = state =>
*
* @returns {Boolean}
*/
-export const shouldRenderSharedRunnerLimitWarning = state =>
+export const shouldRenderSharedRunnerLimitWarning = (state) =>
!isEmpty(state.job.runners) &&
!isEmpty(state.job.runners.quota) &&
state.job.runners.quota.used >= state.job.runners.quota.limit;
-export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete;
+export const isScrollingDown = (state) => isScrolledToBottom() && !state.isTraceComplete;
-export const hasRunnersForProject = state =>
+export const hasRunnersForProject = (state) =>
state.job.runners.available && !state.job.runners.online;
diff --git a/app/assets/javascripts/jobs/store/utils.js b/app/assets/javascripts/jobs/store/utils.js
index ea9c214de32..a0e0a0fb8bd 100644
--- a/app/assets/javascripts/jobs/store/utils.js
+++ b/app/assets/javascripts/jobs/store/utils.js
@@ -43,7 +43,7 @@ export const parseHeaderLine = (line = {}, lineNumber) => ({
* @param Object durationLine
*/
export function addDurationToHeader(data, durationLine) {
- data.forEach(el => {
+ data.forEach((el) => {
if (el.line && el.line.section === durationLine.section) {
el.line.section_duration = durationLine.section_duration;
}
@@ -72,7 +72,7 @@ export const isCollapsibleSection = (acc = [], last = {}, section = {}) =>
* @param Array acc
* @returns Number
*/
-export const getIncrementalLineNumber = acc => {
+export const getIncrementalLineNumber = (acc) => {
let lineNumberValue;
const lastIndex = acc.length - 1;
const lastElement = acc[lastIndex];
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index 469f7ce94b0..92dffb87e1a 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -135,7 +135,7 @@ export default class LabelManager {
getSortedLabelsIds() {
const sortedIds = [];
- this.prioritizedLabels.find('> li').each(function() {
+ this.prioritizedLabels.find('> li').each(function () {
const id = $(this).data('id');
if (id) {
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index ac5aa24d5d8..337d063b02a 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -49,7 +49,7 @@ export default class LabelsSelect {
const fieldName = $dropdown.data('fieldName');
let initialSelected = $selectbox
.find(`input[name="${$dropdown.data('fieldName')}"]`)
- .map(function() {
+ .map(function () {
return this.value;
})
.get();
@@ -64,11 +64,11 @@ export default class LabelsSelect {
);
}
- const saveLabelData = function() {
+ const saveLabelData = function () {
const selected = $dropdown
.closest('.selectbox')
.find(`input[name='${fieldName}']`)
- .map(function() {
+ .map(function () {
return this.value;
})
.get();
@@ -124,15 +124,15 @@ export default class LabelsSelect {
const toRemoveIds = Array.from(
$form.find(`input[type="hidden"][name="${fieldName}"]`),
)
- .map(el => el.value)
+ .map((el) => el.value)
.map(Number);
- data.labels.forEach(label => {
+ data.labels.forEach((label) => {
const index = toRemoveIds.indexOf(label.id);
toRemoveIds.splice(index, 1);
});
- toRemoveIds.forEach(id => {
+ toRemoveIds.forEach((id) => {
$form
.find(`input[type="hidden"][name="${fieldName}"][value="${id}"]`)
.last()
@@ -157,7 +157,7 @@ export default class LabelsSelect {
const labelUrl = $dropdown.attr('data-labels');
axios
.get(labelUrl)
- .then(res => {
+ .then((res) => {
let { data } = res;
if ($dropdown.hasClass('js-extra-options')) {
const extraData = [];
@@ -210,9 +210,7 @@ export default class LabelsSelect {
}
} else {
if (this.id(label)) {
- const dropdownValue = this.id(label)
- .toString()
- .replace(/'/g, "\\'");
+ const dropdownValue = this.id(label).toString().replace(/'/g, "\\'");
if (
$form.find(
@@ -346,10 +344,7 @@ export default class LabelsSelect {
const isMRIndex = page === 'projects:merge_requests:index';
if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
- $dropdown
- .parent()
- .find('.dropdown-clear-active')
- .removeClass('is-active');
+ $dropdown.parent().find('.dropdown-clear-active').removeClass('is-active');
}
if ($dropdown.hasClass('js-issuable-form-dropdown')) {
@@ -395,7 +390,7 @@ export default class LabelsSelect {
);
} else {
let { labels } = boardsStore.detail.issue;
- labels = labels.filter(selectedLabel => selectedLabel.id !== label.id);
+ labels = labels.filter((selectedLabel) => selectedLabel.id !== label.id);
boardsStore.detail.issue.labels = labels;
}
@@ -406,12 +401,12 @@ export default class LabelsSelect {
.update($dropdown.attr('data-issue-update'))
.then(() => {
if (isScopedLabel(label)) {
- const prevIds = oldLabels.map(label => label.id);
- const newIds = boardsStore.detail.issue.labels.map(label => label.id);
- const differentIds = prevIds.filter(x => !newIds.includes(x));
+ const prevIds = oldLabels.map((label) => label.id);
+ const newIds = boardsStore.detail.issue.labels.map((label) => label.id);
+ const differentIds = prevIds.filter((x) => !newIds.includes(x));
$dropdown.data('marked', newIds);
$dropdownMenu
- .find(differentIds.map(id => `[data-label-id="${id}"]`).join(','))
+ .find(differentIds.map((id) => `[data-label-id="${id}"]`).join(','))
.removeClass('is-active');
}
})
@@ -559,7 +554,7 @@ export default class LabelsSelect {
// eslint-disable-next-line class-methods-use-this
setOriginalDropdownData($container, $dropdown) {
const labels = [];
- $container.find('[name="label_name[]"]').map(function() {
+ $container.find('[name="label_name[]"]').map(function () {
return labels.push(this.value);
});
$dropdown.data('marked', labels);
diff --git a/app/assets/javascripts/lazy_loader.js b/app/assets/javascripts/lazy_loader.js
index aa7fe087678..b7cb6aa0a21 100644
--- a/app/assets/javascripts/lazy_loader.js
+++ b/app/assets/javascripts/lazy_loader.js
@@ -28,10 +28,10 @@ export default class LazyLoader {
const lazyImages = [].slice.call(document.querySelectorAll('.lazy'));
if (LazyLoader.supportsNativeLazyLoading()) {
- lazyImages.forEach(img => LazyLoader.loadImage(img));
+ lazyImages.forEach((img) => LazyLoader.loadImage(img));
} else if (LazyLoader.supportsIntersectionObserver()) {
if (this.intersectionObserver) {
- lazyImages.forEach(img => this.intersectionObserver.observe(img));
+ lazyImages.forEach((img) => this.intersectionObserver.observe(img));
}
} else if (lazyImages.length) {
this.lazyImages = lazyImages;
@@ -98,8 +98,8 @@ export default class LazyLoader {
});
};
- onIntersection = entries => {
- entries.forEach(entry => {
+ onIntersection = (entries) => {
+ entries.forEach((entry) => {
// We are using `intersectionRatio > 0` over `isIntersecting`, as some browsers did not ship the latter
// See: https://gitlab.com/gitlab-org/gitlab-foss/issues/54407
if (entry.intersectionRatio > 0) {
@@ -126,7 +126,7 @@ export default class LazyLoader {
const visHeight = scrollTop + window.innerHeight + SCROLL_THRESHOLD;
// Loading Images which are in the current viewport or close to them
- this.lazyImages = this.lazyImages.filter(selectedImage => {
+ this.lazyImages = this.lazyImages.filter((selectedImage) => {
if (selectedImage.getAttribute('data-src')) {
const imgBoundRect = selectedImage.getBoundingClientRect();
const imgTop = scrollTop + imgBoundRect.top;
diff --git a/app/assets/javascripts/lib/chrome_84_icon_fix.js b/app/assets/javascripts/lib/chrome_84_icon_fix.js
index 60497186c19..20fe9590ce3 100644
--- a/app/assets/javascripts/lib/chrome_84_icon_fix.js
+++ b/app/assets/javascripts/lib/chrome_84_icon_fix.js
@@ -30,7 +30,7 @@ document.addEventListener('DOMContentLoaded', async () => {
const fixSVGs = () => {
requestIdleCallback(() => {
- document.querySelectorAll(`use:not([${SKIP_ATTRIBUTE}])`).forEach(use => {
+ document.querySelectorAll(`use:not([${SKIP_ATTRIBUTE}])`).forEach((use) => {
const href = use?.getAttribute('href') ?? use?.getAttribute('xlink:href') ?? '';
if (href.includes(window.gon.sprite_icons)) {
@@ -60,7 +60,7 @@ document.addEventListener('DOMContentLoaded', async () => {
div.classList.add('hidden');
const result = await fetch(url);
div.innerHTML = await result.text();
- div.querySelectorAll('[id]').forEach(node => {
+ div.querySelectorAll('[id]').forEach((node) => {
node.setAttribute('id', `${prefix}-${node.getAttribute('id')}`);
});
document.body.append(div);
diff --git a/app/assets/javascripts/lib/dompurify.js b/app/assets/javascripts/lib/dompurify.js
index d9ea57fbbce..76624c81ed5 100644
--- a/app/assets/javascripts/lib/dompurify.js
+++ b/app/assets/javascripts/lib/dompurify.js
@@ -11,9 +11,9 @@ const defaultConfig = {
const getAllowedIconUrls = (gon = window.gon) =>
[gon.sprite_file_icons, gon.sprite_icons].filter(Boolean);
-const isUrlAllowed = url => getAllowedIconUrls().some(allowedUrl => url.startsWith(allowedUrl));
+const isUrlAllowed = (url) => getAllowedIconUrls().some((allowedUrl) => url.startsWith(allowedUrl));
-const isHrefSafe = url =>
+const isHrefSafe = (url) =>
isUrlAllowed(url) || isUrlAllowed(relativePathToAbsolute(url, getBaseURL()));
const removeUnsafeHref = (node, attr) => {
@@ -36,7 +36,7 @@ const removeUnsafeHref = (node, attr) => {
*
* @param {Object} node - Node to sanitize
*/
-const sanitizeSvgIcon = node => {
+const sanitizeSvgIcon = (node) => {
removeUnsafeHref(node, 'href');
// Note: `xlink:href` is deprecated, but still in use
@@ -44,7 +44,7 @@ const sanitizeSvgIcon = node => {
removeUnsafeHref(node, 'xlink:href');
};
-addHook('afterSanitizeAttributes', node => {
+addHook('afterSanitizeAttributes', (node) => {
if (node.tagName.toLowerCase() === 'use') {
sanitizeSvgIcon(node);
}
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index e0d9a903e0a..5c4bb5ea01f 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -36,13 +36,13 @@ export default (resolvers = {}, config = {}) => {
};
const uploadsLink = ApolloLink.split(
- operation => operation.getContext().hasUpload || operation.getContext().isSingleRequest,
+ (operation) => operation.getContext().hasUpload || operation.getContext().isSingleRequest,
createUploadLink(httpOptions),
new BatchHttpLink(httpOptions),
);
const performanceBarLink = new ApolloLink((operation, forward) => {
- return forward(operation).map(response => {
+ return forward(operation).map((response) => {
const httpResponse = operation.getContext().response;
if (PerformanceBarService.interceptor) {
diff --git a/app/assets/javascripts/lib/utils/ajax_cache.js b/app/assets/javascripts/lib/utils/ajax_cache.js
index 2d976dbdbbe..935bd0f16e9 100644
--- a/app/assets/javascripts/lib/utils/ajax_cache.js
+++ b/app/assets/javascripts/lib/utils/ajax_cache.js
@@ -25,7 +25,7 @@ class AjaxCache extends Cache {
this.internalStorage[endpoint] = data;
delete this.pendingRequests[endpoint];
})
- .catch(e => {
+ .catch((e) => {
const error = new Error(`${endpoint}: ${e.message}`);
error.textStatus = e.message;
diff --git a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
index 5c120dd532f..014823f3831 100644
--- a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
+++ b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js
@@ -7,7 +7,7 @@ import { isEqual, pickBy } from 'lodash';
* @param obj
* @returns {Dictionary<unknown>}
*/
-const pickDefinedValues = obj => pickBy(obj, x => x !== undefined);
+const pickDefinedValues = (obj) => pickBy(obj, (x) => x !== undefined);
/**
* Compares two set of variables, order independent
@@ -28,9 +28,9 @@ export class StartupJSLink extends ApolloLink {
// Extract operationNames from the queries and ensure that we can
// match operationName => element from result array
parseStartupCalls(calls) {
- calls.forEach(call => {
+ calls.forEach((call) => {
const { query, variables, fetchCall } = call;
- const operationName = parse(query)?.definitions?.find(x => x.kind === 'OperationDefinition')
+ const operationName = parse(query)?.definitions?.find((x) => x.kind === 'OperationDefinition')
?.name?.value;
if (operationName) {
@@ -71,9 +71,9 @@ export class StartupJSLink extends ApolloLink {
return forward(operation);
}
- return new Observable(observer => {
+ return new Observable((observer) => {
fetchCall
- .then(response => {
+ .then((response) => {
// Handle HTTP errors
if (!response.ok) {
throw new Error('fetchCall failed');
@@ -81,7 +81,7 @@ export class StartupJSLink extends ApolloLink {
operation.setContext({ response });
return response.json();
})
- .then(result => {
+ .then((result) => {
if (result && (result.errors || !result.data)) {
throw new Error('Received GraphQL error');
}
@@ -92,10 +92,10 @@ export class StartupJSLink extends ApolloLink {
})
.catch(() => {
forward(operation).subscribe({
- next: result => {
+ next: (result) => {
observer.next(result);
},
- error: error => {
+ error: (error) => {
observer.error(error);
},
complete: observer.complete.bind(observer),
diff --git a/app/assets/javascripts/lib/utils/autosave.js b/app/assets/javascripts/lib/utils/autosave.js
index 56df2532528..dac1da743a2 100644
--- a/app/assets/javascripts/lib/utils/autosave.js
+++ b/app/assets/javascripts/lib/utils/autosave.js
@@ -1,6 +1,6 @@
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
-export const clearDraft = autosaveKey => {
+export const clearDraft = (autosaveKey) => {
try {
window.localStorage.removeItem(`autosave/${autosaveKey}`);
} catch (e) {
@@ -9,7 +9,7 @@ export const clearDraft = autosaveKey => {
}
};
-export const getDraft = autosaveKey => {
+export const getDraft = (autosaveKey) => {
try {
return window.localStorage.getItem(`autosave/${autosaveKey}`);
} catch (e) {
diff --git a/app/assets/javascripts/lib/utils/axios_startup_calls.js b/app/assets/javascripts/lib/utils/axios_startup_calls.js
index 7bb1da5aed5..f9d58ff9b1d 100644
--- a/app/assets/javascripts/lib/utils/axios_startup_calls.js
+++ b/app/assets/javascripts/lib/utils/axios_startup_calls.js
@@ -3,9 +3,9 @@ import { mergeUrlParams } from './url_utility';
// We should probably not couple this utility to `gon.gitlab_url`
// Also, this would replace occurrences that aren't at the beginning of the string
-const removeGitLabUrl = url => url.replace(gon.gitlab_url, '');
+const removeGitLabUrl = (url) => url.replace(gon.gitlab_url, '');
-const getFullUrl = req => {
+const getFullUrl = (req) => {
const url = removeGitLabUrl(req.url);
return mergeUrlParams(req.params || {}, url, { sort: true });
};
@@ -36,7 +36,7 @@ const handleStartupCall = async ({ fetchCall }, req) => {
});
};
-const setupAxiosStartupCalls = axios => {
+const setupAxiosStartupCalls = (axios) => {
const { startup_calls: startupCalls } = window.gl || {};
if (!startupCalls || isEmpty(startupCalls)) {
@@ -45,7 +45,7 @@ const setupAxiosStartupCalls = axios => {
const remainingCalls = new Map(Object.entries(startupCalls));
- const interceptor = axios.interceptors.request.use(async req => {
+ const interceptor = axios.interceptors.request.use(async (req) => {
const fullUrl = getFullUrl(req);
const startupCall = remainingCalls.get(fullUrl);
diff --git a/app/assets/javascripts/lib/utils/axios_utils.js b/app/assets/javascripts/lib/utils/axios_utils.js
index 9d517f45caa..cb479e243b2 100644
--- a/app/assets/javascripts/lib/utils/axios_utils.js
+++ b/app/assets/javascripts/lib/utils/axios_utils.js
@@ -9,7 +9,7 @@ axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// Maintain a global counter for active requests
// see: spec/support/wait_for_requests.rb
-axios.interceptors.request.use(config => {
+axios.interceptors.request.use((config) => {
window.pendingRequests = window.pendingRequests || 0;
window.pendingRequests += 1;
return config;
@@ -19,11 +19,11 @@ setupAxiosStartupCalls(axios);
// Remove the global counter
axios.interceptors.response.use(
- response => {
+ (response) => {
window.pendingRequests -= 1;
return response;
},
- err => {
+ (err) => {
window.pendingRequests -= 1;
return Promise.reject(err);
},
@@ -37,8 +37,8 @@ window.addEventListener('beforeunload', () => {
// Ignore AJAX errors caused by requests
// being cancelled due to browser navigation
axios.interceptors.response.use(
- response => response,
- err => suppressAjaxErrorsDuringNavigation(err, isUserNavigating),
+ (response) => response,
+ (err) => suppressAjaxErrorsDuringNavigation(err, isUserNavigating),
);
export default axios;
diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
index 28a7ebfdc69..286fc2568b2 100644
--- a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
+++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
@@ -68,7 +68,7 @@ export default class LinkedTabs {
// since this is a custom event we need jQuery :(
$(document)
.off('shown.bs.tab', tabSelector)
- .on('shown.bs.tab', tabSelector, e => this.tabShown(e));
+ .on('shown.bs.tab', tabSelector, (e) => this.tabShown(e));
this.activateTab(this.action);
}
diff --git a/app/assets/javascripts/lib/utils/chart_utils.js b/app/assets/javascripts/lib/utils/chart_utils.js
index 4a1e6c5d68c..7da3bab0a4b 100644
--- a/app/assets/javascripts/lib/utils/chart_utils.js
+++ b/app/assets/javascripts/lib/utils/chart_utils.js
@@ -34,7 +34,7 @@ const commonChartOptions = () => ({
legend: false,
});
-export const barChartOptions = shouldAdjustFontSize => ({
+export const barChartOptions = (shouldAdjustFontSize) => ({
...commonChartOptions(),
scales: {
...yAxesConfig(shouldAdjustFontSize),
@@ -89,7 +89,7 @@ export const lineChartOptions = ({ width, numberOfPoints, shouldAdjustFontSize }
* @param {Array} data
* @returns {[*, *]}
*/
-export const firstAndLastY = data => {
+export const firstAndLastY = (data) => {
const [firstEntry] = data;
const [lastEntry] = data.slice(-1);
diff --git a/app/assets/javascripts/lib/utils/color_utils.js b/app/assets/javascripts/lib/utils/color_utils.js
index 07fb2915ca7..a1f56b15631 100644
--- a/app/assets/javascripts/lib/utils/color_utils.js
+++ b/app/assets/javascripts/lib/utils/color_utils.js
@@ -4,7 +4,7 @@
* @param hex string
* @returns array|null
*/
-export const hexToRgb = hex => {
+export const hexToRgb = (hex) => {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
const fullHex = hex.replace(shorthandRegex, (_m, r, g, b) => r + r + g + g + b + b);
@@ -15,7 +15,7 @@ export const hexToRgb = hex => {
: null;
};
-export const textColorForBackground = backgroundColor => {
+export const textColorForBackground = (backgroundColor) => {
const [r, g, b] = hexToRgb(backgroundColor);
if (r + g + b > 500) {
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index f88a0433535..128ef5b335e 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -4,9 +4,8 @@
import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import { isFunction } from 'lodash';
+import { isFunction, defer } from 'lodash';
import Cookies from 'js-cookie';
-import axios from './axios_utils';
import { getLocationHash } from './url_utility';
import { convertToCamelCase, convertToSnakeCase } from './text_utility';
import { isObject } from './type_utility';
@@ -54,7 +53,7 @@ export const getCspNonceValue = () => {
return metaTag && metaTag.content;
};
-export const rstrip = val => {
+export const rstrip = (val) => {
if (val) {
return val.replace(/\s+$/, '');
}
@@ -68,7 +67,7 @@ export const disableButtonIfEmptyField = (fieldSelector, buttonSelector, eventNa
closestSubmit.disable();
}
// eslint-disable-next-line func-names
- return field.on(eventName, function() {
+ return field.on(eventName, function () {
if (rstrip($(this).val()) === '') {
return closestSubmit.disable();
}
@@ -149,13 +148,13 @@ export const isInViewport = (el, offset = {}) => {
);
};
-export const parseUrl = url => {
+export const parseUrl = (url) => {
const parser = document.createElement('a');
parser.href = url;
return parser;
};
-export const parseUrlPathname = url => {
+export const parseUrlPathname = (url) => {
const parsedUrl = parseUrl(url);
// parsedUrl.pathname will return an absolute path for Firefox and a relative path for IE11
// We have to make sure we always have an absolute path.
@@ -166,8 +165,8 @@ const splitPath = (path = '') => path.replace(/^\?/, '').split('&');
export const urlParamsToArray = (path = '') =>
splitPath(path)
- .filter(param => param.length > 0)
- .map(param => {
+ .filter((param) => param.length > 0)
+ .map((param) => {
const split = param.split('=');
return [decodeURI(split[0]), split[1]].join('=');
});
@@ -209,13 +208,13 @@ export const urlParamsToObject = (path = '') =>
return data;
}, {});
-export const isMetaKey = e => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
+export const isMetaKey = (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
// Identify following special clicks
// 1) Cmd + Click on Mac (e.metaKey)
// 2) Ctrl + Click on PC (e.ctrlKey)
// 3) Middle-click or Mouse Wheel Click (e.which is 2)
-export const isMetaClick = e => e.metaKey || e.ctrlKey || e.which === 2;
+export const isMetaClick = (e) => e.metaKey || e.ctrlKey || e.which === 2;
export const contentTop = () => {
const isDesktop = breakpointInstance.isDesktop();
@@ -261,23 +260,26 @@ export const contentTop = () => {
};
export const scrollToElement = (element, options = {}) => {
- let $el = element;
- if (!(element instanceof $)) {
- $el = $(element);
+ let el = element;
+ if (element instanceof $) {
+ // eslint-disable-next-line prefer-destructuring
+ el = element[0];
+ } else if (typeof el === 'string') {
+ el = document.querySelector(element);
}
- const { top } = $el.offset();
- const { offset = 0 } = options;
- // eslint-disable-next-line no-jquery/no-animate
- return $('body, html').animate(
- {
- scrollTop: top - contentTop() + offset,
- },
- 200,
- );
+ if (el && el.getBoundingClientRect) {
+ // In the previous implementation, jQuery naturally deferred this scrolling.
+ // Unfortunately, we're quite coupled to this implementation detail now.
+ defer(() => {
+ const { duration = 200, offset = 0 } = options;
+ const y = el.getBoundingClientRect().top + window.pageYOffset + offset - contentTop();
+ window.scrollTo({ top: y, behavior: duration ? 'smooth' : 'auto' });
+ });
+ }
};
-export const scrollToElementWithContext = element => {
+export const scrollToElementWithContext = (element) => {
const offsetMultiplier = -0.1;
return scrollToElement(element, { offset: window.innerHeight * offsetMultiplier });
};
@@ -287,7 +289,7 @@ export const scrollToElementWithContext = element => {
* each browser screen repaint.
* @param {Function} fn
*/
-export const debounceByAnimationFrame = fn => {
+export const debounceByAnimationFrame = (fn) => {
let requestId;
return function debounced(...args) {
@@ -334,7 +336,7 @@ const handleSelectedRange = (range, restrictToNode) => {
return range.cloneContents();
};
-export const getSelectedFragment = restrictToNode => {
+export const getSelectedFragment = (restrictToNode) => {
const selection = window.getSelection();
if (selection.rangeCount === 0) return null;
// Most usages of the selection only want text from a part of the page (e.g. discussion)
@@ -390,10 +392,10 @@ export const insertText = (target, text) => {
this will take in the headers from an API response and normalize them
this way we don't run into production issues when nginx gives us lowercased header keys
*/
-export const normalizeHeaders = headers => {
+export const normalizeHeaders = (headers) => {
const upperCaseHeaders = {};
- Object.keys(headers || {}).forEach(e => {
+ Object.keys(headers || {}).forEach((e) => {
upperCaseHeaders[e.toUpperCase()] = headers[e];
});
@@ -406,7 +408,7 @@ export const normalizeHeaders = headers => {
* @param {Object} paginationInformation
* @returns {Object}
*/
-export const parseIntPagination = paginationInformation => ({
+export const parseIntPagination = (paginationInformation) => ({
perPage: parseInt(paginationInformation['X-PER-PAGE'], 10),
page: parseInt(paginationInformation['X-PAGE'], 10),
total: parseInt(paginationInformation['X-TOTAL'], 10),
@@ -445,10 +447,10 @@ export const parseQueryStringIntoObject = (query = '') => {
*/
export const objectToQueryString = (params = {}) =>
Object.keys(params)
- .map(param => `${param}=${params[param]}`)
+ .map((param) => `${param}=${params[param]}`)
.join('&');
-export const buildUrlWithCurrentLocation = param => {
+export const buildUrlWithCurrentLocation = (param) => {
if (param) return `${window.location.pathname}${param}`;
return window.location.pathname;
@@ -460,7 +462,7 @@ export const buildUrlWithCurrentLocation = param => {
*
* @param {String} param
*/
-export const historyPushState = newUrl => {
+export const historyPushState = (newUrl) => {
window.history.pushState({}, document.title, newUrl);
};
@@ -470,7 +472,7 @@ export const historyPushState = newUrl => {
*
* @param {String} param
*/
-export const historyReplaceState = newUrl => {
+export const historyReplaceState = (newUrl) => {
window.history.replaceState({}, document.title, newUrl);
};
@@ -482,7 +484,7 @@ export const historyReplaceState = newUrl => {
* @param {String} value
* @returns {Boolean}
*/
-export const parseBoolean = value => (value && value.toString()) === 'true';
+export const parseBoolean = (value) => (value && value.toString()) === 'true';
export const BACKOFF_TIMEOUT = 'BACKOFF_TIMEOUT';
@@ -529,7 +531,7 @@ export const backOff = (fn, timeout = 60000) => {
let timeElapsed = 0;
return new Promise((resolve, reject) => {
- const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg));
+ const stop = (arg) => (arg instanceof Error ? reject(arg) : resolve(arg));
const next = () => {
if (timeElapsed < timeout) {
@@ -545,92 +547,6 @@ export const backOff = (fn, timeout = 60000) => {
});
};
-export const createOverlayIcon = (iconPath, overlayPath) => {
- const faviconImage = document.createElement('img');
-
- return new Promise(resolve => {
- faviconImage.onload = () => {
- const size = 32;
-
- const canvas = document.createElement('canvas');
- canvas.width = size;
- canvas.height = size;
-
- const context = canvas.getContext('2d');
- context.clearRect(0, 0, size, size);
- context.drawImage(
- faviconImage,
- 0,
- 0,
- faviconImage.width,
- faviconImage.height,
- 0,
- 0,
- size,
- size,
- );
-
- const overlayImage = document.createElement('img');
- overlayImage.onload = () => {
- context.drawImage(
- overlayImage,
- 0,
- 0,
- overlayImage.width,
- overlayImage.height,
- 0,
- 0,
- size,
- size,
- );
-
- const faviconWithOverlayUrl = canvas.toDataURL();
-
- resolve(faviconWithOverlayUrl);
- };
- overlayImage.src = overlayPath;
- };
- faviconImage.src = iconPath;
- });
-};
-
-export const setFaviconOverlay = overlayPath => {
- const faviconEl = document.getElementById('favicon');
-
- if (!faviconEl) {
- return null;
- }
-
- const iconPath = faviconEl.getAttribute('data-original-href');
-
- return createOverlayIcon(iconPath, overlayPath).then(faviconWithOverlayUrl =>
- faviconEl.setAttribute('href', faviconWithOverlayUrl),
- );
-};
-
-export const resetFavicon = () => {
- const faviconEl = document.getElementById('favicon');
-
- if (faviconEl) {
- const originalFavicon = faviconEl.getAttribute('data-original-href');
- faviconEl.setAttribute('href', originalFavicon);
- }
-};
-
-export const setCiStatusFavicon = pageUrl =>
- axios
- .get(pageUrl)
- .then(({ data }) => {
- if (data && data.favicon) {
- return setFaviconOverlay(data.favicon);
- }
- return resetFavicon();
- })
- .catch(error => {
- resetFavicon();
- throw error;
- });
-
export const spriteIcon = (icon, className = '') => {
const classAttribute = className.length > 0 ? `class="${className}"` : '';
@@ -728,7 +644,7 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) =>
export const convertObjectPropsToSnakeCase = (obj = {}, options = {}) =>
convertObjectProps(convertToSnakeCase, obj, options);
-export const imagePath = imgUrl =>
+export const imagePath = (imgUrl) =>
`${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/${imgUrl}`;
export const addSelectOnFocusBehaviour = (selector = '.js-select-on-focus') => {
@@ -737,7 +653,7 @@ export const addSelectOnFocusBehaviour = (selector = '.js-select-on-focus') => {
$(selector).on('focusin', function selectOnFocusCallback() {
$(this)
.select()
- .one('mouseup', e => {
+ .one('mouseup', (e) => {
e.preventDefault();
});
});
@@ -833,7 +749,7 @@ export const searchBy = (query = '', searchSpace = {}) => {
const normalizedQuery = query.toLowerCase();
const matches = targetKeys
- .filter(item => {
+ .filter((item) => {
const searchItem = `${searchSpace[item]}`.toLowerCase();
return (
@@ -867,9 +783,9 @@ export const isScopedLabel = ({ title = '' }) => title.indexOf('::') !== -1;
// Methods to set and get Cookie
export const setCookie = (name, value) => Cookies.set(name, value, { expires: 365 });
-export const getCookie = name => Cookies.get(name);
+export const getCookie = (name) => Cookies.get(name);
-export const removeCookie = name => Cookies.remove(name);
+export const removeCookie = (name) => Cookies.remove(name);
/**
* Returns the status of a feature flag.
@@ -884,4 +800,4 @@ export const removeCookie = name => Cookies.remove(name);
* @param {String} flag Feature flag
* @returns {Boolean} on/off
*/
-export const isFeatureFlagEnabled = flag => window.gon.features?.[flag];
+export const isFeatureFlagEnabled = (flag) => window.gon.features?.[flag];
diff --git a/app/assets/javascripts/lib/utils/css_utils.js b/app/assets/javascripts/lib/utils/css_utils.js
index 02f092e73e1..76ac442a470 100644
--- a/app/assets/javascripts/lib/utils/css_utils.js
+++ b/app/assets/javascripts/lib/utils/css_utils.js
@@ -1,5 +1,5 @@
export function loadCSSFile(path) {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
if (!path) resolve();
if (document.querySelector(`link[href="${path}"]`)) {
diff --git a/app/assets/javascripts/lib/utils/datetime_range.js b/app/assets/javascripts/lib/utils/datetime_range.js
index 8efbcb89607..391b685f740 100644
--- a/app/assets/javascripts/lib/utils/datetime_range.js
+++ b/app/assets/javascripts/lib/utils/datetime_range.js
@@ -7,7 +7,7 @@ const MINIMUM_DATE = new Date(0);
const DEFAULT_DIRECTION = 'before';
-const durationToMillis = duration => {
+const durationToMillis = (duration) => {
if (Object.entries(duration).length === 1 && Number.isFinite(duration.seconds)) {
return secondsToMilliseconds(duration.seconds);
}
@@ -19,9 +19,9 @@ const dateMinusDuration = (date, duration) => new Date(date.getTime() - duration
const datePlusDuration = (date, duration) => new Date(date.getTime() + durationToMillis(duration));
-const isValidDuration = duration => Boolean(duration && Number.isFinite(duration.seconds));
+const isValidDuration = (duration) => Boolean(duration && Number.isFinite(duration.seconds));
-const isValidDateString = dateString => {
+const isValidDateString = (dateString) => {
if (typeof dateString !== 'string' || !dateString.trim()) {
return false;
}
@@ -225,7 +225,7 @@ export function getRangeType(range) {
*
* @returns {FixedRange} An object with a start and end in ISO8601 format.
*/
-export const convertToFixedRange = dateTimeRange =>
+export const convertToFixedRange = (dateTimeRange) =>
handlers[getRangeType(dateTimeRange)](dateTimeRange);
/**
@@ -242,7 +242,7 @@ export const convertToFixedRange = dateTimeRange =>
* @param {Object} timeRange - A time range object
* @returns Copy of time range
*/
-const pruneTimeRange = timeRange => {
+const pruneTimeRange = (timeRange) => {
const res = pick(timeRange, ['start', 'end', 'anchor', 'duration', 'direction']);
if (res.direction === DEFAULT_DIRECTION) {
return omit(res, 'direction');
@@ -272,7 +272,7 @@ export const isEqualTimeRanges = (timeRange, other) => {
* @param {Array} timeRanges - Array of time tanges (haystack)
*/
export const findTimeRange = (timeRange, timeRanges) =>
- timeRanges.find(element => isEqualTimeRanges(element, timeRange));
+ timeRanges.find((element) => isEqualTimeRanges(element, timeRange));
// Time Ranges as URL Parameters Utils
@@ -289,11 +289,11 @@ export const timeRangeParamNames = ['start', 'end', 'anchor', 'duration_seconds'
* @param {Object} A time range
* @returns key-value pairs object that can be used as parameters in a URL.
*/
-export const timeRangeToParams = timeRange => {
+export const timeRangeToParams = (timeRange) => {
let params = pruneTimeRange(timeRange);
if (timeRange.duration) {
const durationParms = {};
- Object.keys(timeRange.duration).forEach(key => {
+ Object.keys(timeRange.duration).forEach((key) => {
durationParms[`duration_${key}`] = timeRange.duration[key].toString();
});
params = { ...durationParms, ...params };
@@ -309,7 +309,7 @@ export const timeRangeToParams = timeRange => {
*
* @param {params} params - key-value pairs object.
*/
-export const timeRangeFromParams = params => {
+export const timeRangeFromParams = (params) => {
const timeRangeParams = pick(params, timeRangeParamNames);
let range = Object.entries(timeRangeParams).reduce((acc, [key, val]) => {
// unflatten duration
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 46b0f0cbc70..15f7c0c874e 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -4,6 +4,8 @@ import * as timeago from 'timeago.js';
import dateFormat from 'dateformat';
import { languageCode, s__, __, n__ } from '../../locale';
+const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
+
window.timeago = timeago;
/**
@@ -12,7 +14,7 @@ window.timeago = timeago;
*
* @param {Date} date
*/
-export const newDate = date => (date instanceof Date ? new Date(date.getTime()) : new Date());
+export const newDate = (date) => (date instanceof Date ? new Date(date.getTime()) : new Date());
/**
* Returns i18n month names array.
@@ -21,7 +23,7 @@ export const newDate = date => (date instanceof Date ? new Date(date.getTime())
*
* @param {Boolean} abbreviated
*/
-export const getMonthNames = abbreviated => {
+export const getMonthNames = (abbreviated) => {
if (abbreviated) {
return [
s__('Jan'),
@@ -74,7 +76,7 @@ export const getWeekdayNames = () => [
* @param {date} date
* @returns {String}
*/
-export const getDayName = date =>
+export const getDayName = (date) =>
[
__('Sunday'),
__('Monday'),
@@ -242,7 +244,7 @@ export const getDayDifference = (a, b) => {
* @param {Number} seconds
* @return {String}
*/
-export const timeIntervalInWords = intervalInSeconds => {
+export const timeIntervalInWords = (intervalInSeconds) => {
const secondsInteger = parseInt(intervalInSeconds, 10);
const minutes = Math.floor(secondsInteger / 60);
const seconds = secondsInteger - minutes * 60;
@@ -316,7 +318,7 @@ export const monthInWords = (date, abbreviated = false) => {
*
* @param {Date} date
*/
-export const totalDaysInMonth = date => {
+export const totalDaysInMonth = (date) => {
if (!date) {
return 0;
}
@@ -329,7 +331,7 @@ export const totalDaysInMonth = date => {
*
* @param {Array} quarter
*/
-export const totalDaysInQuarter = quarter =>
+export const totalDaysInQuarter = (quarter) =>
quarter.reduce((acc, month) => acc + totalDaysInMonth(month), 0);
/**
@@ -338,7 +340,7 @@ export const totalDaysInQuarter = quarter =>
*
* @param {Date} date
*/
-export const getSundays = date => {
+export const getSundays = (date) => {
if (!date) {
return [];
}
@@ -449,7 +451,7 @@ window.gl.utils = {
* @param milliseconds
* @returns {string}
*/
-export const formatTime = milliseconds => {
+export const formatTime = (milliseconds) => {
const remainingSeconds = Math.floor(milliseconds / 1000) % 60;
const remainingMinutes = Math.floor(milliseconds / 1000 / 60) % 60;
const remainingHours = Math.floor(milliseconds / 1000 / 60 / 60);
@@ -468,7 +470,7 @@ export const formatTime = milliseconds => {
* @param {String} dateString Date in yyyy-mm-dd format
* @return {Date} UTC format
*/
-export const parsePikadayDate = dateString => {
+export const parsePikadayDate = (dateString) => {
const parts = dateString.split('-');
const year = parseInt(parts[0], 10);
const month = parseInt(parts[1] - 1, 10);
@@ -482,7 +484,7 @@ export const parsePikadayDate = dateString => {
* @param {Date} date UTC format
* @return {String} Date formatted in yyyy-mm-dd
*/
-export const pikadayToString = date => {
+export const pikadayToString = (date) => {
const day = pad(date.getDate());
const month = pad(date.getMonth() + 1);
const year = date.getFullYear();
@@ -523,7 +525,7 @@ export const parseSeconds = (
let unorderedMinutes = Math.abs(seconds / SECONDS_PER_MINUTE);
- return mapValues(timePeriodConstraints, minutesPerPeriod => {
+ return mapValues(timePeriodConstraints, (minutesPerPeriod) => {
if (minutesPerPeriod === 0) {
return 0;
}
@@ -567,7 +569,7 @@ export const stringifyTime = (timeObject, fullNameFormat = false) => {
* @param endDate date string that the time difference is calculated for
* @return {Number} number of milliseconds remaining until the given date
*/
-export const calculateRemainingMilliseconds = endDate => {
+export const calculateRemainingMilliseconds = (endDate) => {
const remainingMilliseconds = new Date(endDate).getTime() - Date.now();
return Math.max(remainingMilliseconds, 0);
};
@@ -598,7 +600,7 @@ export const getDateInFuture = (date, daysInFuture) =>
* @param {Date} date
* @returns boolean
*/
-export const isValidDate = date => date instanceof Date && !Number.isNaN(date.getTime());
+export const isValidDate = (date) => date instanceof Date && !Number.isNaN(date.getTime());
/*
* Appending T00:00:00 makes JS assume local time and prevents it from shifting the date
@@ -606,7 +608,7 @@ export const isValidDate = date => date instanceof Date && !Number.isNaN(date.ge
* be consistent with the "edit issue -> due date" UI.
*/
-export const newDateAsLocaleTime = date => {
+export const newDateAsLocaleTime = (date) => {
const suffix = 'T00:00:00';
return new Date(`${date}${suffix}`);
};
@@ -620,7 +622,7 @@ export const endOfDayTime = 'T23:59:59Z';
* @param {Function} formatter
* @return {Any[]} an array of formatted dates between 2 given dates (including start&end date)
*/
-export const getDatesInRange = (d1, d2, formatter = x => x) => {
+export const getDatesInRange = (d1, d2, formatter = (x) => x) => {
if (!(d1 instanceof Date) || !(d2 instanceof Date)) {
return [];
}
@@ -643,7 +645,7 @@ export const getDatesInRange = (d1, d2, formatter = x => x) => {
* @param {Number} seconds
* @return {Number} number of milliseconds
*/
-export const secondsToMilliseconds = seconds => seconds * 1000;
+export const secondsToMilliseconds = (seconds) => seconds * 1000;
/**
* Converts the supplied number of seconds to days.
@@ -651,7 +653,7 @@ export const secondsToMilliseconds = seconds => seconds * 1000;
* @param {Number} seconds
* @return {Number} number of days
*/
-export const secondsToDays = seconds => Math.round(seconds / 86400);
+export const secondsToDays = (seconds) => Math.round(seconds / 86400);
/**
* Converts a numeric utc offset in seconds to +/- hours
@@ -662,7 +664,7 @@ export const secondsToDays = seconds => Math.round(seconds / 86400);
*
* @return {String} the + or - offset in hours
*/
-export const secondsToHours = offset => {
+export const secondsToHours = (offset) => {
const parsed = parseInt(offset, 10);
if (Number.isNaN(parsed) || parsed === 0) {
return `0`;
@@ -682,12 +684,40 @@ export const nDaysAfter = (date, numberOfDays) =>
new Date(newDate(date)).setDate(date.getDate() + numberOfDays);
/**
+ * 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
+ */
+export const nDaysBefore = (date, numberOfDays) => nDaysAfter(date, -numberOfDays);
+
+/**
+ * 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
+ */
+export const nMonthsAfter = (date, numberOfMonths) =>
+ new Date(newDate(date)).setMonth(date.getMonth() + numberOfMonths);
+
+/**
+ * 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
+ */
+export const nMonthsBefore = (date, numberOfMonths) => nMonthsAfter(date, -numberOfMonths);
+
+/**
* Returns the date after the date provided
*
* @param {Date} date the initial date
* @return {Date} the date following the date provided
*/
-export const dayAfter = date => new Date(newDate(date).setDate(date.getDate() + 1));
+export const dayAfter = (date) => new Date(newDate(date).setDate(date.getDate() + 1));
/**
* Mimics the behaviour of the rails distance_of_time_in_words function
@@ -795,7 +825,7 @@ export const differenceInMilliseconds = (startDate, endDate = Date.now()) => {
*
* @return {Date} the date at the first day of the month
*/
-export const dateAtFirstDayOfMonth = date => new Date(newDate(date).setDate(1));
+export const dateAtFirstDayOfMonth = (date) => new Date(newDate(date).setDate(1));
/**
* A utility function which checks if two dates match.
@@ -806,3 +836,62 @@ export const dateAtFirstDayOfMonth = date => new Date(newDate(date).setDate(1));
* @return {Boolean} true if the dates match
*/
export const datesMatch = (date1, date2) => differenceInMilliseconds(date1, date2) === 0;
+
+/**
+ * A utility function which computes a formatted 24 hour
+ * time string from a positive int in the range 0 - 24.
+ *
+ * @param {Int} time a positive Int between 0 and 24
+ *
+ * @returns {String} formatted 24 hour time String
+ */
+export const format24HourTimeStringFromInt = (time) => {
+ if (!Number.isInteger(time) || time < 0 || time > 24) {
+ return '';
+ }
+
+ const formatted24HourString = time > 9 ? `${time}:00` : `0${time}:00`;
+ return formatted24HourString;
+};
+
+/**
+ * A utility function which checks if two date ranges overlap.
+ *
+ * @param {Object} givenPeriodLeft - the first period to compare.
+ * @param {Object} givenPeriodRight - the second period to compare.
+ * @returns {Object} { overlap: number of days the overlap is present, overlapStartDate: the start date of the overlap in time format, overlapEndDate: the end date of the overlap in time format }
+ * @throws {Error} Uncaught Error: Invalid period
+ *
+ * @example
+ * getOverlappingDaysInPeriods(
+ * { start: new Date(2021, 0, 11), end: new Date(2021, 0, 13) },
+ * { start: new Date(2021, 0, 11), end: new Date(2021, 0, 14) }
+ * ) => { daysOverlap: 2, overlapStartDate: 1610323200000, overlapEndDate: 1610496000000 }
+ *
+ */
+export const getOverlappingDaysInPeriods = (givenPeriodLeft = {}, givenPeriodRight = {}) => {
+ const leftStartTime = new Date(givenPeriodLeft.start).getTime();
+ const leftEndTime = new Date(givenPeriodLeft.end).getTime();
+ const rightStartTime = new Date(givenPeriodRight.start).getTime();
+ const rightEndTime = new Date(givenPeriodRight.end).getTime();
+
+ if (!(leftStartTime <= leftEndTime && rightStartTime <= rightEndTime)) {
+ throw new Error(__('Invalid period'));
+ }
+
+ const isOverlapping = leftStartTime < rightEndTime && rightStartTime < leftEndTime;
+
+ if (!isOverlapping) {
+ return { daysOverlap: 0 };
+ }
+
+ const overlapStartDate = Math.max(leftStartTime, rightStartTime);
+ const overlapEndDate = rightEndTime > leftEndTime ? leftEndTime : rightEndTime;
+ const differenceInMs = overlapEndDate - overlapStartDate;
+
+ return {
+ daysOverlap: Math.ceil(differenceInMs / MILLISECONDS_IN_DAY),
+ overlapStartDate,
+ overlapEndDate,
+ };
+};
diff --git a/app/assets/javascripts/lib/utils/dom_utils.js b/app/assets/javascripts/lib/utils/dom_utils.js
index 2f19a0c9b26..f11c7658a88 100644
--- a/app/assets/javascripts/lib/utils/dom_utils.js
+++ b/app/assets/javascripts/lib/utils/dom_utils.js
@@ -6,7 +6,7 @@ import { isInIssuePage, isInMRPage, isInEpicPage } from './common_utils';
*
* @param element DOM element to check
*/
-export const hasHorizontalOverflow = element =>
+export const hasHorizontalOverflow = (element) =>
Boolean(element && element.scrollWidth > element.offsetWidth);
export const addClassIfElementExists = (element, className) => {
@@ -64,7 +64,7 @@ export const parseBooleanDataAttributes = ({ dataset }, names) =>
* @param {HTMLElement} element The element to test
* @returns {Boolean} `true` if the element is currently visible, otherwise false
*/
-export const isElementVisible = element =>
+export const isElementVisible = (element) =>
Boolean(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
/**
@@ -76,4 +76,4 @@ export const isElementVisible = element =>
* @param {HTMLElement} element The element to test
* @returns {Boolean} `true` if the element is currently hidden, otherwise false
*/
-export const isElementHidden = element => !isElementVisible(element);
+export const isElementHidden = (element) => !isElementVisible(element);
diff --git a/app/assets/javascripts/lib/utils/favicon.js b/app/assets/javascripts/lib/utils/favicon.js
new file mode 100644
index 00000000000..47596a76306
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/favicon.js
@@ -0,0 +1,30 @@
+import { FaviconOverlayManager } from '@gitlab/favicon-overlay';
+import { memoize } from 'lodash';
+
+// FaviconOverlayManager is a glorious singleton/static class. Let's start to encapsulate that with this helper.
+const getDefaultFaviconManager = memoize(async () => {
+ await FaviconOverlayManager.initialize({ faviconSelector: '#favicon' });
+
+ return FaviconOverlayManager;
+});
+
+export const setFaviconOverlay = async (path) => {
+ const manager = await getDefaultFaviconManager();
+
+ manager.setFaviconOverlay(path);
+};
+
+export const resetFavicon = async () => {
+ const manager = await getDefaultFaviconManager();
+
+ manager.resetFaviconOverlay();
+};
+
+/**
+ * Clears the cached memoization of the default manager.
+ *
+ * This is needed for determinism in tests.
+ */
+export const clearMemoizeCache = () => {
+ getDefaultFaviconManager.cache.clear();
+};
diff --git a/app/assets/javascripts/lib/utils/favicon_ci.js b/app/assets/javascripts/lib/utils/favicon_ci.js
new file mode 100644
index 00000000000..613e2620e02
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/favicon_ci.js
@@ -0,0 +1,16 @@
+import axios from './axios_utils';
+import { setFaviconOverlay, resetFavicon } from './favicon';
+
+export const setCiStatusFavicon = (pageUrl) =>
+ axios
+ .get(pageUrl)
+ .then(({ data }) => {
+ if (data && data.favicon) {
+ return setFaviconOverlay(data.favicon);
+ }
+ return resetFavicon();
+ })
+ .catch((error) => {
+ resetFavicon();
+ throw error;
+ });
diff --git a/app/assets/javascripts/lib/utils/forms.js b/app/assets/javascripts/lib/utils/forms.js
index 1c5f6cefeda..52e1323412d 100644
--- a/app/assets/javascripts/lib/utils/forms.js
+++ b/app/assets/javascripts/lib/utils/forms.js
@@ -1,14 +1,14 @@
-export const serializeFormEntries = entries =>
+export const serializeFormEntries = (entries) =>
entries.reduce((acc, { name, value }) => Object.assign(acc, { [name]: value }), {});
-export const serializeForm = form => {
+export const serializeForm = (form) => {
const fdata = new FormData(form);
- const entries = Array.from(fdata.keys()).map(key => {
+ const entries = Array.from(fdata.keys()).map((key) => {
let val = fdata.getAll(key);
// Microsoft Edge has a bug in FormData.getAll() that returns an undefined
// value for each form element that does not match the given key:
// https://github.com/jimmywarting/FormData/issues/80
- val = val.filter(n => n);
+ val = val.filter((n) => n);
return { name: key, value: val.length === 1 ? val[0] : val };
});
@@ -27,7 +27,7 @@ export const serializeForm = form => {
* @example
* returns true for '', [], null, undefined
*/
-export const isEmptyValue = value => value == null || value.length === 0;
+export const isEmptyValue = (value) => value == null || value.length === 0;
/**
* A form object serializer
@@ -42,7 +42,7 @@ export const isEmptyValue = value => value == null || value.length === 0;
* Returns
* {"project": "hello", "username": "john"}
*/
-export const serializeFormObject = form =>
+export const serializeFormObject = (form) =>
Object.fromEntries(
Object.entries(form).reduce((acc, [name, { value }]) => {
if (!isEmptyValue(value)) {
diff --git a/app/assets/javascripts/lib/utils/grammar.js b/app/assets/javascripts/lib/utils/grammar.js
index b1f38429369..6d6361d19b6 100644
--- a/app/assets/javascripts/lib/utils/grammar.js
+++ b/app/assets/javascripts/lib/utils/grammar.js
@@ -16,12 +16,12 @@ import { sprintf, s__ } from '~/locale';
*
* @param {String[]} items
*/
-export const toNounSeriesText = items => {
+export const toNounSeriesText = (items, { onlyCommas = false } = {}) => {
if (items.length === 0) {
return '';
} else if (items.length === 1) {
return sprintf(s__(`nounSeries|%{item}`), { item: items[0] }, false);
- } else if (items.length === 2) {
+ } else if (items.length === 2 && !onlyCommas) {
return sprintf(
s__('nounSeries|%{firstItem} and %{lastItem}'),
{
@@ -33,7 +33,7 @@ export const toNounSeriesText = items => {
}
return items.reduce((item, nextItem, idx) =>
- idx === items.length - 1
+ idx === items.length - 1 && !onlyCommas
? sprintf(s__('nounSeries|%{item}, and %{lastItem}'), { item, lastItem: nextItem }, false)
: sprintf(s__('nounSeries|%{item}, %{nextItem}'), { item, nextItem }, false),
);
diff --git a/app/assets/javascripts/lib/utils/headers.js b/app/assets/javascripts/lib/utils/headers.js
new file mode 100644
index 00000000000..80ae3fb146f
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/headers.js
@@ -0,0 +1,3 @@
+export const ContentTypeMultipartFormData = {
+ 'Content-Type': 'multipart/form-data',
+};
diff --git a/app/assets/javascripts/lib/utils/icon_utils.js b/app/assets/javascripts/lib/utils/icon_utils.js
index 043043f2eb5..58274092cf8 100644
--- a/app/assets/javascripts/lib/utils/icon_utils.js
+++ b/app/assets/javascripts/lib/utils/icon_utils.js
@@ -9,7 +9,7 @@ const getSvgDom = memoize(() =>
axios
.get(gon.sprite_icons)
.then(({ data: svgs }) => new DOMParser().parseFromString(svgs, 'text/xml'))
- .catch(e => {
+ .catch((e) => {
getSvgDom.cache.clear();
throw e;
@@ -34,9 +34,9 @@ export const clearSvgIconPathContentCache = () => {
* @param {String} name - Icon name
* @returns A promise that resolves to the svg path
*/
-export const getSvgIconPathContent = name =>
+export const getSvgIconPathContent = (name) =>
getSvgDom()
- .then(doc => {
+ .then((doc) => {
return doc.querySelector(`#${name} path`).getAttribute('d');
})
.catch(() => null);
diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js
index aa7884846a3..2e92c64ab7a 100644
--- a/app/assets/javascripts/lib/utils/notify.js
+++ b/app/assets/javascripts/lib/utils/notify.js
@@ -32,7 +32,7 @@ function notifyMe(message, body, icon, onclick) {
// If it's okay let's create a notification
return notificationGranted(message, opts, onclick);
} else if (Notification.permission !== 'denied') {
- return Notification.requestPermission(permission => {
+ return Notification.requestPermission((permission) => {
// If the user accepts, let's create a notification
if (permission === 'granted') {
return notificationGranted(message, opts, onclick);
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index bc87232f40b..d49382733c0 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -112,7 +112,7 @@ export const isOdd = (number = 0) => number % 2;
* @param {Array} arr An array of numbers
* @returns {Number} The median of the given array
*/
-export const median = arr => {
+export const median = (arr) => {
const middle = Math.floor(arr.length / 2);
const sorted = arr.sort((a, b) => a - b);
return arr.length % 2 !== 0 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index e8583fa951b..6ec1bd206e6 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -102,11 +102,11 @@ export default class Poll {
notificationCallback(true);
return resource[method](data)
- .then(response => {
+ .then((response) => {
this.checkConditions(response);
notificationCallback(false);
})
- .catch(error => {
+ .catch((error) => {
notificationCallback(false);
if (error.status === httpStatusCodes.ABORTED) {
return;
diff --git a/app/assets/javascripts/lib/utils/poll_until_complete.js b/app/assets/javascripts/lib/utils/poll_until_complete.js
index 199d0e6f0f7..d3b551ca755 100644
--- a/app/assets/javascripts/lib/utils/poll_until_complete.js
+++ b/app/assets/javascripts/lib/utils/poll_until_complete.js
@@ -29,7 +29,7 @@ export default (url, config = {}) =>
},
data: { url, config },
method: 'axiosGet',
- successCallback: response => {
+ successCallback: (response) => {
if (response.status === httpStatusCodes.OK) {
resolve(response);
eTagPoll.stop();
diff --git a/app/assets/javascripts/lib/utils/set.js b/app/assets/javascripts/lib/utils/set.js
index 541934c4221..a5393bad8c7 100644
--- a/app/assets/javascripts/lib/utils/set.js
+++ b/app/assets/javascripts/lib/utils/set.js
@@ -5,4 +5,4 @@
* @returns {boolean}
*/
export const isSubset = (subset, superset) =>
- Array.from(subset).every(value => superset.has(value));
+ Array.from(subset).every((value) => superset.has(value));
diff --git a/app/assets/javascripts/lib/utils/simple_poll.js b/app/assets/javascripts/lib/utils/simple_poll.js
index e4e9fb2e6fa..42eb93ea16d 100644
--- a/app/assets/javascripts/lib/utils/simple_poll.js
+++ b/app/assets/javascripts/lib/utils/simple_poll.js
@@ -4,7 +4,7 @@ export default (fn, { interval = 2000, timeout = 60000 } = {}) => {
const startTime = Date.now();
return new Promise((resolve, reject) => {
- const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg));
+ const stop = (arg) => (arg instanceof Error ? reject(arg) : resolve(arg));
const next = () => {
if (timeout === 0 || differenceInMilliseconds(startTime) < timeout) {
setTimeout(fn.bind(null, next, stop), interval);
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index f3244301350..6bb7f09b886 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -67,6 +67,6 @@ export const stickyMonitor = (el, stickyTop, insertPlaceholder = true) => {
* - 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 => {
+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 c711c0bd163..2c993c8b128 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -14,18 +14,12 @@ function addBlockTags(blockTag, selected) {
}
function lineBefore(text, textarea) {
- const split = text
- .substring(0, textarea.selectionStart)
- .trim()
- .split('\n');
+ const split = text.substring(0, textarea.selectionStart).trim().split('\n');
return split[split.length - 1];
}
function lineAfter(text, textarea) {
- return text
- .substring(textarea.selectionEnd)
- .trim()
- .split('\n')[0];
+ return text.substring(textarea.selectionEnd).trim().split('\n')[0];
}
function convertMonacoSelectionToAceFormat(sel) {
@@ -226,7 +220,7 @@ export function insertMarkdownText({
: blockTagText(text, textArea, blockTag, selected);
} else {
textToInsert = selectedSplit
- .map(val => {
+ .map((val) => {
if (tag.indexOf(textPlaceholder) > -1) {
return tag.replace(textPlaceholder, val);
}
@@ -342,7 +336,7 @@ export function addMarkdownListeners(form) {
// eslint-disable-next-line @gitlab/no-global-event-off
const $allToolbarBtns = $('.js-md', form)
.off('click')
- .on('click', function() {
+ .on('click', function () {
const $toolbarBtn = $(this);
return updateTextForToolbarBtn($toolbarBtn);
@@ -355,7 +349,7 @@ export function addEditorMarkdownListeners(editor) {
// eslint-disable-next-line @gitlab/no-global-event-off
$('.js-md')
.off('click')
- .on('click', e => {
+ .on('click', (e) => {
const { mdTag, mdBlock, mdPrepend, mdSelect } = $(e.currentTarget).data();
insertMarkdownText({
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index c398874db24..eaf396a7a59 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -14,7 +14,7 @@ import {
* @param {String} text
* @returns {String}
*/
-export const addDelimiter = text =>
+export const addDelimiter = (text) =>
text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text;
/**
@@ -23,7 +23,7 @@ export const addDelimiter = text =>
* @param {Number} count
* @return {Number|String}
*/
-export const highCountTrim = count => (count > 99 ? '99+' : count);
+export const highCountTrim = (count) => (count > 99 ? '99+' : count);
/**
* Converts first char to uppercase and replaces the given separator with spaces
@@ -43,7 +43,7 @@ export const humanize = (string, separator = '_') => {
* @param {*} str
* @returns {String}
*/
-export const dasherize = str => str.replace(/[_\s]+/g, '-');
+export const dasherize = (str) => str.replace(/[_\s]+/g, '-');
/**
* Replaces whitespace and non-sluggish characters with a given separator
@@ -69,7 +69,7 @@ export const slugify = (str, separator = '-') => {
* @param {String} str
* @returns {String}
*/
-export const slugifyWithUnderscore = str => slugify(str, '_');
+export const slugifyWithUnderscore = (str) => slugify(str, '_');
/**
* Truncates given text
@@ -158,7 +158,7 @@ export const truncateWidth = (string, options = {}) => {
* @param {String} sha
* @returns {String}
*/
-export const truncateSha = sha => sha.substring(0, 8);
+export const truncateSha = (sha) => sha.substring(0, 8);
const ELLIPSIS_CHAR = '…';
export const truncatePathMiddleToLength = (text, maxWidth) => {
@@ -166,7 +166,7 @@ export const truncatePathMiddleToLength = (text, maxWidth) => {
let ellipsisCount = 0;
while (returnText.length >= maxWidth) {
- const textSplit = returnText.split('/').filter(s => s !== ELLIPSIS_CHAR);
+ const textSplit = returnText.split('/').filter((s) => s !== ELLIPSIS_CHAR);
if (textSplit.length === 0) {
// There are n - 1 path separators for n segments, so 2n - 1 <= maxWidth
@@ -243,7 +243,7 @@ export const stripHtml = (string, replace = '') => {
* // returns "trailingUnderscore_"
* convertToCamelCase('trailing_underscore_')
*/
-export const convertToCamelCase = string =>
+export const convertToCamelCase = (string) =>
string.replace(/([a-z0-9])_([a-z0-9])/gi, (match, p1, p2) => `${p1}${p2.toUpperCase()}`);
/**
@@ -251,7 +251,7 @@ export const convertToCamelCase = string =>
*
* @param {*} string
*/
-export const convertToSnakeCase = string =>
+export const convertToSnakeCase = (string) =>
slugifyWithUnderscore((string.match(/([a-zA-Z][^A-Z]*)/g) || [string]).join(' '));
/**
@@ -260,7 +260,7 @@ export const convertToSnakeCase = string =>
*
* @param {*} string
*/
-export const convertToSentenceCase = string => {
+export const convertToSentenceCase = (string) => {
const splitWord = string.split(' ').map((word, index) => (index > 0 ? word.toLowerCase() : word));
return splitWord.join(' ');
@@ -273,7 +273,7 @@ export const convertToSentenceCase = string => {
* @param {String} string
* @returns {String}
*/
-export const convertToTitleCase = string => string.replace(/\b[a-z]/g, s => s.toUpperCase());
+export const convertToTitleCase = (string) => string.replace(/\b[a-z]/g, (s) => s.toUpperCase());
const unicodeConversion = [
[/[ÀÃÂÃÅĀĂĄ]/g, 'A'],
@@ -340,7 +340,7 @@ const unicodeConversion = [
* @param {String} string
* @returns {String}
*/
-export const convertUnicodeToAscii = string => {
+export const convertUnicodeToAscii = (string) => {
let convertedString = string;
unicodeConversion.forEach(([regex, replacer]) => {
@@ -356,7 +356,7 @@ export const convertUnicodeToAscii = string => {
*
* @param {*} string
*/
-export const splitCamelCase = string =>
+export const splitCamelCase = (string) =>
string
.replace(/([A-Z]+)([A-Z][a-z])/g, ' $1 $2')
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
@@ -398,7 +398,7 @@ export const truncateNamespace = (string = '') => {
* @param {String} obj The object to test
* @returns {Boolean}
*/
-export const hasContent = obj => isString(obj) && obj.trim() !== '';
+export const hasContent = (obj) => isString(obj) && obj.trim() !== '';
/**
* A utility function that validates if a
@@ -408,7 +408,7 @@ export const hasContent = obj => isString(obj) && obj.trim() !== '';
*
* @return {Boolean} true if valid
*/
-export const isValidSha1Hash = str => {
+export const isValidSha1Hash = (str) => {
return /^[0-9a-f]{5,40}$/.test(str);
};
diff --git a/app/assets/javascripts/lib/utils/type_utility.js b/app/assets/javascripts/lib/utils/type_utility.js
index 664c0dbbc84..be1911f7c34 100644
--- a/app/assets/javascripts/lib/utils/type_utility.js
+++ b/app/assets/javascripts/lib/utils/type_utility.js
@@ -1 +1 @@
-export const isObject = obj => obj && obj.constructor === Object;
+export const isObject = (obj) => obj && obj.constructor === Object;
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 5d3dd79850e..9d47a1b7132 100644
--- a/app/assets/javascripts/lib/utils/unit_format/formatter_factory.js
+++ b/app/assets/javascripts/lib/utils/unit_format/formatter_factory.js
@@ -106,7 +106,7 @@ export const scaledSIFormatter = (unit = '', prefixOffset = 0) => {
const multiplicative = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
const symbols = [...fractional, '', ...multiplicative];
- const units = symbols.slice(fractional.length + prefixOffset).map(prefix => {
+ const units = symbols.slice(fractional.length + prefixOffset).map((prefix) => {
return `${prefix}${unit}`;
});
@@ -126,7 +126,7 @@ export const scaledBinaryFormatter = (unit = '', prefixOffset = 0) => {
const multiplicative = ['Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'];
const symbols = ['', ...multiplicative];
- const units = symbols.slice(prefixOffset).map(prefix => {
+ const units = symbols.slice(prefixOffset).map((prefix) => {
return `${prefix}${unit}`;
});
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index a9f6901de32..44d3e78b334 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -112,13 +112,13 @@ export function mergeUrlParams(params, url, options = {}) {
const mergedKeys = sort ? Object.keys(merged).sort() : Object.keys(merged);
const newQuery = mergedKeys
- .filter(key => merged[key] !== null)
- .map(key => {
+ .filter((key) => merged[key] !== null)
+ .map((key) => {
let value = merged[key];
const encodedKey = encodeURIComponent(key);
if (spreadArrays && Array.isArray(value)) {
value = merged[key]
- .map(arrayValue => encodeURIComponent(arrayValue))
+ .map((arrayValue) => encodeURIComponent(arrayValue))
.join(`&${encodedKey}[]=`);
return `${encodedKey}[]=${value}`;
}
@@ -150,11 +150,11 @@ export function removeParams(params, url = window.location.href, skipEncoding =
return url;
}
- const removableParams = skipEncoding ? params : params.map(param => encodeURIComponent(param));
+ const removableParams = skipEncoding ? params : params.map((param) => encodeURIComponent(param));
const updatedQuery = query
.split('&')
- .filter(paramPair => {
+ .filter((paramPair) => {
const [foundParam] = paramPair.split('=');
return removableParams.indexOf(foundParam) < 0;
})
@@ -237,7 +237,7 @@ export function redirectTo(url) {
return window.location.assign(url);
}
-export const escapeFileUrl = fileUrl => encodeURIComponent(fileUrl).replace(/%2F/g, '/');
+export const escapeFileUrl = (fileUrl) => encodeURIComponent(fileUrl).replace(/%2F/g, '/');
export function webIDEUrl(route = undefined) {
let returnUrl = `${gon.relative_url_root || ''}/-/ide/`;
@@ -396,7 +396,7 @@ export function queryToObject(query, options = {}) {
*/
export function objectToQuery(obj) {
return Object.keys(obj)
- .map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`)
+ .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`)
.join('&');
}
@@ -420,7 +420,7 @@ export const setUrlParams = (
const queryString = urlObj.search;
const searchParams = clearParams ? new URLSearchParams('') : new URLSearchParams(queryString);
- Object.keys(params).forEach(key => {
+ Object.keys(params).forEach((key) => {
if (params[key] === null || params[key] === undefined) {
searchParams.delete(key);
} else if (Array.isArray(params[key])) {
diff --git a/app/assets/javascripts/lib/utils/users_cache.js b/app/assets/javascripts/lib/utils/users_cache.js
index 9f980fd4899..54f69ef8e1b 100644
--- a/app/assets/javascripts/lib/utils/users_cache.js
+++ b/app/assets/javascripts/lib/utils/users_cache.js
@@ -1,4 +1,4 @@
-import Api from '../../api';
+import { getUsers, getUser, getUserStatus } from '~/rest_api';
import Cache from './cache';
class UsersCache extends Cache {
@@ -7,7 +7,7 @@ class UsersCache extends Cache {
return Promise.resolve(this.get(username));
}
- return Api.users('', { username }).then(({ data }) => {
+ return getUsers('', { username }).then(({ data }) => {
if (!data.length) {
throw new Error(`User "${username}" could not be found!`);
}
@@ -28,7 +28,7 @@ class UsersCache extends Cache {
return Promise.resolve(this.get(userId));
}
- return Api.user(userId).then(({ data }) => {
+ return getUser(userId).then(({ data }) => {
this.internalStorage[userId] = data;
return data;
});
@@ -40,7 +40,7 @@ class UsersCache extends Cache {
return Promise.resolve(this.get(userId).status);
}
- return Api.userStatus(userId).then(({ data }) => {
+ return getUserStatus(userId).then(({ data }) => {
if (!this.hasData(userId)) {
this.internalStorage[userId] = {};
}
diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js
index 8621a133776..aaa8ee40966 100644
--- a/app/assets/javascripts/line_highlighter.js
+++ b/app/assets/javascripts/line_highlighter.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names, no-underscore-dangle, no-param-reassign, consistent-return */
import $ from 'jquery';
-import 'vendor/jquery.scrollTo';
+import { scrollToElement } from '~/lib/utils/common_utils';
// LineHighlighter
//
@@ -32,7 +32,7 @@ import 'vendor/jquery.scrollTo';
// </div>
//
-const LineHighlighter = function(options = {}) {
+const LineHighlighter = function (options = {}) {
options.highlightLineClass = options.highlightLineClass || 'hll';
options.fileHolderSelector = options.fileHolderSelector || '.file-holder';
options.scrollFileHolder = options.scrollFileHolder || false;
@@ -50,15 +50,15 @@ const LineHighlighter = function(options = {}) {
this.highlightHash();
};
-LineHighlighter.prototype.bindEvents = function() {
+LineHighlighter.prototype.bindEvents = function () {
const $fileHolder = $(this.options.fileHolderSelector);
$fileHolder.on('click', 'a[data-line-number]', this.clickHandler);
$fileHolder.on('highlight:line', this.highlightHash);
- window.addEventListener('hashchange', e => this.highlightHash(e.target.location.hash));
+ window.addEventListener('hashchange', (e) => this.highlightHash(e.target.location.hash));
};
-LineHighlighter.prototype.highlightHash = function(newHash) {
+LineHighlighter.prototype.highlightHash = function (newHash) {
let range;
if (newHash && typeof newHash === 'string') this._hash = newHash;
@@ -69,27 +69,21 @@ LineHighlighter.prototype.highlightHash = function(newHash) {
if (range[0]) {
this.highlightRange(range);
const lineSelector = `#L${range[0]}`;
- const scrollOptions = {
+
+ scrollToElement(lineSelector, {
// Scroll to the first highlighted line on initial load
- // Offset -50 for the sticky top bar, and another -100 for some context
- offset: -150,
- };
- if (this.options.scrollFileHolder) {
- $(this.options.fileHolderSelector).scrollTo(lineSelector, scrollOptions);
- } else {
- $.scrollTo(lineSelector, scrollOptions);
- }
+ // Add an offset of -100 for some context
+ offset: -100,
+ });
}
}
};
-LineHighlighter.prototype.clickHandler = function(event) {
+LineHighlighter.prototype.clickHandler = function (event) {
let range;
event.preventDefault();
this.clearHighlight();
- const lineNumber = $(event.target)
- .closest('a')
- .data('lineNumber');
+ const lineNumber = $(event.target).closest('a').data('lineNumber');
const current = this.hashToRange(this._hash);
if (!(current[0] && event.shiftKey)) {
// If there's no current selection, or there is but Shift wasn't held,
@@ -107,7 +101,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
}
};
-LineHighlighter.prototype.clearHighlight = function() {
+LineHighlighter.prototype.clearHighlight = function () {
return $(`.${this.highlightLineClass}`).removeClass(this.highlightLineClass);
};
@@ -122,7 +116,7 @@ LineHighlighter.prototype.clearHighlight = function() {
// hashToRange('#foo') # => [null, null]
//
// Returns an Array
-LineHighlighter.prototype.hashToRange = function(hash) {
+LineHighlighter.prototype.hashToRange = function (hash) {
// ?L(\d+)(?:-(\d+))?$/)
const matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/);
if (matches && matches.length) {
@@ -136,14 +130,14 @@ LineHighlighter.prototype.hashToRange = function(hash) {
// Highlight a single line
//
// lineNumber - Line number to highlight
-LineHighlighter.prototype.highlightLine = function(lineNumber) {
+LineHighlighter.prototype.highlightLine = function (lineNumber) {
return $(`#LC${lineNumber}`).addClass(this.highlightLineClass);
};
// Highlight all lines within a range
//
// range - Array containing the starting and ending line numbers
-LineHighlighter.prototype.highlightRange = function(range) {
+LineHighlighter.prototype.highlightRange = function (range) {
if (range[1]) {
const results = [];
const ref = range[0] <= range[1] ? range : range.reverse();
@@ -158,7 +152,7 @@ LineHighlighter.prototype.highlightRange = function(range) {
};
// Set the URL hash string
-LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
+LineHighlighter.prototype.setHash = function (firstLineNumber, lastLineNumber) {
let hash;
if (lastLineNumber) {
hash = `#L${firstLineNumber}-${lastLineNumber}`;
@@ -172,7 +166,7 @@ LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
// Make the actual hash change in the browser
//
// This method is stubbed in tests.
-LineHighlighter.prototype.__setLocationHash__ = function(value) {
+LineHighlighter.prototype.__setLocationHash__ = function (value) {
return window.history.pushState(
{
url: value,
diff --git a/app/assets/javascripts/locale/ensure_single_line.js b/app/assets/javascripts/locale/ensure_single_line.js
index 47c52fe6c50..c2c63777001 100644
--- a/app/assets/javascripts/locale/ensure_single_line.js
+++ b/app/assets/javascripts/locale/ensure_single_line.js
@@ -18,7 +18,7 @@ module.exports = function ensureSingleLine(str) {
if (str.includes('\n') || str.includes('\r')) {
return str
.split(SPLIT_REGEX)
- .filter(s => s !== '')
+ .filter((s) => s !== '')
.join(' ');
}
return str;
diff --git a/app/assets/javascripts/locale/index.js b/app/assets/javascripts/locale/index.js
index 41aa0f4ddb9..35087b920c7 100644
--- a/app/assets/javascripts/locale/index.js
+++ b/app/assets/javascripts/locale/index.js
@@ -11,7 +11,7 @@ delete window.translations;
@param text The text to be translated
@returns {String} The translated text
*/
-const gettext = text => locale.gettext(ensureSingleLine(text));
+const gettext = (text) => locale.gettext(ensureSingleLine(text));
/**
Translate the text with a number
@@ -56,7 +56,7 @@ const pgettext = (keyOrContext, key) => {
@param formatOptions for available options, please see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
@returns {Intl.DateTimeFormat}
*/
-const createDateTimeFormat = formatOptions => Intl.DateTimeFormat(languageCode(), formatOptions);
+const createDateTimeFormat = (formatOptions) => Intl.DateTimeFormat(languageCode(), formatOptions);
export { languageCode };
export { gettext as __ };
diff --git a/app/assets/javascripts/locale/sprintf.js b/app/assets/javascripts/locale/sprintf.js
index b4658a159d7..82fc816fe9e 100644
--- a/app/assets/javascripts/locale/sprintf.js
+++ b/app/assets/javascripts/locale/sprintf.js
@@ -15,7 +15,7 @@ export default (input, parameters, escapeParameters = true) => {
let output = input;
if (parameters) {
- Object.keys(parameters).forEach(parameterName => {
+ Object.keys(parameters).forEach((parameterName) => {
const parameterValue = parameters[parameterName];
const escapedParameterValue = escapeParameters ? escape(parameterValue) : parameterValue;
output = output.replace(new RegExp(`%{${parameterName}}`, 'g'), escapedParameterValue);
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index f7c0bd5ae13..a114b3c7d4d 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -246,9 +246,7 @@ export default {
</div>{{trace}}
</code></pre>
</template>
- <template #default
- ><div></div
- ></template>
+ <template #default><div></div></template>
</gl-infinite-scroll>
<div ref="logFooter" class="py-2 px-3 text-white bg-secondary-900">
@@ -262,9 +260,7 @@ export default {
>
<template #fetched>{{ logs.lines.length }}</template>
</gl-sprintf>
- <template v-else>
- {{ s__('Environments|Currently showing all results.') }}</template
- >
+ <template v-else> {{ s__('Environments|Currently showing all results.') }}</template>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/logs/components/log_advanced_filters.vue b/app/assets/javascripts/logs/components/log_advanced_filters.vue
index 49bb80b3bfd..37fc4dc3735 100644
--- a/app/assets/javascripts/logs/components/log_advanced_filters.vue
+++ b/app/assets/javascripts/logs/components/log_advanced_filters.vue
@@ -42,7 +42,7 @@ export default {
*/
podOptions() {
if (this.pods.options.length) {
- return this.pods.options.map(podName => ({ value: podName, title: podName }));
+ return this.pods.options.map((podName) => ({ value: podName, title: podName }));
}
return null;
},
diff --git a/app/assets/javascripts/logs/logs_tracking_helper.js b/app/assets/javascripts/logs/logs_tracking_helper.js
index 91b0392f71f..26043d646b0 100644
--- a/app/assets/javascripts/logs/logs_tracking_helper.js
+++ b/app/assets/javascripts/logs/logs_tracking_helper.js
@@ -8,7 +8,7 @@ import Tracking from '~/tracking';
* 3. Change the time range
* 4. Use the search bar
*/
-const trackLogs = label =>
+const trackLogs = (label) =>
Tracking.event(document.body.dataset.page, 'logs_view', {
label,
property: 'count',
diff --git a/app/assets/javascripts/logs/stores/actions.js b/app/assets/javascripts/logs/stores/actions.js
index 623516f349d..a26e6f694c9 100644
--- a/app/assets/javascripts/logs/stores/actions.js
+++ b/app/assets/javascripts/logs/stores/actions.js
@@ -11,14 +11,14 @@ const requestUntilData = (url, params) =>
backOff((next, stop) => {
axios
.get(url, { params })
- .then(res => {
+ .then((res) => {
if (res.status === httpStatusCodes.ACCEPTED) {
next();
return;
}
stop(res);
})
- .catch(err => {
+ .catch((err) => {
stop(err);
});
});
@@ -66,12 +66,12 @@ const requestLogsUntilData = ({ commit, state }) => {
const filtersToParams = (filters = []) => {
// Strings become part of the `search`
const search = filters
- .filter(f => typeof f === 'string')
+ .filter((f) => typeof f === 'string')
.join(' ')
.trim();
// null podName to show all pods
- const podName = filters.find(f => f?.type === TOKEN_TYPE_POD_NAME)?.value?.data ?? null;
+ const podName = filters.find((f) => f?.type === TOKEN_TYPE_POD_NAME)?.value?.data ?? null;
return { search, podName };
};
diff --git a/app/assets/javascripts/logs/stores/getters.js b/app/assets/javascripts/logs/stores/getters.js
index dc392af8381..836e6e82385 100644
--- a/app/assets/javascripts/logs/stores/getters.js
+++ b/app/assets/javascripts/logs/stores/getters.js
@@ -3,9 +3,9 @@ import { formatDate } from '../utils';
const mapTrace = ({ timestamp = null, pod = '', message = '' }) =>
[timestamp ? formatDate(timestamp) : '', pod, message].join(' | ');
-export const trace = state => state.logs.lines.map(mapTrace).join('\n');
+export const trace = (state) => state.logs.lines.map(mapTrace).join('\n');
-export const showAdvancedFilters = state => {
+export const showAdvancedFilters = (state) => {
if (state.environments.current) {
const environment = state.environments.options.find(
({ name }) => name === state.environments.current,
diff --git a/app/assets/javascripts/logs/utils.js b/app/assets/javascripts/logs/utils.js
index 880f762e225..8e21863dd0c 100644
--- a/app/assets/javascripts/logs/utils.js
+++ b/app/assets/javascripts/logs/utils.js
@@ -22,4 +22,4 @@ export const getTimeRange = (seconds = 0) => {
};
};
-export const formatDate = timestamp => dateFormat(timestamp, dateFormatMask);
+export const formatDate = (timestamp) => dateFormat(timestamp, dateFormatMask);
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index de7648c31b1..ef0fef6085b 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -53,7 +53,7 @@ window.$ = jQuery;
jQuery.ajaxSetup({
converters: {
// eslint-disable-next-line @gitlab/require-i18n-strings, func-names
- 'text script': function(text) {
+ 'text script': function (text) {
jQuery.globalEval(text, { nonce: getCspNonceValue() });
return text;
},
@@ -137,9 +137,7 @@ function deferredInitialisation() {
$('.remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() {
tooltips.dispose(this);
- $(this)
- .closest('li')
- .addClass('gl-display-none!');
+ $(this).closest('li').addClass('gl-display-none!');
});
$('.js-remove-tr').on('ajax:before', function removeTRAjaxBeforeCallback() {
@@ -147,9 +145,7 @@ function deferredInitialisation() {
});
$('.js-remove-tr').on('ajax:success', function removeTRAjaxSuccessCallback() {
- $(this)
- .closest('tr')
- .addClass('gl-display-none!');
+ $(this).closest('tr').addClass('gl-display-none!');
});
const glTooltipDelay = localStorage.getItem('gl-tooltip-delay');
@@ -278,15 +274,9 @@ document.addEventListener('DOMContentLoaded', () => {
$this.toggleClass('active');
if ($this.hasClass('active')) {
- notesHolders
- .show()
- .find('.hide, .content')
- .show();
+ notesHolders.show().find('.hide, .content').show();
} else {
- notesHolders
- .hide()
- .find('.content')
- .hide();
+ notesHolders.hide().find('.content').hide();
}
$(document).trigger('toggle.comments');
@@ -308,7 +298,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (flashContainer && flashContainer.children.length) {
flashContainer
.querySelectorAll('.flash-alert, .flash-notice, .flash-success')
- .forEach(flashEl => {
+ .forEach((flashEl) => {
removeFlashClickListener(flashEl);
});
}
diff --git a/app/assets/javascripts/manual_ordering.js b/app/assets/javascripts/manual_ordering.js
index 559efa4c66c..04eaa0c77c3 100644
--- a/app/assets/javascripts/manual_ordering.js
+++ b/app/assets/javascripts/manual_ordering.js
@@ -39,7 +39,7 @@ const initManualOrdering = (draggableSelector = 'li.issue') => {
onStart: () => {
sortableStart();
},
- onUpdate: event => {
+ onUpdate: (event) => {
const el = event.item;
const url = el.getAttribute('url') || el.dataset.url;
diff --git a/app/assets/javascripts/member_expiration_date.js b/app/assets/javascripts/member_expiration_date.js
index ef7d8cc9efe..a28427eb9ac 100644
--- a/app/assets/javascripts/member_expiration_date.js
+++ b/app/assets/javascripts/member_expiration_date.js
@@ -24,8 +24,8 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
format: 'yyyy-mm-dd',
minDate: new Date(),
container: $input.parent().get(0),
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
+ parse: (dateString) => parsePikadayDate(dateString),
+ toString: (date) => pikadayToString(date),
onSelect(dateText) {
$input.val(calendar.toString(dateText));
@@ -41,9 +41,7 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
inputs.next('.js-clear-input').on('click', function clicked(event) {
event.preventDefault();
- const input = $(this)
- .closest('.clearable-input')
- .find(selector);
+ const input = $(this).closest('.clearable-input').find(selector);
const calendar = input.data('pikaday');
calendar.setDate(null);
diff --git a/app/assets/javascripts/members.js b/app/assets/javascripts/members.js
index 5bd228496da..4cf4fdd12bf 100644
--- a/app/assets/javascripts/members.js
+++ b/app/assets/javascripts/members.js
@@ -12,13 +12,9 @@ export default class Members {
addListeners() {
// eslint-disable-next-line @gitlab/no-global-event-off
- $('.js-member-update-control')
- .off('change')
- .on('change', this.formSubmit.bind(this));
+ $('.js-member-update-control').off('change').on('change', this.formSubmit.bind(this));
// eslint-disable-next-line @gitlab/no-global-event-off
- $('.js-edit-member-form')
- .off('ajax:success')
- .on('ajax:success', this.formSuccess.bind(this));
+ $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess.bind(this));
disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change');
}
@@ -50,7 +46,7 @@ export default class Members {
return $el.data('id');
},
toggleLabel: (selected, $el) => this.dropdownToggleLabel(selected, $el, $btn),
- clicked: options => this.dropdownClicked(options),
+ clicked: (options) => this.dropdownClicked(options),
});
});
}
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 10078d5cd64..fcb70dd45a6 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
@@ -28,13 +28,13 @@ export default {
if (this.isCurrentUser) {
return sprintf(
s__('Members|Are you sure you want to withdraw your access request for "%{source}"'),
- { source: source.name },
+ { source: source.fullName },
);
}
return sprintf(
s__('Members|Are you sure you want to deny %{usersName}\'s request to join "%{source}"'),
- { usersName: user.name, source: source.name },
+ { usersName: user.name, source: source.fullName },
);
},
},
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 2b0a75640e2..9a27348f146 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
@@ -25,7 +25,7 @@ export default {
s__(
'Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join "%{source}"',
),
- { inviteEmail: invite.email, source: source.name },
+ { inviteEmail: invite.email, source: source.fullName },
);
},
},
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 f2bc9c7e876..0e5df961782 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
@@ -36,7 +36,7 @@ export default {
s__('Members|Are you sure you want to remove %{usersName} from "%{source}"'),
{
usersName: user.name,
- source: source.name,
+ source: source.fullName,
},
);
}
@@ -44,7 +44,7 @@ export default {
return sprintf(
s__('Members|Are you sure you want to remove this orphaned member from "%{source}"'),
{
- source: source.name,
+ source: source.fullName,
},
);
},
diff --git a/app/assets/javascripts/members/components/avatars/user_avatar.vue b/app/assets/javascripts/members/components/avatars/user_avatar.vue
index fe45ca769af..e2264085e67 100644
--- a/app/assets/javascripts/members/components/avatars/user_avatar.vue
+++ b/app/assets/javascripts/members/components/avatars/user_avatar.vue
@@ -38,7 +38,7 @@ export default {
return this.member.user;
},
badges() {
- return generateBadges(this.member, this.isCurrentUser).filter(badge => badge.show);
+ return generateBadges(this.member, this.isCurrentUser).filter((badge) => badge.show);
},
statusEmoji() {
return this.user?.status?.emoji;
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 c1df0b94234..cf7501d84fa 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
@@ -45,7 +45,7 @@ export default {
computed: {
...mapState(['sourceId', 'filteredSearchBar', 'canManageMembers']),
tokens() {
- return this.$options.availableTokens.filter(token => {
+ return this.$options.availableTokens.filter((token) => {
if (
Object.prototype.hasOwnProperty.call(token, 'requiredPermissions') &&
!this[token.requiredPermissions]
@@ -61,8 +61,8 @@ export default {
const query = queryToObject(window.location.search);
const tokens = this.tokens
- .filter(token => query[token.type])
- .map(token => ({
+ .filter((token) => query[token.type])
+ .map((token) => ({
type: token.type,
value: {
data: query[token.type],
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 de7fbc4241c..bcfe559768d 100644
--- a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
+++ b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
@@ -14,7 +14,7 @@ export default {
return parseSortParam(this.tableSortableFields);
},
activeOption() {
- return FIELDS.find(field => field.key === this.sort.sortByKey);
+ return FIELDS.find((field) => field.key === this.sort.sortByKey);
},
activeOptionLabel() {
return this.activeOption?.label;
@@ -23,18 +23,18 @@ export default {
return !this.sort.sortDesc;
},
filteredOptions() {
- return FIELDS.filter(field => this.tableSortableFields.includes(field.key) && field.sort).map(
- field => ({
- key: field.key,
- label: field.label,
- href: buildSortHref({
- sortBy: field.key,
- sortDesc: false,
- filteredSearchBarTokens: this.filteredSearchBar.tokens,
- filteredSearchBarSearchParam: this.filteredSearchBar.searchParam,
- }),
+ return FIELDS.filter(
+ (field) => this.tableSortableFields.includes(field.key) && field.sort,
+ ).map((field) => ({
+ key: field.key,
+ label: field.label,
+ href: buildSortHref({
+ sortBy: field.key,
+ sortDesc: false,
+ filteredSearchBarTokens: this.filteredSearchBar.tokens,
+ filteredSearchBarSearchParam: this.filteredSearchBar.searchParam,
}),
- );
+ }));
},
},
methods: {
diff --git a/app/assets/javascripts/members/components/modals/leave_modal.vue b/app/assets/javascripts/members/components/modals/leave_modal.vue
index 57a5da774e3..d231c7eabfa 100644
--- a/app/assets/javascripts/members/components/modals/leave_modal.vue
+++ b/app/assets/javascripts/members/components/modals/leave_modal.vue
@@ -35,7 +35,7 @@ export default {
return this.memberPath.replace(/:id$/, 'leave');
},
modalTitle() {
- return sprintf(s__('Members|Leave "%{source}"'), { source: this.member.source.name });
+ return sprintf(s__('Members|Leave "%{source}"'), { source: this.member.source.fullName });
},
},
methods: {
@@ -59,7 +59,7 @@ export default {
<gl-form ref="form" :action="leavePath" method="post">
<p>
<gl-sprintf :message="$options.modalContent">
- <template #source>{{ member.source.name }}</template>
+ <template #source>{{ member.source.fullName }}</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/members/components/table/member_source.vue b/app/assets/javascripts/members/components/table/member_source.vue
index 030d72c3420..30fcbfcd3f8 100644
--- a/app/assets/javascripts/members/components/table/member_source.vue
+++ b/app/assets/javascripts/members/components/table/member_source.vue
@@ -22,6 +22,6 @@ export default {
<template>
<span v-if="isDirectMember">{{ __('Direct member') }}</span>
<a v-else v-gl-tooltip.hover :title="__('Inherited')" :href="memberSource.webUrl">{{
- memberSource.name
+ memberSource.fullName
}}</a>
</template>
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index da77e5caad2..16e0cd5ad4e 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -34,7 +34,16 @@ export default {
computed: {
...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId', 'sourceId']),
filteredFields() {
- return FIELDS.filter(field => this.tableFields.includes(field.key) && this.showField(field));
+ return FIELDS.filter(
+ (field) => this.tableFields.includes(field.key) && this.showField(field),
+ ).map((field) => {
+ const tdClassFunction = this[field.tdClassFunction];
+
+ return {
+ ...field,
+ ...(tdClassFunction && { tdClass: tdClassFunction }),
+ };
+ });
},
userIsLoggedIn() {
return this.currentUserId !== null;
@@ -44,6 +53,14 @@ export default {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
},
methods: {
+ hasActionButtons(member) {
+ return (
+ canRemove(member, this.sourceId) ||
+ canResend(member) ||
+ canUpdate(member, this.currentUserId, this.sourceId) ||
+ canOverride(member)
+ );
+ },
showField(field) {
if (!Object.prototype.hasOwnProperty.call(field, 'showFunction')) {
return true;
@@ -56,14 +73,20 @@ export default {
return false;
}
- return this.members.some(member => {
- return (
- canRemove(member, this.sourceId) ||
- canResend(member) ||
- canUpdate(member, this.currentUserId, this.sourceId) ||
- canOverride(member)
- );
- });
+ return this.members.some((member) => this.hasActionButtons(member));
+ },
+ tdClassActions(value, key, member) {
+ if (this.hasActionButtons(member)) {
+ return 'col-actions';
+ }
+
+ return ['col-actions', 'gl-display-none!', 'gl-display-lg-table-cell!'];
+ },
+ tbodyTrAttr(member) {
+ return {
+ ...this.tableAttrs.tr,
+ ...(member?.id && { 'data-testid': `members-table-row-${member.id}` }),
+ };
},
},
};
@@ -83,7 +106,7 @@ export default {
thead-class="border-bottom"
:empty-text="__('No members found')"
show-empty
- :tbody-tr-attr="tableAttrs.tr"
+ :tbody-tr-attr="tbodyTrAttr"
>
<template #cell(account)="{ item: member }">
<members-table-cell #default="{ memberType, isCurrentUser }" :member="member">
diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js
index 21af825f795..77cb150bff6 100644
--- a/app/assets/javascripts/members/constants.js
+++ b/app/assets/javascripts/members/constants.js
@@ -70,8 +70,8 @@ export const FIELDS = [
{
key: 'actions',
thClass: 'col-actions',
- tdClass: 'col-actions',
showFunction: 'showActionsField',
+ tdClassFunction: 'tdClassActions',
},
];
diff --git a/app/assets/javascripts/members/store/index.js b/app/assets/javascripts/members/store/index.js
index f219f8931b0..34c102999d2 100644
--- a/app/assets/javascripts/members/store/index.js
+++ b/app/assets/javascripts/members/store/index.js
@@ -2,7 +2,7 @@ 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';
-export default initialState => ({
+export default (initialState) => ({
state: createState(initialState),
actions,
mutations,
diff --git a/app/assets/javascripts/members/store/utils.js b/app/assets/javascripts/members/store/utils.js
index 7dcd33111e8..585962be27e 100644
--- a/app/assets/javascripts/members/store/utils.js
+++ b/app/assets/javascripts/members/store/utils.js
@@ -1 +1,2 @@
-export const findMember = (state, memberId) => state.members.find(member => member.id === memberId);
+export const findMember = (state, memberId) =>
+ state.members.find((member) => member.id === memberId);
diff --git a/app/assets/javascripts/members/utils.js b/app/assets/javascripts/members/utils.js
index bf1fc2d7515..780b5a9df57 100644
--- a/app/assets/javascripts/members/utils.js
+++ b/app/assets/javascripts/members/utils.js
@@ -21,7 +21,7 @@ export const generateBadges = (member, isCurrentUser) => [
},
];
-export const isGroup = member => {
+export const isGroup = (member) => {
return Boolean(member.sharedWithGroup);
};
@@ -37,7 +37,7 @@ export const canRemove = (member, sourceId) => {
return isDirectMember(member, sourceId) && member.canRemove;
};
-export const canResend = member => {
+export const canResend = (member) => {
return Boolean(member.invite?.canResend);
};
@@ -47,11 +47,11 @@ export const canUpdate = (member, currentUserId, sourceId) => {
);
};
-export const parseSortParam = sortableFields => {
+export const parseSortParam = (sortableFields) => {
const sortParam = getParameterByName('sort');
- const sortedField = FIELDS.filter(field => sortableFields.includes(field.key)).find(
- field => field.sort?.asc === sortParam || field.sort?.desc === sortParam,
+ const sortedField = FIELDS.filter((field) => sortableFields.includes(field.key)).find(
+ (field) => field.sort?.asc === sortParam || field.sort?.desc === sortParam,
);
if (!sortedField) {
@@ -70,7 +70,7 @@ export const buildSortHref = ({
filteredSearchBarTokens,
filteredSearchBarSearchParam,
}) => {
- const sortDefinition = FIELDS.find(field => field.key === sortBy)?.sort;
+ const sortDefinition = FIELDS.find((field) => field.key === sortBy)?.sort;
if (!sortDefinition) {
return '';
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 356d8619fed..338fbd9078a 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
@@ -6,7 +6,7 @@ import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
-(global => {
+((global) => {
global.mergeConflicts = global.mergeConflicts || {};
global.mergeConflicts.diffFileEditor = Vue.extend({
@@ -60,19 +60,28 @@ import { __ } from '~/locale';
const DataPromise = axios.get(this.file.content_path);
Promise.all([EditorPromise, DataPromise])
- .then(([{ default: EditorLite }, { data: { content, new_path: path } }]) => {
- const contentEl = this.$el.querySelector('.editor');
+ .then(
+ ([
+ { default: EditorLite },
+ {
+ data: { content, new_path: path },
+ },
+ ]) => {
+ const contentEl = this.$el.querySelector('.editor');
- this.originalContent = content;
- this.fileLoaded = true;
+ this.originalContent = content;
+ this.fileLoaded = true;
- this.editor = new EditorLite().createInstance({
- el: contentEl,
- blobPath: path,
- blobContent: content,
- });
- this.editor.onDidChangeModelContent(debounce(this.saveDiffResolution.bind(this), 250));
- })
+ this.editor = new EditorLite().createInstance({
+ el: contentEl,
+ blobPath: path,
+ blobContent: content,
+ });
+ this.editor.onDidChangeModelContent(
+ debounce(this.saveDiffResolution.bind(this), 250),
+ );
+ },
+ )
.catch(() => {
flash(__('An error occurred while loading the file'));
});
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 827cf5f478d..bc926cb9155 100644
--- a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
+++ b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import actionsMixin from '../mixins/line_conflict_actions';
import utilsMixin from '../mixins/line_conflict_utils';
-(global => {
+((global) => {
global.mergeConflicts = global.mergeConflicts || {};
global.mergeConflicts.inlineConflictLines = Vue.extend({
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 3cb406b819d..bb306e74825 100644
--- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
+++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import actionsMixin from '../mixins/line_conflict_actions';
import utilsMixin from '../mixins/line_conflict_utils';
-(global => {
+((global) => {
global.mergeConflicts = global.mergeConflicts || {};
global.mergeConflicts.parallelConflictLines = Vue.extend({
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
index c803774f4a7..693f0b619a8 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
@@ -5,7 +5,7 @@ import Vue from 'vue';
import Cookies from 'js-cookie';
import { s__ } from '~/locale';
-(global => {
+((global) => {
global.mergeConflicts = global.mergeConflicts || {};
const diffViewType = Cookies.get('diff_view');
@@ -48,7 +48,7 @@ import { s__ } from '~/locale';
},
decorateFiles(files) {
- files.forEach(file => {
+ files.forEach((file) => {
file.content = '';
file.resolutionData = {};
file.promptDiscardConfirmation = false;
@@ -72,7 +72,7 @@ import { s__ } from '~/locale';
setInlineLine(file) {
file.inlineLines = [];
- file.sections.forEach(section => {
+ file.sections.forEach((section) => {
let currentLineType = 'new';
const { conflict, lines, id } = section;
@@ -80,7 +80,7 @@ import { s__ } from '~/locale';
file.inlineLines.push(this.getHeadHeaderLine(id));
}
- lines.forEach(line => {
+ lines.forEach((line) => {
const { type } = line;
if ((type === 'new' || type === 'old') && currentLineType !== type) {
@@ -102,7 +102,7 @@ import { s__ } from '~/locale';
file.parallelLines = [];
const linesObj = { left: [], right: [] };
- file.sections.forEach(section => {
+ file.sections.forEach((section) => {
const { conflict, lines, id } = section;
if (conflict) {
@@ -110,7 +110,7 @@ import { s__ } from '~/locale';
linesObj.right.push(this.getHeadHeaderLine(id));
}
- lines.forEach(line => {
+ lines.forEach((line) => {
const { type } = line;
if (conflict) {
@@ -156,9 +156,9 @@ import { s__ } from '~/locale';
const { files } = this.state.conflictsData;
let count = 0;
- files.forEach(file => {
+ files.forEach((file) => {
if (file.type === CONFLICT_TYPES.TEXT) {
- file.sections.forEach(section => {
+ file.sections.forEach((section) => {
if (section.conflict) {
count += 1;
}
@@ -287,14 +287,14 @@ import { s__ } from '~/locale';
},
restoreFileLinesState(file) {
- file.inlineLines.forEach(line => {
+ file.inlineLines.forEach((line) => {
if (line.hasConflict || line.isHeader) {
line.isSelected = false;
line.isUnselected = false;
}
});
- file.parallelLines.forEach(lines => {
+ file.parallelLines.forEach((lines) => {
const left = lines[0];
const right = lines[1];
const isLeftMatch = left.hasConflict || left.isHeader;
@@ -362,7 +362,7 @@ import { s__ } from '~/locale';
files: [],
};
- this.state.conflictsData.files.forEach(file => {
+ this.state.conflictsData.files.forEach((file) => {
const addFile = {
old_path: file.old_path,
new_path: file.new_path,
@@ -388,13 +388,13 @@ import { s__ } from '~/locale';
handleSelected(file, sectionId, selection) {
Vue.set(file.resolutionData, sectionId, selection);
- file.inlineLines.forEach(line => {
+ file.inlineLines.forEach((line) => {
if (line.id === sectionId && (line.hasConflict || line.isHeader)) {
this.markLine(line, selection);
}
});
- file.parallelLines.forEach(lines => {
+ file.parallelLines.forEach((lines) => {
const left = lines[0];
const right = lines[1];
const hasSameId = right.id === sectionId || left.id === sectionId;
@@ -426,7 +426,7 @@ import { s__ } from '~/locale';
},
fileTextTypePresent() {
- return this.state.conflictsData.files.some(f => f.type === CONFLICT_TYPES.TEXT);
+ return this.state.conflictsData.files.some((f) => f.type === CONFLICT_TYPES.TEXT);
},
};
})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 344f8dee5ea..bf9e0a309dd 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -31,7 +31,7 @@ function MergeRequest(opts) {
fieldName: 'description',
selector: '.detail-page-description',
lockVersion: this.$el.data('lockVersion'),
- onSuccess: result => {
+ onSuccess: (result) => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
},
@@ -47,11 +47,11 @@ function MergeRequest(opts) {
}
// Local jQuery finder
-MergeRequest.prototype.$ = function(selector) {
+MergeRequest.prototype.$ = function (selector) {
return this.$el.find(selector);
};
-MergeRequest.prototype.initTabs = function() {
+MergeRequest.prototype.initTabs = function () {
if (window.mrTabs) {
window.mrTabs.unbindEvents();
}
@@ -59,18 +59,18 @@ MergeRequest.prototype.initTabs = function() {
window.mrTabs = new MergeRequestTabs(this.opts);
};
-MergeRequest.prototype.showAllCommits = function() {
+MergeRequest.prototype.showAllCommits = function () {
this.$('.first-commits').remove();
return this.$('.all-commits').removeClass('hide');
};
-MergeRequest.prototype.initMRBtnListeners = function() {
+MergeRequest.prototype.initMRBtnListeners = function () {
const _this = this;
const draftToggles = document.querySelectorAll('.js-draft-toggle-button');
if (draftToggles.length) {
- draftToggles.forEach(draftToggle => {
- draftToggle.addEventListener('click', e => {
+ draftToggles.forEach((draftToggle) => {
+ draftToggle.addEventListener('click', (e) => {
e.preventDefault();
e.stopImmediatePropagation();
@@ -99,7 +99,7 @@ MergeRequest.prototype.initMRBtnListeners = function() {
});
}
- return $('.btn-close, .btn-reopen').on('click', function(e) {
+ return $('.btn-close, .btn-reopen').on('click', function (e) {
const $this = $(this);
const shouldSubmit = $this.hasClass('btn-comment');
if (shouldSubmit && $this.data('submitted')) {
@@ -117,7 +117,7 @@ MergeRequest.prototype.initMRBtnListeners = function() {
});
};
-MergeRequest.prototype.submitNoteForm = function(form, $button) {
+MergeRequest.prototype.submitNoteForm = function (form, $button) {
const noteText = form.find('textarea.js-note-text').val();
if (noteText.trim().length > 0) {
form.submit();
@@ -126,8 +126,8 @@ MergeRequest.prototype.submitNoteForm = function(form, $button) {
}
};
-MergeRequest.prototype.initCommitMessageListeners = function() {
- $(document).on('click', 'a.js-with-description-link', e => {
+MergeRequest.prototype.initCommitMessageListeners = function () {
+ $(document).on('click', 'a.js-with-description-link', (e) => {
const textarea = $('textarea.js-commit-message');
e.preventDefault();
@@ -136,7 +136,7 @@ MergeRequest.prototype.initCommitMessageListeners = function() {
$('.js-without-description-hint').show();
});
- $(document).on('click', 'a.js-without-description-link', e => {
+ $(document).on('click', 'a.js-without-description-link', (e) => {
const textarea = $('textarea.js-commit-message');
e.preventDefault();
@@ -146,7 +146,7 @@ MergeRequest.prototype.initCommitMessageListeners = function() {
});
};
-MergeRequest.setStatusBoxToMerged = function() {
+MergeRequest.setStatusBoxToMerged = function () {
$('.detail-page-header .status-box')
.removeClass('status-box-open')
.addClass('status-box-mr-merged')
@@ -154,20 +154,20 @@ MergeRequest.setStatusBoxToMerged = function() {
.text(__('Merged'));
};
-MergeRequest.decreaseCounter = function(by = 1) {
+MergeRequest.decreaseCounter = function (by = 1) {
const $el = $('.js-merge-counter');
const count = Math.max(parseInt($el.text().replace(/[^\d]/, ''), 10) - by, 0);
$el.text(addDelimiter(count));
};
-MergeRequest.hideCloseButton = function() {
+MergeRequest.hideCloseButton = function () {
const el = document.querySelector('.merge-request .js-issuable-actions');
// Dropdown for mobile screen
el.querySelector('li.js-close-item').classList.add('hidden');
};
-MergeRequest.toggleDraftStatus = function(title, isReady) {
+MergeRequest.toggleDraftStatus = function (title, isReady) {
if (isReady) {
createFlash(__('The merge request can now be merged.'), 'notice');
}
@@ -180,7 +180,7 @@ MergeRequest.toggleDraftStatus = function(title, isReady) {
const draftToggles = document.querySelectorAll('.js-draft-toggle-button');
if (draftToggles.length) {
- draftToggles.forEach(el => {
+ draftToggles.forEach((el) => {
const draftToggle = el;
const url = setUrlParams(
{ 'merge_request[wip_event]': isReady ? 'wip' : 'unwip' },
diff --git a/app/assets/javascripts/merge_request/components/status_box.vue b/app/assets/javascripts/merge_request/components/status_box.vue
new file mode 100644
index 00000000000..fd99802caff
--- /dev/null
+++ b/app/assets/javascripts/merge_request/components/status_box.vue
@@ -0,0 +1,69 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import mrEventHub from '../eventhub';
+
+const CLASSES = {
+ opened: 'status-box-open',
+ closed: 'status-box-mr-closed',
+ merged: 'status-box-mr-merged',
+};
+
+const STATUS = {
+ opened: [__('Open'), 'issue-open-m'],
+ closed: [__('Closed'), 'close'],
+ merged: [__('Merged'), 'git-merge'],
+};
+
+export default {
+ components: {
+ GlIcon,
+ },
+ props: {
+ initialState: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ state: this.initialState,
+ };
+ },
+ computed: {
+ statusBoxClass() {
+ return CLASSES[this.state];
+ },
+ statusHumanName() {
+ return STATUS[this.state][0];
+ },
+ statusIconName() {
+ return STATUS[this.state][1];
+ },
+ },
+ created() {
+ mrEventHub.$on('mr.state.updated', this.updateState);
+ },
+ beforeDestroy() {
+ mrEventHub.$off('mr.state.updated', this.updateState);
+ },
+ methods: {
+ updateState({ state }) {
+ this.state = state;
+ },
+ },
+};
+</script>
+
+<template>
+ <div :class="statusBoxClass" class="issuable-status-box status-box">
+ <gl-icon
+ :name="statusIconName"
+ class="gl-display-block gl-display-sm-none!"
+ data-testid="status-icon"
+ />
+ <span class="gl-display-none gl-display-sm-block">
+ {{ statusHumanName }}
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/merge_request/eventhub.js b/app/assets/javascripts/merge_request/eventhub.js
new file mode 100644
index 00000000000..e31806ad199
--- /dev/null
+++ b/app/assets/javascripts/merge_request/eventhub.js
@@ -0,0 +1,3 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 6e9661ea1a8..81241cd2418 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -1,7 +1,6 @@
/* eslint-disable no-new, class-methods-use-this */
import $ from 'jquery';
-import 'vendor/jquery.scrollTo';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Cookies from 'js-cookie';
import createEventHub from '~/helpers/event_hub_factory';
@@ -14,6 +13,7 @@ import {
handleLocationHash,
isMetaClick,
parseBoolean,
+ scrollToElement,
} from './lib/utils/common_utils';
import { isInVueNoteablePage } from './lib/utils/dom_utils';
import { getLocationHash } from './lib/utils/url_utility';
@@ -128,7 +128,7 @@ export default class MergeRequestTabs {
bindEvents() {
$('.merge-request-tabs a[data-toggle="tabvue"]').on('click', this.clickTab);
- window.addEventListener('popstate', event => {
+ window.addEventListener('popstate', (event) => {
if (event.state && event.state.action) {
this.tabShown(event.state.action, event.target.location);
this.currentAction = event.state.action;
@@ -177,14 +177,14 @@ export default class MergeRequestTabs {
this.currentTab = action;
if (this.mergeRequestTabPanesAll) {
- this.mergeRequestTabPanesAll.forEach(el => {
+ this.mergeRequestTabPanesAll.forEach((el) => {
const tabPane = el;
tabPane.style.display = 'none';
});
}
if (this.mergeRequestTabsAll) {
- this.mergeRequestTabsAll.forEach(el => {
+ this.mergeRequestTabsAll.forEach((el) => {
el.classList.remove('active');
});
}
@@ -255,12 +255,12 @@ export default class MergeRequestTabs {
this.eventHub.$emit('MergeRequestTabChange', action);
}
- scrollToElement(container) {
+ scrollToContainerElement(container) {
if (location.hash) {
- const offset = 0 - ($('.navbar-gitlab').outerHeight() + $('.js-tabs-affix').outerHeight());
const $el = $(`${container} ${location.hash}:not(.match)`);
+
if ($el.length) {
- $.scrollTo($el[0], { offset });
+ scrollToElement($el[0]);
}
}
}
@@ -339,7 +339,7 @@ export default class MergeRequestTabs {
document.querySelector('div#commits').innerHTML = data.html;
localTimeAgo($('.js-timeago', 'div#commits'));
this.commitsLoaded = true;
- this.scrollToElement('#commits');
+ this.scrollToContainerElement('#commits');
this.toggleLoading(false);
initAddContextCommitsTriggers();
@@ -408,7 +408,7 @@ export default class MergeRequestTabs {
this.diffsLoaded = true;
new Diff();
- this.scrollToElement('#diffs');
+ this.scrollToContainerElement('#diffs');
$('.diff-file').each((i, el) => {
new BlobForkSuggestion({
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
index 52e9b67c77d..717766578de 100644
--- a/app/assets/javascripts/milestone.js
+++ b/app/assets/javascripts/milestone.js
@@ -11,7 +11,7 @@ export default class Milestone {
}
bindTabsSwitching() {
- return $('a[data-toggle="tab"]').on('show.bs.tab', e => {
+ return $('a[data-toggle="tab"]').on('show.bs.tab', (e) => {
const $target = $(e.target);
window.location.hash = $target.attr('href');
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index baa5e41989b..921925e15c5 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -89,7 +89,7 @@ export default class MilestoneSelect {
return getMilestones(contextId, reqParams)
.then(({ data }) =>
data
- .map(m => ({
+ .map((m) => ({
...m,
// Public API includes `title` instead of `name`.
name: m.title,
@@ -105,7 +105,7 @@ export default class MilestoneSelect {
return 0;
}),
)
- .then(data => {
+ .then((data) => {
const extraOptions = [];
if (showAny) {
extraOptions.push({
@@ -146,7 +146,7 @@ export default class MilestoneSelect {
$(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
});
},
- renderRow: milestone => {
+ renderRow: (milestone) => {
const milestoneName = milestone.title || milestone.name;
let milestoneDisplayName = escape(milestoneName);
@@ -178,8 +178,8 @@ export default class MilestoneSelect {
},
defaultLabel,
fieldName: $dropdown.data('fieldName'),
- text: milestone => escape(milestone.title),
- id: milestone => {
+ text: (milestone) => escape(milestone.title),
+ id: (milestone) => {
if (milestone !== undefined) {
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
return milestone.name;
@@ -193,7 +193,7 @@ export default class MilestoneSelect {
// display:block overrides the hide-collapse rule
return $value.css('display', '');
},
- opened: e => {
+ opened: (e) => {
const $el = $(e.currentTarget);
if ($dropdown.hasClass('js-issue-board-sidebar') || options.handleClick) {
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
@@ -202,7 +202,7 @@ export default class MilestoneSelect {
$(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
},
vue: $dropdown.hasClass('js-issue-board-sidebar'),
- clicked: clickEvent => {
+ clicked: (clickEvent) => {
const { e } = clickEvent;
let selected = clickEvent.selectedObj;
diff --git a/app/assets/javascripts/milestones/components/milestone_combobox.vue b/app/assets/javascripts/milestones/components/milestone_combobox.vue
index 08fd5a5994f..1db2d10db20 100644
--- a/app/assets/javascripts/milestones/components/milestone_combobox.vue
+++ b/app/assets/javascripts/milestones/components/milestone_combobox.vue
@@ -112,7 +112,7 @@ export default {
value: {
immediate: true,
handler() {
- const milestoneTitles = this.value.map(milestone =>
+ const milestoneTitles = this.value.map((milestone) =>
milestone.title ? milestone.title : milestone,
);
if (!isEqual(milestoneTitles, this.selectedMilestones)) {
diff --git a/app/assets/javascripts/milestones/stores/actions.js b/app/assets/javascripts/milestones/stores/actions.js
index df45c7156ad..48fe0dd1e31 100644
--- a/app/assets/javascripts/milestones/stores/actions.js
+++ b/app/assets/javascripts/milestones/stores/actions.js
@@ -41,10 +41,10 @@ export const fetchProjectMilestones = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.projectMilestones(state.projectId)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_PROJECT_MILESTONES_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_PROJECT_MILESTONES_ERROR, error);
})
.finally(() => {
@@ -56,10 +56,10 @@ export const fetchGroupMilestones = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.groupMilestones(state.groupId)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_GROUP_MILESTONES_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_GROUP_MILESTONES_ERROR, error);
})
.finally(() => {
@@ -76,10 +76,10 @@ export const searchProjectMilestones = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.projectSearch(state.projectId, options)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_PROJECT_MILESTONES_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_PROJECT_MILESTONES_ERROR, error);
})
.finally(() => {
@@ -95,10 +95,10 @@ export const searchGroupMilestones = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.groupMilestones(state.groupId, options)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_GROUP_MILESTONES_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_GROUP_MILESTONES_ERROR, error);
})
.finally(() => {
diff --git a/app/assets/javascripts/milestones/stores/mutations.js b/app/assets/javascripts/milestones/stores/mutations.js
index 601b88cb62a..3a7babf6fa0 100644
--- a/app/assets/javascripts/milestones/stores/mutations.js
+++ b/app/assets/javascripts/milestones/stores/mutations.js
@@ -22,7 +22,7 @@ export default {
},
[types.REMOVE_SELECTED_MILESTONE](state, selectedMilestone) {
const filteredMilestones = state.selectedMilestones.filter(
- milestone => milestone !== selectedMilestone,
+ (milestone) => milestone !== selectedMilestone,
);
Vue.set(state, 'selectedMilestones', filteredMilestones);
},
diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
index d4283701367..05f2f15fa9a 100644
--- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js
+++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
@@ -47,7 +47,7 @@ export default class MiniPipelineGraph {
$(document).on(
'click',
`${this.container} .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`,
- e => {
+ (e) => {
e.stopPropagation();
},
);
@@ -92,11 +92,7 @@ export default class MiniPipelineGraph {
})
.catch(() => {
this.toggleLoading(button);
- if (
- $(button)
- .parent()
- .hasClass('open')
- ) {
+ if ($(button).parent().hasClass('open')) {
$(button).dropdown('toggle');
}
flash(__('An error occurred while fetching the builds.'), 'alert');
diff --git a/app/assets/javascripts/mirrors/mirror_repos.js b/app/assets/javascripts/mirrors/mirror_repos.js
index 18ea27e9a34..f7200f22471 100644
--- a/app/assets/javascripts/mirrors/mirror_repos.js
+++ b/app/assets/javascripts/mirrors/mirror_repos.js
@@ -80,7 +80,7 @@ export default class MirrorRepos {
this.debouncedUpdateUrl = debounce(() => this.updateUrl(), 200);
this.$urlInput.on('input', () => this.debouncedUpdateUrl());
this.$protectedBranchesInput.on('change', () => this.updateProtectedBranches());
- this.$table.on('click', '.js-delete-mirror', event => this.deleteMirror(event));
+ this.$table.on('click', '.js-delete-mirror', (event) => this.deleteMirror(event));
}
togglePassword() {
diff --git a/app/assets/javascripts/mirrors/ssh_mirror.js b/app/assets/javascripts/mirrors/ssh_mirror.js
index c6486350f3b..b692db10e2d 100644
--- a/app/assets/javascripts/mirrors/ssh_mirror.js
+++ b/app/assets/javascripts/mirrors/ssh_mirror.js
@@ -29,10 +29,10 @@ export default class SSHMirror {
this.handleRepositoryUrlInput(true);
this.$repositoryUrl.on('keyup', () => this.handleRepositoryUrlInput());
- this.$knownHosts.on('keyup', e => this.handleSSHKnownHostsInput(e));
- this.$dropdownAuthType.on('change', e => this.handleAuthTypeChange(e));
- this.$btnDetectHostKeys.on('click', e => this.handleDetectHostKeys(e));
- this.$btnSSHHostsShowAdvanced.on('click', e => this.handleSSHHostsAdvanced(e));
+ this.$knownHosts.on('keyup', (e) => this.handleSSHKnownHostsInput(e));
+ this.$dropdownAuthType.on('change', (e) => this.handleAuthTypeChange(e));
+ this.$btnDetectHostKeys.on('click', (e) => this.handleDetectHostKeys(e));
+ this.$btnSSHHostsShowAdvanced.on('click', (e) => this.handleSSHHostsAdvanced(e));
}
/**
@@ -100,7 +100,7 @@ export default class SSHMirror {
})
.catch(stop);
})
- .then(res => {
+ .then((res) => {
$btnLoadSpinner.addClass('d-none');
// Once data is received, we show verification info along with Host keys and fingerprints
this.$hostKeysInformation
@@ -160,7 +160,7 @@ export default class SSHMirror {
showSSHInformation(sshHostKeys) {
const $fingerprintsList = this.$hostKeysInformation.find('.js-fingerprints-list');
let fingerprints = '';
- sshHostKeys.fingerprints.forEach(fingerprint => {
+ sshHostKeys.fingerprints.forEach((fingerprint) => {
const escFingerprints = escape(fingerprint.fingerprint);
fingerprints += `<code>${escFingerprints}</code>`;
});
diff --git a/app/assets/javascripts/monitoring/components/alert_widget.vue b/app/assets/javascripts/monitoring/components/alert_widget.vue
index 8f9c181258f..bf31b86561a 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget.vue
@@ -97,12 +97,12 @@ export default {
return Boolean(this.firingAlerts.length);
},
firingAlerts() {
- return values(this.alertsToManage).filter(alert =>
+ return values(this.alertsToManage).filter((alert) =>
this.passedAlertThreshold(this.getQueryData(alert), alert),
);
},
formattedFiringAlerts() {
- return this.firingAlerts.map(alert => this.formatAlertSummary(alert.alert_path));
+ return this.firingAlerts.map((alert) => this.formatAlertSummary(alert.alert_path));
},
configuredAlert() {
return this.hasAlerts ? values(this.alertsToManage)[0].metricId : '';
@@ -116,13 +116,13 @@ export default {
fetchAlertData() {
this.isLoading = true;
- const queriesWithAlerts = this.relevantQueries.filter(query => query.alert_path);
+ const queriesWithAlerts = this.relevantQueries.filter((query) => query.alert_path);
return Promise.all(
- queriesWithAlerts.map(query =>
+ queriesWithAlerts.map((query) =>
this.service
.readAlert(query.alert_path)
- .then(alertAttributes => this.setAlert(alertAttributes, query.metricId)),
+ .then((alertAttributes) => this.setAlert(alertAttributes, query.metricId)),
),
)
.then(() => {
@@ -141,7 +141,7 @@ export default {
},
formatAlertSummary(alertPath) {
const alert = this.alertsToManage[alertPath];
- const alertQuery = this.relevantQueries.find(query => query.metricId === alert.metricId);
+ const alertQuery = this.relevantQueries.find((query) => query.metricId === alert.metricId);
return `${alertQuery.label} ${alert.operator} ${alert.threshold}`;
},
@@ -150,19 +150,19 @@ export default {
switch (operator) {
case OPERATORS.greaterThan:
- return data.some(value => value > threshold);
+ return data.some((value) => value > threshold);
case OPERATORS.lessThan:
- return data.some(value => value < threshold);
+ return data.some((value) => value < threshold);
case OPERATORS.equalTo:
- return data.some(value => value === threshold);
+ return data.some((value) => value === threshold);
default:
return false;
}
},
getQueryData(alert) {
- const alertQuery = this.relevantQueries.find(query => query.metricId === alert.metricId);
+ const alertQuery = this.relevantQueries.find((query) => query.metricId === alert.metricId);
- return get(alertQuery, 'result[0].values', []).map(value => get(value, '[1]', null));
+ return get(alertQuery, 'result[0].values', []).map((value) => get(value, '[1]', null));
},
showModal() {
this.$root.$emit('bv::show::modal', this.modalId);
@@ -179,7 +179,7 @@ export default {
this.isLoading = true;
this.service
.createAlert(newAlert)
- .then(alertAttributes => {
+ .then((alertAttributes) => {
this.setAlert(alertAttributes, prometheus_metric_id);
this.isLoading = false;
this.hideModal();
@@ -194,7 +194,7 @@ export default {
this.isLoading = true;
this.service
.updateAlert(alert, updatedAlert)
- .then(alertAttributes => {
+ .then((alertAttributes) => {
this.setAlert(alertAttributes, this.alertsToManage[alert].metricId);
this.isLoading = false;
this.hideModal();
diff --git a/app/assets/javascripts/monitoring/components/alert_widget_form.vue b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
index 71691429ece..b26941891e4 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget_form.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
@@ -99,7 +99,7 @@ export default {
return this.alertQuery.length ? true : null;
},
currentQuery() {
- return this.relevantQueries.find(query => query.metricId === this.prometheusMetricId) || {};
+ return this.relevantQueries.find((query) => query.metricId === this.prometheusMetricId) || {};
},
formDisabled() {
// We need a prometheusMetricId to determine whether we're
@@ -151,7 +151,7 @@ export default {
},
methods: {
selectQuery(queryId) {
- const existingAlertPath = findKey(this.alertsToManage, alert => alert.metricId === queryId);
+ const existingAlertPath = findKey(this.alertsToManage, (alert) => alert.metricId === queryId);
const existingAlert = this.alertsToManage[existingAlertPath];
if (existingAlert) {
diff --git a/app/assets/javascripts/monitoring/components/charts/annotations.js b/app/assets/javascripts/monitoring/components/charts/annotations.js
index 418107c4126..aac9d2f8a01 100644
--- a/app/assets/javascripts/monitoring/components/charts/annotations.js
+++ b/app/assets/javascripts/monitoring/components/charts/annotations.js
@@ -52,7 +52,7 @@ export const annotationsYAxis = {
* @param {Object} annotation object
* @returns {Object} markLine object
*/
-export const parseAnnotations = annotations =>
+export const parseAnnotations = (annotations) =>
annotations.reduce(
(acc, annotation) => {
acc.lines.push({
@@ -87,7 +87,7 @@ export const parseAnnotations = annotations =>
*/
export const generateAnnotationsSeries = ({ deployments = [], annotations = [] } = {}) => {
// deployment data points
- const data = deployments.map(deployment => {
+ const data = deployments.map((deployment) => {
return {
name: 'deployments',
value: [deployment.createdAt, annotationsYAxisCoords.pos],
diff --git a/app/assets/javascripts/monitoring/components/charts/anomaly.vue b/app/assets/javascripts/monitoring/components/charts/anomaly.vue
index ac401c6e381..cb533c38fa0 100644
--- a/app/assets/javascripts/monitoring/components/charts/anomaly.vue
+++ b/app/assets/javascripts/monitoring/components/charts/anomaly.vue
@@ -1,4 +1,5 @@
<script>
+import produce from 'immer';
import { flattenDeep, isNumber } from 'lodash';
import { GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { roundOffFloat } from '~/lib/utils/common_utils';
@@ -61,7 +62,7 @@ export default {
},
computed: {
series() {
- return this.graphData.metrics.map(metric => {
+ return this.graphData.metrics.map((metric) => {
const values = metric.result && metric.result[0] ? metric.result[0].values : [];
return {
label: metric.label,
@@ -77,18 +78,20 @@ export default {
* This offset is the lowest value.
*/
yOffset() {
- const values = flattenDeep(this.series.map(ser => ser.data.map(([, y]) => y)));
+ const values = flattenDeep(this.series.map((ser) => ser.data.map(([, y]) => y)));
const min = values.length ? Math.floor(Math.min(...values)) : 0;
return min < 0 ? -min : 0;
},
metricData() {
const originalMetricQuery = this.graphData.metrics[0];
- const metricQuery = { ...originalMetricQuery };
- metricQuery.result[0].values = metricQuery.result[0].values.map(([x, y]) => [
- x,
- y + this.yOffset,
- ]);
+ const metricQuery = produce(originalMetricQuery, (draftQuery) => {
+ // eslint-disable-next-line no-param-reassign
+ draftQuery.result[0].values = draftQuery.result[0].values.map(([x, y]) => [
+ x,
+ y + this.yOffset,
+ ]);
+ });
return {
...this.graphData,
type: panelTypes.LINE_CHART,
@@ -109,7 +112,7 @@ export default {
},
showSymbol: true,
itemStyle: {
- color: params => {
+ color: (params) => {
if (this.isDatapointAnomaly(params.dataIndex)) {
return colorValues.anomalySymbol;
}
@@ -128,7 +131,7 @@ export default {
const yAxisWithOffset = {
axisLabel: {
- formatter: num => roundOffFloat(num - this.yOffset, 3).toString(),
+ formatter: (num) => roundOffFloat(num - this.yOffset, 3).toString(),
},
};
@@ -153,7 +156,7 @@ export default {
boundarySeries.push(
this.makeBoundarySeries({
name: this.formatLegendLabel(upperSeries),
- data: calcOffsetY(upperSeries.data, i => -this.yValue(LOWER, i)),
+ data: calcOffsetY(upperSeries.data, (i) => -this.yValue(LOWER, i)),
areaStyle: {
color: AREA_COLOR,
opacity: AREA_OPACITY,
diff --git a/app/assets/javascripts/monitoring/components/charts/bar.vue b/app/assets/javascripts/monitoring/components/charts/bar.vue
index e1018cd5952..a4cef5ea256 100644
--- a/app/assets/javascripts/monitoring/components/charts/bar.vue
+++ b/app/assets/javascripts/monitoring/components/charts/bar.vue
@@ -67,12 +67,12 @@ export default {
},
setSvg(name) {
getSvgIconPathContent(name)
- .then(path => {
+ .then((path) => {
if (path) {
this.$set(this.svgs, name, `path://${path}`);
}
})
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line no-console, @gitlab/require-i18n-strings
console.error('SVG could not be rendered correctly: ', e);
});
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue
index 511f77a441b..ba947c2fa9c 100644
--- a/app/assets/javascripts/monitoring/components/charts/column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/column.vue
@@ -90,7 +90,7 @@ export default {
},
setSvg(name) {
getSvgIconPathContent(name)
- .then(path => {
+ .then((path) => {
if (path) {
this.$set(this.svgs, name, `path://${path}`);
}
diff --git a/app/assets/javascripts/monitoring/components/charts/heatmap.vue b/app/assets/javascripts/monitoring/components/charts/heatmap.vue
index 7003e2d37cf..22214a76aba 100644
--- a/app/assets/javascripts/monitoring/components/charts/heatmap.vue
+++ b/app/assets/javascripts/monitoring/components/charts/heatmap.vue
@@ -42,10 +42,10 @@ export default {
return this.graphData.y_label || '';
},
xAxisLabels() {
- return this.metrics.result.map(res => Object.values(res.metric)[0]);
+ return this.metrics.result.map((res) => Object.values(res.metric)[0]);
},
yAxisLabels() {
- return this.result.values.map(val => {
+ return this.result.values.map((val) => {
const [yLabel] = val;
return formatDate(new Date(yLabel), {
diff --git a/app/assets/javascripts/monitoring/components/charts/options.js b/app/assets/javascripts/monitoring/components/charts/options.js
index 0cd4a02311c..163a7be6973 100644
--- a/app/assets/javascripts/monitoring/components/charts/options.js
+++ b/app/assets/javascripts/monitoring/components/charts/options.js
@@ -51,7 +51,7 @@ const getDataAxisOptions = ({ format, precision, name }) => {
nameLocation: 'center', // same as gitlab-ui's default
scale: true,
axisLabel: {
- formatter: val => formatter(val, precision, maxDataAxisTickLength),
+ formatter: (val) => formatter(val, precision, maxDataAxisTickLength),
},
};
};
@@ -85,7 +85,7 @@ export const getTimeAxisOptions = ({
name: __('Time'),
type: axisTypes.time,
axisLabel: {
- formatter: date => formatDate(date, { format, timezone }),
+ formatter: (date) => formatDate(date, { format, timezone }),
},
axisPointer: {
snap: false,
@@ -109,7 +109,7 @@ export const getTooltipFormatter = ({
precision = defaultTooltipPrecision,
} = {}) => {
const formatter = getFormatter(format);
- return num => formatter(num, precision);
+ return (num) => formatter(num, precision);
};
// Thresholds
@@ -138,9 +138,9 @@ export const getValidThresholds = ({ mode, range = {}, values = [] } = {}) => {
const uniqueThresholds = uniq(values);
- const numberThresholds = uniqueThresholds.filter(threshold => isFinite(threshold));
+ const numberThresholds = uniqueThresholds.filter((threshold) => isFinite(threshold));
- const validThresholds = numberThresholds.filter(threshold => {
+ const validThresholds = numberThresholds.filter((threshold) => {
let isValid;
if (mode === thresholdModeTypes.PERCENTAGE) {
@@ -152,7 +152,7 @@ export const getValidThresholds = ({ mode, range = {}, values = [] } = {}) => {
return isValid;
});
- const transformedThresholds = validThresholds.map(threshold => {
+ const transformedThresholds = validThresholds.map((threshold) => {
let transformedThreshold;
if (mode === 'percentage') {
diff --git a/app/assets/javascripts/monitoring/components/charts/stacked_column.vue b/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
index 66b4d0d86e6..b5ae6bcfd13 100644
--- a/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
@@ -68,7 +68,7 @@ export default {
if (!result || result.length === 0) {
return [];
}
- return { name, data: result[0].values.map(val => val[1]) };
+ return { name, data: result[0].values.map((val) => val[1]) };
})
.slice(0, 1);
},
@@ -89,7 +89,7 @@ export default {
if (!result || result.length === 0) {
return [];
}
- return result[0].values.map(val => val[0]);
+ return result[0].values.map((val) => val[0]);
},
dataZoomConfig() {
const handleIcon = this.svgs['scroll-handle'];
@@ -106,7 +106,7 @@ export default {
};
},
seriesNames() {
- return this.graphData.metrics.map(metric => metric.label);
+ return this.graphData.metrics.map((metric) => metric.label);
},
},
created() {
@@ -115,12 +115,12 @@ export default {
methods: {
setSvg(name) {
getSvgIconPathContent(name)
- .then(path => {
+ .then((path) => {
if (path) {
this.$set(this.svgs, name, `path://${path}`);
}
})
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line no-console, @gitlab/require-i18n-strings
console.error('SVG could not be rendered correctly: ', e);
});
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index 170c5ff7695..e9f7b11c977 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -11,7 +11,7 @@ import { makeDataSeries } from '~/helpers/monitor_helper';
import { graphDataValidatorForValues } from '../../utils';
import { formatDate, timezones } from '../../format_date';
-export const timestampToISODate = timestamp => new Date(timestamp).toISOString();
+export const timestampToISODate = (timestamp) => new Date(timestamp).toISOString();
const THROTTLED_DATAZOOM_WAIT = 1000; // milliseconds
@@ -304,7 +304,7 @@ export default {
this.tooltip.content = [];
- params.seriesData.forEach(dataPoint => {
+ params.seriesData.forEach((dataPoint) => {
if (dataPoint.value) {
const [, yVal] = dataPoint.value;
this.tooltip.type = dataPoint.name;
@@ -327,12 +327,12 @@ export default {
},
setSvg(name) {
getSvgIconPathContent(name)
- .then(path => {
+ .then((path) => {
if (path) {
this.$set(this.svgs, name, `path://${path}`);
}
})
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line no-console, @gitlab/require-i18n-strings
console.error('SVG could not be rendered correctly: ', e);
});
diff --git a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
index 070277fe2dc..9d1926dca54 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
@@ -1,7 +1,7 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import {
- GlDeprecatedButton,
+ GlButton,
GlDropdown,
GlDropdownDivider,
GlDropdownItem,
@@ -22,7 +22,7 @@ import { getAddMetricTrackingOptions } from '../utils';
export default {
components: {
- GlDeprecatedButton,
+ GlButton,
GlDropdown,
GlDropdownDivider,
GlDropdownItem,
@@ -178,10 +178,10 @@ export default {
/>
</form>
<div slot="modal-footer">
- <gl-deprecated-button @click="hideAddMetricModal">
+ <gl-button @click="hideAddMetricModal">
{{ __('Cancel') }}
- </gl-deprecated-button>
- <gl-deprecated-button
+ </gl-button>
+ <gl-button
v-track-event="getAddMetricTrackingOptions()"
data-testid="add-metric-modal-submit-button"
:disabled="!customMetricsFormIsValid"
@@ -189,7 +189,7 @@ export default {
@click="submitCustomMetricsForm"
>
{{ __('Save changes') }}
- </gl-deprecated-button>
+ </gl-button>
</div>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index ad7127d97de..2b0c3d03b8d 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -271,8 +271,8 @@ export default {
methods: {
getGraphAlerts(queries) {
if (!this.allAlerts) return {};
- const metricIdsForChart = queries.map(q => q.metricId);
- return pickBy(this.allAlerts, alert => metricIdsForChart.includes(alert.metricId));
+ const metricIdsForChart = queries.map((q) => q.metricId);
+ return pickBy(this.allAlerts, (alert) => metricIdsForChart.includes(alert.metricId));
},
getGraphAlertValues(queries) {
return Object.values(this.getGraphAlerts(queries));
@@ -346,10 +346,10 @@ export default {
}
},
getAlertRunbooks(queries) {
- const hasRunbook = alert => Boolean(alert.runbookUrl);
+ const hasRunbook = (alert) => Boolean(alert.runbookUrl);
const graphAlertsWithRunbooks = pickBy(this.getGraphAlerts(queries), hasRunbook);
- const alertToRunbookTransform = alert => {
- const alertQuery = queries.find(query => query.metricId === alert.metricId);
+ const alertToRunbookTransform = (alert) => {
+ const alertQuery = queries.find((query) => query.metricId === alert.metricId);
return {
key: alert.metricId,
href: alert.runbookUrl,
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
index 0a1b1cd2c08..bcfa1b04322 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
@@ -146,7 +146,7 @@ export default {
)
"
>
- <template #code="{content}">
+ <template #code="{ content }">
<code>{{ content }}</code>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
index db5b853d451..627af202028 100644
--- a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
+++ b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
@@ -3,7 +3,7 @@ import { GlFormGroup, GlFormInput, GlFormRadioGroup, GlFormTextarea } from '@git
import { escape as esc } from 'lodash';
import { __, s__, sprintf } from '~/locale';
-const defaultFileName = dashboard => dashboard.path.split('/').reverse()[0];
+const defaultFileName = (dashboard) => dashboard.path.split('/').reverse()[0];
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue b/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue
index e64afc01fd9..b87934a1db2 100644
--- a/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue
+++ b/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue
@@ -42,7 +42,7 @@ export default {
this.loading = true;
this.alert = null;
this.duplicateSystemDashboard(this.form)
- .then(createdDashboard => {
+ .then((createdDashboard) => {
this.loading = false;
this.alert = null;
@@ -55,7 +55,7 @@ export default {
this.form.branch === this.defaultBranch ? createdDashboard : this.selectedDashboard;
this.$emit(events.dashboardDuplicated, dashboard);
})
- .catch(error => {
+ .catch((error) => {
this.loading = false;
this.alert = error;
});
diff --git a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
index 481ba3636cb..c114ae1809f 100644
--- a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
@@ -17,7 +17,7 @@ export default {
urls: {
type: Array,
required: true,
- validator: urls => urls.length > 0,
+ validator: (urls) => urls.length > 0,
},
},
data() {
diff --git a/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue b/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
index 1557a49137e..2fe49152c4f 100644
--- a/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
@@ -101,7 +101,7 @@ export default {
},
}),
chartHasData(chart) {
- return chart.metrics.some(metric => this.metricsWithData.includes(metric.metricId));
+ return chart.metrics.some((metric) => this.metricsWithData.includes(metric.metricId));
},
onSidebarMutation() {
setTimeout(() => {
diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index 5e7c9b5d906..867f7139d71 100644
--- a/app/assets/javascripts/monitoring/components/empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -12,7 +12,7 @@ export default {
selectedState: {
type: String,
required: true,
- validator: state => Object.values(dashboardEmptyStates).includes(state),
+ validator: (state) => Object.values(dashboardEmptyStates).includes(state),
},
documentationPath: {
type: String,
diff --git a/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue b/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue
index 4e48292c48d..ff0327f5f99 100644
--- a/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue
+++ b/app/assets/javascripts/monitoring/components/variables/dropdown_field.vue
@@ -28,7 +28,7 @@ export default {
},
computed: {
text() {
- const selectedOpt = this.options.values?.find(opt => opt.value === this.value);
+ const selectedOpt = this.options.values?.find((opt) => opt.value === this.value);
return selectedOpt?.text || this.value;
},
},
diff --git a/app/assets/javascripts/monitoring/csv_export.js b/app/assets/javascripts/monitoring/csv_export.js
index 20cfa23e9b4..eaeed4a54d4 100644
--- a/app/assets/javascripts/monitoring/csv_export.js
+++ b/app/assets/javascripts/monitoring/csv_export.js
@@ -66,8 +66,8 @@ const csvMetricHeaders = (axisLabel, metrics) =>
*
* @param {Array} metrics - Metrics with results
*/
-const csvMetricValues = metrics =>
- metrics.flatMap(({ result }) => result.map(res => res.values || []));
+const csvMetricValues = (metrics) =>
+ metrics.flatMap(({ result }) => result.map((res) => res.values || []));
/**
* Returns headers and rows for csv, sorted by their timestamp.
@@ -99,7 +99,7 @@ const csvData = (metricHeaders, metricValues) => {
const rows = Object.keys(rowsByTimestamp)
.sort()
- .map(timestamp => {
+ .map((timestamp) => {
// force each row to have the same number of entries
rowsByTimestamp[timestamp].length = metricHeaders.length;
// add timestamp as the first entry
@@ -111,7 +111,7 @@ const csvData = (metricHeaders, metricValues) => {
// appearing inside a field must be escaped by preceding it with
// another double quote."
// https://tools.ietf.org/html/rfc4180#page-2
- const headers = metricHeaders.map(header => `"${header.replace(/"/g, '""')}"`);
+ const headers = metricHeaders.map((header) => `"${header.replace(/"/g, '""')}"`);
return {
headers: ['timestamp', ...headers],
@@ -125,12 +125,12 @@ const csvData = (metricHeaders, metricValues) => {
* @param {Object} graphData - Panel contents
* @returns {String}
*/
-export const graphDataToCsv = graphData => {
+export const graphDataToCsv = (graphData) => {
const delimiter = ',';
const br = '\r\n';
const { metrics = [], y_label: axisLabel } = graphData;
- const metricsWithResults = metrics.filter(metric => metric.result);
+ const metricsWithResults = metrics.filter((metric) => metric.result);
const metricHeaders = csvMetricHeaders(axisLabel, metricsWithResults);
const metricValues = csvMetricValues(metricsWithResults);
const { headers, rows } = csvData(metricHeaders, metricValues);
@@ -140,7 +140,7 @@ export const graphDataToCsv = graphData => {
}
const headerLine = headers.join(delimiter) + br;
- const lines = rows.map(row => row.join(delimiter));
+ const lines = rows.map((row) => row.join(delimiter));
return headerLine + lines.join(br) + br;
};
diff --git a/app/assets/javascripts/monitoring/requests/index.js b/app/assets/javascripts/monitoring/requests/index.js
index 28064361768..4a12ca06197 100644
--- a/app/assets/javascripts/monitoring/requests/index.js
+++ b/app/assets/javascripts/monitoring/requests/index.js
@@ -3,10 +3,10 @@ import statusCodes from '~/lib/utils/http_status';
import { backOff } from '~/lib/utils/common_utils';
import { PROMETHEUS_TIMEOUT } from '../constants';
-const cancellableBackOffRequest = makeRequestCallback =>
+const cancellableBackOffRequest = (makeRequestCallback) =>
backOff((next, stop) => {
makeRequestCallback()
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.NO_CONTENT) {
next();
} else {
@@ -16,19 +16,19 @@ const cancellableBackOffRequest = makeRequestCallback =>
// If the request is cancelled by axios
// then consider it as noop so that its not
// caught by subsequent catches
- .catch(thrown => (axios.isCancel(thrown) ? undefined : stop(thrown)));
+ .catch((thrown) => (axios.isCancel(thrown) ? undefined : stop(thrown)));
}, PROMETHEUS_TIMEOUT);
export const getDashboard = (dashboardEndpoint, params) =>
cancellableBackOffRequest(() => axios.get(dashboardEndpoint, { params })).then(
- axiosResponse => axiosResponse.data,
+ (axiosResponse) => axiosResponse.data,
);
export const getPrometheusQueryData = (prometheusEndpoint, params, opts) =>
cancellableBackOffRequest(() => axios.get(prometheusEndpoint, { params, ...opts }))
- .then(axiosResponse => axiosResponse.data)
- .then(prometheusResponse => prometheusResponse.data)
- .catch(error => {
+ .then((axiosResponse) => axiosResponse.data)
+ .then((prometheusResponse) => prometheusResponse.data)
+ .catch((error) => {
// Prometheus returns errors in specific cases
// https://prometheus.io/docs/prometheus/latest/querying/api/#format-overview
const { response = {} } = error;
diff --git a/app/assets/javascripts/monitoring/services/alerts_service.js b/app/assets/javascripts/monitoring/services/alerts_service.js
index a67675f1a3d..cb6dac7aa15 100644
--- a/app/assets/javascripts/monitoring/services/alerts_service.js
+++ b/app/assets/javascripts/monitoring/services/alerts_service.js
@@ -10,7 +10,7 @@ export default class AlertsService {
}
getAlerts() {
- return axios.get(this.alertsEndpoint).then(resp => mapAlert(resp.data));
+ return axios.get(this.alertsEndpoint).then((resp) => mapAlert(resp.data));
}
createAlert({ prometheus_metric_id, operator, threshold, runbookUrl }) {
@@ -21,23 +21,23 @@ export default class AlertsService {
threshold,
runbook_url: runbookUrl,
})
- .then(resp => mapAlert(resp.data));
+ .then((resp) => mapAlert(resp.data));
}
// eslint-disable-next-line class-methods-use-this
readAlert(alertPath) {
- return axios.get(alertPath).then(resp => mapAlert(resp.data));
+ return axios.get(alertPath).then((resp) => mapAlert(resp.data));
}
// eslint-disable-next-line class-methods-use-this
updateAlert(alertPath, { operator, threshold, runbookUrl }) {
return axios
.put(alertPath, { operator, threshold, runbook_url: runbookUrl })
- .then(resp => mapAlert(resp.data));
+ .then((resp) => mapAlert(resp.data));
}
// eslint-disable-next-line class-methods-use-this
deleteAlert(alertPath) {
- return axios.delete(alertPath).then(resp => resp.data);
+ return axios.delete(alertPath).then((resp) => resp.data);
}
}
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index e7391a4c9d1..44c200cdb54 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -114,7 +114,7 @@ export const fetchDashboard = ({ state, commit, dispatch, getters }) => {
}
return getDashboard(state.dashboardEndpoint, params)
- .then(response => {
+ .then((response) => {
dispatch('receiveMetricsDashboardSuccess', { response });
/**
* After the dashboard is fetched, there can be non-blocking invalid syntax
@@ -125,7 +125,7 @@ export const fetchDashboard = ({ state, commit, dispatch, getters }) => {
*/
dispatch('fetchDashboardValidationWarnings');
})
- .catch(error => {
+ .catch((error) => {
Sentry.captureException(error);
commit(types.SET_ALL_DASHBOARDS, error.response?.data?.all_dashboards ?? []);
@@ -185,9 +185,9 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
dispatch('fetchVariableMetricLabelValues', { defaultQueryParams });
const promises = [];
- state.dashboard.panelGroups.forEach(group => {
- group.panels.forEach(panel => {
- panel.metrics.forEach(metric => {
+ state.dashboard.panelGroups.forEach((group) => {
+ group.panels.forEach((panel) => {
+ panel.metrics.forEach((metric) => {
promises.push(dispatch('fetchPrometheusMetric', { metric, defaultQueryParams }));
});
});
@@ -231,10 +231,10 @@ export const fetchPrometheusMetric = (
commit(types.REQUEST_METRIC_RESULT, { metricId: metric.metricId });
return getPrometheusQueryData(metric.prometheusEndpointPath, queryParams)
- .then(data => {
+ .then((data) => {
commit(types.RECEIVE_METRIC_RESULT_SUCCESS, { metricId: metric.metricId, data });
})
- .catch(error => {
+ .catch((error) => {
Sentry.captureException(error);
commit(types.RECEIVE_METRIC_RESULT_FAILURE, { metricId: metric.metricId, error });
@@ -251,15 +251,15 @@ export const fetchDeploymentsData = ({ state, dispatch }) => {
}
return axios
.get(state.deploymentsEndpoint)
- .then(resp => resp.data)
- .then(response => {
+ .then((resp) => resp.data)
+ .then((response) => {
if (!response || !response.deployments) {
createFlash(s__('Metrics|Unexpected deployment data response from prometheus endpoint'));
}
dispatch('receiveDeploymentsDataSuccess', response.deployments);
})
- .catch(error => {
+ .catch((error) => {
Sentry.captureException(error);
dispatch('receiveDeploymentsDataFailure');
createFlash(s__('Metrics|There was an error getting deployment information.'));
@@ -285,10 +285,10 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
states: [ENVIRONMENT_AVAILABLE_STATE],
},
})
- .then(resp =>
+ .then((resp) =>
parseEnvironmentsResponse(resp.data?.project?.data?.environments, state.projectPath),
)
- .then(environments => {
+ .then((environments) => {
if (!environments) {
createFlash(
s__('Metrics|There was an error fetching the environments data, please try again'),
@@ -297,7 +297,7 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
dispatch('receiveEnvironmentsDataSuccess', environments);
})
- .catch(err => {
+ .catch((err) => {
Sentry.captureException(err);
dispatch('receiveEnvironmentsDataFailure');
createFlash(s__('Metrics|There was an error getting environments information.'));
@@ -326,16 +326,18 @@ export const fetchAnnotations = ({ state, dispatch, getters }) => {
startingFrom: start,
},
})
- .then(resp => resp.data?.project?.environments?.nodes?.[0].metricsDashboard?.annotations.nodes)
+ .then(
+ (resp) => resp.data?.project?.environments?.nodes?.[0].metricsDashboard?.annotations.nodes,
+ )
.then(parseAnnotationsResponse)
- .then(annotations => {
+ .then((annotations) => {
if (!annotations) {
createFlash(s__('Metrics|There was an error fetching annotations. Please try again.'));
}
dispatch('receiveAnnotationsSuccess', annotations);
})
- .catch(err => {
+ .catch((err) => {
Sentry.captureException(err);
dispatch('receiveAnnotationsFailure');
createFlash(s__('Metrics|There was an error getting annotations information.'));
@@ -363,7 +365,7 @@ export const fetchDashboardValidationWarnings = ({ state, dispatch, getters }) =
dashboardPath,
},
})
- .then(resp => resp.data?.project?.environments?.nodes?.[0]?.metricsDashboard)
+ .then((resp) => resp.data?.project?.environments?.nodes?.[0]?.metricsDashboard)
.then(({ schemaValidationWarnings } = {}) => {
const hasWarnings = schemaValidationWarnings && schemaValidationWarnings.length !== 0;
/**
@@ -372,7 +374,7 @@ export const fetchDashboardValidationWarnings = ({ state, dispatch, getters }) =
*/
dispatch('receiveDashboardValidationWarningsSuccess', hasWarnings || false);
})
- .catch(err => {
+ .catch((err) => {
Sentry.captureException(err);
dispatch('receiveDashboardValidationWarningsFailure');
createFlash(
@@ -437,9 +439,9 @@ export const duplicateSystemDashboard = ({ state }, payload) => {
return axios
.post(state.dashboardsEndpoint, params)
- .then(response => response.data)
- .then(data => data.dashboard)
- .catch(error => {
+ .then((response) => response.data)
+ .then((data) => data.dashboard)
+ .catch((error) => {
Sentry.captureException(error);
const { response } = error;
@@ -466,7 +468,7 @@ export const fetchVariableMetricLabelValues = ({ state, commit }, { defaultQuery
const { start_time, end_time } = defaultQueryParams;
const optionsRequests = [];
- state.variables.forEach(variable => {
+ state.variables.forEach((variable) => {
if (variable.type === VARIABLE_TYPES.metric_label_values) {
const { prometheusEndpointPath, label } = variable.options;
@@ -474,7 +476,7 @@ export const fetchVariableMetricLabelValues = ({ state, commit }, { defaultQuery
start_time,
end_time,
})
- .then(data => {
+ .then((data) => {
commit(types.UPDATE_VARIABLE_METRIC_LABEL_VALUES, { variable, label, data });
})
.catch(() => {
@@ -512,7 +514,7 @@ export const fetchPanelPreview = ({ state, commit, dispatch }, panelPreviewYml)
dispatch('fetchPanelPreviewMetrics');
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_PANEL_PREVIEW_FAILURE, extractErrorMessage(error));
});
};
@@ -535,10 +537,10 @@ export const fetchPanelPreviewMetrics = ({ state, commit }) => {
return getPrometheusQueryData(metric.prometheusEndpointPath, params, {
cancelToken: cancelTokenSource.token,
})
- .then(data => {
+ .then((data) => {
commit(types.RECEIVE_PANEL_PREVIEW_METRIC_RESULT_SUCCESS, { index, data });
})
- .catch(error => {
+ .catch((error) => {
Sentry.captureException(error);
commit(types.RECEIVE_PANEL_PREVIEW_METRIC_RESULT_FAILURE, { index, error });
diff --git a/app/assets/javascripts/monitoring/stores/embed_group/getters.js b/app/assets/javascripts/monitoring/stores/embed_group/getters.js
index 47db787dea5..8eddd830c58 100644
--- a/app/assets/javascripts/monitoring/stores/embed_group/getters.js
+++ b/app/assets/javascripts/monitoring/stores/embed_group/getters.js
@@ -1,2 +1,2 @@
export const metricsWithData = (state, getters, rootState, rootGetters) =>
- state.modules.map(module => rootGetters[`${module}/metricsWithData`]().length);
+ state.modules.map((module) => rootGetters[`${module}/metricsWithData`]().length);
diff --git a/app/assets/javascripts/monitoring/stores/getters.js b/app/assets/javascripts/monitoring/stores/getters.js
index 8ed83cf02fe..d6a04006264 100644
--- a/app/assets/javascripts/monitoring/stores/getters.js
+++ b/app/assets/javascripts/monitoring/stores/getters.js
@@ -5,8 +5,10 @@ import {
normalizeCustomDashboardPath,
} from './utils';
-const metricsIdsInPanel = panel =>
- panel.metrics.filter(metric => metric.metricId && metric.result).map(metric => metric.metricId);
+const metricsIdsInPanel = (panel) =>
+ panel.metrics
+ .filter((metric) => metric.metricId && metric.result)
+ .map((metric) => metric.metricId);
/**
* Returns a reference to the currently selected dashboard
@@ -17,8 +19,8 @@ const metricsIdsInPanel = panel =>
export const selectedDashboard = (state, getters) => {
const { allDashboards } = state;
return (
- allDashboards.find(d => d.path === getters.fullDashboardPath) ||
- allDashboards.find(d => d.default) ||
+ allDashboards.find((d) => d.path === getters.fullDashboardPath) ||
+ allDashboards.find((d) => d.default) ||
null
);
};
@@ -32,15 +34,15 @@ export const selectedDashboard = (state, getters) => {
* @returns {Function} A function that returns an array of
* states in all the metric in the dashboard or group.
*/
-export const getMetricStates = state => groupKey => {
+export const getMetricStates = (state) => (groupKey) => {
let groups = state.dashboard.panelGroups;
if (groupKey) {
- groups = groups.filter(group => group.key === groupKey);
+ groups = groups.filter((group) => group.key === groupKey);
}
const metricStates = groups.reduce((acc, group) => {
- group.panels.forEach(panel => {
- panel.metrics.forEach(metric => {
+ group.panels.forEach((panel) => {
+ panel.metrics.forEach((metric) => {
if (metric.state) {
acc.push(metric.state);
}
@@ -64,15 +66,15 @@ export const getMetricStates = state => groupKey => {
* metrics in the dashboard that contain results, optionally
* filtered by group key.
*/
-export const metricsWithData = state => groupKey => {
+export const metricsWithData = (state) => (groupKey) => {
let groups = state.dashboard.panelGroups;
if (groupKey) {
- groups = groups.filter(group => group.key === groupKey);
+ groups = groups.filter((group) => group.key === groupKey);
}
const res = [];
- groups.forEach(group => {
- group.panels.forEach(panel => {
+ groups.forEach((group) => {
+ group.panels.forEach((panel) => {
res.push(...metricsIdsInPanel(panel));
});
});
@@ -89,7 +91,7 @@ export const metricsWithData = state => groupKey => {
* https://gitlab.com/gitlab-org/gitlab/-/issues/28241
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27447
*/
-export const metricsSavedToDb = state => {
+export const metricsSavedToDb = (state) => {
const metricIds = [];
state.dashboard.panelGroups.forEach(({ panels }) => {
panels.forEach(({ metrics }) => {
@@ -111,8 +113,8 @@ export const metricsSavedToDb = state => {
* @param {Object} state
* @returns {Array} List of environments
*/
-export const filteredEnvironments = state =>
- state.environments.filter(env =>
+export const filteredEnvironments = (state) =>
+ state.environments.filter((env) =>
env.name.toLowerCase().includes((state.environmentsSearchTerm || '').trim().toLowerCase()),
);
@@ -125,7 +127,7 @@ export const filteredEnvironments = state =>
* @param {Object} state
* @returns {Array} modified array of links
*/
-export const linksWithMetadata = state => {
+export const linksWithMetadata = (state) => {
const metadata = {
timeRange: state.timeRange,
};
@@ -152,7 +154,7 @@ export const linksWithMetadata = state => {
* in the format of {variables[key1]=value1, variables[key2]=value2}
*/
-export const getCustomVariablesParams = state =>
+export const getCustomVariablesParams = (state) =>
state.variables.reduce((acc, variable) => {
const { name, value } = variable;
if (value !== null) {
@@ -168,5 +170,5 @@ export const getCustomVariablesParams = state =>
* @param {Object} state
* @returns {String} full dashboard path
*/
-export const fullDashboardPath = state =>
+export const fullDashboardPath = (state) =>
normalizeCustomDashboardPath(state.currentDashboard, state.customDashboardBasePath);
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index 09a5861b475..5c5a7d03b97 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -15,9 +15,9 @@ import { optionsFromSeriesData } from './variable_mapping';
*/
const findMetricInDashboard = (metricId, dashboard) => {
let res = null;
- dashboard.panelGroups.forEach(group => {
- group.panels.forEach(panel => {
- panel.metrics.forEach(metric => {
+ dashboard.panelGroups.forEach((group) => {
+ group.panels.forEach((panel) => {
+ panel.metrics.forEach((metric) => {
if (metric.metricId === metricId) {
res = metric;
}
@@ -31,7 +31,7 @@ const findMetricInDashboard = (metricId, dashboard) => {
* Maps a backened error state to a `metricStates` constant
* @param {Object} error - Error from backend response
*/
-const emptyStateFromError = error => {
+const emptyStateFromError = (error) => {
if (!error) {
return metricStates.UNKNOWN_ERROR;
}
@@ -53,7 +53,7 @@ const emptyStateFromError = error => {
return metricStates.UNKNOWN_ERROR;
};
-export const metricStateFromData = data => {
+export const metricStateFromData = (data) => {
if (data?.result?.length) {
const result = normalizeQueryResponseData(data);
return { state: metricStates.OK, result: Object.freeze(result) };
@@ -93,7 +93,7 @@ export default {
state.isUpdatingStarredValue = true;
},
[types.RECEIVE_DASHBOARD_STARRING_SUCCESS](state, { selectedDashboard, newStarredValue }) {
- const index = state.allDashboards.findIndex(d => d === selectedDashboard);
+ const index = state.allDashboards.findIndex((d) => d === selectedDashboard);
state.isUpdatingStarredValue = false;
@@ -196,7 +196,7 @@ export default {
state.showErrorBanner = enabled;
},
[types.SET_PANEL_GROUP_METRICS](state, payload) {
- const panelGroup = state.dashboard.panelGroups.find(pg => payload.key === pg.key);
+ const panelGroup = state.dashboard.panelGroups.find((pg) => payload.key === pg.key);
panelGroup.panels = payload.panels;
},
[types.SET_ENVIRONMENTS_FILTER](state, searchTerm) {
@@ -207,7 +207,7 @@ export default {
state.expandedPanel.panel = panel;
},
[types.UPDATE_VARIABLE_VALUE](state, { name, value }) {
- const variable = state.variables.find(v => v.name === name);
+ const variable = state.variables.find((v) => v.name === name);
if (variable) {
Object.assign(variable, {
value,
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index df7f22e622f..36e5a135d59 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -40,7 +40,7 @@ export const uniqMetricsId = ({ metric_id, id }) => `${metric_id || NOT_IN_DB_PR
* @param {String} str String with leading slash
* @returns {String}
*/
-export const removeLeadingSlash = str => (str || '').replace(/^\/+/, '');
+export const removeLeadingSlash = (str) => (str || '').replace(/^\/+/, '');
/**
* GraphQL environments API returns only id and name.
@@ -52,7 +52,7 @@ export const removeLeadingSlash = str => (str || '').replace(/^\/+/, '');
* @returns {Array}
*/
export const parseEnvironmentsResponse = (response = [], projectPath) =>
- (response || []).map(env => {
+ (response || []).map((env) => {
const id = getIdFromGraphQLId(env.id);
return {
...env,
@@ -75,11 +75,11 @@ export const parseEnvironmentsResponse = (response = [], projectPath) =>
* @param {Array} response annotations response
* @returns {Array} parsed responses
*/
-export const parseAnnotationsResponse = response => {
+export const parseAnnotationsResponse = (response) => {
if (!response) {
return [];
}
- return response.map(annotation => ({
+ return response.map((annotation) => ({
...annotation,
startingAt: new Date(annotation.startingAt),
endingAt: annotation.endingAt ? new Date(annotation.endingAt) : null,
@@ -99,7 +99,7 @@ export const parseAnnotationsResponse = response => {
* @param {Array} metrics - Array of prometheus metrics
* @returns {Object}
*/
-const mapToMetricsViewModel = metrics =>
+const mapToMetricsViewModel = (metrics) =>
metrics.map(({ label, id, metric_id, query_range, prometheus_endpoint_path, ...metric }) => ({
label,
queryRange: query_range,
@@ -230,7 +230,7 @@ const mapToPanelGroupViewModel = ({ group = '', panels = [] }, i) => {
* @param {Object} timeRange
* @returns {Object}
*/
-export const convertToGrafanaTimeRange = timeRange => {
+export const convertToGrafanaTimeRange = (timeRange) => {
const timeRangeType = getRangeType(timeRange);
if (timeRangeType === DATETIME_RANGE_TYPES.fixed) {
return {
@@ -272,7 +272,7 @@ export const convertTimeRanges = (timeRange, type) => {
* @param {Object} metadata
* @returns {Function}
*/
-export const addDashboardMetaDataToLink = metadata => link => {
+export const addDashboardMetaDataToLink = (metadata) => (link) => {
let modifiedLink = { ...link };
if (metadata.timeRange) {
modifiedLink = {
@@ -307,7 +307,7 @@ export const mapToDashboardViewModel = ({
// Prometheus Results Parsing
-const dateTimeFromUnixTime = unixTime => new Date(unixTime * 1000).toISOString();
+const dateTimeFromUnixTime = (unixTime) => new Date(unixTime * 1000).toISOString();
const mapScalarValue = ([unixTime, value]) => [dateTimeFromUnixTime(unixTime), Number(value)];
@@ -324,7 +324,7 @@ const mapStringValue = ([unixTime, value]) => [dateTimeFromUnixTime(unixTime), v
* @param {array} result
* @returns {array}
*/
-const normalizeScalarResult = result => [
+const normalizeScalarResult = (result) => [
{
metric: {},
value: mapScalarValue(result),
@@ -344,7 +344,7 @@ const normalizeScalarResult = result => [
* @param {array} result
* @returns {array}
*/
-const normalizeStringResult = result => [
+const normalizeStringResult = (result) => [
{
metric: {},
value: mapStringValue(result),
@@ -379,7 +379,7 @@ const normalizeStringResult = result => [
* @param {array} result
* @returns {array}
*/
-const normalizeVectorResult = result =>
+const normalizeVectorResult = (result) =>
result.map(({ metric, value }) => {
const scalar = mapScalarValue(value);
// Add a single element to `values`, to support matrix
@@ -407,7 +407,7 @@ const normalizeVectorResult = result =>
* @param {array} result
* @returns {object} Normalized result.
*/
-const normalizeResultMatrix = result =>
+const normalizeResultMatrix = (result) =>
result.map(({ metric, values }) => {
const mappedValues = values.map(mapScalarValue);
return {
@@ -440,7 +440,7 @@ const normalizeResultMatrix = result =>
* ]
*
*/
-export const normalizeQueryResponseData = data => {
+export const normalizeQueryResponseData = (data) => {
const { resultType, result } = data;
if (resultType === 'vector') {
return normalizeVectorResult(result);
@@ -466,7 +466,7 @@ export const normalizeQueryResponseData = data => {
* @param {String} name Variable key that needs to be prefixed
* @returns {String}
*/
-export const addPrefixToCustomVariableParams = name => `variables[${name}]`;
+export const addPrefixToCustomVariableParams = (name) => `variables[${name}]`;
/**
* Normalize custom dashboard paths. This method helps support
diff --git a/app/assets/javascripts/monitoring/stores/variable_mapping.js b/app/assets/javascripts/monitoring/stores/variable_mapping.js
index 4ae5cf04ff9..c9e0e383582 100644
--- a/app/assets/javascripts/monitoring/stores/variable_mapping.js
+++ b/app/assets/javascripts/monitoring/stores/variable_mapping.js
@@ -21,7 +21,7 @@ import { VARIABLE_TYPES } from '../constants';
* @param {String|Object} simpleTextVar
* @returns {Object}
*/
-const textSimpleVariableParser = simpleTextVar => ({
+const textSimpleVariableParser = (simpleTextVar) => ({
type: VARIABLE_TYPES.text,
label: null,
value: simpleTextVar,
@@ -34,7 +34,7 @@ const textSimpleVariableParser = simpleTextVar => ({
* @param {Object} advTextVar
* @returns {Object}
*/
-const textAdvancedVariableParser = advTextVar => ({
+const textAdvancedVariableParser = (advTextVar) => ({
type: VARIABLE_TYPES.text,
label: advTextVar.label,
value: advTextVar.options.default_value,
@@ -62,9 +62,9 @@ const normalizeVariableValues = ({ default: defaultOpt = false, text, value = nu
* @param {Object} advVariable advanced custom variable
* @returns {Object}
*/
-const customAdvancedVariableParser = advVariable => {
+const customAdvancedVariableParser = (advVariable) => {
const values = (advVariable?.options?.values ?? []).map(normalizeVariableValues);
- const defaultValue = values.find(opt => opt.default === true) || values[0];
+ const defaultValue = values.find((opt) => opt.default === true) || values[0];
return {
type: VARIABLE_TYPES.custom,
label: advVariable.label,
@@ -82,7 +82,7 @@ const customAdvancedVariableParser = advVariable => {
* @param {String} opt option from simple custom variable
* @returns {Object}
*/
-export const parseSimpleCustomValues = opt => ({ text: opt, value: opt });
+export const parseSimpleCustomValues = (opt) => ({ text: opt, value: opt });
/**
* Custom simple variables are rendered as dropdown elements in the dashboard
@@ -96,7 +96,7 @@ export const parseSimpleCustomValues = opt => ({ text: opt, value: opt });
* @param {Array} customVariable array of options
* @returns {Object}
*/
-const customSimpleVariableParser = simpleVar => {
+const customSimpleVariableParser = (simpleVar) => {
const values = (simpleVar || []).map(parseSimpleCustomValues);
return {
type: VARIABLE_TYPES.custom,
@@ -126,7 +126,7 @@ const metricLabelValuesVariableParser = ({ label, options = {} }) => ({
* @param {Array|Object} customVar Array if simple, object if advanced
* @returns {Boolean} true if simple, false if advanced
*/
-const isSimpleCustomVariable = customVar => Array.isArray(customVar);
+const isSimpleCustomVariable = (customVar) => Array.isArray(customVar);
/**
* This method returns a parser based on the type of the variable.
@@ -137,7 +137,7 @@ const isSimpleCustomVariable = customVar => Array.isArray(customVar);
* @param {Array|Object} variable
* @return {Function} parser method
*/
-const getVariableParser = variable => {
+const getVariableParser = (variable) => {
if (isString(variable)) {
return textSimpleVariableParser;
} else if (isSimpleCustomVariable(variable)) {
@@ -200,7 +200,7 @@ export const parseTemplatingVariables = (ymlVariables = {}) =>
*/
export const mergeURLVariables = (parsedYmlVariables = []) => {
const varsFromURL = templatingVariablesFromUrl();
- parsedYmlVariables.forEach(variable => {
+ parsedYmlVariables.forEach((variable) => {
const { name } = variable;
if (Object.prototype.hasOwnProperty.call(varsFromURL, name)) {
Object.assign(variable, { value: varsFromURL[name] });
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index a4c5a881fae..01cae7127e5 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -81,15 +81,15 @@ export const graphDataValidatorForValues = (isValues, graphData) => {
const responseValueKeyName = isValues ? 'value' : 'values';
return (
Array.isArray(graphData.metrics) &&
- graphData.metrics.filter(query => {
+ graphData.metrics.filter((query) => {
if (Array.isArray(query.result)) {
return (
- query.result.filter(res => Array.isArray(res[responseValueKeyName])).length ===
+ query.result.filter((res) => Array.isArray(res[responseValueKeyName])).length ===
query.result.length
);
}
return false;
- }).length === graphData.metrics.filter(query => query.result).length
+ }).length === graphData.metrics.filter((query) => query.result).length
);
};
@@ -106,7 +106,7 @@ const isClusterHealthBoard = () => (document.body.dataset.page || '').includes('
* @param {String} chart link that will be sent as a property for the event
* @return {Object} config object for event tracking
*/
-export const generateLinkToChartOptions = chartLink => {
+export const generateLinkToChartOptions = (chartLink) => {
const isCLusterHealthBoard = isClusterHealthBoard();
const category = isCLusterHealthBoard
@@ -124,7 +124,7 @@ export const generateLinkToChartOptions = chartLink => {
* @param {String} chart title that will be sent as a property for the event
* @return {Object} config object for event tracking
*/
-export const downloadCSVOptions = title => {
+export const downloadCSVOptions = (title) => {
const isCLusterHealthBoard = isClusterHealthBoard();
const category = isCLusterHealthBoard
@@ -157,7 +157,7 @@ export const getAddMetricTrackingOptions = () => ({
* @param {Object} graphData the graph data response from a prometheus request
* @returns {boolean} true if the data is valid
*/
-export const graphDataValidatorForAnomalyValues = graphData => {
+export const graphDataValidatorForAnomalyValues = (graphData) => {
const anomalySeriesCount = 3; // metric, upper, lower
return (
graphData.metrics &&
@@ -186,7 +186,7 @@ export const timeRangeFromUrl = (search = window.location.search) => {
* @param {String} label label for the template variable
* @returns {String}
*/
-export const addPrefixToLabel = label => `${VARIABLE_PREFIX}${label}`;
+export const addPrefixToLabel = (label) => `${VARIABLE_PREFIX}${label}`;
/**
* Before the templating variables are passed to the backend the
@@ -197,7 +197,7 @@ export const addPrefixToLabel = label => `${VARIABLE_PREFIX}${label}`;
* @param {String} label label to remove prefix from
* @returns {String}
*/
-export const removePrefixFromLabel = label =>
+export const removePrefixFromLabel = (label) =>
(label || '').replace(new RegExp(`^${VARIABLE_PREFIX}`), '');
/**
@@ -210,7 +210,7 @@ export const removePrefixFromLabel = label =>
* @param {Object} variables
* @returns {Object}
*/
-export const convertVariablesForURL = variables =>
+export const convertVariablesForURL = (variables) =>
variables.reduce((acc, { name, value }) => {
if (value !== null) {
acc[addPrefixToLabel(name)] = value;
@@ -241,7 +241,7 @@ export const templatingVariablesFromUrl = (search = window.location.search) => {
*
* @param {Object} variables user defined variables
*/
-export const setCustomVariablesFromUrl = variables => {
+export const setCustomVariablesFromUrl = (variables) => {
// prep the variables to append to URL
const parsedVariables = convertVariablesForURL(variables);
// update the URL
@@ -353,7 +353,7 @@ export const panelToUrl = (
* @param {Array} values data points
* @returns {Number}
*/
-const metricValueMapper = values => values[0]?.[1];
+const metricValueMapper = (values) => values[0]?.[1];
/**
* Get the metric name from metric object
@@ -364,7 +364,7 @@ const metricValueMapper = values => values[0]?.[1];
* @param {Object} metric metric object
* @returns {String}
*/
-const metricNameMapper = metric => Object.values(metric)?.[0];
+const metricNameMapper = (metric) => Object.values(metric)?.[0];
/**
* Parse metric object to extract metric value and name in
diff --git a/app/assets/javascripts/monitoring/validators.js b/app/assets/javascripts/monitoring/validators.js
index c6b323f6360..05a9d8b9db5 100644
--- a/app/assets/javascripts/monitoring/validators.js
+++ b/app/assets/javascripts/monitoring/validators.js
@@ -1,6 +1,6 @@
import { isSafeURL } from '~/lib/utils/url_utility';
-const isRunbookUrlValid = runbookUrl => {
+const isRunbookUrlValid = (runbookUrl) => {
if (!runbookUrl) {
return true;
}
@@ -21,7 +21,7 @@ const isRunbookUrlValid = runbookUrl => {
// }
// }
export function alertsValidator(value) {
- return Object.keys(value).every(key => {
+ return Object.keys(value).every((key) => {
const alert = value[key];
return (
alert.alert_path &&
@@ -49,7 +49,7 @@ export function alertsValidator(value) {
// ]
export function queriesValidator(value) {
return value.every(
- query =>
+ (query) =>
query.metricId && typeof query.metricId === 'string' && typeof query.label === 'string',
);
}
diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js
index 2be7cc951fc..ab88a610469 100644
--- a/app/assets/javascripts/mr_notes/init_notes.js
+++ b/app/assets/javascripts/mr_notes/init_notes.js
@@ -33,7 +33,7 @@ export default () => {
computed: {
...mapGetters(['discussionTabCounter']),
...mapState({
- activeTab: state => state.page.activeTab,
+ activeTab: (state) => state.page.activeTab,
}),
isShowTabActive() {
return this.activeTab === 'show';
diff --git a/app/assets/javascripts/mr_notes/stores/getters.js b/app/assets/javascripts/mr_notes/stores/getters.js
index 245443d7ecf..556254486db 100644
--- a/app/assets/javascripts/mr_notes/stores/getters.js
+++ b/app/assets/javascripts/mr_notes/stores/getters.js
@@ -1,7 +1,7 @@
// Note: this getter is important because
// `noteableData` is namespaced under `notes` for `~/mr_notes/stores`
// while `noteableData` is directly available as `state.noteableData` for `~/notes/stores`
-export const getNoteableData = state => state.notes.noteableData;
+export const getNoteableData = (state) => state.notes.noteableData;
export default {
isLoggedIn(state, getters) {
diff --git a/app/assets/javascripts/mr_popover/components/mr_popover.vue b/app/assets/javascripts/mr_popover/components/mr_popover.vue
index bf810978648..2058f0c9b76 100644
--- a/app/assets/javascripts/mr_popover/components/mr_popover.vue
+++ b/app/assets/javascripts/mr_popover/components/mr_popover.vue
@@ -72,7 +72,7 @@ export default {
apollo: {
mergeRequest: {
query,
- update: data => data.project.mergeRequest,
+ update: (data) => data.project.mergeRequest,
variables() {
const { projectPath, mergeRequestIID } = this;
diff --git a/app/assets/javascripts/mr_popover/index.js b/app/assets/javascripts/mr_popover/index.js
index 18c0e201300..03ddfd13d50 100644
--- a/app/assets/javascripts/mr_popover/index.js
+++ b/app/assets/javascripts/mr_popover/index.js
@@ -42,7 +42,7 @@ const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) =>
}, 200); // 200ms delay so not every mouseover triggers Popover + API Call
};
-export default elements => {
+export default (elements) => {
const mrLinks = elements || [...document.querySelectorAll('.gfm-merge_request')];
if (mrLinks.length > 0) {
Vue.use(VueApollo);
@@ -52,7 +52,7 @@ export default elements => {
});
const listenerAddedAttr = 'data-mr-listener-added';
- mrLinks.forEach(el => {
+ mrLinks.forEach((el) => {
const { projectPath, mrTitle, iid } = el.dataset;
if (!el.getAttribute(listenerAddedAttr) && projectPath && mrTitle && iid) {
diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js
index 8e123c14814..e668b492ebe 100644
--- a/app/assets/javascripts/namespace_select.js
+++ b/app/assets/javascripts/namespace_select.js
@@ -25,7 +25,7 @@ export default class NamespaceSelect {
return `${selected.kind}: ${selected.full_path}`;
},
data(term, dataCallback) {
- return Api.namespaces(term, namespaces => {
+ return Api.namespaces(term, (namespaces) => {
if (isFilter) {
const anyNamespace = {
text: __('Any namespace'),
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index 3ea597a08d3..3574fc47088 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -66,12 +66,12 @@ export default class BranchGraph {
collectParents() {
const ref = this.commits;
const results = [];
- ref.forEach(c => {
+ ref.forEach((c) => {
this.mtime = Math.max(this.mtime, c.time);
this.mspace = Math.max(this.mspace, c.space);
const ref1 = c.parents;
const results1 = [];
- ref1.forEach(p => {
+ ref1.forEach((p) => {
this.parents[p[0]] = true;
results1.push((this.mspace = Math.max(this.mspace, p[1])));
});
@@ -243,11 +243,11 @@ export default class BranchGraph {
})
.click(() => window.open(options.commit_url.replace('%s', commit.id), '_blank'))
.hover(
- function() {
+ function () {
this.tooltip = r.commitTooltip(x + 5, y, commit);
return top.push(this.tooltip.insertBefore(this));
},
- function() {
+ function () {
return this.tooltip && this.tooltip.remove() && delete this.tooltip;
},
);
diff --git a/app/assets/javascripts/new_branch_form.js b/app/assets/javascripts/new_branch_form.js
index 9d064894433..d93db7399e6 100644
--- a/app/assets/javascripts/new_branch_form.js
+++ b/app/assets/javascripts/new_branch_form.js
@@ -53,14 +53,14 @@ export default class NewBranchForm {
const { indexOf } = [];
this.branchNameError.empty();
- const unique = function(values, value) {
+ const unique = function (values, value) {
if (indexOf.call(values, value) === -1) {
values.push(value);
}
return values;
};
- const formatter = function(values, restriction) {
- const formatted = values.map(value => {
+ const formatter = function (values, restriction) {
+ const formatted = values.map((value) => {
switch (false) {
case !/\s/.test(value):
return 'spaces';
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index c04f2a2d465..d1d5ae5265a 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -77,11 +77,11 @@ function renderKatex(t) {
}
return [text, numInline > 0];
}
-renderer.paragraph = t => {
+renderer.paragraph = (t) => {
const [text, inline] = renderKatex(t);
return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`;
};
-renderer.listitem = t => {
+renderer.listitem = (t) => {
const [text, inline] = renderKatex(t);
return `<li class="${inline ? 'inline-katex' : ''}">${text}</li>`;
};
diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue
index 113d8cfc435..5f7ef4a4377 100644
--- a/app/assets/javascripts/notebook/cells/output/index.vue
+++ b/app/assets/javascripts/notebook/cells/output/index.vue
@@ -2,6 +2,7 @@
import CodeOutput from '../code/index.vue';
import HtmlOutput from './html.vue';
import ImageOutput from './image.vue';
+import LatexOutput from './latex.vue';
export default {
props: {
@@ -35,6 +36,8 @@ export default {
return 'image/jpeg';
} else if (output.data['text/html']) {
return 'text/html';
+ } else if (output.data['text/latex']) {
+ return 'text/latex';
} else if (output.data['image/svg+xml']) {
return 'image/svg+xml';
}
@@ -59,6 +62,8 @@ export default {
return ImageOutput;
} else if (output.data['text/html']) {
return HtmlOutput;
+ } else if (output.data['text/latex']) {
+ return LatexOutput;
} else if (output.data['image/svg+xml']) {
return HtmlOutput;
}
diff --git a/app/assets/javascripts/notebook/cells/output/latex.vue b/app/assets/javascripts/notebook/cells/output/latex.vue
new file mode 100644
index 00000000000..db9e61dce82
--- /dev/null
+++ b/app/assets/javascripts/notebook/cells/output/latex.vue
@@ -0,0 +1,45 @@
+<script>
+import 'mathjax/es5/tex-svg';
+import Prompt from '../prompt.vue';
+
+export default {
+ name: 'LatexOutput',
+ components: {
+ Prompt,
+ },
+ props: {
+ count: {
+ type: Number,
+ required: true,
+ },
+ rawCode: {
+ type: String,
+ required: true,
+ },
+ index: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ code() {
+ // MathJax will not parse out the inline delimeters "$$" correctly
+ // so we remove them from the raw code itself
+ const parsedCode = this.rawCode.replace(/\$\$/g, '');
+ const svg = window.MathJax.tex2svg(parsedCode);
+
+ // NOTE: This is used with `v-html` and not `v-safe-html` due to an
+ // issue with dompurify stripping out xlink attributes from use tags
+ return svg.outerHTML;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="output">
+ <prompt type="Out" :count="count" :show-output="index === 0" />
+ <!-- eslint-disable -->
+ <div ref="maths" v-html="code"></div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 9a887021e5d..857e5a34db6 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -108,10 +108,7 @@ export default class Notes {
// We are in the Merge Requests page so we need another edit form for Changes tab
if (getPagePath(1) === 'merge_requests') {
- $('.note-edit-form')
- .clone()
- .addClass('mr-note-edit-form')
- .insertAfter('.note-edit-form');
+ $('.note-edit-form').clone().addClass('mr-note-edit-form').insertAfter('.note-edit-form');
}
const hash = getLocationHash();
@@ -348,7 +345,7 @@ export default class Notes {
votesBlock = $('.js-awards-block').eq(0);
loadAwardsHandler()
- .then(awardsHandler => {
+ .then((awardsHandler) => {
awardsHandler.addAwardToEmojiBar(votesBlock, noteEntity.commands_changes.emoji_award);
awardsHandler.scrollToAwards();
})
@@ -427,12 +424,7 @@ export default class Notes {
} else if (Notes.isUpdatedNote(noteEntity, $note)) {
// The server can send the same update multiple times so we need to make sure to only update once per actual update.
const isEditing = $note.hasClass('is-editing');
- const initialContent = normalizeNewlines(
- $note
- .find('.original-note-content')
- .text()
- .trim(),
- );
+ const initialContent = normalizeNewlines($note.find('.original-note-content').text().trim());
const $textarea = $note.find('.js-note-text');
const currentContent = $textarea.val();
// There can be CRLF vs LF mismatches if we don't sanitize and compare the same way
@@ -541,14 +533,8 @@ export default class Notes {
form.find('.js-errors').remove();
// reset text and preview
form.find('.js-md-write-button').click();
- form
- .find('.js-note-text')
- .val('')
- .trigger('input');
- form
- .find('.js-note-text')
- .data('autosave')
- .reset();
+ form.find('.js-note-text').val('').trigger('input');
+ form.find('.js-note-text').data('autosave').reset();
const event = document.createEvent('Event');
event.initEvent('autosize:update', true, false);
@@ -690,10 +676,7 @@ export default class Notes {
}
checkContentToAllowEditing($el) {
- const initialContent = $el
- .find('.original-note-content')
- .text()
- .trim();
+ const initialContent = $el.find('.original-note-content').text().trim();
const currentContent = $el.find('.js-note-text').val();
let isAllowed = true;
@@ -877,10 +860,7 @@ export default class Notes {
const form = this.cleanForm(this.formClone.clone());
const replyLink = $(target).closest('.js-discussion-reply-button');
// insert the form after the button
- replyLink
- .closest('.discussion-reply-holder')
- .hide()
- .after(form);
+ replyLink.closest('.discussion-reply-holder').hide().after(form);
// show the form
return this.setupDiscussionNoteForm(replyLink, form);
}
@@ -1069,10 +1049,7 @@ export default class Notes {
const row = form.closest('tr');
const glForm = form.data('glForm');
glForm.destroy();
- form
- .find('.js-note-text')
- .data('autosave')
- .reset();
+ form.find('.js-note-text').data('autosave').reset();
// show the reply button (will only work for replies)
form.prev('.discussion-reply-holder').show();
if (row.is('.js-temp-notes-holder')) {
@@ -1181,16 +1158,10 @@ export default class Notes {
this.glForm = new GLForm($editForm.find('form'), this.enableGFM);
- $editForm
- .find('form')
- .attr('action', `${postUrl}?html=true`)
- .attr('data-remote', 'true');
+ $editForm.find('form').attr('action', `${postUrl}?html=true`).attr('data-remote', 'true');
$editForm.find('.js-form-target-id').val(targetId);
$editForm.find('.js-form-target-type').val(targetType);
- $editForm
- .find('.js-note-text')
- .focus()
- .val(originalContent);
+ $editForm.find('.js-note-text').focus().val(originalContent);
$editForm.find('.js-md-write-button').trigger('click');
$editForm.find('.referenced-users').hide();
}
@@ -1306,9 +1277,7 @@ export default class Notes {
* intrusive.
*/
collapseLongCommitList() {
- const systemNotes = $('#notes-list')
- .find('li.system-note')
- .has('ul');
+ const systemNotes = $('#notes-list').find('li.system-note').has('ul');
$.each(systemNotes, (index, systemNote) => {
const $systemNote = $(systemNote);
@@ -1365,11 +1334,7 @@ export default class Notes {
// There can be CRLF vs LF mismatches if we don't sanitize and compare the same way
const sanitizedNoteEntityText = normalizeNewlines(noteEntity.note.trim());
const currentNoteText = normalizeNewlines(
- $note
- .find('.original-note-content')
- .first()
- .text()
- .trim(),
+ $note.find('.original-note-content').first().text().trim(),
);
return sanitizedNoteEntityText !== currentNoteText;
}
@@ -1431,7 +1396,7 @@ export default class Notes {
let tempFormContent;
// Identify executed quick actions from `formContent`
- const executedCommands = availableQuickActions.filter(command => {
+ const executedCommands = availableQuickActions.filter((command) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(formContent);
});
@@ -1545,10 +1510,7 @@ export default class Notes {
let $form = $submitBtn.parents('form');
const $closeBtn = $form.find('.js-note-target-close');
const isDiscussionNote =
- $submitBtn
- .parent()
- .find('li.droplab-item-selected')
- .attr('id') === 'discussion';
+ $submitBtn.parent().find('li.droplab-item-selected').attr('id') === 'discussion';
const isMainForm = $form.hasClass('js-main-target-form');
const isDiscussionForm = $form.hasClass('js-discussion-note-form');
const isDiscussionResolve = $submitBtn.hasClass('js-comment-resolve-button');
@@ -1621,7 +1583,7 @@ export default class Notes {
// Make request to submit comment on server
return axios
.post(`${formAction}?html=true`, formData)
- .then(res => {
+ .then((res) => {
const note = res.data;
$submitBtn.prop('disabled', false);
diff --git a/app/assets/javascripts/notes/components/comment_field_layout.vue b/app/assets/javascripts/notes/components/comment_field_layout.vue
new file mode 100644
index 00000000000..aaf64702ffd
--- /dev/null
+++ b/app/assets/javascripts/notes/components/comment_field_layout.vue
@@ -0,0 +1,69 @@
+<script>
+import EmailParticipantsWarning from './email_participants_warning.vue';
+import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
+
+const DEFAULT_NOTEABLE_TYPE = 'Issue';
+
+export default {
+ components: {
+ EmailParticipantsWarning,
+ NoteableWarning,
+ },
+ props: {
+ noteableData: {
+ type: Object,
+ required: true,
+ },
+ noteableType: {
+ type: String,
+ required: false,
+ default: DEFAULT_NOTEABLE_TYPE,
+ },
+ withAlertContainer: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ isLocked() {
+ return Boolean(this.noteableData.discussion_locked);
+ },
+ isConfidential() {
+ return Boolean(this.noteableData.confidential);
+ },
+ hasWarning() {
+ return this.isConfidential || this.isLocked;
+ },
+ emailParticipants() {
+ return this.noteableData.issue_email_participants?.map(({ email }) => email) || [];
+ },
+ },
+};
+</script>
+<template>
+ <div
+ class="comment-warning-wrapper gl-border-solid gl-border-1 gl-rounded-base gl-border-gray-100"
+ >
+ <div
+ v-if="withAlertContainer"
+ class="error-alert"
+ data-testid="comment-field-alert-container"
+ ></div>
+ <noteable-warning
+ v-if="hasWarning"
+ class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-100 gl-rounded-base gl-rounded-bottom-left-none gl-rounded-bottom-right-none"
+ :is-locked="isLocked"
+ :is-confidential="isConfidential"
+ :noteable-type="noteableType"
+ :locked-noteable-docs-path="noteableData.locked_discussion_docs_path"
+ :confidential-noteable-docs-path="noteableData.confidential_issues_docs_path"
+ />
+ <slot></slot>
+ <email-participants-warning
+ v-if="emailParticipants.length"
+ class="gl-border-t-1 gl-border-t-solid gl-border-t-gray-100 gl-rounded-base gl-rounded-top-left-none! gl-rounded-top-right-none!"
+ :emails="emailParticipants"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 0363173f912..111af977ec5 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -17,17 +17,17 @@ import {
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import * as constants from '../constants';
import eventHub from '../event_hub';
-import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
import markdownField from '~/vue_shared/components/markdown/field.vue';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.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 issuableStateMixin from '../mixins/issuable_state';
+import CommentFieldLayout from './comment_field_layout.vue';
export default {
name: 'CommentForm',
components: {
- NoteableWarning,
noteSignedOutWidget,
discussionLockedWidget,
markdownField,
@@ -35,8 +35,9 @@ export default {
GlButton,
TimelineEntryItem,
GlIcon,
+ CommentFieldLayout,
},
- mixins: [issuableStateMixin],
+ mixins: [glFeatureFlagsMixin(), issuableStateMixin],
props: {
noteableType: {
type: String,
@@ -286,6 +287,9 @@ export default {
Autosize.update(this.$refs.textarea);
});
},
+ hasEmailParticipants() {
+ return this.getNoteableData.issue_email_participants?.length;
+ },
},
};
</script>
@@ -308,46 +312,41 @@ export default {
</div>
<div class="timeline-content timeline-content-form">
<form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form">
- <div class="error-alert"></div>
-
- <noteable-warning
- v-if="hasWarning(getNoteableData)"
- :is-locked="isLocked(getNoteableData)"
- :is-confidential="isConfidential(getNoteableData)"
+ <comment-field-layout
+ :with-alert-container="true"
+ :noteable-data="getNoteableData"
:noteable-type="noteableType"
- :locked-noteable-docs-path="lockedIssueDocsPath"
- :confidential-noteable-docs-path="confidentialIssueDocsPath"
- />
-
- <markdown-field
- ref="markdownField"
- :is-submitting="isSubmitting"
- :markdown-preview-path="markdownPreviewPath"
- :markdown-docs-path="markdownDocsPath"
- :quick-actions-docs-path="quickActionsDocsPath"
- :add-spacing-classes="false"
- :textarea-value="note"
>
- <textarea
- id="note-body"
- ref="textarea"
- slot="textarea"
- v-model="note"
- dir="auto"
- :disabled="isSubmitting"
- name="note[note]"
- class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
- data-qa-selector="comment_field"
- data-testid="comment-field"
- data-supports-quick-actions="true"
- :aria-label="__('Description')"
- :placeholder="__('Write a comment or drag your files here…')"
- @keydown.up="editCurrentUserLastNote()"
- @keydown.meta.enter="handleSave()"
- @keydown.ctrl.enter="handleSave()"
- ></textarea>
- </markdown-field>
-
+ <markdown-field
+ ref="markdownField"
+ :is-submitting="isSubmitting"
+ :markdown-preview-path="markdownPreviewPath"
+ :markdown-docs-path="markdownDocsPath"
+ :quick-actions-docs-path="quickActionsDocsPath"
+ :add-spacing-classes="false"
+ :textarea-value="note"
+ >
+ <template #textarea>
+ <textarea
+ id="note-body"
+ ref="textarea"
+ v-model="note"
+ dir="auto"
+ :disabled="isSubmitting"
+ name="note[note]"
+ class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
+ data-qa-selector="comment_field"
+ data-testid="comment-field"
+ :data-supports-quick-actions="!glFeatures.tributeAutocomplete"
+ :aria-label="__('Description')"
+ :placeholder="__('Write a comment or drag your files here…')"
+ @keydown.up="editCurrentUserLastNote()"
+ @keydown.meta.enter="handleSave()"
+ @keydown.ctrl.enter="handleSave()"
+ ></textarea>
+ </template>
+ </markdown-field>
+ </comment-field-layout>
<div class="note-form-actions">
<div
class="btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index 1580c94658a..b7355d4d927 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -31,7 +31,7 @@ export default {
},
computed: {
...mapState({
- projectPath: state => state.diffs.projectPath,
+ projectPath: (state) => state.diffs.projectPath,
}),
diffMode() {
return getDiffMode(this.discussion.diff_file);
diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue
index 0272790a75d..da4134ab2c4 100644
--- a/app/assets/javascripts/notes/components/discussion_actions.vue
+++ b/app/assets/javascripts/notes/components/discussion_actions.vue
@@ -2,7 +2,6 @@
import ReplyPlaceholder from './discussion_reply_placeholder.vue';
import ResolveDiscussionButton from './discussion_resolve_button.vue';
import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue';
-import JumpToNextDiscussionButton from './discussion_jump_to_next_button.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
@@ -11,7 +10,6 @@ export default {
ReplyPlaceholder,
ResolveDiscussionButton,
ResolveWithIssueButton,
- JumpToNextDiscussionButton,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -38,14 +36,11 @@ export default {
},
},
computed: {
- hideJumpToNextUnresolvedInThreads() {
- return this.glFeatures.hideJumpToNextUnresolvedInThreads;
- },
resolvableNotes() {
- return this.discussion.notes.filter(x => x.resolvable);
+ return this.discussion.notes.filter((x) => x.resolvable);
},
userCanResolveDiscussion() {
- return this.resolvableNotes.every(note => note.current_user?.can_resolve_discussion);
+ return this.resolvableNotes.every((note) => note.current_user?.can_resolve_discussion);
},
},
};
@@ -74,15 +69,5 @@ export default {
:url="resolveWithIssuePath"
/>
</div>
- <div
- v-if="
- !hideJumpToNextUnresolvedInThreads &&
- discussion.resolvable &&
- shouldShowJumpToNextDiscussion
- "
- class="btn-group discussion-actions ml-sm-2"
- >
- <jump-to-next-discussion-button :from-discussion-id="discussion.id" />
- </div>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 2427a3f98ad..0a72627834d 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -32,10 +32,10 @@ export default {
return this.getNoteableData.create_issue_to_resolve_discussions_path;
},
toggeableDiscussions() {
- return this.discussions.filter(discussion => !discussion.individual_note);
+ return this.discussions.filter((discussion) => !discussion.individual_note);
},
allExpanded() {
- return this.toggeableDiscussions.every(discussion => discussion.expanded);
+ return this.toggeableDiscussions.every((discussion) => discussion.expanded);
},
lineResolveClass() {
return this.allResolved ? 'line-resolve-btn is-active' : 'line-resolve-text';
@@ -48,7 +48,7 @@ export default {
...mapActions(['setExpandDiscussions']),
handleExpandDiscussions() {
this.setExpandDiscussions({
- discussionIds: this.toggeableDiscussions.map(discussion => discussion.id),
+ discussionIds: this.toggeableDiscussions.map((discussion) => discussion.id),
expanded: !this.allExpanded,
});
},
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 08c22f0b4c6..aa61aa9b3cb 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -42,7 +42,7 @@ export default {
...mapGetters(['getNotesDataByProp', 'timelineEnabled']),
currentFilter() {
if (!this.currentValue) return this.filters[0];
- return this.filters.find(filter => filter.value === this.currentValue);
+ return this.filters.find((filter) => filter.value === this.currentValue);
},
},
created() {
diff --git a/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue b/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
deleted file mode 100644
index f94d0060b41..00000000000
--- a/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
+++ /dev/null
@@ -1,38 +0,0 @@
-<script>
-import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import discussionNavigation from '../mixins/discussion_navigation';
-
-export default {
- name: 'JumpToNextDiscussionButton',
- components: {
- GlIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [discussionNavigation],
- props: {
- fromDiscussionId: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <div class="btn-group" role="group">
- <button
- ref="button"
- v-gl-tooltip
- class="btn btn-default discussion-next-btn"
- :title="s__('MergeRequests|Jump to next unresolved thread')"
- data-track-event="click_button"
- data-track-label="mr_next_unresolved_thread"
- data-track-property="click_next_unresolved_thread"
- @click="jumpToNextRelativeDiscussion(fromDiscussionId)"
- >
- <gl-icon name="comment-next" />
- </button>
- </div>
-</template>
diff --git a/app/assets/javascripts/notes/components/email_participants_warning.vue b/app/assets/javascripts/notes/components/email_participants_warning.vue
new file mode 100644
index 00000000000..bb1ff58120a
--- /dev/null
+++ b/app/assets/javascripts/notes/components/email_participants_warning.vue
@@ -0,0 +1,70 @@
+<script>
+import { GlSprintf } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+import { toNounSeriesText } from '~/lib/utils/grammar';
+
+export default {
+ components: {
+ GlSprintf,
+ },
+ props: {
+ emails: {
+ type: Array,
+ required: true,
+ },
+ numberOfLessParticipants: {
+ type: Number,
+ required: false,
+ default: 3,
+ },
+ },
+ data() {
+ return {
+ isShowingMoreParticipants: false,
+ };
+ },
+ computed: {
+ title() {
+ return this.moreParticipantsAvailable
+ ? toNounSeriesText(this.lessParticipants, { onlyCommas: true })
+ : toNounSeriesText(this.emails);
+ },
+ lessParticipants() {
+ return this.emails.slice(0, this.numberOfLessParticipants);
+ },
+ moreLabel() {
+ return sprintf(s__('EmailParticipantsWarning|and %{moreCount} more'), {
+ moreCount: this.emails.length - this.numberOfLessParticipants,
+ });
+ },
+ moreParticipantsAvailable() {
+ return !this.isShowingMoreParticipants && this.emails.length > this.numberOfLessParticipants;
+ },
+ message() {
+ return this.moreParticipantsAvailable
+ ? s__('EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment.')
+ : s__('EmailParticipantsWarning|%{emails} will be notified of your comment.');
+ },
+ },
+ methods: {
+ showMoreParticipants() {
+ this.isShowingMoreParticipants = true;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-note-warning" data-testid="email-participants-warning">
+ <gl-sprintf :message="message">
+ <template #andMore>
+ <button type="button" class="btn-transparent btn-link" @click="showMoreParticipants">
+ {{ moreLabel }}
+ </button>
+ </template>
+ <template #emails>
+ <span>{{ title }}</span>
+ </template>
+ </gl-sprintf>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/multiline_comment_form.vue b/app/assets/javascripts/notes/components/multiline_comment_form.vue
index bb13eb87af7..9fbf2c9265c 100644
--- a/app/assets/javascripts/notes/components/multiline_comment_form.vue
+++ b/app/assets/javascripts/notes/components/multiline_comment_form.vue
@@ -1,5 +1,5 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapState } from 'vuex';
import { GlFormSelect, GlSprintf } from '@gitlab/ui';
import { getSymbol, getLineClasses } from './multiline_comment_utils';
@@ -27,12 +27,13 @@ export default {
};
},
computed: {
+ ...mapState({ selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition }),
lineNumber() {
return this.commentLineOptions[this.commentLineOptions.length - 1].text;
},
},
created() {
- const line = this.lineRange?.start || this.line;
+ const line = this.selectedCommentPosition?.start || this.lineRange?.start || this.line;
this.commentLineStart = {
line_code: line.line_code,
@@ -40,6 +41,8 @@ export default {
old_line: line.old_line,
new_line: line.new_line,
};
+
+ if (this.selectedCommentPosition) return;
this.highlightSelection();
},
destroyed() {
diff --git a/app/assets/javascripts/notes/components/multiline_comment_utils.js b/app/assets/javascripts/notes/components/multiline_comment_utils.js
index 2451400e980..4991695b97e 100644
--- a/app/assets/javascripts/notes/components/multiline_comment_utils.js
+++ b/app/assets/javascripts/notes/components/multiline_comment_utils.js
@@ -48,11 +48,11 @@ export function getLineClasses(line) {
export function commentLineOptions(diffLines, startingLine, lineCode, side = 'left') {
const preferredSide = side === 'left' ? 'old_line' : 'new_line';
const fallbackSide = preferredSide === 'new_line' ? 'old_line' : 'new_line';
- const notMatchType = l => l.type !== 'match';
+ const notMatchType = (l) => l.type !== 'match';
const linesCopy = [...diffLines]; // don't mutate the argument
const startingLineCode = startingLine.line_code;
- const currentIndex = linesCopy.findIndex(line => line.line_code === lineCode);
+ const currentIndex = linesCopy.findIndex((line) => line.line_code === lineCode);
// We're limiting adding comments to only lines above the current line
// to make rendering simpler. Future interations will use a more
@@ -66,10 +66,10 @@ export function commentLineOptions(diffLines, startingLine, lineCode, side = 'le
// If the selected line is "hidden" in an unchanged line block
// or "above" the current group of lines add it to the array so
// that the drop down is not defaulted to empty
- const selectedIndex = lines.findIndex(line => line.line_code === startingLineCode);
+ const selectedIndex = lines.findIndex((line) => line.line_code === startingLineCode);
if (selectedIndex < 0) lines.unshift(startingLine);
- return lines.map(l => {
+ return lines.map((l) => {
const { line_code, type, old_line, new_line } = l;
return {
value: { line_code, type, old_line, new_line },
@@ -103,7 +103,7 @@ export function getCommentedLines(selectedCommentPosition, diffLines) {
};
}
- const findLineCodeIndex = line => position => {
+ const findLineCodeIndex = (line) => (position) => {
return [position.line_code, position.left?.line_code, position.right?.line_code].includes(
line.line_code,
);
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index fc131f548b4..b85cfa83e09 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -206,14 +206,14 @@ export default {
const { project_id, iid } = this.getNoteableData;
if (this.isUserAssigned) {
- assignees = assignees.filter(assignee => assignee.id !== this.author.id);
+ assignees = assignees.filter((assignee) => assignee.id !== this.author.id);
} else {
assignees.push({ id: this.author.id });
}
if (this.targetType === 'issue') {
Api.updateIssue(project_id, iid, {
- assignee_ids: assignees.map(assignee => assignee.id),
+ assignee_ids: assignees.map((assignee) => assignee.id),
})
.then(() => this.handleAssigneeUpdate(assignees))
.catch(() => flash(__('Something went wrong while updating assignees')));
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 65b89b94eaa..8855ceac3d5 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -52,8 +52,9 @@ export default {
return this.getDiscussion(this.note.discussion_id);
},
...mapState({
- batchSuggestionsInfo: state => state.notes.batchSuggestionsInfo,
+ batchSuggestionsInfo: (state) => state.notes.batchSuggestionsInfo,
}),
+ ...mapState('diffs', ['defaultSuggestionCommitMessage']),
noteBody() {
return this.note.note;
},
@@ -98,12 +99,16 @@ export default {
formCancelHandler(shouldConfirm, isDirty) {
this.$emit('cancelForm', shouldConfirm, isDirty);
},
- applySuggestion({ suggestionId, flashContainer, callback = () => {} }) {
+ applySuggestion({ suggestionId, flashContainer, callback = () => {}, message }) {
const { discussion_id: discussionId, id: noteId } = this.note;
- return this.submitSuggestion({ discussionId, noteId, suggestionId, flashContainer }).then(
- callback,
- );
+ return this.submitSuggestion({
+ discussionId,
+ noteId,
+ suggestionId,
+ flashContainer,
+ message,
+ }).then(callback);
},
applySuggestionBatch({ flashContainer }) {
return this.submitSuggestionBatch({ flashContainer });
@@ -130,6 +135,7 @@ export default {
:note-html="note.note_html"
:line-type="lineType"
:help-page-path="helpPagePath"
+ :default-commit-message="defaultSuggestionCommitMessage"
@apply="applySuggestion"
@applyBatch="applySuggestionBatch"
@addToBatch="addSuggestionToBatch"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 84769bfc7c8..9acb837c27f 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -3,20 +3,21 @@
import { mapGetters, mapActions, mapState } from 'vuex';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
-import NoteableWarning from '../../vue_shared/components/notes/noteable_warning.vue';
-import markdownField from '../../vue_shared/components/markdown/field.vue';
+import markdownField from '~/vue_shared/components/markdown/field.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
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 {
name: 'NoteForm',
components: {
- NoteableWarning,
markdownField,
+ CommentFieldLayout,
},
- mixins: [issuableStateMixin, resolvable],
+ mixins: [glFeatureFlagsMixin(), issuableStateMixin, resolvable],
props: {
noteBody: {
type: String,
@@ -114,7 +115,7 @@ export default {
'getUserDataByProp',
]),
...mapState({
- withBatchComments: state => state.batchComments?.withBatchComments,
+ withBatchComments: (state) => state.batchComments?.withBatchComments,
}),
...mapGetters('batchComments', ['hasDrafts']),
showBatchCommentsActions() {
@@ -125,8 +126,8 @@ export default {
return (
this.discussion?.notes
- .filter(n => n.resolvable)
- .some(n => n.current_user?.can_resolve_discussion) || this.isDraft
+ .filter((n) => n.resolvable)
+ .some((n) => n.current_user?.can_resolve_discussion) || this.isDraft
);
},
noteHash() {
@@ -192,8 +193,7 @@ export default {
},
canSuggest() {
return (
- this.getNoteableData.can_receive_suggestion &&
- (this.line && this.line.can_receive_suggestion)
+ this.getNoteableData.can_receive_suggestion && this.line && this.line.can_receive_suggestion
);
},
changedCommentText() {
@@ -303,6 +303,9 @@ export default {
this.$emit('handleFormUpdateAddToReview', this.updatedNoteBody, shouldResolve);
},
+ hasEmailParticipants() {
+ return this.getNoteableData.issue_email_participants?.length;
+ },
},
};
</script>
@@ -316,46 +319,41 @@ export default {
></div>
<div class="flash-container timeline-content"></div>
<form :data-line-code="lineCode" class="edit-note common-note-form js-quick-submit gfm-form">
- <noteable-warning
- v-if="hasWarning(getNoteableData)"
- :is-locked="isLocked(getNoteableData)"
- :is-confidential="isConfidential(getNoteableData)"
- :locked-noteable-docs-path="lockedIssueDocsPath"
- :confidential-noteable-docs-path="confidentialIssueDocsPath"
- />
-
- <markdown-field
- :markdown-preview-path="markdownPreviewPath"
- :markdown-docs-path="markdownDocsPath"
- :quick-actions-docs-path="quickActionsDocsPath"
- :line="line"
- :note="discussionNote"
- :can-suggest="canSuggest"
- :add-spacing-classes="false"
- :help-page-path="helpPagePath"
- :show-suggest-popover="showSuggestPopover"
- :textarea-value="updatedNoteBody"
- @handleSuggestDismissed="() => $emit('handleSuggestDismissed')"
- >
- <textarea
- id="note_note"
- ref="textarea"
- slot="textarea"
- v-model="updatedNoteBody"
- :data-supports-quick-actions="!isEditing"
- name="note[note]"
- class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
- data-qa-selector="reply_field"
- dir="auto"
- :aria-label="__('Description')"
- :placeholder="__('Write a comment or drag your files here…')"
- @keydown.meta.enter="handleKeySubmit()"
- @keydown.ctrl.enter="handleKeySubmit()"
- @keydown.exact.up="editMyLastNote()"
- @keydown.exact.esc="cancelHandler(true)"
- @input="onInput"
- ></textarea>
- </markdown-field>
+ <comment-field-layout :noteable-data="getNoteableData">
+ <markdown-field
+ :markdown-preview-path="markdownPreviewPath"
+ :markdown-docs-path="markdownDocsPath"
+ :quick-actions-docs-path="quickActionsDocsPath"
+ :line="line"
+ :note="discussionNote"
+ :can-suggest="canSuggest"
+ :add-spacing-classes="false"
+ :help-page-path="helpPagePath"
+ :show-suggest-popover="showSuggestPopover"
+ :textarea-value="updatedNoteBody"
+ @handleSuggestDismissed="() => $emit('handleSuggestDismissed')"
+ >
+ <template #textarea>
+ <textarea
+ id="note_note"
+ ref="textarea"
+ v-model="updatedNoteBody"
+ :data-supports-quick-actions="!isEditing && !glFeatures.tributeAutocomplete"
+ name="note[note]"
+ class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
+ data-qa-selector="reply_field"
+ dir="auto"
+ :aria-label="__('Description')"
+ :placeholder="__('Write a comment or drag your files here…')"
+ @keydown.meta.enter="handleKeySubmit()"
+ @keydown.ctrl.enter="handleKeySubmit()"
+ @keydown.exact.up="editMyLastNote()"
+ @keydown.exact.esc="cancelHandler(true)"
+ @input="onInput"
+ ></textarea>
+ </template>
+ </markdown-field>
+ </comment-field-layout>
<div class="note-form-actions clearfix">
<template v-if="showBatchCommentsActions">
<p v-if="showResolveDiscussionToggle">
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 62ee7f30c57..0a9a3da6069 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -201,14 +201,14 @@ export default {
};
this.saveNote(replyData)
- .then(res => {
+ .then((res) => {
if (res.hasFlash !== true) {
this.isReplying = false;
clearDraft(this.autosaveKey);
}
callback();
})
- .catch(err => {
+ .catch((err) => {
this.removePlaceholderNotes();
const msg = __(
'Your comment could not be submitted! Please check your network connection and try again.',
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 5073922e4a4..eaa64cf7c01 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -296,7 +296,7 @@ export default {
this.updateSuccess();
callback();
})
- .catch(response => {
+ .catch((response) => {
if (response.status === httpStatusCodes.GONE) {
this.removeNote(this.note);
this.updateSuccess();
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 9eaa4e422d5..e9e687a8743 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -130,7 +130,7 @@ export default {
const { parentElement } = this.$el;
if (parentElement && parentElement.classList.contains('js-vue-notes-event')) {
- parentElement.addEventListener('toggleAward', event => {
+ parentElement.addEventListener('toggleAward', (event) => {
const { awardName, noteId } = event.detail;
this.toggleAward({ awardName, noteId });
});
@@ -217,7 +217,7 @@ export default {
const noteId = hash && hash.replace(/^note_/, '');
if (noteId) {
- const discussion = this.discussions.find(d => d.notes.some(({ id }) => id === noteId));
+ const discussion = this.discussions.find((d) => d.notes.some(({ id }) => id === noteId));
if (discussion) {
this.expandDiscussion({ discussionId: discussion.id });
diff --git a/app/assets/javascripts/notes/components/timeline_toggle.vue b/app/assets/javascripts/notes/components/timeline_toggle.vue
index d1ffe0a3601..8162878f80d 100644
--- a/app/assets/javascripts/notes/components/timeline_toggle.vue
+++ b/app/assets/javascripts/notes/components/timeline_toggle.vue
@@ -50,7 +50,6 @@ export default {
v-gl-tooltip
v-track-event="trackToggleTimelineView(timelineEnabled)"
icon="comments"
- size="small"
:selected="timelineEnabled"
:title="tooltip"
:aria-label="tooltip"
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index 0628e1d8647..ab7fa793bdc 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -26,9 +26,9 @@ export default {
return this.replies[this.replies.length - 1];
},
uniqueAuthors() {
- const authors = this.replies.map(reply => reply.author || {});
+ const authors = this.replies.map((reply) => reply.author || {});
- return uniqBy(authors, author => author.username);
+ return uniqBy(authors, (author) => author.username);
},
className() {
return this.collapsed ? 'collapsed' : 'expanded';
diff --git a/app/assets/javascripts/notes/discussion_filters.js b/app/assets/javascripts/notes/discussion_filters.js
index cdf9a46c5aa..7c9e7703d59 100644
--- a/app/assets/javascripts/notes/discussion_filters.js
+++ b/app/assets/javascripts/notes/discussion_filters.js
@@ -1,13 +1,13 @@
import Vue from 'vue';
import DiscussionFilter from './components/discussion_filter.vue';
-export default store => {
+export default (store) => {
const discussionFilterEl = document.getElementById('js-vue-discussion-filter');
if (discussionFilterEl) {
const { defaultFilter, notesFilters } = discussionFilterEl.dataset;
const filterValues = notesFilters ? JSON.parse(notesFilters) : {};
- const filters = Object.keys(filterValues).map(entry => ({
+ const filters = Object.keys(filterValues).map((entry) => ({
title: entry,
value: filterValues[entry],
}));
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 c4a42eb1a98..5ce541781d4 100644
--- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js
+++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
@@ -9,9 +9,9 @@ import { formatLineRange } from '~/notes/components/multiline_comment_utils';
export default {
computed: {
...mapState({
- noteableData: state => state.notes.noteableData,
- notesData: state => state.notes.notesData,
- withBatchComments: state => state.batchComments?.withBatchComments,
+ noteableData: (state) => state.notes.noteableData,
+ notesData: (state) => state.notes.notesData,
+ withBatchComments: (state) => state.batchComments?.withBatchComments,
}),
...mapGetters('diffs', ['getDiffFileByHash']),
...mapGetters('batchComments', ['shouldRenderDraftRowInDiscussion', 'draftForDiscussion']),
diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js
index c6932bfacae..96974c4fa2d 100644
--- a/app/assets/javascripts/notes/mixins/discussion_navigation.js
+++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js
@@ -99,7 +99,7 @@ export default {
'getDiscussion',
]),
...mapState({
- currentDiscussionId: state => state.notes.currentDiscussionId,
+ currentDiscussionId: (state) => state.notes.currentDiscussionId,
}),
},
methods: {
diff --git a/app/assets/javascripts/notes/mixins/issuable_state.js b/app/assets/javascripts/notes/mixins/issuable_state.js
index 0ca8c8c98a3..52b67764b70 100644
--- a/app/assets/javascripts/notes/mixins/issuable_state.js
+++ b/app/assets/javascripts/notes/mixins/issuable_state.js
@@ -12,21 +12,10 @@ export default {
lockedIssueDocsPath() {
return this.getNoteableDataByProp('locked_discussion_docs_path');
},
- confidentialIssueDocsPath() {
- return this.getNoteableDataByProp('confidential_issues_docs_path');
- },
},
methods: {
- isConfidential(issue) {
- return Boolean(issue.confidential);
- },
-
isLocked(issue) {
return Boolean(issue.discussion_locked);
},
-
- hasWarning(issue) {
- return this.isConfidential(issue) || this.isLocked(issue);
- },
},
};
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index cef4475ed1d..baada4c5ce8 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -15,7 +15,7 @@ export default {
if (notes) {
// Decide resolved state using store. Only valid for discussions.
- return notes.filter(note => !note.system).every(note => note.resolved);
+ return notes.filter((note) => !note.system).every((note) => note.resolved);
}
return resolved;
diff --git a/app/assets/javascripts/notes/sort_discussions.js b/app/assets/javascripts/notes/sort_discussions.js
index a06c23f5f76..ecfa3223039 100644
--- a/app/assets/javascripts/notes/sort_discussions.js
+++ b/app/assets/javascripts/notes/sort_discussions.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import SortDiscussion from './components/sort_discussion.vue';
-export default store => {
+export default (store) => {
const el = document.getElementById('js-vue-sort-issue-discussions');
if (!el) return null;
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 1fe5d6c2955..c6684efed4d 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -141,7 +141,7 @@ export const updateNote = ({ commit, dispatch }, { endpoint, note }) =>
export const updateOrCreateNotes = ({ commit, state, getters, dispatch }, notes) => {
const { notesById } = getters;
- const debouncedFetchDiscussions = isFetching => {
+ const debouncedFetchDiscussions = (isFetching) => {
if (!isFetching) {
commit(types.SET_FETCHING_DISCUSSIONS, true);
dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
@@ -159,7 +159,7 @@ export const updateOrCreateNotes = ({ commit, state, getters, dispatch }, notes)
}
};
- notes.forEach(note => {
+ notes.forEach((note) => {
if (notesById[note.id]) {
commit(types.UPDATE_NOTE, note);
} else if (note.type === constants.DISCUSSION_NOTE || note.type === constants.DIFF_NOTE) {
@@ -329,7 +329,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
}
}
- const processQuickActions = res => {
+ const processQuickActions = (res) => {
const { errors: { commands_only: message } = { commands_only: null } } = res;
/*
The following reply means that quick actions have been successfully applied:
@@ -347,7 +347,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
return res;
};
- const processEmojiAward = res => {
+ const processEmojiAward = (res) => {
const { commands_changes: commandsChanges } = res;
const { emoji_award: emojiAward } = commandsChanges || {};
if (!emojiAward) {
@@ -357,7 +357,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
const votesBlock = $('.js-awards-block').eq(0);
return loadAwardsHandler()
- .then(awardsHandler => {
+ .then((awardsHandler) => {
awardsHandler.addAwardToEmojiBar(votesBlock, emojiAward);
awardsHandler.scrollToAwards();
})
@@ -371,7 +371,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
.then(() => res);
};
- const processTimeTracking = res => {
+ const processTimeTracking = (res) => {
const { commands_changes: commandsChanges } = res;
const { spend_time: spendTime, time_estimate: timeEstimate } = commandsChanges || {};
if (spendTime != null || timeEstimate != null) {
@@ -383,7 +383,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
return res;
};
- const removePlaceholder = res => {
+ const removePlaceholder = (res) => {
if (replyId) {
commit(types.REMOVE_PLACEHOLDER_NOTES);
}
@@ -391,7 +391,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
return res;
};
- const processErrors = error => {
+ const processErrors = (error) => {
if (error.response) {
const {
response: { data = {} },
@@ -435,7 +435,7 @@ const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
return resp;
};
-const getFetchDataParams = state => {
+const getFetchDataParams = (state) => {
const endpoint = state.notesData.notesPath;
const options = {
headers: {
@@ -559,7 +559,7 @@ export const updateResolvableDiscussionsCounts = ({ commit }) =>
export const submitSuggestion = (
{ commit, dispatch },
- { discussionId, noteId, suggestionId, flashContainer },
+ { discussionId, suggestionId, flashContainer, message },
) => {
const dispatchResolveDiscussion = () =>
dispatch('resolveDiscussion', { discussionId }).catch(() => {});
@@ -567,10 +567,9 @@ export const submitSuggestion = (
commit(types.SET_RESOLVING_DISCUSSION, true);
dispatch('stopPolling');
- return Api.applySuggestion(suggestionId)
- .then(() => commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }))
+ return Api.applySuggestion(suggestionId, message)
.then(dispatchResolveDiscussion)
- .catch(err => {
+ .catch((err) => {
const defaultMessage = __(
'Something went wrong while applying the suggestion. Please try again.',
);
@@ -590,13 +589,8 @@ export const submitSuggestion = (
export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContainer }) => {
const suggestionIds = state.batchSuggestionsInfo.map(({ suggestionId }) => suggestionId);
- const applyAllSuggestions = () =>
- state.batchSuggestionsInfo.map(suggestionInfo =>
- commit(types.APPLY_SUGGESTION, suggestionInfo),
- );
-
const resolveAllDiscussions = () =>
- state.batchSuggestionsInfo.map(suggestionInfo => {
+ state.batchSuggestionsInfo.map((suggestionInfo) => {
const { discussionId } = suggestionInfo;
return dispatch('resolveDiscussion', { discussionId }).catch(() => {});
});
@@ -606,10 +600,9 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContai
dispatch('stopPolling');
return Api.applySuggestionBatch(suggestionIds)
- .then(() => Promise.all(applyAllSuggestions()))
.then(() => Promise.all(resolveAllDiscussions()))
.then(() => commit(types.CLEAR_SUGGESTION_BATCH))
- .catch(err => {
+ .catch((err) => {
const defaultMessage = __(
'Something went wrong while applying the batch of suggestions. Please try again.',
);
@@ -652,10 +645,10 @@ export const fetchDescriptionVersion = ({ dispatch }, { endpoint, startingVersio
return axios
.get(requestUrl)
- .then(res => {
+ .then((res) => {
dispatch('receiveDescriptionVersion', { descriptionVersion: res.data, versionId });
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveDescriptionVersionError', error);
Flash(__('Something went wrong while fetching description changes. Please try again.'));
});
@@ -687,7 +680,7 @@ export const softDeleteDescriptionVersion = (
.then(() => {
dispatch('receiveDeleteDescriptionVersion', versionId);
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveDeleteDescriptionVersionError', error);
Flash(__('Something went wrong while deleting description changes. Please try again.'));
diff --git a/app/assets/javascripts/notes/stores/collapse_utils.js b/app/assets/javascripts/notes/stores/collapse_utils.js
index f34247d4eb0..b2e2f6e2c31 100644
--- a/app/assets/javascripts/notes/stores/collapse_utils.js
+++ b/app/assets/javascripts/notes/stores/collapse_utils.js
@@ -18,7 +18,7 @@ export const getTimeDifferenceMinutes = (noteBeggining, noteEnd) => {
* @param {Object} note
* @returns {Boolean}
*/
-export const isDescriptionSystemNote = note => note.system && note.note === DESCRIPTION_TYPE;
+export const isDescriptionSystemNote = (note) => note.system && note.note === DESCRIPTION_TYPE;
/**
* Collapses the system notes of a description type, e.g. Changed the description, n minutes ago
@@ -29,7 +29,7 @@ export const isDescriptionSystemNote = note => note.system && note.note === DESC
* @param {Array} notes
* @returns {Array}
*/
-export const collapseSystemNotes = notes => {
+export const collapseSystemNotes = (notes) => {
let lastDescriptionSystemNote = null;
let lastDescriptionSystemNoteIndex = -1;
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index 5b3ffa425a0..5891a2e63e3 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -2,14 +2,14 @@ import { flattenDeep, clone } from 'lodash';
import * as constants from '../constants';
import { collapseSystemNotes } from './collapse_utils';
-export const discussions = state => {
+export const discussions = (state) => {
let discussionsInState = clone(state.discussions);
// NOTE: not testing bc will be removed when backend is finished.
if (state.isTimelineEnabled) {
discussionsInState = discussionsInState
.reduce((acc, discussion) => {
- const transformedToIndividualNotes = discussion.notes.map(note => ({
+ const transformedToIndividualNotes = discussion.notes.map((note) => ({
...discussion,
id: note.id,
created_at: note.created_at,
@@ -29,52 +29,52 @@ export const discussions = state => {
return collapseSystemNotes(discussionsInState);
};
-export const convertedDisscussionIds = state => state.convertedDisscussionIds;
+export const convertedDisscussionIds = (state) => state.convertedDisscussionIds;
-export const targetNoteHash = state => state.targetNoteHash;
+export const targetNoteHash = (state) => state.targetNoteHash;
-export const getNotesData = state => state.notesData;
+export const getNotesData = (state) => state.notesData;
-export const isNotesFetched = state => state.isNotesFetched;
+export const isNotesFetched = (state) => state.isNotesFetched;
/*
* WARNING: This is an example of an "unnecessary" getter
* more info found here: https://gitlab.com/groups/gitlab-org/-/epics/2913.
*/
-export const sortDirection = state => state.discussionSortOrder;
+export const sortDirection = (state) => state.discussionSortOrder;
-export const persistSortOrder = state => state.persistSortOrder;
+export const persistSortOrder = (state) => state.persistSortOrder;
-export const timelineEnabled = state => state.isTimelineEnabled;
+export const timelineEnabled = (state) => state.isTimelineEnabled;
-export const isLoading = state => state.isLoading;
+export const isLoading = (state) => state.isLoading;
-export const getNotesDataByProp = state => prop => state.notesData[prop];
+export const getNotesDataByProp = (state) => (prop) => state.notesData[prop];
-export const getNoteableData = state => state.noteableData;
+export const getNoteableData = (state) => state.noteableData;
-export const getNoteableDataByProp = state => prop => state.noteableData[prop];
+export const getNoteableDataByProp = (state) => (prop) => state.noteableData[prop];
-export const getBlockedByIssues = state => state.noteableData.blocked_by_issues;
+export const getBlockedByIssues = (state) => state.noteableData.blocked_by_issues;
-export const userCanReply = state => Boolean(state.noteableData.current_user.can_create_note);
+export const userCanReply = (state) => Boolean(state.noteableData.current_user.can_create_note);
-export const openState = state => state.noteableData.state;
+export const openState = (state) => state.noteableData.state;
-export const getUserData = state => state.userData || {};
+export const getUserData = (state) => state.userData || {};
-export const getUserDataByProp = state => prop => state.userData && state.userData[prop];
+export const getUserDataByProp = (state) => (prop) => state.userData && state.userData[prop];
-export const descriptionVersions = state => state.descriptionVersions;
+export const descriptionVersions = (state) => state.descriptionVersions;
-export const notesById = state =>
+export const notesById = (state) =>
state.discussions.reduce((acc, note) => {
- note.notes.every(n => Object.assign(acc, { [n.id]: n }));
+ note.notes.every((n) => Object.assign(acc, { [n.id]: n }));
return acc;
}, {});
-export const noteableType = state => {
+export const noteableType = (state) => {
const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE, EPIC_NOTEABLE_TYPE } = constants;
if (state.noteableData.noteableType === EPIC_NOTEABLE_TYPE) {
@@ -84,21 +84,21 @@ export const noteableType = state => {
return state.noteableData.merge_params ? MERGE_REQUEST_NOTEABLE_TYPE : ISSUE_NOTEABLE_TYPE;
};
-const reverseNotes = array => array.slice(0).reverse();
+const reverseNotes = (array) => array.slice(0).reverse();
const isLastNote = (note, state) =>
!note.system && state.userData && note.author && note.author.id === state.userData.id;
-export const getCurrentUserLastNote = state =>
- flattenDeep(reverseNotes(state.discussions).map(note => reverseNotes(note.notes))).find(el =>
+export const getCurrentUserLastNote = (state) =>
+ flattenDeep(reverseNotes(state.discussions).map((note) => reverseNotes(note.notes))).find((el) =>
isLastNote(el, state),
);
-export const getDiscussionLastNote = state => discussion =>
- reverseNotes(discussion.notes).find(el => isLastNote(el, state));
+export const getDiscussionLastNote = (state) => (discussion) =>
+ reverseNotes(discussion.notes).find((el) => isLastNote(el, state));
-export const unresolvedDiscussionsCount = state => state.unresolvedDiscussionsCount;
-export const resolvableDiscussionsCount = state => state.resolvableDiscussionsCount;
+export const unresolvedDiscussionsCount = (state) => state.unresolvedDiscussionsCount;
+export const resolvableDiscussionsCount = (state) => state.resolvableDiscussionsCount;
export const showJumpToNextDiscussion = (state, getters) => (mode = 'discussion') => {
const orderedDiffs =
@@ -109,20 +109,20 @@ export const showJumpToNextDiscussion = (state, getters) => (mode = 'discussion'
return orderedDiffs.length > 1;
};
-export const isDiscussionResolved = (state, getters) => discussionId =>
+export const isDiscussionResolved = (state, getters) => (discussionId) =>
getters.resolvedDiscussionsById[discussionId] !== undefined;
-export const allResolvableDiscussions = state =>
- state.discussions.filter(d => !d.individual_note && d.resolvable);
+export const allResolvableDiscussions = (state) =>
+ state.discussions.filter((d) => !d.individual_note && d.resolvable);
-export const resolvedDiscussionsById = state => {
+export const resolvedDiscussionsById = (state) => {
const map = {};
state.discussions
- .filter(d => d.resolvable)
- .forEach(n => {
+ .filter((d) => d.resolvable)
+ .forEach((n) => {
if (n.notes) {
- const resolved = n.notes.filter(note => note.resolvable).every(note => note.resolved);
+ const resolved = n.notes.filter((note) => note.resolvable).every((note) => note.resolved);
if (resolved) {
map[n.id] = n;
@@ -136,7 +136,7 @@ export const resolvedDiscussionsById = state => {
// Gets Discussions IDs ordered by the date of their initial note
export const unresolvedDiscussionsIdsByDate = (state, getters) =>
getters.allResolvableDiscussions
- .filter(d => !d.resolved)
+ .filter((d) => !d.resolved)
.sort((a, b) => {
const aDate = new Date(a.notes[0].created_at);
const bDate = new Date(b.notes[0].created_at);
@@ -147,7 +147,7 @@ export const unresolvedDiscussionsIdsByDate = (state, getters) =>
return aDate === bDate ? 0 : 1;
})
- .map(d => d.id);
+ .map((d) => d.id);
// Gets Discussions IDs ordered by their position in the diff
//
@@ -156,7 +156,7 @@ export const unresolvedDiscussionsIdsByDate = (state, getters) =>
// line numbers.
export const unresolvedDiscussionsIdsByDiff = (state, getters) =>
getters.allResolvableDiscussions
- .filter(d => !d.resolved && d.active)
+ .filter((d) => !d.resolved && d.active)
.sort((a, b) => {
if (!a.diff_file || !b.diff_file) {
return 0;
@@ -176,7 +176,7 @@ export const unresolvedDiscussionsIdsByDiff = (state, getters) =>
? -1
: 1;
})
- .map(d => d.id);
+ .map((d) => d.id);
export const resolvedDiscussionCount = (state, getters) => {
const resolvedMap = getters.resolvedDiscussionsById;
@@ -184,16 +184,16 @@ export const resolvedDiscussionCount = (state, getters) => {
return Object.keys(resolvedMap).length;
};
-export const discussionTabCounter = state =>
+export const discussionTabCounter = (state) =>
state.discussions.reduce(
(acc, discussion) =>
- acc + discussion.notes.filter(note => !note.system && !note.placeholder).length,
+ acc + discussion.notes.filter((note) => !note.system && !note.placeholder).length,
0,
);
// Returns the list of discussion IDs ordered according to given parameter
// @param {Boolean} diffOrder - is ordered by diff?
-export const unresolvedDiscussionsIdsOrdered = (state, getters) => diffOrder => {
+export const unresolvedDiscussionsIdsOrdered = (state, getters) => (diffOrder) => {
if (diffOrder) {
return getters.unresolvedDiscussionsIdsByDiff;
}
@@ -241,17 +241,17 @@ export const previousUnresolvedDiscussionId = (state, getters) => (discussionId,
getters.findUnresolvedDiscussionIdNeighbor({ discussionId, diffOrder, step: -1 });
// @param {Boolean} diffOrder - is ordered by diff?
-export const firstUnresolvedDiscussionId = (state, getters) => diffOrder => {
+export const firstUnresolvedDiscussionId = (state, getters) => (diffOrder) => {
if (diffOrder) {
return getters.unresolvedDiscussionsIdsByDiff[0];
}
return getters.unresolvedDiscussionsIdsByDate[0];
};
-export const getDiscussion = state => discussionId =>
- state.discussions.find(discussion => discussion.id === discussionId);
+export const getDiscussion = (state) => (discussionId) =>
+ state.discussions.find((discussion) => discussion.id === discussionId);
-export const commentsDisabled = state => state.commentsDisabled;
+export const commentsDisabled = (state) => state.commentsDisabled;
export const suggestionsCount = (state, getters) =>
- Object.values(getters.notesById).filter(n => n.suggestions.length).length;
+ Object.values(getters.notesById).filter((n) => n.suggestions.length).length;
diff --git a/app/assets/javascripts/notes/stores/modules/index.js b/app/assets/javascripts/notes/stores/modules/index.js
index 4421a84a6b1..144a3d7ba90 100644
--- a/app/assets/javascripts/notes/stores/modules/index.js
+++ b/app/assets/javascripts/notes/stores/modules/index.js
@@ -15,7 +15,7 @@ export default () => ({
batchSuggestionsInfo: [],
currentlyFetchingDiscussions: false,
/**
- * selectedCommentPosition & selectedCommentPosition structures are the same as `position.line_range`:
+ * selectedCommentPosition & selectedCommentPositionHover structures are the same as `position.line_range`:
* {
* start: { line_code: string, new_line: number, old_line:number, type: string },
* end: { line_code: string, new_line: number, old_line:number, type: string },
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index 53387b2eaff..2c51ce0d970 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -7,7 +7,7 @@ export default {
[types.ADD_NEW_NOTE](state, data) {
const note = data.discussion ? data.discussion.notes[0] : data;
const { discussion_id, type } = note;
- const [exists] = state.discussions.filter(n => n.id === note.discussion_id);
+ const [exists] = state.discussions.filter((n) => n.id === note.discussion_id);
const isDiscussion = type === constants.DISCUSSION_NOTE || type === constants.DIFF_NOTE;
if (!exists) {
@@ -128,7 +128,7 @@ export default {
// To support legacy notes, should be very rare case.
if (discussion.individual_note && discussion.notes.length > 1) {
- discussion.notes.forEach(n => {
+ discussion.notes.forEach((n) => {
acc.push({
...discussion,
...diffData,
@@ -183,7 +183,7 @@ export default {
const { id, name, username } = state.userData;
const hasEmojiAwardedByCurrentUser = note.award_emoji.filter(
- emoji => `${emoji.name}` === `${data.awardName}` && emoji.user.id === id,
+ (emoji) => `${emoji.name}` === `${data.awardName}` && emoji.user.id === id,
);
if (hasEmojiAwardedByCurrentUser.length) {
@@ -206,7 +206,7 @@ export default {
[types.SET_EXPAND_DISCUSSIONS](state, { discussionIds, expanded }) {
if (discussionIds?.length) {
- discussionIds.forEach(discussionId => {
+ discussionIds.forEach((discussionId) => {
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
Object.assign(discussion, { expanded });
});
@@ -236,7 +236,7 @@ export default {
const noteObj = utils.findNoteObjectById(state.discussions, discussionId);
const comment = utils.findNoteObjectById(noteObj.notes, noteId);
- comment.suggestions = comment.suggestions.map(suggestion => ({
+ comment.suggestions = comment.suggestions.map((suggestion) => ({
...suggestion,
applied: suggestion.applied || suggestion.id === suggestionId,
appliable: false,
@@ -244,13 +244,13 @@ export default {
},
[types.SET_APPLYING_BATCH_STATE](state, isApplyingBatch) {
- state.batchSuggestionsInfo.forEach(suggestionInfo => {
+ state.batchSuggestionsInfo.forEach((suggestionInfo) => {
const { discussionId, noteId, suggestionId } = suggestionInfo;
const noteObj = utils.findNoteObjectById(state.discussions, discussionId);
const comment = utils.findNoteObjectById(noteObj.notes, noteId);
- comment.suggestions = comment.suggestions.map(suggestion => ({
+ comment.suggestions = comment.suggestions.map((suggestion) => ({
...suggestion,
is_applying_batch: suggestion.id === suggestionId && isApplyingBatch,
}));
@@ -278,7 +278,7 @@ export default {
[types.UPDATE_DISCUSSION](state, noteData) {
const note = noteData;
- const selectedDiscussion = state.discussions.find(disc => disc.id === note.id);
+ const selectedDiscussion = state.discussions.find((disc) => disc.id === note.id);
note.expanded = true; // override expand flag to prevent collapse
if (note.diff_file) {
Object.assign(note, {
@@ -289,7 +289,7 @@ export default {
},
[types.UPDATE_DISCUSSION_POSITION](state, { discussionId, position }) {
- const selectedDiscussion = state.discussions.find(disc => disc.id === discussionId);
+ const selectedDiscussion = state.discussions.find((disc) => disc.id === discussionId);
if (selectedDiscussion) Object.assign(selectedDiscussion.position, { ...position });
},
@@ -341,13 +341,13 @@ export default {
},
[types.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS](state) {
state.resolvableDiscussionsCount = state.discussions.filter(
- discussion => !discussion.individual_note && discussion.resolvable,
+ (discussion) => !discussion.individual_note && discussion.resolvable,
).length;
state.unresolvedDiscussionsCount = state.discussions.filter(
- discussion =>
+ (discussion) =>
!discussion.individual_note &&
discussion.resolvable &&
- discussion.notes.some(note => note.resolvable && !note.resolved),
+ discussion.notes.some((note) => note.resolvable && !note.resolved),
).length;
},
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index 10faac0c32b..6df926e1249 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -6,13 +6,13 @@ import createGqClient, { fetchPolicies } from '~/lib/graphql';
// factory function because global flag makes RegExp stateful
const createQuickActionsRegex = () => /^\/\w+.*$/gm;
-export const findNoteObjectById = (notes, id) => notes.filter(n => n.id === id)[0];
+export const findNoteObjectById = (notes, id) => notes.filter((n) => n.id === id)[0];
-export const getQuickActionText = note => {
+export const getQuickActionText = (note) => {
let text = __('Applying command');
const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || [];
- const executedCommands = quickActions.filter(command => {
+ const executedCommands = quickActions.filter((command) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(note);
});
@@ -29,12 +29,12 @@ export const getQuickActionText = note => {
return text;
};
-export const hasQuickActions = note => createQuickActionsRegex().test(note);
+export const hasQuickActions = (note) => createQuickActionsRegex().test(note);
-export const stripQuickActions = note => note.replace(createQuickActionsRegex(), '').trim();
+export const stripQuickActions = (note) => note.replace(createQuickActionsRegex(), '').trim();
-export const prepareDiffLines = diffLines =>
- diffLines.map(line => ({ ...trimFirstCharOfLineContent(line) }));
+export const prepareDiffLines = (diffLines) =>
+ diffLines.map((line) => ({ ...trimFirstCharOfLineContent(line) }));
export const gqClient = createGqClient(
{},
diff --git a/app/assets/javascripts/notes/utils.js b/app/assets/javascripts/notes/utils.js
index e6c2eb06a51..7966a884eab 100644
--- a/app/assets/javascripts/notes/utils.js
+++ b/app/assets/javascripts/notes/utils.js
@@ -4,7 +4,7 @@
* Tracks snowplow event when User toggles timeline view
* @param {Boolean} enabled that will be send as a property for the event
*/
-export const trackToggleTimelineView = enabled => ({
+export const trackToggleTimelineView = (enabled) => ({
category: 'Incident Management',
action: 'toggle_incident_comments_into_timeline_view',
label: 'Status',
diff --git a/app/assets/javascripts/notifications_dropdown.js b/app/assets/javascripts/notifications_dropdown.js
index ae992dd5dc5..eaa5ec3a2e4 100644
--- a/app/assets/javascripts/notifications_dropdown.js
+++ b/app/assets/javascripts/notifications_dropdown.js
@@ -12,9 +12,7 @@ export default function notificationsDropdown() {
}
const notificationLevel = $(this).data('notificationLevel');
- const form = $(this)
- .parents('.notification-form')
- .first();
+ const form = $(this).parents('.notification-form').first();
form.find('.js-notification-loading').toggleClass('spinner');
if (form.hasClass('no-label')) {
@@ -25,13 +23,11 @@ export default function notificationsDropdown() {
Rails.fire(form[0], 'submit');
});
- $(document).on('ajax:success', '.notification-form', e => {
+ $(document).on('ajax:success', '.notification-form', (e) => {
const data = e.detail[0];
if (data.saved) {
- $(e.currentTarget)
- .closest('.js-notification-dropdown')
- .replaceWith(data.html);
+ $(e.currentTarget).closest('.js-notification-dropdown').replaceWith(data.html);
} else {
Flash(__('Failed to save new settings'), 'alert');
}
diff --git a/app/assets/javascripts/onboarding_issues/index.js b/app/assets/javascripts/onboarding_issues/index.js
index 27f2f7f0e9d..b23a10c9254 100644
--- a/app/assets/javascripts/onboarding_issues/index.js
+++ b/app/assets/javascripts/onboarding_issues/index.js
@@ -57,7 +57,7 @@ const showPopover = (el, path, footer, options) => {
.popover('show');
// The previous popover actions have been taken, don't show those popovers anymore.
- Object.keys(settings).forEach(pathSetting => {
+ Object.keys(settings).forEach((pathSetting) => {
if (path !== pathSetting) {
settings[pathSetting] = false;
} else {
@@ -71,7 +71,7 @@ const showPopover = (el, path, footer, options) => {
}
};
-export const showLearnGitLabGroupItemPopover = id => {
+export const showLearnGitLabGroupItemPopover = (id) => {
const el = document.querySelector(`#group-${id} .group-text a`);
if (!el) return;
diff --git a/app/assets/javascripts/operation_settings/store/actions.js b/app/assets/javascripts/operation_settings/store/actions.js
index 1d3adeefbd8..bbbff6630d3 100644
--- a/app/assets/javascripts/operation_settings/store/actions.js
+++ b/app/assets/javascripts/operation_settings/store/actions.js
@@ -21,7 +21,7 @@ export const saveChanges = ({ state, dispatch }) =>
},
})
.then(() => dispatch('receiveSaveChangesSuccess'))
- .catch(error => dispatch('receiveSaveChangesError', error));
+ .catch((error) => dispatch('receiveSaveChangesError', error));
export const receiveSaveChangesSuccess = () => {
/**
diff --git a/app/assets/javascripts/operation_settings/store/index.js b/app/assets/javascripts/operation_settings/store/index.js
index e96bb1e8aad..e3dcfd31a83 100644
--- a/app/assets/javascripts/operation_settings/store/index.js
+++ b/app/assets/javascripts/operation_settings/store/index.js
@@ -6,7 +6,7 @@ import mutations from './mutations';
Vue.use(Vuex);
-export const createStore = initialState =>
+export const createStore = (initialState) =>
new Vuex.Store({
state: createState(initialState),
actions,
diff --git a/app/assets/javascripts/packages/details/components/package_files.vue b/app/assets/javascripts/packages/details/components/package_files.vue
index ab46dd0114d..3add454fda3 100644
--- a/app/assets/javascripts/packages/details/components/package_files.vue
+++ b/app/assets/javascripts/packages/details/components/package_files.vue
@@ -25,14 +25,14 @@ export default {
},
computed: {
filesTableRows() {
- return this.packageFiles.map(pf => ({
+ return this.packageFiles.map((pf) => ({
...pf,
size: this.formatSize(pf.size),
pipeline: last(pf.pipelines),
}));
},
showCommitColumn() {
- return this.filesTableRows.some(row => Boolean(row.pipeline?.id));
+ return this.filesTableRows.some((row) => Boolean(row.pipeline?.id));
},
filesTableHeaderFields() {
return [
@@ -55,7 +55,7 @@ export default {
label: __('Created'),
class: 'gl-text-right',
},
- ].filter(c => !c.hide);
+ ].filter((c) => !c.hide);
},
},
methods: {
@@ -90,7 +90,7 @@ export default {
</gl-link>
</template>
- <template #cell(commit)="{item}">
+ <template #cell(commit)="{ item }">
<gl-link
:href="item.pipeline.project.commit_url"
class="gl-text-gray-500"
diff --git a/app/assets/javascripts/packages/list/components/packages_list.vue b/app/assets/javascripts/packages/list/components/packages_list.vue
index 7067f70a923..1e38ee525b8 100644
--- a/app/assets/javascripts/packages/list/components/packages_list.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list.vue
@@ -24,10 +24,10 @@ export default {
},
computed: {
...mapState({
- perPage: state => state.pagination.perPage,
- totalItems: state => state.pagination.total,
- page: state => state.pagination.page,
- isGroupPage: state => state.config.isGroupPage,
+ perPage: (state) => state.pagination.perPage,
+ totalItems: (state) => state.pagination.total,
+ page: (state) => state.pagination.page,
+ isGroupPage: (state) => state.config.isGroupPage,
isLoading: 'isLoading',
}),
...mapGetters({ list: 'getList' }),
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 cbb3bfd35ac..2a786b92515 100644
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue
@@ -25,12 +25,12 @@ export default {
},
computed: {
...mapState({
- emptyListIllustration: state => state.config.emptyListIllustration,
- emptyListHelpUrl: state => state.config.emptyListHelpUrl,
- filterQuery: state => state.filterQuery,
- selectedType: state => state.selectedType,
- packageHelpUrl: state => state.config.packageHelpUrl,
- packagesCount: state => state.pagination?.total,
+ emptyListIllustration: (state) => state.config.emptyListIllustration,
+ emptyListHelpUrl: (state) => state.config.emptyListHelpUrl,
+ filterQuery: (state) => state.filterQuery,
+ selectedType: (state) => state.selectedType,
+ packageHelpUrl: (state) => state.config.packageHelpUrl,
+ packagesCount: (state) => state.pagination?.total,
}),
tabsToRender() {
return PACKAGE_REGISTRY_TABS;
@@ -110,7 +110,7 @@ export default {
<template #description>
<gl-sprintf v-if="filterQuery" :message="$options.i18n.widenFilters" />
<gl-sprintf v-else :message="$options.i18n.noResults">
- <template #noPackagesLink="{content}">
+ <template #noPackagesLink="{ content }">
<gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/packages/list/components/packages_sort.vue b/app/assets/javascripts/packages/list/components/packages_sort.vue
index 47e51bbdca5..4b2d9091f8f 100644
--- a/app/assets/javascripts/packages/list/components/packages_sort.vue
+++ b/app/assets/javascripts/packages/list/components/packages_sort.vue
@@ -12,12 +12,12 @@ export default {
},
computed: {
...mapState({
- isGroupPage: state => state.config.isGroupPage,
- orderBy: state => state.sorting.orderBy,
- sort: state => state.sorting.sort,
+ 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);
+ const field = this.sortableFields.find((s) => s.orderBy === this.orderBy);
return field ? field.label : '';
},
sortableFields() {
diff --git a/app/assets/javascripts/packages/list/stores/getters.js b/app/assets/javascripts/packages/list/stores/getters.js
index 0af7e453f19..85c489deda0 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';
-export default state =>
- state.packages.map(p => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) }));
+export default (state) =>
+ state.packages.map((p) => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) }));
diff --git a/app/assets/javascripts/packages/list/utils.js b/app/assets/javascripts/packages/list/utils.js
index 6a300d7bfe6..ee89d3cdefe 100644
--- a/app/assets/javascripts/packages/list/utils.js
+++ b/app/assets/javascripts/packages/list/utils.js
@@ -1,6 +1,7 @@
import { LIST_KEY_PROJECT, SORT_FIELDS } from './constants';
-export default isGroupPage => SORT_FIELDS.filter(f => f.key !== LIST_KEY_PROJECT || isGroupPage);
+export default (isGroupPage) =>
+ SORT_FIELDS.filter((f) => f.key !== LIST_KEY_PROJECT || isGroupPage);
/**
* A small util function that works out if the delete action has deleted the
diff --git a/app/assets/javascripts/packages/shared/components/package_tags.vue b/app/assets/javascripts/packages/shared/components/package_tags.vue
index 3d7e233c1ba..5172b855fc3 100644
--- a/app/assets/javascripts/packages/shared/components/package_tags.vue
+++ b/app/assets/javascripts/packages/shared/components/package_tags.vue
@@ -43,7 +43,7 @@ export default {
if (this.moreTagsDisplay) {
return this.tags
.slice(this.tagDisplayLimit)
- .map(x => x.name)
+ .map((x) => x.name)
.join(', ');
}
diff --git a/app/assets/javascripts/packages/shared/utils.js b/app/assets/javascripts/packages/shared/utils.js
index d7a883e4397..677550f77ec 100644
--- a/app/assets/javascripts/packages/shared/utils.js
+++ b/app/assets/javascripts/packages/shared/utils.js
@@ -1,13 +1,13 @@
import { s__ } from '~/locale';
import { PackageType, TrackingCategories } from './constants';
-export const packageTypeToTrackCategory = type =>
+export const packageTypeToTrackCategory = (type) =>
// eslint-disable-next-line @gitlab/require-i18n-strings
`UI::${TrackingCategories[type]}`;
-export const beautifyPath = path => (path ? path.split('/').join(' / ') : '');
+export const beautifyPath = (path) => (path ? path.split('/').join(' / ') : '');
-export const getPackageTypeLabel = packageType => {
+export const getPackageTypeLabel = (packageType) => {
switch (packageType) {
case PackageType.CONAN:
return s__('PackageType|Conan');
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
new file mode 100644
index 00000000000..a3d507180c6
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
@@ -0,0 +1,20 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import SettingsApp from './components/group_settings_app.vue';
+import { apolloProvider } from './graphql';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.getElementById('js-packages-and-registries-settings');
+ if (!el) {
+ return null;
+ }
+ return new Vue({
+ el,
+ apolloProvider,
+ 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
new file mode 100644
index 00000000000..6bcecf43a13
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
@@ -0,0 +1,9 @@
+<script>
+export default {
+ name: 'GroupSettingsApp',
+};
+</script>
+
+<template>
+ <section></section>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js
new file mode 100644
index 00000000000..16152eb81f6
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+
+Vue.use(VueApollo);
+
+export const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ assumeImmutableResults: true,
+ },
+ ),
+});
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js
index 038bbe392ba..e92262852cf 100644
--- a/app/assets/javascripts/pages/admin/admin.js
+++ b/app/assets/javascripts/pages/admin/admin.js
@@ -23,7 +23,7 @@ export default function adminInit() {
}
});
- $('body').on('click', '.js-toggle-colors-link', e => {
+ $('body').on('click', '.js-toggle-colors-link', (e) => {
e.preventDefault();
$('.js-toggle-colors-container').toggleClass('hide');
});
@@ -33,7 +33,7 @@ export default function adminInit() {
$(this).tab('show');
});
- $('.log-bottom').on('click', e => {
+ $('.log-bottom').on('click', (e) => {
e.preventDefault();
const $visibleLog = $('.file-content:visible');
@@ -52,7 +52,7 @@ export default function adminInit() {
modal.show();
});
- $('.change-owner-cancel-link').on('click', e => {
+ $('.change-owner-cancel-link').on('click', (e) => {
e.preventDefault();
modal.hide();
$('.change-owner-link').show();
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 f8fc53799a8..b995cb1d3dd 100644
--- a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
@@ -14,7 +14,7 @@ export default class PayloadPreviewer {
this.spinner = this.trigger.querySelector('.js-spinner');
this.text = this.trigger.querySelector('.js-text');
- this.trigger.addEventListener('click', event => {
+ this.trigger.addEventListener('click', (event) => {
event.preventDefault();
if (this.isVisible) return this.hidePayload();
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 a75f5d318a0..9e4c4d9f615 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
@@ -82,7 +82,7 @@ export default () => {
return $jsBroadcastMessagePreview.css(selectedColorStyle);
};
- const setSuggestedColor = e => {
+ const setSuggestedColor = (e) => {
const color = $(e.currentTarget).data('color');
$broadcastMessageColor
.val(color)
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 4b6f52c09be..d65593963ce 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
@@ -26,11 +26,11 @@ export default {
onSubmit() {
return axios
.post(this.url)
- .then(response => {
+ .then((response) => {
// follow the rediect to refresh the page
redirectTo(response.request.responseURL);
})
- .catch(error => {
+ .catch((error) => {
createFlash(s__('AdminArea|Stopping jobs failed'));
throw error;
});
diff --git a/app/assets/javascripts/pages/admin/projects/index.js b/app/assets/javascripts/pages/admin/projects/index.js
index d86c5e2ddb8..fa2b0546c02 100644
--- a/app/assets/javascripts/pages/admin/projects/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index.js
@@ -24,5 +24,5 @@ document.addEventListener('DOMContentLoaded', () => {
document
.querySelectorAll('.js-namespace-select')
- .forEach(dropdown => new NamespaceSelect({ dropdown }));
+ .forEach((dropdown) => new NamespaceSelect({ dropdown }));
});
diff --git a/app/assets/javascripts/pages/admin/projects/index/index.js b/app/assets/javascripts/pages/admin/projects/index/index.js
index ebb1a74e970..bf512ef395d 100644
--- a/app/assets/javascripts/pages/admin/projects/index/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index/index.js
@@ -18,7 +18,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
mounted() {
const deleteProjectButtons = document.querySelectorAll('.delete-project-button');
- deleteProjectButtons.forEach(button => {
+ deleteProjectButtons.forEach((button) => {
button.addEventListener('click', () => {
const buttonProps = button.dataset;
deleteModal.deleteProjectUrl = buttonProps.deleteProjectUrl;
diff --git a/app/assets/javascripts/pages/admin/users/index.js b/app/assets/javascripts/pages/admin/users/index.js
index 07462b4592f..75a8284f5f8 100644
--- a/app/assets/javascripts/pages/admin/users/index.js
+++ b/app/assets/javascripts/pages/admin/users/index.js
@@ -17,7 +17,7 @@ function loadModalsConfigurationFromHtml(modalsElement) {
throw new Error('Modals content element not found!');
}
- Array.from(modalsElement.children).forEach(node => {
+ Array.from(modalsElement.children).forEach((node) => {
const { modal, ...config } = node.dataset;
modalsConfiguration[modal] = {
title: node.dataset.title,
diff --git a/app/assets/javascripts/pages/admin/users/new/index.js b/app/assets/javascripts/pages/admin/users/new/index.js
index 3e6a090cb0e..7b7d4c169ef 100644
--- a/app/assets/javascripts/pages/admin/users/new/index.js
+++ b/app/assets/javascripts/pages/admin/users/new/index.js
@@ -15,7 +15,7 @@ export default class UserInternalRegexHandler {
}
addListenerToEmailField() {
- $('#user_email').on('input', event => {
+ $('#user_email').on('input', (event) => {
this.setExternalCheckbox(event.currentTarget.value);
});
}
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 9fa441348c7..bed753b0c40 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
@@ -57,7 +57,7 @@ export default {
.post(this.calloutsPath, {
feature_name: this.calloutsFeatureId,
})
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line @gitlab/require-i18n-strings, no-console
console.error('Failed to dismiss banner.', e);
});
diff --git a/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js b/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js
index c0735dde1da..8cdcd3134ee 100644
--- a/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js
+++ b/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js
@@ -11,6 +11,6 @@ export default () => {
return new Vue({
el,
provide: { ...el.dataset },
- render: createElement => createElement(CustomizeHomepageBanner),
+ render: (createElement) => createElement(CustomizeHomepageBanner),
});
};
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index 6f8d954d798..bd283201eff 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -154,7 +154,7 @@ export default class Todos {
goToTodoUrl(e) {
const todoLink = this.dataset.url;
- if (!todoLink || e.target.tagName === 'A' || e.target.tagName === 'IMG') {
+ if (!todoLink || e.target.closest('a')) {
return;
}
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index d3900b84fa7..5346e3720e8 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -1,10 +1,11 @@
import Vue from 'vue';
-import Members from 'ee_else_ce/members';
import memberExpirationDate from '~/member_expiration_date';
import UsersSelect from '~/users_select';
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';
@@ -65,6 +66,7 @@ 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
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index 4d0a03e151a..5cb21ca61ab 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -9,6 +9,7 @@ import initManualOrdering from '~/manual_ordering';
const ISSUE_BULK_UPDATE_PREFIX = 'issue_';
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
+IssuableFilteredSearchTokenKeys.removeTokensForKeys('release');
issuableInitBulkUpdateSidebar.init(ISSUE_BULK_UPDATE_PREFIX);
initIssuablesList();
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 83b38b0f1a5..97f3d8cf7f5 100644
--- a/app/assets/javascripts/pages/groups/new/group_path_validator.js
+++ b/app/assets/javascripts/pages/groups/new/group_path_validator.js
@@ -21,11 +21,11 @@ export default class GroupPathValidator extends InputValidator {
const container = opts.container || '';
const validateElements = document.querySelectorAll(`${container} .js-validate-group-path`);
- this.debounceValidateInput = debounce(inputDomElement => {
+ this.debounceValidateInput = debounce((inputDomElement) => {
GroupPathValidator.validateGroupPathInput(inputDomElement);
}, debounceTimeoutDuration);
- validateElements.forEach(element =>
+ validateElements.forEach((element) =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
@@ -45,7 +45,7 @@ export default class GroupPathValidator extends InputValidator {
fetchGroupPathAvailability(groupPath)
.then(({ data }) => data)
- .then(data => {
+ .then((data) => {
GroupPathValidator.setInputState(inputDomElement, !data.exists);
GroupPathValidator.setMessageVisibility(inputDomElement, pendingMessageSelector, false);
GroupPathValidator.setMessageVisibility(
diff --git a/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js b/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js
new file mode 100644
index 00000000000..3b922622d2c
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js
@@ -0,0 +1,3 @@
+import bundle from '~/packages_and_registries/settings/group/bundle';
+
+bundle();
diff --git a/app/assets/javascripts/pages/groups/shared/group_tabs.js b/app/assets/javascripts/pages/groups/shared/group_tabs.js
index c6fe61d2bd9..033843d8504 100644
--- a/app/assets/javascripts/pages/groups/shared/group_tabs.js
+++ b/app/assets/javascripts/pages/groups/shared/group_tabs.js
@@ -20,7 +20,7 @@ export default class GroupTabs extends UserTabs {
bindEvents() {
this.$parentEl
.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
- .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event));
+ .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', (event) => this.tabShown(event));
}
tabShown(event) {
@@ -117,7 +117,7 @@ export default class GroupTabs extends UserTabs {
cleanFilterState() {
const values = Object.values(this.loaded);
- const loadedTabs = values.filter(e => e === true);
+ const loadedTabs = values.filter((e) => e === true);
if (!loadedTabs.length) {
return;
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 93fe38831be..f47945c5a9f 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
@@ -82,7 +82,7 @@ Once deleted, it cannot be undone or recovered.`),
return axios
.delete(this.milestoneUrl)
- .then(response => {
+ .then((response) => {
eventHub.$emit('deleteMilestoneModal.requestFinished', {
milestoneUrl: this.milestoneUrl,
successful: true,
@@ -91,7 +91,7 @@ Once deleted, it cannot be undone or recovered.`),
// follow the rediect to milestones overview page
redirectTo(response.request.responseURL);
})
- .catch(error => {
+ .catch((error) => {
eventHub.$emit('deleteMilestoneModal.requestFinished', {
milestoneUrl: this.milestoneUrl,
successful: false,
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 0dc54b612ba..ecde11aff40 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,28 +1,22 @@
<script>
+import { GlModal } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
-import eventHub from '../event_hub';
export default {
components: {
- GlModal: DeprecatedModal2,
+ GlModal,
},
- props: {
- milestoneTitle: {
- type: String,
- required: true,
- },
- url: {
- type: String,
- required: true,
- },
- groupName: {
- type: String,
- required: true,
- },
+ data() {
+ return {
+ milestoneTitle: '',
+ url: '',
+ groupName: '',
+ currentButton: null,
+ visible: false,
+ };
},
computed: {
title() {
@@ -38,42 +32,71 @@ export default {
);
},
},
+ mounted() {
+ this.getButtons().forEach((button) => {
+ button.addEventListener('click', this.onPromoteButtonClick);
+ button.removeAttribute('disabled');
+ });
+ },
+ beforeDestroy() {
+ this.getButtons().forEach((button) => {
+ button.removeEventListener('click', this.onPromoteButtonClick);
+ });
+ },
methods: {
+ onPromoteButtonClick({ currentTarget }) {
+ const { milestoneTitle, url, groupName } = currentTarget.dataset;
+ currentTarget.setAttribute('disabled', '');
+ this.visible = true;
+ this.milestoneTitle = milestoneTitle;
+ this.url = url;
+ this.groupName = groupName;
+ this.currentButton = currentTarget;
+ },
+ getButtons() {
+ return document.querySelectorAll('.js-promote-project-milestone-button');
+ },
onSubmit() {
- eventHub.$emit('promoteMilestoneModal.requestStarted', this.url);
return axios
.post(this.url, { params: { format: 'json' } })
- .then(response => {
- eventHub.$emit('promoteMilestoneModal.requestFinished', {
- milestoneUrl: this.url,
- successful: true,
- });
+ .then((response) => {
visitUrl(response.data.url);
})
- .catch(error => {
- eventHub.$emit('promoteMilestoneModal.requestFinished', {
- milestoneUrl: this.url,
- successful: false,
- });
+ .catch((error) => {
createFlash(error);
+ })
+ .finally(() => {
+ this.visible = false;
});
},
+ onClose() {
+ this.visible = false;
+ if (this.currentButton) {
+ this.currentButton.removeAttribute('disabled');
+ }
+ },
+ },
+ primaryAction: {
+ text: s__('Milestones|Promote Milestone'),
+ attributes: [{ variant: 'warning' }],
+ },
+ cancelAction: {
+ text: s__('Cancel'),
+ attributes: [],
},
};
</script>
<template>
<gl-modal
- id="promote-milestone-modal"
- :footer-primary-button-text="s__('Milestones|Promote Milestone')"
- footer-primary-button-variant="warning"
- @submit="onSubmit"
+ :visible="visible"
+ modal-id="promote-milestone-modal"
+ :action-primary="$options.primaryAction"
+ :action-cancel="$options.cancelAction"
+ :title="title"
+ @primary="onSubmit"
+ @hide="onClose"
>
- <template #title>
- {{ title }}
- </template>
- <div>
- <p>{{ text }}</p>
- <p>{{ s__('Milestones|This action cannot be reversed.') }}</p>
- </div>
+ <p>{{ text }}</p>
+ <p>{{ s__('Milestones|This action cannot be reversed.') }}</p>
</gl-modal>
</template>
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 6e68114e04b..e8b67891c42 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
@@ -20,7 +20,7 @@ export default () => {
const deleteMilestoneButtons = document.querySelectorAll('.js-delete-milestone-button');
- const onRequestStarted = milestoneUrl => {
+ const onRequestStarted = (milestoneUrl) => {
const button = document.querySelector(
`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
);
@@ -44,7 +44,7 @@ export default () => {
},
mounted() {
eventHub.$on('deleteMilestoneModal.props', this.setModalProps);
- deleteMilestoneButtons.forEach(button => {
+ deleteMilestoneButtons.forEach((button) => {
button.removeAttribute('disabled');
button.addEventListener('click', () => {
this.$root.$emit('bv::show::modal', 'delete-milestone-modal');
diff --git a/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js b/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
index fcc62a2b2af..5472b8c684f 100644
--- a/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
+++ b/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
@@ -1,88 +1,19 @@
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import PromoteMilestoneModal from './components/promote_milestone_modal.vue';
-import eventHub from './event_hub';
Vue.use(Translate);
export default () => {
- const onRequestFinished = ({ milestoneUrl, successful }) => {
- const button = document.querySelector(
- `.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`,
- );
-
- if (!successful) {
- button.removeAttribute('disabled');
- }
- };
-
- const onRequestStarted = milestoneUrl => {
- const button = document.querySelector(
- `.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`,
- );
- button.setAttribute('disabled', '');
- eventHub.$once('promoteMilestoneModal.requestFinished', onRequestFinished);
- };
-
- const onDeleteButtonClick = event => {
- const button = event.currentTarget;
- const modalProps = {
- milestoneTitle: button.dataset.milestoneTitle,
- url: button.dataset.url,
- groupName: button.dataset.groupName,
- };
- eventHub.$once('promoteMilestoneModal.requestStarted', onRequestStarted);
- eventHub.$emit('promoteMilestoneModal.props', modalProps);
- };
-
- const promoteMilestoneButtons = document.querySelectorAll('.js-promote-project-milestone-button');
- promoteMilestoneButtons.forEach(button => {
- button.addEventListener('click', onDeleteButtonClick);
- });
-
- eventHub.$once('promoteMilestoneModal.mounted', () => {
- promoteMilestoneButtons.forEach(button => {
- button.removeAttribute('disabled');
- });
- });
-
const promoteMilestoneModal = document.getElementById('promote-milestone-modal');
- let promoteMilestoneComponent;
-
- if (promoteMilestoneModal) {
- promoteMilestoneComponent = new Vue({
- el: promoteMilestoneModal,
- components: {
- PromoteMilestoneModal,
- },
- data() {
- return {
- modalProps: {
- milestoneTitle: '',
- groupName: '',
- url: '',
- },
- };
- },
- mounted() {
- eventHub.$on('promoteMilestoneModal.props', this.setModalProps);
- eventHub.$emit('promoteMilestoneModal.mounted');
- },
- beforeDestroy() {
- eventHub.$off('promoteMilestoneModal.props', this.setModalProps);
- },
- methods: {
- setModalProps(modalProps) {
- this.modalProps = modalProps;
- },
- },
- render(createElement) {
- return createElement('promote-milestone-modal', {
- props: this.modalProps,
- });
- },
- });
+ if (!promoteMilestoneModal) {
+ return null;
}
- return promoteMilestoneComponent;
+ return new Vue({
+ el: promoteMilestoneModal,
+ render(createElement) {
+ return createElement(PromoteMilestoneModal);
+ },
+ });
};
diff --git a/app/assets/javascripts/pages/profiles/index.js b/app/assets/javascripts/pages/profiles/index.js
index 883be18b336..d2b00d0ef45 100644
--- a/app/assets/javascripts/pages/profiles/index.js
+++ b/app/assets/javascripts/pages/profiles/index.js
@@ -4,7 +4,7 @@ import Profile from '~/profile/profile';
document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line func-names
- $(document).on('input.ssh_key', '#key_key', function() {
+ $(document).on('input.ssh_key', '#key_key', function () {
const $title = $('#key_title');
const comment = $(this)
.val()
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index 60510eac384..b78f24ca2fb 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -14,7 +14,7 @@ document.addEventListener('DOMContentLoaded', () => {
const statusEmojiField = document.getElementById('js-status-emoji-field');
const statusMessageField = document.getElementById('js-status-message-field');
- const toggleNoEmojiPlaceholder = isVisible => {
+ const toggleNoEmojiPlaceholder = (isVisible) => {
const placeholderElement = document.getElementById('js-no-emoji-placeholder');
placeholderElement.classList.toggle('hidden', !isVisible);
};
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index a96b88732b4..57c4ffd3933 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -41,7 +41,7 @@ document.addEventListener('DOMContentLoaded', () => {
const { codeNavigationPath, blobPath, definitionPathPrefix } = codeNavEl.dataset;
// eslint-disable-next-line promise/catch-or-return
- import('~/code_navigation').then(m =>
+ import('~/code_navigation').then((m) =>
m.default({
blobs: [{ path: blobPath, codeNavigationPath }],
definitionPathPrefix,
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index 0750f472341..5cfdb125e4f 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -14,6 +14,8 @@ import flash from '~/flash';
import { __ } from '~/locale';
import loadAwardsHandler from '~/awards_handler';
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';
const hasPerfBar = document.querySelector('.with-performance-bar');
const performanceHeight = hasPerfBar ? 35 : 0;
@@ -45,3 +47,5 @@ if (filesContainer.length) {
new Diff();
}
loadAwardsHandler();
+initRevertCommitModal();
+initRevertCommitTrigger();
diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js
index 7eeb0c852e5..5f1d3edc3ba 100644
--- a/app/assets/javascripts/pages/projects/edit/index.js
+++ b/app/assets/javascripts/pages/projects/edit/index.js
@@ -10,6 +10,7 @@ import initProjectPermissionsSettings from '../shared/permissions';
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';
document.addEventListener('DOMContentLoaded', () => {
initFilePickers();
@@ -30,4 +31,6 @@ document.addEventListener('DOMContentLoaded', () => {
'.js-general-settings-form, .js-mr-settings-form, .js-mr-approvals-form',
),
);
+
+ mountSearchSettings();
});
diff --git a/app/assets/javascripts/pages/projects/edit/mount_search_settings.js b/app/assets/javascripts/pages/projects/edit/mount_search_settings.js
new file mode 100644
index 00000000000..6c477dd7e80
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/edit/mount_search_settings.js
@@ -0,0 +1,12 @@
+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/forks/new/components/fork_groups_list.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
index 6c0d20c55e9..a614443bcd9 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
@@ -31,7 +31,9 @@ export default {
},
computed: {
filteredNamespaces() {
- return this.namespaces.filter(n => n.name.toLowerCase().includes(this.filter.toLowerCase()));
+ return this.namespaces.filter((n) =>
+ n.name.toLowerCase().includes(this.filter.toLowerCase()),
+ );
},
},
@@ -43,7 +45,7 @@ export default {
loadGroups() {
axios
.get(this.endpoint)
- .then(response => {
+ .then((response) => {
this.namespaces = response.data.namespaces;
})
.catch(() => createFlash(__('There was a problem fetching groups.')));
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
index 6cf36463bda..ea38b8e15a4 100644
--- a/app/assets/javascripts/pages/projects/graphs/charts/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -5,7 +5,7 @@ import { __ } from '~/locale';
import CodeCoverage from '../components/code_coverage.vue';
import SeriesDataMixin from './series_data_mixin';
-const seriesDataToBarData = raw => Object.entries(raw).map(([name, data]) => ({ name, data }));
+const seriesDataToBarData = (raw) => Object.entries(raw).map(([name, data]) => ({ name, data }));
document.addEventListener('DOMContentLoaded', () => {
waitForCSSLoaded(() => {
@@ -43,7 +43,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
computed: {
seriesData() {
- return [{ name: 'full', data: this.chartData.map(d => [d.label, d.value]) }];
+ return [{ name: 'full', data: this.chartData.map((d) => [d.label, d.value]) }];
},
},
render(h) {
diff --git a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
index 6dd50958fa4..3b5e764b712 100644
--- a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
+++ b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
@@ -74,7 +74,7 @@ export default {
);
},
formattedData() {
- return this.sortedData.map(value => [dateFormat(value.date, 'mmm dd'), value.coverage]);
+ return this.sortedData.map((value) => [dateFormat(value.date, 'mmm dd'), value.coverage]);
},
chartData() {
return [
@@ -161,9 +161,7 @@ export default {
<template #coveragePercentage>
{{ coveragePercentage }}
</template>
- <template #percentSymbol>
- %
- </template>
+ <template #percentSymbol> % </template>
</gl-sprintf>
</template>
</gl-area-chart>
diff --git a/app/assets/javascripts/pages/projects/init_form.js b/app/assets/javascripts/pages/projects/init_form.js
index 019efe077f7..9f20a3e4e46 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';
-export default function($formEl) {
+export default function ($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/service_desk/filtered_search.js b/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js
index fc0922d9112..ccb453a59ea 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
@@ -21,7 +21,7 @@ export default class FilteredSearchServiceDesk extends FilteredSearchManager {
modifyUrlParams(paramsArray) {
const supportBotParamPair = `${AUTHOR_PARAM_KEY}=${this.supportBotData.username}`;
- const onlyValidParams = paramsArray.filter(param => param.indexOf(AUTHOR_PARAM_KEY) === -1);
+ const onlyValidParams = paramsArray.filter((param) => param.indexOf(AUTHOR_PARAM_KEY) === -1);
// unshift ensures author param is always first token element
onlyValidParams.unshift(supportBotParamPair);
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 614f8262e5b..7068574ecb8 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -16,7 +16,7 @@ import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
import { IssuableType } from '~/issuable_show/constants';
-export default function() {
+export default function () {
const initialDataEl = document.getElementById('js-issuable-app');
const { issueType, ...issuableData } = parseIssuableData(initialDataEl);
@@ -37,7 +37,7 @@ export default function() {
initRelatedMergeRequestsApp();
import(/* webpackChunkName: 'design_management' */ '~/design_management')
- .then(module => module.default())
+ .then((module) => module.default())
.catch(() => {});
new ZenMode(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/jobs/index/index.js b/app/assets/javascripts/pages/projects/jobs/index/index.js
index ae04d070e62..c343a37b292 100644
--- a/app/assets/javascripts/pages/projects/jobs/index/index.js
+++ b/app/assets/javascripts/pages/projects/jobs/index/index.js
@@ -5,7 +5,7 @@ import Tracking from '~/tracking';
document.addEventListener('DOMContentLoaded', () => {
const remainingTimeElements = document.querySelectorAll('.js-remaining-time');
remainingTimeElements.forEach(
- el =>
+ (el) =>
new Vue({
...GlCountdown,
el,
@@ -22,5 +22,5 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
const buttons = document.querySelectorAll('.js-empty-state-button');
- buttons.forEach(button => button.addEventListener('click', trackButtonClick));
+ 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 7b5e0f70b7b..8626fd18233 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
@@ -58,14 +58,14 @@ export default {
eventHub.$emit('promoteLabelModal.requestStarted', this.url);
return axios
.post(this.url, { params: { format: 'json' } })
- .then(response => {
+ .then((response) => {
eventHub.$emit('promoteLabelModal.requestFinished', {
labelUrl: this.url,
successful: true,
});
visitUrl(response.data.url);
})
- .catch(error => {
+ .catch((error) => {
eventHub.$emit('promoteLabelModal.requestFinished', {
labelUrl: this.url,
successful: false,
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index ee129011f9a..4f5e5c8cceb 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -19,7 +19,7 @@ const initLabelIndex = () => {
}
};
- const onRequestStarted = labelUrl => {
+ const onRequestStarted = (labelUrl) => {
const button = document.querySelector(
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
);
@@ -46,7 +46,7 @@ const initLabelIndex = () => {
eventHub.$on('promoteLabelModal.props', this.setModalProps);
eventHub.$emit('promoteLabelModal.mounted');
- promoteLabelButtons.forEach(button => {
+ promoteLabelButtons.forEach((button) => {
button.removeAttribute('disabled');
button.addEventListener('click', () => {
this.$root.$emit('bv::show::modal', 'promote-label-modal');
@@ -77,5 +77,4 @@ const initLabelIndex = () => {
},
});
};
-
-document.addEventListener('DOMContentLoaded', initLabelIndex);
+initLabelIndex();
diff --git a/app/assets/javascripts/pages/projects/labels/new/index.js b/app/assets/javascripts/pages/projects/labels/new/index.js
index 83d6ac9fd14..2e8308fe084 100644
--- a/app/assets/javascripts/pages/projects/labels/new/index.js
+++ b/app/assets/javascripts/pages/projects/labels/new/index.js
@@ -1,3 +1,4 @@
import Labels from 'ee_else_ce/labels';
-document.addEventListener('DOMContentLoaded', () => new Labels());
+// eslint-disable-next-line no-new
+new Labels();
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 46f3f55a400..eb2692c7cb4 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
@@ -19,7 +19,7 @@ const updateCommitList = (url, $loadingIndicator, $commitList, params) => {
});
};
-export default mrNewCompareNode => {
+export default (mrNewCompareNode) => {
const { sourceBranchUrl, targetBranchUrl } = mrNewCompareNode.dataset;
initTargetProjectDropdown();
@@ -29,9 +29,7 @@ export default mrNewCompareNode => {
$(mrNewCompareNode).find('.js-source-loading'),
$(mrNewCompareNode).find('.mr_source_commit'),
{
- ref: $(mrNewCompareNode)
- .find("input[name='merge_request[source_branch]']")
- .val(),
+ ref: $(mrNewCompareNode).find("input[name='merge_request[source_branch]']").val(),
},
);
const updateTargetBranchCommitList = () =>
@@ -43,12 +41,10 @@ export default mrNewCompareNode => {
target_project_id: $(mrNewCompareNode)
.find("input[name='merge_request[target_project_id]']")
.val(),
- ref: $(mrNewCompareNode)
- .find("input[name='merge_request[target_branch]']")
- .val(),
+ ref: $(mrNewCompareNode).find("input[name='merge_request[target_branch]']").val(),
},
);
- initCompareAutocomplete('branches', $dropdown => {
+ initCompareAutocomplete('branches', ($dropdown) => {
if ($dropdown.is('.js-target-branch')) {
updateTargetBranchCommitList();
} else if ($dropdown.is('.js-source-branch')) {
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 0714fc21b17..1a0c5860991 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,3 +1,4 @@
+import Vue from 'vue';
import ZenMode from '~/zen_mode';
import initIssuableSidebar from '~/init_issuable_sidebar';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
@@ -7,8 +8,9 @@ import initSourcegraph from '~/sourcegraph';
import loadAwardsHandler from '~/awards_handler';
import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
+import StatusBox from '~/merge_request/components/status_box.vue';
-export default function() {
+export default function () {
new ZenMode(); // eslint-disable-line no-new
initIssuableSidebar();
initPipelines();
@@ -18,4 +20,17 @@ export default function() {
loadAwardsHandler();
initInviteMemberModal();
initInviteMemberTrigger();
+
+ const el = document.querySelector('.js-mr-status-box');
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render(h) {
+ return h(StatusBox, {
+ props: {
+ initialState: el.dataset.state,
+ },
+ });
+ },
+ });
}
diff --git a/app/assets/javascripts/pages/projects/new/index.js b/app/assets/javascripts/pages/projects/new/index.js
index 19aeb1d1ecf..88f4db3ec08 100644
--- a/app/assets/javascripts/pages/projects/new/index.js
+++ b/app/assets/javascripts/pages/projects/new/index.js
@@ -10,7 +10,7 @@ document.addEventListener('DOMContentLoaded', () => {
import(
/* webpackChunkName: 'experiment_new_project_creation' */ '../../../projects/experiment_new_project_creation'
)
- .then(m => {
+ .then((m) => {
const el = document.querySelector('.js-experiment-new-project-creation');
if (!el) {
@@ -20,6 +20,7 @@ document.addEventListener('DOMContentLoaded', () => {
const config = {
hasErrors: 'hasErrors' in el.dataset,
isCiCdAvailable: 'isCiCdAvailable' in el.dataset,
+ newProjectGuidelines: el.dataset.newProjectGuidelines,
};
m.default(el, config);
})
diff --git a/app/assets/javascripts/pages/projects/pages_domains/form.js b/app/assets/javascripts/pages/projects/pages_domains/form.js
index ae5368179b1..169530685ad 100644
--- a/app/assets/javascripts/pages/projects/pages_domains/form.js
+++ b/app/assets/javascripts/pages/projects/pages_domains/form.js
@@ -1,7 +1,7 @@
import setupToggleButtons from '~/toggle_buttons';
function updateVisibility(selector, isVisible) {
- Array.from(document.querySelectorAll(selector)).forEach(el => {
+ Array.from(document.querySelectorAll(selector)).forEach((el) => {
if (isVisible) {
el.classList.remove('d-none');
} else {
@@ -14,12 +14,12 @@ export default () => {
const toggleContainer = document.querySelector('.js-auto-ssl-toggle-container');
if (toggleContainer) {
- const onToggleButtonClicked = isAutoSslEnabled => {
+ const onToggleButtonClicked = (isAutoSslEnabled) => {
updateVisibility('.js-shown-unless-auto-ssl', !isAutoSslEnabled);
updateVisibility('.js-shown-if-auto-ssl', isAutoSslEnabled);
- Array.from(document.querySelectorAll('.js-enabled-unless-auto-ssl')).forEach(el => {
+ Array.from(document.querySelectorAll('.js-enabled-unless-auto-ssl')).forEach((el) => {
if (isAutoSslEnabled) {
el.setAttribute('disabled', 'disabled');
} else {
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
index 90d2df50d5a..40730ec7e60 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -13,12 +13,12 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-new
new Vue({
el,
- render(createElement) {
- return createElement(PipelineSchedulesCallout);
- },
provide: {
docsUrl,
illustrationUrl,
},
+ render(createElement) {
+ return createElement(PipelineSchedulesCallout);
+ },
});
});
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 5ef1f959b2c..aa7414f3ae7 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
@@ -125,7 +125,7 @@ export default {
:data-testid="option.value"
>
<gl-sprintf v-if="option.link" :message="option.text">
- <template #link="{content}">
+ <template #link="{ content }">
<gl-link :href="option.link" target="_blank" class="gl-font-sm">
{{ content }}
</gl-link>
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
index 4b203891640..6017cd653e4 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
@@ -15,19 +15,19 @@ export default class TargetBranchDropdown {
data: this.formatBranchesList(),
filterable: true,
selectable: true,
- toggleLabel: item => item.name,
+ toggleLabel: (item) => item.name,
search: {
fields: ['name'],
},
- clicked: cfg => this.updateInputValue(cfg),
- text: item => item.name,
+ clicked: (cfg) => this.updateInputValue(cfg),
+ text: (item) => item.name,
});
this.setDropdownToggle();
}
formatBranchesList() {
- return this.$dropdown.data('data').map(val => ({ name: val }));
+ return this.$dropdown.data('data').map((val) => ({ name: val }));
}
setDropdownToggle() {
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
index 2a58e015ff1..16c4a6191b2 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
@@ -5,10 +5,10 @@ const defaults = {
$inputEl: null,
$dropdownEl: null,
onSelectTimezone: null,
- displayFormat: item => item.name,
+ displayFormat: (item) => item.name,
};
-export const formatUtcOffset = offset => {
+export const formatUtcOffset = (offset) => {
const parsed = parseInt(offset, 10);
if (Number.isNaN(parsed) || parsed === 0) {
return `0`;
@@ -17,11 +17,11 @@ export const formatUtcOffset = offset => {
return `${prefix} ${Math.abs(offset / 3600)}`;
};
-export const formatTimezone = item => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`;
+export const formatTimezone = (item) => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`;
export const findTimezoneByIdentifier = (tzList = [], identifier = null) => {
if (tzList && tzList.length && identifier && identifier.length) {
- return tzList.find(tz => tz.identifier === identifier) || null;
+ return tzList.find((tz) => tz.identifier === identifier) || null;
}
return null;
};
@@ -52,8 +52,8 @@ export default class TimezoneDropdown {
search: {
fields: ['name'],
},
- clicked: cfg => this.updateInputValue(cfg),
- text: item => formatTimezone(item),
+ clicked: (cfg) => this.updateInputValue(cfg),
+ text: (item) => formatTimezone(item),
});
this.setDropdownToggle(this.displayFormat(this.initialTimezone));
diff --git a/app/assets/javascripts/pages/projects/pipelines/charts/index.js b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
index d77b84a3b24..44d7555e639 100644
--- a/app/assets/javascripts/pages/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
@@ -1,3 +1,3 @@
import initProjectPipelinesChartsApp from '~/projects/pipelines/charts/index';
-document.addEventListener('DOMContentLoaded', initProjectPipelinesChartsApp);
+initProjectPipelinesChartsApp();
diff --git a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
index 5fd3fce88aa..0c29f8817e7 100644
--- a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
+++ b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
@@ -6,7 +6,7 @@ export default () => {
const fullMergeRequestList = document.querySelector('.js-full-mr-list');
if (mergeRequestListToggle) {
- mergeRequestListToggle.addEventListener('click', e => {
+ mergeRequestListToggle.addEventListener('click', (e) => {
e.preventDefault();
truncatedMergeRequestList.classList.toggle('hide');
fullMergeRequestList.classList.toggle('hide');
diff --git a/app/assets/javascripts/pages/projects/pipelines/new/index.js b/app/assets/javascripts/pages/projects/pipelines/new/index.js
index d5563143f0c..08c31f2b3c6 100644
--- a/app/assets/javascripts/pages/projects/pipelines/new/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/new/index.js
@@ -3,17 +3,15 @@ import NewBranchForm from '~/new_branch_form';
import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
import initNewPipeline from '~/pipeline_new/index';
-document.addEventListener('DOMContentLoaded', () => {
- const el = document.getElementById('js-new-pipeline');
+const el = document.getElementById('js-new-pipeline');
- if (el) {
- initNewPipeline();
- } else {
- new NewBranchForm($('.js-new-pipeline-form')); // eslint-disable-line no-new
+if (el) {
+ initNewPipeline();
+} else {
+ new NewBranchForm($('.js-new-pipeline-form')); // eslint-disable-line no-new
- setupNativeFormVariableList({
- container: $('.js-ci-variable-list-section'),
- formField: 'variables_attributes',
- });
- }
-});
+ setupNativeFormVariableList({
+ container: $('.js-ci-variable-list-section'),
+ formField: 'variables_attributes',
+ });
+}
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 8c7aa04a0b6..ef6953db83b 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -18,34 +18,26 @@ export default class Project {
// Ref switcher
if (document.querySelector('.js-project-refs-dropdown')) {
Project.initRefSwitcher();
- $('.project-refs-select').on('change', function() {
- return $(this)
- .parents('form')
- .trigger('submit');
+ $('.project-refs-select').on('change', function () {
+ return $(this).parents('form').trigger('submit');
});
}
- $('.hide-no-ssh-message').on('click', function(e) {
+ $('.hide-no-ssh-message').on('click', function (e) {
Cookies.set('hide_no_ssh_message', 'false');
- $(this)
- .parents('.no-ssh-key-message')
- .remove();
+ $(this).parents('.no-ssh-key-message').remove();
return e.preventDefault();
});
- $('.hide-no-password-message').on('click', function(e) {
+ $('.hide-no-password-message').on('click', function (e) {
Cookies.set('hide_no_password_message', 'false');
- $(this)
- .parents('.no-password-message')
- .remove();
+ $(this).parents('.no-password-message').remove();
return e.preventDefault();
});
- $('.hide-auto-devops-implicitly-enabled-banner').on('click', function(e) {
+ $('.hide-auto-devops-implicitly-enabled-banner').on('click', function (e) {
const projectId = $(this).data('project-id');
const cookieKey = `hide_auto_devops_implicitly_enabled_banner_${projectId}`;
Cookies.set(cookieKey, 'false');
- $(this)
- .parents('.auto-devops-implicitly-enabled-banner')
- .remove();
+ $(this).parents('.auto-devops-implicitly-enabled-banner').remove();
return e.preventDefault();
});
@@ -54,7 +46,7 @@ export default class Project {
static projectSelectDropdown() {
projectSelect();
- $('.project-item-select').on('click', e => Project.changeProject($(e.currentTarget).val()));
+ $('.project-item-select').on('click', (e) => Project.changeProject($(e.currentTarget).val()));
}
static changeProject(url) {
@@ -67,7 +59,7 @@ export default class Project {
refLink.href = '#';
- return $('.js-project-refs-dropdown').each(function() {
+ return $('.js-project-refs-dropdown').each(function () {
const $dropdown = $(this);
const selected = $dropdown.data('selected');
const fieldName = $dropdown.data('fieldName');
@@ -132,7 +124,7 @@ export default class Project {
if (loc.includes('/-/')) {
const refs = this.fullData.Branches.concat(this.fullData.Tags);
- const currentRef = refs.find(ref => loc.indexOf(ref) > -1);
+ const currentRef = refs.find((ref) => loc.indexOf(ref) > -1);
if (currentRef) {
const targetPath = loc.split(currentRef)[1].slice(1);
selectedUrl.searchParams.set('path', targetPath);
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index e146592e134..3e0a48ee6a2 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -1,9 +1,11 @@
import Vue from 'vue';
-import Members from 'ee_else_ce/members';
+import Members from '~/members';
import memberExpirationDate from '~/member_expiration_date';
import UsersSelect from '~/users_select';
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';
function mountRemoveMemberModal() {
const el = document.querySelector('.js-remove-member-modal');
@@ -24,6 +26,8 @@ document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate();
memberExpirationDate('.js-access-expiration-date-groups');
mountRemoveMemberModal();
+ initInviteMembersModal();
+ initInviteMembersTrigger();
new Members(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new
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 83bec0092cb..1321155b7ec 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
@@ -5,6 +5,7 @@ import initVariableList from '~/ci_variable_list';
import initDeployFreeze from '~/deploy_freeze';
import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers';
import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_toggle';
+import initArtifactsSettings from '~/artifacts_settings';
document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
@@ -23,7 +24,7 @@ document.addEventListener('DOMContentLoaded', () => {
// hide extra auto devops settings based checkbox state
const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings');
const instanceDefaultBadge = document.querySelector('.js-instance-default-badge');
- document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => {
+ document.querySelector('.js-toggle-extra-settings').addEventListener('click', (event) => {
const { target } = event;
if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none';
autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);
@@ -33,6 +34,7 @@ document.addEventListener('DOMContentLoaded', () => {
initDeployFreeze();
initSettingsPipelinesTriggers();
+ initArtifactsSettings();
if (gon?.features?.vueifySharedRunnersToggle) {
initSharedRunnersToggle();
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 242c58c4981..eee666bea05 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
@@ -33,6 +33,11 @@ export default {
required: false,
default: false,
},
+ showToggle: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
featureEnabled() {
@@ -74,6 +79,7 @@ export default {
>
<input v-if="name" :name="name" :value="value" type="hidden" />
<project-feature-toggle
+ v-if="showToggle"
class="gl-flex-grow-0 gl-mr-3"
:value="featureEnabled"
:disabled-input="disabledInput"
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 be197a50775..4af476fbd68 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
@@ -12,6 +12,7 @@ import {
featureAccessLevelMembers,
featureAccessLevelEveryone,
featureAccessLevel,
+ featureAccessLevelNone,
} from '../constants';
import { toggleHiddenClassBySelector } from '../external';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -140,6 +141,7 @@ export default {
metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
analyticsAccessLevel: featureAccessLevel.EVERYONE,
requirementsAccessLevel: featureAccessLevel.EVERYONE,
+ operationsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true,
lfsEnabled: true,
requestAccessEnabled: true,
@@ -167,6 +169,14 @@ export default {
);
},
+ operationsFeatureAccessLevelOptions() {
+ if (!this.operationsEnabled) return [featureAccessLevelNone];
+
+ return this.featureAccessLevelOptions.filter(
+ ([value]) => value <= this.operationsAccessLevel,
+ );
+ },
+
pagesFeatureAccessLevelOptions() {
const options = [featureAccessLevelMembers];
@@ -186,8 +196,12 @@ export default {
return options;
},
- metricsOptionsDropdownEnabled() {
- return this.featureAccessLevelOptions.length < 2;
+ metricsOptionsDropdownDisabled() {
+ return this.operationsFeatureAccessLevelOptions.length < 2 || !this.operationsEnabled;
+ },
+
+ operationsEnabled() {
+ return this.operationsAccessLevel > featureAccessLevel.NOT_ENABLED;
},
repositoryEnabled() {
@@ -250,6 +264,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.requirementsAccessLevel,
);
+ this.operationsAccessLevel = Math.min(
+ featureAccessLevel.PROJECT_MEMBERS,
+ this.operationsAccessLevel,
+ );
if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) {
// When from Internal->Private narrow access for only members
this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS;
@@ -277,6 +295,8 @@ export default {
this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE;
if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
+ if (this.operationsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
+ this.operationsAccessLevel = featureAccessLevel.EVERYONE;
this.highlightChanges();
}
@@ -334,18 +354,21 @@ export default {
<option
:value="visibilityOptions.PRIVATE"
:disabled="!visibilityAllowed(visibilityOptions.PRIVATE)"
- >{{ s__('ProjectSettings|Private') }}</option
>
+ {{ s__('ProjectSettings|Private') }}
+ </option>
<option
:value="visibilityOptions.INTERNAL"
:disabled="!visibilityAllowed(visibilityOptions.INTERNAL)"
- >{{ s__('ProjectSettings|Internal') }}</option
>
+ {{ s__('ProjectSettings|Internal') }}
+ </option>
<option
:value="visibilityOptions.PUBLIC"
:disabled="!visibilityAllowed(visibilityOptions.PUBLIC)"
- >{{ s__('ProjectSettings|Public') }}</option
>
+ {{ s__('ProjectSettings|Public') }}
+ </option>
</select>
<gl-icon
name="chevron-down"
@@ -354,6 +377,11 @@ export default {
/>
</div>
</div>
+ <span v-if="!visibilityAllowed(visibilityLevel)" class="form-text text-muted">{{
+ s__(
+ 'ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project.',
+ )
+ }}</span>
<span class="form-text text-muted">{{ visibilityLevelDescription }}</span>
<label v-if="visibilityLevel !== visibilityOptions.PRIVATE" class="gl-line-height-28">
<input
@@ -562,41 +590,34 @@ export default {
/>
</project-setting-row>
<project-setting-row
- ref="metrics-visibility-settings"
- :label="__('Metrics Dashboard')"
- :help-text="
- s__(
- 'ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics',
- )
- "
+ ref="operations-settings"
+ :label="s__('ProjectSettings|Operations')"
+ :help-text="s__('ProjectSettings|Environments, logs, cluster management, and more')"
>
- <div class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0">
- <div class="select-wrapper gl-flex-fill-1">
- <select
- v-model="metricsDashboardAccessLevel"
- :disabled="metricsOptionsDropdownEnabled"
- name="project[project_feature_attributes][metrics_dashboard_access_level]"
- class="form-control project-repo-select select-control"
- >
- <option
- :value="featureAccessLevelMembers[0]"
- :disabled="!visibilityAllowed(visibilityOptions.INTERNAL)"
- >{{ featureAccessLevelMembers[1] }}</option
- >
- <option
- :value="featureAccessLevelEveryone[0]"
- :disabled="!visibilityAllowed(visibilityOptions.PUBLIC)"
- >{{ featureAccessLevelEveryone[1] }}</option
- >
- </select>
- <gl-icon
- name="chevron-down"
- data-hidden="true"
- class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500"
- />
- </div>
- </div>
+ <project-feature-setting
+ v-model="operationsAccessLevel"
+ :options="featureAccessLevelOptions"
+ name="project[project_feature_attributes][operations_access_level]"
+ />
</project-setting-row>
+ <div class="project-feature-setting-group gl-pl-7 gl-sm-pl-5">
+ <project-setting-row
+ ref="metrics-visibility-settings"
+ :label="__('Metrics Dashboard')"
+ :help-text="
+ s__(
+ 'ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics',
+ )
+ "
+ >
+ <project-feature-setting
+ v-model="metricsDashboardAccessLevel"
+ :show-toggle="false"
+ :options="operationsFeatureAccessLevelOptions"
+ name="project[project_feature_attributes][metrics_dashboard_access_level]"
+ />
+ </project-setting-row>
+ </div>
</div>
<project-setting-row v-if="canDisableEmails" ref="email-settings" class="mb-3">
<label class="js-emails-disabled">
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/external.js b/app/assets/javascripts/pages/projects/shared/permissions/external.js
index 460af4a2111..49f6ebcc20f 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/external.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/external.js
@@ -14,5 +14,5 @@ export function toggleHiddenClassBySelector(selector, hidden) {
if (!selectorCache[selector]) {
selectorCache[selector] = document.querySelectorAll(selector);
}
- selectorCache[selector].forEach(elm => toggleHiddenClass(elm, hidden));
+ selectorCache[selector].forEach((elm) => toggleHiddenClass(elm, hidden));
}
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/index.js b/app/assets/javascripts/pages/projects/shared/permissions/index.js
index dbde8dda634..d7bae44e96e 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/index.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/index.js
@@ -8,6 +8,6 @@ export default function initProjectPermissionsSettings() {
return new Vue({
el: mountPoint,
- render: createElement => createElement(settingsPanel, { props: { ...componentProps } }),
+ render: (createElement) => createElement(settingsPanel, { props: { ...componentProps } }),
});
}
diff --git a/app/assets/javascripts/pages/projects/tags/index/index.js b/app/assets/javascripts/pages/projects/tags/index/index.js
index ec56fa3e075..96e52850936 100644
--- a/app/assets/javascripts/pages/projects/tags/index/index.js
+++ b/app/assets/javascripts/pages/projects/tags/index/index.js
@@ -2,11 +2,8 @@ import { initRemoveTag } from '../remove_tag';
document.addEventListener('DOMContentLoaded', () => {
initRemoveTag({
- onDelete: path => {
- document
- .querySelector(`[data-path="${path}"]`)
- .closest('.js-tag-list')
- .remove();
+ onDelete: (path) => {
+ document.querySelector(`[data-path="${path}"]`).closest('.js-tag-list').remove();
},
});
});
diff --git a/app/assets/javascripts/pages/search/show/refresh_counts.js b/app/assets/javascripts/pages/search/show/refresh_counts.js
index fa75ee6075d..f3f6312cb7c 100644
--- a/app/assets/javascripts/pages/search/show/refresh_counts.js
+++ b/app/assets/javascripts/pages/search/show/refresh_counts.js
@@ -11,7 +11,7 @@ function refreshCount(el) {
return axios
.get(url)
.then(({ data }) => showCount(el, data.count))
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line no-console
console.error(`Failed to fetch search count from '${url}'.`, e);
});
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
index b411b637f36..cbef5ab1bbc 100644
--- a/app/assets/javascripts/pages/search/show/search.js
+++ b/app/assets/javascripts/pages/search/show/search.js
@@ -16,16 +16,12 @@ export default class Search {
}
eventListeners() {
- $(document)
- .off('keyup', this.searchInput)
- .on('keyup', this.searchInput, this.searchKeyUp);
+ $(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);
+ $('a.js-search-clear').off('click', this.clearSearchFilter).on('click', this.clearSearchFilter);
}
static submitSearch() {
@@ -42,10 +38,7 @@ export default class Search {
}
clearSearchField() {
- return $(this.searchInput)
- .val('')
- .trigger('keyup')
- .focus();
+ return $(this.searchInput).val('').trigger('keyup').focus();
}
// We need to manually follow the link on the anchors
diff --git a/app/assets/javascripts/pages/sessions/new/length_validator.js b/app/assets/javascripts/pages/sessions/new/length_validator.js
index 92482c81f3c..17acad10bc1 100644
--- a/app/assets/javascripts/pages/sessions/new/length_validator.js
+++ b/app/assets/javascripts/pages/sessions/new/length_validator.js
@@ -9,7 +9,7 @@ export default class LengthValidator extends InputValidator {
const container = opts.container || '';
const validateLengthElements = document.querySelectorAll(`${container} .js-validate-length`);
- validateLengthElements.forEach(element =>
+ validateLengthElements.forEach((element) =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
diff --git a/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js b/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js
index 1d47a9aed47..70e5e336e78 100644
--- a/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js
+++ b/app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js
@@ -13,7 +13,7 @@ export default function preserveUrlFragment(fragment = '') {
// Append the fragment to all sign-in/sign-up form actions so it is preserved when the user is
// eventually redirected back to the originally requested URL.
const forms = document.querySelectorAll('#signin-container .tab-content form');
- Array.prototype.forEach.call(forms, form => {
+ Array.prototype.forEach.call(forms, (form) => {
const actionWithFragment = setUrlFragment(form.getAttribute('action'), `#${normalFragment}`);
form.setAttribute('action', actionWithFragment);
});
@@ -21,7 +21,7 @@ export default function preserveUrlFragment(fragment = '') {
// Append a redirect_fragment query param to all oauth provider links. The redirect_fragment
// query param will be available in the omniauth callback upon successful authentication
const oauthForms = document.querySelectorAll('#signin-container .omniauth-container form');
- Array.prototype.forEach.call(oauthForms, oauthForm => {
+ Array.prototype.forEach.call(oauthForms, (oauthForm) => {
const newHref = mergeUrlParams(
{ redirect_fragment: normalFragment },
oauthForm.getAttribute('action'),
diff --git a/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js b/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
index 2b8f1e8b0ef..1e7c29aefaa 100644
--- a/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
+++ b/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
@@ -20,7 +20,7 @@ export default class SigninTabsMemoizer {
bootstrap() {
const tabs = document.querySelectorAll(this.tabSelector);
if (tabs.length > 0) {
- tabs[0].addEventListener('click', e => {
+ tabs[0].addEventListener('click', (e) => {
if (e.target && e.target.nodeName === 'A') {
const anchorName = e.target.getAttribute('href');
this.saveData(anchorName);
diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js
index 62f6e3fb84f..f3b0948a40d 100644
--- a/app/assets/javascripts/pages/sessions/new/username_validator.js
+++ b/app/assets/javascripts/pages/sessions/new/username_validator.js
@@ -20,11 +20,11 @@ export default class UsernameValidator extends InputValidator {
const container = opts.container || '';
const validateLengthElements = document.querySelectorAll(`${container} .js-validate-username`);
- this.debounceValidateInput = debounce(inputDomElement => {
+ this.debounceValidateInput = debounce((inputDomElement) => {
UsernameValidator.validateUsernameInput(inputDomElement);
}, debounceTimeoutDuration);
- validateLengthElements.forEach(element =>
+ validateLengthElements.forEach((element) =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
@@ -42,7 +42,7 @@ export default class UsernameValidator extends InputValidator {
if (inputDomElement.checkValidity() && username.length > 1) {
UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector);
UsernameValidator.fetchUsernameAvailability(username)
- .then(usernameTaken => {
+ .then((usernameTaken) => {
UsernameValidator.setInputState(inputDomElement, !usernameTaken);
UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector, false);
UsernameValidator.setMessageVisibility(
diff --git a/app/assets/javascripts/pages/shared/mount_badge_settings.js b/app/assets/javascripts/pages/shared/mount_badge_settings.js
index 1397c0834ff..aeb9f2fb8d3 100644
--- a/app/assets/javascripts/pages/shared/mount_badge_settings.js
+++ b/app/assets/javascripts/pages/shared/mount_badge_settings.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import BadgeSettings from '~/badges/components/badge_settings.vue';
import store from '~/badges/store';
-export default kind => {
+export default (kind) => {
const badgeSettingsElement = document.getElementById('badge-settings');
store.dispatch('loadBadges', {
diff --git a/app/assets/javascripts/pages/shared/wikis/wikis.js b/app/assets/javascripts/pages/shared/wikis/wikis.js
index fe9caba351e..4b4d2f7d238 100644
--- a/app/assets/javascripts/pages/shared/wikis/wikis.js
+++ b/app/assets/javascripts/pages/shared/wikis/wikis.js
@@ -20,12 +20,13 @@ export default class Wikis {
const sidebarToggles = document.querySelectorAll('.js-sidebar-wiki-toggle');
for (let i = 0; i < sidebarToggles.length; i += 1) {
- sidebarToggles[i].addEventListener('click', e => this.handleToggleSidebar(e));
+ sidebarToggles[i].addEventListener('click', (e) => this.handleToggleSidebar(e));
}
this.isNewWikiPage = Boolean(document.querySelector('.js-new-wiki-page'));
this.editTitleInput = document.querySelector('form.wiki-form #wiki_title');
this.commitMessageInput = document.querySelector('form.wiki-form #wiki_message');
+ this.submitButton = document.querySelector('.js-wiki-btn-submit');
this.commitMessageI18n = this.isNewWikiPage
? s__('WikiPageCreate|Create %{pageTitle}')
: s__('WikiPageEdit|Update %{pageTitle}');
@@ -35,7 +36,7 @@ export default class Wikis {
if (this.editTitleInput.value) this.setWikiCommitMessage(this.editTitleInput.value);
// Set the commit message as the page title is changed
- this.editTitleInput.addEventListener('keyup', e => this.handleWikiTitleChange(e));
+ this.editTitleInput.addEventListener('keyup', (e) => this.handleWikiTitleChange(e));
}
window.addEventListener('resize', () => this.renderSidebar());
@@ -45,18 +46,16 @@ export default class Wikis {
const linkExample = document.querySelector('.js-markup-link-example');
if (changeFormatSelect) {
- changeFormatSelect.addEventListener('change', e => {
+ changeFormatSelect.addEventListener('change', (e) => {
linkExample.innerHTML = MARKDOWN_LINK_TEXT[e.target.value];
});
}
- const wikiTextarea = document.querySelector('form.wiki-form #wiki_content');
+ this.wikiTextarea = document.querySelector('form.wiki-form #wiki_content');
const wikiForm = document.querySelector('form.wiki-form');
- if (wikiTextarea) {
- wikiTextarea.addEventListener('input', () => {
- window.onbeforeunload = () => '';
- });
+ if (this.wikiTextarea) {
+ this.wikiTextarea.addEventListener('input', () => this.handleWikiContentChange());
wikiForm.addEventListener('submit', () => {
window.onbeforeunload = null;
@@ -65,12 +64,29 @@ export default class Wikis {
Wikis.trackPageView();
Wikis.showToasts();
+
+ this.updateSubmitButton();
+ }
+
+ handleWikiContentChange() {
+ this.updateSubmitButton();
+
+ window.onbeforeunload = () => '';
}
handleWikiTitleChange(e) {
+ this.updateSubmitButton();
this.setWikiCommitMessage(e.target.value);
}
+ updateSubmitButton() {
+ if (!this.wikiTextarea) return;
+
+ const isEnabled = Boolean(this.wikiTextarea.value.trim() && this.editTitleInput.value.trim());
+ if (isEnabled) this.submitButton.removeAttribute('disabled');
+ else this.submitButton.setAttribute('disabled', 'true');
+ }
+
setWikiCommitMessage(rawTitle) {
let title = rawTitle;
@@ -121,6 +137,6 @@ export default class Wikis {
static showToasts() {
const toasts = document.querySelectorAll('.js-toast-message');
- toasts.forEach(toast => showToast(toast.dataset.message));
+ toasts.forEach((toast) => showToast(toast.dataset.message));
}
}
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 54666af540e..149e666256b 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -42,11 +42,7 @@ function formatTooltipText({ date, count }) {
return `${contribText}<br />${dateDayName} ${dateText}`;
}
-const initColorKey = () =>
- d3
- .scaleLinear()
- .range(['#acd5f2', '#254e77'])
- .domain([0, 3]);
+const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]);
export default class ActivityCalendar {
constructor(
@@ -177,17 +173,17 @@ export default class ActivityCalendar {
return `translate(${this.daySizeWithSpace * i + 1 + this.daySizeWithSpace}, 18)`;
})
.selectAll('rect')
- .data(stamp => stamp)
+ .data((stamp) => stamp)
.enter()
.append('rect')
.attr('x', '0')
- .attr('y', stamp => this.dayYPos(stamp.day))
+ .attr('y', (stamp) => this.dayYPos(stamp.day))
.attr('width', this.daySize)
.attr('height', this.daySize)
- .attr('fill', stamp =>
+ .attr('fill', (stamp) =>
stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed',
)
- .attr('title', stamp => formatTooltipText(stamp))
+ .attr('title', (stamp) => formatTooltipText(stamp))
.attr('class', 'user-contrib-cell has-tooltip')
.attr('data-html', true)
.attr('data-container', 'body')
@@ -230,8 +226,8 @@ export default class ActivityCalendar {
.append('text')
.attr('text-anchor', 'middle')
.attr('x', 8)
- .attr('y', day => day.y)
- .text(day => day.text)
+ .attr('y', (day) => day.y)
+ .text((day) => day.text)
.attr('class', 'user-contrib-text');
}
@@ -243,10 +239,10 @@ export default class ActivityCalendar {
.data(this.months)
.enter()
.append('text')
- .attr('x', date => date.x)
+ .attr('x', (date) => date.x)
.attr('y', 10)
.attr('class', 'user-contrib-text')
- .text(date => this.monthNames[date.month]);
+ .text((date) => this.monthNames[date.month]);
}
renderKey() {
@@ -276,7 +272,7 @@ export default class ActivityCalendar {
.attr('height', this.daySize)
.attr('x', (color, i) => this.daySizeWithSpace * i)
.attr('y', 0)
- .attr('fill', color => color)
+ .attr('fill', (color) => color)
.attr('class', 'has-tooltip')
.attr('title', (color, i) => keyValues[i])
.attr('data-container', 'body')
@@ -291,10 +287,7 @@ export default class ActivityCalendar {
this.colorKey(2),
this.colorKey(3),
];
- return d3
- .scaleThreshold()
- .domain([0, 10, 20, 30])
- .range(colorRange);
+ return d3.scaleThreshold().domain([0, 10, 20, 30]).range(colorRange);
}
clickDay(stamp) {
diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js
index 8adbc2a8168..b22287a0093 100644
--- a/app/assets/javascripts/pages/users/index.js
+++ b/app/assets/javascripts/pages/users/index.js
@@ -8,12 +8,10 @@ function initUserProfile(action) {
new UserTabs({ parentEl: '.user-profile', action });
// hide project limit message
- $('.hide-project-limit-message').on('click', e => {
+ $('.hide-project-limit-message').on('click', (e) => {
e.preventDefault();
Cookies.set('hide_project_limit_message', 'false');
- $(this)
- .parents('.project-limit-message')
- .remove();
+ $(this).parents('.project-limit-message').remove();
});
}
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index 2485853afc7..7c88aa53e4b 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -100,8 +100,8 @@ export default class UserTabs {
bindEvents() {
this.$parentEl
.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
- .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event))
- .on('click', '.gl-pagination a', event => this.changeProjectsPage(event));
+ .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', (event) => this.tabShown(event))
+ .on('click', '.gl-pagination a', (event) => this.changeProjectsPage(event));
window.addEventListener('resize', () => this.onResize());
}
@@ -212,17 +212,19 @@ export default class UserTabs {
const calendarPath = $calendarWrap.data('calendarPath');
AjaxCache.retrieve(calendarPath)
- .then(data => UserTabs.renderActivityCalendar(data, $calendarWrap))
+ .then((data) => UserTabs.renderActivityCalendar(data, $calendarWrap))
.catch(() => {
const cWrap = $calendarWrap[0];
cWrap.querySelector('.spinner').classList.add('invisible');
cWrap.querySelector('.user-calendar-error').classList.remove('invisible');
- cWrap.querySelector('.user-calendar-error .js-retry-load').addEventListener('click', e => {
- e.preventDefault();
- cWrap.querySelector('.user-calendar-error').classList.add('invisible');
- cWrap.querySelector('.spinner').classList.remove('invisible');
- this.loadActivityCalendar();
- });
+ cWrap
+ .querySelector('.user-calendar-error .js-retry-load')
+ .addEventListener('click', (e) => {
+ e.preventDefault();
+ cWrap.querySelector('.user-calendar-error').classList.add('invisible');
+ cWrap.querySelector('.spinner').classList.remove('invisible');
+ this.loadActivityCalendar();
+ });
});
}
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index bbbd9789dc9..c8a04eb72c4 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -40,11 +40,11 @@ export default {
cMapPacked: true,
})
.promise.then(this.renderPages)
- .then(pages => {
+ .then((pages) => {
this.pages = pages;
this.$emit('pdflabload');
})
- .catch(error => {
+ .catch((error) => {
this.$emit('pdflaberror', error);
});
},
diff --git a/app/assets/javascripts/pdf/page/index.vue b/app/assets/javascripts/pdf/page/index.vue
index 843c50cf9bc..ae0a7f0298b 100644
--- a/app/assets/javascripts/pdf/page/index.vue
+++ b/app/assets/javascripts/pdf/page/index.vue
@@ -39,7 +39,7 @@ export default {
.promise.then(() => {
this.rendering = false;
})
- .catch(error => {
+ .catch((error) => {
this.$emit('pdflaberror', error);
});
},
diff --git a/app/assets/javascripts/performance/utils.js b/app/assets/javascripts/performance/utils.js
index 1c87ee2086e..0001ef54244 100644
--- a/app/assets/javascripts/performance/utils.js
+++ b/app/assets/javascripts/performance/utils.js
@@ -3,7 +3,7 @@ export const performanceMarkAndMeasure = ({ mark, measures = [] } = {}) => {
if (mark && !performance.getEntriesByName(mark).length) {
performance.mark(mark);
}
- measures.forEach(measure => {
+ measures.forEach((measure) => {
performance.measure(measure.name, measure.start, measure.end);
});
});
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index 90e14d8325f..930c5e50511 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -76,12 +76,12 @@ export default {
this.openedBacktraces = [...this.openedBacktraces, toggledIndex];
} else {
this.openedBacktraces = this.openedBacktraces.filter(
- openedIndex => openedIndex !== toggledIndex,
+ (openedIndex) => openedIndex !== toggledIndex,
);
}
},
itemHasOpenedBacktrace(toggledIndex) {
- return this.openedBacktraces.find(openedIndex => openedIndex === toggledIndex) >= 0;
+ return this.openedBacktraces.find((openedIndex) => openedIndex === toggledIndex) >= 0;
},
},
};
@@ -141,7 +141,7 @@ export default {
</template>
</table>
- <template #footer>
+ <template #modal-footer>
<div></div>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index 5a9d3a6d313..5666e038f02 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -25,7 +25,7 @@ export default {
},
computed: {
requestsWithWarnings() {
- return this.requests.filter(request => request.hasWarnings);
+ return this.requests.filter((request) => request.hasWarnings);
},
warningMessage() {
return n__(
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index e0b7f2190ca..0d5c294ea56 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -10,7 +10,10 @@ import initPerformanceBarLog from './performance_bar_log';
Vue.use(Translate);
-const initPerformanceBar = el => {
+const initPerformanceBar = (el) => {
+ if (!el) {
+ return undefined;
+ }
const performanceBarData = el.dataset;
return new Vue({
@@ -55,7 +58,7 @@ const initPerformanceBar = el => {
this.store.addRequest(requestId, requestUrl);
PerformanceBarService.fetchRequestDetails(this.peekUrl, requestId)
- .then(res => {
+ .then((res) => {
this.store.addRequestDetails(requestId, res.data);
if (this.requestId === requestId) this.collectFrontendPerformanceMetrics();
@@ -84,7 +87,7 @@ const initPerformanceBar = el => {
if ('PerformanceObserver' in window) {
// We start observing for more incoming timings
- const observer = new PerformanceObserver(list => {
+ const observer = new PerformanceObserver((list) => {
newEntries = newEntries.concat(list.getEntries().map(this.transformResourceEntry));
this.updateFrontendPerformanceMetrics(durationString, newEntries);
});
@@ -126,25 +129,7 @@ const initPerformanceBar = el => {
});
};
-let loadedPeekBar = false;
-function loadBar() {
- const jsPeek = document.querySelector('#js-peek');
- if (!loadedPeekBar && jsPeek) {
- loadedPeekBar = true;
- initPerformanceBar(jsPeek);
- }
-}
-
-// If js-peek is not loaded when this script is executed, this call will do nothing
-// If this is the case, then it will loadBar on DOMContentLoaded. We would prefer it
-// to be initialized before the DOMContetLoaded event in order to pick up all the
-// requests sent from the page.
-loadBar();
-
-document.addEventListener('DOMContentLoaded', () => {
- loadBar();
-});
-
+initPerformanceBar(document.querySelector('#js-peek'));
initPerformanceBarLog();
export default initPerformanceBar;
diff --git a/app/assets/javascripts/performance_bar/performance_bar_log.js b/app/assets/javascripts/performance_bar/performance_bar_log.js
index 3ba7ff1c221..c61b0cb32e8 100644
--- a/app/assets/javascripts/performance_bar/performance_bar_log.js
+++ b/app/assets/javascripts/performance_bar/performance_bar_log.js
@@ -3,7 +3,7 @@ import { getCLS, getFID, getLCP } from 'web-vitals';
import { PERFORMANCE_TYPE_MARK, PERFORMANCE_TYPE_MEASURE } from '~/performance/constants';
const initVitalsLog = () => {
- const reportVital = data => {
+ const reportVital = (data) => {
console.log(`${String.fromCodePoint(0x1f4c8)} ${data.name} : `, data);
};
@@ -18,9 +18,9 @@ const initVitalsLog = () => {
};
const logUserTimingMetrics = () => {
- const metricsProcessor = list => {
+ const metricsProcessor = (list) => {
const entries = list.getEntries();
- entries.forEach(entry => {
+ entries.forEach((entry) => {
const { name, entryType, startTime, duration } = entry;
const typeMapper = {
[PERFORMANCE_TYPE_MARK]: String.fromCodePoint(0x1f3af),
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 3c8303d102e..38255b3a37d 100644
--- a/app/assets/javascripts/performance_bar/services/performance_bar_service.js
+++ b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
@@ -9,7 +9,7 @@ export default class PerformanceBarService {
}
static registerInterceptor(peekUrl, callback) {
- PerformanceBarService.interceptor = response => {
+ PerformanceBarService.interceptor = (response) => {
const [fireCallback, requestId, requestUrl] = PerformanceBarService.callbackParams(
response,
peekUrl,
diff --git a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
index 8c88851f039..9d12d228d35 100644
--- a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
+++ b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
@@ -20,7 +20,7 @@ export default class PerformanceBarStore {
}
findRequest(requestId) {
- return this.requests.find(request => request.id === requestId);
+ return this.requests.find((request) => request.id === requestId);
}
addRequestDetails(requestId, requestDetails) {
@@ -43,13 +43,13 @@ export default class PerformanceBarStore {
}
requestsWithDetails() {
- return this.requests.filter(request => request.details);
+ return this.requests.filter((request) => request.details);
}
canTrackRequest(requestUrl) {
return (
requestUrl.endsWith('/api/graphql') ||
- this.requests.filter(request => request.url === requestUrl).length < 2
+ this.requests.filter((request) => request.url === requestUrl).length < 2
);
}
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
index eded64127b6..db42966d159 100644
--- a/app/assets/javascripts/persistent_user_callout.js
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -28,10 +28,10 @@ export default class PersistentUserCallout {
}
handleCloseButtonCallout(closeButton) {
- closeButton.addEventListener('click', event => this.dismiss(event));
+ closeButton.addEventListener('click', (event) => this.dismiss(event));
if (this.deferLinks) {
- this.container.addEventListener('click', event => {
+ this.container.addEventListener('click', (event) => {
const isDeferredLink = event.target.classList.contains(DEFERRED_LINK_CLASS);
if (isDeferredLink) {
const { href, target } = event.target;
@@ -43,7 +43,7 @@ export default class PersistentUserCallout {
}
handleFollowLinkCallout(followLink) {
- followLink.addEventListener('click', event => this.registerCalloutWithLink(event));
+ followLink.addEventListener('click', (event) => this.registerCalloutWithLink(event));
}
dismiss(event, deferredLinkOptions = null) {
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index d4857a19ff7..c177fe25985 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -11,7 +11,7 @@ const PERSISTENT_USER_CALLOUTS = [
];
const initCallouts = () => {
- PERSISTENT_USER_CALLOUTS.forEach(calloutContainer =>
+ PERSISTENT_USER_CALLOUTS.forEach((calloutContainer) =>
PersistentUserCallout.factory(document.querySelector(calloutContainer)),
);
};
diff --git a/app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue
new file mode 100644
index 00000000000..22f378c571a
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue
@@ -0,0 +1,84 @@
+<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.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
new file mode 100644
index 00000000000..b27ab9a39d3
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
@@ -0,0 +1,53 @@
+<script>
+import { flatten } from 'lodash';
+import { CI_CONFIG_STATUS_VALID } from '../../constants';
+import CiLintResults from './ci_lint_results.vue';
+
+export default {
+ components: {
+ CiLintResults,
+ },
+ inject: {
+ lintHelpPagePath: {
+ default: '',
+ },
+ },
+ props: {
+ ciConfig: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ isValid() {
+ return this.ciConfig?.status === CI_CONFIG_STATUS_VALID;
+ },
+ stages() {
+ return this.ciConfig?.stages || [];
+ },
+ jobs() {
+ const groupedJobs = this.stages.reduce((acc, { groups, name: stageName }) => {
+ return acc.concat(
+ groups.map(({ jobs }) => {
+ return jobs.map((job) => ({
+ stage: stageName,
+ ...job,
+ }));
+ }),
+ );
+ }, []);
+
+ return flatten(groupedJobs);
+ },
+ },
+};
+</script>
+
+<template>
+ <ci-lint-results
+ :valid="isValid"
+ :jobs="jobs"
+ :errors="ciConfig.errors"
+ :lint-help-page-path="lintHelpPagePath"
+ />
+</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 0d1c214c5b1..58a96c3f725 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
@@ -10,11 +10,11 @@ const thBorderColor = 'gl-border-gray-100!';
export default {
correct: {
variant: 'success',
- text: __('syntax is correct.'),
+ text: __('Syntax is correct.'),
},
incorrect: {
variant: 'danger',
- text: __('syntax is incorrect.'),
+ text: __('Syntax is incorrect.'),
},
includesText: __(
'CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}',
@@ -48,19 +48,23 @@ export default {
},
jobs: {
type: Array,
- required: true,
+ required: false,
+ default: () => [],
},
errors: {
type: Array,
- required: true,
+ required: false,
+ default: () => [],
},
warnings: {
type: Array,
- required: true,
+ required: false,
+ default: () => [],
},
dryRun: {
type: Boolean,
- required: true,
+ required: false,
+ default: false,
},
lintHelpPagePath: {
type: String,
@@ -99,7 +103,7 @@ export default {
data-testid="ci-lint-status"
>{{ status.text }}
<gl-sprintf :message="$options.includesText">
- <template #code="{content}">
+ <template #code="{ content }">
<code>
{{ content }}
</code>
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue
index 4929c3206df..ef2be2a5fba 100644
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue
@@ -14,7 +14,7 @@ export default {
},
computed: {
tagList() {
- return this.item.tagList.join(', ');
+ return this.item.tags?.join(', ');
},
onlyPolicy() {
return this.item.only ? this.item.only.refs.join(', ') : this.item.only;
@@ -26,15 +26,15 @@ export default {
return {
beforeScript: {
show: !isEmpty(this.item.beforeScript),
- content: this.item.beforeScript.join('\n'),
+ content: this.item.beforeScript?.join('\n'),
},
script: {
show: !isEmpty(this.item.script),
- content: this.item.script.join('\n'),
+ content: this.item.script?.join('\n'),
},
afterScript: {
show: !isEmpty(this.item.afterScript),
- content: this.item.afterScript.join('\n'),
+ content: this.item.afterScript?.join('\n'),
},
};
},
@@ -43,35 +43,43 @@ export default {
</script>
<template>
- <div>
- <pre v-if="scripts.beforeScript.show" data-testid="ci-lint-before-script">{{
- scripts.beforeScript.content
- }}</pre>
- <pre v-if="scripts.script.show" data-testid="ci-lint-script">{{ scripts.script.content }}</pre>
- <pre v-if="scripts.afterScript.show" data-testid="ci-lint-after-script">{{
- scripts.afterScript.content
+ <div data-testid="ci-lint-value">
+ <pre
+ v-if="scripts.beforeScript.show"
+ class="gl-white-space-pre-wrap"
+ data-testid="ci-lint-before-script"
+ >{{ scripts.beforeScript.content }}</pre
+ >
+ <pre v-if="scripts.script.show" class="gl-white-space-pre-wrap" data-testid="ci-lint-script">{{
+ scripts.script.content
}}</pre>
+ <pre
+ v-if="scripts.afterScript.show"
+ class="gl-white-space-pre-wrap"
+ data-testid="ci-lint-after-script"
+ >{{ scripts.afterScript.content }}</pre
+ >
<ul class="gl-list-style-none gl-pl-0 gl-mb-0">
- <li>
+ <li v-if="tagList">
<b>{{ __('Tag list:') }}</b>
{{ tagList }}
</li>
<div v-if="!dryRun" data-testid="ci-lint-only-except">
- <li>
+ <li v-if="onlyPolicy">
<b>{{ __('Only policy:') }}</b>
{{ onlyPolicy }}
</li>
- <li>
+ <li v-if="exceptPolicy">
<b>{{ __('Except policy:') }}</b>
{{ exceptPolicy }}
</li>
</div>
- <li>
+ <li v-if="item.environment">
<b>{{ __('Environment:') }}</b>
{{ item.environment }}
</li>
- <li>
+ <li v-if="item.when">
<b>{{ __('When:') }}</b>
{{ item.when }}
<b v-if="item.allowFailure">{{ __('Allowed to fail') }}</b>
diff --git a/app/assets/javascripts/pipeline_editor/components/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
index 22f2a32c9ac..b8d49d77ea9 100644
--- a/app/assets/javascripts/pipeline_editor/components/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
@@ -1,14 +1,46 @@
<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 file-name="*.yml" v-bind="$attrs" v-on="$listeners" />
+ <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/editor_tab.vue b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue
new file mode 100644
index 00000000000..b0acd3ca2ee
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue
@@ -0,0 +1,68 @@
+<script>
+import { GlTab } from '@gitlab/ui';
+
+/**
+ * Wrapper of <gl-tab> to optionally lazily render this tab's content
+ * when its shown **without dismounting after its hidden**.
+ *
+ * Usage:
+ *
+ * API is the same as <gl-tab>, for example:
+ *
+ * <gl-tabs>
+ * <editor-tab title="Tab 1" :lazy="true">
+ * lazily mounted content (gets mounted if this is first tab)
+ * </editor-tab>
+ * <editor-tab title="Tab 2" :lazy="true">
+ * lazily mounted content
+ * </editor-tab>
+ * <editor-tab title="Tab 3">
+ * eagerly mounted content
+ * </editor-tab>
+ * </gl-tabs>
+ *
+ * Once the tab is selected it is permanently set as "not-lazy"
+ * so it's contents are not dismounted.
+ *
+ * lazy is "false" by default, as in <gl-tab>.
+ */
+
+export default {
+ components: {
+ GlTab,
+ // Use a small renderless component to know when the tab content mounts because:
+ // - gl-tab always gets mounted, even if lazy is `true`. See:
+ // https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/tabs/tab.js#L180
+ // - we cannot listen to events on <slot />
+ MountSpy: {
+ render: () => null,
+ },
+ },
+ inheritAttrs: false,
+ props: {
+ lazy: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ isLazy: this.lazy,
+ };
+ },
+ methods: {
+ onContentMounted() {
+ // When a child is first mounted make the entire tab
+ // permanently mounted by setting 'lazy' to false.
+ this.isLazy = false;
+ },
+ },
+};
+</script>
+<template>
+ <gl-tab :lazy="isLazy" v-bind="$attrs" v-on="$listeners">
+ <slot v-for="slot in Object.keys($slots)" :slot="slot" :name="slot"></slot>
+ <mount-spy @hook:mounted="onContentMounted" />
+ </gl-tab>
+</template>
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 11bca42fd69..0c58749a8b2 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
@@ -19,7 +19,7 @@ mutation commitCIFileMutation(
}
) {
commit {
- id
+ sha
}
errors
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql
index 496036f690f..5091d63111f 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql
@@ -15,7 +15,7 @@ mutation lintCI($endpoint: String, $content: String, $dry: Boolean) {
}
afterScript
stage
- tagList
+ tags
when
}
}
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 d65d9892260..dfddb29701d 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
@@ -1,7 +1,7 @@
-#import "~/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql"
+#import "~/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql"
-query getCiConfigData($content: String!) {
- ciConfig(content: $content) {
+query getCiConfigData($projectPath: ID!, $content: String!) {
+ ciConfig(projectPath: $projectPath, content: $content) {
errors
status
stages {
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index c1cdb5eb2ee..81e75c32846 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -18,7 +18,7 @@ export const resolvers = {
valid: data.valid,
errors: data.errors,
warnings: data.warnings,
- jobs: data.jobs.map(job => {
+ jobs: data.jobs.map((job) => {
const only = job.only ? { refs: job.only.refs, __typename: 'CiLintJobOnlyPolicy' } : null;
return {
@@ -27,7 +27,7 @@ export const resolvers = {
beforeScript: job.before_script,
script: job.script,
afterScript: job.after_script,
- tagList: job.tag_list,
+ tags: job.tag_list,
environment: job.environment,
when: job.when,
allowFailure: job.allow_failure,
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 8268a907a29..583ba555080 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -14,7 +14,20 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
return null;
}
- const { ciConfigPath, commitId, defaultBranch, newMergeRequestPath, projectPath } = el?.dataset;
+ const {
+ // props
+ ciConfigPath,
+ commitSha,
+ defaultBranch,
+ newMergeRequestPath,
+
+ // `provide/inject` data
+ lintHelpPagePath,
+ projectFullPath,
+ projectPath,
+ projectNamespace,
+ ymlHelpPagePath,
+ } = el?.dataset;
Vue.use(VueApollo);
@@ -25,14 +38,20 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
return new Vue({
el,
apolloProvider,
+ provide: {
+ lintHelpPagePath,
+ projectFullPath,
+ projectPath,
+ projectNamespace,
+ ymlHelpPagePath,
+ },
render(h) {
return h(PipelineEditorApp, {
props: {
ciConfigPath,
- commitId,
+ commitSha,
defaultBranch,
newMergeRequestPath,
- projectPath,
},
});
},
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 96dc782964b..21993e2120a 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,12 +1,16 @@
<script>
-import { GlAlert, GlLoadingIcon, GlTab, GlTabs } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
-import { mergeUrlParams, redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility';
+import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import httpStatusCodes from '~/lib/utils/http_status';
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 getBlobContent from './graphql/queries/blob_content.graphql';
@@ -17,33 +21,33 @@ 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_NO_REF = 'LOAD_FAILURE_NO_REF';
const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
export default {
components: {
+ CiLint,
CommitForm,
+ EditorTab,
GlAlert,
GlLoadingIcon,
- GlTab,
GlTabs,
+ GlTab,
PipelineGraph,
TextEditor,
+ ValidationSegment,
},
mixins: [glFeatureFlagsMixin()],
+ inject: ['projectFullPath'],
props: {
- projectPath: {
- type: String,
- required: true,
- },
defaultBranch: {
type: String,
required: false,
default: null,
},
- commitId: {
+ commitSha: {
type: String,
required: false,
default: null,
@@ -62,12 +66,15 @@ export default {
ciConfigData: {},
content: '',
contentModel: '',
- currentTabIndex: 0,
- editorIsReady: false,
- failureType: null,
- failureReasons: [],
+ lastCommitSha: this.commitSha,
isSaving: false,
+
+ // Success and failure state
+ failureType: null,
showFailureAlert: false,
+ failureReasons: [],
+ successType: null,
+ showSuccessAlert: false,
};
},
apollo: {
@@ -75,7 +82,7 @@ export default {
query: getBlobContent,
variables() {
return {
- projectPath: this.projectPath,
+ projectPath: this.projectFullPath,
path: this.ciConfigPath,
ref: this.defaultBranch,
};
@@ -98,15 +105,16 @@ export default {
},
variables() {
return {
+ projectPath: this.projectFullPath,
content: this.contentModel,
};
},
update(data) {
- const { ciConfigData } = data || {};
- const stageNodes = ciConfigData?.stages?.nodes || [];
+ const { ciConfig } = data || {};
+ const stageNodes = ciConfig?.stages?.nodes || [];
const stages = unwrapStagesWithNeeds(stageNodes);
- return { ...ciConfigData, stages };
+ return { ...ciConfig, stages };
},
error() {
this.reportFailure(LOAD_FAILURE_UNKNOWN);
@@ -117,40 +125,48 @@ export default {
isBlobContentLoading() {
return this.$apollo.queries.content.loading;
},
- isVisualizationTabLoading() {
- return this.$apollo.queries.ciConfigData.loading;
+ isBlobContentError() {
+ return this.failureType === LOAD_FAILURE_NO_FILE;
},
- isVisualizeTabActive() {
- return this.currentTabIndex === 1;
+ isCiConfigDataLoading() {
+ return this.$apollo.queries.ciConfigData.loading;
},
defaultCommitMessage() {
return sprintf(this.$options.i18n.defaultCommitMessage, { sourcePath: this.ciConfigPath });
},
- failure() {
- switch (this.failureType) {
- case LOAD_FAILURE_NO_REF:
+ success() {
+ switch (this.successType) {
+ case COMMIT_SUCCESS:
return {
- text: this.$options.errorTexts[LOAD_FAILURE_NO_REF],
- variant: 'danger',
+ text: this.$options.alertTexts[COMMIT_SUCCESS],
+ variant: 'info',
};
+ default:
+ return null;
+ }
+ },
+ failure() {
+ switch (this.failureType) {
case LOAD_FAILURE_NO_FILE:
return {
- text: this.$options.errorTexts[LOAD_FAILURE_NO_FILE],
+ text: sprintf(this.$options.alertTexts[LOAD_FAILURE_NO_FILE], {
+ filePath: this.ciConfigPath,
+ }),
variant: 'danger',
};
case LOAD_FAILURE_UNKNOWN:
return {
- text: this.$options.errorTexts[LOAD_FAILURE_UNKNOWN],
+ text: this.$options.alertTexts[LOAD_FAILURE_UNKNOWN],
variant: 'danger',
};
case COMMIT_FAILURE:
return {
- text: this.$options.errorTexts[COMMIT_FAILURE],
+ text: this.$options.alertTexts[COMMIT_FAILURE],
variant: 'danger',
};
default:
return {
- text: this.$options.errorTexts[DEFAULT_FAILURE],
+ text: this.$options.alertTexts[DEFAULT_FAILURE],
variant: 'danger',
};
}
@@ -160,30 +176,34 @@ export default {
defaultCommitMessage: __('Update %{sourcePath} file'),
tabEdit: s__('Pipelines|Write pipeline configuration'),
tabGraph: s__('Pipelines|Visualize'),
+ tabLint: s__('Pipelines|Lint'),
},
- errorTexts: {
- [LOAD_FAILURE_NO_REF]: s__(
- 'Pipelines|Repository does not have a default branch, please set one.',
+ alertTexts: {
+ [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_NO_FILE]: s__('Pipelines|No CI file found in this repository, please add one.'),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
- [COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
},
methods: {
handleBlobContentError(error = {}) {
const { networkError } = error;
const { response } = networkError;
- if (response?.status === 404) {
- // 404 for missing CI file
+ // 404 for missing CI file
+ // 400 for blank projects with no repository
+ if (
+ response?.status === httpStatusCodes.NOT_FOUND ||
+ response?.status === httpStatusCodes.BAD_REQUEST
+ ) {
this.reportFailure(LOAD_FAILURE_NO_FILE);
- } else if (response?.status === 400) {
- // 400 for a missing ref when no default branch is set
- this.reportFailure(LOAD_FAILURE_NO_REF);
} else {
this.reportFailure(LOAD_FAILURE_UNKNOWN);
}
},
+
dismissFailure() {
this.showFailureAlert = false;
},
@@ -192,6 +212,14 @@ export default {
this.failureType = type;
this.failureReasons = reasons;
},
+ dismissSuccess() {
+ this.showSuccessAlert = false;
+ },
+ reportSuccess(type) {
+ this.showSuccessAlert = true;
+ this.successType = type;
+ },
+
redirectToNewMergeRequest(sourceBranch) {
const url = mergeUrlParams(
{
@@ -209,18 +237,18 @@ export default {
try {
const {
data: {
- commitCreate: { errors },
+ commitCreate: { errors, commit },
},
} = await this.$apollo.mutate({
mutation: commitCiFileMutation,
variables: {
- projectPath: this.projectPath,
+ projectPath: this.projectFullPath,
branch,
startBranch: this.defaultBranch,
message,
filePath: this.ciConfigPath,
content: this.contentModel,
- lastCommitId: this.commitId,
+ lastCommitId: this.lastCommitSha,
},
});
@@ -232,8 +260,10 @@ export default {
if (openMergeRequest) {
this.redirectToNewMergeRequest(branch);
} else {
- // Refresh the page to ensure commit is updated
- refreshCurrentPage();
+ this.reportSuccess(COMMIT_SUCCESS);
+
+ // Update latest commit
+ this.lastCommitSha = commit.sha;
}
} catch (error) {
this.reportFailure(COMMIT_FAILURE, [error?.message]);
@@ -251,6 +281,14 @@ export default {
<template>
<div class="gl-mt-4">
<gl-alert
+ v-if="showSuccessAlert"
+ :variant="success.variant"
+ :dismissible="true"
+ @dismiss="dismissSuccess"
+ >
+ {{ success.text }}
+ </gl-alert>
+ <gl-alert
v-if="showFailureAlert"
:variant="failure.variant"
:dismissible="true"
@@ -261,25 +299,39 @@ export default {
<li v-for="reason in failureReasons" :key="reason">{{ reason }}</li>
</ul>
</gl-alert>
- <div class="gl-mt-4">
- <gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" />
- <div v-else class="file-editor gl-mb-3">
- <gl-tabs v-model="currentTabIndex">
- <!-- editor should be mounted when its tab is visible, so the container has a size -->
- <gl-tab :title="$options.i18n.tabEdit" :lazy="!editorIsReady">
- <!-- editor should be mounted only once, when the tab is displayed -->
- <text-editor v-model="contentModel" @editor-ready="editorIsReady = true" />
- </gl-tab>
+ <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"
- :lazy="!isVisualizeTabActive"
data-testid="visualization-tab"
>
- <gl-loading-icon v-if="isVisualizationTabLoading" size="lg" class="gl-m-3" />
+ <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
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 f2d68054e80..70c5713b216 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -16,6 +16,7 @@ import {
GlSearchBoxByType,
GlSprintf,
GlLoadingIcon,
+ GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import * as Sentry from '~/sentry/wrapper';
import { s__, __, n__ } from '~/locale';
@@ -34,7 +35,7 @@ export default {
'Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default.',
),
formElementClasses: 'gl-mr-3 gl-mb-3 gl-flex-basis-quarter gl-flex-shrink-0 gl-flex-grow-0',
- errorTitle: __('The form contains the following error:'),
+ errorTitle: __('Pipeline cannot be run.'),
warningTitle: __('The form contains the following warning:'),
maxWarningsSummary: __('%{total} warnings found: showing first %{warningsDisplayed}'),
components: {
@@ -53,6 +54,7 @@ export default {
GlSprintf,
GlLoadingIcon,
},
+ directives: { SafeHtml },
props: {
pipelinesPath: {
type: String,
@@ -121,12 +123,12 @@ export default {
return this.searchTerm.toLowerCase();
},
filteredBranches() {
- return this.branches.filter(branch =>
+ return this.branches.filter((branch) =>
branch.shortName.toLowerCase().includes(this.lowerCasedSearchTerm),
);
},
filteredTags() {
- return this.tags.filter(tag =>
+ return this.tags.filter((tag) =>
tag.shortName.toLowerCase().includes(this.lowerCasedSearchTerm),
);
},
@@ -187,7 +189,7 @@ export default {
setVariable(refValue, type, key, value) {
const { variables } = this.form[refValue];
- const variable = variables.find(v => v.key === key);
+ const variable = variables.find((v) => v.key === key);
if (variable) {
variable.type = type;
variable.value = value;
@@ -270,11 +272,11 @@ export default {
stop(data);
}
})
- .catch(error => {
+ .catch((error) => {
stop(error);
});
}, CONFIG_VARIABLES_TIMEOUT)
- .then(data => {
+ .then((data) => {
const params = {};
const descriptions = {};
@@ -287,7 +289,7 @@ export default {
return { params, descriptions };
})
- .catch(error => {
+ .catch((error) => {
this.isLoading = false;
Sentry.captureException(error);
@@ -314,7 +316,7 @@ export default {
.then(({ data }) => {
redirectTo(`${this.pipelinesPath}/${data.id}`);
})
- .catch(err => {
+ .catch((err) => {
const { errors, warnings, total_warnings: totalWarnings } = err.response.data;
const [error] = errors;
this.error = error;
@@ -335,8 +337,9 @@ export default {
variant="danger"
class="gl-mb-4"
data-testid="run-pipeline-error-alert"
- >{{ error }}</gl-alert
>
+ <span v-safe-html="error"></span>
+ </gl-alert>
<gl-alert
v-if="shouldShowWarning"
:title="$options.warningTitle"
@@ -365,7 +368,7 @@ export default {
</p>
</details>
</gl-alert>
- <gl-form-group :label="s__('Pipeline|Run for')">
+ <gl-form-group :label="s__('Pipeline|Run for branch name or tag')">
<gl-dropdown :text="refShortName" block>
<gl-search-box-by-type v-model.trim="searchTerm" :placeholder="__('Search refs')" />
<gl-dropdown-section-header>{{ __('Branches') }}</gl-dropdown-section-header>
@@ -391,12 +394,6 @@ export default {
{{ tag.shortName }}
</gl-dropdown-item>
</gl-dropdown>
-
- <template #description>
- <div>
- {{ s__('Pipeline|Existing branch name or tag') }}
- </div></template
- >
</gl-form-group>
<gl-loading-icon v-if="isLoading" class="gl-mb-5" size="lg" />
diff --git a/app/assets/javascripts/pipeline_new/utils/format_refs.js b/app/assets/javascripts/pipeline_new/utils/format_refs.js
index e217cd25413..f0fbc5ed7b6 100644
--- a/app/assets/javascripts/pipeline_new/utils/format_refs.js
+++ b/app/assets/javascripts/pipeline_new/utils/format_refs.js
@@ -3,7 +3,7 @@ import { BRANCH_REF_TYPE, TAG_REF_TYPE } from '../constants';
export default (refs, type) => {
let fullName;
- return refs.map(ref => {
+ return refs.map((ref) => {
if (type === BRANCH_REF_TYPE) {
fullName = `refs/heads/${ref}`;
} else if (type === TAG_REF_TYPE) {
diff --git a/app/assets/javascripts/pipelines.js b/app/assets/javascripts/pipelines.js
index 07abe714367..3b4e8d0e019 100644
--- a/app/assets/javascripts/pipelines.js
+++ b/app/assets/javascripts/pipelines.js
@@ -1,5 +1,5 @@
import LinkedTabs from './lib/utils/bootstrap_linked_tabs';
-import { setCiStatusFavicon } from './lib/utils/common_utils';
+import { setCiStatusFavicon } from './lib/utils/favicon_ci';
export default class Pipelines {
constructor(options = {}) {
diff --git a/app/assets/javascripts/pipelines/components/dag/dag.vue b/app/assets/javascripts/pipelines/components/dag/dag.vue
index 85171263f08..2482af2c7f0 100644
--- a/app/assets/javascripts/pipelines/components/dag/dag.vue
+++ b/app/assets/javascripts/pipelines/components/dag/dag.vue
@@ -56,15 +56,15 @@ export default {
const unwrappedGroups = stages
.map(({ name, groups: { nodes: groups } }) => {
- return groups.map(group => {
+ return groups.map((group) => {
return { category: name, ...group };
});
})
.flat(2);
- const nodes = unwrappedGroups.map(group => {
+ const nodes = unwrappedGroups.map((group) => {
const jobs = group.jobs.nodes.map(({ name, needs }) => {
- return { name, needs: needs.nodes.map(need => need.name) };
+ return { name, needs: needs.nodes.map((need) => need.name) };
});
return { ...group, jobs };
diff --git a/app/assets/javascripts/pipelines/components/dag/dag_graph.vue b/app/assets/javascripts/pipelines/components/dag/dag_graph.vue
index 42d1debcddf..5ba0604fa01 100644
--- a/app/assets/javascripts/pipelines/components/dag/dag_graph.vue
+++ b/app/assets/javascripts/pipelines/components/dag/dag_graph.vue
@@ -173,7 +173,7 @@ export default {
createClip(link) {
return link
.append('clipPath')
- .attr('id', d => {
+ .attr('id', (d) => {
return this.createAndAssignId(d, 'clipId', 'dag-clip');
})
.append('path')
@@ -183,7 +183,7 @@ export default {
createGradient(link) {
const gradient = link
.append('linearGradient')
- .attr('id', d => {
+ .attr('id', (d) => {
return this.createAndAssignId(d, 'gradId', 'dag-grad');
})
.attr('gradientUnits', 'userSpaceOnUse')
@@ -251,7 +251,7 @@ export default {
.data(linksData)
.enter()
.append('g')
- .attr('id', d => {
+ .attr('id', (d) => {
return this.createAndAssignId(d, 'uid', LINK_SELECTOR);
})
.classed(
@@ -273,10 +273,10 @@ export default {
`${NODE_SELECTOR} gl-transition-property-stroke ${this.$options.viewOptions.hoverFadeClasses}`,
true,
)
- .attr('id', d => {
+ .attr('id', (d) => {
return this.createAndAssignId(d, 'uid', NODE_SELECTOR);
})
- .attr('stroke', d => {
+ .attr('stroke', (d) => {
const color = this.color(d);
/* eslint-disable-next-line no-param-reassign */
d.color = color;
@@ -284,10 +284,10 @@ export default {
})
.attr('stroke-width', nodeWidth)
.attr('stroke-linecap', 'round')
- .attr('x1', d => Math.floor((d.x1 + d.x0) / 2))
- .attr('x2', d => Math.floor((d.x1 + d.x0) / 2))
- .attr('y1', d => d.y0 + 4)
- .attr('y2', d => d.y1 - 4);
+ .attr('x1', (d) => Math.floor((d.x1 + d.x0) / 2))
+ .attr('x2', (d) => Math.floor((d.x1 + d.x0) / 2))
+ .attr('y1', (d) => d.y0 + 4)
+ .attr('y2', (d) => d.y1 - 4);
},
initColors() {
diff --git a/app/assets/javascripts/pipelines/components/dag/drawing_utils.js b/app/assets/javascripts/pipelines/components/dag/drawing_utils.js
index d56addc473f..3cd09d57ffb 100644
--- a/app/assets/javascripts/pipelines/components/dag/drawing_utils.js
+++ b/app/assets/javascripts/pipelines/components/dag/drawing_utils.js
@@ -92,8 +92,8 @@ export const createSankey = ({
]);
return ({ nodes, links }) =>
sankeyGenerator({
- nodes: nodes.map(d => ({ ...d })),
- links: links.map(d => ({ ...d })),
+ nodes: nodes.map((d) => ({ ...d })),
+ links: links.map((d) => ({ ...d })),
});
};
diff --git a/app/assets/javascripts/pipelines/components/dag/interactions.js b/app/assets/javascripts/pipelines/components/dag/interactions.js
index e9f3e9f0e2c..69f36feeee4 100644
--- a/app/assets/javascripts/pipelines/components/dag/interactions.js
+++ b/app/assets/javascripts/pipelines/components/dag/interactions.js
@@ -13,22 +13,22 @@ export const getLiveLinksAsDict = () => {
return Object.fromEntries(
getLiveLinks()
.data()
- .map(d => [d.uid, d]),
+ .map((d) => [d.uid, d]),
);
};
export const currentIsLive = (idx, collection) =>
getCurrent(idx, collection).classed(IS_HIGHLIGHTED);
-const backgroundLinks = selection => selection.style('stroke-opacity', highlightOut);
-const backgroundNodes = selection => selection.attr('stroke', '#f2f2f2');
-const foregroundLinks = selection => selection.style('stroke-opacity', highlightIn);
-const foregroundNodes = selection => selection.attr('stroke', d => d.color);
+const backgroundLinks = (selection) => selection.style('stroke-opacity', highlightOut);
+const backgroundNodes = (selection) => selection.attr('stroke', '#f2f2f2');
+const foregroundLinks = (selection) => selection.style('stroke-opacity', highlightIn);
+const foregroundNodes = (selection) => selection.attr('stroke', (d) => d.color);
const renewLinks = (selection, baseOpacity) => selection.style('stroke-opacity', baseOpacity);
-const renewNodes = selection => selection.attr('stroke', d => d.color);
+const renewNodes = (selection) => selection.attr('stroke', (d) => d.color);
-export const getAllLinkAncestors = node => {
+export const getAllLinkAncestors = (node) => {
if (node.targetLinks) {
- return node.targetLinks.flatMap(n => {
+ return node.targetLinks.flatMap((n) => {
return [n, ...getAllLinkAncestors(n.source)];
});
}
@@ -36,11 +36,11 @@ export const getAllLinkAncestors = node => {
return [];
};
-const getAllNodeAncestors = node => {
+const getAllNodeAncestors = (node) => {
let allNodes = [];
if (node.targetLinks) {
- allNodes = node.targetLinks.flatMap(n => {
+ allNodes = node.targetLinks.flatMap((n) => {
return getAllNodeAncestors(n.source);
});
}
@@ -74,7 +74,7 @@ const highlightPath = (parentLinks, parentNodes) => {
});
/* highlight correct nodes */
- parentNodes.forEach(id => {
+ parentNodes.forEach((id) => {
foregroundNodes(d3.select(`#${id}`)).classed(IS_HIGHLIGHTED, true);
});
};
@@ -86,7 +86,7 @@ const restoreNodes = () => {
rehighlights their nodes.
*/
- getLiveLinks().each(d => {
+ getLiveLinks().each((d) => {
foregroundNodes(d3.select(`#${d.source.uid}`)).classed(IS_HIGHLIGHTED, true);
foregroundNodes(d3.select(`#${d.target.uid}`)).classed(IS_HIGHLIGHTED, true);
});
@@ -97,7 +97,7 @@ const restorePath = (parentLinks, parentNodes, baseOpacity) => {
renewLinks(d3.select(`#${uid}`), baseOpacity).classed(IS_HIGHLIGHTED, false);
});
- parentNodes.forEach(id => {
+ parentNodes.forEach((id) => {
d3.select(`#${id}`).classed(IS_HIGHLIGHTED, false);
});
@@ -112,7 +112,7 @@ const restorePath = (parentLinks, parentNodes, baseOpacity) => {
restoreNodes();
};
-export const restoreLinks = baseOpacity => {
+export const restoreLinks = (baseOpacity) => {
/*
if there exist live links, reset to highlight out / pale
otherwise, reset to base
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index 4e9b21a5c55..0ce94d4f02f 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -4,6 +4,7 @@ import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { reportToSentry } from './utils';
/**
* Renders either a cancel, retry or play icon button and handles the post request
@@ -50,6 +51,9 @@ export default {
return `${actionIconDash} js-icon-${actionIconDash}`;
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('action_component', `error: ${err}, info: ${info}`);
+ },
methods: {
/**
* The request should not be handled here.
@@ -70,10 +74,12 @@ export default {
this.$emit('pipelineActionRequestComplete');
})
- .catch(() => {
+ .catch((err) => {
this.isDisabled = false;
this.isLoading = false;
+ reportToSentry('action_component', err);
+
createFlash(__('An error occurred while making the request.'));
});
},
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 67b2ed3b596..cd403757fe6 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,12 +1,15 @@
<script>
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
+import LinksLayer from '../graph_shared/links_layer.vue';
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 {
name: 'PipelineGraph',
components: {
+ LinksLayer,
LinkedGraphWrapper,
LinkedPipelinesColumn,
StageColumnComponent,
@@ -31,9 +34,16 @@ export default {
DOWNSTREAM,
UPSTREAM,
},
+ CONTAINER_REF: 'PIPELINE_LINKS_CONTAINER_REF',
+ BASE_CONTAINER_ID: 'pipeline-links-container',
data() {
return {
hoveredJobName: '',
+ highlightedJobs: [],
+ measurements: {
+ width: 0,
+ height: 0,
+ },
pipelineExpanded: {
jobName: '',
expanded: false,
@@ -41,6 +51,9 @@ export default {
};
},
computed: {
+ containerId() {
+ return `${this.$options.BASE_CONTAINER_ID}-${this.pipeline.id}`;
+ },
downstreamPipelines() {
return this.hasDownstreamPipelines ? this.pipeline.downstream : [];
},
@@ -53,12 +66,13 @@ export default {
hasUpstreamPipelines() {
return Boolean(this.pipeline?.upstream?.length > 0);
},
- // The two show checks prevent upstream / downstream from showing redundant linked columns
+ // The show downstream check prevents showing redundant linked columns
showDownstreamPipelines() {
return (
this.hasDownstreamPipelines && this.type !== this.$options.pipelineTypeConstants.UPSTREAM
);
},
+ // The show upstream check prevents showing redundant linked columns
showUpstreamPipelines() {
return (
this.hasUpstreamPipelines && this.type !== this.$options.pipelineTypeConstants.DOWNSTREAM
@@ -68,7 +82,22 @@ export default {
return this.hasUpstreamPipelines ? this.pipeline.upstream : [];
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
+ },
+ mounted() {
+ this.measurements = this.getMeasurements();
+ },
methods: {
+ getMeasurements() {
+ return {
+ width: this.$refs[this.containerId].scrollWidth,
+ height: this.$refs[this.containerId].scrollHeight,
+ };
+ },
+ onError(errorType) {
+ this.$emit('error', errorType);
+ },
setJob(jobName) {
this.hoveredJobName = jobName;
},
@@ -78,14 +107,17 @@ export default {
jobName: expanded ? jobName : '',
};
},
+ updateHighlightedJobs(jobs) {
+ this.highlightedJobs = jobs;
+ },
},
};
</script>
<template>
<div class="js-pipeline-graph">
<div
- class="gl-pipeline-min-h gl-display-flex gl-position-relative gl-overflow-auto gl-bg-gray-10 gl-white-space-nowrap"
- :class="{ 'gl-py-5': !isLinkedPipeline }"
+ 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 }"
>
<linked-graph-wrapper>
<template #upstream>
@@ -94,20 +126,36 @@ export default {
:linked-pipelines="upstreamPipelines"
:column-title="__('Upstream')"
:type="$options.pipelineTypeConstants.UPSTREAM"
- @error="emit('error', errorType)"
+ @error="onError"
/>
</template>
<template #main>
- <stage-column-component
- v-for="stage in graph"
- :key="stage.name"
- :title="stage.name"
- :groups="stage.groups"
- :action="stage.status.action"
- :job-hovered="hoveredJobName"
- :pipeline-expanded="pipelineExpanded"
- @refreshPipelineGraph="$emit('refreshPipelineGraph')"
- />
+ <div :id="containerId" :ref="containerId">
+ <links-layer
+ :pipeline-data="graph"
+ :pipeline-id="pipeline.id"
+ :container-id="containerId"
+ :container-measurements="measurements"
+ :highlighted-job="hoveredJobName"
+ default-link-color="gl-stroke-transparent"
+ @error="onError"
+ @highlightedJobsChange="updateHighlightedJobs"
+ >
+ <stage-column-component
+ v-for="stage in graph"
+ :key="stage.name"
+ :title="stage.name"
+ :groups="stage.groups"
+ :action="stage.status.action"
+ :highlighted-jobs="highlightedJobs"
+ :job-hovered="hoveredJobName"
+ :pipeline-expanded="pipelineExpanded"
+ :pipeline-id="pipeline.id"
+ @refreshPipelineGraph="$emit('refreshPipelineGraph')"
+ @jobHover="setJob"
+ />
+ </links-layer>
+ </div>
</template>
<template #downstream>
<linked-pipelines-column
@@ -117,7 +165,7 @@ export default {
:type="$options.pipelineTypeConstants.DOWNSTREAM"
@downstreamHovered="setJob"
@pipelineExpandToggle="togglePipelineExpanded"
- @error="emit('error', errorType)"
+ @error="onError"
/>
</template>
</linked-graph-wrapper>
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 9ca4dc1e27a..2164dbf4d55 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
@@ -5,6 +5,7 @@ import StageColumnComponentLegacy from './stage_column_component_legacy.vue';
import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
+import { reportToSentry } from './utils';
export default {
name: 'PipelineGraphLegacy',
@@ -78,11 +79,11 @@ export default {
return (
this.pipeline.triggered_by &&
Array.isArray(this.pipeline.triggered_by) &&
- this.pipeline.triggered_by.find(el => el.isExpanded)
+ this.pipeline.triggered_by.find((el) => el.isExpanded)
);
},
expandedDownstream() {
- return this.pipeline.triggered && this.pipeline.triggered.find(el => el.isExpanded);
+ return this.pipeline.triggered && this.pipeline.triggered.find((el) => el.isExpanded);
},
pipelineTypeUpstream() {
return this.type !== this.$options.downstream && this.expandedUpstream;
@@ -94,6 +95,9 @@ export default {
return this.pipeline.project.id;
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
+ },
methods: {
capitalizeStageName(name) {
const escapedName = escape(name);
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
index d98e3aad054..f596333237d 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
@@ -1,10 +1,10 @@
<script>
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import { __ } from '~/locale';
import { DEFAULT, LOAD_FAILURE } from '../../constants';
-import getPipelineDetails from '../../graphql/queries/get_pipeline_details.query.graphql';
import PipelineGraph from './graph_component.vue';
-import { unwrapPipelineData, toggleQueryPollingByVisibility } from './utils';
+import { unwrapPipelineData, toggleQueryPollingByVisibility, reportToSentry } from './utils';
export default {
name: 'PipelineGraphWrapper',
@@ -76,6 +76,9 @@ export default {
mounted() {
toggleQueryPollingByVisibility(this.$apollo.queries.pipeline);
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
+ },
methods: {
hideAlert() {
this.showAlert = false;
@@ -86,6 +89,7 @@ export default {
reportFailure(type) {
this.showAlert = true;
this.failureType = type;
+ reportToSentry(this.$options.name, this.failureType);
},
},
};
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 203d6a12edd..08d6162aeb8 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -2,6 +2,7 @@
import { GlTooltipDirective } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import JobItem from './job_item.vue';
+import { reportToSentry } from './utils';
/**
* Renders the dropdown for the pipeline graph.
@@ -22,13 +23,24 @@ export default {
type: Object,
required: true,
},
+ pipelineId: {
+ type: Number,
+ required: false,
+ default: -1,
+ },
},
computed: {
+ computedJobId() {
+ return this.pipelineId > -1 ? `${this.group.name}-${this.pipelineId}` : '';
+ },
tooltipText() {
const { name, status } = this.group;
return `${name} - ${status.label}`;
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('job_group_dropdown', `error: ${err}, info: ${info}`);
+ },
methods: {
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
@@ -37,7 +49,7 @@ export default {
};
</script>
<template>
- <div class="ci-job-dropdown-container dropdown dropright">
+ <div :id="computedJobId" class="ci-job-dropdown-container dropdown dropright">
<button
v-gl-tooltip.hover="{ boundary: 'viewport' }"
:title="tooltipText"
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 93ebe02d4e8..8262d728a24 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -6,6 +6,7 @@ import { sprintf } from '~/locale';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { accessValue } from './accessors';
import { REST } from './constants';
+import { reportToSentry } from './utils';
/**
* Renders the badge for the pipeline graph and the job's dropdown.
@@ -73,6 +74,11 @@ export default {
required: false,
default: () => ({}),
},
+ pipelineId: {
+ type: Number,
+ required: false,
+ default: -1,
+ },
},
computed: {
boundary() {
@@ -84,6 +90,9 @@ export default {
hasDetails() {
return accessValue(this.dataMethod, 'hasDetails', this.status);
},
+ computedJobId() {
+ return this.pipelineId > -1 ? `${this.job.name}-${this.pipelineId}` : '';
+ },
status() {
return this.job && this.job.status ? this.job.status : {};
},
@@ -130,6 +139,9 @@ export default {
: this.cssClassJobName;
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('job_item', `error: ${err}, info: ${info}`);
+ },
methods: {
hideTooltips() {
this.$root.$emit('bv::hide::tooltip');
@@ -142,6 +154,7 @@ export default {
</script>
<template>
<div
+ :id="computedJobId"
class="ci-job-component gl-display-flex gl-align-items-center gl-justify-content-space-between"
data-qa-selector="job_item_container"
>
@@ -151,8 +164,7 @@ export default {
:href="detailsPath"
:title="tooltipText"
:class="jobClasses"
- class="js-pipeline-graph-job-link qa-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none
- gl-focus-text-decoration-none gl-hover-text-decoration-none"
+ class="js-pipeline-graph-job-link qa-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none"
data-testid="job-with-link"
@click.stop="hideTooltips"
@mouseout="hideTooltips"
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index 1a179de64cd..d18e604f087 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -1,9 +1,10 @@
<script>
-import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon, GlBadge } from '@gitlab/ui';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
import { __, sprintf } from '~/locale';
import { accessValue } from './accessors';
import { DOWNSTREAM, REST, UPSTREAM } from './constants';
+import { reportToSentry } from './utils';
export default {
directives: {
@@ -14,6 +15,7 @@ export default {
GlButton,
GlLink,
GlLoadingIcon,
+ GlBadge,
},
inject: {
dataMethod: {
@@ -114,6 +116,9 @@ export default {
return this.isUpstream ? 'gl-left-0 gl-border-r-1!' : 'gl-right-0 gl-border-l-1!';
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('linked_pipeline', `error: ${err}, info: ${info}`);
+ },
methods: {
onClickLinkedPipeline() {
this.hideTooltips();
@@ -168,7 +173,9 @@ export default {
</div>
</div>
<div class="gl-pt-2">
- <span class="badge badge-primary" data-testid="downstream-pipeline-label">{{ label }}</span>
+ <gl-badge size="sm" variant="info" data-testid="downstream-pipeline-label">
+ {{ label }}
+ </gl-badge>
</div>
<gl-button
:id="buttonId"
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 7d333087874..40e6a01b88c 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -1,9 +1,9 @@
<script>
-import getPipelineDetails from '../../graphql/queries/get_pipeline_details.query.graphql';
+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 { unwrapPipelineData, toggleQueryPollingByVisibility } from './utils';
+import { unwrapPipelineData, toggleQueryPollingByVisibility, reportToSentry } from './utils';
export default {
components: {
@@ -42,8 +42,8 @@ export default {
computed: {
columnClass() {
const positionValues = {
- right: 'gl-ml-11',
- left: 'gl-mr-7',
+ right: 'gl-ml-6',
+ left: 'gl-mr-6',
};
return `graph-position-${this.graphPosition} ${positionValues[this.graphPosition]}`;
},
@@ -80,8 +80,13 @@ export default {
result() {
this.loadingPipelineId = null;
},
- error() {
+ error(err, _vm, _key, type) {
this.$emit('error', LOAD_FAILURE);
+
+ reportToSentry(
+ 'linked_pipelines_column',
+ `error type: ${LOAD_FAILURE}, error: ${err}, apollo error type: ${type}`,
+ );
},
});
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 7d371b33220..2f1390e07d1 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,7 @@
<script>
import LinkedPipeline from './linked_pipeline.vue';
import { UPSTREAM } from './constants';
+import { reportToSentry } from './utils';
export default {
components: {
@@ -42,6 +43,9 @@ export default {
return this.type === UPSTREAM;
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('linked_pipelines_column_legacy', `error: ${err}, info: ${info}`);
+ },
methods: {
onPipelineClick(downstreamNode, pipeline, index) {
this.$emit('linkedPipelineClick', pipeline, index, downstreamNode);
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 b9bddc94ce4..65f8c231885 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -6,6 +6,7 @@ import JobGroupDropdown from './job_group_dropdown.vue';
import ActionComponent from './action_component.vue';
import { GRAPHQL } from './constants';
import { accessValue } from './accessors';
+import { reportToSentry } from './utils';
export default {
components: {
@@ -15,19 +16,28 @@ export default {
MainGraphWrapper,
},
props: {
- title: {
- type: String,
- required: true,
- },
groups: {
type: Array,
required: true,
},
+ pipelineId: {
+ type: Number,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
action: {
type: Object,
required: false,
default: () => ({}),
},
+ highlightedJobs: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
jobHovered: {
type: String,
required: false,
@@ -54,6 +64,9 @@ export default {
return !isEmpty(this.action);
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('stage_column_component', `error: ${err}, info: ${info}`);
+ },
methods: {
getGroupId(group) {
return accessValue(GRAPHQL, 'groupId', group);
@@ -61,11 +74,18 @@ export default {
groupId(group) {
return `ci-badge-${escape(group.name)}`;
},
+ isFadedOut(jobName) {
+ return (
+ this.jobHovered &&
+ this.highlightedJobs.length > 1 &&
+ !this.highlightedJobs.includes(jobName)
+ );
+ },
},
};
</script>
<template>
- <main-graph-wrapper>
+ <main-graph-wrapper class="gl-px-6">
<template #stages>
<div
data-testid="stage-column-title"
@@ -90,16 +110,25 @@ export default {
:key="getGroupId(group)"
data-testid="stage-column-group"
class="gl-relative gl-mb-3 gl-white-space-normal gl-pipeline-job-width"
+ @mouseenter="$emit('jobHover', group.name)"
+ @mouseleave="$emit('jobHover', '')"
>
<job-item
v-if="group.size === 1"
:job="group.jobs[0]"
:job-hovered="jobHovered"
:pipeline-expanded="pipelineExpanded"
+ :pipeline-id="pipelineId"
css-class-job-name="gl-build-content"
+ :class="{ 'gl-opacity-3': isFadedOut(group.name) }"
@pipelineActionRequestComplete="$emit('refreshPipelineGraph')"
/>
- <job-group-dropdown v-else :group="group" />
+ <job-group-dropdown
+ v-else
+ :group="group"
+ :pipeline-id="pipelineId"
+ :class="{ 'gl-opacity-3': isFadedOut(group.name) }"
+ />
</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 258b6bf6b6d..059e8f9f8db 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
@@ -4,6 +4,7 @@ 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 { reportToSentry } from './utils';
export default {
components: {
@@ -52,6 +53,9 @@ export default {
return !isEmpty(this.action);
},
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('stage_column_component_legacy', `error: ${err}, info: ${info}`);
+ },
methods: {
groupId(group) {
return `ci-badge-${escape(group.name)}`;
diff --git a/app/assets/javascripts/pipelines/components/graph/utils.js b/app/assets/javascripts/pipelines/components/graph/utils.js
index 32588feb426..1a935599bfa 100644
--- a/app/assets/javascripts/pipelines/components/graph/utils.js
+++ b/app/assets/javascripts/pipelines/components/graph/utils.js
@@ -1,5 +1,6 @@
import Visibility from 'visibilityjs';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import * as Sentry from '~/sentry/wrapper';
import { unwrapStagesWithNeeds } from '../unwrapping_utils';
const addMulti = (mainPipelineProjectPath, linkedPipeline) => {
@@ -9,7 +10,7 @@ const addMulti = (mainPipelineProjectPath, linkedPipeline) => {
};
};
-const transformId = linkedPipeline => {
+const transformId = (linkedPipeline) => {
return { ...linkedPipeline, id: getIdFromGraphQLId(linkedPipeline.id) };
};
@@ -42,7 +43,7 @@ const unwrapPipelineData = (mainPipelineProjectPath, data) => {
};
const toggleQueryPollingByVisibility = (queryRef, interval = 10000) => {
- const stopStartQuery = query => {
+ const stopStartQuery = (query) => {
if (!Visibility.hidden()) {
query.startPolling(interval);
} else {
@@ -55,3 +56,10 @@ const toggleQueryPollingByVisibility = (queryRef, interval = 10000) => {
};
export { unwrapPipelineData, toggleQueryPollingByVisibility };
+
+export const reportToSentry = (component, failureType) => {
+ Sentry.withScope((scope) => {
+ scope.setTag('component', component);
+ Sentry.captureException(failureType);
+ });
+};
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js b/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
new file mode 100644
index 00000000000..65c215be794
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
@@ -0,0 +1,97 @@
+import * as d3 from 'd3';
+
+export const createUniqueLinkId = (stageName, jobName) => `${stageName}-${jobName}`;
+
+/**
+ * This function expects its first argument data structure
+ * to be the same shaped as the one generated by `parseData`,
+ * which contains nodes and links. For each link,
+ * we find the nodes in the graph, calculate their coordinates and
+ * trace the lines that represent the needs of each job.
+ * @param {Object} nodeDict - Resulting object of `parseData` with nodes and links
+ * @param {String} containerID - Id for the svg the links will be draw in
+ * @returns {Array} Links that contain all the information about them
+ */
+
+export const generateLinksData = ({ links }, containerID, modifier = '') => {
+ const containerEl = document.getElementById(containerID);
+ return links.map((link) => {
+ const path = d3.path();
+
+ const sourceId = link.source;
+ const targetId = link.target;
+
+ const modifiedSourceId = `${sourceId}${modifier}`;
+ const modifiedTargetId = `${targetId}${modifier}`;
+
+ const sourceNodeEl = document.getElementById(modifiedSourceId);
+ const targetNodeEl = document.getElementById(modifiedTargetId);
+
+ const sourceNodeCoordinates = sourceNodeEl.getBoundingClientRect();
+ const targetNodeCoordinates = targetNodeEl.getBoundingClientRect();
+ const containerCoordinates = containerEl.getBoundingClientRect();
+
+ // Because we add the svg dynamically and calculate the coordinates
+ // with plain JS and not D3, we need to account for the fact that
+ // the coordinates we are getting are absolutes, but we want to draw
+ // relative to the svg container, which starts at `containerCoordinates(x,y)`
+ // so we substract these from the total. We also need to remove the padding
+ // from the total to make sure it's aligned properly. We then make the line
+ // 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'),
+ );
+ const paddingTop = parseFloat(
+ window.getComputedStyle(containerEl, null).getPropertyValue('padding-top'),
+ );
+
+ const sourceNodeX = sourceNodeCoordinates.right - containerCoordinates.x - paddingLeft;
+ const sourceNodeY =
+ sourceNodeCoordinates.top -
+ containerCoordinates.y -
+ paddingTop +
+ sourceNodeCoordinates.height / 2;
+ const targetNodeX = targetNodeCoordinates.x - containerCoordinates.x - paddingLeft;
+ const targetNodeY =
+ targetNodeCoordinates.y -
+ containerCoordinates.y -
+ paddingTop +
+ sourceNodeCoordinates.height / 2;
+
+ // Start point
+ path.moveTo(sourceNodeX, sourceNodeY);
+
+ // Make cross-stages lines a straight line all the way
+ // until we can safely draw the bezier to look nice.
+ // The adjustment number here is a magic number to make things
+ // look nice and should change if the padding changes. This goes well
+ // with gl-px-6. gl-px-8 is more like 100.
+ const straightLineDestinationX = targetNodeX - 60;
+ const controlPointX = straightLineDestinationX + (targetNodeX - straightLineDestinationX) / 2;
+
+ if (straightLineDestinationX > 0) {
+ path.lineTo(straightLineDestinationX, sourceNodeY);
+ }
+
+ // Add bezier curve. The first 4 coordinates are the 2 control
+ // points to create the curve, and the last one is the end point (x, y).
+ // We want our control points to be in the middle of the line
+ path.bezierCurveTo(
+ controlPointX,
+ sourceNodeY,
+ controlPointX,
+ targetNodeY,
+ targetNodeX,
+ targetNodeY,
+ );
+
+ return {
+ ...link,
+ source: sourceId,
+ target: targetId,
+ ref: createUniqueLinkId(sourceId, targetId),
+ path: path.toString(),
+ };
+ });
+};
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
new file mode 100644
index 00000000000..89444076ae0
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
@@ -0,0 +1,140 @@
+<script>
+import { isEmpty } from 'lodash';
+import { DRAW_FAILURE } from '../../constants';
+import { createJobsHash, generateJobNeedsDict } from '../../utils';
+import { parseData } from '../parsing_utils';
+import { generateLinksData } from './drawing_utils';
+
+export default {
+ name: 'LinksInner',
+ STROKE_WIDTH: 2,
+ props: {
+ containerId: {
+ type: String,
+ required: true,
+ },
+ containerMeasurements: {
+ type: Object,
+ required: true,
+ },
+ pipelineId: {
+ type: Number,
+ required: true,
+ },
+ pipelineData: {
+ type: Array,
+ required: true,
+ },
+ defaultLinkColor: {
+ type: String,
+ required: false,
+ default: 'gl-stroke-gray-200',
+ },
+ highlightedJob: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ links: [],
+ needsObject: null,
+ };
+ },
+ computed: {
+ hasHighlightedJob() {
+ return Boolean(this.highlightedJob);
+ },
+ isPipelineDataEmpty() {
+ return isEmpty(this.pipelineData);
+ },
+ highlightedJobs() {
+ // If you are hovering on a job, then the jobs we want to highlight are:
+ // The job you are currently hovering + all of its needs.
+ return this.hasHighlightedJob
+ ? [this.highlightedJob, ...this.needsObject[this.highlightedJob]]
+ : [];
+ },
+ highlightedLinks() {
+ // If you are hovering on a job, then the links we want to highlight are:
+ // All the links whose `source` and `target` are highlighted jobs.
+ if (this.hasHighlightedJob) {
+ const filteredLinks = this.links.filter((link) => {
+ return (
+ this.highlightedJobs.includes(link.source) && this.highlightedJobs.includes(link.target)
+ );
+ });
+
+ return filteredLinks.map((link) => link.ref);
+ }
+
+ return [];
+ },
+ viewBox() {
+ return [0, 0, this.containerMeasurements.width, this.containerMeasurements.height];
+ },
+ },
+ watch: {
+ highlightedJob() {
+ // On first hover, generate the needs reference
+ if (!this.needsObject) {
+ const jobs = createJobsHash(this.pipelineData);
+ this.needsObject = generateJobNeedsDict(jobs) ?? {};
+ }
+ },
+ highlightedJobs(jobs) {
+ this.$emit('highlightedJobsChange', jobs);
+ },
+ },
+ mounted() {
+ if (!isEmpty(this.pipelineData)) {
+ this.prepareLinkData();
+ }
+ },
+ methods: {
+ isLinkHighlighted(linkRef) {
+ return this.highlightedLinks.includes(linkRef);
+ },
+ prepareLinkData() {
+ try {
+ const arrayOfJobs = this.pipelineData.flatMap(({ groups }) => groups);
+ const parsedData = parseData(arrayOfJobs);
+ this.links = generateLinksData(parsedData, this.containerId, `-${this.pipelineId}`);
+ } catch {
+ this.$emit('error', DRAW_FAILURE);
+ }
+ },
+ getLinkClasses(link) {
+ return [
+ this.isLinkHighlighted(link.ref) ? 'gl-stroke-blue-400' : this.defaultLinkColor,
+ { 'gl-opacity-3': this.hasHighlightedJob && !this.isLinkHighlighted(link.ref) },
+ ];
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-flex gl-relative">
+ <svg
+ id="link-svg"
+ class="gl-absolute"
+ :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>
+ </svg>
+ <slot></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
new file mode 100644
index 00000000000..0993892a574
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
@@ -0,0 +1,86 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { __ } from '~/locale';
+import LinksInner from './links_inner.vue';
+
+export default {
+ name: 'LinksLayer',
+ components: {
+ GlAlert,
+ LinksInner,
+ },
+ MAX_GROUPS: 200,
+ props: {
+ containerMeasurements: {
+ type: Object,
+ required: true,
+ },
+ pipelineData: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ alertDismissed: false,
+ showLinksOverride: false,
+ };
+ },
+ i18n: {
+ showLinksAnyways: __('Show links anyways'),
+ tooManyJobs: __(
+ 'This graph has a large number of jobs and showing the links between them may have performance implications.',
+ ),
+ },
+ computed: {
+ containerZero() {
+ return !this.containerMeasurements.width || !this.containerMeasurements.height;
+ },
+ numGroups() {
+ return this.pipelineData.reduce((acc, { groups }) => {
+ return acc + Number(groups.length);
+ }, 0);
+ },
+ showAlert() {
+ return !this.showLinkedLayers && !this.alertDismissed;
+ },
+ showLinkedLayers() {
+ return (
+ !this.containerZero && (this.showLinksOverride || this.numGroups < this.$options.MAX_GROUPS)
+ );
+ },
+ },
+ methods: {
+ dismissAlert() {
+ this.alertDismissed = true;
+ },
+ overrideShowLinks() {
+ this.dismissAlert();
+ this.showLinksOverride = true;
+ },
+ },
+};
+</script>
+<template>
+ <links-inner
+ v-if="showLinkedLayers"
+ :container-measurements="containerMeasurements"
+ :pipeline-data="pipelineData"
+ v-bind="$attrs"
+ v-on="$listeners"
+ >
+ <slot></slot>
+ </links-inner>
+ <div v-else>
+ <gl-alert
+ v-if="showAlert"
+ class="gl-w-max-content gl-ml-4"
+ :primary-button-text="$options.i18n.showLinksAnyways"
+ @primaryAction="overrideShowLinks"
+ @dismiss="dismissAlert"
+ >
+ {{ $options.i18n.tooManyJobs }}
+ </gl-alert>
+ <slot></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/main_graph_wrapper.vue b/app/assets/javascripts/pipelines/components/graph_shared/main_graph_wrapper.vue
index 1c9e3236d56..bcd7705669e 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/main_graph_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/main_graph_wrapper.vue
@@ -16,14 +16,11 @@ export default {
</script>
<template>
<div>
- <div
- class="gl-display-flex gl-align-items-center gl-w-full gl-px-8 gl-mb-5"
- :class="stageClasses"
- >
+ <div class="gl-display-flex gl-align-items-center gl-w-full gl-mb-5" :class="stageClasses">
<slot name="stages"> </slot>
</div>
<div
- class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8"
+ class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full"
:class="jobClasses"
>
<slot name="jobs"> </slot>
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index af7c0d0ec3f..a20bd70e90a 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -54,7 +54,7 @@ export default {
iid: this.pipelineIid,
};
},
- update: data => data.project.pipeline,
+ update: (data) => data.project.pipeline,
error() {
this.reportFailure(LOAD_FAILURE);
},
diff --git a/app/assets/javascripts/pipelines/components/parsing_utils.js b/app/assets/javascripts/pipelines/components/parsing_utils.js
index 1ed415688f2..9c97fa832d0 100644
--- a/app/assets/javascripts/pipelines/components/parsing_utils.js
+++ b/app/assets/javascripts/pipelines/components/parsing_utils.js
@@ -33,15 +33,15 @@ import { uniqWith, isEqual } from 'lodash';
10 -> value (constant)
*/
-export const createNodeDict = nodes => {
+export const createNodeDict = (nodes) => {
return nodes.reduce((acc, node) => {
const newNode = {
...node,
- needs: node.jobs.map(job => job.needs || []).flat(),
+ needs: node.jobs.map((job) => job.needs || []).flat(),
};
if (node.size > 1) {
- node.jobs.forEach(job => {
+ node.jobs.forEach((job) => {
acc[job.name] = newNode;
});
}
@@ -54,13 +54,13 @@ export const createNodeDict = nodes => {
export const makeLinksFromNodes = (nodes, nodeDict) => {
const constantLinkValue = 10; // all links are the same weight
return nodes
- .map(group => {
- return group.jobs.map(job => {
+ .map((group) => {
+ return group.jobs.map((job) => {
if (!job.needs) {
return [];
}
- return job.needs.map(needed => {
+ return job.needs.map((needed) => {
return {
source: nodeDict[needed]?.name,
target: group.name,
@@ -74,7 +74,7 @@ export const makeLinksFromNodes = (nodes, nodeDict) => {
export const getAllAncestors = (nodes, nodeDict) => {
const needs = nodes
- .map(node => {
+ .map((node) => {
return nodeDict[node].needs || '';
})
.flat()
@@ -102,13 +102,13 @@ export const filterByAncestors = (links, nodeDict) =>
*/
const targetNode = target;
const targetNodeNeeds = nodeDict[targetNode].needs;
- const targetNodeNeedsMinusSource = targetNodeNeeds.filter(need => need !== source);
+ const targetNodeNeedsMinusSource = targetNodeNeeds.filter((need) => need !== source);
const allAncestors = getAllAncestors(targetNodeNeedsMinusSource, nodeDict);
return !allAncestors.includes(source);
});
-export const parseData = nodes => {
+export const parseData = (nodes) => {
const nodeDict = createNodeDict(nodes);
const allLinks = makeLinksFromNodes(nodes, nodeDict);
const filteredLinks = filterByAncestors(allLinks, nodeDict);
@@ -121,7 +121,7 @@ export const parseData = nodes => {
The number of nodes in the most populous generation drives the height of the graph.
*/
-export const getMaxNodes = nodes => {
+export const getMaxNodes = (nodes) => {
const counts = nodes.reduce((acc, { layer }) => {
if (!acc[layer]) {
acc[layer] = 0;
@@ -141,6 +141,6 @@ export const getMaxNodes = nodes => {
to find nodes that have no relations.
*/
-export const removeOrphanNodes = sankeyfiedNodes => {
- return sankeyfiedNodes.filter(node => node.sourceLinks.length || node.targetLinks.length);
+export const removeOrphanNodes = (sankeyfiedNodes) => {
+ return sankeyfiedNodes.filter((node) => node.sourceLinks.length || node.targetLinks.length);
};
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/drawing_utils.js b/app/assets/javascripts/pipelines/components/pipeline_graph/drawing_utils.js
deleted file mode 100644
index 35230e1511b..00000000000
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/drawing_utils.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import * as d3 from 'd3';
-import { createUniqueLinkId } from '../../utils';
-/**
- * This function expects its first argument data structure
- * to be the same shaped as the one generated by `parseData`,
- * which contains nodes and links. For each link,
- * we find the nodes in the graph, calculate their coordinates and
- * trace the lines that represent the needs of each job.
- * @param {Object} nodeDict - Resulting object of `parseData` with nodes and links
- * @param {Object} jobs - An object where each key is the job name that contains the job data
- * @param {ref} svg - Reference to the svg we draw in
- * @returns {Array} Links that contain all the information about them
- */
-
-export const generateLinksData = ({ links }, containerID) => {
- const containerEl = document.getElementById(containerID);
- return links.map(link => {
- const path = d3.path();
-
- const sourceId = link.source;
- const targetId = link.target;
-
- const sourceNodeEl = document.getElementById(sourceId);
- const targetNodeEl = document.getElementById(targetId);
-
- const sourceNodeCoordinates = sourceNodeEl.getBoundingClientRect();
- const targetNodeCoordinates = targetNodeEl.getBoundingClientRect();
- const containerCoordinates = containerEl.getBoundingClientRect();
-
- // Because we add the svg dynamically and calculate the coordinates
- // with plain JS and not D3, we need to account for the fact that
- // the coordinates we are getting are absolutes, but we want to draw
- // relative to the svg container, which starts at `containerCoordinates(x,y)`
- // so we substract these from the total. We also need to remove the padding
- // from the total to make sure it's aligned properly. We then make the line
- // positioned in the center of the job node by adding half the height
- // of the job pill.
- const paddingLeft = Number(
- window
- .getComputedStyle(containerEl, null)
- .getPropertyValue('padding-left')
- .replace('px', ''),
- );
- const paddingTop = Number(
- window
- .getComputedStyle(containerEl, null)
- .getPropertyValue('padding-top')
- .replace('px', ''),
- );
-
- const sourceNodeX = sourceNodeCoordinates.right - containerCoordinates.x - paddingLeft;
- const sourceNodeY =
- sourceNodeCoordinates.top -
- containerCoordinates.y -
- paddingTop +
- sourceNodeCoordinates.height / 2;
- const targetNodeX = targetNodeCoordinates.x - containerCoordinates.x - paddingLeft;
- const targetNodeY =
- targetNodeCoordinates.y -
- containerCoordinates.y -
- paddingTop +
- sourceNodeCoordinates.height / 2;
-
- // Start point
- path.moveTo(sourceNodeX, sourceNodeY);
-
- // Make cross-stages lines a straight line all the way
- // until we can safely draw the bezier to look nice.
- const straightLineDestinationX = targetNodeX - 100;
- const controlPointX = straightLineDestinationX + (targetNodeX - straightLineDestinationX) / 2;
-
- if (straightLineDestinationX > 0) {
- path.lineTo(straightLineDestinationX, sourceNodeY);
- }
-
- // Add bezier curve. The first 4 coordinates are the 2 control
- // points to create the curve, and the last one is the end point (x, y).
- // We want our control points to be in the middle of the line
- path.bezierCurveTo(
- controlPointX,
- sourceNodeY,
- controlPointX,
- targetNodeY,
- targetNodeX,
- targetNodeY,
- );
-
- return {
- ...link,
- source: sourceId,
- target: targetId,
- ref: createUniqueLinkId(sourceId, targetId),
- path: path.toString(),
- };
- });
-};
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 73e5f2542fb..8636808b69e 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -1,12 +1,10 @@
<script>
-import { isEmpty } from 'lodash';
import { GlAlert } from '@gitlab/ui';
import { __ } from '~/locale';
+import { generateLinksData } from '../graph_shared/drawing_utils';
import JobPill from './job_pill.vue';
import StagePill from './stage_pill.vue';
-import { generateLinksData } from './drawing_utils';
import { parseData } from '../parsing_utils';
-import { unwrapArrayOfJobs } from '../unwrapping_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';
@@ -23,8 +21,6 @@ export default {
errorTexts: {
[DRAW_FAILURE]: __('Could not draw the lines for job relationships'),
[DEFAULT]: __('An unknown error occurred.'),
- },
- warningTexts: {
[EMPTY_PIPELINE_DATA]: __(
'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.',
),
@@ -47,21 +43,24 @@ export default {
};
},
computed: {
+ hideGraph() {
+ // We won't even try to render the graph with these condition
+ // because it would cause additional errors down the line for the user
+ // which is confusing.
+ return this.isPipelineDataEmpty || this.isInvalidCiConfig;
+ },
+ pipelineStages() {
+ return this.pipelineData?.stages || [];
+ },
isPipelineDataEmpty() {
- return !this.isInvalidCiConfig && isEmpty(this.pipelineData?.stages);
+ return !this.isInvalidCiConfig && this.pipelineStages.length === 0;
},
isInvalidCiConfig() {
return this.pipelineData?.status === CI_CONFIG_STATUS_INVALID;
},
- showAlert() {
- return this.hasError || this.hasWarning;
- },
hasError() {
return this.failureType;
},
- hasWarning() {
- return this.warning;
- },
hasHighlightedJob() {
return Boolean(this.highlightedJob);
},
@@ -73,26 +72,32 @@ export default {
return this.warning;
},
failure() {
- const text = this.$options.errorTexts[this.failureType] || this.$options.errorTexts[DEFAULT];
-
- return { text, variant: 'danger', dismissible: true };
- },
- warning() {
- if (this.isPipelineDataEmpty) {
- return {
- text: this.$options.warningTexts[EMPTY_PIPELINE_DATA],
- variant: 'tip',
- dismissible: false,
- };
- } else if (this.isInvalidCiConfig) {
- return {
- text: this.$options.warningTexts[INVALID_CI_CONFIG],
- variant: 'danger',
- dismissible: false,
- };
+ switch (this.failureType) {
+ case DRAW_FAILURE:
+ return {
+ text: this.$options.errorTexts[DRAW_FAILURE],
+ variant: 'danger',
+ dismissible: true,
+ };
+ case EMPTY_PIPELINE_DATA:
+ return {
+ text: this.$options.errorTexts[EMPTY_PIPELINE_DATA],
+ variant: 'tip',
+ dismissible: false,
+ };
+ case INVALID_CI_CONFIG:
+ return {
+ text: this.$options.errorTexts[INVALID_CI_CONFIG],
+ variant: 'danger',
+ dismissible: false,
+ };
+ default:
+ return {
+ text: this.$options.errorTexts[DEFAULT],
+ variant: 'danger',
+ dismissible: true,
+ };
}
-
- return null;
},
viewBox() {
return [0, 0, this.width, this.height];
@@ -100,40 +105,45 @@ export default {
highlightedJobs() {
// If you are hovering on a job, then the jobs we want to highlight are:
// The job you are currently hovering + all of its needs.
- return this.hasHighlightedJob
- ? [this.highlightedJob, ...this.needsObject[this.highlightedJob]]
- : [];
+ return [this.highlightedJob, ...this.needsObject[this.highlightedJob]];
},
highlightedLinks() {
// If you are hovering on a job, then the links we want to highlight are:
// All the links whose `source` and `target` are highlighted jobs.
if (this.hasHighlightedJob) {
- const filteredLinks = this.links.filter(link => {
+ const filteredLinks = this.links.filter((link) => {
return (
this.highlightedJobs.includes(link.source) && this.highlightedJobs.includes(link.target)
);
});
- return filteredLinks.map(link => link.ref);
+ return filteredLinks.map((link) => link.ref);
}
return [];
},
},
- mounted() {
- if (!this.isPipelineDataEmpty && !this.isInvalidCiConfig) {
- // This guarantee that all sub-elements are rendered
- // https://v3.vuejs.org/api/options-lifecycle-hooks.html#mounted
- this.$nextTick(() => {
- this.getGraphDimensions();
- this.prepareLinkData();
- });
- }
+ watch: {
+ pipelineData: {
+ immediate: true,
+ handler() {
+ if (this.isPipelineDataEmpty) {
+ this.reportFailure(EMPTY_PIPELINE_DATA);
+ } else if (this.isInvalidCiConfig) {
+ this.reportFailure(INVALID_CI_CONFIG);
+ } else {
+ this.$nextTick(() => {
+ this.computeGraphDimensions();
+ this.prepareLinkData();
+ });
+ }
+ },
+ },
},
methods: {
prepareLinkData() {
try {
- const arrayOfJobs = unwrapArrayOfJobs(this.pipelineData);
+ const arrayOfJobs = this.pipelineStages.flatMap(({ groups }) => groups);
const parsedData = parseData(arrayOfJobs);
this.links = generateLinksData(parsedData, this.$options.CONTAINER_ID);
} catch {
@@ -141,7 +151,7 @@ export default {
}
},
getStageBackgroundClasses(index) {
- const { length } = this.pipelineData.stages;
+ const { length } = this.pipelineStages;
// It's possible for a graph to have only one stage, in which
// case we concatenate both the left and right rounding classes
if (length === 1) {
@@ -162,7 +172,7 @@ export default {
// The first time we hover, we create the object where
// we store all the data to properly highlight the needs.
if (!this.needsObject) {
- const jobs = createJobsHash(this.pipelineData);
+ const jobs = createJobsHash(this.pipelineStages);
this.needsObject = generateJobNeedsDict(jobs) ?? {};
}
@@ -171,7 +181,7 @@ export default {
removeHighlightNeeds() {
this.highlightedJob = null;
},
- getGraphDimensions() {
+ computeGraphDimensions() {
this.width = `${this.$refs[this.$options.CONTAINER_REF].scrollWidth}`;
this.height = `${this.$refs[this.$options.CONTAINER_REF].scrollHeight}`;
},
@@ -199,7 +209,7 @@ export default {
<template>
<div>
<gl-alert
- v-if="showAlert"
+ v-if="hasError"
:variant="alert.variant"
:dismissible="alert.dismissible"
@dismiss="alert.dismissible ? resetFailure : null"
@@ -207,7 +217,7 @@ export default {
{{ alert.text }}
</gl-alert>
<div
- v-if="!hasWarning"
+ v-if="!hideGraph"
:id="$options.CONTAINER_ID"
:ref="$options.CONTAINER_REF"
class="gl-display-flex gl-bg-gray-50 gl-px-4 gl-overflow-auto gl-relative gl-py-7"
@@ -227,7 +237,7 @@ export default {
</template>
</svg>
<div
- v-for="(stage, index) in pipelineData.stages"
+ v-for="(stage, index) in pipelineStages"
:key="`${stage.name}-${index}`"
class="gl-flex-direction-column"
>
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 78b69073cd3..ee26ea2f007 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
@@ -1,7 +1,25 @@
<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,
+ 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'),
+ },
+ },
name: 'PipelinesEmptyState',
components: {
GlButton,
@@ -20,6 +38,23 @@ 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>
@@ -29,18 +64,16 @@ export default {
</div>
<div class="col-12">
- <div class="gl-text-content">
+ <div class="text-content">
<template v-if="canSetCi">
- <h4 class="gl-text-center" data-testid="header-text">
+ <h4 data-testid="header-text" class="gl-text-center">
{{ s__('Pipelines|Build with confidence') }}
</h4>
-
<p data-testid="info-text">
{{
- 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.`)
+ isExperimentEnabled()
+ ? $options.i18n.experiment.infoMessage
+ : $options.i18n.control.infoMessage
}}
</p>
@@ -50,8 +83,13 @@ export default {
variant="info"
category="primary"
data-testid="get-started-pipelines"
+ @click="track('documentation_clicked')"
>
- {{ s__('Pipelines|Get started with Pipelines') }}
+ {{
+ isExperimentEnabled()
+ ? $options.i18n.experiment.buttonMessage
+ : $options.i18n.control.buttonMessage
+ }}
</gl-button>
</div>
</template>
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 bde0dd53aac..d1bac078642 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink, GlPopover, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
import { SCHEDULE_ORIGIN } from '../../constants';
export default {
@@ -7,10 +7,16 @@ export default {
GlLink,
GlPopover,
GlSprintf,
+ GlBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: {
+ targetProjectFullPath: {
+ default: '',
+ },
+ },
props: {
pipeline: {
type: Object,
@@ -25,11 +31,6 @@ export default {
required: true,
},
},
- inject: {
- targetProjectFullPath: {
- default: '',
- },
- },
computed: {
user() {
return this.pipeline.user;
@@ -50,7 +51,6 @@ export default {
<div class="table-section section-10 d-none d-md-block pipeline-tags">
<gl-link
:href="pipeline.path"
- class="js-pipeline-url-link js-onboarding-pipeline-item"
data-testid="pipeline-url-link"
data-qa-selector="pipeline_url_link"
>
@@ -58,46 +58,49 @@ export default {
</gl-link>
<div class="label-container">
<gl-link v-if="isScheduled" :href="pipelineScheduleUrl" target="__blank">
- <span
+ <gl-badge
v-gl-tooltip
:title="__('This pipeline was triggered by a schedule.')"
- class="badge badge-info"
+ variant="info"
+ size="sm"
data-testid="pipeline-url-scheduled"
- >{{ __('Scheduled') }}</span
+ >{{ __('Scheduled') }}</gl-badge
>
</gl-link>
- <span
+ <gl-badge
v-if="pipeline.flags.latest"
v-gl-tooltip
:title="__('Latest pipeline for the most recent commit on this branch')"
- class="js-pipeline-url-latest badge badge-success"
+ variant="success"
+ size="sm"
data-testid="pipeline-url-latest"
- >{{ __('latest') }}</span
+ >{{ __('latest') }}</gl-badge
>
- <span
+ <gl-badge
v-if="pipeline.flags.yaml_errors"
v-gl-tooltip
:title="pipeline.yaml_errors"
- class="js-pipeline-url-yaml badge badge-danger"
+ variant="danger"
+ size="sm"
data-testid="pipeline-url-yaml"
- >{{ __('yaml invalid') }}</span
+ >{{ __('yaml invalid') }}</gl-badge
>
- <span
+ <gl-badge
v-if="pipeline.flags.failure_reason"
v-gl-tooltip
:title="pipeline.failure_reason"
- class="js-pipeline-url-failure badge badge-danger"
+ variant="danger"
+ size="sm"
data-testid="pipeline-url-failure"
- >{{ __('error') }}</span
+ >{{ __('error') }}</gl-badge
>
<gl-link
v-if="pipeline.flags.auto_devops"
:id="`pipeline-url-autodevops-${pipeline.id}`"
tabindex="0"
- class="js-pipeline-url-autodevops badge badge-info autodevops-badge"
data-testid="pipeline-url-autodevops"
role="button"
- >{{ __('Auto DevOps') }}</gl-link
+ ><gl-badge variant="info" size="sm">{{ __('Auto DevOps') }}</gl-badge></gl-link
>
<gl-popover
:target="`pipeline-url-autodevops-${pipeline.id}`"
@@ -113,7 +116,7 @@ export default {
)
"
>
- <template #strong="{content}">
+ <template #strong="{ content }">
<b>{{ content }}</b>
</template>
</gl-sprintf>
@@ -123,13 +126,14 @@ export default {
__('Learn more about Auto DevOps')
}}</gl-link>
</gl-popover>
- <span
+ <gl-badge
v-if="pipeline.flags.stuck"
- class="js-pipeline-url-stuck badge badge-warning"
+ variant="warning"
+ size="sm"
data-testid="pipeline-url-stuck"
- >{{ __('stuck') }}</span
+ >{{ __('stuck') }}</gl-badge
>
- <span
+ <gl-badge
v-if="pipeline.flags.detached_merge_request_pipeline"
v-gl-tooltip
:title="
@@ -137,17 +141,19 @@ export default {
'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.',
)
"
- class="js-pipeline-url-detached badge badge-info"
+ variant="info"
+ size="sm"
data-testid="pipeline-url-detached"
- >{{ __('detached') }}</span
+ >{{ __('detached') }}</gl-badge
>
- <span
+ <gl-badge
v-if="isInFork"
v-gl-tooltip
:title="__('Pipeline ran in fork of project')"
- class="badge badge-info"
+ variant="info"
+ size="sm"
data-testid="pipeline-url-fork"
- >{{ __('fork') }}</span
+ >{{ __('fork') }}</gl-badge
>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index ff27226b408..ec7c5764be1 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -246,7 +246,7 @@ export default {
filterPipelines(filters) {
this.resetRequestData();
- filters.forEach(filter => {
+ filters.forEach((filter) => {
// do not add Any for username query param, so we
// can fetch all trigger authors
if (
@@ -279,7 +279,7 @@ export default {
<div class="pipelines-container">
<div
v-if="shouldRenderTabs || shouldRenderButtons"
- class="top-area scrolling-tabs-container inner-page-scroll-tabs"
+ class="top-area scrolling-tabs-container inner-page-scroll-tabs gl-border-none"
>
<div class="fade-left"><gl-icon name="chevron-lg-left" :size="12" /></div>
<div class="fade-right"><gl-icon name="chevron-lg-right" :size="12" /></div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
index 55c71e299be..b13460b4c68 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
@@ -1,14 +1,19 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLink, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
export default {
directives: {
GlTooltip: GlTooltipDirective,
},
components: {
- GlIcon,
- GlLink,
+ GlDropdown,
+ GlDropdownItem,
+ GlSprintf,
+ },
+ translations: {
+ artifacts: __('Artifacts'),
+ downloadArtifact: __('Download %{name} artifact'),
},
props: {
artifacts: {
@@ -19,24 +24,25 @@ export default {
};
</script>
<template>
- <div class="btn-group" role="group">
- <button
- v-gl-tooltip
- type="button"
- class="dropdown-toggle build-artifacts btn btn-default js-pipeline-dropdown-download"
- :title="__('Artifacts')"
- data-toggle="dropdown"
- :aria-label="__('Artifacts')"
+ <gl-dropdown
+ v-gl-tooltip
+ class="build-artifacts js-pipeline-dropdown-download"
+ :title="$options.translations.artifacts"
+ :text="$options.translations.artifacts"
+ :aria-label="$options.translations.artifacts"
+ icon="download"
+ text-sr-only
+ >
+ <gl-dropdown-item
+ v-for="(artifact, i) in artifacts"
+ :key="i"
+ :href="artifact.path"
+ rel="nofollow"
+ download
>
- <gl-icon name="download" />
- <gl-icon name="chevron-down" />
- </button>
- <ul class="dropdown-menu dropdown-menu-right">
- <li v-for="(artifact, i) in artifacts" :key="i">
- <gl-link :href="artifact.path" rel="nofollow" download
- >Download {{ artifact.name }} artifact</gl-link
- >
- </li>
- </ul>
- </div>
+ <gl-sprintf :message="$options.translations.downloadArtifact">
+ <template #name>{{ artifact.name }}</template>
+ </gl-sprintf>
+ </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 29345f33367..127503f1307 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
@@ -33,7 +33,7 @@ export default {
},
computed: {
selectedTypes() {
- return this.value.map(i => i.type);
+ return this.value.map((i) => i.type);
},
tokens() {
return [
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 7224ec455f6..b6c4e617a90 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
@@ -346,7 +346,6 @@ export default {
<pipelines-artifacts-component
v-if="pipeline.details.artifacts.length"
:artifacts="pipeline.details.artifacts"
- class="d-md-block"
/>
<gl-button
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
index 581ea5fbb35..a9154d93194 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
@@ -124,7 +124,7 @@ export default {
$(
'.js-builds-dropdown-list button, .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item',
this.$el,
- ).on('click', e => {
+ ).on('click', (e) => {
e.stopPropagation();
});
},
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 60cb697f1af..24456574a6f 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
@@ -34,10 +34,10 @@ export default {
fetchBranches(searchterm) {
Api.branches(this.config.projectId, searchterm)
.then(({ data }) => {
- this.branches = data.map(branch => branch.name);
+ this.branches = data.map((branch) => branch.name);
this.loading = false;
})
- .catch(err => {
+ .catch((err) => {
createFlash(FETCH_BRANCH_ERROR_MESSAGE);
this.loading = false;
throw err;
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue
index dc43d94f4fd..020a08b8cee 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue
@@ -72,7 +72,7 @@ export default {
];
},
findActiveStatus() {
- return this.statuses.find(status => status.value === this.value.data);
+ return this.statuses.find((status) => status.value === this.value.data);
},
},
};
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 d6ba5fcca85..1241803c612 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
@@ -34,10 +34,10 @@ export default {
fetchTags(searchTerm) {
Api.tags(this.config.projectId, searchTerm)
.then(({ data }) => {
- this.tags = data.map(tag => tag.name);
+ this.tags = data.map((tag) => tag.name);
this.loading = false;
})
- .catch(err => {
+ .catch((err) => {
createFlash(FETCH_TAG_ERROR_MESSAGE);
this.loading = false;
throw err;
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
index ae5758233bc..3db5893b565 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
@@ -45,7 +45,7 @@ export default {
return this.value.data.toLowerCase();
},
activeUser() {
- return this.users.find(user => {
+ return this.users.find((user) => {
return user.username.toLowerCase() === this.currentValue;
});
},
@@ -56,11 +56,11 @@ export default {
methods: {
fetchProjectUsers(searchTerm) {
Api.projectUsers(this.config.projectId, searchTerm)
- .then(users => {
+ .then((users) => {
this.users = users;
this.loading = false;
})
- .catch(err => {
+ .catch((err) => {
createFlash(FETCH_AUTHOR_ERROR_MESSAGE);
this.loading = false;
throw err;
@@ -80,7 +80,7 @@ export default {
v-on="$listeners"
@input="searchAuthors"
>
- <template #view="{inputValue}">
+ <template #view="{ inputValue }">
<gl-avatar
v-if="activeUser"
:size="16"
diff --git a/app/assets/javascripts/pipelines/components/unwrapping_utils.js b/app/assets/javascripts/pipelines/components/unwrapping_utils.js
index aa33f622ce6..15073079c0a 100644
--- a/app/assets/javascripts/pipelines/components/unwrapping_utils.js
+++ b/app/assets/javascripts/pipelines/components/unwrapping_utils.js
@@ -1,22 +1,5 @@
-/**
- * This function takes the stages and add the stage name
- * at the group level as `category` to have an easier
- * implementation while constructions nodes with D3
- * @param {Array} stages
- * @returns {Array} - Array of stages with stage name at the group level as `category`
- */
-export const unwrapArrayOfJobs = (stages = []) => {
- return stages
- .map(({ name, groups }) => {
- return groups.map(group => {
- return { category: name, ...group };
- });
- })
- .flat(2);
-};
-
-const unwrapGroups = stages => {
- return stages.map(stage => {
+const unwrapGroups = (stages) => {
+ return stages.map((stage) => {
const {
groups: { nodes: groups },
} = stage;
@@ -25,21 +8,21 @@ const unwrapGroups = stages => {
};
const unwrapNodesWithName = (jobArray, prop, field = 'name') => {
- return jobArray.map(job => {
- return { ...job, [prop]: job[prop].nodes.map(item => item[field]) };
+ return jobArray.map((job) => {
+ return { ...job, [prop]: job[prop].nodes.map((item) => item[field]) };
});
};
-const unwrapJobWithNeeds = denodedJobArray => {
+const unwrapJobWithNeeds = (denodedJobArray) => {
return unwrapNodesWithName(denodedJobArray, 'needs');
};
-const unwrapStagesWithNeeds = denodedStages => {
+const unwrapStagesWithNeeds = (denodedStages) => {
const unwrappedNestedGroups = unwrapGroups(denodedStages);
- const nodes = unwrappedNestedGroups.map(node => {
+ const nodes = unwrappedNestedGroups.map((node) => {
const { groups } = node;
- const groupsWithJobs = groups.map(group => {
+ const groupsWithJobs = groups.map((group) => {
const jobs = unwrapJobWithNeeds(group.jobs.nodes);
return { ...group, jobs };
});
diff --git a/app/assets/javascripts/pipelines/graphql/fragments/linked_pipelines.fragment.graphql b/app/assets/javascripts/pipelines/graphql/fragments/linked_pipelines.fragment.graphql
deleted file mode 100644
index 3bf6d8dc9d8..00000000000
--- a/app/assets/javascripts/pipelines/graphql/fragments/linked_pipelines.fragment.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-fragment LinkedPipelineData on Pipeline {
- id
- iid
- path
- status: detailedStatus {
- group
- label
- icon
- }
- sourceJob {
- name
- }
- project {
- name
- fullPath
- }
-}
diff --git a/app/assets/javascripts/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql b/app/assets/javascripts/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql
new file mode 100644
index 00000000000..f93908aeb04
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql
@@ -0,0 +1,34 @@
+fragment PipelineStagesConnection on CiConfigStageConnection {
+ nodes {
+ name
+ groups {
+ nodes {
+ name
+ size
+ jobs {
+ nodes {
+ name
+ script
+ beforeScript
+ afterScript
+ environment
+ allowFailure
+ tags
+ when
+ only {
+ refs
+ }
+ except {
+ refs
+ }
+ needs {
+ nodes {
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_details.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_details.query.graphql
deleted file mode 100644
index 25aede49631..00000000000
--- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_details.query.graphql
+++ /dev/null
@@ -1,65 +0,0 @@
-#import "../fragments/linked_pipelines.fragment.graphql"
-
-query getPipelineDetails($projectPath: ID!, $iid: ID!) {
- project(fullPath: $projectPath) {
- pipeline(iid: $iid) {
- id
- iid
- downstream {
- nodes {
- ...LinkedPipelineData
- }
- }
- upstream {
- ...LinkedPipelineData
- }
- stages {
- nodes {
- name
- status: detailedStatus {
- action {
- icon
- path
- title
- }
- }
- groups {
- nodes {
- status: detailedStatus {
- label
- group
- icon
- }
- name
- size
- jobs {
- nodes {
- name
- scheduledAt
- needs {
- nodes {
- name
- }
- }
- status: detailedStatus {
- icon
- tooltip
- hasDetails
- detailsPath
- group
- action {
- buttonTitle
- icon
- path
- title
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql b/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql
deleted file mode 100644
index 1da4fa0a72b..00000000000
--- a/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql
+++ /dev/null
@@ -1,20 +0,0 @@
-fragment PipelineStagesConnection on CiConfigStageConnection {
- nodes {
- name
- groups {
- nodes {
- name
- jobs {
- nodes {
- name
- needs {
- nodes {
- name
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js b/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js
index bd1b1664a1e..9f15b6c4ae3 100644
--- a/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/graph_pipeline_bundle_mixin.js
@@ -6,7 +6,7 @@ export default {
getExpandedPipelines(pipeline) {
this.mediator.service
.getPipeline(this.mediator.getExpandedParameters())
- .then(response => {
+ .then((response) => {
this.mediator.store.toggleLoading(pipeline);
this.mediator.store.storePipeline(response.data);
this.mediator.poll.enable({ data: this.mediator.getExpandedParameters() });
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
index e31545bba5c..22cdb6b8f72 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines.js
@@ -90,7 +90,7 @@ export default {
// fetch new data
return this.service
.getPipelines(this.requestData)
- .then(response => {
+ .then((response) => {
this.isLoading = false;
this.successCallback(response);
@@ -124,8 +124,8 @@ export default {
getPipelines() {
return this.service
.getPipelines(this.requestData)
- .then(response => this.successCallback(response))
- .catch(error => this.errorCallback(error));
+ .then((response) => this.successCallback(response))
+ .catch((error) => this.errorCallback(error));
},
setCommonData(pipelines) {
this.store.storePipelines(pipelines);
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 27f71d2b878..133608b9801 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -10,6 +10,7 @@ import legacyPipelineHeader from './components/legacy_header_component.vue';
import eventHub from './event_hub';
import TestReports from './components/test_reports/test_reports.vue';
import createTestReportsStore from './stores/test_reports';
+import { reportToSentry } from './components/graph/utils';
Vue.use(Translate);
@@ -20,7 +21,7 @@ const SELECTORS = {
PIPELINE_TESTS: '#js-pipeline-tests-detail',
};
-const createLegacyPipelinesDetailApp = mediator => {
+const createLegacyPipelinesDetailApp = (mediator) => {
if (!document.querySelector(SELECTORS.PIPELINE_GRAPH)) {
return;
}
@@ -36,6 +37,9 @@ const createLegacyPipelinesDetailApp = mediator => {
mediator,
};
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('pipeline_details_bundle_legacy_details', `error: ${err}, info: ${info}`);
+ },
render(createElement) {
return createElement('pipeline-graph-legacy', {
props: {
@@ -47,15 +51,15 @@ const createLegacyPipelinesDetailApp = mediator => {
refreshPipelineGraph: this.requestRefreshPipelineGraph,
onResetDownstream: (parentPipeline, pipeline) =>
this.resetDownstreamPipelines(parentPipeline, pipeline),
- onClickUpstreamPipeline: pipeline => this.clickUpstreamPipeline(pipeline),
- onClickDownstreamPipeline: pipeline => this.clickDownstreamPipeline(pipeline),
+ onClickUpstreamPipeline: (pipeline) => this.clickUpstreamPipeline(pipeline),
+ onClickDownstreamPipeline: (pipeline) => this.clickDownstreamPipeline(pipeline),
},
});
},
});
};
-const createLegacyPipelineHeaderApp = mediator => {
+const createLegacyPipelineHeaderApp = (mediator) => {
if (!document.querySelector(SELECTORS.PIPELINE_HEADER)) {
return;
}
@@ -78,6 +82,9 @@ const createLegacyPipelineHeaderApp = mediator => {
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
@@ -125,7 +132,7 @@ const createTestDetails = () => {
});
};
-export default async function() {
+export default async function () {
createTestDetails();
createDagApp();
@@ -151,7 +158,7 @@ export default async function() {
);
const { pipelineProjectPath, pipelineIid } = dataset;
- createPipelinesDetailApp(SELECTORS.PIPELINE_DETAILS, pipelineProjectPath, pipelineIid);
+ createPipelinesDetailApp(SELECTORS.PIPELINE_GRAPH, pipelineProjectPath, pipelineIid);
} catch {
Flash(__('An error occurred while loading the pipeline.'));
}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_graph.js b/app/assets/javascripts/pipelines/pipeline_details_graph.js
index 1b296c305cb..2d46bb5ec26 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_graph.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_graph.js
@@ -3,6 +3,7 @@ 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 { reportToSentry } from './components/graph/utils';
Vue.use(VueApollo);
@@ -28,6 +29,9 @@ const createPipelinesDetailApp = (selector, pipelineProjectPath, pipelineIid) =>
pipelineIid,
dataMethod: GRAPHQL,
},
+ errorCaptured(err, _vm, info) {
+ reportToSentry('pipeline_details_graph', `error: ${err}, info: ${info}`);
+ },
render(createElement) {
return createElement(PipelineGraphWrapper);
},
diff --git a/app/assets/javascripts/pipelines/pipeline_details_header.js b/app/assets/javascripts/pipelines/pipeline_details_header.js
index 744a8272709..cba29acdb32 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_header.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_header.js
@@ -9,7 +9,7 @@ const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
-export const createPipelineHeaderApp = elSelector => {
+export const createPipelineHeaderApp = (elSelector) => {
const el = document.querySelector(elSelector);
if (!el) {
diff --git a/app/assets/javascripts/pipelines/pipeline_details_mediator.js b/app/assets/javascripts/pipelines/pipeline_details_mediator.js
index d487970aed7..74c5fc45644 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_mediator.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_mediator.js
@@ -55,7 +55,7 @@ export default class pipelinesMediator {
return this.service
.getPipeline()
- .then(response => this.successCallback(response))
+ .then((response) => this.successCallback(response))
.catch(() => this.errorCallback())
.finally(() =>
this.poll.restart(
diff --git a/app/assets/javascripts/pipelines/stores/pipeline_store.js b/app/assets/javascripts/pipelines/stores/pipeline_store.js
index c6f65277c8d..1f804a107a8 100644
--- a/app/assets/javascripts/pipelines/stores/pipeline_store.js
+++ b/app/assets/javascripts/pipelines/stores/pipeline_store.js
@@ -29,11 +29,11 @@ export default class PipelineStore {
}
if (pipelineCopy.triggered && pipelineCopy.triggered.length) {
- pipelineCopy.triggered.forEach(el => {
+ pipelineCopy.triggered.forEach((el) => {
const oldPipeline =
this.state.pipeline &&
this.state.pipeline.triggered &&
- this.state.pipeline.triggered.find(element => element.id === el.id);
+ this.state.pipeline.triggered.find((element) => element.id === el.id);
this.parseTriggeredPipelines(oldPipeline, el);
});
@@ -67,8 +67,8 @@ export default class PipelineStore {
}
if (newPipeline.triggered_by?.length > 0) {
- newPipeline.triggered_by.forEach(el => {
- const oldTriggeredBy = oldPipeline.triggered_by?.find(element => element.id === el.id);
+ newPipeline.triggered_by.forEach((el) => {
+ const oldTriggeredBy = oldPipeline.triggered_by?.find((element) => element.id === el.id);
this.parseTriggeredPipelines(oldTriggeredBy, el);
});
}
@@ -88,9 +88,9 @@ export default class PipelineStore {
Vue.set(newPipeline, 'isLoading', false);
if (newPipeline.triggered && newPipeline.triggered.length > 0) {
- newPipeline.triggered.forEach(el => {
+ newPipeline.triggered.forEach((el) => {
const oldTriggered =
- oldPipeline.triggered && oldPipeline.triggered.find(element => element.id === el.id);
+ oldPipeline.triggered && oldPipeline.triggered.find((element) => element.id === el.id);
this.parseTriggeredPipelines(oldTriggered, el);
});
}
@@ -102,7 +102,7 @@ export default class PipelineStore {
* @param {Object} pipeline
*/
resetTriggeredByPipeline(parentPipeline, pipeline) {
- parentPipeline.triggered_by.forEach(el => this.closePipeline(el));
+ parentPipeline.triggered_by.forEach((el) => this.closePipeline(el));
if (pipeline.triggered_by && pipeline.triggered_by) {
this.resetTriggeredByPipeline(pipeline, pipeline.triggered_by);
@@ -129,7 +129,7 @@ export default class PipelineStore {
this.closePipeline(pipeline);
if (pipeline.triggered_by && pipeline.triggered_by.length) {
- pipeline.triggered_by.forEach(triggeredBy => this.closeTriggeredByPipeline(triggeredBy));
+ pipeline.triggered_by.forEach((triggeredBy) => this.closeTriggeredByPipeline(triggeredBy));
}
}
@@ -139,10 +139,10 @@ export default class PipelineStore {
* @param {Object} pipeline
*/
resetTriggeredPipelines(parentPipeline, pipeline) {
- parentPipeline.triggered.forEach(el => this.closePipeline(el));
+ parentPipeline.triggered.forEach((el) => this.closePipeline(el));
if (pipeline.triggered && pipeline.triggered.length) {
- pipeline.triggered.forEach(el => this.resetTriggeredPipelines(pipeline, el));
+ pipeline.triggered.forEach((el) => this.resetTriggeredPipelines(pipeline, el));
}
}
@@ -165,7 +165,7 @@ export default class PipelineStore {
this.closePipeline(pipeline);
if (pipeline.triggered && pipeline.triggered.length) {
- pipeline.triggered.forEach(triggered => this.closeTriggeredPipeline(triggered));
+ pipeline.triggered.forEach((triggered) => this.closeTriggeredPipeline(triggered));
}
}
@@ -198,6 +198,9 @@ export default class PipelineStore {
}
removeExpandedPipelineToRequestData(id) {
- this.state.expandedPipelines.splice(this.state.expandedPipelines.findIndex(el => el === id), 1);
+ this.state.expandedPipelines.splice(
+ this.state.expandedPipelines.findIndex((el) => el === id),
+ 1,
+ );
}
}
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/getters.js b/app/assets/javascripts/pipelines/stores/test_reports/getters.js
index 56f769c00fa..c31e7dd114f 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/getters.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/getters.js
@@ -1,18 +1,18 @@
import { addIconStatus, formattedTime } from './utils';
-export const getTestSuites = state => {
+export const getTestSuites = (state) => {
const { test_suites: testSuites = [] } = state.testReports;
- return testSuites.map(suite => ({
+ return testSuites.map((suite) => ({
...suite,
formattedTime: formattedTime(suite.total_time),
}));
};
-export const getSelectedSuite = state =>
+export const getSelectedSuite = (state) =>
state.testReports?.test_suites?.[state.selectedSuiteIndex] || {};
-export const getSuiteTests = state => {
+export const getSuiteTests = (state) => {
const { test_cases: testCases = [] } = getSelectedSuite(state);
const { page, perPage } = state.pageInfo;
const start = (page - 1) * perPage;
@@ -20,4 +20,4 @@ export const getSuiteTests = state => {
return testCases.map(addIconStatus).slice(start, start + perPage);
};
-export const getSuiteTestCount = state => getSelectedSuite(state)?.test_cases?.length || 0;
+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 88f61b09025..204dfc2fb01 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/index.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/index.js
@@ -7,7 +7,7 @@ import mutations from './mutations';
Vue.use(Vuex);
-export default initialState =>
+export default (initialState) =>
new Vuex.Store({
actions,
getters,
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/utils.js b/app/assets/javascripts/pipelines/stores/test_reports/utils.js
index 42406e5a67a..5c1f27b166a 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/utils.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/utils.js
@@ -25,7 +25,7 @@ export const formattedTime = (seconds = 0) => {
return sprintf(__('%{seconds}s'), { seconds: seconds.toFixed(2) });
};
-export const addIconStatus = testCase => ({
+export const addIconStatus = (testCase) => ({
...testCase,
icon: iconForTestStatus(testCase.status),
formattedTime: formattedTime(testCase.execution_time),
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 28d6c0edb0f..50bb23b7e63 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -1,12 +1,11 @@
import { pickBy } from 'lodash';
import { SUPPORTED_FILTER_PARAMETERS } from './constants';
+import { createNodeDict } from './components/parsing_utils';
-export const validateParams = params => {
+export const validateParams = (params) => {
return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val);
};
-export const createUniqueLinkId = (stageName, jobName) => `${stageName}-${jobName}`;
-
/**
* This function takes the stages array and transform it
* into a hash where each key is a job name and the job data
@@ -15,19 +14,8 @@ export const createUniqueLinkId = (stageName, jobName) => `${stageName}-${jobNam
* @returns {Object} - Hash of jobs
*/
export const createJobsHash = (stages = []) => {
- const jobsHash = {};
-
- stages.forEach(stage => {
- if (stage.groups.length > 0) {
- stage.groups.forEach(group => {
- group.jobs.forEach(job => {
- jobsHash[job.name] = job;
- });
- });
- }
- });
-
- return jobsHash;
+ const nodes = stages.flatMap(({ groups }) => groups);
+ return createNodeDict(nodes);
};
/**
@@ -44,18 +32,26 @@ export const generateJobNeedsDict = (jobs = {}) => {
const arrOfJobNames = Object.keys(jobs);
return arrOfJobNames.reduce((acc, value) => {
- const recursiveNeeds = jobName => {
+ const recursiveNeeds = (jobName) => {
if (!jobs[jobName]?.needs) {
return [];
}
return jobs[jobName].needs
- .map(job => {
+ .map((job) => {
// If we already have the needs of a job in the accumulator,
// then we use the memoized data instead of the recursive call
// to save some performance.
const newNeeds = acc[job] ?? recursiveNeeds(job);
+ // In case it's a parallel job (size > 1), the name of the group
+ // and the job will be different. This mean we also need to add the group name
+ // 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, ...newNeeds];
})
.flat(Infinity);
diff --git a/app/assets/javascripts/popovers/components/popovers.vue b/app/assets/javascripts/popovers/components/popovers.vue
index 3bb6d284264..05a209a97ad 100644
--- a/app/assets/javascripts/popovers/components/popovers.vue
+++ b/app/assets/javascripts/popovers/components/popovers.vue
@@ -7,7 +7,7 @@
import { GlPopover } from '@gitlab/ui';
import { sanitize } from '~/lib/dompurify';
-const newPopover = element => {
+const newPopover = (element) => {
const { content, html, placement, title, triggers = 'focus' } = element.dataset;
return {
@@ -30,8 +30,8 @@ export default {
};
},
created() {
- this.observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
+ this.observer = new MutationObserver((mutations) => {
+ mutations.forEach((mutation) => {
mutation.removedNodes.forEach(this.dispose);
});
});
@@ -61,7 +61,7 @@ export default {
if (!target) {
this.popovers = [];
} else {
- const index = this.popovers.findIndex(popover => popover.target === target);
+ const index = this.popovers.findIndex((popover) => popover.target === target);
if (index > -1) {
this.popovers.splice(index, 1);
@@ -69,7 +69,7 @@ export default {
}
},
popoverExists(element) {
- return this.popovers.some(popover => popover.target === element);
+ return this.popovers.some((popover) => popover.target === element);
},
getSafeHtml(html) {
return sanitize(html);
diff --git a/app/assets/javascripts/popovers/index.js b/app/assets/javascripts/popovers/index.js
index bfb61f02a3a..eebbfbdcc68 100644
--- a/app/assets/javascripts/popovers/index.js
+++ b/app/assets/javascripts/popovers/index.js
@@ -32,10 +32,10 @@ const handlePopoverEvent = (rootTarget, e, selector) => {
};
export const initPopovers = () => {
- ['mouseenter', 'focus', 'click'].forEach(event => {
+ ['mouseenter', 'focus', 'click'].forEach((event) => {
document.addEventListener(
event,
- e => handlePopoverEvent(document, e, '[data-toggle="popover"]'),
+ (e) => handlePopoverEvent(document, e, '[data-toggle="popover"]'),
true,
);
});
@@ -43,7 +43,7 @@ export const initPopovers = () => {
return getPopoversApp();
};
-export const dispose = elements => toArray(elements).forEach(getPopoversApp().dispose);
+export const dispose = (elements) => toArray(elements).forEach(getPopoversApp().dispose);
export const destroy = () => {
getPopoversApp().$destroy();
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 5feac7485ad..869fdccc800 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -84,12 +84,12 @@ Please update your Git repository remotes as soon as possible.`),
return axios
.put(this.actionUrl, putData)
- .then(result => {
+ .then((result) => {
Flash(result.data.message, 'notice');
this.username = username;
this.isRequestPending = false;
})
- .catch(error => {
+ .catch((error) => {
Flash(error.response.data.message);
this.isRequestPending = false;
throw error;
diff --git a/app/assets/javascripts/profile/add_ssh_key_validation.js b/app/assets/javascripts/profile/add_ssh_key_validation.js
index ab6a6c1896c..5c78de7ffb0 100644
--- a/app/assets/javascripts/profile/add_ssh_key_validation.js
+++ b/app/assets/javascripts/profile/add_ssh_key_validation.js
@@ -12,7 +12,7 @@ export default class AddSshKeyValidation {
}
register() {
- this.form.addEventListener('submit', event => this.submit(event));
+ this.form.addEventListener('submit', (event) => this.submit(event));
this.confirmSubmitElement.addEventListener('click', () => {
this.isValid = true;
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index ecb69422287..afc78cbe78a 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -61,7 +61,7 @@ import { loadCSSFile } from '../lib/utils/css_utils';
bindEvents() {
const _this = this;
- this.fileInput.on('change', function(e) {
+ this.fileInput.on('change', function (e) {
_this.onFileInputChange(e, this);
this.value = null;
});
@@ -69,7 +69,7 @@ import { loadCSSFile } from '../lib/utils/css_utils';
this.modalCrop.on('shown.bs.modal', this.onModalShow);
this.modalCrop.on('hidden.bs.modal', this.onModalHide);
this.uploadImageBtn.on('click', this.onUploadImageBtnClick);
- this.cropActionsBtn.on('click', function() {
+ this.cropActionsBtn.on('click', function () {
const btn = this;
return _this.onActionBtnClick(btn);
});
@@ -184,8 +184,8 @@ import { loadCSSFile } from '../lib/utils/css_utils';
const cropModal = document.querySelector('.modal-profile-crop');
if (cropModal) loadCSSFile(cropModal.dataset.cropperCssPath);
- $.fn.glCrop = function(opts) {
- return this.each(function() {
+ $.fn.glCrop = function (opts) {
+ return this.each(function () {
return $(this).data('glcrop', new GitLabCrop(this, opts));
});
};
diff --git a/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js b/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
index bcca3140717..744e0174a4e 100644
--- a/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
+++ b/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
@@ -18,6 +18,6 @@ export default () => {
el,
name: 'ProfilePreferencesApp',
provide,
- render: createElement => createElement(ProfilePreferences),
+ render: (createElement) => createElement(ProfilePreferences),
});
};
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index 4755a4aa9ba..bfeeff47163 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -20,7 +20,7 @@ export default class Profile {
this.timezoneDropdown = new TimezoneDropdown({
$inputEl: this.$inputEl,
$dropdownEl: $('.js-timezone-dropdown'),
- displayFormat: selectedItem => formatTimezone(selectedItem),
+ displayFormat: (selectedItem) => formatTimezone(selectedItem),
});
}
@@ -33,15 +33,13 @@ export default class Profile {
uploadImageBtn: '.js-upload-user-avatar',
modalCropImg: '.modal-profile-crop-image',
};
- this.avatarGlCrop = $('.js-user-avatar-input')
- .glCrop(cropOpts)
- .data('glcrop');
+ this.avatarGlCrop = $('.js-user-avatar-input').glCrop(cropOpts).data('glcrop');
}
bindEvents() {
$('.js-preferences-form').on('change.preference', 'input[type=radio]', this.submitForm);
$('.js-group-notification-email').on('change', this.submitForm);
- $('#user_notification_email').on('select2-selecting', event => {
+ $('#user_notification_email').on('select2-selecting', (event) => {
setTimeout(this.submitForm.bind(event.currentTarget));
});
$('#user_notified_of_own_activity').on('change', this.submitForm);
@@ -91,7 +89,7 @@ export default class Profile {
// Enable submit button after requests ends
self.form.find(':input[disabled]').enable();
})
- .catch(error => flash(error.message));
+ .catch((error) => flash(error.message));
}
updateHeaderAvatar() {
diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js
index 0e12c219e45..ddb8956b664 100644
--- a/app/assets/javascripts/project_find_file.js
+++ b/app/assets/javascripts/project_find_file.js
@@ -10,7 +10,7 @@ import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
// highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
-const highlighter = function(element, text, matches) {
+const highlighter = function (element, text, matches) {
let j = 0;
let len = 0;
let lastIndex = 0;
@@ -57,7 +57,7 @@ export default class ProjectFindFile {
initEvent() {
// eslint-disable-next-line @gitlab/no-global-event-off
this.inputElement.off('keyup');
- this.inputElement.on('keyup', event => {
+ this.inputElement.on('keyup', (event) => {
const target = $(event.target);
const value = target.val();
const ref = target.data('oldValue');
@@ -65,11 +65,7 @@ export default class ProjectFindFile {
if (value !== oldValue) {
target.data('oldValue', value);
this.findFile();
- return this.element
- .find('tr.tree-item')
- .eq(0)
- .addClass('selected')
- .focus();
+ return this.element.find('tr.tree-item').eq(0).addClass('selected').focus();
}
});
}
@@ -90,11 +86,7 @@ export default class ProjectFindFile {
this.element.find('.loading').hide();
this.filePaths = data;
this.findFile();
- this.element
- .find('.files-slider tr.tree-item')
- .eq(0)
- .addClass('selected')
- .focus();
+ this.element.find('.files-slider tr.tree-item').eq(0).addClass('selected').focus();
})
.catch(() => flash(__('An error occurred while loading filenames')));
}
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index f7d823802b6..e68430d7dfd 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -9,7 +9,7 @@ import { loadCSSFile } from './lib/utils/css_utils';
const projectSelect = () => {
loadCSSFile(gon.select2_css_path)
.then(() => {
- $('.ajax-project-select').each(function(i, select) {
+ $('.ajax-project-select').each(function (i, select) {
let placeholder;
const simpleFilter = $(select).data('simpleFilter') || false;
const isInstantiated = $(select).data('select2');
@@ -33,17 +33,17 @@ const projectSelect = () => {
$(select).select2({
placeholder,
minimumInputLength: 0,
- query: query => {
+ query: (query) => {
let projectsCallback;
- const finalCallback = function(projects) {
+ const finalCallback = function (projects) {
const data = {
results: projects,
};
return query.callback(data);
};
if (this.includeGroups) {
- projectsCallback = function(projects) {
- const groupsCallback = function(groups) {
+ projectsCallback = function (projects) {
+ const groupsCallback = function (groups) {
const data = groups.concat(projects);
return finalCallback(data);
};
diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js
index 865dd23bd80..4b14df21f05 100644
--- a/app/assets/javascripts/project_select_combo_button.js
+++ b/app/assets/javascripts/project_select_combo_button.js
@@ -17,9 +17,9 @@ export default class ProjectSelectComboButton {
bindEvents() {
this.projectSelectInput
.siblings('.new-project-item-select-button')
- .on('click', e => this.openDropdown(e));
+ .on('click', (e) => this.openDropdown(e));
- this.newItemBtn.on('click', e => {
+ this.newItemBtn.on('click', (e) => {
if (!this.getProjectFromLocalStorage()) {
e.preventDefault();
this.openDropdown(e);
@@ -50,9 +50,7 @@ export default class ProjectSelectComboButton {
// eslint-disable-next-line promise/no-nesting
loadCSSFile(gon.select2_css_path)
.then(() => {
- $(event.currentTarget)
- .siblings('.project-item-select')
- .select2('open');
+ $(event.currentTarget).siblings('.project-item-select').select2('open');
})
.catch(() => {});
})
@@ -104,14 +102,8 @@ export default class ProjectSelectComboButton {
const defaultTextPrefix = this.resourceLabel;
// the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
- const localStorageItemType = `new-${this.resourceType
- .split('_')
- .join('-')
- .slice(0, -1)}`;
- const presetTextSuffix = this.resourceType
- .split('_')
- .join(' ')
- .slice(0, -1);
+ const localStorageItemType = `new-${this.resourceType.split('_').join('-').slice(0, -1)}`;
+ const presetTextSuffix = this.resourceType.split('_').join(' ').slice(0, -1);
return {
localStorageItemType, // new-issue / new-merge-request
diff --git a/app/assets/javascripts/project_visibility.js b/app/assets/javascripts/project_visibility.js
index aaf6723c85c..e3868e2925d 100644
--- a/app/assets/javascripts/project_visibility.js
+++ b/app/assets/javascripts/project_visibility.js
@@ -7,7 +7,7 @@ function setVisibilityOptions(namespaceSelector) {
const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex];
const { name, visibility, visibilityLevel, showPath, editPath } = selectedNamespace.dataset;
- document.querySelectorAll('.visibility-level-setting .form-check').forEach(option => {
+ document.querySelectorAll('.visibility-level-setting .form-check').forEach((option) => {
const optionInput = option.querySelector('input[type=radio]');
const optionValue = optionInput ? optionInput.value : 0;
const optionTitle = option.querySelector('.option-title');
diff --git a/app/assets/javascripts/projects/commit/components/branches_dropdown.vue b/app/assets/javascripts/projects/commit/components/branches_dropdown.vue
new file mode 100644
index 00000000000..3ecc3f1d1d3
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/branches_dropdown.vue
@@ -0,0 +1,94 @@
+<script>
+import {
+ GlDropdown,
+ GlSearchBoxByType,
+ GlDropdownItem,
+ GlDropdownText,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { I18N_DROPDOWN } from '../constants';
+
+export default {
+ name: 'BranchesDropdown',
+ components: {
+ GlDropdown,
+ GlSearchBoxByType,
+ GlDropdownItem,
+ GlDropdownText,
+ GlLoadingIcon,
+ },
+ props: {
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ i18n: I18N_DROPDOWN,
+ data() {
+ return {
+ searchTerm: this.value,
+ };
+ },
+ computed: {
+ ...mapGetters(['joinedBranches']),
+ ...mapState(['isFetching', 'branch', 'branches']),
+ filteredResults() {
+ const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
+ return this.joinedBranches.filter((resultString) =>
+ resultString.toLowerCase().includes(lowerCasedSearchTerm),
+ );
+ },
+ },
+ mounted() {
+ this.fetchBranches(this.searchTerm);
+ },
+ methods: {
+ ...mapActions(['fetchBranches']),
+ selectBranch(branch) {
+ this.$emit('selectBranch', branch);
+ this.searchTerm = branch; // enables isSelected to work as expected
+ },
+ isSelected(selectedBranch) {
+ return selectedBranch === this.branch;
+ },
+ searchTermChanged(value) {
+ this.searchTerm = value;
+ this.fetchBranches(value);
+ },
+ },
+};
+</script>
+<template>
+ <gl-dropdown :text="value" :header-text="$options.i18n.headerTitle">
+ <gl-search-box-by-type
+ :value="searchTerm"
+ trim
+ autocomplete="off"
+ :debounce="250"
+ :placeholder="$options.i18n.searchPlaceholder"
+ @input="searchTermChanged"
+ />
+ <gl-dropdown-item
+ v-for="branch in filteredResults"
+ v-show="!isFetching"
+ :key="branch"
+ :name="branch"
+ :is-checked="isSelected(branch)"
+ is-check-item
+ @click="selectBranch(branch)"
+ >
+ {{ branch }}
+ </gl-dropdown-item>
+ <gl-dropdown-text v-show="isFetching" data-testid="dropdown-text-loading-icon">
+ <gl-loading-icon class="gl-mx-auto" />
+ </gl-dropdown-text>
+ <gl-dropdown-text
+ v-if="!filteredResults.length && !isFetching"
+ data-testid="empty-result-message"
+ >
+ <span class="gl-text-gray-500">{{ $options.i18n.noResultsMessage }}</span>
+ </gl-dropdown-text>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue
new file mode 100644
index 00000000000..6411b1ca921
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/form_modal.vue
@@ -0,0 +1,137 @@
+<script>
+import { GlModal, GlForm, GlFormCheckbox, GlSprintf, GlFormGroup } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
+import eventHub from '../event_hub';
+import csrf from '~/lib/utils/csrf';
+import BranchesDropdown from './branches_dropdown.vue';
+
+export default {
+ components: {
+ BranchesDropdown,
+ GlModal,
+ GlForm,
+ GlFormCheckbox,
+ GlSprintf,
+ GlFormGroup,
+ },
+ inject: {
+ prependedText: {
+ default: '',
+ },
+ },
+ props: {
+ i18n: {
+ type: Object,
+ required: true,
+ },
+ openModal: {
+ type: String,
+ required: true,
+ },
+ modalId: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ checked: true,
+ actionPrimary: {
+ text: this.i18n.actionPrimaryText,
+ attributes: [
+ { variant: 'success' },
+ { category: 'primary' },
+ { 'data-testid': 'submit-commit' },
+ ],
+ },
+ actionCancel: {
+ text: this.i18n.actionCancelText,
+ attributes: [{ 'data-testid': 'cancel-commit' }],
+ },
+ };
+ },
+ computed: {
+ ...mapState([
+ 'branch',
+ 'endpoint',
+ 'pushCode',
+ 'branchCollaboration',
+ 'modalTitle',
+ 'existingBranch',
+ 'prependedText',
+ ]),
+ },
+ mounted() {
+ eventHub.$on(this.openModal, this.show);
+ },
+ methods: {
+ ...mapActions(['clearModal', 'setBranch', 'setSelectedBranch']),
+ show() {
+ this.$root.$emit('bv::show::modal', this.modalId);
+ },
+ handlePrimary() {
+ this.$refs.form.$el.submit();
+ },
+ resetModalHandler() {
+ this.clearModal();
+ this.setSelectedBranch('');
+ this.checked = true;
+ },
+ },
+ csrf,
+};
+</script>
+<template>
+ <gl-modal
+ v-bind="$attrs"
+ data-testid="modal-commit"
+ :modal-id="modalId"
+ size="sm"
+ :title="modalTitle"
+ :action-cancel="actionCancel"
+ :action-primary="actionPrimary"
+ @hidden="resetModalHandler"
+ @primary="handlePrimary"
+ >
+ <p v-if="prependedText.length" data-testid="prepended-text">
+ <gl-sprintf :message="prependedText" />
+ </p>
+
+ <gl-form ref="form" :action="endpoint" method="post">
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+
+ <gl-form-group
+ :label="i18n.branchLabel"
+ label-for="start_branch"
+ data-testid="dropdown-group"
+ >
+ <input id="start_branch" type="hidden" name="start_branch" :value="branch" />
+
+ <branches-dropdown class="gl-w-half" :value="branch" @selectBranch="setBranch" />
+ </gl-form-group>
+
+ <gl-form-checkbox
+ v-if="pushCode"
+ v-model="checked"
+ name="create_merge_request"
+ class="gl-mt-3"
+ >
+ <gl-sprintf :message="i18n.startMergeRequest">
+ <template #newMergeRequest>
+ <strong>{{ i18n.newMergeRequest }}</strong>
+ </template>
+ </gl-sprintf>
+ </gl-form-checkbox>
+ <input v-else type="hidden" name="create_merge_request" value="1" />
+ </gl-form>
+
+ <p v-if="!pushCode" class="gl-mb-0 gl-mt-5" data-testid="appended-text">
+ <gl-sprintf v-if="branchCollaboration" :message="i18n.existingBranch">
+ <template #branchName>
+ <strong>{{ existingBranch }}</strong>
+ </template>
+ </gl-sprintf>
+ <gl-sprintf v-else :message="i18n.branchInFork" />
+ </p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/projects/commit/components/form_trigger.vue b/app/assets/javascripts/projects/commit/components/form_trigger.vue
new file mode 100644
index 00000000000..e92854c1ac3
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/form_trigger.vue
@@ -0,0 +1,32 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import eventHub from '../event_hub';
+
+export default {
+ components: {
+ GlLink,
+ },
+ inject: {
+ displayText: {
+ default: '',
+ },
+ },
+ props: {
+ openModal: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ showModal() {
+ eventHub.$emit(this.openModal);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-link data-is-link="true" data-testid="revert-commit-link" @click="showModal">
+ {{ displayText }}
+ </gl-link>
+</template>
diff --git a/app/assets/javascripts/projects/commit/constants.js b/app/assets/javascripts/projects/commit/constants.js
new file mode 100644
index 00000000000..233f43d56b9
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/constants.js
@@ -0,0 +1,33 @@
+import { s__, __ } from '~/locale';
+
+export const OPEN_REVERT_MODAL = 'openRevertModal';
+export const REVERT_MODAL_ID = 'revert-commit-modal';
+
+export const I18N_MODAL = {
+ startMergeRequest: s__('ChangeTypeAction|Start a %{newMergeRequest} with these changes'),
+ existingBranch: s__(
+ 'ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open.',
+ ),
+ branchInFork: s__(
+ 'ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started.',
+ ),
+ newMergeRequest: __('new merge request'),
+ actionCancelText: __('Cancel'),
+};
+
+export const I18N_REVERT_MODAL = {
+ branchLabel: s__('ChangeTypeAction|Revert in branch'),
+ actionPrimaryText: s__('ChangeTypeAction|Revert'),
+};
+
+export const PREPENDED_MODAL_TEXT = s__(
+ 'ChangeTypeAction|This will create a new commit in order to revert the existing changes.',
+);
+
+export const I18N_DROPDOWN = {
+ noResultsMessage: __('No matching results'),
+ headerTitle: s__('ChangeTypeAction|Switch branch'),
+ searchPlaceholder: s__('ChangeTypeAction|Search branches'),
+};
+
+export const PROJECT_BRANCHES_ERROR = __('Something went wrong while fetching branches');
diff --git a/app/assets/javascripts/projects/commit/event_hub.js b/app/assets/javascripts/projects/commit/event_hub.js
new file mode 100644
index 00000000000..e31806ad199
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/event_hub.js
@@ -0,0 +1,3 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_modal.js b/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
new file mode 100644
index 00000000000..ec0600cd25a
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
@@ -0,0 +1,55 @@
+import Vue from 'vue';
+import CommitFormModal from './components/form_modal.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import createStore from './store';
+import {
+ I18N_MODAL,
+ I18N_REVERT_MODAL,
+ PREPENDED_MODAL_TEXT,
+ OPEN_REVERT_MODAL,
+ REVERT_MODAL_ID,
+} from './constants';
+
+export default function initInviteMembersModal() {
+ const el = document.querySelector('.js-revert-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,
+ provide: {
+ prependedText: PREPENDED_MODAL_TEXT,
+ },
+ render: (createElement) =>
+ createElement(CommitFormModal, {
+ props: {
+ i18n: { ...I18N_REVERT_MODAL, ...I18N_MODAL },
+ openModal: OPEN_REVERT_MODAL,
+ modalId: REVERT_MODAL_ID,
+ },
+ }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js b/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
new file mode 100644
index 00000000000..0bb57f22663
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
@@ -0,0 +1,20 @@
+import Vue from 'vue';
+import RevertCommitTrigger from './components/form_trigger.vue';
+import { OPEN_REVERT_MODAL } from './constants';
+
+export default function initInviteMembersTrigger() {
+ const el = document.querySelector('.js-revert-commit-trigger');
+
+ if (!el) {
+ return false;
+ }
+
+ const { displayText } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: { displayText },
+ render: (createElement) =>
+ createElement(RevertCommitTrigger, { 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
new file mode 100644
index 00000000000..2ae0370d579
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/store/actions.js
@@ -0,0 +1,36 @@
+import * as types from './mutation_types';
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import { PROJECT_BRANCHES_ERROR } from '../constants';
+
+export const clearModal = ({ commit }) => {
+ commit(types.CLEAR_MODAL);
+};
+
+export const requestBranches = ({ commit }) => {
+ commit(types.REQUEST_BRANCHES);
+};
+
+export const fetchBranches = ({ commit, dispatch, state }, query) => {
+ dispatch('requestBranches');
+
+ return axios
+ .get(state.branchesEndpoint, {
+ params: { search: query },
+ })
+ .then((res) => {
+ commit(types.RECEIVE_BRANCHES_SUCCESS, res.data);
+ })
+ .catch(() => {
+ createFlash({ message: PROJECT_BRANCHES_ERROR });
+ });
+};
+
+export const setBranch = ({ commit, dispatch }, branch) => {
+ commit(types.SET_BRANCH, branch);
+ dispatch('setSelectedBranch', branch);
+};
+
+export const setSelectedBranch = ({ commit }, branch) => {
+ commit(types.SET_SELECTED_BRANCH, branch);
+};
diff --git a/app/assets/javascripts/projects/commit/store/getters.js b/app/assets/javascripts/projects/commit/store/getters.js
new file mode 100644
index 00000000000..664eaca32cf
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/store/getters.js
@@ -0,0 +1,5 @@
+import { uniq } from 'lodash';
+
+export const joinedBranches = (state) => {
+ return uniq(state.branches).sort();
+};
diff --git a/app/assets/javascripts/projects/commit/store/index.js b/app/assets/javascripts/projects/commit/store/index.js
new file mode 100644
index 00000000000..83802f6a36f
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/store/index.js
@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
+
+Vue.use(Vuex);
+
+export default (initialState = {}) =>
+ new Vuex.Store({
+ actions,
+ mutations,
+ getters,
+ state: {
+ ...state(),
+ ...initialState,
+ },
+ });
diff --git a/app/assets/javascripts/projects/commit/store/mutation_types.js b/app/assets/javascripts/projects/commit/store/mutation_types.js
new file mode 100644
index 00000000000..de0bb47e18d
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/store/mutation_types.js
@@ -0,0 +1,6 @@
+export const CLEAR_MODAL = 'CLEAR_MODAL';
+
+export const REQUEST_BRANCHES = 'REQUEST_BRANCHES';
+export const RECEIVE_BRANCHES_SUCCESS = 'RECEIVE_BRANCHES_SUCCESS';
+export const SET_BRANCH = 'SET_BRANCH';
+export const SET_SELECTED_BRANCH = 'SET_SELECTED_BRANCH';
diff --git a/app/assets/javascripts/projects/commit/store/mutations.js b/app/assets/javascripts/projects/commit/store/mutations.js
new file mode 100644
index 00000000000..6add00deadb
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/store/mutations.js
@@ -0,0 +1,25 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.REQUEST_BRANCHES](state) {
+ state.isFetching = true;
+ },
+
+ [types.RECEIVE_BRANCHES_SUCCESS](state, branches) {
+ state.isFetching = false;
+ state.branches = branches;
+ state.branches.unshift(state.branch);
+ },
+
+ [types.CLEAR_MODAL](state) {
+ state.branch = state.defaultBranch;
+ },
+
+ [types.SET_BRANCH](state, branch) {
+ state.branch = branch;
+ },
+
+ [types.SET_SELECTED_BRANCH](state, branch) {
+ state.selectedBranch = branch;
+ },
+};
diff --git a/app/assets/javascripts/projects/commit/store/state.js b/app/assets/javascripts/projects/commit/store/state.js
new file mode 100644
index 00000000000..78c294324df
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/store/state.js
@@ -0,0 +1,13 @@
+export default () => ({
+ endpoint: null,
+ branchesEndpoint: null,
+ isFetching: false,
+ branches: [],
+ selectedBranch: '',
+ pushCode: false,
+ branchCollaboration: false,
+ modalTitle: '',
+ existingBranch: '',
+ defaultBranch: '',
+ branch: '',
+});
diff --git a/app/assets/javascripts/projects/commit_box/info/init_details_button.js b/app/assets/javascripts/projects/commit_box/info/init_details_button.js
index 032fbf5316a..833e946af5c 100644
--- a/app/assets/javascripts/projects/commit_box/info/init_details_button.js
+++ b/app/assets/javascripts/projects/commit_box/info/init_details_button.js
@@ -3,9 +3,7 @@ import $ from 'jquery';
export const initDetailsButton = () => {
$('body').on('click', '.js-details-expand', function expand(e) {
e.preventDefault();
- $(this)
- .next('.js-details-content')
- .removeClass('hide');
+ $(this).next('.js-details-content').removeClass('hide');
$(this).hide();
});
};
diff --git a/app/assets/javascripts/projects/commit_box/info/load_branches.js b/app/assets/javascripts/projects/commit_box/info/load_branches.js
index 0efa1998507..8a0b2c30abe 100644
--- a/app/assets/javascripts/projects/commit_box/info/load_branches.js
+++ b/app/assets/javascripts/projects/commit_box/info/load_branches.js
@@ -2,7 +2,7 @@ import axios from 'axios';
import { sanitize } from '~/lib/dompurify';
import { __ } from '~/locale';
-export const loadBranches = containerEl => {
+export const loadBranches = (containerEl) => {
if (!containerEl) {
return;
}
diff --git a/app/assets/javascripts/projects/commits/components/author_select.vue b/app/assets/javascripts/projects/commits/components/author_select.vue
index 3bc772fe60a..752bb594794 100644
--- a/app/assets/javascripts/projects/commits/components/author_select.vue
+++ b/app/assets/javascripts/projects/commits/components/author_select.vue
@@ -69,7 +69,7 @@ export default {
commitsSearchInput.addEventListener(
'keyup',
- debounce(event => this.setSearchParam(event.target.value), 500), // keyup & time is to match effect of "filter by commit message"
+ debounce((event) => this.setSearchParam(event.target.value), 500), // keyup & time is to match effect of "filter by commit message"
);
},
methods: {
diff --git a/app/assets/javascripts/projects/commits/index.js b/app/assets/javascripts/projects/commits/index.js
index 6f85432a77e..03b94fde0f3 100644
--- a/app/assets/javascripts/projects/commits/index.js
+++ b/app/assets/javascripts/projects/commits/index.js
@@ -5,7 +5,7 @@ import store from './store';
Vue.use(Vuex);
-export default el => {
+export default (el) => {
if (!el) {
return null;
}
diff --git a/app/assets/javascripts/projects/commits/store/actions.js b/app/assets/javascripts/projects/commits/store/actions.js
index 157e2409f7f..359d81f32f7 100644
--- a/app/assets/javascripts/projects/commits/store/actions.js
+++ b/app/assets/javascripts/projects/commits/store/actions.js
@@ -26,7 +26,7 @@ export default {
},
})
.then(({ data }) => dispatch('receiveAuthorsSuccess', data))
- .catch(error => {
+ .catch((error) => {
Sentry.captureException(error);
dispatch('receiveAuthorsError');
});
diff --git a/app/assets/javascripts/projects/default_project_templates.js b/app/assets/javascripts/projects/default_project_templates.js
index bc3b29cde0a..2da9449d24e 100644
--- a/app/assets/javascripts/projects/default_project_templates.js
+++ b/app/assets/javascripts/projects/default_project_templates.js
@@ -97,4 +97,8 @@ export default {
text: s__('ProjectTemplates|GitLab Cluster Management'),
icon: '.template-option .icon-cluster_management',
},
+ kotlin_native_linux: {
+ text: s__('ProjectTemplates|Kotlin Native for Linux'),
+ icon: '.template-option .icon-gitlab_logo',
+ },
};
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 2e16071e563..b54f7051806 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,6 +1,6 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlBreadcrumb, GlIcon } from '@gitlab/ui';
+import { GlBreadcrumb, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import WelcomePage from './welcome.vue';
import LegacyContainer from './legacy_container.vue';
import { __, s__ } from '~/locale';
@@ -57,7 +57,9 @@ export default {
WelcomePage,
LegacyContainer,
},
-
+ directives: {
+ SafeHtml,
+ },
props: {
hasErrors: {
type: Boolean,
@@ -69,6 +71,11 @@ export default {
required: false,
default: false,
},
+ newProjectGuidelines: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
@@ -83,11 +90,11 @@ export default {
return PANELS;
}
- return PANELS.filter(p => p.name !== CI_CD_PANEL);
+ return PANELS.filter((p) => p.name !== CI_CD_PANEL);
},
activePanel() {
- return PANELS.find(p => p.name === this.activeTab);
+ return PANELS.find((p) => p.name === this.activeTab);
},
breadcrumbs() {
@@ -113,7 +120,7 @@ export default {
this.handleLocationHashChange();
this.resetProjectErrors();
});
- this.$root.$on('clicked::link', e => {
+ this.$root.$on('clicked::link', (e) => {
window.location = e.target.href;
});
},
@@ -142,9 +149,14 @@ export default {
<welcome-page v-if="activeTab === null" :panels="availablePanels" />
<div v-else class="row">
<div class="col-lg-3">
- <div class="text-center" v-html="activePanel.illustration"></div>
+ <div class="gl-text-white" v-html="activePanel.illustration"></div>
<h4>{{ activePanel.title }}</h4>
<p>{{ activePanel.description }}</p>
+ <div
+ v-if="newProjectGuidelines"
+ id="new-project-guideline"
+ v-safe-html="newProjectGuidelines"
+ ></div>
</div>
<div class="col-lg-9">
<gl-breadcrumb v-if="breadcrumbs" :items="breadcrumbs">
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
index 022328cd8a2..63a65975fff 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
@@ -37,7 +37,7 @@ export default {
class="blank-state blank-state-link experiment-new-project-page-blank-state"
@click="track('click_tab', { label: panel.name })"
>
- <div class="blank-state-icon" v-html="panel.illustration"></div>
+ <div class="blank-state-icon gl-text-white" v-html="panel.illustration"></div>
<div class="blank-state-body gl-pl-4!">
<h3 class="blank-state-title experiment-new-project-page-blank-state-title">
{{ panel.title }}
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/blank-project.svg b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/blank-project.svg
index 0d8021658d1..f73ae70dba8 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/blank-project.svg
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/blank-project.svg
@@ -1,27 +1,9 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="215px" height="115px" viewBox="0 0 215 115" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
- <title>create-new-project-md</title>
- <desc>Created with Sketch.</desc>
- <g id="create-new-project-md" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Group-3" transform="translate(71.000000, 18.000000)" fill-rule="nonzero">
- <g id="New-Blank1">
- <path d="M6.11141667,3.90697674 L62.6947849,3.90697674 C65.9485064,3.90697674 68.5891473,6.56494969 68.5891473,9.8400273 L68.5891473,78.0669494 C68.5891473,81.342027 65.9485064,84 62.6947849,84 L6.11141667,84 C2.85769514,84 0.217054264,81.342027 0.217054264,78.0669494 L0.217054264,9.8400273 C0.217054264,6.56494969 2.85769514,3.90697674 6.11141667,3.90697674 Z" id="Path" fill="#F9F9F9"></path>
- <path d="M8.89436241,1 L65.4777306,1 C68.7314521,1 71.372093,3.65598929 71.372093,6.9286227 L71.372093,74.5132378 C71.372093,77.7858712 68.7314521,80.4418605 65.4777306,80.4418605 L8.89436241,80.4418605 C5.64064088,80.4418605 3,77.7858712 3,74.5132378 L3,6.9286227 C3.00209243,3.65598929 5.64064088,1 8.89436241,1 Z" id="Path" fill="#FFFFFF"></path>
- <path d="M9.2677971,2.35980136 C6.65357171,2.35980136 4.53489427,4.47043114 4.53489427,7.07940407 L4.53489427,74.3201325 C4.53489427,76.9270116 6.65147193,79.0397352 9.2677971,79.0397352 L66.0500324,79.0397352 C68.6642577,79.0397352 70.7829352,76.9291055 70.7829352,74.3201325 L70.7829352,7.07731019 C70.7829352,4.47043114 68.6663575,2.35770748 66.0500324,2.35770748 L9.2677971,2.35980136 L9.2677971,2.35980136 Z M9.2677971,0 L66.0500324,0 C69.9724203,0 73.1472868,3.16803856 73.1472868,7.07731019 L73.1472868,74.3180386 C73.1472868,78.2294042 69.9703205,81.3953488 66.0500324,81.3953488 L9.2677971,81.3953488 C5.34540913,81.3953488 2.17054264,78.2273103 2.17054264,74.3180386 L2.17054264,7.07731019 C2.17054264,3.17222631 5.34750891,0 9.2677971,0 Z" id="Shape" fill="#EEEEEE"></path>
- <path d="M21.6234891,28.6511628 L28.9501543,28.6511628 C29.6221266,28.6511628 30.1705426,29.2387129 30.1705426,29.9534884 C30.1705426,30.6682639 29.6199589,31.255814 28.9501543,31.255814 L21.6234891,31.255814 C20.9515168,31.255814 20.4031008,30.6682639 20.4031008,29.9534884 C20.4031008,29.2387129 20.9515168,28.6511628 21.6234891,28.6511628 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M33.9142229,35.8139535 L36.1943042,35.8139535 C36.8214783,35.8139535 37.3333333,36.4015036 37.3333333,37.1162791 C37.3333333,37.8333678 36.8194552,38.4186047 36.1943042,38.4186047 L33.9142229,38.4186047 C33.2870488,38.4186047 32.7751938,37.8310546 32.7751938,37.1162791 C32.7751938,36.4015036 33.2890719,35.8139535 33.9142229,35.8139535 Z" id="Path" fill="#FC6D26"></path>
- <path d="M24.200844,42.9767442 L28.9774506,42.9767442 C29.6343929,42.9767442 30.1705426,43.5642943 30.1705426,44.2790698 C30.1705426,44.9961585 29.6322737,45.5813953 28.9774506,45.5813953 L24.200844,45.5813953 C23.5439017,45.5813953 23.0077519,44.9938453 23.0077519,44.2790698 C23.0077519,43.5642943 23.5439017,42.9767442 24.200844,42.9767442 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M41.0770181,35.8139535 L43.3570964,35.8139535 C43.9842697,35.8139535 44.496124,36.4015036 44.496124,37.1162791 C44.496124,37.8333678 43.9822466,38.4186047 43.3570964,38.4186047 L41.0770181,38.4186047 C40.4498448,38.4186047 39.9379845,37.8310546 39.9379845,37.1162791 C39.9359673,36.4015036 40.4498448,35.8139535 41.0770181,35.8139535 Z" id="Path" fill="#FC6D26"></path>
- <path d="M33.9372473,28.6511628 L47.89221,28.6511628 C48.5320619,28.6511628 49.0542636,29.2387129 49.0542636,29.9534884 C49.0542636,30.6682639 48.5299978,31.255814 47.89221,31.255814 L33.9372473,31.255814 C33.2973955,31.255814 32.7751938,30.6682639 32.7751938,29.9534884 C32.7751938,29.2387129 33.2994595,28.6511628 33.9372473,28.6511628 Z" id="Path" fill="#C3B8E3"></path>
- <path d="M33.9142229,42.9767442 L36.1943042,42.9767442 C36.8214783,42.9767442 37.3333333,43.5642943 37.3333333,44.2790698 C37.3333333,44.9961585 36.8194552,45.5813953 36.1943042,45.5813953 L33.9142229,45.5813953 C33.2870488,45.5813953 32.7751938,44.9938453 32.7751938,44.2790698 C32.7751938,43.5642943 33.2890719,42.9767442 33.9142229,42.9767442 Z" id="Path" fill="#6B4FBB"></path>
- <g id="Group" transform="translate(16.000000, 19.000000)">
- <circle id="Oval" fill="#FFFFFF" cx="20.8396947" cy="20.8396947" r="20.7533889"></circle>
- <path d="M20.8396947,41.5930835 C9.3778626,41.5930835 0.0863058062,32.3015267 0.0863058062,20.8396947 C0.0863058062,9.3778626 9.3778626,0.0863058062 20.8396947,0.0863058062 C32.3015267,0.0863058062 41.5930835,9.3778626 41.5930835,20.8396947 C41.5930835,32.3015267 32.3015267,41.5930835 20.8396947,41.5930835 Z M20.8396947,39.2207263 C30.9922045,39.2207263 39.2207263,30.9900995 39.2207263,20.8396947 C39.2207263,10.6892898 30.9900995,2.45866297 20.8396947,2.45866297 C10.6892898,2.45866297 2.45866297,10.6892898 2.45866297,20.8396947 C2.45866297,30.9900995 10.6871848,39.2207263 20.8396947,39.2207263 Z" id="Shape" fill="#EEEEEE"></path>
- <path d="M13.7647236,19.060953 L27.9967615,19.060953 C28.6493176,19.060953 29.1818876,19.595628 29.1818876,20.2460791 C29.1818876,20.8986352 28.6472126,21.4312052 27.9967615,21.4312052 L13.7647236,21.4312052 C13.1121675,21.4312052 12.5795975,20.8965302 12.5795975,20.2460791 C12.5795975,19.593523 13.1142725,19.060953 13.7647236,19.060953 Z" id="Path" fill="#6B4FBB"></path>
- <path d="M22.0669211,13.1311127 L22.0669211,27.3631506 C22.0669211,28.0157067 21.5322461,28.5482767 20.881795,28.5482767 C20.231344,28.5482767 19.696669,28.0136017 19.696669,27.3631506 L19.696669,13.1311127 C19.696669,12.4785566 20.231344,11.9459866 20.881795,11.9459866 C21.5322461,11.9459866 22.0669211,12.4785566 22.0669211,13.1311127 Z" id="Path" fill="#6B4FBB"></path>
- </g>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
+<svg width="82" height="80" viewBox="0 0 82 80" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M66.1912 8.19118H77.6176C78.2755 8.19118 78.8088 8.72448 78.8088 9.38235V69.6176C78.8088 70.2755 78.2755 70.8088 77.6176 70.8088H66.1912V8.19118Z" fill="#F0F0F0" stroke="#DBDBDB" stroke-width="2.38235"/>
+<path d="M22.0517 19.2723L22.0094 10.1001C22.004 8.92546 22.8555 7.92221 24.0153 7.73664L63.3613 1.44139C64.8087 1.2098 66.12 2.32794 66.12 3.79382V75.8717C66.12 77.3323 64.8177 78.449 63.3742 78.2262L24.3037 72.1952C23.1461 72.0165 22.2902 71.023 22.2848 69.8517L22.2428 60.7554" stroke="#DBDBDB" stroke-width="2.38235"/>
+<circle cx="23" cy="40" r="21" stroke="#6E49CB" stroke-width="2.38235"/>
+<circle cx="23" cy="40" r="17" fill="#6E49CB"/>
+<circle cx="23" cy="40" r="17" fill="white" fill-opacity="0.9"/>
+<path d="M22.3125 48V33.3659" stroke="#6E49CB" stroke-width="2.38235" stroke-linecap="round"/>
+<path d="M15 40.3049H30" stroke="#6E49CB" stroke-width="2.38235" stroke-linecap="round"/>
+</svg>
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/ci-cd-project.svg b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/ci-cd-project.svg
index c85e1a245b8..8d6cf58f196 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/ci-cd-project.svg
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/ci-cd-project.svg
@@ -1,73 +1,23 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="215px" height="115px" viewBox="0 0 215 115" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
- <title>run-CICD-pipelines-md</title>
- <desc>Created with Sketch.</desc>
- <g id="run-CICD-pipelines-md" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="CICD-Repoj1" transform="translate(22.000000, 16.000000)">
- <g id="Group" transform="translate(100.000000, 0.000000)">
- <path d="M5.88230137,4.144 L61.8884384,4.144 C65.1195616,4.144 67.7155068,6.804 67.7155068,10.052 L67.7155068,78.064 C67.7155068,81.34 65.0919452,83.972 61.8884384,83.972 L5.88230137,83.972 C2.65117808,83.972 0.0552328767,81.312 0.0552328767,78.064 L0.0552328767,10.052 C0.0552328767,6.804 2.67879452,4.144 5.88230137,4.144 Z" id="Path" fill="#F9F9F9" fill-rule="nonzero"></path>
- <path d="M8.80964384,1.176 L64.8157808,1.176 C68.0469041,1.176 70.6428493,3.836 70.6428493,7.084 L70.6428493,74.508 C70.6428493,77.784 68.0192877,80.416 64.8157808,80.416 L8.80964384,80.416 C5.57852055,80.416 2.98257534,77.756 2.98257534,74.508 L2.98257534,7.112 C2.98257534,3.836 5.57852055,1.176 8.80964384,1.176 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
- <path d="M8.80964384,2.38 C6.24131507,2.38 4.14246575,4.508 4.14246575,7.112 L4.14246575,74.536 C4.14246575,77.14 6.24131507,79.268 8.80964384,79.268 L64.8157808,79.268 C67.3841096,79.268 69.4829589,77.14 69.4829589,74.536 L69.4829589,7.112 C69.4829589,4.508 67.3841096,2.38 64.8157808,2.38 L8.80964384,2.38 L8.80964384,2.38 Z M8.80964384,0 L64.8157808,0 C68.6820822,0 71.8027397,3.164 71.8027397,7.084 L71.8027397,74.508 C71.8027397,78.428 68.6820822,81.592 64.8157808,81.592 L8.80964384,81.592 C4.94334247,81.592 1.82250462,78.4 1.82250462,74.508 L1.82250462,7.112 C1.79506849,3.192 4.94334247,0 8.80964384,0 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M14.6367123,14.784 L21.6236712,14.784 C22.2588493,14.784 22.7835616,15.316 22.7835616,15.96 C22.7835616,16.604 22.2588493,17.136 21.6236712,17.136 L14.6367123,17.136 C14.0015342,17.136 13.4768219,16.604 13.4768219,15.96 C13.4768219,15.316 14.0015342,14.784 14.6367123,14.784 Z M33.3054247,21.896 L40.2923836,21.896 C40.9275616,21.896 41.452274,22.428 41.452274,23.072 C41.452274,23.716 40.9275616,24.248 40.2923836,24.248 L33.3054247,24.248 C32.6702466,24.248 32.1455342,23.716 32.1455342,23.072 C32.1455342,22.428 32.6702466,21.896 33.3054247,21.896 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M40.32,14.784 L47.3069589,14.784 C47.942137,14.784 48.4668493,15.316 48.4668493,15.96 C48.4668493,16.604 47.942137,17.136 47.3069589,17.136 L40.32,17.136 C39.6848219,17.136 39.1601096,16.604 39.1601096,15.96 C39.1324932,15.316 39.6572055,14.784 40.32,14.784 Z" id="Path" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M21.6512877,28.98 L28.6382466,28.98 C29.2734247,28.98 29.798137,29.512 29.798137,30.156 C29.798137,30.8 29.2734247,31.332 28.6382466,31.332 L21.6512877,31.332 C21.0161096,31.332 20.4913973,30.8 20.4913973,30.156 C20.4637808,29.512 20.9884932,28.98 21.6512877,28.98 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M26.2908493,14.784 L28.6382466,14.784 C29.2734247,14.784 29.798137,15.316 29.798137,15.96 C29.798137,16.604 29.2734247,17.136 28.6382466,17.136 L26.2908493,17.136 C25.6556712,17.136 25.1309589,16.604 25.1309589,15.96 C25.1309589,15.316 25.6556712,14.784 26.2908493,14.784 Z" id="Path" fill="#FEE1D3" fill-rule="nonzero"></path>
- <path d="M33.3054247,36.092 L35.6528219,36.092 C36.288,36.092 36.8127123,36.624 36.8127123,37.268 C36.8127123,37.912 36.288,38.444 35.6528219,38.444 L33.3054247,38.444 C32.6702466,38.444 32.1455342,37.912 32.1455342,37.268 C32.1455342,36.624 32.6702466,36.092 33.3054247,36.092 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M44.9595616,21.896 L47.3069589,21.896 C47.942137,21.896 48.4668493,22.428 48.4668493,23.072 C48.4668493,23.716 47.942137,24.248 47.3069589,24.248 L44.9595616,24.248 C44.3243836,24.248 43.7996712,23.716 43.7996712,23.072 C43.7996712,22.428 44.3243836,21.896 44.9595616,21.896 Z M51.974137,14.784 L54.3215342,14.784 C54.9567123,14.784 55.4814247,15.316 55.4814247,15.96 C55.4814247,16.604 54.9567123,17.136 54.3215342,17.136 L51.974137,17.136 C51.3389589,17.136 50.8142466,16.604 50.8142466,15.96 C50.8142466,15.316 51.3389589,14.784 51.974137,14.784 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M23.9710685,43.176 L28.6382466,43.176 C29.2734247,43.176 29.798137,43.708 29.798137,44.352 C29.798137,44.996 29.2734247,45.528 28.6382466,45.528 L23.9710685,45.528 C23.3358904,45.528 22.8111781,44.996 22.8111781,44.352 C22.8111781,43.708 23.3358904,43.176 23.9710685,43.176 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M40.32,36.092 L42.6673973,36.092 C43.3025753,36.092 43.8272877,36.624 43.8272877,37.268 C43.8272877,37.912 43.3025753,38.444 42.6673973,38.444 L40.32,38.444 C39.6848219,38.444 39.1601096,37.912 39.1601096,37.268 C39.1324932,36.624 39.6572055,36.092 40.32,36.092 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M52.2503014,33.712 C53.0511781,33.712 53.7139726,34.384 53.7139726,35.196 C53.7139726,36.008 53.0511781,36.68 52.2503014,36.68 C51.4494247,36.68 50.7866301,36.008 50.7866301,35.196 C50.8142466,34.384 51.4494247,33.712 52.2503014,33.712 Z M58.1049863,50.876 C58.905863,50.876 59.5686575,51.548 59.5686575,52.36 C59.5686575,53.172 58.905863,53.844 58.1049863,53.844 C57.3041096,53.844 56.6413151,53.172 56.6413151,52.36 C56.6413151,51.548 57.3041096,50.876 58.1049863,50.876 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M63.3521096,50.876 C64.1529863,50.876 64.8157808,51.548 64.8157808,52.36 C64.8157808,53.172 64.1529863,53.844 63.3521096,53.844 C62.5512329,53.844 61.8884384,53.172 61.8884384,52.36 C61.8884384,51.548 62.5512329,50.876 63.3521096,50.876 Z M33.3054247,14.784 L35.6528219,14.784 C36.288,14.784 36.8127123,15.316 36.8127123,15.96 C36.8127123,16.604 36.288,17.136 35.6528219,17.136 L33.3054247,17.136 C32.6702466,17.136 32.1455342,16.604 32.1455342,15.96 C32.1455342,15.316 32.6702466,14.784 33.3054247,14.784 Z" id="Shape" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6367123,36.092 L28.6382466,36.092 C29.2734247,36.092 29.798137,36.624 29.798137,37.268 C29.798137,37.912 29.2734247,38.444 28.6382466,38.444 L14.6367123,38.444 C14.0015342,38.444 13.4768219,37.912 13.4768219,37.268 C13.4768219,36.624 14.0015342,36.092 14.6367123,36.092 Z M44.0482192,42 L61.0599452,42 C61.8332055,42 62.4683836,42.672 62.4683836,43.484 C62.4683836,44.296 61.8332055,44.968 61.0599452,44.968 L44.0758356,44.968 C43.3025753,44.968 42.6673973,44.296 42.6673973,43.484 C42.6673973,42.672 43.2749589,42 44.0482192,42 L44.0482192,42 L44.0482192,42 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M35.3214247,50.876 L52.3055342,50.876 C53.0787945,50.876 53.7139726,51.548 53.7139726,52.36 C53.7139726,53.172 53.0787945,53.844 52.3055342,53.844 L35.3214247,53.844 C34.5481644,53.844 33.9129863,53.172 33.9129863,52.36 C33.8853699,51.548 34.5205479,50.876 35.3214247,50.876 L35.3214247,50.876 L35.3214247,50.876 Z" id="Path" fill="#EFEDF8" fill-rule="nonzero"></path>
- <path d="M14.6367123,21.896 L28.6382466,21.896 C29.2734247,21.896 29.798137,22.428 29.798137,23.072 C29.798137,23.716 29.2734247,24.248 28.6382466,24.248 L14.6367123,24.248 C14.0015342,24.248 13.4768219,23.716 13.4768219,23.072 C13.4768219,22.428 14.0015342,21.896 14.6367123,21.896 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M33.3054247,28.98 L47.3069589,28.98 C47.942137,28.98 48.4668493,29.512 48.4668493,30.156 C48.4668493,30.8 47.942137,31.332 47.3069589,31.332 L33.3054247,31.332 C32.6702466,31.332 32.1455342,30.8 32.1455342,30.156 C32.1455342,29.512 32.6702466,28.98 33.3054247,28.98 Z" id="Path" fill="#C3B8E3" fill-rule="nonzero"></path>
- <path d="M14.6367123,28.98 L16.9841096,28.98 C17.6192877,28.98 18.144,29.512 18.144,30.156 C18.144,30.8 17.6192877,31.332 16.9841096,31.332 L14.6367123,31.332 C14.0015342,31.332 13.4768219,30.8 13.4768219,30.156 C13.4768219,29.512 14.0015342,28.98 14.6367123,28.98 Z" id="Path" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M33.3054247,43.176 L35.6528219,43.176 C36.288,43.176 36.8127123,43.708 36.8127123,44.352 C36.8127123,44.996 36.288,45.528 35.6528219,45.528 L33.3054247,45.528 C32.6702466,45.528 32.1455342,44.996 32.1455342,44.352 C32.1455342,43.708 32.6702466,43.176 33.3054247,43.176 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M14.6367123,43.176 L19.3038904,43.176 C19.9390685,43.176 20.4637808,43.708 20.4637808,44.352 C20.4637808,44.996 19.9390685,45.528 19.3038904,45.528 L14.6367123,45.528 C14.0015342,45.528 13.4768219,44.996 13.4768219,44.352 C13.4768219,43.708 14.0015342,43.176 14.6367123,43.176 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6367123,50.288 L19.3038904,50.288 C19.9390685,50.288 20.4637808,50.82 20.4637808,51.464 C20.4637808,52.108 19.9390685,52.64 19.3038904,52.64 L14.6367123,52.64 C14.0015342,52.64 13.4768219,52.108 13.4768219,51.464 C13.4768219,50.82 14.0015342,50.288 14.6367123,50.288 Z M23.9710685,50.288 L28.6382466,50.288 C29.2734247,50.288 29.798137,50.82 29.798137,51.464 C29.798137,52.108 29.2734247,52.64 28.6382466,52.64 L23.9710685,52.64 C23.3358904,52.64 22.8111781,52.108 22.8111781,51.464 C22.8111781,50.82 23.3358904,50.288 23.9710685,50.288 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M14.6367123,57.372 L21.6236712,57.372 C22.2588493,57.372 22.7835616,57.904 22.7835616,58.548 C22.7835616,59.192 22.2588493,59.724 21.6236712,59.724 L14.6367123,59.724 C14.0015342,59.724 13.4768219,59.192 13.4768219,58.548 C13.4768219,57.904 14.0015342,57.372 14.6367123,57.372 Z" id="Path" fill="#EFEDF8" fill-rule="nonzero"></path>
- <path d="M25.3518904,64.484 L33.6644384,64.484 C34.4376986,64.484 35.0452603,65.016 35.0452603,65.66 C35.0452603,66.304 34.4376986,66.836 33.6644384,66.836 L25.3518904,66.836 C24.5786301,66.836 23.9710685,66.304 23.9710685,65.66 C23.9710685,65.016 24.5786301,64.484 25.3518904,64.484 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M44.0206027,59.136 L52.3331507,59.136 C53.106411,59.136 53.7139726,59.808 53.7139726,60.62 C53.7139726,61.432 53.106411,62.104 52.3331507,62.104 L44.0206027,62.104 C43.2473425,62.104 42.6397808,61.432 42.6397808,60.62 C42.6397808,59.808 43.2473425,59.136 44.0206027,59.136 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M26.2908493,57.372 L28.6382466,57.372 C29.2734247,57.372 29.798137,57.904 29.798137,58.548 C29.798137,59.192 29.2734247,59.724 28.6382466,59.724 L26.2908493,59.724 C25.6556712,59.724 25.1309589,59.192 25.1309589,58.548 C25.1309589,57.904 25.6556712,57.372 26.2908493,57.372 Z" id="Path" fill="#FEE1D3" fill-rule="nonzero"></path>
- <path d="M36.8127123,64.484 L39.1601096,64.484 C39.7952877,64.484 40.32,65.016 40.32,65.66 C40.32,66.304 39.7952877,66.836 39.1601096,66.836 L36.8127123,66.836 C36.1775342,66.836 35.6528219,66.304 35.6528219,65.66 C35.6528219,65.016 36.1775342,64.484 36.8127123,64.484 Z M58.1049863,59.136 L61.0323288,59.136 C61.8332055,59.136 62.496,59.808 62.496,60.62 C62.496,61.432 61.8332055,62.104 61.0323288,62.104 L58.1049863,62.104 C57.3041096,62.104 56.6413151,61.432 56.6413151,60.62 C56.6413151,59.808 57.3041096,59.136 58.1049863,59.136 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M35.3490411,59.136 L38.2763836,59.136 C39.0772603,59.136 39.7400548,59.808 39.7400548,60.62 C39.7400548,61.432 39.0772603,62.104 38.2763836,62.104 L35.3490411,62.104 C34.5481644,62.104 33.8853699,61.432 33.8853699,60.62 C33.8853699,59.808 34.5481644,59.136 35.3490411,59.136 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6367123,64.484 L20.4637808,64.484 C21.0989589,64.484 21.6236712,65.016 21.6236712,65.66 C21.6236712,66.304 21.0989589,66.836 20.4637808,66.836 L14.6367123,66.836 C14.0015342,66.836 13.4768219,66.304 13.4768219,65.66 C13.4768219,65.016 14.0015342,64.484 14.6367123,64.484 Z" id="Path" fill="#EEEEEE" fill-rule="nonzero"></path>
- <ellipse id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="36.7574795" cy="38.612" rx="20.4085479" ry="20.692"></ellipse>
- <path d="M36.7574795,59.304 C25.4899726,59.304 16.3489315,50.036 16.3489315,38.612 C16.3489315,27.188 25.4899726,17.92 36.7574795,17.92 C48.0249863,17.92 57.1660274,27.188 57.1660274,38.612 C57.1660274,50.036 48.0526027,59.304 36.7574795,59.304 Z M36.7574795,56.952 C46.7546301,56.952 54.8462466,48.748 54.8462466,38.612 C54.8462466,28.476 46.7546301,20.272 36.7574795,20.272 C26.7603288,20.272 18.6687123,28.476 18.6687123,38.612 C18.6687123,48.748 26.7879452,56.952 36.7574795,56.952 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <g transform="translate(26.787945, 29.400000)" id="Path">
- <path d="M19.7457534,10.528 L18.6410959,7.112 L16.4593973,0.336 C16.3489315,7.97972799e-15 15.8794521,7.97972799e-15 15.7413699,0.336 L13.5872877,7.112 L6.37939726,7.112 L4.19769863,0.336 C4.08723288,7.97972799e-15 3.61775342,7.97972799e-15 3.47967123,0.336 L1.2979726,7.112 L0.193315068,10.528 C0.0828493151,10.836 0.193315068,11.172 0.469479452,11.368 L9.94191781,18.34 L19.4143562,11.368 C19.718137,11.172 19.8286027,10.836 19.7457534,10.528" fill="#FC6D26"></path>
- <polygon fill="#E24329" points="9.96953425 18.34 13.5596712 7.112 6.35178082 7.112"></polygon>
- <polygon fill="#FC6D26" points="9.96953425 18.34 6.37939726 7.112 1.32558904 7.112"></polygon>
- <path d="M1.32558904,7.112 L0.220931507,10.528 C0.110465753,10.836 0.220931507,11.172 0.49709589,11.368 L9.96953425,18.34 L1.32558904,7.112 Z" fill="#FCA326"></path>
- <path d="M1.32558904,7.112 L6.37939726,7.112 L4.19769863,0.336 C4.08723288,7.9658502e-15 3.61775342,7.9658502e-15 3.47967123,0.336 L1.32558904,7.112 Z" fill="#E24329"></path>
- <polygon fill="#FC6D26" points="9.96953425 18.34 13.5596712 7.112 18.6134795 7.112"></polygon>
- <path d="M18.6410959,7.112 L19.7457534,10.528 C19.8562192,10.836 19.7457534,11.172 19.469589,11.368 L9.99715068,18.34 L18.6410959,7.112 Z" fill="#FCA326"></path>
- <path d="M18.6410959,7.112 L13.5872877,7.112 L15.7689863,0.336 C15.8794521,7.9658502e-15 16.3489315,7.9658502e-15 16.4870137,0.336 L18.6410959,7.112 Z" fill="#E24329"></path>
- </g>
- </g>
- <path d="M76,41.475 C76,40.660967 76.8066938,40 77.8150611,40 L81.4537653,40 C82.4578417,40 83.2688264,40.6540094 83.2688264,41.475 C83.2688264,42.289033 82.4621326,42.95 81.4537653,42.95 L77.8150611,42.95 C76.8152757,42.95 76,42.2959906 76,41.4819575 C76,41.4784788 76,41.4784788 76,41.475 Z M88.7311736,41.475 C88.7311736,40.660967 89.5378674,40 90.5462347,40 L94.1849389,40 C95.1890152,40 96,40.6540094 96,41.475 C96,42.289033 95.1933062,42.95 94.1849389,42.95 L90.5462347,42.95 C89.5464493,42.95 88.7311736,42.2959906 88.7311736,41.4819575 C88.7311736,41.4784788 88.7311736,41.4784788 88.7311736,41.475 Z" id="Shape" fill="#E5E5E5" fill-rule="nonzero"></path>
- <g id="Group">
- <g transform="translate(3.686038, 58.800000)">
- <path d="M6.33328302,0.207529412 L17.1233208,0.207529412 C20.541283,0.207529412 23.2890566,3.04376471 23.2890566,6.57176471 L23.2890566,17.7091765 C23.2890566,21.2025882 20.541283,24.0734118 17.1233208,24.0734118 L6.33328302,24.0734118 C2.94883019,24.0734118 0.16754717,21.2371765 0.16754717,17.7091765 L0.16754717,6.57176471 C0.16754717,3.04376471 2.91532075,0.207529412 6.33328302,0.207529412 Z" id="Path" fill="#FFFFFF"></path>
- <path d="M6.33328302,3.38964706 C4.62430189,3.38964706 3.25041509,4.80776471 3.25041509,6.57176471 L3.25041509,17.7091765 C3.25041509,19.4731765 4.62430189,20.8912941 6.33328302,20.8912941 L17.1233208,20.8912941 C18.8323019,20.8912941 20.2061887,19.4731765 20.2061887,17.7091765 L20.2061887,6.57176471 C20.2061887,4.80776471 18.8323019,3.38964706 17.1233208,3.38964706 L6.33328302,3.38964706 Z M6.33328302,0.207529412 L17.1233208,0.207529412 C20.541283,0.207529412 23.2890566,3.04376471 23.2890566,6.57176471 L23.2890566,17.7091765 C23.2890566,21.2025882 20.541283,24.0734118 17.1233208,24.0734118 L6.33328302,24.0734118 C2.94883019,24.0734118 0.16754717,21.2371765 0.16754717,17.7091765 L0.16754717,6.57176471 C0.16754717,3.04376471 2.91532075,0.207529412 6.33328302,0.207529412 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M11.7283019,8.12823529 L11.7283019,8.12823529 C13.8393962,8.12823529 15.5818868,9.89223529 15.5818868,12.1058824 L15.5818868,12.1058824 C15.5818868,14.3195294 13.8729057,16.0835294 11.7283019,16.0835294 L11.7283019,16.0835294 C9.61720755,16.0835294 7.87471698,14.3195294 7.87471698,12.1058824 L7.87471698,12.1058824 C7.87471698,9.92682353 9.58369811,8.12823529 11.7283019,8.12823529 Z" id="Path" fill="#6B4FBB"></path>
- </g>
- <path d="M4.62430189,3.35505882 C3.78656604,3.35505882 3.08286792,4.08141176 3.08286792,4.94611765 L3.08286792,14.4924706 C3.08286792,15.3571765 3.78656604,16.0835294 4.62430189,16.0835294 L13.8729057,16.0835294 C14.7106415,16.0835294 15.4143396,15.3571765 15.4143396,14.4924706 L15.4143396,4.94611765 C15.4143396,4.08141176 14.7106415,3.35505882 13.8729057,3.35505882 L4.62430189,3.35505882 Z" id="Path" fill="#FFFFFF"></path>
- <path d="M4.62430189,3.35505882 C3.78656604,3.35505882 3.08286792,4.08141176 3.08286792,4.94611765 L3.08286792,14.4924706 C3.08286792,15.3571765 3.78656604,16.0835294 4.62430189,16.0835294 L13.8729057,16.0835294 C14.7106415,16.0835294 15.4143396,15.3571765 15.4143396,14.4924706 L15.4143396,4.94611765 C15.4143396,4.08141176 14.7106415,3.35505882 13.8729057,3.35505882 L4.62430189,3.35505882 Z M4.62430189,0.172941176 L13.8729057,0.172941176 C16.4196226,0.172941176 18.4972075,2.31741176 18.4972075,4.94611765 L18.4972075,14.4924706 C18.4972075,17.1211765 16.4196226,19.2656471 13.8729057,19.2656471 L4.62430189,19.2656471 C2.07758491,19.2656471 -1.19049424e-15,17.1211765 -1.19049424e-15,14.4924706 L-1.19049424e-15,4.94611765 C-1.19049424e-15,2.31741176 2.07758491,0.172941176 4.62430189,0.172941176 Z" id="Shape" fill="#FDC4A8" fill-rule="nonzero"></path>
- <path d="M9.24860377,6.53717647 L9.24860377,6.53717647 C10.9575849,6.53717647 12.3314717,7.95529412 12.3314717,9.71929412 L12.3314717,9.71929412 C12.3314717,11.4832941 10.9575849,12.9014118 9.24860377,12.9014118 L9.24860377,12.9014118 C7.53962264,12.9014118 6.16573585,11.4832941 6.16573585,9.71929412 L6.16573585,9.71929412 C6.16573585,7.95529412 7.53962264,6.53717647 9.24860377,6.53717647 Z" id="Path" fill="#FC6D26"></path>
- <g transform="translate(35.184906, 23.174118)">
- <path d="M7.94173585,1.62564706 L27.9803774,1.62564706 C32.2360755,1.62564706 35.6875472,5.18823529 35.6875472,9.58094118 L35.6875472,30.2647059 C35.6875472,34.6574118 32.2360755,38.22 27.9803774,38.22 L7.94173585,38.22 C3.68603774,38.22 0.234566038,34.6574118 0.234566038,30.2647059 L0.234566038,9.58094118 C0.234566038,5.18823529 3.68603774,1.62564706 7.94173585,1.62564706 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M7.94173585,0.0345882353 L27.9803774,0.0345882353 C32.2360755,0.0345882353 35.6875472,3.59717647 35.6875472,7.98988235 L35.6875472,28.6736471 C35.6875472,33.0663529 32.2360755,36.6289412 27.9803774,36.6289412 L7.94173585,36.6289412 C3.68603774,36.6289412 0.234566038,33.0663529 0.234566038,28.6736471 L0.234566038,7.98988235 C0.234566038,3.59717647 3.68603774,0.0345882353 7.94173585,0.0345882353 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M7.94173585,3.21670588 C5.39501887,3.21670588 3.31743396,5.36117647 3.31743396,7.98988235 L3.31743396,28.6736471 C3.31743396,31.3023529 5.39501887,33.4468235 7.94173585,33.4468235 L27.9803774,33.4468235 C30.5270943,33.4468235 32.6046792,31.3023529 32.6046792,28.6736471 L32.6046792,7.98988235 C32.6046792,5.36117647 30.5270943,3.21670588 27.9803774,3.21670588 C27.9468679,3.21670588 7.94173585,3.21670588 7.94173585,3.21670588 Z M7.94173585,0.0345882353 L27.9803774,0.0345882353 C32.2360755,0.0345882353 35.6875472,3.59717647 35.6875472,7.98988235 L35.6875472,28.6736471 C35.6875472,33.0663529 32.2360755,36.6289412 27.9803774,36.6289412 L7.94173585,36.6289412 C3.68603774,36.6289412 0.234566038,33.0663529 0.234566038,28.6736471 L0.234566038,7.98988235 C0.234566038,3.59717647 3.68603774,0.0345882353 7.94173585,0.0345882353 Z" id="Shape" fill="#C3B8E3" fill-rule="nonzero"></path>
- <path d="M14.1074717,12.7630588 L21.8146415,12.7630588 C22.6523774,12.7630588 23.3560755,13.4894118 23.3560755,14.3541176 L23.3560755,22.3094118 C23.3560755,23.1741176 22.6523774,23.9004706 21.8146415,23.9004706 L14.1074717,23.9004706 C13.2697358,23.9004706 12.5660377,23.1741176 12.5660377,22.3094118 L12.5660377,14.3541176 C12.5660377,13.4894118 13.2362264,12.7630588 14.1074717,12.7630588 Z" id="Path" fill="#6B4FBB"></path>
- </g>
- <path d="M32.6716981,71.4592941 C32.0685283,72.0818824 31.0967547,72.0818824 30.4935849,71.4592941 C29.8904151,70.8367059 29.8904151,69.8336471 30.4935849,69.2110588 L32.1355472,67.5162353 C32.738717,66.8936471 33.7104906,66.8936471 34.3136604,67.5162353 C34.9168302,68.1388235 34.9168302,69.1418824 34.3136604,69.7644706 L32.6716981,71.4592941 Z" id="Path" fill="#C3B8E3" fill-rule="nonzero"></path>
- <path d="M37.5640755,66.4094118 C36.9609057,67.032 35.9891321,67.032 35.3859623,66.4094118 C34.7827925,65.7868235 34.7827925,64.7837647 35.3859623,64.1611765 L37.0279245,62.4663529 C37.6310943,61.8437647 38.6028679,61.8437647 39.2060377,62.4663529 C39.8092075,63.0889412 39.8092075,64.092 39.2060377,64.7145882 L37.5640755,66.4094118 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M21.3455094,21.2717647 C20.7088302,20.7183529 20.6083019,19.7152941 21.1444528,19.0235294 C21.6806038,18.3663529 22.6523774,18.2625882 23.322566,18.816 L25.098566,20.3378824 C25.7352453,20.8912941 25.8357736,21.8943529 25.2996226,22.5861176 C24.7634717,23.2432941 23.7916981,23.3470588 23.1215094,22.7936471 L21.3455094,21.2717647 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M26.64,25.872 C26.0033208,25.3185882 25.9027925,24.3155294 26.4389434,23.6237647 C26.9750943,22.9665882 27.9468679,22.8628235 28.6170566,23.4162353 L30.3930566,24.9381176 C31.0297358,25.4915294 31.1302642,26.4945882 30.5941132,27.1863529 C30.0579623,27.8781176 29.0861887,27.9472941 28.416,27.3938824 L26.64,25.872 Z" id="Path" fill="#C3B8E3"></path>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
+<svg width="169" height="78" viewBox="0 0 169 78" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M115.571 41.5714L147.714 41.5714C158.365 41.5714 167 32.9369 167 22.2857C167 11.6345 158.365 3 147.714 3C137.063 3 128.429 11.6345 128.429 22.2857C128.429 27.3128 130.352 31.8907 133.503 35.3235" stroke="#DBDBDB" stroke-width="2.63203" stroke-linecap="round"/>
+<path d="M115.107 41.5714H125.786C133.084 41.5714 139 47.4877 139 54.7857C139 62.0838 133.084 68 125.786 68C118.488 68 112.571 62.0838 112.571 54.7857C112.571 53.039 112.91 51.3715 113.526 49.8453" stroke="#DBDBDB" stroke-width="2.63203" stroke-linecap="round"/>
+<path d="M87.5486 37H76.3943C75.6243 37 75 36.3746 75 35.6032C75 34.8318 75.6243 34.2064 76.3943 34.2064H87.5486C88.3187 34.2064 88.9429 34.8318 88.9429 35.6032C88.9429 36.3746 88.3187 37 87.5486 37Z" fill="#FC6D26"/>
+<path d="M118.703 37H96.3943C95.6243 37 95 36.3746 95 35.6032C95 34.8318 95.6243 34.2064 96.3943 34.2064H118.703C119.473 34.2064 120.097 34.8318 120.097 35.6032C120.097 36.3746 119.473 37 118.703 37Z" fill="#FC6D26"/>
+<path d="M118.703 37H96.3943C95.6243 37 95 36.3746 95 35.6032C95 34.8318 95.6243 34.2064 96.3943 34.2064H118.703C119.473 34.2064 120.097 34.8318 120.097 35.6032C120.097 36.3746 119.473 37 118.703 37Z" fill="white" fill-opacity="0.6"/>
+<path d="M93.8573 32H71.3944C70.6243 32 70.0001 31.3746 70.0001 30.6032C70.0001 29.8318 70.6243 29.2064 71.3944 29.2064L93.8573 29.2064C94.6273 29.2064 95.2516 29.8318 95.2516 30.6032C95.2516 31.3746 94.6273 32 93.8573 32Z" fill="#6E49CB"/>
+<path d="M93.8573 32H71.3944C70.6243 32 70.0001 31.3746 70.0001 30.6032C70.0001 29.8318 70.6243 29.2064 71.3944 29.2064L93.8573 29.2064C94.6273 29.2064 95.2516 29.8318 95.2516 30.6032C95.2516 31.3746 94.6273 32 93.8573 32Z" fill="white" fill-opacity="0.8"/>
+<path d="M86.8573 49H71.3944C70.6243 49 70.0001 48.3746 70.0001 47.6032C70.0001 46.8317 70.6243 46.2064 71.3944 46.2064H86.8573C87.6273 46.2064 88.2516 46.8317 88.2516 47.6032C88.2516 48.3746 87.6273 49 86.8573 49Z" fill="#6E49CB"/>
+<path d="M86.8573 49H71.3944C70.6243 49 70.0001 48.3746 70.0001 47.6032C70.0001 46.8317 70.6243 46.2064 71.3944 46.2064H86.8573C87.6273 46.2064 88.2516 46.8317 88.2516 47.6032C88.2516 48.3746 87.6273 49 86.8573 49Z" fill="white" fill-opacity="0.8"/>
+<path d="M109.166 43L73.3944 43C72.6243 43 72.0001 42.3746 72.0001 41.6032C72.0001 40.8317 72.6243 40.2064 73.3944 40.2064L109.166 40.2064C109.936 40.2064 110.56 40.8317 110.56 41.6032C110.56 42.3746 109.936 43 109.166 43Z" fill="#6E49CB"/>
+<path d="M109.166 43L73.3944 43C72.6243 43 72.0001 42.3746 72.0001 41.6032C72.0001 40.8317 72.6243 40.2064 73.3944 40.2064L109.166 40.2064C109.936 40.2064 110.56 40.8317 110.56 41.6032C110.56 42.3746 109.936 43 109.166 43Z" fill="white" fill-opacity="0.4"/>
+<path d="M146.262 24.2349L143.048 21.0153C142.767 20.7338 142.282 20.7323 141.983 21.0313L140.394 22.6236C140.1 22.9181 140.088 23.4002 140.378 23.6903L145.344 28.6651C145.841 29.1637 146.666 29.1795 147.166 28.6793L147.866 27.9779L155.864 19.9653C156.171 19.658 156.167 19.1776 155.868 18.8786L154.279 17.2863C153.985 16.9918 153.495 16.9891 153.194 17.2903L146.262 24.2349Z" fill="#FC6D26"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M125.682 56.7113L123.087 59.3221C122.858 59.5529 122.547 59.6825 122.223 59.6824C121.898 59.6824 121.587 59.5526 121.358 59.3218C121.129 59.091 121 58.7779 121 58.4515C121 58.1251 121.129 57.8121 121.358 57.5813L123.087 55.8412L121.358 54.1011C121.129 53.8703 121 53.5573 121 53.2309C121 52.9045 121.129 52.5915 121.358 52.3606C121.587 52.1298 121.898 52.0001 122.223 52C122.547 51.9999 122.858 52.1296 123.087 52.3603L125.682 54.9711C125.911 55.2019 126.04 55.5149 126.04 55.8412C126.04 56.1675 125.911 56.4805 125.682 56.7113ZM131.796 56.7113L129.202 59.3221C129.088 59.4364 128.954 59.527 128.805 59.5888C128.657 59.6506 128.498 59.6824 128.337 59.6824C128.177 59.6824 128.018 59.6505 127.869 59.5886C127.721 59.5268 127.586 59.4361 127.472 59.3218C127.359 59.2075 127.269 59.0718 127.207 58.9225C127.146 58.7732 127.114 58.6131 127.114 58.4515C127.114 58.2899 127.146 58.1299 127.208 57.9806C127.269 57.8313 127.359 57.6956 127.473 57.5813L129.202 55.8412L127.473 54.1011C127.359 53.9868 127.269 53.8512 127.208 53.7018C127.146 53.5525 127.114 53.3925 127.114 53.2309C127.114 53.0693 127.146 52.9092 127.207 52.7599C127.269 52.6106 127.359 52.4749 127.472 52.3606C127.586 52.2463 127.721 52.1556 127.869 52.0938C128.018 52.0319 128.177 52 128.337 52C128.498 52 128.657 52.0318 128.805 52.0936C128.954 52.1554 129.088 52.246 129.202 52.3603L131.796 54.9711C132.026 55.2019 132.154 55.5149 132.154 55.8412C132.154 56.1675 132.026 56.4805 131.796 56.7113Z" fill="#6E49CB"/>
+<path d="M2 26C2 28.415 14.4361 30.3727 29.7769 30.3727C33.7709 30.3727 37.568 30.24 41 30.0011" stroke="#DBDBDB" stroke-width="1.28173"/>
+<path d="M2 50C2 52.415 14.4361 54.3727 29.7769 54.3727C35.6133 54.3727 41.0293 54.0893 45.5 53.6052" stroke="#DBDBDB" stroke-width="1.28173"/>
+<path d="M57.5537 5V22M2 5V68.6673C2 73.1731 20.9696 75.5204 29.7769 75.5204C38.5842 75.5204 57.5537 73.1731 57.5537 68.6673V57" stroke="#DBDBDB" stroke-width="2.56346" stroke-linejoin="round"/>
+<ellipse cx="29.7769" cy="5.64391" rx="27.7769" ry="3.64391" stroke="#DBDBDB" stroke-width="2.56346"/>
+<ellipse cx="55.4286" cy="39.46" rx="17.4286" ry="17.46" stroke="#6E49CB" stroke-width="2.56346"/>
+<ellipse cx="55.2458" cy="39.2696" rx="13.2458" ry="13.2696" fill="#6E49CB"/>
+<ellipse cx="55.2458" cy="39.2696" rx="13.2458" ry="13.2696" fill="white" fill-opacity="0.9"/>
+<path d="M61.763 38.5893C62.5797 39.0892 62.5797 40.2756 61.763 40.7756L52.951 46.1704C52.0969 46.6933 51 46.0787 51 45.0773L51 34.2875C51 33.2861 52.0969 32.6715 52.951 33.1944L61.763 38.5893Z" fill="#6E49CB"/>
+</svg>
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/create-from-template.svg b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/create-from-template.svg
index e90c354fe65..2ff4e4969b1 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/create-from-template.svg
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/create-from-template.svg
@@ -1,54 +1,13 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="215px" height="115px" viewBox="0 0 215 115" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
- <title>create-project-from-template-md</title>
- <desc>Created with Sketch.</desc>
- <g id="create-project-from-template-md" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="New-Template1" transform="translate(71.000000, 15.000000)">
- <g id="Group">
- <path d="M5.88230137,4.144 L61.8884384,4.144 C65.1195616,4.144 67.7155068,6.804 67.7155068,10.052 L67.7155068,78.064 C67.7155068,81.34 65.0919452,83.972 61.8884384,83.972 L5.88230137,83.972 C2.65117808,83.972 0.0552328767,81.312 0.0552328767,78.064 L0.0552328767,10.052 C0.0552328767,6.804 2.67879452,4.144 5.88230137,4.144 Z" id="Path" fill="#F9F9F9" fill-rule="nonzero"></path>
- <path d="M8.82706849,1 L64.8332055,1 C68.0643288,1 70.660274,3.66 70.660274,6.908 L70.660274,74.332 C70.660274,77.608 68.0367123,80.24 64.8332055,80.24 L8.82706849,80.24 C5.59594521,80.24 3,77.58 3,74.332 L3,6.936 C3,3.66 5.59594521,1 8.82706849,1 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
- <path d="M8.80964384,2.38 C6.24131507,2.38 4.14246575,4.508 4.14246575,7.112 L4.14246575,74.536 C4.14246575,77.14 6.24131507,79.268 8.80964384,79.268 L64.8157808,79.268 C67.3841096,79.268 69.4829589,77.14 69.4829589,74.536 L69.4829589,7.112 C69.4829589,4.508 67.3841096,2.38 64.8157808,2.38 L8.80964384,2.38 L8.80964384,2.38 Z M8.80964384,0 L64.8157808,0 C68.6820822,0 71.8027397,3.164 71.8027397,7.084 L71.8027397,74.508 C71.8027397,78.428 68.6820822,81.592 64.8157808,81.592 L8.80964384,81.592 C4.94334247,81.592 1.82250462,78.4 1.82250462,74.508 L1.82250462,7.112 C1.79506849,3.192 4.94334247,0 8.80964384,0 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M14.6367123,14.784 L21.6236712,14.784 C22.2588493,14.784 22.7835616,15.316 22.7835616,15.96 C22.7835616,16.604 22.2588493,17.136 21.6236712,17.136 L14.6367123,17.136 C14.0015342,17.136 13.4768219,16.604 13.4768219,15.96 C13.4768219,15.316 14.0015342,14.784 14.6367123,14.784 Z M33.3054247,21.896 L40.2923836,21.896 C40.9275616,21.896 41.452274,22.428 41.452274,23.072 C41.452274,23.716 40.9275616,24.248 40.2923836,24.248 L33.3054247,24.248 C32.6702466,24.248 32.1455342,23.716 32.1455342,23.072 C32.1455342,22.428 32.6702466,21.896 33.3054247,21.896 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M40.32,14.784 L47.3069589,14.784 C47.942137,14.784 48.4668493,15.316 48.4668493,15.96 C48.4668493,16.604 47.942137,17.136 47.3069589,17.136 L40.32,17.136 C39.6848219,17.136 39.1601096,16.604 39.1601096,15.96 C39.1324932,15.316 39.6572055,14.784 40.32,14.784 Z" id="Path" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M21.6512877,28.98 L28.6382466,28.98 C29.2734247,28.98 29.798137,29.512 29.798137,30.156 C29.798137,30.8 29.2734247,31.332 28.6382466,31.332 L21.6512877,31.332 C21.0161096,31.332 20.4913973,30.8 20.4913973,30.156 C20.4637808,29.512 20.9884932,28.98 21.6512877,28.98 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M26.2908493,14.784 L28.6382466,14.784 C29.2734247,14.784 29.798137,15.316 29.798137,15.96 C29.798137,16.604 29.2734247,17.136 28.6382466,17.136 L26.2908493,17.136 C25.6556712,17.136 25.1309589,16.604 25.1309589,15.96 C25.1309589,15.316 25.6556712,14.784 26.2908493,14.784 Z" id="Path" fill="#FEE1D3" fill-rule="nonzero"></path>
- <path d="M33.3054247,36.092 L35.6528219,36.092 C36.288,36.092 36.8127123,36.624 36.8127123,37.268 C36.8127123,37.912 36.288,38.444 35.6528219,38.444 L33.3054247,38.444 C32.6702466,38.444 32.1455342,37.912 32.1455342,37.268 C32.1455342,36.624 32.6702466,36.092 33.3054247,36.092 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M44.9595616,21.896 L47.3069589,21.896 C47.942137,21.896 48.4668493,22.428 48.4668493,23.072 C48.4668493,23.716 47.942137,24.248 47.3069589,24.248 L44.9595616,24.248 C44.3243836,24.248 43.7996712,23.716 43.7996712,23.072 C43.7996712,22.428 44.3243836,21.896 44.9595616,21.896 Z M51.974137,14.784 L54.3215342,14.784 C54.9567123,14.784 55.4814247,15.316 55.4814247,15.96 C55.4814247,16.604 54.9567123,17.136 54.3215342,17.136 L51.974137,17.136 C51.3389589,17.136 50.8142466,16.604 50.8142466,15.96 C50.8142466,15.316 51.3389589,14.784 51.974137,14.784 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M23.9710685,43.176 L28.6382466,43.176 C29.2734247,43.176 29.798137,43.708 29.798137,44.352 C29.798137,44.996 29.2734247,45.528 28.6382466,45.528 L23.9710685,45.528 C23.3358904,45.528 22.8111781,44.996 22.8111781,44.352 C22.8111781,43.708 23.3358904,43.176 23.9710685,43.176 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M40.32,36.092 L42.6673973,36.092 C43.3025753,36.092 43.8272877,36.624 43.8272877,37.268 C43.8272877,37.912 43.3025753,38.444 42.6673973,38.444 L40.32,38.444 C39.6848219,38.444 39.1601096,37.912 39.1601096,37.268 C39.1324932,36.624 39.6572055,36.092 40.32,36.092 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M52.2503014,33.712 C53.0511781,33.712 53.7139726,34.384 53.7139726,35.196 C53.7139726,36.008 53.0511781,36.68 52.2503014,36.68 C51.4494247,36.68 50.7866301,36.008 50.7866301,35.196 C50.8142466,34.384 51.4494247,33.712 52.2503014,33.712 Z M58.1049863,50.876 C58.905863,50.876 59.5686575,51.548 59.5686575,52.36 C59.5686575,53.172 58.905863,53.844 58.1049863,53.844 C57.3041096,53.844 56.6413151,53.172 56.6413151,52.36 C56.6413151,51.548 57.3041096,50.876 58.1049863,50.876 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M63.3521096,50.876 C64.1529863,50.876 64.8157808,51.548 64.8157808,52.36 C64.8157808,53.172 64.1529863,53.844 63.3521096,53.844 C62.5512329,53.844 61.8884384,53.172 61.8884384,52.36 C61.8884384,51.548 62.5512329,50.876 63.3521096,50.876 Z M33.3054247,14.784 L35.6528219,14.784 C36.288,14.784 36.8127123,15.316 36.8127123,15.96 C36.8127123,16.604 36.288,17.136 35.6528219,17.136 L33.3054247,17.136 C32.6702466,17.136 32.1455342,16.604 32.1455342,15.96 C32.1455342,15.316 32.6702466,14.784 33.3054247,14.784 Z" id="Shape" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6367123,36.092 L28.6382466,36.092 C29.2734247,36.092 29.798137,36.624 29.798137,37.268 C29.798137,37.912 29.2734247,38.444 28.6382466,38.444 L14.6367123,38.444 C14.0015342,38.444 13.4768219,37.912 13.4768219,37.268 C13.4768219,36.624 14.0015342,36.092 14.6367123,36.092 Z M44.0482192,42 L61.0599452,42 C61.8332055,42 62.4683836,42.672 62.4683836,43.484 C62.4683836,44.296 61.8332055,44.968 61.0599452,44.968 L44.0758356,44.968 C43.3025753,44.968 42.6673973,44.296 42.6673973,43.484 C42.6673973,42.672 43.2749589,42 44.0482192,42 L44.0482192,42 L44.0482192,42 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M35.3214247,50.876 L52.3055342,50.876 C53.0787945,50.876 53.7139726,51.548 53.7139726,52.36 C53.7139726,53.172 53.0787945,53.844 52.3055342,53.844 L35.3214247,53.844 C34.5481644,53.844 33.9129863,53.172 33.9129863,52.36 C33.8853699,51.548 34.5205479,50.876 35.3214247,50.876 L35.3214247,50.876 L35.3214247,50.876 Z" id="Path" fill="#EFEDF8" fill-rule="nonzero"></path>
- <path d="M14.6367123,21.896 L28.6382466,21.896 C29.2734247,21.896 29.798137,22.428 29.798137,23.072 C29.798137,23.716 29.2734247,24.248 28.6382466,24.248 L14.6367123,24.248 C14.0015342,24.248 13.4768219,23.716 13.4768219,23.072 C13.4768219,22.428 14.0015342,21.896 14.6367123,21.896 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M33.3054247,28.98 L47.3069589,28.98 C47.942137,28.98 48.4668493,29.512 48.4668493,30.156 C48.4668493,30.8 47.942137,31.332 47.3069589,31.332 L33.3054247,31.332 C32.6702466,31.332 32.1455342,30.8 32.1455342,30.156 C32.1455342,29.512 32.6702466,28.98 33.3054247,28.98 Z" id="Path" fill="#C3B8E3" fill-rule="nonzero"></path>
- <path d="M14.6367123,28.98 L16.9841096,28.98 C17.6192877,28.98 18.144,29.512 18.144,30.156 C18.144,30.8 17.6192877,31.332 16.9841096,31.332 L14.6367123,31.332 C14.0015342,31.332 13.4768219,30.8 13.4768219,30.156 C13.4768219,29.512 14.0015342,28.98 14.6367123,28.98 Z" id="Path" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M33.3054247,43.176 L35.6528219,43.176 C36.288,43.176 36.8127123,43.708 36.8127123,44.352 C36.8127123,44.996 36.288,45.528 35.6528219,45.528 L33.3054247,45.528 C32.6702466,45.528 32.1455342,44.996 32.1455342,44.352 C32.1455342,43.708 32.6702466,43.176 33.3054247,43.176 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M14.6367123,43.176 L19.3038904,43.176 C19.9390685,43.176 20.4637808,43.708 20.4637808,44.352 C20.4637808,44.996 19.9390685,45.528 19.3038904,45.528 L14.6367123,45.528 C14.0015342,45.528 13.4768219,44.996 13.4768219,44.352 C13.4768219,43.708 14.0015342,43.176 14.6367123,43.176 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6367123,50.288 L19.3038904,50.288 C19.9390685,50.288 20.4637808,50.82 20.4637808,51.464 C20.4637808,52.108 19.9390685,52.64 19.3038904,52.64 L14.6367123,52.64 C14.0015342,52.64 13.4768219,52.108 13.4768219,51.464 C13.4768219,50.82 14.0015342,50.288 14.6367123,50.288 Z M23.9710685,50.288 L28.6382466,50.288 C29.2734247,50.288 29.798137,50.82 29.798137,51.464 C29.798137,52.108 29.2734247,52.64 28.6382466,52.64 L23.9710685,52.64 C23.3358904,52.64 22.8111781,52.108 22.8111781,51.464 C22.8111781,50.82 23.3358904,50.288 23.9710685,50.288 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M14.6367123,57.372 L21.6236712,57.372 C22.2588493,57.372 22.7835616,57.904 22.7835616,58.548 C22.7835616,59.192 22.2588493,59.724 21.6236712,59.724 L14.6367123,59.724 C14.0015342,59.724 13.4768219,59.192 13.4768219,58.548 C13.4768219,57.904 14.0015342,57.372 14.6367123,57.372 Z" id="Path" fill="#EFEDF8" fill-rule="nonzero"></path>
- <path d="M25.3518904,64.484 L33.6644384,64.484 C34.4376986,64.484 35.0452603,65.016 35.0452603,65.66 C35.0452603,66.304 34.4376986,66.836 33.6644384,66.836 L25.3518904,66.836 C24.5786301,66.836 23.9710685,66.304 23.9710685,65.66 C23.9710685,65.016 24.5786301,64.484 25.3518904,64.484 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M44.0206027,59.136 L52.3331507,59.136 C53.106411,59.136 53.7139726,59.808 53.7139726,60.62 C53.7139726,61.432 53.106411,62.104 52.3331507,62.104 L44.0206027,62.104 C43.2473425,62.104 42.6397808,61.432 42.6397808,60.62 C42.6397808,59.808 43.2473425,59.136 44.0206027,59.136 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M26.2908493,57.372 L28.6382466,57.372 C29.2734247,57.372 29.798137,57.904 29.798137,58.548 C29.798137,59.192 29.2734247,59.724 28.6382466,59.724 L26.2908493,59.724 C25.6556712,59.724 25.1309589,59.192 25.1309589,58.548 C25.1309589,57.904 25.6556712,57.372 26.2908493,57.372 Z" id="Path" fill="#FEE1D3" fill-rule="nonzero"></path>
- <path d="M36.8127123,64.484 L39.1601096,64.484 C39.7952877,64.484 40.32,65.016 40.32,65.66 C40.32,66.304 39.7952877,66.836 39.1601096,66.836 L36.8127123,66.836 C36.1775342,66.836 35.6528219,66.304 35.6528219,65.66 C35.6528219,65.016 36.1775342,64.484 36.8127123,64.484 Z M58.1049863,59.136 L61.0323288,59.136 C61.8332055,59.136 62.496,59.808 62.496,60.62 C62.496,61.432 61.8332055,62.104 61.0323288,62.104 L58.1049863,62.104 C57.3041096,62.104 56.6413151,61.432 56.6413151,60.62 C56.6413151,59.808 57.3041096,59.136 58.1049863,59.136 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M35.3490411,59.136 L38.2763836,59.136 C39.0772603,59.136 39.7400548,59.808 39.7400548,60.62 C39.7400548,61.432 39.0772603,62.104 38.2763836,62.104 L35.3490411,62.104 C34.5481644,62.104 33.8853699,61.432 33.8853699,60.62 C33.8853699,59.808 34.5481644,59.136 35.3490411,59.136 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6367123,64.484 L20.4637808,64.484 C21.0989589,64.484 21.6236712,65.016 21.6236712,65.66 C21.6236712,66.304 21.0989589,66.836 20.4637808,66.836 L14.6367123,66.836 C14.0015342,66.836 13.4768219,66.304 13.4768219,65.66 C13.4768219,65.016 14.0015342,64.484 14.6367123,64.484 Z" id="Path" fill="#EEEEEE" fill-rule="nonzero"></path>
- <g id="Group-2" transform="translate(16.000000, 20.000000)">
- <ellipse id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="20.4085479" cy="20.692" rx="20.4085479" ry="20.692"></ellipse>
- <path d="M20.4085479,41.384 C9.1410411,41.384 8.17124146e-14,32.116 8.17124146e-14,20.692 C8.17124146e-14,9.268 9.1410411,1.0658141e-14 20.4085479,1.0658141e-14 C31.6760548,1.0658141e-14 40.8170959,9.268 40.8170959,20.692 C40.8170959,32.116 31.7036712,41.384 20.4085479,41.384 Z M20.4085479,39.032 C30.4056986,39.032 38.4973151,30.828 38.4973151,20.692 C38.4973151,10.556 30.4056986,2.352 20.4085479,2.352 C10.4113973,2.352 2.31978082,10.556 2.31978082,20.692 C2.31978082,30.828 10.4390137,39.032 20.4085479,39.032 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <g id="Group" transform="translate(10.439014, 11.480000)">
- <path d="M19.7457534,10.528 L18.6410959,7.112 L16.4593973,0.336 C16.3489315,7.97972799e-15 15.8794521,7.97972799e-15 15.7413699,0.336 L13.5872877,7.112 L6.37939726,7.112 L4.19769863,0.336 C4.08723288,7.97972799e-15 3.61775342,7.97972799e-15 3.47967123,0.336 L1.2979726,7.112 L0.193315068,10.528 C0.0828493151,10.836 0.193315068,11.172 0.469479452,11.368 L9.94191781,18.34 L19.4143562,11.368 C19.718137,11.172 19.8286027,10.836 19.7457534,10.528" id="Path" fill="#FC6D26"></path>
- <polygon id="Path" fill="#E24329" points="9.96953425 18.34 13.5596712 7.112 6.35178082 7.112"></polygon>
- <polygon id="Path" fill="#FC6D26" points="9.96953425 18.34 6.37939726 7.112 1.32558904 7.112"></polygon>
- <path d="M1.32558904,7.112 L0.220931507,10.528 C0.110465753,10.836 0.220931507,11.172 0.49709589,11.368 L9.96953425,18.34 L1.32558904,7.112 Z" id="Path" fill="#FCA326"></path>
- <path d="M1.32558904,7.112 L6.37939726,7.112 L4.19769863,0.336 C4.08723288,7.9658502e-15 3.61775342,7.9658502e-15 3.47967123,0.336 L1.32558904,7.112 Z" id="Path" fill="#E24329"></path>
- <polygon id="Path" fill="#FC6D26" points="9.96953425 18.34 13.5596712 7.112 18.6134795 7.112"></polygon>
- <path d="M18.6410959,7.112 L19.7457534,10.528 C19.8562192,10.836 19.7457534,11.172 19.469589,11.368 L9.99715068,18.34 L18.6410959,7.112 Z" id="Path" fill="#FCA326"></path>
- <path d="M18.6410959,7.112 L13.5872877,7.112 L15.7689863,0.336 C15.8794521,7.9658502e-15 16.3489315,7.9658502e-15 16.4870137,0.336 L18.6410959,7.112 Z" id="Path" fill="#E24329"></path>
- </g>
- </g>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
+<svg width="82" height="80" viewBox="0 0 82 80" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M68.1765 8.17647H79.6471C80.2968 8.17647 80.8235 8.70319 80.8235 9.35294V69.6471C80.8235 70.2968 80.2968 70.8235 79.6471 70.8235H68.1765V8.17647Z" fill="#F0F0F0" stroke="#DBDBDB" stroke-width="2.35294"/>
+<path d="M24.0504 19L24.0093 10.0746C24.0039 8.9145 24.8449 7.92363 25.9905 7.74035L65.393 1.43595C66.8226 1.20721 68.1176 2.31155 68.1176 3.75934V75.903C68.1176 77.3456 66.8314 78.4485 65.4057 78.2284L26.2788 72.1887C25.1356 72.0122 24.2902 71.0309 24.2849 69.8742L24.244 61" stroke="#DBDBDB" stroke-width="2.35294"/>
+<path d="M60.0194 11.1796L30.0195 15.2198C29.4357 15.2984 29 15.7966 29 16.3857V19.1235C29 19.8153 29.594 20.3578 30.283 20.2951L60.283 17.5679C60.889 17.5128 61.3529 17.0047 61.3529 16.3962V12.3455C61.3529 11.6334 60.7252 11.0845 60.0194 11.1796Z" fill="#DBDBDB" stroke="#DBDBDB" stroke-width="0.588235" stroke-linecap="round" stroke-linejoin="bevel"/>
+<path d="M51.1704 29.1021L41.8902 29.8481C41.0202 29.918 40.5266 30.8776 40.9756 31.626L42.6523 34.4205C42.8676 34.7793 43.2573 34.9968 43.6758 34.9916L51.2794 34.8968C51.9233 34.8888 52.4412 34.3645 52.4412 33.7205V30.2748C52.4412 29.5879 51.8551 29.0471 51.1704 29.1021Z" fill="#DBDBDB" stroke="#DBDBDB" stroke-width="0.588235" stroke-linecap="round" stroke-linejoin="bevel"/>
+<path d="M61.2104 70.6341V40.1765C61.2104 39.5267 60.6837 39 60.0339 39H44.9909C44.4469 39 43.9738 39.373 43.8469 39.9019L41.118 51.2721C41.0819 51.4226 41.0148 51.5672 40.923 51.6918C37.1778 56.7763 34.7228 57.4741 29.7135 59.6826C29.2815 59.873 29.0064 60.3064 29.0162 60.7783L29.1309 66.295C29.1428 66.8693 29.5679 67.3511 30.1362 67.4345L59.8631 71.7981C60.5732 71.9024 61.2104 71.3519 61.2104 70.6341Z" fill="#DBDBDB" stroke="#DBDBDB" stroke-width="0.588235" stroke-linecap="round" stroke-linejoin="bevel"/>
+<path d="M43.5694 24L36 24.5" stroke="#DBDBDB" stroke-width="1.17647" stroke-linecap="round"/>
+<circle cx="23" cy="40" r="21" stroke="#6E49CB" stroke-width="2.35294"/>
+<circle cx="23" cy="40" r="17" fill="#6E49CB"/>
+<circle cx="23" cy="40" r="17" fill="white" fill-opacity="0.9"/>
+<path d="M22.3125 48V33" stroke="#6E49CB" stroke-width="2.35294" stroke-linecap="round"/>
+<path d="M15 41.3148H30" stroke="#6E49CB" stroke-width="2.35294" stroke-linecap="round"/>
+</svg>
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/import-project.svg b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/import-project.svg
index c507fb8d73d..46b4b097bb6 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/import-project.svg
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/illustrations/import-project.svg
@@ -1,95 +1,38 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="215px" height="115px" viewBox="0 0 215 115" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
- <title>import-project-md</title>
- <desc>Created with Sketch.</desc>
- <g id="import-project-md" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Group-4" transform="translate(14.000000, 15.000000)">
- <g id="Group-7" transform="translate(0.000000, 0.007864)" fill-rule="nonzero">
- <path d="M5.84551724,4.12490066 L61.9641379,4.12490066 C65.1917241,4.12490066 67.8096552,6.76450331 67.8096552,10.0188079 L67.8096552,77.8001325 C67.8096552,81.0544371 65.1917241,83.6940397 61.9641379,83.6940397 L5.84551724,83.6940397 C2.61793103,83.6940397 2.84217094e-14,81.0544371 2.84217094e-14,77.8001325 L2.84217094e-14,10.0188079 C2.84217094e-14,6.76450331 2.61793103,4.12490066 5.84551724,4.12490066 Z" id="Path" fill="#F9F9F9"></path>
- <path d="M8.76965517,1.17933775 L64.8882759,1.17933775 C68.1158621,1.17933775 70.7337931,3.8189404 70.7337931,7.07324503 L70.7337931,74.2649007 C70.7337931,77.5192053 68.1158621,80.1588079 64.8882759,80.1588079 L8.76965517,80.1588079 C5.54206897,80.1588079 2.92413793,77.5192053 2.92413793,74.2649007 L2.92413793,7.07324503 C2.92413793,3.81615894 5.53931034,1.17933775 8.76965517,1.17933775 Z" id="Path" fill="#FFFFFF"></path>
- <path d="M64.8882759,2.20268248e-13 C68.7613793,2.20268248e-13 71.9034483,3.16807947 71.9034483,7.07324503 L71.9024828,19.847 L69.5634828,19.847 L69.5641379,7.07324503 C69.5641379,4.46980132 67.4703448,2.3586755 64.8882759,2.3586755 L8.76965517,2.3586755 L8.76965517,2.35589404 C6.18758621,2.35589404 4.0937931,4.46701987 4.0937931,7.07046358 L4.0937931,74.2621192 C4.0937931,76.8655629 6.18758621,78.9766887 8.76965517,78.9766887 L64.8882759,78.9766887 C67.4703448,78.9766887 69.5641379,76.8655629 69.5641379,74.2621192 L69.5624828,54.847 L71.9014828,54.847 L71.9034483,74.2649007 C71.9034483,78.1700662 68.7613793,81.3381457 64.8882759,81.3381457 L8.76965517,81.3381457 C4.89655172,81.3381457 1.75448276,78.1700662 1.75448276,74.2649007 L1.75448276,7.07324503 C1.75448276,3.16529801 4.8937931,2.20268248e-13 8.76965517,2.20268248e-13 L64.8882759,2.20268248e-13 Z M71.9014828,44.847 L71.9004828,48.847 L69.5614828,48.847 L69.5624828,44.847 L71.9014828,44.847 Z M71.9024828,26.847 L71.9014828,31.847 L69.5624828,31.847 L69.5634828,26.847 L71.9024828,26.847 Z" id="Combined-Shape" fill="#EEEEEE"></path>
- <path d="M14.6151724,14.7333775 L21.6275862,14.7333775 C22.2731034,14.7333775 22.7972414,15.2618543 22.7972414,15.9127152 C22.7972414,16.5635762 22.2731034,17.092053 21.6275862,17.092053 L14.6151724,17.092053 C13.9696552,17.092053 13.4455172,16.5635762 13.4455172,15.9127152 C13.4455172,15.2618543 13.9696552,14.7333775 14.6151724,14.7333775 Z M33.3213793,21.8066225 L40.3365517,21.8066225 C40.982069,21.8066225 41.5062069,22.3350993 41.5062069,22.9859603 C41.5062069,23.6368212 40.982069,24.165298 40.3365517,24.165298 L33.3213793,24.165298 C32.6758621,24.165298 32.1517241,23.6368212 32.1517241,22.9859603 C32.1517241,22.3350993 32.6731034,21.8066225 33.3213793,21.8066225 Z" id="Shape" fill="#E1DBF1"></path>
- <path d="M40.3337931,14.7333775 L47.3489655,14.7333775 C47.9944828,14.7333775 48.5186207,15.2618543 48.5186207,15.9127152 C48.5186207,16.5635762 47.9944828,17.092053 47.3489655,17.092053 L40.3337931,17.092053 C39.6882759,17.092053 39.1641379,16.5635762 39.1641379,15.9127152 C39.1668966,15.2618543 39.6882759,14.7333775 40.3337931,14.7333775 Z" id="Path" fill="#EEEEEE"></path>
- <path d="M21.6275862,28.8798675 L28.6427586,28.8798675 C29.2882759,28.8798675 29.8124138,29.4083444 29.8124138,30.0592053 C29.8124138,30.7100662 29.2882759,31.238543 28.6427586,31.238543 L21.6275862,31.238543 C20.982069,31.238543 20.457931,30.7100662 20.457931,30.0592053 C20.4606897,29.4083444 20.982069,28.8798675 21.6275862,28.8798675 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M26.3062069,14.7333775 L28.6455172,14.7333775 C29.2910345,14.7333775 29.8151724,15.2618543 29.8151724,15.9127152 C29.8151724,16.5635762 29.2910345,17.092053 28.6455172,17.092053 L26.3062069,17.092053 C25.6606897,17.092053 25.1365517,16.5635762 25.1365517,15.9127152 C25.1365517,15.2618543 25.6606897,14.7333775 26.3062069,14.7333775 Z" id="Path" fill="#FEE1D3"></path>
- <path d="M33.3213793,35.9531126 L35.6606897,35.9531126 C36.3062069,35.9531126 36.8303448,36.4815894 36.8303448,37.1324503 C36.8303448,37.7833113 36.3062069,38.3117881 35.6606897,38.3117881 L33.3213793,38.3117881 C32.6758621,38.3117881 32.1517241,37.7833113 32.1517241,37.1324503 C32.1517241,36.4815894 32.6731034,35.9531126 33.3213793,35.9531126 Z" id="Path" fill="#FC6D26"></path>
- <path d="M52.0248276,14.7333775 L54.3641379,14.7333775 C55.0096552,14.7333775 55.5337931,15.2618543 55.5337931,15.9127152 C55.5337931,16.5635762 55.0096552,17.092053 54.3641379,17.092053 L52.0248276,17.092053 C51.3793103,17.092053 50.8551724,16.5635762 50.8551724,15.9127152 C50.857931,15.2618543 51.3793103,14.7333775 52.0248276,14.7333775 Z" id="Shape" fill="#FEF0E8"></path>
- <path d="M23.9668966,43.0263576 L28.6427586,43.0263576 C29.2882759,43.0263576 29.8124138,43.5548344 29.8124138,44.2056954 C29.8124138,44.8565563 29.2882759,45.3850331 28.6427586,45.3850331 L23.9668966,45.3850331 C23.3213793,45.3850331 22.7972414,44.8565563 22.7972414,44.2056954 C22.7972414,43.5548344 23.3213793,43.0263576 23.9668966,43.0263576 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M40.3337931,35.9531126 L42.6731034,35.9531126 C43.3186207,35.9531126 43.8427586,36.4815894 43.8427586,37.1324503 C43.8427586,37.7833113 43.3186207,38.3117881 42.6731034,38.3117881 L40.3337931,38.3117881 C39.6882759,38.3117881 39.1641379,37.7833113 39.1641379,37.1324503 C39.1641379,36.4815894 39.6882759,35.9531126 40.3337931,35.9531126 Z" id="Path" fill="#FC6D26"></path>
- <path d="M52.3172414,33.5944371 C53.1255172,33.5944371 53.7793103,34.2536424 53.7793103,35.0686093 C53.7793103,35.8835762 53.1255172,36.5427815 52.3172414,36.5427815 C51.5089655,36.5427815 50.8551724,35.8835762 50.8551724,35.0686093 C50.8551724,34.2536424 51.5117241,33.5944371 52.3172414,33.5944371 Z M58.1627586,50.6892715 C58.9710345,50.6892715 59.6248276,51.3484768 59.6248276,52.1634437 C59.6248276,52.9784106 58.9710345,53.6376159 58.1627586,53.6376159 C57.3544828,53.6376159 56.7006897,52.9784106 56.7006897,52.1634437 C56.7006897,51.3484768 57.3572414,50.6892715 58.1627586,50.6892715 Z" id="Shape" fill="#E1DBF1"></path>
- <path d="M63.4262069,50.6892715 C64.2344828,50.6892715 64.8882759,51.3484768 64.8882759,52.1634437 C64.8882759,52.9784106 64.2344828,53.6376159 63.4262069,53.6376159 C62.617931,53.6376159 61.9641379,52.9784106 61.9641379,52.1634437 C61.9641379,51.3484768 62.617931,50.6892715 63.4262069,50.6892715 Z M33.3213793,14.7333775 L35.6606897,14.7333775 C36.3062069,14.7333775 36.8303448,15.2618543 36.8303448,15.9127152 C36.8303448,16.5635762 36.3062069,17.092053 35.6606897,17.092053 L33.3213793,17.092053 C32.6758621,17.092053 32.1517241,16.5635762 32.1517241,15.9127152 C32.1517241,15.2618543 32.6731034,14.7333775 33.3213793,14.7333775 Z" id="Shape" fill="#FC6D26"></path>
- <path d="M59.1696552,33.8470199 L66.182069,33.8470199 C66.8275862,33.8470199 67.3517241,34.3754967 67.3517241,35.0263576 C67.3517241,35.6772185 66.8275862,36.2056954 66.182069,36.2056954 L59.1696552,36.2056954 C58.5241379,36.2056954 58,35.6772185 58,35.0263576 C58,34.3754967 58.5241379,33.8470199 59.1696552,33.8470199 Z" id="Shape" fill="#E1DBF1"></path>
- <path d="M70.8606897,33.8470199 L73.2,33.8470199 C73.8455172,33.8470199 74.3696552,34.3754967 74.3696552,35.0263576 C74.3696552,35.6772185 73.8455172,36.2056954 73.2,36.2056954 L70.8606897,36.2056954 C70.2151724,36.2056954 69.6910345,35.6772185 69.6910345,35.0263576 C69.6910345,34.3754967 70.2151724,33.8470199 70.8606897,33.8470199 Z" id="Path" fill="#FEE1D3"></path>
- <path d="M77.8758621,33.8470199 L80.2151724,33.8470199 C80.8606897,33.8470199 81.3848276,34.3754967 81.3848276,35.0263576 C81.3848276,35.6772185 80.8606897,36.2056954 80.2151724,36.2056954 L77.8758621,36.2056954 C77.2303448,36.2056954 76.7062069,35.6772185 76.7062069,35.0263576 C76.7062069,34.3754967 77.2275862,33.8470199 77.8758621,33.8470199 Z" id="Shape" fill="#FC6D26"></path>
- <path d="M14.6151724,35.9531126 L28.6455172,35.9531126 C29.2910345,35.9531126 29.8151724,36.4815894 29.8151724,37.1324503 C29.8151724,37.7833113 29.2910345,38.3117881 28.6455172,38.3117881 L14.6151724,38.3117881 C13.9696552,38.3117881 13.4455172,37.7833113 13.4455172,37.1324503 C13.4455172,36.4815894 13.9696552,35.9531126 14.6151724,35.9531126 Z M44.0937931,41.8470199 L61.1282759,41.8470199 C61.9117241,41.8470199 62.5489655,42.5062252 62.5489655,43.3211921 C62.5489655,44.1361589 61.9144828,44.7953642 61.1282759,44.7953642 L44.0937931,44.7953642 C43.3103448,44.7953642 42.6731034,44.1361589 42.6731034,43.3211921 C42.6731034,42.5062252 43.3103448,41.8470199 44.0937931,41.8470199 L44.0937931,41.8470199 L44.0937931,41.8470199 Z" id="Shape" fill="#EEEEEE"></path>
- <path d="M35.3241379,50.6892715 L52.3586207,50.6892715 C53.142069,50.6892715 53.7793103,51.3484768 53.7793103,52.1634437 C53.7793103,52.9784106 53.1448276,53.6376159 52.3586207,53.6376159 L35.3241379,53.6376159 C34.5406897,53.6376159 33.9034483,52.9784106 33.9034483,52.1634437 C33.9034483,51.3484768 34.5406897,50.6892715 35.3241379,50.6892715 L35.3241379,50.6892715 L35.3241379,50.6892715 Z" id="Path" fill="#EFEDF8"></path>
- <path d="M14.6151724,21.8066225 L28.6455172,21.8066225 C29.2910345,21.8066225 29.8151724,22.3350993 29.8151724,22.9859603 C29.8151724,23.6368212 29.2910345,24.165298 28.6455172,24.165298 L14.6151724,24.165298 C13.9696552,24.165298 13.4455172,23.6368212 13.4455172,22.9859603 C13.4455172,22.3350993 13.9696552,21.8066225 14.6151724,21.8066225 Z" id="Path" fill="#6B4FBB"></path>
- <path d="M33.3213793,28.8798675 L47.3517241,28.8798675 C47.9972414,28.8798675 48.5213793,29.4083444 48.5213793,30.0592053 C48.5213793,30.7100662 47.9972414,31.238543 47.3517241,31.238543 L33.3213793,31.238543 C32.6758621,31.238543 32.1517241,30.7100662 32.1517241,30.0592053 C32.1517241,29.4083444 32.6731034,28.8798675 33.3213793,28.8798675 Z" id="Path" fill="#C3B8E3"></path>
- <path d="M14.6151724,28.8798675 L16.9544828,28.8798675 C17.6,28.8798675 18.1241379,29.4083444 18.1241379,30.0592053 C18.1241379,30.7100662 17.6,31.238543 16.9544828,31.238543 L14.6151724,31.238543 C13.9696552,31.238543 13.4455172,30.7100662 13.4455172,30.0592053 C13.4455172,29.4083444 13.9696552,28.8798675 14.6151724,28.8798675 Z" id="Path" fill="#FEF0E8"></path>
- <path d="M75.182069,50.8470199 L82.1972414,50.8470199 C82.8427586,50.8470199 83.3668966,51.3754967 83.3668966,52.0263576 C83.3668966,52.6772185 82.8427586,53.2056954 82.1972414,53.2056954 L75.182069,53.2056954 C74.5365517,53.2056954 74.0124138,52.6772185 74.0124138,52.0263576 C74.0151724,51.3754967 74.5365517,50.8470199 75.182069,50.8470199 Z" id="Path" fill="#E1DBF1"></path>
- <path d="M86.8758621,50.8470199 L100.906207,50.8470199 C101.551724,50.8470199 102.075862,51.5079868 102.075862,52.3220199 C102.075862,53.1360529 101.551724,53.7970199 100.906207,53.7970199 L86.8758621,53.7970199 C86.2303448,53.7970199 85.7062069,53.1360529 85.7062069,52.3220199 C85.7062069,51.5079868 86.2275862,50.8470199 86.8758621,50.8470199 Z" id="Path" fill="#C3B8E3"></path>
- <path d="M68.1696552,50.8470199 L70.5089655,50.8470199 C71.1544828,50.8470199 71.6786207,51.3754967 71.6786207,52.0263576 C71.6786207,52.6772185 71.1544828,53.2056954 70.5089655,53.2056954 L68.1696552,53.2056954 C67.5241379,53.2056954 67,52.6772185 67,52.0263576 C67,51.3754967 67.5241379,50.8470199 68.1696552,50.8470199 Z" id="Path" fill="#FEF0E8"></path>
- <path d="M33.3213793,43.0263576 L35.6606897,43.0263576 C36.3062069,43.0263576 36.8303448,43.5548344 36.8303448,44.2056954 C36.8303448,44.8565563 36.3062069,45.3850331 35.6606897,45.3850331 L33.3213793,45.3850331 C32.6758621,45.3850331 32.1517241,44.8565563 32.1517241,44.2056954 C32.1517241,43.5548344 32.6731034,43.0263576 33.3213793,43.0263576 Z" id="Path" fill="#6B4FBB"></path>
- <path d="M14.6151724,43.0263576 L19.2910345,43.0263576 C19.9365517,43.0263576 20.4606897,43.5548344 20.4606897,44.2056954 C20.4606897,44.8565563 19.9365517,45.3850331 19.2910345,45.3850331 L14.6151724,45.3850331 C13.9696552,45.3850331 13.4455172,44.8565563 13.4455172,44.2056954 C13.4455172,43.5548344 13.9696552,43.0263576 14.6151724,43.0263576 Z" id="Path" fill="#FC6D26"></path>
- <path d="M14.6151724,50.0996026 L19.2910345,50.0996026 C19.9365517,50.0996026 20.4606897,50.6280795 20.4606897,51.2789404 C20.4606897,51.9298013 19.9365517,52.4582781 19.2910345,52.4582781 L14.6151724,52.4582781 C13.9696552,52.4582781 13.4455172,51.9298013 13.4455172,51.2789404 C13.4455172,50.625298 13.9696552,50.0996026 14.6151724,50.0996026 Z M23.9668966,50.0996026 L28.6427586,50.0996026 C29.2882759,50.0996026 29.8124138,50.6280795 29.8124138,51.2789404 C29.8124138,51.9298013 29.2882759,52.4582781 28.6427586,52.4582781 L23.9668966,52.4582781 C23.3213793,52.4582781 22.7972414,51.9298013 22.7972414,51.2789404 C22.7972414,50.625298 23.3213793,50.0996026 23.9668966,50.0996026 Z" id="Shape" fill="#FEF0E8"></path>
- <path d="M88.7172414,21.8029139 C89.5255172,21.8029139 90.1793103,22.4621192 90.1793103,23.2770861 C90.1793103,24.092053 89.5255172,24.7512583 88.7172414,24.7512583 C87.9089655,24.7512583 87.2551724,24.092053 87.2551724,23.2770861 C87.2551724,22.4621192 87.9117241,21.8029139 88.7172414,21.8029139 Z" id="Shape" fill="#FEE1D3"></path>
- <path d="M93.9806897,21.8029139 C94.7889655,21.8029139 95.4427586,22.4621192 95.4427586,23.2770861 C95.4427586,24.092053 94.7889655,24.7512583 93.9806897,24.7512583 C93.1724138,24.7512583 92.5186207,24.092053 92.5186207,23.2770861 C92.5186207,22.4621192 93.1724138,21.8029139 93.9806897,21.8029139 Z" id="Shape" fill="#6B4FBB"></path>
- <path d="M65.8786207,21.8029139 L82.9131034,21.8029139 C83.6965517,21.8029139 84.3337931,22.4624894 84.3337931,23.2779139 C84.3337931,24.0933384 83.6993103,24.7529139 82.9131034,24.7529139 L65.8786207,24.7529139 C65.0951724,24.7529139 64.457931,24.0933384 64.457931,23.2779139 C64.457931,22.4624894 65.0951724,21.8029139 65.8786207,21.8029139 L65.8786207,21.8029139 L65.8786207,21.8029139 Z" id="Path" fill="#FC6D26"></path>
- <path d="M54.5213793,21.213245 L59.1972414,21.213245 C59.8427586,21.213245 60.3668966,21.7417219 60.3668966,22.3925828 C60.3668966,23.0434437 59.8427586,23.5719205 59.1972414,23.5719205 L54.5213793,23.5719205 C53.8758621,23.5719205 53.3517241,23.0434437 53.3517241,22.3925828 C53.3517241,21.7389404 53.8758621,21.213245 54.5213793,21.213245 Z" id="Shape" fill="#FEF0E8"></path>
- <path d="M45.1696552,21.213245 L49.8455172,21.213245 C50.4910345,21.213245 51.0151724,21.7417219 51.0151724,22.3925828 C51.0151724,23.0434437 50.4910345,23.5719205 49.8455172,23.5719205 L45.1696552,23.5719205 C44.5241379,23.5719205 44,23.0434437 44,22.3925828 C44,21.7389404 44.5241379,21.213245 45.1696552,21.213245 Z" id="Path" fill="#EEEEEE"></path>
- <path d="M14.6151724,57.1728477 L21.6275862,57.1728477 C22.2731034,57.1728477 22.7972414,57.7013245 22.7972414,58.3521854 C22.7972414,59.0030464 22.2731034,59.5315232 21.6275862,59.5315232 L14.6151724,59.5315232 C13.9696552,59.5315232 13.4455172,59.0030464 13.4455172,58.3521854 C13.4455172,57.698543 13.9696552,57.1728477 14.6151724,57.1728477 Z" id="Path" fill="#EFEDF8"></path>
- <path d="M25.3544828,64.2433113 L33.6855172,64.2433113 C34.4524138,64.2433113 35.0731034,64.7717881 35.0731034,65.422649 C35.0731034,66.0735099 34.4524138,66.6019868 33.6855172,66.6019868 L25.3544828,66.6019868 C24.5875862,66.6019868 23.9668966,66.0735099 23.9668966,65.422649 C23.9668966,64.7717881 24.5875862,64.2433113 25.3544828,64.2433113 Z" id="Path" fill="#FC6D26"></path>
- <path d="M44.0606897,58.9390728 L52.3917241,58.9390728 C53.1586207,58.9390728 53.7793103,59.5982781 53.7793103,60.413245 C53.7793103,61.2254305 53.1586207,61.8874172 52.3917241,61.8874172 L44.0606897,61.8874172 C43.2937931,61.8874172 42.6731034,61.2282119 42.6731034,60.413245 C42.6731034,59.6010596 43.2937931,58.9390728 44.0606897,58.9390728 Z" id="Path" fill="#6B4FBB"></path>
- <path d="M26.3062069,57.1728477 L28.6455172,57.1728477 C29.2910345,57.1728477 29.8151724,57.7013245 29.8151724,58.3521854 C29.8151724,59.0030464 29.2910345,59.5315232 28.6455172,59.5315232 L26.3062069,59.5315232 C25.6606897,59.5315232 25.1365517,59.0030464 25.1365517,58.3521854 C25.1365517,57.698543 25.6606897,57.1728477 26.3062069,57.1728477 Z" id="Path" fill="#FEE1D3"></path>
- <path d="M36.8275862,64.2433113 L39.1668966,64.2433113 C39.8124138,64.2433113 40.3365517,64.7717881 40.3365517,65.422649 C40.3365517,66.0735099 39.8124138,66.6019868 39.1668966,66.6019868 L36.8275862,66.6019868 C36.182069,66.6019868 35.657931,66.0735099 35.657931,65.422649 C35.657931,64.7717881 36.182069,64.2433113 36.8275862,64.2433113 Z M58.1627586,58.9390728 L61.0868966,58.9390728 C61.8951724,58.9390728 62.5489655,59.5982781 62.5489655,60.413245 C62.5489655,61.2282119 61.8951724,61.8874172 61.0868966,61.8874172 L58.1627586,61.8874172 C57.3544828,61.8874172 56.7006897,61.2282119 56.7006897,60.413245 C56.7034483,59.5982781 57.3572414,58.9390728 58.1627586,58.9390728 Z" id="Shape" fill="#FEF0E8"></path>
- <path d="M35.3655172,58.9390728 L38.2896552,58.9390728 C39.097931,58.9390728 39.7517241,59.5982781 39.7517241,60.413245 C39.7517241,61.2282119 39.097931,61.8874172 38.2896552,61.8874172 L35.3655172,61.8874172 C34.5572414,61.8874172 33.9034483,61.2282119 33.9034483,60.413245 C33.9034483,59.5982781 34.56,58.9390728 35.3655172,58.9390728 Z" id="Path" fill="#FC6D26"></path>
- <path d="M66.1696552,40.8470199 L73.182069,40.8470199 C73.8275862,40.8470199 74.3517241,41.3754967 74.3517241,42.0263576 C74.3517241,42.6772185 73.8275862,43.2056954 73.182069,43.2056954 L66.1696552,43.2056954 C65.5241379,43.2056954 65,42.6772185 65,42.0263576 C65,41.3727152 65.5241379,40.8470199 66.1696552,40.8470199 Z" id="Path" fill="#EFEDF8"></path>
- <path d="M95.6151724,42.613245 L103.946207,42.613245 C104.713103,42.613245 105.333793,43.1409054 105.333793,43.793245 C105.333793,44.4433582 104.713103,44.973245 103.946207,44.973245 L95.6151724,44.973245 C94.8482759,44.973245 94.2275862,44.4455847 94.2275862,43.793245 C94.2275862,43.1431318 94.8482759,42.613245 95.6151724,42.613245 Z" id="Path" fill="#6B4FBB"></path>
- <path d="M77.8606897,40.8470199 L80.2,40.8470199 C80.8455172,40.8470199 81.3696552,41.3754967 81.3696552,42.0263576 C81.3696552,42.6772185 80.8455172,43.2056954 80.2,43.2056954 L77.8606897,43.2056954 C77.2151724,43.2056954 76.6910345,42.6772185 76.6910345,42.0263576 C76.6910345,41.3727152 77.2151724,40.8470199 77.8606897,40.8470199 Z" id="Path" fill="#FEE1D3"></path>
- <path d="M86.92,42.613245 L89.8441379,42.613245 C90.6524138,42.613245 91.3062069,43.1409054 91.3062069,43.793245 C91.3062069,44.4455847 90.6524138,44.973245 89.8441379,44.973245 L86.92,44.973245 C86.1117241,44.973245 85.457931,44.4455847 85.457931,43.793245 C85.457931,43.1409054 86.1144828,42.613245 86.92,42.613245 Z" id="Path" fill="#FC6D26"></path>
- <path d="M14.6151724,64.2433113 L20.4606897,64.2433113 C21.1062069,64.2433113 21.6303448,64.7717881 21.6303448,65.422649 C21.6303448,66.0735099 21.1062069,66.6019868 20.4606897,66.6019868 L14.6151724,66.6019868 C13.9696552,66.6019868 13.4455172,66.0735099 13.4455172,65.422649 C13.4455172,64.7717881 13.9696552,64.2433113 14.6151724,64.2433113 Z" id="Path" fill="#EEEEEE"></path>
- </g>
- <g id="Group-12" transform="translate(112.058152, -0.000000)">
- <path d="M5.84861758,4.12465116 L62.0003099,4.12465116 C65.229233,4.12465116 67.8489253,6.76465116 67.8489253,10.0186047 L67.8489253,77.8046512 C67.8489253,81.0586047 65.229233,83.6986047 62.0003099,83.6986047 L5.84861758,83.6986047 C2.6196945,83.6986047 1.42108547e-14,81.0586047 1.42108547e-14,77.8046512 L1.42108547e-14,10.0213953 C-0.00276703963,6.76744186 2.6196945,4.12465116 5.84861758,4.12465116 Z" id="Path" fill="#F9F9F9" fill-rule="nonzero"></path>
- <path d="M8.77292527,1.17767442 L64.9246176,1.17767442 C68.1535407,1.17767442 70.773233,3.81767442 70.773233,7.07162791 L70.773233,74.2688372 C70.773233,77.5227907 68.1535407,80.1627907 64.9246176,80.1627907 L8.77292527,80.1627907 C5.54400219,80.1627907 2.92430988,77.5227907 2.92430988,74.2688372 L2.92430988,7.07162791 C2.92430988,3.81767442 5.54400219,1.17767442 8.77292527,1.17767442 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
- <path d="M8.77292527,2.35813953 C6.18646373,2.35813953 4.09292527,4.46790698 4.09292527,7.0744186 L4.09292527,74.2716279 C4.09292527,76.8781395 6.18646373,78.987907 8.77292527,78.987907 L64.9246176,78.987907 C67.5110791,78.987907 69.6046176,76.8781395 69.6046176,74.2716279 L69.6046176,7.07162791 C69.6046176,4.46511628 67.5110791,2.35534884 64.9246176,2.35534884 L8.77292527,2.35813953 L8.77292527,2.35813953 Z M8.77292527,-4.19220214e-13 L64.9246176,-4.19220214e-13 C68.8043099,-4.19220214e-13 71.9418483,3.16744186 71.9418483,7.07162791 L71.9418483,74.2688372 C71.9418483,78.1786047 68.7987714,81.3404651 64.9246176,81.3404651 L8.77292527,81.3404651 C4.89323296,81.3404651 1.75569267,78.1730233 1.75569267,74.2688372 L1.75569267,7.07162791 C1.75292527,3.17023256 4.89600219,-4.19220214e-13 8.77292527,-4.19220214e-13 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M14.6215407,14.7348837 L21.6387714,14.7348837 C22.281233,14.7348837 22.8073868,15.2651163 22.8073868,15.9125581 C22.8073868,16.56 22.281233,17.0902326 21.6387714,17.0902326 L14.6215407,17.0902326 C13.9790791,17.0902326 13.4529253,16.56 13.4529253,15.9125581 C13.4529253,15.2651163 13.9763099,14.7348837 14.6215407,14.7348837 Z M33.3387714,21.8093023 L40.3560022,21.8093023 C40.9984637,21.8093023 41.5246176,22.3395349 41.5246176,22.9869767 C41.5246176,23.6344186 40.9984637,24.1646512 40.3560022,24.1646512 L33.3387714,24.1646512 C32.6963099,24.1646512 32.170156,23.6344186 32.170156,22.9869767 C32.170156,22.3395349 32.6963099,21.8093023 33.3387714,21.8093023 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M40.3587714,14.7348837 L47.3760022,14.7348837 C48.0184637,14.7348837 48.5446176,15.2651163 48.5446176,15.9125581 C48.5446176,16.56 48.0184637,17.0902326 47.3760022,17.0902326 L40.3587714,17.0902326 C39.7163099,17.0902326 39.1901452,16.56 39.1901452,15.9125581 C39.1873868,15.267907 39.7163099,14.7348837 40.3587714,14.7348837 Z" id="Path" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M21.6415407,28.8837209 L28.6587714,28.8837209 C29.301233,28.8837209 29.8273868,29.4139535 29.8273868,30.0613953 C29.8273868,30.7088372 29.301233,31.2390698 28.6587714,31.2390698 L21.6415407,31.2390698 C20.9990791,31.2390698 20.4729253,30.7088372 20.4729253,30.0613953 C20.4729253,29.4139535 20.9990791,28.8837209 21.6415407,28.8837209 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M26.3187714,14.7348837 L28.6587714,14.7348837 C29.301233,14.7348837 29.8273868,15.2651163 29.8273868,15.9125581 C29.8273868,16.56 29.301233,17.0902326 28.6587714,17.0902326 L26.3187714,17.0902326 C25.6763099,17.0902326 25.150156,16.56 25.150156,15.9125581 C25.150156,15.2651163 25.6763099,14.7348837 26.3187714,14.7348837 Z" id="Path" fill="#FEE1D3" fill-rule="nonzero"></path>
- <path d="M33.3387714,35.9553488 L35.6787714,35.9553488 C36.321233,35.9553488 36.8473868,36.4855814 36.8473868,37.1330233 C36.8473868,37.7804651 36.321233,38.3106977 35.6787714,38.3106977 L33.3387714,38.3106977 C32.6963099,38.3106977 32.170156,37.7804651 32.170156,37.1330233 C32.170156,36.4855814 32.6963099,35.9553488 33.3387714,35.9553488 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M45.0360022,21.8093023 L47.3760022,21.8093023 C48.0184637,21.8093023 48.5446176,22.3395349 48.5446176,22.9869767 C48.5446176,23.6344186 48.0184637,24.1646512 47.3760022,24.1646512 L45.0360022,24.1646512 C44.3935407,24.1646512 43.8673868,23.6344186 43.8673868,22.9869767 C43.8673868,22.3395349 44.3935407,21.8093023 45.0360022,21.8093023 Z M52.0560022,14.7348837 L54.3960022,14.7348837 C55.0384637,14.7348837 55.5646176,15.2651163 55.5646176,15.9125581 C55.5646176,16.56 55.0384637,17.0902326 54.3960022,17.0902326 L52.0560022,17.0902326 C51.4135407,17.0902326 50.8873868,16.56 50.8873868,15.9125581 C50.8873868,15.2651163 51.4135407,14.7348837 52.0560022,14.7348837 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M23.9787714,43.0297674 L28.6587714,43.0297674 C29.301233,43.0297674 29.8273868,43.56 29.8273868,44.2074419 C29.8273868,44.8548837 29.301233,45.3851163 28.6587714,45.3851163 L23.9787714,45.3851163 C23.3363099,45.3851163 22.810156,44.8548837 22.810156,44.2074419 C22.810156,43.56 23.3363099,43.0297674 23.9787714,43.0297674 Z" id="Path" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M40.3587714,35.9553488 L42.6987714,35.9553488 C43.341233,35.9553488 43.8673868,36.4855814 43.8673868,37.1330233 C43.8673868,37.7804651 43.341233,38.3106977 42.6987714,38.3106977 L40.3587714,38.3106977 C39.7163099,38.3106977 39.1901452,37.7804651 39.1901452,37.1330233 C39.1873868,36.4883721 39.7163099,35.9553488 40.3587714,35.9553488 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M52.3495407,33.5972093 C53.158156,33.5972093 53.8116945,34.255814 53.8116945,35.0706977 C53.8116945,35.8855814 53.158156,36.544186 52.3495407,36.544186 C51.5409253,36.544186 50.8873868,35.8855814 50.8873868,35.0706977 C50.8873868,34.2586047 51.5436945,33.5972093 52.3495407,33.5972093 Z M58.198156,50.6930233 C59.0067714,50.6930233 59.6603099,51.3516279 59.6603099,52.1665116 C59.6603099,52.9813953 59.0067714,53.64 58.198156,53.64 C57.3895407,53.64 56.7360022,52.9813953 56.7360022,52.1665116 C56.7360022,51.3516279 57.3895407,50.6930233 58.198156,50.6930233 Z" id="Shape" fill="#E1DBF1" fill-rule="nonzero"></path>
- <path d="M63.4624637,50.6930233 C64.2710791,50.6930233 64.9246176,51.3516279 64.9246176,52.1665116 C64.9246176,52.9813953 64.2710791,53.64 63.4624637,53.64 C62.6538483,53.64 62.0003099,52.9813953 62.0003099,52.1665116 C62.0003099,51.3516279 62.6566176,50.6930233 63.4624637,50.6930233 Z M33.3387714,14.7348837 L35.6787714,14.7348837 C36.321233,14.7348837 36.8473868,15.2651163 36.8473868,15.9125581 C36.8473868,16.56 36.321233,17.0902326 35.6787714,17.0902326 L33.3387714,17.0902326 C32.6963099,17.0902326 32.170156,16.56 32.170156,15.9125581 C32.170156,15.2651163 32.6963099,14.7348837 33.3387714,14.7348837 Z" id="Shape" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6215407,35.9553488 L28.6615407,35.9553488 C29.3040022,35.9553488 29.830156,36.4855814 29.830156,37.1330233 C29.830156,37.7804651 29.3040022,38.3106977 28.6615407,38.3106977 L14.6215407,38.3106977 C13.9790791,38.3106977 13.4529253,37.7804651 13.4529253,37.1330233 C13.4529253,36.4855814 13.9763099,35.9553488 14.6215407,35.9553488 Z M44.1193868,41.8493023 L61.1640022,41.8493023 C61.9476945,41.8493023 62.5873868,42.507907 62.5873868,43.3227907 C62.5873868,44.1376744 61.9504637,44.7962791 61.1640022,44.7962791 L44.1193868,44.7962791 C43.3356945,44.7962791 42.6960022,44.1376744 42.6960022,43.3227907 C42.6960022,42.507907 43.3356945,41.8493023 44.1193868,41.8493023 L44.1193868,41.8493023 L44.1193868,41.8493023 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M35.3464637,50.6930233 L52.3910791,50.6930233 C53.1747714,50.6930233 53.8144637,51.3516279 53.8144637,52.1665116 C53.8144637,52.9813953 53.1775407,53.64 52.3910791,53.64 L35.3464637,53.64 C34.5627714,53.64 33.9230791,52.9813953 33.9230791,52.1665116 C33.9230791,51.3516279 34.5600022,50.6930233 35.3464637,50.6930233 L35.3464637,50.6930233 L35.3464637,50.6930233 Z" id="Path" fill="#EFEDF8" fill-rule="nonzero"></path>
- <path d="M14.6215407,21.8093023 L28.6615407,21.8093023 C29.3040022,21.8093023 29.830156,22.3395349 29.830156,22.9869767 C29.830156,23.6344186 29.3040022,24.1646512 28.6615407,24.1646512 L14.6215407,24.1646512 C13.9790791,24.1646512 13.4529253,23.6344186 13.4529253,22.9869767 C13.4529253,22.3395349 13.9763099,21.8093023 14.6215407,21.8093023 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M33.3387714,28.8837209 L47.3787714,28.8837209 C48.021233,28.8837209 48.5473868,29.4139535 48.5473868,30.0613953 C48.5473868,30.7088372 48.021233,31.2390698 47.3787714,31.2390698 L33.3387714,31.2390698 C32.6963099,31.2390698 32.170156,30.7088372 32.170156,30.0613953 C32.170156,29.4139535 32.6963099,28.8837209 33.3387714,28.8837209 Z" id="Path" fill="#C3B8E3" fill-rule="nonzero"></path>
- <path d="M14.6215407,28.8837209 L16.9615407,28.8837209 C17.6040022,28.8837209 18.130156,29.4139535 18.130156,30.0613953 C18.130156,30.7088372 17.6040022,31.2390698 16.9615407,31.2390698 L14.6215407,31.2390698 C13.9790791,31.2390698 13.4529253,30.7088372 13.4529253,30.0613953 C13.4529253,29.4139535 13.9763099,28.8837209 14.6215407,28.8837209 Z" id="Path" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M33.3387714,43.0297674 L35.6787714,43.0297674 C36.321233,43.0297674 36.8473868,43.56 36.8473868,44.2074419 C36.8473868,44.8548837 36.321233,45.3851163 35.6787714,45.3851163 L33.3387714,45.3851163 C32.6963099,45.3851163 32.170156,44.8548837 32.170156,44.2074419 C32.170156,43.56 32.6963099,43.0297674 33.3387714,43.0297674 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M14.6215407,43.0297674 L19.3015407,43.0297674 C19.9440022,43.0297674 20.470156,43.56 20.470156,44.2074419 C20.470156,44.8548837 19.9440022,45.3851163 19.3015407,45.3851163 L14.6215407,45.3851163 C13.9790791,45.3851163 13.4529253,44.8548837 13.4529253,44.2074419 C13.4529253,43.56 13.9763099,43.0297674 14.6215407,43.0297674 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6215407,50.104186 L19.3015407,50.104186 C19.9440022,50.104186 20.470156,50.6344186 20.470156,51.2818605 C20.470156,51.9293023 19.9440022,52.4595349 19.3015407,52.4595349 L14.6215407,52.4595349 C13.9790791,52.4595349 13.4529253,51.9293023 13.4529253,51.2818605 C13.4529253,50.6344186 13.9763099,50.104186 14.6215407,50.104186 Z M23.9787714,50.104186 L28.6587714,50.104186 C29.301233,50.104186 29.8273868,50.6344186 29.8273868,51.2818605 C29.8273868,51.9293023 29.301233,52.4595349 28.6587714,52.4595349 L23.9787714,52.4595349 C23.3363099,52.4595349 22.810156,51.9293023 22.810156,51.2818605 C22.810156,50.6344186 23.3363099,50.104186 23.9787714,50.104186 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M14.6215407,57.175814 L21.6387714,57.175814 C22.281233,57.175814 22.8073868,57.7060465 22.8073868,58.3534884 C22.8073868,59.0009302 22.281233,59.5311628 21.6387714,59.5311628 L14.6215407,59.5311628 C13.9790791,59.5311628 13.4529253,59.0009302 13.4529253,58.3534884 C13.4529253,57.7060465 13.9763099,57.175814 14.6215407,57.175814 Z" id="Path" fill="#EFEDF8" fill-rule="nonzero"></path>
- <path d="M25.366156,64.2502326 L33.7015407,64.2502326 C34.4686176,64.2502326 35.0916945,64.7748837 35.0916945,65.427907 C35.0916945,66.0753488 34.4713868,66.6055814 33.7015407,66.6055814 L25.366156,66.6055814 C24.5990791,66.6055814 23.9760022,66.0753488 23.9760022,65.427907 C23.9787714,64.7804651 24.6018483,64.2502326 25.366156,64.2502326 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M44.0833868,58.9451163 L52.4187714,58.9451163 C53.1858483,58.9451163 53.8089253,59.6037209 53.8089253,60.4186047 C53.8089253,61.2334884 53.1886176,61.892093 52.4187714,61.892093 L44.0833868,61.892093 C43.3163099,61.892093 42.693233,61.2334884 42.693233,60.4186047 C42.6960022,59.6065116 43.3190791,58.9451163 44.0833868,58.9451163 Z" id="Path" fill="#6B4FBB" fill-rule="nonzero"></path>
- <path d="M26.3187714,57.175814 L28.6587714,57.175814 C29.301233,57.175814 29.8273868,57.7060465 29.8273868,58.3534884 C29.8273868,59.0009302 29.301233,59.5311628 28.6587714,59.5311628 L26.3187714,59.5311628 C25.6763099,59.5311628 25.150156,59.0009302 25.150156,58.3534884 C25.150156,57.7060465 25.6763099,57.175814 26.3187714,57.175814 Z" id="Path" fill="#FEE1D3" fill-rule="nonzero"></path>
- <path d="M36.850156,64.2502326 L39.190156,64.2502326 C39.8326176,64.2502326 40.3587714,64.7804651 40.3587714,65.427907 C40.3587714,66.0753488 39.8326176,66.6055814 39.190156,66.6055814 L36.850156,66.6055814 C36.2076945,66.6055814 35.6815407,66.0753488 35.6815407,65.427907 C35.6815407,64.7804651 36.2049253,64.2502326 36.850156,64.2502326 Z M58.198156,58.9451163 L61.1224637,58.9451163 C61.9310791,58.9451163 62.5846176,59.6037209 62.5846176,60.4186047 C62.5846176,61.2334884 61.9310791,61.892093 61.1224637,61.892093 L58.198156,61.892093 C57.3895407,61.892093 56.7360022,61.2334884 56.7360022,60.4186047 C56.7360022,59.6065116 57.3895407,58.9451163 58.198156,58.9451163 Z" id="Shape" fill="#FEF0E8" fill-rule="nonzero"></path>
- <path d="M35.385233,58.9451163 L38.3095407,58.9451163 C39.118156,58.9451163 39.7716945,59.6037209 39.7716945,60.4186047 C39.7716945,61.2334884 39.118156,61.892093 38.3095407,61.892093 L35.385233,61.892093 C34.5766176,61.892093 33.9230791,61.2334884 33.9230791,60.4186047 C33.9230791,59.6065116 34.5793868,58.9451163 35.385233,58.9451163 Z" id="Path" fill="#FC6D26" fill-rule="nonzero"></path>
- <path d="M14.6215407,64.2502326 L20.470156,64.2502326 C21.1126176,64.2502326 21.6387714,64.7804651 21.6387714,65.427907 C21.6387714,66.0753488 21.1126176,66.6055814 20.470156,66.6055814 L14.6215407,66.6055814 C13.9790791,66.6055814 13.4529253,66.0753488 13.4529253,65.427907 C13.4529253,64.7804651 13.9763099,64.2502326 14.6215407,64.2502326 Z" id="Path" fill="#EEEEEE" fill-rule="nonzero"></path>
- <ellipse id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="36.814156" cy="38.4725581" rx="20.4729231" ry="20.6316279"></ellipse>
- <path d="M36.814156,59.104186 C25.5073868,59.104186 16.341233,49.8669767 16.341233,38.4725581 C16.341233,27.0781395 25.5073868,17.8409302 36.814156,17.8409302 C48.1209253,17.8409302 57.2870791,27.0781395 57.2870791,38.4725581 C57.2870791,49.8669767 48.1209253,59.104186 36.814156,59.104186 Z M36.814156,56.7460465 C46.8276945,56.7460465 54.9470791,48.5637209 54.9470791,38.4725581 C54.9470791,28.3813953 46.8276945,20.1990698 36.814156,20.1990698 C26.8006176,20.1990698 18.681233,28.3813953 18.681233,38.4725581 C18.681233,48.5637209 26.8006176,56.7460465 36.814156,56.7460465 Z" id="Shape" fill="#EEEEEE" fill-rule="nonzero"></path>
- <path d="M46.5895407,39.7813953 L45.490156,36.3739535 L43.3135407,29.6260465 C43.2027714,29.28 42.718156,29.28 42.5990791,29.6260465 L40.4280022,36.3739535 L33.2030791,36.3739535 L31.0264637,29.6260465 C30.9156945,29.28 30.4310791,29.28 30.3120022,29.6260465 L28.1353868,36.3739535 L27.0360022,39.7813953 C26.9363099,40.0939535 27.0470791,40.4288372 27.3046176,40.624186 L36.8086176,47.5786047 L46.3126176,40.624186 C46.581233,40.4288372 46.689233,40.0883721 46.5895407,39.7813953" id="Path" fill="#FC6D26"></path>
- <polygon id="Path" fill="#E24329" points="36.814156 47.5813953 40.4280022 36.3767442 33.2030791 36.3767442"></polygon>
- <polygon id="Path" fill="#FC6D26" points="36.814156 47.5813953 33.2003099 36.3767442 28.1353868 36.3767442"></polygon>
- <path d="M28.138156,36.3739535 L27.0387714,39.7813953 C26.9390791,40.0939535 27.0498483,40.4288372 27.3073868,40.624186 L36.8113868,47.5786047 L28.138156,36.3739535 Z" id="Path" fill="#FCA326"></path>
- <path d="M28.138156,36.3739535 L33.2030791,36.3739535 L31.0264637,29.6260465 C30.9156945,29.28 30.4310791,29.28 30.3120022,29.6260465 L28.138156,36.3739535 Z" id="Path" fill="#E24329"></path>
- <polygon id="Path" fill="#FC6D26" points="36.814156 47.5813953 40.4280022 36.3767442 45.4929253 36.3767442"></polygon>
- <path d="M45.4929253,36.3739535 L46.5923099,39.7813953 C46.6920022,40.0939535 46.581233,40.4288372 46.3236945,40.624186 L36.8196945,47.5786047 L45.4929253,36.3739535 Z" id="Path" fill="#FCA326"></path>
- <path d="M45.4929253,36.3739535 L40.4280022,36.3739535 L42.6046176,29.6260465 C42.7153868,29.28 43.2000022,29.28 43.3190791,29.6260465 L45.4929253,36.3739535 Z" id="Path" fill="#E24329"></path>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
+<svg width="169" height="84" viewBox="0 0 169 84" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0)">
+<path d="M153.5 74.5714H165.684C166.411 74.5714 167 73.9822 167 73.2554V8.74461C167 8.01779 166.411 7.42859 165.684 7.42859H153.5" stroke="#DBDBDB" stroke-width="2.63203"/>
+<path d="M107.94 57L108.014 72.9062C108.017 73.5536 108.49 74.1026 109.13 74.2008L151.913 80.7674C152.71 80.8897 153.429 80.273 153.429 79.4666V2.54193C153.429 1.73264 152.705 1.11511 151.906 1.24226L108.829 8.09543C108.187 8.19744 107.716 8.7519 107.719 9.4012L107.771 20.5" stroke="#DBDBDB" stroke-width="2.63203"/>
+<path d="M133.539 52.5313L122.91 51.9925M137.311 52.7225L148.969 53.3135" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M132.224 43.9783L124 43.6955M135.998 44.1081L147.665 44.5092" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M148.238 12.3644L131.189 14.604M117.282 16.4529L126.416 15.2311" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M149.032 36.8519L131.839 37.0342M125 37.0852L127.024 37.0852" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M112.038 66.3444L120.582 67.4102M148.266 70.8634L134.595 69.1581M125.025 67.9644L129.468 68.5186" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M114.352 23.3947L116.215 23.2387M129.258 22.147L119.433 22.9693M137.388 21.4665L145.18 20.8143" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M135.832 29.2067L125.981 29.5888M138.724 28.9864L146.537 28.6833" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M115.114 59.5557L128.942 60.8796M133.782 61.3429L145.19 62.4351" stroke="#DFDFDF" stroke-width="1.31602" stroke-linecap="round"/>
+<path d="M53.4286 42.4286H21.2857C10.6345 42.4286 2.00002 33.7941 2.00002 23.1429C2.00002 12.4917 10.6345 3.85718 21.2857 3.85718C31.9369 3.85718 40.5714 12.4917 40.5714 23.1429C40.5714 28.17 38.648 32.7479 35.4969 36.1807" stroke="#DBDBDB" stroke-width="2.63203" stroke-linecap="round"/>
+<path d="M53.0361 42.4286H42.3571C35.0591 42.4286 29.1428 48.3448 29.1428 55.6429C29.1428 62.9409 35.0591 68.8572 42.3571 68.8572C49.6552 68.8572 55.5714 62.9409 55.5714 55.6429C55.5714 53.8962 55.2325 52.2287 54.6169 50.7025" stroke="#DBDBDB" stroke-width="2.63203" stroke-linecap="round"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M38.4286 51.7144C38.4286 50.9254 39.0682 50.2858 39.8572 50.2858H44.1429C44.829 50.2858 45.4022 50.7695 45.5399 51.4146L47.7105 52.6677C48.3938 53.0622 48.6279 53.9359 48.2334 54.6192C47.3183 56.2042 45.5714 59.2248 45.4609 59.4191C45.1836 59.9063 44.7237 60.2858 44.1429 60.2858H39.8572C39.0682 60.2858 38.4286 59.6462 38.4286 58.8572V51.7144ZM39.8572 51.7144H44.1429V58.8572H39.8572L39.8572 51.7144ZM45.5714 56.3727L46.9962 53.9049L45.5714 53.0823V56.3727Z" fill="#FC6D26"/>
+<path d="M25.5984 15.2331C25.8026 14.471 25.3503 13.6877 24.5882 13.4835C23.8261 13.2793 23.0428 13.7315 22.8386 14.4936L18.4017 31.0524C18.1975 31.8145 18.6497 32.5978 19.4118 32.802C20.1739 33.0062 20.9573 32.5539 21.1615 31.7918L25.5984 15.2331Z" fill="#6E49CB"/>
+<path d="M17.2958 17.8469C17.8537 18.4048 17.8537 19.3093 17.2958 19.8672L14.0203 23.1428L17.2958 26.4183C17.8537 26.9762 17.8537 27.8807 17.2958 28.4386C16.738 28.9965 15.8334 28.9965 15.2755 28.4386L10.9898 24.1529C10.4319 23.595 10.4319 22.6905 10.9898 22.1326L15.2755 17.8469C15.8334 17.289 16.738 17.289 17.2958 17.8469Z" fill="#6E49CB"/>
+<path d="M26.7041 17.8469C26.1462 18.4048 26.1462 19.3093 26.7041 19.8672L29.9797 23.1428L26.7041 26.4183C26.1462 26.9762 26.1462 27.8807 26.7041 28.4386C27.262 28.9965 28.1665 28.9965 28.7244 28.4386L33.0101 24.1529C33.568 23.595 33.568 22.6905 33.0101 22.1326L28.7244 17.8469C28.1665 17.289 27.262 17.289 26.7041 17.8469Z" fill="#6E49CB"/>
+<path d="M50.5714 35.2857L62 35.2857C62.7889 35.2857 63.4285 35.9253 63.4285 36.7143C63.4285 37.5032 62.7889 38.1428 62 38.1428L50.5714 38.1428C49.7824 38.1428 49.1428 37.5032 49.1428 36.7143C49.1428 35.9253 49.7824 35.2857 50.5714 35.2857Z" fill="#FC6D26"/>
+<path d="M50.5714 35.2857L62 35.2857C62.7889 35.2857 63.4285 35.9253 63.4285 36.7143C63.4285 37.5032 62.7889 38.1428 62 38.1428L50.5714 38.1428C49.7824 38.1428 49.1428 37.5032 49.1428 36.7143C49.1428 35.9253 49.7824 35.2857 50.5714 35.2857Z" fill="white" fill-opacity="0.6"/>
+<path d="M70.5713 35.2857L83.4285 35.2857C84.2175 35.2857 84.8571 35.9253 84.8571 36.7143C84.8571 37.5032 84.2175 38.1428 83.4285 38.1428L70.5713 38.1428C69.7824 38.1428 69.1428 37.5032 69.1428 36.7143C69.1428 35.9253 69.7824 35.2857 70.5713 35.2857Z" fill="#FC6D26"/>
+<path d="M76.2856 46.7144L92.1428 46.7144C92.9318 46.7144 93.5714 47.3539 93.5714 48.1429C93.5714 48.9319 92.9318 49.5715 92.1428 49.5715L76.2856 49.5715C75.4967 49.5715 74.8571 48.9319 74.8571 48.1429C74.8571 47.354 75.4967 46.7144 76.2856 46.7144Z" fill="#6E49CB"/>
+<path d="M76.2856 46.7144L92.1428 46.7144C92.9318 46.7144 93.5714 47.3539 93.5714 48.1429C93.5714 48.9319 92.9318 49.5715 92.1428 49.5715L76.2856 49.5715C75.4967 49.5715 74.8571 48.9319 74.8571 48.1429C74.8571 47.354 75.4967 46.7144 76.2856 46.7144Z" fill="white" fill-opacity="0.8"/>
+<path d="M62.7142 40.9999L90 40.9999C90.7889 40.9999 91.4285 41.6395 91.4285 42.4285C91.4285 43.2175 90.7889 43.8571 90 43.8571L62.7142 43.8571C61.9253 43.8571 61.2857 43.2175 61.2857 42.4285C61.2857 41.6395 61.9253 40.9999 62.7142 40.9999Z" fill="#6E49CB"/>
+<path d="M62.7142 40.9999L90 40.9999C90.7889 40.9999 91.4285 41.6395 91.4285 42.4285C91.4285 43.2175 90.7889 43.8571 90 43.8571L62.7142 43.8571C61.9253 43.8571 61.2857 43.2175 61.2857 42.4285C61.2857 41.6395 61.9253 40.9999 62.7142 40.9999Z" fill="white" fill-opacity="0.6"/>
+<path d="M69.8571 29.5714L91.5714 29.5714C92.3603 29.5714 92.9999 30.211 92.9999 31C92.9999 31.789 92.3603 32.4286 91.5714 32.4286L69.8571 32.4286C69.0681 32.4286 68.4285 31.789 68.4285 31C68.4285 30.211 69.0681 29.5714 69.8571 29.5714Z" fill="#6E49CB"/>
+<path d="M69.8571 29.5714L91.5714 29.5714C92.3603 29.5714 92.9999 30.211 92.9999 31C92.9999 31.789 92.3603 32.4286 91.5714 32.4286L69.8571 32.4286C69.0681 32.4286 68.4285 31.789 68.4285 31C68.4285 30.211 69.0681 29.5714 69.8571 29.5714Z" fill="white" fill-opacity="0.8"/>
+<circle cx="107.714" cy="38.8571" r="17.8571" stroke="#6E49CB" stroke-width="2.63203"/>
+<circle cx="107.714" cy="38.8573" r="13.5714" fill="#6E49CB"/>
+<circle cx="107.714" cy="38.8573" r="13.5714" fill="white" fill-opacity="0.9"/>
+<path d="M111.431 35.0867L115.367 39.0232L111.431 42.9597C111.016 43.3744 110.344 43.3744 109.929 42.9597C109.515 42.545 109.515 41.8727 109.929 41.458L111.302 40.0851H101.123C100.537 40.0851 100.061 39.6097 100.061 39.0232C100.061 38.4367 100.537 37.9613 101.123 37.9613H111.302L109.929 36.5884C109.515 36.1737 109.515 35.5014 109.929 35.0867C110.344 34.672 111.016 34.672 111.431 35.0867Z" fill="#6E49CB"/>
+</g>
+<defs>
+<clipPath id="clip0">
+<rect width="169" height="84" fill="white"/>
+</clipPath>
+</defs>
+</svg>
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 3715c52b6b9..06920a5ab19 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 (el, props) {
return new Vue({
el,
components: {
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 4bf837faed1..7bb62cf4a73 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -1,37 +1,18 @@
<script>
-import dateFormat from 'dateformat';
-import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import { GlAlert, GlSkeletonLoader } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-import { getDateInPast } from '~/lib/utils/datetime_utility';
+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 StatisticsList from './statistics_list.vue';
-import PipelinesAreaChart from './pipelines_area_chart.vue';
+import PipelineCharts from './pipeline_charts.vue';
+
import {
- CHART_CONTAINER_HEIGHT,
- CHART_DATE_FORMAT,
DEFAULT,
- INNER_CHART_HEIGHT,
LOAD_ANALYTICS_FAILURE,
LOAD_PIPELINES_FAILURE,
- ONE_WEEK_AGO_DAYS,
- ONE_MONTH_AGO_DAYS,
PARSE_FAILURE,
UNSUPPORTED_DATA,
- X_AXIS_LABEL_ROTATION,
- X_AXIS_TITLE_OFFSET,
} from '../constants';
-const defaultCountValues = {
- totalPipelines: {
- count: 0,
- },
- successfulPipelines: {
- count: 0,
- },
-};
-
const defaultAnalyticsValues = {
weekPipelinesTotals: [],
weekPipelinesLabels: [],
@@ -46,15 +27,29 @@ const defaultAnalyticsValues = {
pipelineTimesValues: [],
};
+const defaultCountValues = {
+ totalPipelines: {
+ count: 0,
+ },
+ successfulPipelines: {
+ count: 0,
+ },
+};
+
export default {
components: {
GlAlert,
- GlColumnChart,
- GlSkeletonLoader,
- StatisticsList,
- PipelinesAreaChart,
+ GlTabs,
+ GlTab,
+ PipelineCharts,
+ DeploymentFrequencyCharts: () =>
+ import('ee_component/projects/pipelines/charts/components/deployment_frequency_charts.vue'),
},
inject: {
+ shouldRenderDeploymentFrequencyCharts: {
+ type: Boolean,
+ default: false,
+ },
projectPath: {
type: String,
default: '',
@@ -62,14 +57,10 @@ export default {
},
data() {
return {
- counts: {
- ...defaultCountValues,
- },
- analytics: {
- ...defaultAnalyticsValues,
- },
showFailureAlert: false,
failureType: null,
+ analytics: { ...defaultAnalyticsValues },
+ counts: { ...defaultCountValues },
};
},
apollo: {
@@ -127,47 +118,6 @@ export default {
};
}
},
- 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,
- totalPipelineDuration,
- } = this.counts;
-
- return {
- total: totalPipelines?.count,
- success: successfulPipelines?.count,
- failed: failedPipelines?.count,
- successRatio: this.successRatio,
- totalDuration: totalPipelineDuration,
- };
- },
- areaCharts() {
- const { lastWeek, lastMonth, lastYear } = this.$options.chartTitles;
- let areaChartsData = [];
-
- try {
- areaChartsData = [
- this.buildAreaChartData(lastWeek, this.lastWeekChartData),
- this.buildAreaChartData(lastMonth, this.lastMonthChartData),
- this.buildAreaChartData(lastYear, this.lastYearChartData),
- ];
- } catch {
- areaChartsData = [];
- this.reportFailure(PARSE_FAILURE);
- }
-
- return areaChartsData;
- },
lastWeekChartData() {
return {
labels: this.analytics.weekPipelinesLabels,
@@ -189,39 +139,32 @@ export default {
success: this.analytics.yearPipelinesSuccessful,
};
},
- timesChartTransformedData() {
- return [
- {
- name: 'full',
- data: this.mergeLabelsAndValues(
- this.analytics.pipelineTimesLabels,
- this.analytics.pipelineTimesValues,
- ),
- },
- ];
+ timesChartData() {
+ return {
+ labels: this.analytics.pipelineTimesLabels,
+ values: this.analytics.pipelineTimesValues,
+ };
},
- },
- methods: {
- mergeLabelsAndValues(labels, values) {
- return labels.map((label, index) => [label, values[index]]);
+ 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;
},
- buildAreaChartData(title, data) {
- const { labels, totals, success } = data;
+ formattedCounts() {
+ const { totalPipelines, successfulPipelines, failedPipelines } = this.counts;
return {
- title,
- data: [
- {
- name: 'all',
- data: this.mergeLabelsAndValues(labels, totals),
- },
- {
- name: 'success',
- data: this.mergeLabelsAndValues(labels, success),
- },
- ],
+ total: totalPipelines?.count,
+ success: successfulPipelines?.count,
+ failed: failedPipelines?.count,
+ successRatio: this.successRatio,
};
},
+ },
+ methods: {
hideAlert() {
this.showFailureAlert = false;
},
@@ -230,16 +173,6 @@ export default {
this.failureType = type;
},
},
- chartContainerHeight: CHART_CONTAINER_HEIGHT,
- timesChartOptions: {
- height: INNER_CHART_HEIGHT,
- xAxis: {
- axisLabel: {
- rotate: X_AXIS_LABEL_ROTATION,
- },
- nameGap: X_AXIS_TITLE_OFFSET,
- },
- },
errorTexts: {
[LOAD_ANALYTICS_FAILURE]: s__(
'PipelineCharts|An error has ocurred when retrieving the analytics data',
@@ -250,60 +183,38 @@ export default {
[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.'),
},
- get chartTitles() {
- 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})'), {
- oneWeekAgo: pastDate(ONE_WEEK_AGO_DAYS),
- today,
- }),
- lastMonth: sprintf(__('Pipelines for last month (%{oneMonthAgo} - %{today})'), {
- oneMonthAgo: pastDate(ONE_MONTH_AGO_DAYS),
- today,
- }),
- lastYear: __('Pipelines for last year'),
- };
- },
};
</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>
- <h4 class="gl-my-4">{{ s__('PipelineCharts|Overall statistics') }}</h4>
- <div class="row">
- <div class="col-md-6">
- <gl-skeleton-loader v-if="$apollo.queries.counts.loading" :lines="5" />
- <statistics-list v-else :counts="formattedCounts" />
- </div>
- <div class="col-md-6">
- <strong>
- {{ __('Duration for the last 30 commits') }}
- </strong>
- <gl-column-chart
- :height="$options.chartContainerHeight"
- :option="$options.timesChartOptions"
- :bars="timesChartTransformedData"
- :y-axis-title="__('Minutes')"
- :x-axis-title="__('Commit')"
- x-axis-type="category"
+ <gl-alert v-if="showFailureAlert" :variant="failure.variant" @dismiss="hideAlert">{{
+ failure.text
+ }}</gl-alert>
+ <gl-tabs v-if="shouldRenderDeploymentFrequencyCharts">
+ <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"
/>
- </div>
- </div>
- <hr />
- <h4 class="gl-my-4">{{ __('Pipelines charts') }}</h4>
- <pipelines-area-chart
- v-for="(chart, index) in areaCharts"
- :key="index"
- :chart-data="chart.data"
- >
- {{ chart.title }}
- </pipelines-area-chart>
+ </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"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue b/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue
deleted file mode 100644
index c6e2b2e1140..00000000000
--- a/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue
+++ /dev/null
@@ -1,151 +0,0 @@
-<script>
-import dateFormat from 'dateformat';
-import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import { __, sprintf } from '~/locale';
-import { getDateInPast } from '~/lib/utils/datetime_utility';
-import StatisticsList from './statistics_list.vue';
-import PipelinesAreaChart from './pipelines_area_chart.vue';
-import {
- CHART_CONTAINER_HEIGHT,
- INNER_CHART_HEIGHT,
- X_AXIS_LABEL_ROTATION,
- X_AXIS_TITLE_OFFSET,
- CHART_DATE_FORMAT,
- ONE_WEEK_AGO_DAYS,
- ONE_MONTH_AGO_DAYS,
-} from '../constants';
-
-export default {
- components: {
- StatisticsList,
- GlColumnChart,
- PipelinesAreaChart,
- },
- props: {
- counts: {
- type: Object,
- required: true,
- },
- timesChartData: {
- type: Object,
- required: true,
- },
- lastWeekChartData: {
- type: Object,
- required: true,
- },
- lastMonthChartData: {
- type: Object,
- required: true,
- },
- lastYearChartData: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- timesChartTransformedData: [
- {
- name: 'full',
- data: this.mergeLabelsAndValues(this.timesChartData.labels, this.timesChartData.values),
- },
- ],
- };
- },
- computed: {
- areaCharts() {
- const { lastWeek, lastMonth, lastYear } = this.$options.chartTitles;
-
- return [
- this.buildAreaChartData(lastWeek, this.lastWeekChartData),
- this.buildAreaChartData(lastMonth, this.lastMonthChartData),
- this.buildAreaChartData(lastYear, this.lastYearChartData),
- ];
- },
- },
- methods: {
- mergeLabelsAndValues(labels, values) {
- return labels.map((label, index) => [label, values[index]]);
- },
- buildAreaChartData(title, data) {
- const { labels, totals, success } = data;
-
- return {
- title,
- data: [
- {
- name: 'all',
- data: this.mergeLabelsAndValues(labels, totals),
- },
- {
- name: 'success',
- data: this.mergeLabelsAndValues(labels, success),
- },
- ],
- };
- },
- },
- chartContainerHeight: CHART_CONTAINER_HEIGHT,
- timesChartOptions: {
- height: INNER_CHART_HEIGHT,
- xAxis: {
- axisLabel: {
- rotate: X_AXIS_LABEL_ROTATION,
- },
- nameGap: X_AXIS_TITLE_OFFSET,
- },
- },
- get chartTitles() {
- 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})'), {
- oneWeekAgo: pastDate(ONE_WEEK_AGO_DAYS),
- today,
- }),
- lastMonth: sprintf(__('Pipelines for last month (%{oneMonthAgo} - %{today})'), {
- oneMonthAgo: pastDate(ONE_MONTH_AGO_DAYS),
- today,
- }),
- lastYear: __('Pipelines for last year'),
- };
- },
-};
-</script>
-<template>
- <div>
- <div class="mb-3">
- <h3>{{ s__('PipelineCharts|CI / CD Analytics') }}</h3>
- </div>
- <h4 class="my-4">{{ s__('PipelineCharts|Overall statistics') }}</h4>
- <div class="row">
- <div class="col-md-6">
- <statistics-list :counts="counts" />
- </div>
- <div class="col-md-6">
- <strong>
- {{ __('Duration for the last 30 commits') }}
- </strong>
- <gl-column-chart
- :height="$options.chartContainerHeight"
- :option="$options.timesChartOptions"
- :bars="timesChartTransformedData"
- :y-axis-title="__('Minutes')"
- :x-axis-title="__('Commit')"
- x-axis-type="category"
- />
- </div>
- </div>
- <hr />
- <h4 class="my-4">{{ __('Pipelines charts') }}</h4>
- <pipelines-area-chart
- v-for="(chart, index) in areaCharts"
- :key="index"
- :chart-data="chart.data"
- >
- {{ chart.title }}
- </pipelines-area-chart>
- </div>
-</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
new file mode 100644
index 00000000000..3590e2c4632
--- /dev/null
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
@@ -0,0 +1,41 @@
+<script>
+import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
+import { CHART_CONTAINER_HEIGHT } from '../constants';
+
+export default {
+ name: 'CiCdAnalyticsAreaChart',
+ components: {
+ GlAreaChart,
+ ResizableChartContainer,
+ },
+ props: {
+ chartData: {
+ type: Array,
+ required: true,
+ },
+ areaChartOptions: {
+ type: Object,
+ required: true,
+ },
+ },
+ chartContainerHeight: CHART_CONTAINER_HEIGHT,
+};
+</script>
+<template>
+ <div class="gl-mt-3">
+ <p>
+ <slot></slot>
+ </p>
+ <resizable-chart-container>
+ <gl-area-chart
+ slot-scope="{ width }"
+ :width="width"
+ :height="$options.chartContainerHeight"
+ :data="chartData"
+ :include-legend-avg-max="false"
+ :option="areaChartOptions"
+ />
+ </resizable-chart-container>
+ </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
new file mode 100644
index 00000000000..bec4ab407f0
--- /dev/null
+++ b/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue
@@ -0,0 +1,176 @@
+<script>
+import dateFormat from 'dateformat';
+import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import { GlSkeletonLoader } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
+import { getDateInPast } from '~/lib/utils/datetime_utility';
+import {
+ CHART_CONTAINER_HEIGHT,
+ CHART_DATE_FORMAT,
+ INNER_CHART_HEIGHT,
+ ONE_WEEK_AGO_DAYS,
+ ONE_MONTH_AGO_DAYS,
+ X_AXIS_LABEL_ROTATION,
+ X_AXIS_TITLE_OFFSET,
+ PARSE_FAILURE,
+} from '../constants';
+import StatisticsList from './statistics_list.vue';
+import CiCdAnalyticsAreaChart from './ci_cd_analytics_area_chart.vue';
+
+export default {
+ components: {
+ GlColumnChart,
+ GlSkeletonLoader,
+ StatisticsList,
+ CiCdAnalyticsAreaChart,
+ },
+ props: {
+ counts: {
+ required: true,
+ type: Object,
+ },
+ loading: {
+ required: false,
+ default: false,
+ type: Boolean,
+ },
+ lastWeek: {
+ required: true,
+ type: Object,
+ },
+ lastMonth: {
+ required: true,
+ type: Object,
+ },
+ lastYear: {
+ required: true,
+ type: Object,
+ },
+ timesChart: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ areaCharts() {
+ const { lastWeek, lastMonth, lastYear } = this.$options.chartTitles;
+ const charts = [
+ { title: lastWeek, data: this.lastWeek },
+ { title: lastMonth, data: this.lastMonth },
+ { title: lastYear, data: this.lastYear },
+ ];
+ let areaChartsData = [];
+
+ try {
+ areaChartsData = charts.map(this.buildAreaChartData);
+ } catch {
+ areaChartsData = [];
+ this.vm.$emit('report-failure', PARSE_FAILURE);
+ }
+
+ return areaChartsData;
+ },
+ timesChartTransformedData() {
+ return [
+ {
+ name: 'full',
+ data: this.mergeLabelsAndValues(this.timesChart.labels, this.timesChart.values),
+ },
+ ];
+ },
+ },
+ methods: {
+ mergeLabelsAndValues(labels, values) {
+ return labels.map((label, index) => [label, values[index]]);
+ },
+ buildAreaChartData({ title, data }) {
+ const { labels, totals, success } = data;
+
+ return {
+ title,
+ data: [
+ {
+ name: 'all',
+ data: this.mergeLabelsAndValues(labels, totals),
+ },
+ {
+ name: 'success',
+ data: this.mergeLabelsAndValues(labels, success),
+ },
+ ],
+ };
+ },
+ },
+ chartContainerHeight: CHART_CONTAINER_HEIGHT,
+ timesChartOptions: {
+ height: INNER_CHART_HEIGHT,
+ xAxis: {
+ axisLabel: {
+ rotate: X_AXIS_LABEL_ROTATION,
+ },
+ nameGap: X_AXIS_TITLE_OFFSET,
+ },
+ },
+ areaChartOptions: {
+ xAxis: {
+ name: s__('Pipeline|Date'),
+ type: 'category',
+ },
+ yAxis: {
+ name: s__('Pipeline|Pipelines'),
+ },
+ },
+ get chartTitles() {
+ 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})'), {
+ oneWeekAgo: pastDate(ONE_WEEK_AGO_DAYS),
+ today,
+ }),
+ lastMonth: sprintf(__('Pipelines for last month (%{oneMonthAgo} - %{today})'), {
+ oneMonthAgo: pastDate(ONE_MONTH_AGO_DAYS),
+ today,
+ }),
+ lastYear: __('Pipelines for last year'),
+ };
+ },
+};
+</script>
+<template>
+ <div>
+ <div class="gl-mb-3">
+ <h3>{{ s__('PipelineCharts|CI / CD Analytics') }}</h3>
+ </div>
+ <h4 class="gl-my-4">{{ s__('PipelineCharts|Overall statistics') }}</h4>
+ <div class="row">
+ <div class="col-md-6">
+ <gl-skeleton-loader v-if="loading" :lines="5" />
+ <statistics-list v-else :counts="counts" />
+ </div>
+ <div v-if="!loading" class="col-md-6">
+ <strong>{{ __('Duration for the last 30 commits') }}</strong>
+ <gl-column-chart
+ :height="$options.chartContainerHeight"
+ :option="$options.timesChartOptions"
+ :bars="timesChartTransformedData"
+ :y-axis-title="__('Minutes')"
+ :x-axis-title="__('Commit')"
+ x-axis-type="category"
+ />
+ </div>
+ </div>
+ <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
+ >
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue b/app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue
deleted file mode 100644
index d726196aadf..00000000000
--- a/app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-<script>
-import { GlAreaChart } from '@gitlab/ui/dist/charts';
-import { s__ } from '~/locale';
-import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
-import { CHART_CONTAINER_HEIGHT } from '../constants';
-
-export default {
- components: {
- GlAreaChart,
- ResizableChartContainer,
- },
- props: {
- chartData: {
- type: Array,
- required: true,
- },
- },
- areaChartOptions: {
- xAxis: {
- name: s__('Pipeline|Date'),
- type: 'category',
- },
- yAxis: {
- name: s__('Pipeline|Pipelines'),
- },
- },
- chartContainerHeight: CHART_CONTAINER_HEIGHT,
-};
-</script>
-<template>
- <div class="gl-mt-3">
- <p>
- <slot></slot>
- </p>
- <resizable-chart-container>
- <gl-area-chart
- slot-scope="{ width }"
- :width="width"
- :height="$options.chartContainerHeight"
- :data="chartData"
- :include-legend-avg-max="false"
- :option="$options.areaChartOptions"
- />
- </resizable-chart-container>
- </div>
-</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue b/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
index 94cecd2e479..7bc3b787f75 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
@@ -1,5 +1,4 @@
<script>
-import { formatTime } from '~/lib/utils/datetime_utility';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { s__, n__ } from '~/locale';
@@ -13,9 +12,6 @@ export default {
},
},
computed: {
- totalDuration() {
- return formatTime(this.counts.totalDuration);
- },
statistics() {
const formatter = getFormatter(SUPPORTED_FORMATS.percentHundred);
@@ -36,10 +32,6 @@ export default {
title: s__('PipelineCharts|Success ratio:'),
value: formatter(this.counts.successRatio, defaultPrecision),
},
- {
- title: s__('PipelineCharts|Total duration:'),
- value: this.totalDuration,
- },
];
},
},
diff --git a/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql b/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql
index eb0dbf8dd16..d68df689f5f 100644
--- a/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql
+++ b/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql
@@ -9,6 +9,5 @@ query getPipelineCountByStatus($projectPath: ID!) {
failedPipelines: pipelines(status: FAILED) {
count
}
- totalPipelineDuration
}
}
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index f6e79f0ab51..7e746423b6a 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import ProjectPipelinesChartsLegacy from './components/app_legacy.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
import ProjectPipelinesCharts from './components/app.vue';
Vue.use(VueApollo);
@@ -10,99 +10,25 @@ const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
-const mountPipelineChartsApp = el => {
- // Not all of the values will be defined since some them will be
- // empty depending on the value of the graphql_pipeline_analytics
- // feature flag, once the rollout of the feature flag is completed
- // the undefined values will be deleted
- const {
- countsFailed,
- countsSuccess,
- countsTotal,
- countsTotalDuration,
- successRatio,
- timesChartLabels,
- timesChartValues,
- lastWeekChartLabels,
- lastWeekChartTotals,
- lastWeekChartSuccess,
- lastMonthChartLabels,
- lastMonthChartTotals,
- lastMonthChartSuccess,
- lastYearChartLabels,
- lastYearChartTotals,
- lastYearChartSuccess,
- projectPath,
- } = el.dataset;
+const mountPipelineChartsApp = (el) => {
+ const { projectPath } = el.dataset;
- const parseAreaChartData = (labels, totals, success) => {
- let parsedData = {};
-
- try {
- parsedData = {
- labels: JSON.parse(labels),
- totals: JSON.parse(totals),
- success: JSON.parse(success),
- };
- } catch {
- parsedData = {};
- }
-
- return parsedData;
- };
-
- if (gon?.features?.graphqlPipelineAnalytics) {
- return new Vue({
- el,
- name: 'ProjectPipelinesChartsApp',
- components: {
- ProjectPipelinesCharts,
- },
- apolloProvider,
- provide: {
- projectPath,
- },
- render: createElement => createElement(ProjectPipelinesCharts, {}),
- });
- }
+ const shouldRenderDeploymentFrequencyCharts = parseBoolean(
+ el.dataset.shouldRenderDeploymentFrequencyCharts,
+ );
return new Vue({
el,
- name: 'ProjectPipelinesChartsAppLegacy',
+ name: 'ProjectPipelinesChartsApp',
components: {
- ProjectPipelinesChartsLegacy,
+ ProjectPipelinesCharts,
+ },
+ apolloProvider,
+ provide: {
+ projectPath,
+ shouldRenderDeploymentFrequencyCharts,
},
- render: createElement =>
- createElement(ProjectPipelinesChartsLegacy, {
- props: {
- counts: {
- failed: countsFailed,
- success: countsSuccess,
- total: countsTotal,
- successRatio,
- totalDuration: countsTotalDuration,
- },
- timesChartData: {
- labels: JSON.parse(timesChartLabels),
- values: JSON.parse(timesChartValues),
- },
- lastWeekChartData: parseAreaChartData(
- lastWeekChartLabels,
- lastWeekChartTotals,
- lastWeekChartSuccess,
- ),
- lastMonthChartData: parseAreaChartData(
- lastMonthChartLabels,
- lastMonthChartTotals,
- lastMonthChartSuccess,
- ),
- lastYearChartData: parseAreaChartData(
- lastYearChartLabels,
- lastYearChartTotals,
- lastYearChartSuccess,
- ),
- },
- }),
+ render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
};
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index d54a48cc444..e3ba84102a8 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -39,7 +39,7 @@ const setProjectNamePathHandlers = ($projectNameInput, $projectPathInput) => {
});
};
-const deriveProjectPathFromUrl = $projectImportUrl => {
+const deriveProjectPathFromUrl = ($projectImportUrl) => {
const $currentProjectName = $projectImportUrl
.parents('.toggle-import-form')
.find('#project_name');
@@ -89,11 +89,9 @@ const bindEvents = () => {
return;
}
- $('.how_to_import_link').on('click', e => {
+ $('.how_to_import_link').on('click', (e) => {
e.preventDefault();
- $(e.currentTarget)
- .next('.modal')
- .show();
+ $(e.currentTarget).next('.modal').show();
});
$('.modal-header .close').on('click', () => {
@@ -114,7 +112,7 @@ const bindEvents = () => {
$pushNewProjectTipTrigger
.removeAttr('rel')
.removeAttr('target')
- .on('click', e => {
+ .on('click', (e) => {
e.preventDefault();
})
.popover({
@@ -124,7 +122,7 @@ const bindEvents = () => {
content: $('.push-new-project-tip-template').html(),
})
.on('shown.bs.popover', () => {
- $(document).on('click.popover touchstart.popover', event => {
+ $(document).on('click.popover touchstart.popover', (event) => {
if ($(event.target).closest('.popover').length === 0) {
$pushNewProjectTipTrigger.trigger('click');
}
@@ -151,10 +149,7 @@ const bindEvents = () => {
const selectedTemplate = DEFAULT_PROJECT_TEMPLATES[value];
$selectedTemplateText.text(selectedTemplate.text);
- $(selectedTemplate.icon)
- .clone()
- .addClass('d-block')
- .appendTo($selectedIcon);
+ $(selectedTemplate.icon).clone().addClass('d-block').appendTo($selectedIcon);
const $activeTabProjectName = $('.tab-pane.active #project_name');
const $activeTabProjectPath = $('.tab-pane.active #project_path');
diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js
index cb4fd5265da..a62b5d423de 100644
--- a/app/assets/javascripts/projects/settings/access_dropdown.js
+++ b/app/assets/javascripts/projects/settings/access_dropdown.js
@@ -25,7 +25,7 @@ export default class AccessDropdown {
this.setSelectedItems([]);
this.persistPreselectedItems();
- this.noOneObj = this.accessLevelsData.find(level => level.id === ACCESS_LEVEL_NONE);
+ this.noOneObj = this.accessLevelsData.find((level) => level.id === ACCESS_LEVEL_NONE);
this.initDropdown();
}
@@ -45,7 +45,7 @@ export default class AccessDropdown {
onHide();
}
},
- clicked: options => {
+ clicked: (options) => {
const { $el, e } = options;
const item = options.selectedObj;
const fossWithMergeAccess = !this.hasLicense && this.accessLevel === ACCESS_LEVELS.MERGE;
@@ -56,7 +56,7 @@ export default class AccessDropdown {
// We're not multiselecting quite yet in "Merge" access dropdown, on FOSS:
// remove all preselected items before selecting this item
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37499
- this.accessLevelsData.forEach(level => {
+ this.accessLevelsData.forEach((level) => {
this.removeSelectedItem(level);
});
}
@@ -65,7 +65,7 @@ export default class AccessDropdown {
if (this.noOneObj) {
if (item.id === this.noOneObj.id && !fossWithMergeAccess) {
// remove all others selected items
- this.accessLevelsData.forEach(level => {
+ this.accessLevelsData.forEach((level) => {
if (level.id !== item.id) {
this.removeSelectedItem(level);
}
@@ -109,7 +109,7 @@ export default class AccessDropdown {
return;
}
- const persistedItems = itemsToPreselect.map(item => {
+ const persistedItems = itemsToPreselect.map((item) => {
const persistedItem = { ...item };
persistedItem.persisted = true;
return persistedItem;
@@ -123,7 +123,7 @@ export default class AccessDropdown {
}
getSelectedItems() {
- return this.items.filter(item => !item._destroy);
+ return this.items.filter((item) => !item._destroy);
}
getAllSelectedItems() {
@@ -134,7 +134,7 @@ export default class AccessDropdown {
getInputData() {
const selectedItems = this.getAllSelectedItems();
- const accessLevels = selectedItems.map(item => {
+ const accessLevels = selectedItems.map((item) => {
const obj = {};
if (typeof item.id !== 'undefined') {
@@ -288,12 +288,14 @@ export default class AccessDropdown {
$dropdownToggleText.removeClass('is-default');
if (currentItems.length === 1 && currentItems[0].type === LEVEL_TYPES.ROLE) {
- const roleData = this.accessLevelsData.find(data => data.id === currentItems[0].access_level);
+ const roleData = this.accessLevelsData.find(
+ (data) => data.id === currentItems[0].access_level,
+ );
return roleData.text;
}
const labelPieces = [];
- const counts = countBy(currentItems, item => item.type);
+ const counts = countBy(currentItems, (item) => item.type);
if (counts[LEVEL_TYPES.ROLE] > 0) {
labelPieces.push(n__('1 role', '%d roles', counts[LEVEL_TYPES.ROLE]));
@@ -336,7 +338,7 @@ export default class AccessDropdown {
});
} else {
this.getDeployKeys(query)
- .then(deployKeysResponse => callback(this.consolidateData(deployKeysResponse.data)))
+ .then((deployKeysResponse) => callback(this.consolidateData(deployKeysResponse.data)))
.catch(() => createFlash({ message: __('Failed to load deploy keys.') }));
}
}
@@ -365,7 +367,7 @@ export default class AccessDropdown {
/*
* Build roles
*/
- const roles = this.accessLevelsData.map(level => {
+ const roles = this.accessLevelsData.map((level) => {
/* eslint-disable no-param-reassign */
// This re-assignment is intentional as
// level.type property is being used in removeSelectedItem()
@@ -389,7 +391,7 @@ export default class AccessDropdown {
/*
* Build groups
*/
- const groups = groupsResponse.map(group => ({
+ const groups = groupsResponse.map((group) => ({
...group,
type: LEVEL_TYPES.GROUP,
}));
@@ -398,8 +400,8 @@ export default class AccessDropdown {
* Build users
*/
const users = selectedItems
- .filter(item => item.type === LEVEL_TYPES.USER)
- .map(item => {
+ .filter((item) => item.type === LEVEL_TYPES.USER)
+ .map((item) => {
// Save identifiers for easy-checking more later
map.push(LEVEL_TYPES.USER + item.user_id);
@@ -414,7 +416,7 @@ export default class AccessDropdown {
// Has to be checked against server response
// because the selected item can be in filter results
- usersResponse.forEach(response => {
+ usersResponse.forEach((response) => {
// Add is it has not been added
if (map.indexOf(LEVEL_TYPES.USER + response.id) === -1) {
const user = { ...response };
@@ -444,7 +446,7 @@ export default class AccessDropdown {
}
if (this.deployKeysOnProtectedBranchesEnabled) {
- const deployKeys = deployKeysResponse.map(response => {
+ const deployKeys = deployKeysResponse.map((response) => {
const {
id,
fingerprint,
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 a4924033c1e..51281def7d0 100644
--- a/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
+++ b/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
@@ -46,7 +46,7 @@ export default {
this.isLoading = false;
this.isSharedRunnerEnabled = !this.isSharedRunnerEnabled;
})
- .catch(error => {
+ .catch((error) => {
this.isLoading = false;
this.errorMessage = error.response?.data?.error || DEFAULT_ERROR_MESSAGE;
});
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 a07c57c42cb..909f1afd9f6 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
@@ -108,11 +108,11 @@ export default {
.updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
.then(({ data }) => {
this.updatedCustomEmail = data?.service_desk_address;
- this.showAlert(__('Changes were successfully made.'), 'success');
+ this.showAlert(__('Changes saved.'), 'success');
})
- .catch(err => {
+ .catch((err) => {
this.showAlert(
- sprintf(__('An error occured while making the changes: %{error}'), {
+ sprintf(__('An error occured while saving changes: %{error}'), {
error: err?.response?.data?.message,
}),
);
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 2896cb491b5..a850374fc88 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
@@ -103,7 +103,6 @@ export default {
id="service-desk-checkbox"
:value="isEnabled"
class="d-inline-block align-middle mr-1"
- label="Service desk"
label-position="left"
@change="onCheckboxToggle"
/>
@@ -113,7 +112,7 @@ export default {
<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">
- {{ __('Forward external support email address to') }}
+ {{ __('Email address to use for Support Desk') }}
</strong>
<template v-if="email">
<div class="input-group">
@@ -137,7 +136,7 @@ export default {
</div>
</div>
<span v-if="hasCustomEmail" class="form-text text-muted">
- <gl-sprintf :message="__('Emails sent to %{email} will still be supported')">
+ <gl-sprintf :message="__('Emails sent to %{email} are also supported.')">
<template #email>
<code>{{ incomingEmail }}</code>
</template>
@@ -156,9 +155,7 @@ export default {
<input id="service-desk-project-suffix" v-model.trim="projectKey" class="form-control" />
<span class="form-text text-muted">
{{
- __(
- 'Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address.',
- )
+ __('A string appended to the project path to form the Service Desk email address.')
}}
</span>
</template>
@@ -176,7 +173,7 @@ export default {
</label>
<input id="service-desk-email-from-name" v-model.trim="outgoingName" class="form-control" />
<span class="form-text text-muted">
- {{ __('Emails sent from Service Desk will have this name') }}
+ {{ __('Emails sent from Service Desk have this name.') }}
</span>
<div class="gl-display-flex gl-justify-content-end">
<gl-button
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 e582d5c3e47..0f01167988d 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
@@ -63,7 +63,7 @@ export default {
this.poll = new Poll({
resource: this.service,
method: 'fetchData',
- successCallback: response => this.successCallback(response),
+ successCallback: (response) => this.successCallback(response),
errorCallback: this.errorCallback,
});
@@ -83,10 +83,7 @@ export default {
});
},
fetchPipelineCommitData() {
- this.service
- .fetchData()
- .then(this.successCallback)
- .catch(this.errorCallback);
+ this.service.fetchData().then(this.successCallback).catch(this.errorCallback);
},
},
};
diff --git a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
index 6f60141d7ab..91de6d93e19 100644
--- a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
+++ b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
@@ -61,7 +61,7 @@ export default {
resetKey() {
axios
.post(this.changeKeyUrl)
- .then(res => {
+ .then((res) => {
this.authorizationKey = res.data.token;
})
.catch(() => {
diff --git a/app/assets/javascripts/prometheus_metrics/custom_metrics.js b/app/assets/javascripts/prometheus_metrics/custom_metrics.js
index 36df7837785..e891b8bf3b6 100644
--- a/app/assets/javascripts/prometheus_metrics/custom_metrics.js
+++ b/app/assets/javascripts/prometheus_metrics/custom_metrics.js
@@ -65,12 +65,12 @@ export default class CustomMetrics extends PrometheusMetrics {
// eslint-disable-next-line class-methods-use-this
setHidden(els) {
- els.forEach(el => el.addClass('hidden'));
+ els.forEach((el) => el.addClass('hidden'));
}
setVisible(...els) {
- this.setHidden(this.$els.filter(el => !els.includes(el)));
- els.forEach(el => el.removeClass('hidden'));
+ this.setHidden(this.$els.filter((el) => !els.includes(el)));
+ els.forEach((el) => el.removeClass('hidden'));
}
showMonitoringCustomMetricsPanelState(stateName) {
@@ -98,14 +98,14 @@ export default class CustomMetrics extends PrometheusMetrics {
}
populateCustomMetrics() {
- const capitalizeGroup = metric => ({
+ const capitalizeGroup = (metric) => ({
...metric,
group: capitalizeFirstCharacter(metric.group),
});
const sortedMetrics = sortBy(this.customMetrics.map(capitalizeGroup), ['group', 'title']);
- sortedMetrics.forEach(metric => {
+ sortedMetrics.forEach((metric) => {
this.$monitoredCustomMetricsList.append(CustomMetrics.customMetricTemplate(metric));
});
@@ -145,7 +145,7 @@ export default class CustomMetrics extends PrometheusMetrics {
this.populateCustomMetrics(customMetrics.data.metrics);
}
})
- .catch(customMetricError => {
+ .catch((customMetricError) => {
this.showFlashMessage(customMetricError);
this.showMonitoringCustomMetricsPanelState(PANEL_STATE.EMPTY);
});
diff --git a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
index bb9689f09a1..57f9cec9682 100644
--- a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
+++ b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
@@ -26,8 +26,8 @@ export default class PrometheusMetrics {
this.activeMetricsEndpoint = this.$monitoredMetricsPanel.data('activeMetrics');
this.helpMetricsPath = this.$monitoredMetricsPanel.data('metrics-help-path');
- this.$panelToggleRight.on('click', e => this.handlePanelToggle(e));
- this.$panelToggleDown.on('click', e => this.handlePanelToggle(e));
+ this.$panelToggleRight.on('click', (e) => this.handlePanelToggle(e));
+ this.$panelToggleDown.on('click', (e) => this.handlePanelToggle(e));
}
init() {
@@ -72,7 +72,7 @@ export default class PrometheusMetrics {
let totalMissingEnvVarMetrics = 0;
let totalExporters = 0;
- metrics.forEach(metric => {
+ metrics.forEach((metric) => {
if (metric.active_metrics > 0) {
totalExporters += 1;
this.$monitoredMetricsList.append(
@@ -137,7 +137,7 @@ export default class PrometheusMetrics {
})
.catch(stop);
})
- .then(res => {
+ .then((res) => {
if (res && res.data && res.data.length) {
this.populateActiveMetrics(res.data);
} else {
diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js b/app/assets/javascripts/protected_branches/protected_branch_create.js
index 19f6666fd52..a5c7b18f709 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_create.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_create.js
@@ -90,12 +90,12 @@ export default class ProtectedBranchCreate {
},
};
- Object.keys(ACCESS_LEVELS).forEach(level => {
+ Object.keys(ACCESS_LEVELS).forEach((level) => {
const accessLevel = ACCESS_LEVELS[level];
const selectedItems = this[`${accessLevel}_dropdown`].getSelectedItems();
const levelAttributes = [];
- selectedItems.forEach(item => {
+ selectedItems.forEach((item) => {
if (item.type === LEVEL_TYPES.USER) {
levelAttributes.push({
user_id: item.user_id,
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index 1f079123081..f5f27b67c71 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
@@ -108,7 +108,7 @@ export default class ProtectedBranchEdit {
.then(({ data }) => {
this.hasChanges = false;
- Object.keys(ACCESS_LEVELS).forEach(level => {
+ Object.keys(ACCESS_LEVELS).forEach((level) => {
const accessLevelName = ACCESS_LEVELS[level];
// The data coming from server will be the new persisted *state* for each dropdown
@@ -125,7 +125,7 @@ export default class ProtectedBranchEdit {
}
setSelectedItemsToDropdown(items = [], dropdownName) {
- const itemsToAdd = items.map(currentItem => {
+ const itemsToAdd = items.map((currentItem) => {
if (currentItem.user_id) {
// Do this only for users for now
// get the current data for selected items
diff --git a/app/assets/javascripts/read_more.js b/app/assets/javascripts/read_more.js
index d2d1ac8c76a..769782607b8 100644
--- a/app/assets/javascripts/read_more.js
+++ b/app/assets/javascripts/read_more.js
@@ -22,7 +22,7 @@ export default function initReadMore(triggerSelector = '.js-read-more-trigger')
if (!triggerEls) return;
- triggerEls.forEach(triggerEl => {
+ triggerEls.forEach((triggerEl) => {
const targetEl = triggerEl.previousElementSibling;
if (!targetEl) {
@@ -31,7 +31,7 @@ export default function initReadMore(triggerSelector = '.js-read-more-trigger')
triggerEl.addEventListener(
'click',
- e => {
+ (e) => {
targetEl.classList.add('is-expanded');
e.target.remove();
},
diff --git a/app/assets/javascripts/ref/components/ref_results_section.vue b/app/assets/javascripts/ref/components/ref_results_section.vue
index dc74f86fd70..87ce4f1a49c 100644
--- a/app/assets/javascripts/ref/components/ref_results_section.vue
+++ b/app/assets/javascripts/ref/components/ref_results_section.vue
@@ -39,7 +39,7 @@ export default {
items: {
type: Array,
required: true,
- validator: items => Array.isArray(items) && items.every(item => item.name),
+ validator: (items) => Array.isArray(items) && items.every((item) => item.name),
},
/**
diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue
index 0084450c9b0..20aec3e12be 100644
--- a/app/assets/javascripts/ref/components/ref_selector.vue
+++ b/app/assets/javascripts/ref/components/ref_selector.vue
@@ -50,9 +50,9 @@ export default {
},
computed: {
...mapState({
- matches: state => state.matches,
- lastQuery: state => state.query,
- selectedRef: state => state.selectedRef,
+ matches: (state) => state.matches,
+ lastQuery: (state) => state.query,
+ selectedRef: (state) => state.selectedRef,
}),
...mapGetters(['isLoading', 'isQueryPossiblyASha']),
i18n() {
diff --git a/app/assets/javascripts/ref/stores/actions.js b/app/assets/javascripts/ref/stores/actions.js
index 8fcc99cef38..d9bdd64ace5 100644
--- a/app/assets/javascripts/ref/stores/actions.js
+++ b/app/assets/javascripts/ref/stores/actions.js
@@ -18,10 +18,10 @@ export const searchBranches = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.branches(state.projectId, state.query)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_BRANCHES_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_BRANCHES_ERROR, error);
})
.finally(() => {
@@ -33,10 +33,10 @@ export const searchTags = ({ commit, state }) => {
commit(types.REQUEST_START);
Api.tags(state.projectId, state.query)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_TAGS_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_TAGS_ERROR, error);
})
.finally(() => {
@@ -50,10 +50,10 @@ export const searchCommits = ({ commit, state, getters }) => {
commit(types.REQUEST_START);
Api.commit(state.projectId, state.query)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_COMMITS_SUCCESS, response);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_COMMITS_ERROR, error);
})
.finally(() => {
diff --git a/app/assets/javascripts/ref/stores/mutations.js b/app/assets/javascripts/ref/stores/mutations.js
index 73f9d7ee487..75026a40175 100644
--- a/app/assets/javascripts/ref/stores/mutations.js
+++ b/app/assets/javascripts/ref/stores/mutations.js
@@ -23,7 +23,7 @@ export default {
[types.RECEIVE_BRANCHES_SUCCESS](state, response) {
state.matches.branches = {
- list: convertObjectPropsToCamelCase(response.data).map(b => ({
+ list: convertObjectPropsToCamelCase(response.data).map((b) => ({
name: b.name,
default: b.default,
})),
@@ -41,7 +41,7 @@ export default {
[types.RECEIVE_TAGS_SUCCESS](state, response) {
state.matches.tags = {
- list: convertObjectPropsToCamelCase(response.data).map(b => ({
+ list: convertObjectPropsToCamelCase(response.data).map((b) => ({
name: b.name,
})),
totalCount: parseInt(response.headers[X_TOTAL_HEADER], 10),
diff --git a/app/assets/javascripts/ref_select_dropdown.js b/app/assets/javascripts/ref_select_dropdown.js
index af8729c1d08..c283fb1ea08 100644
--- a/app/assets/javascripts/ref_select_dropdown.js
+++ b/app/assets/javascripts/ref_select_dropdown.js
@@ -31,7 +31,7 @@ class RefSelectDropdown {
const $fieldInput = $(`input[name="${$dropdownButton.data('fieldName')}"]`, $dropdownContainer);
const $filterInput = $('input[type="search"]', $dropdownContainer);
- $filterInput.on('keyup', e => {
+ $filterInput.on('keyup', (e) => {
const keyCode = e.keyCode || e.which;
if (keyCode !== 13) return;
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue b/app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue
index 8bdf043a106..56d2ff86fb7 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue
+++ b/app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue
@@ -60,7 +60,7 @@ export default {
@dismiss="$emit('change', null)"
>
<gl-sprintf :message="deleteAlertConfig.message">
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="garbageCollectionHelpPagePath" target="_blank">
{{ content }}
</gl-link>
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 3eeb7b29386..ed02aa264ed 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,12 +1,29 @@
<script>
import { GlSprintf } from '@gitlab/ui';
-import { sprintf } from '~/locale';
+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 timeagoMixin from '~/vue_shared/mixins/timeago';
-import { DETAILS_PAGE_TITLE, UPDATED_AT } from '../../constants/index';
+import {
+ DETAILS_PAGE_TITLE,
+ UPDATED_AT,
+ CLEANUP_UNSCHEDULED_TEXT,
+ CLEANUP_SCHEDULED_TEXT,
+ CLEANUP_ONGOING_TEXT,
+ CLEANUP_UNFINISHED_TEXT,
+ CLEANUP_DISABLED_TEXT,
+ CLEANUP_SCHEDULED_TOOLTIP,
+ CLEANUP_ONGOING_TOOLTIP,
+ CLEANUP_UNFINISHED_TOOLTIP,
+ CLEANUP_DISABLED_TOOLTIP,
+ UNFINISHED_STATUS,
+ UNSCHEDULED_STATUS,
+ SCHEDULED_STATUS,
+ ONGOING_STATUS,
+} from '../../constants/index';
export default {
+ name: 'DetailsHeader',
components: { GlSprintf, TitleArea, MetadataItem },
mixins: [timeagoMixin],
props: {
@@ -14,6 +31,11 @@ export default {
type: Object,
required: true,
},
+ metadataLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
visibilityIcon() {
@@ -25,6 +47,24 @@ export default {
updatedText() {
return sprintf(UPDATED_AT, { time: this.timeAgo });
},
+ tagCountText() {
+ return n__('%d tag', '%d tags', this.image.tagsCount);
+ },
+ cleanupTextAndTooltip() {
+ if (!this.image.project.containerExpirationPolicy?.enabled) {
+ return { text: CLEANUP_DISABLED_TEXT, tooltip: CLEANUP_DISABLED_TOOLTIP };
+ }
+ return {
+ [UNSCHEDULED_STATUS]: {
+ text: sprintf(CLEANUP_UNSCHEDULED_TEXT, {
+ time: this.timeFormatted(this.image.project.containerExpirationPolicy.nextRunAt),
+ }),
+ },
+ [SCHEDULED_STATUS]: { text: CLEANUP_SCHEDULED_TEXT, tooltip: CLEANUP_SCHEDULED_TOOLTIP },
+ [ONGOING_STATUS]: { text: CLEANUP_ONGOING_TEXT, tooltip: CLEANUP_ONGOING_TOOLTIP },
+ [UNFINISHED_STATUS]: { text: CLEANUP_UNFINISHED_TEXT, tooltip: CLEANUP_UNFINISHED_TOOLTIP },
+ }[this.image?.expirationPolicyCleanupStatus];
+ },
},
i18n: {
DETAILS_PAGE_TITLE,
@@ -33,7 +73,7 @@ export default {
</script>
<template>
- <title-area>
+ <title-area :metadata-loading="metadataLoading">
<template #title>
<gl-sprintf :message="$options.i18n.DETAILS_PAGE_TITLE">
<template #imageName>
@@ -41,6 +81,20 @@ export default {
</template>
</gl-sprintf>
</template>
+ <template #metadata-tags-count>
+ <metadata-item icon="tag" :text="tagCountText" data-testid="tags-count" />
+ </template>
+
+ <template #metadata-cleanup>
+ <metadata-item
+ icon="expire"
+ :text="cleanupTextAndTooltip.text"
+ :text-tooltip="cleanupTextAndTooltip.tooltip"
+ size="xl"
+ data-testid="cleanup"
+ />
+ </template>
+
<template #metadata-updated>
<metadata-item
:icon="visibilityIcon"
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue b/app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue
index d13d815a59e..12095655126 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue
+++ b/app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue
@@ -23,12 +23,12 @@ export default {
<template>
<gl-alert variant="warning" :title="$options.i18n.DELETE_ALERT_TITLE" @dismiss="$emit('dismiss')">
<gl-sprintf :message="$options.i18n.DELETE_ALERT_LINK_TEXT">
- <template #adminLink="{content}">
+ <template #adminLink="{ content }">
<gl-link data-testid="run-link" :href="runCleanupPoliciesHelpPagePath" target="_blank">{{
content
}}</gl-link>
</template>
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link data-testid="help-link" :href="cleanupPoliciesHelpPagePath" target="_blank">{{
content
}}</gl-link>
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 ad39a898e7b..1e0736c4a53 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
@@ -4,6 +4,7 @@ import TagsListRow from './tags_list_row.vue';
import { REMOVE_TAGS_BUTTON_TITLE, TAGS_LIST_TITLE } from '../../constants/index';
export default {
+ name: 'TagsList',
components: {
GlButton,
TagsListRow,
@@ -31,10 +32,10 @@ export default {
},
computed: {
hasSelectedItems() {
- return this.tags.some(tag => this.selectedItems[tag.name]);
+ return this.tags.some((tag) => this.selectedItems[tag.name]);
},
showMultiDeleteButton() {
- return this.tags.some(tag => tag.canDelete) && !this.isMobile;
+ return this.tags.some((tag) => tag.canDelete) && !this.isMobile;
},
},
methods: {
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 3a5cccc7d08..2e4a489f2cb 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
@@ -140,9 +140,7 @@ export default {
<template #left-secondary>
<span data-testid="size">
{{ formattedSize }}
- <template v-if="formattedSize && layers"
- >&middot;</template
- >
+ <template v-if="formattedSize && layers">&middot;</template>
{{ layers }}
</span>
</template>
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue b/app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue
index 319666210d6..07ee3c6083b 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue
@@ -19,8 +19,8 @@ export default {
GlDropdown,
CodeInstruction,
},
- inject: ['config', 'dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand'],
mixins: [Tracking.mixin({ label: trackingLabel })],
+ inject: ['config', 'dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand'],
trackingLabel,
i18n: {
QUICK_START,
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue b/app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue
index 26e9fee63af..a68c4de5aa6 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue
@@ -3,12 +3,12 @@ import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
export default {
name: 'GroupEmptyState',
- inject: ['config'],
components: {
GlEmptyState,
GlSprintf,
GlLink,
},
+ inject: ['config'],
};
</script>
<template>
@@ -25,7 +25,7 @@ export default {
)
"
>
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="config.helpPagePath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/image_list.vue b/app/assets/javascripts/registry/explorer/components/list_page/image_list.vue
index f8b3233438f..10ad99d5956 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/image_list.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/image_list.vue
@@ -13,6 +13,11 @@ export default {
type: Array,
required: true,
},
+ metadataLoading: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
pageInfo: {
type: Object,
required: true,
@@ -33,6 +38,7 @@ export default {
:key="index"
:item="listItem"
:first="index === 0"
+ :metadata-loading="metadataLoading"
@delete="$emit('delete', $event)"
/>
<div class="gl-display-flex gl-justify-content-center">
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 3fe61dc231a..264a3c27cde 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,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlIcon, GlSprintf } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
import { n__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
@@ -18,13 +18,14 @@ import {
} from '../../constants/index';
export default {
- name: 'ImageListrow',
+ name: 'ImageListRow',
components: {
ClipboardButton,
DeleteButton,
GlSprintf,
GlIcon,
ListItem,
+ GlSkeletonLoader,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -34,6 +35,11 @@ export default {
type: Object,
required: true,
},
+ metadataLoading: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
},
i18n: {
LIST_DELETE_BUTTON_DISABLED,
@@ -107,7 +113,11 @@ export default {
/>
</template>
<template #left-secondary>
- <span class="gl-display-flex gl-align-items-center" data-testid="tagsCount">
+ <span
+ v-if="!metadataLoading"
+ class="gl-display-flex gl-align-items-center"
+ data-testid="tags-count"
+ >
<gl-icon name="tag" class="gl-mr-2" />
<gl-sprintf :message="tagsCountText">
<template #count>
@@ -115,6 +125,13 @@ export default {
</template>
</gl-sprintf>
</span>
+
+ <div v-else class="gl-w-full">
+ <gl-skeleton-loader :width="900" :height="16" preserve-aspect-ratio="xMinYMax meet">
+ <circle cx="6" cy="8" r="6" />
+ <rect x="16" y="4" width="100" height="8" rx="4" />
+ </gl-skeleton-loader>
+ </div>
</template>
<template #right-action>
<delete-button
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue b/app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue
index 5308b025cc0..5aa04419ca0 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue
@@ -45,7 +45,7 @@ export default {
<template #description>
<p>
<gl-sprintf :message="$options.i18n.introText">
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="config.helpPagePath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
@@ -53,10 +53,10 @@ export default {
<h5>{{ $options.i18n.quickStart }}</h5>
<p>
<gl-sprintf :message="$options.i18n.notLoggedInMessage">
- <template #twofaDocLink="{content}">
+ <template #twofaDocLink="{ content }">
<gl-link :href="config.twoFactorAuthHelpLink" target="_blank">{{ content }}</gl-link>
</template>
- <template #personalAccessTokensDocLink="{content}">
+ <template #personalAccessTokensDocLink="{ content }">
<gl-link :href="config.personalAccessTokensHelpLink" target="_blank">{{
content
}}</gl-link>
@@ -81,7 +81,7 @@ export default {
<p class="gl-mb-4">
{{ $options.i18n.addImageText }}
</p>
- <gl-form-input-group class="gl-mb-4 ">
+ <gl-form-input-group class="gl-mb-4">
<gl-form-input
:value="dockerBuildCommand"
readonly
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 c2bd01701df..f01e3c9d24a 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
@@ -13,6 +13,7 @@ import {
} from '../../constants/index';
export default {
+ name: 'ListHeader',
components: {
TitleArea,
MetadataItem,
@@ -43,6 +44,11 @@ export default {
required: false,
default: false,
},
+ metadataLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
loader: {
repeat: 10,
@@ -92,7 +98,11 @@ export default {
</script>
<template>
- <title-area :title="$options.i18n.CONTAINER_REGISTRY_TITLE" :info-messages="infoMessages">
+ <title-area
+ :title="$options.i18n.CONTAINER_REGISTRY_TITLE"
+ :info-messages="infoMessages"
+ :metadata-loading="metadataLoading"
+ >
<template #right-actions>
<slot name="commands"></slot>
</template>
diff --git a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
index 1cedcc41b2b..e77eda31596 100644
--- a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
+++ b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
@@ -1,66 +1,51 @@
<script>
-/* eslint-disable vue/no-v-html */
-// We are forced to use `v-html` untill this gitlab-ui issue is resolved: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1079
-// then we can re-write this to use gl-breadcrumb
-import { initial, first, last } from 'lodash';
-import { sanitize } from '~/lib/dompurify';
+// We are using gl-breadcrumb only at the last child of the handwritten breadcrumb
+// until this gitlab-ui issue is resolved: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1079
+//
+// See the CSS workaround in app/assets/stylesheets/pages/registry.scss when this file is changed.
+import { GlBreadcrumb, GlIcon } from '@gitlab/ui';
export default {
- props: {
- crumbs: {
- type: Array,
- required: true,
- },
+ components: {
+ GlBreadcrumb,
+ GlIcon,
},
computed: {
- parsedCrumbs() {
- return this.crumbs.map(c => ({ ...c, innerHTML: sanitize(c.innerHTML) }));
- },
rootRoute() {
- return this.$router.options.routes.find(r => r.meta.root);
+ return this.$router.options.routes.find((r) => r.meta.root);
+ },
+ detailsRoute() {
+ return this.$router.options.routes.find((r) => r.name === 'details');
},
isRootRoute() {
return this.$route.name === this.rootRoute.name;
},
- rootCrumbs() {
- return initial(this.parsedCrumbs);
- },
- divider() {
- const { classList, tagName, innerHTML } = first(this.crumbs).querySelector('svg');
- return { classList: [...classList], tagName, innerHTML: sanitize(innerHTML) };
+ isLoaded() {
+ return this.isRootRoute || this.$store?.state.imageDetails?.name;
},
- lastCrumb() {
- const { children } = last(this.crumbs);
- const { tagName, className } = first(children);
- return {
- tagName,
- className,
- text: this.$route.meta.nameGenerator(),
- path: { to: this.$route.name },
- };
+ allCrumbs() {
+ const crumbs = [
+ {
+ text: this.rootRoute.meta.nameGenerator(),
+ to: this.rootRoute.path,
+ },
+ ];
+ if (!this.isRootRoute) {
+ crumbs.push({
+ text: this.detailsRoute.meta.nameGenerator(),
+ href: this.detailsRoute.meta.path,
+ });
+ }
+ return crumbs;
},
},
};
</script>
<template>
- <ul>
- <li
- v-for="(crumb, index) in rootCrumbs"
- :key="index"
- :class="crumb.className"
- v-html="crumb.innerHTML"
- ></li>
- <li v-if="!isRootRoute">
- <router-link ref="rootRouteLink" :to="rootRoute.path">
- {{ rootRoute.meta.nameGenerator() }}
- </router-link>
- <component :is="divider.tagName" :class="divider.classList" v-html="divider.innerHTML" />
- </li>
- <li>
- <component :is="lastCrumb.tagName" ref="lastCrumb" :class="lastCrumb.className">
- <router-link ref="childRouteLink" :to="lastCrumb.path">{{ lastCrumb.text }}</router-link>
- </component>
- </li>
- </ul>
+ <gl-breadcrumb :key="isLoaded" :items="allCrumbs">
+ <template #separator>
+ <gl-icon name="angle-right" :size="8" />
+ </template>
+ </gl-breadcrumb>
</template>
diff --git a/app/assets/javascripts/registry/explorer/constants/details.js b/app/assets/javascripts/registry/explorer/constants/details.js
index 1babaaa93da..b5627352857 100644
--- a/app/assets/javascripts/registry/explorer/constants/details.js
+++ b/app/assets/javascripts/registry/explorer/constants/details.js
@@ -60,6 +60,22 @@ export const UPDATED_AT = s__('ContainerRegistry|Last updated %{time}');
export const NOT_AVAILABLE_TEXT = __('N/A');
export const NOT_AVAILABLE_SIZE = __('0 bytes');
+
+export const CLEANUP_UNSCHEDULED_TEXT = s__('ContainerRegistry|Cleanup will run %{time}');
+export const CLEANUP_SCHEDULED_TEXT = s__('ContainerRegistry|Cleanup pending');
+export const CLEANUP_ONGOING_TEXT = s__('ContainerRegistry|Cleanup in progress');
+export const CLEANUP_UNFINISHED_TEXT = s__('ContainerRegistry|Cleanup incomplete');
+export const CLEANUP_DISABLED_TEXT = s__('ContainerRegistry|Cleanup disabled');
+
+export const CLEANUP_SCHEDULED_TOOLTIP = s__('ContainerRegistry|Cleanup will run soon');
+export const CLEANUP_ONGOING_TOOLTIP = s__('ContainerRegistry|Cleanup is currently removing tags');
+export const CLEANUP_UNFINISHED_TOOLTIP = s__(
+ 'ContainerRegistry|Cleanup ran but some tags were not removed',
+);
+export const CLEANUP_DISABLED_TOOLTIP = s__(
+ 'ContainerRegistry|Cleanup is disabled for this project',
+);
+
// Parameters
export const DEFAULT_PAGE = 1;
@@ -76,3 +92,8 @@ export const ALERT_MESSAGES = {
[ALERT_SUCCESS_TAGS]: DELETE_TAGS_SUCCESS_MESSAGE,
[ALERT_DANGER_TAGS]: DELETE_TAGS_ERROR_MESSAGE,
};
+
+export const UNFINISHED_STATUS = 'UNFINISHED';
+export const UNSCHEDULED_STATUS = 'UNSCHEDULED';
+export const SCHEDULED_STATUS = 'SCHEDULED';
+export const ONGOING_STATUS = 'ONGOING';
diff --git a/app/assets/javascripts/registry/explorer/graphql/fragments/container_repository.fragment.graphql b/app/assets/javascripts/registry/explorer/graphql/fragments/container_repository.fragment.graphql
deleted file mode 100644
index 9a3579ee8e0..00000000000
--- a/app/assets/javascripts/registry/explorer/graphql/fragments/container_repository.fragment.graphql
+++ /dev/null
@@ -1,11 +0,0 @@
-fragment ContainerRepositoryFields on ContainerRepository {
- id
- name
- path
- status
- location
- canDelete
- createdAt
- tagsCount
- expirationPolicyStartedAt
-}
diff --git a/app/assets/javascripts/registry/explorer/graphql/index.js b/app/assets/javascripts/registry/explorer/graphql/index.js
index 16152eb81f6..d934bcc7419 100644
--- a/app/assets/javascripts/registry/explorer/graphql/index.js
+++ b/app/assets/javascripts/registry/explorer/graphql/index.js
@@ -8,6 +8,7 @@ export const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
+ batchMax: 1,
assumeImmutableResults: true,
},
),
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
new file mode 100644
index 00000000000..8b6d778c655
--- /dev/null
+++ b/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
@@ -0,0 +1,26 @@
+query getContainerRepositoriesDetails(
+ $fullPath: ID!
+ $name: String
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
+ $isGroupPage: Boolean!
+) {
+ project(fullPath: $fullPath) @skip(if: $isGroupPage) {
+ containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ nodes {
+ id
+ tagsCount
+ }
+ }
+ }
+ group(fullPath: $fullPath) @include(if: $isGroupPage) {
+ containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ nodes {
+ id
+ tagsCount
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql b/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
index b40200e020b..3fd019467ac 100644
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
+++ b/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
@@ -18,6 +18,7 @@ query getContainerRepositoryDetails(
updatedAt
tagsCount
expirationPolicyStartedAt
+ expirationPolicyCleanupStatus
tags(after: $after, before: $before, first: $first, last: $last) {
nodes {
digest
@@ -36,6 +37,10 @@ query getContainerRepositoryDetails(
}
project {
visibility
+ containerExpirationPolicy {
+ enabled
+ nextRunAt
+ }
}
}
}
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_group_container_repositories.query.graphql b/app/assets/javascripts/registry/explorer/graphql/queries/get_group_container_repositories.query.graphql
deleted file mode 100644
index 348eda97ea7..00000000000
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_group_container_repositories.query.graphql
+++ /dev/null
@@ -1,23 +0,0 @@
-#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-#import "../fragments/container_repository.fragment.graphql"
-
-query getGroupContainerRepositories(
- $fullPath: ID!
- $name: String
- $first: Int
- $last: Int
- $after: String
- $before: String
-) {
- group(fullPath: $fullPath) {
- containerRepositoriesCount
- containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
- nodes {
- ...ContainerRepositoryFields
- }
- pageInfo {
- ...PageInfo
- }
- }
- }
-}
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_project_container_repositories.query.graphql b/app/assets/javascripts/registry/explorer/graphql/queries/get_project_container_repositories.query.graphql
deleted file mode 100644
index 338e27745f7..00000000000
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_project_container_repositories.query.graphql
+++ /dev/null
@@ -1,23 +0,0 @@
-#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-#import "../fragments/container_repository.fragment.graphql"
-
-query getProjectContainerRepositories(
- $fullPath: ID!
- $name: String
- $first: Int
- $last: Int
- $after: String
- $before: String
-) {
- project(fullPath: $fullPath) {
- containerRepositoriesCount
- containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
- nodes {
- ...ContainerRepositoryFields
- }
- pageInfo {
- ...PageInfo
- }
- }
- }
-}
diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js
index d887b6a1b15..a3890ab5c42 100644
--- a/app/assets/javascripts/registry/explorer/index.js
+++ b/app/assets/javascripts/registry/explorer/index.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
import Translate from '~/vue_shared/translate';
import { parseBoolean } from '~/lib/utils/common_utils';
+import PerformancePlugin from '~/performance/vue_performance_plugin';
import RegistryExplorer from './pages/index.vue';
import RegistryBreadcrumb from './components/registry_breadcrumb.vue';
import createRouter from './router';
@@ -10,6 +11,17 @@ import { apolloProvider } from './graphql/index';
Vue.use(Translate);
Vue.use(GlToast);
+Vue.use(PerformancePlugin, {
+ components: [
+ 'RegistryListPage',
+ 'ListHeader',
+ 'ImageListRow',
+ 'RegistryDetailsPage',
+ 'DetailsHeader',
+ 'TagsList',
+ ],
+});
+
export default () => {
const el = document.getElementById('js-container-registry');
@@ -59,16 +71,28 @@ export default () => {
});
const attachBreadcrumb = () => {
- const breadCrumbEl = document.querySelector('nav .js-breadcrumbs-list');
- const crumbs = [...document.querySelectorAll('.js-breadcrumbs-list li')];
+ const breadCrumbEls = document.querySelectorAll('nav .js-breadcrumbs-list li');
+ const breadCrumbEl = breadCrumbEls[breadCrumbEls.length - 1];
+ const crumbs = [breadCrumbEl.querySelector('h2')];
+ const nestedBreadcrumbEl = document.createElement('div');
+ breadCrumbEl.replaceChild(nestedBreadcrumbEl, breadCrumbEl.querySelector('h2'));
return new Vue({
- el: breadCrumbEl,
+ el: nestedBreadcrumbEl,
router,
apolloProvider,
components: {
RegistryBreadcrumb,
},
render(createElement) {
+ // FIXME(@tnir): this is a workaround until the MR gets merged:
+ // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48115
+ const parentEl = breadCrumbEl.parentElement.parentElement;
+ if (parentEl) {
+ parentEl.classList.remove('breadcrumbs-container');
+ parentEl.classList.add('gl-display-flex');
+ parentEl.classList.add('w-100');
+ }
+ // End of FIXME(@tnir)
return createElement('registry-breadcrumb', {
class: breadCrumbEl.className,
props: {
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue
index 540f02d58d4..0894fd6fcfa 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/registry/explorer/pages/details.vue
@@ -22,9 +22,11 @@ import {
ALERT_DANGER_TAGS,
GRAPHQL_PAGE_SIZE,
FETCH_IMAGES_LIST_ERROR_MESSAGE,
+ UNFINISHED_STATUS,
} from '../constants/index';
export default {
+ name: 'RegistryDetailsPage',
components: {
DeleteAlert,
PartialCleanupAlert,
@@ -35,11 +37,11 @@ export default {
TagsLoader,
EmptyTagsState,
},
- inject: ['breadCrumbState', 'config'],
directives: {
GlResizeObserver: GlResizeObserverDirective,
},
mixins: [Tracking.mixin()],
+ inject: ['breadCrumbState', 'config'],
apollo: {
image: {
query: getContainerRepositoryDetailsQuery,
@@ -83,7 +85,10 @@ export default {
return this.image?.tags?.nodes || [];
},
showPartialCleanupWarning() {
- return this.image?.expirationPolicyStartedAt && !this.dismissPartialCleanupWarning;
+ return (
+ this.image?.expirationPolicyCleanupStatus === UNFINISHED_STATUS &&
+ !this.dismissPartialCleanupWarning
+ );
},
tracking() {
return {
@@ -97,7 +102,7 @@ export default {
},
methods: {
deleteTags(toBeDeleted) {
- this.itemsToBeDeleted = this.tags.filter(tag => toBeDeleted[tag.name]);
+ this.itemsToBeDeleted = this.tags.filter((tag) => toBeDeleted[tag.name]);
this.track('click_button');
this.$refs.deleteModal.show();
},
@@ -111,7 +116,7 @@ export default {
mutation: deleteContainerRepositoryTagsMutation,
variables: {
id: this.queryVariables.id,
- tagNames: itemsToBeDeleted.map(i => i.name),
+ tagNames: itemsToBeDeleted.map((i) => i.name),
},
awaitRefetchQueries: true,
refetchQueries: [
@@ -183,7 +188,7 @@ export default {
@dismiss="dismissPartialCleanupWarning = true"
/>
- <details-header :image="image" />
+ <details-header :image="image" :metadata-loading="isLoading" />
<tags-loader v-if="isLoading" />
<template v-else>
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 3192ba82db8..336a997d629 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -9,17 +9,13 @@ import {
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 ProjectEmptyState from '../components/list_page/project_empty_state.vue';
-import GroupEmptyState from '../components/list_page/group_empty_state.vue';
import RegistryHeader from '../components/list_page/registry_header.vue';
-import ImageList from '../components/list_page/image_list.vue';
-import CliCommands from '../components/list_page/cli_commands.vue';
-import getProjectContainerRepositoriesQuery from '../graphql/queries/get_project_container_repositories.query.graphql';
-import getGroupContainerRepositoriesQuery from '../graphql/queries/get_group_container_repositories.query.graphql';
+import getContainerRepositoriesDetails from '../graphql/queries/get_container_repositories_details.query.graphql';
import deleteContainerRepositoryMutation from '../graphql/mutations/delete_container_repository.mutation.graphql';
import {
@@ -38,12 +34,25 @@ import {
} from '../constants/index';
export default {
- name: 'RegistryListApp',
+ name: 'RegistryListPage',
components: {
GlEmptyState,
- ProjectEmptyState,
- GroupEmptyState,
- ImageList,
+ ProjectEmptyState: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/project_empty_state.vue'
+ ),
+ GroupEmptyState: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/group_empty_state.vue'
+ ),
+ ImageList: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/image_list.vue'
+ ),
+ CliCommands: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/cli_commands.vue'
+ ),
GlModal,
GlSprintf,
GlLink,
@@ -51,13 +60,12 @@ export default {
GlSkeletonLoader,
GlSearchBoxByClick,
RegistryHeader,
- CliCommands,
},
- inject: ['config'],
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [Tracking.mixin()],
+ inject: ['config'],
loader: {
repeat: 10,
width: 1000,
@@ -74,10 +82,8 @@ export default {
EMPTY_RESULT_MESSAGE,
},
apollo: {
- images: {
- query() {
- return this.graphQlQuery;
- },
+ baseImages: {
+ query: getContainerRepositoriesQuery,
variables() {
return this.queryVariables;
},
@@ -92,10 +98,26 @@ export default {
createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
+ additionalDetails: {
+ skip() {
+ return !this.fetchAdditionalDetails;
+ },
+ query: getContainerRepositoriesDetails,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data[this.graphqlResource]?.containerRepositories.nodes;
+ },
+ error() {
+ createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
+ },
+ },
},
data() {
return {
- images: [],
+ baseImages: [],
+ additionalDetails: [],
pageInfo: {},
containerRepositoriesCount: 0,
itemToDelete: {},
@@ -103,21 +125,24 @@ export default {
searchValue: null,
name: null,
mutationLoading: false,
+ fetchAdditionalDetails: false,
};
},
computed: {
+ images() {
+ return this.baseImages.map((image, index) => ({
+ ...image,
+ ...get(this.additionalDetails, index, {}),
+ }));
+ },
graphqlResource() {
return this.config.isGroupPage ? 'group' : 'project';
},
- graphQlQuery() {
- return this.config.isGroupPage
- ? getGroupContainerRepositoriesQuery
- : getProjectContainerRepositoriesQuery;
- },
queryVariables() {
return {
name: this.name,
fullPath: this.config.isGroupPage ? this.config.groupPath : this.config.projectPath,
+ isGroupPage: this.config.isGroupPage,
first: GRAPHQL_PAGE_SIZE,
};
},
@@ -127,7 +152,7 @@ export default {
};
},
isLoading() {
- return this.$apollo.queries.images.loading || this.mutationLoading;
+ return this.$apollo.queries.baseImages.loading || this.mutationLoading;
},
showCommands() {
return Boolean(!this.isLoading && !this.config?.isGroupPage && this.images?.length);
@@ -141,6 +166,13 @@ export default {
: DELETE_IMAGE_ERROR_MESSAGE;
},
},
+ mounted() {
+ // If the two graphql calls - which are not batched - resolve togheter we will have a race
+ // condition when apollo sets the cache, with this we give the 'base' call an headstart
+ setTimeout(() => {
+ this.fetchAdditionalDetails = true;
+ }, 200);
+ },
methods: {
deleteImage(item) {
this.track('click_button');
@@ -175,30 +207,46 @@ export default {
this.deleteAlertType = null;
this.itemToDelete = {};
},
- fetchNextPage() {
+ updateQuery(_, { fetchMoreResult }) {
+ return fetchMoreResult;
+ },
+ async fetchNextPage() {
if (this.pageInfo?.hasNextPage) {
- this.$apollo.queries.images.fetchMore({
- variables: {
- after: this.pageInfo?.endCursor,
- first: GRAPHQL_PAGE_SIZE,
- },
- updateQuery(previousResult, { fetchMoreResult }) {
- return fetchMoreResult;
- },
+ const variables = {
+ after: this.pageInfo?.endCursor,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+
+ this.$apollo.queries.baseImages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+
+ await this.$nextTick();
+
+ this.$apollo.queries.additionalDetails.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
});
}
},
- fetchPreviousPage() {
+ async fetchPreviousPage() {
if (this.pageInfo?.hasPreviousPage) {
- this.$apollo.queries.images.fetchMore({
- variables: {
- first: null,
- before: this.pageInfo?.startCursor,
- last: GRAPHQL_PAGE_SIZE,
- },
- updateQuery(previousResult, { fetchMoreResult }) {
- return fetchMoreResult;
- },
+ const variables = {
+ first: null,
+ before: this.pageInfo?.startCursor,
+ last: GRAPHQL_PAGE_SIZE,
+ };
+ this.$apollo.queries.baseImages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+
+ await this.$nextTick();
+
+ this.$apollo.queries.additionalDetails.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
});
}
},
@@ -230,7 +278,7 @@ export default {
<template #description>
<p>
<gl-sprintf :message="$options.i18n.CONNECTION_ERROR_MESSAGE">
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="`${config.helpPagePath}#docker-connection-error`" target="_blank">
{{ content }}
</gl-link>
@@ -242,6 +290,7 @@ export default {
<template v-else>
<registry-header
+ :metadata-loading="isLoading"
:images-count="containerRepositoriesCount"
:expiration-policy="config.expirationPolicy"
:help-page-path="config.helpPagePath"
@@ -285,6 +334,7 @@ export default {
<image-list
v-if="images.length"
:images="images"
+ :metadata-loading="$apollo.queries.additionalDetails.loading"
:page-info="pageInfo"
@delete="deleteImage"
@prev-page="fetchPreviousPage"
diff --git a/app/assets/javascripts/registry/settings/components/expiration_input.vue b/app/assets/javascripts/registry/settings/components/expiration_input.vue
index 2dbd9d26f60..42b7c7918a5 100644
--- a/app/assets/javascripts/registry/settings/components/expiration_input.vue
+++ b/app/assets/javascripts/registry/settings/components/expiration_input.vue
@@ -83,7 +83,7 @@ export default {
<template #label>
<span data-testid="label">
<gl-sprintf :message="label">
- <template #italic="{content}">
+ <template #italic="{ content }">
<i>{{ content }}</i>
</template>
</gl-sprintf>
@@ -100,7 +100,7 @@ export default {
<template #description>
<span data-testid="description" class="gl-text-gray-400">
<gl-sprintf :message="description">
- <template #link="{content}">
+ <template #link="{ content }">
<gl-link :href="tagsRegexHelpPagePath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/registry/settings/components/expiration_toggle.vue b/app/assets/javascripts/registry/settings/components/expiration_toggle.vue
index 7f045244926..0ffd8216ab1 100644
--- a/app/assets/javascripts/registry/settings/components/expiration_toggle.vue
+++ b/app/assets/javascripts/registry/settings/components/expiration_toggle.vue
@@ -42,7 +42,7 @@ export default {
<gl-toggle id="expiration-policy-toggle" v-model="enabled" :disabled="disabled" />
<span class="gl-ml-5 gl-line-height-24" data-testid="description">
<gl-sprintf :message="toggleText">
- <template #strong="{content}">
+ <template #strong="{ content }">
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
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 35c7a8be4ea..66eb681784e 100644
--- a/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
+++ b/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
@@ -33,7 +33,7 @@ export default {
projectPath: this.projectPath,
};
},
- update: data => data.project?.containerExpirationPolicy,
+ update: (data) => data.project?.containerExpirationPolicy,
result({ data }) {
this.workingCopy = { ...get(data, 'project.containerExpirationPolicy', {}) };
},
diff --git a/app/assets/javascripts/registry/settings/components/settings_form.vue b/app/assets/javascripts/registry/settings/components/settings_form.vue
index 1f374c7b60e..7043cea49ba 100644
--- a/app/assets/javascripts/registry/settings/components/settings_form.vue
+++ b/app/assets/javascripts/registry/settings/components/settings_form.vue
@@ -96,7 +96,7 @@ export default {
return this.isLoading || this.mutationLoading;
},
fieldsAreValid() {
- return Object.values(this.localErrors).every(error => error);
+ return Object.values(this.localErrors).every((error) => error);
},
isSubmitButtonDisabled() {
return !this.fieldsAreValid || this.showLoadingIcon;
@@ -121,7 +121,7 @@ export default {
},
methods: {
findDefaultOption(option) {
- return this.value[option] || this.$options.formOptions[option].find(f => f.default)?.key;
+ return this.value[option] || this.$options.formOptions[option].find((f) => f.default)?.key;
},
reset() {
this.track('reset_form');
@@ -131,7 +131,7 @@ export default {
},
setApiErrors(response) {
this.apiErrors = response.graphQLErrors.reduce((acc, curr) => {
- curr.extensions.problems.forEach(item => {
+ curr.extensions.problems.forEach((item) => {
acc[item.path[0]] = item.message;
});
return acc;
@@ -163,7 +163,7 @@ export default {
this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' });
}
})
- .catch(error => {
+ .catch((error) => {
this.setApiErrors(error);
this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE, { type: 'error' });
})
@@ -214,10 +214,10 @@ export default {
<div>
<p>
<gl-sprintf :message="$options.i18n.KEEP_INFO_TEXT">
- <template #strong="{content}">
+ <template #strong="{ content }">
<strong>{{ content }}</strong>
</template>
- <template #secondStrong="{content}">
+ <template #secondStrong="{ content }">
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
@@ -253,10 +253,10 @@ export default {
<div>
<p>
<gl-sprintf :message="$options.i18n.REMOVE_INFO_TEXT">
- <template #strong="{content}">
+ <template #strong="{ content }">
<strong>{{ content }}</strong>
</template>
- <template #secondStrong="{content}">
+ <template #secondStrong="{ content }">
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/registry/settings/constants.js b/app/assets/javascripts/registry/settings/constants.js
index 21c54299632..165c4aae3cb 100644
--- a/app/assets/javascripts/registry/settings/constants.js
+++ b/app/assets/javascripts/registry/settings/constants.js
@@ -23,7 +23,7 @@ export const KEEP_INFO_TEXT = s__(
export const KEEP_N_LABEL = s__('ContainerRegistry|Keep the most recent:');
export const NAME_REGEX_KEEP_LABEL = s__('ContainerRegistry|Keep tags matching:');
export const NAME_REGEX_KEEP_DESCRIPTION = s__(
- 'ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}',
+ 'ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}',
);
export const REMOVE_HEADER_TEXT = s__('ContainerRegistry|Remove these tags');
@@ -34,7 +34,7 @@ export const EXPIRATION_SCHEDULE_LABEL = s__('ContainerRegistry|Remove tags olde
export const NAME_REGEX_LABEL = s__('ContainerRegistry|Remove tags matching:');
export const NAME_REGEX_PLACEHOLDER = '.*';
export const NAME_REGEX_DESCRIPTION = s__(
- 'ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}',
+ 'ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}',
);
export const ENABLED_TOGGLE_DESCRIPTION = s__(
diff --git a/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js b/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js
index 05b4125a2fc..6becaa38c7e 100644
--- a/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js
+++ b/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js
@@ -1,14 +1,14 @@
import { produce } from 'immer';
import expirationPolicyQuery from '../queries/get_expiration_policy.query.graphql';
-export const updateContainerExpirationPolicy = projectPath => (client, { data: updatedData }) => {
+export const updateContainerExpirationPolicy = (projectPath) => (client, { data: updatedData }) => {
const queryAndParams = {
query: expirationPolicyQuery,
variables: { projectPath },
};
const sourceData = client.readQuery(queryAndParams);
- const data = produce(sourceData, draftState => {
+ const data = produce(sourceData, (draftState) => {
// eslint-disable-next-line no-param-reassign
draftState.project.containerExpirationPolicy = {
...updatedData.updateContainerExpirationPolicy.containerExpirationPolicy,
diff --git a/app/assets/javascripts/registry/settings/utils.js b/app/assets/javascripts/registry/settings/utils.js
index 51b4fb6bdb8..4a2d7c7d466 100644
--- a/app/assets/javascripts/registry/settings/utils.js
+++ b/app/assets/javascripts/registry/settings/utils.js
@@ -1,18 +1,18 @@
import { n__ } from '~/locale';
import { KEEP_N_OPTIONS, CADENCE_OPTIONS, OLDER_THAN_OPTIONS } from './constants';
-export const findDefaultOption = options => {
- const item = options.find(o => o.default);
+export const findDefaultOption = (options) => {
+ const item = options.find((o) => o.default);
return item ? item.key : null;
};
-export const olderThanTranslationGenerator = variable => n__('%d day', '%d days', variable);
+export const olderThanTranslationGenerator = (variable) => n__('%d day', '%d days', variable);
-export const keepNTranslationGenerator = variable =>
+export const keepNTranslationGenerator = (variable) =>
n__('%d tag per image name', '%d tags per image name', variable);
export const optionLabelGenerator = (collection, translationFn) =>
- collection.map(option => ({
+ collection.map((option) => ({
...option,
label: translationFn(option.variable),
}));
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 b05a873e939..a124b055e19 100644
--- a/app/assets/javascripts/related_issues/components/related_issuable_input.vue
+++ b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
@@ -118,7 +118,7 @@ export default {
let position = 0;
const untouchedRawRefs = rawRefs
- .filter(ref => {
+ .filter((ref) => {
let isTouched = false;
if (caretPos >= position && caretPos <= position + ref.length) {
@@ -130,7 +130,7 @@ export default {
return !isTouched;
})
- .filter(ref => ref.trim().length > 0);
+ .filter((ref) => ref.trim().length > 0);
this.$emit('addIssuableFormInput', {
newValue: value,
@@ -208,7 +208,7 @@ export default {
:path-id-separator="pathIdSeparator"
event-namespace="pendingIssuable"
@pendingIssuableRemoveRequest="
- params => {
+ (params) => {
$emit('pendingIssuableRemoveRequest', params);
}
"
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 c913745a8e1..2591e3e7f48 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -90,11 +90,11 @@ export default {
categorisedIssues() {
if (this.showCategorizedIssues) {
return Object.values(linkedIssueTypesMap)
- .map(linkType => ({
+ .map((linkType) => ({
linkType,
- issues: this.relatedIssues.filter(issue => issue.linkType === linkType),
+ issues: this.relatedIssues.filter((issue) => issue.linkType === linkType),
}))
- .filter(obj => obj.issues.length > 0);
+ .filter((obj) => obj.issues.length > 0);
}
return [{ issues: this.relatedIssues }];
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 73ea13ddc40..a81edcf141c 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_root.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_root.vue
@@ -110,7 +110,7 @@ export default {
},
methods: {
findRelatedIssueById(id) {
- return this.state.relatedIssues.find(issue => issue.id === id);
+ return this.state.relatedIssues.find((issue) => issue.id === id);
},
onRelatedIssueRemoveRequest(idToRemove) {
const issueToRemove = this.findRelatedIssueById(idToRemove);
@@ -120,7 +120,7 @@ export default {
.then(({ data }) => {
this.store.setRelatedIssues(data.issuables);
})
- .catch(res => {
+ .catch((res) => {
if (res && res.status !== 404) {
Flash(relatedIssuesRemoveErrorMap[this.issuableType]);
}
@@ -219,7 +219,7 @@ export default {
this.processAllReferences(newValue);
},
processAllReferences(value = '') {
- const rawReferences = value.split(/\s+/).filter(reference => reference.trim().length > 0);
+ const rawReferences = value.split(/\s+/).filter((reference) => reference.trim().length > 0);
this.store.addPendingReferences(rawReferences);
this.inputValue = '';
diff --git a/app/assets/javascripts/related_issues/index.js b/app/assets/javascripts/related_issues/index.js
index 2e8626890cb..0ee99df1455 100644
--- a/app/assets/javascripts/related_issues/index.js
+++ b/app/assets/javascripts/related_issues/index.js
@@ -11,7 +11,7 @@ export default function initRelatedIssues() {
components: {
relatedIssuesRoot: RelatedIssuesRoot,
},
- render: createElement =>
+ render: (createElement) =>
createElement('related-issues-root', {
props: {
endpoint: relatedIssuesRootElement.dataset.endpoint,
diff --git a/app/assets/javascripts/related_issues/stores/related_issues_store.js b/app/assets/javascripts/related_issues/stores/related_issues_store.js
index 14d71628cad..0f0ab150c28 100644
--- a/app/assets/javascripts/related_issues/stores/related_issues_store.js
+++ b/app/assets/javascripts/related_issues/stores/related_issues_store.js
@@ -19,7 +19,7 @@ class RelatedIssuesStore {
}
removeRelatedIssue(issue) {
- this.state.relatedIssues = this.state.relatedIssues.filter(x => x.id !== issue.id);
+ this.state.relatedIssues = this.state.relatedIssues.filter((x) => x.id !== issue.id);
}
updateIssueOrder(oldIndex, newIndex) {
diff --git a/app/assets/javascripts/related_merge_requests/index.js b/app/assets/javascripts/related_merge_requests/index.js
index 092ff1df00f..ce33cf7df1d 100644
--- a/app/assets/javascripts/related_merge_requests/index.js
+++ b/app/assets/javascripts/related_merge_requests/index.js
@@ -15,7 +15,7 @@ export default function initRelatedMergeRequests() {
RelatedMergeRequests,
},
store: createStore(),
- render: createElement =>
+ render: (createElement) =>
createElement('related-merge-requests', {
props: { endpoint, projectNamespace, projectPath },
}),
diff --git a/app/assets/javascripts/related_merge_requests/store/actions.js b/app/assets/javascripts/related_merge_requests/store/actions.js
index 65f77f2fe19..7baab165820 100644
--- a/app/assets/javascripts/related_merge_requests/store/actions.js
+++ b/app/assets/javascripts/related_merge_requests/store/actions.js
@@ -21,7 +21,7 @@ export const fetchMergeRequests = ({ state, dispatch }) => {
return axios
.get(`${state.apiEndpoint}?per_page=${REQUEST_PAGE_COUNT}`)
- .then(res => {
+ .then((res) => {
const { headers, data } = res;
const total = Number(normalizeHeaders(headers)['X-TOTAL']) || 0;
diff --git a/app/assets/javascripts/releases/components/release_block_assets.vue b/app/assets/javascripts/releases/components/release_block_assets.vue
index eb83d8657c0..36929f559b5 100644
--- a/app/assets/javascripts/releases/components/release_block_assets.vue
+++ b/app/assets/javascripts/releases/components/release_block_assets.vue
@@ -47,7 +47,7 @@ export default {
sections() {
return [
{
- links: get(this.assets, 'sources', []).map(s => ({
+ links: get(this.assets, 'sources', []).map((s) => ({
url: s.url,
name: sprintf(__('Source code (%{fileExtension})'), { fileExtension: s.format }),
})),
@@ -73,7 +73,7 @@ export default {
links: this.otherLinks,
iconName: 'link',
},
- ].filter(section => section.links.length > 0);
+ ].filter((section) => section.links.length > 0);
},
},
methods: {
@@ -81,7 +81,7 @@ export default {
this.isAssetsExpanded = !this.isAssetsExpanded;
},
linksForType(type) {
- return this.assets.links.filter(l => l.linkType === type);
+ return this.assets.links.filter((l) => l.linkType === type);
},
},
externalLinkTooltipText: __('This link points to external content'),
diff --git a/app/assets/javascripts/releases/components/release_block_milestone_info.vue b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
index daa9c3480f4..cf4a6e07af7 100644
--- a/app/assets/javascripts/releases/components/release_block_milestone_info.vue
+++ b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
@@ -64,7 +64,7 @@ export default {
},
issueCounts() {
return this.milestones
- .map(m => m.issueStats || {})
+ .map((m) => m.issueStats || {})
.reduce(
(acc, current) => {
acc.total += current.total || 0;
@@ -79,11 +79,11 @@ export default {
);
},
showMergeRequestStats() {
- return this.milestones.some(m => m.mrStats);
+ return this.milestones.some((m) => m.mrStats);
},
mergeRequestCounts() {
return this.milestones
- .map(m => m.mrStats || {})
+ .map((m) => m.mrStats || {})
.reduce(
(acc, current) => {
acc.total += current.total || 0;
diff --git a/app/assets/javascripts/releases/components/releases_sort.vue b/app/assets/javascripts/releases/components/releases_sort.vue
index 50f6f3c19bd..c8e6e0e4996 100644
--- a/app/assets/javascripts/releases/components/releases_sort.vue
+++ b/app/assets/javascripts/releases/components/releases_sort.vue
@@ -11,14 +11,14 @@ export default {
},
computed: {
...mapState('list', {
- orderBy: state => state.sorting.orderBy,
- sort: state => state.sorting.sort,
+ orderBy: (state) => state.sorting.orderBy,
+ sort: (state) => state.sorting.sort,
}),
sortOptions() {
return SORT_OPTIONS;
},
sortText() {
- const option = this.sortOptions.find(s => s.orderBy === this.orderBy);
+ const option = this.sortOptions.find((s) => s.orderBy === this.orderBy);
return option.label;
},
isSortAscending() {
diff --git a/app/assets/javascripts/releases/constants.js b/app/assets/javascripts/releases/constants.js
index 8979aa1394d..f9653e0befa 100644
--- a/app/assets/javascripts/releases/constants.js
+++ b/app/assets/javascripts/releases/constants.js
@@ -13,7 +13,7 @@ export const ASSET_LINK_TYPE = Object.freeze({
export const DEFAULT_ASSET_LINK_TYPE = ASSET_LINK_TYPE.OTHER;
-export const PAGE_SIZE = 20;
+export const PAGE_SIZE = 10;
export const ASCENDING_ODER = 'asc';
export const DESCENDING_ORDER = 'desc';
diff --git a/app/assets/javascripts/releases/mount_edit.js b/app/assets/javascripts/releases/mount_edit.js
index 2f4b0e64e36..1232d55847b 100644
--- a/app/assets/javascripts/releases/mount_edit.js
+++ b/app/assets/javascripts/releases/mount_edit.js
@@ -18,6 +18,6 @@ export default () => {
return new Vue({
el,
store,
- render: h => h(ReleaseEditNewApp),
+ render: (h) => h(ReleaseEditNewApp),
});
};
diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js
index cd4fa5c5df5..a9538cbc9e5 100644
--- a/app/assets/javascripts/releases/mount_index.js
+++ b/app/assets/javascripts/releases/mount_index.js
@@ -21,6 +21,6 @@ export default () => {
graphqlMilestoneStats: Boolean(gon.features?.graphqlMilestoneStats),
},
}),
- render: h => h(ReleaseListApp),
+ render: (h) => h(ReleaseListApp),
});
};
diff --git a/app/assets/javascripts/releases/mount_new.js b/app/assets/javascripts/releases/mount_new.js
index 5c481498ffb..d85f4cf77d5 100644
--- a/app/assets/javascripts/releases/mount_new.js
+++ b/app/assets/javascripts/releases/mount_new.js
@@ -18,6 +18,6 @@ export default () => {
return new Vue({
el,
store,
- render: h => h(ReleaseEditNewApp),
+ render: (h) => h(ReleaseEditNewApp),
});
};
diff --git a/app/assets/javascripts/releases/mount_show.js b/app/assets/javascripts/releases/mount_show.js
index b09ecc9fb55..f3ed7d6c5ff 100644
--- a/app/assets/javascripts/releases/mount_show.js
+++ b/app/assets/javascripts/releases/mount_show.js
@@ -21,6 +21,6 @@ export default () => {
return new Vue({
el,
store,
- render: h => h(ReleaseShowApp),
+ render: (h) => h(ReleaseShowApp),
});
};
diff --git a/app/assets/javascripts/releases/stores/getters.js b/app/assets/javascripts/releases/stores/getters.js
index 6a1da63289c..2a06f398e26 100644
--- a/app/assets/javascripts/releases/stores/getters.js
+++ b/app/assets/javascripts/releases/stores/getters.js
@@ -2,7 +2,7 @@
* @returns {Boolean} `true` if all the feature flags
* required to enable the GraphQL endpoint are enabled
*/
-export const useGraphQLEndpoint = rootState => {
+export const useGraphQLEndpoint = (rootState) => {
return Boolean(
rootState.featureFlags.graphqlReleaseData &&
rootState.featureFlags.graphqlReleasesPage &&
diff --git a/app/assets/javascripts/releases/stores/modules/detail/actions.js b/app/assets/javascripts/releases/stores/modules/detail/actions.js
index e8a46f40d20..127646826a6 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/actions.js
@@ -36,12 +36,12 @@ export const fetchRelease = ({ commit, state, rootState }) => {
tagName: state.tagName,
},
})
- .then(response => {
+ .then((response) => {
const { data: release } = convertOneReleaseGraphQLResponse(response);
commit(types.RECEIVE_RELEASE_SUCCESS, release);
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_RELEASE_ERROR, error);
createFlash(s__('Release|Something went wrong while getting the release details'));
});
@@ -52,7 +52,7 @@ export const fetchRelease = ({ commit, state, rootState }) => {
.then(({ data }) => {
commit(types.RECEIVE_RELEASE_SUCCESS, apiJsonToRelease(data));
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_RELEASE_ERROR, error);
createFlash(s__('Release|Something went wrong while getting the release details'));
});
@@ -121,7 +121,7 @@ export const createRelease = ({ commit, dispatch, state, getters }) => {
.then(({ data }) => {
dispatch('receiveSaveReleaseSuccess', apiJsonToRelease(data));
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
createFlash(s__('Release|Something went wrong while creating a new release'));
});
@@ -163,7 +163,7 @@ export const updateRelease = ({ commit, dispatch, state, getters }) => {
// Delete all links currently associated with this Release
return Promise.all(
- getters.releaseLinksToDelete.map(l =>
+ getters.releaseLinksToDelete.map((l) =>
api.deleteReleaseLink(state.projectId, state.release.tagName, l.id),
),
);
@@ -171,7 +171,7 @@ export const updateRelease = ({ commit, dispatch, state, getters }) => {
.then(() => {
// Create a new link for each link in the form
return Promise.all(
- apiJson.assets.links.map(l =>
+ apiJson.assets.links.map((l) =>
api.createReleaseLink(state.projectId, state.release.tagName, l),
),
);
@@ -179,7 +179,7 @@ export const updateRelease = ({ commit, dispatch, state, getters }) => {
.then(() => {
dispatch('receiveSaveReleaseSuccess', apiJsonToRelease(updatedRelease));
})
- .catch(error => {
+ .catch((error) => {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
createFlash(s__('Release|Something went wrong while saving the release details'));
})
diff --git a/app/assets/javascripts/releases/stores/modules/detail/getters.js b/app/assets/javascripts/releases/stores/modules/detail/getters.js
index 809ed075c16..831037c8861 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/getters.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/getters.js
@@ -5,7 +5,7 @@ import { hasContent } from '~/lib/utils/text_utility';
* @returns {Boolean} `true` if the app is editing an existing release.
* `false` if the app is creating a new release.
*/
-export const isExistingRelease = state => {
+export const isExistingRelease = (state) => {
return Boolean(state.tagName);
};
@@ -15,19 +15,19 @@ export const isExistingRelease = state => {
* empty (or whitespace-only) values for both `url` and `name`.
* Otherwise, `false`.
*/
-const isEmptyReleaseLink = link => !hasContent(link.url) && !hasContent(link.name);
+const isEmptyReleaseLink = (link) => !hasContent(link.url) && !hasContent(link.name);
/** Returns all release links that aren't empty */
-export const releaseLinksToCreate = state => {
+export const releaseLinksToCreate = (state) => {
if (!state.release) {
return [];
}
- return state.release.assets.links.filter(l => !isEmptyReleaseLink(l));
+ return state.release.assets.links.filter((l) => !isEmptyReleaseLink(l));
};
/** Returns all release links that should be deleted */
-export const releaseLinksToDelete = state => {
+export const releaseLinksToDelete = (state) => {
if (!state.originalRelease) {
return [];
}
@@ -36,7 +36,7 @@ export const releaseLinksToDelete = state => {
};
/** Returns all validation errors on the release object */
-export const validationErrors = state => {
+export const validationErrors = (state) => {
const errors = {
assets: {
links: {},
@@ -56,7 +56,7 @@ export const validationErrors = state => {
// This is used for detecting duplicate URLs.
const urlToLinksMap = new Map();
- state.release.assets.links.forEach(link => {
+ state.release.assets.links.forEach((link) => {
errors.assets.links[link.id] = {};
// Only validate non-empty URLs
@@ -81,7 +81,7 @@ export const validationErrors = state => {
// add a validation error for each link that shares this URL
const duplicates = urlToLinksMap.get(normalizedUrl);
duplicates.push(link);
- duplicates.forEach(duplicateLink => {
+ duplicates.forEach((duplicateLink) => {
errors.assets.links[duplicateLink.id].isDuplicate = true;
});
} else {
diff --git a/app/assets/javascripts/releases/stores/modules/detail/index.js b/app/assets/javascripts/releases/stores/modules/detail/index.js
index 40fdb04f2eb..e1b7e69accc 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/index.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/index.js
@@ -3,7 +3,7 @@ import * as getters from './getters';
import mutations from './mutations';
import createState from './state';
-export default initialState => ({
+export default (initialState) => ({
namespaced: true,
actions,
getters,
diff --git a/app/assets/javascripts/releases/stores/modules/detail/mutations.js b/app/assets/javascripts/releases/stores/modules/detail/mutations.js
index 58a1958c5e2..8f4bfbc9b86 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/mutations.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/mutations.js
@@ -3,7 +3,7 @@ import * as types from './mutation_types';
import { DEFAULT_ASSET_LINK_TYPE } from '../../../constants';
const findReleaseLink = (release, id) => {
- return release.assets.links.find(l => l.id === id);
+ return release.assets.links.find((l) => l.id === id);
};
export default {
@@ -93,6 +93,6 @@ export default {
},
[types.REMOVE_ASSET_LINK](state, linkIdToRemove) {
- state.release.assets.links = state.release.assets.links.filter(l => l.id !== linkIdToRemove);
+ state.release.assets.links = state.release.assets.links.filter((l) => l.id !== linkIdToRemove);
},
};
diff --git a/app/assets/javascripts/releases/stores/modules/list/actions.js b/app/assets/javascripts/releases/stores/modules/list/actions.js
index a62f7c25464..4c4f6e19a93 100644
--- a/app/assets/javascripts/releases/stores/modules/list/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/list/actions.js
@@ -68,7 +68,7 @@ export const fetchReleasesGraphQl = (
...paginationParams,
},
})
- .then(response => {
+ .then((response) => {
const { data, paginationInfo: graphQlPageInfo } = convertAllReleasesGraphQLResponse(response);
commit(types.RECEIVE_RELEASES_SUCCESS, {
diff --git a/app/assets/javascripts/releases/stores/modules/list/index.js b/app/assets/javascripts/releases/stores/modules/list/index.js
index 0f97fa83ced..244f41b6609 100644
--- a/app/assets/javascripts/releases/stores/modules/list/index.js
+++ b/app/assets/javascripts/releases/stores/modules/list/index.js
@@ -2,7 +2,7 @@ import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default initialState => ({
+export default (initialState) => ({
namespaced: true,
actions,
mutations,
diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js
index 464f0594b8d..b24a226cf9c 100644
--- a/app/assets/javascripts/releases/util.js
+++ b/app/assets/javascripts/releases/util.js
@@ -17,7 +17,7 @@ export const releaseToApiJson = (release, createFrom = null) => {
// Milestones may be either a list of milestone objects OR just a list
// of milestone titles. The API requires only the titles be sent.
- const milestones = (release.milestones || []).map(m => m.title || m);
+ const milestones = (release.milestones || []).map((m) => m.title || m);
return convertObjectPropsToSnakeCase(
{
@@ -37,7 +37,7 @@ export const releaseToApiJson = (release, createFrom = null) => {
* into the structure this Vue application can work with.
* @param {Object} json The JSON object received from the release API
*/
-export const apiJsonToRelease = json => {
+export const apiJsonToRelease = (json) => {
const release = convertObjectPropsToCamelCase(json, { deep: true });
release.milestones = release.milestones || [];
@@ -47,7 +47,7 @@ export const apiJsonToRelease = json => {
export const gqClient = createGqClient({}, { fetchPolicy: fetchPolicies.NO_CACHE });
-const convertScalarProperties = graphQLRelease =>
+const convertScalarProperties = (graphQLRelease) =>
pick(graphQLRelease, [
'name',
'tagName',
@@ -57,29 +57,29 @@ const convertScalarProperties = graphQLRelease =>
'upcomingRelease',
]);
-const convertAssets = graphQLRelease => ({
+const convertAssets = (graphQLRelease) => ({
assets: {
count: graphQLRelease.assets.count,
sources: [...graphQLRelease.assets.sources.nodes],
- links: graphQLRelease.assets.links.nodes.map(l => ({
+ links: graphQLRelease.assets.links.nodes.map((l) => ({
...l,
linkType: l.linkType?.toLowerCase(),
})),
},
});
-const convertEvidences = graphQLRelease => ({
- evidences: graphQLRelease.evidences.nodes.map(e => e),
+const convertEvidences = (graphQLRelease) => ({
+ evidences: graphQLRelease.evidences.nodes.map((e) => e),
});
-const convertLinks = graphQLRelease => ({
+const convertLinks = (graphQLRelease) => ({
_links: {
...graphQLRelease.links,
self: graphQLRelease.links?.selfUrl,
},
});
-const convertCommit = graphQLRelease => {
+const convertCommit = (graphQLRelease) => {
if (!graphQLRelease.commit) {
return {};
}
@@ -93,10 +93,10 @@ const convertCommit = graphQLRelease => {
};
};
-const convertAuthor = graphQLRelease => ({ author: graphQLRelease.author });
+const convertAuthor = (graphQLRelease) => ({ author: graphQLRelease.author });
-const convertMilestones = graphQLRelease => ({
- milestones: graphQLRelease.milestones.nodes.map(m => ({
+const convertMilestones = (graphQLRelease) => ({
+ milestones: graphQLRelease.milestones.nodes.map((m) => ({
...m,
webUrl: m.webPath,
webPath: undefined,
@@ -115,7 +115,7 @@ const convertMilestones = graphQLRelease => ({
*
* @param graphQLRelease The release object returned from a GraphQL query
*/
-export const convertGraphQLRelease = graphQLRelease => ({
+export const convertGraphQLRelease = (graphQLRelease) => ({
...convertScalarProperties(graphQLRelease),
...convertAssets(graphQLRelease),
...convertEvidences(graphQLRelease),
@@ -134,7 +134,7 @@ export const convertGraphQLRelease = graphQLRelease => ({
*
* @param response The response received from the GraphQL endpoint
*/
-export const convertAllReleasesGraphQLResponse = response => {
+export const convertAllReleasesGraphQLResponse = (response) => {
const releases = response.data.project.releases.nodes.map(convertGraphQLRelease);
const paginationInfo = {
@@ -153,7 +153,7 @@ export const convertAllReleasesGraphQLResponse = response => {
*
* @param response The response received from the GraphQL endpoint
*/
-export const convertOneReleaseGraphQLResponse = response => {
+export const convertOneReleaseGraphQLResponse = (response) => {
const release = convertGraphQLRelease(response.data.project.release);
return { data: release };
diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js
index 312b333a771..8f8eec11c7f 100644
--- a/app/assets/javascripts/reports/accessibility_report/store/getters.js
+++ b/app/assets/javascripts/reports/accessibility_report/store/getters.js
@@ -1,7 +1,7 @@
import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants';
import { s__, n__ } from '~/locale';
-export const groupedSummaryText = state => {
+export const groupedSummaryText = (state) => {
if (state.isLoading) {
return s__('Reports|Accessibility scanning results are being parsed');
}
@@ -22,7 +22,7 @@ export const groupedSummaryText = state => {
);
};
-export const summaryStatus = state => {
+export const summaryStatus = (state) => {
if (state.isLoading) {
return LOADING;
}
@@ -34,12 +34,12 @@ export const summaryStatus = state => {
return SUCCESS;
};
-export const shouldRenderIssuesList = state =>
- Object.values(state.report).some(x => Array.isArray(x) && x.length > 0);
+export const shouldRenderIssuesList = (state) =>
+ Object.values(state.report).some((x) => Array.isArray(x) && x.length > 0);
// We could just map state, but we're going to iterate in the future
// to add notes and warnings to these issue lists, so I'm going to
// keep these as getters
-export const unresolvedIssues = state => state.report.existing_errors;
-export const resolvedIssues = state => state.report.resolved_errors;
-export const newIssues = state => state.report.new_errors;
+export const unresolvedIssues = (state) => state.report.existing_errors;
+export const resolvedIssues = (state) => state.report.resolved_errors;
+export const newIssues = (state) => state.report.new_errors;
diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js
index 9fa2c589324..5bfcd69edec 100644
--- a/app/assets/javascripts/reports/accessibility_report/store/index.js
+++ b/app/assets/javascripts/reports/accessibility_report/store/index.js
@@ -7,11 +7,11 @@ import state from './state';
Vue.use(Vuex);
-export const getStoreConfig = initialState => ({
+export const getStoreConfig = (initialState) => ({
actions,
getters,
mutations,
state: state(initialState),
});
-export default initialState => new Vuex.Store(getStoreConfig(initialState));
+export default (initialState) => new Vuex.Store(getStoreConfig(initialState));
diff --git a/app/assets/javascripts/reports/codequality_report/store/actions.js b/app/assets/javascripts/reports/codequality_report/store/actions.js
index bf84d27b5ea..e5fb5caca2e 100644
--- a/app/assets/javascripts/reports/codequality_report/store/actions.js
+++ b/app/assets/javascripts/reports/codequality_report/store/actions.js
@@ -11,13 +11,13 @@ export const fetchReports = ({ state, dispatch, commit }) => {
return dispatch('receiveReportsError');
}
return Promise.all([axios.get(state.headPath), axios.get(state.basePath)])
- .then(results =>
+ .then((results) =>
doCodeClimateComparison(
parseCodeclimateMetrics(results[0].data, state.headBlobPath),
parseCodeclimateMetrics(results[1].data, state.baseBlobPath),
),
)
- .then(data => dispatch('receiveReportsSuccess', data))
+ .then((data) => dispatch('receiveReportsSuccess', data))
.catch(() => dispatch('receiveReportsError'));
};
diff --git a/app/assets/javascripts/reports/codequality_report/store/getters.js b/app/assets/javascripts/reports/codequality_report/store/getters.js
index d7c31bcf459..e017bab976c 100644
--- a/app/assets/javascripts/reports/codequality_report/store/getters.js
+++ b/app/assets/javascripts/reports/codequality_report/store/getters.js
@@ -2,10 +2,10 @@ import { LOADING, ERROR, SUCCESS } from '../../constants';
import { sprintf, __, s__, n__ } from '~/locale';
import { spriteIcon } from '~/lib/utils/common_utils';
-export const hasCodequalityIssues = state =>
+export const hasCodequalityIssues = (state) =>
Boolean(state.newIssues?.length || state.resolvedIssues?.length);
-export const codequalityStatus = state => {
+export const codequalityStatus = (state) => {
if (state.isLoading) {
return LOADING;
}
@@ -16,7 +16,7 @@ export const codequalityStatus = state => {
return SUCCESS;
};
-export const codequalityText = state => {
+export const codequalityText = (state) => {
const { newIssues, resolvedIssues } = state;
const text = [];
@@ -41,7 +41,7 @@ export const codequalityText = state => {
return text.join('');
};
-export const codequalityPopover = state => {
+export const codequalityPopover = (state) => {
if (state.headPath && !state.basePath) {
return {
title: s__('ciReport|Base pipeline codequality artifact not found'),
diff --git a/app/assets/javascripts/reports/codequality_report/store/index.js b/app/assets/javascripts/reports/codequality_report/store/index.js
index 9fa2c589324..5bfcd69edec 100644
--- a/app/assets/javascripts/reports/codequality_report/store/index.js
+++ b/app/assets/javascripts/reports/codequality_report/store/index.js
@@ -7,11 +7,11 @@ import state from './state';
Vue.use(Vuex);
-export const getStoreConfig = initialState => ({
+export const getStoreConfig = (initialState) => ({
actions,
getters,
mutations,
state: state(initialState),
});
-export default initialState => new Vuex.Store(getStoreConfig(initialState));
+export default (initialState) => new Vuex.Store(getStoreConfig(initialState));
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 eba9e340c4e..fd775f52f7d 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
@@ -1,7 +1,7 @@
import CodeQualityComparisonWorker from '../../workers/codequality_comparison_worker';
export const parseCodeclimateMetrics = (issues = [], path = '') => {
- return issues.map(issue => {
+ return issues.map((issue) => {
const parsedIssue = {
...issue,
name: issue.description,
diff --git a/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js b/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js
index fc55602f95c..ae389d266f8 100644
--- a/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js
+++ b/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js
@@ -3,7 +3,7 @@ import { differenceBy } from 'lodash';
const KEY_TO_FILTER_BY = 'fingerprint';
// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', e => {
+self.addEventListener('message', (e) => {
const { data } = e;
if (data === undefined) {
diff --git a/app/assets/javascripts/reports/components/grouped_issues_list.vue b/app/assets/javascripts/reports/components/grouped_issues_list.vue
index 97587636644..1826fbaddac 100644
--- a/app/assets/javascripts/reports/components/grouped_issues_list.vue
+++ b/app/assets/javascripts/reports/components/grouped_issues_list.vue
@@ -41,7 +41,7 @@ export default {
computed: {
groups() {
return this.$options.groups
- .map(group => ({
+ .map((group) => ({
name: group,
issues: this[`${group}Issues`],
heading: this[`${group}Heading`],
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 c13df60198b..bf1868d427e 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -10,7 +10,6 @@ import IssuesList from './issues_list.vue';
import Modal from './modal.vue';
import createStore from '../store';
import Tracking from '~/tracking';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
summaryTextBuilder,
reportTextBuilder,
@@ -28,7 +27,7 @@ export default {
Modal,
GlButton,
},
- mixins: [glFeatureFlagsMixin(), Tracking.mixin()],
+ mixins: [Tracking.mixin()],
props: {
endpoint: {
type: String,
@@ -44,8 +43,9 @@ export default {
computed: {
...mapState(['reports', 'isLoading', 'hasError', 'summary']),
...mapState({
- modalTitle: state => state.modal.title || '',
- modalData: state => state.modal.data || {},
+ modalTitle: (state) => state.modal.title || '',
+ modalData: (state) => state.modal.data || {},
+ modalOpen: (state) => state.modal.open || false,
}),
...mapGetters(['summaryStatus']),
groupedSummaryText() {
@@ -77,7 +77,7 @@ export default {
this.fetchReports();
},
methods: {
- ...mapActions(['setEndpoint', 'fetchReports']),
+ ...mapActions(['setEndpoint', 'fetchReports', 'closeModal']),
reportText(report) {
const { name, summary } = report || {};
@@ -92,7 +92,7 @@ export default {
return reportTextBuilder(name, summary);
},
hasRecentFailures(summary) {
- return this.glFeatures.testFailureHistory && summary?.recentlyFailed > 0;
+ return summary?.recentlyFailed > 0;
},
recentFailuresText(summary) {
return recentFailuresTextBuilder(summary);
@@ -171,8 +171,12 @@ export default {
class="report-block-group-list"
/>
</template>
-
- <modal :title="modalTitle" :modal-data="modalData" />
+ <modal
+ :visible="modalOpen"
+ :title="modalTitle"
+ :modal-data="modalData"
+ @hide="closeModal"
+ />
</div>
</template>
</report-section>
diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue
index ee07efea3b0..16d5b14d3e9 100644
--- a/app/assets/javascripts/reports/components/issues_list.vue
+++ b/app/assets/javascripts/reports/components/issues_list.vue
@@ -3,7 +3,7 @@ import ReportItem from '~/reports/components/report_item.vue';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
-const wrapIssueWithState = (status, isNew = false) => issue => ({
+const wrapIssueWithState = (status, isNew = false) => (issue) => ({
status: issue.status || status,
isNew,
issue,
diff --git a/app/assets/javascripts/reports/components/modal.vue b/app/assets/javascripts/reports/components/modal.vue
index ca95db6c826..6243bddf941 100644
--- a/app/assets/javascripts/reports/components/modal.vue
+++ b/app/assets/javascripts/reports/components/modal.vue
@@ -1,15 +1,21 @@
<script>
-// import { sprintf, __ } from '~/locale';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
+import { GlModal, GlLink, GlSprintf } from '@gitlab/ui';
+
import CodeBlock from '~/vue_shared/components/code_block.vue';
import { fieldTypes } from '../constants';
export default {
components: {
- Modal: DeprecatedModal2,
CodeBlock,
+ GlModal,
+ GlLink,
+ GlSprintf,
},
props: {
+ visible: {
+ type: Boolean,
+ required: true,
+ },
title: {
type: String,
required: true,
@@ -23,39 +29,43 @@ export default {
};
</script>
<template>
- <modal
- id="modal-mrwidget-reports"
- :header-title-text="title"
- class="modal-security-report-dast modal-hide-footer"
+ <gl-modal
+ :visible="visible"
+ modal-id="modal-mrwidget-reports"
+ :title="title"
+ :hide-footer="true"
+ @hide="$emit('hide')"
>
- <slot>
- <div
- v-for="(field, key, index) in modalData"
- v-if="field.value"
- :key="index"
- class="row gl-mt-3 gl-mb-3"
- >
- <strong class="col-sm-3 text-right"> {{ field.text }}: </strong>
+ <div
+ v-for="(field, key, index) in modalData"
+ v-if="field.value"
+ :key="index"
+ class="row gl-mt-3 gl-mb-3"
+ >
+ <strong class="col-sm-3 text-right"> {{ field.text }}: </strong>
- <div class="col-sm-9 text-secondary">
- <code-block v-if="field.type === $options.fieldTypes.codeBock" :code="field.value" />
+ <div class="col-sm-9 text-secondary">
+ <code-block v-if="field.type === $options.fieldTypes.codeBock" :code="field.value" />
- <template v-else-if="field.type === $options.fieldTypes.link">
- <a :href="field.value" target="_blank" rel="noopener noreferrer" class="js-modal-link">
- {{ field.value }}
- </a>
- </template>
+ <gl-link
+ v-else-if="field.type === $options.fieldTypes.link"
+ :href="field.value"
+ target="_blank"
+ >
+ {{ field.value }}
+ </gl-link>
- <template v-else-if="field.type === $options.fieldTypes.seconds">{{
- sprintf(__('%{value} s'), { value: field.value })
- }}</template>
+ <gl-sprintf
+ v-else-if="field.type === $options.fieldTypes.seconds"
+ :message="__('%{value} s')"
+ >
+ <template #value>{{ field.value }}</template>
+ </gl-sprintf>
- <template v-else-if="field.type === $options.fieldTypes.text">
- {{ field.value }}
- </template>
- </div>
+ <template v-else-if="field.type === $options.fieldTypes.text">
+ {{ field.value }}
+ </template>
</div>
- </slot>
- <div slot="footer"></div>
- </modal>
+ </div>
+ </gl-modal>
</template>
diff --git a/app/assets/javascripts/reports/components/modal_open_name.vue b/app/assets/javascripts/reports/components/modal_open_name.vue
deleted file mode 100644
index 78e1fcb205b..00000000000
--- a/app/assets/javascripts/reports/components/modal_open_name.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-<script>
-import { GlTooltipDirective, GlResizeObserverDirective } from '@gitlab/ui';
-import { mapActions } from 'vuex';
-
-export default {
- directives: {
- GlTooltip: GlTooltipDirective,
- GlResizeObserverDirective,
- },
- props: {
- issue: {
- type: Object,
- required: true,
- },
- // failed || success
- status: {
- type: String,
- required: true,
- },
- },
- data: () => ({
- tooltipTitle: '',
- }),
- mounted() {
- this.updateTooltipTitle();
- },
- methods: {
- ...mapActions(['openModal']),
- handleIssueClick() {
- const { issue, status, openModal } = this;
- openModal({ issue, status });
- },
- updateTooltipTitle() {
- // Only show the tooltip if the text is truncated with an ellipsis.
- this.tooltipTitle = this.$el.offsetWidth < this.$el.scrollWidth ? this.issue.title : '';
- },
- },
-};
-</script>
-<template>
- <button
- v-gl-tooltip="{ boundary: 'viewport' }"
- v-gl-resize-observer-directive="updateTooltipTitle"
- class="btn-link gl-text-truncate"
- :aria-label="s__('Reports|Vulnerability Name')"
- :title="tooltipTitle"
- @click="handleIssueClick()"
- >
- {{ issue.title }}
- </button>
-</template>
diff --git a/app/assets/javascripts/reports/components/report_item.vue b/app/assets/javascripts/reports/components/report_item.vue
index 1b47d03aa01..df20d5c19ba 100644
--- a/app/assets/javascripts/reports/components/report_item.vue
+++ b/app/assets/javascripts/reports/components/report_item.vue
@@ -17,7 +17,7 @@ export default {
type: String,
required: false,
default: '',
- validator: value => value === '' || Object.values(componentNames).includes(value),
+ validator: (value) => value === '' || Object.values(componentNames).includes(value),
},
// failed || success
status: {
diff --git a/app/assets/javascripts/reports/components/report_link.vue b/app/assets/javascripts/reports/components/report_link.vue
index f285b526a54..1f68f79e487 100644
--- a/app/assets/javascripts/reports/components/report_link.vue
+++ b/app/assets/javascripts/reports/components/report_link.vue
@@ -21,16 +21,10 @@ export default {
rel="noopener noreferrer nofollow"
class="break-link"
>
- {{ issue.path
- }}<template v-if="issue.line"
- >:{{ issue.line }}</template
- >
+ {{ issue.path }}<template v-if="issue.line">:{{ issue.line }}</template>
</a>
<template v-else>
- {{ issue.path
- }}<template v-if="issue.line"
- >:{{ issue.line }}</template
- >
+ {{ issue.path }}<template v-if="issue.line">:{{ issue.line }}</template>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/reports/components/test_issue_body.vue b/app/assets/javascripts/reports/components/test_issue_body.vue
index 69b0dcf881d..ad980b334bb 100644
--- a/app/assets/javascripts/reports/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/components/test_issue_body.vue
@@ -1,7 +1,6 @@
<script>
import { mapActions } from 'vuex';
import { GlBadge, GlSprintf } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'TestIssueBody',
@@ -9,7 +8,6 @@ export default {
GlBadge,
GlSprintf,
},
- mixins: [glFeatureFlagsMixin()],
props: {
issue: {
type: Object,
@@ -28,11 +26,7 @@ export default {
},
computed: {
showRecentFailures() {
- return (
- this.glFeatures.testFailureHistory &&
- this.issue.recent_failures?.count &&
- this.issue.recent_failures?.base_branch
- );
+ return this.issue.recent_failures?.count && this.issue.recent_failures?.base_branch;
},
},
methods: {
diff --git a/app/assets/javascripts/reports/store/actions.js b/app/assets/javascripts/reports/store/actions.js
index c5860db6601..301fdce7989 100644
--- a/app/assets/javascripts/reports/store/actions.js
+++ b/app/assets/javascripts/reports/store/actions.js
@@ -1,5 +1,4 @@
import Visibility from 'visibilityjs';
-import $ from 'jquery';
import axios from '../../lib/utils/axios_utils';
import Poll from '../../lib/utils/poll';
import * as types from './mutation_types';
@@ -78,10 +77,6 @@ export const receiveReportsSuccess = ({ commit }, response) => {
export const receiveReportsError = ({ commit }) => commit(types.RECEIVE_REPORTS_ERROR);
-export const openModal = ({ dispatch }, payload) => {
- dispatch('setModalData', payload);
+export const openModal = ({ commit }, payload) => commit(types.SET_ISSUE_MODAL_DATA, payload);
- $('#modal-mrwidget-reports').modal('show');
-};
-
-export const setModalData = ({ commit }, payload) => commit(types.SET_ISSUE_MODAL_DATA, payload);
+export const closeModal = ({ commit }, payload) => commit(types.RESET_ISSUE_MODAL_DATA, payload);
diff --git a/app/assets/javascripts/reports/store/getters.js b/app/assets/javascripts/reports/store/getters.js
index d49e5760b3f..cc8c4cc446c 100644
--- a/app/assets/javascripts/reports/store/getters.js
+++ b/app/assets/javascripts/reports/store/getters.js
@@ -1,6 +1,6 @@
import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../constants';
-export const summaryStatus = state => {
+export const summaryStatus = (state) => {
if (state.isLoading) {
return LOADING;
}
diff --git a/app/assets/javascripts/reports/store/mutation_types.js b/app/assets/javascripts/reports/store/mutation_types.js
index 599d4862dfe..337085f9bf0 100644
--- a/app/assets/javascripts/reports/store/mutation_types.js
+++ b/app/assets/javascripts/reports/store/mutation_types.js
@@ -4,3 +4,4 @@ export const REQUEST_REPORTS = 'REQUEST_REPORTS';
export const RECEIVE_REPORTS_SUCCESS = 'RECEIVE_REPORTS_SUCCESS';
export const RECEIVE_REPORTS_ERROR = 'RECEIVE_REPORTS_ERROR';
export const SET_ISSUE_MODAL_DATA = 'SET_ISSUE_MODAL_DATA';
+export const RESET_ISSUE_MODAL_DATA = 'RESET_ISSUE_MODAL_DATA';
diff --git a/app/assets/javascripts/reports/store/mutations.js b/app/assets/javascripts/reports/store/mutations.js
index acaa98754b0..3bb31d71d8f 100644
--- a/app/assets/javascripts/reports/store/mutations.js
+++ b/app/assets/javascripts/reports/store/mutations.js
@@ -9,7 +9,7 @@ export default {
state.isLoading = true;
},
[types.RECEIVE_REPORTS_SUCCESS](state, response) {
- state.hasError = response.suites.some(suite => suite.status === 'error');
+ state.hasError = response.suites.some((suite) => suite.status === 'error');
state.isLoading = false;
@@ -44,7 +44,7 @@ export default {
[types.SET_ISSUE_MODAL_DATA](state, payload) {
state.modal.title = payload.issue.name;
- Object.keys(payload.issue).forEach(key => {
+ Object.keys(payload.issue).forEach((key) => {
if (Object.prototype.hasOwnProperty.call(state.modal.data, key)) {
state.modal.data[key] = {
...state.modal.data[key],
@@ -52,5 +52,19 @@ export default {
};
}
});
+
+ state.modal.open = true;
+ },
+ [types.RESET_ISSUE_MODAL_DATA](state) {
+ state.modal.open = false;
+
+ // Resetting modal data
+ state.modal.title = null;
+ Object.keys(state.modal.data).forEach((key) => {
+ state.modal.data[key] = {
+ ...state.modal.data[key],
+ value: null,
+ };
+ });
},
};
diff --git a/app/assets/javascripts/reports/store/state.js b/app/assets/javascripts/reports/store/state.js
index 4f9eb53e787..e8a0db2e1a8 100644
--- a/app/assets/javascripts/reports/store/state.js
+++ b/app/assets/javascripts/reports/store/state.js
@@ -38,6 +38,7 @@ export default () => ({
modal: {
title: null,
+ open: false,
data: {
class: {
diff --git a/app/assets/javascripts/reports/store/utils.js b/app/assets/javascripts/reports/store/utils.js
index 2d32daee9d0..d89833032a0 100644
--- a/app/assets/javascripts/reports/store/utils.js
+++ b/app/assets/javascripts/reports/store/utils.js
@@ -7,7 +7,7 @@ import {
ICON_NOTFOUND,
} from '../constants';
-const textBuilder = results => {
+const textBuilder = (results) => {
const { failed, errored, resolved, total } = results;
const failedOrErrored = (failed || 0) + (errored || 0);
@@ -70,18 +70,18 @@ export const recentFailuresTextBuilder = (summary = {}) => {
);
};
-export const countRecentlyFailedTests = subject => {
+export const countRecentlyFailedTests = (subject) => {
// handle either a single report or an array of reports
const reports = !subject.length ? [subject] : subject;
return reports
- .map(report => {
+ .map((report) => {
return (
[report.new_failures, report.existing_failures, report.resolved_failures]
// only count tests which have failed more than once
.map(
- failureArray =>
- failureArray.filter(failure => failure.recent_failures?.count > 1).length,
+ (failureArray) =>
+ failureArray.filter((failure) => failure.recent_failures?.count > 1).length,
)
.reduce((total, count) => total + count, 0)
);
@@ -89,7 +89,7 @@ export const countRecentlyFailedTests = subject => {
.reduce((total, count) => total + count, 0);
};
-export const statusIcon = status => {
+export const statusIcon = (status) => {
if (status === STATUS_FAILED) {
return ICON_WARNING;
}
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index a1f1c77df2f..c9862572b16 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -40,7 +40,7 @@ export default {
projectPath: this.projectPath,
};
},
- update: data => data.project?.userPermissions,
+ update: (data) => data.project?.userPermissions,
error(error) {
throw error;
},
@@ -105,7 +105,7 @@ export default {
pathLinks() {
return this.currentPath
.split('/')
- .filter(p => p !== '')
+ .filter((p) => p !== '')
.reduce(
(acc, name, i) => {
const path = joinPaths(i > 0 ? acc[i].path : '', escapeFileUrl(name));
diff --git a/app/assets/javascripts/repository/components/directory_download_links.vue b/app/assets/javascripts/repository/components/directory_download_links.vue
index dffadade082..8c029fc9973 100644
--- a/app/assets/javascripts/repository/components/directory_download_links.vue
+++ b/app/assets/javascripts/repository/components/directory_download_links.vue
@@ -18,7 +18,7 @@ export default {
},
computed: {
normalizedLinks() {
- return this.links.map(link => ({
+ return this.links.map((link) => ({
text: link.text,
path: `${link.path}?path=${this.currentPath}`,
}));
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 2626bace363..0241c803514 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -39,7 +39,7 @@ export default {
path: this.currentPath.replace(/^\//, ''),
};
},
- update: data => {
+ update: (data) => {
const pipelines = data.project?.repository?.tree?.lastCommit?.pipelines?.edges;
return {
@@ -81,6 +81,10 @@ export default {
showCommitId() {
return this.commit?.sha?.substr(0, 8);
},
+ commitDescription() {
+ // Strip the newline at the beginning
+ return this.commit?.descriptionHtml?.replace(/^&#x000A;/, '');
+ },
},
watch: {
currentPath() {
@@ -146,10 +150,10 @@ export default {
<timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" />
</div>
<pre
- v-if="commit.descriptionHtml"
+ v-if="commitDescription"
:class="{ 'd-block': showDescription }"
class="commit-row-description gl-mb-3"
- v-html="commit.descriptionHtml"
+ v-html="commitDescription"
></pre>
</div>
<div class="commit-actions flex-row">
diff --git a/app/assets/javascripts/repository/components/table/parent_row.vue b/app/assets/javascripts/repository/components/table/parent_row.vue
index b4095e00884..fb0e505a16e 100644
--- a/app/assets/javascripts/repository/components/table/parent_row.vue
+++ b/app/assets/javascripts/repository/components/table/parent_row.vue
@@ -25,7 +25,7 @@ export default {
const splitArray = this.path.split('/');
splitArray.pop();
- return splitArray.map(p => encodeURIComponent(p)).join('/');
+ return splitArray.map((p) => encodeURIComponent(p)).join('/');
},
parentRoute() {
return { path: `/-/tree/${this.commitRef}/${this.parentPath}` };
@@ -48,9 +48,7 @@ export default {
inline
class="d-inline-block align-text-bottom"
/>
- <router-link v-else :to="parentRoute" :aria-label="__('Go to parent')">
- ..
- </router-link>
+ <router-link v-else :to="parentRoute" :aria-label="__('Go to parent')"> .. </router-link>
</td>
</tr>
</template>
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index b42f88631b5..7fe6863d006 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -113,7 +113,7 @@ export default {
}
}
})
- .catch(error => {
+ .catch((error) => {
createFlash(__('An error occurred while fetching folder content.'));
throw error;
});
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
index 8dd18027945..dbe129859bc 100644
--- a/app/assets/javascripts/repository/graphql.js
+++ b/app/assets/javascripts/repository/graphql.js
@@ -18,7 +18,7 @@ const defaultClient = createDefaultClient(
{
Query: {
commit(_, { path, fileName, type }) {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
fetchLogsTree(defaultClient, path, '0', {
resolve,
entry: {
@@ -38,7 +38,7 @@ const defaultClient = createDefaultClient(
{
cacheConfig: {
fragmentMatcher,
- dataIdFromObject: obj => {
+ dataIdFromObject: (obj) => {
/* eslint-disable @gitlab/require-i18n-strings */
// eslint-disable-next-line no-underscore-dangle
switch (obj.__typename) {
diff --git a/app/assets/javascripts/repository/log_tree.js b/app/assets/javascripts/repository/log_tree.js
index fc8fa40a855..9001bcd8fc3 100644
--- a/app/assets/javascripts/repository/log_tree.js
+++ b/app/assets/javascripts/repository/log_tree.js
@@ -9,7 +9,9 @@ const fetchpromises = {};
const resolvers = {};
export function resolveCommit(commits, path, { resolve, entry }) {
- const commit = commits.find(c => c.filePath === `${path}/${entry.name}` && c.type === entry.type);
+ const commit = commits.find(
+ (c) => c.filePath === `${path}/${entry.name}` && c.type === entry.type,
+ );
if (commit) {
resolve(commit);
@@ -42,7 +44,7 @@ export function fetchLogsTree(client, path, offset, resolver = null) {
.then(({ data: newData, headers }) => {
const headerLogsOffset = headers['more-logs-offset'];
const sourceData = client.readQuery({ query: commitsQuery });
- const data = produce(sourceData, draftState => {
+ const data = produce(sourceData, (draftState) => {
draftState.commits.push(...normalizeData(newData, path));
});
client.writeQuery({
@@ -50,7 +52,7 @@ export function fetchLogsTree(client, path, offset, resolver = null) {
data,
});
- resolvers[path].forEach(r => resolveCommit(data.commits, path, r));
+ resolvers[path].forEach((r) => resolveCommit(data.commits, path, r));
delete fetchpromises[path];
diff --git a/app/assets/javascripts/repository/queries/project_path.query.graphql b/app/assets/javascripts/repository/queries/project_path.query.graphql
index 74e73e07577..9e5c10b3de3 100644
--- a/app/assets/javascripts/repository/queries/project_path.query.graphql
+++ b/app/assets/javascripts/repository/queries/project_path.query.graphql
@@ -1,3 +1,3 @@
query getProjectPath {
- projectPath
+ projectPath @client
}
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
index 38a596e229e..e2924454239 100644
--- a/app/assets/javascripts/repository/router.js
+++ b/app/assets/javascripts/repository/router.js
@@ -10,7 +10,7 @@ Vue.use(VueRouter);
export default function createRouter(base, baseRef) {
const treePathRoute = {
component: TreePage,
- props: route => ({
+ props: (route) => ({
path: route.params.path?.replace(/^\//, '') || '/',
}),
};
diff --git a/app/assets/javascripts/repository/utils/commit.js b/app/assets/javascripts/repository/utils/commit.js
index 0704ac1627f..a67252ec004 100644
--- a/app/assets/javascripts/repository/utils/commit.js
+++ b/app/assets/javascripts/repository/utils/commit.js
@@ -1,5 +1,5 @@
export function normalizeData(data, path, extra = () => {}) {
- return data.map(d => ({
+ return data.map((d) => ({
sha: d.commit.id,
message: d.commit.message,
titleHtml: d.commit_title_html,
diff --git a/app/assets/javascripts/repository/utils/dom.js b/app/assets/javascripts/repository/utils/dom.js
index abf726194ac..b667cd53b18 100644
--- a/app/assets/javascripts/repository/utils/dom.js
+++ b/app/assets/javascripts/repository/utils/dom.js
@@ -1,7 +1,9 @@
import { joinPaths } from '~/lib/utils/url_utility';
export const updateElementsVisibility = (selector, isVisible) => {
- document.querySelectorAll(selector).forEach(elem => elem.classList.toggle('hidden', !isVisible));
+ document
+ .querySelectorAll(selector)
+ .forEach((elem) => elem.classList.toggle('hidden', !isVisible));
};
export const updateFormAction = (selector, basePath, path) => {
diff --git a/app/assets/javascripts/repository/utils/readme.js b/app/assets/javascripts/repository/utils/readme.js
index 50692779b1a..c666cd95038 100644
--- a/app/assets/javascripts/repository/utils/readme.js
+++ b/app/assets/javascripts/repository/utils/readme.js
@@ -18,14 +18,14 @@ const MARKUP_EXTENSIONS = [
'wiki',
];
-const isRichReadme = file => {
+const isRichReadme = (file) => {
const re = new RegExp(`^(${FILENAMES.join('|')})\\.(${MARKUP_EXTENSIONS.join('|')})$`, 'i');
return re.test(file.name);
};
-const isPlainReadme = file => {
+const isPlainReadme = (file) => {
const re = new RegExp(`^(${FILENAMES.join('|')})(\\.txt)?$`, 'i');
return re.test(file.name);
};
-export const readmeFile = blobs => blobs.find(isRichReadme) || blobs.find(isPlainReadme);
+export const readmeFile = (blobs) => blobs.find(isRichReadme) || blobs.find(isPlainReadme);
diff --git a/app/assets/javascripts/rest_api.js b/app/assets/javascripts/rest_api.js
new file mode 100644
index 00000000000..ea8f87001f0
--- /dev/null
+++ b/app/assets/javascripts/rest_api.js
@@ -0,0 +1,15 @@
+export * from './api/groups_api';
+export * from './api/projects_api';
+export * from './api/user_api';
+
+// Note: It's not possible to spy on methods imported from this file in
+// Jest tests. See https://stackoverflow.com/a/53307822/1063392.
+// As a workaround, in Jest tests, import the methods from the file
+// in which they are defined:
+//
+// import * as UserApi from '~/api/user_api';
+// vs...
+// import * as UserApi from '~/rest_api';
+//
+// // This will only work with option #2 above.
+// jest.spyOn(UserApi, 'getUsers')
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 6f43f837374..b9bc799fb0b 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -15,13 +15,13 @@ function Sidebar() {
this.addEventListeners();
}
-Sidebar.initialize = function() {
+Sidebar.initialize = function () {
if (!this.instance) {
this.instance = new Sidebar();
}
};
-Sidebar.prototype.removeListeners = function() {
+Sidebar.prototype.removeListeners = function () {
this.sidebar.off('click', '.sidebar-collapsed-icon');
// eslint-disable-next-line @gitlab/no-global-event-off
this.sidebar.off('hidden.gl.dropdown');
@@ -32,7 +32,7 @@ Sidebar.prototype.removeListeners = function() {
$(document).off('click', '.js-sidebar-toggle');
};
-Sidebar.prototype.addEventListeners = function() {
+Sidebar.prototype.addEventListeners = function () {
const $document = $(document);
this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked);
@@ -44,7 +44,7 @@ Sidebar.prototype.addEventListeners = function() {
.on('click', '.js-issuable-todo', this.toggleTodo);
};
-Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
+Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
const $this = $(this);
const $collapseIcon = $('.js-sidebar-collapse');
const $expandIcon = $('.js-sidebar-expand');
@@ -60,9 +60,7 @@ Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
$('aside.right-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed');
- $('.layout-page')
- .removeClass('right-sidebar-expanded')
- .addClass('right-sidebar-collapsed');
+ $('.layout-page').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
} else {
$toggleContainer.data('is-expanded', true);
$expandIcon.addClass('hidden');
@@ -70,9 +68,7 @@ Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
$('aside.right-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded');
- $('.layout-page')
- .removeClass('right-sidebar-collapsed')
- .addClass('right-sidebar-expanded');
+ $('.layout-page').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
}
$this.attr('data-original-title', tooltipLabel);
@@ -82,16 +78,14 @@ Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
}
};
-Sidebar.prototype.toggleTodo = function(e) {
+Sidebar.prototype.toggleTodo = function (e) {
const $this = $(e.currentTarget);
const ajaxType = $this.data('deletePath') ? 'delete' : 'post';
const url = String($this.data('deletePath') || $this.data('createPath'));
hide($this);
- $('.js-issuable-todo')
- .disable()
- .addClass('is-loading');
+ $('.js-issuable-todo').disable().addClass('is-loading');
axios[ajaxType](url, {
issuable_id: $this.data('issuableId'),
@@ -110,7 +104,7 @@ Sidebar.prototype.toggleTodo = function(e) {
);
};
-Sidebar.prototype.todoUpdateDone = function(data) {
+Sidebar.prototype.todoUpdateDone = function (data) {
const deletePath = data.delete_path ? data.delete_path : null;
const attrPrefix = deletePath ? 'mark' : 'todo';
const $todoBtns = $('.js-issuable-todo');
@@ -140,7 +134,7 @@ Sidebar.prototype.todoUpdateDone = function(data) {
});
};
-Sidebar.prototype.sidebarCollapseClicked = function(e) {
+Sidebar.prototype.sidebarCollapseClicked = function (e) {
if ($(e.currentTarget).hasClass('dont-change-state')) {
return;
}
@@ -150,7 +144,7 @@ Sidebar.prototype.sidebarCollapseClicked = function(e) {
return sidebar.openDropdown($block);
};
-Sidebar.prototype.openDropdown = function(blockOrName) {
+Sidebar.prototype.openDropdown = function (blockOrName) {
const $block = typeof blockOrName === 'string' ? this.getBlock(blockOrName) : blockOrName;
if (!this.isOpen()) {
this.setCollapseAfterUpdate($block);
@@ -164,19 +158,19 @@ Sidebar.prototype.openDropdown = function(blockOrName) {
});
};
-Sidebar.prototype.setCollapseAfterUpdate = function($block) {
+Sidebar.prototype.setCollapseAfterUpdate = function ($block) {
$block.addClass('collapse-after-update');
return $('.layout-page').addClass('with-overlay');
};
-Sidebar.prototype.onSidebarDropdownHidden = function(e) {
+Sidebar.prototype.onSidebarDropdownHidden = function (e) {
const sidebar = e.data;
e.preventDefault();
const $block = $(e.target).closest('.block');
return sidebar.sidebarDropdownHidden($block);
};
-Sidebar.prototype.sidebarDropdownHidden = function($block) {
+Sidebar.prototype.sidebarDropdownHidden = function ($block) {
if ($block.hasClass('collapse-after-update')) {
$block.removeClass('collapse-after-update');
$('.layout-page').removeClass('with-overlay');
@@ -184,11 +178,11 @@ Sidebar.prototype.sidebarDropdownHidden = function($block) {
}
};
-Sidebar.prototype.triggerOpenSidebar = function() {
+Sidebar.prototype.triggerOpenSidebar = function () {
return this.sidebar.find('.js-sidebar-toggle').trigger('click');
};
-Sidebar.prototype.toggleSidebar = function(action) {
+Sidebar.prototype.toggleSidebar = function (action) {
if (action == null) {
action = 'toggle';
}
@@ -207,11 +201,11 @@ Sidebar.prototype.toggleSidebar = function(action) {
}
};
-Sidebar.prototype.isOpen = function() {
+Sidebar.prototype.isOpen = function () {
return this.sidebar.is('.right-sidebar-expanded');
};
-Sidebar.prototype.getBlock = function(name) {
+Sidebar.prototype.getBlock = function (name) {
return this.sidebar.find(`.block.${name}`);
};
diff --git a/app/assets/javascripts/search/highlight_blob_search_result.js b/app/assets/javascripts/search/highlight_blob_search_result.js
index e17c87735b4..3c3ac3582d0 100644
--- a/app/assets/javascripts/search/highlight_blob_search_result.js
+++ b/app/assets/javascripts/search/highlight_blob_search_result.js
@@ -4,9 +4,9 @@ export default () => {
const searchTerm = contentBody.querySelector('.js-search-input').value.toLowerCase();
const blobs = contentBody.querySelectorAll('.blob-result');
- blobs.forEach(blob => {
+ blobs.forEach((blob) => {
const lines = blob.querySelectorAll('.line');
- lines.forEach(line => {
+ lines.forEach((line) => {
if (line.textContent.toLowerCase().includes(searchTerm)) {
line.classList.add(highlightLineClass);
}
diff --git a/app/assets/javascripts/search/sidebar/index.js b/app/assets/javascripts/search/sidebar/index.js
index 6419e8ac2c6..1414adcac27 100644
--- a/app/assets/javascripts/search/sidebar/index.js
+++ b/app/assets/javascripts/search/sidebar/index.js
@@ -4,7 +4,7 @@ import GlobalSearchSidebar from './components/app.vue';
Vue.use(Translate);
-export const initSidebar = store => {
+export const initSidebar = (store) => {
const el = document.getElementById('js-search-sidebar');
if (!el) return false;
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
index 082beb5930d..bdfe966d990 100644
--- a/app/assets/javascripts/search/store/actions.js
+++ b/app/assets/javascripts/search/store/actions.js
@@ -7,7 +7,7 @@ import * as types from './mutation_types';
export const fetchGroups = ({ commit }, search) => {
commit(types.REQUEST_GROUPS);
Api.groups(search)
- .then(data => {
+ .then((data) => {
commit(types.RECEIVE_GROUPS_SUCCESS, data);
})
.catch(() => {
@@ -19,7 +19,7 @@ export const fetchGroups = ({ commit }, search) => {
export const fetchProjects = ({ commit, state }, search) => {
commit(types.REQUEST_PROJECTS);
const groupId = state.query?.group_id;
- const callback = data => {
+ const callback = (data) => {
if (data) {
commit(types.RECEIVE_PROJECTS_SUCCESS, data);
} else {
diff --git a/app/assets/javascripts/search/store/index.js b/app/assets/javascripts/search/store/index.js
index e0a7e488f9f..1923c8b96ab 100644
--- a/app/assets/javascripts/search/store/index.js
+++ b/app/assets/javascripts/search/store/index.js
@@ -12,5 +12,5 @@ export const getStoreConfig = ({ query }) => ({
state: createState({ query }),
});
-const createStore = config => new Vuex.Store(getStoreConfig(config));
+const createStore = (config) => new Vuex.Store(getStoreConfig(config));
export default createStore;
diff --git a/app/assets/javascripts/search/topbar/index.js b/app/assets/javascripts/search/topbar/index.js
index 024544148a0..f0308109b32 100644
--- a/app/assets/javascripts/search/topbar/index.js
+++ b/app/assets/javascripts/search/topbar/index.js
@@ -40,5 +40,5 @@ const searchableDropdowns = [
},
];
-export const initTopbar = store =>
- searchableDropdowns.map(dropdown => mountSearchableDropdown(store, dropdown));
+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 97674348436..b8a5836e2d4 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -76,8 +76,8 @@ export class SearchAutocomplete {
this.wrap = wrap || $('.search');
this.optsEl = optsEl || this.wrap.find('.search-autocomplete-opts');
this.autocompletePath = autocompletePath || this.optsEl.data('autocompletePath');
- this.projectId = projectId || (this.optsEl.data('autocompleteProjectId') || '');
- this.projectRef = projectRef || (this.optsEl.data('autocompleteProjectRef') || '');
+ this.projectId = projectId || this.optsEl.data('autocompleteProjectId') || '';
+ this.projectRef = projectRef || this.optsEl.data('autocompleteProjectRef') || '';
this.dropdown = this.wrap.find('.dropdown');
this.dropdownToggle = this.wrap.find('.js-dropdown-search-toggle');
this.dropdownMenu = this.dropdown.find('.dropdown-menu');
@@ -172,7 +172,7 @@ export class SearchAutocomplete {
term,
},
})
- .then(response => {
+ .then((response) => {
const options = this.scopedSearchOptions(term);
// List results
@@ -345,7 +345,7 @@ export class SearchAutocomplete {
this.clearInput.on('click', this.onClearInputClick);
this.dropdownContent.on('scroll', throttle(this.setScrollFade, 250));
- this.searchInput.on('click', e => {
+ this.searchInput.on('click', (e) => {
e.stopPropagation();
});
}
diff --git a/app/assets/javascripts/search_settings/components/search_settings.vue b/app/assets/javascripts/search_settings/components/search_settings.vue
new file mode 100644
index 00000000000..820055dc656
--- /dev/null
+++ b/app/assets/javascripts/search_settings/components/search_settings.vue
@@ -0,0 +1,129 @@
+<script>
+import { GlSearchBoxByType } from '@gitlab/ui';
+import { uniq } from 'lodash';
+import { EXCLUDED_NODES, HIDE_CLASS, HIGHLIGHT_CLASS, TYPING_DELAY } from '../constants';
+
+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) {
+ expandSection(section);
+ } else {
+ collapseSection(section);
+ }
+ });
+};
+
+const clearHighlights = () => {
+ document
+ .querySelectorAll(`.${HIGHLIGHT_CLASS}`)
+ .forEach((element) => element.classList.remove(HIGHLIGHT_CLASS));
+};
+
+const hideSectionsExcept = (sectionSelector, visibleSections) => {
+ Array.from(document.querySelectorAll(sectionSelector))
+ .filter((section) => !visibleSections.includes(section))
+ .forEach((section) => {
+ section.classList.add(HIDE_CLASS);
+ });
+};
+
+const highlightElements = (elements = []) => {
+ elements.forEach((element) => element.classList.add(HIGHLIGHT_CLASS));
+};
+
+const displayResults = ({ sectionSelector, expandSection }, matches) => {
+ const elements = matches.map((match) => match.parentElement);
+ const sections = uniq(elements.map((element) => findSettingsSection(sectionSelector, element)));
+
+ hideSectionsExcept(sectionSelector, sections);
+ sections.forEach(expandSection);
+ highlightElements(elements);
+};
+
+const clearResults = (params) => {
+ resetSections(params);
+ clearHighlights();
+};
+
+const includeNode = (node, lowerSearchTerm) =>
+ node.textContent.toLowerCase().includes(lowerSearchTerm) &&
+ EXCLUDED_NODES.every((excluded) => !node.parentElement.closest(excluded));
+
+const search = (root, searchTerm) => {
+ const iterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT, {
+ acceptNode(node) {
+ return includeNode(node, searchTerm.toLowerCase())
+ ? NodeFilter.FILTER_ACCEPT
+ : NodeFilter.FILTER_REJECT;
+ },
+ });
+ const results = [];
+
+ for (let currentNode = iterator.nextNode(); currentNode; currentNode = iterator.nextNode()) {
+ results.push(currentNode);
+ }
+
+ return results;
+};
+
+export default {
+ components: {
+ GlSearchBoxByType,
+ },
+ props: {
+ searchRoot: {
+ type: Element,
+ required: true,
+ },
+ sectionSelector: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ };
+ },
+ methods: {
+ search(value) {
+ const displayOptions = {
+ sectionSelector: this.sectionSelector,
+ expandSection: this.expandSection,
+ collapseSection: this.collapseSection,
+ };
+
+ this.searchTerm = value;
+
+ clearResults(displayOptions);
+
+ if (value.length) {
+ displayResults(displayOptions, search(this.searchRoot, value));
+ }
+ },
+ expandSection(section) {
+ this.$emit('expand', section);
+ },
+ collapseSection(section) {
+ this.$emit('collapse', section);
+ },
+ },
+ TYPING_DELAY,
+};
+</script>
+<template>
+ <div class="gl-mt-5">
+ <gl-search-box-by-type
+ :value="searchTerm"
+ :debounce="$options.TYPING_DELAY"
+ :placeholder="__('Search settings')"
+ @input="search"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/search_settings/constants.js b/app/assets/javascripts/search_settings/constants.js
new file mode 100644
index 00000000000..499e42854ed
--- /dev/null
+++ b/app/assets/javascripts/search_settings/constants.js
@@ -0,0 +1,11 @@
+// We do not consider these nodes in the search index
+export const EXCLUDED_NODES = ['OPTION'];
+
+// Used to hide the sections that do not match * the search term
+export const HIDE_CLASS = 'gl-display-none';
+
+// used to highlight the text that matches the * search term
+export const HIGHLIGHT_CLASS = 'gl-bg-orange-50';
+
+// How many seconds to wait until the user * stops typing
+export const TYPING_DELAY = 400;
diff --git a/app/assets/javascripts/search_settings/index.js b/app/assets/javascripts/search_settings/index.js
new file mode 100644
index 00000000000..1fb1a378ffb
--- /dev/null
+++ b/app/assets/javascripts/search_settings/index.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import $ from 'jquery';
+import { expandSection, closeSection } from '~/settings_panels';
+import SearchSettings from '~/search_settings/components/search_settings.vue';
+
+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)),
+ },
+ }),
+ });
+
+export default initSearch;
diff --git a/app/assets/javascripts/self_monitor/store/actions.js b/app/assets/javascripts/self_monitor/store/actions.js
index 10deec6921c..99731309a62 100644
--- a/app/assets/javascripts/self_monitor/store/actions.js
+++ b/app/assets/javascripts/self_monitor/store/actions.js
@@ -9,7 +9,7 @@ const TWO_MINUTES = 120000;
function backOffRequest(makeRequestCallback) {
return backOff((next, stop) => {
makeRequestCallback()
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.ACCEPTED) {
next();
} else {
@@ -30,24 +30,24 @@ export const requestCreateProject = ({ dispatch, state, commit }) => {
commit(types.SET_LOADING, true);
axios
.post(state.createProjectEndpoint)
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.ACCEPTED) {
dispatch('requestCreateProjectStatus', resp.data.job_id);
}
})
- .catch(error => {
+ .catch((error) => {
dispatch('requestCreateProjectError', error);
});
};
export const requestCreateProjectStatus = ({ dispatch, state }, jobId) => {
backOffRequest(() => axios.get(state.createProjectStatusEndpoint, { params: { job_id: jobId } }))
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.OK) {
dispatch('requestCreateProjectSuccess', resp.data);
}
})
- .catch(error => {
+ .catch((error) => {
dispatch('requestCreateProjectError', error);
});
};
@@ -82,24 +82,24 @@ export const requestDeleteProject = ({ dispatch, state, commit }) => {
commit(types.SET_LOADING, true);
axios
.delete(state.deleteProjectEndpoint)
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.ACCEPTED) {
dispatch('requestDeleteProjectStatus', resp.data.job_id);
}
})
- .catch(error => {
+ .catch((error) => {
dispatch('requestDeleteProjectError', error);
});
};
export const requestDeleteProjectStatus = ({ dispatch, state }, jobId) => {
backOffRequest(() => axios.get(state.deleteProjectStatusEndpoint, { params: { job_id: jobId } }))
- .then(resp => {
+ .then((resp) => {
if (resp.status === statusCodes.OK) {
dispatch('requestDeleteProjectSuccess', resp.data);
}
})
- .catch(error => {
+ .catch((error) => {
dispatch('requestDeleteProjectError', error);
});
};
diff --git a/app/assets/javascripts/self_monitor/store/index.js b/app/assets/javascripts/self_monitor/store/index.js
index a222e9c87b8..1144fff759a 100644
--- a/app/assets/javascripts/self_monitor/store/index.js
+++ b/app/assets/javascripts/self_monitor/store/index.js
@@ -6,7 +6,7 @@ import mutations from './mutations';
Vue.use(Vuex);
-export const createStore = initialState =>
+export const createStore = (initialState) =>
new Vuex.Store({
modules: {
selfMonitoring: {
diff --git a/app/assets/javascripts/sentry_error_stack_trace/index.js b/app/assets/javascripts/sentry_error_stack_trace/index.js
index 9b24ddc335d..80fa0988f0a 100644
--- a/app/assets/javascripts/sentry_error_stack_trace/index.js
+++ b/app/assets/javascripts/sentry_error_stack_trace/index.js
@@ -13,7 +13,7 @@ export default function initSentryErrorStacktrace() {
SentryErrorStackTrace,
},
store,
- render: createElement =>
+ render: (createElement) =>
createElement('sentry-error-stack-trace', {
props: { issueStackTracePath },
}),
diff --git a/app/assets/javascripts/serverless/components/area.vue b/app/assets/javascripts/serverless/components/area.vue
index 71f2e948917..056b342cf39 100644
--- a/app/assets/javascripts/serverless/components/area.vue
+++ b/app/assets/javascripts/serverless/components/area.vue
@@ -39,13 +39,13 @@ export default {
}, {});
},
extractTimeData() {
- return this.chartData.requests.map(data => data.time);
+ return this.chartData.requests.map((data) => data.time);
},
generateSeries() {
return {
name: __('Invocations'),
type: 'line',
- data: this.chartData.requests.map(data => [data.time, data.value]),
+ data: this.chartData.requests.map((data) => [data.time, data.value]),
symbolSize: 0,
};
},
@@ -69,7 +69,7 @@ export default {
name: 'time',
type: 'time',
axisLabel: {
- formatter: date => dateFormat(date, 'h:MM TT'),
+ formatter: (date) => dateFormat(date, 'h:MM TT'),
},
data: this.extractTimeData,
nameTextStyle: {
@@ -90,7 +90,7 @@ export default {
};
},
xAxisLabel() {
- return this.graphData.queries.map(query => query.label).join(', ');
+ return this.graphData.queries.map((query) => query.label).join(', ');
},
yAxisLabel() {
const [query] = this.graphData.queries;
diff --git a/app/assets/javascripts/serverless/store/actions.js b/app/assets/javascripts/serverless/store/actions.js
index b9d57138efa..acd7020f70f 100644
--- a/app/assets/javascripts/serverless/store/actions.js
+++ b/app/assets/javascripts/serverless/store/actions.js
@@ -30,7 +30,7 @@ export const receiveMetricsError = ({ commit }, error) =>
export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
let retryCount = 0;
- const functionsPartiallyFetched = data => {
+ const functionsPartiallyFetched = (data) => {
if (data.functions !== null && data.functions.length) {
dispatch('receiveFunctionsPartial', data);
}
@@ -41,7 +41,7 @@ export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
backOff((next, stop) => {
axios
.get(functionsPath)
- .then(response => {
+ .then((response) => {
if (response.data.knative_installed === CHECKING_INSTALLED) {
retryCount += 1;
if (retryCount < MAX_REQUESTS) {
@@ -56,7 +56,7 @@ export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
})
.catch(stop);
})
- .then(data => {
+ .then((data) => {
if (data === TIMEOUT) {
dispatch('receiveFunctionsTimeout');
createFlash(__('Loading functions timed out. Please reload the page to try again.'));
@@ -66,7 +66,7 @@ export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
dispatch('receiveFunctionsNoDataSuccess', data);
}
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveFunctionsError', error);
createFlash(error);
});
@@ -83,7 +83,7 @@ export const fetchMetrics = ({ dispatch }, { metricsPath, hasPrometheus }) => {
backOff((next, stop) => {
axios
.get(metricsPath)
- .then(response => {
+ .then((response) => {
if (response.status === statusCodes.NO_CONTENT) {
retryCount += 1;
if (retryCount < MAX_REQUESTS) {
@@ -98,15 +98,15 @@ export const fetchMetrics = ({ dispatch }, { metricsPath, hasPrometheus }) => {
})
.catch(stop);
})
- .then(data => {
+ .then((data) => {
if (data === null) {
return;
}
const updatedMetric = data.metrics;
- const queries = data.metrics.queries.map(query => ({
+ const queries = data.metrics.queries.map((query) => ({
...query,
- result: query.result.map(result => ({
+ result: query.result.map((result) => ({
...result,
values: result.values.map(([timestamp, value]) => ({
time: new Date(timestamp * 1000).toISOString(),
@@ -118,7 +118,7 @@ export const fetchMetrics = ({ dispatch }, { metricsPath, hasPrometheus }) => {
updatedMetric.queries = queries;
dispatch('receiveMetricsSuccess', updatedMetric);
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveMetricsError', error);
createFlash(error);
});
diff --git a/app/assets/javascripts/serverless/store/getters.js b/app/assets/javascripts/serverless/store/getters.js
index c9b1d22799a..da975c56e5d 100644
--- a/app/assets/javascripts/serverless/store/getters.js
+++ b/app/assets/javascripts/serverless/store/getters.js
@@ -1,7 +1,7 @@
import { translate } from '../utils';
-export const hasPrometheusMissingData = state => state.hasPrometheus && !state.hasPrometheusData;
+export const hasPrometheusMissingData = (state) => state.hasPrometheus && !state.hasPrometheusData;
// Convert the function list into a k/v grouping based on the environment scope
-export const getFunctions = state => translate(state.functions);
+export const getFunctions = (state) => translate(state.functions);
diff --git a/app/assets/javascripts/serverless/utils.js b/app/assets/javascripts/serverless/utils.js
index 1bf03ea8d42..e218a9aa3fd 100644
--- a/app/assets/javascripts/serverless/utils.js
+++ b/app/assets/javascripts/serverless/utils.js
@@ -1,16 +1,16 @@
// Validate that the object coming in has valid query details and results
-export const validateGraphData = data =>
+export const validateGraphData = (data) =>
data.queries &&
Array.isArray(data.queries) &&
- data.queries.filter(query => {
+ data.queries.filter((query) => {
if (Array.isArray(query.result)) {
- return query.result.filter(res => Array.isArray(res.values)).length === query.result.length;
+ return query.result.filter((res) => Array.isArray(res.values)).length === query.result.length;
}
return false;
}).length === data.queries.length;
-export const translate = functions =>
+export const translate = (functions) =>
functions.reduce(
(acc, func) =>
Object.assign(acc, {
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 f2685dfbcdb..c8efbd73b48 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
@@ -6,7 +6,7 @@ import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import { GlToast, GlModal, GlTooltipDirective, GlIcon, GlFormCheckbox } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __, s__ } from '~/locale';
-import Api from '~/api';
+import { updateUserStatus } from '~/rest_api';
import EmojiMenuInModal from './emoji_menu_in_modal';
import { isUserBusy, isValidAvailibility } from './utils';
import * as Emoji from '~/emoji';
@@ -163,7 +163,7 @@ export default {
setStatus() {
const { emoji, message, availability } = this;
- Api.postUserStatus({
+ updateUserStatus({
emoji,
message,
availability: availability ? AVAILABILITY_STATUS.BUSY : AVAILABILITY_STATUS.NOT_SET,
@@ -172,10 +172,7 @@ export default {
.catch(this.onUpdateFail);
},
onUpdateSuccess() {
- this.$toast.show(s__('SetStatusModal|Status updated'), {
- type: 'success',
- position: 'top-center',
- });
+ this.$toast.show(s__('SetStatusModal|Status updated'));
this.closeModal();
window.location.reload();
},
diff --git a/app/assets/javascripts/set_status_modal/utils.js b/app/assets/javascripts/set_status_modal/utils.js
index dccb66be11f..faee4012ef4 100644
--- a/app/assets/javascripts/set_status_modal/utils.js
+++ b/app/assets/javascripts/set_status_modal/utils.js
@@ -3,7 +3,7 @@ export const AVAILABILITY_STATUS = {
NOT_SET: 'not_set',
};
-export const isUserBusy = status => status === AVAILABILITY_STATUS.BUSY;
+export const isUserBusy = (status) => status === AVAILABILITY_STATUS.BUSY;
-export const isValidAvailibility = availability =>
+export const isValidAvailibility = (availability) =>
availability.length ? Object.values(AVAILABILITY_STATUS).includes(availability) : true;
diff --git a/app/assets/javascripts/settings_panels.js b/app/assets/javascripts/settings_panels.js
index 18160421136..1f1f6e42576 100644
--- a/app/assets/javascripts/settings_panels.js
+++ b/app/assets/javascripts/settings_panels.js
@@ -1,13 +1,10 @@
import $ from 'jquery';
import { __ } from './locale';
-function expandSection($section) {
+export function expandSection($section) {
$section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Collapse'));
// eslint-disable-next-line @gitlab/no-global-event-off
- $section
- .find('.settings-content')
- .off('scroll.expandSection')
- .scrollTop(0);
+ $section.find('.settings-content').off('scroll.expandSection').scrollTop(0);
$section.addClass('expanded');
if (!$section.hasClass('no-animate')) {
$section
@@ -16,7 +13,7 @@ function expandSection($section) {
}
}
-function closeSection($section) {
+export function closeSection($section) {
$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');
@@ -27,7 +24,7 @@ function closeSection($section) {
}
}
-function toggleSection($section) {
+export function toggleSection($section) {
$section.removeClass('no-animate');
if ($section.hasClass('expanded')) {
closeSection($section);
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index 3baf4bf0742..84e7110e2b2 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -34,8 +34,8 @@ export default {
return !this.users.length;
},
sortedAssigness() {
- const canMergeUsers = this.users.filter(user => user.can_merge);
- const canNotMergeUsers = this.users.filter(user => !user.can_merge);
+ const canMergeUsers = this.users.filter((user) => user.can_merge);
+ const canNotMergeUsers = this.users.filter((user) => !user.can_merge);
return [...canMergeUsers, ...canNotMergeUsers];
},
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
index bf0c52b2341..0eee287e0c2 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
@@ -59,7 +59,7 @@ export default {
handleFetchResult({ data }) {
const { nodes } = data.project.issue.assignees;
- const assignees = nodes.map(n => ({
+ const assignees = nodes.map((n) => ({
...n,
avatar_url: n.avatarUrl,
id: getIdFromGraphQLId(n.id),
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 362ca4ab917..b713b0f960c 100644
--- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
@@ -39,7 +39,7 @@ export default {
return this.users.length > 2;
},
allAssigneesCanMerge() {
- return this.users.every(user => user.can_merge);
+ return this.users.every((user) => user.can_merge);
},
sidebarAvatarCounter() {
if (this.users.length > DEFAULT_MAX_COUNTER) {
@@ -58,7 +58,7 @@ export default {
return '';
}
- const mergeLength = this.users.filter(u => u.can_merge).length;
+ const mergeLength = this.users.filter((u) => u.can_merge).length;
if (mergeLength === this.users.length) {
return '';
@@ -74,7 +74,7 @@ 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);
+ const names = renderUsers.map((u) => u.name);
if (!this.users.length) {
return __('Assignee(s)');
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 46d51138ccf..d210f9efcb3 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -48,7 +48,7 @@ export default {
.then(() => {
eventHub.$emit('updateIssuableConfidentiality', confidential);
})
- .catch(err => {
+ .catch((err) => {
Flash(
err || __('Something went wrong trying to change the confidentiality of this issue'),
);
diff --git a/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue b/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue
new file mode 100644
index 00000000000..8c8241cf6a4
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue
@@ -0,0 +1,43 @@
+<script>
+import { s__, __, sprintf } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+
+export default {
+ i18n: {
+ copyEmail: __('Copy email address'),
+ },
+ components: {
+ ClipboardButton,
+ },
+ props: {
+ copyText: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ emailText() {
+ return sprintf(s__('RightSidebar|Issue email: %{copyText}'), { copyText: this.copyText });
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ data-qa-selector="copy-forward-email"
+ class="copy-email-address gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ >
+ <span
+ class="gl-overflow-hidden gl-text-overflow-ellipsis gl-white-space-nowrap hide-collapsed gl-w-85p"
+ >{{ emailText }}</span
+ >
+ <clipboard-button
+ class="copy-email-button gl-bg-none!"
+ category="tertiary"
+ :title="$options.i18n.copyEmail"
+ :text="copyText"
+ tooltip-placement="left"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
index 07abfa8d103..e01e1f032e3 100644
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -50,9 +50,13 @@ export default {
$(this.$el).trigger('hidden.gl.dropdown');
},
getUpdateVariables(dropdownLabels) {
- const currentLabelIds = this.selectedLabels.map(label => label.id);
- const userAddedLabelIds = dropdownLabels.filter(label => label.set).map(label => label.id);
- const userRemovedLabelIds = dropdownLabels.filter(label => !label.set).map(label => label.id);
+ const currentLabelIds = this.selectedLabels.map((label) => label.id);
+ const userAddedLabelIds = dropdownLabels
+ .filter((label) => label.set)
+ .map((label) => label.id);
+ const userRemovedLabelIds = dropdownLabels
+ .filter((label) => !label.set)
+ .map((label) => label.id);
const labelIds = difference(union(currentLabelIds, userAddedLabelIds), userRemovedLabelIds);
@@ -116,7 +120,7 @@ export default {
}
const issuableType = camelCase(this.issuableType);
- this.selectedLabels = data[mutationName]?.[issuableType]?.labels?.nodes?.map(label => ({
+ this.selectedLabels = data[mutationName]?.[issuableType]?.labels?.nodes?.map((label) => ({
...label,
id: getIdFromGraphQLId(label.id),
}));
diff --git a/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
index 10b16a44261..9554a98121f 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
@@ -33,7 +33,7 @@ export default {
return this.users.length > 2;
},
allReviewersCanMerge() {
- return this.users.every(user => user.can_merge);
+ return this.users.every((user) => user.can_merge);
},
sidebarAvatarCounter() {
if (this.users.length > DEFAULT_MAX_COUNTER) {
@@ -48,7 +48,7 @@ export default {
return this.users.slice(0, collapsedLength);
},
tooltipTitleMergeStatus() {
- const mergeLength = this.users.filter(u => u.can_merge).length;
+ const mergeLength = this.users.filter((u) => u.can_merge).length;
if (mergeLength === this.users.length) {
return '';
@@ -64,7 +64,7 @@ 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);
+ const names = renderUsers.map((u) => u.name);
if (!this.users.length) {
return __('Reviewer(s)');
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
index d64b483acb1..a461d992222 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
@@ -1,14 +1,13 @@
<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 { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
export default {
name: 'ReviewerTitle',
components: {
GlLoadingIcon,
- GlIcon,
},
props: {
loading: {
@@ -24,11 +23,6 @@ export default {
type: Boolean,
required: true,
},
- showToggle: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
reviewerTitle() {
@@ -52,14 +46,5 @@ export default {
>
{{ __('Edit') }}
</a>
- <a
- v-if="showToggle"
- :aria-label="__('Toggle sidebar')"
- class="gutter-toggle float-right js-sidebar-toggle"
- href="#"
- role="button"
- >
- <gl-icon data-hidden="true" name="chevron-double-lg-right" :size="12" />
- </a>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
index 6a3d88f6385..cd62fe5be0f 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
@@ -36,8 +36,8 @@ export default {
return !this.users.length;
},
sortedReviewers() {
- const canMergeUsers = this.users.filter(user => user.can_merge);
- const canNotMergeUsers = this.users.filter(user => !user.can_merge);
+ const canMergeUsers = this.users.filter((user) => user.can_merge);
+ const canNotMergeUsers = this.users.filter((user) => !user.can_merge);
return [...canMergeUsers, ...canNotMergeUsers];
},
diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
index aee94a55134..1a2473e5f6c 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
@@ -2,6 +2,7 @@
// 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 eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -25,11 +26,6 @@ export default {
type: String,
required: true,
},
- signedIn: {
- type: Boolean,
- required: false,
- default: false,
- },
issuableType: {
type: String,
required: false,
@@ -80,8 +76,7 @@ export default {
.saveReviewers(this.field)
.then(() => {
this.loading = false;
- // Uncomment once this issue has been addressed > https://gitlab.com/gitlab-org/gitlab/-/issues/237922
- // refreshUserMergeRequestCounts();
+ refreshUserMergeRequestCounts();
})
.catch(() => {
this.loading = false;
@@ -98,7 +93,6 @@ export default {
:number-of-reviewers="store.reviewers.length"
:loading="loading || store.isFetching.reviewers"
:editable="store.editable"
- :show-toggle="!signedIn"
/>
<reviewers
v-if="!store.isFetching.reviewers"
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
index 8f3610b912a..0cf11e83349 100644
--- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -41,7 +41,7 @@ export default {
type: String,
required: false,
default: ISSUABLE_TYPES.INCIDENT,
- validator: value => {
+ validator: (value) => {
// currently severity is supported only for incidents, but this list might be extended
return [ISSUABLE_TYPES.INCIDENT].includes(value);
},
@@ -67,7 +67,7 @@ export default {
return this.isDropdownShowing ? 'show' : 'gl-display-none';
},
selectedItem() {
- return this.severitiesList.find(severity => severity.value === this.severity);
+ return this.severitiesList.find((severity) => severity.value === this.severity);
},
},
mounted() {
@@ -106,7 +106,7 @@ export default {
projectPath: this.projectPath,
},
})
- .then(resp => {
+ .then((resp) => {
const {
data: {
issueSetSeverity: {
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
deleted file mode 100644
index 8a80b1bf13f..00000000000
--- a/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
+++ /dev/null
@@ -1,18 +0,0 @@
-<script>
-export default {
- name: 'TimeTrackingEstimateOnlyPane',
- props: {
- timeEstimateHumanReadable: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <div data-testid="estimateOnlyPane">
- <span class="gl-font-weight-bold">{{ s__('TimeTracking|Estimated:') }} </span
- >{{ timeEstimateHumanReadable }}
- </div>
-</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
deleted file mode 100644
index 2d3d0ce8dc5..00000000000
--- a/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-<script>
-export default {
- name: 'TimeTrackingNoTrackingPane',
-};
-</script>
-
-<template>
- <div data-testid="noTrackingPane">
- <span class="no-value">{{ __('No estimate or time spent') }}</span>
- </div>
-</template>
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 6bef5ed67a4..26e0a0da860 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
@@ -27,7 +27,7 @@ export default {
listenForQuickActions() {
$(document).on('ajax:success', '.gfm-form', this.quickActionListened);
- eventHub.$on('timeTrackingUpdated', data => {
+ eventHub.$on('timeTrackingUpdated', (data) => {
this.quickActionListened({ detail: [data] });
});
},
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 3199ed1e615..26b8e087512 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,22 +1,23 @@
<script>
import { GlIcon } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
import TimeTrackingHelpState from './help_state.vue';
import TimeTrackingCollapsedState from './collapsed_state.vue';
import TimeTrackingSpentOnlyPane from './spent_only_pane.vue';
-import TimeTrackingNoTrackingPane from './no_tracking_pane.vue';
-import TimeTrackingEstimateOnlyPane from './estimate_only_pane.vue';
import TimeTrackingComparisonPane from './comparison_pane.vue';
import eventHub from '../../event_hub';
export default {
name: 'IssuableTimeTracker',
+ i18n: {
+ noTimeTrackingText: __('No estimate or time spent'),
+ estimatedOnlyText: s__('TimeTracking|Estimated:'),
+ },
components: {
GlIcon,
TimeTrackingCollapsedState,
- TimeTrackingEstimateOnlyPane,
TimeTrackingSpentOnlyPane,
- TimeTrackingNoTrackingPane,
TimeTrackingComparisonPane,
TimeTrackingHelpState,
},
@@ -139,15 +140,17 @@ export default {
</div>
</div>
<div class="time-tracking-content hide-collapsed">
- <time-tracking-estimate-only-pane
- v-if="showEstimateOnlyState"
- :time-estimate-human-readable="humanTimeEstimate"
- />
+ <div v-if="showEstimateOnlyState" data-testid="estimateOnlyPane">
+ <span class="gl-font-weight-bold">{{ $options.i18n.estimatedOnlyText }} </span
+ >{{ humanTimeEstimate }}
+ </div>
<time-tracking-spent-only-pane
v-if="showSpentOnlyState"
:time-spent-human-readable="humanTimeSpent"
/>
- <time-tracking-no-tracking-pane v-if="showNoTimeTrackingState" />
+ <div v-if="showNoTimeTrackingState" data-testid="noTrackingPane">
+ <span class="gl-text-gray-500">{{ $options.i18n.noTimeTrackingText }}</span>
+ </div>
<time-tracking-comparison-pane
v-if="showComparisonState"
:time-estimate="timeEstimate"
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index edeb1bba020..55847fc43f0 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -46,14 +46,14 @@ class SidebarMoveIssue {
() => new window.Flash(__('An error occurred while fetching projects autocomplete.')),
);
},
- renderRow: project => `
+ renderRow: (project) => `
<li>
<a href="#" class="js-move-issue-dropdown-item">
${escape(project.name_with_namespace)}
</a>
</li>
`,
- clicked: options => {
+ clicked: (options) => {
const project = options.selectedObj;
const selectedProjectId = options.isMarking ? project.id : 0;
this.mediator.setMoveToProjectId(selectedProjectId);
diff --git a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
index 0f5f8f2b53b..4d9e99941d1 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -16,7 +16,7 @@ export default class SidebarMilestone {
components: {
timeTracker,
},
- render: createElement =>
+ render: (createElement) =>
createElement('timeTracker', {
props: {
timeEstimate: parseInt(timeEstimate, 10),
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 984cd8a3b1d..2760bf431ea 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -12,6 +12,7 @@ import sidebarParticipants from './components/participants/sidebar_participants.
import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.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';
@@ -40,7 +41,7 @@ function mountAssigneesComponent(mediator) {
components: {
SidebarAssignees,
},
- render: createElement =>
+ render: (createElement) =>
createElement('sidebar-assignees', {
props: {
mediator,
@@ -70,14 +71,13 @@ function mountReviewersComponent(mediator) {
components: {
SidebarReviewers,
},
- render: createElement =>
+ render: (createElement) =>
createElement('sidebar-reviewers', {
props: {
mediator,
issuableIid: String(iid),
projectPath: fullPath,
field: el.dataset.field,
- signedIn: el.hasAttribute('data-signed-in'),
issuableType: isInIssuePage() ? 'issue' : 'merge_request',
},
}),
@@ -105,7 +105,7 @@ export function mountSidebarLabels() {
allowScopedLabels: parseBoolean(el.dataset.allowScopedLabels),
initiallySelectedLabels: JSON.parse(el.dataset.selectedLabels),
},
- render: createElement => createElement(SidebarLabels),
+ render: (createElement) => createElement(SidebarLabels),
});
}
@@ -128,7 +128,7 @@ function mountConfidentialComponent(mediator) {
components: {
ConfidentialIssueSidebar,
},
- render: createElement =>
+ render: (createElement) =>
createElement('confidential-issue-sidebar', {
props: {
iid: String(iid),
@@ -163,20 +163,20 @@ function mountLockComponent() {
);
} else {
importStore = import(/* webpackChunkName: 'mrNotesStore' */ '~/mr_notes/stores').then(
- store => store.default,
+ (store) => store.default,
);
}
importStore
.then(
- store =>
+ (store) =>
new Vue({
el,
store,
provide: {
fullPath,
},
- render: createElement =>
+ render: (createElement) =>
createElement(IssuableLockForm, {
props: {
isEditable: initialData.is_editable,
@@ -200,7 +200,7 @@ function mountParticipantsComponent(mediator) {
components: {
sidebarParticipants,
},
- render: createElement =>
+ render: (createElement) =>
createElement('sidebar-participants', {
props: {
mediator,
@@ -220,7 +220,7 @@ function mountSubscriptionsComponent(mediator) {
components: {
sidebarSubscriptions,
},
- render: createElement =>
+ render: (createElement) =>
createElement('sidebar-subscriptions', {
props: {
mediator,
@@ -240,7 +240,7 @@ function mountTimeTrackingComponent() {
components: {
SidebarTimeTracking,
},
- render: createElement => createElement('sidebar-time-tracking', {}),
+ render: (createElement) => createElement('sidebar-time-tracking', {}),
});
}
@@ -262,7 +262,7 @@ function mountSeverityComponent() {
components: {
SidebarSeverity,
},
- render: createElement =>
+ render: (createElement) =>
createElement('sidebar-severity', {
props: {
projectPath: fullPath,
@@ -273,6 +273,21 @@ function mountSeverityComponent() {
});
}
+function mountCopyEmailComponent() {
+ const el = document.getElementById('issuable-copy-email');
+
+ if (!el) return;
+
+ const { createNoteEmail } = getSidebarOptions();
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render: (createElement) =>
+ createElement(CopyEmailToClipboard, { props: { copyText: createNoteEmail } }),
+ });
+}
+
export function mountSidebar(mediator) {
mountAssigneesComponent(mediator);
mountReviewersComponent(mediator);
@@ -280,6 +295,7 @@ export function mountSidebar(mediator) {
mountLockComponent();
mountParticipantsComponent(mediator);
mountSubscriptionsComponent(mediator);
+ mountCopyEmailComponent();
new SidebarMoveIssue(
mediator,
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 2146fb83b13..d143283653b 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -30,7 +30,7 @@ export default class SidebarMediator {
}
saveAssignees(field) {
- const selected = this.store.assignees.map(u => u.id);
+ const selected = this.store.assignees.map((u) => u.id);
// If there are no ids, that means we have to unassign (which is id = 0)
// And it only accepts an array, hence [0]
@@ -41,7 +41,7 @@ export default class SidebarMediator {
}
saveReviewers(field) {
- const selected = this.store.reviewers.map(u => u.id);
+ const selected = this.store.reviewers.map((u) => u.id);
// If there are no ids, that means we have to unassign (which is id = 0)
// And it only accepts an array, hence [0]
@@ -80,7 +80,7 @@ export default class SidebarMediator {
this.store.setSubscribedState(!this.store.subscribed);
this.store.setFetchingState('subscriptions', false);
})
- .catch(err => {
+ .catch((err) => {
this.store.setFetchingState('subscriptions', false);
throw err;
});
diff --git a/app/assets/javascripts/sidebar/utils.js b/app/assets/javascripts/sidebar/utils.js
index 23730508b56..20cd4ce9d99 100644
--- a/app/assets/javascripts/sidebar/utils.js
+++ b/app/assets/javascripts/sidebar/utils.js
@@ -1 +1 @@
-export const toLabelGid = id => `gid://gitlab/Label/${id}`;
+export const toLabelGid = (id) => `gid://gitlab/Label/${id}`;
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index f751df6367e..192eb0784d4 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -29,22 +29,17 @@ export default class SingleFileDiff {
this.isOpen = !this.diffForPath;
if (this.diffForPath) {
this.collapsedContent = this.content;
- this.loadingContent = $(WRAPPER)
- .addClass('loading')
- .html(LOADING_HTML)
- .hide();
+ this.loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide();
this.content = null;
this.collapsedContent.after(this.loadingContent);
this.$chevronRightIcon.removeClass('gl-display-none');
} else {
- this.collapsedContent = $(WRAPPER)
- .html(COLLAPSED_HTML)
- .hide();
+ this.collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide();
this.content.after(this.collapsedContent);
this.$chevronDownIcon.removeClass('gl-display-none');
}
- $('.js-file-title, .click-to-expand', this.file).on('click', e => {
+ $('.js-file-title, .click-to-expand', this.file).on('click', (e) => {
this.toggleDiff($(e.target));
});
}
diff --git a/app/assets/javascripts/smart_interval.js b/app/assets/javascripts/smart_interval.js
index c4655d35cf0..15d04dadb15 100644
--- a/app/assets/javascripts/smart_interval.js
+++ b/app/assets/javascripts/smart_interval.js
@@ -96,9 +96,7 @@ export default class SmartInterval {
window.removeEventListener('focus', this.onWindowVisibilityChange);
this.cancel();
// eslint-disable-next-line @gitlab/no-global-event-off
- $(document)
- .off('visibilitychange')
- .off('beforeunload');
+ $(document).off('visibilitychange').off('beforeunload');
}
/* private */
@@ -121,7 +119,7 @@ export default class SmartInterval {
.then(() => {
this.isLoading = false;
})
- .catch(err => {
+ .catch((err) => {
this.isLoading = false;
throw err;
});
diff --git a/app/assets/javascripts/snippet/collapsible_input.js b/app/assets/javascripts/snippet/collapsible_input.js
index e7225162f86..75465d96043 100644
--- a/app/assets/javascripts/snippet/collapsible_input.js
+++ b/app/assets/javascripts/snippet/collapsible_input.js
@@ -1,7 +1,7 @@
-const hide = el => el.classList.add('d-none');
-const show = el => el.classList.remove('d-none');
+const hide = (el) => el.classList.add('d-none');
+const show = (el) => el.classList.remove('d-none');
-const setupCollapsibleInput = el => {
+const setupCollapsibleInput = (el) => {
const collapsedEl = el.querySelector('.js-collapsed');
const expandedEl = el.querySelector('.js-expanded');
const collapsedInputEl = collapsedEl.querySelector('textarea,input,select');
@@ -21,7 +21,7 @@ const setupCollapsibleInput = el => {
// NOTE:
// We add focus listener to all form inputs so that we can collapse
// when something is focused that's not the expanded input.
- formEl.addEventListener('focusin', e => {
+ formEl.addEventListener('focusin', (e) => {
if (e.target === collapsedInputEl) {
expand();
expandedInputEl.focus();
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index 08683f25651..ffb5e242973 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -73,7 +73,7 @@ export default {
return this.actions.length > 0;
},
hasValidBlobs() {
- return this.actions.every(x => x.content);
+ return this.actions.every((x) => x.content);
},
updatePrevented() {
return this.snippet.title === '' || !this.hasValidBlobs || this.isUpdating;
@@ -130,7 +130,7 @@ export default {
},
getAttachedFiles() {
const fileInputs = Array.from(this.$el.querySelectorAll('[name="files[]"]'));
- return fileInputs.map(node => node.value);
+ return fileInputs.map((node) => node.value);
},
createMutation() {
return {
@@ -166,7 +166,7 @@ export default {
redirectTo(baseObj.snippet.webUrl);
}
})
- .catch(e => {
+ .catch((e) => {
this.flashAPIFailure(e);
});
},
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 ab2553265a2..ff27c90a84d 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
@@ -74,7 +74,7 @@ export default {
this.blobsOrig = blobsById;
this.blobs = cloneDeep(blobsById);
- this.blobIds = blobs.map(x => x.id);
+ this.blobIds = blobs.map((x) => x.id);
// Show 1 empty blob if none exist
if (!this.blobIds.length) {
@@ -108,7 +108,7 @@ export default {
this.blobIds.push(blob.id);
},
deleteBlob(id) {
- this.blobIds = this.blobIds.filter(x => x !== id);
+ this.blobIds = this.blobIds.filter((x) => x !== id);
this.$delete(this.blobs, id);
},
updateBlob(id, args) {
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
index 6a10dc38f2c..c8545e334a6 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
@@ -55,12 +55,12 @@ export default {
axios
.get(url, {
// This prevents axios from automatically JSON.parse response
- transformResponse: [f => f],
+ transformResponse: [(f) => f],
})
- .then(res => {
+ .then((res) => {
this.notifyAboutUpdates({ content: res.data });
})
- .catch(e => this.flashAPIFailure(e));
+ .catch((e) => this.flashAPIFailure(e));
},
flashAPIFailure(err) {
Flash(sprintf(SNIPPET_BLOB_CONTENT_FETCH_ERROR, { err }));
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_view.vue b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
index b965c15306d..4326c3c3159 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
@@ -41,6 +41,11 @@ export default {
},
},
},
+ provide() {
+ return {
+ blobHash: Math.random().toString().split('.')[1],
+ };
+ },
props: {
snippet: {
type: Object,
@@ -51,13 +56,6 @@ export default {
required: true,
},
},
- provide() {
- return {
- blobHash: Math.random()
- .toString()
- .split('.')[1],
- };
- },
data() {
return {
blobContent: '',
@@ -90,7 +88,7 @@ export default {
const {
blobs: { nodes: dataBlobs },
} = data.snippets.nodes[0];
- const updatedBlobData = dataBlobs.find(blob => blob.path === blobPath);
+ const updatedBlobData = dataBlobs.find((blob) => blob.path === blobPath);
return updatedBlobData.richData || updatedBlobData.plainData;
},
},
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index 32c4c1039f5..5ba62908b43 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -69,7 +69,7 @@ export default {
},
computed: {
snippetHasBinary() {
- return Boolean(this.snippet.blobs.find(blob => blob.binary));
+ return Boolean(this.snippet.blobs.find((blob) => blob.binary));
},
authoredMessage() {
return this.snippet.author
@@ -164,7 +164,7 @@ export default {
this.closeDeleteModal();
this.redirectToSnippets();
})
- .catch(err => {
+ .catch((err) => {
this.isDeleting = false;
this.errorMessage = err.message;
});
@@ -200,6 +200,13 @@ export default {
<gl-avatar :size="24" :src="snippet.author.avatarUrl" />
<span class="bold">{{ snippet.author.name }}</span>
</a>
+ <gl-emoji
+ v-if="snippet.author.status"
+ v-gl-tooltip
+ class="gl-vertical-align-baseline font-size-inherit gl-mr-1"
+ :title="snippet.author.status.message"
+ :data-name="snippet.author.status.emoji"
+ />
</template>
</gl-sprintf>
</div>
diff --git a/app/assets/javascripts/snippets/mixins/snippets.js b/app/assets/javascripts/snippets/mixins/snippets.js
index 5844a55e4f5..89a88958152 100644
--- a/app/assets/javascripts/snippets/mixins/snippets.js
+++ b/app/assets/javascripts/snippets/mixins/snippets.js
@@ -11,7 +11,7 @@ export const getSnippetMixin = {
ids: [this.snippetGid],
};
},
- update: data => {
+ update: (data) => {
const res = data.snippets.nodes[0];
if (res) {
res.blobs = res.blobs.nodes;
diff --git a/app/assets/javascripts/snippets/utils/blob.js b/app/assets/javascripts/snippets/utils/blob.js
index 5081c648e36..a47418323f2 100644
--- a/app/assets/javascripts/snippets/utils/blob.js
+++ b/app/assets/javascripts/snippets/utils/blob.js
@@ -12,7 +12,7 @@ import { SNIPPET_MARK_BLOBS_CONTENT, SNIPPET_MEASURE_BLOBS_CONTENT } from '~/per
const createLocalId = () => uniqueId('blob_local_');
-export const decorateBlob = blob => ({
+export const decorateBlob = (blob) => ({
...blob,
id: createLocalId(),
isLoaded: false,
@@ -54,7 +54,7 @@ const diff = ({ content, path }, origBlob) => {
*/
export const diffAll = (blobs, origBlobs) => {
const deletedEntries = Object.values(origBlobs)
- .filter(x => !blobs[x.id])
+ .filter((x) => !blobs[x.id])
.map(({ path, content }) => ({
action: SNIPPET_BLOB_ACTION_DELETE,
previousPath: path,
@@ -63,15 +63,15 @@ export const diffAll = (blobs, origBlobs) => {
}));
const newEntries = Object.values(blobs)
- .map(blob => diff(blob, origBlobs[blob.id]))
- .filter(x => x);
+ .map((blob) => diff(blob, origBlobs[blob.id]))
+ .filter((x) => x);
return [...deletedEntries, ...newEntries];
};
-export const defaultSnippetVisibilityLevels = arr => {
+export const defaultSnippetVisibilityLevels = (arr) => {
if (Array.isArray(arr)) {
- return arr.map(l => {
+ return arr.map((l) => {
const translatedLevel = SNIPPET_LEVELS_MAP[l];
return {
value: translatedLevel,
diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js
index 64842ae7f8d..232c97ecae0 100644
--- a/app/assets/javascripts/star.js
+++ b/app/assets/javascripts/star.js
@@ -16,10 +16,7 @@ export default class Star {
.post($this.data('endpoint'))
.then(({ data }) => {
const isStarred = $starSpan.hasClass('starred');
- $this
- .parent()
- .find('.count')
- .text(data.star_count);
+ $this.parent().find('.count').text(data.star_count);
if (isStarred) {
$starSpan.removeClass('starred').text(s__('StarProject|Star'));
diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js
index a13f7d3ad53..bce320ed805 100644
--- a/app/assets/javascripts/static_site_editor/graphql/index.js
+++ b/app/assets/javascripts/static_site_editor/graphql/index.js
@@ -8,7 +8,7 @@ import hasSubmittedChangesResolver from './resolvers/has_submitted_changes';
Vue.use(VueApollo);
-const createApolloProvider = appData => {
+const createApolloProvider = (appData) => {
const defaultClient = createDefaultClient(
{
Project: {
@@ -26,7 +26,7 @@ const createApolloProvider = appData => {
);
// eslint-disable-next-line @gitlab/require-i18n-strings
- const mounts = appData.mounts.map(mount => ({ __typename: 'Mount', ...mount }));
+ const mounts = appData.mounts.map((mount) => ({ __typename: 'Mount', ...mount }));
defaultClient.cache.writeData({
data: {
diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/file.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/file.js
index 16f176581cb..fc3cac52e2a 100644
--- a/app/assets/javascripts/static_site_editor/graphql/resolvers/file.js
+++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/file.js
@@ -1,7 +1,7 @@
import loadSourceContent from '../../services/load_source_content';
const fileResolver = ({ fullPath: projectId }, { path: sourcePath }) => {
- return loadSourceContent({ projectId, sourcePath }).then(sourceContent => ({
+ return loadSourceContent({ projectId, sourcePath }).then((sourceContent) => ({
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'File',
...sourceContent,
diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js
index ea49b21eb0d..35ecf6d698c 100644
--- a/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js
+++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js
@@ -4,7 +4,7 @@ import query from '../queries/app_data.query.graphql';
const hasSubmittedChangesResolver = (_, { input: { hasSubmittedChanges } }, { cache }) => {
const oldData = cache.readQuery({ query });
- const data = produce(oldData, draftState => {
+ const data = produce(oldData, (draftState) => {
// punctually modifying draftState as per immer docs upsets our linters
return {
...draftState,
diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js
index 1bd79d40071..0b74c99b319 100644
--- a/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js
+++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js
@@ -25,8 +25,8 @@ const submitContentChangesResolver = (
images,
mergeRequestMeta,
formattedMarkdown,
- }).then(savedContentMeta => {
- const data = produce(savedContentMeta, draftState => {
+ }).then((savedContentMeta) => {
+ const data = produce(savedContentMeta, (draftState) => {
return {
savedContentMeta: {
__typename: 'SavedContentMeta',
diff --git a/app/assets/javascripts/static_site_editor/image_repository.js b/app/assets/javascripts/static_site_editor/image_repository.js
index b5ff4385d3c..56b2434d2e2 100644
--- a/app/assets/javascripts/static_site_editor/image_repository.js
+++ b/app/assets/javascripts/static_site_editor/image_repository.js
@@ -4,15 +4,15 @@ import { getBinary } from './services/image_service';
const imageRepository = () => {
const images = new Map();
- const flash = message => new Flash(message);
+ const flash = (message) => new Flash(message);
const add = (file, url) => {
getBinary(file)
- .then(content => images.set(url, content))
+ .then((content) => images.set(url, content))
.catch(() => flash(__('Something went wrong while inserting your image. Please try again.')));
};
- const get = path => images.get(path);
+ const get = (path) => images.get(path);
const getAll = () => images;
diff --git a/app/assets/javascripts/static_site_editor/index.js b/app/assets/javascripts/static_site_editor/index.js
index b58564388de..fbb14be21ba 100644
--- a/app/assets/javascripts/static_site_editor/index.js
+++ b/app/assets/javascripts/static_site_editor/index.js
@@ -4,7 +4,7 @@ import App from './components/app.vue';
import createRouter from './router';
import createApolloProvider from './graphql';
-const initStaticSiteEditor = el => {
+const initStaticSiteEditor = (el) => {
const {
isSupportedContent,
path: sourcePath,
diff --git a/app/assets/javascripts/static_site_editor/pages/home.vue b/app/assets/javascripts/static_site_editor/pages/home.vue
index 1e52e73294e..6c958cb2d22 100644
--- a/app/assets/javascripts/static_site_editor/pages/home.vue
+++ b/app/assets/javascripts/static_site_editor/pages/home.vue
@@ -118,7 +118,7 @@ export default {
},
},
})
- .catch(e => {
+ .catch((e) => {
this.submitChangesError = e.message;
})
.finally(() => {
diff --git a/app/assets/javascripts/static_site_editor/services/formatter.js b/app/assets/javascripts/static_site_editor/services/formatter.js
index 9a5dcd307eb..e841c664406 100644
--- a/app/assets/javascripts/static_site_editor/services/formatter.js
+++ b/app/assets/javascripts/static_site_editor/services/formatter.js
@@ -24,7 +24,7 @@ const nestedLineRegexp = /^\s+/;
* This function attempts to correct this problem before the content is loaded
* by Toast UI.
*/
-const correctNestedContentIndenation = source => {
+const correctNestedContentIndenation = (source) => {
const lines = source.split('\n');
let topLevelOrderedListDetected = false;
@@ -40,7 +40,7 @@ const correctNestedContentIndenation = source => {
.join('\n');
};
-const removeOrphanedBrTags = source => {
+const removeOrphanedBrTags = (source) => {
/* Until the underlying Squire editor of Toast UI Editor resolves duplicate `<br>` tags, this
`replace` solution will clear out orphaned `<br>` tags that it generates. Additionally,
it cleans up orphaned `<br>` tags in the source markdown document that should be new lines.
@@ -49,7 +49,7 @@ const removeOrphanedBrTags = source => {
return source.replace(/\n^<br>$/gm, '');
};
-const format = source => {
+const format = (source) => {
return correctNestedContentIndenation(removeOrphanedBrTags(source));
};
diff --git a/app/assets/javascripts/static_site_editor/services/front_matterify.js b/app/assets/javascripts/static_site_editor/services/front_matterify.js
index 60a5d799d11..6b897b42648 100644
--- a/app/assets/javascripts/static_site_editor/services/front_matterify.js
+++ b/app/assets/javascripts/static_site_editor/services/front_matterify.js
@@ -8,7 +8,7 @@ const hasMatter = (firstThreeChars, fourthChar) => {
return isYamlDelimiter && isFourthCharNewline;
};
-export const frontMatterify = source => {
+export const frontMatterify = (source) => {
let index = 3;
let offset;
const delimiter = source.slice(0, index);
diff --git a/app/assets/javascripts/static_site_editor/services/image_service.js b/app/assets/javascripts/static_site_editor/services/image_service.js
index 25ab1084572..a9b85057e3d 100644
--- a/app/assets/javascripts/static_site_editor/services/image_service.js
+++ b/app/assets/javascripts/static_site_editor/services/image_service.js
@@ -1,8 +1,8 @@
-export const getBinary = file => {
+export const getBinary = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result.split(',')[1]);
- reader.onerror = error => reject(error);
+ reader.onerror = (error) => reject(error);
});
};
diff --git a/app/assets/javascripts/static_site_editor/services/load_source_content.js b/app/assets/javascripts/static_site_editor/services/load_source_content.js
index 1af93a8a2bc..fcf69efafd8 100644
--- a/app/assets/javascripts/static_site_editor/services/load_source_content.js
+++ b/app/assets/javascripts/static_site_editor/services/load_source_content.js
@@ -1,6 +1,6 @@
import Api from '~/api';
-const extractTitle = content => {
+const extractTitle = (content) => {
const matches = content.match(/title: (.+)\n/i);
return matches ? Array.from(matches)[1] : '';
diff --git a/app/assets/javascripts/static_site_editor/services/parse_source_file.js b/app/assets/javascripts/static_site_editor/services/parse_source_file.js
index 39126eb7bcc..d7499d75a21 100644
--- a/app/assets/javascripts/static_site_editor/services/parse_source_file.js
+++ b/app/assets/javascripts/static_site_editor/services/parse_source_file.js
@@ -1,6 +1,6 @@
import { frontMatterify, stringify } from './front_matterify';
-const parseSourceFile = raw => {
+const parseSourceFile = (raw) => {
let editable;
const syncContent = (newVal, isBody) => {
@@ -20,7 +20,7 @@ const parseSourceFile = raw => {
const matter = () => editable.matter;
- const syncMatter = settings => {
+ const syncMatter = (settings) => {
editable.matter = settings;
};
diff --git a/app/assets/javascripts/static_site_editor/services/renderers/render_image.js b/app/assets/javascripts/static_site_editor/services/renderers/render_image.js
index b0d863bdb5a..b5651e7163e 100644
--- a/app/assets/javascripts/static_site_editor/services/renderers/render_image.js
+++ b/app/assets/javascripts/static_site_editor/services/renderers/render_image.js
@@ -4,16 +4,16 @@ const canRender = ({ type }) => type === 'image';
let metadata;
-const getCachedContent = basePath => metadata.imageRepository.get(basePath);
+const getCachedContent = (basePath) => metadata.imageRepository.get(basePath);
-const isRelativeToCurrentDirectory = basePath => !basePath.startsWith('/');
+const isRelativeToCurrentDirectory = (basePath) => !basePath.startsWith('/');
-const extractSourceDirectory = url => {
+const extractSourceDirectory = (url) => {
const sourceDir = /^(.+)\/([^/]+)$/.exec(url); // Extracts the base path and fileName from an image path
return sourceDir || [null, null, url]; // If no source directory was extracted it means only a fileName was specified (e.g. url='file.png')
};
-const parseCurrentDirectory = basePath => {
+const parseCurrentDirectory = (basePath) => {
const baseUrl = decodeURIComponent(metadata.baseUrl);
const sourceDirectory = extractSourceDirectory(baseUrl)[1];
const currentDirectory = sourceDirectory.split(`/-/sse/${metadata.branch}`)[1];
@@ -23,7 +23,7 @@ const parseCurrentDirectory = basePath => {
// For more context around this logic, please see the following comment:
// https://gitlab.com/gitlab-org/gitlab/-/issues/241166#note_409413500
-const generateSourceDirectory = basePath => {
+const generateSourceDirectory = (basePath) => {
let sourceDir = '';
let defaultSourceDir = '';
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 e57028ea05a..84e90deacfc 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
@@ -32,7 +32,7 @@ const createImageActions = (images, markdown) => {
}
images.forEach((imageContent, filePath) => {
- const imageExistsInMarkdown = path => new RegExp(`!\\[([^[\\]\\n]*)\\](\\(${path})\\)`); // matches the image markdown syntax: ![<any-string-except-newline>](<path>)
+ const imageExistsInMarkdown = (path) => new RegExp(`!\\[([^[\\]\\n]*)\\](\\(${path})\\)`); // matches the image markdown syntax: ![<any-string-except-newline>](<path>)
if (imageExistsInMarkdown(filePath).test(markdown)) {
actions.push(
diff --git a/app/assets/javascripts/static_site_editor/services/templater.js b/app/assets/javascripts/static_site_editor/services/templater.js
index d302aea78a3..47fc36c3d18 100644
--- a/app/assets/javascripts/static_site_editor/services/templater.js
+++ b/app/assets/javascripts/static_site_editor/services/templater.js
@@ -40,10 +40,10 @@ const mark = (source, groups) => {
const hash = {};
Object.entries(groups).forEach(([groupKey, group]) => {
- group.forEach(pattern => {
+ group.forEach((pattern) => {
const matches = text.match(pattern);
if (matches) {
- matches.forEach(match => {
+ matches.forEach((match) => {
const key = `${markPrefix}-${groupKey}-${id}`;
text = text.replace(match, key);
hash[key] = match;
@@ -67,12 +67,12 @@ const unmark = (text, hash) => {
return source;
};
-const unwrap = source => {
+const unwrap = (source) => {
let text = source;
const matches = text.match(reTemplated);
if (matches) {
- matches.forEach(match => {
+ matches.forEach((match) => {
const initial = match.replace(`${wrapPrefix}`, '').replace(`${wrapPostfix}`, '');
text = text.replace(match, initial);
});
@@ -81,7 +81,7 @@ const unwrap = source => {
return text;
};
-const wrap = source => {
+const wrap = (source) => {
const { text, hash } = mark(unwrap(source), patternGroups);
return unmark(text, hash);
};
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index b51951674d5..81d9d9d37a7 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -35,7 +35,7 @@ export default class TaskList {
`${this.taskListContainerSelector} .js-task-list-field[data-value]`,
);
- taskListFields.forEach(taskListField => {
+ taskListFields.forEach((taskListField) => {
// eslint-disable-next-line no-param-reassign
taskListField.value = taskListField.dataset.value;
});
diff --git a/app/assets/javascripts/terminal/terminal.js b/app/assets/javascripts/terminal/terminal.js
index bae320cb705..26cc538994f 100644
--- a/app/assets/javascripts/terminal/terminal.js
+++ b/app/assets/javascripts/terminal/terminal.js
@@ -64,11 +64,11 @@ export default class GLTerminal {
const decoder = new TextDecoder('utf-8');
const encoder = new TextEncoder('utf-8');
- this.terminal.on('data', data => {
+ this.terminal.on('data', (data) => {
this.socket.send(encoder.encode(data));
});
- this.socket.addEventListener('message', ev => {
+ this.socket.addEventListener('message', (ev) => {
this.terminal.write(decoder.decode(ev.data));
});
@@ -110,7 +110,7 @@ export default class GLTerminal {
this.terminal.dispose();
this.socket.close();
- this.onDispose.forEach(fn => fn());
+ this.onDispose.forEach((fn) => fn());
this.onDispose.length = 0;
}
diff --git a/app/assets/javascripts/terraform/components/terraform_list.vue b/app/assets/javascripts/terraform/components/terraform_list.vue
index 26a0bfe5fa5..b71133d8813 100644
--- a/app/assets/javascripts/terraform/components/terraform_list.vue
+++ b/app/assets/javascripts/terraform/components/terraform_list.vue
@@ -15,7 +15,7 @@ export default {
...this.cursor,
};
},
- update: data => data,
+ update: (data) => data,
error() {
this.states = null;
},
diff --git a/app/assets/javascripts/test_utils/simulate_input.js b/app/assets/javascripts/test_utils/simulate_input.js
index c300c806e6d..90c1b7cb57e 100644
--- a/app/assets/javascripts/test_utils/simulate_input.js
+++ b/app/assets/javascripts/test_utils/simulate_input.js
@@ -12,7 +12,7 @@ export default function simulateInput(target, text) {
}
if (text.length > 0) {
- Array.prototype.forEach.call(text, char => {
+ Array.prototype.forEach.call(text, (char) => {
input.value += char;
triggerEvents(input);
});
diff --git a/app/assets/javascripts/toggle_buttons.js b/app/assets/javascripts/toggle_buttons.js
index 10a9d29e694..2f933823842 100644
--- a/app/assets/javascripts/toggle_buttons.js
+++ b/app/assets/javascripts/toggle_buttons.js
@@ -49,7 +49,7 @@ function onToggleClicked(toggle, input, clickCallback) {
export default function setupToggleButtons(container, clickCallback = () => {}) {
const toggles = container.querySelectorAll('.js-project-feature-toggle');
- toggles.forEach(toggle => {
+ toggles.forEach((toggle) => {
const input = toggle.querySelector('.js-project-feature-toggle-input');
const isOn = parseBoolean(input.value);
diff --git a/app/assets/javascripts/tooltips/components/tooltips.vue b/app/assets/javascripts/tooltips/components/tooltips.vue
index 05927006ea6..90bdf06bc4c 100644
--- a/app/assets/javascripts/tooltips/components/tooltips.vue
+++ b/app/assets/javascripts/tooltips/components/tooltips.vue
@@ -2,7 +2,7 @@
import { GlTooltip, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { uniqueId } from 'lodash';
-const getTooltipTitle = element => {
+const getTooltipTitle = (element) => {
return element.getAttribute('title') || element.dataset.title;
};
@@ -37,8 +37,8 @@ export default {
};
},
created() {
- this.observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
+ this.observer = new MutationObserver((mutations) => {
+ mutations.forEach((mutation) => {
mutation.removedNodes.forEach(this.dispose);
});
});
@@ -49,10 +49,11 @@ export default {
methods: {
addTooltips(elements, config) {
const newTooltips = elements
- .filter(element => !this.tooltipExists(element))
- .map(element => newTooltip(element, config));
+ .filter((element) => !this.tooltipExists(element))
+ .map((element) => newTooltip(element, config))
+ .filter((tooltip) => tooltip.title);
- newTooltips.forEach(tooltip => this.observe(tooltip));
+ newTooltips.forEach((tooltip) => this.observe(tooltip));
this.tooltips.push(...newTooltips);
},
@@ -90,9 +91,12 @@ export default {
return Boolean(this.findTooltipByTarget(element));
},
findTooltipByTarget(element) {
- return this.tooltips.find(tooltip => tooltip.target === element);
+ return this.tooltips.find((tooltip) => tooltip.target === element);
},
},
+ safeHtmlConfig: {
+ ADD_TAGS: ['gl-emoji'],
+ },
};
</script>
<template>
@@ -110,7 +114,7 @@ export default {
:disabled="tooltip.disabled"
:show="tooltip.show"
>
- <span v-if="tooltip.html" v-safe-html="tooltip.title"></span>
+ <span v-if="tooltip.html" v-safe-html:[$options.safeHtmlConfig]="tooltip.title"></span>
<span v-else>{{ tooltip.title }}</span>
</gl-tooltip>
</div>
diff --git a/app/assets/javascripts/tooltips/index.js b/app/assets/javascripts/tooltips/index.js
index f7cad6639ae..b216affc818 100644
--- a/app/assets/javascripts/tooltips/index.js
+++ b/app/assets/javascripts/tooltips/index.js
@@ -68,7 +68,7 @@ const invokeBootstrapApi = (elements, method) => {
}
};
-const isGlTooltipsEnabled = () => Boolean(window.gon.glTooltipsEnabled);
+const isGlTooltipsEnabled = () => Boolean(window.gon.features?.glTooltips);
const tooltipApiInvoker = ({ glHandler, bsHandler }) => (elements, ...params) => {
if (isGlTooltipsEnabled()) {
@@ -81,12 +81,12 @@ const tooltipApiInvoker = ({ glHandler, bsHandler }) => (elements, ...params) =>
export const initTooltips = (config = {}) => {
if (isGlTooltipsEnabled()) {
const triggers = config?.triggers || DEFAULT_TRIGGER;
- const events = triggers.split(' ').map(trigger => EVENTS_MAP[trigger]);
+ const events = triggers.split(' ').map((trigger) => EVENTS_MAP[trigger]);
- events.forEach(event => {
+ events.forEach((event) => {
document.addEventListener(
event,
- e => handleTooltipEvent(document, e, config.selector, config),
+ (e) => handleTooltipEvent(document, e, config.selector, config),
true,
);
});
@@ -103,28 +103,28 @@ export const add = (elements, config = {}) => {
return invokeBootstrapApi(elements, config);
};
export const dispose = tooltipApiInvoker({
- glHandler: element => tooltipsApp().dispose(element),
- bsHandler: elements => invokeBootstrapApi(elements, 'dispose'),
+ glHandler: (element) => tooltipsApp().dispose(element),
+ bsHandler: (elements) => invokeBootstrapApi(elements, 'dispose'),
});
export const fixTitle = tooltipApiInvoker({
- glHandler: element => tooltipsApp().fixTitle(element),
- bsHandler: elements => invokeBootstrapApi(elements, '_fixTitle'),
+ 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'),
+ 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'),
+ 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'),
+ 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'),
+ glHandler: (element) => tooltipsApp().triggerEvent(element, 'open'),
+ bsHandler: (elements) => invokeBootstrapApi(elements, 'show'),
});
export const destroy = () => {
tooltipsApp().$destroy();
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index 0a1211d0a76..5d82d56f4ba 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -43,7 +43,7 @@ const eventHandler = (e, func, opts = {}) => {
};
const eventHandlers = (category, func) => {
- const handler = opts => e => eventHandler(e, func, { ...{ category }, ...opts });
+ const handler = (opts) => (e) => eventHandler(e, func, { ...{ category }, ...opts });
const handlers = [];
handlers.push({ name: 'click', func: handler() });
handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
@@ -79,7 +79,7 @@ export default class Tracking {
parent.trackingBound = true;
const handlers = eventHandlers(category, (...args) => this.event(...args));
- handlers.forEach(event => parent.addEventListener(event.name, event.func));
+ handlers.forEach((event) => parent.addEventListener(event.name, event.func));
return handlers;
}
@@ -88,7 +88,7 @@ export default class Tracking {
const loadEvents = parent.querySelectorAll('[data-track-event="render"]');
- loadEvents.forEach(element => {
+ loadEvents.forEach((element) => {
const { action, data } = createEventPayload(element);
this.event(category, action, data);
});
diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js
index 947246b2fbb..58bff370fa5 100644
--- a/app/assets/javascripts/tree.js
+++ b/app/assets/javascripts/tree.js
@@ -8,7 +8,7 @@ export default class TreeView {
this.initKeyNav();
// Code browser tree slider
// Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
- $('.tree-content-holder .tree-item').on('click', function(e) {
+ $('.tree-content-holder .tree-item').on('click', function (e) {
const $clickedEl = $(e.target);
const path = $('.tree-item-file-name a', this).attr('href');
if (!$clickedEl.is('a') && !$clickedEl.is('.str-truncated')) {
@@ -20,15 +20,13 @@ export default class TreeView {
}
});
// Show the "Loading commit data" for only the first element
- $('span.log_loading')
- .first()
- .removeClass('hide');
+ $('span.log_loading').first().removeClass('hide');
}
initKeyNav() {
const li = $('tr.tree-item');
let liSelected = null;
- return $('body').keydown(e => {
+ return $('body').keydown((e) => {
let next, path;
if ($('input:focus').length > 0 && (e.which === 38 || e.which === 40)) {
return false;
diff --git a/app/assets/javascripts/ui_development_kit.js b/app/assets/javascripts/ui_development_kit.js
index 4f32e143de8..028b047d9f5 100644
--- a/app/assets/javascripts/ui_development_kit.js
+++ b/app/assets/javascripts/ui_development_kit.js
@@ -10,19 +10,19 @@ export default () => {
{
order_by: 'last_activity_at',
},
- data => {
+ (data) => {
callback(data);
},
);
},
- text: project => project.name_with_namespace || project.name,
+ text: (project) => project.name_with_namespace || project.name,
selectable: true,
fieldName: 'author_id',
filterable: true,
search: {
fields: ['name_with_namespace'],
},
- id: data => data.id,
- isSelected: data => data.id === 2,
+ id: (data) => data.id,
+ isSelected: (data) => data.id === 2,
});
};
diff --git a/app/assets/javascripts/usage_ping_consent.js b/app/assets/javascripts/usage_ping_consent.js
index a69620c1762..94d476d13ae 100644
--- a/app/assets/javascripts/usage_ping_consent.js
+++ b/app/assets/javascripts/usage_ping_consent.js
@@ -5,7 +5,7 @@ import { parseBoolean } from './lib/utils/common_utils';
import { __ } from './locale';
export default () => {
- $('body').on('click', '.js-usage-consent-action', e => {
+ $('body').on('click', '.js-usage-consent-action', (e) => {
e.preventDefault();
e.stopImmediatePropagation(); // overwrite rails listener
diff --git a/app/assets/javascripts/user_callout.js b/app/assets/javascripts/user_callout.js
index df00f38dd70..44e54c85f3c 100644
--- a/app/assets/javascripts/user_callout.js
+++ b/app/assets/javascripts/user_callout.js
@@ -15,7 +15,7 @@ export default class UserCallout {
init() {
if (!this.isCalloutDismissed || this.isCalloutDismissed === 'false') {
- this.userCalloutBody.find('.js-close-callout').on('click', e => this.dismissCallout(e));
+ this.userCalloutBody.find('.js-close-callout').on('click', (e) => this.dismissCallout(e));
}
}
diff --git a/app/assets/javascripts/user_lists/components/user_list_form.vue b/app/assets/javascripts/user_lists/components/user_list_form.vue
index 657acb51fee..a0364089d68 100644
--- a/app/assets/javascripts/user_lists/components/user_list_form.vue
+++ b/app/assets/javascripts/user_lists/components/user_list_form.vue
@@ -41,7 +41,7 @@ export default {
],
},
translations: {
- formLabel: s__('UserLists|Feature flag list'),
+ formLabel: s__('UserLists|Feature flag user list'),
formSubtitle: s__(
'UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}',
),
diff --git a/app/assets/javascripts/user_lists/store/edit/actions.js b/app/assets/javascripts/user_lists/store/edit/actions.js
index 8f0a2bafec7..6db2e65cf04 100644
--- a/app/assets/javascripts/user_lists/store/edit/actions.js
+++ b/app/assets/javascripts/user_lists/store/edit/actions.js
@@ -7,7 +7,7 @@ export const fetchUserList = ({ commit, state }) => {
commit(types.REQUEST_USER_LIST);
return Api.fetchFeatureFlagUserList(state.projectId, state.userListIid)
.then(({ data }) => commit(types.RECEIVE_USER_LIST_SUCCESS, data))
- .catch(response => commit(types.RECEIVE_USER_LIST_ERROR, getErrorMessages(response)));
+ .catch((response) => commit(types.RECEIVE_USER_LIST_ERROR, getErrorMessages(response)));
};
export const dismissErrorAlert = ({ commit }) => commit(types.DISMISS_ERROR_ALERT);
@@ -18,5 +18,5 @@ export const updateUserList = ({ commit, state }, userList) => {
name: userList.name,
})
.then(({ data }) => redirectTo(data.path))
- .catch(response => commit(types.RECEIVE_USER_LIST_ERROR, getErrorMessages(response)));
+ .catch((response) => commit(types.RECEIVE_USER_LIST_ERROR, getErrorMessages(response)));
};
diff --git a/app/assets/javascripts/user_lists/store/edit/index.js b/app/assets/javascripts/user_lists/store/edit/index.js
index b30b0b04b9e..3b19b2b12ec 100644
--- a/app/assets/javascripts/user_lists/store/edit/index.js
+++ b/app/assets/javascripts/user_lists/store/edit/index.js
@@ -3,7 +3,7 @@ import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default initialState =>
+export default (initialState) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/user_lists/store/new/actions.js b/app/assets/javascripts/user_lists/store/new/actions.js
index 185508bcfbc..478fca40142 100644
--- a/app/assets/javascripts/user_lists/store/new/actions.js
+++ b/app/assets/javascripts/user_lists/store/new/actions.js
@@ -11,5 +11,5 @@ export const createUserList = ({ commit, state }, userList) => {
...userList,
})
.then(({ data }) => redirectTo(data.path))
- .catch(response => commit(types.RECEIVE_CREATE_USER_LIST_ERROR, getErrorMessages(response)));
+ .catch((response) => commit(types.RECEIVE_CREATE_USER_LIST_ERROR, getErrorMessages(response)));
};
diff --git a/app/assets/javascripts/user_lists/store/new/index.js b/app/assets/javascripts/user_lists/store/new/index.js
index b30b0b04b9e..3b19b2b12ec 100644
--- a/app/assets/javascripts/user_lists/store/new/index.js
+++ b/app/assets/javascripts/user_lists/store/new/index.js
@@ -3,7 +3,7 @@ import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default initialState =>
+export default (initialState) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/user_lists/store/show/actions.js b/app/assets/javascripts/user_lists/store/show/actions.js
index 15b971aa5e8..dcd57efc146 100644
--- a/app/assets/javascripts/user_lists/store/show/actions.js
+++ b/app/assets/javascripts/user_lists/store/show/actions.js
@@ -5,7 +5,7 @@ import * as types from './mutation_types';
export const fetchUserList = ({ commit, state }) => {
commit(types.REQUEST_USER_LIST);
return Api.fetchFeatureFlagUserList(state.projectId, state.userListIid)
- .then(response => commit(types.RECEIVE_USER_LIST_SUCCESS, response.data))
+ .then((response) => commit(types.RECEIVE_USER_LIST_SUCCESS, response.data))
.catch(() => commit(types.RECEIVE_USER_LIST_ERROR));
};
@@ -27,6 +27,6 @@ export const updateUserList = ({ commit, state }) => {
...state.userList,
user_xids: stringifyUserIds(state.userIds),
})
- .then(response => commit(types.RECEIVE_USER_LIST_SUCCESS, response.data))
+ .then((response) => commit(types.RECEIVE_USER_LIST_SUCCESS, response.data))
.catch(() => commit(types.RECEIVE_USER_LIST_ERROR));
};
diff --git a/app/assets/javascripts/user_lists/store/show/index.js b/app/assets/javascripts/user_lists/store/show/index.js
index b30b0b04b9e..3b19b2b12ec 100644
--- a/app/assets/javascripts/user_lists/store/show/index.js
+++ b/app/assets/javascripts/user_lists/store/show/index.js
@@ -3,7 +3,7 @@ import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default initialState =>
+export default (initialState) =>
new Vuex.Store({
actions,
mutations,
diff --git a/app/assets/javascripts/user_lists/store/show/mutations.js b/app/assets/javascripts/user_lists/store/show/mutations.js
index c3e766465a7..3cf3b2d8371 100644
--- a/app/assets/javascripts/user_lists/store/show/mutations.js
+++ b/app/assets/javascripts/user_lists/store/show/mutations.js
@@ -20,10 +20,10 @@ export default {
[types.ADD_USER_IDS](state, ids) {
state.userIds = [
...state.userIds,
- ...parseUserIds(ids).filter(id => id && !state.userIds.includes(id)),
+ ...parseUserIds(ids).filter((id) => id && !state.userIds.includes(id)),
];
},
[types.REMOVE_USER_ID](state, id) {
- state.userIds = state.userIds.filter(uid => uid !== id);
+ state.userIds = state.userIds.filter((uid) => uid !== id);
},
};
diff --git a/app/assets/javascripts/user_lists/store/utils.js b/app/assets/javascripts/user_lists/store/utils.js
index f4e46947759..16f510bc32d 100644
--- a/app/assets/javascripts/user_lists/store/utils.js
+++ b/app/assets/javascripts/user_lists/store/utils.js
@@ -1,5 +1,6 @@
-export const parseUserIds = userIds => userIds.split(/\s*,\s*/g);
+export const parseUserIds = (userIds) => userIds.split(/\s*,\s*/g);
-export const stringifyUserIds = userIds => userIds.join(',');
+export const stringifyUserIds = (userIds) => userIds.join(',');
-export const getErrorMessages = error => [].concat(error?.response?.data?.message ?? error.message);
+export const getErrorMessages = (error) =>
+ [].concat(error?.response?.data?.message ?? error.message);
diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js
index 3521c1a105f..c18f4fb46cc 100644
--- a/app/assets/javascripts/user_popovers.js
+++ b/app/assets/javascripts/user_popovers.js
@@ -5,14 +5,14 @@ import { sanitize } from '~/lib/dompurify';
import UsersCache from './lib/utils/users_cache';
import UserPopover from './vue_shared/components/user_popover/user_popover.vue';
-const removeTitle = el => {
+const removeTitle = (el) => {
// Removing titles so its not showing tooltips also
el.dataset.originalTitle = '';
el.setAttribute('title', '');
};
-const getPreloadedUserInfo = dataset => {
+const getPreloadedUserInfo = (dataset) => {
const userId = dataset.user || dataset.userId;
const { username, name, avatarUrl } = dataset;
@@ -28,7 +28,7 @@ const getPreloadedUserInfo = dataset => {
* Adds a UserPopover component to the body, hands over as much data as the target element has in data attributes.
* loads based on data-user-id more data about a user from the API and sets it on the popover
*/
-const populateUserInfo = user => {
+const populateUserInfo = (user) => {
const { userId } = user;
return Promise.all([UsersCache.retrieveById(userId), UsersCache.retrieveStatusById(userId)]).then(
@@ -66,7 +66,7 @@ export default (elements = document.querySelectorAll('.js-user-link')) => {
return userLinks
.filter(({ dataset }) => dataset.user || dataset.userId)
- .map(el => {
+ .map((el) => {
if (initializedPopovers.has(el)) {
return initializedPopovers.get(el);
}
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index e693c3e90a4..79dc20fd498 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -75,7 +75,7 @@ function UsersSelect(currentUser, els, options = {}) {
selectedId = selectedIdDefault;
}
- const assignYourself = function() {
+ const assignYourself = function () {
const unassignedSelected = $dropdown
.closest('.selectbox')
.find(`input[name='${$dropdown.data('fieldName')}'][value=0]`);
@@ -108,17 +108,17 @@ function UsersSelect(currentUser, els, options = {}) {
$block[0].addEventListener('assignYourself', assignYourself);
}
- const getSelectedUserInputs = function() {
+ const getSelectedUserInputs = function () {
return $selectbox.find(`input[name="${$dropdown.data('fieldName')}"]`);
};
- const getSelected = function() {
+ const getSelected = function () {
return getSelectedUserInputs()
.map((index, input) => parseInt(input.value, 10))
.get();
};
- const checkMaxSelect = function() {
+ const checkMaxSelect = function () {
const maxSelect = $dropdown.data('maxSelect');
if (maxSelect) {
const selected = getSelected();
@@ -144,15 +144,15 @@ function UsersSelect(currentUser, els, options = {}) {
}
};
- const getMultiSelectDropdownTitle = function(selectedUser, isSelected) {
- const selectedUsers = getSelected().filter(u => u !== 0);
+ const getMultiSelectDropdownTitle = function (selectedUser, isSelected) {
+ const selectedUsers = getSelected().filter((u) => u !== 0);
const firstUser = getSelectedUserInputs()
.map((index, input) => ({
name: input.dataset.meta,
value: parseInt(input.value, 10),
}))
- .filter(u => u.id !== 0)
+ .filter((u) => u.id !== 0)
.get(0);
if (selectedUsers.length === 0) {
@@ -160,7 +160,7 @@ function UsersSelect(currentUser, els, options = {}) {
} else if (selectedUsers.length === 1) {
return firstUser.name;
} else if (isSelected) {
- const otherSelected = selectedUsers.filter(s => s !== selectedUser.id);
+ const otherSelected = selectedUsers.filter((s) => s !== selectedUser.id);
return sprintf(s__('UsersSelect|%{name} + %{length} more'), {
name: selectedUser.name,
length: otherSelected.length,
@@ -172,7 +172,7 @@ function UsersSelect(currentUser, els, options = {}) {
});
};
- $assignToMeLink.on('click', e => {
+ $assignToMeLink.on('click', (e) => {
e.preventDefault();
$(e.currentTarget).hide();
@@ -196,12 +196,12 @@ function UsersSelect(currentUser, els, options = {}) {
}
});
- $block.on('click', '.js-assign-yourself', e => {
+ $block.on('click', '.js-assign-yourself', (e) => {
e.preventDefault();
return assignTo(userSelect.currentUser.id);
});
- assignTo = function(selected) {
+ assignTo = function (selected) {
const data = {};
data[abilityName] = {};
data[abilityName].assignee_id = selected != null ? selected : null;
@@ -250,7 +250,7 @@ function UsersSelect(currentUser, els, options = {}) {
return initDeprecatedJQueryDropdown($dropdown, {
showMenuAbove,
data(term, callback) {
- return userSelect.users(term, options, users => {
+ return userSelect.users(term, options, (users) => {
// GitLabDropdownFilter returns this.instance
// GitLabDropdownRemote returns this.options.instance
const deprecatedJQueryDropdown = this.instance || this.options.instance;
@@ -266,14 +266,14 @@ function UsersSelect(currentUser, els, options = {}) {
// Potential duplicate entries when dealing with issue board
// because issue board is also managed by vue
- const selectedUsers = uniqBy(selectedInputs, a => a.value)
- .filter(input => {
+ const selectedUsers = uniqBy(selectedInputs, (a) => a.value)
+ .filter((input) => {
const userId = parseInt(input.value, 10);
- const inUsersArray = users.find(u => u.id === userId);
+ const inUsersArray = users.find((u) => u.id === userId);
return !inUsersArray && userId !== 0;
})
- .map(input => {
+ .map((input) => {
const userId = parseInt(input.value, 10);
const { avatarUrl, avatar_url, name, username, canMerge } = input.dataset;
return {
@@ -334,7 +334,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
if ($dropdown.hasClass('js-multiselect')) {
- const selected = getSelected().filter(i => i !== 0);
+ const selected = getSelected().filter((i) => i !== 0);
if (selected.length > 0) {
if ($dropdown.data('dropdownHeader')) {
@@ -346,12 +346,12 @@ function UsersSelect(currentUser, els, options = {}) {
}
const selectedUsers = users
- .filter(u => selected.indexOf(u.id) !== -1)
+ .filter((u) => selected.indexOf(u.id) !== -1)
.sort((a, b) => a.name > b.name);
- users = users.filter(u => selected.indexOf(u.id) === -1);
+ users = users.filter((u) => selected.indexOf(u.id) === -1);
- selectedUsers.forEach(selectedUser => {
+ selectedUsers.forEach((selectedUser) => {
showDivider += 1;
users.splice(showDivider, 0, selectedUser);
});
@@ -477,7 +477,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
}
- if (getSelected().find(u => u === gon.current_user_id)) {
+ if (getSelected().find((u) => u === gon.current_user_id)) {
$assignToMeLink.hide();
} else {
$assignToMeLink.show();
@@ -544,7 +544,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
if (selected.length > 0) {
- getSelected().forEach(selectedId => highlightSelected(selectedId));
+ getSelected().forEach((selectedId) => highlightSelected(selectedId));
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
highlightSelected(0);
} else {
@@ -559,7 +559,7 @@ function UsersSelect(currentUser, els, options = {}) {
let selected = false;
if (this.multiSelect) {
- selected = getSelected().find(u => user.id === u);
+ selected = getSelected().find((u) => user.id === u);
const { fieldName } = this;
const field = $dropdown
@@ -613,7 +613,7 @@ function UsersSelect(currentUser, els, options = {}) {
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query(query) {
- return userSelect.users(query.term, options, users => {
+ return userSelect.users(query.term, options, (users) => {
let name;
const data = {
results: users,
@@ -694,7 +694,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
}
-UsersSelect.prototype.initSelection = function(element, callback) {
+UsersSelect.prototype.initSelection = function (element, callback) {
const id = $(element).val();
if (id === '0') {
const nullUser = {
@@ -706,7 +706,7 @@ UsersSelect.prototype.initSelection = function(element, callback) {
}
};
-UsersSelect.prototype.formatResult = function(user) {
+UsersSelect.prototype.formatResult = function (user) {
let avatar = gon.default_avatar_url;
if (user.avatar_url) {
avatar = user.avatar_url;
@@ -728,11 +728,11 @@ UsersSelect.prototype.formatResult = function(user) {
`;
};
-UsersSelect.prototype.formatSelection = function(user) {
+UsersSelect.prototype.formatSelection = function (user) {
return escape(user.name);
};
-UsersSelect.prototype.user = function(user_id, callback) {
+UsersSelect.prototype.user = function (user_id, callback) {
if (!/^\d+$/.test(user_id)) {
return false;
}
@@ -746,7 +746,7 @@ UsersSelect.prototype.user = function(user_id, callback) {
// Return users list. Filtered by query
// Only active users retrieved
-UsersSelect.prototype.users = function(query, options, callback) {
+UsersSelect.prototype.users = function (query, options, callback) {
const url = this.buildUrl(this.usersPath);
const params = {
search: query,
@@ -755,8 +755,8 @@ UsersSelect.prototype.users = function(query, options, callback) {
};
const isMergeRequest = options.issuableType === 'merge_request';
- const isEditMergeRequest = !options.issuableType && (options.iid && options.targetBranch);
- const isNewMergeRequest = !options.issuableType && (!options.iid && options.targetBranch);
+ const isEditMergeRequest = !options.issuableType && options.iid && options.targetBranch;
+ const isNewMergeRequest = !options.issuableType && !options.iid && options.targetBranch;
if (isMergeRequest || isEditMergeRequest || isNewMergeRequest) {
params.merge_request_iid = options.iid || null;
@@ -772,14 +772,14 @@ UsersSelect.prototype.users = function(query, options, callback) {
});
};
-UsersSelect.prototype.buildUrl = function(url) {
+UsersSelect.prototype.buildUrl = function (url) {
if (gon.relative_url_root != null) {
url = gon.relative_url_root.replace(/\/$/, '') + url;
}
return url;
};
-UsersSelect.prototype.renderRow = function(
+UsersSelect.prototype.renderRow = function (
issuableType,
user,
selected,
@@ -815,7 +815,7 @@ UsersSelect.prototype.renderRow = function(
`;
};
-UsersSelect.prototype.renderRowAvatar = function(issuableType, user, img) {
+UsersSelect.prototype.renderRowAvatar = function (issuableType, user, img) {
if (user.beforeDivider) {
return img;
}
@@ -831,22 +831,22 @@ UsersSelect.prototype.renderRowAvatar = function(issuableType, user, img) {
</span>`;
};
-UsersSelect.prototype.renderApprovalRules = function(elsClassName, approvalRules = []) {
- if (!gon.features?.reviewerApprovalRules || !elsClassName?.includes('reviewer')) {
+UsersSelect.prototype.renderApprovalRules = function (elsClassName, approvalRules = []) {
+ const count = approvalRules.length;
+
+ if (!gon.features?.reviewerApprovalRules || !elsClassName?.includes('reviewer') || !count) {
return '';
}
- const count = approvalRules.length;
const [rule] = approvalRules;
const countText = sprintf(__('(+%{count}&nbsp;rules)'), { count });
const renderApprovalRulesCount = count > 1 ? `<span class="ml-1">${countText}</span>` : '';
+ const ruleName = rule.rule_type === 'code_owner' ? __('Code Owner') : rule.name;
- return count
- ? `<div class="gl-display-flex gl-font-sm">
- <span class="gl-text-truncate" title="${rule.name}">${rule.name}</span>
- ${renderApprovalRulesCount}
- </div>`
- : '';
+ return `<div class="gl-display-flex gl-font-sm">
+ <span class="gl-text-truncate" title="${ruleName}">${ruleName}</span>
+ ${renderApprovalRulesCount}
+ </div>`;
};
export default UsersSelect;
diff --git a/app/assets/javascripts/vue_alerts.js b/app/assets/javascripts/vue_alerts.js
index 6550eb31491..abc1dd75645 100644
--- a/app/assets/javascripts/vue_alerts.js
+++ b/app/assets/javascripts/vue_alerts.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
-const mountVueAlert = el => {
+const mountVueAlert = (el) => {
const props = {
html: el.innerHTML,
};
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 7297f8f8677..9b822657184 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
@@ -74,7 +74,7 @@ export default {
return this.mr.approvals || {};
},
approvedBy() {
- return this.approvals.approved_by ? this.approvals.approved_by.map(x => x.user) : [];
+ return this.approvals.approved_by ? this.approvals.approved_by.map((x) => x.user) : [];
},
userHasApproved() {
return Boolean(this.approvals.user_has_approved);
@@ -136,7 +136,7 @@ export default {
approveWithAuth(data) {
this.updateApproval(
() => this.service.approveMergeRequestWithAuth(data),
- error => {
+ (error) => {
if (error && error.response && error.response.status === 401) {
this.hasApprovalAuthError = true;
return;
@@ -155,7 +155,7 @@ export default {
this.isApproving = true;
this.clearError();
return serviceFn()
- .then(data => {
+ .then((data) => {
this.mr.setApprovals(data);
eventHub.$emit('MRWidgetUpdateRequested');
this.$emit('updated');
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 b90cbfd1a1a..215df8acece 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
@@ -121,7 +121,7 @@ export default {
this.actionInProgress = actionName;
MRWidgetService.executeInlineAction(endpoint)
- .then(resp => {
+ .then((resp) => {
const redirectUrl = resp?.data?.redirect_url;
if (redirectUrl) {
visitUrl(redirectUrl);
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
index e3c0b7935d7..abc831c8abe 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
@@ -57,7 +57,7 @@ export default {
return this.deployment.changes && this.deployment.changes.length > 1;
},
filteredChanges() {
- return this.deployment?.changes?.filter(change => change.path.includes(this.searchTerm));
+ return this.deployment?.changes?.filter((change) => change.path.includes(this.searchTerm));
},
},
};
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 9b2cd41092e..2f27216f2e9 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
@@ -102,7 +102,7 @@ export default {
loadMetrics() {
backOff((next, stop) => {
MRWidgetService.fetchMetrics(this.metricsUrl)
- .then(res => {
+ .then((res) => {
if (res.status === statusCodes.NO_CONTENT) {
this.backOffRequestCounter += 1;
/* eslint-disable no-unused-expressions */
@@ -113,14 +113,14 @@ export default {
})
.catch(stop);
})
- .then(res => {
+ .then((res) => {
if (res.status === statusCodes.NO_CONTENT) {
return res;
}
return res.data;
})
- .then(data => {
+ .then((data) => {
this.computeGraphData(data.metrics, data.deployment_time);
return data;
})
@@ -145,7 +145,7 @@ export default {
<template #metricsLink="{ content }">
<gl-link :href="metricsMonitoringUrl">{{ content }}</gl-link>
</template>
- <template #emphasis="{content}">
+ <template #emphasis="{ content }">
<strong>{{ content }}</strong>
</template>
<template #memoryFrom>{{ memoryFrom }}</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
index eff26729fa7..33809b953ee 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -67,11 +67,11 @@ export default {
},
mounted() {
this.fetchCollapsedData(this.$props)
- .then(data => {
+ .then((data) => {
this.collapsedData = data;
this.loadingState = null;
})
- .catch(e => {
+ .catch((e) => {
this.loadingState = LOADING_STATES.collapsedError;
throw e;
});
@@ -86,11 +86,11 @@ export default {
this.loadingState = LOADING_STATES.expandedLoading;
this.fetchFullData(this.$props)
- .then(data => {
+ .then((data) => {
this.loadingState = null;
this.fullData = data;
})
- .catch(e => {
+ .catch((e) => {
this.loadingState = null;
throw e;
});
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
index 5014c12dc30..529160de6a7 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
@@ -11,7 +11,7 @@ export default {
return h(
'div',
{},
- extensions.map(extension =>
+ extensions.map((extension) =>
h(extension, {
props: extensions[0].props.reduce(
(acc, key) => ({
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
index 2bfaec8a1c9..9796bb44939 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
@@ -3,7 +3,7 @@ import ExtensionBase from './base.vue';
// Holds all the currently registered extensions
export const extensions = [];
-export const registerExtension = extension => {
+export const registerExtension = (extension) => {
// Pushes into the extenions array a dynamically created Vue component
// that gets exteneded from `base.vue`
extensions.push({
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
index a2636ce52ad..560a68031ef 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
@@ -13,7 +13,7 @@ export default {
type: String,
required: false,
default: DANGER,
- validator: value => [WARNING, DANGER].includes(value),
+ validator: (value) => [WARNING, DANGER].includes(value),
},
helpPath: {
type: String,
@@ -36,7 +36,7 @@ export default {
</script>
<template>
- <div class="m-3 ml-7" :class="messageClass">
+ <div class="gl-m-3 gl-ml-7" :class="messageClass">
<slot></slot>
<gl-link v-if="helpPath" :href="helpPath" target="_blank">
<gl-icon :size="16" name="question-o" class="align-middle" />
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue
index 1727383ea2c..3cd003461b3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue
@@ -30,7 +30,7 @@ export default {
};
</script>
<template>
- <section class="mr-widget-help font-italic">
+ <section class="gl-py-3 gl-pr-3 gl-pl-5 gl-ml-7 mr-widget-help gl-font-style-italic">
<template v-if="missingBranch">
{{ missingBranchInfo }}
</template>
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 5066a88b52b..4c130945487 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
@@ -11,6 +11,7 @@ import {
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 CiIcon from '~/vue_shared/components/ci_icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
@@ -23,6 +24,7 @@ export default {
GlIcon,
GlSprintf,
GlTooltip,
+ PipelineArtifacts,
PipelineStage,
TooltipOnTruncate,
LinkedPipelinesMiniList: () =>
@@ -97,6 +99,9 @@ export default {
hasCommitInfo() {
return this.pipeline.commit && Object.keys(this.pipeline.commit).length > 0;
},
+ hasArtifacts() {
+ return this.pipeline?.details?.artifacts?.length > 0;
+ },
isMergeRequestPipeline() {
return Boolean(this.pipeline.flags && this.pipeline.flags.merge_request_pipeline);
},
@@ -142,7 +147,7 @@ export default {
data-testid="ci-error-message"
>
<gl-sprintf :message="$options.errorText">
- <template #link="{content}">
+ <template #link="{ content }">
<gl-link :href="mrTroubleshootingDocsPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
@@ -218,7 +223,6 @@ export default {
data-testid="pipeline-coverage-delta"
>({{ pipelineCoverageDelta }}%)</span
>
-
{{ pipelineCoverageJobNumberText }}
<span ref="pipelineCoverageQuestion">
<gl-icon name="question" :size="12" />
@@ -258,6 +262,11 @@ export default {
</template>
</span>
<linked-pipelines-mini-list v-if="triggered.length" :triggered="triggered" />
+ <pipeline-artifacts
+ v-if="hasArtifacts"
+ :artifacts="pipeline.details.artifacts"
+ class="gl-ml-3"
+ />
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index 56a50b55f9d..43317130b08 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -30,7 +30,7 @@ export default {
};
</script>
<template>
- <section class="mr-info-list mr-links">
+ <section class="mr-info-list gl-ml-7 gl-pb-5">
<p v-if="relatedLinks.closing">{{ closesText }} <span v-html="relatedLinks.closing"></span></p>
<p v-if="relatedLinks.mentioned">
{{ s__('mrWidget|Mentions') }} <span v-html="relatedLinks.mentioned"></span>
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 a9d148505e1..7acdd695cc2 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
@@ -86,12 +86,12 @@ export default {
to create one.`)
"
>
- <template #prefixToLink="{content}">
+ <template #prefixToLink="{ content }">
<strong>
{{ content }}
</strong>
</template>
- <template #addPipelineLink="{content}">
+ <template #addPipelineLink="{ content }">
<gl-link
:href="pipelinePath"
class="gl-ml-1"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
index c917b69953f..d50d97e3570 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -18,7 +18,7 @@ export default {
</script>
<template>
- <p v-once class="mr-info-list mr-links gl-mb-0">
+ <p v-once class="mr-info-list gl-ml-7 gl-pb-5 gl-mb-0">
<span class="status-text">
<gl-sprintf :message="$options.i18n.removesBranchText">
<template #strong="{ content }">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
index b6722de5277..73d75352cb5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
@@ -25,12 +25,13 @@ export default {
class="mr-commit-dropdown"
>
<gl-dropdown-item
- v-for="commit in commits"
- :key="commit.short_id"
+ v-for="(commit, index) in commits"
+ :key="index"
class="text-nowrap text-truncate"
@click="$emit('input', commit.message)"
>
- <span class="monospace mr-2">{{ commit.short_id }}</span> {{ commit.title }}
+ <span class="monospace mr-2">{{ commit.shortId || commit.short_id }}</span>
+ {{ commit.title }}
</gl-dropdown-item>
</gl-dropdown>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
index bdcea9871ea..d331f1690f5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
@@ -83,6 +83,7 @@ export default {
:aria-label="ariaLabel"
category="tertiary"
class="commit-edit-toggle gl-mr-3"
+ size="small"
:icon="collapseIcon"
@click.stop="toggle()"
/>
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 750014c599a..20ac8f5a467 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
@@ -1,21 +1,37 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+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 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 mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
export default {
name: 'MRWidgetAutoMergeEnabled',
+ apollo: {
+ state: {
+ query: autoMergeEnabledQuery,
+ skip() {
+ return !this.glFeatures.mergeRequestWidgetGraphql;
+ },
+ variables() {
+ return this.mergeRequestQueryVariables;
+ },
+ update: (data) => data.project?.mergeRequest,
+ },
+ },
components: {
MrWidgetAuthor,
statusIcon,
GlLoadingIcon,
+ GlSkeletonLoader,
},
- mixins: [autoMergeMixin],
+ mixins: [autoMergeMixin, glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
mr: {
type: Object,
@@ -30,20 +46,47 @@ export default {
},
data() {
return {
+ state: {},
isCancellingAutoMerge: false,
isRemovingSourceBranch: false,
};
},
computed: {
+ loading() {
+ return this.glFeatures.mergeRequestWidgetGraphql && this.$apollo.queries.state.loading;
+ },
+ mergeUser() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.mergeUser;
+ }
+
+ return this.mr.setToAutoMergeBy;
+ },
+ targetBranch() {
+ return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).targetBranch;
+ },
+ shouldRemoveSourceBranch() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.shouldRemoveSourceBranch || this.state.forceRemoveSourceBranch;
+ }
+
+ return this.mr.shouldRemoveSourceBranch;
+ },
+ autoMergeStrategy() {
+ return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).autoMergeStrategy;
+ },
canRemoveSourceBranch() {
- const {
- shouldRemoveSourceBranch,
- canRemoveSourceBranch,
- mergeUserId,
- currentUserId,
- } = this.mr;
+ const { currentUserId } = this.mr;
+ const mergeUserId = this.glFeatures.mergeRequestWidgetGraphql
+ ? this.state.mergeUser?.id
+ : this.mr.mergeUserId;
+ const canRemoveSourceBranch = this.glFeatures.mergeRequestWidgetGraphql
+ ? this.state.userPermissions.removeSourceBranch
+ : this.mr.canRemoveSourceBranch;
- return !shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId;
+ return (
+ !this.shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId
+ );
},
},
methods: {
@@ -51,8 +94,8 @@ export default {
this.isCancellingAutoMerge = true;
this.service
.cancelAutomaticMerge()
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
eventHub.$emit('UpdateWidgetData', data);
})
.catch(() => {
@@ -63,15 +106,15 @@ export default {
removeSourceBranch() {
const options = {
sha: this.mr.sha,
- auto_merge_strategy: this.mr.autoMergeStrategy,
+ auto_merge_strategy: this.autoMergeStrategy,
should_remove_source_branch: true,
};
this.isRemovingSourceBranch = true;
this.service
.merge(options)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
if (AUTO_MERGE_STRATEGIES.includes(data.status)) {
eventHub.$emit('MRWidgetUpdateRequested');
}
@@ -86,49 +129,64 @@ export default {
</script>
<template>
<div class="mr-widget-body media">
- <status-icon status="success" />
- <div class="media-body">
- <h4 class="d-flex align-items-start">
- <span class="gl-mr-3">
- <span class="js-status-text-before-author">{{ statusTextBeforeAuthor }}</span>
- <mr-widget-author :author="mr.setToAutoMergeBy" />
- <span class="js-status-text-after-author">{{ statusTextAfterAuthor }}</span>
- </span>
- <a
- v-if="mr.canCancelAutomaticMerge"
- :disabled="isCancellingAutoMerge"
- role="button"
- href="#"
- class="btn btn-sm btn-default js-cancel-auto-merge"
- @click.prevent="cancelAutomaticMerge"
- >
- <gl-loading-icon v-if="isCancellingAutoMerge" inline class="gl-mr-1" />
- {{ cancelButtonText }}
- </a>
- </h4>
- <section class="mr-info-list">
- <p>
- {{ s__('mrWidget|The changes will be merged into') }}
- <a :href="mr.targetBranchPath" class="label-branch">{{ mr.targetBranch }}</a>
- </p>
- <p v-if="mr.shouldRemoveSourceBranch">
- {{ s__('mrWidget|The source branch will be deleted') }}
- </p>
- <p v-else class="d-flex align-items-start">
- <span class="gl-mr-3">{{ s__('mrWidget|The source branch will not be deleted') }}</span>
+ <div v-if="loading" class="gl-w-full mr-conflict-loader">
+ <gl-skeleton-loader :width="334" :height="30">
+ <rect x="0" y="3" width="24" height="24" rx="4" />
+ <rect x="32" y="7" width="150" height="16" rx="4" />
+ <rect x="190" y="7" width="144" height="16" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ <template v-else>
+ <status-icon status="success" />
+ <div class="media-body">
+ <h4 class="gl-display-flex">
+ <span class="gl-mr-3">
+ <span class="js-status-text-before-author" data-testid="beforeStatusText">{{
+ statusTextBeforeAuthor
+ }}</span>
+ <mr-widget-author :author="mergeUser" />
+ <span class="js-status-text-after-author" data-testid="afterStatusText">{{
+ statusTextAfterAuthor
+ }}</span>
+ </span>
<a
- v-if="canRemoveSourceBranch"
- :disabled="isRemovingSourceBranch"
+ v-if="mr.canCancelAutomaticMerge"
+ :disabled="isCancellingAutoMerge"
role="button"
- class="btn btn-sm btn-default js-remove-source-branch"
href="#"
- @click.prevent="removeSourceBranch"
+ class="btn btn-sm btn-default js-cancel-auto-merge"
+ data-testid="cancelAutomaticMergeButton"
+ @click.prevent="cancelAutomaticMerge"
>
- <gl-loading-icon v-if="isRemovingSourceBranch" inline class="gl-mr-1" />
- {{ s__('mrWidget|Delete source branch') }}
+ <gl-loading-icon v-if="isCancellingAutoMerge" inline class="gl-mr-1" />
+ {{ cancelButtonText }}
</a>
- </p>
- </section>
- </div>
+ </h4>
+ <section class="mr-info-list">
+ <p>
+ {{ s__('mrWidget|The changes will be merged into') }}
+ <a :href="mr.targetBranchPath" class="label-branch">{{ targetBranch }}</a>
+ </p>
+ <p v-if="shouldRemoveSourceBranch">
+ {{ s__('mrWidget|The source branch will be deleted') }}
+ </p>
+ <p v-else class="gl-display-flex">
+ <span class="gl-mr-3">{{ s__('mrWidget|The source branch will not be deleted') }}</span>
+ <a
+ v-if="canRemoveSourceBranch"
+ :disabled="isRemovingSourceBranch"
+ role="button"
+ class="btn btn-sm btn-default js-remove-source-branch"
+ href="#"
+ data-testid="removeSourceBranchButton"
+ @click.prevent="removeSourceBranch"
+ >
+ <gl-loading-icon v-if="isRemovingSourceBranch" inline class="gl-mr-1" />
+ {{ s__('mrWidget|Delete source branch') }}
+ </a>
+ </p>
+ </section>
+ </div>
+ </template>
</div>
</template>
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 30da9947859..a2771bc4bfb 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
@@ -1,7 +1,10 @@
<script>
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';
export default {
name: 'MRWidgetAutoMergeFailed',
@@ -10,6 +13,19 @@ export default {
GlLoadingIcon,
GlButton,
},
+ mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
+ apollo: {
+ mergeError: {
+ query: autoMergeFailedQuery,
+ skip() {
+ return !this.glFeatures.mergeRequestWidgetGraphql;
+ },
+ variables() {
+ return this.mergeRequestQueryVariables;
+ },
+ update: (data) => data.project?.mergeRequest?.mergeError,
+ },
+ },
props: {
mr: {
type: Object,
@@ -18,6 +34,7 @@ export default {
},
data() {
return {
+ mergeError: this.glFeatures.mergeRequestWidgetGraphql ? null : this.mr.mergeError,
isRefreshing: false,
};
},
@@ -36,7 +53,7 @@ export default {
<status-icon status="warning" />
<div class="media-body space-children gl-display-flex gl-flex-wrap gl-align-items-center">
<span class="bold">
- <template v-if="mr.mergeError">{{ mr.mergeError }}</template>
+ <template v-if="mergeError">{{ mergeError }}</template>
{{ s__('mrWidget|This merge request failed to be merged automatically') }}
</span>
<gl-button
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 87c59e5ece9..3d5daa4979b 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
@@ -30,7 +30,7 @@ export default {
variables() {
return this.mergeRequestQueryVariables;
},
- update: data => data.project.mergeRequest.userPermissions,
+ update: (data) => data.project.mergeRequest.userPermissions,
},
stateData: {
query: conflictsStateQuery,
@@ -40,7 +40,7 @@ export default {
variables() {
return this.mergeRequestQueryVariables;
},
- update: data => data.project.mergeRequest,
+ update: (data) => data.project.mergeRequest,
},
},
props: {
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 17cd740ddd9..9d646dbfb3e 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
@@ -83,8 +83,8 @@ export default {
this.service
.removeSourceBranch()
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
// eslint-disable-next-line @gitlab/require-i18n-strings
if (data.message === 'Branch was deleted') {
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 8511797286d..3f68979bc0e 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
@@ -25,7 +25,7 @@ export default {
variables() {
return this.mergeRequestQueryVariables;
},
- update: data => data.project.mergeRequest,
+ update: (data) => data.project.mergeRequest,
},
},
props: {
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 14c2e9fa828..bf86e0d8b07 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
@@ -1,19 +1,36 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlButton } from '@gitlab/ui';
+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 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 { __, sprintf } from '~/locale';
export default {
name: 'MRWidgetRebase',
+ apollo: {
+ state: {
+ query: rebaseQuery,
+ skip() {
+ return !this.glFeatures.mergeRequestWidgetGraphql;
+ },
+ variables() {
+ return this.mergeRequestQueryVariables;
+ },
+ update: (data) => data.project.mergeRequest,
+ },
+ },
components: {
statusIcon,
GlButton,
+ GlSkeletonLoader,
},
+ mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
mr: {
type: Object,
@@ -26,16 +43,41 @@ export default {
},
data() {
return {
+ state: {},
isMakingRequest: false,
rebasingError: null,
};
},
computed: {
+ isLoading() {
+ return this.glFeatures.mergeRequestWidgetGraphql && this.$apollo.queries.state.loading;
+ },
+ rebaseInProgress() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.rebaseInProgress;
+ }
+
+ return this.mr.rebaseInProgress;
+ },
+ canPushToSourceBranch() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.userPermissions.pushToSourceBranch;
+ }
+
+ return this.mr.canPushToSourceBranch;
+ },
+ targetBranch() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.targetBranch;
+ }
+
+ return this.mr.targetBranch;
+ },
status() {
- if (this.mr.rebaseInProgress || this.isMakingRequest) {
+ if (this.rebaseInProgress || this.isMakingRequest) {
return 'loading';
}
- if (!this.mr.canPushToSourceBranch && !this.mr.rebaseInProgress) {
+ if (!this.canPushToSourceBranch && !this.rebaseInProgress) {
return 'warning';
}
return 'success';
@@ -49,7 +91,7 @@ export default {
'Fast-forward merge is not possible. Rebase the source branch onto %{targetBranch} to allow this merge request to be merged.',
),
{
- targetBranch: `<span class="label-branch">${escape(this.mr.targetBranch)}</span>`,
+ targetBranch: `<span class="label-branch">${escape(this.targetBranch)}</span>`,
},
false,
);
@@ -65,7 +107,7 @@ export default {
.then(() => {
simplePoll(this.checkRebaseStatus);
})
- .catch(error => {
+ .catch((error) => {
this.isMakingRequest = false;
if (error.response && error.response.data && error.response.data.merge_error) {
@@ -78,8 +120,8 @@ export default {
checkRebaseStatus(continuePolling, stopPolling) {
this.service
.poll()
- .then(res => res.data)
- .then(res => {
+ .then((res) => res.data)
+ .then((res) => {
if (res.rebase_in_progress) {
continuePolling();
} else {
@@ -105,17 +147,30 @@ export default {
</script>
<template>
<div class="mr-widget-body media">
- <status-icon :status="status" :show-disabled-button="showDisabledButton" />
+ <div v-if="isLoading" class="gl-w-full mr-conflict-loader">
+ <gl-skeleton-loader :width="334" :height="30">
+ <rect x="0" y="3" width="24" height="24" rx="4" />
+ <rect x="32" y="5" width="302" height="20" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ <template v-else>
+ <status-icon :status="status" :show-disabled-button="showDisabledButton" />
- <div class="rebase-state-find-class-convention media media-body space-children">
- <template v-if="mr.rebaseInProgress || isMakingRequest">
- <span class="bold" data-testid="rebase-message">{{ __('Rebase in progress') }}</span>
- </template>
- <template v-if="!mr.rebaseInProgress && !mr.canPushToSourceBranch">
- <span class="bold" data-testid="rebase-message" v-html="fastForwardMergeText"></span>
- </template>
- <template v-if="!mr.rebaseInProgress && mr.canPushToSourceBranch && !isMakingRequest">
+ <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!"
+ data-testid="rebase-message"
+ >{{ __('Rebase in progress') }}</span
+ >
+ <span
+ v-if="!rebaseInProgress && !canPushToSourceBranch"
+ class="gl-font-weight-bold gl-ml-0!"
+ data-testid="rebase-message"
+ v-html="fastForwardMergeText"
+ ></span>
<div
+ v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest"
class="accept-merge-holder clearfix js-toggle-container accept-action media space-children"
>
<gl-button
@@ -126,14 +181,21 @@ export default {
>
{{ __('Rebase') }}
</gl-button>
- <span v-if="!rebasingError" class="bold" data-testid="rebase-message">{{
- __(
- 'Fast-forward merge is not possible. Rebase the source branch onto the target branch.',
- )
+ <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">{{
+ rebasingError
}}</span>
- <span v-else class="bold danger" data-testid="rebase-message">{{ rebasingError }}</span>
</div>
- </template>
- </div>
+ </div>
+ </template>
</div>
</template>
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 2c1f2285dda..a890b176df0 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
@@ -9,13 +9,18 @@ import {
GlSprintf,
GlLink,
GlTooltipDirective,
+ GlSkeletonLoader,
} from '@gitlab/ui';
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 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 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';
@@ -35,6 +40,31 @@ const MERGE_HOOK_VALIDATION_ERROR_STATUS = 'hook_validation_error';
export default {
name: 'ReadyToMerge',
+ apollo: {
+ state: {
+ query: readyToMergeQuery,
+ skip() {
+ return !this.glFeatures.mergeRequestWidgetGraphql;
+ },
+ variables() {
+ return this.mergeRequestQueryVariables;
+ },
+ manual: true,
+ result({ data }) {
+ this.state = {
+ ...data.project.mergeRequest,
+ mergeRequestsFfOnlyEnabled: data.mergeRequestsFfOnlyEnabled,
+ onlyAllowMergeIfPipelineSucceeds: data.onlyAllowMergeIfPipelineSucceeds,
+ };
+ this.removeSourceBranch = data.project.mergeRequest.shouldRemoveSourceBranch;
+ this.commitMessage = data.project.mergeRequest.defaultMergeCommitMessage;
+ this.squashBeforeMerge = data.project.mergeRequest.squashOnMerge;
+ this.isSquashReadOnly = data.project.squashReadOnly;
+ this.squashCommitMessage = data.project.mergeRequest.defaultSquashCommitMessage;
+ this.loading = false;
+ },
+ },
+ },
components: {
statusIcon,
SquashBeforeMerge,
@@ -48,6 +78,7 @@ export default {
GlButtonGroup,
GlDropdown,
GlDropdownItem,
+ GlSkeletonLoader,
MergeTrainHelperText: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_text.vue'),
MergeImmediatelyConfirmationDialog: () =>
@@ -58,13 +89,15 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [readyToMergeMixin],
+ mixins: [readyToMergeMixin, glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
mr: { type: Object, required: true },
service: { type: Object, required: true },
},
data() {
return {
+ loading: this.glFeatures.mergeRequestWidgetGraphql,
+ state: {},
removeSourceBranch: this.mr.shouldRemoveSourceBranch,
isMakingRequest: false,
isMergingImmediately: false,
@@ -75,13 +108,93 @@ export default {
};
},
computed: {
+ stateData() {
+ return this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr;
+ },
+ hasCI() {
+ return this.stateData.hasCI || this.stateData.hasCi;
+ },
isAutoMergeAvailable() {
- return !isEmpty(this.mr.availableAutoMergeStrategies);
+ return !isEmpty(this.stateData.availableAutoMergeStrategies);
+ },
+ pipeline() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.pipelines?.nodes?.[0];
+ }
+
+ return this.mr.pipeline;
+ },
+ isPipelineFailed() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return ['FAILED', 'CANCELED'].indexOf(this.pipeline?.status) !== -1;
+ }
+
+ return this.mr.isPipelineFailed;
+ },
+ isMergeAllowed() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.mergeable || false;
+ }
+
+ return this.mr.isMergeAllowed;
+ },
+ canRemoveSourceBranch() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.userPermissions.removeSourceBranch;
+ }
+
+ return this.mr.canRemoveSourceBranch;
+ },
+ commits() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.commitsWithoutMergeCommits.nodes;
+ }
+
+ return this.mr.commits;
+ },
+ commitsCount() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.state.commitCount || 0;
+ }
+
+ return this.mr.commitsCount;
+ },
+ preferredAutoMergeStrategy() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return MergeRequestStore.getPreferredAutoMergeStrategy(
+ this.state.availableAutoMergeStrategies,
+ );
+ }
+
+ return this.mr.preferredAutoMergeStrategy;
+ },
+ isSHAMismatch() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.mr.sha !== this.state.diffHeadSha;
+ }
+
+ return this.mr.isSHAMismatch;
+ },
+ squashIsSelected() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.squashReadOnly ? this.state.squashOnMerge : this.state.squash;
+ }
+
+ return this.mr.squashIsSelected;
+ },
+ isPipelineActive() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return this.pipeline?.active || false;
+ }
+
+ return this.mr.isPipelineActive;
},
status() {
- const { pipeline, isPipelineFailed, hasCI, ciStatus } = this.mr;
+ const ciStatus = this.glFeatures.mergeRequestWidgetGraphql
+ ? this.pipeline?.status.toLowerCase()
+ : this.mr.ciStatus;
- if ((hasCI && !ciStatus) || this.hasPipelineMustSucceedConflict) {
+ if ((this.hasCI && !ciStatus) || this.hasPipelineMustSucceedConflict) {
return PIPELINE_FAILED_STATE;
}
@@ -89,7 +202,7 @@ export default {
return PIPELINE_PENDING_STATE;
}
- if (pipeline && isPipelineFailed) {
+ if (this.pipeline && this.isPipelineFailed) {
return PIPELINE_FAILED_STATE;
}
@@ -114,7 +227,7 @@ export default {
if (
this.status === PIPELINE_FAILED_STATE ||
!this.commitMessage.length ||
- !this.mr.isMergeAllowed ||
+ !this.isMergeAllowed ||
this.mr.preventMerge
) {
return WARNING;
@@ -133,27 +246,31 @@ export default {
return __('Merge');
},
hasPipelineMustSucceedConflict() {
- return !this.mr.hasCI && this.mr.onlyAllowMergeIfPipelineSucceeds;
+ return !this.hasCI && this.stateData.onlyAllowMergeIfPipelineSucceeds;
},
isRemoveSourceBranchButtonDisabled() {
return this.isMergeButtonDisabled;
},
shouldShowSquashBeforeMerge() {
- const { commitsCount, enableSquashBeforeMerge, squashIsReadonly, squashIsSelected } = this.mr;
+ const { enableSquashBeforeMerge } = this.mr;
- if (squashIsReadonly && !squashIsSelected) {
+ if (this.isSquashReadOnly && !this.squashIsSelected) {
return false;
}
- return enableSquashBeforeMerge && commitsCount > 1;
+ return enableSquashBeforeMerge && this.commitsCount > 1;
},
shouldShowMergeControls() {
- return this.mr.isMergeAllowed || this.isAutoMergeAvailable;
+ return this.isMergeAllowed || this.isAutoMergeAvailable;
},
shouldShowSquashEdit() {
return this.squashBeforeMerge && this.shouldShowSquashBeforeMerge;
},
shouldShowMergeEdit() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ return !this.state.mergeRequestsFfOnlyEnabled;
+ }
+
return !this.mr.ffOnlyEnabled;
},
shaMismatchLink() {
@@ -162,18 +279,26 @@ export default {
},
methods: {
updateMergeCommitMessage(includeDescription) {
- const { commitMessageWithDescription, commitMessage } = this.mr;
+ const commitMessage = this.glFeatures.mergeRequestWidgetGraphql
+ ? this.state.defaultMergeCommitMessage
+ : this.mr.commitMessage;
+ const commitMessageWithDescription = this.glFeatures.mergeRequestWidgetGraphql
+ ? this.state.defaultMergeCommitMessageWithDescription
+ : this.mr.commitMessageWithDescription;
this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage;
},
handleMergeButtonClick(useAutoMerge, mergeImmediately = false) {
if (mergeImmediately) {
this.isMergingImmediately = true;
}
+ const latestSha = this.glFeatures.mergeRequestWidgetGraphql
+ ? this.state.diffHeadSha
+ : this.mr.latestSHA;
const options = {
- sha: this.mr.latestSHA || this.mr.sha,
+ sha: latestSha || this.mr.sha,
commit_message: this.commitMessage,
- auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined,
+ auto_merge_strategy: useAutoMerge ? this.preferredAutoMergeStrategy : undefined,
should_remove_source_branch: this.removeSourceBranch === true,
squash: this.squashBeforeMerge,
};
@@ -188,8 +313,8 @@ export default {
this.isMakingRequest = true;
this.service
.merge(options)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
const hasError =
data.status === MERGE_FAILED_STATUS ||
data.status === MERGE_HOOK_VALIDATION_ERROR_STATUS;
@@ -228,8 +353,8 @@ export default {
handleMergePolling(continuePolling, stopPolling) {
this.service
.poll()
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
if (data.state === 'merged') {
// If state is merged we should update the widget and stop the polling
eventHub.$emit('MRWidgetUpdateRequested');
@@ -270,8 +395,8 @@ export default {
handleRemoveBranchPolling(continuePolling, stopPolling) {
this.service
.poll()
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
// If source branch exists then we should continue polling
// because removing a source branch is a background task and takes time
if (data.source_branch_exists) {
@@ -294,156 +419,168 @@ export default {
<template>
<div>
- <div class="mr-widget-body media" :class="{ 'gl-pb-3': shouldRenderMergeTrainHelperText }">
- <status-icon :status="iconClass" />
- <div class="media-body">
- <div class="mr-widget-body-controls media space-children">
- <gl-button-group>
- <gl-button
- size="medium"
- category="primary"
- class="qa-merge-button accept-merge-request"
- :variant="mergeButtonVariant"
- :disabled="isMergeButtonDisabled"
- :loading="isMakingRequest"
- @click="handleMergeButtonClick(isAutoMergeAvailable)"
- >{{ mergeButtonText }}</gl-button
- >
- <gl-dropdown
- v-if="shouldShowMergeImmediatelyDropdown"
- v-gl-tooltip.hover.focus="__('Select merge moment')"
- :disabled="isMergeButtonDisabled"
- variant="info"
- data-qa-selector="merge_moment_dropdown"
- toggle-class="btn-icon js-merge-moment"
- >
- <template #button-content>
- <gl-icon name="chevron-down" class="mr-0" />
- <span class="sr-only">{{ __('Select merge moment') }}</span>
- </template>
- <gl-dropdown-item
- icon-name="warning"
- button-class="accept-merge-request js-merge-immediately-button"
- data-qa-selector="merge_immediately_option"
- @click="handleMergeImmediatelyButtonClick"
+ <div v-if="loading" class="mr-widget-body">
+ <div class="gl-w-full mr-ready-to-merge-loader">
+ <gl-skeleton-loader :width="418" :height="30">
+ <rect x="0" y="3" width="24" height="24" rx="4" />
+ <rect x="32" y="0" width="70" height="30" rx="4" />
+ <rect x="110" y="7" width="150" height="16" rx="4" />
+ <rect x="268" y="7" width="150" height="16" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ </div>
+ <template v-else>
+ <div class="mr-widget-body media" :class="{ 'gl-pb-3': shouldRenderMergeTrainHelperText }">
+ <status-icon :status="iconClass" />
+ <div class="media-body">
+ <div class="mr-widget-body-controls media space-children">
+ <gl-button-group>
+ <gl-button
+ size="medium"
+ category="primary"
+ class="qa-merge-button accept-merge-request"
+ :variant="mergeButtonVariant"
+ :disabled="isMergeButtonDisabled"
+ :loading="isMakingRequest"
+ @click="handleMergeButtonClick(isAutoMergeAvailable)"
+ >{{ mergeButtonText }}</gl-button
>
- {{ __('Merge immediately') }}
- </gl-dropdown-item>
- <merge-immediately-confirmation-dialog
- ref="confirmationDialog"
- :docs-url="mr.mergeImmediatelyDocsPath"
- @mergeImmediately="onMergeImmediatelyConfirmation"
- />
- </gl-dropdown>
- </gl-button-group>
- <div class="media-body-wrap space-children">
- <template v-if="shouldShowMergeControls">
- <label v-if="mr.canRemoveSourceBranch">
- <input
- id="remove-source-branch-input"
- v-model="removeSourceBranch"
- :disabled="isRemoveSourceBranchButtonDisabled"
- class="js-remove-source-branch-checkbox"
- type="checkbox"
+ <gl-dropdown
+ v-if="shouldShowMergeImmediatelyDropdown"
+ v-gl-tooltip.hover.focus="__('Select merge moment')"
+ :disabled="isMergeButtonDisabled"
+ variant="info"
+ data-qa-selector="merge_moment_dropdown"
+ toggle-class="btn-icon js-merge-moment"
+ >
+ <template #button-content>
+ <gl-icon name="chevron-down" class="mr-0" />
+ <span class="sr-only">{{ __('Select merge moment') }}</span>
+ </template>
+ <gl-dropdown-item
+ icon-name="warning"
+ button-class="accept-merge-request js-merge-immediately-button"
+ data-qa-selector="merge_immediately_option"
+ @click="handleMergeImmediatelyButtonClick"
+ >
+ {{ __('Merge immediately') }}
+ </gl-dropdown-item>
+ <merge-immediately-confirmation-dialog
+ ref="confirmationDialog"
+ :docs-url="mr.mergeImmediatelyDocsPath"
+ @mergeImmediately="onMergeImmediatelyConfirmation"
/>
- {{ __('Delete source branch') }}
- </label>
+ </gl-dropdown>
+ </gl-button-group>
+ <div class="media-body-wrap space-children">
+ <template v-if="shouldShowMergeControls">
+ <label v-if="canRemoveSourceBranch">
+ <input
+ id="remove-source-branch-input"
+ v-model="removeSourceBranch"
+ :disabled="isRemoveSourceBranchButtonDisabled"
+ class="js-remove-source-branch-checkbox"
+ type="checkbox"
+ />
+ {{ __('Delete source branch') }}
+ </label>
- <!-- Placeholder for EE extension of this component -->
- <squash-before-merge
- v-if="shouldShowSquashBeforeMerge"
- v-model="squashBeforeMerge"
- :help-path="mr.squashBeforeMergeHelpPath"
- :is-disabled="isSquashReadOnly"
- />
- </template>
- <template v-else>
- <div class="bold js-resolve-mr-widget-items-message">
- <div
- v-if="hasPipelineMustSucceedConflict"
- class="gl-display-flex gl-align-items-center"
- data-testid="pipeline-succeed-conflict"
- >
- <gl-sprintf :message="pipelineMustSucceedConflictText" />
- <gl-link
- :href="mr.pipelineMustSucceedDocsPath"
- target="_blank"
- class="gl-display-flex gl-ml-2"
+ <!-- Placeholder for EE extension of this component -->
+ <squash-before-merge
+ v-if="shouldShowSquashBeforeMerge"
+ v-model="squashBeforeMerge"
+ :help-path="mr.squashBeforeMergeHelpPath"
+ :is-disabled="isSquashReadOnly"
+ />
+ </template>
+ <template v-else>
+ <div class="bold js-resolve-mr-widget-items-message">
+ <div
+ v-if="hasPipelineMustSucceedConflict"
+ class="gl-display-flex gl-align-items-center"
+ data-testid="pipeline-succeed-conflict"
>
- <gl-icon name="question" />
- </gl-link>
+ <gl-sprintf :message="pipelineMustSucceedConflictText" />
+ <gl-link
+ :href="mr.pipelineMustSucceedDocsPath"
+ target="_blank"
+ class="gl-display-flex gl-ml-2"
+ >
+ <gl-icon name="question" />
+ </gl-link>
+ </div>
+ <gl-sprintf v-else :message="mergeDisabledText" />
</div>
- <gl-sprintf v-else :message="mergeDisabledText" />
- </div>
- </template>
- </div>
- </div>
- <div v-if="mr.isSHAMismatch" class="d-flex align-items-center mt-2 js-sha-mismatch">
- <gl-icon name="warning-solid" class="text-warning mr-1" />
- <span class="text-warning">
- <gl-sprintf
- :message="
- __('New changes were added. %{linkStart}Reload the page to review them%{linkEnd}')
- "
- >
- <template #link="{ content }">
- <gl-link :href="mr.mergeRequestDiffsPath">{{ content }}</gl-link>
</template>
- </gl-sprintf>
- </span>
+ </div>
+ </div>
+ <div v-if="isSHAMismatch" class="d-flex align-items-center mt-2 js-sha-mismatch">
+ <gl-icon name="warning-solid" class="text-warning mr-1" />
+ <span class="text-warning">
+ <gl-sprintf
+ :message="
+ __('New changes were added. %{linkStart}Reload the page to review them%{linkEnd}')
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="mr.mergeRequestDiffsPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ </div>
</div>
</div>
- </div>
- <merge-train-helper-text
- v-if="shouldRenderMergeTrainHelperText"
- :pipeline-id="mr.pipeline.id"
- :pipeline-link="mr.pipeline.path"
- :merge-train-length="mr.mergeTrainsCount"
- :merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
- />
- <template v-if="shouldShowMergeControls">
- <div v-if="mr.ffOnlyEnabled" class="mr-fast-forward-message">
- {{ __('Fast-forward merge without a merge commit') }}
- </div>
- <commits-header
- v-if="shouldShowSquashEdit || shouldShowMergeEdit"
- :is-squash-enabled="squashBeforeMerge"
- :commits-count="mr.commitsCount"
- :target-branch="mr.targetBranch"
- :is-fast-forward-enabled="mr.ffOnlyEnabled"
- :class="{ 'border-bottom': mr.mergeError }"
- >
- <ul class="border-top content-list commits-list flex-list">
- <commit-edit
- v-if="shouldShowSquashEdit"
- v-model="squashCommitMessage"
- :label="__('Squash commit message')"
- input-id="squash-message-edit"
- squash
- >
- <commit-message-dropdown
- slot="header"
+ <merge-train-helper-text
+ v-if="shouldRenderMergeTrainHelperText"
+ :pipeline-id="pipeline.id"
+ :pipeline-link="pipeline.path"
+ :merge-train-length="stateData.mergeTrainsCount"
+ :merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
+ />
+ <template v-if="shouldShowMergeControls">
+ <div v-if="!shouldShowMergeEdit" class="mr-fast-forward-message">
+ {{ __('Fast-forward merge without a merge commit') }}
+ </div>
+ <commits-header
+ v-if="shouldShowSquashEdit || shouldShowMergeEdit"
+ :is-squash-enabled="squashBeforeMerge"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :class="{ 'border-bottom': stateData.mergeError }"
+ >
+ <ul class="border-top content-list commits-list flex-list">
+ <commit-edit
+ v-if="shouldShowSquashEdit"
v-model="squashCommitMessage"
- :commits="mr.commits"
- />
- </commit-edit>
- <commit-edit
- v-if="shouldShowMergeEdit"
- v-model="commitMessage"
- :label="__('Merge commit message')"
- input-id="merge-message-edit"
- >
- <label slot="checkbox">
- <input
- id="include-description"
- type="checkbox"
- @change="updateMergeCommitMessage($event.target.checked)"
+ :label="__('Squash commit message')"
+ input-id="squash-message-edit"
+ squash
+ >
+ <commit-message-dropdown
+ slot="header"
+ v-model="squashCommitMessage"
+ :commits="commits"
/>
- {{ __('Include merge request description') }}
- </label>
- </commit-edit>
- </ul>
- </commits-header>
+ </commit-edit>
+ <commit-edit
+ v-if="shouldShowMergeEdit"
+ v-model="commitMessage"
+ :label="__('Merge commit message')"
+ input-id="merge-message-edit"
+ >
+ <label slot="checkbox">
+ <input
+ id="include-description"
+ type="checkbox"
+ @change="updateMergeCommitMessage($event.target.checked)"
+ />
+ {{ __('Include merge request description') }}
+ </label>
+ </commit-edit>
+ </ul>
+ </commits-header>
+ </template>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
index 1c9909e7178..12fdfe601a4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -46,7 +46,7 @@ export default {
name="squash"
class="qa-squash-checkbox js-squash-checkbox gl-mb-0 gl-mr-2"
:title="tooltipTitle"
- @change="checked => $emit('input', checked)"
+ @change="(checked) => $emit('input', checked)"
>
{{ $options.i18n.checkboxLabel }}
</gl-form-checkbox>
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 1d591168a17..3f1db815f95 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
@@ -29,7 +29,7 @@ export default {
variables() {
return this.mergeRequestQueryVariables;
},
- update: data => data.project.mergeRequest.userPermissions,
+ update: (data) => data.project.mergeRequest.userPermissions,
},
},
props: {
@@ -86,7 +86,7 @@ export default {
variables: mergeRequestQueryVariables,
});
- const data = produce(sourceData, draftState => {
+ const data = produce(sourceData, (draftState) => {
// eslint-disable-next-line no-param-reassign
draftState.project.mergeRequest.workInProgress = workInProgress;
// eslint-disable-next-line no-param-reassign
@@ -113,10 +113,18 @@ export default {
},
},
})
- .then(({ data: { mergeRequestSetWip: { mergeRequest: { title } } } }) => {
- createFlash(__('The merge request can now be merged.'), 'notice');
- $('.merge-request .detail-page-description .title').text(title);
- })
+ .then(
+ ({
+ data: {
+ mergeRequestSetWip: {
+ mergeRequest: { title },
+ },
+ },
+ }) => {
+ createFlash(__('The merge request can now be merged.'), 'notice');
+ $('.merge-request .detail-page-description .title').text(title);
+ },
+ )
.catch(() => createFlash(__('Something went wrong. Please try again.')))
.finally(() => {
this.isMakingRequest = false;
@@ -129,8 +137,8 @@ export default {
this.isMakingRequest = true;
this.service
.removeWIP()
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
eventHub.$emit('UpdateWidgetData', data);
MergeRequest.toggleDraftStatus(this.mr.title, true);
})
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 4de41dd5887..180db7828a8 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
@@ -40,7 +40,7 @@ export default {
);
},
numberOfInvalidPlans() {
- return Object.values(this.plansObject).filter(plan => plan.tf_report_error).length;
+ return Object.values(this.plansObject).filter((plan) => plan.tf_report_error).length;
},
numberOfPlans() {
return Object.keys(this.plansObject).length;
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
index 2d21ced1b28..6c6f5e7fc73 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -38,7 +38,7 @@ export default {
.query({ query: issuesQuery, variables: { projectPath: targetProjectFullPath } })
.then(({ data }) => {
// Return some transformed data to be rendered in the expanded state
- return data.project.issues.nodes.map(issue => ({
+ return data.project.issues.nodes.map((issue) => ({
id: issue.id, // Required: The ID of the object
text: issue.title, // Required: The text to get used on each row
// Icon to get rendered on the side of each row
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index 8f2cca3309a..d512877a20d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -26,7 +26,11 @@ export default () => {
registerExtension(issueExtension);
- const vm = new Vue({ ...MrWidgetOptions, apolloProvider });
+ const vm = new Vue({
+ el: '#js-vue-mr-widget',
+ ...MrWidgetOptions,
+ apolloProvider,
+ });
window.gl.mrWidget = {
checkStatus: vm.checkStatus,
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js b/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js
index e50555ca875..943011949fd 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/approvals.js
@@ -11,7 +11,7 @@ export default {
}
},
refreshApprovals() {
- return this.service.fetchApprovals().then(data => {
+ return this.service.fetchApprovals().then((data) => {
this.mr.setApprovals(data);
});
},
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 dc8a6b56d58..fe512d68ea2 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
@@ -27,7 +27,7 @@ export default {
return __('Merge when pipeline succeeds');
},
shouldShowMergeImmediatelyDropdown() {
- return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds;
+ return this.isPipelineActive && !this.stateData.onlyAllowMergeIfPipelineSucceeds;
},
isMergeImmediatelyDangerous() {
return false;
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 3f1f2144d8e..519576d9fe6 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
@@ -43,12 +43,11 @@ import SourceBranchRemovalStatus from './components/source_branch_removal_status
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/common_utils';
+import { setFaviconOverlay } from '../lib/utils/favicon';
import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
import getStateQuery from './queries/get_state.query.graphql';
export default {
- el: '#js-vue-mr-widget',
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'MRWidget',
@@ -166,7 +165,8 @@ export default {
return (
!this.mr.canRemoveSourceBranch &&
this.mr.shouldRemoveSourceBranch &&
- (!this.mr.isNothingToMergeState && !this.mr.isMergedState)
+ !this.mr.isNothingToMergeState &&
+ !this.mr.isMergedState
);
},
shouldRenderCollaborationStatus() {
@@ -190,9 +190,13 @@ export default {
mergeError = mergeError.slice(0, -1);
}
- return sprintf(s__('mrWidget|Merge failed: %{mergeError}. Please try again.'), {
- mergeError,
- });
+ return sprintf(
+ s__('mrWidget|Merge failed: %{mergeError}. Please try again.'),
+ {
+ mergeError,
+ },
+ false,
+ );
},
shouldShowAccessibilityReport() {
return this.mr.accessibilityReportPath;
@@ -306,8 +310,7 @@ export default {
callback: this.checkStatus,
startingInterval: this.startingPollInterval,
maxInterval: this.startingPollInterval + secondsToMilliseconds(4 * 60),
- hiddenInterval:
- window.gon?.features?.widgetVisibilityPolling && secondsToMilliseconds(6 * 60),
+ hiddenInterval: secondsToMilliseconds(6 * 60),
incrementByFactorOf: 2,
});
},
@@ -357,7 +360,7 @@ export default {
fetchActionsContent() {
this.service
.fetchMergeActionsContent()
- .then(res => {
+ .then((res) => {
if (res.data) {
const el = document.createElement('div');
el.innerHTML = res.data;
@@ -387,26 +390,26 @@ export default {
this.pollingInterval.stopTimer();
},
bindEventHubListeners() {
- eventHub.$on('MRWidgetUpdateRequested', cb => {
+ eventHub.$on('MRWidgetUpdateRequested', (cb) => {
this.checkStatus(cb);
});
- eventHub.$on('MRWidgetRebaseSuccess', cb => {
+ eventHub.$on('MRWidgetRebaseSuccess', (cb) => {
this.checkStatus(cb, true);
});
// `params` should be an Array contains a Boolean, like `[true]`
// Passing parameter as Boolean didn't work.
- eventHub.$on('SetBranchRemoveFlag', params => {
+ eventHub.$on('SetBranchRemoveFlag', (params) => {
[this.mr.isRemovingSourceBranch] = params;
});
- eventHub.$on('FailedToMerge', mergeError => {
+ eventHub.$on('FailedToMerge', (mergeError) => {
this.mr.state = 'failedToMerge';
this.mr.mergeError = mergeError;
});
- eventHub.$on('UpdateWidgetData', data => {
+ eventHub.$on('UpdateWidgetData', (data) => {
this.mr.setData(data);
});
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
new file mode 100644
index 00000000000..64cd70fcf42
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
@@ -0,0 +1,15 @@
+fragment autoMergeEnabled on MergeRequest {
+ autoMergeStrategy
+ mergeUser {
+ name
+ username
+ webUrl
+ avatarUrl
+ }
+ targetBranch
+ shouldRemoveSourceBranch
+ forceRemoveSourceBranch
+ userPermissions {
+ removeSourceBranch
+ }
+}
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
new file mode 100644
index 00000000000..bdcb7a8206b
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
@@ -0,0 +1,10 @@
+#import "./auto_merge_enabled.fragment.graphql"
+
+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/auto_merge_failed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql
new file mode 100644
index 00000000000..2fe0d174b67
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql
@@ -0,0 +1,7 @@
+query autoMergeFailedQuery($projectPath: ID!, $iid: String!) {
+ project(fullPath: $projectPath) {
+ mergeRequest(iid: $iid) {
+ mergeError
+ }
+ }
+}
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
new file mode 100644
index 00000000000..9479ef3cf79
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
@@ -0,0 +1,41 @@
+fragment ReadyToMerge on Project {
+ onlyAllowMergeIfPipelineSucceeds
+ mergeRequestsFfOnlyEnabled
+ squashReadOnly
+ mergeRequest(iid: $iid) {
+ autoMergeEnabled
+ shouldRemoveSourceBranch
+ defaultMergeCommitMessage
+ defaultMergeCommitMessageWithDescription
+ defaultSquashCommitMessage
+ squash
+ squashOnMerge
+ availableAutoMergeStrategies
+ hasCi
+ mergeable
+ mergeWhenPipelineSucceeds
+ commitCount
+ diffHeadSha
+ userPermissions {
+ removeSourceBranch
+ }
+ targetBranch
+ mergeError
+ commitsWithoutMergeCommits {
+ nodes {
+ sha
+ shortId
+ title
+ message
+ }
+ }
+ pipelines(first: 1) {
+ nodes {
+ id
+ status
+ path
+ active
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
new file mode 100644
index 00000000000..78259e1f553
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
@@ -0,0 +1,7 @@
+#import "./ready_to_merge.fragment.graphql"
+
+query readyToMergeQuery($projectPath: ID!, $iid: String!) {
+ project(fullPath: $projectPath) {
+ ...ReadyToMerge
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql
new file mode 100644
index 00000000000..a8c7d2610bf
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql
@@ -0,0 +1,11 @@
+query rebaseQuery($projectPath: ID!, $iid: String!) {
+ project(fullPath: $projectPath) {
+ mergeRequest(iid: $iid) {
+ rebaseInProgress
+ targetBranch
+ userPermissions {
+ pushToSourceBranch
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js b/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
index 2ad15f231bb..7dcb4881e7f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
+++ b/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
@@ -60,15 +60,15 @@ export default class MRWidgetService {
}
fetchApprovals() {
- return axios.get(this.apiApprovalsPath).then(res => res.data);
+ return axios.get(this.apiApprovalsPath).then((res) => res.data);
}
approveMergeRequest() {
- return axios.post(this.apiApprovePath).then(res => res.data);
+ return axios.post(this.apiApprovePath).then((res) => res.data);
}
unapproveMergeRequest() {
- return axios.post(this.apiUnapprovePath).then(res => res.data);
+ return axios.post(this.apiUnapprovePath).then((res) => res.data);
}
static executeInlineAction(url) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/getters.js b/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/getters.js
index 15d67ea18ea..7740147c8e4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/getters.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/getters.js
@@ -1,6 +1,6 @@
import { s__, n__ } from '~/locale';
-export const title = state => {
+export const title = (state) => {
if (state.isLoading) {
return s__('BuildArtifacts|Loading artifacts');
}
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 f8abbc99f0f..e6cb5ead089 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
@@ -7,10 +7,11 @@ import state from './state';
Vue.use(Vuex);
-export default () =>
- new Vuex.Store({
- actions,
- mutations,
- getters,
- state: state(),
- });
+export const getStoreConfig = () => ({
+ actions,
+ mutations,
+ getters,
+ state: state(),
+});
+
+export default () => new Vuex.Store(getStoreConfig());
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 f50b6caf0f5..a6bbab47a06 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,5 +1,6 @@
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';
@@ -154,6 +155,10 @@ export default class MergeRequestStore {
this.canRevertInCurrentMR = currentUser.can_revert_on_current_merge_request || false;
this.setState();
+
+ mrEventHub.$emit('mr.state.updated', {
+ state: this.mergeRequestState,
+ });
}
setGraphqlData(project) {
@@ -167,7 +172,7 @@ export default class MergeRequestStore {
this.canBeMerged = mergeRequest.mergeStatus === 'can_be_merged';
this.canMerge = mergeRequest.userPermissions.canMerge;
this.ciStatus = pipeline?.status.toLowerCase();
- this.commitsCount = mergeRequest.commitCount;
+ this.commitsCount = mergeRequest.commitCount || 10;
this.branchMissing = !mergeRequest.sourceBranchExists || !mergeRequest.targetBranchExists;
this.hasConflicts = mergeRequest.conflicts;
this.hasMergeableDiscussionsState = mergeRequest.mergeableDiscussionsState === false;
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue
index cb4c5f20377..2dc2c27f7ea 100644
--- a/app/assets/javascripts/vue_shared/components/actions_button.vue
+++ b/app/assets/javascripts/vue_shared/components/actions_button.vue
@@ -43,7 +43,7 @@ export default {
return this.actions.length > 1;
},
selectedAction() {
- return this.actions.find(x => x.key === this.selectedKey) || this.actions[0];
+ return this.actions.find((x) => x.key === this.selectedKey) || this.actions[0];
},
},
methods: {
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 3e2b4cd35ab..655b867574d 100644
--- a/app/assets/javascripts/vue_shared/components/alert_details_table.vue
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -49,7 +49,8 @@ export default {
label: s__('AlertManagement|Key'),
thClass,
tdClass,
- formatter: string => capitalizeFirstCharacter(convertToSentenceCase(splitCamelCase(string))),
+ formatter: (string) =>
+ capitalizeFirstCharacter(convertToSentenceCase(splitCamelCase(string))),
},
{
key: 'value',
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index 9a6433963bc..c1da2b8c305 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -48,7 +48,7 @@ export default {
groupedAwards() {
const { thumbsup, thumbsdown, ...rest } = {
...this.groupedDefaultAwards,
- ...groupBy(this.awards, x => x.name),
+ ...groupBy(this.awards, (x) => x.name),
};
return [
@@ -73,7 +73,7 @@ export default {
return false;
}
- return awardList.some(award => award.user.id === this.currentUserId);
+ return awardList.some((award) => award.user.id === this.currentUserId);
},
createAwardList(name, list) {
return {
@@ -95,11 +95,11 @@ export default {
// Filter myself from list if I am awarded.
if (hasReactionByCurrentUser) {
- awardList = awardList.filter(award => award.user.id !== this.currentUserId);
+ awardList = awardList.filter((award) => award.user.id !== this.currentUserId);
}
// Get only 9-10 usernames to show in tooltip text.
- const namesToShow = awardList.slice(0, TOOLTIP_NAME_COUNT).map(award => award.user.name);
+ const namesToShow = awardList.slice(0, TOOLTIP_NAME_COUNT).map((award) => award.user.name);
// Get the remaining list to use in `and x more` text.
const remainingAwardList = awardList.slice(TOOLTIP_NAME_COUNT, awardList.length);
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
index f28e49df56e..14e99977a85 100644
--- a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -79,6 +79,8 @@ export default {
:title="tooltipTitle"
:class="{ 'ml-auto': isCentered }"
class="file-changed-icon d-inline-block"
+ data-qa-selector="changed_file_icon_content"
+ :data-qa-title="tooltipTitle"
>
<gl-icon v-if="showIcon" :name="changedIcon" :size="size" :class="changedIconClass" />
</span>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index e01a651806d..deca934e283 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -54,7 +54,7 @@ export default {
type: Object,
required: false,
default: undefined,
- validator: ref =>
+ validator: (ref) =>
ref === undefined || (Number.isFinite(ref.iid) && isString(ref.path) && !isEmpty(ref.path)),
},
@@ -107,7 +107,7 @@ export default {
},
computed: {
/**
- * Determines if we shoud render the ref info section based
+ * Determines if we should render the ref info section based
*/
shouldShowRefInfo() {
return this.showRefInfo && (this.commitRef || this.mergeRequestRef);
diff --git a/app/assets/javascripts/vue_shared/components/confirm_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
index 96f800511d2..7c1d3772acd 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
@@ -30,8 +30,8 @@ export default {
};
},
mounted() {
- document.querySelectorAll(this.selector).forEach(button => {
- button.addEventListener('click', e => {
+ document.querySelectorAll(this.selector).forEach((button) => {
+ button.addEventListener('click', (e) => {
e.preventDefault();
this.path = button.dataset.path;
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 5ac30424f98..9ff35132ac9 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
@@ -11,7 +11,7 @@ export default {
},
props: {
content: {
- type: String,
+ type: [String, ArrayBuffer],
default: '',
required: false,
},
@@ -54,7 +54,7 @@ export default {
</script>
<template>
- <div class="preview-container">
+ <div class="preview-container" data-qa-selector="preview_container">
<image-viewer v-if="type === 'image'" :path="path" :file-size="fileSize" />
<markdown-viewer
v-if="type === 'markdown'"
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
index 8d55701f499..af85a2fda06 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
@@ -39,11 +39,16 @@ export default {
<div class="file-content">
<p class="gl-mt-3 file-info">
{{ fileName }}
- <template v-if="fileSize > 0">
- ({{ fileSizeReadable }})
- </template>
+ <template v-if="fileSize > 0"> ({{ fileSizeReadable }}) </template>
</p>
- <a :href="path" class="btn btn-default" rel="nofollow" :download="fileName" target="_blank">
+ <a
+ :href="path"
+ class="btn btn-default"
+ rel="nofollow"
+ :download="fileName"
+ target="_blank"
+ data-qa-selector="download_button"
+ >
<gl-icon :size="16" name="download" class="float-left gl-mr-3" />
{{ __('Download') }}
</a>
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 eb7e24734ce..9ece6a52805 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
@@ -82,7 +82,7 @@ export default {
</script>
<template>
- <div data-testid="image-viewer">
+ <div data-testid="image-viewer" data-qa-selector="image_viewer_container">
<div :class="innerCssClasses" class="position-relative">
<img ref="contentImg" :src="path" @load="onImgLoad" />
<slot
@@ -95,9 +95,7 @@ export default {
<template v-if="hasFileSize">
{{ fileSizeReadable }}
</template>
- <template v-if="hasFileSize && hasDimensions">
- |
- </template>
+ <template v-if="hasFileSize && hasDimensions"> | </template>
<template v-if="hasDimensions">
<strong>{{ s__('ImageViewerDimensions|W') }}</strong
>: {{ width }} | <strong>{{ s__('ImageViewerDimensions|H') }}</strong
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 67be76604a3..24386c90954 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
@@ -111,6 +111,6 @@ export default {
<template>
<div ref="markdownPreview" class="md-previewer" data-testid="md-previewer">
<gl-skeleton-loading v-if="isLoading" />
- <div v-else class="md" v-html="previewContent"></div>
+ <div v-else class="md gl-ml-auto gl-mr-auto" v-html="previewContent"></div>
</div>
</template>
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 79cdf308ac5..d0c2672b162 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
@@ -202,7 +202,7 @@ export default {
<template>
<tooltip-on-truncate
:title="timeWindowText"
- :truncate-target="elem => elem.querySelector('.gl-dropdown-toggle-text')"
+ :truncate-target="(elem) => elem.querySelector('.gl-dropdown-toggle-text')"
placement="top"
class="d-inline-block"
>
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 32a24844d71..39c1caf928e 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
@@ -20,12 +20,12 @@ export default {
state: {
default: null,
required: true,
- validator: prop => typeof prop === 'boolean' || prop === null,
+ validator: (prop) => typeof prop === 'boolean' || prop === null,
},
value: {
default: null,
required: false,
- validator: prop => typeof prop === 'string' || prop === null,
+ validator: (prop) => typeof prop === 'string' || prop === null,
},
label: {
type: String,
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js
index aaadc9766db..aec67a18a05 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js
@@ -25,7 +25,7 @@ export const defaultTimeRanges = [
},
];
-export const defaultTimeRange = defaultTimeRanges.find(tr => tr.default);
+export const defaultTimeRange = defaultTimeRanges.find((tr) => tr.default);
export const dateFormats = {
/**
@@ -49,7 +49,7 @@ export const dateFormats = {
* @param {string} value - Value as typed by the user
* @returns true if the value can be parsed as a valid date, false otherwise
*/
-export const isValidInputString = value => {
+export const isValidInputString = (value) => {
try {
// dateformat throws error that can be caught.
// This is better than using `new Date()`
diff --git a/app/assets/javascripts/vue_shared/components/deployment_instance.vue b/app/assets/javascripts/vue_shared/components/deployment_instance.vue
new file mode 100644
index 00000000000..41b783aa011
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/deployment_instance.vue
@@ -0,0 +1,91 @@
+<script>
+/**
+ * An instance in deploy board is represented by a square in this mockup:
+ * https://gitlab.com/gitlab-org/gitlab-foss/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png
+ *
+ * Each instance has a state and a tooltip.
+ * The state needs to be represented in different colors,
+ * see more information about this in
+ * https://gitlab.com/gitlab-org/gitlab/uploads/f1f00df6293d30f241dbeaa876a1e939/Screen_Shot_2019-11-26_at_3.35.43_PM.png
+ *
+ * An instance can represent a normal deploy or a canary deploy. In the latter we need to provide
+ * this information in the tooltip and the colors.
+ * Mockup is https://gitlab.com/gitlab-org/gitlab/issues/35570
+ */
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+
+export default {
+ components: {
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+
+ props: {
+ /**
+ * Represents the status of the pod. Each state is represented with a different
+ * color.
+ * It should be one of the following:
+ * succeeded || running || failed || pending || unknown
+ */
+ status: {
+ type: String,
+ required: true,
+ default: 'succeeded',
+ },
+
+ tooltipText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+
+ stable: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+
+ podName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+
+ logsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+
+ computed: {
+ isLink() {
+ return this.logsPath !== '' && this.podName !== '';
+ },
+
+ cssClass() {
+ return {
+ [`deployment-instance-${this.status}`]: true,
+ 'deployment-instance-canary': !this.stable,
+ link: this.isLink,
+ };
+ },
+
+ computedLogPath() {
+ return this.isLink ? mergeUrlParams({ pod_name: this.podName }, this.logsPath) : null;
+ },
+ },
+};
+</script>
+<template>
+ <gl-link
+ v-gl-tooltip
+ :class="cssClass"
+ :title="tooltipText"
+ :href="computedLogPath"
+ class="deployment-instance d-flex justify-content-center align-items-center"
+ />
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue
deleted file mode 100644
index c4bce860ae4..00000000000
--- a/app/assets/javascripts/vue_shared/components/deprecated_modal_2.vue
+++ /dev/null
@@ -1,121 +0,0 @@
-<script>
-import $ from 'jquery';
-import { GlButton } from '@gitlab/ui';
-
-const buttonVariants = ['danger', 'primary', 'success', 'warning'];
-const sizeVariants = ['sm', 'md', 'lg', 'xl'];
-
-export default {
- name: 'DeprecatedModal2', // use GlModal instead
-
- components: {
- GlButton,
- },
- props: {
- id: {
- type: String,
- required: false,
- default: null,
- },
- modalSize: {
- type: String,
- required: false,
- default: 'md',
- validator: value => sizeVariants.includes(value),
- },
- headerTitleText: {
- type: String,
- required: false,
- default: '',
- },
- footerPrimaryButtonVariant: {
- type: String,
- required: false,
- default: 'primary',
- validator: value => buttonVariants.includes(value),
- },
- footerPrimaryButtonText: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- modalSizeClass() {
- return this.modalSize === 'md' ? '' : `modal-${this.modalSize}`;
- },
- },
- mounted() {
- $(this.$el)
- .on('shown.bs.modal', this.opened)
- .on('hidden.bs.modal', this.closed);
- },
- beforeDestroy() {
- $(this.$el)
- .off('shown.bs.modal', this.opened)
- .off('hidden.bs.modal', this.closed);
- },
- methods: {
- emitCancel(event) {
- this.$emit('cancel', event);
- },
- emitSubmit(event) {
- this.$emit('submit', event);
- },
- opened() {
- this.$emit('open');
- },
- closed() {
- this.$emit('closed');
- },
- },
-};
-</script>
-
-<template>
- <div :id="id" class="modal fade" tabindex="-1" role="dialog">
- <div :class="modalSizeClass" class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header gl-pr-4">
- <slot name="header">
- <h4 class="modal-title">
- <slot name="title"> {{ headerTitleText }} </slot>
- </h4>
- <gl-button
- :aria-label="s__('Modal|Close')"
- variant="default"
- category="tertiary"
- size="small"
- icon="close"
- class="js-modal-close-action"
- data-dismiss="modal"
- @click="emitCancel($event)"
- />
- </slot>
- </div>
-
- <div class="modal-body"><slot></slot></div>
-
- <div class="modal-footer">
- <slot name="footer">
- <gl-button
- class="js-modal-cancel-action qa-modal-cancel-button"
- data-dismiss="modal"
- @click="emitCancel($event)"
- >
- {{ s__('Modal|Cancel') }}
- </gl-button>
- <gl-button
- :class="`btn-${footerPrimaryButtonVariant}`"
- class="js-modal-primary-action qa-modal-primary-button"
- data-dismiss="modal"
- @click="emitSubmit($event)"
- >
- {{ footerPrimaryButtonText }}
- </gl-button>
- </slot>
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_container.vue b/app/assets/javascripts/vue_shared/components/dismissible_container.vue
index 6d5fd065751..2eaf833a6be 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_container.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_container.vue
@@ -22,7 +22,7 @@ export default {
.post(this.path, {
feature_name: this.featureId,
})
- .catch(e => {
+ .catch((e) => {
// eslint-disable-next-line @gitlab/require-i18n-strings, no-console
console.error('Failed to dismiss message.', e);
});
diff --git a/app/assets/javascripts/vue_shared/components/editor_lite.vue b/app/assets/javascripts/vue_shared/components/editor_lite.vue
index cfe3ce0a11c..7218b84cf8a 100644
--- a/app/assets/javascripts/vue_shared/components/editor_lite.vue
+++ b/app/assets/javascripts/vue_shared/components/editor_lite.vue
@@ -84,6 +84,9 @@ export default {
onFileChange() {
this.$emit('input', this.editor.getValue());
},
+ getEditor() {
+ return this.editor;
+ },
},
};
</script>
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 05403b38850..27933f87929 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/index.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
@@ -128,7 +128,7 @@ export default {
this.focusedIndex = 0;
}
- Mousetrap.bind(['t', 'mod+p'], e => {
+ Mousetrap.bind(['t', 'mod+p'], (e) => {
if (e.preventDefault) {
e.preventDefault();
}
diff --git a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
index 91a0ac3aa92..f7cfb59be01 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
+++ b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
@@ -593,15 +593,6 @@ const fileNameIcons = {
export default function getIconForFile(name) {
return (
- fileNameIcons[name] ||
- fileExtensionIcons[
- name
- ? name
- .split('.')
- .pop()
- .toLowerCase()
- : ''
- ] ||
- ''
+ fileNameIcons[name] || fileExtensionIcons[name ? name.split('.').pop().toLowerCase() : ''] || ''
);
}
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 4d07d9fcfdd..96567111bbc 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -137,7 +137,11 @@ export default {
@click="clickFile"
@mouseleave="$emit('mouseleave', $event)"
>
- <div class="file-row-name-container">
+ <div
+ class="file-row-name-container"
+ data-qa-selector="file_row_container"
+ :data-qa-file-name="file.name"
+ >
<span
ref="textOutput"
:style="levelIndentation"
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 3988b3814f9..a4c5ca28494 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
@@ -59,7 +59,7 @@ export default {
type: String,
required: false,
default: '',
- validator: value => value === '' || /(_desc)|(_asc)/g.test(value),
+ validator: (value) => value === '' || /(_desc)|(_asc)/g.test(value),
},
showCheckbox: {
type: Boolean,
@@ -89,7 +89,7 @@ export default {
if (this.initialSortBy) {
selectedSortOption = this.sortOptions
.filter(
- sortBy =>
+ (sortBy) =>
sortBy.sortDirection.ascending === this.initialSortBy ||
sortBy.sortDirection.descending === this.initialSortBy,
)
@@ -204,12 +204,12 @@ export default {
this.recentSearchesStore = new RecentSearchesStore({
isLocalStorageAvailable: RecentSearchesService.isAvailable(),
- allowedKeys: this.tokens.map(token => token.type),
+ allowedKeys: this.tokens.map((token) => token.type),
});
this.recentSearchesPromise = this.recentSearchesService
.fetch()
- .catch(error => {
+ .catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
createFlash(__('An error occurred while parsing recent searches'));
@@ -217,7 +217,7 @@ export default {
// Gracefully fail to empty array
return [];
})
- .then(searches => {
+ .then((searches) => {
if (!searches) return;
// Put any searches that may have come in before
@@ -250,13 +250,13 @@ export default {
* spaces.
*/
removeQuotesEnclosure(filters = []) {
- return filters.map(filter => {
+ return filters.map((filter) => {
if (typeof filter === 'object') {
const valueString = filter.value.data;
return {
...filter,
value: {
- data: stripQuotes(valueString),
+ data: typeof valueString === 'string' ? stripQuotes(valueString) : valueString,
operator: filter.value.operator,
},
};
@@ -305,8 +305,8 @@ export default {
},
historyTokenOptionTitle(historyToken) {
const tokenOption = this.tokens
- .find(token => token.type === historyToken.type)
- ?.options?.find(option => option.value === historyToken.value.data);
+ .find((token) => token.type === historyToken.type)
+ ?.options?.find((option) => option.value === historyToken.value.data);
if (!tokenOption?.title) {
return historyToken.value.data;
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
index e7d7b7d9f1b..a15cf220ee5 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
@@ -8,7 +8,7 @@ import { queryToObject } from '~/lib/utils/url_utility';
*
* @returns {String} String without any enclosure
*/
-export const stripQuotes = value => value.replace(/^('|")(.*)('|")$/, '$2');
+export const stripQuotes = (value) => value.replace(/^('|")(.*)('|")$/, '$2');
/**
* This method removes duplicate tokens from tokens array.
@@ -17,7 +17,7 @@ export const stripQuotes = value => value.replace(/^('|")(.*)('|")$/, '$2');
*
* @returns {Array} Unique array of tokens
*/
-export const uniqueTokens = tokens => {
+export const uniqueTokens = (tokens) => {
const knownTokens = [];
return tokens.reduce((uniques, token) => {
if (typeof token === 'object' && token.type !== 'filtered-search-term') {
@@ -61,7 +61,7 @@ export function prepareTokens(filters = {}) {
return memo;
}
if (Array.isArray(value)) {
- return [...memo, ...value.map(filterValue => createToken(key, filterValue))];
+ return [...memo, ...value.map((filterValue) => createToken(key, filterValue))];
}
return [...memo, createToken(key, value)];
@@ -99,8 +99,8 @@ export function filterToQueryObject(filters = {}) {
let selected;
let unselected;
if (Array.isArray(filter)) {
- selected = filter.filter(item => item.operator === '=').map(item => item.value);
- unselected = filter.filter(item => item.operator === '!=').map(item => item.value);
+ selected = filter.filter((item) => item.operator === '=').map((item) => item.value);
+ unselected = filter.filter((item) => item.operator === '!=').map((item) => item.value);
} else {
selected = filter?.operator === '=' ? filter.value : null;
unselected = filter?.operator === '!=' ? filter.value : null;
@@ -155,7 +155,7 @@ export function urlQueryToFilter(query = '') {
previousValues = memo[filterName];
}
if (Array.isArray(value)) {
- const newAdditions = value.filter(Boolean).map(item => ({ value: item, operator }));
+ const newAdditions = value.filter(Boolean).map((item) => ({ value: item, operator }));
return { ...memo, [filterName]: [...previousValues, ...newAdditions] };
}
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 443cb28cf10..411654d15f4 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
@@ -17,7 +17,7 @@ export function fetchBranches({ commit, state }, search = '') {
commit(types.REQUEST_BRANCHES);
return Api.branches(projectEndpoint, search)
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_BRANCHES_SUCCESS, response.data);
return response;
})
@@ -34,7 +34,7 @@ export const fetchMilestones = ({ commit, state }, search_title = '') => {
return axios
.get(milestonesEndpoint, { params: { search_title } })
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_MILESTONES_SUCCESS, response.data);
return response;
})
@@ -50,7 +50,7 @@ export const fetchLabels = ({ commit, state }, search = '') => {
return axios
.get(state.labelsEndpoint, { params: { search } })
- .then(response => {
+ .then((response) => {
commit(types.RECEIVE_LABELS_SUCCESS, response.data);
return response;
})
@@ -67,13 +67,13 @@ function fetchUser(options = {}) {
let fetchUserPromise;
if (projectEndpoint) {
- fetchUserPromise = Api.projectUsers(projectEndpoint, query).then(data => ({ data }));
+ fetchUserPromise = Api.projectUsers(projectEndpoint, query).then((data) => ({ data }));
} else {
fetchUserPromise = Api.groupMembers(groupEndpoint, { query });
}
return fetchUserPromise
- .then(response => {
+ .then((response) => {
commit(`RECEIVE_${action}_SUCCESS`, response.data);
return response;
})
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
index ee0e00b0f5d..d53c829a48e 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
@@ -43,7 +43,7 @@ export default {
return this.value.data.toLowerCase();
},
activeAuthor() {
- return this.authors.find(author => author.username.toLowerCase() === this.currentValue);
+ return this.authors.find((author) => author.username.toLowerCase() === this.currentValue);
},
},
watch: {
@@ -63,7 +63,7 @@ export default {
: this.config.fetchAuthors(searchTerm);
fetchPromise
- .then(res => {
+ .then((res) => {
// We'd want to avoid doing this check but
// users.json and /groups/:id/members & /projects/:id/users
// return response differently.
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
index c18bdfc5c20..694dcd95b5e 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
@@ -43,7 +43,7 @@ export default {
return this.value.data.toLowerCase();
},
activeBranch() {
- return this.branches.find(branch => branch.name.toLowerCase() === this.currentValue);
+ return this.branches.find((branch) => branch.name.toLowerCase() === this.currentValue);
},
},
watch: {
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 7a9c5c277eb..d59e9200e6c 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
@@ -47,7 +47,7 @@ export default {
},
activeLabel() {
return this.labels.find(
- label => label.title.toLowerCase() === stripQuotes(this.currentValue),
+ (label) => label.title.toLowerCase() === stripQuotes(this.currentValue),
);
},
containerStyle() {
@@ -74,7 +74,7 @@ export default {
this.loading = true;
this.config
.fetchLabels(searchTerm)
- .then(res => {
+ .then((res) => {
// We'd want to avoid doing this check but
// labels.json and /groups/:id/labels & /projects/:id/labels
// return response differently.
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 c24df5e081d..0dd7820073a 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
@@ -43,7 +43,7 @@ export default {
},
activeMilestone() {
return this.milestones.find(
- milestone => milestone.title.toLowerCase() === stripQuotes(this.currentValue),
+ (milestone) => milestone.title.toLowerCase() === stripQuotes(this.currentValue),
);
},
},
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
index 1ad0ca36bf8..9ab91e567e6 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
@@ -4,6 +4,7 @@ import {
GfmAutocompleteType,
tributeConfig,
} from 'ee_else_ce/vue_shared/components/gfm_autocomplete/utils';
+import * as Emoji from '~/emoji';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -27,7 +28,7 @@ export default {
},
computed: {
config() {
- return this.autocompleteTypes.map(type => ({
+ return this.autocompleteTypes.map((type) => ({
...tributeConfig[type].config,
loadingItemTemplate: `<span class="gl-spinner gl-vertical-align-text-bottom gl-ml-3 gl-mr-2"></span>${__(
'Loading',
@@ -55,7 +56,7 @@ export default {
if (!this.assignees || !isAssigneesLengthSame) {
this.assignees =
- SidebarMediator.singleton?.store?.assignees?.map(assignee => assignee.username) || [];
+ SidebarMediator.singleton?.store?.assignees?.map((assignee) => assignee.username) || [];
}
},
filterValues(type) {
@@ -76,10 +77,18 @@ export default {
return (inputText, processValues) => {
if (this.cache[type]) {
processValues(this.filterValues(type));
+ } else if (type === GfmAutocompleteType.Emojis) {
+ Emoji.initEmojiMap()
+ .then(() => {
+ const emojis = Emoji.getValidEmojiNames();
+ this.cache[type] = emojis;
+ processValues(emojis);
+ })
+ .catch(() => createFlash({ message: this.$options.errorMessage }));
} else if (this.dataSources[type]) {
axios
.get(this.dataSources[type])
- .then(response => {
+ .then((response) => {
this.cache[type] = response.data;
processValues(this.filterValues(type));
})
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 2581888b504..809932b0f29 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
@@ -1,16 +1,24 @@
import { escape, last } from 'lodash';
+import * as Emoji from '~/emoji';
import { spriteIcon } from '~/lib/utils/common_utils';
const groupType = 'Group'; // eslint-disable-line @gitlab/require-i18n-strings
+// Number of users to show in the autocomplete menu to avoid doing a mass fetch of 100+ avatars
+const memberLimit = 10;
+
const nonWordOrInteger = /\W|^\d+$/;
+export const menuItemLimit = 100;
+
export const GfmAutocompleteType = {
+ Emojis: 'emojis',
Issues: 'issues',
Labels: 'labels',
Members: 'members',
MergeRequests: 'mergeRequests',
Milestones: 'milestones',
+ QuickActions: 'commands',
Snippets: 'snippets',
};
@@ -21,10 +29,21 @@ function doesCurrentLineStartWith(searchString, fullText, selectionStart) {
}
export const tributeConfig = {
+ [GfmAutocompleteType.Emojis]: {
+ config: {
+ trigger: ':',
+ lookup: (value) => value,
+ menuItemLimit,
+ menuItemTemplate: ({ original }) => `${original} ${Emoji.glEmojiTag(original)}`,
+ selectTemplate: ({ original }) => `:${original}:`,
+ },
+ },
+
[GfmAutocompleteType.Issues]: {
config: {
trigger: '#',
- lookup: value => `${value.iid}${value.title}`,
+ lookup: (value) => `${value.iid}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) =>
`<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `#${original.iid}`,
@@ -35,6 +54,7 @@ export const tributeConfig = {
config: {
trigger: '~',
lookup: 'title',
+ menuItemLimit,
menuItemTemplate: ({ original }) => `
<span class="dropdown-label-box" style="background: ${escape(original.color)};"></span>
${escape(original.title)}`,
@@ -45,11 +65,11 @@ export const tributeConfig = {
},
filterValues({ collection, fullText, selectionStart }) {
if (doesCurrentLineStartWith('/label', fullText, selectionStart)) {
- return collection.filter(label => !label.set);
+ return collection.filter((label) => !label.set);
}
if (doesCurrentLineStartWith('/unlabel', fullText, selectionStart)) {
- return collection.filter(label => label.set);
+ return collection.filter((label) => label.set);
}
return collection;
@@ -60,8 +80,9 @@ export const tributeConfig = {
config: {
trigger: '@',
fillAttr: 'username',
- lookup: value =>
+ lookup: (value) =>
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 noAvatarClasses = `${commonClasses} gl-rounded-small
@@ -101,11 +122,11 @@ export const tributeConfig = {
},
filterValues({ assignees, collection, fullText, selectionStart }) {
if (doesCurrentLineStartWith('/assign', fullText, selectionStart)) {
- return collection.filter(member => !assignees.includes(member.username));
+ return collection.filter((member) => !assignees.includes(member.username));
}
if (doesCurrentLineStartWith('/unassign', fullText, selectionStart)) {
- return collection.filter(member => assignees.includes(member.username));
+ return collection.filter((member) => assignees.includes(member.username));
}
return collection;
@@ -115,7 +136,8 @@ export const tributeConfig = {
[GfmAutocompleteType.MergeRequests]: {
config: {
trigger: '!',
- lookup: value => `${value.iid}${value.title}`,
+ lookup: (value) => `${value.iid}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) =>
`<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `!${original.iid}`,
@@ -126,16 +148,47 @@ export const tributeConfig = {
config: {
trigger: '%',
lookup: 'title',
+ menuItemLimit,
menuItemTemplate: ({ original }) => escape(original.title),
selectTemplate: ({ original }) => `%"${escape(original.title)}"`,
},
},
+ [GfmAutocompleteType.QuickActions]: {
+ config: {
+ trigger: '/',
+ fillAttr: 'name',
+ lookup: (value) => `${value.name}${value.aliases.join()}`,
+ menuItemLimit,
+ menuItemTemplate: ({ original }) => {
+ const aliases = original.aliases.length
+ ? `<small>(or /${original.aliases.join(', /')})</small>`
+ : '';
+
+ const params = original.params.length ? `<small>${original.params.join(' ')}</small>` : '';
+
+ let description = '';
+
+ if (original.warning) {
+ const confidentialIcon =
+ original.icon === 'confidential' ? spriteIcon('eye-slash', 's16 gl-mr-2') : '';
+ description = `<small>${confidentialIcon}<em>${original.warning}</em></small>`;
+ } else if (original.description) {
+ description = `<small><em>${original.description}</em></small>`;
+ }
+
+ return `<div>/${original.name} ${aliases} ${params}</div>
+ <div>${description}</div>`;
+ },
+ },
+ },
+
[GfmAutocompleteType.Snippets]: {
config: {
trigger: '$',
fillAttr: 'id',
- lookup: value => `${value.id}${value.title}`,
+ lookup: (value) => `${value.id}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) => `<small>${original.id}</small> ${escape(original.title)}`,
},
},
diff --git a/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js b/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js
index 221c4f5b8a8..0a6b50674f0 100644
--- a/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js
+++ b/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js
@@ -15,5 +15,5 @@ function cleanSuggestionLine(line = {}) {
}
export function selectDiffLines(lines) {
- return lines.filter(line => line.type !== 'match').map(line => cleanSuggestionLine(line));
+ return lines.filter((line) => line.type !== 'match').map((line) => cleanSuggestionLine(line));
}
diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
index b9729a3dc5c..10887aee689 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
@@ -1,6 +1,5 @@
<script>
import { GlDropdown, GlDropdownForm, GlFormTextarea, GlButton } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
export default {
components: { GlDropdown, GlDropdownForm, GlFormTextarea, GlButton },
@@ -10,7 +9,7 @@ export default {
required: false,
default: false,
},
- fileName: {
+ defaultCommitMessage: {
type: String,
required: true,
},
@@ -18,18 +17,11 @@ export default {
data() {
return {
message: null,
- buttonText: __('Apply suggestion'),
- headerText: __('Apply suggestion commit message'),
};
},
- computed: {
- placeholderText() {
- return sprintf(__('Apply suggestion on %{fileName}'), { fileName: this.fileName });
- },
- },
methods: {
onApply() {
- this.$emit('apply', this.message || this.placeholderText);
+ this.$emit('apply', this.message);
},
},
};
@@ -37,18 +29,26 @@ export default {
<template>
<gl-dropdown
- :text="buttonText"
- :header-text="headerText"
+ :text="__('Apply suggestion')"
:disabled="disabled"
boundary="window"
right
- menu-class="gl-w-full! gl-pb-0!"
+ menu-class="gl-w-full!"
+ @shown="$refs.commitMessage.$el.focus()"
>
- <gl-dropdown-form class="gl-m-3!">
- <gl-form-textarea v-model="message" :placeholder="placeholderText" />
+ <gl-dropdown-form class="gl-px-4! gl-m-0!">
+ <label for="commit-message">{{ __('Commit message') }}</label>
+ <gl-form-textarea
+ id="commit-message"
+ ref="commitMessage"
+ v-model="message"
+ :placeholder="defaultCommitMessage"
+ submit-on-enter
+ @submit="onApply"
+ />
<gl-button
- class="gl-w-quarter! gl-mt-3 gl-text-center! float-right"
- category="secondary"
+ class="gl-w-auto! gl-mt-3 gl-text-center! gl-hover-text-white! gl-transition-medium! float-right"
+ category="primary"
variant="success"
@click="onApply"
>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 232a3054cd0..b6e167524aa 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -158,7 +158,7 @@ export default {
const mediaInPreview = this.$refs['markdown-preview'].querySelectorAll('video, audio');
if (mediaInPreview) {
- mediaInPreview.forEach(media => {
+ mediaInPreview.forEach((media) => {
media.pause();
});
}
@@ -169,7 +169,7 @@ export default {
return new GLForm(
$(this.$refs['gl-form']),
{
- emojis: this.enableAutocomplete,
+ emojis: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
members: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
issues: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
mergeRequests: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
@@ -199,7 +199,7 @@ export default {
this.markdownPreview = __('Loading…');
axios
.post(this.markdownPreviewPath, { text: this.textareaValue })
- .then(response => this.renderMarkdown(response.data))
+ .then((response) => this.renderMarkdown(response.data))
.catch(() => new Flash(__('Error loading markdown preview')));
} else {
this.renderMarkdown();
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index d0a0560846a..173d192dab0 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -110,7 +110,7 @@ export default {
const area = this.$el.parentNode.querySelector('textarea');
CopyAsGFM.nodeToGFM(transformed)
- .then(gfm => {
+ .then((gfm) => {
CopyAsGFM.insertPastedText(area, documentFragment.textContent, CopyAsGFM.quoted(gfm));
})
.catch(() => {});
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 13ec7a6ada9..93a270b8a97 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -27,6 +27,10 @@ export default {
type: String,
required: true,
},
+ defaultCommitMessage: {
+ type: String,
+ required: true,
+ },
suggestionsCount: {
type: Number,
required: false,
@@ -47,8 +51,8 @@ export default {
},
},
methods: {
- applySuggestion(callback) {
- this.$emit('apply', { suggestionId: this.suggestion.id, callback });
+ applySuggestion(callback, message) {
+ this.$emit('apply', { suggestionId: this.suggestion.id, callback, message });
},
applySuggestionBatch() {
this.$emit('applyBatch');
@@ -74,6 +78,7 @@ export default {
:is-applying-batch="suggestion.is_applying_batch"
:batch-suggestions-count="batchSuggestionsCount"
:help-page-path="helpPagePath"
+ :default-commit-message="defaultCommitMessage"
:inapplicable-reason="suggestion.inapplicable_reason"
@apply="applySuggestion"
@applyBatch="applySuggestionBatch"
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 fb51840b689..63341b433e0 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
@@ -2,9 +2,10 @@
import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import ApplySuggestion from './apply_suggestion.vue';
export default {
- components: { GlIcon, GlButton, GlLoadingIcon },
+ components: { GlIcon, GlButton, GlLoadingIcon, ApplySuggestion },
directives: { 'gl-tooltip': GlTooltipDirective },
mixins: [glFeatureFlagsMixin()],
props: {
@@ -37,6 +38,10 @@ export default {
type: String,
required: true,
},
+ defaultCommitMessage: {
+ type: String,
+ required: true,
+ },
inapplicableReason: {
type: String,
required: false,
@@ -57,6 +62,9 @@ export default {
canBeBatched() {
return Boolean(this.glFeatures.batchSuggestions);
},
+ canAddCustomCommitMessage() {
+ return this.glFeatures.suggestionsCustomCommit;
+ },
isApplying() {
return this.isApplyingSingle || this.isApplyingBatch;
},
@@ -77,10 +85,10 @@ export default {
},
},
methods: {
- applySuggestion() {
+ applySuggestion(message) {
if (!this.canApply) return;
this.isApplyingSingle = true;
- this.$emit('apply', this.applySuggestionCallback);
+ this.$emit('apply', this.applySuggestionCallback, message);
},
applySuggestionCallback() {
this.isApplyingSingle = false;
@@ -142,7 +150,14 @@ export default {
>
{{ __('Add suggestion to batch') }}
</gl-button>
- <span v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
+ <apply-suggestion
+ v-if="canAddCustomCommitMessage"
+ :disabled="isDisableButton"
+ :default-commit-message="defaultCommitMessage"
+ class="gl-ml-3"
+ @apply="applySuggestion"
+ />
+ <span v-else v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
<gl-button
v-if="isLoggedIn"
class="btn-inverted js-apply-btn btn-grouped"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 927a93487e6..5ee51764555 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -38,6 +38,10 @@ export default {
type: String,
required: true,
},
+ defaultCommitMessage: {
+ type: String,
+ required: true,
+ },
suggestionsCount: {
type: Number,
required: false,
@@ -82,27 +86,41 @@ export default {
this.isRendered = true;
},
generateDiff(suggestionIndex) {
- const { suggestions, disabled, batchSuggestionsInfo, helpPagePath, suggestionsCount } = this;
+ const {
+ suggestions,
+ disabled,
+ batchSuggestionsInfo,
+ helpPagePath,
+ defaultCommitMessage,
+ suggestionsCount,
+ } = this;
const suggestion =
suggestions && suggestions[suggestionIndex] ? suggestions[suggestionIndex] : {};
const SuggestionDiffComponent = Vue.extend(SuggestionDiff);
const suggestionDiff = new SuggestionDiffComponent({
- propsData: { disabled, suggestion, batchSuggestionsInfo, helpPagePath, suggestionsCount },
+ propsData: {
+ disabled,
+ suggestion,
+ batchSuggestionsInfo,
+ helpPagePath,
+ defaultCommitMessage,
+ suggestionsCount,
+ },
});
- suggestionDiff.$on('apply', ({ suggestionId, callback }) => {
- this.$emit('apply', { suggestionId, callback, flashContainer: this.$el });
+ suggestionDiff.$on('apply', ({ suggestionId, callback, message }) => {
+ this.$emit('apply', { suggestionId, callback, flashContainer: this.$el, message });
});
suggestionDiff.$on('applyBatch', () => {
this.$emit('applyBatch', { flashContainer: this.$el });
});
- suggestionDiff.$on('addToBatch', suggestionId => {
+ suggestionDiff.$on('addToBatch', (suggestionId) => {
this.$emit('addToBatch', suggestionId);
});
- suggestionDiff.$on('removeFromBatch', suggestionId => {
+ suggestionDiff.$on('removeFromBatch', (suggestionId) => {
this.$emit('removeFromBatch', suggestionId);
});
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 5824cb9438f..15c5b9d6733 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -49,10 +49,10 @@ export default {
)
"
>
- <template #markdownDocsLink="{content}">
+ <template #markdownDocsLink="{ content }">
<gl-link :href="markdownDocsPath" target="_blank">{{ content }}</gl-link>
</template>
- <template #quickActionsDocsLink="{content}">
+ <template #quickActionsDocsLink="{ content }">
<gl-link :href="quickActionsDocsPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
@@ -81,7 +81,7 @@ export default {
)
"
>
- <template #retryButton="{content}">
+ <template #retryButton="{ content }">
<gl-button
variant="link"
category="primary"
@@ -90,7 +90,7 @@ export default {
{{ content }}
</gl-button>
</template>
- <template #newFileButton="{content}">
+ <template #newFileButton="{ content }">
<gl-button
variant="link"
category="primary"
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 de9c84dd157..e3a7f144321 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -55,6 +55,11 @@ export default {
required: false,
default: null,
},
+ category: {
+ type: String,
+ required: false,
+ default: 'primary',
+ },
},
computed: {
modalDomId() {
@@ -70,14 +75,14 @@ export default {
document.body,
});
this.clipboard
- .on('success', e => {
+ .on('success', (e) => {
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();
e.trigger.blur();
})
- .on('error', e => this.$emit('error', e));
+ .on('error', (e) => this.$emit('error', e));
});
},
destroyed() {
@@ -95,6 +100,7 @@ export default {
:data-clipboard-target="target"
:data-clipboard-text="text"
:title="title"
+ :category="category"
icon="copy-to-clipboard"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
index 3749888ee36..653ee7f20e9 100644
--- a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { GlBadge, GlTabs, GlTab } from '@gitlab/ui';
/**
* Given an array of tabs, renders non linked bootstrap tabs.
@@ -23,6 +24,11 @@ import $ from 'jquery';
*/
export default {
name: 'NavigationTabs',
+ components: {
+ GlBadge,
+ GlTabs,
+ GlTab,
+ },
props: {
tabs: {
type: Array,
@@ -50,24 +56,21 @@ export default {
};
</script>
<template>
- <ul class="nav-links scrolling-tabs separator">
- <li
+ <gl-tabs class="gl-display-flex gl-w-full" nav-class="gl-border-0!">
+ <gl-tab
v-for="(tab, i) in tabs"
:key="i"
- :class="{
- active: tab.isActive,
- }"
+ :title-link-class="`js-${scope}-tab-${tab.scope} gl-display-inline-flex`"
+ :title-link-attributes="{ 'data-testid': `${scope}-tab-${tab.scope}` }"
+ :active="tab.isActive"
+ @click="onTabClick(tab)"
>
- <a
- :class="`js-${scope}-tab-${tab.scope}`"
- :data-testid="`${scope}-tab-${tab.scope}`"
- role="button"
- @click="onTabClick(tab)"
- >
- {{ tab.name }}
-
- <span v-if="shouldRenderBadge(tab.count)" class="badge badge-pill"> {{ tab.count }} </span>
- </a>
- </li>
- </ul>
+ <template #title>
+ <span class="gl-mr-2"> {{ tab.name }} </span>
+ <gl-badge v-if="shouldRenderBadge(tab.count)" size="sm" class="gl-tab-counter-badge">{{
+ tab.count
+ }}</gl-badge>
+ </template>
+ </gl-tab>
+ </gl-tabs>
</template>
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 f30676e8ef3..cc1203f83f0 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -78,16 +78,10 @@ export default {
},
// following 2 methods taken from code in `collapseLongCommitList` of notes.js:
actionTextHtml() {
- return $(this.note.note_html)
- .unwrap()
- .html();
+ return $(this.note.note_html).unwrap().html();
},
hasMoreCommits() {
- return (
- $(this.note.note_html)
- .filter('ul')
- .children().length > MAX_VISIBLE_COMMIT_LIST_COUNT
- );
+ return $(this.note.note_html).filter('ul').children().length > MAX_VISIBLE_COMMIT_LIST_COUNT;
},
descriptionVersion() {
return this.descriptionVersions[this.note.description_version_id];
diff --git a/app/assets/javascripts/vue_shared/components/ordered_layout.vue b/app/assets/javascripts/vue_shared/components/ordered_layout.vue
index 117e79ca39f..a57ff10de71 100644
--- a/app/assets/javascripts/vue_shared/components/ordered_layout.vue
+++ b/app/assets/javascripts/vue_shared/components/ordered_layout.vue
@@ -4,7 +4,7 @@ export default {
render(h, context) {
const { slotKeys } = context.props;
const slots = context.slots();
- const children = slotKeys.map(key => slots[key]).filter(x => x);
+ const children = slotKeys.map((key) => slots[key]).filter((x) => x);
return children;
},
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 1fc39c7cb8e..d03987bbbe0 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
@@ -203,7 +203,7 @@ export default {
this.resetPagination();
const filterParams = { authorUsername: '', assigneeUsername: '', search: '' };
- filters.forEach(filter => {
+ filters.forEach((filter) => {
if (typeof filter === 'object') {
switch (filter.type) {
case 'author_username':
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js
index 7de4263acbb..7855c7ea6cb 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/utils.js
@@ -6,6 +6,6 @@ import { __ } from '~/locale';
* @param {String} value
* @returns {String}
*/
-export const isAny = value => {
+export const isAny = (value) => {
return value === __('Any') ? '' : value;
};
diff --git a/app/assets/javascripts/vue_shared/components/pikaday.vue b/app/assets/javascripts/vue_shared/components/pikaday.vue
index 85481f3f7b4..3c0ac32e512 100644
--- a/app/assets/javascripts/vue_shared/components/pikaday.vue
+++ b/app/assets/javascripts/vue_shared/components/pikaday.vue
@@ -1,20 +1,13 @@
<script>
-import Pikaday from 'pikaday';
-import { GlIcon } from '@gitlab/ui';
-import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
+import { GlDatepicker } from '@gitlab/ui';
+import { pikadayToString } from '~/lib/utils/datetime_utility';
export default {
name: 'DatePicker',
components: {
- GlIcon,
+ GlDatepicker,
},
props: {
- label: {
- type: String,
- required: false,
- default: __('Date picker'),
- },
selectedDate: {
type: Date,
required: false,
@@ -31,32 +24,9 @@ export default {
default: null,
},
},
- mounted() {
- this.calendar = new Pikaday({
- field: this.$el.querySelector('.dropdown-menu-toggle'),
- theme: 'gitlab-theme animate-picker',
- format: 'yyyy-mm-dd',
- container: this.$el,
- defaultDate: this.selectedDate,
- setDefaultDate: Boolean(this.selectedDate),
- minDate: this.minDate,
- maxDate: this.maxDate,
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
- onSelect: this.selected.bind(this),
- onClose: this.toggled.bind(this),
- firstDay: gon.first_day_of_week,
- });
-
- this.$el.append(this.calendar.el);
- this.calendar.show();
- },
- beforeDestroy() {
- this.calendar.destroy();
- },
methods: {
- selected(dateText) {
- this.$emit('newDateSelected', this.calendar.toString(dateText));
+ selected(date) {
+ this.$emit('newDateSelected', pikadayToString(date));
},
toggled() {
this.$emit('hidePicker');
@@ -66,12 +36,13 @@ export default {
</script>
<template>
- <div class="pikaday-container">
- <div class="dropdown open">
- <button type="button" class="dropdown-menu-toggle" data-toggle="dropdown" @click="toggled">
- <span class="dropdown-toggle-text"> {{ label }} </span>
- <gl-icon name="chevron-down" class="gl-absolute gl-right-3 gl-top-3 gl-text-gray-500" />
- </button>
- </div>
- </div>
+ <gl-datepicker
+ :value="selectedDate"
+ :min-date="minDate"
+ :max-date="maxDate"
+ start-opened
+ @close="toggled"
+ @click="toggled"
+ @input="selected"
+ />
</template>
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index 154671fe9fa..65bd4e4382d 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
@@ -13,7 +13,7 @@ export default {
project: {
type: Object,
required: true,
- validator: p =>
+ validator: (p) =>
(Number.isFinite(p.id) || isString(p.id)) &&
isString(p.name) &&
(isString(p.name_with_namespace) || isString(p.nameWithNamespace)),
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 4e2029cd74f..e659e2155fb 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
@@ -48,10 +48,14 @@ export default {
data() {
return {
searchQuery: '',
+ hasSearched: false,
};
},
computed: {
legendText() {
+ if (!this.hasSearched) {
+ return '';
+ }
const count = this.projectSearchResults.length;
const total = this.totalResults;
@@ -75,6 +79,9 @@ export default {
return this.selectedProjects.some(({ id }) => project.id === id);
},
onInput: debounce(function debouncedOnInput() {
+ if (!this.hasSearched) {
+ this.hasSearched = true;
+ }
this.$emit('searched', this.searchQuery);
}, SEARCH_INPUT_TIMEOUT_MS),
},
@@ -115,7 +122,7 @@ export default {
</template>
<template #default>
- {{ legendText }}
+ <span data-testid="legend-text">{{ legendText }}</span>
</template>
</gl-infinite-scroll>
<div v-if="showNoResultsMessage" class="text-muted ml-2 js-no-results-message">
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 7046ac5be03..8965dba3e83 100644
--- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -39,7 +39,7 @@ export default {
},
},
mounted() {
- this.detailsSlots = Object.keys(this.$slots).filter(k => k.startsWith('details-'));
+ this.detailsSlots = Object.keys(this.$slots).filter((k) => k.startsWith('details-'));
},
methods: {
toggleDetails() {
diff --git a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
index 8ef623b68eb..93396219a54 100644
--- a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon, GlLink } from '@gitlab/ui';
+import { GlIcon, GlLink, GlTooltipDirective } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
export default {
@@ -9,6 +9,9 @@ export default {
GlLink,
TooltipOnTruncate,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
icon: {
type: String,
@@ -32,6 +35,11 @@ export default {
return !value || ['xs', 's', 'm', 'l', 'xl'].includes(value);
},
},
+ textTooltip: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
sizeClass() {
@@ -55,9 +63,12 @@ export default {
class="gl-font-weight-bold gl-display-inline-flex"
:class="sizeClass"
>
- <tooltip-on-truncate :title="text" class="gl-text-truncate">
+ <tooltip-on-truncate v-if="!textTooltip" :title="text" class="gl-text-truncate">
{{ text }}
</tooltip-on-truncate>
+ <span v-else v-gl-tooltip="{ title: textTooltip }" data-testid="text-tooltip-container">
+ {{ text }}</span
+ >
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/title_area.vue b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
index 4d47a34c9a3..c63d91b78d3 100644
--- a/app/assets/javascripts/vue_shared/components/registry/title_area.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAvatar, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlAvatar, GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui';
export default {
name: 'TitleArea',
@@ -7,6 +7,7 @@ export default {
GlAvatar,
GlSprintf,
GlLink,
+ GlSkeletonLoader,
},
props: {
avatar: {
@@ -24,6 +25,11 @@ export default {
default: () => [],
required: false,
},
+ metadataLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -32,11 +38,11 @@ export default {
},
async mounted() {
const METADATA_PREFIX = 'metadata-';
- this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith(METADATA_PREFIX));
+ this.metadataSlots = Object.keys(this.$slots).filter((k) => k.startsWith(METADATA_PREFIX));
// we need to wait for next tick to ensure that dynamic names slots are picked up
await this.$nextTick();
- this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith(METADATA_PREFIX));
+ this.metadataSlots = Object.keys(this.$slots).filter((k) => k.startsWith(METADATA_PREFIX));
},
};
</script>
@@ -44,7 +50,7 @@ export default {
<template>
<div class="gl-display-flex gl-flex-direction-column">
<div class="gl-display-flex gl-justify-content-space-between gl-py-3">
- <div class="gl-flex-direction-column">
+ <div class="gl-flex-direction-column gl-flex-grow-1">
<div class="gl-display-flex">
<gl-avatar
v-if="avatar"
@@ -68,13 +74,23 @@ export default {
</div>
<div class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3">
- <div
- v-for="(row, metadataIndex) in metadataSlots"
- :key="metadataIndex"
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <slot :name="row"></slot>
- </div>
+ <template v-if="!metadataLoading">
+ <div
+ v-for="(row, metadataIndex) in metadataSlots"
+ :key="metadataIndex"
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <slot :name="row"></slot>
+ </div>
+ </template>
+ <template v-else>
+ <div class="gl-w-full">
+ <gl-skeleton-loader :width="960" :height="16" preserve-aspect-ratio="xMinYMax meet">
+ <circle cx="6" cy="8" r="6" />
+ <rect x="16" y="4" width="200" height="8" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ </template>
</div>
</div>
<div v-if="$slots['right-actions']" class="gl-mt-3">
@@ -89,7 +105,7 @@ export default {
data-testid="info-message"
>
<gl-sprintf :message="message.text">
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="message.link" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
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 fe50a459e52..5d4c192c78f 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
@@ -20,7 +20,7 @@ export default {
components: {
ToastEditor: () =>
import(/* webpackChunkName: 'toast_editor' */ '@toast-ui/vue-editor').then(
- toast => toast.Editor,
+ (toast) => toast.Editor,
),
AddImageModal,
InsertVideoModal,
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 108c60c3edb..624b5b09b38 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
@@ -17,12 +17,12 @@ const listItemRenderers = [renderListItem];
const softbreakRenderers = [renderSoftbreak];
const executeRenderer = (renderers, node, context) => {
- const availableRenderer = renderers.find(renderer => renderer.canRender(node, context));
+ const availableRenderer = renderers.find((renderer) => renderer.canRender(node, context));
return availableRenderer ? availableRenderer.render(node, context) : context.origin();
};
-const buildCustomHTMLRenderer = customRenderers => {
+const buildCustomHTMLRenderer = (customRenderers) => {
const renderersByType = {
...customRenderers,
htmlBlock: union(htmlBlockRenderers, customRenderers?.htmlBlock),
@@ -34,7 +34,7 @@ const buildCustomHTMLRenderer = customRenderers => {
softbreak: union(softbreakRenderers, customRenderers?.softbreak),
};
- return mapValues(renderersByType, renderers => {
+ return mapValues(renderersByType, (renderers) => {
return (node, context) => executeRenderer(renderers, node, context);
});
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
index 9744e25a8e1..273e0a59963 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
@@ -9,7 +9,7 @@ const DEFAULTS = {
emphasis: '_',
};
-const countIndentSpaces = text => {
+const countIndentSpaces = (text) => {
const matches = text.match(/^\s+/m);
return matches ? matches[0].length : 0;
@@ -52,7 +52,7 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
const firstLevelIndentSpacesCount = countIndentSpaces(baseResult) || 1;
const reindentedList = baseResult
.split('\n')
- .map(line => {
+ .map((line) => {
const itemIndentSpacesCount = countIndentSpaces(line);
const nestingLevel = Math.ceil(itemIndentSpacesCount / firstLevelIndentSpacesCount);
const indentSpaces = repeat(' ', subListIndentSpaces * nestingLevel);
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 463e64b4936..be78651d38d 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
@@ -6,7 +6,7 @@ import buildCustomHTMLRenderer from './build_custom_renderer';
import { TOOLBAR_ITEM_CONFIGS, VIDEO_ATTRIBUTES } from '../constants';
import sanitizeHTML from './sanitize_html';
-const buildWrapper = propsData => {
+const buildWrapper = (propsData) => {
const instance = new Vue({
render(createElement) {
return createElement(ToolbarItem, propsData);
@@ -17,7 +17,7 @@ const buildWrapper = propsData => {
return instance.$el;
};
-const buildVideoIframe = src => {
+const buildVideoIframe = (src) => {
const wrapper = document.createElement('figure');
const iframe = document.createElement('iframe');
const videoAttributes = { ...VIDEO_ATTRIBUTES, src };
@@ -48,7 +48,7 @@ const buildImg = (alt, originalSrc, file) => {
return img;
};
-export const generateToolbarItem = config => {
+export const generateToolbarItem = (config) => {
const { icon, classes, event, command, tooltip, isDivider } = config;
if (isDivider) {
@@ -92,14 +92,14 @@ export const insertVideo = ({ editor }, url) => {
}
};
-export const getMarkdown = editorInstance => editorInstance.invoke('getMarkdown');
+export const getMarkdown = (editorInstance) => editorInstance.invoke('getMarkdown');
/**
* This function allow us to extend Toast UI HTML to Markdown renderer. It is
* a temporary measure because Toast UI does not provide an API
* to achieve this goal.
*/
-export const registerHTMLToMarkdownRenderer = editorApi => {
+export const registerHTMLToMarkdownRenderer = (editorApi) => {
const { renderer } = editorApi.toMarkOptions;
Object.assign(editorApi.toMarkOptions, {
@@ -107,10 +107,10 @@ export const registerHTMLToMarkdownRenderer = editorApi => {
});
};
-export const getEditorOptions = externalOptions => {
+export const getEditorOptions = (externalOptions) => {
return defaults({
customHTMLRenderer: buildCustomHTMLRenderer(externalOptions?.customRenderers),
- toolbarItems: TOOLBAR_ITEM_CONFIGS.map(toolbarItem => generateToolbarItem(toolbarItem)),
- customHTMLSanitizer: html => sanitizeHTML(html),
+ toolbarItems: TOOLBAR_ITEM_CONFIGS.map((toolbarItem) => generateToolbarItem(toolbarItem)),
+ customHTMLSanitizer: (html) => sanitizeHTML(html),
});
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
index 1dcecd5fb8c..638e5fd6f60 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
@@ -32,20 +32,20 @@ export const buildUneditableCloseTokens = (token, tagType = TAG_TYPES.block) =>
// Complete helpers (open plus close)
-export const buildTextToken = content => buildToken('text', null, { content });
+export const buildTextToken = (content) => buildToken('text', null, { content });
-export const buildUneditableBlockTokens = token => {
+export const buildUneditableBlockTokens = (token) => {
return [...buildUneditableOpenTokens(token), buildUneditableCloseToken()];
};
-export const buildUneditableInlineTokens = token => {
+export const buildUneditableInlineTokens = (token) => {
return [
...buildUneditableOpenTokens(token, TAG_TYPES.inline),
buildUneditableCloseToken(TAG_TYPES.inline),
];
};
-export const buildUneditableHtmlAsTextTokens = node => {
+export const buildUneditableHtmlAsTextTokens = (node) => {
/*
Toast UI internally appends ' data-tomark-pass ' attribute flags so it can target certain
nested nodes for internal use during Markdown <=> WYSIWYG conversions. In our case, we want
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 18bd17d43d9..30012c1123f 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
@@ -2,7 +2,7 @@ import { buildUneditableHtmlAsTextTokens } from './build_uneditable_token';
import { ALLOWED_VIDEO_ORIGINS } from '../../constants';
import { getURLOrigin } from '~/lib/utils/url_utility';
-const isVideoFrame = html => {
+const isVideoFrame = (html) => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const {
@@ -18,6 +18,6 @@ const canRender = ({ type, literal }) => {
return type === 'htmlBlock' && !isVideoFrame(literal);
};
-const render = node => buildUneditableHtmlAsTextTokens(node);
+const render = (node) => buildUneditableHtmlAsTextTokens(node);
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
index a9c3dfcd728..d7716543b53 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
@@ -17,7 +17,7 @@ Regexp notes:
*/
const identifierInstanceRegex = /((?:\[.+?\]){1}(?:\[\]|\[.+?\])?(?!:))/g;
-const isIdentifierInstance = literal => {
+const isIdentifierInstance = (literal) => {
// Reset lastIndex as global flag in regexp are stateful (https://stackoverflow.com/a/11477448)
identifierInstanceRegex.lastIndex = 0;
return identifierInstanceRegex.test(literal);
@@ -25,9 +25,9 @@ const isIdentifierInstance = literal => {
const canRender = ({ literal }) => isIdentifierInstance(literal);
-const tokenize = text => {
+const tokenize = (text) => {
const matches = text.split(identifierInstanceRegex);
- const tokens = matches.map(match => {
+ const tokens = matches.map((match) => {
const token = buildTextToken(match);
return isIdentifierInstance(match) ? buildUneditableInlineTokens(token) : token;
});
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
index 3f9c6291d1b..4829f0f2243 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
@@ -1,6 +1,6 @@
const identifierRegex = /(^\[.+\]: .+)/;
-const isIdentifier = text => {
+const isIdentifier = (text) => {
return identifierRegex.test(text);
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
index 389ade5f27a..c004e839821 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
@@ -1,4 +1,4 @@
-const canRender = node => ['emph', 'strong'].includes(node.parent?.type);
+const canRender = (node) => ['emph', 'strong'].includes(node.parent?.type);
const render = () => ({
type: 'text',
content: ' ',
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
index 4cba2c70486..eff5dbf59f2 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
@@ -11,9 +11,9 @@ export const renderUneditableBranch = (_, { entering, origin }) =>
const attributeDefinitionRegexp = /(^{:.+}$)/;
-export const isAttributeDefinition = text => attributeDefinitionRegexp.test(text);
+export const isAttributeDefinition = (text) => attributeDefinitionRegexp.test(text);
-const findAttributeDefinition = node => {
+const findAttributeDefinition = (node) => {
const literal =
node?.next?.firstChild?.literal || node?.firstChild?.firstChild?.next?.next?.literal; // for headings // for list items;
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 eae2e0335c1..cb0f1d51cb1 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
@@ -5,7 +5,7 @@ import { getURLOrigin } from '~/lib/utils/url_utility';
const sanitizer = createSanitizer(window);
const ADD_TAGS = ['iframe'];
-sanitizer.addHook('uponSanitizeElement', node => {
+sanitizer.addHook('uponSanitizeElement', (node) => {
if (node.tagName !== 'IFRAME') {
return;
}
@@ -17,6 +17,6 @@ sanitizer.addHook('uponSanitizeElement', node => {
}
});
-const sanitize = content => sanitizer.sanitize(content, { ADD_TAGS });
+const sanitize = (content) => sanitizer.sanitize(content, { ADD_TAGS });
export default sanitize;
diff --git a/app/assets/javascripts/vue_shared/components/select2_select.vue b/app/assets/javascripts/vue_shared/components/select2_select.vue
index 3dbf0ccdfa9..6574a5ddfde 100644
--- a/app/assets/javascripts/vue_shared/components/select2_select.vue
+++ b/app/assets/javascripts/vue_shared/components/select2_select.vue
@@ -26,7 +26,7 @@ export default {
$(this.$refs.dropdownInput)
.val(this.value)
.select2(this.options)
- .on('change', event => this.$emit('input', event.target.value));
+ .on('change', (event) => this.$emit('input', event.target.value));
})
.catch(() => {});
},
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 1ef3d5627ae..22d86ee25d1 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
@@ -143,7 +143,7 @@ export default {
>
<slot></slot>
</dropdown-value>
- <div v-if="canEdit" class="selectbox js-selectbox" style="display: none;">
+ <div v-if="canEdit" class="selectbox js-selectbox" style="display: none">
<dropdown-hidden-input
v-for="label in context.labels"
:key="label.id"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
index 434aabc3df9..795f16f4efc 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
@@ -18,7 +18,7 @@ export default {
},
created() {
const rawLabelsColors = gon.suggested_label_colors;
- this.suggestedColors = Object.keys(rawLabelsColors).map(colorCode => ({
+ this.suggestedColors = Object.keys(rawLabelsColors).map((colorCode) => ({
colorCode,
title: rawLabelsColors[colorCode],
}));
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
index 973cc314ee3..122250d1ce7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
@@ -20,7 +20,7 @@ export default {
const labelsString = this.labels.length
? this.labels
.slice(0, 5)
- .map(label => label.title)
+ .map((label) => label.title)
.join(', ')
: s__('LabelSelect|Labels');
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 55e2fb68275..41308e352e3 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
@@ -25,7 +25,7 @@ export default {
},
suggestedColors() {
const colorsMap = gon.suggested_label_colors;
- return Object.keys(colorsMap).map(color => ({ [color]: colorsMap[color] }));
+ return Object.keys(colorsMap).map((color) => ({ [color]: colorsMap[color] }));
},
},
methods: {
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 8ce624aa303..683889b8611 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
@@ -182,9 +182,9 @@ export default {
!state.showDropdownButton &&
!state.showDropdownContents
) {
- let filterFn = label => label.touched;
+ let filterFn = (label) => label.touched;
if (this.isDropdownVariantEmbedded) {
- filterFn = label => label.set;
+ filterFn = (label) => label.set;
}
this.handleDropdownClose(state.labels.filter(filterFn));
}
@@ -204,13 +204,13 @@ export default {
'js-btn-cancel-create',
'js-sidebar-dropdown-toggle',
].some(
- className =>
+ (className) =>
target?.classList.contains(className) ||
target?.parentElement?.classList.contains(className),
);
const hadExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
- className => $(target).parents(className).length,
+ (className) => $(target).parents(className).length,
);
if (
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js
index 5a30e29cad3..d14f96720b7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/getters.js
@@ -9,7 +9,7 @@ import { DropdownVariant } from '../constants';
*/
export const dropdownButtonText = (state, getters) => {
const selectedLabels = getters.isDropdownVariantSidebar
- ? state.labels.filter(label => label.set)
+ ? state.labels.filter((label) => label.set)
: state.selectedLabels;
if (!selectedLabels.length) {
@@ -28,25 +28,25 @@ export const dropdownButtonText = (state, getters) => {
* selectedLabels array.
* @param {object} state
*/
-export const selectedLabelsList = state => state.selectedLabels.map(label => label.id);
+export const selectedLabelsList = (state) => state.selectedLabels.map((label) => label.id);
/**
* Returns boolean representing whether dropdown variant
* is `sidebar`
* @param {object} state
*/
-export const isDropdownVariantSidebar = state => state.variant === DropdownVariant.Sidebar;
+export const isDropdownVariantSidebar = (state) => state.variant === DropdownVariant.Sidebar;
/**
* Returns boolean representing whether dropdown variant
* is `standalone`
* @param {object} state
*/
-export const isDropdownVariantStandalone = state => state.variant === DropdownVariant.Standalone;
+export const isDropdownVariantStandalone = (state) => state.variant === DropdownVariant.Standalone;
/**
* Returns boolean representing whether dropdown variant
* is `embedded`
* @param {object} state
*/
-export const isDropdownVariantEmbedded = state => state.variant === DropdownVariant.Embedded;
+export const isDropdownVariantEmbedded = (state) => state.variant === DropdownVariant.Embedded;
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 54f8c78b4e1..6de436ffd13 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
@@ -33,7 +33,7 @@ export default {
// Iterate over every label and add a `set` prop
// to determine whether it is already a part of
// selectedLabels array.
- const selectedLabelIds = state.selectedLabels.map(label => label.id);
+ const selectedLabelIds = state.selectedLabels.map((label) => label.id);
state.labelsFetchInProgress = false;
state.labels = labels.reduce((allLabels, label) => {
allLabels.push({
@@ -61,7 +61,7 @@ export default {
// Find the label to update from all the labels
// and change `set` prop value to represent their current state.
const labelId = labels.pop()?.id;
- const candidateLabel = state.labels.find(label => labelId === label.id);
+ const candidateLabel = state.labels.find((label) => labelId === label.id);
if (candidateLabel) {
candidateLabel.touched = true;
candidateLabel.set = !candidateLabel.set;
diff --git a/app/assets/javascripts/vue_shared/components/split_button.vue b/app/assets/javascripts/vue_shared/components/split_button.vue
index 11049028ff6..61b317d0d1d 100644
--- a/app/assets/javascripts/vue_shared/components/split_button.vue
+++ b/app/assets/javascripts/vue_shared/components/split_button.vue
@@ -2,7 +2,7 @@
import { isString } from 'lodash';
import { GlDropdown, GlDropdownDivider, GlDropdownItem } from '@gitlab/ui';
-const isValidItem = item =>
+const isValidItem = (item) =>
isString(item.eventName) && isString(item.title) && isString(item.description);
export default {
diff --git a/app/assets/javascripts/vue_shared/components/tabs/tabs.js b/app/assets/javascripts/vue_shared/components/tabs/tabs.js
index 9b9e4bb47bd..233df96a520 100644
--- a/app/assets/javascripts/vue_shared/components/tabs/tabs.js
+++ b/app/assets/javascripts/vue_shared/components/tabs/tabs.js
@@ -17,8 +17,8 @@ export default {
},
methods: {
updateTabs() {
- this.tabs = this.$children.filter(child => child.isTab);
- this.currentIndex = this.tabs.findIndex(tab => tab.localActive);
+ this.tabs = this.$children.filter((child) => child.isTab);
+ this.currentIndex = this.tabs.findIndex((tab) => tab.localActive);
},
setTab(e, index) {
if (this.stopPropagation) {
@@ -48,7 +48,7 @@ export default {
href: '#',
},
on: {
- click: e => this.setTab(e, i),
+ click: (e) => this.setTab(e, i),
},
},
tab.$slots.title || tab.title,
diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
index 3fa8efcd145..f1db26ff4fc 100644
--- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
@@ -36,14 +36,14 @@ export default {
},
computed: {
timezones() {
- return this.timezoneData.map(timezone => ({
+ return this.timezoneData.map((timezone) => ({
formattedTimezone: this.formatTimezone(timezone),
identifier: timezone.identifier,
}));
},
filteredResults() {
const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.timezones.filter(timezone =>
+ return this.timezones.filter((timezone) =>
timezone.formattedTimezone.toLowerCase().includes(lowerCasedSearchTerm),
);
},
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 b645758d891..01ba2cf5c39 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
@@ -62,7 +62,9 @@ export default {
return files.every(this.isFileValid);
},
isValidDragDataType({ dataTransfer }) {
- return Boolean(dataTransfer && dataTransfer.types.some(t => t === VALID_DATA_TRANSFER_TYPE));
+ return Boolean(
+ dataTransfer && dataTransfer.types.some((t) => t === VALID_DATA_TRANSFER_TYPE),
+ );
},
ondrop({ dataTransfer = {} }) {
this.dragCounter = 0;
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
index ea483416c46..efb99eb0d94 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
@@ -104,7 +104,7 @@ export default {
:target="() => $refs.userAvatarImage"
:placement="tooltipPlacement"
boundary="window"
- class="js-user-avatar-image-toolip"
+ class="js-user-avatar-image-tooltip"
>
<slot> {{ tooltipText }} </slot>
</gl-tooltip>
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 dbb1a075e76..c957876f8ab 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -72,7 +72,7 @@ export default {
},
computed: {
actions() {
- return [this.webIdeAction, this.editAction, this.gitpodAction].filter(action => action);
+ return [this.webIdeAction, this.editAction, this.gitpodAction].filter((action) => action);
},
editAction() {
if (!this.showEditButton) {
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index 5511145fba2..5262a15136b 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -54,5 +54,6 @@ export const timeRanges = [
},
];
-export const defaultTimeRange = timeRanges.find(tr => tr.default);
-export const getTimeWindow = timeWindowName => timeRanges.find(tr => tr.name === timeWindowName);
+export const defaultTimeRange = timeRanges.find((tr) => tr.default);
+export const getTimeWindow = (timeWindowName) =>
+ timeRanges.find((tr) => tr.name === timeWindowName);
diff --git a/app/assets/javascripts/vue_shared/directives/autofocusonshow.js b/app/assets/javascripts/vue_shared/directives/autofocusonshow.js
index 4659ec20ceb..1be4612a7e4 100644
--- a/app/assets/javascripts/vue_shared/directives/autofocusonshow.js
+++ b/app/assets/javascripts/vue_shared/directives/autofocusonshow.js
@@ -11,8 +11,8 @@ export default {
inserted(el) {
if ('IntersectionObserver' in window) {
// Element visibility is dynamic, so we attach observer
- el.visibilityObserver = new IntersectionObserver(entries => {
- entries.forEach(entry => {
+ el.visibilityObserver = new IntersectionObserver((entries) => {
+ entries.forEach((entry) => {
// Combining `intersectionRatio > 0` and
// element's `offsetParent` presence will
// deteremine if element is truely visible
diff --git a/app/assets/javascripts/vue_shared/directives/validation.js b/app/assets/javascripts/vue_shared/directives/validation.js
index 09bec78edcc..ece09df272c 100644
--- a/app/assets/javascripts/vue_shared/directives/validation.js
+++ b/app/assets/javascripts/vue_shared/directives/validation.js
@@ -12,19 +12,19 @@ import { s__ } from '~/locale';
*/
const defaultFeedbackMap = {
valueMissing: {
- isInvalid: el => el.validity?.valueMissing,
+ isInvalid: (el) => el.validity?.valueMissing,
message: s__('Please fill out this field.'),
},
urlTypeMismatch: {
- isInvalid: el => el.type === 'url' && el.validity?.typeMismatch,
+ isInvalid: (el) => el.type === 'url' && el.validity?.typeMismatch,
message: s__('Please enter a valid URL format, ex: http://www.example.com/home'),
},
};
const getFeedbackForElement = (feedbackMap, el) =>
- Object.values(feedbackMap).find(f => f.isInvalid(el))?.message || el.validationMessage;
+ Object.values(feedbackMap).find((f) => f.isInvalid(el))?.message || el.validationMessage;
-const focusFirstInvalidInput = e => {
+const focusFirstInvalidInput = (e) => {
const { target: formEl } = e;
const invalidInput = formEl.querySelector('input:invalid');
@@ -33,7 +33,7 @@ const focusFirstInvalidInput = e => {
}
};
-const isEveryFieldValid = form => Object.values(form.fields).every(({ state }) => state === true);
+const isEveryFieldValid = (form) => Object.values(form.fields).every(({ state }) => state === true);
const createValidator = (context, feedbackMap) => ({ el, reportInvalidInput = false }) => {
const { form } = context;
@@ -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 (customFeedbackMap = {}) {
const feedbackMap = merge(defaultFeedbackMap, customFeedbackMap);
const elDataMap = new WeakMap();
diff --git a/app/assets/javascripts/vue_shared/gl_feature_flags_plugin.js b/app/assets/javascripts/vue_shared/gl_feature_flags_plugin.js
index 3488a44bd0f..e1734809bce 100644
--- a/app/assets/javascripts/vue_shared/gl_feature_flags_plugin.js
+++ b/app/assets/javascripts/vue_shared/gl_feature_flags_plugin.js
@@ -1,4 +1,4 @@
-export default Vue => {
+export default (Vue) => {
Vue.mixin({
provide: {
glFeatures: { ...((window.gon && window.gon.features) || {}) },
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
index cdbde55901d..be04ff158e7 100644
--- a/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
+++ b/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
@@ -48,7 +48,7 @@ export default {
this.poll.stop();
const queryString = Object.keys(parameters)
- .map(parameter => {
+ .map((parameter) => {
const value = parameters[parameter];
// update internal state for UI
this[parameter] = value;
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/security_summary.vue b/app/assets/javascripts/vue_shared/security_reports/components/security_summary.vue
index babb9fddcf6..e3aa25a294e 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/security_summary.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/security_summary.vue
@@ -34,13 +34,13 @@ export default {
<template>
<span>
<gl-sprintf :message="message.message">
- <template #total="{content}">
+ <template #total="{ content }">
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
<span v-if="shouldShowCountMessage" class="gl-font-sm">
<gl-sprintf :message="message.countMessage">
- <template v-for="slotName in $options.slotNames" #[slotName]="{content}">
+ <template v-for="slotName in $options.slotNames" #[slotName]="{ content }">
<span :key="slotName">
<strong
v-if="message[slotName] > 0"
diff --git a/app/assets/javascripts/vue_shared/security_reports/constants.js b/app/assets/javascripts/vue_shared/security_reports/constants.js
index 68241a8c5be..dd591f7bba3 100644
--- a/app/assets/javascripts/vue_shared/security_reports/constants.js
+++ b/app/assets/javascripts/vue_shared/security_reports/constants.js
@@ -5,6 +5,15 @@ export const FEEDBACK_TYPE_ISSUE = 'issue';
export const FEEDBACK_TYPE_MERGE_REQUEST = 'merge_request';
/**
+ * Security artifact file types
+ */
+export const REPORT_FILE_TYPES = {
+ ARCHIVE: 'ARCHIVE',
+ TRACE: 'TRACE',
+ METADATA: 'METADATA',
+};
+
+/**
* Security scan report types, as provided by the backend.
*/
export const REPORT_TYPE_SAST = 'sast';
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 bdbf9957ad4..a6c7b59aa71 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
@@ -97,7 +97,7 @@ export default {
projectPath: this.targetProjectFullPath,
iid: String(this.mrIid),
reportTypes: this.$options.reportTypes.map(
- reportType => reportTypeToSecurityReportTypeEnum[reportType],
+ (reportType) => reportTypeToSecurityReportTypeEnum[reportType],
),
};
},
@@ -151,7 +151,7 @@ export default {
created() {
if (!this.canShowDownloads) {
this.checkAvailableSecurityReports(this.$options.reportTypes)
- .then(availableSecurityReports => {
+ .then((availableSecurityReports) => {
this.onCheckingAvailableSecurityReports(Array.from(availableSecurityReports));
})
.catch(this.showError);
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 1e5a60c32fd..443255b0e6a 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/getters.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/getters.js
@@ -3,7 +3,7 @@ import { countVulnerabilities, groupedTextBuilder } from './utils';
import { LOADING, ERROR, SUCCESS } from '~/reports/constants';
import { TRANSLATION_IS_LOADING } from './messages';
-export const summaryCounts = state =>
+export const summaryCounts = (state) =>
countVulnerabilities(
state.reportTypes.reduce((acc, reportType) => {
acc.push(...state[reportType].newIssues);
@@ -50,17 +50,17 @@ export const summaryStatus = (state, getters) => {
return SUCCESS;
};
-export const areReportsLoading = state =>
- state.reportTypes.some(reportType => state[reportType].isLoading);
+export const areReportsLoading = (state) =>
+ state.reportTypes.some((reportType) => state[reportType].isLoading);
-export const areAllReportsLoading = state =>
- state.reportTypes.every(reportType => state[reportType].isLoading);
+export const areAllReportsLoading = (state) =>
+ state.reportTypes.every((reportType) => state[reportType].isLoading);
-export const allReportsHaveError = state =>
- state.reportTypes.every(reportType => state[reportType].hasError);
+export const allReportsHaveError = (state) =>
+ state.reportTypes.every((reportType) => state[reportType].hasError);
-export const anyReportHasError = state =>
- state.reportTypes.some(reportType => state[reportType].hasError);
+export const anyReportHasError = (state) =>
+ state.reportTypes.some((reportType) => state[reportType].hasError);
-export const anyReportHasIssues = state =>
- state.reportTypes.some(reportType => state[reportType].newIssues.length > 0);
+export const anyReportHasIssues = (state) =>
+ state.reportTypes.some((reportType) => state[reportType].newIssues.length > 0);
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 22a45341c51..0f26e3c30ef 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
@@ -15,7 +15,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
dispatch('requestDiff');
return fetchDiffData(rootState, state.paths.diffEndpoint, 'sast')
- .then(data => {
+ .then((data) => {
dispatch('receiveDiffSuccess', data);
})
.catch(() => {
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
index c9da824613d..e3ae5435f5d 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
@@ -15,7 +15,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
dispatch('requestDiff');
return fetchDiffData(rootState, state.paths.diffEndpoint, 'secret_detection')
- .then(data => {
+ .then((data) => {
dispatch('receiveDiffSuccess', data);
})
.catch(() => {
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 c5e786c92b1..fd6613ae11c 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/utils.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
@@ -29,7 +29,7 @@ export const fetchDiffData = (state, endpoint, category) => {
*/
export const enrichVulnerabilityWithFeedback = (vulnerability, feedback = []) =>
feedback
- .filter(fb => fb.project_fingerprint === vulnerability.project_fingerprint)
+ .filter((fb) => fb.project_fingerprint === vulnerability.project_fingerprint)
.reduce((vuln, fb) => {
if (fb.feedback_type === FEEDBACK_TYPE_DISMISSAL) {
return {
@@ -63,7 +63,7 @@ export const enrichVulnerabilityWithFeedback = (vulnerability, feedback = []) =>
* @returns {Object}
*/
export const parseDiff = (diff, enrichData) => {
- const enrichVulnerability = vulnerability => ({
+ const enrichVulnerability = (vulnerability) => ({
...enrichVulnerabilityWithFeedback(vulnerability, enrichData),
category: vulnerability.report_type,
title: vulnerability.message || vulnerability.name,
diff --git a/app/assets/javascripts/vue_shared/security_reports/utils.js b/app/assets/javascripts/vue_shared/security_reports/utils.js
index 827a87f9aaf..ad819bf7081 100644
--- a/app/assets/javascripts/vue_shared/security_reports/utils.js
+++ b/app/assets/javascripts/vue_shared/security_reports/utils.js
@@ -1,4 +1,18 @@
-import { securityReportTypeEnumToReportType } from './constants';
+import { capitalize } from 'lodash';
+import {
+ securityReportTypeEnumToReportType,
+ REPORT_FILE_TYPES,
+} from 'ee_else_ce/vue_shared/security_reports/constants';
+
+const addReportTypeIfExists = (acc, reportTypes, reportType, getName, downloadPath) => {
+ if (reportTypes && reportTypes.includes(reportType)) {
+ acc.push({
+ reportType,
+ name: getName(reportType),
+ path: downloadPath,
+ });
+ }
+};
export const extractSecurityReportArtifacts = (reportTypes, data) => {
const jobs = data.project?.mergeRequest?.headPipeline?.jobs?.nodes ?? [];
@@ -7,14 +21,21 @@ export const extractSecurityReportArtifacts = (reportTypes, data) => {
const artifacts = job.artifacts?.nodes ?? [];
artifacts.forEach(({ downloadPath, fileType }) => {
- const reportType = securityReportTypeEnumToReportType[fileType];
- if (reportType && reportTypes.includes(reportType)) {
- acc.push({
- name: job.name,
- reportType,
- path: downloadPath,
- });
- }
+ addReportTypeIfExists(
+ acc,
+ reportTypes,
+ securityReportTypeEnumToReportType[fileType],
+ () => job.name,
+ downloadPath,
+ );
+
+ addReportTypeIfExists(
+ acc,
+ reportTypes,
+ REPORT_FILE_TYPES[fileType],
+ (reportType) => `${job.name} ${capitalize(reportType)}`,
+ downloadPath,
+ );
});
return acc;
diff --git a/app/assets/javascripts/vue_shared/translate.js b/app/assets/javascripts/vue_shared/translate.js
index e0baf03acc3..616848639f1 100644
--- a/app/assets/javascripts/vue_shared/translate.js
+++ b/app/assets/javascripts/vue_shared/translate.js
@@ -1,6 +1,6 @@
import { __, n__, s__, sprintf } from '../locale';
-export default Vue => {
+export default (Vue) => {
Vue.mixin({
methods: {
/**
diff --git a/app/assets/javascripts/vuex_shared/bindings.js b/app/assets/javascripts/vuex_shared/bindings.js
index cc18b41e2de..741690886b7 100644
--- a/app/assets/javascripts/vuex_shared/bindings.js
+++ b/app/assets/javascripts/vuex_shared/bindings.js
@@ -11,7 +11,7 @@
*/
export const mapComputed = (list, defaultUpdateFn, root) => {
const result = {};
- list.forEach(item => {
+ list.forEach((item) => {
const [getter, key, updateFn] =
typeof item === 'string'
? [false, item, defaultUpdateFn]
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
index 560cabd3bba..0a81f172fe9 100644
--- a/app/assets/javascripts/whats_new/components/app.vue
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -71,7 +71,7 @@ export default {
this.setDrawerBodyHeight(height);
},
featuresForVersion(version) {
- return this.features.filter(feature => {
+ return this.features.filter((feature) => {
return feature.release === parseFloat(version);
});
},
@@ -90,11 +90,12 @@ export default {
ref="drawer"
v-gl-resize-observer="handleResize"
class="whats-new-drawer"
+ :z-index="700"
:open="open"
@close="closeDrawer"
>
<template #header>
- <h4 class="page-title gl-my-2">{{ __("What's new at GitLab") }}</h4>
+ <h4 class="page-title gl-my-2">{{ __("What's new") }}</h4>
</template>
<template v-if="features.length">
<gl-infinite-scroll
diff --git a/app/assets/javascripts/whats_new/index.js b/app/assets/javascripts/whats_new/index.js
index ed0258c3992..6da141cb19a 100644
--- a/app/assets/javascripts/whats_new/index.js
+++ b/app/assets/javascripts/whats_new/index.js
@@ -6,7 +6,7 @@ import { getStorageKey, setNotification } from './utils/notification';
let whatsNewApp;
-export default el => {
+export default (el) => {
if (whatsNewApp) {
store.dispatch('openDrawer');
} else {
diff --git a/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js b/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js
index 21fc90c34a4..7d6c2392974 100644
--- a/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js
+++ b/app/assets/javascripts/whats_new/utils/get_drawer_body_height.js
@@ -1,4 +1,4 @@
-export const getDrawerBodyHeight = drawer => {
+export const getDrawerBodyHeight = (drawer) => {
const drawerViewableHeight = drawer.clientHeight - drawer.getBoundingClientRect().top;
const drawerHeaderHeight = drawer.querySelector('.gl-drawer-header').clientHeight;
diff --git a/app/assets/javascripts/whats_new/utils/notification.js b/app/assets/javascripts/whats_new/utils/notification.js
index f261a089554..52ca8058d1c 100644
--- a/app/assets/javascripts/whats_new/utils/notification.js
+++ b/app/assets/javascripts/whats_new/utils/notification.js
@@ -1,6 +1,6 @@
-export const getStorageKey = appEl => appEl.getAttribute('data-storage-key');
+export const getStorageKey = (appEl) => appEl.getAttribute('data-storage-key');
-export const setNotification = appEl => {
+export const setNotification = (appEl) => {
const storageKey = getStorageKey(appEl);
const notificationEl = document.querySelector('.header-help');
let notificationCountEl = notificationEl.querySelector('.js-whats-new-notification-count');
diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js
index ab0b0b02aa8..06ba2496a99 100644
--- a/app/assets/javascripts/zen_mode.js
+++ b/app/assets/javascripts/zen_mode.js
@@ -1,4 +1,4 @@
-/* eslint-disable consistent-return, class-methods-use-this */
+/* eslint-disable consistent-return */
// Zen Mode (full screen) textarea
//
@@ -6,10 +6,10 @@
/*= provides zen_mode:leave */
import $ from 'jquery';
-import 'vendor/jquery.scrollTo';
import Dropzone from 'dropzone';
import Mousetrap from 'mousetrap';
import 'mousetrap/plugins/pause/mousetrap-pause';
+import { scrollToElement } from '~/lib/utils/common_utils';
Dropzone.autoDiscover = false;
@@ -39,25 +39,21 @@ export default class ZenMode {
constructor() {
this.active_backdrop = null;
this.active_textarea = null;
- $(document).on('click', '.js-zen-enter', e => {
+ $(document).on('click', '.js-zen-enter', (e) => {
e.preventDefault();
return $(e.currentTarget).trigger('zen_mode:enter');
});
- $(document).on('click', '.js-zen-leave', e => {
+ $(document).on('click', '.js-zen-leave', (e) => {
e.preventDefault();
return $(e.currentTarget).trigger('zen_mode:leave');
});
- $(document).on('zen_mode:enter', e => {
- this.enter(
- $(e.target)
- .closest('.md-area')
- .find('.zen-backdrop'),
- );
+ $(document).on('zen_mode:enter', (e) => {
+ this.enter($(e.target).closest('.md-area').find('.zen-backdrop'));
});
$(document).on('zen_mode:leave', () => {
this.exit();
});
- $(document).on('keydown', e => {
+ $(document).on('keydown', (e) => {
// Esc
if (e.keyCode === 27) {
e.preventDefault();
@@ -80,7 +76,7 @@ export default class ZenMode {
if (this.active_textarea) {
Mousetrap.unpause();
this.active_textarea.closest('.zen-backdrop').removeClass('fullscreen');
- this.scrollTo(this.active_textarea);
+ scrollToElement(this.active_textarea, { duration: 0, offset: -100 });
this.active_textarea = null;
this.active_backdrop = null;
@@ -90,10 +86,4 @@ export default class ZenMode {
}
}
}
-
- scrollTo(zenArea) {
- return $.scrollTo(zenArea, 0, {
- offset: -150,
- });
- }
}
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index f56665553ba..42d15635566 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -10,7 +10,6 @@
@import './pages/events';
@import './pages/groups';
@import './pages/help';
-@import './pages/incident_management_list';
@import './pages/issuable';
@import './pages/issues/issue_count_badge';
@import './pages/issues';
@@ -28,6 +27,7 @@
@import './pages/profiles/preferences';
@import './pages/projects';
@import './pages/prometheus';
+@import './pages/registry';
@import './pages/runners';
@import './pages/search';
@import './pages/service_desk';
diff --git a/app/assets/stylesheets/components/avatar.scss b/app/assets/stylesheets/components/avatar.scss
index 67213eedca8..3c8abe43070 100644
--- a/app/assets/stylesheets/components/avatar.scss
+++ b/app/assets/stylesheets/components/avatar.scss
@@ -68,7 +68,7 @@ $avatar-sizes: (
);
$identicon-backgrounds: $identicon-red, $identicon-purple, $identicon-indigo, $identicon-blue, $identicon-teal,
- $identicon-orange, $gray-darker;
+ $identicon-orange, $identicon-gray;
%avatar-circle {
float: left;
@@ -125,8 +125,8 @@ $identicon-backgrounds: $identicon-red, $identicon-purple, $identicon-indigo, $i
.identicon {
text-align: center;
vertical-align: top;
- color: $gray-700;
- background-color: $gray-darker;
+ color: $identicon-text-color;
+ background-color: $identicon-gray;
// Sizes
@each $size, $size-config in $avatar-sizes {
diff --git a/app/assets/stylesheets/components/deployment_instance.scss b/app/assets/stylesheets/components/deployment_instance.scss
new file mode 100644
index 00000000000..a8c3400deca
--- /dev/null
+++ b/app/assets/stylesheets/components/deployment_instance.scss
@@ -0,0 +1,91 @@
+.deployment-instance {
+ width: $gl-padding;
+ height: $gl-padding;
+ margin: 1px;
+ border: 1px solid;
+ border-radius: $border-radius-small;
+ position: relative;
+
+ &-succeeded {
+ background-color: $green-600;
+ border-color: $green-800;
+
+ &.link:hover {
+ background-color: $green-800;
+ border-color: $green-950;
+ }
+ }
+
+ &-running {
+ background-color: $green-300;
+ border-color: $green-600;
+
+ &.link:hover {
+ background-color: $green-500;
+ border-color: $green-800;
+ }
+ }
+
+ &-failed {
+ background-color: $red-600;
+ border-color: $red-800;
+
+ &::before {
+ content: '';
+ border: 1px solid $white;
+ background: $white;
+ transform: rotate(45deg);
+ position: absolute;
+ border-radius: 1px;
+ top: -2px;
+ bottom: -2px;
+ }
+
+ &.link:hover {
+ background-color: $red-800;
+ border-color: $red-950;
+ }
+ }
+
+ &-pending {
+ background-color: $gray-200;
+ border-color: $gray-500;
+
+ &.link:hover {
+ background-color: $gray-300;
+ border-color: $gray-900;
+ }
+ }
+
+ &-unknown {
+ background-color: $white;
+ border-color: $gray-500;
+
+ &.link:hover {
+ background-color: $white;
+ border-color: $gray-900;
+ }
+ }
+
+ &.deployment-instance-canary {
+ &::after {
+ width: 7px;
+ height: 7px;
+ border: 1px solid $white;
+ background-color: $orange-300;
+ border-radius: 50%;
+ content: '';
+ z-index: 1;
+ }
+ }
+
+ &-canary-icon {
+ background-color: transparent;
+ border: 0;
+
+ &::after {
+ width: $gl-padding !important;
+ height: $gl-padding !important;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/components/whats_new.scss b/app/assets/stylesheets/components/whats_new.scss
index 51bf2686be2..3e9060e869b 100644
--- a/app/assets/stylesheets/components/whats_new.scss
+++ b/app/assets/stylesheets/components/whats_new.scss
@@ -57,7 +57,7 @@
}
.whats-new-modal-backdrop {
- z-index: 9;
+ z-index: 699;
}
.whats-new-notification-count {
diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss
index a1e757afe56..0ada5fabde9 100644
--- a/app/assets/stylesheets/framework/blank.scss
+++ b/app/assets/stylesheets/framework/blank.scss
@@ -123,6 +123,10 @@
justify-content: center;
text-align: center;
}
+
+ .blank-state-icon {
+ min-width: 215px;
+ }
}
$experiment-new-project-indigo-700: #41419f;
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 48252762546..745d469e3e8 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -436,11 +436,7 @@
padding: 6px 16px;
margin: 0 0 0 -15px;
height: 46px;
-
- i {
- font-size: 20px;
- color: $gl-text-color-secondary;
- }
+ color: $gl-text-color;
@include media-breakpoint-down(sm) {
display: flex;
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index cf9363b77be..499b9c00116 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -588,6 +588,12 @@ table.code {
// Merge request diff grid layout
.diff-grid {
+ .diff-td {
+ // By default min-width is auto with 1fr which causes some overflow problems
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/296222
+ min-width: 0;
+ }
+
.diff-grid-row {
display: grid;
grid-template-columns: 1fr 1fr;
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index e2335c184b0..41fc4d3dd4e 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -567,14 +567,13 @@
margin-bottom: 10px;
padding: 0 10px;
- .fa,
.input-icon,
.dropdown-input-clear,
.dropdown-input-search {
position: absolute;
top: $gl-padding-8;
right: 20px;
- color: $dropdown-input-fa-color;
+ color: $gray-500;
font-size: 12px;
pointer-events: none;
}
@@ -796,6 +795,14 @@
.navbar-gitlab {
li.dropdown {
position: static;
+
+ &.user-counter {
+ margin-left: 8px !important;
+
+ > a {
+ padding: 0 4px !important;
+ }
+ }
}
}
@@ -979,6 +986,8 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
.labels-select-wrapper {
&.is-standalone {
+ min-width: $input-md-width;
+
.labels-select-dropdown-contents {
max-height: 350px;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index a6a01c7b090..730e10114c3 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -172,7 +172,7 @@
}
li {
- .badge.badge-pill {
+ .badge.badge-pill:not(.merge-request-badge) {
box-shadow: none;
font-weight: $gl-font-weight-bold;
}
@@ -438,7 +438,7 @@
.title-container,
.navbar-nav {
- .badge.badge-pill {
+ .badge.badge-pill:not(.merge-request-badge) {
position: inherit;
font-weight: $gl-font-weight-normal;
margin-left: -6px;
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 73a2170fc68..28577e2801e 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -45,7 +45,8 @@
a {
font-family: $monospace-font;
- display: block;
+ display: flex;
+ justify-content: flex-end;
font-size: $code-font-size !important;
white-space: nowrap;
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 7ba9236b833..e3d02d01496 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -99,6 +99,10 @@
line-height: $list-text-height;
color: $gl-text-color-secondary;
+ @include media-breakpoint-down(xs) {
+ padding-top: $gl-padding-6;
+ }
+
span {
margin-right: 15px;
}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index d867cc96dbc..bef33bd2ef0 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -58,6 +58,19 @@
height: $gl-padding;
}
}
+
+ .copy-email-button { // TODO: replace with utility
+ @include gl-w-full;
+ @include gl-h-full;
+ }
+
+ .copy-email-address {
+ height: 60px;
+
+ &:hover {
+ background: $gray-100;
+ }
+ }
}
.right-sidebar-expanded {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 808813599c5..674ba1a307b 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -516,9 +516,12 @@ $line-removed-dark-transparent: rgba(246, 53, 85, 0.2);
$line-number-old: #f9d7dc;
$line-number-new: #ddfbe6;
$line-number-select: #fbf2da;
+$line-number-commented: #dae5fb;
$line-target-blue: $blue-50;
$line-select-yellow: #fcf8e7;
$line-select-yellow-dark: #f0e2bd;
+$line-commented-blue: #e8effc;
+$line-commented-blue-dark: #bccef0;
$dark-diff-match-bg: rgba($white, 0.3);
$dark-diff-match-color: rgba($white, 0.1);
$diff-image-info-color: #808080;
@@ -546,7 +549,6 @@ $dropdown-vertical-offset: 4px;
$dropdown-empty-row-bg: rgba(#000, 0.04);
$dropdown-shadow-color: rgba(#000, 0.1);
$dropdown-title-btn-color: #bfbfbf;
-$dropdown-input-fa-color: #c7c7c7;
$dropdown-input-focus-shadow: rgba($blue-300, 0.4);
$dropdown-loading-bg: rgba($white, 0.6);
$dropdown-chevron-size: 10px;
@@ -629,12 +631,14 @@ $note-icon-gutter-width: 55px;
/*
* Identicon
*/
+$identicon-text-color: #525252 !default;
$identicon-red: #ffebee !default;
$identicon-purple: #f3e5f5 !default;
$identicon-indigo: #e8eaf6 !default;
$identicon-blue: #e3f2fd !default;
$identicon-teal: #e0f2f1 !default;
$identicon-orange: #fbe9e7 !default;
+$identicon-gray: #eee !default;
/*
* Calendar
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index d9b9f3694c1..6c050f33b07 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -1,4 +1,5 @@
@import '../framework/variables';
+@import './conflict_colors';
@mixin diff-background($background, $idiff, $border) {
background: $background;
@@ -35,11 +36,11 @@
transition: border-left 0.1s ease-out;
&.coverage {
- border-left: 3px solid $coverage;
+ border-left: 4px solid $coverage;
}
&.no-coverage {
- border-left: 3px solid $no-coverage;
+ border-left: 2px solid $no-coverage;
}
}
@@ -51,3 +52,44 @@
color: darken($color, 15%);
}
}
+
+@mixin conflict-colors($theme) {
+ .diff-line-num {
+ &.conflict_marker_our,
+ &.conflict_our {
+ background-color: map-get($conflict-colors, #{$theme}-header-head-neutral);
+ border-color: map-get($conflict-colors, #{$theme}-header-head-neutral);
+ }
+
+ &.conflict_marker_their,
+ &.conflict_their {
+ background-color: map-get($conflict-colors, #{$theme}-header-origin-neutral);
+ border-color: map-get($conflict-colors, #{$theme}-header-origin-neutral);
+ }
+ }
+
+ .line_holder {
+ .line_content,
+ .line-coverage {
+ &.conflict_marker_our {
+ background-color: map-get($conflict-colors, #{$theme}-header-head-neutral);
+ border-color: map-get($conflict-colors, #{$theme}-header-head-neutral);
+ }
+
+ &.conflict_marker_their {
+ background-color: map-get($conflict-colors, #{$theme}-header-origin-neutral);
+ border-color: map-get($conflict-colors, #{$theme}-header-origin-neutral);
+ }
+
+ &.conflict_our {
+ background-color: map-get($conflict-colors, #{$theme}-line-head-neutral);
+ border-color: map-get($conflict-colors, #{$theme}-line-head-neutral);
+ }
+
+ &.conflict_their {
+ background-color: map-get($conflict-colors, #{$theme}-line-origin-neutral);
+ border-color: map-get($conflict-colors, #{$theme}-line-origin-neutral);
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/highlight/conflict_colors.scss b/app/assets/stylesheets/highlight/conflict_colors.scss
new file mode 100644
index 00000000000..98ca3775b72
--- /dev/null
+++ b/app/assets/stylesheets/highlight/conflict_colors.scss
@@ -0,0 +1,119 @@
+// Disabled to use the color map for creating color schemes
+// scss-lint:disable ColorVariable
+$conflict-colors: (
+ white-header-head-neutral : #e1fad7,
+ white-line-head-neutral : #effdec,
+ white-button-head-neutral : #9adb84,
+
+ white-header-head-chosen : #baf0a8,
+ white-line-head-chosen : #e1fad7,
+ white-button-head-chosen : #52c22d,
+
+ white-header-origin-neutral : #e0f0ff,
+ white-line-origin-neutral : #f2f9ff,
+ white-button-origin-neutral : #87c2fa,
+
+ white-header-origin-chosen : #add8ff,
+ white-line-origin-chosen : #e0f0ff,
+ white-button-origin-chosen : #268ced,
+
+ white-header-not-chosen : #f0f0f0,
+ white-line-not-chosen : $gray-light,
+
+ dark-header-head-neutral : rgba(#3f3, 0.2),
+ dark-line-head-neutral : rgba(#3f3, 0.1),
+ dark-button-head-neutral : #40874f,
+
+ dark-header-head-chosen : rgba(#3f3, 0.33),
+ dark-line-head-chosen : rgba(#3f3, 0.2),
+ dark-button-head-chosen : #258537,
+
+ dark-header-origin-neutral : rgba(#2878c9, 0.4),
+ dark-line-origin-neutral : rgba(#2878c9, 0.3),
+ dark-button-origin-neutral : #2a5c8c,
+
+ dark-header-origin-chosen : rgba(#2878c9, 0.6),
+ dark-line-origin-chosen : rgba(#2878c9, 0.4),
+ dark-button-origin-chosen : #1d6cbf,
+
+ dark-header-not-chosen : rgba(#fff, 0.25),
+ dark-line-not-chosen : rgba(#fff, 0.1),
+
+ monokai-header-head-neutral : rgba(#a6e22e, 0.25),
+ monokai-line-head-neutral : rgba(#a6e22e, 0.1),
+ monokai-button-head-neutral : #376b20,
+
+ monokai-header-head-chosen : rgba(#a6e22e, 0.4),
+ monokai-line-head-chosen : rgba(#a6e22e, 0.25),
+ monokai-button-head-chosen : #39800d,
+
+ monokai-header-origin-neutral : rgba(#60d9f1, 0.35),
+ monokai-line-origin-neutral : rgba(#60d9f1, 0.15),
+ monokai-button-origin-neutral : #38848c,
+
+ monokai-header-origin-chosen : rgba(#60d9f1, 0.5),
+ monokai-line-origin-chosen : rgba(#60d9f1, 0.35),
+ monokai-button-origin-chosen : #3ea4b2,
+
+ monokai-header-not-chosen : rgba(#76715d, 0.24),
+ monokai-line-not-chosen : rgba(#76715d, 0.1),
+
+ solarized-light-header-head-neutral : rgba(#859900, 0.37),
+ solarized-light-line-head-neutral : rgba(#859900, 0.2),
+ solarized-light-button-head-neutral : #afb262,
+
+ solarized-light-header-head-chosen : rgba(#859900, 0.5),
+ solarized-light-line-head-chosen : rgba(#859900, 0.37),
+ solarized-light-button-head-chosen : #94993d,
+
+ solarized-light-header-origin-neutral : rgba(#2878c9, 0.37),
+ solarized-light-line-origin-neutral : rgba(#2878c9, 0.15),
+ solarized-light-button-origin-neutral : #60a1bf,
+
+ solarized-light-header-origin-chosen : rgba(#2878c9, 0.6),
+ solarized-light-line-origin-chosen : rgba(#2878c9, 0.37),
+ solarized-light-button-origin-chosen : #2482b2,
+
+ solarized-light-header-not-chosen : rgba(#839496, 0.37),
+ solarized-light-line-not-chosen : rgba(#839496, 0.2),
+
+ solarized-dark-header-head-neutral : rgba(#859900, 0.35),
+ solarized-dark-line-head-neutral : rgba(#859900, 0.15),
+ solarized-dark-button-head-neutral : #376b20,
+
+ solarized-dark-header-head-chosen : rgba(#859900, 0.5),
+ solarized-dark-line-head-chosen : rgba(#859900, 0.35),
+ solarized-dark-button-head-chosen : #39800d,
+
+ solarized-dark-header-origin-neutral : rgba(#2878c9, 0.35),
+ solarized-dark-line-origin-neutral : rgba(#2878c9, 0.15),
+ solarized-dark-button-origin-neutral : #086799,
+
+ solarized-dark-header-origin-chosen : rgba(#2878c9, 0.6),
+ solarized-dark-line-origin-chosen : rgba(#2878c9, 0.35),
+ solarized-dark-button-origin-chosen : #0082cc,
+
+ solarized_dark_header_not_chosen : rgba(#839496, 0.25),
+ solarized_dark_line_not_chosen : rgba(#839496, 0.15),
+
+ none_header_head_neutral : $gray-normal,
+ none_line_head_neutral : $gray-normal,
+ none_button_head_neutral : $gray-normal,
+
+ none_header_head_chosen : $gray-darker,
+ none_line_head_chosen : $gray-darker,
+ none_button_head_chosen : $gray-darker,
+
+ none_header_origin_neutral : $gray-normal,
+ none_line_origin_neutral : $gray-normal,
+ none_button_origin_neutral : $gray-normal,
+
+ none_header_origin_chosen : $gray-darker,
+ none_line_origin_chosen : $gray-darker,
+ none_button_origin_chosen : $gray-darker,
+
+ none_header_not_chosen : $gray-light,
+ none_line_not_chosen : $gray-light
+
+);
+// scss-lint:enable ColorVariable
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index d51d5b7137d..64387fbce09 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -24,8 +24,8 @@ $dark-pre-hll-bg: #373b41;
$dark-hll-bg: #373b41;
$dark-over-bg: #9f9ab5;
$dark-expanded-bg: #3e3e3e;
-$dark-coverage: #b5bd68;
-$dark-no-coverage: #de935f;
+$dark-coverage: #b3e841;
+$dark-no-coverage: #ff4f33;
$dark-c: #969896;
$dark-err: #c66;
$dark-k: #b294bb;
@@ -198,6 +198,8 @@ $dark-il: #de935f;
}
}
+ @include conflict-colors('dark');
+
// highlight line via anchor
pre .hll {
background-color: $dark-pre-hll-bg !important;
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index e690f9c7c74..119908ffba8 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -198,6 +198,8 @@ $monokai-gi: #a6e22e;
}
}
+ @include conflict-colors('monokai');
+
// highlight line via anchor
pre .hll {
background-color: $monokai-hll !important;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index 8c532f53182..f95f5393323 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -202,6 +202,8 @@ $solarized-dark-il: #2aa198;
}
}
+ @include conflict-colors('solarized-dark');
+
// highlight line via anchor
pre .hll {
background-color: $solarized-dark-hll-bg !important;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index 1f9042a9534..dc4bc2f32c2 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -210,6 +210,8 @@ $solarized-light-il: #2aa198;
}
}
+ @include conflict-colors('solarized-light');
+
// highlight line via anchor
pre .hll {
background-color: $solarized-light-hll-bg !important;
diff --git a/app/assets/stylesheets/highlight/themes/white.scss b/app/assets/stylesheets/highlight/themes/white.scss
index 6362dd734f6..ed1d9c924c0 100644
--- a/app/assets/stylesheets/highlight/themes/white.scss
+++ b/app/assets/stylesheets/highlight/themes/white.scss
@@ -1,3 +1,5 @@
.code.white {
@import '../white_base';
+
+ @include conflict-colors('white');
}
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index bb5ca94af33..777332881f3 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -81,6 +81,17 @@ $white-gc-bg: #eaf2f5;
.line-numbers,
.diff-line-num {
background-color: $gray-light;
+
+ &.conflict_marker,
+ &.conflict_our {
+ background-color: map-get($conflict-colors, 'white-header-head-neutral');
+ border-color: map-get($conflict-colors, 'white-header-head-neutral');
+ }
+
+ &.conflict_their {
+ background-color: map-get($conflict-colors, 'white-header-origin-neutral');
+ border-color: map-get($conflict-colors, 'white-header-origin-neutral');
+ }
}
.diff-line-num,
@@ -115,7 +126,7 @@ pre.code,
.diff-grid-left:hover,
.diff-grid-right:hover {
- .diff-line-num:not(.empty-cell) {
+ .diff-line-num:not(.empty-cell):not(.conflict_marker_their):not(.conflict_marker_our) {
@include line-number-hover($white-over-bg);
}
}
@@ -203,7 +214,7 @@ pre.code,
}
.line-coverage {
- @include line-coverage-border-color($green-500, $orange-500);
+ @include line-coverage-border-color($green-400, $red-400);
&.old {
background-color: $line-removed;
diff --git a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
index 52cc7d3449e..093cba3560f 100644
--- a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
@@ -85,13 +85,12 @@
color: var(--ide-input-border, $gl-text-color-tertiary);
}
- .dropdown-input .fa,
.dropdown-input .dropdown-input-clear {
- color: var(--ide-input-border, $dropdown-input-fa-color);
+ color: var(--ide-input-border, $gray-500);
}
.ide-nav-form .input-icon {
- color: var(--ide-input-border, $dropdown-input-fa-color);
+ color: var(--ide-input-border, $gray-500);
}
code {
diff --git a/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss b/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
index cc876c9a635..72e2a45565e 100644
--- a/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
+++ b/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
@@ -148,18 +148,13 @@
&:hover {
box-shadow: inset 0 0 0 0.0625rem $dropdown-toggle-active-border-color;
- background-color: $gray-darker;
-
- svg {
- fill: $gl-text-color;
- }
+ background-color: var(--gray-50, $gray-50);
}
.spinner,
svg {
width: $ci-action-dropdown-svg-size;
height: $ci-action-dropdown-svg-size;
- fill: $gl-text-color-secondary;
position: relative;
top: 1px;
vertical-align: initial;
diff --git a/app/assets/stylesheets/page_bundles/environments.scss b/app/assets/stylesheets/page_bundles/environments.scss
index 871f118ea9d..7d5f501d633 100644
--- a/app/assets/stylesheets/page_bundles/environments.scss
+++ b/app/assets/stylesheets/page_bundles/environments.scss
@@ -129,3 +129,92 @@
width: 38px;
}
}
+
+/**
+ * Deploy boards
+*/
+.deploy-board {
+ background-color: var(--gray-50, $gray-50);
+ min-height: 20px;
+
+ > .loading-icon,
+ > .deploy-board-empty,
+ > .deploy-board-information {
+ padding: 10px;
+ }
+
+ .deploy-board-information {
+ display: flex;
+ justify-content: space-between;
+
+ .deploy-board-status {
+ order: 1;
+ display: flex;
+ width: 70px;
+ flex-wrap: wrap;
+ justify-content: center;
+ margin: 20px 0 0 5px;
+ }
+
+ .deploy-board-instances {
+ order: 2;
+ margin-left: 20px;
+ width: 100%;
+ }
+
+ .deploy-board-canary-ingress {
+ order: 7;
+ }
+
+ .deploy-board-actions {
+ order: 3;
+ align-self: center;
+ min-width: 150px;
+ margin-left: 10px;
+ }
+
+ &.deploy-board-error-message {
+ justify-content: center;
+ }
+
+ .deploy-board-empty-state-svg {
+ order: 1;
+ width: 90px;
+ margin: auto 0 auto 20px;
+ }
+
+ .deploy-board-empty-state-text {
+ order: 2;
+ flex-wrap: wrap;
+ margin: auto auto 15px 0;
+ }
+
+ .deploy-board-empty-state-title {
+ order: 1;
+ font-size: 17px;
+ line-height: 40px;
+ }
+ }
+
+ .deploy-board-legend .legend-text {
+ color: var(--gray-900, $gray-900);
+ font-size: $gl-font-size-small;
+ font-weight: $gl-font-weight-bold;
+ line-height: $gl-line-height-14;
+ }
+}
+
+.deploy-board-icon {
+ display: none;
+
+ @include media-breakpoint-up(md) {
+ float: left;
+ display: block;
+ }
+
+ i {
+ cursor: pointer;
+ color: var(--gray-200, $gray-200);
+ padding-right: 10px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/error_tracking_index.scss b/app/assets/stylesheets/page_bundles/error_tracking_index.scss
index 65bddfb7890..5c49bcc0348 100644
--- a/app/assets/stylesheets/page_bundles/error_tracking_index.scss
+++ b/app/assets/stylesheets/page_bundles/error_tracking_index.scss
@@ -5,6 +5,10 @@
min-width: auto;
}
+ .filtered-search-box .form-control {
+ min-width: unset;
+ }
+
.sort-control {
.btn {
padding-right: 2rem;
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 15cc10d1532..f6b9473d235 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -179,6 +179,10 @@ $ide-commit-header-height: 48px;
overflow: auto;
padding: $gl-padding;
background-color: var(--ide-empty-state-background, transparent);
+
+ .md {
+ max-width: $limited-layout-width;
+ }
}
.file-container {
diff --git a/app/assets/stylesheets/page_bundles/incident_management_list.scss b/app/assets/stylesheets/page_bundles/incident_management_list.scss
new file mode 100644
index 00000000000..30a75103c30
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/incident_management_list.scss
@@ -0,0 +1,153 @@
+@import 'mixins_and_variables_and_functions';
+
+.incident-management-list {
+ .new-alert {
+ background-color: var(--green-50, $green-50);
+ }
+
+ // these styles need to be deleted once GlTable component looks in GitLab same as in @gitlab/ui
+ table {
+ color: var(--gray-500, $gray-500);
+
+ tbody {
+ tr:not(.b-table-busy-slot):not(.b-table-empty-row) {
+ &:hover {
+ @include gl-border-t-double;
+
+ td {
+ @include gl-border-b-initial;
+ }
+ }
+ }
+ }
+
+ tr {
+ &:focus {
+ @include gl-outline-none;
+ }
+
+ td,
+ th {
+ @include gl-py-5;
+ @include gl-outline-none;
+ @include gl-relative;
+ }
+
+ th {
+ @include gl-bg-transparent;
+ @include gl-font-weight-bold;
+ color: var(--gray-400, $gray-400);
+
+
+ &[aria-sort='none']:hover {
+ background-image: url('data:image/svg+xml, %3csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="4 0 8 16"%3e %3cpath style="fill: %23BABABA;" fill-rule="evenodd" d="M11.707085,11.7071 L7.999975,15.4142 L4.292875,11.7071 C3.902375,11.3166 3.902375, 10.6834 4.292875,10.2929 C4.683375,9.90237 5.316575,9.90237 5.707075,10.2929 L6.999975, 11.5858 L6.999975,2 C6.999975,1.44771 7.447695,1 7.999975,1 C8.552255,1 8.999975,1.44771 8.999975,2 L8.999975,11.5858 L10.292865,10.2929 C10.683395 ,9.90237 11.316555,9.90237 11.707085,10.2929 C12.097605,10.6834 12.097605,11.3166 11.707085,11.7071 Z"/%3e %3c/svg%3e');
+ }
+ }
+ }
+
+ @include media-breakpoint-up(md) {
+ tr {
+ &:last-child {
+ td {
+ @include gl-border-0;
+ }
+ }
+ }
+
+ .sortable-cell {
+ padding-left: calc(0.75rem + 0.65em);
+ }
+ }
+ }
+
+ @include media-breakpoint-down(sm) {
+ table {
+ tr {
+ @include gl-border-t-0;
+
+ .table-col {
+ min-height: 68px;
+ }
+
+ &:hover {
+ background-color: var(--white, $white);
+ @include gl-border-none;
+ }
+
+ th,
+ td {
+ @include gl-pt-6;
+ }
+ }
+
+ &.alert-management-table {
+ .table-col {
+ &:last-child {
+ background-color: var(--gray-10, $gray-10);
+
+ &::before {
+ content: none !important;
+ }
+
+ div:not(.dropdown-title) {
+ width: 100% !important;
+ padding: 0 !important;
+ }
+ }
+ }
+ }
+
+ .b-table-empty-row {
+ td {
+ @include gl-border-b-0;
+
+ div {
+ text-align: unset !important;
+ }
+ }
+ }
+
+ .b-table-busy-slot {
+ td {
+ @include gl-border-b-0;
+
+ div {
+ text-align: center !important;
+ }
+ }
+ }
+ }
+ }
+
+ .gl-tabs-nav {
+ @include gl-border-b-0;
+
+ .gl-tab-nav-item {
+ color: var(--gray-500, $gray-500);
+
+ > .gl-tab-counter-badge {
+ @include gl-reset-color;
+ @include gl-font-sm;
+ background-color: var(--gray-50, $gray-50);
+ }
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .list-header {
+ @include gl-flex-direction-column-reverse;
+ }
+
+ .create-incident-button {
+ @include gl-w-full;
+ }
+ }
+
+ .integration-list {
+ .b-table-empty-row {
+ td {
+ @include gl-px-0;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index c3e49da92a6..231723ca4e3 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -1,6 +1,23 @@
@import 'mixins_and_variables_and_functions';
+
+@import '@gitlab/ui/src/scss/bootstrap';
+@import 'bootstrap-vue/src/index';
+
+@import '@gitlab/ui/src/scss/utilities';
+@import '@gitlab/ui/src/components/base/alert/alert';
+
// We should only import styles that we actually use.
-// @import '@gitlab/ui/src/scss/gitlab_ui';
+@import '@gitlab/ui/src/components/base/alert/alert';
+@import '@gitlab/ui/src/components/base/avatar/avatar';
+@import '@gitlab/ui/src/components/base/badge/badge';
+@import '@gitlab/ui/src/components/base/button/button';
+@import '@gitlab/ui/src/components/base/icon/icon';
+@import '@gitlab/ui/src/components/base/link/link';
+@import '@gitlab/ui/src/components/base/loading_icon/loading_icon';
+@import '@gitlab/ui/src/components/base/modal/modal';
+@import '@gitlab/ui/src/components/base/pagination/pagination';
+@import '@gitlab/ui/src/components/base/tabs/tabs/tabs';
+@import '@gitlab/ui/src/components/base/tooltip/tooltip';
$atlaskit-border-color: #dfe1e6;
@@ -40,14 +57,16 @@ $header-height: 40px;
}
.jira-connect-user {
- float: right;
- position: relative;
- top: -30px;
+ font-size: $gl-font-size;
+ position: fixed;
+ top: 10px;
+ right: 20px;
}
.jira-connect-app {
margin-top: $header-height;
max-width: 600px;
+ min-height: 95vh;
padding-top: 48px;
padding-left: 16px;
padding-right: 16px;
@@ -108,5 +127,6 @@ svg {
}
.browser-limitations-notice {
+ font-size: $gl-font-size;
margin-top: 32px;
}
diff --git a/app/assets/stylesheets/page_bundles/merge_conflicts.scss b/app/assets/stylesheets/page_bundles/merge_conflicts.scss
index a26affb10a9..d7473d2c942 100644
--- a/app/assets/stylesheets/page_bundles/merge_conflicts.scss
+++ b/app/assets/stylesheets/page_bundles/merge_conflicts.scss
@@ -1,183 +1,65 @@
@import 'mixins_and_variables_and_functions';
-// Disabled to use the color map for creating color schemes
-// scss-lint:disable ColorVariable
-$colors: (
- white-header-head-neutral : #e1fad7,
- white-line-head-neutral : #effdec,
- white-button-head-neutral : #9adb84,
-
- white-header-head-chosen : #baf0a8,
- white-line-head-chosen : #e1fad7,
- white-button-head-chosen : #52c22d,
-
- white-header-origin-neutral : #e0f0ff,
- white-line-origin-neutral : #f2f9ff,
- white-button-origin-neutral : #87c2fa,
-
- white-header-origin-chosen : #add8ff,
- white-line-origin-chosen : #e0f0ff,
- white-button-origin-chosen : #268ced,
-
- white-header-not-chosen : #f0f0f0,
- white-line-not-chosen : $gray-light,
-
- dark-header-head-neutral : rgba(#3f3, 0.2),
- dark-line-head-neutral : rgba(#3f3, 0.1),
- dark-button-head-neutral : #40874f,
-
- dark-header-head-chosen : rgba(#3f3, 0.33),
- dark-line-head-chosen : rgba(#3f3, 0.2),
- dark-button-head-chosen : #258537,
-
- dark-header-origin-neutral : rgba(#2878c9, 0.4),
- dark-line-origin-neutral : rgba(#2878c9, 0.3),
- dark-button-origin-neutral : #2a5c8c,
-
- dark-header-origin-chosen : rgba(#2878c9, 0.6),
- dark-line-origin-chosen : rgba(#2878c9, 0.4),
- dark-button-origin-chosen : #1d6cbf,
-
- dark-header-not-chosen : rgba(#fff, 0.25),
- dark-line-not-chosen : rgba(#fff, 0.1),
-
- monokai-header-head-neutral : rgba(#a6e22e, 0.25),
- monokai-line-head-neutral : rgba(#a6e22e, 0.1),
- monokai-button-head-neutral : #376b20,
-
- monokai-header-head-chosen : rgba(#a6e22e, 0.4),
- monokai-line-head-chosen : rgba(#a6e22e, 0.25),
- monokai-button-head-chosen : #39800d,
-
- monokai-header-origin-neutral : rgba(#60d9f1, 0.35),
- monokai-line-origin-neutral : rgba(#60d9f1, 0.15),
- monokai-button-origin-neutral : #38848c,
-
- monokai-header-origin-chosen : rgba(#60d9f1, 0.5),
- monokai-line-origin-chosen : rgba(#60d9f1, 0.35),
- monokai-button-origin-chosen : #3ea4b2,
-
- monokai-header-not-chosen : rgba(#76715d, 0.24),
- monokai-line-not-chosen : rgba(#76715d, 0.1),
-
- solarized-light-header-head-neutral : rgba(#859900, 0.37),
- solarized-light-line-head-neutral : rgba(#859900, 0.2),
- solarized-light-button-head-neutral : #afb262,
-
- solarized-light-header-head-chosen : rgba(#859900, 0.5),
- solarized-light-line-head-chosen : rgba(#859900, 0.37),
- solarized-light-button-head-chosen : #94993d,
-
- solarized-light-header-origin-neutral : rgba(#2878c9, 0.37),
- solarized-light-line-origin-neutral : rgba(#2878c9, 0.15),
- solarized-light-button-origin-neutral : #60a1bf,
-
- solarized-light-header-origin-chosen : rgba(#2878c9, 0.6),
- solarized-light-line-origin-chosen : rgba(#2878c9, 0.37),
- solarized-light-button-origin-chosen : #2482b2,
-
- solarized-light-header-not-chosen : rgba(#839496, 0.37),
- solarized-light-line-not-chosen : rgba(#839496, 0.2),
-
- solarized-dark-header-head-neutral : rgba(#859900, 0.35),
- solarized-dark-line-head-neutral : rgba(#859900, 0.15),
- solarized-dark-button-head-neutral : #376b20,
-
- solarized-dark-header-head-chosen : rgba(#859900, 0.5),
- solarized-dark-line-head-chosen : rgba(#859900, 0.35),
- solarized-dark-button-head-chosen : #39800d,
-
- solarized-dark-header-origin-neutral : rgba(#2878c9, 0.35),
- solarized-dark-line-origin-neutral : rgba(#2878c9, 0.15),
- solarized-dark-button-origin-neutral : #086799,
-
- solarized-dark-header-origin-chosen : rgba(#2878c9, 0.6),
- solarized-dark-line-origin-chosen : rgba(#2878c9, 0.35),
- solarized-dark-button-origin-chosen : #0082cc,
-
- solarized_dark_header_not_chosen : rgba(#839496, 0.25),
- solarized_dark_line_not_chosen : rgba(#839496, 0.15),
-
- none_header_head_neutral : $gray-normal,
- none_line_head_neutral : $gray-normal,
- none_button_head_neutral : $gray-normal,
-
- none_header_head_chosen : $gray-darker,
- none_line_head_chosen : $gray-darker,
- none_button_head_chosen : $gray-darker,
-
- none_header_origin_neutral : $gray-normal,
- none_line_origin_neutral : $gray-normal,
- none_button_origin_neutral : $gray-normal,
-
- none_header_origin_chosen : $gray-darker,
- none_line_origin_chosen : $gray-darker,
- none_button_origin_chosen : $gray-darker,
-
- none_header_not_chosen : $gray-light,
- none_line_not_chosen : $gray-light
-
-);
-// scss-lint:enable ColorVariable
+@import '../highlight/conflict_colors';
@mixin color-scheme($color) {
.header.line_content,
.diff-line-num {
&.origin {
- background-color: map-get($colors, #{$color}-header-origin-neutral);
- border-color: map-get($colors, #{$color}-header-origin-neutral);
+ background-color: map-get($conflict-colors, #{$color}-header-origin-neutral);
+ border-color: map-get($conflict-colors, #{$color}-header-origin-neutral);
button {
- background-color: map-get($colors, #{$color}-button-origin-neutral);
- border-color: darken(map-get($colors, #{$color}-button-origin-neutral), 15);
+ background-color: map-get($conflict-colors, #{$color}-button-origin-neutral);
+ border-color: darken(map-get($conflict-colors, #{$color}-button-origin-neutral), 15);
}
&.selected {
- background-color: map-get($colors, #{$color}-header-origin-chosen);
- border-color: map-get($colors, #{$color}-header-origin-chosen);
+ background-color: map-get($conflict-colors, #{$color}-header-origin-chosen);
+ border-color: map-get($conflict-colors, #{$color}-header-origin-chosen);
button {
- background-color: map-get($colors, #{$color}-button-origin-chosen);
- border-color: darken(map-get($colors, #{$color}-button-origin-chosen), 15);
+ background-color: map-get($conflict-colors, #{$color}-button-origin-chosen);
+ border-color: darken(map-get($conflict-colors, #{$color}-button-origin-chosen), 15);
}
}
&.unselected {
- background-color: map-get($colors, #{$color}-header-not-chosen);
- border-color: map-get($colors, #{$color}-header-not-chosen);
+ background-color: map-get($conflict-colors, #{$color}-header-not-chosen);
+ border-color: map-get($conflict-colors, #{$color}-header-not-chosen);
button {
- background-color: lighten(map-get($colors, #{$color}-button-origin-neutral), 15);
- border-color: map-get($colors, #{$color}-button-origin-neutral);
+ background-color: lighten(map-get($conflict-colors, #{$color}-button-origin-neutral), 15);
+ border-color: map-get($conflict-colors, #{$color}-button-origin-neutral);
}
}
}
&.head {
- background-color: map-get($colors, #{$color}-header-head-neutral);
- border-color: map-get($colors, #{$color}-header-head-neutral);
+ background-color: map-get($conflict-colors, #{$color}-header-head-neutral);
+ border-color: map-get($conflict-colors, #{$color}-header-head-neutral);
button {
- background-color: map-get($colors, #{$color}-button-head-neutral);
- border-color: darken(map-get($colors, #{$color}-button-head-neutral), 15);
+ background-color: map-get($conflict-colors, #{$color}-button-head-neutral);
+ border-color: darken(map-get($conflict-colors, #{$color}-button-head-neutral), 15);
}
&.selected {
- background-color: map-get($colors, #{$color}-header-head-chosen);
- border-color: map-get($colors, #{$color}-header-head-chosen);
+ background-color: map-get($conflict-colors, #{$color}-header-head-chosen);
+ border-color: map-get($conflict-colors, #{$color}-header-head-chosen);
button {
- background-color: map-get($colors, #{$color}-button-head-chosen);
- border-color: darken(map-get($colors, #{$color}-button-head-chosen), 15);
+ background-color: map-get($conflict-colors, #{$color}-button-head-chosen);
+ border-color: darken(map-get($conflict-colors, #{$color}-button-head-chosen), 15);
}
}
&.unselected {
- background-color: map-get($colors, #{$color}-header-not-chosen);
- border-color: map-get($colors, #{$color}-header-not-chosen);
+ background-color: map-get($conflict-colors, #{$color}-header-not-chosen);
+ border-color: map-get($conflict-colors, #{$color}-header-not-chosen);
button {
- background-color: lighten(map-get($colors, #{$color}-button-head-neutral), 15);
- border-color: map-get($colors, #{$color}-button-head-neutral);
+ background-color: lighten(map-get($conflict-colors, #{$color}-button-head-neutral), 15);
+ border-color: map-get($conflict-colors, #{$color}-button-head-neutral);
}
}
}
@@ -185,26 +67,26 @@ $colors: (
.line_content {
&.origin {
- background-color: map-get($colors, #{$color}-line-origin-neutral);
+ background-color: map-get($conflict-colors, #{$color}-line-origin-neutral);
&.selected {
- background-color: map-get($colors, #{$color}-line-origin-chosen);
+ background-color: map-get($conflict-colors, #{$color}-line-origin-chosen);
}
&.unselected {
- background-color: map-get($colors, #{$color}-line-not-chosen);
+ background-color: map-get($conflict-colors, #{$color}-line-not-chosen);
}
}
&.head {
- background-color: map-get($colors, #{$color}-line-head-neutral);
+ background-color: map-get($conflict-colors, #{$color}-line-head-neutral);
&.selected {
- background-color: map-get($colors, #{$color}-line-head-chosen);
+ background-color: map-get($conflict-colors, #{$color}-line-head-chosen);
}
&.unselected {
- background-color: map-get($colors, #{$color}-line-not-chosen);
+ background-color: map-get($conflict-colors, #{$color}-line-not-chosen);
}
}
}
diff --git a/app/assets/stylesheets/page_bundles/oncall_schedules.scss b/app/assets/stylesheets/page_bundles/oncall_schedules.scss
index 3c95ecc9bf0..1b190024457 100644
--- a/app/assets/stylesheets/page_bundles/oncall_schedules.scss
+++ b/app/assets/stylesheets/page_bundles/oncall_schedules.scss
@@ -29,6 +29,22 @@
}
}
+.rotations-modal {
+ .gl-card {
+ min-width: 75%;
+ }
+
+ &.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
$header-item-height: 72px;
$item-height: 40px;
@@ -97,8 +113,6 @@ $column-right-gradient: linear-gradient(to right, $gradient-dark-gray 0%, $gradi
}
.item-label {
- @include gl-py-4;
- @include gl-pl-4;
border-right: $border-style;
border-bottom: $border-style;
}
diff --git a/app/assets/stylesheets/page_bundles/wiki.scss b/app/assets/stylesheets/page_bundles/wiki.scss
index eb34e7f3876..9f0fa137910 100644
--- a/app/assets/stylesheets/page_bundles/wiki.scss
+++ b/app/assets/stylesheets/page_bundles/wiki.scss
@@ -15,11 +15,6 @@
padding: 11px 0;
}
- .wiki-page-title {
- margin: 0;
- font-size: 22px;
- }
-
.wiki-last-edit-by {
display: block;
color: var(--gray-500, $gray-500);
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index e0e10d63f8e..52bd16d1a79 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -181,6 +181,7 @@
.license-selector,
.gitignore-selector,
.gitlab-ci-yml-selector,
+ .gitlab-ci-syntax-yml-selector,
.dockerfile-selector,
.template-type-selector,
.metrics-dashboard-selector {
diff --git a/app/assets/stylesheets/pages/incident_management_list.scss b/app/assets/stylesheets/pages/incident_management_list.scss
deleted file mode 100644
index ba363e2d119..00000000000
--- a/app/assets/stylesheets/pages/incident_management_list.scss
+++ /dev/null
@@ -1,150 +0,0 @@
-.incident-management-list {
- .new-alert {
- background-color: $issues-today-bg;
- }
-
- // these styles need to be deleted once GlTable component looks in GitLab same as in @gitlab/ui
- table {
- @include gl-text-gray-500;
-
- tbody {
- tr:not(.b-table-busy-slot):not(.b-table-empty-row) {
- &:hover {
- @include gl-border-t-double;
-
- td {
- @include gl-border-b-initial;
- }
- }
- }
- }
-
- tr {
- &:focus {
- @include gl-outline-none;
- }
-
- td,
- th {
- @include gl-py-5;
- @include gl-outline-none;
- @include gl-relative;
- }
-
- th {
- @include gl-bg-transparent;
- @include gl-font-weight-bold;
- @include gl-text-gray-400;
-
- &[aria-sort='none']:hover {
- background-image: url('data:image/svg+xml, %3csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="4 0 8 16"%3e %3cpath style="fill: %23BABABA;" fill-rule="evenodd" d="M11.707085,11.7071 L7.999975,15.4142 L4.292875,11.7071 C3.902375,11.3166 3.902375, 10.6834 4.292875,10.2929 C4.683375,9.90237 5.316575,9.90237 5.707075,10.2929 L6.999975, 11.5858 L6.999975,2 C6.999975,1.44771 7.447695,1 7.999975,1 C8.552255,1 8.999975,1.44771 8.999975,2 L8.999975,11.5858 L10.292865,10.2929 C10.683395 ,9.90237 11.316555,9.90237 11.707085,10.2929 C12.097605,10.6834 12.097605,11.3166 11.707085,11.7071 Z"/%3e %3c/svg%3e');
- }
- }
- }
-
- @include media-breakpoint-up(md) {
- tr {
- &:last-child {
- td {
- @include gl-border-0;
- }
- }
- }
-
- .sortable-cell {
- padding-left: calc(0.75rem + 0.65em);
- }
- }
- }
-
- @include media-breakpoint-down(sm) {
- table {
- tr {
- @include gl-border-t-0;
-
- .table-col {
- min-height: 68px;
- }
-
- &:hover {
- @include gl-bg-white;
- @include gl-border-none;
- }
-
- th,
- td {
- @include gl-pt-6;
- }
- }
-
- &.alert-management-table {
- .table-col {
- &:last-child {
- @include gl-bg-gray-10;
-
- &::before {
- content: none !important;
- }
-
- div:not(.dropdown-title) {
- width: 100% !important;
- padding: 0 !important;
- }
- }
- }
- }
-
- .b-table-empty-row {
- td {
- @include gl-border-b-0;
-
- div {
- text-align: unset !important;
- }
- }
- }
-
- .b-table-busy-slot {
- td {
- @include gl-border-b-0;
-
- div {
- text-align: center !important;
- }
- }
- }
- }
- }
-
- .gl-tabs-nav {
- @include gl-border-b-0;
-
- .gl-tab-nav-item {
- @include gl-text-gray-500;
-
- > .gl-tab-counter-badge {
- @include gl-reset-color;
- @include gl-font-sm;
- @include gl-bg-gray-50;
- }
- }
- }
-
- @include media-breakpoint-down(xs) {
- .list-header {
- @include gl-flex-direction-column-reverse;
- }
-
- .create-incident-button {
- @include gl-w-full;
- }
- }
-
- .integration-list {
- .b-table-empty-row {
- td {
- @include gl-px-0;
- }
- }
- }
-}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index efca82def92..b99e619cc98 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -124,7 +124,7 @@ $mr-widget-min-height: 69px;
padding: $gl-padding;
@include media-breakpoint-up(md) {
- padding-left: $gl-padding-8 * 7;
+ margin-left: $gl-spacing-scale-7;
}
}
}
@@ -301,7 +301,8 @@ $mr-widget-min-height: 69px;
margin: 0 0 0 10px;
}
- .bold {
+ .bold,
+ .gl-font-weight-bold {
font-weight: $gl-font-weight-bold;
color: $gray-600;
margin-left: 10px;
@@ -317,7 +318,8 @@ $mr-widget-min-height: 69px;
}
.spacing,
- .bold {
+ .bold,
+ .gl-font-weight-bold {
vertical-align: middle;
}
@@ -394,10 +396,6 @@ $mr-widget-min-height: 69px;
}
}
- .mr-widget-help {
- padding: 10px 16px 10px ($gl-padding-8 * 7);
- }
-
.ci-coverage {
float: right;
}
@@ -1016,3 +1014,11 @@ $mr-widget-min-height: 69px;
vertical-align: middle;
}
}
+
+.mr-ready-to-merge-loader {
+ max-width: 418px;
+
+ > svg {
+ vertical-align: middle;
+ }
+}
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 0c24ea9ccc6..254ad96bb57 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -100,8 +100,6 @@
color: $orange-600;
background-color: $orange-50;
border-radius: $border-radius-default $border-radius-default 0 0;
- border: 1px solid $border-gray-normal;
- border-bottom: 0;
padding: 3px 12px;
margin: auto;
align-items: center;
@@ -454,3 +452,9 @@ table {
.markdown-selector {
color: $blue-600;
}
+
+.comment-warning-wrapper {
+ .md-area {
+ border: 0;
+ }
+}
diff --git a/app/assets/stylesheets/pages/registry.scss b/app/assets/stylesheets/pages/registry.scss
new file mode 100644
index 00000000000..31c6dbd2970
--- /dev/null
+++ b/app/assets/stylesheets/pages/registry.scss
@@ -0,0 +1,8 @@
+// Workaround for gl-breadcrumb at the last child of the handwritten breadcrumb
+// until this gitlab-ui issue is resolved: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1079
+//
+// See app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue when this is changed.
+.breadcrumbs-container .gl-breadcrumbs {
+ padding: 0;
+ box-shadow: none;
+}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 335e177d169..f31b6d96f03 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -43,7 +43,7 @@
.settings-header {
position: relative;
- padding: 20px 110px 0 0;
+ padding: 24px 110px 0 0;
h4 {
margin-top: 0;
diff --git a/app/assets/stylesheets/pages/settings_ci_cd.scss b/app/assets/stylesheets/pages/settings_ci_cd.scss
index ebf21f58208..346b3f61caa 100644
--- a/app/assets/stylesheets/pages/settings_ci_cd.scss
+++ b/app/assets/stylesheets/pages/settings_ci_cd.scss
@@ -17,10 +17,6 @@
}
}
-.registry-placeholder {
- min-height: 60px;
-}
-
.auto-devops-card {
margin-bottom: $gl-vert-padding;
}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 8f3574a337b..352050f7b01 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -98,6 +98,7 @@
.tree-table {
margin-bottom: 0;
+ table-layout: fixed;
tr {
border-bottom: 1px solid $white-normal;
diff --git a/app/assets/stylesheets/pages/trials.scss b/app/assets/stylesheets/pages/trials.scss
index 3fb9054b2b8..55f323b7df7 100644
--- a/app/assets/stylesheets/pages/trials.scss
+++ b/app/assets/stylesheets/pages/trials.scss
@@ -3,13 +3,13 @@
* MR link https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22716
*/
.gl-select2-html5-required-fix div.select2-container+select.select2 {
+ @include gl-opacity-0;
+ @include gl-border-0;
+ @include gl-bg-none;
+ @include gl-bg-transparent;
display: block !important;
width: 1px;
height: 1px;
z-index: -1;
- opacity: 0;
margin: -3px auto 0;
- background-image: none;
- background-color: transparent;
- border: 0;
}
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index d875f758ead..31a501f3a36 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -1242,8 +1242,8 @@ body.gl-dark .navbar-gitlab .search form {
line-height: 18px;
margin: 4px 0 4px 2px;
}
-.title-container .badge.badge-pill,
-.navbar-nav .badge.badge-pill {
+.title-container .badge.badge-pill:not(.merge-request-badge),
+.navbar-nav .badge.badge-pill:not(.merge-request-badge) {
position: inherit;
font-weight: 400;
margin-left: -6px;
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index a98e91b32eb..7f6e537af8f 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -1163,8 +1163,8 @@ input {
line-height: 18px;
margin: 4px 0 4px 2px;
}
-.title-container .badge.badge-pill,
-.navbar-nav .badge.badge-pill {
+.title-container .badge.badge-pill:not(.merge-request-badge),
+.navbar-nav .badge.badge-pill:not(.merge-request-badge) {
position: inherit;
font-weight: 400;
margin-left: -6px;
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index 7f2bea9bf26..d8f74a2913e 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -168,6 +168,20 @@ body.gl-dark {
--black: #{$black};
--svg-status-bg: #{$white};
+
+ .gl-button.gl-button,
+ .gl-button.gl-button.btn-block {
+ &.btn-default,
+ &.btn-dashed,
+ &.btn-info,
+ &.btn-success,
+ &.btn-danger,
+ &.btn-warning {
+ &-tertiary {
+ mix-blend-mode: screen;
+ }
+ }
+ }
}
$border-white-light: $gray-900;
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index bf251993c38..ab330ed69c6 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -143,16 +143,3 @@
flex-direction: column !important;
}
}
-
-// These will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1091
-.gl-w-10p {
- width: 10%;
-}
-
-.gl-w-20p {
- width: 20%;
-}
-
-.gl-w-40p {
- width: 40%;
-}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 56ec10fa43a..179e6ef60fb 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -31,7 +31,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
feature_category :source_code_management, [:repository, :clear_repository_check_states]
feature_category :continuous_integration, [:ci_cd, :reset_registration_token]
- feature_category :collection, [:usage_data]
+ feature_category :usage_ping, [:usage_data]
feature_category :integrations, [:integrations]
feature_category :pages, [:lets_encrypt_terms_of_service]
diff --git a/app/controllers/admin/dev_ops_report_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb
index 59b2200fb59..4ebc643be33 100644
--- a/app/controllers/admin/dev_ops_report_controller.rb
+++ b/app/controllers/admin/dev_ops_report_controller.rb
@@ -3,6 +3,8 @@
class Admin::DevOpsReportController < Admin::ApplicationController
include Analytics::UniqueVisitsHelper
+ helper_method :show_adoption?
+
track_unique_visits :show, target_id: 'i_analytics_dev_ops_score'
feature_category :devops_reports
@@ -12,4 +14,10 @@ class Admin::DevOpsReportController < Admin::ApplicationController
@metric = DevOpsReport::Metric.order(:created_at).last&.present
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def show_adoption?
+ false
+ end
end
+
+Admin::DevOpsReportController.prepend_if_ee('EE::Admin::DevOpsReportController')
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index c4564478462..39718793c1d 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -57,6 +57,10 @@ class Admin::ProjectsController < Admin::ApplicationController
namespace = Namespace.find_by(id: params[:new_namespace_id])
::Projects::TransferService.new(@project, current_user, params.dup).execute(namespace)
+ if @project.errors[:new_namespace].present?
+ flash[:alert] = @project.errors[:new_namespace].first
+ end
+
@project.reset
redirect_to admin_project_path(@project)
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b78029a52cd..3cb7373a970 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -103,14 +103,6 @@ class ApplicationController < ActionController::Base
head :forbidden, retry_after: Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window
end
- rescue_from GRPC::Unavailable, Gitlab::Git::CommandError do |exception|
- log_exception(exception)
-
- headers['Retry-After'] = exception.retry_after if exception.respond_to?(:retry_after)
-
- render_503
- end
-
def redirect_back_or_default(default: root_path, options: {})
redirect_back(fallback_location: default, **options)
end
@@ -246,19 +238,6 @@ class ApplicationController < ActionController::Base
head :unprocessable_entity
end
- def render_503
- respond_to do |format|
- format.html do
- render(
- file: Rails.root.join("public", "503"),
- layout: false,
- status: :service_unavailable
- )
- end
- format.any { head :service_unavailable }
- end
- end
-
def no_cache_headers
DEFAULT_GITLAB_NO_CACHE_HEADERS.each do |k, v|
headers[k] = v
@@ -286,6 +265,14 @@ class ApplicationController < ActionController::Base
end
end
+ def stream_csv_headers(csv_filename)
+ no_cache_headers
+ stream_headers
+
+ headers['Content-Type'] = 'text/csv; charset=utf-8; header=present'
+ headers['Content-Disposition'] = "attachment; filename=\"#{csv_filename}\""
+ end
+
def default_cache_control
if request.xhr?
ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL
@@ -468,6 +455,7 @@ class ApplicationController < ActionController::Base
project: -> { @project if @project&.persisted? },
namespace: -> { @group if @group&.persisted? },
caller_id: caller_id,
+ remote_ip: request.ip,
feature_category: feature_category) do
yield
ensure
diff --git a/app/controllers/concerns/invisible_captcha_on_signup.rb b/app/controllers/concerns/invisible_captcha_on_signup.rb
index 9bea6145ff3..c7fd6d08744 100644
--- a/app/controllers/concerns/invisible_captcha_on_signup.rb
+++ b/app/controllers/concerns/invisible_captcha_on_signup.rb
@@ -8,7 +8,7 @@ module InvisibleCaptchaOnSignup
end
def on_honeypot_spam_callback
- return unless Feature.enabled?(:invisible_captcha)
+ return unless Gitlab::CurrentSettings.invisible_captcha_enabled
invisible_captcha_honeypot_counter.increment
log_request('Invisible_Captcha_Honeypot_Request')
@@ -17,7 +17,7 @@ module InvisibleCaptchaOnSignup
end
def on_timestamp_spam_callback
- return unless Feature.enabled?(:invisible_captcha)
+ return unless Gitlab::CurrentSettings.invisible_captcha_enabled
invisible_captcha_timestamp_counter.increment
log_request('Invisible_Captcha_Timestamp_Request')
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 3b46a547d47..57d4203ad43 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -217,6 +217,7 @@ module IssuableActions
:issuable_ids,
:assignee_id,
:milestone_id,
+ :sprint_id,
:state_event,
:subscription_event,
assignee_ids: [],
diff --git a/app/controllers/concerns/redis_tracking.rb b/app/controllers/concerns/redis_tracking.rb
index d81bd10d5bb..d71935356b8 100644
--- a/app/controllers/concerns/redis_tracking.rb
+++ b/app/controllers/concerns/redis_tracking.rb
@@ -33,7 +33,7 @@ module RedisTracking
return unless metric_feature_enabled?(feature, feature_default_enabled)
return unless visitor_id
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, event_name)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: visitor_id)
end
def trackable_request?
diff --git a/app/controllers/concerns/show_inherited_labels_checker.rb b/app/controllers/concerns/show_inherited_labels_checker.rb
deleted file mode 100644
index 9847226f599..00000000000
--- a/app/controllers/concerns/show_inherited_labels_checker.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module ShowInheritedLabelsChecker
- extend ActiveSupport::Concern
-
- private
-
- def show_inherited_labels?(include_ancestor_groups)
- Feature.enabled?(:show_inherited_labels, @project || @group, default_enabled: true) || include_ancestor_groups # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
-end
diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb
index 50c93441dd4..4ec561014a8 100644
--- a/app/controllers/concerns/spammable_actions.rb
+++ b/app/controllers/concerns/spammable_actions.rb
@@ -32,10 +32,6 @@ module SpammableActions
elsif render_recaptcha?
ensure_spam_config_loaded!
- if params[:recaptcha_verification]
- flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
- end
-
respond_to do |format|
format.html do
render :verify
@@ -56,9 +52,9 @@ module SpammableActions
def spammable_params
default_params = { request: request }
- recaptcha_check = params[:recaptcha_verification] &&
+ recaptcha_check = recaptcha_response &&
ensure_spam_config_loaded! &&
- verify_recaptcha
+ verify_recaptcha(response: recaptcha_response)
return default_params unless recaptcha_check
@@ -66,6 +62,23 @@ module SpammableActions
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.
+ #
+ # It is used in the `Recaptcha::Verify#verify_recaptcha` 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']
+ end
+
def spammable
raise NotImplementedError, "#{self.class} does not implement #{__method__}"
end
diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb
index 6fe3d878639..01dc0b1ab00 100644
--- a/app/controllers/dashboard/snippets_controller.rb
+++ b/app/controllers/dashboard/snippets_controller.rb
@@ -18,6 +18,7 @@ class Dashboard::SnippetsController < Dashboard::ApplicationController
.execute
.page(params[:page])
.inc_author
+ .inc_projects_namespace_route
return if redirect_out_of_range(@snippets)
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index d210d0f66fd..1fd3cfd11f9 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -9,13 +9,16 @@ class Explore::ProjectsController < Explore::ApplicationController
include SortingPreference
MIN_SEARCH_LENGTH = 3
+ PAGE_LIMIT = 50
before_action :set_non_archived_param
before_action :set_sorting
- # Limit taken from https://gitlab.com/gitlab-org/gitlab/issues/38357
+ # For background information on the limit, see:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/38357
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/262682
before_action only: [:index, :trending, :starred] do
- limit_pages(200)
+ limit_pages(PAGE_LIMIT)
end
rescue_from PageOutOfBoundsError, with: :page_out_of_bounds
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index d1b09e1b49e..5df7ff0632a 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -14,10 +14,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
# Authorize
before_action :authorize_admin_group_member!, except: admin_not_required_endpoints
- before_action do
- push_frontend_feature_flag(:group_members_filtered_search, @group, default_enabled: true)
- end
-
skip_before_action :check_two_factor_requirement, only: :leave
skip_cross_project_access_check :index, :create, :update, :destroy, :request_access,
:approve_access_request, :leave, :resend_invite,
diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb
index 34856f8d84e..c5dd3e1df35 100644
--- a/app/controllers/groups/labels_controller.rb
+++ b/app/controllers/groups/labels_controller.rb
@@ -2,7 +2,6 @@
class Groups::LabelsController < Groups::ApplicationController
include ToggleSubscriptionAction
- include ShowInheritedLabelsChecker
before_action :label, only: [:edit, :update, :destroy]
before_action :authorize_admin_labels!, only: [:new, :create, :edit, :update, :destroy]
@@ -112,7 +111,7 @@ class Groups::LabelsController < Groups::ApplicationController
current_user,
group_id: @group.id,
only_group_labels: options[:only_group_labels],
- include_ancestor_groups: show_inherited_labels?(params[:include_ancestor_groups]),
+ include_ancestor_groups: true,
sort: sort,
subscribed: options[:subscribed],
include_descendant_groups: options[:include_descendant_groups],
diff --git a/app/controllers/groups/settings/packages_and_registries_controller.rb b/app/controllers/groups/settings/packages_and_registries_controller.rb
new file mode 100644
index 00000000000..dbc1e68742b
--- /dev/null
+++ b/app/controllers/groups/settings/packages_and_registries_controller.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Groups
+ module Settings
+ class PackagesAndRegistriesController < Groups::ApplicationController
+ before_action :authorize_admin_group!
+
+ feature_category :package_registry
+
+ def index
+ end
+ end
+ end
+end
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 4417cfe9098..7394e8bf615 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -1,11 +1,15 @@
# frozen_string_literal: true
class Import::BulkImportsController < ApplicationController
+ include ActionView::Helpers::SanitizeHelper
+
before_action :ensure_group_import_enabled
before_action :verify_blocked_uri, only: :status
feature_category :importers
+ POLLING_INTERVAL = 3_000
+
rescue_from BulkImports::Clients::Http::ConnectionError, with: :bulk_import_connection_error
def configure
@@ -32,6 +36,12 @@ class Import::BulkImportsController < ApplicationController
render json: :ok
end
+ def realtime_changes
+ Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
+
+ render json: current_user_bulk_imports.to_json(only: [:id], methods: [:status_name])
+ end
+
private
def serialized_importable_data
@@ -43,7 +53,22 @@ class Import::BulkImportsController < ApplicationController
end
def importable_data
- client.get('groups', top_level_only: true).parsed_response
+ client.get('groups', query_params).parsed_response
+ end
+
+ # Default query string params used to fetch groups from GitLab source instance
+ #
+ # top_level_only: fetch only top level groups (subgroups are fetched during import itself)
+ # min_access_level: fetch only groups user has maintainer or above permissions
+ # search: optional search param to search user's groups by a keyword
+ def query_params
+ query_params = {
+ top_level_only: true,
+ min_access_level: Gitlab::Access::MAINTAINER
+ }
+
+ query_params[:search] = sanitized_filter_param if sanitized_filter_param
+ query_params
end
def client
@@ -131,4 +156,12 @@ class Import::BulkImportsController < ApplicationController
access_token: session[access_token_key]
}
end
+
+ def sanitized_filter_param
+ @filter ||= sanitize(params[:filter])&.downcase
+ end
+
+ def current_user_bulk_imports
+ current_user.bulk_imports.gitlab
+ end
end
diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb
index d1ba8a98c64..137f830e40b 100644
--- a/app/controllers/jira_connect/app_descriptor_controller.rb
+++ b/app/controllers/jira_connect/app_descriptor_controller.rb
@@ -65,6 +65,8 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
}
modules.merge!(build_information_module)
+ modules.merge!(deployment_information_module)
+ modules.merge!(feature_flag_module)
modules
end
@@ -73,17 +75,46 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
view_context.image_url('gitlab_logo.png')
end
+ # See: https://developer.atlassian.com/cloud/jira/software/modules/deployment/
+ def deployment_information_module
+ {
+ jiraDeploymentInfoProvider: common_module_properties.merge(
+ actions: {}, # TODO: list deployments
+ name: { value: "GitLab Deployments" },
+ key: "gitlab-deployments"
+ )
+ }
+ end
+
+ # see: https://developer.atlassian.com/cloud/jira/software/modules/feature-flag/
+ def feature_flag_module
+ {
+ jiraFeatureFlagInfoProvider: common_module_properties.merge(
+ actions: {}, # TODO: create, link and list feature flags https://gitlab.com/gitlab-org/gitlab/-/issues/297386
+ name: {
+ value: 'GitLab Feature Flags'
+ },
+ key: 'gitlab-feature-flags'
+ )
+ }
+ end
+
# See: https://developer.atlassian.com/cloud/jira/software/modules/build/
def build_information_module
{
- jiraBuildInfoProvider: {
- homeUrl: HOME_URL,
- logoUrl: logo_url,
- documentationUrl: DOC_URL,
+ jiraBuildInfoProvider: common_module_properties.merge(
actions: {},
name: { value: "GitLab CI" },
key: "gitlab-ci"
- }
+ )
+ }
+ end
+
+ def common_module_properties
+ {
+ homeUrl: HOME_URL,
+ logoUrl: logo_url,
+ documentationUrl: DOC_URL
}
end
diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb
index 3ff12f29f10..161280a05fc 100644
--- a/app/controllers/jira_connect/subscriptions_controller.rb
+++ b/app/controllers/jira_connect/subscriptions_controller.rb
@@ -19,6 +19,9 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController
before_action :allow_rendering_in_iframe, only: :index
before_action :verify_qsh_claim!, only: :index
before_action :authenticate_user!, only: :create
+ before_action do
+ push_frontend_feature_flag(:new_jira_connect_ui, type: :development, default_enabled: :yaml)
+ end
def index
@subscriptions = current_jira_installation.subscriptions.preload_namespace_route
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index c2089a0fca3..1ef1e12bb02 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -18,9 +18,19 @@ class MetricsController < ActionController::Base
render plain: response, content_type: 'text/plain; version=0.0.4'
end
+ def system
+ render json: system_metrics
+ end
+
private
def metrics_service
@metrics_service ||= MetricsService.new
end
+
+ def system_metrics
+ Gitlab::Metrics::System.summary.merge(
+ worker_id: Prometheus::PidProvider.worker_id
+ )
+ end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 8f16650a6f2..8c66f45dd79 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -31,6 +31,9 @@ class Projects::BlobController < Projects::ApplicationController
before_action :editor_variables, except: [:show, :preview, :diff]
before_action :validate_diff_params, only: :diff
before_action :set_last_commit_sha, only: [:edit, :update]
+ before_action only: :new do
+ 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
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index cc391868df0..ef9025ae52f 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -3,7 +3,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: false)
+ push_frontend_feature_flag(:ci_config_visualization_tab, @project, default_enabled: :yaml)
end
feature_category :pipeline_authoring
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index ab1cf63c885..5c15a5d246c 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -7,7 +7,6 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
include Analytics::UniqueVisitsHelper
include GracefulTimeoutHandling
- before_action :whitelist_query_limiting, only: [:show]
before_action :authorize_read_cycle_analytics!
track_unique_visits :show, target_id: 'p_analytics_valuestream'
@@ -38,8 +37,4 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
permissions: @cycle_analytics.permissions(user: current_user)
}
end
-
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42671')
- end
end
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index c37abf82fe9..92483607e65 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -15,6 +15,9 @@ class Projects::EnvironmentsController < Projects::ApplicationController
push_frontend_feature_flag(:prometheus_computed_alerts)
push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate)
end
+ before_action do
+ push_frontend_feature_flag(:canary_ingress_weight_control, default_enabled: true)
+ end
before_action :authorize_read_environment!, except: [:metrics, :additional_metrics, :metrics_dashboard, :metrics_redirect]
before_action :authorize_create_environment!, only: [:new, :create]
before_action :authorize_stop_environment!, only: [:stop]
diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb
index da9dcd1c09c..6b6606c4f41 100644
--- a/app/controllers/projects/feature_flags_controller.rb
+++ b/app/controllers/projects/feature_flags_controller.rb
@@ -10,12 +10,10 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
before_action :feature_flag, only: [:edit, :update, :destroy]
- before_action :ensure_legacy_flags_writable!, only: [:update]
+ before_action :ensure_flag_writable!, only: [:update]
before_action do
push_frontend_feature_flag(:feature_flag_permissions)
- push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true)
- push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project)
end
feature_category :feature_flags
@@ -103,10 +101,8 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
@feature_flag ||= @noteable = project.operations_feature_flags.find_by_iid!(params[:iid])
end
- def ensure_legacy_flags_writable!
- if ::Feature.enabled?(:feature_flags_legacy_read_only, project, default_enabled: true) &&
- ::Feature.disabled?(:feature_flags_legacy_read_only_override, project) &&
- feature_flag.legacy_flag?
+ def ensure_flag_writable!
+ if feature_flag.legacy_flag?
render_error_json(['Legacy feature flags are read-only'])
end
end
diff --git a/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb b/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb
index f1264ca4a45..408652b4b9e 100644
--- a/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb
+++ b/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb
@@ -26,7 +26,7 @@ module Projects
end
def webhook_processor
- ::IncidentManagement::PagerDuty::ProcessWebhookService.new(project, nil, payload)
+ ::IncidentManagement::PagerDuty::ProcessWebhookService.new(project, payload)
end
def payload
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index ba8e6b90971..3992165d07c 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -2,7 +2,6 @@
class Projects::LabelsController < Projects::ApplicationController
include ToggleSubscriptionAction
- include ShowInheritedLabelsChecker
before_action :check_issuables_available!
before_action :label, only: [:edit, :update, :destroy, :promote]
@@ -164,7 +163,7 @@ class Projects::LabelsController < Projects::ApplicationController
@available_labels ||=
LabelsFinder.new(current_user,
project_id: @project.id,
- include_ancestor_groups: show_inherited_labels?(params[:include_ancestor_groups]),
+ include_ancestor_groups: true,
search: params[:search],
subscribed: params[:subscribed],
sort: sort).execute
diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb
index 63a36732d87..ac204427885 100644
--- a/app/controllers/projects/mattermosts_controller.rb
+++ b/app/controllers/projects/mattermosts_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Projects::MattermostsController < Projects::ApplicationController
- include TriggersHelper
+ include Ci::TriggersHelper
include ActionView::Helpers::AssetUrlHelper
layout 'project_settings'
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index 7d3e7759081..858bdc066c1 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -14,7 +14,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
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)
+ 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 da19ddf6105..9180b3f6b62 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -11,6 +11,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
around_action :allow_gitaly_ref_name_caching
+ after_action :track_viewed_diffs_events, only: [:diffs_batch]
+
def show
render_diffs
end
@@ -163,7 +165,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
def render_merge_ref_head_diff?
- Gitlab::Utils.to_boolean(params[:diff_head]) && @merge_request.diffable_merge_ref?
+ Gitlab::Utils.to_boolean(params[:diff_head]) && @merge_request.diffable_merge_ref? && @start_sha.nil?
end
def note_positions
@@ -188,4 +190,16 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
Discussions::CaptureDiffNotePositionsService.new(@merge_request).execute
end
+
+ def track_viewed_diffs_events
+ return if request.headers['DNT'] == '1'
+
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ .track_mr_diffs_action(merge_request: @merge_request)
+
+ return unless current_user&.view_diffs_file_by_file
+
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ .track_mr_diffs_single_file_action(merge_request: @merge_request, user: current_user)
+ end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 382fbfaac25..d452a5e02e2 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -28,22 +28,21 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
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(:widget_visibility_polling, @project, default_enabled: true)
- push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true)
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(:hide_jump_to_next_unresolved_in_threads, default_enabled: true)
push_frontend_feature_flag(:merge_request_widget_graphql, @project)
- push_frontend_feature_flag(:unified_diff_components, @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(: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(:test_failure_history, @project)
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)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)
@@ -53,7 +52,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
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)
+ push_frontend_feature_flag(:reviewer_approval_rules, @project, default_enabled: :yaml)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
@@ -69,8 +68,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
:toggle_award_emoji, :toggle_subscription, :update
]
- feature_category :code_testing, [:test_reports, :coverage_reports, :terraform_reports]
+ feature_category :code_testing, [:test_reports, :coverage_reports]
feature_category :accessibility_testing, [:accessibility_reports]
+ feature_category :infrastructure_as_code, [:terraform_reports]
def index
@merge_requests = @issuables
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 5655d3b4c0d..4af7508b935 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -17,7 +17,6 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
@scope = params[:scope]
@all_schedules = Ci::PipelineSchedulesFinder.new(@project).execute
@schedules = Ci::PipelineSchedulesFinder.new(@project).execute(scope: params[:scope])
- .includes(:last_pipeline)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/pipelines/tests_controller.rb b/app/controllers/projects/pipelines/tests_controller.rb
index 1c212964df5..924d52898ea 100644
--- a/app/controllers/projects/pipelines/tests_controller.rb
+++ b/app/controllers/projects/pipelines/tests_controller.rb
@@ -6,6 +6,8 @@ module Projects
before_action :authorize_read_build!
before_action :builds, only: [:show]
+ feature_category :code_testing
+
def summary
respond_to do |format|
format.json do
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 74513da8675..e44c00e501e 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -17,10 +17,10 @@ class Projects::PipelinesController < Projects::ApplicationController
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(:graphql_pipeline_analytics, project, type: :development)
push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development, default_enabled: true)
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? }
@@ -45,7 +45,11 @@ class Projects::PipelinesController < Projects::ApplicationController
@pipelines_count = limited_pipelines_count(project)
respond_to do |format|
- format.html
+ format.html do
+ record_empty_pipeline_experiment
+
+ render :index
+ end
format.json do
Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
@@ -184,23 +188,6 @@ class Projects::PipelinesController < Projects::ApplicationController
end
end
- def charts
- @charts = {}
- @counts = {}
-
- return if Feature.enabled?(:graphql_pipeline_analytics)
-
- @charts[:week] = Gitlab::Ci::Charts::WeekChart.new(project)
- @charts[:month] = Gitlab::Ci::Charts::MonthChart.new(project)
- @charts[:year] = Gitlab::Ci::Charts::YearChart.new(project)
- @charts[:pipeline_times] = Gitlab::Ci::Charts::PipelineTime.new(project)
-
- @counts[:total] = @project.all_pipelines.count(:all)
- @counts[:success] = @project.all_pipelines.success.count(:all)
- @counts[:failed] = @project.all_pipelines.failed.count(:all)
- @counts[:total_duration] = @project.all_pipelines.total_duration
- end
-
def test_report
respond_to do |format|
format.html do
@@ -313,6 +300,20 @@ 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 631f627838b..5972b29a298 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -17,17 +17,18 @@ class Projects::ProjectMembersController < Projects::ApplicationController
@skip_groups += @project.group.self_and_ancestors_ids if @project.group
@group_links = @project.project_group_links
- @group_links = @group_links.search(params[:search]) if params[:search].present?
+ @group_links = @group_links.search(params[:search_groups]) if params[:search_groups].present?
- @project_members = MembersFinder
+ project_members = MembersFinder
.new(@project, current_user, params: filter_params)
.execute(include_relations: requested_relations)
- @project_members = present_members(@project_members.page(params[:page]))
+ if helpers.can_manage_project_members?(@project)
+ @invited_members = present_members(project_members.invite)
+ @requesters = present_members(AccessRequestsFinder.new(@project).execute(current_user))
+ end
- @requesters = present_members(
- AccessRequestsFinder.new(@project).execute(current_user)
- )
+ @project_members = present_members(project_members.non_invite.page(params[:page]))
@project_member = @project.project_members.new
end
diff --git a/app/controllers/projects/usage_ping_controller.rb b/app/controllers/projects/usage_ping_controller.rb
index 9b4ddb326c1..77ee53f2e5d 100644
--- a/app/controllers/projects/usage_ping_controller.rb
+++ b/app/controllers/projects/usage_ping_controller.rb
@@ -3,7 +3,7 @@
class Projects::UsagePingController < Projects::ApplicationController
before_action :authenticate_user!
- feature_category :collection
+ feature_category :usage_ping
def web_ide_clientside_preview
return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 3744517934a..0c40478d877 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -94,7 +94,7 @@ class ProjectsController < Projects::ApplicationController
redirect_to(edit_project_path(@project, anchor: 'js-general-project-settings'))
end
else
- flash.now[:alert] = result[:message]
+ flash[:alert] = result[:message]
@project.reset
format.html { render_edit }
@@ -197,13 +197,13 @@ class ProjectsController < Projects::ApplicationController
end
def housekeeping
- ::Projects::HousekeepingService.new(@project, :gc).execute
+ ::Repositories::HousekeepingService.new(@project, :gc).execute
redirect_to(
project_path(@project),
notice: _("Housekeeping successfully started")
)
- rescue ::Projects::HousekeepingService::LeaseTaken => ex
+ rescue ::Repositories::HousekeepingService::LeaseTaken => ex
redirect_to(
edit_project_path(@project, anchor: 'js-project-advanced-settings'),
alert: ex.to_s
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index 9b7cbcb2dfe..2de29da4b45 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -103,18 +103,13 @@ module Repositories
end
def upload_headers
- headers = {
+ {
Authorization: authorization_header,
# git-lfs v2.5.0 sets the Content-Type based on the uploaded file. This
# ensures that Workhorse can intercept the request.
- 'Content-Type': LFS_TRANSFER_CONTENT_TYPE
+ 'Content-Type': LFS_TRANSFER_CONTENT_TYPE,
+ 'Transfer-Encoding': 'chunked'
}
-
- if Feature.enabled?(:lfs_chunked_encoding, project, default_enabled: true)
- headers['Transfer-Encoding'] = 'chunked'
- end
-
- headers
end
def lfs_check_batch_operation!
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 46245286820..62208d838c1 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -33,10 +33,8 @@ class UsersController < ApplicationController
end
format.json do
- # In 13.8, this endpoint will be removed:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/289972
- load_events
- pager_json("events/_events", @events.count, events: @events)
+ msg = "This endpoint is deprecated. Use %s instead." % user_activity_path
+ render json: { message: msg }, status: :not_found
end
end
end
diff --git a/app/enums/.keep b/app/enums/.keep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/app/enums/.keep
diff --git a/app/experiments/application_experiment.rb b/app/experiments/application_experiment.rb
index e8f7d22bf77..7a8851d11ce 100644
--- a/app/experiments/application_experiment.rb
+++ b/app/experiments/application_experiment.rb
@@ -19,7 +19,9 @@ class ApplicationExperiment < Gitlab::Experiment
private
def resolve_variant_name
- variant_names.first if Feature.enabled?(name, self, type: :experiment)
+ return variant_names.first if Feature.enabled?(name, self, type: :experiment)
+
+ nil # Returning nil vs. :control is important for not caching and rollouts.
end
# Cache is an implementation on top of Gitlab::Redis::SharedState that also
@@ -61,7 +63,7 @@ class ApplicationExperiment < Gitlab::Experiment
end
def hkey(key)
- key.split(':') # this assumes the default strategy in gitlab-experiment
+ key.to_s.split(':') # this assumes the default strategy in gitlab-experiment
end
def read_entry(key, **options)
diff --git a/app/finders/alert_management/alerts_finder.rb b/app/finders/alert_management/alerts_finder.rb
index be3b329fb6f..8e0444d324a 100644
--- a/app/finders/alert_management/alerts_finder.rb
+++ b/app/finders/alert_management/alerts_finder.rb
@@ -32,6 +32,8 @@ module AlertManagement
attr_reader :current_user, :project, :params
def by_domain(collection)
+ return collection if params[:iid].present?
+
collection.with_operations_alerts
end
diff --git a/app/finders/autocomplete/group_finder.rb b/app/finders/autocomplete/group_finder.rb
index dd97ac4c817..90fa48c2dc9 100644
--- a/app/finders/autocomplete/group_finder.rb
+++ b/app/finders/autocomplete/group_finder.rb
@@ -27,8 +27,7 @@ module Autocomplete
# This removes the need for using `return render_404` and similar patterns
# in controllers that use this finder.
unless Ability.allowed?(current_user, :read_group, group)
- raise ActiveRecord::RecordNotFound
- .new("Could not find a Group with ID #{group_id}")
+ raise ActiveRecord::RecordNotFound, "Could not find a Group with ID #{group_id}"
end
group
diff --git a/app/finders/autocomplete/project_finder.rb b/app/finders/autocomplete/project_finder.rb
index 3a4696f4c2e..6e51ae4c70d 100644
--- a/app/finders/autocomplete/project_finder.rb
+++ b/app/finders/autocomplete/project_finder.rb
@@ -25,8 +25,7 @@ module Autocomplete
# This removes the need for using `return render_404` and similar patterns
# in controllers that use this finder.
unless Ability.allowed?(current_user, :read_project, project)
- raise ActiveRecord::RecordNotFound
- .new("Could not find a Project with ID #{project_id}")
+ raise ActiveRecord::RecordNotFound, "Could not find a Project with ID #{project_id}"
end
project
diff --git a/app/finders/ci/pipelines_for_merge_request_finder.rb b/app/finders/ci/pipelines_for_merge_request_finder.rb
index da8dfc2579a..1f6ee9d75ad 100644
--- a/app/finders/ci/pipelines_for_merge_request_finder.rb
+++ b/app/finders/ci/pipelines_for_merge_request_finder.rb
@@ -34,11 +34,7 @@ module Ci
pipelines =
if merge_request.persisted?
- if Feature.enabled?(:ci_pipelines_for_merge_request_finder_new_cte, target_project)
- pipelines_using_cte
- else
- pipelines_using_legacy_cte
- end
+ pipelines_using_cte
else
triggered_for_branch.for_sha(commit_shas)
end
@@ -49,18 +45,6 @@ module Ci
private
- def pipelines_using_legacy_cte
- cte = Gitlab::SQL::CTE.new(:shas, merge_request.all_commits.select(:sha))
-
- source_sha_join = cte.table[:sha].eq(Ci::Pipeline.arel_table[:source_sha])
- merged_result_pipelines = filter_by(triggered_by_merge_request, cte, source_sha_join)
- detached_merge_request_pipelines = filter_by_sha(triggered_by_merge_request, cte)
- pipelines_for_branch = filter_by_sha(triggered_for_branch, cte)
-
- Ci::Pipeline.with(cte.to_arel) # rubocop: disable CodeReuse/ActiveRecord
- .from_union([merged_result_pipelines, detached_merge_request_pipelines, pipelines_for_branch])
- end
-
def pipelines_using_cte
cte = Gitlab::SQL::CTE.new(:shas, merge_request.all_commits.select(:sha))
diff --git a/app/finders/concerns/finder_methods.rb b/app/finders/concerns/finder_methods.rb
index 622cbcf4928..193b52b1694 100644
--- a/app/finders/concerns/finder_methods.rb
+++ b/app/finders/concerns/finder_methods.rb
@@ -22,7 +22,7 @@ module FinderMethods
def raise_not_found_unless_authorized(result)
result = if_authorized(result)
- raise ActiveRecord::RecordNotFound.new("Couldn't find #{model}") unless result
+ raise(ActiveRecord::RecordNotFound, "Couldn't find #{model}") unless result
result
end
diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb
new file mode 100644
index 00000000000..524e7aa7ff9
--- /dev/null
+++ b/app/finders/concerns/packages/finder_helper.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Packages
+ module FinderHelper
+ extend ActiveSupport::Concern
+
+ private
+
+ def packages_visible_to_user(user, within_group:)
+ return ::Packages::Package.none unless within_group
+ return ::Packages::Package.none unless Ability.allowed?(user, :read_package, within_group)
+
+ projects = projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id))
+ ::Packages::Package.for_projects(projects.select(:id))
+ end
+
+ def projects_visible_to_user(user, within_group:)
+ return ::Project.none unless within_group
+ return ::Project.none unless Ability.allowed?(user, :read_package, within_group)
+
+ projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id))
+ end
+
+ def projects_visible_to_reporters(user, namespace_ids)
+ ::Project.in_namespace(namespace_ids)
+ .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
+ end
+ end
+end
diff --git a/app/finders/concerns/time_frame_filter.rb b/app/finders/concerns/time_frame_filter.rb
index d1ebed730f6..7412bea340e 100644
--- a/app/finders/concerns/time_frame_filter.rb
+++ b/app/finders/concerns/time_frame_filter.rb
@@ -2,7 +2,7 @@
module TimeFrameFilter
def by_timeframe(items)
- return items unless params[:start_date] && params[:start_date]
+ return items unless params[:start_date] && params[:end_date]
start_date = params[:start_date].to_date
end_date = params[:end_date].to_date
diff --git a/app/finders/deployments_finder.rb b/app/finders/deployments_finder.rb
index 0bb8ce6b4da..4038f93cf2d 100644
--- a/app/finders/deployments_finder.rb
+++ b/app/finders/deployments_finder.rb
@@ -4,10 +4,10 @@ class DeploymentsFinder
attr_reader :project, :params
ALLOWED_SORT_VALUES = %w[id iid created_at updated_at ref].freeze
- DEFAULT_SORT_VALUE = 'id'.freeze
+ DEFAULT_SORT_VALUE = 'id'
ALLOWED_SORT_DIRECTIONS = %w[asc desc].freeze
- DEFAULT_SORT_DIRECTION = 'asc'.freeze
+ DEFAULT_SORT_DIRECTION = 'asc'
def initialize(project, params = {})
@project = project
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 922b53b514d..fc03d5cd90c 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -4,6 +4,9 @@
#
# Used to filter Issues and MergeRequests collections by set of params
#
+# Note: This class is NOT meant to be instantiated. Instead you should
+# look at IssuesFinder or EpicsFinder, which inherit from this.
+#
# Arguments:
# klass - actual class like Issue or MergeRequest
# current_user - which user use
@@ -92,6 +95,10 @@ class IssuableFinder
IssuableFinder::Params
end
+ def klass
+ raise NotImplementedError
+ end
+
def initialize(current_user, params = {})
@current_user = current_user
@params = params_class.new(params, current_user, klass)
@@ -451,6 +458,7 @@ class IssuableFinder
def by_release(items)
return items unless params.releases?
+ return items if params.group? # don't allow release filtering at group level
if params.filter_by_no_release?
items.without_release
diff --git a/app/finders/issuable_finder/params.rb b/app/finders/issuable_finder/params.rb
index b481afee338..803b30e86ac 100644
--- a/app/finders/issuable_finder/params.rb
+++ b/app/finders/issuable_finder/params.rb
@@ -108,16 +108,8 @@ class IssuableFinder
project_id.present?
end
- def group
- strong_memoize(:group) do
- if params[:group_id].is_a?(Group)
- params[:group_id]
- elsif params[:group_id].present?
- Group.find(params[:group_id])
- else
- nil
- end
- end
+ def group?
+ group_id.present?
end
def related_groups
@@ -143,10 +135,25 @@ class IssuableFinder
end
end
+ def group
+ strong_memoize(:group) do
+ next nil unless group?
+
+ group = group_id.is_a?(Group) ? group_id : Group.find(group_id)
+ group = nil unless Ability.allowed?(current_user, :read_group, group)
+
+ group
+ end
+ end
+
def project_id
params[:project_id]
end
+ def group_id
+ params[:group_id]
+ end
+
def projects
strong_memoize(:projects) do
next [project] if project?
@@ -216,14 +223,14 @@ class IssuableFinder
strong_memoize(:milestones) do
if milestones?
if project?
- group_id = project.group&.id
+ project_group_id = project.group&.id
project_id = project.id
end
- group_id = group.id if group
+ project_group_id = group.id if group
search_params =
- { title: params[:milestone_title], project_ids: project_id, group_ids: group_id }
+ { title: params[:milestone_title], project_ids: project_id, group_ids: project_group_id }
MilestonesFinder.new(search_params).execute # rubocop: disable CodeReuse/Finder
else
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index 978550aedaf..9f9e2afa7fe 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -57,7 +57,7 @@ class MergeRequestsFinder < IssuableFinder
end
def params_class
- MergeRequestsFinder::Params
+ MergeRequestsFinder.const_get(:Params, false) # rubocop: disable CodeReuse/Finder
end
def filter_items(_items)
@@ -84,7 +84,7 @@ class MergeRequestsFinder < IssuableFinder
def by_commit(items)
return items unless params[:commit_sha].presence
- items.by_commit_sha(params[:commit_sha])
+ items.by_related_commit_sha(params[:commit_sha])
end
def source_branch
diff --git a/app/finders/packages/debian/distributions_finder.rb b/app/finders/packages/debian/distributions_finder.rb
new file mode 100644
index 00000000000..e64b6bdfec1
--- /dev/null
+++ b/app/finders/packages/debian/distributions_finder.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class DistributionsFinder
+ def initialize(container, params = {})
+ @container, @params = container, params
+ end
+
+ def execute
+ collection = relation.with_container(container)
+ collection = by_codename(collection)
+ collection = by_suite(collection)
+ collection = by_codename_or_suite(collection)
+ collection
+ end
+
+ private
+
+ attr_reader :container, :params
+
+ def relation
+ case container
+ when Project
+ Packages::Debian::ProjectDistribution
+ when Group
+ Packages::Debian::GroupDistribution
+ else
+ raise ArgumentError, "Unexpected container type of '#{container.class}'"
+ end
+ end
+
+ def by_codename(collection)
+ return collection unless params[:codename].present?
+
+ collection.with_codename(params[:codename])
+ end
+
+ def by_suite(collection)
+ return collection unless params[:suite].present?
+
+ collection.with_suite(params[:suite])
+ end
+
+ def by_codename_or_suite(collection)
+ return collection unless params[:codename_or_suite].present?
+
+ collection.with_codename_or_suite(params[:codename_or_suite])
+ end
+ end
+ end
+end
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index a51057571f1..860c4068b31 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -27,9 +27,9 @@ module Packages
.including_tags
.for_projects(group_projects_visible_to_current_user.select(:id))
.processed
- .has_version
.sort_by_attribute("#{params[:order_by]}_#{params[:sort]}")
+ packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
packages
@@ -72,5 +72,11 @@ module Packages
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/maven/package_finder.rb b/app/finders/packages/maven/package_finder.rb
index 775db12adb7..7e753705cbd 100644
--- a/app/finders/packages/maven/package_finder.rb
+++ b/app/finders/packages/maven/package_finder.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Packages
module Maven
class PackageFinder
@@ -27,17 +28,22 @@ module Packages
elsif group
packages_for_multiple_projects
else
- packages
+ ::Packages::Package.none
end
end
def packages_with_path
- base.only_maven_packages_with_path(path)
+ matching_packages = base.only_maven_packages_with_path(path)
+ matching_packages = matching_packages.order_by_package_file if versionless_package?(matching_packages)
+
+ matching_packages
end
- # Produces a query that returns all packages.
- def packages
- ::Packages::Package.all
+ def versionless_package?(matching_packages)
+ return if matching_packages.empty?
+
+ # if one matching package is versionless, they all are.
+ matching_packages.first&.version.nil?
end
# Produces a query that retrieves packages from a single project.
diff --git a/app/finders/packages/nuget/package_finder.rb b/app/finders/packages/nuget/package_finder.rb
index e6fb6712d47..8f585f045a1 100644
--- a/app/finders/packages/nuget/package_finder.rb
+++ b/app/finders/packages/nuget/package_finder.rb
@@ -1,11 +1,15 @@
# frozen_string_literal: true
+
module Packages
module Nuget
class PackageFinder
+ include ::Packages::FinderHelper
+
MAX_PACKAGES_COUNT = 50
- def initialize(project, package_name:, package_version: nil, limit: MAX_PACKAGES_COUNT)
- @project = project
+ def initialize(current_user, project_or_group, package_name:, package_version: nil, limit: MAX_PACKAGES_COUNT)
+ @current_user = current_user
+ @project_or_group = project_or_group
@package_name = package_name
@package_version = package_version
@limit = limit
@@ -17,15 +21,32 @@ module Packages
private
+ def base
+ if project?
+ @project_or_group.packages
+ elsif group?
+ packages_visible_to_user(@current_user, within_group: @project_or_group)
+ else
+ ::Packages::Package.none
+ end
+ end
+
def packages
- result = @project.packages
- .nuget
- .has_version
- .processed
- .with_name_like(@package_name)
+ result = base.nuget
+ .has_version
+ .processed
+ .with_name_like(@package_name)
result = result.with_version(@package_version) if @package_version.present?
result
end
+
+ def project?
+ @project_or_group.is_a?(::Project)
+ end
+
+ def group?
+ @project_or_group.is_a?(::Group)
+ end
end
end
end
diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb
index 519e8bf9c34..72a63224d2f 100644
--- a/app/finders/packages/packages_finder.rb
+++ b/app/finders/packages/packages_finder.rb
@@ -18,7 +18,7 @@ module Packages
.including_project_route
.including_tags
.processed
- .has_version
+ packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
packages = order_packages(packages)
@@ -27,6 +27,12 @@ module Packages
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]
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 05dc69ebff6..f1df4fbb0d8 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -52,7 +52,7 @@ class ProjectsFinder < UnionFinder
collection = Project.wrap_with_cte(collection) if use_cte
collection = filter_projects(collection)
- if params[:sort] == 'similarity' && params[:search] && Feature.enabled?(:project_finder_similarity_sort)
+ if params[:sort] == 'similarity' && params[:search] && Feature.enabled?(:project_finder_similarity_sort, current_user)
collection.sorted_by_similarity_desc(params[:search])
else
sort(collection)
diff --git a/app/finders/template_finder.rb b/app/finders/template_finder.rb
index a35376e905e..dac7c526474 100644
--- a/app/finders/template_finder.rb
+++ b/app/finders/template_finder.rb
@@ -7,6 +7,7 @@ class TemplateFinder
dockerfiles: ::Gitlab::Template::DockerfileTemplate,
gitignores: ::Gitlab::Template::GitignoreTemplate,
gitlab_ci_ymls: ::Gitlab::Template::GitlabCiYmlTemplate,
+ gitlab_ci_syntax_ymls: ::Gitlab::Template::GitlabCiSyntaxYmlTemplate,
metrics_dashboard_ymls: ::Gitlab::Template::MetricsDashboardTemplate,
issues: ::Gitlab::Template::IssueTemplate,
merge_requests: ::Gitlab::Template::MergeRequestTemplate
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index cc94536bf79..42042406f3f 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -34,6 +34,7 @@ class UsersFinder
users = User.all.order_id_desc
users = by_username(users)
users = by_id(users)
+ users = by_admins(users)
users = by_search(users)
users = by_blocked(users)
users = by_active(users)
@@ -62,6 +63,12 @@ class UsersFinder
users.id_in(params[:id])
end
+ def by_admins(users)
+ return users unless params[:admins] && current_user&.can_read_all_resources?
+
+ users.admins
+ end
+
def by_search(users)
return users unless params[:search].present?
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index 17f9b5b5637..32ca6de9b96 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -18,12 +18,12 @@ module Mutations
argument :queue_name,
GraphQL::STRING_TYPE,
required: true,
- description: 'The name of the queue to delete jobs from'
+ description: 'The name of the queue to delete jobs from.'
field :result,
Types::Admin::SidekiqQueues::DeleteJobsResponseType,
null: true,
- description: 'Information about the status of the deletion request'
+ description: 'Information about the status of the deletion request.'
def ready?(**args)
unless current_user&.admin?
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
index 8c6b4005cf8..3a57cb9670d 100644
--- a/app/graphql/mutations/alert_management/base.rb
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -7,26 +7,26 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: "The project the alert to mutate is in"
+ description: "The project the alert to mutate is in."
argument :iid, GraphQL::STRING_TYPE,
required: true,
- description: "The IID of the alert to mutate"
+ description: "The IID of the alert to mutate."
field :alert,
Types::AlertManagement::AlertType,
null: true,
- description: "The alert after mutation"
+ description: "The alert after mutation."
field :todo,
Types::TodoType,
null: true,
- description: "The todo after mutation"
+ description: "The todo after mutation."
field :issue,
Types::IssueType,
null: true,
- description: "The issue created after mutation"
+ description: "The issue created after mutation."
authorize :update_alert_management_alert
diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb
index ddb75e66bb4..ff165d7f302 100644
--- a/app/graphql/mutations/alert_management/http_integration/create.rb
+++ b/app/graphql/mutations/alert_management/http_integration/create.rb
@@ -10,32 +10,41 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'The project to create the integration in'
+ description: 'The project to create the integration in.'
argument :name, GraphQL::STRING_TYPE,
required: true,
- description: 'The name of the integration'
+ description: 'The name of the integration.'
argument :active, GraphQL::BOOLEAN_TYPE,
required: true,
- description: 'Whether the integration is receiving alerts'
+ description: 'Whether the integration is receiving alerts.'
def resolve(args)
- project = authorized_find!(full_path: args[:project_path])
+ @project = authorized_find!(full_path: args[:project_path])
response ::AlertManagement::HttpIntegrations::CreateService.new(
project,
current_user,
- args.slice(:name, :active)
+ http_integration_params(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
end
+
+Mutations::AlertManagement::HttpIntegration::Create.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::Create')
diff --git a/app/graphql/mutations/alert_management/http_integration/destroy.rb b/app/graphql/mutations/alert_management/http_integration/destroy.rb
index 45d4bd778da..d0420e2bcb5 100644
--- a/app/graphql/mutations/alert_management/http_integration/destroy.rb
+++ b/app/graphql/mutations/alert_management/http_integration/destroy.rb
@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
required: true,
- description: "The ID of the integration to remove"
+ description: "The ID of the integration to remove."
def resolve(id:)
integration = authorized_find!(id: id)
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 d328eabf244..147df982bec 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
@@ -7,7 +7,7 @@ module Mutations
field :integration,
Types::AlertManagement::HttpIntegrationType,
null: true,
- description: "The HTTP integration"
+ description: "The HTTP integration."
authorize :admin_operations
diff --git a/app/graphql/mutations/alert_management/http_integration/reset_token.rb b/app/graphql/mutations/alert_management/http_integration/reset_token.rb
index 3938b38260e..bf73a9eaae7 100644
--- a/app/graphql/mutations/alert_management/http_integration/reset_token.rb
+++ b/app/graphql/mutations/alert_management/http_integration/reset_token.rb
@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
required: true,
- description: "The ID of the integration to mutate"
+ description: "The ID of the integration to mutate."
def resolve(id:)
integration = authorized_find!(id: id)
diff --git a/app/graphql/mutations/alert_management/http_integration/update.rb b/app/graphql/mutations/alert_management/http_integration/update.rb
index 98e0f7eb14f..431fccaa5e5 100644
--- a/app/graphql/mutations/alert_management/http_integration/update.rb
+++ b/app/graphql/mutations/alert_management/http_integration/update.rb
@@ -8,15 +8,15 @@ module Mutations
argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
required: true,
- description: "The ID of the integration to mutate"
+ description: "The ID of the integration to mutate."
argument :name, GraphQL::STRING_TYPE,
required: false,
- description: "The name of the integration"
+ description: "The name of the integration."
argument :active, GraphQL::BOOLEAN_TYPE,
required: false,
- description: "Whether the integration is receiving alerts"
+ description: "Whether the integration is receiving alerts."
def resolve(args)
integration = authorized_find!(id: args[:id])
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
index 935ec53795c..c676cde90b4 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/create.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -10,15 +10,15 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'The project to create the integration in'
+ description: 'The project to create the integration in.'
argument :active, GraphQL::BOOLEAN_TYPE,
required: true,
- description: 'Whether the integration is receiving alerts'
+ description: 'Whether the integration is receiving alerts.'
argument :api_url, GraphQL::STRING_TYPE,
required: true,
- description: 'Endpoint at which prometheus can be queried'
+ description: 'Endpoint at which prometheus can be queried.'
def resolve(args)
project = authorized_find!(full_path: args[:project_path])
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
index 6b690ac239a..cb243f49b33 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
@@ -7,7 +7,7 @@ module Mutations
field :integration,
Types::AlertManagement::PrometheusIntegrationType,
null: true,
- description: "The newly created integration"
+ description: "The newly created integration."
authorize :admin_project
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
index effecd8364d..428be091436 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::PrometheusService],
required: true,
- description: "The ID of the integration to mutate"
+ description: "The ID of the integration to mutate."
def resolve(id:)
integration = authorized_find!(id: id)
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/update.rb b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
index 46f4c23b739..62fb81bca5a 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/update.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
@@ -8,15 +8,15 @@ module Mutations
argument :id, Types::GlobalIDType[::PrometheusService],
required: true,
- description: "The ID of the integration to mutate"
+ description: "The ID of the integration to mutate."
argument :active, GraphQL::BOOLEAN_TYPE,
required: false,
- description: "Whether the integration is receiving alerts"
+ description: "Whether the integration is receiving alerts."
argument :api_url, GraphQL::STRING_TYPE,
required: false,
- description: "Endpoint at which prometheus can be queried"
+ description: "Endpoint at which prometheus can be queried."
def resolve(args)
integration = authorized_find!(id: args[:id])
diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb
index 74185dca529..67f8ba9118f 100644
--- a/app/graphql/mutations/alert_management/update_alert_status.rb
+++ b/app/graphql/mutations/alert_management/update_alert_status.rb
@@ -7,7 +7,7 @@ module Mutations
argument :status, Types::AlertManagement::StatusEnum,
required: true,
- description: 'The status to set the alert'
+ description: 'The status to set the alert.'
def resolve(project_path:, iid:, status:)
alert = authorized_find!(project_path: project_path, iid: iid)
diff --git a/app/graphql/mutations/award_emojis/base.rb b/app/graphql/mutations/award_emojis/base.rb
index 4bd8304c3fc..4f41a9cafd8 100644
--- a/app/graphql/mutations/award_emojis/base.rb
+++ b/app/graphql/mutations/award_emojis/base.rb
@@ -12,7 +12,7 @@ module Mutations
argument :awardable_id,
::Types::GlobalIDType[::Awardable],
required: true,
- description: 'The global ID of the awardable resource'
+ description: 'The global ID of the awardable resource.'
argument :name,
GraphQL::STRING_TYPE,
@@ -22,7 +22,7 @@ module Mutations
field :award_emoji,
Types::AwardEmojis::AwardEmojiType,
null: true,
- description: 'The award emoji after mutation'
+ description: 'The award emoji after mutation.'
private
diff --git a/app/graphql/mutations/boards/destroy.rb b/app/graphql/mutations/boards/destroy.rb
index 7c381113d38..8ec13b885d5 100644
--- a/app/graphql/mutations/boards/destroy.rb
+++ b/app/graphql/mutations/boards/destroy.rb
@@ -8,11 +8,11 @@ module Mutations
field :board,
Types::BoardType,
null: true,
- description: 'The board after mutation'
+ description: 'The board after mutation.'
argument :id,
::Types::GlobalIDType[::Board],
required: true,
- description: 'The global ID of the board to destroy'
+ description: 'The global ID of the board to destroy.'
authorize :admin_board
diff --git a/app/graphql/mutations/boards/issues/issue_move_list.rb b/app/graphql/mutations/boards/issues/issue_move_list.rb
index 813b6d3cb2a..91dfd9fc3e9 100644
--- a/app/graphql/mutations/boards/issues/issue_move_list.rb
+++ b/app/graphql/mutations/boards/issues/issue_move_list.rb
@@ -9,31 +9,31 @@ module Mutations
argument :board_id, GraphQL::ID_TYPE,
required: true,
loads: Types::BoardType,
- description: 'Global ID of the board that the issue is in'
+ description: 'Global ID of the board that the issue is in.'
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'Project the issue to mutate is in'
+ description: 'Project the issue to mutate is in.'
argument :iid, GraphQL::STRING_TYPE,
required: true,
- description: 'IID of the issue to mutate'
+ description: 'IID of the issue to mutate.'
argument :from_list_id, GraphQL::ID_TYPE,
required: false,
- description: 'ID of the board list that the issue will be moved from'
+ description: 'ID of the board list that the issue will be moved from.'
argument :to_list_id, GraphQL::ID_TYPE,
required: false,
- description: 'ID of the board list that the issue will be moved to'
+ description: 'ID of the board list that the issue will be moved to.'
argument :move_before_id, GraphQL::ID_TYPE,
required: false,
- description: 'ID of issue that should be placed before the current issue'
+ description: 'ID of issue that should be placed before the current issue.'
argument :move_after_id, GraphQL::ID_TYPE,
required: false,
- description: 'ID of issue that should be placed after the current issue'
+ description: 'ID of issue that should be placed after the current issue.'
def ready?(**args)
if move_arguments(args).blank?
diff --git a/app/graphql/mutations/boards/lists/base.rb b/app/graphql/mutations/boards/lists/base.rb
index d244d6bf8dd..34c138bddc9 100644
--- a/app/graphql/mutations/boards/lists/base.rb
+++ b/app/graphql/mutations/boards/lists/base.rb
@@ -8,12 +8,12 @@ module Mutations
argument :board_id, ::Types::GlobalIDType[::Board],
required: true,
- description: 'Global ID of the issue board to mutate'
+ description: 'Global ID of the issue board to mutate.'
field :list,
Types::BoardListType,
null: true,
- description: 'List of the issue board'
+ description: 'List of the issue board.'
authorize :admin_list
diff --git a/app/graphql/mutations/boards/lists/create.rb b/app/graphql/mutations/boards/lists/create.rb
index f6df63365b2..9eb9a4d4b87 100644
--- a/app/graphql/mutations/boards/lists/create.rb
+++ b/app/graphql/mutations/boards/lists/create.rb
@@ -8,11 +8,11 @@ module Mutations
argument :backlog, GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Create the backlog list'
+ description: 'Create the backlog list.'
argument :label_id, ::Types::GlobalIDType[::Label],
required: false,
- description: 'Global ID of an existing label'
+ description: 'Global ID of an existing label.'
def ready?(**args)
if args.slice(*mutually_exclusive_args).size != 1
diff --git a/app/graphql/mutations/boards/lists/update.rb b/app/graphql/mutations/boards/lists/update.rb
index 14502b5174f..d30d1d89bb2 100644
--- a/app/graphql/mutations/boards/lists/update.rb
+++ b/app/graphql/mutations/boards/lists/update.rb
@@ -13,16 +13,16 @@ module Mutations
argument :position, GraphQL::INT_TYPE,
required: false,
- description: 'Position of list within the board'
+ description: 'Position of list within the board.'
argument :collapsed, GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Indicates if list is collapsed for this user'
+ description: 'Indicates if list is collapsed for this user.'
field :list,
Types::BoardListType,
null: true,
- description: 'Mutated list'
+ description: 'Mutated list.'
def resolve(list: nil, **args)
raise_resource_not_available_error! unless can_read_list?(list)
diff --git a/app/graphql/mutations/boards/update.rb b/app/graphql/mutations/boards/update.rb
index 5cb434e41fd..b4f8179829e 100644
--- a/app/graphql/mutations/boards/update.rb
+++ b/app/graphql/mutations/boards/update.rb
@@ -30,6 +30,8 @@ module Mutations
}
end
+ private
+
def find_object(id:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb
index 214fead2e80..9fe9bef5403 100644
--- a/app/graphql/mutations/branches/create.rb
+++ b/app/graphql/mutations/branches/create.rb
@@ -9,21 +9,21 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'Project full path the branch is associated with'
+ description: 'Project full path the branch is associated with.'
argument :name, GraphQL::STRING_TYPE,
required: true,
- description: 'Name of the branch'
+ description: 'Name of the branch.'
argument :ref,
GraphQL::STRING_TYPE,
required: true,
- description: 'Branch name or commit SHA to create branch from'
+ description: 'Branch name or commit SHA to create branch from.'
field :branch,
Types::BranchType,
null: true,
- description: 'Branch after mutation'
+ description: 'Branch after mutation.'
authorize :push_code
diff --git a/app/graphql/mutations/ci/base.rb b/app/graphql/mutations/ci/base.rb
deleted file mode 100644
index 0ccee5661b7..00000000000
--- a/app/graphql/mutations/ci/base.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Ci
- class Base < BaseMutation
- PipelineID = ::Types::GlobalIDType[::Ci::Pipeline]
-
- argument :id, PipelineID,
- required: true,
- description: 'The ID of the pipeline to mutate'
-
- private
-
- def find_object(id:)
- # TODO: remove this line when the compatibility layer is removed
- # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
- id = PipelineID.coerce_isolated_input(id)
- GlobalID::Locator.locate(id)
- end
- end
- end
-end
diff --git a/app/graphql/mutations/ci/ci_cd_settings_update.rb b/app/graphql/mutations/ci/ci_cd_settings_update.rb
new file mode 100644
index 00000000000..6b7750ee860
--- /dev/null
+++ b/app/graphql/mutations/ci/ci_cd_settings_update.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ class CiCdSettingsUpdate < BaseMutation
+ include FindsProject
+
+ graphql_name 'CiCdSettingsUpdate'
+
+ authorize :admin_project
+
+ argument :full_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Full Path of the project the settings belong to.'
+
+ argument :keep_latest_artifact, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Indicates if the latest artifact should be kept for this project.'
+
+ def resolve(full_path:, **args)
+ project = authorized_find!(full_path)
+ settings = project.ci_cd_settings
+ settings.update(args)
+
+ { errors: errors_on_object(settings) }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline/base.rb b/app/graphql/mutations/ci/pipeline/base.rb
new file mode 100644
index 00000000000..ebfab56e743
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline/base.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Pipeline
+ class Base < BaseMutation
+ PipelineID = ::Types::GlobalIDType[::Ci::Pipeline]
+
+ argument :id, PipelineID,
+ required: true,
+ description: 'The ID of the pipeline to mutate.'
+
+ private
+
+ def find_object(id:)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = PipelineID.coerce_isolated_input(id)
+ GlobalID::Locator.locate(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline/cancel.rb b/app/graphql/mutations/ci/pipeline/cancel.rb
new file mode 100644
index 00000000000..3fb34a37cfc
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline/cancel.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Pipeline
+ class Cancel < Base
+ graphql_name 'PipelineCancel'
+
+ authorize :update_pipeline
+
+ def resolve(id:)
+ pipeline = authorized_find!(id: id)
+
+ if pipeline.cancelable?
+ pipeline.cancel_running
+ { success: true, errors: [] }
+ else
+ { success: false, errors: ['Pipeline is not cancelable'] }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline/destroy.rb b/app/graphql/mutations/ci/pipeline/destroy.rb
new file mode 100644
index 00000000000..3f933818ce1
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline/destroy.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Pipeline
+ class Destroy < Base
+ graphql_name 'PipelineDestroy'
+
+ authorize :destroy_pipeline
+
+ def resolve(id:)
+ pipeline = authorized_find!(id: id)
+ project = pipeline.project
+
+ result = ::Ci::DestroyPipelineService.new(project, current_user).execute(pipeline)
+ {
+ success: result.success?,
+ errors: result.errors
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline/retry.rb b/app/graphql/mutations/ci/pipeline/retry.rb
new file mode 100644
index 00000000000..a12330470f0
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline/retry.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Pipeline
+ class Retry < Base
+ graphql_name 'PipelineRetry'
+
+ field :pipeline,
+ Types::Ci::PipelineType,
+ null: true,
+ description: 'The pipeline after mutation.'
+
+ authorize :update_pipeline
+
+ def resolve(id:)
+ pipeline = authorized_find!(id: id)
+ project = pipeline.project
+
+ ::Ci::RetryPipelineService.new(project, current_user).execute(pipeline)
+ {
+ pipeline: pipeline,
+ errors: errors_on_object(pipeline)
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline_cancel.rb b/app/graphql/mutations/ci/pipeline_cancel.rb
deleted file mode 100644
index bc881e2ac02..00000000000
--- a/app/graphql/mutations/ci/pipeline_cancel.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Ci
- class PipelineCancel < Base
- graphql_name 'PipelineCancel'
-
- authorize :update_pipeline
-
- def resolve(id:)
- pipeline = authorized_find!(id: id)
-
- if pipeline.cancelable?
- pipeline.cancel_running
- { success: true, errors: [] }
- else
- { success: false, errors: ['Pipeline is not cancelable'] }
- end
- end
- end
- end
-end
diff --git a/app/graphql/mutations/ci/pipeline_destroy.rb b/app/graphql/mutations/ci/pipeline_destroy.rb
deleted file mode 100644
index bb24d416583..00000000000
--- a/app/graphql/mutations/ci/pipeline_destroy.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Ci
- class PipelineDestroy < Base
- graphql_name 'PipelineDestroy'
-
- authorize :destroy_pipeline
-
- def resolve(id:)
- pipeline = authorized_find!(id: id)
- project = pipeline.project
-
- result = ::Ci::DestroyPipelineService.new(project, current_user).execute(pipeline)
- {
- success: result.success?,
- errors: result.errors
- }
- end
- end
- end
-end
diff --git a/app/graphql/mutations/ci/pipeline_retry.rb b/app/graphql/mutations/ci/pipeline_retry.rb
deleted file mode 100644
index 0669bfc449c..00000000000
--- a/app/graphql/mutations/ci/pipeline_retry.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Ci
- class PipelineRetry < Base
- graphql_name 'PipelineRetry'
-
- field :pipeline,
- Types::Ci::PipelineType,
- null: true,
- description: 'The pipeline after mutation'
-
- authorize :update_pipeline
-
- def resolve(id:)
- pipeline = authorized_find!(id: id)
- project = pipeline.project
-
- ::Ci::RetryPipelineService.new(project, current_user).execute(pipeline)
- {
- pipeline: pipeline,
- errors: errors_on_object(pipeline)
- }
- end
- end
- end
-end
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index 2b9107350fd..ae14401558b 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -9,15 +9,15 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'Project full path the branch is associated with'
+ description: 'Project full path the branch is associated with.'
argument :branch, GraphQL::STRING_TYPE,
required: true,
- description: 'Name of the branch to commit into, it can be a new branch'
+ description: 'Name of the branch to commit into, it can be a new branch.'
argument :start_branch, GraphQL::STRING_TYPE,
required: false,
- description: 'If on a new branch, name of the original branch'
+ description: 'If on a new branch, name of the original branch.'
argument :message,
GraphQL::STRING_TYPE,
@@ -27,12 +27,12 @@ module Mutations
argument :actions,
[Types::CommitActionType],
required: true,
- description: 'Array of action hashes to commit as a batch'
+ description: 'Array of action hashes to commit as a batch.'
field :commit,
Types::CommitType,
null: true,
- description: 'The commit after mutation'
+ description: 'The commit after mutation.'
authorize :push_code
diff --git a/app/graphql/mutations/concerns/mutations/authorizes_project.rb b/app/graphql/mutations/concerns/mutations/authorizes_project.rb
deleted file mode 100644
index 87341525d6c..00000000000
--- a/app/graphql/mutations/concerns/mutations/authorizes_project.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module AuthorizesProject
- include ResolvesProject
-
- def authorized_find_project!(full_path:)
- authorized_find!(full_path: full_path)
- end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
- end
-end
diff --git a/app/graphql/mutations/concerns/mutations/finds_project.rb b/app/graphql/mutations/concerns/mutations/finds_project.rb
new file mode 100644
index 00000000000..577f9dc90f8
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/finds_project.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Mutations
+ module FindsProject
+ private
+
+ def find_object(full_path)
+ Project.find_by_full_path(full_path)
+ end
+ end
+end
diff --git a/app/graphql/mutations/concerns/mutations/resolves_namespace.rb b/app/graphql/mutations/concerns/mutations/resolves_namespace.rb
new file mode 100644
index 00000000000..35009623c69
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/resolves_namespace.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ResolvesNamespace
+ extend ActiveSupport::Concern
+
+ def resolve_namespace(full_path:)
+ namespace_resolver.resolve(full_path: full_path)
+ end
+
+ def namespace_resolver
+ Resolvers::NamespaceResolver.new(object: nil, context: context, field: nil)
+ 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 04a9abf9529..e2b3f4b046f 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: 'The project full path the resource is associated with.'
argument :group_path, GraphQL::ID_TYPE,
required: false,
- description: 'The group full path the resource is associated with'
+ description: 'The group full path the resource is associated with.'
end
def ready?(**args)
diff --git a/app/graphql/mutations/concerns/mutations/resolves_subscription.rb b/app/graphql/mutations/concerns/mutations/resolves_subscription.rb
index e8c5d0d404d..e26ae7d228c 100644
--- a/app/graphql/mutations/concerns/mutations/resolves_subscription.rb
+++ b/app/graphql/mutations/concerns/mutations/resolves_subscription.rb
@@ -7,7 +7,7 @@ module Mutations
argument :subscribed_state,
GraphQL::BOOLEAN_TYPE,
required: true,
- description: 'The desired state of the subscription'
+ description: 'The desired state of the subscription.'
end
def resolve(project_path:, iid:, subscribed_state:)
diff --git a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb b/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
index 7aef55f8011..e5df8565618 100644
--- a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
+++ b/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
@@ -8,7 +8,7 @@ module Mutations
field :spam,
GraphQL::BOOLEAN_TYPE,
null: true,
- description: 'Indicates whether the operation returns a record detected as spam'
+ description: 'Indicates whether the operation returns a record detected as spam.'
end
def with_spam_params(&block)
diff --git a/app/graphql/mutations/container_expiration_policies/update.rb b/app/graphql/mutations/container_expiration_policies/update.rb
index 4bff04bb705..37cf2fa6bf3 100644
--- a/app/graphql/mutations/container_expiration_policies/update.rb
+++ b/app/graphql/mutations/container_expiration_policies/update.rb
@@ -12,7 +12,7 @@ module Mutations
argument :project_path,
GraphQL::ID_TYPE,
required: true,
- description: 'The project path where the container expiration policy is located'
+ description: 'The project path where the container expiration policy is located.'
argument :enabled,
GraphQL::BOOLEAN_TYPE,
@@ -47,7 +47,7 @@ module Mutations
field :container_expiration_policy,
Types::ContainerExpirationPolicyType,
null: true,
- description: 'The container expiration policy after mutation'
+ description: 'The container expiration policy after mutation.'
def resolve(project_path:, **args)
project = authorized_find!(full_path: project_path)
diff --git a/app/graphql/mutations/container_repositories/destroy_tags.rb b/app/graphql/mutations/container_repositories/destroy_tags.rb
index ca6a67867c3..636ceccee04 100644
--- a/app/graphql/mutations/container_repositories/destroy_tags.rb
+++ b/app/graphql/mutations/container_repositories/destroy_tags.rb
@@ -28,7 +28,7 @@ module Mutations
field :deleted_tag_names,
[GraphQL::STRING_TYPE],
- description: 'Deleted container repository tags',
+ description: 'Deleted container repository tags.',
null: false
def resolve(id:, tag_names:)
diff --git a/app/graphql/mutations/custom_emoji/create.rb b/app/graphql/mutations/custom_emoji/create.rb
index d912a29d12e..9ec96be0f26 100644
--- a/app/graphql/mutations/custom_emoji/create.rb
+++ b/app/graphql/mutations/custom_emoji/create.rb
@@ -12,20 +12,20 @@ module Mutations
field :custom_emoji,
Types::CustomEmojiType,
null: true,
- description: 'The new custom emoji'
+ description: 'The new custom emoji.'
argument :group_path, GraphQL::ID_TYPE,
required: true,
- description: 'Namespace full path the emoji is associated with'
+ description: 'Namespace full path the emoji is associated with.'
argument :name, GraphQL::STRING_TYPE,
required: true,
- description: 'Name of the emoji'
+ description: 'Name of the emoji.'
argument :url, GraphQL::STRING_TYPE,
required: true,
as: :file,
- description: 'Location of the emoji file'
+ description: 'Location of the emoji file.'
def resolve(group_path:, **args)
group = authorized_find!(group_path: group_path)
diff --git a/app/graphql/mutations/design_management/base.rb b/app/graphql/mutations/design_management/base.rb
index 69fd22e46cd..14d85885793 100644
--- a/app/graphql/mutations/design_management/base.rb
+++ b/app/graphql/mutations/design_management/base.rb
@@ -7,11 +7,11 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: "The project where the issue is to upload designs for"
+ description: "The project where the issue is to upload designs for."
argument :iid, GraphQL::ID_TYPE,
required: true,
- description: "The IID of the issue to modify designs for"
+ description: "The IID of the issue to modify designs for."
private
diff --git a/app/graphql/mutations/design_management/delete.rb b/app/graphql/mutations/design_management/delete.rb
index d2ef2c9bcca..f604542edef 100644
--- a/app/graphql/mutations/design_management/delete.rb
+++ b/app/graphql/mutations/design_management/delete.rb
@@ -9,14 +9,14 @@ module Mutations
argument :filenames, [GraphQL::STRING_TYPE],
required: true,
- description: "The filenames of the designs to delete",
+ description: "The filenames of the designs to delete.",
prepare: ->(names, _ctx) do
names.presence || (raise Errors::ArgumentError, 'no filenames')
end
field :version, Types::DesignManagement::VersionType,
null: true, # null on error
- description: 'The new version in which the designs are deleted'
+ description: 'The new version in which the designs are deleted.'
authorize :destroy_design
diff --git a/app/graphql/mutations/design_management/move.rb b/app/graphql/mutations/design_management/move.rb
index aed4cfec0fd..fe280e926d2 100644
--- a/app/graphql/mutations/design_management/move.rb
+++ b/app/graphql/mutations/design_management/move.rb
@@ -8,17 +8,17 @@ module Mutations
DesignID = ::Types::GlobalIDType[::DesignManagement::Design]
argument :id, DesignID, required: true, as: :current_design,
- description: "ID of the design to move"
+ description: "ID of the design to move."
argument :previous, DesignID, required: false, as: :previous_design,
- description: "ID of the immediately preceding design"
+ description: "ID of the immediately preceding design."
argument :next, DesignID, required: false, as: :next_design,
- description: "ID of the immediately following design"
+ description: "ID of the immediately following design."
field :design_collection, Types::DesignManagement::DesignCollectionType,
null: true,
- description: "The current state of the collection"
+ description: "The current state of the collection."
def resolve(**args)
service = ::DesignManagement::MoveDesignsService.new(current_user, parameters(**args))
diff --git a/app/graphql/mutations/design_management/upload.rb b/app/graphql/mutations/design_management/upload.rb
index 1ed7f8e49e6..2ccf2ef8ff5 100644
--- a/app/graphql/mutations/design_management/upload.rb
+++ b/app/graphql/mutations/design_management/upload.rb
@@ -7,13 +7,13 @@ module Mutations
argument :files, [ApolloUploadServer::Upload],
required: true,
- description: "The files to upload"
+ description: "The files to upload."
authorize :create_design
field :designs, [Types::DesignManagement::DesignType],
null: false,
- description: "The designs that were uploaded by the mutation"
+ description: "The designs that were uploaded by the mutation."
field :skipped_designs, [Types::DesignManagement::DesignType],
null: false,
diff --git a/app/graphql/mutations/discussions/toggle_resolve.rb b/app/graphql/mutations/discussions/toggle_resolve.rb
index 0e3baf8d548..c9834c946b2 100644
--- a/app/graphql/mutations/discussions/toggle_resolve.rb
+++ b/app/graphql/mutations/discussions/toggle_resolve.rb
@@ -10,17 +10,17 @@ module Mutations
argument :id,
Types::GlobalIDType[Discussion],
required: true,
- description: 'The global ID of the discussion'
+ description: 'The global ID of the discussion.'
argument :resolve,
GraphQL::BOOLEAN_TYPE,
required: true,
- description: 'Will resolve the discussion when true, and unresolve the discussion when false'
+ description: 'Will resolve the discussion when true, and unresolve the discussion when false.'
field :discussion,
Types::Notes::DiscussionType,
null: true,
- description: 'The discussion after mutation'
+ description: 'The discussion after mutation.'
def resolve(id:, resolve:)
discussion = authorized_find_discussion!(id: id)
diff --git a/app/graphql/mutations/environments/canary_ingress/update.rb b/app/graphql/mutations/environments/canary_ingress/update.rb
index 1798143053a..45dcc8314a0 100644
--- a/app/graphql/mutations/environments/canary_ingress/update.rb
+++ b/app/graphql/mutations/environments/canary_ingress/update.rb
@@ -11,12 +11,12 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Environment],
required: true,
- description: 'The global ID of the environment to update'
+ description: 'The global ID of the environment to update.'
argument :weight,
GraphQL::INT_TYPE,
required: true,
- description: 'The weight of the Canary Ingress'
+ description: 'The weight of the Canary Ingress.'
def resolve(id:, **kwargs)
environment = authorized_find!(id: id)
diff --git a/app/graphql/mutations/issues/base.rb b/app/graphql/mutations/issues/base.rb
index 529d48f3cd0..b25987a43f6 100644
--- a/app/graphql/mutations/issues/base.rb
+++ b/app/graphql/mutations/issues/base.rb
@@ -7,16 +7,16 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: "The project the issue to mutate is in"
+ description: "The project the issue to mutate is in."
argument :iid, GraphQL::STRING_TYPE,
required: true,
- description: "The IID of the issue to mutate"
+ description: "The IID of the issue to mutate."
field :issue,
Types::IssueType,
null: true,
- description: "The issue after mutation"
+ description: "The issue after mutation."
authorize :update_issue
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 1454916bc77..18b80ff1736 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -12,11 +12,11 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'Project full path the issue is associated with'
+ description: 'Project full path the issue is associated with.'
argument :iid, GraphQL::INT_TYPE,
required: false,
- description: 'The IID (internal ID) of a project issue. Only admins and project owners can modify'
+ description: 'The IID (internal ID) of a project issue. Only admins and project owners can modify.'
argument :title, GraphQL::STRING_TYPE,
required: true,
@@ -24,7 +24,7 @@ module Mutations
argument :milestone_id, ::Types::GlobalIDType[::Milestone],
required: false,
- description: 'The ID of the milestone to assign to the issue. On update milestone will be removed if set to null'
+ description: 'The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.'
argument :labels, [GraphQL::STRING_TYPE],
required: false,
@@ -32,28 +32,28 @@ module Mutations
argument :label_ids, [::Types::GlobalIDType[::Label]],
required: false,
- description: 'The IDs of labels to be added to the issue'
+ description: 'The IDs of labels to be added to the issue.'
argument :created_at, Types::TimeType,
required: false,
- description: 'Timestamp when the issue was created. Available only for admins and project owners'
+ description: 'Timestamp when the issue was created. Available only for admins and project owners.'
argument :merge_request_to_resolve_discussions_of, ::Types::GlobalIDType[::MergeRequest],
required: false,
- description: 'The IID of a merge request for which to resolve discussions'
+ description: 'The IID of a merge request for which to resolve discussions.'
argument :discussion_to_resolve, GraphQL::STRING_TYPE,
required: false,
- description: 'The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`'
+ description: 'The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`.'
argument :assignee_ids, [::Types::GlobalIDType[::User]],
required: false,
- description: 'The array of user IDs to assign to the issue'
+ description: 'The array of user IDs to assign to the issue.'
field :issue,
Types::IssueType,
null: true,
- description: 'The issue after mutation'
+ description: 'The issue after mutation.'
def ready?(**args)
if args.slice(*mutually_exclusive_label_args).size > 1
diff --git a/app/graphql/mutations/issues/move.rb b/app/graphql/mutations/issues/move.rb
index e6971c9df8c..3f97325c921 100644
--- a/app/graphql/mutations/issues/move.rb
+++ b/app/graphql/mutations/issues/move.rb
@@ -8,7 +8,7 @@ module Mutations
argument :target_project_path,
GraphQL::ID_TYPE,
required: true,
- description: 'The project to move the issue to'
+ description: 'The project to move the issue to.'
def resolve(project_path:, iid:, target_project_path:)
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/267762')
diff --git a/app/graphql/mutations/issues/set_due_date.rb b/app/graphql/mutations/issues/set_due_date.rb
index effd863c541..da7892f4ed4 100644
--- a/app/graphql/mutations/issues/set_due_date.rb
+++ b/app/graphql/mutations/issues/set_due_date.rb
@@ -8,7 +8,7 @@ module Mutations
argument :due_date,
Types::TimeType,
required: true,
- description: 'The desired due date for the issue'
+ description: 'The desired due date for the issue.'
def resolve(project_path:, iid:, due_date:)
issue = authorized_find!(project_path: project_path, iid: iid)
diff --git a/app/graphql/mutations/issues/set_locked.rb b/app/graphql/mutations/issues/set_locked.rb
index 63a8483067a..611226e48ad 100644
--- a/app/graphql/mutations/issues/set_locked.rb
+++ b/app/graphql/mutations/issues/set_locked.rb
@@ -8,7 +8,7 @@ module Mutations
argument :locked,
GraphQL::BOOLEAN_TYPE,
required: true,
- description: 'Whether or not to lock discussion on the issue'
+ description: 'Whether or not to lock discussion on the issue.'
def resolve(project_path:, iid:, locked:)
issue = authorized_find!(project_path: project_path, iid: iid)
diff --git a/app/graphql/mutations/issues/update.rb b/app/graphql/mutations/issues/update.rb
index d34e351b2a6..eea2cd49aa0 100644
--- a/app/graphql/mutations/issues/update.rb
+++ b/app/graphql/mutations/issues/update.rb
@@ -13,18 +13,18 @@ module Mutations
argument :milestone_id, GraphQL::ID_TYPE, # rubocop: disable Graphql/IDType
required: false,
- description: 'The ID of the milestone to assign to the issue. On update milestone will be removed if set to null'
+ description: 'The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.'
argument :add_label_ids, [GraphQL::ID_TYPE],
required: false,
- description: 'The IDs of labels to be added to the issue'
+ description: 'The IDs of labels to be added to the issue.'
argument :remove_label_ids, [GraphQL::ID_TYPE],
required: false,
- description: 'The IDs of labels to be removed from the issue'
+ description: 'The IDs of labels to be removed from the issue.'
argument :state_event, Types::IssueStateEventEnum,
- description: 'Close or reopen an issue',
+ description: 'Close or reopen an issue.',
required: false
def resolve(project_path:, iid:, **args)
diff --git a/app/graphql/mutations/jira_import/import_users.rb b/app/graphql/mutations/jira_import/import_users.rb
index 0d59537b903..616ef390657 100644
--- a/app/graphql/mutations/jira_import/import_users.rb
+++ b/app/graphql/mutations/jira_import/import_users.rb
@@ -14,10 +14,10 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'The project to import the Jira users into'
+ description: 'The project to import the Jira users into.'
argument :start_at, GraphQL::INT_TYPE,
required: false,
- description: 'The index of the record the import should started at, default 0 (50 records returned)'
+ 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)
diff --git a/app/graphql/mutations/jira_import/start.rb b/app/graphql/mutations/jira_import/start.rb
index eda28059272..3d50ebde13a 100644
--- a/app/graphql/mutations/jira_import/start.rb
+++ b/app/graphql/mutations/jira_import/start.rb
@@ -10,21 +10,21 @@ module Mutations
field :jira_import,
Types::JiraImportType,
null: true,
- description: 'The Jira import data after mutation'
+ description: 'The Jira import data after mutation.'
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'The project to import the Jira project into'
+ description: 'The project to import the Jira project into.'
argument :jira_project_key, GraphQL::STRING_TYPE,
required: true,
- description: 'Project key of the importer Jira project'
+ description: 'Project key of the importer Jira project.'
argument :jira_project_name, GraphQL::STRING_TYPE,
required: false,
- description: 'Project name of the importer Jira project'
+ description: 'Project name of the importer Jira project.'
argument :users_mapping,
[Types::JiraUsersMappingInputType],
required: false,
- description: 'The mapping of Jira to GitLab users'
+ description: 'The mapping of Jira to GitLab users.'
def resolve(project_path:, jira_project_key:, users_mapping:)
project = authorized_find!(full_path: project_path)
diff --git a/app/graphql/mutations/labels/create.rb b/app/graphql/mutations/labels/create.rb
index cb03651618e..ccbd1c37cbf 100644
--- a/app/graphql/mutations/labels/create.rb
+++ b/app/graphql/mutations/labels/create.rb
@@ -10,20 +10,20 @@ module Mutations
field :label,
Types::LabelType,
null: true,
- description: 'The label after mutation'
+ description: 'The label after mutation.'
argument :title, GraphQL::STRING_TYPE,
required: true,
- description: 'Title of the label'
+ description: 'Title of the label.'
argument :description, GraphQL::STRING_TYPE,
required: false,
- description: 'Description of the label'
+ description: 'Description of the label.'
argument :color, GraphQL::STRING_TYPE,
required: false,
default_value: Label::DEFAULT_COLOR,
- description: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords"
+ description: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords."
authorize :admin_label
diff --git a/app/graphql/mutations/merge_requests/base.rb b/app/graphql/mutations/merge_requests/base.rb
index 57920259cf7..cd919a19ba2 100644
--- a/app/graphql/mutations/merge_requests/base.rb
+++ b/app/graphql/mutations/merge_requests/base.rb
@@ -7,16 +7,16 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: "The project the merge request to mutate is in"
+ description: "The project the merge request to mutate is in."
argument :iid, GraphQL::STRING_TYPE,
required: true,
- description: "The IID of the merge request to mutate"
+ description: "The IID of the merge request to mutate."
field :merge_request,
Types::MergeRequestType,
null: true,
- description: "The merge request after mutation"
+ description: "The merge request after mutation."
authorize :update_merge_request
diff --git a/app/graphql/mutations/merge_requests/create.rb b/app/graphql/mutations/merge_requests/create.rb
index fd2cd58a5ee..64fa8417e50 100644
--- a/app/graphql/mutations/merge_requests/create.rb
+++ b/app/graphql/mutations/merge_requests/create.rb
@@ -9,7 +9,7 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'Project full path the merge request is associated with'
+ description: 'Project full path the merge request is associated with.'
argument :title, GraphQL::STRING_TYPE,
required: true,
@@ -34,7 +34,7 @@ module Mutations
field :merge_request,
Types::MergeRequestType,
null: true,
- description: 'The merge request after mutation'
+ description: 'The merge request after mutation.'
authorize :create_merge_request_from
diff --git a/app/graphql/mutations/merge_requests/update.rb b/app/graphql/mutations/merge_requests/update.rb
index b583fdfca9b..4721ebab41b 100644
--- a/app/graphql/mutations/merge_requests/update.rb
+++ b/app/graphql/mutations/merge_requests/update.rb
@@ -20,7 +20,7 @@ module Mutations
description: copy_field_description(Types::MergeRequestType, :description)
def resolve(args)
- merge_request = authorized_find!(args.slice(:project_path, :iid))
+ merge_request = authorized_find!(**args.slice(:project_path, :iid))
attributes = args.slice(:title, :description, :target_branch).compact
::MergeRequests::UpdateService
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/create.rb b/app/graphql/mutations/metrics/dashboard/annotations/create.rb
index c2ec88c68ed..85937809eb8 100644
--- a/app/graphql/mutations/metrics/dashboard/annotations/create.rb
+++ b/app/graphql/mutations/metrics/dashboard/annotations/create.rb
@@ -15,35 +15,35 @@ module Mutations
field :annotation,
Types::Metrics::Dashboards::AnnotationType,
null: true,
- description: 'The created annotation'
+ description: 'The created annotation.'
argument :environment_id,
::Types::GlobalIDType[::Environment],
required: false,
- description: 'The global ID of the environment to add an annotation to'
+ description: 'The global ID of the environment to add an annotation to.'
argument :cluster_id,
::Types::GlobalIDType[::Clusters::Cluster],
required: false,
- description: 'The global ID of the cluster to add an annotation to'
+ description: 'The global ID of the cluster to add an annotation to.'
argument :starting_at, Types::TimeType,
required: true,
- description: 'Timestamp indicating starting moment to which the annotation relates'
+ description: 'Timestamp indicating starting moment to which the annotation relates.'
argument :ending_at, Types::TimeType,
required: false,
- description: 'Timestamp indicating ending moment to which the annotation relates'
+ description: 'Timestamp indicating ending moment to which the annotation relates.'
argument :dashboard_path,
GraphQL::STRING_TYPE,
required: true,
- description: 'The path to a file defining the dashboard on which the annotation should be added'
+ description: 'The path to a file defining the dashboard on which the annotation should be added.'
argument :description,
GraphQL::STRING_TYPE,
required: true,
- description: 'The description of the annotation'
+ description: 'The description of the annotation.'
AnnotationSource = Struct.new(:object, keyword_init: true) do
def type_keys
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
index 5d6763d8711..e0fadff13d4 100644
--- a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
+++ b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
@@ -11,7 +11,7 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Metrics::Dashboard::Annotation],
required: true,
- description: 'Global ID of the annotation to delete'
+ description: 'Global ID of the annotation to delete.'
def resolve(id:)
annotation = authorized_find!(id: id)
diff --git a/app/graphql/mutations/namespace/package_settings/update.rb b/app/graphql/mutations/namespace/package_settings/update.rb
new file mode 100644
index 00000000000..ca21c3418fc
--- /dev/null
+++ b/app/graphql/mutations/namespace/package_settings/update.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Namespace
+ module PackageSettings
+ class Update < Mutations::BaseMutation
+ include Mutations::ResolvesNamespace
+
+ graphql_name 'UpdateNamespacePackageSettings'
+
+ authorize :create_package_settings
+
+ argument :namespace_path,
+ GraphQL::ID_TYPE,
+ required: true,
+ description: 'The namespace path where the namespace package setting is located.'
+
+ argument :maven_duplicates_allowed,
+ GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :maven_duplicates_allowed)
+
+ argument :maven_duplicate_exception_regex,
+ Types::UntrustedRegexp,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :maven_duplicate_exception_regex)
+
+ field :package_settings,
+ Types::Namespace::PackageSettingsType,
+ null: true,
+ description: 'The namespace package setting after mutation.'
+
+ def resolve(namespace_path:, **args)
+ namespace = authorized_find!(namespace_path: namespace_path)
+
+ result = ::Namespaces::PackageSettings::UpdateService
+ .new(container: namespace, current_user: current_user, params: args)
+ .execute
+
+ {
+ package_settings: result.payload[:package_settings],
+ errors: result.errors
+ }
+ end
+
+ private
+
+ def find_object(namespace_path:)
+ resolve_namespace(full_path: namespace_path)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/notes/base.rb b/app/graphql/mutations/notes/base.rb
index f2678211335..ff401167ba1 100644
--- a/app/graphql/mutations/notes/base.rb
+++ b/app/graphql/mutations/notes/base.rb
@@ -6,7 +6,7 @@ module Mutations
field :note,
Types::Notes::NoteType,
null: true,
- description: 'The note after mutation'
+ description: 'The note after mutation.'
private
diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb
index a1d81c62d91..2351af01813 100644
--- a/app/graphql/mutations/notes/create/base.rb
+++ b/app/graphql/mutations/notes/create/base.rb
@@ -11,7 +11,7 @@ module Mutations
argument :noteable_id,
::Types::GlobalIDType[::Noteable],
required: true,
- description: 'The global ID of the resource to add a note to'
+ description: 'The global ID of the resource to add a note to.'
argument :body,
GraphQL::STRING_TYPE,
diff --git a/app/graphql/mutations/notes/create/note.rb b/app/graphql/mutations/notes/create/note.rb
index f1cd3bddca8..7af93521e0d 100644
--- a/app/graphql/mutations/notes/create/note.rb
+++ b/app/graphql/mutations/notes/create/note.rb
@@ -9,7 +9,7 @@ module Mutations
argument :discussion_id,
::Types::GlobalIDType[::Discussion],
required: false,
- description: 'The global ID of the discussion this note is in reply to'
+ description: 'The global ID of the discussion this note is in reply to.'
private
diff --git a/app/graphql/mutations/notes/destroy.rb b/app/graphql/mutations/notes/destroy.rb
index 0e6a215bf00..21b2cd15a7e 100644
--- a/app/graphql/mutations/notes/destroy.rb
+++ b/app/graphql/mutations/notes/destroy.rb
@@ -10,7 +10,7 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Note],
required: true,
- description: 'The global ID of the note to destroy'
+ description: 'The global ID of the note to destroy.'
def resolve(id:)
note = authorized_find!(id: id)
diff --git a/app/graphql/mutations/notes/reposition_image_diff_note.rb b/app/graphql/mutations/notes/reposition_image_diff_note.rb
index 15bfb361b13..31d3b7c9bb0 100644
--- a/app/graphql/mutations/notes/reposition_image_diff_note.rb
+++ b/app/graphql/mutations/notes/reposition_image_diff_note.rb
@@ -16,7 +16,7 @@ module Mutations
loads: Types::Notes::NoteType,
as: :note,
required: true,
- description: 'The global ID of the DiffNote to update'
+ description: 'The global ID of the DiffNote to update.'
argument :position,
Types::Notes::UpdateDiffImagePositionInputType,
diff --git a/app/graphql/mutations/notes/update/base.rb b/app/graphql/mutations/notes/update/base.rb
index 42dac20f5d3..4edb7429b97 100644
--- a/app/graphql/mutations/notes/update/base.rb
+++ b/app/graphql/mutations/notes/update/base.rb
@@ -11,7 +11,7 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Note],
required: true,
- description: 'The global ID of the note to update'
+ description: 'The global ID of the note to update.'
def resolve(args)
note = authorized_find!(id: args[:id])
diff --git a/app/graphql/mutations/releases/base.rb b/app/graphql/mutations/releases/base.rb
index d53cfbe6a11..dd1724fe320 100644
--- a/app/graphql/mutations/releases/base.rb
+++ b/app/graphql/mutations/releases/base.rb
@@ -7,7 +7,7 @@ module Mutations
argument :project_path, GraphQL::ID_TYPE,
required: true,
- description: 'Full path of the project the release is associated with'
+ description: 'Full path of the project the release is associated with.'
private
diff --git a/app/graphql/mutations/releases/create.rb b/app/graphql/mutations/releases/create.rb
index 156cd252848..91ac256033e 100644
--- a/app/graphql/mutations/releases/create.rb
+++ b/app/graphql/mutations/releases/create.rb
@@ -8,23 +8,23 @@ module Mutations
field :release,
Types::ReleaseType,
null: true,
- description: 'The release after mutation'
+ description: 'The release after mutation.'
argument :tag_name, GraphQL::STRING_TYPE,
required: true, as: :tag,
- description: 'Name of the tag to associate with the release'
+ description: 'Name of the tag to associate with the release.'
argument :ref, GraphQL::STRING_TYPE,
required: false,
- description: 'The commit SHA or branch name to use if creating a new tag'
+ description: 'The commit SHA or branch name to use if creating a new tag.'
argument :name, GraphQL::STRING_TYPE,
required: false,
- description: 'Name of the release'
+ description: 'Name of the release.'
argument :description, GraphQL::STRING_TYPE,
required: false,
- description: 'Description (also known as "release notes") of the release'
+ description: 'Description (also known as "release notes") of the release.'
argument :released_at, Types::TimeType,
required: false,
@@ -36,7 +36,7 @@ module Mutations
argument :assets, Types::ReleaseAssetsInputType,
required: false,
- description: 'Assets associated to the release'
+ description: 'Assets associated to the release.'
authorize :create_release
diff --git a/app/graphql/mutations/releases/update.rb b/app/graphql/mutations/releases/update.rb
index bf72b907679..dff743254bd 100644
--- a/app/graphql/mutations/releases/update.rb
+++ b/app/graphql/mutations/releases/update.rb
@@ -12,19 +12,19 @@ module Mutations
argument :tag_name, GraphQL::STRING_TYPE,
required: true, as: :tag,
- description: 'Name of the tag associated with the release'
+ description: 'Name of the tag associated with the release.'
argument :name, GraphQL::STRING_TYPE,
required: false,
- description: 'Name of the release'
+ description: 'Name of the release.'
argument :description, GraphQL::STRING_TYPE,
required: false,
- description: 'Description (release notes) of the release'
+ description: 'Description (release notes) of the release.'
argument :released_at, Types::TimeType,
required: false,
- description: 'The release date'
+ description: 'The release date.'
argument :milestones, [GraphQL::STRING_TYPE],
required: false,
@@ -51,17 +51,17 @@ module Mutations
params = scalars.with_indifferent_access
- release_result = ::Releases::UpdateService.new(project, current_user, params).execute
+ result = ::Releases::UpdateService.new(project, current_user, params).execute
- if release_result[:status] == :success
+ if result[:status] == :success
{
- release: release_result[:release],
+ release: result[:release],
errors: []
}
else
{
release: nil,
- errors: [release_result[:message]]
+ errors: [result[:message]]
}
end
end
diff --git a/app/graphql/mutations/snippets/base.rb b/app/graphql/mutations/snippets/base.rb
index 023f876d035..5196bc5c7ed 100644
--- a/app/graphql/mutations/snippets/base.rb
+++ b/app/graphql/mutations/snippets/base.rb
@@ -6,7 +6,7 @@ module Mutations
field :snippet,
Types::SnippetType,
null: true,
- description: 'The snippet after mutation'
+ description: 'The snippet after mutation.'
private
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index 56c3b398949..b4485e28c5a 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -12,30 +12,30 @@ module Mutations
field :snippet,
Types::SnippetType,
null: true,
- description: 'The snippet after mutation'
+ description: 'The snippet after mutation.'
argument :title, GraphQL::STRING_TYPE,
required: true,
- description: 'Title of the snippet'
+ description: 'Title of the snippet.'
argument :description, GraphQL::STRING_TYPE,
required: false,
- description: 'Description of the snippet'
+ description: 'Description of the snippet.'
argument :visibility_level, Types::VisibilityLevelsEnum,
- description: 'The visibility level of the snippet',
+ description: 'The visibility level of the snippet.',
required: true
argument :project_path, GraphQL::ID_TYPE,
required: false,
- description: 'The project full path the snippet is associated with'
+ description: 'The project full path the snippet is associated with.'
argument :uploaded_files, [GraphQL::STRING_TYPE],
required: false,
- description: 'The paths to files uploaded in the snippet description'
+ description: 'The paths to files uploaded in the snippet description.'
argument :blob_actions, [Types::Snippets::BlobActionInputType],
- description: 'Actions to perform over the snippet repository and blobs',
+ description: 'Actions to perform over the snippet repository and blobs.',
required: false
def resolve(project_path: nil, **args)
diff --git a/app/graphql/mutations/snippets/destroy.rb b/app/graphql/mutations/snippets/destroy.rb
index bee6503372d..9b00f62e2f9 100644
--- a/app/graphql/mutations/snippets/destroy.rb
+++ b/app/graphql/mutations/snippets/destroy.rb
@@ -9,7 +9,7 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
- description: 'The global ID of the snippet to destroy'
+ description: 'The global ID of the snippet to destroy.'
def resolve(id:)
snippet = authorized_find!(id: id)
diff --git a/app/graphql/mutations/snippets/mark_as_spam.rb b/app/graphql/mutations/snippets/mark_as_spam.rb
index 2d6fea1f5ec..d6e3e131b81 100644
--- a/app/graphql/mutations/snippets/mark_as_spam.rb
+++ b/app/graphql/mutations/snippets/mark_as_spam.rb
@@ -7,7 +7,7 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
- description: 'The global ID of the snippet to update'
+ description: 'The global ID of the snippet to update.'
def resolve(id:)
snippet = authorized_find!(id: id)
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 6df1ad6d8b9..930440fbd35 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -9,22 +9,22 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
- description: 'The global ID of the snippet to update'
+ description: 'The global ID of the snippet to update.'
argument :title, GraphQL::STRING_TYPE,
required: false,
- description: 'Title of the snippet'
+ description: 'Title of the snippet.'
argument :description, GraphQL::STRING_TYPE,
required: false,
- description: 'Description of the snippet'
+ description: 'Description of the snippet.'
argument :visibility_level, Types::VisibilityLevelsEnum,
- description: 'The visibility level of the snippet',
+ description: 'The visibility level of the snippet.',
required: false
argument :blob_actions, [Types::Snippets::BlobActionInputType],
- description: 'Actions to perform over the snippet repository and blobs',
+ description: 'Actions to perform over the snippet repository and blobs.',
required: false
def resolve(id:, **args)
diff --git a/app/graphql/mutations/terraform/state/base.rb b/app/graphql/mutations/terraform/state/base.rb
index b1721c784b1..01f69934ea3 100644
--- a/app/graphql/mutations/terraform/state/base.rb
+++ b/app/graphql/mutations/terraform/state/base.rb
@@ -9,7 +9,7 @@ module Mutations
argument :id,
Types::GlobalIDType[::Terraform::State],
required: true,
- description: 'Global ID of the Terraform state'
+ description: 'Global ID of the Terraform state.'
private
diff --git a/app/graphql/mutations/todos/create.rb b/app/graphql/mutations/todos/create.rb
index 53c88696fdd..814f7ec4fc4 100644
--- a/app/graphql/mutations/todos/create.rb
+++ b/app/graphql/mutations/todos/create.rb
@@ -10,11 +10,11 @@ module Mutations
argument :target_id,
Types::GlobalIDType[Todoable],
required: true,
- description: "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported"
+ description: "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported."
field :todo, Types::TodoType,
null: true,
- description: 'The to-do created'
+ description: 'The to-do 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 97bbbeeaa2f..c8359953567 100644
--- a/app/graphql/mutations/todos/mark_all_done.rb
+++ b/app/graphql/mutations/todos/mark_all_done.rb
@@ -11,11 +11,11 @@ module Mutations
[::Types::GlobalIDType[::Todo]],
null: false,
deprecated: { reason: 'Use todos', milestone: '13.2' },
- description: 'Ids of the updated todos'
+ description: 'Ids of the updated todos.'
field :todos, [::Types::TodoType],
null: false,
- description: 'Updated todos'
+ description: 'Updated todos.'
def resolve
authorize!(current_user)
diff --git a/app/graphql/mutations/todos/mark_done.rb b/app/graphql/mutations/todos/mark_done.rb
index 2ae50846108..95144abb040 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 todo to mark as done.'
field :todo, Types::TodoType,
null: false,
- description: 'The requested todo'
+ description: 'The requested todo.'
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 c532b455a16..e496627aec2 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 todo to restore.'
field :todo, Types::TodoType,
null: false,
- description: 'The requested todo'
+ description: 'The requested todo.'
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 59965589856..9263c1d9afe 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 todos 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',
+ description: 'The IDs of the updated todo items.',
deprecated: { reason: 'Use todos', milestone: '13.2' }
field :todos, [::Types::TodoType],
null: false,
- description: 'Updated todos'
+ description: 'Updated todos.'
def resolve(ids:)
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
new file mode 100644
index 00000000000..6171233c446
--- /dev/null
+++ b/app/graphql/queries/container_registry/get_container_repositories.query.graphql
@@ -0,0 +1,60 @@
+query getProjectContainerRepositories(
+ $fullPath: ID!
+ $name: String
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
+ $isGroupPage: Boolean!
+) {
+ project(fullPath: $fullPath) @skip(if: $isGroupPage) {
+ __typename
+ containerRepositoriesCount
+ containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ __typename
+ nodes {
+ id
+ name
+ path
+ status
+ location
+ canDelete
+ createdAt
+ expirationPolicyStartedAt
+ __typename
+ }
+ pageInfo {
+ __typename
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ endCursor
+ }
+ }
+ }
+ group(fullPath: $fullPath) @include(if: $isGroupPage) {
+ __typename
+ containerRepositoriesCount
+ containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ __typename
+ nodes {
+ id
+ name
+ path
+ status
+ location
+ canDelete
+ createdAt
+ expirationPolicyStartedAt
+ __typename
+ }
+ pageInfo {
+ __typename
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ endCursor
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
new file mode 100644
index 00000000000..92323923266
--- /dev/null
+++ b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
@@ -0,0 +1,101 @@
+fragment LinkedPipelineData on Pipeline {
+ __typename
+ id
+ iid
+ path
+ status: detailedStatus {
+ __typename
+ group
+ label
+ icon
+ }
+ sourceJob {
+ __typename
+ name
+ }
+ project {
+ __typename
+ name
+ fullPath
+ }
+}
+
+query getPipelineDetails($projectPath: ID!, $iid: ID!) {
+ project(fullPath: $projectPath) {
+ __typename
+ pipeline(iid: $iid) {
+ __typename
+ id
+ iid
+ downstream {
+ __typename
+ nodes {
+ ...LinkedPipelineData
+ }
+ }
+ upstream {
+ ...LinkedPipelineData
+ }
+ stages {
+ __typename
+ nodes {
+ __typename
+ name
+ status: detailedStatus {
+ __typename
+ action {
+ __typename
+ icon
+ path
+ title
+ }
+ }
+ groups {
+ __typename
+ nodes {
+ __typename
+ status: detailedStatus {
+ __typename
+ label
+ group
+ icon
+ }
+ name
+ size
+ jobs {
+ __typename
+ nodes {
+ __typename
+ name
+ scheduledAt
+ needs {
+ __typename
+ nodes {
+ __typename
+ name
+ }
+ }
+ status: detailedStatus {
+ __typename
+ icon
+ tooltip
+ hasDetails
+ detailsPath
+ group
+ action {
+ __typename
+ buttonTitle
+ icon
+ path
+ title
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/graphql/queries/snippet/snippet.query.graphql b/app/graphql/queries/snippet/snippet.query.graphql
index 2205dc26642..ebfc135c51c 100644
--- a/app/graphql/queries/snippet/snippet.query.graphql
+++ b/app/graphql/queries/snippet/snippet.query.graphql
@@ -59,6 +59,11 @@ query GetSnippetQuery($ids: [SnippetID!]) {
name
username
webUrl
+ status {
+ __typename
+ emoji
+ message
+ }
}
}
}
diff --git a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb b/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
index 9bac9f222ab..9df07df24d8 100644
--- a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
+++ b/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
@@ -11,15 +11,15 @@ module Resolvers
argument :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum,
required: true,
- description: 'The type of measurement/statistics to retrieve'
+ description: 'The type of measurement/statistics to retrieve.'
argument :recorded_after, Types::TimeType,
required: false,
- description: 'Measurement recorded after this date'
+ description: 'Measurement recorded after this date.'
argument :recorded_before, Types::TimeType,
required: false,
- description: 'Measurement recorded before this date'
+ description: 'Measurement recorded before this date.'
def resolve(identifier:, recorded_before: nil, recorded_after: nil)
authorize!
diff --git a/app/graphql/resolvers/alert_management/alert_resolver.rb b/app/graphql/resolvers/alert_management/alert_resolver.rb
index b115bd80113..d60cabde62b 100644
--- a/app/graphql/resolvers/alert_management/alert_resolver.rb
+++ b/app/graphql/resolvers/alert_management/alert_resolver.rb
@@ -7,19 +7,19 @@ module Resolvers
argument :iid, GraphQL::STRING_TYPE,
required: false,
- description: 'IID of the alert. For example, "1"'
+ description: 'IID of the alert. For example, "1".'
argument :statuses, [Types::AlertManagement::StatusEnum],
as: :status,
required: false,
- description: 'Alerts with the specified statues. For example, [TRIGGERED]'
+ description: 'Alerts with the specified statues. For example, [TRIGGERED].'
argument :sort, Types::AlertManagement::AlertSortEnum,
- description: 'Sort alerts by this criteria',
+ description: 'Sort alerts by this criteria.',
required: false
argument :domain, Types::AlertManagement::DomainFilterEnum,
- description: 'Filter query for given domain',
+ description: 'Filter query for given domain.',
required: true,
default_value: 'operations'
@@ -29,7 +29,7 @@ module Resolvers
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of a user assigned to the issue'
+ description: 'Username of a user assigned to the issue.'
type Types::AlertManagement::AlertType, null: true
diff --git a/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb b/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb
index 8fc0f9fd1ff..410f72cff84 100644
--- a/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb
+++ b/app/graphql/resolvers/alert_management/alert_status_counts_resolver.rb
@@ -11,7 +11,7 @@ module Resolvers
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of a user assigned to the issue'
+ description: 'Username of a user assigned to the issue.'
def resolve(**args)
::Gitlab::AlertManagement::AlertStatusCounts.new(context[:current_user], object, args)
diff --git a/app/graphql/resolvers/board_list_issues_resolver.rb b/app/graphql/resolvers/board_list_issues_resolver.rb
index 3e4a5a3cb70..29e66a59a15 100644
--- a/app/graphql/resolvers/board_list_issues_resolver.rb
+++ b/app/graphql/resolvers/board_list_issues_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
argument :filters, Types::Boards::BoardIssueInputType,
required: false,
- description: 'Filters applied when selecting issues in the board list'
+ description: 'Filters applied when selecting issues in the board list.'
type Types::IssueType, null: true
diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb
index 35d938c50be..7bdff8ba61f 100644
--- a/app/graphql/resolvers/board_lists_resolver.rb
+++ b/app/graphql/resolvers/board_lists_resolver.rb
@@ -13,11 +13,11 @@ module Resolvers
argument :id, Types::GlobalIDType[List],
required: false,
- description: 'Find a list by its global ID'
+ description: 'Find a list by its global ID.'
argument :issue_filters, Types::Boards::BoardIssueInputType,
required: false,
- description: 'Filters applied when getting issue metadata in the board list'
+ description: 'Filters applied when getting issue metadata in the board list.'
alias_method :board, :object
diff --git a/app/graphql/resolvers/board_resolver.rb b/app/graphql/resolvers/board_resolver.rb
index 517f4e514c9..582707cc1e4 100644
--- a/app/graphql/resolvers/board_resolver.rb
+++ b/app/graphql/resolvers/board_resolver.rb
@@ -8,7 +8,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::Board],
required: true,
- description: 'The board\'s ID'
+ description: 'The board\'s ID.'
def resolve(id: nil)
return unless parent
diff --git a/app/graphql/resolvers/boards_resolver.rb b/app/graphql/resolvers/boards_resolver.rb
index 42b6ce03118..cdb15dc8f37 100644
--- a/app/graphql/resolvers/boards_resolver.rb
+++ b/app/graphql/resolvers/boards_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::Board],
required: false,
- description: 'Find a board by its ID'
+ description: 'Find a board by its ID.'
def resolve(id: nil)
# The project or group could have been loaded in batch by `BatchLoader`.
diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb
index d6e7c206691..72d3ae30d73 100644
--- a/app/graphql/resolvers/ci/config_resolver.rb
+++ b/app/graphql/resolvers/ci/config_resolver.rb
@@ -3,40 +3,64 @@
module Resolvers
module Ci
class ConfigResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include ResolvesProject
+
type Types::Ci::Config::ConfigType, null: true
+ authorize :read_pipeline
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'The project of the CI config.'
+
argument :content, GraphQL::STRING_TYPE,
required: true,
- description: 'Contents of .gitlab-ci.yml'
-
- def resolve(content:)
- result = ::Gitlab::Ci::YamlProcessor.new(content).execute
-
- response = if result.errors.empty?
- {
- status: :valid,
- errors: [],
- stages: make_stages(result.jobs)
- }
- else
- {
- status: :invalid,
- errors: result.errors
- }
- end
-
- response.merge(merged_yaml: result.merged_yaml)
+ description: "Contents of '.gitlab-ci.yml'."
+
+ argument :dry_run, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Run pipeline creation simulation, or only do static check.'
+
+ def resolve(project_path:, content:, dry_run: false)
+ project = authorized_find!(project_path: project_path)
+
+ result = ::Gitlab::Ci::Lint
+ .new(project: project, current_user: context[:current_user])
+ .validate(content, dry_run: dry_run)
+
+ if result.errors.empty?
+ {
+ status: :valid,
+ errors: [],
+ stages: make_stages(result.jobs)
+ }
+ else
+ {
+ status: :invalid,
+ errors: result.errors
+ }
+ end
end
private
def make_jobs(config_jobs)
- config_jobs.map do |job_name, job|
+ config_jobs.map do |job|
{
- name: job_name,
+ name: job[:name],
stage: job[:stage],
- group_name: CommitStatus.new(name: job_name).group_name,
- needs: job.dig(:needs, :job) || []
+ group_name: CommitStatus.new(name: job[:name]).group_name,
+ needs: job.dig(:needs) || [],
+ allow_failure: job[:allow_failure],
+ before_script: job[:before_script],
+ script: job[:script],
+ after_script: job[:after_script],
+ only: job[:only],
+ except: job[:except],
+ when: job[:when],
+ tags: job[:tag_list],
+ environment: job[:environment]
}
end
end
@@ -55,6 +79,10 @@ module Resolvers
.group_by { |group| group[:stage] }
.map { |name, groups| { name: name, groups: groups } }
end
+
+ def find_object(project_path:)
+ resolve_project(full_path: project_path)
+ end
end
end
end
diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb
index 2c4911748a5..dd565094017 100644
--- a/app/graphql/resolvers/ci/jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/jobs_resolver.rb
@@ -9,7 +9,7 @@ module Resolvers
argument :security_report_types, [Types::Security::ReportTypeEnum],
required: false,
- description: 'Filter jobs by the type of security report they produce'
+ description: 'Filter jobs by the type of security report they produce.'
def resolve(security_report_types: [])
if security_report_types.present?
diff --git a/app/graphql/resolvers/ci/runner_setup_resolver.rb b/app/graphql/resolvers/ci/runner_setup_resolver.rb
index f68d71174c3..ac2a56b89a7 100644
--- a/app/graphql/resolvers/ci/runner_setup_resolver.rb
+++ b/app/graphql/resolvers/ci/runner_setup_resolver.rb
@@ -7,19 +7,19 @@ module Resolvers
argument :platform, GraphQL::STRING_TYPE,
required: true,
- description: 'Platform to generate the instructions for'
+ description: 'Platform to generate the instructions for.'
argument :architecture, GraphQL::STRING_TYPE,
required: true,
- description: 'Architecture to generate the instructions for'
+ description: 'Architecture to generate the instructions for.'
argument :project_id, ::Types::GlobalIDType[::Project],
required: false,
- description: 'Project to register the runner for'
+ description: 'Project to register the runner for.'
argument :group_id, ::Types::GlobalIDType[::Group],
required: false,
- description: 'Group to register the runner for'
+ description: 'Group to register the runner for.'
def resolve(platform:, architecture:, **args)
instructions = Gitlab::Ci::RunnerInstructions.new(
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
index 4715b867ecb..84b0dafe213 100644
--- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -8,52 +8,52 @@ module IssueResolverArguments
argument :iid, GraphQL::STRING_TYPE,
required: false,
- description: 'IID of the issue. For example, "1"'
+ description: 'IID of the issue. For example, "1".'
argument :iids, [GraphQL::STRING_TYPE],
required: false,
- description: 'List of IIDs of issues. For example, [1, 2]'
+ description: 'List of IIDs of issues. For example, [1, 2].'
argument :label_name, GraphQL::STRING_TYPE.to_list_type,
required: false,
- description: 'Labels applied to this issue'
+ description: 'Labels applied to this issue.'
argument :milestone_title, GraphQL::STRING_TYPE.to_list_type,
required: false,
- description: 'Milestone applied to this issue'
+ description: 'Milestone applied to this issue.'
argument :author_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of the author of the issue'
+ description: 'Username of the author of the issue.'
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of a user assigned to the issue'
+ description: 'Username of a user assigned to the issue.'
argument :assignee_usernames, [GraphQL::STRING_TYPE],
required: false,
- description: 'Usernames of users assigned to the issue'
+ description: 'Usernames of users assigned to the issue.'
argument :assignee_id, GraphQL::STRING_TYPE,
required: false,
- description: 'ID of a user assigned to the issues, "none" and "any" values are supported'
+ description: 'ID of a user assigned to the issues, "none" and "any" values are supported.'
argument :created_before, Types::TimeType,
required: false,
- description: 'Issues created before this date'
+ description: 'Issues created before this date.'
argument :created_after, Types::TimeType,
required: false,
- description: 'Issues created after this date'
+ description: 'Issues created after this date.'
argument :updated_before, Types::TimeType,
required: false,
- description: 'Issues updated before this date'
+ description: 'Issues updated before this date.'
argument :updated_after, Types::TimeType,
required: false,
- description: 'Issues updated after this date'
+ description: 'Issues updated after this date.'
argument :closed_before, Types::TimeType,
required: false,
- description: 'Issues closed before this date'
+ description: 'Issues closed before this date.'
argument :closed_after, Types::TimeType,
required: false,
- description: 'Issues closed after this date'
+ description: 'Issues closed after this date.'
argument :search, GraphQL::STRING_TYPE,
required: false,
- description: 'Search query for issue title or description'
+ description: 'Search query for issue title or description.'
argument :types, [Types::IssueTypeEnum],
as: :issue_types,
- description: 'Filter issues by the given issue types',
+ description: 'Filter issues by the given issue types.',
required: false
end
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
index d468047b539..77a85edfba6 100644
--- a/app/graphql/resolvers/concerns/looks_ahead.rb
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -20,11 +20,11 @@ module LooksAhead
includes = preloads.each.flat_map do |name, requirements|
selection&.selects?(name) ? requirements : []
end
- preloads = (unconditional_includes + includes).uniq
+ all_preloads = (unconditional_includes + includes).uniq
- return query if preloads.empty?
+ return query if all_preloads.empty?
- query.preload(*preloads) # rubocop: disable CodeReuse/ActiveRecord
+ query.preload(*all_preloads) # rubocop: disable CodeReuse/ActiveRecord
end
private
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
index ab83476ddea..31444b0c592 100644
--- a/app/graphql/resolvers/concerns/resolves_merge_requests.rb
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -40,6 +40,8 @@ module ResolvesMergeRequests
def preloads
{
assignees: [:assignees],
+ reviewers: [:reviewers],
+ participants: MergeRequest.participant_includes,
labels: [:labels],
author: [:author],
merged_at: [:metrics],
@@ -47,6 +49,7 @@ module ResolvesMergeRequests
diff_stats_summary: [:metrics],
approved_by: [:approved_by_users],
milestone: [:milestone],
+ security_auto_fix: [:author],
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }]
}
end
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index f061f5f1606..bbf33c0b5eb 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -8,15 +8,15 @@ module ResolvesPipelines
argument :status,
Types::Ci::PipelineStatusEnum,
required: false,
- description: "Filter pipelines by their status"
+ description: "Filter pipelines by their status."
argument :ref,
GraphQL::STRING_TYPE,
required: false,
- description: "Filter pipelines by the ref they are run for"
+ description: "Filter pipelines by the ref they are run for."
argument :sha,
GraphQL::STRING_TYPE,
required: false,
- description: "Filter pipelines by the sha of the commit they are run for"
+ description: "Filter pipelines by the sha of the commit they are run for."
end
class_methods do
diff --git a/app/graphql/resolvers/concerns/resolves_snippets.rb b/app/graphql/resolvers/concerns/resolves_snippets.rb
index 790ff4f774f..0bc38188b9a 100644
--- a/app/graphql/resolvers/concerns/resolves_snippets.rb
+++ b/app/graphql/resolvers/concerns/resolves_snippets.rb
@@ -8,11 +8,11 @@ module ResolvesSnippets
argument :ids, [::Types::GlobalIDType[::Snippet]],
required: false,
- description: 'Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"'
+ description: 'Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1".'
argument :visibility, Types::Snippets::VisibilityScopesEnum,
required: false,
- description: 'The visibility of the snippet'
+ description: 'The visibility of the snippet.'
end
def resolve(**args)
diff --git a/app/graphql/resolvers/concerns/time_frame_arguments.rb b/app/graphql/resolvers/concerns/time_frame_arguments.rb
index 94bfe6f7f9f..6cac46a71d2 100644
--- a/app/graphql/resolvers/concerns/time_frame_arguments.rb
+++ b/app/graphql/resolvers/concerns/time_frame_arguments.rb
@@ -18,7 +18,7 @@ module TimeFrameArguments
argument :timeframe, Types::TimeframeInputType,
required: false,
- description: 'List items overlapping the given timeframe'
+ description: 'List items overlapping the given timeframe.'
end
# TODO: remove when the start_date and end_date arguments are removed
diff --git a/app/graphql/resolvers/container_repositories_resolver.rb b/app/graphql/resolvers/container_repositories_resolver.rb
index b4b2893a3b8..8042a368e33 100644
--- a/app/graphql/resolvers/container_repositories_resolver.rb
+++ b/app/graphql/resolvers/container_repositories_resolver.rb
@@ -8,7 +8,7 @@ module Resolvers
argument :name, GraphQL::STRING_TYPE,
required: false,
- description: 'Filter the container repositories by their name'
+ description: 'Filter the container repositories by their name.'
def resolve(name: nil)
ContainerRepositoriesFinder.new(user: current_user, subject: object, params: { name: name })
diff --git a/app/graphql/resolvers/design_management/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/design_at_version_resolver.rb
index 1b69efebe4e..533692e2b12 100644
--- a/app/graphql/resolvers/design_management/design_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/design_at_version_resolver.rb
@@ -11,7 +11,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::DesignManagement::DesignAtVersion],
required: true,
- description: 'The Global ID of the design at this version'
+ description: 'The Global ID of the design at this version.'
def resolve(id:)
authorized_find!(id: id)
diff --git a/app/graphql/resolvers/design_management/design_resolver.rb b/app/graphql/resolvers/design_management/design_resolver.rb
index b60c14ca835..e640f57f04a 100644
--- a/app/graphql/resolvers/design_management/design_resolver.rb
+++ b/app/graphql/resolvers/design_management/design_resolver.rb
@@ -9,11 +9,11 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::DesignManagement::Design],
required: false,
- description: 'Find a design by its ID'
+ description: 'Find a design by its ID.'
argument :filename, GraphQL::STRING_TYPE,
required: false,
- description: 'Find a design by its filename'
+ description: 'Find a design by its filename.'
def resolve(filename: nil, id: nil)
params = parse_args(filename, id)
diff --git a/app/graphql/resolvers/design_management/designs_resolver.rb b/app/graphql/resolvers/design_management/designs_resolver.rb
index c588142ea6b..c45e4d01f6e 100644
--- a/app/graphql/resolvers/design_management/designs_resolver.rb
+++ b/app/graphql/resolvers/design_management/designs_resolver.rb
@@ -10,10 +10,10 @@ module Resolvers
argument :ids, [DesignID],
required: false,
- description: 'Filters designs by their ID'
+ description: 'Filters designs by their ID.'
argument :filenames, [GraphQL::STRING_TYPE],
required: false,
- description: 'Filters designs by their filename'
+ description: 'Filters designs by their filename.'
argument :at_version, VersionID,
required: false,
description: 'Filters designs to only those that existed at the version. ' \
diff --git a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
index 49a4974bfbf..fea74cbfb0b 100644
--- a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
@@ -19,13 +19,13 @@ module Resolvers
argument :id, DesignAtVersionID,
required: false,
as: :design_at_version_id,
- description: 'The ID of the DesignAtVersion'
+ description: 'The ID of the DesignAtVersion.'
argument :design_id, DesignID,
required: false,
- description: 'The ID of a specific design'
+ description: 'The ID of a specific design.'
argument :filename, GraphQL::STRING_TYPE,
required: false,
- description: 'The filename of a specific design'
+ description: 'The filename of a specific design.'
def self.single
self
diff --git a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
index a129d8620d4..930b1b60d0e 100644
--- a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
@@ -15,11 +15,11 @@ module Resolvers
argument :ids, [DesignID],
required: false,
- description: 'Filters designs by their ID'
+ description: 'Filters designs by their ID.'
argument :filenames,
[GraphQL::STRING_TYPE],
required: false,
- description: 'Filters designs by their filename'
+ description: 'Filters designs by their filename.'
def self.single
::Resolvers::DesignManagement::Version::DesignAtVersionResolver
diff --git a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
index 7d20cfc2c8e..593974beb04 100644
--- a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
+++ b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
@@ -17,11 +17,11 @@ module Resolvers
argument :sha, GraphQL::STRING_TYPE,
required: false,
- description: "The SHA256 of a specific version"
+ description: "The SHA256 of a specific version."
argument :id, VersionID,
as: :version_id,
required: false,
- description: 'The Global ID of the version'
+ description: 'The Global ID of the version.'
def resolve(version_id: nil, sha: nil)
# TODO: remove this line when the compatibility layer is removed
diff --git a/app/graphql/resolvers/design_management/version_resolver.rb b/app/graphql/resolvers/design_management/version_resolver.rb
index 1bc9c1a7cd6..2144e588208 100644
--- a/app/graphql/resolvers/design_management/version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version_resolver.rb
@@ -11,7 +11,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::DesignManagement::Version],
required: true,
- description: 'The Global ID of the version'
+ description: 'The Global ID of the version.'
def resolve(id:)
authorized_find!(id: id)
diff --git a/app/graphql/resolvers/design_management/versions_resolver.rb b/app/graphql/resolvers/design_management/versions_resolver.rb
index 3c718a631db..619448cbc18 100644
--- a/app/graphql/resolvers/design_management/versions_resolver.rb
+++ b/app/graphql/resolvers/design_management/versions_resolver.rb
@@ -14,12 +14,12 @@ module Resolvers
argument :earlier_or_equal_to_sha, GraphQL::STRING_TYPE,
as: :sha,
required: false,
- description: 'The SHA256 of the most recent acceptable version'
+ description: 'The SHA256 of the most recent acceptable version.'
argument :earlier_or_equal_to_id, VersionID,
as: :id,
required: false,
- description: 'The Global ID of the most recent acceptable version'
+ description: 'The Global ID of the most recent acceptable version.'
# This resolver has a custom singular resolver
def self.single
diff --git a/app/graphql/resolvers/echo_resolver.rb b/app/graphql/resolvers/echo_resolver.rb
index 6b85b700712..0c7dad622cf 100644
--- a/app/graphql/resolvers/echo_resolver.rb
+++ b/app/graphql/resolvers/echo_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
description 'Testing endpoint to validate the API with'
argument :text, GraphQL::STRING_TYPE, required: true,
- description: 'Text to echo back'
+ description: 'Text to echo back.'
def resolve(text:)
username = current_user&.username
diff --git a/app/graphql/resolvers/environments_resolver.rb b/app/graphql/resolvers/environments_resolver.rb
index 1b916a89796..ed3395d05aa 100644
--- a/app/graphql/resolvers/environments_resolver.rb
+++ b/app/graphql/resolvers/environments_resolver.rb
@@ -4,15 +4,15 @@ module Resolvers
class EnvironmentsResolver < BaseResolver
argument :name, GraphQL::STRING_TYPE,
required: false,
- description: 'Name of the environment'
+ description: 'Name of the environment.'
argument :search, GraphQL::STRING_TYPE,
required: false,
- description: 'Search query for environment name'
+ description: 'Search query for environment name.'
argument :states, [GraphQL::STRING_TYPE],
required: false,
- description: 'States of environments that should be included in result'
+ description: 'States of environments that should be included in result.'
type Types::EnvironmentType, null: true
diff --git a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
index 09e76dba645..7032af46221 100644
--- a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError],
required: true,
- description: 'ID of the Sentry issue'
+ description: 'ID of the Sentry issue.'
def resolve(id:)
# TODO: remove this line when the compatibility layer is removed
diff --git a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb
index 13b5672d750..8876f8badcd 100644
--- a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError],
required: true,
- description: 'ID of the Sentry issue'
+ description: 'ID of the Sentry issue.'
def resolve(id:)
# TODO: remove this line when the compatibility layer is removed
diff --git a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
index e844ffedbeb..4cd65daa655 100644
--- a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
@@ -7,12 +7,12 @@ module Resolvers
extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
argument :search_term, ::GraphQL::STRING_TYPE,
- description: 'Search query for the Sentry error details',
+ description: 'Search query for the Sentry error details.',
required: false
# TODO: convert to Enum
argument :sort, ::GraphQL::STRING_TYPE,
- description: 'Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default',
+ description: 'Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.',
required: false
delegate :project, to: :object
diff --git a/app/graphql/resolvers/full_path_resolver.rb b/app/graphql/resolvers/full_path_resolver.rb
index cbb0bf998a6..d01cdf749a1 100644
--- a/app/graphql/resolvers/full_path_resolver.rb
+++ b/app/graphql/resolvers/full_path_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
prepended do
argument :full_path, GraphQL::ID_TYPE,
required: true,
- description: 'The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss"'
+ description: 'The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss".'
end
def model_by_full_path(model, full_path)
diff --git a/app/graphql/resolvers/group_members_resolver.rb b/app/graphql/resolvers/group_members_resolver.rb
index fcdf7c01d8b..36e1977b756 100644
--- a/app/graphql/resolvers/group_members_resolver.rb
+++ b/app/graphql/resolvers/group_members_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
authorize :read_group_member
argument :relations, [Types::GroupMemberRelationEnum],
- description: 'Filter members by the given member relations',
+ description: 'Filter members by the given member relations.',
required: false,
default_value: GroupMembersFinder::DEFAULT_RELATIONS
diff --git a/app/graphql/resolvers/group_milestones_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb
index 83b82e2720b..179283fd7b7 100644
--- a/app/graphql/resolvers/group_milestones_resolver.rb
+++ b/app/graphql/resolvers/group_milestones_resolver.rb
@@ -5,7 +5,7 @@ module Resolvers
class GroupMilestonesResolver < MilestonesResolver
argument :include_descendants, GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Also return milestones in all subgroups and subprojects'
+ description: 'Also return milestones in all subgroups and subprojects.'
type Types::MilestoneType.connection_type, null: true
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index ae27cce9113..ac3bdda0f12 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -6,9 +6,9 @@ module Resolvers
argument :state, Types::IssuableStateEnum,
required: false,
- description: 'Current state of this issue'
+ description: 'Current state of this issue.'
argument :sort, Types::IssueSortEnum,
- description: 'Sort issues by this criteria',
+ description: 'Sort issues by this criteria.',
required: false,
default_value: :created_desc
@@ -19,7 +19,7 @@ module Resolvers
milestone_due_asc milestone_due_desc].freeze
def continue_issue_resolve(parent, finder, **args)
- issues = apply_lookahead(Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all)
+ issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) }
if non_stable_cursor_sort?(args[:sort])
# Certain complex sorts are not supported by the stable cursor pagination yet.
@@ -32,6 +32,14 @@ module Resolvers
private
+ def unconditional_includes
+ [
+ {
+ project: [:project_feature]
+ }
+ ]
+ end
+
def preloads
{
alert_management_alert: [:alert_management_alert],
diff --git a/app/graphql/resolvers/members_resolver.rb b/app/graphql/resolvers/members_resolver.rb
index cf51fd298bd..76c3ae936ee 100644
--- a/app/graphql/resolvers/members_resolver.rb
+++ b/app/graphql/resolvers/members_resolver.rb
@@ -9,7 +9,7 @@ module Resolvers
argument :search, GraphQL::STRING_TYPE,
required: false,
- description: 'Search query'
+ description: 'Search query.'
def resolve_with_lookahead(**args)
authorize!(object)
diff --git a/app/graphql/resolvers/merge_request_resolver.rb b/app/graphql/resolvers/merge_request_resolver.rb
index 4cad65fa697..8fd33c6626e 100644
--- a/app/graphql/resolvers/merge_request_resolver.rb
+++ b/app/graphql/resolvers/merge_request_resolver.rb
@@ -11,7 +11,7 @@ module Resolvers
argument :iid, GraphQL::STRING_TYPE,
required: true,
as: :iids,
- description: 'IID of the merge request, for example `1`'
+ description: 'IID of the merge request, for example `1`.'
def no_results_possible?(args)
project.nil?
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index 98c95565778..ecbdaaa3f55 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -11,24 +11,24 @@ module Resolvers
def self.accept_assignee
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of the assignee'
+ description: 'Username of the assignee.'
end
def self.accept_author
argument :author_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of the author'
+ description: 'Username of the author.'
end
def self.accept_reviewer
argument :reviewer_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of the reviewer'
+ description: 'Username of the reviewer.'
end
argument :iids, [GraphQL::STRING_TYPE],
required: false,
- description: 'Array of IIDs of merge requests, for example `[1, 2]`'
+ description: 'Array of IIDs of merge requests, for example `[1, 2]`.'
argument :source_branches, [GraphQL::STRING_TYPE],
required: false,
@@ -50,15 +50,15 @@ module Resolvers
description: 'Array of label names. All resolved merge requests will have all of these labels.'
argument :merged_after, Types::TimeType,
required: false,
- description: 'Merge requests merged after this date'
+ description: 'Merge requests merged after this date.'
argument :merged_before, Types::TimeType,
required: false,
- description: 'Merge requests merged before this date'
+ description: 'Merge requests merged before this date.'
argument :milestone_title, GraphQL::STRING_TYPE,
required: false,
- description: 'Title of the milestone'
+ description: 'Title of the milestone.'
argument :sort, Types::MergeRequestSortEnum,
- description: 'Sort merge requests by this criteria',
+ description: 'Sort merge requests by this criteria.',
required: false,
default_value: :created_desc
diff --git a/app/graphql/resolvers/metrics/dashboard_resolver.rb b/app/graphql/resolvers/metrics/dashboard_resolver.rb
index 18a654c7dc5..f569cb0b2c3 100644
--- a/app/graphql/resolvers/metrics/dashboard_resolver.rb
+++ b/app/graphql/resolvers/metrics/dashboard_resolver.rb
@@ -5,7 +5,7 @@ module Resolvers
class DashboardResolver < Resolvers::BaseResolver
argument :path, GraphQL::STRING_TYPE,
required: true,
- description: "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'"
+ description: "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'."
type Types::Metrics::DashboardType, null: true
diff --git a/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb b/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb
index 2dd224bb17b..9d6b0486c04 100644
--- a/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb
+++ b/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb
@@ -6,11 +6,11 @@ module Resolvers
class AnnotationResolver < Resolvers::BaseResolver
argument :from, Types::TimeType,
required: true,
- description: "Timestamp marking date and time from which annotations need to be fetched"
+ description: "Timestamp marking date and time from which annotations need to be fetched."
argument :to, Types::TimeType,
required: false,
- description: "Timestamp marking date and time to which annotations need to be fetched"
+ description: "Timestamp marking date and time to which annotations need to be fetched."
type Types::Metrics::Dashboards::AnnotationType, null: true
diff --git a/app/graphql/resolvers/milestones_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb
index 564e388d571..9a715e4d08b 100644
--- a/app/graphql/resolvers/milestones_resolver.rb
+++ b/app/graphql/resolvers/milestones_resolver.rb
@@ -7,23 +7,23 @@ module Resolvers
argument :ids, [GraphQL::ID_TYPE],
required: false,
- description: 'Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1"'
+ description: 'Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1".'
argument :state, Types::MilestoneStateEnum,
required: false,
- description: 'Filter milestones by state'
+ description: 'Filter milestones by state.'
argument :title, GraphQL::STRING_TYPE,
required: false,
- description: 'The title of the milestone'
+ description: 'The title of the milestone.'
argument :search_title, GraphQL::STRING_TYPE,
required: false,
- description: 'A search string for the title'
+ description: 'A search string for the title.'
argument :containing_date, Types::TimeType,
required: false,
- description: 'A date that the milestone contains'
+ description: 'A date that the milestone contains.'
type Types::MilestoneType.connection_type, null: true
diff --git a/app/graphql/resolvers/namespace_projects_resolver.rb b/app/graphql/resolvers/namespace_projects_resolver.rb
index 9f57c8f3405..da44b9b5623 100644
--- a/app/graphql/resolvers/namespace_projects_resolver.rb
+++ b/app/graphql/resolvers/namespace_projects_resolver.rb
@@ -5,17 +5,17 @@ module Resolvers
argument :include_subgroups, GraphQL::BOOLEAN_TYPE,
required: false,
default_value: false,
- description: 'Include also subgroup projects'
+ description: 'Include also subgroup projects.'
argument :search, GraphQL::STRING_TYPE,
required: false,
default_value: nil,
- description: 'Search project with most similar names or paths'
+ description: 'Search project with most similar names or paths.'
argument :sort, Types::Projects::NamespaceProjectSortEnum,
required: false,
default_value: nil,
- description: 'Sort projects by this criteria'
+ description: 'Sort projects by this criteria.'
type Types::ProjectType, null: true
diff --git a/app/graphql/resolvers/package_details_resolver.rb b/app/graphql/resolvers/package_details_resolver.rb
new file mode 100644
index 00000000000..dcf4430e55f
--- /dev/null
+++ b/app/graphql/resolvers/package_details_resolver.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Resolvers
+ # No return types defined because they can be different.
+ # rubocop: disable Graphql/ResolverType
+ class PackageDetailsResolver < BaseResolver
+ argument :id, ::Types::GlobalIDType[::Packages::Package],
+ required: true,
+ description: 'The global ID of the package.'
+
+ def resolve(id:)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ::Types::GlobalIDType[::Packages::Package].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/packages_resolver.rb b/app/graphql/resolvers/packages_resolver.rb
index 519fb87183e..d19099e94d4 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::PackageType, null: true
+ type Types::Packages::PackageType, null: true
def resolve(**args)
return unless packages_available?
diff --git a/app/graphql/resolvers/project_members_resolver.rb b/app/graphql/resolvers/project_members_resolver.rb
index 659b12c2563..e889b47c000 100644
--- a/app/graphql/resolvers/project_members_resolver.rb
+++ b/app/graphql/resolvers/project_members_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
authorize :read_project_member
argument :relations, [Types::ProjectMemberRelationEnum],
- description: 'Filter members by the given member relations',
+ description: 'Filter members by the given member relations.',
required: false,
default_value: MembersFinder::DEFAULT_RELATIONS
diff --git a/app/graphql/resolvers/project_milestones_resolver.rb b/app/graphql/resolvers/project_milestones_resolver.rb
index c88c9ce7219..4cd9cb53f56 100644
--- a/app/graphql/resolvers/project_milestones_resolver.rb
+++ b/app/graphql/resolvers/project_milestones_resolver.rb
@@ -5,7 +5,7 @@ module Resolvers
class ProjectMilestonesResolver < MilestonesResolver
argument :include_ancestors, GraphQL::BOOLEAN_TYPE,
required: false,
- description: "Also return milestones in the project's parent group and its ancestors"
+ description: "Also return milestones in the project's parent group and its ancestors."
type Types::MilestoneType.connection_type, null: true
diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb
index 8bf4e0b08ef..b604a408928 100644
--- a/app/graphql/resolvers/project_pipeline_resolver.rb
+++ b/app/graphql/resolvers/project_pipeline_resolver.rb
@@ -8,7 +8,7 @@ module Resolvers
argument :iid, GraphQL::ID_TYPE,
required: true,
- description: 'IID of the Pipeline, e.g., "1"'
+ description: 'IID of the Pipeline, e.g., "1".'
def resolve(iid:)
BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args|
diff --git a/app/graphql/resolvers/projects/jira_projects_resolver.rb b/app/graphql/resolvers/projects/jira_projects_resolver.rb
index 31f42d305b0..de85e8c42e6 100644
--- a/app/graphql/resolvers/projects/jira_projects_resolver.rb
+++ b/app/graphql/resolvers/projects/jira_projects_resolver.rb
@@ -6,11 +6,12 @@ module Resolvers
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::Projects::Services::JiraProjectType.connection_type, null: true
+ authorize :admin_project
argument :name,
GraphQL::STRING_TYPE,
required: false,
- description: 'Project name or key'
+ description: 'Project name or key.'
def resolve(name: nil, **args)
authorize!(project)
@@ -31,10 +32,6 @@ module Resolvers
end
end
- def authorized_resource?(project)
- Ability.allowed?(context[:current_user], :admin_project, project)
- end
-
private
alias_method :jira_service, :object
diff --git a/app/graphql/resolvers/projects/services_resolver.rb b/app/graphql/resolvers/projects/services_resolver.rb
index 4f5a6cddbb3..f618bf2df77 100644
--- a/app/graphql/resolvers/projects/services_resolver.rb
+++ b/app/graphql/resolvers/projects/services_resolver.rb
@@ -12,11 +12,11 @@ module Resolvers
argument :active,
GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Indicates if the service is active'
+ description: 'Indicates if the service is active.'
argument :type,
Types::Projects::ServiceTypeEnum,
required: false,
- description: 'Class name of the service'
+ description: 'Class name of the service.'
alias_method :project, :object
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index 69438229a50..11d18a0a080 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -6,23 +6,23 @@ module Resolvers
argument :membership, GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Limit projects that the current user is a member of'
+ description: 'Limit projects that the current user is a member of.'
argument :search, GraphQL::STRING_TYPE,
required: false,
- description: 'Search query for project name, path, or description'
+ description: 'Search query for project name, path, or description.'
argument :ids, [GraphQL::ID_TYPE],
required: false,
- description: 'Filter projects by IDs'
+ description: 'Filter projects by IDs.'
argument :search_namespaces, GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Include namespace in project search'
+ description: 'Include namespace in project search.'
argument :sort, GraphQL::STRING_TYPE,
required: false,
- description: 'Sort order of results'
+ description: 'Sort order of results.'
def resolve(**args)
ProjectsFinder
diff --git a/app/graphql/resolvers/release_milestones_resolver.rb b/app/graphql/resolvers/release_milestones_resolver.rb
new file mode 100644
index 00000000000..7582c91272f
--- /dev/null
+++ b/app/graphql/resolvers/release_milestones_resolver.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ReleaseMilestonesResolver < BaseResolver
+ type Types::MilestoneType.connection_type, null: true
+
+ alias_method :release, :object
+
+ def resolve(**args)
+ offset_pagination(release.milestones.order_by_dates_and_title)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/release_resolver.rb b/app/graphql/resolvers/release_resolver.rb
index 1edcc8c70b5..20ef01f8593 100644
--- a/app/graphql/resolvers/release_resolver.rb
+++ b/app/graphql/resolvers/release_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
argument :tag_name, GraphQL::STRING_TYPE,
required: true,
- description: 'The name of the tag associated to the release'
+ description: 'The name of the tag associated to the release.'
alias_method :project, :object
diff --git a/app/graphql/resolvers/releases_resolver.rb b/app/graphql/resolvers/releases_resolver.rb
index 8e8127cf279..01c1e9b11e7 100644
--- a/app/graphql/resolvers/releases_resolver.rb
+++ b/app/graphql/resolvers/releases_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
argument :sort, Types::ReleaseSortEnum,
required: false, default_value: :released_at_desc,
- description: 'Sort releases by this criteria'
+ description: 'Sort releases by this criteria.'
alias_method :project, :object
diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb
index cfb1711aed4..868d34ae7ad 100644
--- a/app/graphql/resolvers/snippets/blobs_resolver.rb
+++ b/app/graphql/resolvers/snippets/blobs_resolver.rb
@@ -13,7 +13,7 @@ module Resolvers
argument :paths, [GraphQL::STRING_TYPE],
required: false,
- description: 'Paths of the blobs'
+ description: 'Paths of the blobs.'
def resolve(**args)
authorize!(snippet)
diff --git a/app/graphql/resolvers/snippets_resolver.rb b/app/graphql/resolvers/snippets_resolver.rb
index 77099565df0..7153c919062 100644
--- a/app/graphql/resolvers/snippets_resolver.rb
+++ b/app/graphql/resolvers/snippets_resolver.rb
@@ -11,20 +11,20 @@ module Resolvers
argument :author_id, ::Types::GlobalIDType[::User],
required: false,
- description: 'The ID of an author'
+ description: 'The ID of an author.'
argument :project_id, ::Types::GlobalIDType[::Project],
required: false,
- description: 'The ID of a project'
+ description: 'The ID of a project.'
argument :type, Types::Snippets::TypeEnum,
required: false,
- description: 'The type of snippet'
+ description: 'The type of snippet.'
argument :explore,
GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Explore personal snippets'
+ description: 'Explore personal snippets.'
def resolve(**args)
if args[:author_id].present? && args[:project_id].present?
diff --git a/app/graphql/resolvers/todo_resolver.rb b/app/graphql/resolvers/todo_resolver.rb
index 9a8f7a71154..8966285fccc 100644
--- a/app/graphql/resolvers/todo_resolver.rb
+++ b/app/graphql/resolvers/todo_resolver.rb
@@ -8,27 +8,27 @@ module Resolvers
argument :action, [Types::TodoActionEnum],
required: false,
- description: 'The action to be filtered'
+ description: 'The action to be filtered.'
argument :author_id, [GraphQL::ID_TYPE],
required: false,
- description: 'The ID of an author'
+ description: 'The ID of an author.'
argument :project_id, [GraphQL::ID_TYPE],
required: false,
- description: 'The ID of a project'
+ description: 'The ID of a project.'
argument :group_id, [GraphQL::ID_TYPE],
required: false,
- description: 'The ID of a group'
+ description: 'The ID of a group.'
argument :state, [Types::TodoStateEnum],
required: false,
- description: 'The state of the todo'
+ description: 'The state of the todo.'
argument :type, [Types::TodoTargetEnum],
required: false,
- description: 'The type of the todo'
+ description: 'The type of the todo.'
def resolve(**args)
return Todo.none unless current_user.present? && target.present?
diff --git a/app/graphql/resolvers/tree_resolver.rb b/app/graphql/resolvers/tree_resolver.rb
index 075a1929c47..7a70c35897d 100644
--- a/app/graphql/resolvers/tree_resolver.rb
+++ b/app/graphql/resolvers/tree_resolver.rb
@@ -7,15 +7,15 @@ module Resolvers
argument :path, GraphQL::STRING_TYPE,
required: false,
default_value: '',
- description: 'The path to get the tree for. Default value is the root of the repository'
+ description: 'The path to get the tree for. Default value is the root of the repository.'
argument :ref, GraphQL::STRING_TYPE,
required: false,
default_value: :head,
- description: 'The commit ref to get the tree for. Default value is HEAD'
+ description: 'The commit ref to get the tree for. Default value is HEAD.'
argument :recursive, GraphQL::BOOLEAN_TYPE,
required: false,
default_value: false,
- description: 'Used to get a recursive tree. Default is false'
+ description: 'Used to get a recursive tree. Default is false.'
alias_method :repository, :object
diff --git a/app/graphql/resolvers/user_resolver.rb b/app/graphql/resolvers/user_resolver.rb
index 06c1f0cb42d..84bc03091d9 100644
--- a/app/graphql/resolvers/user_resolver.rb
+++ b/app/graphql/resolvers/user_resolver.rb
@@ -8,11 +8,11 @@ module Resolvers
argument :id, Types::GlobalIDType[User],
required: false,
- description: 'ID of the User'
+ description: 'ID of the User.'
argument :username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of the User'
+ description: 'Username of the User.'
def ready?(id: nil, username: nil)
unless id.present? ^ username.present?
diff --git a/app/graphql/resolvers/user_starred_projects_resolver.rb b/app/graphql/resolvers/user_starred_projects_resolver.rb
index cc3bb90decf..db420b3d116 100644
--- a/app/graphql/resolvers/user_starred_projects_resolver.rb
+++ b/app/graphql/resolvers/user_starred_projects_resolver.rb
@@ -6,7 +6,7 @@ module Resolvers
argument :search, GraphQL::STRING_TYPE,
required: false,
- description: 'Search query'
+ description: 'Search query.'
alias_method :user, :object
diff --git a/app/graphql/resolvers/users/snippets_resolver.rb b/app/graphql/resolvers/users/snippets_resolver.rb
index c2d42437ffd..e8048b9deb9 100644
--- a/app/graphql/resolvers/users/snippets_resolver.rb
+++ b/app/graphql/resolvers/users/snippets_resolver.rb
@@ -10,7 +10,7 @@ module Resolvers
argument :type, Types::Snippets::TypeEnum,
required: false,
- description: 'The type of snippet'
+ description: 'The type of snippet.'
private
diff --git a/app/graphql/resolvers/users_resolver.rb b/app/graphql/resolvers/users_resolver.rb
index a0ed076595d..95ced131504 100644
--- a/app/graphql/resolvers/users_resolver.rb
+++ b/app/graphql/resolvers/users_resolver.rb
@@ -9,13 +9,13 @@ module Resolvers
argument :ids, [GraphQL::ID_TYPE],
required: false,
- description: 'List of user Global IDs'
+ description: 'List of user Global IDs.'
argument :usernames, [GraphQL::STRING_TYPE], required: false,
- description: 'List of usernames'
+ description: 'List of usernames.'
argument :sort, Types::SortEnum,
- description: 'Sort users by this criteria',
+ description: 'Sort users by this criteria.',
required: false,
default_value: :created_desc
@@ -23,10 +23,15 @@ module Resolvers
required: false,
description: "Query to search users by name, username, or primary email."
- def resolve(ids: nil, usernames: nil, sort: nil, search: nil)
+ argument :admins, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ default_value: false,
+ description: 'Return only admin users.'
+
+ def resolve(ids: nil, usernames: nil, sort: nil, search: nil, admins: nil)
authorize!
- ::UsersFinder.new(context[:current_user], finder_params(ids, usernames, sort, search)).execute
+ ::UsersFinder.new(context[:current_user], finder_params(ids, usernames, sort, search, admins)).execute
end
def ready?(**args)
@@ -34,7 +39,7 @@ module Resolvers
return super if args.values.compact.blank?
- if args.values.all?
+ if args[:usernames]&.present? && args[:ids]&.present?
raise Gitlab::Graphql::Errors::ArgumentError, 'Provide either a list of usernames or ids'
end
@@ -47,12 +52,13 @@ module Resolvers
private
- def finder_params(ids, usernames, sort, search)
+ def finder_params(ids, usernames, sort, search, admins)
params = {}
params[:sort] = sort if sort
params[:username] = usernames if usernames
params[:id] = parse_gids(ids) if ids
params[:search] = search if search
+ params[:admins] = admins if admins
params
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 d45341077a4..eab42c2b78d 100644
--- a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
+++ b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
@@ -1,14 +1,16 @@
# frozen_string_literal: true
-# rubocop:disable Graphql/AuthorizeTypes
module Types
module Admin
module Analytics
module InstanceStatistics
class MeasurementType < BaseObject
+ include Gitlab::Graphql::Authorize::AuthorizeResource
graphql_name 'InstanceStatisticsMeasurement'
description 'Represents a recorded measurement (object count) for the Admins'
+ authorize :read_instance_statistics_measurements
+
field :recorded_at, Types::TimeType, null: true,
description: 'The time the measurement was recorded'
diff --git a/app/graphql/types/alert_management/domain_filter_enum.rb b/app/graphql/types/alert_management/domain_filter_enum.rb
index 58dbc8bb2cf..a798cfb9ee9 100644
--- a/app/graphql/types/alert_management/domain_filter_enum.rb
+++ b/app/graphql/types/alert_management/domain_filter_enum.rb
@@ -6,7 +6,7 @@ module Types
graphql_name 'AlertManagementDomainFilter'
description 'Filters the alerts based on given domain'
- value 'operations', description: 'Alerts for operations domain '
+ value 'operations', description: 'Alerts for operations domain'
value 'threat_monitoring', description: 'Alerts for threat monitoring domain'
end
end
diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb
index 159443641bc..cbd45b46dd6 100644
--- a/app/graphql/types/base_enum.rb
+++ b/app/graphql/types/base_enum.rb
@@ -5,6 +5,25 @@ module Types
extend GitlabStyleDeprecations
class << self
+ # Registers enum definition by the given DeclarativeEnum module
+ #
+ # @param enum_mod [Module] The enum module to be used
+ # @param use_name [Boolean] Does not override the name if set `false`
+ # @param use_description [Boolean] Does not override the description if set `false`
+ #
+ # Example:
+ #
+ # class MyEnum < BaseEnum
+ # declarative_enum MyDeclarativeEnum
+ # end
+ #
+ def declarative_enum(enum_mod, use_name: true, use_description: true)
+ 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) }
+ end
+
def value(*args, **kwargs, &block)
enum[args[0].downcase] = kwargs[:value] || args[0]
kwargs = gitlab_deprecation(kwargs)
diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb
index f47c744d1bb..f576fd83840 100644
--- a/app/graphql/types/board_type.rb
+++ b/app/graphql/types/board_type.rb
@@ -7,6 +7,8 @@ module Types
accepts ::Board
authorize :read_board
+ present_using BoardPresenter
+
field :id, type: GraphQL::ID_TYPE, null: false,
description: 'ID (global ID) of the board'
field :name, type: GraphQL::STRING_TYPE, null: true,
@@ -24,6 +26,12 @@ module Types
description: 'Lists of the board',
resolver: Resolvers::BoardListsResolver,
extras: [:lookahead]
+
+ field :web_path, GraphQL::STRING_TYPE, null: false,
+ description: 'Web path of the board.'
+
+ field :web_url, GraphQL::STRING_TYPE, null: false,
+ description: 'Web URL of the board.'
end
end
diff --git a/app/graphql/types/ci/build_need_type.rb b/app/graphql/types/ci/build_need_type.rb
new file mode 100644
index 00000000000..3bd81f8fa8f
--- /dev/null
+++ b/app/graphql/types/ci/build_need_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ # This type is only accessible from CiJob
+ class BuildNeedType < BaseObject
+ graphql_name 'CiBuildNeed'
+
+ field :name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the job we need to complete.'
+ 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 207c37f9538..e80771cdf9d 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -11,8 +11,10 @@ module Types
description: 'Whether merge pipelines are enabled.',
method: :merge_pipelines_enabled?
field :merge_trains_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Whether merge trains are enabled.',
+ 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.'
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 e54b345f3d3..29093c6d3c9 100644
--- a/app/graphql/types/ci/config/config_type.rb
+++ b/app/graphql/types/ci/config/config_type.rb
@@ -11,7 +11,7 @@ module Types
description: 'Linting errors'
field :merged_yaml, GraphQL::STRING_TYPE, null: true,
description: 'Merged CI config YAML'
- field :stages, [Types::Ci::Config::StageType], null: true,
+ field :stages, Types::Ci::Config::StageType.connection_type, null: true,
description: 'Stages of the pipeline'
field :status, Types::Ci::Config::StatusEnum, null: true,
description: 'Status of linting, can be either valid or invalid'
diff --git a/app/graphql/types/ci/config/group_type.rb b/app/graphql/types/ci/config/group_type.rb
index 8b0db2934a4..8e133bbcba8 100644
--- a/app/graphql/types/ci/config/group_type.rb
+++ b/app/graphql/types/ci/config/group_type.rb
@@ -9,7 +9,7 @@ module Types
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the job group'
- field :jobs, [Types::Ci::Config::JobType], null: true,
+ field :jobs, Types::Ci::Config::JobType.connection_type, null: true,
description: 'Jobs in group'
field :size, GraphQL::INT_TYPE, null: true,
description: 'Size of the job group'
diff --git a/app/graphql/types/ci/config/job_restriction_type.rb b/app/graphql/types/ci/config/job_restriction_type.rb
new file mode 100644
index 00000000000..294e3c94571
--- /dev/null
+++ b/app/graphql/types/ci/config/job_restriction_type.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ module Config
+ class JobRestrictionType < BaseObject
+ graphql_name 'CiConfigJobRestriction'
+
+ field :refs, [GraphQL::STRING_TYPE], null: true,
+ description: 'The Git refs the job restriction applies to.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/config/job_type.rb b/app/graphql/types/ci/config/job_type.rb
index 59bcbd9ef49..65fdc4c2615 100644
--- a/app/graphql/types/ci/config/job_type.rb
+++ b/app/graphql/types/ci/config/job_type.rb
@@ -8,13 +8,36 @@ module Types
graphql_name 'CiConfigJob'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the job'
+ description: 'Name of the job.'
field :group_name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the job group'
+ description: 'Name of the job group.'
field :stage, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the job stage'
- field :needs, [Types::Ci::Config::NeedType], null: true,
- description: 'Builds that must complete before the jobs run'
+ description: 'Name of the job stage.'
+ field :needs, Types::Ci::Config::NeedType.connection_type, null: true,
+ description: 'Builds that must complete before the jobs run.'
+ field :allow_failure, GraphQL::BOOLEAN_TYPE, null: true,
+ description: 'Allow job to fail.'
+ field :before_script, [GraphQL::STRING_TYPE], null: true,
+ description: 'Override a set of commands that are executed before the job.'
+ field :script, [GraphQL::STRING_TYPE], null: true,
+ description: 'Shell script that is executed by a runner.'
+ field :after_script, [GraphQL::STRING_TYPE], null: true,
+ description: 'Override a set of commands that are executed after the job.'
+ field :when, GraphQL::STRING_TYPE, null: true,
+ description: 'When to run the job.',
+ resolver_method: :restrict_when_to_run_jobs
+ field :environment, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of an environment to which the job deploys.'
+ field :except, Types::Ci::Config::JobRestrictionType, null: true,
+ description: 'Limit when jobs are not created.'
+ field :only, Types::Ci::Config::JobRestrictionType, null: true,
+ description: 'Jobs are created when these conditions do not apply.'
+ field :tags, [GraphQL::STRING_TYPE], null: true,
+ description: 'List of tags that are used to select a runner.'
+
+ def restrict_when_to_run_jobs
+ object[:when]
+ end
end
end
end
diff --git a/app/graphql/types/ci/config/stage_type.rb b/app/graphql/types/ci/config/stage_type.rb
index 20618bc41f8..2008c553629 100644
--- a/app/graphql/types/ci/config/stage_type.rb
+++ b/app/graphql/types/ci/config/stage_type.rb
@@ -9,7 +9,7 @@ module Types
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the stage'
- field :groups, [Types::Ci::Config::GroupType], null: true,
+ field :groups, Types::Ci::Config::GroupType.connection_type, null: true,
description: 'Groups of jobs for the stage'
end
end
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 5b6e8fe8567..f8bf1732e63 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -2,16 +2,16 @@
module Types
module Ci
- # rubocop: disable Graphql/AuthorizeTypes
class JobType < BaseObject
graphql_name 'CiJob'
+ authorize :read_commit_status
field :pipeline, Types::Ci::PipelineType, null: true,
description: 'Pipeline the job belongs to'
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the job'
- field :needs, JobType.connection_type, null: true,
- description: 'Builds that must complete before the jobs run'
+ field :needs, BuildNeedType.connection_type, null: true,
+ 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'
field :scheduled_at, Types::TimeType, null: true,
diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb
index fd0bde90836..695e7c61bd9 100644
--- a/app/graphql/types/ci/stage_type.rb
+++ b/app/graphql/types/ci/stage_type.rb
@@ -9,6 +9,7 @@ module Types
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the stage'
field :groups, Ci::GroupType.connection_type, null: true,
+ extras: [:lookahead],
description: 'Group of jobs for the stage'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
description: 'Detailed status of the stage'
@@ -16,6 +17,38 @@ module Types
def detailed_status
object.detailed_status(context[:current_user])
end
+
+ # Issues one query per pipeline
+ def groups(lookahead:)
+ key = ::Gitlab::Graphql::BatchKey.new(object, lookahead, object_name: :stage)
+
+ BatchLoader::GraphQL.for(key).batch(default_value: []) do |keys, loader|
+ by_pipeline = keys.group_by(&:pipeline)
+ include_needs = keys.any? { |k| k.requires?(%i[nodes jobs nodes needs]) }
+
+ by_pipeline.each do |pl, key_group|
+ project = pl.project
+ indexed = key_group.index_by(&:id)
+
+ jobs_for_pipeline(pl, indexed.keys, include_needs).each do |stage_id, statuses|
+ key = indexed[stage_id]
+ groups = ::Ci::Group.fabricate(project, key.stage, statuses)
+ loader.call(key, groups)
+ end
+ end
+ end
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def jobs_for_pipeline(pipeline, stage_ids, include_needs)
+ results = pipeline.latest_statuses.where(stage_id: stage_ids)
+ results = results.preload(:needs) if include_needs
+
+ results.group_by(&:stage_id)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/app/graphql/types/data_visualization_palette/color_enum.rb b/app/graphql/types/data_visualization_palette/color_enum.rb
new file mode 100644
index 00000000000..d55dde44048
--- /dev/null
+++ b/app/graphql/types/data_visualization_palette/color_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module DataVisualizationPalette
+ class ColorEnum < BaseEnum
+ graphql_name 'DataVisualizationColorEnum'
+ description 'Color of the data visualization palette'
+
+ Enums::DataVisualizationPalette.colors.keys.each do |unit|
+ value unit.upcase, value: unit, description: "#{unit.to_s.titleize} color"
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/data_visualization_palette/weight_enum.rb b/app/graphql/types/data_visualization_palette/weight_enum.rb
new file mode 100644
index 00000000000..b2b12a90ee4
--- /dev/null
+++ b/app/graphql/types/data_visualization_palette/weight_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module DataVisualizationPalette
+ class WeightEnum < BaseEnum
+ graphql_name 'DataVisualizationWeightEnum'
+ description 'Weight of the data visualization palette'
+
+ ::Enums::DataVisualizationPalette.weights.keys.each do |unit|
+ value "weight_#{unit}".upcase, value: unit, description: "#{unit.to_s.titleize} weight"
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 83b8a834801..78fb20650e9 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -121,6 +121,9 @@ module Types
field :moved_to, Types::IssueType, null: true,
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'
+
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
@@ -140,6 +143,10 @@ module Types
def discussion_locked
!!object.discussion_locked
end
+
+ def create_note_email
+ object.creatable_note_email_address(context[:current_user])
+ end
end
end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 816160e58f7..ee7d5780f7a 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -96,6 +96,8 @@ module Types
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'
+ field :default_squash_commit_message, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
+ 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'
field :source_branch_exists, GraphQL::BOOLEAN_TYPE,
@@ -126,10 +128,12 @@ module Types
description: 'The milestone of the merge request'
field :assignees, Types::UserType.connection_type, null: true, complexity: 5,
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'
- field :participants, Types::UserType.connection_type, null: true, complexity: 5,
- description: 'Participants in the 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'
field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
@@ -159,6 +163,8 @@ module Types
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'
+ field :squash, GraphQL::BOOLEAN_TYPE, null: false,
+ 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'
field :has_ci, GraphQL::BOOLEAN_TYPE, null: false, method: :has_ci?,
@@ -169,6 +175,10 @@ module Types
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'
+ field :merge_user, Types::UserType, null: true,
+ description: 'User who merged this merge request'
def approved_by
object.approved_by_users
@@ -235,6 +245,10 @@ module Types
def security_auto_fix
object.author == User.security_bot
end
+
+ def reviewers
+ object.reviewers if object.allows_reviewers?
+ end
end
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 9eea81c9d3e..f9dd11cbe37 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -88,9 +88,11 @@ module Types
mount_mutation Mutations::ContainerExpirationPolicies::Update
mount_mutation Mutations::ContainerRepositories::Destroy
mount_mutation Mutations::ContainerRepositories::DestroyTags
- mount_mutation Mutations::Ci::PipelineCancel
- mount_mutation Mutations::Ci::PipelineDestroy
- mount_mutation Mutations::Ci::PipelineRetry
+ mount_mutation Mutations::Ci::Pipeline::Cancel
+ mount_mutation Mutations::Ci::Pipeline::Destroy
+ mount_mutation Mutations::Ci::Pipeline::Retry
+ mount_mutation Mutations::Ci::CiCdSettingsUpdate
+ mount_mutation Mutations::Namespace::PackageSettings::Update
end
end
diff --git a/app/graphql/types/namespace/package_settings_type.rb b/app/graphql/types/namespace/package_settings_type.rb
new file mode 100644
index 00000000000..0720a1cfb4b
--- /dev/null
+++ b/app/graphql/types/namespace/package_settings_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ class Namespace::PackageSettingsType < BaseObject
+ graphql_name 'PackageSettings'
+
+ description 'Namespace-level Package Registry settings'
+
+ authorize :read_package_settings
+
+ field :maven_duplicates_allowed, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
+ field :maven_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
+ end
+end
diff --git a/app/graphql/types/namespace_type.rb b/app/graphql/types/namespace_type.rb
index 4dec6f4c5e6..ab614d92b06 100644
--- a/app/graphql/types/namespace_type.rb
+++ b/app/graphql/types/namespace_type.rb
@@ -37,6 +37,11 @@ module Types
description: 'Projects within this namespace',
resolver: ::Resolvers::NamespaceProjectsResolver
+ field :package_settings,
+ Types::Namespace::PackageSettingsType,
+ null: true,
+ description: 'The package settings for the namespace'
+
def root_storage_statistics
Gitlab::Graphql::Loaders::BatchRootStorageStatisticsLoader.new(object.id).find
end
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index f4e05e19eca..84b61340e93 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -46,6 +46,13 @@ module Types
field :confidential, GraphQL::BOOLEAN_TYPE, null: true,
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'
+
+ def url
+ ::Gitlab::UrlBuilder.build(object)
+ end
def system_note_icon_name
SystemNoteHelper.system_note_icon_name(object) if object.system?
diff --git a/app/graphql/types/package_type.rb b/app/graphql/types/package_type.rb
deleted file mode 100644
index 0604bf827a5..00000000000
--- a/app/graphql/types/package_type.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- class PackageType < BaseObject
- graphql_name 'Package'
- description 'Represents a package'
- 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 update date'
- field :version, GraphQL::STRING_TYPE, null: true, description: 'The version of the package'
- field :package_type, Types::PackageTypeEnum, null: false, description: 'The type of the package'
- end
-end
diff --git a/app/graphql/types/package_type_enum.rb b/app/graphql/types/package_type_enum.rb
deleted file mode 100644
index 6f50c166da3..00000000000
--- a/app/graphql/types/package_type_enum.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- class PackageTypeEnum < BaseEnum
- PACKAGE_TYPE_NAMES = {
- pypi: 'PyPI',
- npm: 'NPM'
- }.freeze
-
- ::Packages::Package.package_types.keys.each do |package_type|
- type_name = PACKAGE_TYPE_NAMES.fetch(package_type.to_sym, package_type.capitalize)
- value package_type.to_s.upcase, "Packages from the #{type_name} package manager", value: package_type.to_s
- end
- end
-end
diff --git a/app/graphql/types/packages/composer/details_type.rb b/app/graphql/types/packages/composer/details_type.rb
new file mode 100644
index 00000000000..8c6845a6fb3
--- /dev/null
+++ b/app/graphql/types/packages/composer/details_type.rb
@@ -0,0 +1,16 @@
+# 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/json_type.rb b/app/graphql/types/packages/composer/json_type.rb
new file mode 100644
index 00000000000..b7aa32f0170
--- /dev/null
+++ b/app/graphql/types/packages/composer/json_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Composer
+ # rubocop: disable Graphql/AuthorizeTypes
+ class JsonType < BaseObject
+ graphql_name 'PackageComposerJsonType'
+ description 'Represents a composer JSON file'
+
+ field :name, GraphQL::STRING_TYPE, null: true, description: 'The name set in the Composer JSON file.'
+ field :type, GraphQL::STRING_TYPE, null: true, description: 'The type set in the Composer JSON file.'
+ field :license, GraphQL::STRING_TYPE, null: true, description: 'The license set in the Composer JSON file.'
+ field :version, GraphQL::STRING_TYPE, null: true, description: 'The version set in the Composer JSON file.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/composer/metadatum_type.rb b/app/graphql/types/packages/composer/metadatum_type.rb
new file mode 100644
index 00000000000..a97818b1fb8
--- /dev/null
+++ b/app/graphql/types/packages/composer/metadatum_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Composer
+ class MetadatumType < BaseObject
+ graphql_name 'PackageComposerMetadatumType'
+ description 'Composer metadatum'
+
+ authorize :read_package
+
+ field :target_sha, GraphQL::STRING_TYPE, null: false, description: 'Target SHA of the package.'
+ field :composer_json, Types::Packages::Composer::JsonType, null: false, description: 'Data of the Composer JSON file.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_tag_type.rb b/app/graphql/types/packages/package_tag_type.rb
new file mode 100644
index 00000000000..a05ce03da67
--- /dev/null
+++ b/app/graphql/types/packages/package_tag_type.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageTagType < BaseObject
+ graphql_name 'PackageTag'
+ description 'Represents a package tag'
+ authorize :read_package
+
+ field :id, GraphQL::ID_TYPE, null: false, description: 'The ID of the tag.'
+ field :name, GraphQL::STRING_TYPE, null: false, description: 'The name of the tag.'
+ field :created_at, Types::TimeType, null: false, description: 'The created date.'
+ field :updated_at, Types::TimeType, null: false, description: 'The updated date.'
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
new file mode 100644
index 00000000000..b13d16e91c6
--- /dev/null
+++ b/app/graphql/types/packages/package_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageType < BaseObject
+ 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
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_type_enum.rb b/app/graphql/types/packages/package_type_enum.rb
new file mode 100644
index 00000000000..9713c9d49b1
--- /dev/null
+++ b/app/graphql/types/packages/package_type_enum.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageTypeEnum < BaseEnum
+ PACKAGE_TYPE_NAMES = {
+ pypi: 'PyPI',
+ npm: 'NPM'
+ }.freeze
+
+ ::Packages::Package.package_types.keys.each do |package_type|
+ type_name = PACKAGE_TYPE_NAMES.fetch(package_type.to_sym, package_type.capitalize)
+ value package_type.to_s.upcase, "Packages from the #{type_name} package manager", value: package_type.to_s
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index a7d9548610e..f66d8926a9f 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -175,7 +175,7 @@ module Types
description: 'A single issue of the project',
resolver: Resolvers::IssuesResolver.single
- field :packages, Types::PackageType.connection_type, null: true,
+ field :packages, Types::Packages::PackageType.connection_type, null: true,
description: 'Packages of the project',
resolver: Resolvers::PackagesResolver
@@ -315,9 +315,6 @@ module Types
description: 'Pipeline analytics',
resolver: Resolvers::ProjectPipelineStatisticsResolver
- field :total_pipeline_duration, GraphQL::INT_TYPE, null: true,
- description: 'Total pipeline duration for all of the pipelines in a project'
-
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
@@ -362,10 +359,6 @@ module Types
project.container_repositories.size
end
- def total_pipeline_duration
- object.all_pipelines.total_duration
- end
-
private
def project
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 05bb371088c..0e0c060f374 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -58,6 +58,11 @@ module Types
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',
+ resolver: Resolvers::PackageDetailsResolver
+
field :user, Types::UserType,
null: true,
description: 'Find a user',
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index b715b981483..e7afa7ce7f7 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -35,7 +35,8 @@ module Types
field :links, Types::ReleaseLinksType, null: true, method: :itself,
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'
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index f0c25e13a26..5b86871142c 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -10,7 +10,7 @@ module Types
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'
- field :exists, GraphQL::BOOLEAN_TYPE, null: false, method: :exists?,
+ field :exists, GraphQL::BOOLEAN_TYPE, null: false, method: :exists?, calls_gitaly: true,
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'
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 512ba7e2a66..2a1652cf2ba 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -4,8 +4,6 @@ require 'digest/md5'
require 'uri'
module ApplicationHelper
- include StartupCssHelper
-
# See https://docs.gitlab.com/ee/development/ee_features.html#code-in-appviews
# rubocop: disable CodeReuse/ActiveRecord
# We allow partial to be nil so that collection views can be passed in
@@ -46,7 +44,7 @@ module ApplicationHelper
# current_controller?('gitlab/application') # => false
def current_controller?(*args)
args.any? do |v|
- v.to_s.downcase == controller.controller_name || v.to_s.downcase == controller.controller_path
+ Gitlab::Utils.safe_downcase!(v.to_s) == controller.controller_name || Gitlab::Utils.safe_downcase!(v.to_s) == controller.controller_path
end
end
@@ -61,7 +59,7 @@ module ApplicationHelper
# current_action?(:create) # => false
# current_action?(:new, :create) # => true
def current_action?(*args)
- args.any? { |v| v.to_s.downcase == action_name }
+ args.any? { |v| Gitlab::Utils.safe_downcase!(v.to_s) == action_name }
end
def admin_section?
@@ -250,11 +248,7 @@ module ApplicationHelper
end
def stylesheet_link_tag_defer(path)
- if use_startup_css?
- stylesheet_link_tag(path, media: "print", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil)
- else
- stylesheet_link_tag(path, media: "all")
- end
+ stylesheet_link_tag(path, media: "print", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil)
end
def outdated_browser?
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 7866e3e3d9f..ed30adfabf0 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -242,6 +242,7 @@ module ApplicationSettingsHelper
:housekeeping_incremental_repack_period,
:html_emails_enabled,
:import_sources,
+ :invisible_captcha_enabled,
:max_artifacts_size,
:max_attachment_size,
:max_import_size,
@@ -335,7 +336,8 @@ module ApplicationSettingsHelper
:group_export_limit,
:group_download_export_limit,
:wiki_page_max_content_bytes,
- :container_registry_delete_tags_service_timeout
+ :container_registry_delete_tags_service_timeout,
+ :rate_limiting_response_text
]
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 0c5823894c5..bca53dfb88a 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -106,11 +106,12 @@ module BlobHelper
return unless blob
common_classes = "btn btn-#{btn_class}"
+ base_button = button_tag(label, class: "#{common_classes} disabled", disabled: true)
if !on_top_of_branch?(project, ref)
- button_tag label, class: "#{common_classes} disabled has-tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' }
+ modify_file_button_tooltip(base_button, _("You can only %{action} files when you are on a branch") % { action: action })
elsif blob.stored_externally?
- button_tag label, class: "#{common_classes} disabled has-tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' }
+ modify_file_button_tooltip(base_button, _("It is not possible to %{action} files that are stored in LFS using the web interface") % { action: action })
elsif can_modify_blob?(blob, project, ref)
button_tag label, class: "#{common_classes}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal'
elsif can?(current_user, :fork_project, project) && can?(current_user, :create_merge_request_in, project)
@@ -217,6 +218,10 @@ module BlobHelper
@gitlab_ci_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_ymls, project).execute)
end
+ def gitlab_ci_syntax_ymls(project)
+ @gitlab_ci_syntax_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_syntax_ymls, project).execute)
+ end
+
def metrics_dashboard_ymls(project)
@metrics_dashboard_ymls ||= template_dropdown_names(TemplateFinder.build(:metrics_dashboard_ymls, project).execute)
end
@@ -360,7 +365,11 @@ module BlobHelper
end
def edit_disabled_button_tag(button_text, common_classes)
- button_tag(button_text, class: "#{common_classes} disabled has-tooltip", title: _('You can only edit files when you are on a branch'), data: { container: 'body' })
+ button = button_tag(button_text, class: "#{common_classes} disabled", disabled: true)
+
+ # Disabled buttons with tooltips should have the tooltip attached
+ # to a wrapper element https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
+ content_tag(:span, button, class: 'has-tooltip', title: _('You can only edit files when you are on a branch'), data: { container: 'body' })
end
def edit_link_tag(link_text, edit_path, common_classes, data)
@@ -397,4 +406,12 @@ module BlobHelper
@path.to_s.end_with?(Ci::Pipeline::CONFIG_EXTENSION) ||
@path.to_s == @project.ci_config_path_or_default
end
+
+ private
+
+ def modify_file_button_tooltip(button, tooltip_message)
+ # Disabled buttons with tooltips should have the tooltip attached
+ # to a wrapper element https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
+ content_tag(:span, button, class: 'btn-group has-tooltip', title: tooltip_message, data: { container: 'body' })
+ end
end
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index 309aa477108..8a6f0821dbb 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -26,6 +26,10 @@ module Ci
_("%{message} showing first %{warnings_displayed}") % { message: message, warnings_displayed: MAX_LIMIT }
end
+ def has_gitlab_ci?(project)
+ project.has_ci? && project.builds_enabled?
+ end
+
private
def warning_markdown(pipeline)
diff --git a/app/helpers/ci/triggers_helper.rb b/app/helpers/ci/triggers_helper.rb
new file mode 100644
index 00000000000..01555b6e2cc
--- /dev/null
+++ b/app/helpers/ci/triggers_helper.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Ci::TriggersHelper
+ def builds_trigger_url(project_id, ref: nil)
+ if ref.nil?
+ "#{Settings.gitlab.url}/api/v4/projects/#{project_id}/trigger/pipeline"
+ else
+ "#{Settings.gitlab.url}/api/v4/projects/#{project_id}/ref/#{ref}/trigger/pipeline"
+ end
+ end
+
+ def service_trigger_url(service)
+ "#{Settings.gitlab.url}/api/v4/projects/#{service.project_id}/services/#{service.to_param}/trigger"
+ end
+end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 02d48386e31..e6e2b5b128b 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -110,8 +110,16 @@ module CommitsHelper
end
end
- def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
- commit_action_link('revert', commit, continue_to_path, btn_class: btn_class, has_tooltip: has_tooltip)
+ def revert_commit_link(commit, continue_to_path, btn_class: nil, pajamas: false)
+ 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
end
def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 195b3162039..08f357916b5 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -11,6 +11,10 @@ module DashboardHelper
merge_requests_dashboard_path(assignee_username: current_user.username)
end
+ def reviewer_mrs_dashboard_path
+ merge_requests_dashboard_path(reviewer_username: current_user.username)
+ end
+
def dashboard_nav_links
@dashboard_nav_links ||= get_dashboard_nav_links
end
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index 017981c8c8e..b58ff21b257 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -214,6 +214,29 @@ module EmailsHelper
end
end
+ def group_membership_expiration_changed_text(member, group)
+ if member.expires?
+ days = (member.expires_at - Date.today).to_i
+ days_formatted = pluralize(days, 'day')
+
+ _('Your %{group} membership will now expire in %{days}.') % { group: group.human_name, days: days_formatted }
+ else
+ _('Your membership in %{group} no longer expires.') % { group: group.human_name }
+ end
+ end
+
+ def group_membership_expiration_changed_link(member, group, format: nil)
+ url = group_group_members_url(group, search: member.user.username)
+
+ case format
+ when :html
+ link_to = generate_link('group membership', url).html_safe
+ _('For additional information, review your %{link_to} or contact your group owner.').html_safe % { link_to: link_to }
+ else
+ _('For additional information, review your group membership: %{link_to} or contact your group owner.') % { link_to: url }
+ end
+ end
+
def instance_access_request_text(user, format: nil)
gitlab_host = Gitlab.config.gitlab.host
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index 24072d1ab46..abb3c5a7af8 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -22,4 +22,10 @@ module GraphHelper
ratio = (counts[:success].to_f / (counts[:success] + counts[:failed])) * 100
ratio.to_i
end
+
+ def should_render_deployment_frequency_charts
+ false
+ end
end
+
+GraphHelper.prepend_if_ee('EE::GraphHelper')
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
index adc9d85a384..a4159ed6b19 100644
--- a/app/helpers/groups/group_members_helper.rb
+++ b/app/helpers/groups/group_members_helper.rb
@@ -18,7 +18,7 @@ module Groups::GroupMembersHelper
end
def members_data_json(group, members)
- members_data(group, members).to_json
+ MemberSerializer.new.represent(members, { current_user: current_user, group: group }).to_json
end
# Overridden in `ee/app/helpers/ee/groups/group_members_helper.rb`
@@ -38,84 +38,6 @@ module Groups::GroupMembersHelper
group_id: group.id
}
end
-
- private
-
- def members_data(group, members)
- members.map do |member|
- user = member.user
- source = member.source
-
- data = {
- id: member.id,
- created_at: member.created_at,
- expires_at: member.expires_at&.to_time,
- requested_at: member.requested_at,
- can_update: member.can_update?,
- can_remove: member.can_remove?,
- access_level: {
- string_value: member.human_access,
- integer_value: member.access_level
- },
- source: {
- id: source.id,
- name: source.full_name,
- web_url: Gitlab::UrlBuilder.build(source)
- },
- valid_roles: member.valid_level_roles
- }.merge(member_created_by_data(member.created_by))
-
- if member.invite?
- data[:invite] = member_invite_data(member)
- elsif user.present?
- data[:user] = member_user_data(user)
- end
-
- data
- end
- end
-
- def member_created_by_data(created_by)
- return {} unless created_by.present?
-
- {
- created_by: {
- name: created_by.name,
- web_url: Gitlab::UrlBuilder.build(created_by)
- }
- }
- end
-
- def member_user_data(user)
- {
- id: user.id,
- name: user.name,
- username: user.username,
- web_url: Gitlab::UrlBuilder.build(user),
- avatar_url: avatar_icon_for_user(user, AVATAR_SIZE),
- blocked: user.blocked?,
- two_factor_enabled: user.two_factor_enabled?
- }.merge(member_user_status_data(user.status))
- end
-
- def member_user_status_data(status)
- return {} unless status.present?
-
- {
- status: {
- emoji: status.emoji,
- message_html: status.message_html
- }
- }
- end
-
- def member_invite_data(member)
- {
- email: member.invite_email,
- avatar_url: avatar_icon_for_email(member.invite_email, AVATAR_SIZE),
- can_resend: member.can_resend_invite?
- }
- end
end
Groups::GroupMembersHelper.prepend_if_ee('EE::Groups::GroupMembersHelper')
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index e8eb6a5d417..133d9d21a14 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -22,6 +22,7 @@ module GroupsHelper
ldap_group_links#index
hooks#index
pipeline_quota#index
+ packages_and_registries#index
]
end
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index cea28fd4611..a643fea6d5a 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -22,4 +22,34 @@ module InviteMembersHelper
def invite_group_members?(group)
experiment_enabled?(:invite_members_empty_group_version_a) && Ability.allowed?(current_user, :admin_group_member, group)
end
+
+ def dropdown_invite_members_link(form_model)
+ link_to invite_members_url(form_model),
+ data: {
+ 'track-event': 'click_link',
+ 'track-label': tracking_label(current_user),
+ 'track-property': experiment_tracking_category_and_group(:invite_members_new_dropdown, subject: current_user)
+ } do
+ invite_member_link_content
+ end
+ end
+
+ private
+
+ def invite_members_url(form_model)
+ case form_model
+ when Project
+ project_project_members_path(form_model)
+ when Group
+ group_group_members_path(form_model)
+ end
+ end
+
+ def invite_member_link_content
+ text = s_('InviteMember|Invite members')
+
+ return text unless experiment_enabled?(:invite_members_new_dropdown)
+
+ "#{text} #{emoji_icon('shaking_hands', 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe
+ end
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 15842dec3dd..da142cbed0e 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -442,7 +442,8 @@ module IssuablesHelper
fullPath: issuable[:project_full_path],
iid: issuable[:iid],
severity: issuable[:severity],
- timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours
+ timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours,
+ createNoteEmail: issuable[:create_note_email]
}
end
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
new file mode 100644
index 00000000000..f1527b9b85a
--- /dev/null
+++ b/app/helpers/jira_connect_helper.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module JiraConnectHelper
+ def new_jira_connect_ui?
+ Feature.enabled?(:new_jira_connect_ui, type: :development, default_enabled: :yaml)
+ end
+
+ def jira_connect_app_data
+ {
+ groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER })
+ }
+ end
+end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 37e701c1c2b..6ab5f499b9a 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -159,6 +159,36 @@ module MergeRequestsHelper
issuable_path(issuable, { merge_request: { wip_event: wip_event } })
end
+
+ def user_merge_requests_counts
+ @user_merge_requests_counts ||= begin
+ assigned_count = assigned_issuables_count(:merge_requests)
+ review_requested_count = review_requested_merge_requests_count
+ total_count = assigned_count + review_requested_count
+
+ {
+ assigned: assigned_count,
+ review_requested: review_requested_count,
+ total: total_count
+ }
+ 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
+
+ def default_suggestion_commit_message
+ @project.suggestion_commit_message.presence || Gitlab::Suggestions::CommitMessage::DEFAULT_SUGGESTION_COMMIT_MESSAGE
+ end
end
MergeRequestsHelper.prepend_if_ee('EE::MergeRequestsHelper')
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index e3d82e7a091..8920133734c 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -159,7 +159,7 @@ module PageLayoutHelper
end
def user_status_properties(user)
- default_properties = { current_emoji: '', current_message: '', can_set_user_availability: Feature.enabled?(:set_user_availability_status, user), default_emoji: UserStatus::DEFAULT_EMOJI }
+ default_properties = { current_emoji: '', current_message: '', can_set_user_availability: Feature.enabled?(:set_user_availability_status, user, default_enabled: :yaml), default_emoji: UserStatus::DEFAULT_EMOJI }
return default_properties unless user&.status
default_properties.merge({
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 5310aef5bad..c2a77abb9c9 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -82,7 +82,7 @@ module PreferencesHelper
def integration_views
[].tap do |views|
- views << { name: 'gitpod', message: gitpod_enable_description, message_url: 'https://gitpod.io/', help_link: help_page_path('integration/gitpod.md') } if Gitlab::Gitpod.feature_and_settings_enabled?
+ views << { name: 'gitpod', message: gitpod_enable_description, message_url: 'https://gitpod.io/', help_link: help_page_path('integration/gitpod.md') } if Gitlab::CurrentSettings.gitpod_enabled
views << { name: 'sourcegraph', message: sourcegraph_url_message, message_url: Gitlab::CurrentSettings.sourcegraph_url, help_link: help_page_path('user/profile/preferences.md', anchor: 'sourcegraph') } if Gitlab::Sourcegraph.feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
end
end
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index 997551d9659..58f1abb2818 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -34,5 +34,3 @@ module Projects::AlertManagementHelper
)
end
end
-
-Projects::AlertManagementHelper.prepend_if_ee('EE::Projects::AlertManagementHelper')
diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb
new file mode 100644
index 00000000000..168526d2abb
--- /dev/null
+++ b/app/helpers/projects/project_members_helper.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Projects::ProjectMembersHelper
+ def can_manage_project_members?(project)
+ can?(current_user, :admin_project_member, project)
+ end
+
+ def show_groups?(group_links)
+ group_links.exists? || groups_tab_active?
+ end
+
+ def show_invited_members?(project, invited_members)
+ can_manage_project_members?(project) && invited_members.exists?
+ end
+
+ def show_access_requests?(project, requesters)
+ can_manage_project_members?(project) && requesters.exists?
+ end
+
+ def groups_tab_active?
+ params[:search_groups].present?
+ end
+
+ def current_user_is_group_owner?(project)
+ return false if project.group.nil?
+
+ project.group.has_owner?(current_user)
+ end
+end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 80206654cd1..b21d3ca51db 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -150,13 +150,7 @@ module ProjectsHelper
end
def can_change_visibility_level?(project, current_user)
- return false unless can?(current_user, :change_visibility_level, project)
-
- if project.fork_source
- project.fork_source.visibility_level > Gitlab::VisibilityLevel::PRIVATE
- else
- true
- end
+ can?(current_user, :change_visibility_level, project)
end
def can_disable_emails?(project, current_user)
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index 3516000e296..5f361e6653d 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -76,6 +76,8 @@ module ServicesHelper
end
def scoped_reset_integration_path(integration, group: nil)
+ return '' unless integration.persisted?
+
if group.present?
reset_group_settings_integration_path(group, integration)
else
@@ -102,7 +104,7 @@ module ServicesHelper
cancel_path: scoped_integrations_path,
can_test: integration.can_test?.to_s,
test_path: scoped_test_integration_path(integration),
- reset_path: reset_integration?(integration, group: group) ? scoped_reset_integration_path(integration, group: group) : ''
+ reset_path: scoped_reset_integration_path(integration, group: group)
}
end
@@ -126,10 +128,6 @@ module ServicesHelper
!Gitlab.com?
end
- def reset_integration?(integration, group: nil)
- integration.persisted? && Feature.enabled?(:reset_integrations, group, type: :development)
- end
-
extend self
private
diff --git a/app/helpers/startup_css_helper.rb b/app/helpers/startup_css_helper.rb
deleted file mode 100644
index b54e19bfc0d..00000000000
--- a/app/helpers/startup_css_helper.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module StartupCssHelper
- def use_startup_css?
- (Feature.enabled?(:startup_css) || params[:startup_css] == 'true' || cookies['startup_css'] == 'true') && !Rails.env.test?
- end
-end
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 6fbe2642056..e81986d4453 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -72,7 +72,8 @@ module TabHelper
# Add our custom class into the html_options, which may or may not exist
# and which may or may not already have a :class key
o = options.delete(:html_options) || {}
- o[:class] = [*o[:class], klass].join(' ').strip
+ o[:class] = [*o[:class], klass].join(' ')
+ o[:class].strip!
if block_given?
content_tag(:li, capture(&block), o)
diff --git a/app/helpers/triggers_helper.rb b/app/helpers/triggers_helper.rb
deleted file mode 100644
index 5cfdc0971f0..00000000000
--- a/app/helpers/triggers_helper.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module TriggersHelper
- def builds_trigger_url(project_id, ref: nil)
- if ref.nil?
- "#{Settings.gitlab.url}/api/v4/projects/#{project_id}/trigger/pipeline"
- else
- "#{Settings.gitlab.url}/api/v4/projects/#{project_id}/ref/#{ref}/trigger/pipeline"
- end
- end
-
- def service_trigger_url(service)
- "#{Settings.gitlab.url}/api/v4/projects/#{service.project_id}/services/#{service.to_param}/trigger"
- end
-end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index a58f8a6f792..a5d4d6872df 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -3,7 +3,7 @@
module UsersHelper
def admin_users_data_attributes(users)
{
- users: Admin::UserSerializer.new.represent(users).to_json,
+ users: Admin::UserSerializer.new.represent(users, { current_user: current_user }).to_json,
paths: admin_users_paths.to_json
}
end
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index 0a37257e124..696f29164fd 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -26,76 +26,6 @@ module VisibilityLevelHelper
end
end
- def project_visibility_level_description(level)
- case level
- when Gitlab::VisibilityLevel::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.")
- when Gitlab::VisibilityLevel::INTERNAL
- _("The project can be accessed by any logged in user except external users.")
- when Gitlab::VisibilityLevel::PUBLIC
- _("The project can be accessed without any authentication.")
- end
- end
-
- def group_visibility_level_description(level)
- case level
- when Gitlab::VisibilityLevel::PRIVATE
- _("The group and its projects can only be viewed by members.")
- when Gitlab::VisibilityLevel::INTERNAL
- _("The group and any internal projects can be viewed by any logged in user except external users.")
- when Gitlab::VisibilityLevel::PUBLIC
- _("The group and any public projects can be viewed without any authentication.")
- end
- end
-
- # Note: these messages closely mirror the form validation strings found in the project
- # model and any changes or additons to these may also need to be made there.
- def disallowed_project_visibility_level_description(level, project)
- level_name = Gitlab::VisibilityLevel.level_name(level).downcase
- reasons = []
- instructions = []
-
- unless project.visibility_level_allowed_as_fork?(level)
- reasons << "the fork source project has lower visibility"
- end
-
- unless project.visibility_level_allowed_by_group?(level)
- errors = visibility_level_errors_for_group(project.group, level_name)
-
- reasons << errors[:reason]
- instructions << errors[:instruction]
- end
-
- reasons = reasons.any? ? ' because ' + reasons.to_sentence : ''
- "This project cannot be #{level_name}#{reasons}.#{instructions.join}".html_safe
- end
-
- # Note: these messages closely mirror the form validation strings found in the group
- # model and any changes or additons to these may also need to be made there.
- def disallowed_group_visibility_level_description(level, group)
- level_name = Gitlab::VisibilityLevel.level_name(level).downcase
- reasons = []
- instructions = []
-
- unless group.visibility_level_allowed_by_projects?(level)
- reasons << "it contains projects with higher visibility"
- end
-
- unless group.visibility_level_allowed_by_sub_groups?(level)
- reasons << "it contains sub-groups with higher visibility"
- end
-
- unless group.visibility_level_allowed_by_parent?(level)
- errors = visibility_level_errors_for_group(group.parent, level_name)
-
- reasons << errors[:reason]
- instructions << errors[:instruction]
- end
-
- reasons = reasons.any? ? ' because ' + reasons.to_sentence : ''
- "This group cannot be #{level_name}#{reasons}.#{instructions.join}".html_safe
- end
-
def visibility_icon_description(form_model)
if form_model.respond_to?(:visibility_level_allowed_as_fork?)
project_visibility_icon_description(form_model.visibility_level)
@@ -104,14 +34,6 @@ module VisibilityLevelHelper
end
end
- def group_visibility_icon_description(level)
- "#{visibility_level_label(level)} - #{group_visibility_level_description(level)}"
- end
-
- def project_visibility_icon_description(level)
- "#{visibility_level_label(level)} - #{project_visibility_level_description(level)}"
- end
-
def visibility_level_label(level)
# The visibility level can be:
# 'VisibilityLevel|Private', 'VisibilityLevel|Internal', 'VisibilityLevel|Public'
@@ -203,11 +125,33 @@ module VisibilityLevelHelper
current_level
end
- def visibility_level_errors_for_group(group, level_name)
- group_name = link_to group.name, group_path(group)
- change_visibility = link_to 'change the visibility', edit_group_path(group)
+ def project_visibility_level_description(level)
+ case level
+ when Gitlab::VisibilityLevel::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.")
+ when Gitlab::VisibilityLevel::INTERNAL
+ _("The project can be accessed by any logged in user except external users.")
+ when Gitlab::VisibilityLevel::PUBLIC
+ _("The project can be accessed without any authentication.")
+ end
+ end
+
+ def group_visibility_level_description(level)
+ case level
+ when Gitlab::VisibilityLevel::PRIVATE
+ _("The group and its projects can only be viewed by members.")
+ when Gitlab::VisibilityLevel::INTERNAL
+ _("The group and any internal projects can be viewed by any logged in user except external users.")
+ when Gitlab::VisibilityLevel::PUBLIC
+ _("The group and any public projects can be viewed without any authentication.")
+ end
+ end
- { reason: "the visibility of #{group_name} is #{group.visibility}",
- instruction: " To make this group #{level_name}, you must first #{change_visibility} of the parent group." }
+ def project_visibility_icon_description(level)
+ "#{visibility_level_label(level)} - #{project_visibility_level_description(level)}"
+ end
+
+ def group_visibility_icon_description(level)
+ "#{visibility_level_label(level)} - #{group_visibility_level_description(level)}"
end
end
diff --git a/app/helpers/web_ide_button_helper.rb b/app/helpers/web_ide_button_helper.rb
index 7aa0adc31bd..6c73d365e8e 100644
--- a/app/helpers/web_ide_button_helper.rb
+++ b/app/helpers/web_ide_button_helper.rb
@@ -26,7 +26,7 @@ module WebIdeButtonHelper
end
def show_gitpod_button?
- show_web_ide_button? && Gitlab::Gitpod.feature_and_settings_enabled?(@project)
+ show_web_ide_button? && Gitlab::CurrentSettings.gitpod_enabled
end
def can_push_code?
@@ -54,7 +54,7 @@ module WebIdeButtonHelper
end
def gitpod_url
- return "" unless Gitlab::Gitpod.feature_and_settings_enabled?(@project)
+ return "" unless Gitlab::CurrentSettings.gitpod_enabled
"#{Gitlab::CurrentSettings.gitpod_url}##{project_tree_url(@project, tree_join(@ref, @path || ''))}"
end
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index b2c1351bd28..c565df1a2ee 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -106,6 +106,8 @@ module Emails
@count = export_status.fetch(:rows_expected)
@written_count = export_status.fetch(:rows_written)
@truncated = export_status.fetch(:truncated)
+ @size_limit = ActiveSupport::NumberHelper
+ .number_to_human_size(Issuable::ExportCsv::BaseService::TARGET_FILESIZE)
filename = "#{project.full_path.parameterize}_issues_#{Date.today.iso8601}.csv"
attachments[filename] = { content: csv_data, mime_type: 'text/csv' }
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 759181bd3cb..69f5fe1430a 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -114,6 +114,23 @@ module Emails
subject: subject('Invitation declined'))
end
+ def member_expiration_date_updated_email(member_source_type, member_id)
+ @member_source_type = member_source_type
+ @member_id = member_id
+
+ return unless member_exists?
+
+ subject = if member.expires?
+ _('Group membership expiration date changed')
+ else
+ _('Group membership expiration date removed')
+ end
+
+ member_email_with_layout(
+ to: member.user.notification_email_for(notification_group),
+ subject: subject(subject))
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def member
@member ||= Member.find_by(id: @member_id)
@@ -147,3 +164,5 @@ module Emails
end
end
end
+
+Emails::Members.prepend_if_ee('EE::Emails::Members')
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 28ac752f550..4faa1a11276 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -115,6 +115,8 @@ module Emails
@count = export_status.fetch(:rows_expected)
@written_count = export_status.fetch(:rows_written)
@truncated = export_status.fetch(:truncated)
+ @size_limit = ActiveSupport::NumberHelper
+ .number_to_human_size(Issuable::ExportCsv::BaseService::TARGET_FILESIZE)
filename = "#{project.full_path.parameterize}_merge_requests_#{Date.current.iso8601}.csv"
attachments[filename] = { content: csv_data, mime_type: 'text/csv' }
diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb
index f2538d28a1a..0b830f4ee5e 100644
--- a/app/mailers/emails/pipelines.rb
+++ b/app/mailers/emails/pipelines.rb
@@ -3,15 +3,15 @@
module Emails
module Pipelines
def pipeline_success_email(pipeline, recipients)
- pipeline_mail(pipeline, recipients, 'succeeded')
+ pipeline_mail(pipeline, recipients, 'Succesful')
end
def pipeline_failed_email(pipeline, recipients)
- pipeline_mail(pipeline, recipients, 'failed')
+ pipeline_mail(pipeline, recipients, 'Failed')
end
def pipeline_fixed_email(pipeline, recipients)
- pipeline_mail(pipeline, recipients, 'been fixed')
+ pipeline_mail(pipeline, recipients, 'Fixed')
end
private
@@ -50,10 +50,13 @@ module Emails
end
def pipeline_subject(status)
- commit = [@pipeline.short_sha]
- commit << "in #{@merge_request.to_reference}" if @merge_request
+ subject = []
- subject("Pipeline ##{@pipeline.id} has #{status} for #{@pipeline.source_ref}", commit.join(' '))
+ subject << "#{status} pipeline for #{@pipeline.source_ref}"
+ subject << @project.name if @project
+ subject << @pipeline.short_sha
+
+ subject.join(' | ')
end
end
end
diff --git a/app/mailers/previews/devise_mailer_preview.rb b/app/mailers/previews/devise_mailer_preview.rb
index 68f281f825e..2919d466073 100644
--- a/app/mailers/previews/devise_mailer_preview.rb
+++ b/app/mailers/previews/devise_mailer_preview.rb
@@ -31,6 +31,6 @@ class DeviseMailerPreview < ActionMailer::Preview
private
def unsaved_user
- User.new(name: 'Jane Doe', email: 'jdoe@example.com')
+ User.new(name: 'Jane Doe', email: 'jdoe@example.com', created_at: 1.minute.ago)
end
end
diff --git a/app/models/alert_management/http_integration.rb b/app/models/alert_management/http_integration.rb
index 0c916c576cb..2d9a2d7031c 100644
--- a/app/models/alert_management/http_integration.rb
+++ b/app/models/alert_management/http_integration.rb
@@ -52,6 +52,10 @@ module AlertManagement
endpoint_identifier == LEGACY_IDENTIFIER
end
+ def token_changed?
+ attribute_changed?(:token)
+ end
+
# Blank token assignment triggers token reset
def prevent_token_assignment
if token.present? && token_changed?
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 71235ed1002..44d1b6cf907 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -77,4 +77,9 @@ class ApplicationRecord < ActiveRecord::Base
def self.where_exists(query)
where('EXISTS (?)', query.select(1))
end
+
+ def self.declarative_enum(enum_mod)
+ values = enum_mod.definition.transform_values { |v| v[:value] }
+ enum(enum_mod.key => values)
+ end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 9b9db7f93fd..5655ea4d4bf 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -171,7 +171,7 @@ class ApplicationSetting < ApplicationRecord
validates :default_artifacts_expire_in, presence: true, duration: true
validates :container_expiration_policies_enable_historic_entries,
- inclusion: { in: [true, false], message: 'must be a boolean value' }
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
validates :container_registry_token_expire_delay,
presence: true,
@@ -303,9 +303,15 @@ class ApplicationSetting < ApplicationRecord
validates :container_registry_delete_tags_service_timeout,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :container_registry_cleanup_tags_service_max_list_size,
+ numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+
validates :container_registry_expiration_policies_worker_capacity,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :invisible_captcha_enabled,
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
+
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
@@ -400,6 +406,42 @@ class ApplicationSetting < ApplicationRecord
validates :ci_jwt_signing_key,
rsa_key: true, allow_nil: true
+ validates :rate_limiting_response_text,
+ length: { maximum: 255, message: _('is too long (maximum is %{count} characters)') },
+ allow_blank: true
+
+ validates :throttle_unauthenticated_requests_per_period,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_unauthenticated_period_in_seconds,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_authenticated_api_requests_per_period,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_authenticated_api_period_in_seconds,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_authenticated_web_requests_per_period,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_authenticated_web_period_in_seconds,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_protected_paths_requests_per_period,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ validates :throttle_protected_paths_period_in_seconds,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
@@ -430,7 +472,7 @@ class ApplicationSetting < ApplicationRecord
attr_encrypted :cloud_license_auth_token, encryption_options_base_truncated_aes_256_gcm
validates :disable_feed_token,
- inclusion: { in: [true, false], message: 'must be a boolean value' }
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
before_validation :ensure_uuid!
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 105889a364a..b05355f14b4 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -91,12 +91,13 @@ module ApplicationSettingImplementation
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
+ invisible_captcha_enabled: false,
issues_create_limit: 300,
local_markdown_version: 0,
login_recaptcha_protection_enabled: false,
max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
- max_import_size: 50,
+ max_import_size: 0,
minimum_password_length: DEFAULT_MINIMUM_PASSWORD_LENGTH,
mirror_available: true,
notify_on_unknown_sign_in: true,
@@ -172,7 +173,8 @@ module ApplicationSettingImplementation
container_registry_delete_tags_service_timeout: 250,
container_registry_expiration_policies_worker_capacity: 0,
kroki_enabled: false,
- kroki_url: nil
+ kroki_url: nil,
+ rate_limiting_response_text: nil
}
end
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index a4d991b040c..d1c0bb11dc8 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -4,6 +4,7 @@ class AuditEvent < ApplicationRecord
include CreatedAtFilterable
include BulkInsertSafe
include EachBatch
+ include PartitionedTable
PARALLEL_PERSISTENCE_COLUMNS = [
:author_name,
@@ -15,6 +16,8 @@ class AuditEvent < ApplicationRecord
self.primary_key = :id
+ partitioned_by :created_at, strategy: :monthly
+
serialize :details, Hash # rubocop:disable Cop/ActiveRecordSerialize
belongs_to :user, foreign_key: :author_id
diff --git a/app/models/audit_event_archived.rb b/app/models/audit_event_archived.rb
new file mode 100644
index 00000000000..3119f56fbcc
--- /dev/null
+++ b/app/models/audit_event_archived.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+# This model is not intended to be used.
+# It is a temporary reference to the pre-partitioned
+# audit_events table.
+# Please refer to https://gitlab.com/groups/gitlab-org/-/epics/3206
+# for details.
+class AuditEventArchived < ApplicationRecord
+ self.table_name = 'audit_events_archived'
+end
diff --git a/app/models/audit_event_partitioned.rb b/app/models/audit_event_partitioned.rb
deleted file mode 100644
index 672daebd14a..00000000000
--- a/app/models/audit_event_partitioned.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-# This model is not yet intended to be used.
-# It is in a transitioning phase while we are partitioning
-# the table on the database-side.
-# Please refer to https://gitlab.com/groups/gitlab-org/-/epics/3206
-# for details.
-class AuditEventPartitioned < ApplicationRecord
- include PartitionedTable
-
- self.table_name = 'audit_events_part_5fc467ac26'
-
- partitioned_by :created_at, strategy: :monthly
-end
diff --git a/app/models/authentication_event.rb b/app/models/authentication_event.rb
index 9d191e6ae4d..1e822629ba1 100644
--- a/app/models/authentication_event.rb
+++ b/app/models/authentication_event.rb
@@ -3,10 +3,10 @@
class AuthenticationEvent < ApplicationRecord
include UsageStatistics
- TWO_FACTOR = 'two-factor'.freeze
- TWO_FACTOR_U2F = 'two-factor-via-u2f-device'.freeze
- TWO_FACTOR_WEBAUTHN = 'two-factor-via-webauthn-device'.freeze
- STANDARD = 'standard'.freeze
+ TWO_FACTOR = 'two-factor'
+ TWO_FACTOR_U2F = 'two-factor-via-u2f-device'
+ TWO_FACTOR_WEBAUTHN = 'two-factor-via-webauthn-device'
+ STANDARD = 'standard'
STATIC_PROVIDERS = [TWO_FACTOR, TWO_FACTOR_U2F, TWO_FACTOR_WEBAUTHN, STANDARD].freeze
belongs_to :user, optional: true
diff --git a/app/models/blob_viewer/gitlab_ci_yml.rb b/app/models/blob_viewer/gitlab_ci_yml.rb
index 11228e620c9..e255b6d15d2 100644
--- a/app/models/blob_viewer/gitlab_ci_yml.rb
+++ b/app/models/blob_viewer/gitlab_ci_yml.rb
@@ -15,7 +15,9 @@ module BlobViewer
prepare!
- @validation_message = Gitlab::Ci::YamlProcessor.validation_message(blob.data, opts)
+ @validation_message = Gitlab::Ci::Lint
+ .new(project: opts[:project], current_user: opts[:user], sha: opts[:sha])
+ .validate(blob.data).errors.first
end
def valid?(opts)
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 19a0d424e33..ef3891908f7 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -7,7 +7,6 @@ module Ci
include Importable
include AfterCommitQueue
include Ci::HasRef
- extend ::Gitlab::Utils::Override
InvalidBridgeTypeError = Class.new(StandardError)
InvalidTransitionError = Class.new(StandardError)
@@ -200,13 +199,6 @@ module Ci
end
end
- override :dependency_variables
- def dependency_variables
- return [] unless ::Feature.enabled?(:ci_bridge_dependency_variables, project, default_enabled: true)
-
- super
- end
-
def target_revision_ref
downstream_pipeline_params.dig(:target_revision, :ref)
end
@@ -218,7 +210,8 @@ module Ci
project: downstream_project,
source: :pipeline,
target_revision: {
- ref: target_ref || downstream_project.default_branch
+ ref: target_ref || downstream_project.default_branch,
+ variables_attributes: downstream_variables
},
execute_params: {
ignore_skip_ci: true,
@@ -238,7 +231,8 @@ module Ci
checkout_sha: parent_pipeline.sha,
before: parent_pipeline.before_sha,
source_sha: parent_pipeline.source_sha,
- target_sha: parent_pipeline.target_sha
+ target_sha: parent_pipeline.target_sha,
+ variables_attributes: downstream_variables
},
execute_params: {
ignore_skip_ci: true,
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 71939f070cb..5e3f42d7c2c 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -27,7 +27,8 @@ module Ci
upload_multiple_artifacts: -> (build) { build.publishes_artifacts_reports? },
refspecs: -> (build) { build.merge_request_ref? },
artifacts_exclude: -> (build) { build.supports_artifacts_exclude? },
- multi_build_steps: -> (build) { build.multi_build_steps? }
+ multi_build_steps: -> (build) { build.multi_build_steps? },
+ return_exit_code: -> (build) { build.exit_codes_defined? }
}.freeze
DEFAULT_RETRIES = {
@@ -146,6 +147,12 @@ module Ci
.includes(:metadata, :job_artifacts_metadata)
end
+ scope :with_project_and_metadata, -> do
+ if Feature.enabled?(:non_public_artifacts, type: :development)
+ joins(:metadata).includes(:project, :metadata)
+ end
+ end
+
scope :with_artifacts_not_expired, -> { with_downloadable_artifacts.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.current) }
scope :with_expired_artifacts, -> { with_downloadable_artifacts.where('artifacts_expire_at < ?', Time.current) }
scope :last_month, -> { where('created_at > ?', Date.today - 1.month) }
@@ -382,12 +389,8 @@ module Ci
end
after_transition any => [:skipped, :canceled] do |build, transition|
- if Feature.enabled?(:cd_skipped_deployment_status, build.project)
- if transition.to_name == :skipped
- build.deployment&.skip
- else
- build.deployment&.cancel
- end
+ if transition.to_name == :skipped
+ build.deployment&.skip
else
build.deployment&.cancel
end
@@ -741,6 +744,16 @@ module Ci
artifacts_metadata?
end
+ def artifacts_public?
+ return true unless Feature.enabled?(:non_public_artifacts, type: :development)
+
+ artifacts_public = options.dig(:artifacts, :public)
+
+ return true if artifacts_public.nil? # Default artifacts:public to true
+
+ options.dig(:artifacts, :public)
+ end
+
def artifacts_metadata_entry(path, **options)
artifacts_metadata.open do |metadata_stream|
metadata = Gitlab::Ci::Build::Artifacts::Metadata.new(
@@ -1007,14 +1020,23 @@ module Ci
end
def debug_mode?
- return false unless Feature.enabled?(:restrict_access_to_build_debug_mode, default_enabled: true)
-
# TODO: Have `debug_mode?` check against data on sent back from runner
# to capture all the ways that variables can be set.
# See (https://gitlab.com/gitlab-org/gitlab/-/issues/290955)
variables.any? { |variable| variable[:key] == 'CI_DEBUG_TRACE' && variable[:value].casecmp('true') == 0 }
end
+ def drop_with_exit_code!(failure_reason, exit_code)
+ transaction do
+ conditionally_allow_failure!(exit_code)
+ drop!(failure_reason)
+ end
+ end
+
+ def exit_codes_defined?
+ options.dig(:allow_failure_criteria, :exit_codes).present?
+ end
+
protected
def run_status_commit_hooks!
@@ -1098,6 +1120,22 @@ module Ci
Gitlab::ErrorTracking.track_exception(e)
end
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)
+ update_columns(allow_failure: true)
+ end
+ end
+
+ def allowed_to_fail_with_code?(exit_code)
+ options
+ .dig(:allow_failure_criteria, :exit_codes)
+ .to_a
+ .include?(exit_code)
+ end
end
end
diff --git a/app/models/ci/build_need.rb b/app/models/ci/build_need.rb
index b977a5f4419..fac615f97b9 100644
--- a/app/models/ci/build_need.rb
+++ b/app/models/ci/build_need.rb
@@ -6,7 +6,7 @@ module Ci
include BulkInsertSafe
- belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id, inverse_of: :needs
+ belongs_to :build, class_name: "Ci::Processable", foreign_key: :build_id, inverse_of: :needs
validates :build, presence: true
validates :name, presence: true, length: { maximum: 128 }
diff --git a/app/models/ci/build_runner_session.rb b/app/models/ci/build_runner_session.rb
index bc7f17f046c..b6196048ca1 100644
--- a/app/models/ci/build_runner_session.rb
+++ b/app/models/ci/build_runner_session.rb
@@ -7,8 +7,8 @@ module Ci
extend Gitlab::Ci::Model
TERMINAL_SUBPROTOCOL = 'terminal.gitlab.com'
- DEFAULT_SERVICE_NAME = 'build'.freeze
- DEFAULT_PORT_NAME = 'default_port'.freeze
+ DEFAULT_SERVICE_NAME = 'build'
+ DEFAULT_PORT_NAME = 'default_port'
self.table_name = 'ci_builds_runner_session'
diff --git a/app/models/ci/commit_with_pipeline.rb b/app/models/ci/commit_with_pipeline.rb
new file mode 100644
index 00000000000..7f952fb77a0
--- /dev/null
+++ b/app/models/ci/commit_with_pipeline.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class Ci::CommitWithPipeline < SimpleDelegator
+ include Presentable
+
+ def initialize(commit)
+ @latest_pipelines = {}
+ super(commit)
+ end
+
+ def pipelines
+ project.ci_pipelines.where(sha: sha)
+ end
+
+ def last_pipeline
+ strong_memoize(:last_pipeline) do
+ pipelines.last
+ end
+ end
+
+ def latest_pipeline(ref = nil)
+ @latest_pipelines.fetch(ref) do |ref|
+ @latest_pipelines[ref] = latest_pipeline_for_project(ref, project)
+ end
+ end
+
+ def latest_pipeline_for_project(ref, pipeline_project)
+ pipeline_project.ci_pipelines.latest_pipeline_per_commit(id, ref)[id]
+ end
+
+ def set_latest_pipeline_for_ref(ref, pipeline)
+ @latest_pipelines[ref] = pipeline
+ end
+
+ def status(ref = nil)
+ latest_pipeline(ref)&.status
+ end
+end
diff --git a/app/models/ci/group.rb b/app/models/ci/group.rb
index f0c035635b9..c7c0ec61e62 100644
--- a/app/models/ci/group.rb
+++ b/app/models/ci/group.rb
@@ -24,9 +24,22 @@ module Ci
def status
strong_memoize(:status) do
+ status_struct.status
+ end
+ end
+
+ def success?
+ status.to_s == 'success'
+ end
+
+ def has_warnings?
+ status_struct.warnings?
+ end
+
+ def status_struct
+ strong_memoize(:status_struct) do
Gitlab::Ci::Status::Composite
.new(@jobs)
- .status
end
end
@@ -39,8 +52,13 @@ module Ci
end
end
- def self.fabricate(project, stage)
- stage.latest_statuses
+ # Construct a grouping of statuses for this stage.
+ # We allow the caller to pass in statuses for efficiency (avoiding N+1
+ # queries).
+ def self.fabricate(project, stage, statuses = nil)
+ statuses ||= stage.latest_statuses
+
+ statuses
.sort_by(&:sortable_name).group_by(&:group_name)
.map do |group_name, grouped_statuses|
self.new(project, stage, name: group_name, jobs: grouped_statuses)
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index c80d50ea131..f13be3b3c86 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -9,6 +9,7 @@ module Ci
include Sortable
include Artifactable
include FileStoreMounter
+ include EachBatch
extend Gitlab::Ci::Model
TEST_REPORT_FILE_TYPES = %w[junit].freeze
@@ -133,6 +134,12 @@ module Ci
scope :for_sha, ->(sha, project_id) { joins(job: :pipeline).where(ci_pipelines: { sha: sha, project_id: project_id }) }
scope :for_job_name, ->(name) { joins(:job).where(ci_builds: { name: name }) }
+ scope :with_job, -> do
+ if Feature.enabled?(:non_public_artifacts, type: :development)
+ joins(:job).includes(:job)
+ end
+ end
+
scope :with_file_types, -> (file_types) do
types = self.file_types.select { |file_type| file_types.include?(file_type) }.values
@@ -170,7 +177,8 @@ module Ci
end
scope :downloadable, -> { where(file_type: DOWNLOADABLE_TYPES) }
- scope :unlocked, -> { joins(job: :pipeline).merge(::Ci::Pipeline.unlocked).order(expire_at: :desc) }
+ scope :unlocked, -> { joins(job: :pipeline).merge(::Ci::Pipeline.unlocked) }
+ scope :order_expired_desc, -> { order(expire_at: :desc) }
scope :with_destroy_preloads, -> { includes(project: [:route, :statistics]) }
scope :scoped_project, -> { where('ci_job_artifacts.project_id = projects.id') }
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 5e5f51d776f..4a579892e3f 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -68,8 +68,8 @@ module Ci
has_many :variables, class_name: 'Ci::PipelineVariable'
has_many :deployments, through: :builds
has_many :environments, -> { distinct }, through: :deployments
- has_many :latest_builds, -> { latest }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Build'
- has_many :downloadable_artifacts, -> { not_expired.downloadable }, through: :latest_builds, source: :job_artifacts
+ has_many :latest_builds, -> { latest.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Build'
+ has_many :downloadable_artifacts, -> { not_expired.downloadable.with_job }, through: :latest_builds, source: :job_artifacts
has_many :messages, class_name: 'Ci::PipelineMessage', inverse_of: :pipeline
@@ -249,7 +249,7 @@ module Ci
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
pipeline.run_after_commit do
- ::Ci::Pipelines::CreateArtifactWorker.perform_async(pipeline.id)
+ ::Ci::PipelineArtifacts::CoverageReportWorker.perform_async(pipeline.id)
end
end
diff --git a/app/models/ci/ref.rb b/app/models/ci/ref.rb
index 6e9b8416c10..713a0bf9c45 100644
--- a/app/models/ci/ref.rb
+++ b/app/models/ci/ref.rb
@@ -33,6 +33,9 @@ module Ci
state :still_failing, value: 5
after_transition any => [:fixed, :success] do |ci_ref|
+ # Do not try to unlock if no artifacts are locked
+ next unless ci_ref.artifacts_locked?
+
ci_ref.run_after_commit do
Ci::PipelineSuccessUnlockArtifactsWorker.perform_async(ci_ref.last_finished_pipeline_id)
end
@@ -54,6 +57,10 @@ module Ci
Ci::Pipeline.last_finished_for_ref_id(self.id)&.id
end
+ def artifacts_locked?
+ self.pipelines.where(locked: :artifacts_locked).exists?
+ end
+
def update_status_by!(pipeline)
retry_lock(self) do
next unless last_finished_pipeline_id == pipeline.id
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
index d32fff14590..8560826928a 100644
--- a/app/models/clusters/applications/cert_manager.rb
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -65,7 +65,7 @@ module Clusters
end
def retry_command(command)
- "for i in $(seq 1 90); do #{command} && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
+ Gitlab::Kubernetes::PodCmd.retry_command(command, times: 90)
end
def post_delete_script
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index b1c3116d77c..7c131e031c1 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Knative < ApplicationRecord
- VERSION = '0.9.0'
+ VERSION = '0.10.0'
REPOSITORY = 'https://charts.gitlab.io'
METRICS_CONFIG = 'https://gitlab.com/gitlab-org/charts/knative/-/raw/v0.9.0/vendor/istio-metrics.yml'
FETCH_IP_ADDRESS_DELAY = 30.seconds
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 1e41b6f4f31..56acac53e0b 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.23.0'
+ VERSION = '0.24.0'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 84de5828491..e3dcd5b0d07 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -247,7 +247,7 @@ module Clusters
def prevent_modification
return if provided_by_user?
- if api_url_changed? || token_changed? || ca_pem_changed?
+ if api_url_changed? || attribute_changed?(:token) || ca_pem_changed?
errors.add(:base, _('Cannot modify managed Kubernetes cluster'))
return false
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 80dd02981c1..edce9ad293e 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -37,7 +37,7 @@ class Commit
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :full_title, pipeline: :single_line
- cache_markdown_field :description, pipeline: :commit_description
+ cache_markdown_field :description, pipeline: :commit_description, limit: 1.megabyte
class << self
def decorate(commits, container)
@@ -80,7 +80,7 @@ class Commit
def diff_hard_limit_files(project: nil)
if Feature.enabled?(:increased_diff_limits, project)
- 2000
+ 3000
else
1000
end
@@ -88,7 +88,7 @@ class Commit
def diff_hard_limit_lines(project: nil)
if Feature.enabled?(:increased_diff_limits, project)
- 75000
+ 100000
else
50000
end
@@ -148,7 +148,7 @@ class Commit
to: :with_pipeline
def with_pipeline
- @with_pipeline ||= CommitWithPipeline.new(self)
+ @with_pipeline ||= Ci::CommitWithPipeline.new(self)
end
def id
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index ee9c2501bfc..a399ffc32de 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -80,9 +80,9 @@ class CommitStatus < ApplicationRecord
merge(or_conditions)
end
- # We use `Enums::CommitStatus.failure_reasons` here so that EE can more easily
+ # We use `Enums::Ci::CommitStatus.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
- enum_with_nil failure_reason: Enums::CommitStatus.failure_reasons
+ enum_with_nil failure_reason: Enums::Ci::CommitStatus.failure_reasons
##
# We still create some CommitStatuses outside of CreatePipelineService.
@@ -159,6 +159,12 @@ class CommitStatus < ApplicationRecord
commit_status.failure_reason = CommitStatus.failure_reasons[failure_reason]
end
+ before_transition [:skipped, :manual] => :created do |commit_status, transition|
+ transition.args.first.try do |user|
+ commit_status.user = user
+ end
+ end
+
after_transition do |commit_status, transition|
next if transition.loopback?
next if commit_status.processed?
@@ -203,7 +209,7 @@ class CommitStatus < ApplicationRecord
def group_name
# 'rspec:linux: 1/10' => 'rspec:linux'
- common_name = name.to_s.gsub(%r{\d+[\s:\/\\]+\d+\s*}, '')
+ 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}, '')
diff --git a/app/models/commit_with_pipeline.rb b/app/models/commit_with_pipeline.rb
index f382ae8f55a..7f952fb77a0 100644
--- a/app/models/commit_with_pipeline.rb
+++ b/app/models/commit_with_pipeline.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CommitWithPipeline < SimpleDelegator
+class Ci::CommitWithPipeline < SimpleDelegator
include Presentable
def initialize(commit)
diff --git a/app/models/concerns/boards/listable.rb b/app/models/concerns/boards/listable.rb
new file mode 100644
index 00000000000..b7c0a8b3489
--- /dev/null
+++ b/app/models/concerns/boards/listable.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Boards
+ module Listable
+ extend ActiveSupport::Concern
+
+ included do
+ validates :label, :position, presence: true, if: :label?
+ validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :movable?
+
+ before_destroy :can_be_destroyed
+
+ scope :ordered, -> { order(:list_type, :position) }
+ scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
+ scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
+ end
+
+ class_methods do
+ def destroyable_types
+ [:label]
+ end
+
+ def movable_types
+ [:label]
+ end
+ end
+
+ def destroyable?
+ self.class.destroyable_types.include?(list_type&.to_sym)
+ end
+
+ def movable?
+ self.class.movable_types.include?(list_type&.to_sym)
+ end
+
+ def title
+ if label?
+ label.name
+ elsif backlog?
+ _('Open')
+ else
+ list_type.humanize
+ end
+ end
+
+ private
+
+ def can_be_destroyed
+ throw(:abort) unless destroyable? # rubocop:disable Cop/BanCatchThrow
+ end
+ end
+end
diff --git a/app/models/concerns/bulk_insert_safe.rb b/app/models/concerns/bulk_insert_safe.rb
index f9eb3fb875e..3748e77e933 100644
--- a/app/models/concerns/bulk_insert_safe.rb
+++ b/app/models/concerns/bulk_insert_safe.rb
@@ -53,9 +53,9 @@ module BulkInsertSafe
class_methods do
def set_callback(name, *args)
unless _bulk_insert_callback_allowed?(name, args)
- raise MethodNotAllowedError.new(
+ raise MethodNotAllowedError,
"Not allowed to call `set_callback(#{name}, #{args})` when model extends `BulkInsertSafe`." \
- "Callbacks that fire per each record being inserted do not work with bulk-inserts.")
+ "Callbacks that fire per each record being inserted do not work with bulk-inserts."
end
super
diff --git a/app/models/concerns/ci/artifactable.rb b/app/models/concerns/ci/artifactable.rb
index 24df86dbc3c..cbe7d3b6abb 100644
--- a/app/models/concerns/ci/artifactable.rb
+++ b/app/models/concerns/ci/artifactable.rb
@@ -18,7 +18,8 @@ module Ci
gzip: 3
}, _suffix: true
- scope :expired, -> (limit) { where('expire_at < ?', Time.current).limit(limit) }
+ scope :expired_before, -> (timestamp) { where(arel_table[:expire_at].lt(timestamp)) }
+ scope :expired, -> (limit) { expired_before(Time.current).limit(limit) }
end
def each_blob(&blk)
diff --git a/app/models/concerns/each_batch.rb b/app/models/concerns/each_batch.rb
index af5f4e30d06..a59f00d73ec 100644
--- a/app/models/concerns/each_batch.rb
+++ b/app/models/concerns/each_batch.rb
@@ -47,7 +47,7 @@ module EachBatch
# order_hint does not affect the search results. For example,
# `ORDER BY id ASC, updated_at ASC` means the same thing as `ORDER
# BY id ASC`.
- def each_batch(of: 1000, column: primary_key, order_hint: nil)
+ def each_batch(of: 1000, column: primary_key, order: :asc, order_hint: nil)
unless column
raise ArgumentError,
'the column: argument must be set to a column name to use for ordering rows'
@@ -55,7 +55,7 @@ module EachBatch
start = except(:select)
.select(column)
- .reorder(column => :asc)
+ .reorder(column => order)
start = start.order(order_hint) if order_hint
start = start.take
@@ -66,10 +66,12 @@ module EachBatch
arel_table = self.arel_table
1.step do |index|
+ start_cond = arel_table[column].gteq(start_id)
+ start_cond = arel_table[column].lteq(start_id) if order == :desc
stop = except(:select)
.select(column)
- .where(arel_table[column].gteq(start_id))
- .reorder(column => :asc)
+ .where(start_cond)
+ .reorder(column => order)
stop = stop.order(order_hint) if order_hint
stop = stop
@@ -77,12 +79,14 @@ module EachBatch
.limit(1)
.take
- relation = where(arel_table[column].gteq(start_id))
+ relation = where(start_cond)
if stop
stop_id = stop[column]
start_id = stop_id
- relation = relation.where(arel_table[column].lt(stop_id))
+ stop_cond = arel_table[column].lt(stop_id)
+ stop_cond = arel_table[column].gt(stop_id) if order == :desc
+ relation = relation.where(stop_cond)
end
# Any ORDER BYs are useless for this relation and can lead to less
diff --git a/app/models/concerns/enums/ci/commit_status.rb b/app/models/concerns/enums/ci/commit_status.rb
new file mode 100644
index 00000000000..48b4a402974
--- /dev/null
+++ b/app/models/concerns/enums/ci/commit_status.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+module Enums
+ module Ci
+ module CommitStatus
+ # Returns the Hash to use for creating the `failure_reason` enum for
+ # `CommitStatus`.
+ def self.failure_reasons
+ {
+ unknown_failure: nil,
+ script_failure: 1,
+ api_failure: 2,
+ stuck_or_timeout_failure: 3,
+ runner_system_failure: 4,
+ missing_dependency_failure: 5,
+ runner_unsupported: 6,
+ stale_schedule: 7,
+ job_execution_timeout: 8,
+ archived_failure: 9,
+ unmet_prerequisites: 10,
+ scheduler_failure: 11,
+ data_integrity_failure: 12,
+ forward_deployment_failure: 13,
+ insufficient_bridge_permissions: 1_001,
+ downstream_bridge_project_not_found: 1_002,
+ invalid_bridge_trigger: 1_003,
+ bridge_pipeline_is_child_pipeline: 1_006, # not used anymore, but cannot be deleted because of old data
+ downstream_pipeline_creation_failed: 1_007,
+ secrets_provider_not_found: 1_008,
+ reached_max_descendant_pipelines_depth: 1_009
+ }
+ end
+ end
+ end
+end
+
+Enums::Ci::CommitStatus.prepend_if_ee('EE::Enums::Ci::CommitStatus')
diff --git a/app/models/concerns/enums/commit_status.rb b/app/models/concerns/enums/commit_status.rb
deleted file mode 100644
index faeed7276ab..00000000000
--- a/app/models/concerns/enums/commit_status.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module Enums
- module CommitStatus
- # Returns the Hash to use for creating the `failure_reason` enum for
- # `CommitStatus`.
- def self.failure_reasons
- {
- unknown_failure: nil,
- script_failure: 1,
- api_failure: 2,
- stuck_or_timeout_failure: 3,
- runner_system_failure: 4,
- missing_dependency_failure: 5,
- runner_unsupported: 6,
- stale_schedule: 7,
- job_execution_timeout: 8,
- archived_failure: 9,
- unmet_prerequisites: 10,
- scheduler_failure: 11,
- data_integrity_failure: 12,
- forward_deployment_failure: 13,
- insufficient_bridge_permissions: 1_001,
- downstream_bridge_project_not_found: 1_002,
- invalid_bridge_trigger: 1_003,
- bridge_pipeline_is_child_pipeline: 1_006, # not used anymore, but cannot be deleted because of old data
- downstream_pipeline_creation_failed: 1_007,
- secrets_provider_not_found: 1_008,
- reached_max_descendant_pipelines_depth: 1_009
- }
- end
- end
-end
-
-Enums::CommitStatus.prepend_if_ee('EE::Enums::CommitStatus')
diff --git a/app/models/concerns/enums/vulnerability.rb b/app/models/concerns/enums/vulnerability.rb
new file mode 100644
index 00000000000..4b2e9e9e0b2
--- /dev/null
+++ b/app/models/concerns/enums/vulnerability.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Enums
+ module Vulnerability
+ CONFIDENCE_LEVELS = {
+ # undefined: 0, no longer applicable
+ ignore: 1,
+ unknown: 2,
+ experimental: 3,
+ low: 4,
+ medium: 5,
+ high: 6,
+ confirmed: 7
+ }.with_indifferent_access.freeze
+
+ REPORT_TYPES = {
+ sast: 0,
+ secret_detection: 4
+ }.with_indifferent_access.freeze
+
+ SEVERITY_LEVELS = {
+ # undefined: 0, no longer applicable
+ info: 1,
+ unknown: 2,
+ # experimental: 3, formerly used by confidence, no longer applicable
+ low: 4,
+ medium: 5,
+ high: 6,
+ critical: 7
+ }.with_indifferent_access.freeze
+
+ def self.confidence_levels
+ CONFIDENCE_LEVELS
+ end
+
+ def self.report_types
+ REPORT_TYPES
+ end
+
+ def self.severity_levels
+ SEVERITY_LEVELS
+ end
+ end
+end
+
+Enums::Vulnerability.prepend_if_ee('EE::Enums::Vulnerability')
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index c3a394c1ca5..83ff5b16efe 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -196,6 +196,10 @@ module Issuable
is_a?(Issue)
end
+ def supports_assignee?
+ false
+ end
+
def severity
return IssuableSeverity::DEFAULT unless supports_severity?
@@ -216,6 +220,10 @@ module Issuable
end
class_methods do
+ def participant_includes
+ [:assignees, :author, { notes: [:author, :award_emoji] }]
+ end
+
# Searches for records with a matching title.
#
# This method uses ILIKE on PostgreSQL.
@@ -344,12 +352,15 @@ module Issuable
#
# Returns an array of arel columns
def grouping_columns(sort)
+ sort = sort.to_s
grouping_columns = [arel_table[:id]]
if %w(milestone_due_desc milestone_due_asc milestone).include?(sort)
milestone_table = Milestone.arel_table
grouping_columns << milestone_table[:id]
grouping_columns << milestone_table[:due_date]
+ elsif %w(merged_at_desc merged_at_asc).include?(sort)
+ grouping_columns << MergeRequest::Metrics.arel_table[:merged_at]
end
grouping_columns
diff --git a/app/models/concerns/issue_available_features.rb b/app/models/concerns/issue_available_features.rb
index 886db133a94..a5ffa959174 100644
--- a/app/models/concerns/issue_available_features.rb
+++ b/app/models/concerns/issue_available_features.rb
@@ -9,7 +9,10 @@ module IssueAvailableFeatures
class_methods do
# EE only features are listed on EE::IssueAvailableFeatures
def available_features_for_issue_types
- {}.with_indifferent_access
+ {
+ assignee: %w(issue incident),
+ confidentiality: %(issue incident)
+ }.with_indifferent_access
end
end
diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb
index b1698bc2ee3..ccb334343ff 100644
--- a/app/models/concerns/milestoneable.rb
+++ b/app/models/concerns/milestoneable.rb
@@ -51,7 +51,7 @@ module Milestoneable
# Overridden on EE module
#
def supports_milestone?
- respond_to?(:milestone_id) && !incident?
+ respond_to?(:milestone_id)
end
end
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index 2dbe9360d42..f3cc68e4b85 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -19,6 +19,11 @@ module Noteable
def resolvable_types
%w(MergeRequest DesignManagement::Design)
end
+
+ # `Noteable` class names that support creating/forwarding individual notes.
+ def email_creatable_types
+ %w(Issue)
+ end
end
# The timestamp of the note (e.g. the :created_at or :updated_at attribute if provided via
@@ -55,6 +60,10 @@ module Noteable
supports_discussions? && self.class.replyable_types.include?(base_class_name)
end
+ def supports_creating_notes_by_email?
+ self.class.email_creatable_types.include?(base_class_name)
+ end
+
def supports_suggestion?
false
end
@@ -158,6 +167,18 @@ module Noteable
def after_note_destroyed(_note)
# no-op
end
+
+ # Email address that an authorized user can send/forward an email to be added directly
+ # to an issue or merge request.
+ # example: incoming+h5bp-html5-boilerplate-8-1234567890abcdef123456789-issue-34@localhost.com
+ def creatable_note_email_address(author)
+ return unless supports_creating_notes_by_email?
+
+ project_email = project.new_issuable_address(author, self.class.name.underscore)
+ return unless project_email
+
+ project_email.sub('@', "-#{iid}@")
+ end
end
Noteable.extend(Noteable::ClassMethods)
diff --git a/app/models/concerns/packages/debian/architecture.rb b/app/models/concerns/packages/debian/architecture.rb
new file mode 100644
index 00000000000..4aa633e0357
--- /dev/null
+++ b/app/models/concerns/packages/debian/architecture.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ module Architecture
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :distribution, class_name: "Packages::Debian::#{container_type.capitalize}Distribution", inverse_of: :architectures
+
+ validates :distribution,
+ presence: true
+
+ validates :name,
+ presence: true,
+ length: { maximum: 255 },
+ uniqueness: { scope: %i[distribution_id] },
+ format: { with: Gitlab::Regex.debian_architecture_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/distribution.rb b/app/models/concerns/packages/debian/distribution.rb
new file mode 100644
index 00000000000..285d293c9ee
--- /dev/null
+++ b/app/models/concerns/packages/debian/distribution.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ module Distribution
+ extend ActiveSupport::Concern
+
+ included do
+ include FileStoreMounter
+
+ def self.container_foreign_key
+ "#{container_type}_id".to_sym
+ end
+
+ alias_attribute :container, container_type
+ alias_attribute :container_id, "#{container_type}_id"
+
+ belongs_to container_type
+ belongs_to :creator, class_name: 'User'
+
+ has_many :architectures,
+ class_name: "Packages::Debian::#{container_type.capitalize}Architecture",
+ foreign_key: :distribution_id,
+ inverse_of: :distribution
+
+ validates :codename,
+ presence: true,
+ uniqueness: { scope: [container_foreign_key] },
+ format: { with: Gitlab::Regex.debian_distribution_regex }
+
+ validates :suite,
+ allow_nil: true,
+ format: { with: Gitlab::Regex.debian_distribution_regex }
+ validates :suite,
+ uniqueness: { scope: [container_foreign_key] },
+ if: :suite
+
+ validate :unique_codename_and_suite
+
+ validates :origin,
+ allow_nil: true,
+ format: { with: Gitlab::Regex.debian_distribution_regex }
+
+ validates :label,
+ allow_nil: true,
+ format: { with: Gitlab::Regex.debian_distribution_regex }
+
+ validates :version,
+ allow_nil: true,
+ format: { with: Gitlab::Regex.debian_version_regex }
+
+ # The Valid-Until field is a security measure to prevent malicious attackers to
+ # serve an outdated repository, with vulnerable packages
+ # (keeping in mind that most Debian repository are not using TLS but use GPG
+ # signatures instead).
+ # A minimum of 24 hours is simply to avoid generating indices too often
+ # (which generates load).
+ # Official Debian repositories are generated 4 times a day, and valid for 7 days.
+ # Full ref: https://wiki.debian.org/DebianRepository/Format#Date.2C_Valid-Until
+ validates :valid_time_duration_seconds,
+ allow_nil: true,
+ numericality: { greater_than_or_equal_to: 24.hours.to_i }
+
+ validates container_type, presence: true
+ validates :file_store, presence: true
+
+ validates :file_signature, absence: true
+ validates :signing_keys, absence: true
+
+ scope :with_container, ->(subject) { where(container_type => subject) }
+ scope :with_codename, ->(codename) { where(codename: codename) }
+ scope :with_suite, ->(suite) { where(suite: suite) }
+ scope :with_codename_or_suite, ->(codename_or_suite) { with_codename(codename_or_suite).or(with_suite(codename_or_suite)) }
+
+ attr_encrypted :signing_keys,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm',
+ encode: false,
+ encode_iv: false
+
+ mount_file_store_uploader Packages::Debian::DistributionReleaseFileUploader
+
+ def needs_update?
+ !file.exists? || time_duration_expired?
+ end
+
+ private
+
+ def time_duration_expired?
+ return false unless valid_time_duration_seconds.present?
+
+ updated_at + valid_time_duration_seconds.seconds + 6.hours < Time.current
+ end
+
+ def unique_codename_and_suite
+ errors.add(:codename, _('has already been taken as Suite')) if codename_exists_as_suite?
+ errors.add(:suite, _('has already been taken as Codename')) if suite_exists_as_codename?
+ end
+
+ def codename_exists_as_suite?
+ return false unless codename.present?
+
+ self.class.with_container(container).with_suite(codename).exists?
+ end
+
+ def suite_exists_as_codename?
+ return false unless suite.present?
+
+ self.class.with_container(container).with_codename(suite).exists?
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/repositories/can_housekeep_repository.rb b/app/models/concerns/repositories/can_housekeep_repository.rb
new file mode 100644
index 00000000000..2b79851a07c
--- /dev/null
+++ b/app/models/concerns/repositories/can_housekeep_repository.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Repositories
+ module CanHousekeepRepository
+ extend ActiveSupport::Concern
+
+ def pushes_since_gc
+ Gitlab::Redis::SharedState.with { |redis| redis.get(pushes_since_gc_redis_shared_state_key).to_i }
+ end
+
+ def increment_pushes_since_gc
+ Gitlab::Redis::SharedState.with { |redis| redis.incr(pushes_since_gc_redis_shared_state_key) }
+ end
+
+ def reset_pushes_since_gc
+ Gitlab::Redis::SharedState.with { |redis| redis.del(pushes_since_gc_redis_shared_state_key) }
+ end
+
+ private
+
+ def pushes_since_gc_redis_shared_state_key
+ "#{self.class.name.underscore.pluralize}/#{id}/pushes_since_gc"
+ end
+ end
+end
diff --git a/app/models/cycle_analytics/level_base.rb b/app/models/cycle_analytics/level_base.rb
deleted file mode 100644
index 901636a7263..00000000000
--- a/app/models/cycle_analytics/level_base.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-module CycleAnalytics
- module LevelBase
- STAGES = %i[issue plan code test review staging].freeze
-
- # This is a temporary adapter class which makes the new value stream (cycle analytics)
- # backend compatible with the old implementation.
- class StageAdapter
- def initialize(stage, options)
- @stage = stage
- @options = options
- end
-
- # rubocop: disable CodeReuse/Presenter
- def as_json(serializer: AnalyticsStageSerializer)
- presenter = Analytics::CycleAnalytics::StagePresenter.new(stage)
-
- serializer.new.represent(OpenStruct.new(
- title: presenter.title,
- description: presenter.description,
- legend: presenter.legend,
- name: stage.name,
- project_median: median,
- group_median: median
- ))
- end
- # rubocop: enable CodeReuse/Presenter
-
- def events
- data_collector.records_fetcher.serialized_records
- end
-
- def median
- data_collector.median.seconds
- end
-
- alias_method :project_median, :median
- alias_method :group_median, :median
-
- private
-
- attr_reader :stage, :options
-
- def data_collector
- @data_collector ||= Gitlab::Analytics::CycleAnalytics::DataCollector.new(stage: stage, params: options)
- end
- end
-
- def all_medians_by_stage
- STAGES.each_with_object({}) do |stage_name, medians_per_stage|
- medians_per_stage[stage_name] = self[stage_name].median
- end
- end
-
- def stats
- @stats ||= STAGES.map do |stage_name|
- self[stage_name].as_json
- end
- end
-
- def [](stage_name)
- if Feature.enabled?(:new_project_level_vsa_backend, resource_parent, default_enabled: true)
- StageAdapter.new(build_stage(stage_name), options)
- else
- Gitlab::CycleAnalytics::Stage[stage_name].new(options: options)
- end
- end
-
- def stage_params_by_name(name)
- Gitlab::Analytics::CycleAnalytics::DefaultStages.find_by_name!(name)
- end
- end
-end
diff --git a/app/models/cycle_analytics/project_level.rb b/app/models/cycle_analytics/project_level.rb
index 26cdcc0db4b..5bd07b3f6c3 100644
--- a/app/models/cycle_analytics/project_level.rb
+++ b/app/models/cycle_analytics/project_level.rb
@@ -2,7 +2,6 @@
module CycleAnalytics
class ProjectLevel
- include LevelBase
attr_reader :project, :options
def initialize(project, options:)
@@ -21,13 +20,29 @@ module CycleAnalytics
Gitlab::CycleAnalytics::Permissions.get(user: user, project: project)
end
+ def stats
+ @stats ||= default_stage_names.map do |stage_name|
+ self[stage_name].as_json
+ end
+ end
+
+ def [](stage_name)
+ CycleAnalytics::ProjectLevelStageAdapter.new(build_stage(stage_name), options)
+ end
+
+ private
+
def build_stage(stage_name)
stage_params = stage_params_by_name(stage_name).merge(project: project)
Analytics::CycleAnalytics::ProjectStage.new(stage_params)
end
- def resource_parent
- project
+ def stage_params_by_name(name)
+ Gitlab::Analytics::CycleAnalytics::DefaultStages.find_by_name!(name)
+ end
+
+ def default_stage_names
+ Gitlab::Analytics::CycleAnalytics::DefaultStages.symbolized_stage_names
end
end
end
diff --git a/app/models/cycle_analytics/project_level_stage_adapter.rb b/app/models/cycle_analytics/project_level_stage_adapter.rb
new file mode 100644
index 00000000000..dd4afa9b809
--- /dev/null
+++ b/app/models/cycle_analytics/project_level_stage_adapter.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# This adapter class makes the new value stream (cycle analytics) backend
+# compatible with the old value stream controller actions.
+module CycleAnalytics
+ class ProjectLevelStageAdapter
+ def initialize(stage, options)
+ @stage = stage
+ @options = options
+ end
+
+ # rubocop: disable CodeReuse/Presenter
+ def as_json(serializer: AnalyticsStageSerializer)
+ presenter = Analytics::CycleAnalytics::StagePresenter.new(stage)
+
+ serializer.new.represent(OpenStruct.new(
+ title: presenter.title,
+ description: presenter.description,
+ legend: presenter.legend,
+ name: stage.name,
+ project_median: median
+ ))
+ end
+ # rubocop: enable CodeReuse/Presenter
+
+ def events
+ data_collector.records_fetcher.serialized_records
+ end
+
+ def median
+ data_collector.median.seconds
+ end
+
+ alias_method :project_median, :median
+
+ private
+
+ attr_reader :stage, :options
+
+ def data_collector
+ @data_collector ||= Gitlab::Analytics::CycleAnalytics::DataCollector.new(stage: stage, params: options)
+ end
+ end
+end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index b93b714ec8b..6f40466394a 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -109,6 +109,23 @@ class Deployment < ApplicationRecord
Deployments::ExecuteHooksWorker.perform_async(id)
end
end
+
+ 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)
+ end
+ end
+ 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
end
enum status: {
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index 944a64f5419..c8a0773cc5b 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -111,6 +111,10 @@ class DiffNote < Note
super.merge(suggestions_filter_enabled: true)
end
+ def multiline?
+ position&.multiline?
+ end
+
private
def enqueue_diff_file_creation_job
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index a4cacab25ee..7dbc95f617a 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -16,7 +16,9 @@ class Experiment < ApplicationRecord
# Create or update the recorded experiment_user row for the user in this experiment.
def record_user_and_group(user, group_type, context = {})
- experiment_users.find_or_initialize_by(user: user).update!(group_type: group_type, context: context)
+ experiment_user = experiment_users.find_or_initialize_by(user: user)
+ merged_context = experiment_user.context.deep_merge(context.deep_stringify_keys)
+ experiment_user.update!(group_type: group_type, context: merged_context)
end
def record_conversion_event_for_user(user)
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index 995baf8565c..ca6857a14b6 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -127,3 +127,5 @@ class GpgKey < ApplicationRecord
end
end
end
+
+GpgKey.prepend_if_ee('EE::GpgKey')
diff --git a/app/models/group.rb b/app/models/group.rb
index 739135e82dd..903d0154969 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -75,6 +75,9 @@ 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
+ has_many :debian_distributions, class_name: 'Packages::Debian::GroupDistribution', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+
accepts_nested_attributes_for :variables, allow_destroy: true
validate :visibility_level_allowed_by_projects
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 253f4465cd9..5da9f67f6ef 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -434,6 +434,10 @@ class Issue < ApplicationRecord
moved_to || duplicated_to
end
+ def supports_assignee?
+ issue_type_supports?(:assignee)
+ end
+
private
def ensure_metrics
diff --git a/app/models/list.rb b/app/models/list.rb
index 1df565c83e6..49834af3dfb 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class List < ApplicationRecord
+ include Boards::Listable
include Importable
belongs_to :board
@@ -10,30 +11,13 @@ class List < ApplicationRecord
enum list_type: { backlog: 0, label: 1, closed: 2, assignee: 3, milestone: 4, iteration: 5 }
validates :board, :list_type, presence: true, unless: :importing?
- validates :label, :position, presence: true, if: :label?
validates :label_id, uniqueness: { scope: :board_id }, if: :label?
- validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :movable?
-
- before_destroy :can_be_destroyed
-
- scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
- scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
scope :preload_associated_models, -> { preload(:board, label: :priorities) }
- scope :ordered, -> { order(:list_type, :position) }
-
alias_method :preferences, :list_user_preferences
class << self
- def destroyable_types
- [:label]
- end
-
- def movable_types
- [:label]
- end
-
def preload_preferences_for_user(lists, user)
return unless user
@@ -60,18 +44,6 @@ class List < ApplicationRecord
preferences_for(user).update(preferences)
end
- def destroyable?
- self.class.destroyable_types.include?(list_type&.to_sym)
- end
-
- def movable?
- self.class.movable_types.include?(list_type&.to_sym)
- end
-
- def title
- label? ? label.name : list_type.humanize
- end
-
def collapsed?(user)
preferences = preferences_for(user)
@@ -95,12 +67,6 @@ class List < ApplicationRecord
end
end
end
-
- private
-
- def can_be_destroyed
- throw(:abort) unless destroyable? # rubocop:disable Cop/BanCatchThrow
- end
end
List.prepend_if_ee('::EE::List')
diff --git a/app/models/member.rb b/app/models/member.rb
index 687830f5267..2e79b50d6b7 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -13,6 +13,8 @@ class Member < ApplicationRecord
include FromUnion
include UpdateHighestRole
+ AVATAR_SIZE = 40
+
attr_accessor :raw_invite_token
belongs_to :created_by, class_name: "User"
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 2bbcdbbe5ce..c30f6dc81ee 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -62,7 +62,9 @@ class GroupMember < Member
end
def post_create_hook
- run_after_commit_or_now { notification_service.new_group_member(self) }
+ if send_welcome_email?
+ run_after_commit_or_now { notification_service.new_group_member(self) }
+ end
super
end
@@ -72,6 +74,10 @@ class GroupMember < Member
run_after_commit { notification_service.update_group_member(self) }
end
+ if saved_change_to_expires_at?
+ run_after_commit { notification_service.updated_group_member_expiration(self) }
+ end
+
super
end
@@ -87,6 +93,10 @@ class GroupMember < Member
super
end
+
+ def send_welcome_email?
+ true
+ end
end
GroupMember.prepend_if_ee('EE::GroupMember')
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 043f07cf9f3..64b8223a1f0 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -261,6 +261,19 @@ class MergeRequest < ApplicationRecord
scope :by_merge_commit_sha, -> (sha) do
where(merge_commit_sha: sha)
end
+ scope :by_squash_commit_sha, -> (sha) do
+ where(squash_commit_sha: sha)
+ end
+ scope :by_related_commit_sha, -> (sha) do
+ from_union(
+ [
+ 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
joins(:notes).where(notes: { commit_id: sha })
end
@@ -493,6 +506,10 @@ class MergeRequest < ApplicationRecord
work_in_progress?(title) ? title : "Draft: #{title}"
end
+ def self.participant_includes
+ [:reviewers, :award_emoji] + super
+ end
+
def committers
@committers ||= commits.committers
end
@@ -1639,18 +1656,6 @@ class MergeRequest < ApplicationRecord
!has_commits?
end
- def mergeable_with_quick_action?(current_user, autocomplete_precheck: false, last_diff_sha: nil)
- return false unless can_be_merged_by?(current_user)
-
- return true if autocomplete_precheck
-
- return false unless mergeable?(skip_ci_check: true)
- return false if actual_head_pipeline && !(actual_head_pipeline.success? || actual_head_pipeline.active?)
- return false if last_diff_sha != diff_head_sha
-
- true
- end
-
def pipeline_coverage_delta
if base_pipeline&.coverage && head_pipeline&.coverage
'%.2f' % (head_pipeline.coverage.to_f - base_pipeline.coverage.to_f)
@@ -1762,6 +1767,10 @@ class MergeRequest < ApplicationRecord
false
end
+ def supports_assignee?
+ true
+ end
+
private
def with_rebase_lock
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index c244150e7a3..aa4ddfede99 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -33,6 +33,7 @@ class Milestone < ApplicationRecord
scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) }
scope :reorder_by_due_date_asc, -> { reorder(Gitlab::Database.nulls_last_order('due_date', 'ASC')) }
scope :with_api_entity_associations, -> { preload(project: [:project_feature, :route, namespace: :route]) }
+ scope :order_by_dates_and_title, -> { order(due_date: :asc, start_date: :asc, title: :asc) }
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 238e8f70778..6f7b377ee52 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -28,7 +28,7 @@ class Namespace < ApplicationRecord
has_many :runner_namespaces, inverse_of: :namespace, class_name: 'Ci::RunnerNamespace'
has_many :runners, through: :runner_namespaces, source: :runner, class_name: 'Ci::Runner'
- has_many :namespace_onboarding_actions
+ has_one :onboarding_progress
# This should _not_ be `inverse_of: :namespace`, because that would also set
# `user.namespace` when this user creates a group with themselves as `owner`.
@@ -40,6 +40,7 @@ class Namespace < ApplicationRecord
has_one :chat_team, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :root_storage_statistics, class_name: 'Namespace::RootStorageStatistics'
has_one :aggregation_schedule, class_name: 'Namespace::AggregationSchedule'
+ has_one :package_setting_relation, inverse_of: :namespace, class_name: 'PackageSetting'
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
@@ -160,6 +161,10 @@ class Namespace < ApplicationRecord
end
end
+ def package_settings
+ package_setting_relation || build_package_setting_relation
+ end
+
def default_branch_protection
super || Gitlab::CurrentSettings.default_branch_protection
end
@@ -438,6 +443,10 @@ class Namespace < ApplicationRecord
end
end
+ def root?
+ !has_parent?
+ end
+
private
def all_projects_with_pages
diff --git a/app/models/namespace/package_setting.rb b/app/models/namespace/package_setting.rb
new file mode 100644
index 00000000000..a2064e020b3
--- /dev/null
+++ b/app/models/namespace/package_setting.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class Namespace::PackageSetting < ApplicationRecord
+ self.primary_key = :namespace_id
+ self.table_name = 'namespace_package_settings'
+
+ PackageSettingNotImplemented = Class.new(StandardError)
+
+ PACKAGES_WITH_SETTINGS = %w[maven].freeze
+
+ belongs_to :namespace, inverse_of: :package_setting_relation
+
+ validates :namespace, presence: true
+ validates :maven_duplicates_allowed, inclusion: { in: [true, false] }
+ validates :maven_duplicate_exception_regex, untrusted_regexp: true, length: { maximum: 255 }
+
+ class << self
+ def duplicates_allowed?(package)
+ return true unless package
+ raise PackageSettingNotImplemented unless PACKAGES_WITH_SETTINGS.include?(package.package_type)
+
+ duplicates_allowed = package.package_settings["#{package.package_type}_duplicates_allowed"]
+ regex = ::Gitlab::UntrustedRegexp.new("\\A#{package.package_settings["#{package.package_type}_duplicate_exception_regex"]}\\z")
+
+ duplicates_allowed || regex.match?(package.name)
+ end
+ end
+end
diff --git a/app/models/namespace/root_storage_statistics.rb b/app/models/namespace/root_storage_statistics.rb
index a3df82998c4..90aeee7a4f1 100644
--- a/app/models/namespace/root_storage_statistics.rb
+++ b/app/models/namespace/root_storage_statistics.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Namespace::RootStorageStatistics < ApplicationRecord
- SNIPPETS_SIZE_STAT_NAME = 'snippets_size'.freeze
+ SNIPPETS_SIZE_STAT_NAME = 'snippets_size'
STATISTICS_ATTRIBUTES = %W(
storage_size
repository_size
diff --git a/app/models/namespace_onboarding_action.rb b/app/models/namespace_onboarding_action.rb
deleted file mode 100644
index 43dd872673c..00000000000
--- a/app/models/namespace_onboarding_action.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class NamespaceOnboardingAction < ApplicationRecord
- belongs_to :namespace, optional: false
-
- validates :action, presence: true
-
- ACTIONS = {
- subscription_created: 1,
- git_write: 2,
- merge_request_created: 3,
- git_read: 4,
- user_added: 6
- }.freeze
-
- enum action: ACTIONS
-
- class << self
- def completed?(namespace, action)
- where(namespace: namespace, action: action).exists?
- end
-
- def create_action(namespace, action)
- NamespaceOnboardingAction.safe_find_or_create_by(namespace: namespace, action: action)
- end
- end
-end
diff --git a/app/models/onboarding_progress.rb b/app/models/onboarding_progress.rb
new file mode 100644
index 00000000000..419bbd595e9
--- /dev/null
+++ b/app/models/onboarding_progress.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+class OnboardingProgress < ApplicationRecord
+ belongs_to :namespace, optional: false
+
+ validate :namespace_is_root_namespace
+
+ ACTIONS = [
+ :git_pull,
+ :git_write,
+ :merge_request_created,
+ :pipeline_created,
+ :user_added,
+ :trial_started,
+ :subscription_created,
+ :required_mr_approvals_enabled,
+ :code_owners_enabled,
+ :scoped_label_created,
+ :security_scan_enabled,
+ :issue_auto_closed,
+ :repository_imported,
+ :repository_mirrored
+ ].freeze
+
+ class << self
+ def onboard(namespace)
+ return unless root_namespace?(namespace)
+
+ safe_find_or_create_by(namespace: namespace)
+ end
+
+ def register(namespace, action)
+ return unless root_namespace?(namespace) && ACTIONS.include?(action)
+
+ action_column = column_name(action)
+ onboarding_progress = find_by(namespace: namespace, action_column => nil)
+ onboarding_progress&.update!(action_column => Time.current)
+ end
+
+ def completed?(namespace, action)
+ return unless root_namespace?(namespace) && ACTIONS.include?(action)
+
+ action_column = column_name(action)
+ where(namespace: namespace).where.not(action_column => nil).exists?
+ end
+
+ private
+
+ def column_name(action)
+ :"#{action}_at"
+ end
+
+ def root_namespace?(namespace)
+ namespace && namespace.root?
+ end
+ end
+
+ private
+
+ def namespace_is_root_namespace
+ return unless namespace
+
+ errors.add(:namespace, _('must be a root namespace')) if namespace.has_parent?
+ end
+end
diff --git a/app/models/packages/conan/file_metadatum.rb b/app/models/packages/conan/file_metadatum.rb
index de54580e948..64ae5cd88a5 100644
--- a/app/models/packages/conan/file_metadatum.rb
+++ b/app/models/packages/conan/file_metadatum.rb
@@ -3,8 +3,8 @@
class Packages::Conan::FileMetadatum < ApplicationRecord
belongs_to :package_file, inverse_of: :conan_file_metadatum
- DEFAULT_PACKAGE_REVISION = '0'.freeze
- DEFAULT_RECIPE_REVISION = '0'.freeze
+ DEFAULT_PACKAGE_REVISION = '0'
+ DEFAULT_RECIPE_REVISION = '0'
validates :package_file, presence: true
diff --git a/app/models/packages/debian.rb b/app/models/packages/debian.rb
new file mode 100644
index 00000000000..f7f7f9f95e9
--- /dev/null
+++ b/app/models/packages/debian.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ def self.table_name_prefix
+ 'packages_debian_'
+ end
+ end
+end
diff --git a/app/models/packages/debian/file_metadatum.rb b/app/models/packages/debian/file_metadatum.rb
new file mode 100644
index 00000000000..7c9f4f5f3f1
--- /dev/null
+++ b/app/models/packages/debian/file_metadatum.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class Packages::Debian::FileMetadatum < ApplicationRecord
+ belongs_to :package_file, inverse_of: :debian_file_metadatum
+
+ validates :package_file, presence: true
+ validate :valid_debian_package_type
+
+ enum file_type: {
+ unknown: 1, source: 2, dsc: 3, deb: 4, udeb: 5, buildinfo: 6, changes: 7
+ }
+
+ validates :file_type, presence: true
+ validates :file_type, inclusion: { in: %w[unknown] }, if: -> { package_file&.package&.debian_incoming? }
+ validates :file_type,
+ inclusion: { in: %w[source dsc deb udeb buildinfo changes] },
+ if: -> { package_file&.package&.debian_package? }
+
+ validates :component,
+ presence: true,
+ format: { with: Gitlab::Regex.debian_component_regex },
+ if: :requires_component?
+ validates :component, absence: true, unless: :requires_component?
+
+ validates :architecture,
+ presence: true,
+ format: { with: Gitlab::Regex.debian_architecture_regex },
+ if: :requires_architecture?
+ validates :architecture, absence: true, unless: :requires_architecture?
+
+ validates :fields,
+ presence: true,
+ json_schema: { filename: "debian_fields" },
+ if: :requires_fields?
+ validates :fields, absence: true, unless: :requires_fields?
+
+ private
+
+ def valid_debian_package_type
+ return if package_file&.package&.debian?
+
+ errors.add(:package_file, _('Package type must be Debian'))
+ end
+
+ def requires_architecture?
+ deb? || udeb?
+ end
+
+ def requires_component?
+ source? || dsc? || requires_architecture? || buildinfo?
+ end
+
+ def requires_fields?
+ dsc? || requires_architecture? || buildinfo? || changes?
+ end
+end
diff --git a/app/models/packages/debian/group_architecture.rb b/app/models/packages/debian/group_architecture.rb
new file mode 100644
index 00000000000..570f6accd3c
--- /dev/null
+++ b/app/models/packages/debian/group_architecture.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::GroupArchitecture < ApplicationRecord
+ def self.container_type
+ :group
+ end
+
+ include Packages::Debian::Architecture
+end
diff --git a/app/models/packages/debian/group_distribution.rb b/app/models/packages/debian/group_distribution.rb
new file mode 100644
index 00000000000..eea7acacc96
--- /dev/null
+++ b/app/models/packages/debian/group_distribution.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::GroupDistribution < ApplicationRecord
+ def self.container_type
+ :group
+ end
+
+ include Packages::Debian::Distribution
+end
diff --git a/app/models/packages/debian/project_architecture.rb b/app/models/packages/debian/project_architecture.rb
new file mode 100644
index 00000000000..44a38dfaf44
--- /dev/null
+++ b/app/models/packages/debian/project_architecture.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::ProjectArchitecture < ApplicationRecord
+ def self.container_type
+ :project
+ end
+
+ include Packages::Debian::Architecture
+end
diff --git a/app/models/packages/debian/project_distribution.rb b/app/models/packages/debian/project_distribution.rb
new file mode 100644
index 00000000000..a73c12d172d
--- /dev/null
+++ b/app/models/packages/debian/project_distribution.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::ProjectDistribution < ApplicationRecord
+ def self.container_type
+ :project
+ end
+
+ include Packages::Debian::Distribution
+end
diff --git a/app/models/packages/dependency.rb b/app/models/packages/dependency.rb
index 51b80934827..a32c3c05bb3 100644
--- a/app/models/packages/dependency.rb
+++ b/app/models/packages/dependency.rb
@@ -6,7 +6,7 @@ class Packages::Dependency < ApplicationRecord
validates :name, uniqueness: { scope: :version_pattern }
- NAME_VERSION_PATTERN_TUPLE_MATCHING = '(name, version_pattern) = (?, ?)'.freeze
+ NAME_VERSION_PATTERN_TUPLE_MATCHING = '(name, version_pattern) = (?, ?)'
MAX_STRING_LENGTH = 255.freeze
MAX_CHUNKED_QUERIES_COUNT = 10.freeze
diff --git a/app/models/packages/event.rb b/app/models/packages/event.rb
index 13da82d16d3..98c9d5246db 100644
--- a/app/models/packages/event.rb
+++ b/app/models/packages/event.rb
@@ -6,6 +6,8 @@ class Packages::Event < ApplicationRecord
UNIQUE_EVENTS_ALLOWED = %i[push_package delete_package pull_package].freeze
EVENT_SCOPES = ::Packages::Package.package_types.merge(container: 1000, tag: 1001).freeze
+ EVENT_PREFIX = "i_package"
+
enum event_scope: EVENT_SCOPES
enum event_type: {
@@ -24,13 +26,6 @@ class Packages::Event < ApplicationRecord
enum originator_type: { user: 0, deploy_token: 1, guest: 2 }
- def self.allowed_event_name(event_scope, event_type, originator)
- return unless event_allowed?(event_type)
-
- # remove `package` from the event name to avoid issues with HLLRedisCounter class parsing
- "i_package_#{event_scope}_#{originator}_#{event_type.gsub(/_packages?/, "")}"
- end
-
# Remove some of the events, for now, so we don't hammer Redis too hard.
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/280770
def self.event_allowed?(event_type)
@@ -38,4 +33,23 @@ class Packages::Event < ApplicationRecord
false
end
+
+ # counter names for unique user tracking (for MAU)
+ def self.unique_counters_for(event_scope, event_type, originator_type)
+ return [] unless event_allowed?(event_type)
+ return [] if originator_type.to_s == 'guest'
+
+ ["#{EVENT_PREFIX}_#{event_scope}_#{originator_type}"]
+ end
+
+ # total counter names for tracking number of events
+ def self.counters_for(event_scope, event_type, originator_type)
+ return [] unless event_allowed?(event_type)
+
+ [
+ "#{EVENT_PREFIX}_#{event_type}",
+ "#{EVENT_PREFIX}_#{event_type}_by_#{originator_type}",
+ "#{EVENT_PREFIX}_#{event_scope}_#{event_type}"
+ ]
+ end
end
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 10c98f03804..2067a800ad5 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -112,6 +112,7 @@ class Packages::Package < ApplicationRecord
scope :order_project_name_desc, -> { joins(:project).reorder('projects.name DESC') }
scope :order_project_path, -> { joins(:project).reorder('projects.path ASC, id ASC') }
scope :order_project_path_desc, -> { joins(:project).reorder('projects.path DESC, id DESC') }
+ scope :order_by_package_file, -> { joins(:package_files).order('packages_package_files.created_at ASC') }
def self.for_projects(projects)
return none unless projects.any?
@@ -199,6 +200,12 @@ class Packages::Package < ApplicationRecord
debian? && !version.nil?
end
+ def package_settings
+ strong_memoize(:package_settings) do
+ project.namespace.package_settings
+ end
+ end
+
private
def composer_tag_version?
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index e8d1dd1e8c4..389edaea392 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -5,14 +5,17 @@ class Packages::PackageFile < ApplicationRecord
delegate :project, :project_id, to: :package
delegate :conan_file_type, to: :conan_file_metadatum
+ delegate :file_type, :architecture, :fields, to: :debian_file_metadatum, prefix: :debian
belongs_to :package
has_one :conan_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Conan::FileMetadatum'
has_many :package_file_build_infos, inverse_of: :package_file, class_name: 'Packages::PackageFileBuildInfo'
has_many :pipelines, through: :package_file_build_infos
+ has_one :debian_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Debian::FileMetadatum'
accepts_nested_attributes_for :conan_file_metadatum
+ accepts_nested_attributes_for :debian_file_metadatum
validates :package, presence: true
validates :file, presence: true
@@ -25,12 +28,18 @@ class Packages::PackageFile < ApplicationRecord
scope :with_file_name_like, ->(file_name) { where(arel_table[:file_name].matches(file_name)) }
scope :with_files_stored_locally, -> { where(file_store: ::Packages::PackageFileUploader::Store::LOCAL) }
scope :preload_conan_file_metadata, -> { preload(:conan_file_metadatum) }
+ scope :preload_debian_file_metadata, -> { preload(:debian_file_metadatum) }
scope :with_conan_file_type, ->(file_type) do
joins(:conan_file_metadatum)
.where(packages_conan_file_metadata: { conan_file_type: ::Packages::Conan::FileMetadatum.conan_file_types[file_type] })
end
+ scope :with_debian_file_type, ->(file_type) do
+ joins(:debian_file_metadatum)
+ .where(packages_debian_file_metadata: { debian_file_type: ::Packages::Debian::FileMetadatum.debian_file_types[file_type] })
+ end
+
scope :with_conan_package_reference, ->(conan_package_reference) do
joins(:conan_file_metadatum)
.where(packages_conan_file_metadata: { conan_package_reference: conan_package_reference })
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 4004ea9a662..4d60489e599 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -188,7 +188,7 @@ class PagesDomain < ApplicationRecord
def user_provided_key=(key)
self.key = key
- self.certificate_source = 'user_provided' if key_changed?
+ self.certificate_source = 'user_provided' if attribute_changed?(:key)
end
def user_provided_certificate
@@ -207,7 +207,7 @@ class PagesDomain < ApplicationRecord
def gitlab_provided_key=(key)
self.key = key
- self.certificate_source = 'gitlab_provided' if key_changed?
+ self.certificate_source = 'gitlab_provided' if attribute_changed?(:key)
end
def pages_virtual_domain
diff --git a/app/models/plan.rb b/app/models/plan.rb
index b4091e0a755..6a7f32a5d5f 100644
--- a/app/models/plan.rb
+++ b/app/models/plan.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Plan < ApplicationRecord
- DEFAULT = 'default'.freeze
+ DEFAULT = 'default'
has_one :limits, class_name: 'PlanLimits'
diff --git a/app/models/project.rb b/app/models/project.rb
index daa5605c2e0..ec790798806 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -34,6 +34,7 @@ class Project < ApplicationRecord
include FromUnion
include IgnorableColumns
include Integration
+ include Repositories::CanHousekeepRepository
include EachBatch
extend Gitlab::Cache::RequestCache
extend Gitlab::Utils::Override
@@ -146,7 +147,6 @@ class Project < ApplicationRecord
has_many :boards
# Project services
- has_one :alerts_service
has_one :campfire_service
has_one :datadog_service
has_one :discord_service
@@ -200,6 +200,8 @@ 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
+ 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
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -408,6 +410,9 @@ 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 :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
delegate :allow_merge_on_skipped_pipeline, :allow_merge_on_skipped_pipeline?,
:allow_merge_on_skipped_pipeline=, :has_confluence?, :allow_editing_commit_messages?,
@@ -831,6 +836,10 @@ class Project < ApplicationRecord
webide_pipelines.running_or_pending.for_user(user)
end
+ def latest_pipeline_locked
+ ci_keep_latest_artifact? ? :artifacts_locked : :unlocked
+ end
+
def autoclose_referenced_issues
return true if super.nil?
@@ -1331,19 +1340,11 @@ class Project < ApplicationRecord
end
def external_wiki
- if has_external_wiki.nil?
- cache_has_external_wiki
- end
+ cache_has_external_wiki if has_external_wiki.nil?
- if has_external_wiki
- @external_wiki ||= services.external_wikis.first
- else
- nil
- end
- end
+ return unless has_external_wiki?
- def cache_has_external_wiki
- update_column(:has_external_wiki, services.external_wikis.any?) if Gitlab::Database.read_write?
+ @external_wiki ||= services.external_wikis.first
end
def find_or_initialize_services
@@ -1355,9 +1356,9 @@ class Project < ApplicationRecord
end
def disabled_services
- return ['datadog'] unless Feature.enabled?(:datadog_ci_integration, self)
+ return %w(datadog alerts) unless Feature.enabled?(:datadog_ci_integration, self)
- []
+ %w(alerts)
end
def find_or_initialize_service(name)
@@ -1829,6 +1830,15 @@ class Project < ApplicationRecord
ensure_pages_metadatum.update!(pages_deployment: deployment)
end
+ def set_first_pages_deployment!(deployment)
+ ensure_pages_metadatum
+
+ # where().update_all to perform update in the single transaction with check for null
+ ProjectPagesMetadatum
+ .where(project_id: id, pages_deployment_id: nil)
+ .update_all(pages_deployment_id: deployment.id)
+ end
+
def write_repository_config(gl_full_path: full_path)
# We'd need to keep track of project full path otherwise directory tree
# created with hashed storage enabled cannot be usefully imported using
@@ -1980,6 +1990,7 @@ class Project < ApplicationRecord
.append(key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level))
.append(key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: repository_languages.map(&:name).join(',').downcase)
.append(key: 'CI_DEFAULT_BRANCH', value: default_branch)
+ .append(key: 'CI_PROJECT_CONFIG_PATH', value: ci_config_path_or_default)
end
def predefined_ci_server_variables
@@ -2113,18 +2124,6 @@ class Project < ApplicationRecord
(auto_devops || build_auto_devops)&.predefined_variables
end
- def pushes_since_gc
- Gitlab::Redis::SharedState.with { |redis| redis.get(pushes_since_gc_redis_shared_state_key).to_i }
- end
-
- def increment_pushes_since_gc
- Gitlab::Redis::SharedState.with { |redis| redis.incr(pushes_since_gc_redis_shared_state_key) }
- end
-
- def reset_pushes_since_gc
- Gitlab::Redis::SharedState.with { |redis| redis.del(pushes_since_gc_redis_shared_state_key) }
- end
-
def route_map_for(commit_sha)
@route_maps_by_commit ||= Hash.new do |h, sha|
h[sha] = begin
@@ -2430,10 +2429,6 @@ class Project < ApplicationRecord
protected_branches.limit(limit)
end
- def alerts_service_activated?
- alerts_service&.active?
- end
-
def self_monitoring?
Gitlab::CurrentSettings.self_monitoring_project_id == id
end
@@ -2486,16 +2481,12 @@ class Project < ApplicationRecord
end
def service_desk_custom_address
- return unless service_desk_custom_address_enabled?
+ return unless Gitlab::ServiceDeskEmail.enabled?
key = service_desk_setting&.project_key
return unless key.present?
- ::Gitlab::ServiceDeskEmail.address_for_key("#{full_path_slug}-#{key}")
- end
-
- def service_desk_custom_address_enabled?
- ::Gitlab::ServiceDeskEmail.enabled? && ::Feature.enabled?(:service_desk_custom_address, self, default_enabled: true)
+ Gitlab::ServiceDeskEmail.address_for_key("#{full_path_slug}-#{key}")
end
def root_namespace
@@ -2633,10 +2624,6 @@ class Project < ApplicationRecord
from && self != from
end
- def pushes_since_gc_redis_shared_state_key
- "projects/#{id}/pushes_since_gc"
- end
-
def update_project_statistics
stats = statistics || build_statistics
stats.update(namespace_id: namespace_id)
@@ -2699,6 +2686,10 @@ class Project < ApplicationRecord
objects.each_batch { |relation| out.concat(relation.pluck(:oid)) }
end
end
+
+ def cache_has_external_wiki
+ update_column(:has_external_wiki, services.external_wikis.any?) if Gitlab::Database.read_write?
+ end
end
Project.prepend_if_ee('EE::Project')
diff --git a/app/models/project_feature_usage.rb b/app/models/project_feature_usage.rb
index b167c2e371b..4f445758653 100644
--- a/app/models/project_feature_usage.rb
+++ b/app/models/project_feature_usage.rb
@@ -3,8 +3,8 @@
class ProjectFeatureUsage < ApplicationRecord
self.primary_key = :project_id
- JIRA_DVCS_CLOUD_FIELD = 'jira_dvcs_cloud_last_sync_at'.freeze
- JIRA_DVCS_SERVER_FIELD = 'jira_dvcs_server_last_sync_at'.freeze
+ JIRA_DVCS_CLOUD_FIELD = 'jira_dvcs_cloud_last_sync_at'
+ JIRA_DVCS_SERVER_FIELD = 'jira_dvcs_server_last_sync_at'
belongs_to :project
validates :project, presence: true
diff --git a/app/models/project_pages_metadatum.rb b/app/models/project_pages_metadatum.rb
index bd1919fe7ed..2bef0056732 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
+ include EachBatch
+
self.primary_key = :project_id
belongs_to :project, inverse_of: :pages_metadatum
@@ -8,4 +10,5 @@ class ProjectPagesMetadatum < ApplicationRecord
belongs_to :pages_deployment
scope :deployed, -> { where(deployed: true) }
+ scope :only_on_legacy_storage, -> { deployed.where(pages_deployment: nil) }
end
diff --git a/app/models/project_services/alerts_service.rb b/app/models/project_services/alerts_service.rb
index 5b7d149ace1..4afce0dfe95 100644
--- a/app/models/project_services/alerts_service.rb
+++ b/app/models/project_services/alerts_service.rb
@@ -1,54 +1,10 @@
# frozen_string_literal: true
-require 'securerandom'
-
+# 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
- has_one :data, class_name: 'AlertsServiceData', autosave: true,
- inverse_of: :service, foreign_key: :service_id
-
- attribute :token, :string
- delegate :token, :token=, :token_changed?, :token_was, to: :data
-
- validates :token, presence: true, if: :activated?
-
- before_validation :prevent_token_assignment
- before_validation :ensure_token, if: :activated?
-
- after_save :update_http_integration
-
- def url
- return if instance? || template?
-
- url_helpers.project_alerts_notify_url(project, format: :json)
- end
-
- def json_fields
- super + %w(token)
- end
-
- def editable?
- false
- end
-
- def show_active_box?
- false
- end
-
- def can_test?
- false
- end
-
- def title
- _('Alerts endpoint')
- end
-
- def description
- _('Authorize external services to send alerts to GitLab')
- end
-
- def detailed_description
- description
- end
+ before_save :prevent_save
def self.to_param
'alerts'
@@ -58,35 +14,15 @@ class AlertsService < Service
%w()
end
- def data
- super || build_data
- end
-
private
- def prevent_token_assignment
- self.token = token_was if token.present? && token_changed?
- end
-
- def ensure_token
- self.token = generate_token if token.blank?
- end
-
- def generate_token
- SecureRandom.hex
- end
-
- def url_helpers
- Gitlab::Routing.url_helpers
- end
-
- def update_http_integration
- return unless project_id && type == 'AlertsService'
+ 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')
- AlertManagement::SyncAlertServiceDataService # rubocop: disable CodeReuse/ServiceClass
- .new(self)
- .execute
+ # 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
-
-AlertsService.prepend_if_ee('EE::AlertsService')
diff --git a/app/models/project_services/alerts_service_data.rb b/app/models/project_services/alerts_service_data.rb
deleted file mode 100644
index 5a52ed83455..00000000000
--- a/app/models/project_services/alerts_service_data.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'securerandom'
-
-class AlertsServiceData < ApplicationRecord
- belongs_to :service, class_name: 'AlertsService'
-
- validates :service, presence: true
-
- attr_encrypted :token,
- mode: :per_attribute_iv,
- key: Settings.attr_encrypted_db_key_base_truncated,
- algorithm: 'aes-256-gcm'
-end
diff --git a/app/models/project_services/datadog_service.rb b/app/models/project_services/datadog_service.rb
index 543843ab1b0..3a742bfdcda 100644
--- a/app/models/project_services/datadog_service.rb
+++ b/app/models/project_services/datadog_service.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
class DatadogService < Service
- DEFAULT_SITE = 'datadoghq.com'.freeze
- URL_TEMPLATE = 'https://webhooks-http-intake.logs.%{datadog_site}/v1/input/'.freeze
- URL_TEMPLATE_API_KEYS = 'https://app.%{datadog_site}/account/settings#api'.freeze
- URL_API_KEYS_DOCS = "https://docs.#{DEFAULT_SITE}/account_management/api-app-keys/".freeze
+ DEFAULT_SITE = 'datadoghq.com'
+ URL_TEMPLATE = 'https://webhooks-http-intake.logs.%{datadog_site}/v1/input/'
+ URL_TEMPLATE_API_KEYS = 'https://app.%{datadog_site}/account/settings#api'
+ URL_API_KEYS_DOCS = "https://docs.#{DEFAULT_SITE}/account_management/api-app-keys/"
SUPPORTED_EVENTS = %w[
pipeline job
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 1f4abfc1aca..dafd3d095ec 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -157,8 +157,12 @@ class JiraService < IssueTrackerService
# support any events.
end
+ def find_issue(issue_key)
+ jira_request { client.Issue.find(issue_key) }
+ end
+
def close_issue(entity, external_issue)
- issue = jira_request { client.Issue.find(external_issue.iid) }
+ issue = find_issue(external_issue.iid)
return if issue.nil? || has_resolution?(issue) || !jira_issue_transition_id.present?
@@ -172,7 +176,7 @@ class JiraService < IssueTrackerService
# Depending on the Jira project's workflow, a comment during transition
# may or may not be allowed. Refresh the issue after transition and check
# if it is closed, so we don't have one comment for every commit.
- issue = jira_request { client.Issue.find(issue.key) } if transition_issue(issue)
+ issue = find_issue(issue.key) if transition_issue(issue)
add_issue_solved_comment(issue, commit_id, commit_url) if has_resolution?(issue)
end
@@ -181,7 +185,7 @@ class JiraService < IssueTrackerService
return s_("JiraService|Events for %{noteable_model_name} are disabled.") % { noteable_model_name: noteable.model_name.plural.humanize(capitalize: false) }
end
- jira_issue = jira_request { client.Issue.find(mentioned.id) }
+ jira_issue = find_issue(mentioned.id)
return unless jira_issue.present?
diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb
index 0fd85e3a5a9..f39d3947e5b 100644
--- a/app/models/project_services/mattermost_slash_commands_service.rb
+++ b/app/models/project_services/mattermost_slash_commands_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class MattermostSlashCommandsService < SlashCommandsService
- include TriggersHelper
+ include Ci::TriggersHelper
prop_accessor :token
diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb
index 01ded0495a7..548f3623504 100644
--- a/app/models/project_services/slack_slash_commands_service.rb
+++ b/app/models/project_services/slack_slash_commands_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class SlackSlashCommandsService < SlashCommandsService
- include TriggersHelper
+ include Ci::TriggersHelper
def title
'Slack slash commands'
diff --git a/app/models/protectable_dropdown.rb b/app/models/protectable_dropdown.rb
index 25e70ab406c..e1336be9528 100644
--- a/app/models/protectable_dropdown.rb
+++ b/app/models/protectable_dropdown.rb
@@ -12,6 +12,8 @@ class ProtectableDropdown
# Tags/branches which are yet to be individually protected
def protectable_ref_names
+ return [] if @project.empty_repo?
+
@protectable_ref_names ||= ref_names - non_wildcard_protected_ref_names
end
diff --git a/app/models/release.rb b/app/models/release.rb
index bebf91fb247..2b82fdc37f6 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -82,7 +82,7 @@ class Release < ApplicationRecord
end
def milestone_titles
- self.milestones.map {|m| m.title }.sort.join(", ")
+ self.milestones.order_by_dates_and_title.map {|m| m.title }.join(', ')
end
def to_hook_data(action)
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 6b8b34ce4d2..880970b72a8 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -308,7 +308,7 @@ class RemoteMirror < ApplicationRecord
end
def mirror_url_changed?
- url_changed? || credentials_changed?
+ url_changed? || attribute_changed?(:credentials)
end
def saved_change_to_mirror_url?
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 93f22dbe122..c19448332f8 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -24,10 +24,10 @@ class Repository
attr_accessor :full_path, :shard, :disk_path, :container, :repo_type
- delegate :ref_name_for_sha, to: :raw_repository
- delegate :bundle_to_disk, to: :raw_repository
delegate :lfs_enabled?, to: :container
+ delegate_missing_to :raw_repository
+
CreateTreeError = Class.new(StandardError)
AmbiguousRefError = Class.new(StandardError)
@@ -386,10 +386,6 @@ class Repository
raw_repository.expire_has_local_branches_cache
end
- def lookup_cache
- @lookup_cache ||= {}
- end
-
def expire_exists_cache
expire_method_caches(%i(exists?))
end
@@ -494,19 +490,12 @@ class Repository
expire_branches_cache if expire_cache
end
- def method_missing(msg, *args, &block)
- if msg == :lookup && !block_given?
- lookup_cache[msg] ||= {}
- lookup_cache[msg][args.join(":")] ||= raw_repository.__send__(msg, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
- else
- raw_repository.__send__(msg, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ def lookup(sha)
+ strong_memoize("lookup_#{sha}") do
+ raw_repository.lookup(sha)
end
end
- def respond_to_missing?(method, include_private = false)
- raw_repository.respond_to?(method, include_private) || super
- end
-
def blob_at(sha, path)
blob = Blob.decorate(raw_repository.blob_at(sha, path), container)
diff --git a/app/models/service.rb b/app/models/service.rb
index 57c099d6f04..e5626462dd3 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -19,7 +19,6 @@ class Service < ApplicationRecord
PROJECT_SPECIFIC_SERVICE_NAMES = %w[
jenkins
- alerts
].freeze
# Fake services to help with local development.
@@ -48,7 +47,6 @@ class Service < ApplicationRecord
after_commit :reset_updated_properties
after_commit :cache_project_has_external_issue_tracker
- after_commit :cache_project_has_external_wiki
belongs_to :project, inverse_of: :services
belongs_to :group, inverse_of: :services
@@ -469,12 +467,6 @@ class Service < ApplicationRecord
end
end
- def cache_project_has_external_wiki
- if project && !project.destroyed?
- project.cache_has_external_wiki
- end
- end
-
def valid_recipients?
activated? && !importing?
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 817f9d014eb..c4a7c5e25dc 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -20,6 +20,7 @@ class Snippet < ApplicationRecord
extend ::Gitlab::Utils::Override
MAX_FILE_COUNT = 10
+ MASTER_BRANCH = 'master'
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :description
@@ -82,6 +83,7 @@ class Snippet < ApplicationRecord
scope :inc_author, -> { includes(:author) }
scope :inc_relations_for_view, -> { includes(author: :status) }
scope :with_statistics, -> { joins(:statistics) }
+ scope :inc_projects_namespace_route, -> { includes(project: [:route, :namespace]) }
attr_mentionable :description
@@ -311,13 +313,27 @@ class Snippet < ApplicationRecord
override :default_branch
def default_branch
- super || 'master'
+ super || MASTER_BRANCH
end
def repository_storage
snippet_repository&.shard_name || self.class.pick_repository_storage
end
+ # Repositories are created by default with the `master` branch.
+ # This method changes the `HEAD` file to point to the existing
+ # default branch in case it's not master.
+ def change_head_to_default_branch
+ return unless repository.exists?
+ return if default_branch == MASTER_BRANCH
+ # All snippets must have at least 1 file. Therefore, if
+ # `HEAD` is empty is because it's pointing to the wrong
+ # default branch
+ return unless repository.empty? || list_files('HEAD').empty?
+
+ repository.raw_repository.write_ref('HEAD', "refs/heads/#{default_branch}")
+ end
+
def create_repository
return if repository_exists? && snippet_repository
diff --git a/app/models/snippet_repository.rb b/app/models/snippet_repository.rb
index fa25a6f8441..54dbc579d54 100644
--- a/app/models/snippet_repository.rb
+++ b/app/models/snippet_repository.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class SnippetRepository < ApplicationRecord
+ include EachBatch
include Shardable
DEFAULT_EMPTY_FILE_NAME = 'snippetfile'
diff --git a/app/models/snippet_repository_storage_move.rb b/app/models/snippet_repository_storage_move.rb
index a365569bfa8..bb157c08995 100644
--- a/app/models/snippet_repository_storage_move.rb
+++ b/app/models/snippet_repository_storage_move.rb
@@ -12,7 +12,11 @@ class SnippetRepositoryStorageMove < ApplicationRecord
override :schedule_repository_storage_update_worker
def schedule_repository_storage_update_worker
- # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/218991
+ SnippetUpdateRepositoryStorageWorker.perform_async(
+ snippet_id,
+ destination_storage_name,
+ id
+ )
end
private
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index 1b99f310e1a..efbbd86ae4a 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -27,6 +27,8 @@ module Terraform
validates :uuid, presence: true, uniqueness: true, length: { is: UUID_LENGTH },
format: { with: HEX_REGEXP, message: 'only allows hex characters' }
+ before_destroy :ensure_state_is_unlocked
+
default_value_for(:uuid, allows_nil: false) { SecureRandom.hex(UUID_LENGTH / 2) }
def latest_file
@@ -87,6 +89,13 @@ module Terraform
new_version.save!
end
+ def ensure_state_is_unlocked
+ return unless locked?
+
+ errors.add(:base, s_("Terraform|You cannot remove the State file because it's locked. Unlock the State file first before removing it."))
+ throw :abort # rubocop:disable Cop/BanCatchThrow
+ end
+
def parse_serial(file)
Gitlab::Json.parse(file)["serial"]
rescue JSON::ParserError
diff --git a/app/models/user.rb b/app/models/user.rb
index c735f20b92c..b4ec6064ff8 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -31,7 +31,7 @@ class User < ApplicationRecord
INSTANCE_ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
- BLOCKED_PENDING_APPROVAL_STATE = 'blocked_pending_approval'.freeze
+ BLOCKED_PENDING_APPROVAL_STATE = 'blocked_pending_approval'
add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) }
add_authentication_token_field :feed_token
@@ -1358,6 +1358,7 @@ class User < ApplicationRecord
def hook_attrs
{
+ id: id,
name: name,
username: username,
avatar_url: avatar_url(only_path: false),
@@ -1377,7 +1378,14 @@ class User < ApplicationRecord
def set_username_errors
namespace_path_errors = self.errors.delete(:"namespace.path")
- self.errors[:username].concat(namespace_path_errors) if namespace_path_errors
+
+ return unless namespace_path_errors&.any?
+
+ if namespace_path_errors.include?('has already been taken') && !User.exists?(username: username)
+ self.errors.add(:base, :username_exists_as_a_different_namespace)
+ else
+ self.errors[:username].concat(namespace_path_errors)
+ end
end
def username_changed_hook
@@ -1564,6 +1572,12 @@ class User < ApplicationRecord
end
end
+ def review_requested_open_merge_requests_count(force: false)
+ Rails.cache.fetch(['users', id, 'review_requested_open_merge_requests_count'], force: force, expires_in: 20.minutes) do
+ MergeRequestsFinder.new(self, reviewer_id: id, state: 'opened', non_archived: true).execute.count
+ end
+ end
+
def assigned_open_issues_count(force: false)
Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force, expires_in: 20.minutes) do
IssuesFinder.new(self, assignee_id: self.id, state: 'opened', non_archived: true).execute.count
@@ -1607,6 +1621,7 @@ class User < ApplicationRecord
def invalidate_merge_request_cache_counts
Rails.cache.delete(['users', id, 'assigned_open_merge_requests_count'])
+ Rails.cache.delete(['users', id, 'review_requested_open_merge_requests_count'])
end
def invalidate_todos_done_count
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index b49a7eb72dc..49b93ffaf66 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -8,8 +8,6 @@ class UserPreference < ApplicationRecord
# extra methods that aren't really needed here.
NOTES_FILTERS = { all_notes: 0, only_comments: 1, only_activity: 2 }.freeze
- ignore_column :feature_filter_type, remove_with: '13.8', remove_after: '2021-01-22'
-
belongs_to :user
scope :with_user, -> { joins(:user) }
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index e329a094319..11c10a61d18 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -3,6 +3,7 @@
class Wiki
extend ::Gitlab::Utils::Override
include HasRepository
+ include Repositories::CanHousekeepRepository
include Gitlab::Utils::StrongMemoize
include GlobalID::Identification
diff --git a/app/policies/analytics/instance_statistics/measurement_policy.rb b/app/policies/analytics/instance_statistics/measurement_policy.rb
new file mode 100644
index 00000000000..3d6a5a08ff6
--- /dev/null
+++ b/app/policies/analytics/instance_statistics/measurement_policy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Analytics
+ module InstanceStatistics
+ class MeasurementPolicy < BasePolicy
+ delegate { :global }
+ end
+ end
+end
diff --git a/app/policies/ci/build_policy.rb b/app/policies/ci/build_policy.rb
index 7e69e1fdd88..65f2a70672b 100644
--- a/app/policies/ci/build_policy.rb
+++ b/app/policies/ci/build_policy.rb
@@ -37,6 +37,10 @@ module Ci
@subject.archived?
end
+ condition(:artifacts_public, scope: :subject) do
+ @subject.artifacts_public?
+ end
+
condition(:terminal, scope: :subject) do
@subject.has_terminal?
end
@@ -57,6 +61,10 @@ module Ci
can?(:update_build, @subject.project)
end
+ condition(:project_developer) do
+ can?(:developer_access, @subject.project)
+ end
+
rule { project_read_build }.enable :read_build_trace
rule { debug_mode & ~project_update_build }.prevent :read_build_trace
@@ -94,6 +102,9 @@ module Ci
rule { ~can?(:build_service_proxy_enabled) }.policy do
prevent :create_build_service_proxy
end
+
+ rule { project_read_build }.enable :read_job_artifacts
+ rule { ~artifacts_public & ~project_developer }.prevent :read_job_artifacts
end
end
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index b5c1ec0181e..9c79a797a6a 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -100,6 +100,7 @@ class GlobalPolicy < BasePolicy
enable :update_custom_attribute
enable :approve_user
enable :reject_user
+ enable :read_instance_statistics_measurements
end
# We can't use `read_statistics` because the user may have different permissions for different projects
diff --git a/app/policies/group_member_policy.rb b/app/policies/group_member_policy.rb
index 78a2be7a9f8..09cac96e3a5 100644
--- a/app/policies/group_member_policy.rb
+++ b/app/policies/group_member_policy.rb
@@ -10,7 +10,11 @@ class GroupMemberPolicy < BasePolicy
with_score 0
condition(:is_target_user) { @user && @subject.user_id == @user.id }
- rule { anonymous }.prevent_all
+ rule { anonymous }.policy do
+ prevent :update_group_member
+ prevent :destroy_group_member
+ end
+
rule { last_owner }.policy do
prevent :update_group_member
prevent :destroy_group_member
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 7d0db222eaf..7dd88fcc1ff 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -66,7 +66,7 @@ class GroupPolicy < BasePolicy
with_scope :subject
condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
- rule { design_management_enabled }.policy do
+ rule { can?(:read_group) & design_management_enabled }.policy do
enable :read_design_activity
end
@@ -116,17 +116,20 @@ class GroupPolicy < BasePolicy
enable :delete_metrics_dashboard_annotation
enable :update_metrics_dashboard_annotation
enable :create_custom_emoji
+ enable :create_package_settings
end
rule { reporter }.policy do
enable :reporter_access
enable :read_container_image
+ enable :admin_board
enable :admin_label
enable :admin_list
enable :admin_issue
enable :read_metrics_dashboard_annotation
enable :read_prometheus
enable :read_package
+ enable :read_package_settings
end
rule { maintainer }.policy do
diff --git a/app/policies/namespace/package_setting_policy.rb b/app/policies/namespace/package_setting_policy.rb
new file mode 100644
index 00000000000..7fe388c633e
--- /dev/null
+++ b/app/policies/namespace/package_setting_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class Namespace::PackageSettingPolicy < BasePolicy
+ delegate { @subject.namespace }
+end
diff --git a/app/policies/namespace_policy.rb b/app/policies/namespace_policy.rb
index b1d680b4264..13eb4a13cac 100644
--- a/app/policies/namespace_policy.rb
+++ b/app/policies/namespace_policy.rb
@@ -14,6 +14,8 @@ class NamespacePolicy < BasePolicy
enable :read_namespace
enable :read_statistics
enable :create_jira_connect_subscription
+ enable :create_package_settings
+ enable :read_package_settings
end
rule { personal_project & ~can_create_personal_project }.prevent :create_projects
diff --git a/app/policies/packages/composer/metadatum_policy.rb b/app/policies/packages/composer/metadatum_policy.rb
new file mode 100644
index 00000000000..66bac31f48f
--- /dev/null
+++ b/app/policies/packages/composer/metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Composer
+ class MetadatumPolicy < BasePolicy
+ delegate { @subject.package }
+ end
+ end
+end
diff --git a/app/policies/packages/tag_policy.rb b/app/policies/packages/tag_policy.rb
new file mode 100644
index 00000000000..84bad30470a
--- /dev/null
+++ b/app/policies/packages/tag_policy.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module Packages
+ class TagPolicy < BasePolicy
+ delegate { @subject.package }
+ end
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 3b8c59c6bf8..03cb53f55be 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -135,6 +135,10 @@ class ProjectPolicy < BasePolicy
::Feature.enabled?(:build_service_proxy, @subject)
end
+ condition(:user_defined_variables_allowed) do
+ !@subject.restrict_user_defined_variables?
+ end
+
with_scope :subject
condition(:packages_disabled) { !@subject.packages_enabled }
@@ -236,6 +240,7 @@ class ProjectPolicy < BasePolicy
enable :read_commit_status
enable :read_build
enable :read_container_image
+ enable :read_deploy_board
enable :read_pipeline
enable :read_pipeline_schedule
enable :read_environment
@@ -615,6 +620,10 @@ class ProjectPolicy < BasePolicy
enable :admin_resource_access_tokens
end
+ rule { user_defined_variables_allowed | can?(:maintainer_access) }.policy do
+ enable :set_pipeline_variables
+ end
+
private
def user_is_user?
diff --git a/app/presenters/board_presenter.rb b/app/presenters/board_presenter.rb
new file mode 100644
index 00000000000..d7cecd44dd7
--- /dev/null
+++ b/app/presenters/board_presenter.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class BoardPresenter < Gitlab::View::Presenter::Delegated
+ presents :board
+end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 64461fa9193..ffa33dc9f15 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -93,7 +93,22 @@ module Ci
end
def refspec_for_persistent_ref
- "+#{persistent_ref_path}:#{persistent_ref_path}"
+ #
+ # 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
+ # 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
end
def persistent_ref_exist?
@@ -107,10 +122,6 @@ module Ci
pipeline.persistent_ref.exist?
end
- def persistent_ref_path
- pipeline.persistent_ref.path
- end
-
def git_depth_variable
strong_memoize(:git_depth_variable) do
variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }
diff --git a/app/presenters/packages/composer/packages_presenter.rb b/app/presenters/packages/composer/packages_presenter.rb
index cce006cbb1a..ed0e9d3b731 100644
--- a/app/presenters/packages/composer/packages_presenter.rb
+++ b/app/presenters/packages/composer/packages_presenter.rb
@@ -20,33 +20,17 @@ module Packages
end
def package_versions(packages = @packages)
- { 'packages' => { packages.first.name => package_versions_map(packages) } }
+ package_versions_index(packages).as_json
end
private
- def package_versions_map(packages)
- packages.each_with_object({}) do |package, map|
- map[package.version] = package_metadata(package)
- end
+ def package_versions_sha(packages = @packages)
+ package_versions_index(packages).sha
end
- def package_metadata(package)
- json = package.composer_metadatum.composer_json
-
- json.merge('dist' => package_dist(package), 'uid' => package.id, 'version' => package.version)
- end
-
- def package_dist(package)
- sha = package.composer_metadatum.target_sha
- archive_api_path = api_v4_projects_packages_composer_archives_package_name_path({ id: package.project_id, package_name: package.name, format: '.zip' }, true)
-
- {
- 'type' => 'zip',
- 'url' => expose_url(archive_api_path) + "?sha=#{sha}",
- 'reference' => sha,
- 'shasum' => ''
- }
+ def package_versions_index(packages)
+ ::Gitlab::Composer::VersionIndex.new(packages)
end
def providers_map
@@ -59,10 +43,6 @@ module Packages
map
end
- def package_versions_sha(packages)
- Digest::SHA256.hexdigest(package_versions(packages).to_json)
- end
-
def provider_sha
Digest::SHA256.hexdigest(provider.to_json)
end
diff --git a/app/presenters/packages/nuget/service_index_presenter.rb b/app/presenters/packages/nuget/service_index_presenter.rb
index ed00b36b362..b3cc912b811 100644
--- a/app/presenters/packages/nuget/service_index_presenter.rb
+++ b/app/presenters/packages/nuget/service_index_presenter.rb
@@ -19,10 +19,13 @@ module Packages
metadata: 'Get package metadata.'
}.freeze
- VERSION = '3.0.0'.freeze
+ VERSION = '3.0.0'
- def initialize(project)
- @project = project
+ PROJECT_LEVEL_SERVICES = %i[download publish].freeze
+ GROUP_LEVEL_SERVICES = %i[search metadata].freeze
+
+ def initialize(project_or_group)
+ @project_or_group = project_or_group
end
def version
@@ -30,16 +33,21 @@ module Packages
end
def resources
- [
- build_service(:download),
- build_service(:search),
- build_service(:publish),
- build_service(:metadata)
- ].flatten
+ available_services.map { |service| build_service(service) }
+ .flatten
end
private
+ def available_services
+ case scope
+ when :group
+ GROUP_LEVEL_SERVICES
+ when :project
+ (GROUP_LEVEL_SERVICES + PROJECT_LEVEL_SERVICES).flatten
+ end
+ end
+
def build_service(service_type)
url = build_service_url(service_type)
comment = SERVICE_COMMENTS[service_type]
@@ -50,36 +58,72 @@ module Packages
end
def build_service_url(service_type)
- base_path = api_v4_projects_packages_nuget_path(id: @project.id)
-
full_path = case service_type
when :download
- api_v4_projects_packages_nuget_download_package_name_package_version_package_filename_path(
- {
- id: @project.id,
- package_name: nil,
- package_version: nil,
- package_filename: nil
- },
- true
- )
+ download_service_url
when :search
- "#{base_path}/query"
+ search_service_url
when :metadata
- api_v4_projects_packages_nuget_metadata_package_name_package_version_path(
- {
- id: @project.id,
- package_name: nil,
- package_version: nil
- },
- true
- )
+ metadata_service_url
when :publish
- base_path
+ publish_service_url
end
expose_url(full_path)
end
+
+ def scope
+ return :project if @project_or_group.is_a?(::Project)
+ return :group if @project_or_group.is_a?(::Group)
+ end
+
+ def download_service_url
+ params = {
+ id: @project_or_group.id,
+ package_name: nil,
+ package_version: nil,
+ package_filename: nil
+ }
+
+ api_v4_projects_packages_nuget_download_package_name_package_version_package_filename_path(
+ params,
+ true
+ )
+ end
+
+ def metadata_service_url
+ params = {
+ id: @project_or_group.id,
+ package_name: nil,
+ package_version: nil
+ }
+
+ case scope
+ when :group
+ api_v4_groups___packages_nuget_metadata_package_name_package_version_path(
+ params,
+ true
+ )
+ when :project
+ api_v4_projects_packages_nuget_metadata_package_name_package_version_path(
+ params,
+ true
+ )
+ end
+ end
+
+ def search_service_url
+ case scope
+ when :group
+ api_v4_groups___packages_nuget_query_path(id: @project_or_group.id)
+ when :project
+ api_v4_projects_packages_nuget_query_path(id: @project_or_group.id)
+ end
+ end
+
+ def publish_service_url
+ api_v4_projects_packages_nuget_path(id: @project_or_group.id)
+ end
end
end
end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 917c416ce33..2432a6a0e4d 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -26,7 +26,7 @@ class BuildDetailsEntity < JobEntity
DeploymentClusterEntity.represent(build.deployment, options)
end
- expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do
+ expose :artifact, if: -> (*) { can?(current_user, :read_job_artifacts, build) } do
expose :download_path, if: -> (*) { build.locked_artifacts? || build.artifacts? } do |build|
download_project_job_artifacts_path(project, build)
end
diff --git a/app/serializers/diffs_metadata_entity.rb b/app/serializers/diffs_metadata_entity.rb
index 7b0de3bce4e..681e629244f 100644
--- a/app/serializers/diffs_metadata_entity.rb
+++ b/app/serializers/diffs_metadata_entity.rb
@@ -18,8 +18,30 @@ class DiffsMetadataEntity < DiffsEntity
options[:merge_request].can_be_merged_by?(request.current_user)
end
+ expose :project_path
+ expose :project_name
+
+ expose :username
+ expose :user_full_name
+
private
+ def project_path
+ request.project&.full_path
+ end
+
+ def project_name
+ request.project&.name
+ end
+
+ def username
+ request.current_user&.username
+ end
+
+ def user_full_name
+ request.current_user&.name
+ end
+
def presenter(merge_request)
@presenters ||= {}
@presenters[merge_request] ||= MergeRequestPresenter.new(merge_request, current_user: request.current_user) # rubocop: disable CodeReuse/Presenter
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index 8c6ad010d69..66ca2382901 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -19,6 +19,7 @@ class EnvironmentEntity < Grape::Entity
expose :name_without_type
expose :last_deployment, using: DeploymentEntity
expose :stop_action_available?, as: :has_stop_action
+ expose :rollout_status, if: -> (*) { can_read_deploy_board? }, using: RolloutStatusEntity
expose :upcoming_deployment, expose_nil: false do |environment, ops|
DeploymentEntity.represent(environment.upcoming_deployment,
@@ -104,6 +105,10 @@ class EnvironmentEntity < Grape::Entity
can?(current_user, :read_pod_logs, environment.project)
end
+ def can_read_deploy_board?
+ can?(current_user, :read_deploy_board, environment.project)
+ end
+
def cluster_platform_kubernetes?
deployment_platform && deployment_platform.is_a?(Clusters::Platforms::Kubernetes)
end
diff --git a/app/serializers/group_analytics_stage_entity.rb b/app/serializers/group_analytics_stage_entity.rb
deleted file mode 100644
index 81be20e7dd8..00000000000
--- a/app/serializers/group_analytics_stage_entity.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class GroupAnalyticsStageEntity < Grape::Entity
- include EntityDateHelper
-
- expose :title
- expose :name
- expose :legend
- expose :description
-
- expose :group_median, as: :value do |stage|
- # group_median returns a BatchLoader instance which we first have to unwrap by using to_f
- # we use to_f to make sure results below 1 are presented to the end-user
- stage.group_median.to_f.nonzero? ? distance_of_time_in_words(stage.group_median) : nil
- end
-end
diff --git a/app/serializers/group_analytics_stage_serializer.rb b/app/serializers/group_analytics_stage_serializer.rb
deleted file mode 100644
index ec448dea602..00000000000
--- a/app/serializers/group_analytics_stage_serializer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class GroupAnalyticsStageSerializer < BaseSerializer
- entity GroupAnalyticsStageEntity
-end
diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb
index 53c123c06fd..4b3d6f21d6d 100644
--- a/app/serializers/issuable_sidebar_basic_entity.rb
+++ b/app/serializers/issuable_sidebar_basic_entity.rb
@@ -103,6 +103,10 @@ class IssuableSidebarBasicEntity < Grape::Entity
issuable.project.emails_disabled?
end
+ expose :create_note_email do |issuable|
+ issuable.creatable_note_email_address(current_user)
+ end
+
expose :supports_time_tracking?, as: :supports_time_tracking
expose :supports_milestone?, as: :supports_milestone
expose :supports_severity?, as: :supports_severity
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 7c12e0956f3..647a73495f8 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -71,6 +71,10 @@ class IssueEntity < IssuableEntity
expose :archived_project_docs_path, if: -> (issue) { issue.project.archived? } do |issue|
help_page_path('user/project/settings/index.md', anchor: 'archiving-a-project')
end
+
+ expose :issue_email_participants do |issue|
+ issue.issue_email_participants.map { |x| { email: x.email } }
+ end
end
IssueEntity.prepend_if_ee('::EE::IssueEntity')
diff --git a/app/serializers/member_entity.rb b/app/serializers/member_entity.rb
new file mode 100644
index 00000000000..584ba4c62de
--- /dev/null
+++ b/app/serializers/member_entity.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+class MemberEntity < Grape::Entity
+ include RequestAwareEntity
+ include AvatarsHelper
+
+ expose :id
+ expose :created_at
+ expose :expires_at do |member|
+ member.expires_at&.to_time
+ end
+ expose :requested_at
+
+ expose :created_by, if: -> (member) { member.created_by.present? } do |member|
+ UserEntity.represent(member.created_by, only: [:name, :web_url])
+ end
+
+ expose :can_update do |member|
+ member.can_update?
+ end
+
+ expose :can_remove do |member|
+ member.can_remove?
+ end
+
+ expose :access_level do
+ expose :human_access, as: :string_value
+ expose :access_level, as: :integer_value
+ end
+
+ expose :source do |member|
+ GroupEntity.represent(member.source, only: [:id, :full_name, :web_url])
+ end
+
+ expose :valid_level_roles, as: :valid_roles
+
+ expose :user, if: -> (member) { member.user.present? }, using: MemberUserEntity
+
+ expose :invite, if: -> (member) { member.invite? } do
+ expose :email do |member|
+ member.invite_email
+ end
+
+ expose :avatar_url do |member|
+ avatar_icon_for_email(member.invite_email, Member::AVATAR_SIZE)
+ end
+
+ expose :can_resend do |member|
+ member.can_resend_invite?
+ end
+ end
+end
+
+MemberEntity.prepend_if_ee('EE::MemberEntity')
diff --git a/app/serializers/member_serializer.rb b/app/serializers/member_serializer.rb
new file mode 100644
index 00000000000..b34d7f30a58
--- /dev/null
+++ b/app/serializers/member_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class MemberSerializer < BaseSerializer
+ entity MemberEntity
+end
diff --git a/app/serializers/member_user_entity.rb b/app/serializers/member_user_entity.rb
new file mode 100644
index 00000000000..a022966c041
--- /dev/null
+++ b/app/serializers/member_user_entity.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class MemberUserEntity < UserEntity
+ unexpose :show_status
+ unexpose :path
+ unexpose :state
+ unexpose :status_tooltip_html
+
+ expose :avatar_url do |user|
+ user.avatar_url(size: Member::AVATAR_SIZE, only_path: false)
+ end
+
+ expose :blocked do |user|
+ user.blocked?
+ end
+
+ expose :two_factor_enabled do |user|
+ user.two_factor_enabled?
+ end
+
+ expose :status, if: -> (user) { user.status.present? } do
+ expose :emoji do |user|
+ user.status.emoji
+ end
+ end
+end
+
+MemberUserEntity.prepend_if_ee('EE::MemberUserEntity')
diff --git a/app/serializers/merge_request_poll_cached_widget_entity.rb b/app/serializers/merge_request_poll_cached_widget_entity.rb
index 080b6554de1..1db4ec37d4a 100644
--- a/app/serializers/merge_request_poll_cached_widget_entity.rb
+++ b/app/serializers/merge_request_poll_cached_widget_entity.rb
@@ -104,6 +104,16 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
presenter(merge_request).api_unapprove_path
end
+ expose :blob_path do
+ expose :head_path, if: -> (mr, _) { mr.source_branch_sha } do |merge_request|
+ project_blob_path(merge_request.project, merge_request.source_branch_sha)
+ end
+
+ expose :base_path, if: -> (mr, _) { mr.diff_base_sha } do |merge_request|
+ project_blob_path(merge_request.project, merge_request.diff_base_sha)
+ end
+ end
+
private
delegate :current_user, to: :request
diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb
index 9609a894e6d..4c34da3fc88 100644
--- a/app/serializers/merge_request_poll_widget_entity.rb
+++ b/app/serializers/merge_request_poll_widget_entity.rb
@@ -85,6 +85,12 @@ class MergeRequestPollWidgetEntity < Grape::Entity
end
end
+ expose :codequality_reports_path do |merge_request|
+ if merge_request.has_codequality_reports?
+ codequality_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
expose :terraform_reports_path do |merge_request|
if merge_request.has_terraform_reports?
terraform_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index afd4d5b9a2b..ca4e16bc5ff 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -115,16 +115,6 @@ class MergeRequestWidgetEntity < Grape::Entity
end
end
- expose :blob_path do
- expose :head_path, if: -> (mr, _) { mr.source_branch_sha } do |merge_request|
- project_blob_path(merge_request.project, merge_request.source_branch_sha)
- end
-
- expose :base_path, if: -> (mr, _) { mr.diff_base_sha } do |merge_request|
- project_blob_path(merge_request.project, merge_request.diff_base_sha)
- end
- end
-
expose :codeclimate, if: -> (mr, _) { head_pipeline_downloadable_path_for_report_type(:codequality) } do
expose :head_path do |merge_request|
head_pipeline_downloadable_path_for_report_type(:codequality)
diff --git a/app/serializers/merge_requests/pipeline_entity.rb b/app/serializers/merge_requests/pipeline_entity.rb
index 97d7620154e..8b684d4641b 100644
--- a/app/serializers/merge_requests/pipeline_entity.rb
+++ b/app/serializers/merge_requests/pipeline_entity.rb
@@ -21,6 +21,16 @@ class MergeRequests::PipelineEntity < Grape::Entity
pipeline.present.name
end
+ expose :artifacts do |pipeline, options|
+ rel = pipeline.downloadable_artifacts
+
+ if Feature.enabled?(:non_public_artifacts, type: :development)
+ rel = rel.select { |artifact| can?(request.current_user, :read_job_artifacts, artifact.job) }
+ end
+
+ BuildArtifactEntity.represent(rel, options)
+ end
+
expose :detailed_status, as: :status, with: DetailedStatusEntity do |pipeline|
pipeline.detailed_status(request.current_user)
end
diff --git a/app/serializers/pipeline_details_entity.rb b/app/serializers/pipeline_details_entity.rb
index 50efa9ea15d..e53fa7873ac 100644
--- a/app/serializers/pipeline_details_entity.rb
+++ b/app/serializers/pipeline_details_entity.rb
@@ -11,6 +11,10 @@ class PipelineDetailsEntity < PipelineEntity
expose :artifacts do |pipeline, options|
rel = pipeline.downloadable_artifacts
+ if Feature.enabled?(:non_public_artifacts, type: :development)
+ rel = rel.select { |artifact| can?(request.current_user, :read_job_artifacts, artifact.job) }
+ end
+
BuildArtifactEntity.represent(rel, options)
end
expose :manual_actions, using: BuildActionEntity
diff --git a/app/services/alert_management/http_integrations/create_service.rb b/app/services/alert_management/http_integrations/create_service.rb
index 576e38c23aa..e7f1084ce5c 100644
--- a/app/services/alert_management/http_integrations/create_service.rb
+++ b/app/services/alert_management/http_integrations/create_service.rb
@@ -9,14 +9,14 @@ module AlertManagement
def initialize(project, current_user, params)
@project = project
@current_user = current_user
- @params = params
+ @params = params.with_indifferent_access
end
def execute
return error_no_permissions unless allowed?
return error_multiple_integrations unless creation_allowed?
- integration = project.alert_management_http_integrations.create(params)
+ integration = project.alert_management_http_integrations.create(permitted_params)
return error_in_create(integration) unless integration.valid?
success(integration)
@@ -34,6 +34,15 @@ module AlertManagement
project.alert_management_http_integrations.empty?
end
+ def permitted_params
+ params.slice(*permitted_params_keys)
+ end
+
+ # overriden in EE
+ def permitted_params_keys
+ %i[name active]
+ end
+
def error(message)
ServiceResponse.error(message: message)
end
diff --git a/app/services/alert_management/sync_alert_service_data_service.rb b/app/services/alert_management/sync_alert_service_data_service.rb
deleted file mode 100644
index 1ba197065c5..00000000000
--- a/app/services/alert_management/sync_alert_service_data_service.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-module AlertManagement
- class SyncAlertServiceDataService
- # @param alert_service [AlertsService]
- def initialize(alert_service)
- @alert_service = alert_service
- end
-
- def execute
- http_integration = find_http_integration
-
- result = if http_integration
- update_integration_data(http_integration)
- else
- create_integration
- end
-
- result ? ServiceResponse.success : ServiceResponse.error(message: 'Update failed')
- end
-
- private
-
- attr_reader :alert_service
-
- def find_http_integration
- AlertManagement::HttpIntegrationsFinder.new(
- alert_service.project,
- endpoint_identifier: ::AlertManagement::HttpIntegration::LEGACY_IDENTIFIER
- )
- .execute
- .first
- end
-
- def create_integration
- new_integration = AlertManagement::HttpIntegration.create(
- project_id: alert_service.project_id,
- name: 'HTTP endpoint',
- endpoint_identifier: AlertManagement::HttpIntegration::LEGACY_IDENTIFIER,
- active: alert_service.active,
- encrypted_token: alert_service.data.encrypted_token,
- encrypted_token_iv: alert_service.data.encrypted_token_iv
- )
-
- new_integration.persisted?
- end
-
- def update_integration_data(http_integration)
- http_integration.update(
- active: alert_service.active,
- encrypted_token: alert_service.data.encrypted_token,
- encrypted_token_iv: alert_service.data.encrypted_token_iv
- )
- end
- end
-end
diff --git a/app/services/boards/base_items_list_service.rb b/app/services/boards/base_items_list_service.rb
new file mode 100644
index 00000000000..851120ef597
--- /dev/null
+++ b/app/services/boards/base_items_list_service.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+module Boards
+ class BaseItemsListService < Boards::BaseService
+ include Gitlab::Utils::StrongMemoize
+ include ActiveRecord::ConnectionAdapters::Quoting
+
+ def execute
+ return items.order_closed_date_desc if list&.closed?
+
+ ordered_items
+ end
+
+ private
+
+ def ordered_items
+ raise NotImplementedError
+ end
+
+ def finder
+ raise NotImplementedError
+ end
+
+ def board
+ raise NotImplementedError
+ end
+
+ def item_model
+ raise NotImplementedError
+ end
+
+ # We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query.
+ # rubocop: disable CodeReuse/ActiveRecord
+ def items
+ strong_memoize(:items) do
+ filter(finder.execute).reorder(nil)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def filter(items)
+ # when grouping board issues by epics (used in board swimlanes)
+ # we need to get all issues in the board
+ # TODO: ignore hidden columns -
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/233870
+ return items if params[:all_lists]
+
+ items = without_board_labels(items) unless list&.movable? || list&.closed?
+ items = with_list_label(items) if list&.label?
+ items
+ end
+
+ def list
+ return unless params.key?(:id)
+
+ strong_memoize(:list) do
+ id = params[:id]
+
+ if board.lists.loaded?
+ board.lists.find { |l| l.id == id }
+ else
+ board.lists.find(id)
+ end
+ end
+ end
+
+ def filter_params
+ set_parent
+ set_state
+ set_attempt_search_optimizations
+
+ params
+ end
+
+ def set_parent
+ if parent.is_a?(Group)
+ params[:group_id] = parent.id
+ else
+ params[:project_id] = parent.id
+ end
+ end
+
+ def set_state
+ return if params[:all_lists]
+
+ params[:state] = list && list.closed? ? 'closed' : 'opened'
+ end
+
+ def set_attempt_search_optimizations
+ return unless params[:search].present?
+
+ if board.group_board?
+ params[:attempt_group_search_optimizations] = true
+ else
+ params[:attempt_project_search_optimizations] = true
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def board_label_ids
+ @board_label_ids ||= board.lists.movable.pluck(:label_id)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def without_board_labels(items)
+ return items unless board_label_ids.any?
+
+ items.where.not('EXISTS (?)', label_links(board_label_ids).limit(1))
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def label_links(label_ids)
+ LabelLink
+ .where('label_links.target_type = ?', item_model)
+ .where(item_model.arel_table[:id].eq(LabelLink.arel_table[:target_id]).to_sql)
+ .where(label_id: label_ids)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def with_list_label(items)
+ items.where('EXISTS (?)', label_links(list.label_id).limit(1))
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb
index ab9d11abe98..27d59e052c7 100644
--- a/app/services/boards/issues/list_service.rb
+++ b/app/services/boards/issues/list_service.rb
@@ -2,26 +2,20 @@
module Boards
module Issues
- class ListService < Boards::BaseService
+ class ListService < Boards::BaseItemsListService
include Gitlab::Utils::StrongMemoize
def self.valid_params
IssuesFinder.valid_params
end
- def execute
- return fetch_issues.order_closed_date_desc if list&.closed?
-
- fetch_issues.order_by_position_and_priority(with_cte: params[:search].present?)
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def metadata
issues = Issue.arel_table
keys = metadata_fields.keys
# TODO: eliminate need for SQL literal fragment
columns = Arel.sql(metadata_fields.values_at(*keys).join(', '))
- results = Issue.where(id: fetch_issues.select(issues[:id])).pluck(columns)
+ results = Issue.where(id: items.select(issues[:id])).pluck(columns)
Hash[keys.zip(results.flatten)]
end
@@ -29,74 +23,28 @@ module Boards
private
- def metadata_fields
- { size: 'COUNT(*)' }
- end
-
- # We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query.
- # rubocop: disable CodeReuse/ActiveRecord
- def fetch_issues
- strong_memoize(:fetch_issues) do
- issues = IssuesFinder.new(current_user, filter_params).execute
-
- filter(issues).reorder(nil)
- end
+ def ordered_items
+ items.order_by_position_and_priority(with_cte: params[:search].present?)
end
- # rubocop: enable CodeReuse/ActiveRecord
- def filter(issues)
- # when grouping board issues by epics (used in board swimlanes)
- # we need to get all issues in the board
- # TODO: ignore hidden columns -
- # https://gitlab.com/gitlab-org/gitlab/-/issues/233870
- return issues if params[:all_lists]
-
- issues = without_board_labels(issues) unless list&.movable? || list&.closed?
- issues = with_list_label(issues) if list&.label?
- issues
+ def finder
+ IssuesFinder.new(current_user, filter_params)
end
def board
@board ||= parent.boards.find(params[:board_id])
end
- def list
- return unless params.key?(:id)
-
- strong_memoize(:list) do
- id = params[:id]
-
- if board.lists.loaded?
- board.lists.find { |l| l.id == id }
- else
- board.lists.find(id)
- end
- end
+ def metadata_fields
+ { size: 'COUNT(*)' }
end
def filter_params
- set_parent
- set_state
set_scope
set_non_archived
- set_attempt_search_optimizations
set_issue_types
- params
- end
-
- def set_parent
- if parent.is_a?(Group)
- params[:group_id] = parent.id
- else
- params[:project_id] = parent.id
- end
- end
-
- def set_state
- return if params[:all_lists]
-
- params[:state] = list && list.closed? ? 'closed' : 'opened'
+ super
end
def set_scope
@@ -107,49 +55,12 @@ module Boards
params[:non_archived] = parent.is_a?(Group)
end
- def set_attempt_search_optimizations
- return unless params[:search].present?
-
- if board.group_board?
- params[:attempt_group_search_optimizations] = true
- else
- params[:attempt_project_search_optimizations] = true
- end
- end
-
def set_issue_types
params[:issue_types] = Issue::TYPES_FOR_LIST
end
- # rubocop: disable CodeReuse/ActiveRecord
- def board_label_ids
- @board_label_ids ||= board.lists.movable.pluck(:label_id)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- def without_board_labels(issues)
- return issues unless board_label_ids.any?
-
- issues.where.not('EXISTS (?)', issues_label_links.limit(1))
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- def issues_label_links
- LabelLink.where("label_links.target_type = 'Issue' AND label_links.target_id = issues.id").where(label_id: board_label_ids)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- def with_list_label(issues)
- issues.where('EXISTS (?)', LabelLink.where("label_links.target_type = 'Issue' AND label_links.target_id = issues.id")
- .where("label_links.label_id = ?", list.label_id).limit(1))
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def board_group
- board.group_board? ? parent : parent.group
+ def item_model
+ Issue
end
end
end
diff --git a/app/services/bulk_create_integration_service.rb b/app/services/bulk_create_integration_service.rb
index 61c5565db60..df78c3645c7 100644
--- a/app/services/bulk_create_integration_service.rb
+++ b/app/services/bulk_create_integration_service.rb
@@ -38,10 +38,6 @@ class BulkCreateIntegrationService
if integration.external_issue_tracker?
Project.where(id: batch.select(:id)).update_all(has_external_issue_tracker: true)
end
-
- if integration.external_wiki?
- Project.where(id: batch.select(:id)).update_all(has_external_wiki: true)
- end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/ci/create_downstream_pipeline_service.rb b/app/services/ci/create_downstream_pipeline_service.rb
index 86d0cf079fc..629d85b041f 100644
--- a/app/services/ci/create_downstream_pipeline_service.rb
+++ b/app/services/ci/create_downstream_pipeline_service.rb
@@ -33,9 +33,7 @@ module Ci
pipeline_params.fetch(:target_revision))
downstream_pipeline = service.execute(
- pipeline_params.fetch(:source), **pipeline_params[:execute_params]) do |pipeline|
- pipeline.variables.build(@bridge.downstream_variables)
- end
+ pipeline_params.fetch(:source), **pipeline_params[:execute_params])
downstream_pipeline.tap do |pipeline|
update_bridge_status!(@bridge, pipeline)
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index dbe81521cfc..d3001e54288 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -27,6 +27,7 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Limit::JobActivity,
Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines,
Gitlab::Ci::Pipeline::Chain::Metrics,
+ Gitlab::Ci::Pipeline::Chain::TemplateUsage,
Gitlab::Ci::Pipeline::Chain::Pipeline::Process].freeze
# Create a new pipeline in the specified project.
@@ -81,7 +82,11 @@ module Ci
.new(pipeline, command, SEQUENCE)
.build!
- schedule_head_pipeline_update if pipeline.persisted?
+ if pipeline.persisted?
+ schedule_head_pipeline_update
+ record_conversion_event
+ create_namespace_onboarding_action
+ end
# If pipeline is not persisted, try to recover IID
pipeline.reset_project_iid unless pipeline.persisted?
@@ -116,6 +121,15 @@ module Ci
end
end
+ 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
+ Namespaces::OnboardingPipelineCreatedWorker.perform_async(project.namespace_id)
+ end
+
def extra_options(content: nil, dry_run: false)
{ content: content, dry_run: dry_run }
end
diff --git a/app/services/ci/create_web_ide_terminal_service.rb b/app/services/ci/create_web_ide_terminal_service.rb
index a78281aed16..785d82094b9 100644
--- a/app/services/ci/create_web_ide_terminal_service.rb
+++ b/app/services/ci/create_web_ide_terminal_service.rb
@@ -6,7 +6,7 @@ module Ci
TerminalCreationError = Class.new(StandardError)
- TERMINAL_NAME = 'terminal'.freeze
+ TERMINAL_NAME = 'terminal'
attr_reader :terminal
diff --git a/app/services/ci/destroy_expired_job_artifacts_service.rb b/app/services/ci/destroy_expired_job_artifacts_service.rb
index 6e7caba8545..7d8a3c17abe 100644
--- a/app/services/ci/destroy_expired_job_artifacts_service.rb
+++ b/app/services/ci/destroy_expired_job_artifacts_service.rb
@@ -12,6 +12,10 @@ module Ci
EXCLUSIVE_LOCK_KEY = 'expired_job_artifacts:destroy:lock'
LOCK_TIMEOUT = 6.minutes
+ def initialize
+ @removed_artifacts_count = 0
+ end
+
##
# Destroy expired job artifacts on GitLab instance
#
@@ -20,40 +24,22 @@ module Ci
# which is scheduled every 7 minutes.
def execute
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
- loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
- destroy_artifacts_batch
- end
+ destroy_job_artifacts_with_slow_iteration(Time.current)
end
- end
-
- private
- def destroy_artifacts_batch
- destroy_job_artifacts_batch || destroy_pipeline_artifacts_batch
+ @removed_artifacts_count
end
- def destroy_job_artifacts_batch
- artifacts = Ci::JobArtifact
- .expired(BATCH_SIZE)
- .unlocked
- .with_destroy_preloads
- .to_a
-
- return false if artifacts.empty?
-
- parallel_destroy_batch(artifacts)
- true
- end
-
- # TODO: Make sure this can also be parallelized
- # https://gitlab.com/gitlab-org/gitlab/-/issues/270973
- def destroy_pipeline_artifacts_batch
- artifacts = Ci::PipelineArtifact.expired(BATCH_SIZE).to_a
- return false if artifacts.empty?
+ private
- artifacts.each(&:destroy!)
+ def destroy_job_artifacts_with_slow_iteration(start_at)
+ Ci::JobArtifact.expired_before(start_at).each_batch(of: BATCH_SIZE, column: :expire_at, order: :desc) do |relation, index|
+ artifacts = relation.unlocked.with_destroy_preloads.to_a
- true
+ parallel_destroy_batch(artifacts) if artifacts.any?
+ break if loop_timeout?(start_at)
+ break if index >= LOOP_LIMIT
+ end
end
def parallel_destroy_batch(job_artifacts)
@@ -64,14 +50,14 @@ module Ci
end
# This is executed outside of the transaction because it depends on Redis
- update_statistics_for(job_artifacts)
- destroyed_artifacts_counter.increment({}, job_artifacts.size)
+ update_project_statistics_for(job_artifacts)
+ increment_monitoring_statistics(job_artifacts.size)
end
# This method is implemented in EE and it must do only database work
def destroy_related_records_for(job_artifacts); end
- def update_statistics_for(job_artifacts)
+ def update_project_statistics_for(job_artifacts)
artifacts_by_project = job_artifacts.group_by(&:project)
artifacts_by_project.each do |project, artifacts|
delta = -artifacts.sum { |artifact| artifact.size.to_i }
@@ -80,6 +66,11 @@ module Ci
end
end
+ def increment_monitoring_statistics(size)
+ destroyed_artifacts_counter.increment({}, size)
+ @removed_artifacts_count += size
+ end
+
def destroyed_artifacts_counter
strong_memoize(:destroyed_artifacts_counter) do
name = :destroyed_job_artifacts_count_total
@@ -88,6 +79,10 @@ module Ci
::Gitlab::Metrics.counter(name, comment)
end
end
+
+ def loop_timeout?(start_at)
+ Time.current > start_at + LOOP_TIMEOUT
+ end
end
end
diff --git a/app/services/ci/pipeline_artifacts/coverage_report_service.rb b/app/services/ci/pipeline_artifacts/coverage_report_service.rb
new file mode 100644
index 00000000000..9f5c445c91a
--- /dev/null
+++ b/app/services/ci/pipeline_artifacts/coverage_report_service.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+module Ci
+ module PipelineArtifacts
+ class CoverageReportService
+ def execute(pipeline)
+ return unless pipeline.can_generate_coverage_reports?
+ return if pipeline.has_coverage_reports?
+
+ file = build_carrierwave_file(pipeline)
+
+ pipeline.pipeline_artifacts.create!(
+ project_id: pipeline.project_id,
+ file_type: :code_coverage,
+ file_format: :raw,
+ 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: pipeline.coverage_reports.to_json,
+ filename: Ci::PipelineArtifact::DEFAULT_FILE_NAMES.fetch(:code_coverage),
+ content_type: 'application/json'
+ )
+ end
+ end
+ end
+end
diff --git a/app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb b/app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb
new file mode 100644
index 00000000000..0dbabe178da
--- /dev/null
+++ b/app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class DestroyExpiredArtifactsService
+ include ::Gitlab::LoopHelpers
+ include ::Gitlab::Utils::StrongMemoize
+
+ BATCH_SIZE = 100
+ LOOP_TIMEOUT = 5.minutes
+ LOOP_LIMIT = 1000
+
+ def initialize
+ @removed_artifacts_count = 0
+ end
+
+ def execute
+ loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
+ destroy_artifacts_batch
+ end
+
+ @removed_artifacts_count
+ end
+
+ private
+
+ def destroy_artifacts_batch
+ artifacts = ::Ci::PipelineArtifact.expired(BATCH_SIZE).to_a
+ return false if artifacts.empty?
+
+ artifacts.each(&:destroy!)
+ increment_stats(artifacts.size)
+
+ true
+ end
+
+ def increment_stats(size)
+ destroyed_artifacts_counter.increment({}, size)
+ @removed_artifacts_count += size
+ end
+
+ def destroyed_artifacts_counter
+ strong_memoize(:destroyed_artifacts_counter) do
+ name = :destroyed_pipeline_artifacts_count_total
+ comment = 'Counter of destroyed expired pipeline artifacts'
+
+ ::Gitlab::Metrics.counter(name, comment)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb
index d9f41b7040e..a31f5e9056e 100644
--- a/app/services/ci/pipeline_trigger_service.rb
+++ b/app/services/ci/pipeline_trigger_service.rb
@@ -21,10 +21,10 @@ module Ci
# this check is to not leak the presence of the project if user cannot read it
return unless trigger.project == project
- pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: params[:ref])
+ pipeline = Ci::CreatePipelineService
+ .new(project, trigger.owner, ref: params[:ref], variables_attributes: variables)
.execute(:trigger, ignore_skip_ci: true) do |pipeline|
pipeline.trigger_requests.build(trigger: trigger)
- pipeline.variables.build(variables)
end
if pipeline.persisted?
@@ -44,7 +44,8 @@ module Ci
# this check is to not leak the presence of the project if user cannot read it
return unless can?(job.user, :read_project, project)
- pipeline = Ci::CreatePipelineService.new(project, job.user, ref: params[:ref])
+ pipeline = Ci::CreatePipelineService
+ .new(project, job.user, ref: params[:ref], variables_attributes: variables)
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
source = job.sourced_pipelines.build(
source_pipeline: job.pipeline,
@@ -53,7 +54,6 @@ module Ci
project: project)
pipeline.source_pipeline = source
- pipeline.variables.build(variables)
end
if pipeline.persisted?
diff --git a/app/services/ci/pipelines/create_artifact_service.rb b/app/services/ci/pipelines/create_artifact_service.rb
deleted file mode 100644
index bfaf317241a..00000000000
--- a/app/services/ci/pipelines/create_artifact_service.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-module Ci
- module Pipelines
- class CreateArtifactService
- def execute(pipeline)
- return unless pipeline.can_generate_coverage_reports?
- return if pipeline.has_coverage_reports?
-
- file = build_carrierwave_file(pipeline)
-
- pipeline.pipeline_artifacts.create!(
- project_id: pipeline.project_id,
- file_type: :code_coverage,
- file_format: :raw,
- 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: pipeline.coverage_reports.to_json,
- filename: Ci::PipelineArtifact::DEFAULT_FILE_NAMES.fetch(:code_coverage),
- content_type: 'application/json'
- )
- end
- end
- end
-end
diff --git a/app/services/ci/play_build_service.rb b/app/services/ci/play_build_service.rb
index 6adeca624a8..ebc980a9053 100644
--- a/app/services/ci/play_build_service.rb
+++ b/app/services/ci/play_build_service.rb
@@ -5,6 +5,10 @@ module Ci
def execute(build, job_variables_attributes = nil)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :play_job, build)
+ if job_variables_attributes.present? && !can?(current_user, :set_pipeline_variables, project)
+ raise Gitlab::Access::AccessDeniedError
+ end
+
# Try to enqueue the build, otherwise create a duplicate.
#
if build.enqueue
diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb
index 12cdca24066..dd7b562cdb7 100644
--- a/app/services/ci/process_build_service.rb
+++ b/app/services/ci/process_build_service.rb
@@ -26,6 +26,27 @@ module Ci
end
def valid_statuses_for_build(build)
+ if ::Feature.enabled?(:skip_dag_manual_and_delayed_jobs, default_enabled: :yaml)
+ current_valid_statuses_for_build(build)
+ else
+ legacy_valid_statuses_for_build(build)
+ end
+ end
+
+ def current_valid_statuses_for_build(build)
+ case build.when
+ when 'on_success', 'manual', 'delayed'
+ build.scheduling_type_dag? ? %w[success] : %w[success skipped]
+ when 'on_failure'
+ %w[failed]
+ when 'always'
+ %w[success failed skipped]
+ else
+ []
+ end
+ end
+
+ def legacy_valid_statuses_for_build(build)
case build.when
when 'on_success'
build.scheduling_type_dag? ? %w[success] : %w[success skipped]
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 04d620d1d38..59691fe4ef3 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -8,8 +8,8 @@ module Ci
JOB_QUEUE_DURATION_SECONDS_BUCKETS = [1, 3, 10, 30, 60, 300, 900, 1800, 3600].freeze
JOBS_RUNNING_FOR_PROJECT_MAX_BUCKET = 5.freeze
- METRICS_SHARD_TAG_PREFIX = 'metrics_shard::'.freeze
- DEFAULT_METRICS_SHARD = 'default'.freeze
+ METRICS_SHARD_TAG_PREFIX = 'metrics_shard::'
+ DEFAULT_METRICS_SHARD = 'default'
Result = Struct.new(:build, :build_json, :valid?)
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index f397ada0696..e5e79f70616 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -2,6 +2,8 @@
module Ci
class RetryBuildService < ::BaseService
+ include Gitlab::OptimisticLocking
+
def self.clone_accessors
%i[pipeline project ref tag options name
allow_failure stage stage_id stage_idx trigger_request
@@ -65,8 +67,8 @@ module Ci
end
def mark_subsequent_stages_as_processable(build)
- build.pipeline.processables.skipped.after_stage(build.stage_idx).find_each do |processable|
- Gitlab::OptimisticLocking.retry_lock(processable, &:process)
+ build.pipeline.processables.skipped.after_stage(build.stage_idx).find_each do |skipped|
+ retry_optimistic_lock(skipped) { |build| build.process(current_user) }
end
end
end
diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb
index 45244d16393..dea4bf73a4c 100644
--- a/app/services/ci/retry_pipeline_service.rb
+++ b/app/services/ci/retry_pipeline_service.rb
@@ -23,7 +23,7 @@ module Ci
end
pipeline.builds.latest.skipped.find_each do |skipped|
- retry_optimistic_lock(skipped) { |build| build.process }
+ retry_optimistic_lock(skipped) { |build| build.process(current_user) }
end
pipeline.reset_ancestor_bridges!
diff --git a/app/services/ci/test_failure_history_service.rb b/app/services/ci/test_failure_history_service.rb
index 99a2592ec06..61fda79a4a2 100644
--- a/app/services/ci/test_failure_history_service.rb
+++ b/app/services/ci/test_failure_history_service.rb
@@ -30,7 +30,6 @@ module Ci
end
def should_track_failures?
- return false unless Feature.enabled?(:test_failure_history, project)
return false unless project.default_branch_or_master == pipeline.ref
# We fetch for up to MAX_TRACKABLE_FAILURES + 1 builds. So if ever we get
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index f01d41d9414..874f4bf459a 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -111,7 +111,7 @@ module Ci
Result.new(status: 200)
when 'failed'
- build.drop!(params[:failure_reason] || :unknown_failure)
+ build.drop_with_exit_code!(params[:failure_reason] || :unknown_failure, params[:exit_code])
Result.new(status: 200)
else
diff --git a/app/services/concerns/schedule_bulk_repository_shard_moves_methods.rb b/app/services/concerns/schedule_bulk_repository_shard_moves_methods.rb
new file mode 100644
index 00000000000..eb03f3a9f3a
--- /dev/null
+++ b/app/services/concerns/schedule_bulk_repository_shard_moves_methods.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module ScheduleBulkRepositoryShardMovesMethods
+ extend ActiveSupport::Concern
+ include BaseServiceUtility
+
+ class_methods do
+ def enqueue(source_storage_name, destination_storage_name = nil)
+ schedule_bulk_worker_klass.perform_async(source_storage_name, destination_storage_name)
+ end
+
+ def schedule_bulk_worker_klass
+ raise NotImplementedError
+ end
+ end
+
+ def execute(source_storage_name, destination_storage_name = nil)
+ shard = Shard.find_by_name!(source_storage_name)
+
+ repository_klass.for_shard(shard).each_batch(column: container_column) do |relation|
+ container_klass.id_in(relation.select(container_column)).each do |container|
+ container.with_lock do
+ next if container.repository_storage != source_storage_name
+
+ storage_move = container.repository_storage_moves.build(
+ source_storage_name: source_storage_name,
+ destination_storage_name: destination_storage_name
+ )
+
+ unless storage_move.schedule
+ log_info("Container #{container.full_path} (#{container.id}) was skipped: #{storage_move.errors.full_messages.to_sentence}")
+ end
+ end
+ end
+ end
+
+ success
+ end
+
+ private
+
+ def repository_klass
+ raise NotImplementedError
+ end
+
+ def container_klass
+ raise NotImplementedError
+ end
+
+ def container_column
+ raise NotImplementedError
+ end
+end
diff --git a/app/services/concerns/update_repository_storage_methods.rb b/app/services/concerns/update_repository_storage_methods.rb
new file mode 100644
index 00000000000..c3a55e9379e
--- /dev/null
+++ b/app/services/concerns/update_repository_storage_methods.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+module UpdateRepositoryStorageMethods
+ 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
+
+ def initialize(repository_storage_move)
+ @repository_storage_move = repository_storage_move
+ end
+
+ def execute
+ repository_storage_move.with_lock do
+ return ServiceResponse.success unless repository_storage_move.scheduled? # rubocop:disable Cop/AvoidReturnFromBlocks
+
+ repository_storage_move.start!
+ end
+
+ raise SameFilesystemError if same_filesystem?(source_storage_name, destination_storage_name)
+
+ mirror_repositories
+
+ repository_storage_move.transaction do
+ repository_storage_move.finish_replication!
+
+ track_repository(destination_storage_name)
+ end
+
+ remove_old_paths
+ enqueue_housekeeping
+
+ repository_storage_move.finish_cleanup!
+
+ ServiceResponse.success
+ rescue StandardError => e
+ repository_storage_move.do_fail!
+
+ Gitlab::ErrorTracking.track_exception(e, container_klass: container.class.to_s, container_path: container.full_path)
+
+ ServiceResponse.error(
+ message: s_("UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}") % { container_full_path: container.full_path, message: e.message }
+ )
+ end
+
+ private
+
+ def track_repository(destination_shard)
+ raise NotImplementedError
+ end
+
+ def mirror_repositories
+ raise NotImplementedError
+ end
+
+ def mirror_repository(type:)
+ unless wait_for_pushes(type)
+ raise Error, s_('UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes') % { type: type.name }
+ end
+
+ repository = type.repository_for(container)
+ full_path = repository.full_path
+ raw_repository = repository.raw
+ checksum = repository.checksum
+
+ # Initialize a git repository on the target path
+ new_repository = Gitlab::Git::Repository.new(
+ destination_storage_name,
+ raw_repository.relative_path,
+ raw_repository.gl_repository,
+ full_path
+ )
+
+ new_repository.replicate(raw_repository)
+ new_checksum = new_repository.checksum
+
+ if checksum != new_checksum
+ raise Error, s_('UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}') % { type: type.name, old: checksum, new: new_checksum }
+ end
+ end
+
+ def same_filesystem?(old_storage, new_storage)
+ Gitlab::GitalyClient.filesystem_id(old_storage) == Gitlab::GitalyClient.filesystem_id(new_storage)
+ end
+
+ def remove_old_paths
+ if container.repository_exists?
+ Gitlab::Git::Repository.new(
+ source_storage_name,
+ "#{container.disk_path}.git",
+ nil,
+ nil
+ ).remove
+ end
+ end
+
+ def enqueue_housekeeping
+ # no-op
+ end
+
+ def wait_for_pushes(type)
+ reference_counter = container.reference_counter(type: type)
+
+ # Try for 30 seconds, polling every 10
+ 3.times do
+ return true if reference_counter.value == 0
+
+ sleep 10
+ end
+
+ false
+ end
+end
diff --git a/app/services/container_expiration_policies/cleanup_service.rb b/app/services/container_expiration_policies/cleanup_service.rb
index 4719c99af6d..b9e623e2e07 100644
--- a/app/services/container_expiration_policies/cleanup_service.rb
+++ b/app/services/container_expiration_policies/cleanup_service.rb
@@ -4,6 +4,8 @@ module ContainerExpirationPolicies
class CleanupService
attr_reader :repository
+ SERVICE_RESULT_FIELDS = %i[original_size before_truncate_size after_truncate_size before_delete_size].freeze
+
def initialize(repository)
@repository = repository
end
@@ -13,28 +15,37 @@ module ContainerExpirationPolicies
repository.start_expiration_policy!
- result = Projects::ContainerRepository::CleanupTagsService
+ service_result = Projects::ContainerRepository::CleanupTagsService
.new(project, nil, policy_params.merge('container_expiration_policy' => true))
.execute(repository)
- if result[:status] == :success
+ if service_result[:status] == :success
repository.update!(
expiration_policy_cleanup_status: :cleanup_unscheduled,
expiration_policy_started_at: nil,
expiration_policy_completed_at: Time.zone.now
)
- success(:finished)
+ success(:finished, service_result)
else
repository.cleanup_unfinished!
- success(:unfinished)
+ success(:unfinished, service_result)
end
end
private
- def success(cleanup_status)
- ServiceResponse.success(message: "cleanup #{cleanup_status}", payload: { cleanup_status: cleanup_status, container_repository_id: repository.id })
+ def success(cleanup_status, service_result)
+ payload = {
+ cleanup_status: cleanup_status,
+ container_repository_id: repository.id
+ }
+
+ SERVICE_RESULT_FIELDS.each do |field|
+ payload["cleanup_tags_service_#{field}".to_sym] = service_result[field]
+ end
+
+ ServiceResponse.success(message: "cleanup #{cleanup_status}", payload: payload)
end
def policy_params
diff --git a/app/services/draft_notes/base_service.rb b/app/services/draft_notes/base_service.rb
index 89daae0e8f4..95c291ea800 100644
--- a/app/services/draft_notes/base_service.rb
+++ b/app/services/draft_notes/base_service.rb
@@ -8,6 +8,10 @@ module DraftNotes
@merge_request, @current_user, @params = merge_request, current_user, params.dup
end
+ def merge_request_activity_counter
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ end
+
private
def draft_notes
diff --git a/app/services/draft_notes/create_service.rb b/app/services/draft_notes/create_service.rb
index 501778b7d5f..5ff971b66c1 100644
--- a/app/services/draft_notes/create_service.rb
+++ b/app/services/draft_notes/create_service.rb
@@ -31,6 +31,10 @@ module DraftNotes
merge_request.diffs.clear_cache
end
+ if draft_note.persisted?
+ merge_request_activity_counter.track_create_review_note_action(user: current_user)
+ end
+
draft_note
end
diff --git a/app/services/draft_notes/publish_service.rb b/app/services/draft_notes/publish_service.rb
index a9a7304e5ed..316abff4552 100644
--- a/app/services/draft_notes/publish_service.rb
+++ b/app/services/draft_notes/publish_service.rb
@@ -9,6 +9,7 @@ module DraftNotes
publish_draft_note(draft)
else
publish_draft_notes
+ merge_request_activity_counter.track_publish_review_action(user: current_user)
end
success
diff --git a/app/services/feature_flags/base_service.rb b/app/services/feature_flags/base_service.rb
index 9b27df90992..c11c465252e 100644
--- a/app/services/feature_flags/base_service.rb
+++ b/app/services/feature_flags/base_service.rb
@@ -6,6 +6,11 @@ module FeatureFlags
AUDITABLE_ATTRIBUTES = %w(name description active).freeze
+ def success(**args)
+ sync_to_jira(args[:feature_flag])
+ super
+ end
+
protected
def audit_event(feature_flag)
@@ -34,6 +39,16 @@ module FeatureFlags
audit_event.security_event
end
+ 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
+ ::JiraConnect::SyncFeatureFlagsWorker.perform_async(feature_flag.id, seq_id)
+ end
+ end
+
def created_scope_message(scope)
"Created rule <strong>#{scope.environment_scope}</strong> "\
"and set it as <strong>#{scope.active ? "active" : "inactive"}</strong> "\
diff --git a/app/services/git/branch_push_service.rb b/app/services/git/branch_push_service.rb
index 2ec6ac99ece..d250bca7bf2 100644
--- a/app/services/git/branch_push_service.rb
+++ b/app/services/git/branch_push_service.rb
@@ -72,10 +72,10 @@ module Git
end
def perform_housekeeping
- housekeeping = Projects::HousekeepingService.new(project)
+ housekeeping = Repositories::HousekeepingService.new(project)
housekeeping.increment!
housekeeping.execute if housekeeping.needed?
- rescue Projects::HousekeepingService::LeaseTaken
+ rescue Repositories::HousekeepingService::LeaseTaken
end
def removing_branch?
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index 52600f5b88f..06a3b31c665 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -35,6 +35,7 @@ module Groups
@group.add_owner(current_user)
@group.create_namespace_settings
Service.create_from_active_default_integrations(@group, :group_id)
+ OnboardingProgress.onboard(@group)
end
end
diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb
index 1bff70e6c2e..c7107e2fa56 100644
--- a/app/services/groups/destroy_service.rb
+++ b/app/services/groups/destroy_service.rb
@@ -29,17 +29,32 @@ module Groups
group.chat_team&.remove_mattermost_team(current_user)
- user_ids_for_project_authorizations_refresh = group.user_ids_for_project_authorizations
+ # If any other groups are shared with the group that is being destroyed,
+ # we should specifically trigger update of all project authorizations
+ # for users that are the members of this group.
+ # If not, the project authorization records of these users to projects within the shared groups
+ # will never be removed, causing inconsistencies with access permissions.
+ if any_other_groups_are_shared_with_this_group?
+ user_ids_for_project_authorizations_refresh = group.user_ids_for_project_authorizations
+ end
group.destroy
- UserProjectAccessChangedService
- .new(user_ids_for_project_authorizations_refresh)
- .execute(blocking: true)
+ if user_ids_for_project_authorizations_refresh.present?
+ UserProjectAccessChangedService
+ .new(user_ids_for_project_authorizations_refresh)
+ .execute(blocking: true)
+ end
group
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def any_other_groups_are_shared_with_this_group?
+ group.shared_group_links.any?
+ end
end
end
diff --git a/app/services/ide/base_config_service.rb b/app/services/ide/base_config_service.rb
index 1f8d5c17584..0501fab53af 100644
--- a/app/services/ide/base_config_service.rb
+++ b/app/services/ide/base_config_service.rb
@@ -4,7 +4,7 @@ module Ide
class BaseConfigService < ::BaseService
ValidationError = Class.new(StandardError)
- WEBIDE_CONFIG_FILE = '.gitlab/.gitlab-webide.yml'.freeze
+ WEBIDE_CONFIG_FILE = '.gitlab/.gitlab-webide.yml'
attr_reader :config, :config_content
diff --git a/app/services/incident_management/pager_duty/process_webhook_service.rb b/app/services/incident_management/pager_duty/process_webhook_service.rb
index 027425e4aaa..ccbca671b37 100644
--- a/app/services/incident_management/pager_duty/process_webhook_service.rb
+++ b/app/services/incident_management/pager_duty/process_webhook_service.rb
@@ -2,7 +2,7 @@
module IncidentManagement
module PagerDuty
- class ProcessWebhookService < BaseService
+ class ProcessWebhookService
include Gitlab::Utils::StrongMemoize
include IncidentManagement::Settings
@@ -12,6 +12,11 @@ module IncidentManagement
# https://developer.pagerduty.com/docs/webhooks/v2-overview/#webhook-types
PAGER_DUTY_PROCESSABLE_EVENT_TYPES = %w(incident.trigger).freeze
+ def initialize(project, payload)
+ @project = project
+ @payload = payload
+ end
+
def execute(token)
return forbidden unless webhook_setting_active?
return unauthorized unless valid_token?(token)
@@ -24,6 +29,8 @@ module IncidentManagement
private
+ attr_reader :project, :payload
+
def process_incidents
pager_duty_processable_events.each do |event|
::IncidentManagement::PagerDuty::ProcessIncidentWorker.perform_async(project.id, event['incident'])
@@ -33,7 +40,7 @@ module IncidentManagement
def pager_duty_processable_events
strong_memoize(:pager_duty_processable_events) do
::PagerDuty::WebhookPayloadParser
- .call(params.to_h)
+ .call(payload.to_h)
.filter { |msg| msg['event'].to_s.in?(PAGER_DUTY_PROCESSABLE_EVENT_TYPES) }
end
end
@@ -47,7 +54,7 @@ module IncidentManagement
end
def valid_payload_size?
- Gitlab::Utils::DeepSize.new(params, max_size: PAGER_DUTY_PAYLOAD_SIZE_LIMIT).valid?
+ Gitlab::Utils::DeepSize.new(payload, max_size: PAGER_DUTY_PAYLOAD_SIZE_LIMIT).valid?
end
def accepted
diff --git a/app/services/issuable/bulk_update_service.rb b/app/services/issuable/bulk_update_service.rb
index 79be771b3fb..d3d543edcd7 100644
--- a/app/services/issuable/bulk_update_service.rb
+++ b/app/services/issuable/bulk_update_service.rb
@@ -34,6 +34,8 @@ module Issuable
def permitted_attrs(type)
attrs = %i(state_event milestone_id add_label_ids remove_label_ids subscription_event)
+ attrs.push(:sprint_id) if type == 'issue'
+
if type == 'issue' || type == 'merge_request'
attrs.push(:assignee_ids)
else
diff --git a/app/services/issuable/export_csv/base_service.rb b/app/services/issuable/export_csv/base_service.rb
new file mode 100644
index 00000000000..49ff05935c9
--- /dev/null
+++ b/app/services/issuable/export_csv/base_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Issuable
+ module ExportCsv
+ class BaseService
+ # Target attachment size before base64 encoding
+ TARGET_FILESIZE = 15.megabytes
+
+ def initialize(issuables_relation, project)
+ @issuables = issuables_relation
+ @project = project
+ end
+
+ def csv_data
+ csv_builder.render(TARGET_FILESIZE)
+ end
+
+ private
+
+ attr_reader :project, :issuables
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def csv_builder
+ @csv_builder ||=
+ CsvBuilder.new(issuables.preload(associations_to_preload), header_to_value_hash)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def associations_to_preload
+ []
+ end
+
+ def header_to_value_hash
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 60e5293e218..6d41d449683 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -158,7 +158,9 @@ class IssuableBaseService < BaseService
after_create(issuable)
execute_hooks(issuable)
- invalidate_cache_counts(issuable, users: issuable.assignees)
+
+ users_to_invalidate = issuable.allows_reviewers? ? issuable.assignees | issuable.reviewers : issuable.assignees
+ invalidate_cache_counts(issuable, users: users_to_invalidate)
issuable.update_project_counter_caches
end
diff --git a/app/services/issues/clone_service.rb b/app/services/issues/clone_service.rb
index 789da312958..4c9c34f1247 100644
--- a/app/services/issues/clone_service.rb
+++ b/app/services/issues/clone_service.rb
@@ -88,3 +88,5 @@ module Issues
end
end
end
+
+Issues::CloneService.prepend_if_ee('EE::Issues::CloneService')
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index c3677de015f..baf7974c45d 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -31,7 +31,7 @@ module Issues
closed_via = _("commit %{commit_id}") % { commit_id: closed_via.id } if closed_via.is_a?(Commit)
- notification_service.async.close_issue(issue, current_user, closed_via: closed_via) if notifications
+ notification_service.async.close_issue(issue, current_user, { closed_via: closed_via }) if notifications
todo_service.close_issue(issue, current_user)
resolve_alert(issue)
execute_hooks(issue, 'close')
@@ -39,7 +39,10 @@ module Issues
issue.update_project_counter_caches
track_incident_action(current_user, issue, :incident_closed)
- store_first_mentioned_in_commit_at(issue, closed_via) if closed_via.is_a?(MergeRequest)
+ if closed_via.is_a?(MergeRequest)
+ store_first_mentioned_in_commit_at(issue, closed_via)
+ OnboardingProgressService.new(project.namespace).execute(action: :issue_auto_closed)
+ end
delete_milestone_closed_issue_counter_cache(issue.milestone)
end
diff --git a/app/services/issues/export_csv_service.rb b/app/services/issues/export_csv_service.rb
index 8f513632929..2181c46c90d 100644
--- a/app/services/issues/export_csv_service.rb
+++ b/app/services/issues/export_csv_service.rb
@@ -1,36 +1,14 @@
# frozen_string_literal: true
module Issues
- class ExportCsvService
+ class ExportCsvService < Issuable::ExportCsv::BaseService
include Gitlab::Routing.url_helpers
include GitlabRoutingHelper
- # Target attachment size before base64 encoding
- TARGET_FILESIZE = 15000000
-
- attr_reader :project
-
- def initialize(issues_relation, project)
- @issues = issues_relation
- @labels = @issues.labels_hash
- @project = project
- end
-
- def csv_data
- csv_builder.render(TARGET_FILESIZE)
- end
-
def email(user)
Notify.issues_csv_email(user, project, csv_data, csv_builder.status).deliver_now
end
- # rubocop: disable CodeReuse/ActiveRecord
- def csv_builder
- @csv_builder ||=
- CsvBuilder.new(@issues.preload(associations_to_preload), header_to_value_hash)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
private
def associations_to_preload
@@ -63,7 +41,7 @@ module Issues
end
def issue_labels(issue)
- @labels[issue.id].sort.join(',').presence
+ issuables.labels_hash[issue.id].sort.join(',').presence
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/services/jira_connect/sync_service.rb b/app/services/jira_connect/sync_service.rb
index b2af284f1f0..bddc7cbe5a0 100644
--- a/app/services/jira_connect/sync_service.rb
+++ b/app/services/jira_connect/sync_service.rb
@@ -31,7 +31,7 @@ module JiraConnect
jira_response: response&.to_json
}
- if response && (response['errorMessages'] || response['rejectedBuilds'].present?)
+ if response && response['errorMessages'].present?
logger.error(message)
else
logger.info(message)
diff --git a/app/services/jira_connect_subscriptions/create_service.rb b/app/services/jira_connect_subscriptions/create_service.rb
index b169d97615d..38e5fe7e690 100644
--- a/app/services/jira_connect_subscriptions/create_service.rb
+++ b/app/services/jira_connect_subscriptions/create_service.rb
@@ -35,8 +35,6 @@ module JiraConnectSubscriptions
end
def schedule_sync_project_jobs
- return unless Feature.enabled?(:jira_connect_full_namespace_sync)
-
namespace.all_projects.each_batch(of: MERGE_REQUEST_SYNC_BATCH_SIZE) do |projects, index|
JiraConnect::SyncProjectWorker.bulk_perform_in_with_contexts(
index * MERGE_REQUEST_SYNC_BATCH_DELAY,
diff --git a/app/services/labels/create_service.rb b/app/services/labels/create_service.rb
index a5b30e29e55..665d1035b2b 100644
--- a/app/services/labels/create_service.rb
+++ b/app/services/labels/create_service.rb
@@ -25,3 +25,5 @@ module Labels
end
end
end
+
+Labels::CreateService.prepend_if_ee('EE::Labels::CreateService')
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index 3588cda180f..5fcf2d711b0 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -54,7 +54,8 @@ module Members
end
def enqueue_onboarding_progress_action(source)
- Namespaces::OnboardingUserAddedWorker.perform_async(source.id)
+ namespace_id = source.is_a?(Project) ? source.namespace_id : source.id
+ Namespaces::OnboardingUserAddedWorker.perform_async(namespace_id)
end
end
end
diff --git a/app/services/merge_requests/after_create_service.rb b/app/services/merge_requests/after_create_service.rb
index fbb9d5fa9dc..03fcb5a4c1b 100644
--- a/app/services/merge_requests/after_create_service.rb
+++ b/app/services/merge_requests/after_create_service.rb
@@ -4,6 +4,7 @@ module MergeRequests
class AfterCreateService < MergeRequests::BaseService
def execute(merge_request)
event_service.open_mr(merge_request, current_user)
+ merge_request_activity_counter.track_create_mr_action(user: current_user)
notification_service.new_merge_request(merge_request, current_user)
create_pipeline_for(merge_request, current_user)
@@ -12,7 +13,7 @@ module MergeRequests
merge_request.diffs(include_stats: false).write_cache
merge_request.create_cross_references!(current_user)
- NamespaceOnboardingAction.create_action(merge_request.target_project.namespace, :merge_request_created)
+ OnboardingProgressService.new(merge_request.target_project.namespace).execute(action: :merge_request_created)
end
end
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 265b211066e..0613c061f2e 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -52,6 +52,10 @@ module MergeRequests
"#<#{self.class} #{merge_request.to_reference(full: true)}>"
end
+ def merge_request_activity_counter
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ end
+
private
def enqueue_jira_connect_messages_for(merge_request)
diff --git a/app/services/merge_requests/cleanup_refs_service.rb b/app/services/merge_requests/cleanup_refs_service.rb
index 23ac8e393f4..2094ea00160 100644
--- a/app/services/merge_requests/cleanup_refs_service.rb
+++ b/app/services/merge_requests/cleanup_refs_service.rb
@@ -36,6 +36,8 @@ module MergeRequests
return error('Failed to update schedule.') unless update_schedule
success
+ rescue Gitlab::Git::Repository::GitError, Gitlab::Git::CommandError => e
+ error(e.message)
end
private
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index b0a7face594..f83b14c7269 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -13,11 +13,12 @@ module MergeRequests
if merge_request.close
create_event(merge_request)
+ merge_request_activity_counter.track_close_mr_action(user: current_user)
create_note(merge_request)
notification_service.async.close_mr(merge_request, current_user)
todo_service.close_merge_request(merge_request, current_user)
execute_hooks(merge_request, 'close')
- invalidate_cache_counts(merge_request, users: merge_request.assignees)
+ invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
cleanup_environments(merge_request)
abort_auto_merge(merge_request, 'merge request was closed')
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index 95fb99d3e7a..78b462174c9 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -85,7 +85,8 @@ module MergeRequests
source_project_id: target_project.id,
source_branch: branch_name,
target_project_id: target_project.id,
- target_branch: target_branch
+ target_branch: target_branch,
+ assignee_ids: [current_user.id]
}
end
diff --git a/app/services/merge_requests/export_csv_service.rb b/app/services/merge_requests/export_csv_service.rb
index 1e7f0c8e722..8f2a70575e5 100644
--- a/app/services/merge_requests/export_csv_service.rb
+++ b/app/services/merge_requests/export_csv_service.rb
@@ -1,32 +1,16 @@
# frozen_string_literal: true
module MergeRequests
- class ExportCsvService
+ class ExportCsvService < Issuable::ExportCsv::BaseService
include Gitlab::Routing.url_helpers
include GitlabRoutingHelper
- # Target attachment size before base64 encoding
- TARGET_FILESIZE = 15.megabytes
-
- def initialize(merge_requests, project)
- @project = project
- @merge_requests = merge_requests
- end
-
- def csv_data
- csv_builder.render(TARGET_FILESIZE)
- end
-
def email(user)
- Notify.merge_requests_csv_email(user, @project, csv_data, csv_builder.status).deliver_now
+ Notify.merge_requests_csv_email(user, project, csv_data, csv_builder.status).deliver_now
end
private
- def csv_builder
- @csv_builder ||= CsvBuilder.new(@merge_requests.with_csv_entity_associations, header_to_value_hash)
- end
-
def header_to_value_hash
{
'MR IID' => 'iid',
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index ba22b458777..f4454db0af8 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -88,7 +88,9 @@ module MergeRequests
end
def try_merge
- repository.merge(current_user, source, merge_request, commit_message)
+ repository.merge(current_user, source, merge_request, commit_message).tap do
+ merge_request.update_column(:squash_commit_sha, source) if merge_request.squash_on_merge?
+ end
rescue Gitlab::Git::PreReceiveError => e
raise MergeError,
"Something went wrong during merge pre-receive hook. #{e.message}".strip
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
index 627c747203c..96a2322f6a0 100644
--- a/app/services/merge_requests/mergeability_check_service.rb
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -38,7 +38,6 @@ module MergeRequests
# error otherwise.
def execute(recheck: false, retry_lease: true)
return service_error if service_error
- return check_mergeability(recheck) unless merge_ref_auto_sync_lock_enabled?
in_write_lock(retry_lease: retry_lease) do |retried|
# When multiple calls are waiting for the same lock (retry_lease),
@@ -64,10 +63,6 @@ module MergeRequests
return ServiceResponse.error(message: 'Merge request is not mergeable')
end
- unless merge_ref_auto_sync_enabled?
- return ServiceResponse.error(message: 'Merge ref is outdated due to disabled feature')
- end
-
unless payload.fetch(:merge_ref_head)
return ServiceResponse.error(message: 'Merge ref cannot be updated')
end
@@ -142,7 +137,6 @@ module MergeRequests
#
# Returns true if the merge-ref does not exists or is out of sync.
def outdated_merge_ref?
- return false unless merge_ref_auto_sync_enabled?
return false unless merge_request.open?
return true unless ref_head = merge_request.merge_ref_head
@@ -157,21 +151,11 @@ module MergeRequests
end
def merge_to_ref
- return true unless merge_ref_auto_sync_enabled?
-
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
- def merge_ref_auto_sync_enabled?
- Feature.enabled?(:merge_ref_auto_sync, project, default_enabled: true)
- end
-
- def merge_ref_auto_sync_lock_enabled?
- Feature.enabled?(:merge_ref_auto_sync_lock, project, default_enabled: true)
- end
-
def service_error
strong_memoize(:service_error) do
if !merge_request
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index 1c78fca3c26..f04ec3c3e80 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -15,9 +15,10 @@ module MergeRequests
todo_service.merge_merge_request(merge_request, current_user)
create_event(merge_request)
create_note(merge_request)
+ merge_request_activity_counter.track_merge_mr_action(user: current_user)
notification_service.merge_mr(merge_request, current_user)
execute_hooks(merge_request, 'merge')
- invalidate_cache_counts(merge_request, users: merge_request.assignees)
+ invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
delete_non_latest_diffs(merge_request)
cancel_review_app_jobs!(merge_request)
diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb
index bcedbc61c65..35c50d63da0 100644
--- a/app/services/merge_requests/reopen_service.rb
+++ b/app/services/merge_requests/reopen_service.rb
@@ -8,11 +8,12 @@ module MergeRequests
if merge_request.reopen
create_event(merge_request)
create_note(merge_request, 'reopened')
+ merge_request_activity_counter.track_reopen_mr_action(user: current_user)
notification_service.async.reopen_mr(merge_request, current_user)
execute_hooks(merge_request, 'reopen')
merge_request.reload_diff(current_user)
merge_request.mark_as_unchecked
- invalidate_cache_counts(merge_request, users: merge_request.assignees)
+ invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
merge_request.cache_merge_request_closes_issues!(current_user)
merge_request.cleanup_schedule&.destroy
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index bff7a43dd7b..d2e5a2a1619 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -112,9 +112,11 @@ module MergeRequests
end
def handle_reviewers_change(merge_request, old_reviewers)
+ affected_reviewers = (old_reviewers + merge_request.reviewers) - (old_reviewers & merge_request.reviewers)
create_reviewer_note(merge_request, old_reviewers)
notification_service.async.changed_reviewer_of_merge_request(merge_request, current_user, old_reviewers)
todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
+ invalidate_cache_counts(merge_request, users: affected_reviewers.compact)
end
def create_branch_change_note(issuable, branch_type, old_branch, new_branch)
@@ -126,27 +128,29 @@ module MergeRequests
override :handle_quick_actions
def handle_quick_actions(merge_request)
super
+
+ # Ensure this parameter does not get used as an attribute
+ rebase = params.delete(:rebase)
+
+ if rebase
+ rebase_from_quick_action(merge_request)
+ # Ignore "/merge" if "/rebase" is used to avoid an unexpected race
+ params.delete(:merge)
+ end
+
merge_from_quick_action(merge_request) if params[:merge]
end
+ def rebase_from_quick_action(merge_request)
+ merge_request.rebase_async(current_user.id)
+ end
+
def merge_from_quick_action(merge_request)
last_diff_sha = params.delete(:merge)
- if Feature.enabled?(:merge_orchestration_service, merge_request.project, default_enabled: true)
- MergeRequests::MergeOrchestrationService
- .new(project, current_user, { sha: last_diff_sha })
- .execute(merge_request)
- else
- return unless merge_request.mergeable_with_quick_action?(current_user, last_diff_sha: last_diff_sha)
-
- merge_request.update(merge_error: nil)
-
- if merge_request.head_pipeline_active?
- AutoMergeService.new(project, current_user, { sha: last_diff_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
- else
- merge_request.merge_async(current_user.id, { sha: last_diff_sha })
- end
- end
+ MergeRequests::MergeOrchestrationService
+ .new(project, current_user, { sha: last_diff_sha })
+ .execute(merge_request)
end
override :quick_action_options
diff --git a/app/services/namespaces/package_settings/update_service.rb b/app/services/namespaces/package_settings/update_service.rb
new file mode 100644
index 00000000000..0964963647a
--- /dev/null
+++ b/app/services/namespaces/package_settings/update_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Namespaces
+ module PackageSettings
+ class UpdateService < BaseContainerService
+ include Gitlab::Utils::StrongMemoize
+
+ ALLOWED_ATTRIBUTES = %i[maven_duplicates_allowed maven_duplicate_exception_regex].freeze
+
+ def execute
+ return ServiceResponse.error(message: 'Access Denied', http_status: 403) unless allowed?
+
+ if package_settings.update(package_settings_params)
+ ServiceResponse.success(payload: { package_settings: package_settings })
+ else
+ ServiceResponse.error(
+ message: package_settings.errors.full_messages.to_sentence || 'Bad request',
+ http_status: 400
+ )
+ end
+ end
+
+ private
+
+ def package_settings
+ strong_memoize(:package_settings) do
+ @container.package_settings
+ end
+ end
+
+ def allowed?
+ Ability.allowed?(current_user, :create_package_settings, @container)
+ end
+
+ def package_settings_params
+ @params.slice(*ALLOWED_ATTRIBUTES)
+ end
+ end
+ end
+end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 9fffb6c372b..04b7fba207b 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -75,6 +75,7 @@ module Notes
end
track_note_creation_usage_for_issues(note) if note.for_issue?
+ track_note_creation_usage_for_merge_requests(note) if note.for_merge_request?
end
def do_commands(note, update_params, message, only_commands)
@@ -119,5 +120,9 @@ module Notes
def track_note_creation_usage_for_issues(note)
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_added_action(author: note.author)
end
+
+ def track_note_creation_usage_for_merge_requests(note)
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_create_comment_action(note: note)
+ end
end
end
diff --git a/app/services/notes/destroy_service.rb b/app/services/notes/destroy_service.rb
index 2b6ec47eaef..85f54a39add 100644
--- a/app/services/notes/destroy_service.rb
+++ b/app/services/notes/destroy_service.rb
@@ -9,6 +9,7 @@ module Notes
clear_noteable_diffs_cache(note)
track_note_removal_usage_for_issues(note) if note.for_issue?
+ track_note_removal_usage_for_merge_requests(note) if note.for_merge_request?
end
private
@@ -16,6 +17,10 @@ module Notes
def track_note_removal_usage_for_issues(note)
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_removed_action(author: note.author)
end
+
+ def track_note_removal_usage_for_merge_requests(note)
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_remove_comment_action(note: note)
+ end
end
end
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
index 37872f7fbdb..857ffbb6965 100644
--- a/app/services/notes/update_service.rb
+++ b/app/services/notes/update_service.rb
@@ -15,6 +15,7 @@ module Notes
end
track_note_edit_usage_for_issues(note) if note.for_issue?
+ track_note_edit_usage_for_merge_requests(note) if note.for_merge_request?
only_commands = false
@@ -95,6 +96,10 @@ module Notes
def track_note_edit_usage_for_issues(note)
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_edited_action(author: note.author)
end
+
+ def track_note_edit_usage_for_merge_requests(note)
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_edit_comment_action(note: note)
+ end
end
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 4ff462191fe..5a71e0eac7c 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -118,8 +118,8 @@ class NotificationService
# * project team members with notification level higher then Participating
# * users with custom level checked with "close issue"
#
- def close_issue(issue, current_user, closed_via: nil)
- close_resource_email(issue, current_user, :closed_issue_email, closed_via: closed_via)
+ def close_issue(issue, current_user, params = {})
+ close_resource_email(issue, current_user, :closed_issue_email, closed_via: params[:closed_via])
end
# When we reassign an issue we should send an email to:
@@ -481,6 +481,12 @@ class NotificationService
mailer.member_access_granted_email(group_member.real_source_type, group_member.id).deliver_later
end
+ def updated_group_member_expiration(group_member)
+ return true unless group_member.notifiable?(:mention)
+
+ mailer.member_expiration_date_updated_email(group_member.real_source_type, group_member.id).deliver_later
+ end
+
def project_was_moved(project, old_path_with_namespace)
recipients = project_moved_recipients(project)
recipients = notifiable_users(recipients, :custom, custom_action: :moved_project, project: project)
diff --git a/app/services/onboarding_progress_service.rb b/app/services/onboarding_progress_service.rb
index ebe7caabdef..241bd8a01ca 100644
--- a/app/services/onboarding_progress_service.rb
+++ b/app/services/onboarding_progress_service.rb
@@ -2,10 +2,12 @@
class OnboardingProgressService
def initialize(namespace)
- @namespace = namespace.root_ancestor
+ @namespace = namespace&.root_ancestor
end
def execute(action:)
- NamespaceOnboardingAction.create_action(@namespace, action)
+ return unless @namespace
+
+ OnboardingProgress.register(@namespace, action)
end
end
diff --git a/app/services/packages/create_event_service.rb b/app/services/packages/create_event_service.rb
index f0328ceb08a..63248ef07c9 100644
--- a/app/services/packages/create_event_service.rb
+++ b/app/services/packages/create_event_service.rb
@@ -3,11 +3,13 @@
module Packages
class CreateEventService < BaseService
def execute
- if Feature.enabled?(:collect_package_events_redis) && redis_event_name
- if guest?
- ::Gitlab::UsageDataCounters::GuestPackageEventCounter.count(redis_event_name)
- else
- ::Gitlab::UsageDataCounters::HLLRedisCounter.track_event(current_user.id, redis_event_name)
+ if Feature.enabled?(:collect_package_events_redis, default_enabled: true)
+ ::Packages::Event.unique_counters_for(event_scope, event_name, originator_type).each do |event_name|
+ ::Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: current_user.id)
+ end
+
+ ::Packages::Event.counters_for(event_scope, event_name, originator_type).each do |event_name|
+ ::Gitlab::UsageDataCounters::PackageEventCounter.count(event_name)
end
end
@@ -23,10 +25,6 @@ module Packages
private
- def redis_event_name
- @redis_event_name ||= ::Packages::Event.allowed_event_name(event_scope, event_name, originator_type)
- end
-
def event_scope
@event_scope ||= scope.is_a?(::Packages::Package) ? scope.package_type : scope
end
diff --git a/app/services/packages/debian/create_package_file_service.rb b/app/services/packages/debian/create_package_file_service.rb
new file mode 100644
index 00000000000..2022a63a725
--- /dev/null
+++ b/app/services/packages/debian/create_package_file_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class CreatePackageFileService
+ def initialize(package, params)
+ @package = package
+ @params = params
+ end
+
+ def execute
+ raise ArgumentError, "Invalid package" unless package.present?
+
+ # Debian package file are first uploaded to incoming with empty metadata,
+ # and are moved later by Packages::Debian::ProcessChangesService
+ package.package_files.create!(
+ file: params[:file],
+ size: params[:file]&.size,
+ file_name: params[:file_name],
+ file_sha1: params[:file_sha1],
+ file_sha256: params[:file]&.sha256,
+ file_md5: params[:file_md5],
+ debian_file_metadatum_attributes: {
+ file_type: 'unknown',
+ architecture: nil,
+ fields: nil
+ }
+ )
+ end
+
+ private
+
+ attr_reader :package, :params
+ end
+ end
+end
diff --git a/app/services/packages/debian/extract_metadata_service.rb b/app/services/packages/debian/extract_metadata_service.rb
new file mode 100644
index 00000000000..fd5832bc0ba
--- /dev/null
+++ b/app/services/packages/debian/extract_metadata_service.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class ExtractMetadataService
+ include Gitlab::Utils::StrongMemoize
+
+ ExtractionError = Class.new(StandardError)
+
+ def initialize(package_file)
+ @package_file = package_file
+ end
+
+ def execute
+ raise ExtractionError.new('invalid package file') unless valid_package_file?
+
+ extract_metadata
+ end
+
+ private
+
+ attr_reader :package_file
+
+ def valid_package_file?
+ package_file &&
+ package_file.package&.debian? &&
+ package_file.file.size > 0 # rubocop:disable Style/ZeroLengthPredicate
+ end
+
+ def file_type_basic
+ %i[dsc deb udeb buildinfo changes].each do |format|
+ return format if package_file.file_name.end_with?(".#{format}")
+ end
+
+ nil
+ end
+
+ def file_type_source
+ # https://manpages.debian.org/buster/dpkg-dev/dpkg-source.1.en.html
+ %i[gzip bzip2 lzma xz].each do |format|
+ return :source if package_file.file_name.end_with?(".tar.#{format}")
+ end
+
+ nil
+ end
+
+ def file_type
+ strong_memoize(:file_type) do
+ file_type_basic || file_type_source || :unknown
+ end
+ end
+
+ def file_type_debian?
+ file_type == :deb || file_type == :udeb
+ end
+
+ def file_type_meta?
+ file_type == :dsc || file_type == :buildinfo || file_type == :changes
+ end
+
+ def extracted_fields
+ if file_type_debian?
+ package_file.file.use_file do |file_path|
+ ::Packages::Debian::ExtractDebMetadataService.new(file_path).execute
+ end
+ elsif file_type_meta?
+ package_file.file.use_file do |file_path|
+ ::Packages::Debian::ParseDebian822Service.new(File.read(file_path)).execute.each_value.first
+ end
+ end
+ end
+
+ def extract_metadata
+ fields = extracted_fields
+ architecture = fields.delete(:Architecture) if file_type_debian?
+
+ {
+ file_type: file_type,
+ architecture: architecture,
+ fields: fields
+ }
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/get_or_create_incoming_service.rb b/app/services/packages/debian/get_or_create_incoming_service.rb
new file mode 100644
index 00000000000..09e7877a2b4
--- /dev/null
+++ b/app/services/packages/debian/get_or_create_incoming_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class GetOrCreateIncomingService < ::Packages::CreatePackageService
+ def execute
+ find_or_create_package!(:debian, name: 'incoming', version: nil)
+ end
+ end
+ end
+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 f598b5e7cd4..8ee449cbfdc 100644
--- a/app/services/packages/maven/find_or_create_package_service.rb
+++ b/app/services/packages/maven/find_or_create_package_service.rb
@@ -2,14 +2,23 @@
module Packages
module Maven
class FindOrCreatePackageService < BaseService
- MAVEN_METADATA_FILE = 'maven-metadata.xml'.freeze
- SNAPSHOT_TERM = '-SNAPSHOT'.freeze
+ MAVEN_METADATA_FILE = 'maven-metadata.xml'
+ SNAPSHOT_TERM = '-SNAPSHOT'
def execute
package =
::Packages::Maven::PackageFinder.new(params[:path], current_user, project: project)
.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
+ end
+
unless package
# Maven uploads several files during `mvn deploy` in next order:
# - my-company/my-app/1.0-SNAPSHOT/my-app.jar
@@ -48,7 +57,15 @@ module Packages
package.build_infos.safe_find_or_create_by!(pipeline: params[:build].pipeline) if params[:build].present?
- package
+ ServiceResponse.success(payload: { package: package })
+ end
+
+ private
+
+ def extname(filename)
+ return if filename.blank?
+
+ File.extname(filename)
end
end
end
diff --git a/app/services/packages/nuget/search_service.rb b/app/services/packages/nuget/search_service.rb
index b95aa30bec1..1eead1e62b3 100644
--- a/app/services/packages/nuget/search_service.rb
+++ b/app/services/packages/nuget/search_service.rb
@@ -3,6 +3,7 @@
module Packages
module Nuget
class SearchService < BaseService
+ include ::Packages::FinderHelper
include Gitlab::Utils::StrongMemoize
include ActiveRecord::ConnectionAdapters::Quoting
@@ -16,8 +17,9 @@ module Packages
padding: 0
}.freeze
- def initialize(project, search_term, options = {})
- @project = project
+ def initialize(current_user, project_or_group, search_term, options = {})
+ @current_user = current_user
+ @project_or_group = project_or_group
@search_term = search_term
@options = DEFAULT_OPTIONS.merge(options)
@@ -26,8 +28,8 @@ module Packages
end
def execute
- OpenStruct.new(
- total_count: package_names.total_count,
+ Result.new(
+ total_count: non_paginated_matching_package_names.count,
results: search_packages
)
end
@@ -39,52 +41,104 @@ module Packages
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24182#technical-notes
# and https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
subquery_name = :partition_subquery
- arel_table = Arel::Table.new(:partition_subquery)
+ arel_table = Arel::Table.new(subquery_name)
column_names = Packages::Package.column_names.map do |cn|
"#{subquery_name}.#{quote_column_name(cn)}"
end
# rubocop: disable CodeReuse/ActiveRecord
- pkgs = Packages::Package.select(column_names.join(','))
- .from(package_names_partition, subquery_name)
- .where(arel_table[:row_number].lteq(MAX_VERSIONS_PER_PACKAGE))
+ pkgs = Packages::Package
+ pkgs = pkgs.with(project_ids_cte.to_arel) if use_project_ids_cte?
+ pkgs = pkgs.select(column_names.join(','))
+ .from(package_names_partition, subquery_name)
+ .where(arel_table[:row_number].lteq(MAX_VERSIONS_PER_PACKAGE))
return pkgs if include_prerelease_versions?
# we can't use pkgs.without_version_like since we have a custom from
pkgs.where.not(arel_table[:version].matches(PRE_RELEASE_VERSION_MATCHING_TERM))
+ # rubocop: enable CodeReuse/ActiveRecord
end
def package_names_partition
+ # rubocop: disable CodeReuse/ActiveRecord
table_name = quote_table_name(Packages::Package.table_name)
name_column = "#{table_name}.#{quote_column_name('name')}"
created_at_column = "#{table_name}.#{quote_column_name('created_at')}"
select_sql = "ROW_NUMBER() OVER (PARTITION BY #{name_column} ORDER BY #{created_at_column} DESC) AS row_number, #{table_name}.*"
- @project.packages
- .select(select_sql)
- .nuget
- .has_version
- .without_nuget_temporary_name
- .with_name(package_names)
+ nuget_packages.select(select_sql)
+ .with_name(paginated_matching_package_names)
+ .where(project_id: project_ids)
+ # rubocop: enable CodeReuse/ActiveRecord
end
- def package_names
- strong_memoize(:package_names) do
- pkgs = @project.packages
- .nuget
- .has_version
- .without_nuget_temporary_name
- .order_name
- .select_distinct_name
+ def paginated_matching_package_names
+ pkgs = base_matching_package_names
+ pkgs.page(0) # we're using a padding
+ .per(per_page)
+ .padding(padding)
+ end
+
+ def non_paginated_matching_package_names
+ # rubocop: disable CodeReuse/ActiveRecord
+ pkgs = base_matching_package_names
+ pkgs = pkgs.with(project_ids_cte.to_arel) if use_project_ids_cte?
+ pkgs
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ def base_matching_package_names
+ strong_memoize(:base_matching_package_names) do
+ # rubocop: disable CodeReuse/ActiveRecord
+ pkgs = nuget_packages.order_name
+ .select_distinct_name
+ .where(project_id: project_ids)
pkgs = pkgs.without_version_like(PRE_RELEASE_VERSION_MATCHING_TERM) unless include_prerelease_versions?
pkgs = pkgs.search_by_name(@search_term) if @search_term.present?
- pkgs.page(0) # we're using a padding
- .per(per_page)
- .padding(padding)
+ pkgs
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
+ def nuget_packages
+ Packages::Package.nuget
+ .has_version
+ .without_nuget_temporary_name
+ end
+
+ def project_ids_cte
+ return unless use_project_ids_cte?
+
+ strong_memoize(:project_ids_cte) do
+ query = projects_visible_to_user(@current_user, within_group: @project_or_group)
+ Gitlab::SQL::CTE.new(:project_ids, query.select(:id))
+ end
+ end
+
+ def project_ids
+ return @project_or_group.id if project?
+
+ if use_project_ids_cte?
+ # rubocop: disable CodeReuse/ActiveRecord
+ Project.select(:id)
+ .from(project_ids_cte.table)
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+
+ def use_project_ids_cte?
+ group?
+ end
+
+ def project?
+ @project_or_group.is_a?(::Project)
+ end
+
+ def group?
+ @project_or_group.is_a?(::Group)
+ end
+
def include_prerelease_versions?
@options[:include_prerelease_versions]
end
@@ -96,6 +150,12 @@ module Packages
def per_page
[@options[:per_page], MAX_PER_PAGE].min
end
+
+ class Result
+ include ActiveModel::Model
+
+ attr_accessor :results, :total_count
+ end
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
new file mode 100644
index 00000000000..dac994b2ccc
--- /dev/null
+++ b/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Pages
+ class MigrateLegacyStorageToDeploymentService
+ ExclusiveLeaseTakenError = Class.new(StandardError)
+
+ include BaseServiceUtility
+ include ::Pages::LegacyStorageLease
+
+ attr_reader :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ result = try_obtain_lease do
+ execute_unsafe
+ end
+
+ raise ExclusiveLeaseTakenError, "Can't migrate pages for project #{project.id}: exclusive lease taken" if result.nil?
+
+ result
+ end
+
+ private
+
+ def execute_unsafe
+ zip_result = ::Pages::ZipDirectoryService.new(project.pages_path).execute
+
+ if zip_result[:status] == :error
+ if !project.pages_metadatum&.reload&.pages_deployment &&
+ Feature.enabled?(:pages_migration_mark_as_not_deployed, project)
+ project.mark_pages_as_not_deployed
+ end
+
+ return error("Can't create zip archive: #{zip_result[:message]}")
+ end
+
+ archive_path = zip_result[:archive_path]
+
+ deployment = nil
+ File.open(archive_path) do |file|
+ deployment = project.pages_deployments.create!(
+ file: file,
+ file_count: zip_result[:entries_count],
+ file_sha256: Digest::SHA256.file(archive_path).hexdigest
+ )
+ end
+
+ project.set_first_pages_deployment!(deployment)
+
+ success
+ ensure
+ FileUtils.rm_f(archive_path) if archive_path
+ end
+ end
+end
diff --git a/app/services/pages/zip_directory_service.rb b/app/services/pages/zip_directory_service.rb
index a27ad5fda46..ba7a8571e88 100644
--- a/app/services/pages/zip_directory_service.rb
+++ b/app/services/pages/zip_directory_service.rb
@@ -2,37 +2,43 @@
module Pages
class ZipDirectoryService
- InvalidArchiveError = Class.new(RuntimeError)
- InvalidEntryError = Class.new(RuntimeError)
+ include BaseServiceUtility
+ include Gitlab::Utils::StrongMemoize
+
+ # used only to track exceptions in Sentry
+ InvalidEntryError = Class.new(StandardError)
PUBLIC_DIR = 'public'
def initialize(input_dir)
- @input_dir = File.realpath(input_dir)
- @output_file = File.join(@input_dir, "@migrated.zip") # '@' to avoid any name collision with groups or projects
+ @input_dir = input_dir
end
def execute
- FileUtils.rm_f(@output_file)
+ return error("Can not find valid public dir in #{@input_dir}") unless valid_path?(public_dir)
+
+ output_file = File.join(real_dir, "@migrated.zip") # '@' to avoid any name collision with groups or projects
+
+ FileUtils.rm_f(output_file)
- count = 0
- ::Zip::File.open(@output_file, ::Zip::File::CREATE) do |zipfile|
+ entries_count = 0
+ ::Zip::File.open(output_file, ::Zip::File::CREATE) do |zipfile|
write_entry(zipfile, PUBLIC_DIR)
- count = zipfile.entries.count
+ entries_count = zipfile.entries.count
end
- [@output_file, count]
+ success(archive_path: output_file, entries_count: entries_count)
+ rescue => e
+ FileUtils.rm_f(output_file) if output_file
+ raise e
end
private
def write_entry(zipfile, zipfile_path)
- disk_file_path = File.join(@input_dir, zipfile_path)
+ disk_file_path = File.join(real_dir, zipfile_path)
unless valid_path?(disk_file_path)
- # archive without public directory is completelly unusable
- raise InvalidArchiveError if zipfile_path == PUBLIC_DIR
-
# archive with invalid entry will just have this entry missing
raise InvalidEntryError
end
@@ -71,13 +77,24 @@ module Pages
def valid_path?(disk_file_path)
realpath = File.realpath(disk_file_path)
- realpath == File.join(@input_dir, PUBLIC_DIR) ||
- realpath.start_with?(File.join(@input_dir, PUBLIC_DIR + "/"))
+ 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: @input_dir, disk_file_path: disk_file_path)
+ 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/post_receive_service.rb b/app/services/post_receive_service.rb
index bd9588844ad..84d9db5435b 100644
--- a/app/services/post_receive_service.rb
+++ b/app/services/post_receive_service.rb
@@ -94,7 +94,7 @@ class PostReceiveService
end
def record_onboarding_progress
- NamespaceOnboardingAction.create_action(project.namespace, :git_write)
+ OnboardingProgressService.new(project.namespace).execute(action: :git_write)
end
end
diff --git a/app/services/projects/after_import_service.rb b/app/services/projects/after_import_service.rb
index b37ae56ba0f..bb0d084d191 100644
--- a/app/services/projects/after_import_service.rb
+++ b/app/services/projects/after_import_service.rb
@@ -9,7 +9,7 @@ module Projects
end
def execute
- service = Projects::HousekeepingService.new(@project)
+ service = Repositories::HousekeepingService.new(@project)
service.execute do
import_failure_service.with_retry(action: 'delete_all_refs') do
@@ -21,7 +21,7 @@ module Projects
# import actually changed, so we increment the counter to avoid
# causing GC to run every time.
service.increment!
- rescue Projects::HousekeepingService::LeaseTaken => e
+ rescue Repositories::HousekeepingService::LeaseTaken => e
Gitlab::Import::Logger.info(
message: 'Project housekeeping failed',
project_full_path: @project.full_path,
diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb
index b8047a1ad71..af0107436c8 100644
--- a/app/services/projects/container_repository/cleanup_tags_service.rb
+++ b/app/services/projects/container_repository/cleanup_tags_service.rb
@@ -8,12 +8,26 @@ module Projects
return error('invalid regex') unless valid_regex?
tags = container_repository.tags
+ original_size = tags.size
+
tags = without_latest(tags)
tags = filter_by_name(tags)
+
+ before_truncate_size = tags.size
+ tags = truncate(tags)
+ after_truncate_size = tags.size
+
tags = filter_keep_n(tags)
tags = filter_by_older_than(tags)
- delete_tags(container_repository, tags)
+ delete_tags(container_repository, tags).tap do |result|
+ result[:original_size] = original_size
+ result[:before_truncate_size] = before_truncate_size
+ result[:after_truncate_size] = after_truncate_size
+ result[:before_delete_size] = tags.size
+
+ result[:status] = :error if before_truncate_size != after_truncate_size
+ end
end
private
@@ -23,12 +37,14 @@ module Projects
tag_names = tags.map(&:name)
- Projects::ContainerRepository::DeleteTagsService
- .new(container_repository.project,
- current_user,
- tags: tag_names,
- container_expiration_policy: params['container_expiration_policy'])
- .execute(container_repository)
+ service = Projects::ContainerRepository::DeleteTagsService.new(
+ container_repository.project,
+ current_user,
+ tags: tag_names,
+ container_expiration_policy: params['container_expiration_policy']
+ )
+
+ service.execute(container_repository)
end
def without_latest(tags)
@@ -54,7 +70,7 @@ module Projects
return tags unless params['keep_n']
tags = order_by_date(tags)
- tags.drop(params['keep_n'].to_i)
+ tags.drop(keep_n)
end
def filter_by_older_than(tags)
@@ -83,6 +99,31 @@ module Projects
::Gitlab::ErrorTracking.log_exception(e, project_id: project.id)
false
end
+
+ def truncate(tags)
+ return tags unless throttling_enabled?
+ return tags if max_list_size == 0
+
+ # truncate the list to make sure that after the #filter_keep_n
+ # execution, the resulting list will be max_list_size
+ truncated_size = max_list_size + keep_n
+
+ return tags if tags.size <= truncated_size
+
+ tags.sample(truncated_size)
+ end
+
+ def throttling_enabled?
+ Feature.enabled?(:container_registry_expiration_policies_throttling)
+ end
+
+ def max_list_size
+ ::Gitlab::CurrentSettings.current_application_settings.container_registry_cleanup_tags_service_max_list_size.to_i
+ end
+
+ def keep_n
+ params['keep_n'].to_i
+ end
end
end
end
diff --git a/app/services/projects/container_repository/gitlab/delete_tags_service.rb b/app/services/projects/container_repository/gitlab/delete_tags_service.rb
index e4e22dd9543..589aac5c3ac 100644
--- a/app/services/projects/container_repository/gitlab/delete_tags_service.rb
+++ b/app/services/projects/container_repository/gitlab/delete_tags_service.rb
@@ -24,9 +24,9 @@ module Projects
return success(deleted: []) if @tag_names.empty?
delete_tags
- rescue TimeoutError => e
+ rescue TimeoutError, ::Faraday::Error => e
::Gitlab::ErrorTracking.track_exception(e, tags_count: @tag_names&.size, container_repository_id: @container_repository&.id)
- error('timeout while deleting tags', nil, pass_back: { deleted: @deleted_tags })
+ error('error while deleting tags', nil, pass_back: { deleted: @deleted_tags, exception_class_name: e.class.name })
end
private
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 0b4963e356a..050bfdd862d 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -34,11 +34,6 @@ module Projects
new_project = CreateService.new(current_user, new_fork_params).execute
return new_project unless new_project.persisted?
- # Set the forked_from_project relation after saving to avoid having to
- # reload the project to reset the association information and cause an
- # extra query.
- new_project.forked_from_project = @project
-
builds_access_level = @project.project_feature.builds_access_level
new_project.project_feature.update(builds_access_level: builds_access_level)
@@ -47,6 +42,7 @@ module Projects
def new_fork_params
new_params = {
+ forked_from_project: @project,
visibility_level: allowed_visibility_level,
description: @project.description,
name: target_name,
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index 9428575591e..b5589d556aa 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -1,107 +1,16 @@
# frozen_string_literal: true
-# Projects::HousekeepingService class
+# This is a compatibility class to avoid calling a non-existent
+# class from sidekiq during deployment.
#
-# Used for git housekeeping
+# We're deploying the rename of this class in 13.9. Nevertheless,
+# we cannot remove this class entirely because there can be jobs
+# referencing it.
#
-# Ex.
-# Projects::HousekeepingService.new(project).execute
+# We can get rid of this class in 13.10
+# https://gitlab.com/gitlab-org/gitlab/-/issues/297580
#
module Projects
- class HousekeepingService < BaseService
- # Timeout set to 24h
- LEASE_TIMEOUT = 86400
- PACK_REFS_PERIOD = 6
-
- class LeaseTaken < StandardError
- def to_s
- "Somebody already triggered housekeeping for this project in the past #{LEASE_TIMEOUT / 60} minutes"
- end
- end
-
- def initialize(project, task = nil)
- @project = project
- @task = task
- end
-
- def execute
- lease_uuid = try_obtain_lease
- raise LeaseTaken unless lease_uuid.present?
-
- yield if block_given?
-
- execute_gitlab_shell_gc(lease_uuid)
- end
-
- def needed?
- pushes_since_gc > 0 && period_match? && housekeeping_enabled?
- end
-
- def increment!
- Gitlab::Metrics.measure(:increment_pushes_since_gc) do
- @project.increment_pushes_since_gc
- end
- end
-
- private
-
- def execute_gitlab_shell_gc(lease_uuid)
- GitGarbageCollectWorker.perform_async(@project.id, task, lease_key, lease_uuid)
- ensure
- if pushes_since_gc >= gc_period
- Gitlab::Metrics.measure(:reset_pushes_since_gc) do
- @project.reset_pushes_since_gc
- end
- end
- end
-
- def try_obtain_lease
- Gitlab::Metrics.measure(:obtain_housekeeping_lease) do
- lease = ::Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT)
- lease.try_obtain
- end
- end
-
- def lease_key
- "project_housekeeping:#{@project.id}"
- end
-
- def pushes_since_gc
- @project.pushes_since_gc
- end
-
- def task
- return @task if @task
-
- if pushes_since_gc % gc_period == 0
- :gc
- elsif pushes_since_gc % full_repack_period == 0
- :full_repack
- elsif pushes_since_gc % repack_period == 0
- :incremental_repack
- else
- :pack_refs
- end
- end
-
- def period_match?
- [gc_period, full_repack_period, repack_period, PACK_REFS_PERIOD].any? { |period| pushes_since_gc % period == 0 }
- end
-
- def housekeeping_enabled?
- Gitlab::CurrentSettings.housekeeping_enabled
- end
-
- def gc_period
- Gitlab::CurrentSettings.housekeeping_gc_period
- end
-
- def full_repack_period
- Gitlab::CurrentSettings.housekeeping_full_repack_period
- end
-
- def repack_period
- Gitlab::CurrentSettings.housekeeping_incremental_repack_period
- end
+ class HousekeepingService < ::Repositories::HousekeepingService
end
end
diff --git a/app/services/projects/schedule_bulk_repository_shard_moves_service.rb b/app/services/projects/schedule_bulk_repository_shard_moves_service.rb
index dd49910207f..53de9abdb59 100644
--- a/app/services/projects/schedule_bulk_repository_shard_moves_service.rb
+++ b/app/services/projects/schedule_bulk_repository_shard_moves_service.rb
@@ -3,33 +3,29 @@
module Projects
# Tries to schedule a move for every project with repositories on the source shard
class ScheduleBulkRepositoryShardMovesService
- include BaseServiceUtility
+ include ScheduleBulkRepositoryShardMovesMethods
+ extend ::Gitlab::Utils::Override
- def execute(source_storage_name, destination_storage_name = nil)
- shard = Shard.find_by_name!(source_storage_name)
+ private
- ProjectRepository.for_shard(shard).each_batch(column: :project_id) do |relation|
- Project.id_in(relation.select(:project_id)).each do |project|
- project.with_lock do
- next if project.repository_storage != source_storage_name
-
- storage_move = project.repository_storage_moves.build(
- source_storage_name: source_storage_name,
- destination_storage_name: destination_storage_name
- )
+ override :repository_klass
+ def repository_klass
+ ProjectRepository
+ end
- unless storage_move.schedule
- log_info("Project #{project.full_path} (#{project.id}) was skipped: #{storage_move.errors.full_messages.to_sentence}")
- end
- end
- end
- end
+ override :container_klass
+ def container_klass
+ Project
+ end
- success
+ override :container_column
+ def container_column
+ :project_id
end
- def self.enqueue(source_storage_name, destination_storage_name = nil)
- ::ProjectScheduleBulkRepositoryShardMovesWorker.perform_async(source_storage_name, destination_storage_name)
+ override :schedule_bulk_worker_klass
+ def self.schedule_bulk_worker_klass
+ ::ProjectScheduleBulkRepositoryShardMovesWorker
end
end
end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 1574c90d2ac..8a5e0706126 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -37,7 +37,7 @@ module Projects
private
- attr_reader :old_path, :new_path, :new_namespace
+ attr_reader :old_path, :new_path, :new_namespace, :old_namespace
# rubocop: disable CodeReuse/ActiveRecord
def transfer(project)
@@ -96,7 +96,7 @@ module Projects
execute_system_hooks
end
- move_pages(project)
+ post_update_hooks(project)
rescue Exception # rubocop:disable Lint/RescueException
rollback_side_effects
raise
@@ -104,6 +104,11 @@ module Projects
refresh_permissions
end
+ # Overridden in EE
+ def post_update_hooks(project)
+ move_pages(project)
+ end
+
def transfer_missing_group_resources(group)
Labels::TransferService.new(current_user, group, project).execute
diff --git a/app/services/projects/unlink_fork_service.rb b/app/services/projects/unlink_fork_service.rb
index 52aea8c51a5..6ba3356d612 100644
--- a/app/services/projects/unlink_fork_service.rb
+++ b/app/services/projects/unlink_fork_service.rb
@@ -9,6 +9,8 @@ module Projects
return unless fork_network
+ log_info(message: "UnlinkForkService: Unlinking fork network", fork_network_id: fork_network.id)
+
merge_requests = fork_network
.merge_requests
.opened
@@ -16,6 +18,7 @@ module Projects
merge_requests.find_each do |mr|
::MergeRequests::CloseService.new(@project, @current_user).execute(mr)
+ log_info(message: "UnlinkForkService: Closed merge request", merge_request_id: mr.id)
end
Project.transaction do
@@ -31,6 +34,16 @@ module Projects
end
end
+ # rubocop: disable Cop/InBatches
+ Project.uncached do
+ @project.forked_to_members.in_batches do |fork_relation|
+ fork_relation.pluck(:id).each do |fork_id| # rubocop: disable CodeReuse/ActiveRecord
+ log_info(message: "UnlinkForkService: Unlinked fork of root_project", project_id: @project.id, forked_project_id: fork_id)
+ end
+ end
+ end
+ # rubocop: enable Cop/InBatches
+
# When the project getting out of the network is a node with parent
# and children, both the parent and the node needs a cache refresh.
[forked_from, @project].compact.each do |project|
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 53872c67f49..25d46ada885 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -37,16 +37,11 @@ module Projects
raise InvalidStateError, 'missing pages artifacts' unless build.artifacts?
raise InvalidStateError, 'build SHA is outdated for this ref' unless latest?
- # Create temporary directory in which we will extract the artifacts
- make_secure_tmp_dir(tmp_path) do |archive_path|
- extract_archive!(archive_path)
+ build.artifacts_file.use_file do |artifacts_path|
+ deploy_to_legacy_storage(artifacts_path)
- # Check if we did extract public directory
- archive_public_path = File.join(archive_path, PUBLIC_DIR)
- raise InvalidStateError, 'pages miss the public folder' unless Dir.exist?(archive_public_path)
- raise InvalidStateError, 'build SHA is outdated for this ref' unless latest?
+ create_pages_deployment(artifacts_path, build)
- deploy_page!(archive_public_path)
success
end
rescue InvalidStateError => e
@@ -84,15 +79,29 @@ module Projects
)
end
- def extract_archive!(temp_path)
+ def deploy_to_legacy_storage(artifacts_path)
+ # 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)
+
+ # Check if we did extract public directory
+ archive_public_path = File.join(tmp_path, PUBLIC_DIR)
+ raise InvalidStateError, 'pages miss the public folder' unless Dir.exist?(archive_public_path)
+ raise InvalidStateError, 'build SHA is outdated for this ref' unless latest?
+
+ deploy_page!(archive_public_path)
+ end
+ end
+
+ def extract_archive!(artifacts_path, temp_path)
if artifacts.ends_with?('.zip')
- extract_zip_archive!(temp_path)
+ extract_zip_archive!(artifacts_path, temp_path)
else
raise InvalidStateError, 'unsupported artifacts format'
end
end
- def extract_zip_archive!(temp_path)
+ def extract_zip_archive!(artifacts_path, temp_path)
raise InvalidStateError, 'missing artifacts metadata' unless build.artifacts_metadata?
# Calculate page size after extract
@@ -102,11 +111,8 @@ module Projects
raise InvalidStateError, "artifacts for pages are too large: #{public_entry.total_size}"
end
- build.artifacts_file.use_file do |artifacts_path|
- SafeZip::Extract.new(artifacts_path)
- .extract(directories: [PUBLIC_DIR], to: temp_path)
- create_pages_deployment(artifacts_path, build)
- end
+ SafeZip::Extract.new(artifacts_path)
+ .extract(directories: [PUBLIC_DIR], to: temp_path)
rescue SafeZip::Extract::Error => e
raise FailedToExtractError, e.message
end
@@ -150,6 +156,9 @@ module Projects
deployment = project.pages_deployments.create!(file: file,
file_count: entries_count,
file_sha256: sha256)
+
+ raise InvalidStateError, 'build SHA is outdated for this ref' unless latest?
+
project.update_pages_deployment!(deployment)
end
diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb
index e0d2398bc66..7c63216af5e 100644
--- a/app/services/projects/update_repository_storage_service.rb
+++ b/app/services/projects/update_repository_storage_service.rb
@@ -2,59 +2,19 @@
module Projects
class UpdateRepositoryStorageService
- Error = Class.new(StandardError)
- SameFilesystemError = Class.new(Error)
+ include UpdateRepositoryStorageMethods
- attr_reader :repository_storage_move
- delegate :project, :source_storage_name, :destination_storage_name, to: :repository_storage_move
-
- def initialize(repository_storage_move)
- @repository_storage_move = repository_storage_move
- end
-
- def execute
- repository_storage_move.with_lock do
- return ServiceResponse.success unless repository_storage_move.scheduled? # rubocop:disable Cop/AvoidReturnFromBlocks
-
- repository_storage_move.start!
- end
-
- raise SameFilesystemError if same_filesystem?(source_storage_name, destination_storage_name)
-
- mirror_repositories
-
- repository_storage_move.transaction do
- repository_storage_move.finish_replication!
-
- project.leave_pool_repository
- project.track_project_repository
- end
-
- remove_old_paths
- enqueue_housekeeping
-
- repository_storage_move.finish_cleanup!
-
- ServiceResponse.success
-
- rescue StandardError => e
- repository_storage_move.do_fail!
-
- Gitlab::ErrorTracking.track_exception(e, project_path: project.full_path)
-
- ServiceResponse.error(
- message: s_("UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}") % { project_full_path: project.full_path, message: e.message }
- )
- end
+ delegate :project, to: :repository_storage_move
private
- def same_filesystem?(old_storage, new_storage)
- Gitlab::GitalyClient.filesystem_id(old_storage) == Gitlab::GitalyClient.filesystem_id(new_storage)
+ def track_repository(_destination_storage_name)
+ project.leave_pool_repository
+ project.track_project_repository
end
def mirror_repositories
- mirror_repository if project.repository_exists?
+ mirror_repository(type: Gitlab::GlRepository::PROJECT) if project.repository_exists?
if project.wiki.repository_exists?
mirror_repository(type: Gitlab::GlRepository::WIKI)
@@ -65,41 +25,21 @@ module Projects
end
end
- def mirror_repository(type: Gitlab::GlRepository::PROJECT)
- unless wait_for_pushes(type)
- raise Error, s_('UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes') % { type: type.name }
- end
-
- repository = type.repository_for(project)
- full_path = repository.full_path
- raw_repository = repository.raw
- checksum = repository.checksum
-
- # Initialize a git repository on the target path
- new_repository = Gitlab::Git::Repository.new(
- destination_storage_name,
- raw_repository.relative_path,
- raw_repository.gl_repository,
- full_path
- )
-
- new_repository.replicate(raw_repository)
- new_checksum = new_repository.checksum
+ # The underlying FetchInternalRemote call uses a `git fetch` to move data
+ # to the new repository, which leaves it in a less-well-packed state,
+ # lacking bitmaps and commit graphs. Housekeeping will boost performance
+ # significantly.
+ def enqueue_housekeeping
+ return unless Gitlab::CurrentSettings.housekeeping_enabled?
+ return unless Feature.enabled?(:repack_after_shard_migration, project)
- if checksum != new_checksum
- raise Error, s_('UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}') % { type: type.name, old: checksum, new: new_checksum }
- end
+ Repositories::HousekeepingService.new(project, :gc).execute
+ rescue Repositories::HousekeepingService::LeaseTaken
+ # No action required
end
def remove_old_paths
- if project.repository_exists?
- Gitlab::Git::Repository.new(
- source_storage_name,
- "#{project.disk_path}.git",
- nil,
- nil
- ).remove
- end
+ super
if project.wiki.repository_exists?
Gitlab::Git::Repository.new(
@@ -119,31 +59,5 @@ module Projects
).remove
end
end
-
- # The underlying FetchInternalRemote call uses a `git fetch` to move data
- # to the new repository, which leaves it in a less-well-packed state,
- # lacking bitmaps and commit graphs. Housekeeping will boost performance
- # significantly.
- def enqueue_housekeeping
- return unless Gitlab::CurrentSettings.housekeeping_enabled?
- return unless Feature.enabled?(:repack_after_shard_migration, project)
-
- Projects::HousekeepingService.new(project, :gc).execute
- rescue Projects::HousekeepingService::LeaseTaken
- # No action required
- end
-
- def wait_for_pushes(type)
- reference_counter = project.reference_counter(type: type)
-
- # Try for 30 seconds, polling every 10
- 3.times do
- return true if reference_counter.value == 0
-
- sleep 10
- end
-
- false
- end
end
end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index d44f5e637f1..50a544ed1a5 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -87,11 +87,6 @@ module Projects
system_hook_service.execute_hooks_for(project, :update)
end
- if project.visibility_level_decreased? && project.unlink_forks_upon_visibility_decrease_enabled?
- # It's a system-bounded operation, so no extra authorization check is required.
- Projects::UnlinkForkService.new(project, current_user).execute
- end
-
update_pages_config if changing_pages_related_config?
end
diff --git a/app/services/repositories/housekeeping_service.rb b/app/services/repositories/housekeeping_service.rb
new file mode 100644
index 00000000000..6a2fa95d25f
--- /dev/null
+++ b/app/services/repositories/housekeeping_service.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+# Used for git housekeeping
+#
+# Ex.
+# Repositories::HousekeepingService.new(project).execute
+# Repositories::HousekeepingService.new(project.wiki).execute
+#
+module Repositories
+ class HousekeepingService < BaseService
+ # Timeout set to 24h
+ LEASE_TIMEOUT = 86400
+ PACK_REFS_PERIOD = 6
+
+ class LeaseTaken < StandardError
+ def to_s
+ "Somebody already triggered housekeeping for this resource in the past #{LEASE_TIMEOUT / 60} minutes"
+ end
+ end
+
+ def initialize(resource, task = nil)
+ @resource = resource
+ @task = task
+ end
+
+ def execute
+ lease_uuid = try_obtain_lease
+ raise LeaseTaken unless lease_uuid.present?
+
+ yield if block_given?
+
+ execute_gitlab_shell_gc(lease_uuid)
+ end
+
+ def needed?
+ pushes_since_gc > 0 && period_match? && housekeeping_enabled?
+ end
+
+ def increment!
+ Gitlab::Metrics.measure(:increment_pushes_since_gc) do
+ @resource.increment_pushes_since_gc
+ end
+ end
+
+ private
+
+ def execute_gitlab_shell_gc(lease_uuid)
+ GitGarbageCollectWorker.perform_async(@resource.id, task, lease_key, lease_uuid)
+ ensure
+ if pushes_since_gc >= gc_period
+ Gitlab::Metrics.measure(:reset_pushes_since_gc) do
+ @resource.reset_pushes_since_gc
+ end
+ end
+ end
+
+ def try_obtain_lease
+ Gitlab::Metrics.measure(:obtain_housekeeping_lease) do
+ lease = ::Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT)
+ lease.try_obtain
+ end
+ end
+
+ def lease_key
+ "#{@resource.class.name.underscore.pluralize}_housekeeping:#{@resource.id}"
+ end
+
+ def pushes_since_gc
+ @resource.pushes_since_gc
+ end
+
+ def task
+ return @task if @task
+
+ if pushes_since_gc % gc_period == 0
+ :gc
+ elsif pushes_since_gc % full_repack_period == 0
+ :full_repack
+ elsif pushes_since_gc % repack_period == 0
+ :incremental_repack
+ else
+ :pack_refs
+ end
+ end
+
+ def period_match?
+ [gc_period, full_repack_period, repack_period, PACK_REFS_PERIOD].any? { |period| pushes_since_gc % period == 0 }
+ end
+
+ def housekeeping_enabled?
+ Gitlab::CurrentSettings.housekeeping_enabled
+ end
+
+ def gc_period
+ Gitlab::CurrentSettings.housekeeping_gc_period
+ end
+
+ def full_repack_period
+ Gitlab::CurrentSettings.housekeeping_full_repack_period
+ end
+
+ def repack_period
+ Gitlab::CurrentSettings.housekeeping_incremental_repack_period
+ end
+ end
+end
diff --git a/app/services/resource_events/change_state_service.rb b/app/services/resource_events/change_state_service.rb
index cd6d82df46f..c5120ba82e1 100644
--- a/app/services/resource_events/change_state_service.rb
+++ b/app/services/resource_events/change_state_service.rb
@@ -19,7 +19,7 @@ module ResourceEvents
state: ResourceStateEvent.states[state],
close_after_error_tracking_resolve: close_after_error_tracking_resolve,
close_auto_resolve_prometheus_alert: close_auto_resolve_prometheus_alert,
- created_at: Time.zone.now
+ created_at: resource.system_note_timestamp
)
resource.expire_note_etag_cache
diff --git a/app/services/serverless/associate_domain_service.rb b/app/services/serverless/associate_domain_service.rb
index 673f1f83260..0c6ee58924c 100644
--- a/app/services/serverless/associate_domain_service.rb
+++ b/app/services/serverless/associate_domain_service.rb
@@ -2,7 +2,7 @@
module Serverless
class AssociateDomainService
- PLACEHOLDER_HOSTNAME = 'example.com'.freeze
+ PLACEHOLDER_HOSTNAME = 'example.com'
def initialize(knative, pages_domain_id:, creator:)
@knative = knative
diff --git a/app/services/service_desk_settings/update_service.rb b/app/services/service_desk_settings/update_service.rb
index 32d1c5c1c87..5fe74f1f2ff 100644
--- a/app/services/service_desk_settings/update_service.rb
+++ b/app/services/service_desk_settings/update_service.rb
@@ -5,10 +5,6 @@ module ServiceDeskSettings
def execute
settings = ServiceDeskSetting.safe_find_or_create_by!(project_id: project.id)
- unless ::Feature.enabled?(:service_desk_custom_address, project, default_enabled: true)
- params.delete(:project_key)
- end
-
params[:project_key] = nil if params[:project_key].blank?
if settings.update(params)
diff --git a/app/services/snippets/schedule_bulk_repository_shard_moves_service.rb b/app/services/snippets/schedule_bulk_repository_shard_moves_service.rb
new file mode 100644
index 00000000000..f7bdd0a99a5
--- /dev/null
+++ b/app/services/snippets/schedule_bulk_repository_shard_moves_service.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Snippets
+ # Tries to schedule a move for every snippet with repositories on the source shard
+ class ScheduleBulkRepositoryShardMovesService
+ include ScheduleBulkRepositoryShardMovesMethods
+ extend ::Gitlab::Utils::Override
+
+ private
+
+ override :repository_klass
+ def repository_klass
+ SnippetRepository
+ end
+
+ override :container_klass
+ def container_klass
+ Snippet
+ end
+
+ override :container_column
+ def container_column
+ :snippet_id
+ end
+
+ override :schedule_bulk_worker_klass
+ def self.schedule_bulk_worker_klass
+ ::SnippetScheduleBulkRepositoryShardMovesWorker
+ end
+ end
+end
diff --git a/app/services/snippets/update_repository_storage_service.rb b/app/services/snippets/update_repository_storage_service.rb
new file mode 100644
index 00000000000..3addae3b3be
--- /dev/null
+++ b/app/services/snippets/update_repository_storage_service.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Snippets
+ class UpdateRepositoryStorageService
+ include UpdateRepositoryStorageMethods
+
+ delegate :snippet, to: :repository_storage_move
+
+ private
+
+ def track_repository(destination_storage_name)
+ snippet.track_snippet_repository(destination_storage_name)
+ end
+
+ def mirror_repositories
+ return unless snippet.repository_exists?
+
+ mirror_repository(type: Gitlab::GlRepository::SNIPPET)
+ end
+ end
+end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 0eb099753cb..12d26fe890b 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -216,7 +216,7 @@ class TodoService
def create_todos(users, attributes)
Array(users).map do |user|
- next if pending_todos(user, attributes).exists?
+ next if pending_todos(user, attributes).exists? && Feature.disabled?(:multiple_todos, user)
issue_type = attributes.delete(:issue_type)
track_todo_creation(user, issue_type)
@@ -278,7 +278,7 @@ class TodoService
create_todos(directly_addressed_users, attributes)
# Create Todos for mentioned users
- mentioned_users = filter_mentioned_users(parent, note || target, author, skip_users)
+ mentioned_users = filter_mentioned_users(parent, note || target, author, skip_users + directly_addressed_users)
attributes = attributes_for_todo(parent, target, author, Todo::MENTIONED, note)
create_todos(mentioned_users, attributes)
end
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index aef07b13cae..5a51b42f9f9 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -54,7 +54,9 @@ class WebHookService
http_status: response.code,
message: response.to_s
}
- rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep, Gitlab::Json::LimitedEncoder::LimitExceeded => e
+ rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
+ Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep,
+ Gitlab::Json::LimitedEncoder::LimitExceeded, URI::InvalidURIError => e
execution_duration = Gitlab::Metrics::System.monotonic_time - start_time
log_execution(
trigger: hook_name,
diff --git a/app/uploaders/packages/debian/distribution_release_file_uploader.rb b/app/uploaders/packages/debian/distribution_release_file_uploader.rb
new file mode 100644
index 00000000000..9a30aac6396
--- /dev/null
+++ b/app/uploaders/packages/debian/distribution_release_file_uploader.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+class Packages::Debian::DistributionReleaseFileUploader < GitlabUploader
+ extend Workhorse::UploadPath
+ include ObjectStorage::Concern
+
+ storage_options Gitlab.config.packages
+
+ after :store, :schedule_background_upload
+
+ alias_method :upload, :model
+
+ def filename
+ 'Release'
+ end
+
+ def store_dir
+ dynamic_segment
+ end
+
+ private
+
+ def dynamic_segment
+ raise ObjectNotReadyError, 'Package model not ready' unless model.id
+
+ Gitlab::HashedPath.new("debian_#{model.class.container_type}_distribution", model.id, root_hash: model.container_id)
+ end
+end
diff --git a/app/uploaders/packages/package_file_uploader.rb b/app/uploaders/packages/package_file_uploader.rb
index 61fbe2b4c49..4b6dbe5b358 100644
--- a/app/uploaders/packages/package_file_uploader.rb
+++ b/app/uploaders/packages/package_file_uploader.rb
@@ -22,6 +22,8 @@ class Packages::PackageFileUploader < GitlabUploader
def dynamic_segment
raise ObjectNotReadyError, "Package model not ready" unless model.id
- Gitlab::HashedPath.new('packages', model.package.id, 'files', model.id, root_hash: model.package.project_id)
+ package_segment = model.package.debian? ? 'debian' : model.package.id
+
+ Gitlab::HashedPath.new('packages', package_segment, 'files', model.id, root_hash: model.package.project_id)
end
end
diff --git a/app/validators/feature_flag_strategies_validator.rb b/app/validators/feature_flag_strategies_validator.rb
index e542d52c50a..a933a307626 100644
--- a/app/validators/feature_flag_strategies_validator.rb
+++ b/app/validators/feature_flag_strategies_validator.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
class FeatureFlagStrategiesValidator < ActiveModel::EachValidator
- STRATEGY_DEFAULT = 'default'.freeze
- STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId'.freeze
- STRATEGY_USERWITHID = 'userWithId'.freeze
+ STRATEGY_DEFAULT = 'default'
+ STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId'
+ STRATEGY_USERWITHID = 'userWithId'
# Order key names alphabetically
STRATEGIES = {
STRATEGY_DEFAULT => [].freeze,
diff --git a/app/validators/json_schemas/debian_fields.json b/app/validators/json_schemas/debian_fields.json
new file mode 100644
index 00000000000..b9f6ad2b31d
--- /dev/null
+++ b/app/validators/json_schemas/debian_fields.json
@@ -0,0 +1,9 @@
+{
+ "description": "Debian fields",
+ "type": "object",
+ "patternProperties": {
+ ".*": {
+ "type": "string"
+ }
+ }
+}
diff --git a/app/validators/json_schemas/http_integration_payload_attribute_mapping.json b/app/validators/json_schemas/http_integration_payload_attribute_mapping.json
index e457b8a292b..a194daf5e45 100644
--- a/app/validators/json_schemas/http_integration_payload_attribute_mapping.json
+++ b/app/validators/json_schemas/http_integration_payload_attribute_mapping.json
@@ -6,7 +6,8 @@
"required": ["path", "type"],
"properties": {
"path": { "type": "array" },
- "type": { "type": "string" }
+ "type": { "type": "string" },
+ "label": { "type": ["string", "null"] }
},
"additionalProperties": false
}
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index ae0da214fb7..c3d7fac6df7 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -12,7 +12,9 @@
= _('(removed)')
%td
%strong.subheading.d-block.d-sm-none
- = _('Reported by %{reporter}') % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
+ = _('Reported by %{reporter}').html_safe % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
+ .light.gl-display-none.gl-display-sm-block
+ = link_to(reporter.name, reporter)
.light.small
= time_ago_with_tooltip(abuse_report.created_at)
%td
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index 1baec07fa25..7f78cce4575 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -1,4 +1,3 @@
-- return unless Gitlab::Gitpod.feature_available?
- expanded = integration_expanded?('gitpod_')
%section.settings.no-animate#js-gitpod-settings{ class: ('expanded' if expanded) }
diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml
index b06070d15d4..11ffe3f56e3 100644
--- a/app/views/admin/application_settings/_ip_limits.html.haml
+++ b/app/views/admin/application_settings/_ip_limits.html.haml
@@ -49,5 +49,12 @@
.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'
+ %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.submit 'Save changes', class: "gl-button btn btn-success", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index 2f2d42e297e..92477dff3d8 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
.form-check
- = f.check_box :signup_enabled, class: 'form-check-input'
+ = f.check_box :signup_enabled, class: 'form-check-input', data: { qa_selector: 'signup_enabled_checkbox' }
= f.label :signup_enabled, class: 'form-check-label' do
Sign-up enabled
.form-text.text-muted
diff --git a/app/views/admin/application_settings/_spam.html.haml b/app/views/admin/application_settings/_spam.html.haml
index b54f1d7c829..2b871d3693c 100644
--- a/app/views/admin/application_settings/_spam.html.haml
+++ b/app/views/admin/application_settings/_spam.html.haml
@@ -30,6 +30,14 @@
.form-group
.form-check
+ = f.check_box :invisible_captcha_enabled, class: 'form-check-input'
+ = f.label :invisible_captcha_enabled, class: 'form-check-label' do
+ = _('Enable Invisible Captcha during sign up')
+ %span.form-text.text-muted
+ = _('Helps prevent bots from creating accounts.')
+
+ .form-group
+ .form-check
= f.check_box :akismet_enabled, class: 'form-check-input'
= f.label :akismet_enabled, class: 'form-check-label' do
Enable Akismet
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 2ba7dcefd44..fe83d4b807c 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -33,7 +33,7 @@
%pre.usage-data.js-syntax-highlight.code.highlight.mt-2.d-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
- else
= _('The usage ping is disabled, and cannot be configured through this form.')
- - deactivating_usage_ping_path = help_page_path('development/product_analytics/usage_ping', anchor: 'disable-usage-ping')
+ - deactivating_usage_ping_path = help_page_path('development/usage_ping', anchor: 'disable-usage-ping')
- deactivating_usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: deactivating_usage_ping_path }
= s_('For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}.').html_safe % { deactivating_usage_ping_link_start: deactivating_usage_ping_link_start, deactivating_usage_ping_link_end: '</a>'.html_safe }
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index c60e44b3864..6ea139844d4 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -11,7 +11,7 @@
%p
- recaptcha_v2_link_url = 'https://developers.google.com/recaptcha/docs/versions'
- recaptcha_v2_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: recaptcha_v2_link_url }
- = _('Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
+ = _('Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
.settings-content
= render 'spam'
diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml
index bbb47e29bb9..9ba72caa88e 100644
--- a/app/views/admin/background_jobs/show.html.haml
+++ b/app/views/admin/background_jobs/show.html.haml
@@ -4,5 +4,5 @@
%p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing
%hr
-.card
+.card.gl-rounded-0
%iframe{ src: sidekiq_path, width: '100%', height: 970, style: "border: 0" }
diff --git a/app/views/admin/dev_ops_report/_report.html.haml b/app/views/admin/dev_ops_report/_report.html.haml
index 24c805d273a..5faadd15ef8 100644
--- a/app/views/admin/dev_ops_report/_report.html.haml
+++ b/app/views/admin/dev_ops_report/_report.html.haml
@@ -4,7 +4,7 @@
= render 'callout'
- if !usage_ping_enabled
- #js-devops-empty-state{ data: { is_admin: current_user&.admin.to_s, 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('development/product_analytics/usage_ping') } }
+ #js-devops-empty-state{ data: { is_admin: current_user&.admin.to_s, 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('development/usage_ping') } }
- elsif @metric.blank?
= render 'no_data'
- else
diff --git a/app/views/admin/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml
index 75398f3aa21..c16ef7af76d 100644
--- a/app/views/admin/dev_ops_report/show.html.haml
+++ b/app/views/admin/dev_ops_report/show.html.haml
@@ -3,7 +3,7 @@
.container
.gl-mt-3
- - if Gitlab.ee? && Feature.enabled?(:devops_adoption_feature, default_enabled: true) && License.feature_available?(:devops_adoption)
+ - if show_adoption?
= render_if_exists 'admin/dev_ops_report/devops_tabs'
- else
= render 'report'
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 386df99717b..b949d08718a 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -80,8 +80,9 @@
= storage_counter(project.statistics.storage_size)
%span.float-right.light
%span.monospace= project.full_path + '.git'
- .card-footer
- = paginate @projects, param_name: 'projects_page', theme: 'gitlab'
+ - unless @projects.size < Kaminari.config.default_per_page
+ .card-footer
+ = paginate @projects, param_name: 'projects_page', theme: 'gitlab'
- shared_projects = @group.shared_projects.sort_by(&:name)
- unless shared_projects.empty?
@@ -134,5 +135,6 @@
group: @group,
show_controls: false,
current_user_is_group_owner: current_user_is_group_owner }
- .card-footer
- = paginate @members, param_name: 'members_page', theme: 'gitlab'
+ - unless @members.size < Kaminari.config.default_per_page
+ .card-footer
+ = paginate @members, param_name: 'members_page', theme: 'gitlab'
diff --git a/app/views/admin/hooks/_form.html.haml b/app/views/admin/hooks/_form.html.haml
index 5bc5404fada..e6abd8ff85a 100644
--- a/app/views/admin/hooks/_form.html.haml
+++ b/app/views/admin/hooks/_form.html.haml
@@ -1,52 +1,33 @@
= form_errors(hook)
.form-group
- = form.label :url, 'URL', class: 'label-bold'
+ = form.label :url, _('URL'), class: 'label-bold'
= form.text_field :url, class: 'form-control'
.form-group
- = form.label :token, 'Secret Token', class: 'label-bold'
+ = 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
+ %p.form-text.text-muted= _('Use this token to validate received payloads')
.form-group
- = form.label :url, 'Trigger', class: 'label-bold'
- %ul.list-unstyled
- %li
- .form-text.text-muted
- 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.
-
- .gl-mt-3
- = form.check_box :repository_update_events, class: 'float-left'
- .gl-ml-6
- = form.label :repository_update_events, class: 'list-label' do
- %strong Repository update events
- %p.light
- This URL will be triggered when repository is updated
- %li
- = form.check_box :push_events, class: 'float-left'
- .gl-ml-6
- = form.label :push_events, class: 'list-label' do
- %strong Push events
- %p.light
- This URL will be triggered for each branch updated to the repository
- %li
- = form.check_box :tag_push_events, class: 'float-left'
- .gl-ml-6
- = form.label :tag_push_events, class: 'list-label' do
- %strong Tag push events
- %p.light
- This URL will be triggered when a new tag is pushed to the repository
- %li
- = form.check_box :merge_requests_events, class: 'float-left'
- .gl-ml-6
- = form.label :merge_requests_events, class: 'list-label' do
- %strong Merge request events
- %p.light
- This URL will be triggered when a merge request is created/updated/merged
+ = 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.')
+ %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')
+ %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')
+ %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')
+ %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')
.form-group
- = form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'
+ = form.label :enable_ssl_verification, _('SSL verification'), class: 'label-bold checkbox'
.form-check
= form.check_box :enable_ssl_verification, class: 'form-check-input'
- = form.label :enable_ssl_verification, class: 'form-check-label' do
- %strong Enable SSL verification
+ = form.label :enable_ssl_verification, _('Enable SSL verification'), class: 'label-bold form-check-label'
diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml
index 8eaf84c8df9..ce377eeea54 100644
--- a/app/views/admin/jobs/index.html.haml
+++ b/app/views/admin/jobs/index.html.haml
@@ -1,3 +1,5 @@
+- add_page_specific_style 'page_bundles/ci_status'
+
- breadcrumb_title _("Jobs")
- page_title _("Jobs")
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 3d3b8c28a17..9f19d3f5d4e 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -5,34 +5,34 @@
.col-sm-6
.bs-callout
%p
- = (_"A 'Runner' is a process which runs a job. You can set up as many Runners as you need.")
+ = (_"Runners are processes that pick up and execute CI/CD jobs for GitLab.")
%br
- = _('Runners can be placed on separate users, servers, even on your local machine.')
+ = _('You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want.')
%br
%div
- %span= _('Each Runner can be in one of the following states and/or belong to one of the following types:')
+ %span= _('Runners can be:')
%ul
%li
- %span.badge.badge-success shared
+ %span.badge.badge-pill.gl-badge.sm.badge-success shared
\-
- = _('Runner runs jobs from all unassigned projects')
+ = _('Runs jobs from all unassigned projects.')
%li
- %span.badge.badge-success group
+ %span.badge.badge-pill.gl-badge.sm.badge-success group
\-
- = _('Runner runs jobs from all unassigned projects in its group')
+ = _('Runs jobs from all unassigned projects in its group.')
%li
- %span.badge.badge-info specific
+ %span.badge.badge-pill.gl-badge.sm.badge-info specific
\-
- = _('Runner runs jobs from assigned projects')
+ = _('Runs jobs from assigned projects.')
%li
- %span.badge.badge-warning locked
+ %span.badge.badge-pill.gl-badge.sm.badge-warning locked
\-
- = _('Runner cannot be assigned to other projects')
+ = _('Cannot be assigned to other projects.')
%li
- %span.badge.badge-danger paused
+ %span.badge.badge-pill.gl-badge.sm.badge-danger paused
\-
- = _('Runner will not receive any new jobs')
+ = _('Not available to run jobs.')
.col-sm-6
.bs-callout
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 06925964dc5..aca50de3852 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -1,3 +1,5 @@
+- add_page_specific_style 'page_bundles/ci_status'
+
= content_for :title do
%h3.project-title
Runner ##{@runner.id}
@@ -15,17 +17,17 @@
- if @runner.instance_type?
.bs-callout.bs-callout-success
- %h4 This Runner will process jobs from ALL UNASSIGNED projects
+ %h4= _('This runner processes jobs for all unassigned projects.')
%p
- If you want Runners to build only specific projects, enable them in the table below.
- Keep in mind that this is a one way transition.
+ = _('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.')
- elsif @runner.group_type?
.bs-callout.bs-callout-success
- %h4 This runner will process jobs from all projects in its group and subgroups
+ %h4= _('This runner processes jobs for all projects in its group and subgroups.')
- else
.bs-callout.bs-callout-info
- %h4 This Runner will process jobs only from ASSIGNED projects
- %p You can't make this a shared Runner.
+ %h4= _('This runner processes jobs for assigned projects only.')
+ %p
+ = _('You cannot make this a shared runner.')
%hr
.gl-mb-6
@@ -33,12 +35,12 @@
.row
.col-md-6
- %h4 Restrict projects for this Runner
+ %h4= _('Restrict projects for this runner')
- if @runner.projects.any?
%table.table.assigned-projects
%thead
%tr
- %th Assigned projects
+ %th= _('Assigned projects')
- @runner.runner_projects.each do |runner_project|
- project = runner_project.project
- if project
@@ -55,7 +57,7 @@
%table.table.unassigned-projects
%thead
%tr
- %th Project
+ %th= _('Project')
%th
%tr
@@ -78,15 +80,15 @@
= paginate_without_count @projects
.col-md-6
- %h4 Recent jobs served by this Runner
+ %h4= _('Recent jobs served by this runner')
%table.table.ci-table.runner-builds
%thead
%tr
- %th Job
- %th Status
- %th Project
- %th Commit
- %th Finished at
+ %th= _('Job')
+ %th= _('Status')
+ %th= _('Project')
+ %th= _('Commit')
+ %th= _('Finished at')
- @builds.each do |build|
- project = build.project
diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml
index ca6efe9b095..7a34972dfbf 100644
--- a/app/views/admin/system_info/show.html.haml
+++ b/app/views/admin/system_info/show.html.haml
@@ -3,29 +3,41 @@
.gl-mt-3
.row
.col-sm
- .bg-light.light-well
- %h4= _('CPU')
+ .bg-light.info-well.p-3
+ %h4.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('pod', size: 18, css_class: 'pod-icon gl-mr-3')
+ = _('CPU')
.data
- if @cpus
%h2= _('%{cores} cores') % { cores: @cpus.length }
- else
= sprite_icon('warning-solid', css_class: 'text-warning')
= _('Unable to collect CPU info')
- .bg-light.light-well.gl-mt-3
- %h4= _('Memory Usage')
+ .bg-light.info-well.p-3.gl-mt-3
+ %h4.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('status-health', size: 18, css_class: 'pod-icon gl-mr-3')
+ = _('Memory Usage')
.data
- if @memory
%h2 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}
- else
= sprite_icon('warning-solid', css_class: 'text-warning')
= _('Unable to collect memory info')
- .bg-light.light-well.gl-mt-3
- %h4= _('Uptime')
+ .bg-light.info-well.p-3.gl-mt-3
+ %h4.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('clock', size: 18, css_class: 'pod-icon gl-mr-3')
+ = _('Uptime')
.data
%h2= distance_of_time_in_words_to_now(Rails.application.config.booted_at)
.col-sm
- .bg-light.light-well
- %h4= _('Disk Usage')
+ .bg-light.info-well.p-3
+ %h4.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('disk', size: 18, css_class: 'pod-icon gl-mr-3')
+ = _('Disk Usage')
.data
%ul
- @disks.each do |disk|
diff --git a/app/views/admin/users/_admin_notes.html.haml b/app/views/admin/users/_admin_notes.html.haml
index 5d91ba1a1ca..4da70a504f7 100644
--- a/app/views/admin/users/_admin_notes.html.haml
+++ b/app/views/admin/users/_admin_notes.html.haml
@@ -1,7 +1,7 @@
%fieldset
%legend= _('Admin notes')
.form-group.row
- .col-sm-2.col-form-label.text-right
+ .col-sm-2.col-form-label
= f.label :note, s_('AdminNote|Note')
.col-sm-10
= f.text_area :note, class: 'form-control'
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index b86abb893a9..cef16b1881e 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -44,6 +44,7 @@
%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
@@ -51,7 +52,7 @@
- if params[:filter].present?
= hidden_field_tag "filter", h(params[:filter])
.search-holder
- .search-field-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
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 4ea3b0f0fb9..fc3d5360f9b 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -1,21 +1,23 @@
-- link = link_to _("Install GitLab Runner"), 'https://docs.gitlab.com/runner/install/', target: '_blank'
+- link = link_to _("Install GitLab Runner and ensure it's running."), 'https://docs.gitlab.com/runner/install/', target: '_blank'
.gl-mb-3
- %h4= _("Set up a %{type} Runner manually") % { type: type }
+ %h5= _("Set up a %{type} runner manually") % { type: type }
%ol
%li
= link.html_safe
%li
- = _("Specify the following URL during the Runner setup:")
+ = _("Register the runner with this URL:")
+ %br
%code#coordinator_address= root_url(only_path: false)
= clipboard_button(target: '#coordinator_address', title: _("Copy URL"), class: "btn-transparent btn-clipboard")
- %li
- = _("Use the following registration token during setup:")
+ %br
+ %br
+ = _("And this registration token:")
+ %br
%code#registration_token= registration_token
= clipboard_button(target: '#registration_token', title: _("Copy token"), class: "btn-transparent btn-clipboard")
- .gl-mt-3.gl-mb-3
- = button_to _("Reset runners registration token"), reset_token_url,
- method: :put, class: 'gl-button btn btn-default',
- data: { confirm: _("Are you sure you want to reset registration token?") }
- %li
- = _("Start the Runner!")
+
+.gl-mt-3.gl-mb-3
+= 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?") }
diff --git a/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml b/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml
index 343abf6099e..7140c0f4e7c 100644
--- a/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner_automatically.html.haml
@@ -1,22 +1,21 @@
-.gl-mb-3
- %h4= _('Set up a %{type} Runner automatically') % { type: type }
+%h5= _('Set up a %{type} runner automatically') % { type: type }
%p
- - link_to_help_page = link_to(_('Learn more about Kubernetes'),
+ - link_to_help_page = link_to(_('Learn more.'),
help_page_path('user/project/clusters/index'),
target: '_blank',
rel: 'noopener noreferrer')
- = _('You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page }
+ = _('Register a runner on a Kubernetes cluster. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page }
%ol
%li
- = _('Click the button below to begin the install process by navigating to the Kubernetes page')
+ = _('Click the button below.')
%li
- = _('Select an existing Kubernetes cluster or create a new one')
+ = _('Select an existing Kubernetes cluster or create a new one.')
%li
- = _('From the Kubernetes cluster details view, install Runner from the applications list')
+ = _('From the Kubernetes cluster details view, applications list, install GitLab Runner.')
-= link_to _('Install Runner on Kubernetes'),
+= link_to _('Install GitLab Runner on Kubernetes'),
clusters_path,
class: 'gl-button btn btn-info'
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index 660fd1a48a7..3f6d60c2620 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -21,7 +21,7 @@
} }
- if !@group && @project.group
- .settings-header.border-top.prepend-top-20
+ .settings-header.border-top.gl-mt-6
= render 'ci/group_variables/header'
.settings-content.pr-0
= render 'ci/group_variables/index'
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index 573b96caae5..50e3d29f974 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -1,4 +1,3 @@
-= javascript_include_tag 'https://apis.google.com/js/api.js'
- external_link_icon = sprite_icon('external-link')
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index ff33fb46db8..74e336723ba 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -2,7 +2,6 @@
- page_title _('Kubernetes Cluster')
- active_tab = local_assigns.fetch(:active_tab, 'create')
- provider = params[:provider]
-= javascript_include_tag 'https://apis.google.com/js/api.js'
= render_gcp_signup_offer
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index c34e457dbd9..bf61d0bd1f0 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -65,7 +65,7 @@
data: { data: todo_actions_options, default_label: 'Action' } })
.filter-item.sort-filter
.dropdown
- %button.dropdown-menu-toggle.dropdown-menu-toggle-sort{ type: 'button', 'data-toggle' => 'dropdown' }
+ %button.dropdown-menu-toggle.dropdown-menu-toggle-sort{ type: 'button', class: 'gl-xs-w-full!', 'data-toggle' => 'dropdown' }
%span.light
- if @sort.present?
= sort_options_hash[@sort]
diff --git a/app/views/devise/shared/_footer.html.haml b/app/views/devise/shared/_footer.html.haml
new file mode 100644
index 00000000000..ca1adb48543
--- /dev/null
+++ b/app/views/devise/shared/_footer.html.haml
@@ -0,0 +1,8 @@
+%hr.footer-fixed
+.container.footer-container
+ .footer-links
+ - unless public_visibility_restricted?
+ = link_to _("Explore"), explore_root_path
+ = link_to _("Help"), help_path
+ = link_to _("About GitLab"), "https://about.gitlab.com/"
+= footer_message
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 3c4cbbbc3bd..acbf3b398b0 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -10,7 +10,7 @@
= form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- - if Feature.enabled?(:invisible_captcha)
+ - if Gitlab::CurrentSettings.invisible_captcha_enabled
= invisible_captcha
.name.form-row
.col.form-group
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
index b5bfbc7bd1c..d89c4bf0161 100644
--- a/app/views/doorkeeper/authorizations/new.html.haml
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -38,6 +38,8 @@
= hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope
= hidden_field_tag :nonce, @pre_auth.nonce
+ = hidden_field_tag :code_challenge, @pre_auth.code_challenge
+ = hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method
= submit_tag _("Deny"), class: "gl-button btn btn-danger"
= form_tag oauth_authorization_path, method: :post, class: 'inline' do
= hidden_field_tag :client_id, @pre_auth.client.uid
@@ -46,4 +48,6 @@
= hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope
= hidden_field_tag :nonce, @pre_auth.nonce
+ = hidden_field_tag :code_challenge, @pre_auth.code_challenge
+ = hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method
= submit_tag _("Authorize"), class: "gl-button btn btn-success gl-ml-3", data: { qa_selector: 'authorization_button' }
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 4c1ee5fd3b7..d6662e1fc31 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -9,7 +9,7 @@
- many_refs = event.ref_count.to_i > 1
%span.event-type.d-inline-block.gl-mr-2.pushed= many_refs ? "#{event.action_name} #{event.ref_count} #{event.ref_type.pluralize}" : "#{event.action_name} #{event.ref_type}"
- unless many_refs
- %span.gl-mr-2
+ %span.gl-mr-2.text-truncate
- commits_link = project_commits_path(project, event.ref_name)
- should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name)
= link_to_if should_link, event.ref_name, commits_link, class: 'ref-name'
diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml
index b2154f71082..a55dfb110f0 100644
--- a/app/views/explore/projects/_projects.html.haml
+++ b/app/views/explore/projects/_projects.html.haml
@@ -2,4 +2,4 @@
.nothing-here-block
%h5= _('Enter at least three characters to search')
- else
- = render 'shared/projects/list', projects: projects, user: current_user, explore_page: true, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true)
+ = render 'shared/projects/list', projects: projects, user: current_user, explore_page: true, pipeline_status: Feature.enabled?(:explore_pipeline_status, type: :ops)
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index 3aae81cef8d..bd53f73230e 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -1,7 +1,7 @@
- if invite_members_allowed?(group)
.js-invite-members-modal{ data: { id: group.id,
name: group.name,
- is_project: false,
+ is_project: 'false',
access_levels: GroupMember.access_level_roles.to_json,
default_access_level: Gitlab::Access::GUEST,
help_link: help_page_url('user/permissions') } }
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 33cd90ce5d3..229e04a371a 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -35,8 +35,8 @@
%button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = s_('GroupSettings|Customize your group badges.')
- = link_to s_('GroupSettings|Learn more about badges.'), help_page_path('user/project/badges')
+ = s_('GroupSettings|Customize this group\'s badges.')
+ = link_to s_('GroupSettings|What are badges?'), help_page_path('user/project/badges')
.settings-content
= render 'shared/badges/badge_settings'
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index a1527a74898..ab3998be009 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -3,136 +3,80 @@
- show_invited_members = can_manage_members && @invited_members.exists?
- show_access_requests = can_manage_members && @requesters.exists?
- invited_active = params[:search_invited].present? || params[:invited_members_page].present?
-- vue_members_list_enabled = Feature.enabled?(:vue_group_members_list, @group, default_enabled: true)
-- filtered_search_enabled = Feature.enabled?(:group_members_filtered_search, @group, default_enabled: true)
-- current_user_is_group_owner = @group && @group.has_owner?(current_user)
-
-- form_item_label_css_class = 'label-bold gl-mr-2 gl-mb-0 gl-py-2 align-self-md-center'
.js-remove-member-modal
-.project-members-page.gl-mt-3
- %h4
- = _('Group members')
- %hr
- - if can_manage_members
- %ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
- %li.nav-tab{ role: 'presentation' }
- %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _('Invite member')
- %li.nav-tab{ role: 'presentation' }
- %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab', qa_selector: 'invite_group_tab' }, role: 'tab' }= _('Invite group')
- .tab-content.gitlab-tab-content
- .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
- = render_invite_member_for_group(@group, @group_member.access_level)
- .tab-pane{ id: 'invite-group-pane', role: 'tabpanel' }
- = render 'shared/members/invite_group', submit_url: group_group_links_path(@group), access_levels: GroupMember.access_level_roles, default_access_level: @group_member.access_level, group_link_field: 'shared_with_group_id', group_access_field: 'shared_group_access'
+.row.gl-mt-3
+ .col-lg-12
+ .gl-display-flex.gl-flex-wrap
+ - if can_manage_members
+ .gl-w-half.gl-xs-w-full
+ %h4
+ = _('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)
+ .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)
+ %hr.gl-mt-4
+ %ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
+ %li.nav-tab{ role: 'presentation' }
+ %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _('Invite member')
+ %li.nav-tab{ role: 'presentation' }
+ %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab', qa_selector: 'invite_group_tab' }, role: 'tab' }= _('Invite group')
+ .tab-content.gitlab-tab-content
+ .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
+ = render_invite_member_for_group(@group, @group_member.access_level)
+ .tab-pane{ id: 'invite-group-pane', role: 'tabpanel' }
+ = render 'shared/members/invite_group', submit_url: group_group_links_path(@group), access_levels: GroupMember.access_level_roles, default_access_level: @group_member.access_level, group_link_field: 'shared_with_group_id', group_access_field: 'shared_group_access'
- = render_if_exists 'groups/group_members/ldap_sync'
+ = render_if_exists 'groups/group_members/ldap_sync'
- %ul.nav-links.mobile-separator.nav.nav-tabs
- %li.nav-item
- = link_to '#tab-members', class: ['nav-link', ('active' unless invited_active)], data: { toggle: 'tab' } do
- %span
- = _('Members')
- %span.badge.badge-pill= @members.total_count
- - if @group.shared_with_group_links.any?
- %li.nav-item
- = link_to '#tab-groups', class: ['nav-link'] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
- %span
- = _('Groups')
- %span.badge.badge-pill= @group.shared_with_group_links.count
- - if show_invited_members
+ %ul.nav-links.mobile-separator.nav.nav-tabs
%li.nav-item
- = link_to '#tab-invited-members', class: ['nav-link', ('active' if invited_active)], data: { toggle: 'tab' } do
+ = link_to '#tab-members', class: ['nav-link', ('active' unless invited_active)], data: { toggle: 'tab' } do
%span
- = _('Invited')
- %span.badge.badge-pill= @invited_members.total_count
- - if show_access_requests
- %li.nav-item
- = link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
- %span
- = _('Access requests')
- %span.badge.badge-pill= @requesters.count
- .tab-content
- #tab-members.tab-pane{ class: ('active' unless invited_active) }
- .card.card-without-border
- - unless filtered_search_enabled
- = render 'groups/group_members/tab_pane/header' do
- = render 'groups/group_members/tab_pane/title' do
- = html_escape(_('Members with access to %{strong_start}%{group_name}%{strong_end}')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- = form_tag group_group_members_path(@group), method: :get, class: 'user-search-form gl-display-flex gl-md-align-items-center gl-flex-wrap gl-flex-direction-column gl-md-flex-direction-row gl-mx-n3 gl-my-n3', data: { testid: 'user-search-form' } do
- .gl-px-3.gl-py-2
- .search-control-wrap.gl-relative
- = render 'shared/members/search_field'
- - if can_manage_members
- = render 'groups/group_members/tab_pane/form_item' do
- = label_tag '2fa', _('2FA'), class: form_item_label_css_class
- = render 'shared/members/filter_2fa_dropdown'
- = render 'groups/group_members/tab_pane/form_item' do
- = label_tag :sort_by, _('Sort by'), class: form_item_label_css_class
- = render 'shared/members/sort_dropdown'
- - if vue_members_list_enabled
- .js-group-members-list{ data: group_members_list_data_attributes(@group, @members) }
+ = _('Members')
+ %span.badge.badge-pill= @members.total_count
+ - if @group.shared_with_group_links.any?
+ %li.nav-item
+ = link_to '#tab-groups', class: ['nav-link'] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
+ %span
+ = _('Groups')
+ %span.badge.badge-pill= @group.shared_with_group_links.count
+ - if show_invited_members
+ %li.nav-item
+ = link_to '#tab-invited-members', class: ['nav-link', ('active' if invited_active)], data: { toggle: 'tab' } do
+ %span
+ = _('Invited')
+ %span.badge.badge-pill= @invited_members.total_count
+ - if show_access_requests
+ %li.nav-item
+ = link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
+ %span
+ = _('Access requests')
+ %span.badge.badge-pill= @requesters.count
+ .tab-content
+ #tab-members.tab-pane{ class: ('active' unless invited_active) }
+ .js-group-members-list{ data: group_members_list_data_attributes(@group, @members) }
+ .loading
+ .spinner.spinner-md
+ = 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) }
+ .loading
+ .spinner.spinner-md
+ - if show_invited_members
+ #tab-invited-members.tab-pane{ class: ('active' if invited_active) }
+ .js-group-invited-members-list{ data: group_members_list_data_attributes(@group, @invited_members) }
.loading
.spinner.spinner-md
- - else
- %ul.content-list.members-list{ data: { qa_selector: 'members_list' } }
- = render partial: 'shared/members/member',
- collection: @members, as: :member,
- locals: { membership_source: @group,
- group: @group,
- current_user_is_group_owner: current_user_is_group_owner }
- = paginate @members, theme: 'gitlab', params: { invited_members_page: nil, search_invited: nil }
- - if @group.shared_with_group_links.any?
- #tab-groups.tab-pane
- .card.card-without-border
- - unless filtered_search_enabled
- = render 'groups/group_members/tab_pane/header' do
- = render 'groups/group_members/tab_pane/title' do
- = html_escape(_('Groups with access to %{strong_start}%{group_name}%{strong_end}')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- - if vue_members_list_enabled
- .js-group-linked-list{ data: linked_groups_list_data_attributes(@group) }
- .loading
- .spinner.spinner-md
- - else
- %ul.content-list.members-list{ data: { qa_selector: 'groups_list' } }
- - @group.shared_with_group_links.each do |group_link|
- = render 'shared/members/group', group_link: group_link, can_admin_member: can_manage_members, group_link_path: group_group_link_path(@group, group_link)
- - if show_invited_members
- #tab-invited-members.tab-pane{ class: ('active' if invited_active) }
- .card.card-without-border
- - unless filtered_search_enabled
- = render 'groups/group_members/tab_pane/header' do
- = render 'groups/group_members/tab_pane/title' do
- = html_escape(_('Members invited to %{strong_start}%{group_name}%{strong_end}')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- = form_tag group_group_members_path(@group), method: :get, class: 'user-search-form', data: { testid: 'user-search-form' } do
- = render 'shared/members/search_field', name: 'search_invited'
- - if vue_members_list_enabled
- .js-group-invited-members-list{ data: group_members_list_data_attributes(@group, @invited_members) }
- .loading
- .spinner.spinner-md
- - else
- %ul.content-list.members-list
- = render partial: 'shared/members/member',
- collection: @invited_members, as: :member,
- locals: { membership_source: @group,
- group: @group,
- current_user_is_group_owner: current_user_is_group_owner }
= paginate @invited_members, param_name: 'invited_members_page', theme: 'gitlab', params: { page: nil }
- - if show_access_requests
- #tab-access-requests.tab-pane
- .card.card-without-border
- - unless filtered_search_enabled
- = render 'groups/group_members/tab_pane/header' do
- = render 'groups/group_members/tab_pane/title' do
- = html_escape(_('Users requesting access to %{strong_start}%{group_name}%{strong_end}')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- - if vue_members_list_enabled
- .js-group-access-requests-list{ data: group_members_list_data_attributes(@group, @requesters) }
- .loading
- .spinner.spinner-md
- - else
- %ul.content-list.members-list
- = render partial: 'shared/members/member',
- collection: @requesters, as: :member,
- locals: { membership_source: @group,
- group: @group,
- current_user_is_group_owner: current_user_is_group_owner }
+ - if show_access_requests
+ #tab-access-requests.tab-pane
+ .js-group-access-requests-list{ data: group_members_list_data_attributes(@group, @requesters) }
+ .loading
+ .spinner.spinner-md
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index e26b8317c1c..6d0a3e03019 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -1,21 +1,20 @@
- 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} )
%section
- .row.registry-placeholder.prepend-bottom-10
- .col-12
- #js-container-registry{ data: { endpoint: group_container_registries_path(@group),
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
- "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
- "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
- "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
- "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
- "registry_host_url_with_port" => escape_once(registry_config.host_port),
- "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
- "run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
- "cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
- "is_admin": current_user&.admin.to_s,
- is_group_page: "true",
- "group_path": @group.full_path,
- "gid_prefix": container_repository_gid_prefix,
- character_error: @character_error.to_s } }
+ #js-container-registry{ data: { endpoint: group_container_registries_path(@group),
+ "help_page_path" => help_page_path('user/packages/container_registry/index'),
+ "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
+ "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
+ "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
+ "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
+ "registry_host_url_with_port" => escape_once(registry_config.host_port),
+ "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
+ "run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
+ "cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
+ "is_admin": current_user&.admin.to_s,
+ is_group_page: "true",
+ "group_path": @group.full_path,
+ "gid_prefix": container_repository_gid_prefix,
+ character_error: @character_error.to_s } }
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index 554240b7aef..944ef3435c1 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -1,11 +1,11 @@
-- link = link_to _('Runners API'), help_page_path('api/runners.md')
+- link = link_to _('Runner API'), help_page_path('api/runners.md')
-%h3
- = _('Group Runners')
+%h4
+ = _('Group runners')
-.bs-callout.bs-callout-warning
- = _('GitLab Group Runners can execute code for all the projects in this group.')
- = _('They can be managed using the %{link}.').html_safe % { link: link }
+%p
+ = _('These runners are shared across projects in this group.')
+ = _('Group runners can be managed with the %{link}.').html_safe % { link: link }
-# Proper policies should be implemented per
-# https://gitlab.com/gitlab-org/gitlab-foss/issues/45894
@@ -18,3 +18,4 @@
locals: { registration_token: @group.runners_token,
type: 'group',
reset_token_url: reset_registration_token_group_settings_ci_cd_path }
+ %br
diff --git a/app/views/groups/runners/_index.html.haml b/app/views/groups/runners/_index.html.haml
index b342b589d93..7cbc709ecf8 100644
--- a/app/views/groups/runners/_index.html.haml
+++ b/app/views/groups/runners/_index.html.haml
@@ -2,8 +2,6 @@
%hr
-%p.lead
- = _('To start serving your jobs you can add Runners to your group')
.row
.col-sm-6
= render 'groups/runners/group_runners'
@@ -11,7 +9,7 @@
= render 'groups/runners/shared_runners'
%h4.underlined-title
- = _('Available Runners: %{runners}').html_safe % { runners: limited_counter_with_delimiter(@all_group_runners) }
+ = _('Available runners: %{runners}').html_safe % { runners: limited_counter_with_delimiter(@all_group_runners) }
-# haml-lint:disable NoPlainNodes
.row
diff --git a/app/views/groups/settings/_two_factor_auth.html.haml b/app/views/groups/settings/_two_factor_auth.html.haml
index d2d4c27c826..fac3df5237f 100644
--- a/app/views/groups/settings/_two_factor_auth.html.haml
+++ b/app/views/groups/settings/_two_factor_auth.html.haml
@@ -18,6 +18,6 @@
- unless group.has_parent?
.form-group
.form-check
- = f.check_box :allow_mfa_for_subgroups, class: 'form-check-input', checked: group.namespace_settings.allow_mfa_for_subgroups
+ = f.check_box :allow_mfa_for_subgroups, class: 'form-check-input', checked: group.namespace_settings&.allow_mfa_for_subgroups
= f.label :allow_mfa_for_subgroups, class: 'form-check-label' do
= _('Allow subgroups to set up their own two-factor authentication rules')
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 2b5019222f8..8f1ce11ce40 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
@@ -10,6 +10,6 @@
%strong= s_('GroupSettings|Default to Auto DevOps pipeline for all projects within this group')
%span.badge.badge-info#auto-devops-badge= badge_for_auto_devops_scope(group)
.form-text.text-muted
- = s_('GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
- = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
+ = 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'
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 5b5f357dbec..4a0a92fa91f 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -31,8 +31,8 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: "button" }
= expanded ? _('Collapse') : _('Expand')
%p
- = _("Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project.")
- = link_to s_('More information'), help_page_path('ci/runners/README')
+ = _("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')
.settings-content
= render 'groups/runners/index'
@@ -47,7 +47,7 @@
- quickstart_url = help_page_path('topics/autodevops/quick_start_guide')
- auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
- quickstart_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: quickstart_url }
- = s_('AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
+ = s_('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}').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
.settings-content
= render 'groups/settings/ci_cd/auto_devops_form', group: @group
diff --git a/app/views/groups/settings/packages_and_registries/index.html.haml b/app/views/groups/settings/packages_and_registries/index.html.haml
new file mode 100644
index 00000000000..33719d56af1
--- /dev/null
+++ b/app/views/groups/settings/packages_and_registries/index.html.haml
@@ -0,0 +1,5 @@
+- breadcrumb_title _('Packages & Registries')
+- page_title _('Packages & Registries')
+- @content_class = 'limit-container-width' unless fluid_layout
+
+%section#js-packages-and-registries-settings
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
index b826a1b6fc6..ed765f80b74 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -9,10 +9,9 @@
= link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
.jira-connect-app
- %h1
- GitLab for Jira Configuration
-
- if current_user.blank? && @subscriptions.empty?
+ %h1
+ GitLab for Jira Configuration
%h2.heading-with-border Sign in to GitLab.com to get started.
.gl-mt-5
@@ -21,17 +20,18 @@
.gl-mt-5
%p Note: this integration only works with accounts on GitLab.com (SaaS).
- else
- .js-jira-connect-app
+ .js-jira-connect-app{ data: jira_connect_app_data }
- %form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
- .ak-field-group
- %label
- GitLab namespace
+ - unless new_jira_connect_ui?
+ %form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
+ .ak-field-group
+ %label
+ GitLab namespace
- .ak-field-group.field-group-input
- %input#namespace-input.ak-field-text{ type: 'text', required: true, placeholder: 'e.g. "MyCompany" or "MyCompany/GroupName"' }
- %button.ak-button.ak-button__appearance-primary{ type: 'submit' }
- Link namespace to Jira
+ .ak-field-group.field-group-input
+ %input#namespace-input.ak-field-text{ type: 'text', required: true, placeholder: 'e.g. "MyCompany" or "MyCompany/GroupName"' }
+ %button.ak-button.ak-button__appearance-primary{ type: 'submit' }
+ Link namespace to Jira
- if @subscriptions.present?
%table.subscriptions
@@ -49,6 +49,7 @@
- else
%h4.empty-subscriptions
No linked namespaces
+ %p= s_('Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance.')
%p.browser-limitations-notice
%strong Browser limitations:
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index bdd506ab3be..7aa57331c51 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -43,8 +43,6 @@
= stylesheet_link_tag_defer "application"
= yield :page_specific_styles
= stylesheet_link_tag_defer "application_utilities"
- - unless use_startup_css?
- = stylesheet_link_tag_defer "themes/#{user_application_theme_css_filename}" if user_application_theme_css_filename
= stylesheet_link_tag "disable_animations", media: "all" if Rails.env.test? || Gitlab.config.gitlab['disable_animations']
= stylesheet_link_tag_defer "highlight/themes/#{user_color_scheme}"
diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml
index 2f674f79b2f..35b91c8d35e 100644
--- a/app/views/layouts/_startup_css.haml
+++ b/app/views/layouts/_startup_css.haml
@@ -1,5 +1,3 @@
-- return unless use_startup_css?
-
- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general'
%style{ type: "text/css" }
diff --git a/app/views/layouts/_startup_css_activation.haml b/app/views/layouts/_startup_css_activation.haml
index 5fb53385acc..7dfb9cd1530 100644
--- a/app/views/layouts/_startup_css_activation.haml
+++ b/app/views/layouts/_startup_css_activation.haml
@@ -1,5 +1,3 @@
-- return unless use_startup_css?
-
= javascript_tag do
:plain
document.querySelectorAll('link[media="print"]').forEach(linkTag => {
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 5daee24cb51..ef61a04c288 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -38,12 +38,4 @@
.col-sm-5.order-1.order-sm-12.new-session-forms-container
= yield
- %hr.footer-fixed
- .container.footer-container
- .footer-links
- - if !public_visibility_restricted?
- = link_to _("Explore"), explore_root_path
- = link_to _("Help"), help_path
- = link_to _("About GitLab"), "https://about.gitlab.com/"
-
- = footer_message
+ = render 'devise/shared/footer', footer_message: footer_message
diff --git a/app/views/layouts/devise_empty.html.haml b/app/views/layouts/devise_empty.html.haml
index 6ac80a5aba3..b5649be8917 100644
--- a/app/views/layouts/devise_empty.html.haml
+++ b/app/views/layouts/devise_empty.html.haml
@@ -1,5 +1,5 @@
!!! 5
-%html{ lang: "en", class: system_message_class }
+%html.devise-layout-html{ lang: "en", class: system_message_class }
= render "layouts/head"
%body.ui-indigo.login-page.application.navless{ class: "#{client_class_list}" }
= header_message
@@ -11,11 +11,4 @@
= render "layouts/flash"
= yield
- %hr
- .container
- .footer-links
- - if !public_visibility_restricted?
- = link_to _("Explore"), explore_root_path
- = link_to _("Help"), help_path
- = link_to _("About GitLab"), "https://about.gitlab.com/"
- = footer_message
+ = render 'devise/shared/footer', footer_message: footer_message
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 70ab0a56581..f7e93182ca2 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -16,7 +16,7 @@
= logo_text
- if Gitlab.com_and_canary?
= link_to 'https://next.gitlab.com', class: 'canary-badge bg-transparent', target: :_blank do
- %span.color-label.has-tooltip.badge.badge-pill.green-badge
+ %span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
- if current_user
@@ -47,17 +47,36 @@
%span.badge.badge-pill.issues-count.green-badge{ class: ('hidden' if issues_count == 0) }
= number_with_delimiter(issues_count)
- if header_link?(:merge_requests)
- = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter" }) do
- = link_to assigned_mrs_dashboard_path, title: _('Merge requests'), class: 'dashboard-shortcuts-merge_requests', aria: { label: _('Merge requests') },
- data: { qa_selector: 'merge_requests_shortcut_button', toggle: 'tooltip', placement: 'bottom',
+ - reviewers_enabled = merge_request_reviewers_enabled?
+ = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter #{reviewers_enabled ? '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",
+ placement: 'bottom',
track_label: 'main_navigation',
track_event: 'click_merge_link',
track_property: 'navigation',
container: 'body' } do
= sprite_icon('git-merge')
- - merge_requests_count = assigned_issuables_count(:merge_requests)
- %span.badge.badge-pill.merge-requests-count{ class: ('hidden' if merge_requests_count == 0) }
- = number_with_delimiter(merge_requests_count)
+ %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]
- 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',
diff --git a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml
new file mode 100644
index 00000000000..cb74c77dff8
--- /dev/null
+++ b/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml
@@ -0,0 +1,3 @@
+- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, @group)
+
+%li= dropdown_invite_members_link(@group)
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index 2c5cd7e96c7..1fc9831d271 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -2,7 +2,7 @@
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
= sprite_icon('plus-square')
= sprite_icon('chevron-down', css_class: 'caret-down')
- .dropdown-menu.dropdown-menu-right
+ .dropdown-menu.dropdown-menu-right.dropdown-extended-height
%ul
- if @group&.persisted?
- create_group_project = can?(current_user, :create_projects, @group)
@@ -16,6 +16,7 @@
- if create_group_subgroup
%li= link_to _('New subgroup'), new_group_path(parent_id: @group.id)
= render_if_exists 'layouts/header/create_epic_new_dropdown_item'
+ = render 'layouts/header/group_invite_members_new_dropdown_item'
%li.divider
%li.dropdown-bold-header GitLab
@@ -33,6 +34,7 @@
%li= link_to _('New merge request'), project_new_merge_request_path(merge_project)
- if create_project_snippet
%li= link_to _('New snippet'), new_project_snippet_path(@project)
+ = render 'layouts/header/project_invite_members_new_dropdown_item'
%li.divider
%li.dropdown-bold-header GitLab
- if current_user.can_create_project?
diff --git a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml
new file mode 100644
index 00000000000..2cb67e857e3
--- /dev/null
+++ b/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml
@@ -0,0 +1,3 @@
+- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_import_members?
+
+%li= dropdown_invite_members_link(@project)
diff --git a/app/views/layouts/jira_connect.html.haml b/app/views/layouts/jira_connect.html.haml
index 0d4ecfc5a10..d996b3387a3 100644
--- a/app/views/layouts/jira_connect.html.haml
+++ b/app/views/layouts/jira_connect.html.haml
@@ -3,8 +3,9 @@
%meta{ content: "text/html; charset=utf-8", "http-equiv" => "Content-Type" }
%title
GitLab
- = stylesheet_link_tag 'https://unpkg.com/@atlaskit/css-reset@3.0.6/dist/bundle.css'
- = stylesheet_link_tag 'https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.5/dist/bundle.css'
+ - unless new_jira_connect_ui?
+ = stylesheet_link_tag 'https://unpkg.com/@atlaskit/css-reset@3.0.6/dist/bundle.css'
+ = stylesheet_link_tag 'https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.5/dist/bundle.css'
= yield :page_specific_styles
= javascript_include_tag 'https://connect-cdn.atl-paas.net/all.js'
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 43f1011a85b..dd2c5e2a19e 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -8,7 +8,7 @@
- if defined?(@left_sidebar)
= button_tag class: 'toggle-mobile-nav', type: 'button' do
%span.sr-only= _("Open sidebar")
- = sprite_icon('hamburger')
+ = sprite_icon('hamburger', size: 18)
.breadcrumbs-links.js-title-container{ data: { qa_selector: 'breadcrumb_links_content' } }
%ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
- unless hide_top_links
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index efe8e57cadf..473a0d131b8 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -10,6 +10,8 @@
.sidebar-context-title
= @group.name
%ul.sidebar-top-level-items.qa-group-sidebar
+ = render_if_exists 'layouts/nav/sidebar/group_trial_status_widget', group: @group
+
- if group_sidebar_link?(:overview)
- paths = group_overview_nav_link_paths
= nav_link(path: paths, unless: -> { current_path?('groups/contribution_analytics#show') }, html_options: { class: 'home' }) do
@@ -148,7 +150,7 @@
= sprite_icon('settings')
%span.nav-item-name.qa-group-settings-item
= _('Settings')
- %ul.sidebar-sub-level-items.qa-group-sidebar-submenu
+ %ul.sidebar-sub-level-items.qa-group-sidebar-submenu{ data: { testid: 'group-settings-menu' } }
= nav_link(path: %w[groups#projects groups#edit badges#index ci_cd#show], html_options: { class: "fly-out-top-item" } ) do
= link_to edit_group_path(@group) do
%strong.fly-out-top-item-name
@@ -179,6 +181,12 @@
%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_if_exists "groups/ee/settings_nav"
= render_if_exists "groups/ee/administration_nav"
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 5cadabd5f90..e02b8333c60 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -300,8 +300,8 @@
= link_to _('Auto DevOps'), help_page_path('topics/autodevops/index.md')
%span= _('uses Kubernetes clusters to deploy your code!')
%hr
- %button.btn.btn-success.btn-sm.dismiss-feature-highlight{ type: 'button' }
- %span= _("Got it!")
+ %button.gl-button.btn.btn-success.btn-sm.dismiss-feature-highlight{ type: 'button' }
+ %span.gl-mr-2= _("Got it!")
= sprite_icon('thumb-up')
- if project_nav_tab? :environments
diff --git a/app/views/notify/_issuable_csv_export.html.haml b/app/views/notify/_issuable_csv_export.html.haml
index 5a581811179..3b1fe90eaee 100644
--- a/app/views/notify/_issuable_csv_export.html.haml
+++ b/app/views/notify/_issuable_csv_export.html.haml
@@ -3,4 +3,4 @@
= _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.to_s.titleize.downcase), project_link: project_link }
- if @truncated
%p
- = _('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.') % { written_count: @written_count, count: @count }
+ = _('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}.') % { written_count: @written_count, count: @count, issuables: type.to_s.pluralize, size_limit: @size_limit }
diff --git a/app/views/notify/issue_due_email.html.haml b/app/views/notify/issue_due_email.html.haml
index 08bc98ca05c..adb9da05694 100644
--- a/app/views/notify/issue_due_email.html.haml
+++ b/app/views/notify/issue_due_email.html.haml
@@ -1,5 +1,5 @@
%p.details
- #{link_to @issue.author_name, user_url(@issue.author)}'s issue is due soon.
+ #{link_to @issue.author_name, user_url(@issue.author)}'s issue #{issue_reference_link(@issue)} is due soon.
- if @issue.assignees.any?
%p
diff --git a/app/views/notify/issue_due_email.text.erb b/app/views/notify/issue_due_email.text.erb
index ae50b703fe3..e5bfcc70355 100644
--- a/app/views/notify/issue_due_email.text.erb
+++ b/app/views/notify/issue_due_email.text.erb
@@ -1,6 +1,6 @@
The following issue is due on <%= @issue.due_date %>:
-Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+Issue <%= @issue.iid %>: <%= issue_reference_link(@issue) %>
Author: <%= @issue.author_name %>
<%= assignees_label(@issue) %>
diff --git a/app/views/notify/issues_csv_email.text.erb b/app/views/notify/issues_csv_email.text.erb
index a1d2a4691bc..cf2910c4014 100644
--- a/app/views/notify/issues_csv_email.text.erb
+++ b/app/views/notify/issues_csv_email.text.erb
@@ -1,5 +1,5 @@
<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'issue'), project_name: @project.full_name, project_url: project_url(@project) } %>
<% if @truncated %>
- <%= _('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.') % { written_count: @written_count, issues_count: @issues_count} %>
+ <%= _('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.') % { written_count: @written_count, issues_count: @issues_count, size_limit: @size_limit } %>
<% end %>
diff --git a/app/views/notify/member_expiration_date_updated_email.html.haml b/app/views/notify/member_expiration_date_updated_email.html.haml
new file mode 100644
index 00000000000..6c4db22eeaa
--- /dev/null
+++ b/app/views/notify/member_expiration_date_updated_email.html.haml
@@ -0,0 +1,6 @@
+= email_default_heading(say_hi(@member.user))
+
+%p
+ = group_membership_expiration_changed_text(@member, @member_source)
+%p
+ = group_membership_expiration_changed_link(@member, @member_source, format: :html)
diff --git a/app/views/notify/member_expiration_date_updated_email.text.erb b/app/views/notify/member_expiration_date_updated_email.text.erb
new file mode 100644
index 00000000000..8b3a5a55e77
--- /dev/null
+++ b/app/views/notify/member_expiration_date_updated_email.text.erb
@@ -0,0 +1,5 @@
+<%= say_hi(@member.user) %>
+
+<%= group_membership_expiration_changed_text(@member, @member_source) %>
+
+<%= group_membership_expiration_changed_link(@member, @member_source) %>
diff --git a/app/views/notify/merge_requests_csv_email.text.erb b/app/views/notify/merge_requests_csv_email.text.erb
index 9ed971bbe9c..78d11dde69f 100644
--- a/app/views/notify/merge_requests_csv_email.text.erb
+++ b/app/views/notify/merge_requests_csv_email.text.erb
@@ -1,5 +1,5 @@
<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'merge request'), project_name: @project.full_name, project_url: project_url(@project) } %>
<% if @truncated %>
- <%= _('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.') % { written_count: @written_count, merge_requests_count: @merge_requests_count} %>
+ <%= _('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.') % { written_count: @written_count, merge_requests_count: @merge_requests_count, size_limit: @size_limit} %>
<% end %>
diff --git a/app/views/notify/pipeline_failed_email.html.haml b/app/views/notify/pipeline_failed_email.html.haml
index 575ec8c488e..4e8d8a20ef1 100644
--- a/app/views/notify/pipeline_failed_email.html.haml
+++ b/app/views/notify/pipeline_failed_email.html.haml
@@ -6,7 +6,7 @@
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;line-height:1;" }
%img{ alt: "✖", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red-inverted.gif'), style: "display:block;", width: "13" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
- Your pipeline has failed.
+ Pipeline ##{@pipeline.id} has failed!
%tr.spacer
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
&nbsp;
diff --git a/app/views/notify/pipeline_failed_email.text.erb b/app/views/notify/pipeline_failed_email.text.erb
index a30e331d892..2deca375db1 100644
--- a/app/views/notify/pipeline_failed_email.text.erb
+++ b/app/views/notify/pipeline_failed_email.text.erb
@@ -1,4 +1,4 @@
-Your pipeline has failed.
+Pipeline #<%= @pipeline.id %> has failed!
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
diff --git a/app/views/notify/pipeline_fixed_email.html.haml b/app/views/notify/pipeline_fixed_email.html.haml
index 05c0027a6fc..f2dbb3b20b7 100644
--- a/app/views/notify/pipeline_fixed_email.html.haml
+++ b/app/views/notify/pipeline_fixed_email.html.haml
@@ -1 +1 @@
-= render 'notify/successful_pipeline', title: 'Your pipeline has been fixed!'
+= render 'notify/successful_pipeline', title: "Pipeline has been fixed and ##{@pipeline.id} has passed!"
diff --git a/app/views/notify/pipeline_fixed_email.text.erb b/app/views/notify/pipeline_fixed_email.text.erb
index 75268531bdc..32334260a5e 100644
--- a/app/views/notify/pipeline_fixed_email.text.erb
+++ b/app/views/notify/pipeline_fixed_email.text.erb
@@ -1 +1 @@
-<%= render 'notify/successful_pipeline', title: 'Your pipeline has been fixed!' -%>
+<%= render 'notify/successful_pipeline', title: "Pipeline has been fixed and ##{@pipeline.id} has passed!" -%>
diff --git a/app/views/notify/pipeline_success_email.html.haml b/app/views/notify/pipeline_success_email.html.haml
index c34e02b5fee..47832907663 100644
--- a/app/views/notify/pipeline_success_email.html.haml
+++ b/app/views/notify/pipeline_success_email.html.haml
@@ -1 +1 @@
-= render 'notify/successful_pipeline', title: 'Your pipeline has passed.'
+= render 'notify/successful_pipeline', title: "Pipeline ##{@pipeline.id} has passed!"
diff --git a/app/views/notify/pipeline_success_email.text.erb b/app/views/notify/pipeline_success_email.text.erb
index b554bffc908..83cdb72d252 100644
--- a/app/views/notify/pipeline_success_email.text.erb
+++ b/app/views/notify/pipeline_success_email.text.erb
@@ -1 +1 @@
-<%= render 'notify/successful_pipeline', title: 'Your pipeline has passed.' -%>
+<%= render 'notify/successful_pipeline', title: "Pipeline ##{@pipeline.id} has passed!" -%>
diff --git a/app/views/notify/provisioned_member_access_granted_email.erb b/app/views/notify/provisioned_member_access_granted_email.erb
new file mode 100644
index 00000000000..485ee5a5242
--- /dev/null
+++ b/app/views/notify/provisioned_member_access_granted_email.erb
@@ -0,0 +1,14 @@
+<% 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
new file mode 100644
index 00000000000..2f2fd33145a
--- /dev/null
+++ b/app/views/notify/provisioned_member_access_granted_email.haml
@@ -0,0 +1,24 @@
+- 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/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml
index e0b0f839455..782850afcda 100644
--- a/app/views/profiles/chat_names/index.html.haml
+++ b/app/views/profiles/chat_names/index.html.haml
@@ -9,7 +9,7 @@
= _('You can see your chat accounts.')
.col-lg-8
- %h5 Active chat names (#{@chat_names.size})
+ %h5.gl-mt-0 Active chat names (#{@chat_names.size})
- if @chat_names.present?
.table-responsive
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index bf9f1336a4f..41699d6f01f 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -70,7 +70,7 @@
prepend: emoji_button,
append: reset_message_button,
placeholder: s_("Profiles|What's your status?")
- - if Feature.enabled?(:set_user_availability_status, @user)
+ - if Feature.enabled?(:set_user_availability_status, @user, default_enabled: :yaml)
.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')
diff --git a/app/views/profiles/two_factor_auths/_codes.html.haml b/app/views/profiles/two_factor_auths/_codes.html.haml
index 178a9d3f8b4..9f850842f58 100644
--- a/app/views/profiles/two_factor_auths/_codes.html.haml
+++ b/app/views/profiles/two_factor_auths/_codes.html.haml
@@ -1,18 +1,3 @@
- show_success_alert = local_assigns.fetch(:show_success_alert, nil)
-- if Feature.enabled?(:vue_2fa_recovery_codes, current_user, default_enabled: true)
- .js-2fa-recovery-codes{ data: { codes: @codes.to_json, profile_account_path: profile_account_path(two_factor_auth_enabled_successfully: show_success_alert) } }
-- else
- %p.slead
- - lose_2fa_message = _('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.') % { b_start:'<b>', b_end:'</b>' }
- = lose_2fa_message.html_safe
-
- .codes.card{ data: { qa_selector: 'codes_content' } }
- %ul
- - @codes.each do |code|
- %li
- %span.monospace{ data: { qa_selector: 'code_content' } }= code
-
- .d-flex
- = link_to _('Proceed'), profile_account_path, class: 'gl-button btn btn-success gl-mr-3', data: { qa_selector: 'proceed_button' }
- = link_to _('Download codes'), "data:text/plain;charset=utf-8,#{CGI.escape(@codes.join("\n"))}", download: "gitlab-recovery-codes.txt", class: 'gl-button btn btn-default'
+.js-2fa-recovery-codes{ data: { codes: @codes.to_json, profile_account_path: profile_account_path(two_factor_auth_enabled_successfully: show_success_alert) } }
diff --git a/app/views/profiles/two_factor_auths/create.html.haml b/app/views/profiles/two_factor_auths/create.html.haml
index be4800024cf..606dda5ed55 100644
--- a/app/views/profiles/two_factor_auths/create.html.haml
+++ b/app/views/profiles/two_factor_auths/create.html.haml
@@ -1,8 +1,4 @@
- page_title _('Two-factor Authentication'), _('Account')
- add_page_specific_style 'page_bundles/profile_two_factor_auth'
-- unless Feature.enabled?(:vue_2fa_recovery_codes, current_user, default_enabled: true)
- .gl-alert.gl-alert-success.gl-mb-5
- = _('Congratulations! You have enabled Two-factor Authentication!')
-
= render 'codes', show_success_alert: true
diff --git a/app/views/projects/_export.html.haml b/app/views/projects/_export.html.haml
index 5ec2dc57f96..86dfcda6d1b 100644
--- a/app/views/projects/_export.html.haml
+++ b/app/views/projects/_export.html.haml
@@ -2,7 +2,7 @@
- project = local_assigns.fetch(:project)
-.sub-section
+.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.')
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index ebb0dd8b39f..3e1d08e646e 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -25,7 +25,7 @@
%span.access-request-links.gl-ml-3
= render 'shared/members/access_request_links', source: @project
- if @project.tag_list.present?
- %span.home-panel-topic-list.mt-2.w-100.d-inline-flex.gl-font-base.gl-font-weight-normal
+ %span.home-panel-topic-list.mt-2.w-100.d-inline-flex.gl-font-base.gl-font-weight-normal.gl-align-items-center
= sprite_icon('tag', css_class: 'icon gl-relative gl-mr-2')
- @project.topics_to_show.each do |topic|
diff --git a/app/views/projects/_invite_members_modal.html.haml b/app/views/projects/_invite_members_modal.html.haml
index ad95f39bbfa..e8f61336882 100644
--- a/app/views/projects/_invite_members_modal.html.haml
+++ b/app/views/projects/_invite_members_modal.html.haml
@@ -1,7 +1,7 @@
- if invite_members_allowed?(project.group)
.js-invite-members-modal{ data: { id: project.id,
name: project.name,
- is_project: true,
+ is_project: 'true',
access_levels: GroupMember.access_level_roles.to_json,
default_access_level: Gitlab::Access::GUEST,
help_link: help_page_url('user/permissions') } }
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 3b2b3a2ba67..153235c37d2 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -2,17 +2,17 @@
%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.btn.js-settings-toggle
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
- %p= _('Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.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 }
.settings-content
- if ::Gitlab::ServiceDesk.supported?
.js-service-desk-setting-root{ data: { endpoint: project_service_desk_path(@project),
enabled: "#{@project.service_desk_enabled}",
incoming_email: (@project.service_desk_incoming_address if @project.service_desk_enabled),
custom_email: (@project.service_desk_custom_address if @project.service_desk_enabled),
- custom_email_enabled: "#{@project.service_desk_custom_address_enabled?}",
+ custom_email_enabled: "#{Gitlab::ServiceDeskEmail.enabled?}",
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
project_key: "#{@project.service_desk_setting&.project_key}",
diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml
index 314211057f9..182164d2175 100644
--- a/app/views/projects/_visibility_modal.html.haml
+++ b/app/views/projects/_visibility_modal.html.haml
@@ -18,9 +18,9 @@
= _('Once you confirm and press "Reduce project visibility":')
%ul
%li
- = ("Current forks will keep their visibility level but their fork relationship with this project will be %{strong_start}removed%{strong_end}.").html_safe % { strong_start: strong_start, strong_end: strong_end }
+ = _("Current forks will keep their visibility level.").html_safe
%label{ for: "confirm_path_input" }
- = ("To confirm, type %{phrase_code}").html_safe % { phrase_code: '<code class="js-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: @project.full_path } }
+ = _("To confirm, type %{phrase_code}").html_safe % { phrase_code: '<code class="js-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: @project.full_path } }
.form-group
= text_field_tag 'confirm_path_input', '', class: 'form-control js-confirm-danger-input qa-confirm-input'
.form-actions
diff --git a/app/views/projects/alert_management/index.html.haml b/app/views/projects/alert_management/index.html.haml
index 415820ac3ad..3bb489f2b69 100644
--- a/app/views/projects/alert_management/index.html.haml
+++ b/app/views/projects/alert_management/index.html.haml
@@ -1,3 +1,4 @@
- page_title _('Alerts')
+- add_page_specific_style 'page_bundles/incident_management_list'
#js-alert_management{ data: alert_management_data(@current_user, @project) }
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
index b4962f4e78e..70a4202a5d0 100644
--- a/app/views/projects/blob/_template_selectors.html.haml
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -11,5 +11,8 @@
= dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-metrics-dashboard-selector qa-metrics-dashboard-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: metrics_dashboard_ymls(@project) } } )
#gitlab-ci-yml-selector.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitlab-ci-yml-selector qa-gitlab-ci-yml-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls(@project) } } )
+ - if experiment_enabled?(:ci_syntax_templates, subject: current_user)
+ .gitlab-ci-syntax-yml-selector.js-gitlab-ci-syntax-yml-selector-wrap.js-template-selector-wrap.hidden
+ = dropdown_tag(_("Learn CI/CD syntax"), options: { toggle_class: 'js-gitlab-ci-syntax-yml-selector qa-gitlab-ci-syntax-yml-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_syntax_ymls(@project) } } )
.dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-dockerfile-selector qa-dockerfile-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: dockerfile_names(@project) } } )
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
index 3326cded42a..d8d27c3330b 100644
--- a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
@@ -1,9 +1,9 @@
- if viewer.valid?(project: @project, sha: @commit.sha, user: @current_user)
= sprite_icon('check')
- This GitLab CI configuration is valid.
+ = s_('Pipelines|This GitLab CI configuration is valid.')
- else
= sprite_icon('warning-solid')
- This GitLab CI configuration is invalid:
+ = s_('Pipelines|This GitLab CI configuration is invalid:')
= viewer.validation_message(project: @project, sha: @commit.sha, user: @current_user)
-= link_to 'Learn more', help_page_path('ci/yaml/README')
+= link_to _('Learn more'), help_page_path('ci/yaml/README')
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
index 379a6c3084a..b1c8e110493 100644
--- a/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
@@ -1,4 +1,4 @@
= loading_icon(css_class: "gl-vertical-align-text-bottom mr-1")
-Validating GitLab CI configuration…
+= s_('Pipelines|Validating GitLab CI configuration…')
-= link_to 'Learn more', help_page_path('ci/yaml/README')
+= link_to _('Learn more'), help_page_path('ci/yaml/README')
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 8f5fac1a40b..dc4172e2f09 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -4,7 +4,7 @@
%li{ class: "branch-item js-branch-item js-branch-#{branch.name}", data: { name: branch.name } }
.branch-info
.branch-title
- = sprite_icon('fork', size: 12)
+ = sprite_icon('fork', size: 12, css_class: 'gl-flex-shrink-0')
= 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
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 24dfb59dc85..17314cd7c5a 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -2,9 +2,12 @@
- default_ref = params[:ref] || @project.default_branch
- if @error
- .alert.alert-danger
- %button.close{ type: "button", "data-dismiss" => "alert" } &times;
- = @error
+ .gl-alert.gl-alert-danger
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
+ = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ .gl-alert-body
+ = @error
%h3.page-title
New Branch
%hr
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 8b4411776bc..017c804ced0 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -43,16 +43,16 @@
.label-container
- if job.tags.any?
- job.tags.each do |tag|
- %span.badge.badge-primary
+ %span.badge.badge-pill.gl-badge.sm.badge-primary
= tag
- if job.try(:trigger_request)
- %span.badge.badge-info= _('triggered')
+ %span.badge.badge-pill.gl-badge.sm.badge-info= _('triggered')
- if job.try(:allow_failure) && !job.success?
- %span.badge.badge-warning= _('allowed to fail')
+ %span.badge.badge-pill.gl-badge.sm.badge-warning= _('allowed to fail')
- if job.schedulable?
- %span.badge.badge-info= s_('DelayedJobs|delayed')
+ %span.badge.badge-pill.gl-badge.sm.badge-info= s_('DelayedJobs|delayed')
- elsif job.action?
- %span.badge.badge-info= _('manual')
+ %span.badge.badge-pill.gl-badge.sm.badge-info= _('manual')
- if pipeline_link
%td
@@ -98,7 +98,7 @@
%td
.gl-display-flex
- - if can?(current_user, :read_build, job) && job.artifacts?
+ - 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)
diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml
index feccea6cfc0..4463220e951 100644
--- a/app/views/projects/ci/lints/show.html.haml
+++ b/app/views/projects/ci/lints/show.html.haml
@@ -1,6 +1,6 @@
- page_title _("CI Lint")
- page_description _("Validate your GitLab CI configuration file")
-%h2.pt-3.pb-3= _("Validate your GitLab CI configuration")
+%h4.pt-3.pb-3= _("Validate your GitLab CI configuration")
#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), pipeline_simulation_help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') , lint_help_page_path: help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax') } }
diff --git a/app/views/projects/ci/pipeline_editor/show.html.haml b/app/views/projects/ci/pipeline_editor/show.html.haml
index f1f8658fa3b..10aed15f380 100644
--- a/app/views/projects/ci/pipeline_editor/show.html.haml
+++ b/app/views/projects/ci/pipeline_editor/show.html.haml
@@ -1,8 +1,12 @@
- page_title s_('Pipelines|Pipeline Editor')
#js-pipeline-editor{ data: { "ci-config-path": @project.ci_config_path_or_default,
- "project-path" => @project.full_path,
+ "project-path" => @project.path,
+ "project-full-path" => @project.full_path,
+ "project-namespace" => @project.namespace.full_path,
"default-branch" => @project.default_branch,
- "commit-id" => @project.commit ? @project.commit.id : '',
+ "commit-sha" => @project.commit ? @project.commit.sha : '',
"new-merge-request-path" => namespace_project_new_merge_request_path,
+ "lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
+ "yml-help-page-path" => help_page_path('ci/yaml/README'),
} }
diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml
index 11adc7fd64a..69b20fbc6d0 100644
--- a/app/views/projects/commit/_change.html.haml
+++ b/app/views/projects/commit/_change.html.haml
@@ -6,34 +6,20 @@
- 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
+
- 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')
-
-.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'
+ = render "projects/commit/commit_modal", title: title, type: type, commit: commit, branch_label: branch_label, description: description, label: label
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 6f2797654d0..e8d524daced 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -37,7 +37,7 @@
#{ _('Browse Files') }
- if can_collaborate && !@commit.has_been_reverted?(current_user)
%li.clearfix
- = revert_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false)
+ = revert_commit_link(@commit, project_commit_path(@project, @commit.id), pajamas: true)
- if can_collaborate
%li.clearfix
= cherry_pick_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false)
diff --git a/app/views/projects/commit/_commit_modal.html.haml b/app/views/projects/commit/_commit_modal.html.haml
new file mode 100644
index 00000000000..a82d77fdc91
--- /dev/null
+++ b/app/views/projects/commit/_commit_modal.html.haml
@@ -0,0 +1,26 @@
+.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/show.html.haml b/app/views/projects/commit/show.html.haml
index 003a27f4c9a..e7b2e757ce4 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -17,5 +17,5 @@
.limited-width-notes
= render "shared/notes/notes_with_form", :autocomplete => true
- if can_collaborate_with_project?(@project)
- - %w(revert cherry-pick).each do |type|
- = render "projects/commit/change", type: type, commit: @commit, title: @commit.title
+ = render "projects/commit/change", type: 'revert', commit: @commit, pajamas: true
+ = render "projects/commit/change", type: 'cherry-pick', commit: @commit, title: @commit.title
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 387564f6408..cde8a5f69dd 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -3,17 +3,19 @@
- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
+= render "shared/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.btn.btn-default.js-settings-toggle{ type: 'button' }= _('Collapse')
+ %button.gl-button.btn.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.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %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.')
.settings-content
@@ -28,7 +30,7 @@
%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.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
= render_if_exists 'projects/merge_request_settings_description_text'
.settings-content
@@ -46,11 +48,10 @@
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
%p
- = s_('ProjectSettings|Customize your project badges.')
- = link_to s_('ProjectSettings|Learn more about badges.'), help_page_path('user/project/badges')
+ = s_('ProjectSettings|Customize this project\'s badges.')
+ = link_to s_('ProjectSettings|What are badges?'), help_page_path('user/project/badges')
.settings-content
= render 'shared/badges/badge_settings'
@@ -61,7 +62,7 @@
%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.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
%p= _('Housekeeping, export, path, transfer, remove, archive.')
.settings-content
diff --git a/app/views/projects/environments/_metrics_button.html.haml b/app/views/projects/environments/_metrics_button.html.haml
index 5a691676a68..65abaf44082 100644
--- a/app/views/projects/environments/_metrics_button.html.haml
+++ b/app/views/projects/environments/_metrics_button.html.haml
@@ -3,5 +3,5 @@
- return unless can?(current_user, :read_environment, environment)
= link_to environment_metrics_path(environment), title: _('See metrics'), class: 'gl-button btn metrics-button' do
- = sprite_icon('chart')
+ = sprite_icon('chart', css_class: 'gl-mr-2')
= _("Monitoring")
diff --git a/app/views/projects/incidents/index.html.haml b/app/views/projects/incidents/index.html.haml
index a89e93618bc..c29ab11a720 100644
--- a/app/views/projects/incidents/index.html.haml
+++ b/app/views/projects/incidents/index.html.haml
@@ -1,3 +1,4 @@
- page_title _('Incidents')
+- add_page_specific_style 'page_bundles/incident_management_list'
#js-incidents{ data: incidents_data(@project, params) }
diff --git a/app/views/projects/issues/_design_management.html.haml b/app/views/projects/issues/_design_management.html.haml
index ad0605b10a8..a2ff9620c0c 100644
--- a/app/views/projects/issues/_design_management.html.haml
+++ b/app/views/projects/issues/_design_management.html.haml
@@ -3,7 +3,7 @@
- requirements_link_url = help_page_path('user/project/issues/design_management', anchor: 'requirements')
- requirements_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: requirements_link_url }
- link_end = '</a>'.html_safe
-- enable_lfs_message = s_("DesignManagement|To upload designs, you'll need to enable LFS and have admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}").html_safe % { requirements_link_start: requirements_link_start, requirements_link_end: link_end }
+- enable_lfs_message = s_("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}").html_safe % { requirements_link_start: requirements_link_start, requirements_link_end: link_end }
- if @project.design_management_enabled?
- add_page_startup_graphql_call('design_management/get_design_list', { fullPath: @project.full_path, iid: @issue.iid.to_s, atVersion: nil })
diff --git a/app/views/projects/issues/import_csv/_button.html.haml b/app/views/projects/issues/import_csv/_button.html.haml
index ea8f53f7342..e60460687a9 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.rounded-right.text-center{ class: ('has-tooltip' if type == :icon), title: (_('Import issues') if type == :icon),
+ %button.btn.gl-button.rounded-right.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/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index cd062fcf675..e14473708af 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -8,10 +8,11 @@
.nav-controls
- if can?(current_user, :update_build, @project)
- if !@repository.gitlab_ci_yml && !experiment_enabled?(:jobs_empty_state)
- = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn gl-button btn-info js-empty-state-button'
+ = 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
+ %span
+ = _('CI Lint')
.content-list.builds-content-list
= render "table", builds: @builds, project: @project
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 1691a304e8b..6a42f33db7d 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -12,9 +12,9 @@
.detail-page-header.border-bottom-0.pt-0.pb-0
.detail-page-header-body
- .issuable-status-box.status-box{ class: status_box_class(@merge_request) }
- = sprite_icon(state_icon_name, css_class: 'd-block d-sm-none')
- %span.d-none.d-sm-block
+ .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
= state_human_name
.issuable-meta
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index c70fc624dde..849cfac825f 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -57,6 +57,8 @@
= render "projects/merge_requests/awards_block"
- if mr_action === "show"
- 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,
noteable_data: serialize_issuable(@merge_request, serializer: 'noteable'),
noteable_type: 'MergeRequest',
@@ -88,7 +90,8 @@
dismiss_endpoint: user_callouts_path,
show_suggest_popover: show_suggest_popover?.to_s,
show_whitespace_default: @show_whitespace_default.to_s,
- file_by_file_default: @file_by_file_default.to_s }
+ file_by_file_default: @file_by_file_default.to_s,
+ default_suggestion_commit_message: default_suggestion_commit_message }
.mr-loading-status
.loading.hide
diff --git a/app/views/projects/mirrors/_instructions.html.haml b/app/views/projects/mirrors/_instructions.html.haml
index 97b04acea31..a91751da0aa 100644
--- a/app/views/projects/mirrors/_instructions.html.haml
+++ b/app/views/projects/mirrors/_instructions.html.haml
@@ -3,12 +3,12 @@
%li
= html_escape(_('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}.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- %li= html_escape(_('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.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ %li= html_escape(_('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.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li= html_escape(_('Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li
- minutes = Gitlab.config.gitlab_shell.git_timeout / 60
= _("The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination.") % { number_of_minutes: minutes }
%li= mirror_lfs_sync_message
%li
- = _('This user will be the author of all events in the activity feed that are the result of an update,
+ = _('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.')
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 5b074ff8a28..98d35845b31 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -10,7 +10,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
= _('Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically.')
- = link_to _('Read more'), help_page_path('user/project/repository/repository_mirroring.md'), target: '_blank'
+ = link_to _('How do I mirror repositories?'), help_page_path('user/project/repository/repository_mirroring'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
- if mirror_settings_enabled
@@ -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 your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", autocomplete: 'new-password'
+ = 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'
= render 'projects/mirrors/instructions'
@@ -29,8 +29,10 @@
.form-check.gl-mb-3
= check_box_tag :only_protected_branches, '1', false, class: 'js-mirror-protected form-check-input'
- = label_tag :only_protected_branches, _('Only mirror protected branches'), class: 'form-check-label'
- = link_to sprite_icon('question-o'), help_page_path('user/project/protected_branches'), target: '_blank'
+ = label_tag :only_protected_branches, _('Mirror only protected branches'), class: 'form-check-label'
+ .form-text.text-muted
+ = _('If enabled, only protected branches will be mirrored.')
+ = link_to _('Learn more.'), help_page_path('user/project/repository/repository_mirroring', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
.panel-footer
= f.submit _('Mirror repository'), class: 'gl-button btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
index 03839146f3b..04f44f4748e 100644
--- a/app/views/projects/mirrors/_mirror_repos_push.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -10,4 +10,6 @@
.form-check.gl-mb-3
= check_box_tag :keep_divergent_refs, '1', false, class: 'js-mirror-keep-divergent-refs form-check-input'
= label_tag :keep_divergent_refs, _('Keep divergent refs'), class: 'form-check-label'
- = link_to sprite_icon('question-o'), help_page_path('user/project/repository/repository_mirroring', anchor: 'keep-divergent-refs'), target: '_blank'
+ .form-text.text-muted
+ = _('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.')
+ = link_to _('Learn more.'), help_page_path('user/project/repository/repository_mirroring', anchor: 'keep-divergent-refs'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index a407aa9ac13..6af185696b0 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -8,7 +8,7 @@
.project-edit-errors
= render 'projects/errors'
- .js-experiment-new-project-creation{ data: { is_ci_cd_available: (ci_cd_projects_available? if Gitlab.ee?), has_errors: @project.errors.any? } }
+ .js-experiment-new-project-creation{ data: { is_ci_cd_available: (ci_cd_projects_available? if Gitlab.ee?), has_errors: @project.errors.any?, new_project_guidelines: brand_new_project_guidelines } }
.row{ 'v-cloak': true }
.col-lg-3.profile-settings-sidebar
diff --git a/app/views/projects/pages/_destroy.haml b/app/views/projects/pages/_destroy.haml
index 2714b5f221a..99efb0b98c6 100644
--- a/app/views/projects/pages/_destroy.haml
+++ b/app/views/projects/pages/_destroy.haml
@@ -5,10 +5,10 @@
= s_('GitLabPages|Remove pages')
.errors-holder
.card-body
- %p
+ %p.gl-mb-0
= s_('GitLabPages|Removing pages will prevent them from being exposed to the outside world.')
- .form-actions
- = link_to s_('GitLabPages|Remove pages'), project_pages_path(@project), data: { confirm: s_('GitLabPages|Are you sure?')}, method: :delete, class: "btn gl-button btn-danger"
+ .card-footer
+ = link_to s_('GitLabPages|Remove pages'), project_pages_path(@project), data: { confirm: s_('GitLabPages|Are you sure?')}, method: :delete, class: "btn gl-button btn-danger"
- else
.nothing-here-block
= s_('GitLabPages|Only project maintainers can remove pages')
diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml
index ab44fd77e1e..e9ace8c72f1 100644
--- a/app/views/projects/pages/_use.html.haml
+++ b/app/views/projects/pages/_use.html.haml
@@ -3,7 +3,7 @@
.card-header.bg-info.text-white
= s_('GitLabPages|Configure pages')
.card-body
- %p
+ %p.gl-mb-0
- link_start = "<a href='#{help_page_path('user/project/pages/index.md')}' 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,
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index a52a6138402..90417a852d5 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -16,5 +16,5 @@
%ul.content-list
= render partial: "table"
- else
- .card.bg-light
+ .card.bg-light.gl-mt-3
.nothing-here-block= _("No schedules")
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index f77f22cc555..77aa537dfdb 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -21,24 +21,24 @@
.icon-container
= sprite_icon('flag')
- if @pipeline.child?
- %span.js-pipeline-child.badge.badge-primary.has-tooltip{ title: s_("Pipelines|This is a child pipeline within the parent pipeline") }
+ %span.js-pipeline-child.badge.badge-pill.gl-badge.sm.badge-primary.has-tooltip{ title: s_("Pipelines|This is a child pipeline within the parent pipeline") }
= s_('Pipelines|Child pipeline')
= surround '(', ')' do
= link_to s_('Pipelines|parent'), pipeline_path(@pipeline.triggered_by_pipeline), class: 'text-white text-underline'
- if @pipeline.latest?
- %span.js-pipeline-url-latest.badge.badge-success.has-tooltip{ title: _("Latest pipeline for the most recent commit on this branch") }
+ %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.has_yaml_errors?
- %span.js-pipeline-url-yaml.badge.badge-danger.has-tooltip{ title: @pipeline.yaml_errors }
+ %span.js-pipeline-url-yaml.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.yaml_errors }
yaml invalid
- if @pipeline.failure_reason?
- %span.js-pipeline-url-failure.badge.badge-danger.has-tooltip{ title: @pipeline.failure_reason }
+ %span.js-pipeline-url-failure.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.failure_reason }
error
- if @pipeline.auto_devops_source?
- popover_title_text = html_escape(_('This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}')) % { b_open: '<b>'.html_safe, b_close: '</b>'.html_safe }
- popover_content_url = help_page_path('topics/autodevops/index.md')
- popover_content_text = _('Learn more about Auto DevOps')
- %a.js-pipeline-url-autodevops.badge.badge-info.autodevops-badge{ href: "#", tabindex: "0", role: "button", data: { container: "body",
+ %a.js-pipeline-url-autodevops.badge.badge-pill.gl-badge.sm.badge-info.autodevops-badge{ href: "#", tabindex: "0", role: "button", data: { container: "body",
toggle: "popover",
placement: "top",
html: "true",
@@ -48,10 +48,10 @@
} }
Auto DevOps
- if @pipeline.detached_merge_request_pipeline?
- %span.js-pipeline-url-mergerequest.badge.badge-info.has-tooltip{ title: _('Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results.') }
+ %span.js-pipeline-url-mergerequest.badge.badge-pill.gl-badge.sm.badge-info.has-tooltip{ title: _('Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results.') }
detached
- if @pipeline.stuck?
- %span.js-pipeline-url-stuck.badge.badge-warning
+ %span.js-pipeline-url-stuck.badge.badge-pill.gl-badge.sm.badge-warning
stuck
.well-segment.branch-info
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index f3360e150ad..ff728ab2fb3 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,10 +1,4 @@
- page_title _('CI / CD Analytics')
-- if Feature.enabled?(:graphql_pipeline_analytics)
- #js-project-pipelines-charts-app{ data: { project_path: @project.full_path } }
-- else
- #js-project-pipelines-charts-app{ data: { counts: @counts, success_ratio: success_ratio(@counts),
- times_chart: { labels: @charts[:pipeline_times].labels, values: @charts[:pipeline_times].pipeline_times },
- last_week_chart: { labels: @charts[:week].labels, totals: @charts[:week].total, success: @charts[:week].success },
- last_month_chart: { labels: @charts[:month].labels, totals: @charts[:month].total, success: @charts[:month].success },
- last_year_chart: { labels: @charts[:year].labels, totals: @charts[:year].total, success: @charts[:year].success } } }
+#js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
+ should_render_deployment_frequency_charts: should_render_deployment_frequency_charts.to_s } }
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 64ae4ff8daf..6a4dd88ae07 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -17,4 +17,4 @@
"new-pipeline-path" => can?(current_user, :create_pipeline, @project) && new_project_pipeline_path(@project),
"ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project),
"reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project) ,
- "has-gitlab-ci" => (@project.has_ci? && @project.builds_enabled?).to_s } }
+ "has-gitlab-ci" => has_gitlab_ci?(@project).to_s } }
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index 847b96cbd0e..b3ad210aa47 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -6,6 +6,9 @@
- add_page_specific_style 'page_bundles/reports'
- add_page_specific_style 'page_bundles/ci_status'
+- if Feature.enabled?(:graphql_pipeline_details, @project)
+ - 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}" } }
#js-pipeline-header-vue.pipeline-header-container{ data: { full_path: @project.full_path, pipeline_iid: @pipeline.iid, pipeline_id: @pipeline.id, pipelines_path: project_pipelines_path(@project) } }
- if @pipeline.commit.present?
diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml
index 39ef1e52a0d..fe8a50ebb42 100644
--- a/app/views/projects/project_members/_groups.html.haml
+++ b/app/views/projects/project_members/_groups.html.haml
@@ -1,8 +1,11 @@
-.card.project-members-groups
- .card-header
- = html_escape(_("Groups with access to %{strong_open}%{project_name}%{strong_close}")) % { project_name: sanitize(@project.name, tags: []), strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
- %span.badge.badge-pill= group_links.size
- %ul.content-list.members-list
- - can_admin_member = can?(current_user, :admin_project_member, @project)
+.card.card-without-border
+ = render 'shared/members/tab_pane/header' do
+ = render 'shared/members/tab_pane/title' do
+ = html_escape(_("Groups with access to %{strong_open}%{project_name}%{strong_close}")) % { project_name: sanitize(@project.name, tags: []), strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
+ = form_tag project_project_members_path(@project), method: :get, class: 'user-search-form gl-mx-n3 gl-my-n3', data: { testid: 'group-link-search-form' } do
+ .gl-px-3.gl-py-2
+ .search-control-wrap.gl-relative
+ = render 'shared/members/search_field', name: 'search_groups'
+ %ul.content-list.members-list{ data: { testid: 'project-member-groups' } }
- @group_links.each do |group_link|
- = render 'shared/members/group', group_link: group_link, can_admin_member: can_admin_member, group_link_path: project_group_link_path(@project, group_link)
+ = render 'shared/members/group', group_link: group_link, can_admin_member: can_manage_project_members?(@project), group_link_path: project_group_link_path(@project, group_link)
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index 171212b6a96..24ca7ebded9 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -1,20 +1,18 @@
- project = local_assigns.fetch(:project)
- members = local_assigns.fetch(:members)
- group = local_assigns.fetch(:group)
-- current_user_is_group_owner = group && group.has_owner?(current_user)
+- current_user_is_group_owner = local_assigns.fetch(:current_user_is_group_owner)
-.card
- .card-header.flex-project-members-panel
- %span.flex-project-title
+.card.card-without-border
+ = render 'shared/members/tab_pane/header' do
+ = render 'shared/members/tab_pane/title' do
= html_escape(_("Members of %{strong_open}%{project_name}%{strong_close}")) % { project_name: sanitize(project.name, tags: []), strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
- %span.badge.badge-pill= members.total_count
- = form_tag project_project_members_path(project), method: :get, class: 'form-inline user-search-form flex-users-form' do
- .form-group
- .position-relative
- = search_field_tag :search, params[:search], { placeholder: _('Find existing members by name'), class: 'form-control', spellcheck: false }
- %button.user-search-btn{ type: "submit", "aria-label" => _("Submit search") }
- = sprite_icon('search', css_class: 'gl-vertical-align-middle!')
- = label_tag :sort_by, _('Sort by'), class: 'col-form-label label-bold px-2'
+ = form_tag project_project_members_path(project), method: :get, class: 'user-search-form gl-display-flex gl-md-align-items-center gl-flex-wrap gl-flex-direction-column gl-md-flex-direction-row gl-mx-n3 gl-my-n3', data: { testid: 'user-search-form' } do
+ .gl-px-3.gl-py-2
+ .search-control-wrap.gl-relative
+ = render 'shared/members/search_field'
+ = render 'shared/members/tab_pane/form_item' do
+ = label_tag :sort_by, _('Sort by'), class: 'label-bold gl-mr-2 gl-mb-0 gl-py-2 align-self-md-center'
= render 'shared/members/sort_dropdown'
%ul.content-list.members-list{ data: { qa_selector: 'members_list', testid: 'members-table' } }
= render partial: 'shared/members/member',
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index cad76d7aeac..cf39ac4dd56 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,44 +1,97 @@
- page_title _("Members")
-- can_admin_project_members = can?(current_user, :admin_project_member, @project)
- group = @project.group
.js-remove-member-modal
.row.gl-mt-3
.col-lg-12
- - if project_can_be_shared?
- %h4
- = _("Project members")
- - if can_admin_project_members
- %p= share_project_description(@project)
- - else
- %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)
+ .row
+ .col-md-12.col-lg-6.gl-display-flex
+ .gl-flex-direction-column.gl-flex-wrap.align-items-baseline
+ %h4
+ = _("Project members")
+ .gl-justify-content-bottom.gl-display-flex.align-items-center
+ - if can_manage_project_members?(@project)
+ %p= share_project_description(@project)
+ - else
+ %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 }
+ .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
- .light
- - if can_admin_project_members && 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' }
- %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite member")
- %li.nav-tab{ role: 'presentation', class: ('active' if membership_locked?) }
- %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab', qa_selector: 'invite_group_tab' }, role: 'tab' }= _("Invite group")
+ - else
+ - if project_can_be_shared?
+ %h4
+ = _("Project members")
+ - if can_manage_project_members?(@project)
+ %p= share_project_description(@project)
+ - else
+ %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 }
- .tab-content.gitlab-tab-content
- .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
- = render 'shared/members/invite_member', submit_url: project_project_members_path(@project), access_levels: ProjectMember.access_level_roles, default_access_level: @project_member.access_level, can_import_members?: can_import_members?, import_path: import_project_project_members_path(@project)
- .tab-pane{ id: 'invite-group-pane', role: 'tabpanel', class: ('active' if membership_locked?) }
- = render 'shared/members/invite_group', submit_url: project_group_links_path(@project), access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, group_link_field: 'link_group_id', group_access_field: 'link_group_access'
- - elsif !membership_locked?
- .invite-member= render 'shared/members/invite_member', submit_url: project_project_members_path(@project), access_levels: ProjectMember.access_level_roles, default_access_level: @project_member.access_level, can_import_members?: can_import_members?, import_path: import_project_project_members_path(@project)
- - elsif @project.allowed_to_share_with_group?
- .invite-group= render 'shared/members/invite_group', access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, submit_url: project_group_links_path(@project), group_link_field: 'link_group_id', group_access_field: 'link_group_access'
+ - if !invite_members_allowed?(group) && 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' }
+ %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite member")
+ %li.nav-tab{ role: 'presentation', class: ('active' if membership_locked?) }
+ %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab', qa_selector: 'invite_group_tab' }, role: 'tab' }= _("Invite group")
- = render 'shared/members/requests', membership_source: @project, group: group, requesters: @requesters
- .clearfix
- %h5.member.existing-title
- = _("Existing members and groups")
- - if @group_links.any?
+ .tab-content.gitlab-tab-content
+ .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
+ = render 'shared/members/invite_member', submit_url: project_project_members_path(@project), access_levels: ProjectMember.access_level_roles, default_access_level: @project_member.access_level, can_import_members?: can_import_members?, import_path: import_project_project_members_path(@project)
+ .tab-pane{ id: 'invite-group-pane', role: 'tabpanel', class: ('active' if membership_locked?) }
+ = render 'shared/members/invite_group', submit_url: project_group_links_path(@project), access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, group_link_field: 'link_group_id', group_access_field: 'link_group_access'
+ - elsif !membership_locked?
+ .invite-member= render 'shared/members/invite_member', submit_url: project_project_members_path(@project), access_levels: ProjectMember.access_level_roles, default_access_level: @project_member.access_level, can_import_members?: can_import_members?, import_path: import_project_project_members_path(@project)
+ - elsif @project.allowed_to_share_with_group?
+ .invite-group= render 'shared/members/invite_group', access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, submit_url: project_group_links_path(@project), group_link_field: 'link_group_id', group_access_field: 'link_group_access'
+ %ul.nav-links.mobile-separator.nav.nav-tabs
+ %li.nav-item
+ = link_to '#tab-members', class: ['nav-link', ('active' unless groups_tab_active?)], data: { toggle: 'tab' } do
+ %span
+ = _('Members')
+ %span.badge.badge-pill= @project_members.total_count
+ - if show_groups?(@group_links)
+ %li.nav-item
+ = link_to '#tab-groups', class: ['nav-link', ('active' if groups_tab_active?)] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
+ %span
+ = _('Groups')
+ %span.badge.badge-pill= @group_links.count
+ - if show_invited_members?(@project, @invited_members)
+ %li.nav-item
+ = link_to '#tab-invited-members', class: 'nav-link', data: { toggle: 'tab' } do
+ %span
+ = _('Invited')
+ %span.badge.badge-pill= @invited_members.count
+ - if show_access_requests?(@project, @requesters)
+ %li.nav-item
+ = link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
+ %span
+ = _('Access requests')
+ %span.badge.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)
+ = 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
-
- = render 'projects/project_members/team', project: @project, group: group, members: @project_members
- = paginate @project_members, theme: "gitlab"
+ - 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 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 }
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index 7131e9925b3..6ce01566a42 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -6,24 +6,21 @@
.card-body
= form_errors(@protected_branch)
.form-group.row
- .col-md-2.text-right
- = f.label :name, 'Branch:'
+ = f.label :name, s_('ProtectedBranch|Branch:'), class: 'col-md-2 text-left text-md-right'
.col-md-10
= render partial: "projects/protected_branches/shared/dropdown", locals: { f: f }
.form-text.text-muted
- wildcards_url = help_page_url('user/project/protected_branches', anchor: 'wildcard-protected-branches')
- wildcards_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wildcards_url }
- = (s_("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") % { wildcards_link_start: wildcards_link_start, wildcards_link_end: '</a>', code_tag_start: '<code>', code_tag_end: '</code>' }).html_safe
+ = (s_("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.") % { wildcards_link_start: wildcards_link_start, wildcards_link_end: '</a>', code_tag_start: '<code>', code_tag_end: '</code>' }).html_safe
.form-group.row
- %label.col-md-2.text-right{ for: 'merge_access_levels_attributes' }
- = s_("ProtectedBranch|Allowed to merge:")
+ = f.label :merge_access_levels_attributes, s_("ProtectedBranch|Allowed to merge:"), class: 'col-md-2 text-left text-md-right'
.col-md-10
= yield :merge_access_levels
.form-group.row
- %label.col-md-2.text-right{ for: 'push_access_levels_attributes' }
- = s_("ProtectedBranch|Allowed to push:")
+ = f.label :push_access_levels_attributes, s_("ProtectedBranch|Allowed to push:"), class: 'col-md-2 text-left text-md-right'
.col-md-10
= yield :push_access_levels
- = render_if_exists 'projects/protected_branches/ee/code_owner_approval_form'
+ = render_if_exists 'projects/protected_branches/ee/code_owner_approval_form', f: f
.card-footer
= f.submit s_('ProtectedBranch|Protect'), class: 'btn-success btn', disabled: true, data: { qa_selector: 'protect_button' }
diff --git a/app/views/projects/protected_branches/shared/_index.html.haml b/app/views/projects/protected_branches/shared/_index.html.haml
index f27936703de..66173c4759b 100644
--- a/app/views/projects/protected_branches/shared/_index.html.haml
+++ b/app/views/projects/protected_branches/shared/_index.html.haml
@@ -7,16 +7,15 @@
%button.btn.js-settings-toggle.qa-expand-protected-branches{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
- Keep stable branches secure and force developers to use merge requests.
+ Keep stable branches secure, and force developers to use merge requests. #{link_to "What are protected branches?", help_page_path("user/project/protected_branches")}
.settings-content
%p
- By default, protected branches are designed to:
+ By default, protected branches protect your code and:
%ul
- %li prevent their creation, if not already created, from everybody except Maintainers
- %li prevent pushes from everybody except Maintainers
- %li prevent <strong>anyone</strong> from force pushing to the branch
- %li prevent <strong>anyone</strong> from deleting the branch
- %p Read more about #{link_to "protected branches", help_page_path("user/project/protected_branches")} and #{link_to "project permissions", help_page_path("user/permissions")}.
+ %li Allow only users with Maintainer #{link_to "permissions", help_page_path("user/permissions")} to create new protected branches.
+ %li Allow only users with Maintainer permissions to push code.
+ %li Prevent <strong>anyone</strong> from force-pushing to the branch.
+ %li Prevent <strong>anyone</strong> from deleting the branch.
- if can? current_user, :admin_project, @project
= content_for :create_protected_branch
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
index c4bf2d20ecf..332cdd98e4a 100644
--- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -2,24 +2,19 @@
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-tags-settings' }
.card
.card-header
- Protect a tag
+ = _('Protect a tag')
.card-body
= form_errors(@protected_tag)
.form-group.row
- .col-md-2.text-right
- = f.label :name, 'Tag:'
+ = f.label :name, _('Tag:'), class: 'col-md-2 text-left text-md-right'
.col-md-10.protected-tags-dropdown
= render partial: "projects/protected_tags/shared/dropdown", locals: { f: f }
.form-text.text-muted
- = link_to 'Wildcards', help_page_path('user/project/protected_tags', anchor: 'wildcard-protected-tags')
- such as
- %code v*
- or
- %code *-release
- are supported
+ - wildcards_url = help_page_path('user/project/protected_tags', anchor: 'wildcard-protected-tags')
+ - wildcards_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wildcards_url }
+ = html_escape(_("%{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.")) % { wildcards_link_start: wildcards_link_start, wildcards_link_end: '</a>'.html_safe, code_tag_start: '<code>'.html_safe, code_tag_end: '</code>'.html_safe }
.form-group.row
- %label.col-md-2.text-right{ for: 'create_access_levels_attributes' }
- Allowed to create:
+ = f.label :create_access_levels_attributes, _('Allowed to create:'), class: 'col-md-2 text-left text-md-right'
.col-md-10
.create_access_levels-container
= yield :create_access_levels
diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml
index 4bf3ce09fc7..5734b7dc3c9 100644
--- a/app/views/projects/protected_tags/shared/_index.html.haml
+++ b/app/views/projects/protected_tags/shared/_index.html.haml
@@ -7,16 +7,14 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
- Limit access to creating and updating tags.
+ Limit access to creating and updating tags. #{link_to "What are protected tags?", help_page_path("user/project/protected_tags")}
.settings-content
%p
- By default, protected tags are designed to:
+ By default, protected tags protect your code and:
%ul
- %li Prevent tag creation by everybody except Maintainers
- %li Prevent <strong>anyone</strong> from updating the tag
- %li Prevent <strong>anyone</strong> from deleting the tag
-
- %p Read more about #{link_to "protected tags", help_page_path("user/project/protected_tags")}.
+ %li Allow only users with Maintainer #{link_to "permissions", help_page_path("user/permissions")} to create tags.
+ %li Prevent <strong>anyone</strong> from updating tags.
+ %li Prevent <strong>anyone</strong> from deleting tags.
- if can? current_user, :admin_project, @project
= yield :create_protected_tag
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 382ea848243..a5a43072744 100644
--- a/app/views/projects/protected_tags/shared/_tags_list.html.haml
+++ b/app/views/projects/protected_tags/shared/_tags_list.html.haml
@@ -1,9 +1,9 @@
.protected-tags-list.js-protected-tags-list
- if @protected_tags.empty?
.card-header
- Protected tag (#{@protected_tags_count})
+ Protected tags (#{@protected_tags_count})
%p.settings-message.text-center
- There are currently no protected tags, protect a tag with the form above.
+ No tags are protected.
- else
- can_admin_project = can?(current_user, :admin_project, @project)
@@ -16,7 +16,7 @@
%col
%thead
%tr
- %th Protected tag (#{@protected_tags_count})
+ %th Protected tags (#{@protected_tags_count})
%th Last commit
%th Allowed to create
- if can_admin_project
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index b53fbc97c02..97bc366544f 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -1,23 +1,22 @@
- 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} )
%section
- .row.registry-placeholder.prepend-bottom-10
- .col-12
- #js-container-registry{ data: { endpoint: project_container_registry_index_path(@project),
- expiration_policy: @project.container_expiration_policy.to_json,
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
- "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
- "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
- "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
- "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
- "repository_url" => escape_once(@project.container_registry_url),
- "registry_host_url_with_port" => escape_once(registry_config.host_port),
- "expiration_policy_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'expiration-policy'),
- "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
- "run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
- "cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
- "project_path": @project.full_path,
- "gid_prefix": container_repository_gid_prefix,
- "is_admin": current_user&.admin.to_s,
- character_error: @character_error.to_s } }
+ #js-container-registry{ data: { endpoint: project_container_registry_index_path(@project),
+ expiration_policy: @project.container_expiration_policy.to_json,
+ "help_page_path" => help_page_path('user/packages/container_registry/index'),
+ "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
+ "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
+ "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
+ "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
+ "repository_url" => escape_once(@project.container_registry_url),
+ "registry_host_url_with_port" => escape_once(registry_config.host_port),
+ "expiration_policy_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'expiration-policy'),
+ "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
+ "run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
+ "cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
+ "project_path": @project.full_path,
+ "gid_prefix": container_repository_gid_prefix,
+ "is_admin": current_user&.admin.to_s,
+ character_error: @character_error.to_s } }
diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml
index a24ada53bac..9415516d6f6 100644
--- a/app/views/projects/runners/_group_runners.html.haml
+++ b/app/views/projects/runners/_group_runners.html.haml
@@ -1,37 +1,40 @@
-- link = link_to _('Runners API'), help_page_path('api/runners.md')
+- link = link_to _('Runner API'), help_page_path('api/runners.md')
-%h3
- = _('Group Runners')
+%h4
+ = _('Group runners')
.bs-callout.bs-callout-warning
- = _('GitLab Group Runners can execute code for all the projects in this group.')
- = _('They can be managed using the %{link}.').html_safe % { link: link }
+ = _('These runners are shared across projects in this group.')
+ %br
+ %br
+ = _('Group runners can be managed with the %{link}.').html_safe % { link: link }
- if @project.group
- %hr
+ %br
+ %br
- if @project.group_runners_enabled?
= link_to toggle_group_runners_project_runners_path(@project), class: 'btn btn-close', method: :post do
- = _('Disable group Runners')
+ = _('Disable group runners')
- else
= link_to toggle_group_runners_project_runners_path(@project), class: 'btn btn-success btn-inverted', method: :post do
- = _('Enable group Runners')
+ = _('Enable group runners')
&nbsp;
= _('for this project')
- if !@project.group
- = _('This project does not belong to a group and can therefore not make use of group Runners.')
+ = _('This project does not belong to a group and cannot make use of group runners.')
- elsif @group_runners.empty?
- = _('This group does not provide any group Runners yet.')
+ = _('This group does not have any group runners yet.')
- if can?(current_user, :admin_pipeline, @project.group)
- - group_link = link_to _('Group CI/CD settings'), group_settings_ci_cd_path(@project.group)
+ - group_link = link_to _("group's CI/CD settings."), group_settings_ci_cd_path(@project.group)
= _('Group maintainers can register group runners in the %{link}').html_safe % { link: group_link }
- else
- = _('Ask your group maintainer to set up a group Runner.')
+ = _('Ask your group maintainer to set up a group runner.')
- else
%h4.underlined-title
- = _('Available group Runners: %{runners}').html_safe % { runners: @group_runners.count }
+ = _('Available group runners: %{runners}').html_safe % { runners: @group_runners.count }
%ul.bordered-list
= render partial: 'projects/runners/runner', collection: @group_runners, as: :runner
diff --git a/app/views/projects/runners/_index.html.haml b/app/views/projects/runners/_index.html.haml
index ae4fee1e14c..a02bdac442b 100644
--- a/app/views/projects/runners/_index.html.haml
+++ b/app/views/projects/runners/_index.html.haml
@@ -1,8 +1,5 @@
= render 'shared/runners/runner_description'
-%hr
-
-%p.lead= _('To start serving your jobs you can either add specific Runners to your project or use shared Runners')
.row
.col-sm-6
= render 'projects/runners/specific_runners'
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 1a3ba690184..85bd0335b92 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -23,7 +23,7 @@
- else
= link_to _('Resume'), resume_project_runner_path(@project, runner), method: :post, class: 'btn 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 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'
diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml
index 4093f0a0719..fd8b4eb0d39 100644
--- a/app/views/projects/runners/_shared_runners.html.haml
+++ b/app/views/projects/runners/_shared_runners.html.haml
@@ -2,7 +2,8 @@
= render layout: 'shared/runners/shared_runners_description' do
- if !isVueifySharedRunnersToggleEnabled
- %hr
+ %br
+ %br
- if @project.group&.shared_runners_setting == 'disabled_and_unoverridable'
%h5.gl-text-red-500
= _('Shared runners disabled on group level')
@@ -19,8 +20,8 @@
#toggle-shared-runners-form{ data: toggle_shared_runners_settings_data(@project) }
- if @shared_runners_count == 0
- = _('This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area.')
+ = _('This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area.')
- else
- %h4.underlined-title #{_('Available shared Runners:')} #{@shared_runners_count}
+ %h4.underlined-title #{_('Available shared runners:')} #{@shared_runners_count}
%ul.bordered-list.available-shared-runners
= render partial: 'projects/runners/runner', collection: @shared_runners, as: :runner
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index ed9e6aac346..3e325b80efd 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -1,7 +1,9 @@
-%h3
- = _('Specific Runners')
+%h4
+ = _('Specific runners')
.bs-callout.help-callout
+ = _('These runners are specific to this project.')
+ %hr
= render partial: 'ci/runner/how_to_setup_runner_automatically',
locals: { type: 'specific',
clusters_path: project_clusters_path(@project) }
@@ -11,14 +13,16 @@
type: 'specific',
reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path }
+%hr
+
- if @project_runners.any?
- %h4.underlined-title= _('Runners activated for this project')
+ %h4.underlined-title= _('Available specific runners')
%ul.bordered-list.activated-specific-runners
= render partial: 'projects/runners/runner', collection: @project_runners, as: :runner
= paginate @project_runners, theme: "gitlab", param_name: "project_page", params: { expand_runners: true, anchor: 'js-runners-settings' }
- if @assignable_runners.any?
- %h4.underlined-title= _('Available specific runners')
+ %h4.underlined-title= _('Other available runners')
%ul.bordered-list.available-specific-runners
= render partial: 'projects/runners/runner', collection: @assignable_runners, as: :runner
= paginate @assignable_runners, theme: "gitlab", param_name: "specific_page", :params => { :anchor => 'js-runners-settings'}
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index b9d8e154913..f93cd23c83e 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -1,4 +1,4 @@
-- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", _('Runners')
+- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", _('runners')
%h4 Runner ##{@runner.id}
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 2b1e08f4880..59b3afa476f 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -5,10 +5,8 @@
.col-lg-4
%h3.page-title.gl-mt-0
= @service.title
- - [true, false].each do |value|
- - hide_class = 'd-none' if @service.operating? != value
- %span.js-service-active-status{ class: hide_class, data: { value: value.to_s } }
- = boolean_to_icon value
+ - if @service.operating?
+ = sprite_icon('check', css_class: 'gl-text-green-500')
- if @service.respond_to?(:detailed_description)
%p= @service.detailed_description
diff --git a/app/views/projects/services/alerts/_help.html.haml b/app/views/projects/services/alerts/_help.html.haml
deleted file mode 100644
index 7abd198bea5..00000000000
--- a/app/views/projects/services/alerts/_help.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-.js-alerts-service-settings{ data: alerts_settings_data(disabled: true) }
diff --git a/app/views/projects/services/alerts/_top.html.haml b/app/views/projects/services/alerts/_top.html.haml
deleted file mode 100644
index e3bcb6bd3a0..00000000000
--- a/app/views/projects/services/alerts/_top.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-.row
- .col-lg-12
- .gl-alert.gl-alert-info{ role: 'alert' }
- = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- = _('You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. 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 new-gl-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 453deff7756..2e4542a033e 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -25,15 +25,15 @@
- if auto_devops_enabled
%span.badge.badge-info.js-instance-default-badge= badge_for_auto_devops_scope(@project)
.form-text.text-muted
- = s_('CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
- = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
+ = s_('CICD|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'
.card-footer.js-extra-settings{ class: auto_devops_enabled || 'hidden' }
- if @project.all_clusters.empty?
%p.settings-message.text-center
- = s_('CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable.').html_safe % { kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
+ = s_('CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable.').html_safe % { kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
- elsif !has_base_domain
%p.settings-message.text-center
- = s_('CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work.').html_safe % { base_domain_link_start: base_domain_link_start, kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
+ = s_('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.').html_safe % { base_domain_link_start: base_domain_link_start, kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
%label.gl-mt-3
%strong= s_('CICD|Deployment strategy')
.form-check
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 0bef82ee325..55b6cf372fb 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -27,7 +27,7 @@
- quickstart_url = help_page_path('topics/autodevops/quick_start_guide')
- auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
- quickstart_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: quickstart_url }
- = s_('AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
+ = s_('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}').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
.settings-content
= render 'autodevops_form', auto_devops_enabled: @project.auto_devops_enabled?
@@ -40,11 +40,22 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _("Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project.")
- = link_to s_('More information'), help_page_path('ci/runners/README')
+ = _("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')
.settings-content
= render 'projects/runners/index'
+%section.settings.no-animate#js-artifacts-settings{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4
+ = _("Artifacts")
+ %button.btn.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.")
+ .settings-content
+ #js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
+
%section.qa-variables-settings.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { qa_selector: 'variables_settings_content' } }
.settings-header
= render 'ci/variables/header', expanded: expanded
@@ -71,7 +82,7 @@
= 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 _('More information'), 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'
diff --git a/app/views/projects/settings/operations/_alert_management.html.haml b/app/views/projects/settings/operations/_alert_management.html.haml
index 9e76ad52ecb..46f45df00df 100644
--- a/app/views/projects/settings/operations/_alert_management.html.haml
+++ b/app/views/projects/settings/operations/_alert_management.html.haml
@@ -1,6 +1,7 @@
- return unless can?(current_user, :admin_operations, @project)
- expanded = expanded_by_default?
- add_page_specific_style 'page_bundles/alert_management_settings'
+- add_page_specific_style 'page_bundles/incident_management_list'
%section.settings.no-animate#js-alert-management-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 5b9f868a71a..40faf91eadf 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,3 +1,5 @@
+- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
+- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
- @content_class = "limit-container-width" unless fluid_layout
- @skip_current_level_breadcrumb = true
diff --git a/app/views/projects/snippets/verify.html.haml b/app/views/projects/snippets/verify.html.haml
deleted file mode 100644
index 3c4f08e1df7..00000000000
--- a/app/views/projects/snippets/verify.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-= render 'layouts/recaptcha_verification', spammable: @snippet
-
diff --git a/app/views/projects/tracings/_tracing_button.html.haml b/app/views/projects/tracings/_tracing_button.html.haml
index c9a6afd3761..b0ab6fa21e1 100644
--- a/app/views/projects/tracings/_tracing_button.html.haml
+++ b/app/views/projects/tracings/_tracing_button.html.haml
@@ -1,2 +1,2 @@
-= link_to project_settings_operations_path(@project), title: _('Configure Tracing'), class: 'btn btn-success' do
+= link_to project_settings_operations_path(@project), title: _('Configure Tracing'), class: 'gl-button btn btn-success' do
= _('Add Jaeger URL')
diff --git a/app/views/shared/_recaptcha_form.html.haml b/app/views/shared/_recaptcha_form.html.haml
index 245a86721eb..aa9e9a34c90 100644
--- a/app/views/shared/_recaptcha_form.html.haml
+++ b/app/views/shared/_recaptcha_form.html.haml
@@ -9,8 +9,11 @@
- params[resource_name].each do |field, value|
= hidden_field(resource_name, field, value: value)
= hidden_field_tag(:spam_log_id, spammable.spam_log.id)
- = hidden_field_tag(:recaptcha_verification, true)
+ -# The reCAPTCHA response value will be returned in the 'g-recaptcha-response' field
= recaptcha_tags script: script, callback: 'recaptchaDialogCallback' unless Rails.env.test?
+ -# Fake the 'g-recaptcha-response' field in the test environment, so that the feature spec
+ -# can get to the (mocked) SpamVerdictService check.
+ = hidden_field_tag('g-recaptcha-response', 'abc123') if Rails.env.test?
-# Yields a block with given extra params.
= yield
diff --git a/app/views/shared/_search_settings.html.haml b/app/views/shared/_search_settings.html.haml
new file mode 100644
index 00000000000..ea3d7b97327
--- /dev/null
+++ b/app/views/shared/_search_settings.html.haml
@@ -0,0 +1,2 @@
+- if Feature.enabled?(:search_settings_in_page, @project, default_enabled: false)
+ .js-search-settings-app
diff --git a/app/views/shared/_zen.html.haml b/app/views/shared/_zen.html.haml
index 9cf189e8120..5a4efe7fe7f 100644
--- a/app/views/shared/_zen.html.haml
+++ b/app/views/shared/_zen.html.haml
@@ -3,6 +3,7 @@
- supports_autocomplete = local_assigns.fetch(:supports_autocomplete, true)
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
- qa_selector = local_assigns.fetch(:qa_selector, '')
+- autofocus = local_assigns.fetch(:autofocus, false)
.zen-backdrop
- classes << ' js-gfm-input js-autosize markdown-area'
- if defined?(f) && f
@@ -12,7 +13,8 @@
dir: 'auto',
data: { supports_quick_actions: supports_quick_actions,
supports_autocomplete: supports_autocomplete,
- qa_selector: qa_selector }
+ qa_selector: qa_selector,
+ autofocus: autofocus }
- else
= text_area_tag attr, current_text, data: { qa_selector: qa_selector }, class: classes, placeholder: placeholder
%a.zen-control.zen-control-leave.js-zen-leave.gl-text-gray-500{ href: "#" }
diff --git a/app/views/shared/deploy_tokens/_index.html.haml b/app/views/shared/deploy_tokens/_index.html.haml
index 540b9b0054f..c26400690a6 100644
--- a/app/views/shared/deploy_tokens/_index.html.haml
+++ b/app/views/shared/deploy_tokens/_index.html.haml
@@ -3,7 +3,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')
- %button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
+ %button.gl-button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
= description
diff --git a/app/views/shared/deploy_tokens/_revoke_modal.html.haml b/app/views/shared/deploy_tokens/_revoke_modal.html.haml
index 5a3759ef755..2b31c675f74 100644
--- a/app/views/shared/deploy_tokens/_revoke_modal.html.haml
+++ b/app/views/shared/deploy_tokens/_revoke_modal.html.haml
@@ -10,6 +10,6 @@
%p
= s_('DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}.').html_safe % { b_start: '<b>'.html_safe, name: token.name, b_end: '</b>'.html_safe }
= s_('DeployTokens|This action cannot be undone.')
- .modal-footer
- %a{ href: '#', data: { dismiss: 'modal' }, class: 'btn btn-default' }= _('Cancel')
- = link_to s_('DeployTokens|Revoke %{name}') % { name: token.name }, revoke_deploy_token_path(group_or_project, token), method: :put, class: 'btn btn-danger'
+ .modal-footer.gl-flex-direction-row
+ %a{ href: '#', data: { dismiss: 'modal' }, class: 'gl-button btn btn-default' }= _('Cancel')
+ = link_to s_('DeployTokens|Revoke %{name}') % { name: token.name }, revoke_deploy_token_path(group_or_project, token), method: :put, class: 'gl-button btn btn-danger text-truncate'
diff --git a/app/views/shared/empty_states/_snippets.html.haml b/app/views/shared/empty_states/_snippets.html.haml
index db8da50d868..aa762782c46 100644
--- a/app/views/shared/empty_states/_snippets.html.haml
+++ b/app/views/shared/empty_states/_snippets.html.haml
@@ -1,6 +1,6 @@
- button_path = local_assigns.fetch(:button_path, false)
-.row.empty-state.mt-0
+.row.empty-state
.col-12
.svg-content
= image_tag 'illustrations/snippets_empty.svg', data: { qa_selector: 'svg_content' }
@@ -16,5 +16,3 @@
= link_to s_('SnippetsEmptyState|Documentation'), help_page_path('user/snippets.md'), class: 'btn btn-default', title: s_('SnippetsEmptyState|Documentation')
- else
%h4.text-center= s_('SnippetsEmptyState|There are no snippets to show.')
-
-
diff --git a/app/views/shared/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml
index 656acafd416..4150406a4ea 100644
--- a/app/views/shared/empty_states/_wikis.html.haml
+++ b/app/views/shared/empty_states/_wikis.html.haml
@@ -3,7 +3,7 @@
- if can?(current_user, :create_wiki, @wiki.container)
- create_path = wiki_page_path(@wiki, params[:id], view: 'create')
- - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn btn-success qa-create-first-page-link', title: s_('WikiEmpty|Create your first page')
+ - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn gl-button btn-success qa-create-first-page-link', title: s_('WikiEmpty|Create your first page')
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_login_empty.svg' } do
%h4.text-left
@@ -14,11 +14,11 @@
- if show_enable_confluence_integration?(@wiki.container)
= link_to s_('WikiEmpty|Enable the Confluence Wiki integration'),
edit_project_service_path(@project, :confluence),
- class: 'btn', title: s_('WikiEmpty|Enable the Confluence Wiki integration')
+ class: 'btn gl-button', title: s_('WikiEmpty|Enable the Confluence Wiki integration')
- elsif @project && can?(current_user, :read_issue, @project)
- issues_link = link_to s_('WikiEmptyIssueMessage|issue tracker'), project_issues_path(@project)
- - new_issue_link = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn btn-success', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement')
+ - new_issue_link = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn gl-button btn-success', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement')
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_logout_empty.svg' } do
%h4
diff --git a/app/views/shared/integrations/_index.html.haml b/app/views/shared/integrations/_index.html.haml
index edc85f04d91..ccc2c448f69 100644
--- a/app/views/shared/integrations/_index.html.haml
+++ b/app/views/shared/integrations/_index.html.haml
@@ -16,7 +16,8 @@
- activated_label = (integration.activated? ? s_("ProjectService|%{service_title}: status on") : s_("ProjectService|%{service_title}: status off")) % { service_title: integration.title }
%tr{ role: 'row' }
%td{ role: 'cell', 'aria-colindex': 1, 'aria-label': activated_label, title: activated_label }
- = boolean_to_icon integration.operating?
+ - if integration.operating?
+ = sprite_icon('check', css_class: 'gl-text-green-500')
%td{ role: 'cell', 'aria-colindex': 2 }
= link_to integration.title, scoped_edit_integration_path(integration), class: 'gl-font-weight-bold', data: { qa_selector: "#{integration.to_param}_link" }
%td.d-none.d-sm-table-cell{ role: 'cell', 'aria-colindex': 3 }
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index cd265c10451..911bef482dd 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -2,6 +2,7 @@
This should be removed when this sidebar is converted to Vue since assignee data is also available in the `issuable_sidebar` hash
- issuable_type = issuable_sidebar[:type]
+- show_forwarding_email = !issuable_sidebar[:create_note_email].nil?
- signed_in = !!issuable_sidebar.dig(:current_user, :id)
- can_edit_issuable = issuable_sidebar.dig(:current_user, :can_edit)
- add_page_startup_api_call "#{issuable_sidebar[:issuable_json_path]}?serializer=sidebar_extras"
@@ -57,7 +58,7 @@
.selectbox.hide-collapsed
= 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?
+ - 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
- if issuable_sidebar[:supports_time_tracking]
@@ -65,7 +66,7 @@
// Fallback while content is loading
.title.hide-collapsed
= _('Time tracking')
- = loading_icon
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom')
- if issuable_sidebar.has_key?(:due_date)
.block.due_date
.sidebar-collapsed-icon.has-tooltip{ data: { placement: 'left', container: 'body', html: 'true', boundary: 'viewport' }, title: sidebar_due_date_tooltip_label(issuable_sidebar[:due_date]) }
@@ -145,12 +146,15 @@
= _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<cite class='ref-name' title='#{source_branch}'>".html_safe, source_branch_close: "</cite>".html_safe, source_branch: source_branch }
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
+ - if show_forwarding_email
+ .block
+ #issuable-copy-email
- if issuable_sidebar.dig(:current_user, :can_move)
.block.js-sidebar-move-issue-block
.sidebar-collapsed-icon{ data: { toggle: 'tooltip', placement: 'left', container: 'body', boundary: 'viewport' }, title: _('Move issue') }
= custom_icon('icon_arrow_right')
.dropdown.sidebar-move-issue-dropdown.hide-collapsed
- %button.btn.btn-default.btn-block.js-sidebar-dropdown-toggle.js-move-issue{ type: 'button',
+ %button.gl-button.btn.btn-default.btn-block.js-sidebar-dropdown-toggle.js-move-issue{ type: 'button',
data: { toggle: 'dropdown', display: 'static', track_label: "right_sidebar", track_property: "move_issue", track_event: "click_button", track_value: "" } }
= _('Move issue')
.dropdown-menu.dropdown-menu-selectable.dropdown-extended-height
@@ -159,7 +163,7 @@
= dropdown_content
= dropdown_loading
= dropdown_footer add_content_class: true do
- %button.btn.btn-success.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ type: 'button', disabled: true }
+ %button.gl-button.btn.btn-success.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ type: 'button', disabled: true }
= _('Move')
= loading_icon(css_class: 'gl-vertical-align-text-bottom sidebar-move-issue-confirmation-loading-icon')
diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index a425f5f810e..70e931ac164 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -6,6 +6,17 @@
- source_title, target_title = format_mr_branch_names(@merge_request)
+- vis010 = _('This merge request is from a private project to an internal project.')
+- vis020 = _('This merge request is from a private project to a public project.')
+- vis1020 = _('This merge request is from an internal project to a public project.')
+- i18n = { '010' => vis010, '020' => vis020, '1020' => vis1020 }
+
+- source_level = @merge_request.source_project.visibility_level
+- source_visibility = @merge_request.source_project.visibility
+- target_level = @merge_request.target_project.visibility_level
+
+- visibilityMismatchString = i18n["#{source_level}#{target_level}"]
+
.form-group.row.d-flex.gl-px-5.branch-selector
.align-self-center
%span
@@ -24,4 +35,12 @@
= form.hidden_field(:target_branch,
{ class: 'target_branch js-target-branch-select ref-name mw-xl',
data: { placeholder: _('Select branch'), endpoint: refs_project_path(@project, sort: 'updated_desc', find: 'branches') }})
+
+- if source_level < target_level
+ .gl-alert.gl-alert-warning.gl-mt-4
+ = sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ = visibilityMismatchString
+ %br
+ = _('Review the target project before submitting to avoid exposing %{source} changes.') % { source: source_visibility }
%hr
diff --git a/app/views/shared/members/_badge.html.haml b/app/views/shared/members/_badge.html.haml
index e304207f3e9..5f925ff0cad 100644
--- a/app/views/shared/members/_badge.html.haml
+++ b/app/views/shared/members/_badge.html.haml
@@ -1,4 +1,4 @@
- type ||= 'info'
%span.px-1.py-1
- %span{ class: "badge badge-#{type}" }= yield
+ %span{ class: "badge badge-pill gl-badge sm badge-#{type}" }= yield
diff --git a/app/views/shared/members/_invite_member.html.haml b/app/views/shared/members/_invite_member.html.haml
index 59b0600e2dd..0302b2fc3cf 100644
--- a/app/views/shared/members/_invite_member.html.haml
+++ b/app/views/shared/members/_invite_member.html.haml
@@ -23,6 +23,6 @@
.clearable-input
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
= sprite_icon('close', size: 16, css_class: 'clear-icon js-clear-input gl-text-gray-200')
- = submit_tag _("Invite"), class: "btn btn-success", data: { qa_selector: 'invite_member_button' }
+ = submit_tag _("Invite"), class: "gl-button btn btn-success", data: { qa_selector: 'invite_member_button' }
- if can_import_members
- = link_to _("Import"), import_path, class: "btn btn-default", title: _("Import members from another project")
+ = link_to _("Import"), import_path, class: "gl-button btn btn-default", title: _("Import members from another project")
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 79bbb74d601..c76051a25b2 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -127,8 +127,5 @@
= _("Delete")
- unless force_mobile_view
= sprite_icon('remove', css_class: 'd-none d-sm-block gl-icon')
- = render_if_exists 'shared/members/ee/override_member_buttons', group: group, member: member, user: user, action: :edit, can_override: member.can_override?
- else
%span.member-access-text.user-access-role= member.human_access
-
-= render_if_exists 'shared/members/ee/override_member_buttons', group: group, member: member, user: user, action: :confirm, can_override: member.can_override?
diff --git a/app/views/groups/group_members/tab_pane/_form_item.html.haml b/app/views/shared/members/tab_pane/_form_item.html.haml
index 9e57d3329d7..9e57d3329d7 100644
--- a/app/views/groups/group_members/tab_pane/_form_item.html.haml
+++ b/app/views/shared/members/tab_pane/_form_item.html.haml
diff --git a/app/views/groups/group_members/tab_pane/_header.html.haml b/app/views/shared/members/tab_pane/_header.html.haml
index a02bf90eddf..a02bf90eddf 100644
--- a/app/views/groups/group_members/tab_pane/_header.html.haml
+++ b/app/views/shared/members/tab_pane/_header.html.haml
diff --git a/app/views/groups/group_members/tab_pane/_title.html.haml b/app/views/shared/members/tab_pane/_title.html.haml
index c1418a5f7c8..c1418a5f7c8 100644
--- a/app/views/groups/group_members/tab_pane/_title.html.haml
+++ b/app/views/shared/members/tab_pane/_title.html.haml
diff --git a/app/views/shared/milestones/_header.html.haml b/app/views/shared/milestones/_header.html.haml
index 19ca00ce482..541d7a52385 100644
--- a/app/views/shared/milestones/_header.html.haml
+++ b/app/views/shared/milestones/_header.html.haml
@@ -14,12 +14,9 @@
= link_to _('Edit'), edit_milestone_path(milestone), class: 'btn gl-button btn-grouped'
- if milestone.project_milestone? && milestone.project.group
- %button.js-promote-project-milestone-button.btn.gl-button.btn-grouped{ data: { toggle: 'modal',
- target: '#promote-milestone-modal',
- milestone_title: milestone.title,
+ %button.js-promote-project-milestone-button.btn.gl-button.btn-grouped{ data: { milestone_title: milestone.title,
group_name: milestone.project.group.name,
- url: promote_project_milestone_path(milestone.project, milestone),
- container: 'body' },
+ url: promote_project_milestone_path(milestone.project, milestone)},
disabled: true,
type: 'button' }
= _('Promote')
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 92ac6929e6a..48a97ed66bb 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -51,10 +51,7 @@
type: 'button',
data: { url: promote_project_milestone_path(milestone.project, milestone),
milestone_title: milestone.title,
- group_name: @project.group.name,
- target: '#promote-milestone-modal',
- container: 'body',
- toggle: 'modal' } }
+ group_name: @project.group.name } }
= sprite_icon('level-up', size: 14)
- if can?(current_user, :admin_milestone, milestone)
diff --git a/app/views/shared/promotions/_promote_servicedesk.html.haml b/app/views/shared/promotions/_promote_servicedesk.html.haml
index 237416a869b..3a5123acdeb 100644
--- a/app/views/shared/promotions/_promote_servicedesk.html.haml
+++ b/app/views/shared/promotions/_promote_servicedesk.html.haml
@@ -6,8 +6,6 @@
= custom_icon('icon_service_desk')
.user-callout-copy
%h4
- = _("Improve customer support with GitLab Service Desk.")
+ = _("Improve customer support with Service Desk")
%p
- = _("GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email.")
- = link_to _('Read more'), help_page_path('user/project/service_desk.md'), target: '_blank'
-
+ = _("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.")
diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml
index 675a8f922c4..bb2aa93740e 100644
--- a/app/views/shared/runners/_form.html.haml
+++ b/app/views/shared/runners/_form.html.haml
@@ -5,7 +5,7 @@
.col-sm-10
.form-check
= f.check_box :active, { class: 'form-check-input' }
- %label.light{ for: :runner_active }= _("Paused Runners don't accept new jobs")
+ %label.light{ for: :runner_active }= _("Paused runners don't accept new jobs")
.form-group.row
= label :protected, _("Protected"), class: 'col-form-label col-sm-2'
.col-sm-10
@@ -40,13 +40,13 @@
= _('Maximum job timeout')
.col-sm-10
= f.text_field :maximum_timeout_human_readable, class: 'form-control'
- .form-text.text-muted= _('This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like "1 hour". Values without specification represent seconds.')
+ .form-text.text-muted= _('Enter the number of seconds, or other human-readable input, like "1 hour". This timeout takes precedence over lower timeouts set for the project.')
.form-group.row
= label_tag :tag_list, class: 'col-form-label col-sm-2' do
= _('Tags')
.col-sm-10
= f.text_field :tag_list, value: runner.tag_list.sort.join(', '), class: 'form-control'
- .form-text.text-muted= _('You can set up jobs to only use Runners with specific tags. Separate tags with commas.')
+ .form-text.text-muted= _('You can set up jobs to only use runners with specific tags. Separate tags with commas.')
- if local_assigns[:in_gitlab_com_admin_context]
.form-group.row
= label_tag :public_projects_minutes_cost_factor, class: 'col-form-label col-sm-2' do
diff --git a/app/views/shared/runners/_runner_description.html.haml b/app/views/shared/runners/_runner_description.html.haml
index d3e50cfe92f..6a65145d42b 100644
--- a/app/views/shared/runners/_runner_description.html.haml
+++ b/app/views/shared/runners/_runner_description.html.haml
@@ -1,16 +1,12 @@
.light.gl-mt-3
%p
- = _("You can set up as many Runners as you need to run your jobs.")
- %br
- = _('Runners can be placed on separate users, servers, and even on your local machine.')
+ = _("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:")
- %p
- = _('Each Runner can be in one of the following states:')
%div
%ul
%li
- %span.badge.badge-success active
- = _('- Runner is active and can process any new jobs')
+ %span.badge.badge-pill.gl-badge.sm.badge-success active
+ = _('- Available to run jobs.')
%li
- %span.badge.badge-danger paused
- = _('- Runner is paused and will not receive any new jobs')
+ %span.badge.badge-pill.gl-badge.sm.badge-danger paused
+ = _('- Not available to run jobs.')
diff --git a/app/views/shared/runners/_shared_runners_description.html.haml b/app/views/shared/runners/_shared_runners_description.html.haml
index b9fb518b1aa..92564ec48bd 100644
--- a/app/views/shared/runners/_shared_runners_description.html.haml
+++ b/app/views/shared/runners/_shared_runners_description.html.haml
@@ -1,9 +1,11 @@
- link = link_to _('MaxBuilds'), 'https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section', target: '_blank'
-%h3
+%h4
= _('Shared runners')
.bs-callout.shared-runners-description
+ = _('These runners are shared across this GitLab instance.')
+ %p
- if Gitlab::CurrentSettings.shared_runners_text.present?
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :shared_runners_text)
- else
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index a957f9f6dfa..13fe8f76bd3 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -5,8 +5,8 @@
%div
- hook.class.triggers.each_value do |trigger|
- if hook.public_send(trigger)
- %span.badge.badge-gray.deploy-project-label= trigger.to_s.titleize
- %span.badge.badge-gray
+ %span.gl-badge.gl-bg-gray-10.gl-mt-2.rounded.deploy-project-label= trigger.to_s.titleize
+ %span.gl-badge.gl-bg-gray-10.gl-mt-2.rounded
= _('SSL Verification:')
= hook.enable_ssl_verification ? _('enabled') : _('disabled')
diff --git a/app/views/shared/wikis/_form.html.haml b/app/views/shared/wikis/_form.html.haml
index b6504c7a17e..5fd22665633 100644
--- a/app/views/shared/wikis/_form.html.haml
+++ b/app/views/shared/wikis/_form.html.haml
@@ -42,7 +42,7 @@
.col-sm-2.col-form-label= f.label :content, class: 'control-label-full-width'
.col-sm-10
= render layout: 'shared/md_preview', locals: { url: wiki_page_path(@wiki, @page, action: :preview_markdown) } do
- = render 'shared/zen', f: f, attr: :content, classes: 'note-textarea qa-wiki-content-textarea', placeholder: s_("WikiPage|Write your content or drag files here…")
+ = render 'shared/zen', f: f, attr: :content, classes: 'note-textarea qa-wiki-content-textarea', placeholder: s_("WikiPage|Write your content or drag files here…"), autofocus: @page.persisted?
= render 'shared/notes/hints'
.clearfix
@@ -70,10 +70,10 @@
.form-actions
- if @page && @page.persisted?
- = f.submit _("Save changes"), class: 'btn-success btn qa-save-changes-button'
+ = f.submit _("Save changes"), class: 'btn gl-button btn-success qa-save-changes-button js-wiki-btn-submit', disabled: 'true'
.float-right
- = link_to _("Cancel"), wiki_page_path(@wiki, @page), class: 'btn gl-button btn-cancel btn-grouped'
+ = link_to _("Cancel"), wiki_page_path(@wiki, @page), class: 'btn gl-button btn-cancel btn-default'
- else
- = f.submit s_("Wiki|Create page"), class: 'btn-success btn qa-create-page-button rspec-create-page-button'
+ = f.submit s_("Wiki|Create page"), class: 'btn-success gl-button btn qa-create-page-button rspec-create-page-button js-wiki-btn-submit', disabled: 'true'
.float-right
- = link_to _("Cancel"), wiki_path(@wiki), class: 'btn gl-button btn-cancel'
+ = link_to _("Cancel"), wiki_path(@wiki), class: 'btn gl-button btn-cancel btn-default'
diff --git a/app/views/shared/wikis/_sidebar.html.haml b/app/views/shared/wikis/_sidebar.html.haml
index a906bf7aa63..4e9fdc8b95a 100644
--- a/app/views/shared/wikis/_sidebar.html.haml
+++ b/app/views/shared/wikis/_sidebar.html.haml
@@ -1,13 +1,23 @@
+- editing ||= false
+
%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" } }
.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: "#" }
= sprite_icon('chevron-double-lg-right', css_class: 'gl-icon')
- - git_access_url = wiki_path(@wiki, action: :git_access)
- = link_to git_access_url, class: active_nav_link?(path: 'wikis#git_access') ? 'active' : '', data: { qa_selector: 'clone_repository_link' } do
- = sprite_icon('download', css_class: 'gl-mr-2')
- %span= _("Clone repository")
+ .gl-display-flex.gl-flex-wrap
+ - git_access_url = wiki_path(@wiki, action: :git_access)
+ = link_to git_access_url, class: 'gl-mr-5' + (active_nav_link?(path: 'wikis#git_access') ? ' active' : ''), data: { qa_selector: 'clone_repository_link' } do
+ = sprite_icon('download', css_class: 'gl-mr-2')
+ %span= _("Clone repository")
+
+ - if can?(current_user, :create_wiki, @wiki)
+ - edit_sidebar_url = wiki_page_path(@wiki, Wiki::SIDEBAR, action: :edit)
+ - link_class = (editing && @page&.slug == Wiki::SIDEBAR) ? 'active' : ''
+ = link_to edit_sidebar_url, class: link_class, data: { qa_selector: 'edit_sidebar_link' } do
+ = sprite_icon('pencil-square', css_class: 'gl-mr-2')
+ %span= _("Edit sidebar")
- if @sidebar_error.present?
= render 'shared/alert_info', body: s_('Wiki|The sidebar failed to load. You can reload the page to try again.')
diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml
index 68bbbd66f4a..19167f04855 100644
--- a/app/views/shared/wikis/diff.html.haml
+++ b/app/views/shared/wikis/diff.html.haml
@@ -5,12 +5,11 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- .nav-text
- %h2.wiki-page-title
- = link_to_wiki_page @page
- %span.light
- &middot;
- = _('Changes')
+ %h3.page-title.gl-flex-fill-1
+ = link_to_wiki_page @page
+ %span.light
+ &middot;
+ = _('Changes')
.nav-controls.pb-md-3.pb-lg-0
= link_to wiki_page_path(@wiki, @page, action: :history), class: 'btn gl-button', role: 'button', data: { qa_selector: 'page_history_button' } do
diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml
index 834749caaba..c2b0e474c03 100644
--- a/app/views/shared/wikis/edit.html.haml
+++ b/app/views/shared/wikis/edit.html.haml
@@ -6,15 +6,14 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- .nav-text
- %h2.wiki-page-title
- - if @page.persisted?
- = link_to_wiki_page @page
- %span.light
- &middot;
- = s_("Wiki|Edit Page")
- - else
- = s_("Wiki|Create New Page")
+ %h3.page-title.gl-flex-fill-1
+ - if @page.persisted?
+ = link_to_wiki_page @page
+ %span.light
+ &middot;
+ = s_("Wiki|Edit Page")
+ - else
+ = s_("Wiki|Create New Page")
.nav-controls.pb-md-3.pb-lg-0
- if @page.persisted?
@@ -23,4 +22,4 @@
= render 'shared/wikis/form', uploads_path: wiki_attachment_upload_url
-= render 'shared/wikis/sidebar'
+= render 'shared/wikis/sidebar', editing: true
diff --git a/app/views/shared/wikis/history.html.haml b/app/views/shared/wikis/history.html.haml
index 50ccfdeabd5..b1dcd2cd400 100644
--- a/app/views/shared/wikis/history.html.haml
+++ b/app/views/shared/wikis/history.html.haml
@@ -4,12 +4,11 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- .nav-text
- %h2.wiki-page-title
- = link_to_wiki_page @page
- %span.light
- &middot;
- = _('History')
+ %h3.page-title
+ = link_to_wiki_page @page
+ %span.light
+ &middot;
+ = _('History')
.prepend-top-default.gl-mb-3
.table-holder
diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml
index 76fc9510740..f5ba1c83de4 100644
--- a/app/views/shared/wikis/pages.html.haml
+++ b/app/views/shared/wikis/pages.html.haml
@@ -6,9 +6,9 @@
.wiki-page-header.top-area.flex-column.flex-lg-row
- .nav-text.flex-fill
- %h2.wiki-page-title
- = s_("Wiki|Wiki Pages")
+
+ %h3.page-title.gl-flex-fill-1
+ = s_("Wiki|Wiki Pages")
.nav-controls.pb-md-3.pb-lg-0
= link_to wiki_path(@wiki, action: :git_access), class: 'btn gl-button' do
diff --git a/app/views/shared/wikis/show.html.haml b/app/views/shared/wikis/show.html.haml
index 6f1c1a3a801..6d14ba8fe7b 100644
--- a/app/views/shared/wikis/show.html.haml
+++ b/app/views/shared/wikis/show.html.haml
@@ -7,7 +7,7 @@
.nav-text.flex-fill
%span.wiki-last-edit-by
- if @page.last_version
- = (_("Last edited by %{name}") % { name: "<strong>#{@page.last_version.author_name}</strong>" }).html_safe
+ = html_escape(_("Last edited by %{link_start}%{avatar} %{name}%{link_end}")) % { avatar: image_tag(avatar_icon_for_email(@page.last_version.author_email, 24), class: "avatar s24 float-none gl-mr-0!"), name: "<strong>#{@page.last_version.author_name}</strong>".html_safe, link_start: "<a href='#{@page.last_version.author_url}'>".html_safe, link_end: '</a>'.html_safe }
= time_ago_with_tooltip(@page.last_version.authored_date)
.nav-controls.pb-md-3.pb-lg-0
diff --git a/app/views/sherlock/transactions/show.html.haml b/app/views/sherlock/transactions/show.html.haml
index 8f2b36123bb..162b14f01e1 100644
--- a/app/views/sherlock/transactions/show.html.haml
+++ b/app/views/sherlock/transactions/show.html.haml
@@ -18,8 +18,8 @@
.row-content-block
.float-right
- = link_to(sherlock_transactions_path, class: 'btn') do
- = sprite_icon('arrow-left')
+ = link_to(sherlock_transactions_path, class: 'gl-button btn') do
+ = sprite_icon('arrow-left', css_class: 'gl-mr-3')
= t('sherlock.all_transactions')
.oneline
= t('sherlock.transaction')
diff --git a/app/views/snippets/verify.html.haml b/app/views/snippets/verify.html.haml
deleted file mode 100644
index 3c4f08e1df7..00000000000
--- a/app/views/snippets/verify.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-= render 'layouts/recaptcha_verification', spammable: @snippet
-
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 1f2e8213b64..4c4a314a1e6 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -147,6 +147,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:ci_pipeline_artifacts_expire_artifacts
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:ci_platform_metrics_update_cron
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -188,7 +196,7 @@
:idempotent:
:tags: []
- :name: cronjob:gitlab_usage_ping
- :feature_category: :collection
+ :feature_category: :usage_ping
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -881,7 +889,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
:tags: []
- :name: jira_connect:jira_connect_sync_builds
:feature_category: :integrations
@@ -891,13 +899,29 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: jira_connect:jira_connect_sync_deployments
+ :feature_category: :integrations
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: jira_connect:jira_connect_sync_feature_flags
+ :feature_category: :integrations
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: jira_connect:jira_connect_sync_merge_request
:feature_category: :integrations
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
:tags: []
- :name: jira_connect:jira_connect_sync_project
:feature_category: :integrations
@@ -1070,22 +1094,22 @@
:idempotent: true
:tags: []
- :name: pipeline_background:ci_daily_build_group_report_results
- :feature_category: :continuous_integration
+ :feature_category: :code_testing
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
-- :name: pipeline_background:ci_pipeline_success_unlock_artifacts
- :feature_category: :continuous_integration
+- :name: pipeline_background:ci_pipeline_artifacts_coverage_report
+ :feature_category: :code_testing
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
-- :name: pipeline_background:ci_pipelines_create_artifact
+- :name: pipeline_background:ci_pipeline_success_unlock_artifacts
:feature_category: :continuous_integration
:has_external_dependencies:
:urgency: :low
@@ -1418,6 +1442,14 @@
:tags: []
- :name: bulk_import
:feature_category: :importers
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
+- :name: bulk_imports_entity
+ :feature_category: :importers
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :unknown
@@ -1577,6 +1609,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: experiments_record_conversion_event
+ :feature_category: :users
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: expire_build_instance_artifacts
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1787,6 +1827,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: namespaces_onboarding_pipeline_created
+ :feature_category: :subgroups
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: namespaces_onboarding_user_added
:feature_category: :users
:has_external_dependencies:
@@ -2095,6 +2143,22 @@
:weight: 1
:idempotent:
:tags: []
+- :name: snippet_schedule_bulk_repository_shard_moves
+ :feature_category: :gitaly
+ :has_external_dependencies:
+ :urgency: :throttled
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: snippet_update_repository_storage
+ :feature_category: :gitaly
+ :has_external_dependencies:
+ :urgency: :throttled
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: system_hook_push
:feature_category: :source_code_management
:has_external_dependencies:
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
index 7828d046036..81099d4e5f7 100644
--- a/app/workers/bulk_import_worker.rb
+++ b/app/workers/bulk_import_worker.rb
@@ -7,9 +7,58 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: false, dead: false
- worker_has_external_dependencies!
+ PERFORM_DELAY = 5.seconds
+ DEFAULT_BATCH_SIZE = 5
def perform(bulk_import_id)
- BulkImports::Importers::GroupsImporter.new(bulk_import_id).execute
+ @bulk_import = BulkImport.find_by_id(bulk_import_id)
+
+ return unless @bulk_import
+ return if @bulk_import.finished?
+ return @bulk_import.finish! if all_entities_processed? && @bulk_import.started?
+ return re_enqueue if max_batch_size_exceeded? # Do not start more jobs if max allowed are already running
+
+ @bulk_import.start! if @bulk_import.created?
+
+ created_entities.first(next_batch_size).each do |entity|
+ entity.start!
+
+ BulkImports::EntityWorker.perform_async(entity.id)
+ end
+
+ re_enqueue
+ end
+
+ private
+
+ def entities
+ @entities ||= @bulk_import.entities
+ end
+
+ def started_entities
+ entities.with_status(:started)
+ end
+
+ def created_entities
+ entities.with_status(:created)
+ end
+
+ def all_entities_processed?
+ entities.all? { |entity| entity.finished? || entity.failed? }
+ end
+
+ def max_batch_size_exceeded?
+ started_entities.count >= DEFAULT_BATCH_SIZE
+ end
+
+ def next_batch_size
+ [DEFAULT_BATCH_SIZE - started_entities.count, 0].max
+ end
+
+ # A new BulkImportWorker job is enqueued to either
+ # - Process the new BulkImports::Entity created during import (e.g. for the subgroups)
+ # - Or to mark the `bulk_import` as finished
+ def re_enqueue
+ BulkImportWorker.perform_in(PERFORM_DELAY, @bulk_import.id)
end
end
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
new file mode 100644
index 00000000000..9b29ad8f326
--- /dev/null
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class EntityWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ feature_category :importers
+
+ sidekiq_options retry: false, dead: false
+
+ worker_has_external_dependencies!
+
+ def perform(entity_id)
+ entity = BulkImports::Entity.with_status(:started).find_by_id(entity_id)
+
+ if entity
+ entity.update!(jid: jid)
+
+ BulkImports::Importers::GroupImporter.new(entity).execute
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/daily_build_group_report_results_worker.rb b/app/workers/ci/daily_build_group_report_results_worker.rb
index a6d3c485e24..687cadc6366 100644
--- a/app/workers/ci/daily_build_group_report_results_worker.rb
+++ b/app/workers/ci/daily_build_group_report_results_worker.rb
@@ -5,6 +5,8 @@ module Ci
include ApplicationWorker
include PipelineBackgroundQueue
+ feature_category :code_testing
+
idempotent!
def perform(pipeline_id)
diff --git a/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb b/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb
new file mode 100644
index 00000000000..4de56f54f44
--- /dev/null
+++ b/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class CoverageReportWorker
+ include ApplicationWorker
+ include PipelineBackgroundQueue
+
+ feature_category :code_testing
+
+ idempotent!
+
+ def perform(pipeline_id)
+ Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
+ Ci::PipelineArtifacts::CoverageReportService.new.execute(pipeline)
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb b/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb
new file mode 100644
index 00000000000..0bb911bc6c8
--- /dev/null
+++ b/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class ExpireArtifactsWorker
+ include ApplicationWorker
+ # rubocop:disable Scalability/CronWorkerContext
+ # This worker does not perform work scoped to a context
+ include CronjobQueue
+ # rubocop:enable Scalability/CronWorkerContext
+
+ deduplicate :until_executed, including_scheduled: true
+ idempotent!
+ feature_category :continuous_integration
+
+ def perform
+ service = ::Ci::PipelineArtifacts::DestroyExpiredArtifactsService.new
+ artifacts_count = service.execute
+ log_extra_metadata_on_done(:destroyed_pipeline_artifacts_count, artifacts_count)
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/pipelines/create_artifact_worker.rb b/app/workers/ci/pipelines/create_artifact_worker.rb
deleted file mode 100644
index 220df975503..00000000000
--- a/app/workers/ci/pipelines/create_artifact_worker.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- module Pipelines
- class CreateArtifactWorker
- include ApplicationWorker
- include PipelineBackgroundQueue
-
- idempotent!
-
- def perform(pipeline_id)
- Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
- Ci::Pipelines::CreateArtifactService.new.execute(pipeline)
- end
- end
- end
- end
-end
diff --git a/app/workers/concerns/update_repository_storage_worker.rb b/app/workers/concerns/update_repository_storage_worker.rb
new file mode 100644
index 00000000000..f46b64895a2
--- /dev/null
+++ b/app/workers/concerns/update_repository_storage_worker.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module UpdateRepositoryStorageWorker
+ extend ActiveSupport::Concern
+ include ApplicationWorker
+
+ included do
+ idempotent!
+ feature_category :gitaly
+ urgency :throttled
+ end
+
+ def perform(container_id, new_repository_storage_key, repository_storage_move_id = nil)
+ repository_storage_move =
+ if repository_storage_move_id
+ find_repository_storage_move(repository_storage_move_id)
+ else
+ # maintain compatibility with workers queued before release
+ container = find_container(container_id)
+ container.repository_storage_moves.create!(
+ source_storage_name: container.repository_storage,
+ destination_storage_name: new_repository_storage_key
+ )
+ end
+
+ update_repository_storage(repository_storage_move)
+ end
+
+ private
+
+ def find_repository_storage_move(repository_storage_move_id)
+ raise NotImplementedError
+ end
+
+ def find_container(container_id)
+ raise NotImplementedError
+ end
+
+ def update_repository_storage(repository_storage_move)
+ raise NotImplementedError
+ 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 8c3c2e9e103..7c86b194574 100644
--- a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
+++ b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
@@ -12,6 +12,14 @@ module ContainerExpirationPolicies
worker_resource_boundary :unknown
idempotent!
+ LOG_ON_DONE_FIELDS = %i[
+ cleanup_status
+ cleanup_tags_service_original_size
+ cleanup_tags_service_before_truncate_size
+ cleanup_tags_service_after_truncate_size
+ cleanup_tags_service_before_delete_size
+ ].freeze
+
def perform_work
return unless throttling_enabled?
return unless container_repository
@@ -26,7 +34,7 @@ module ContainerExpirationPolicies
result = ContainerExpirationPolicies::CleanupService.new(container_repository)
.execute
- log_extra_metadata_on_done(:cleanup_status, result.payload[:cleanup_status])
+ log_on_done(result)
end
def remaining_work_count
@@ -92,5 +100,22 @@ module ContainerExpirationPolicies
def log_info(extra_structure)
logger.info(structured_payload(extra_structure))
end
+
+ def log_on_done(result)
+ LOG_ON_DONE_FIELDS.each do |field|
+ value = result.payload[field]
+
+ next if value.nil?
+
+ log_extra_metadata_on_done(field, value)
+ end
+
+ before_truncate_size = result.payload[:cleanup_tags_service_before_truncate_size]
+ after_truncate_size = result.payload[:cleanup_tags_service_after_truncate_size]
+ truncated = before_truncate_size &&
+ after_truncate_size &&
+ before_truncate_size != after_truncate_size
+ log_extra_metadata_on_done(:cleanup_tags_service_truncated, !!truncated)
+ end
end
end
diff --git a/app/workers/experiments/record_conversion_event_worker.rb b/app/workers/experiments/record_conversion_event_worker.rb
new file mode 100644
index 00000000000..e38ce7b3d01
--- /dev/null
+++ b/app/workers/experiments/record_conversion_event_worker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Experiments
+ class RecordConversionEventWorker
+ include ApplicationWorker
+
+ feature_category :users
+ urgency :low
+
+ idempotent!
+
+ def perform(experiment, user_id)
+ return unless Gitlab::Experimentation.active?(experiment)
+
+ ::Experiment.record_conversion_event(experiment, user_id)
+ end
+ end
+end
diff --git a/app/workers/expire_build_artifacts_worker.rb b/app/workers/expire_build_artifacts_worker.rb
index 12372961250..5db9f0b67e0 100644
--- a/app/workers/expire_build_artifacts_worker.rb
+++ b/app/workers/expire_build_artifacts_worker.rb
@@ -10,6 +10,8 @@ class ExpireBuildArtifactsWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :continuous_integration
def perform
- Ci::DestroyExpiredJobArtifactsService.new.execute
+ service = Ci::DestroyExpiredJobArtifactsService.new
+ artifacts_count = service.execute
+ log_extra_metadata_on_done(:destroyed_job_artifacts_count, artifacts_count)
end
end
diff --git a/app/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker.rb b/app/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker.rb
index 0809d0b7c29..790e8b0eccf 100644
--- a/app/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker.rb
@@ -11,18 +11,11 @@ module Gitlab
# client - An instance of Gitlab::GithubImport::Client.
# project - An instance of Project.
def import(client, project)
- waiter =
- if Feature.enabled?(:github_import_pull_request_reviews, project, default_enabled: true)
- waiter = Importer::PullRequestsReviewsImporter
- .new(project, client)
- .execute
+ waiter = Importer::PullRequestsReviewsImporter
+ .new(project, client)
+ .execute
- project.import_state.refresh_jid_expiration
-
- waiter
- else
- JobWaiter.new
- end
+ project.import_state.refresh_jid_expiration
AdvanceStageWorker.perform_async(
project.id,
diff --git a/app/workers/gitlab_performance_bar_stats_worker.rb b/app/workers/gitlab_performance_bar_stats_worker.rb
index d63f8111864..558df0ab7b3 100644
--- a/app/workers/gitlab_performance_bar_stats_worker.rb
+++ b/app/workers/gitlab_performance_bar_stats_worker.rb
@@ -7,12 +7,13 @@ class GitlabPerformanceBarStatsWorker
LEASE_TIMEOUT = 600
WORKER_DELAY = 120
STATS_KEY = 'performance_bar_stats:pending_request_ids'
+ STATS_KEY_EXPIRE = 30.minutes.to_i
feature_category :metrics
idempotent!
def perform(lease_uuid)
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
request_ids = fetch_request_ids(redis, lease_uuid)
stats = Gitlab::PerformanceBar::Stats.new(redis)
diff --git a/app/workers/gitlab_usage_ping_worker.rb b/app/workers/gitlab_usage_ping_worker.rb
index 1bb600bbd13..782b089261f 100644
--- a/app/workers/gitlab_usage_ping_worker.rb
+++ b/app/workers/gitlab_usage_ping_worker.rb
@@ -8,7 +8,7 @@ class GitlabUsagePingWorker # rubocop:disable Scalability/IdempotentWorker
include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
include Gitlab::ExclusiveLeaseHelpers
- feature_category :collection
+ feature_category :usage_ping
sidekiq_options retry: 3, dead: false
sidekiq_retry_in { |count| (count + 1) * 8.hours.to_i }
diff --git a/app/workers/issuable_export_csv_worker.rb b/app/workers/issuable_export_csv_worker.rb
index d91ba77287f..33452b14edb 100644
--- a/app/workers/issuable_export_csv_worker.rb
+++ b/app/workers/issuable_export_csv_worker.rb
@@ -7,47 +7,45 @@ class IssuableExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
worker_resource_boundary :cpu
loggable_arguments 2
- PERMITTED_TYPES = [:merge_request, :issue].freeze
-
def perform(type, current_user_id, project_id, params)
- @type = type.to_sym
- check_permitted_type!
- process_params!(params, project_id)
-
- @current_user = User.find(current_user_id)
- @project = Project.find(project_id)
- @service = service(find_objects(params))
+ user = User.find(current_user_id)
+ project = Project.find(project_id)
+ finder_params = map_params(params, project_id)
- @service.email(@current_user)
+ export_service(type.to_sym, user, project, finder_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 find_objects(params)
- case @type
- when :issue
- IssuesFinder.new(@current_user, params).execute
- when :merge_request
- MergeRequestsFinder.new(@current_user, params).execute
- end
+ def map_params(params, project_id)
+ params
+ .symbolize_keys
+ .except(:sort)
+ .merge(project_id: project_id)
end
- def service(issuables)
- case @type
+ 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)
+ end
+
+ def service_classes_for(type)
+ case type
when :issue
- Issues::ExportCsvService.new(issuables, @project)
+ { finder: IssuesFinder, service: Issues::ExportCsvService }
when :merge_request
- MergeRequests::ExportCsvService.new(issuables, @project)
+ { finder: MergeRequestsFinder, service: MergeRequests::ExportCsvService }
+ else
+ raise ArgumentError, type_error_message(type)
end
end
- def process_params!(params, project_id)
- params.symbolize_keys!
- params[:project_id] = project_id
- params.delete(:sort)
- end
-
- def check_permitted_type!
- raise ArgumentError, "type parameter must be :issue or :merge_request, it was #{@type}" unless PERMITTED_TYPES.include?(@type)
+ def type_error_message(type)
+ "Type parameter must be :issue or :merge_request, it was #{type}"
end
end
+
+IssuableExportCsvWorker.prepend_if_ee('::EE::IssuableExportCsvWorker')
diff --git a/app/workers/jira_connect/sync_branch_worker.rb b/app/workers/jira_connect/sync_branch_worker.rb
index d7e773b0861..1af51c4bb74 100644
--- a/app/workers/jira_connect/sync_branch_worker.rb
+++ b/app/workers/jira_connect/sync_branch_worker.rb
@@ -8,8 +8,9 @@ module JiraConnect
feature_category :integrations
loggable_arguments 1, 2
worker_has_external_dependencies!
+ idempotent!
- def perform(project_id, branch_name, commit_shas, update_sequence_id = nil)
+ def perform(project_id, branch_name, commit_shas, update_sequence_id)
project = Project.find_by_id(project_id)
return unless project
diff --git a/app/workers/jira_connect/sync_deployments_worker.rb b/app/workers/jira_connect/sync_deployments_worker.rb
new file mode 100644
index 00000000000..0f261e29464
--- /dev/null
+++ b/app/workers/jira_connect/sync_deployments_worker.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class SyncDeploymentsWorker
+ include ApplicationWorker
+
+ idempotent!
+ worker_has_external_dependencies!
+
+ queue_namespace :jira_connect
+ feature_category :integrations
+
+ def perform(deployment_id, sequence_id)
+ deployment = Deployment.find_by_id(deployment_id)
+
+ return unless deployment
+ return unless Feature.enabled?(:jira_sync_deployments, deployment.project)
+
+ ::JiraConnect::SyncService
+ .new(deployment.project)
+ .execute(deployments: [deployment], update_sequence_id: sequence_id)
+ end
+
+ def self.perform_async(id)
+ seq_id = ::Atlassian::JiraConnect::Client.generate_update_sequence_id
+ super(id, seq_id)
+ end
+ end
+end
diff --git a/app/workers/jira_connect/sync_feature_flags_worker.rb b/app/workers/jira_connect/sync_feature_flags_worker.rb
new file mode 100644
index 00000000000..7e98d0eada7
--- /dev/null
+++ b/app/workers/jira_connect/sync_feature_flags_worker.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class SyncFeatureFlagsWorker
+ include ApplicationWorker
+
+ idempotent!
+ worker_has_external_dependencies!
+
+ queue_namespace :jira_connect
+ feature_category :integrations
+
+ def perform(feature_flag_id, sequence_id)
+ 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)
+ .execute(feature_flags: [feature_flag], update_sequence_id: sequence_id)
+ end
+ end
+end
diff --git a/app/workers/jira_connect/sync_merge_request_worker.rb b/app/workers/jira_connect/sync_merge_request_worker.rb
index 6ef426790b3..543d8e002fe 100644
--- a/app/workers/jira_connect/sync_merge_request_worker.rb
+++ b/app/workers/jira_connect/sync_merge_request_worker.rb
@@ -6,10 +6,11 @@ module JiraConnect
queue_namespace :jira_connect
feature_category :integrations
+ idempotent!
worker_has_external_dependencies!
- def perform(merge_request_id, update_sequence_id = nil)
+ def perform(merge_request_id, update_sequence_id)
merge_request = MergeRequest.find_by_id(merge_request_id)
return unless merge_request && merge_request.project
diff --git a/app/workers/namespaces/onboarding_pipeline_created_worker.rb b/app/workers/namespaces/onboarding_pipeline_created_worker.rb
new file mode 100644
index 00000000000..e1de6d0046b
--- /dev/null
+++ b/app/workers/namespaces/onboarding_pipeline_created_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class OnboardingPipelineCreatedWorker
+ include ApplicationWorker
+
+ feature_category :subgroups
+ urgency :low
+
+ deduplicate :until_executing
+ idempotent!
+
+ def perform(namespace_id)
+ namespace = Namespace.find_by_id(namespace_id)
+ return unless namespace
+
+ OnboardingProgressService.new(namespace).execute(action: :pipeline_created)
+ end
+ end
+end
diff --git a/app/workers/object_pool/join_worker.rb b/app/workers/object_pool/join_worker.rb
index f1008d3be83..8103c04b507 100644
--- a/app/workers/object_pool/join_worker.rb
+++ b/app/workers/object_pool/join_worker.rb
@@ -15,7 +15,7 @@ module ObjectPool
project.link_pool_repository
- Projects::HousekeepingService.new(project).execute
+ Repositories::HousekeepingService.new(project).execute
end
end
end
diff --git a/app/workers/project_update_repository_storage_worker.rb b/app/workers/project_update_repository_storage_worker.rb
index 7c0b1ae07fa..5636eec8233 100644
--- a/app/workers/project_update_repository_storage_worker.rb
+++ b/app/workers/project_update_repository_storage_worker.rb
@@ -1,25 +1,23 @@
# frozen_string_literal: true
-class ProjectUpdateRepositoryStorageWorker
- include ApplicationWorker
+class ProjectUpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
+ extend ::Gitlab::Utils::Override
+ include UpdateRepositoryStorageWorker
- idempotent!
- feature_category :gitaly
- urgency :throttled
+ private
- def perform(project_id, new_repository_storage_key, repository_storage_move_id = nil)
- repository_storage_move =
- if repository_storage_move_id
- ProjectRepositoryStorageMove.find(repository_storage_move_id)
- else
- # maintain compatibility with workers queued before release
- project = Project.find(project_id)
- project.repository_storage_moves.create!(
- source_storage_name: project.repository_storage,
- destination_storage_name: new_repository_storage_key
- )
- end
+ override :find_repository_storage_move
+ def find_repository_storage_move(repository_storage_move_id)
+ ProjectRepositoryStorageMove.find(repository_storage_move_id)
+ end
+
+ override :find_container
+ def find_container(container_id)
+ Project.find(container_id)
+ end
+ override :update_repository_storage
+ def update_repository_storage(repository_storage_move)
::Projects::UpdateRepositoryStorageService.new(repository_storage_move).execute
end
end
diff --git a/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb b/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
new file mode 100644
index 00000000000..47f24ad3500
--- /dev/null
+++ b/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class SnippetScheduleBulkRepositoryShardMovesWorker
+ include ApplicationWorker
+
+ idempotent!
+ feature_category :gitaly
+ urgency :throttled
+
+ def perform(source_storage_name, destination_storage_name = nil)
+ Snippets::ScheduleBulkRepositoryShardMovesService.new.execute(source_storage_name, destination_storage_name)
+ end
+end
diff --git a/app/workers/snippet_update_repository_storage_worker.rb b/app/workers/snippet_update_repository_storage_worker.rb
new file mode 100644
index 00000000000..a28a02a0298
--- /dev/null
+++ b/app/workers/snippet_update_repository_storage_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class SnippetUpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
+ extend ::Gitlab::Utils::Override
+ include UpdateRepositoryStorageWorker
+
+ private
+
+ override :find_repository_storage_move
+ def find_repository_storage_move(repository_storage_move_id)
+ SnippetRepositoryStorageMove.find(repository_storage_move_id)
+ end
+
+ override :find_container
+ def find_container(container_id)
+ Snippet.find(container_id)
+ end
+
+ override :update_repository_storage
+ def update_repository_storage(repository_storage_move)
+ ::Snippets::UpdateRepositoryStorageService.new(repository_storage_move).execute
+ end
+end
diff --git a/changelogs/unreleased/10io-fix-graphql-container-repository-tag-size-type.yml b/changelogs/unreleased/10io-fix-graphql-container-repository-tag-size-type.yml
new file mode 100644
index 00000000000..5323ac46f9f
--- /dev/null
+++ b/changelogs/unreleased/10io-fix-graphql-container-repository-tag-size-type.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the graphQL type for container repository tags
+merge_request: 50419
+author:
+type: fixed
diff --git a/changelogs/unreleased/10io-use-empty-string-when-sending-local-file.yml b/changelogs/unreleased/10io-use-empty-string-when-sending-local-file.yml
new file mode 100644
index 00000000000..0e655195384
--- /dev/null
+++ b/changelogs/unreleased/10io-use-empty-string-when-sending-local-file.yml
@@ -0,0 +1,5 @@
+---
+title: Use an empty body when sending a file with X-Sendfile
+merge_request: 51115
+author:
+type: fixed
diff --git a/changelogs/unreleased/13019-improve-error-messages-when-adding-namespaces-in-jira-connect-app.yml b/changelogs/unreleased/13019-improve-error-messages-when-adding-namespaces-in-jira-connect-app.yml
new file mode 100644
index 00000000000..a6724919107
--- /dev/null
+++ b/changelogs/unreleased/13019-improve-error-messages-when-adding-namespaces-in-jira-connect-app.yml
@@ -0,0 +1,5 @@
+---
+title: Improve error messages when adding namespaces in Jira Connect App
+merge_request: 48651
+author:
+type: changed
diff --git a/changelogs/unreleased/18816-forward-an-e-mail-to-an-existing-issue-as-a-new-comment.yml b/changelogs/unreleased/18816-forward-an-e-mail-to-an-existing-issue-as-a-new-comment.yml
new file mode 100644
index 00000000000..7e139c69ee3
--- /dev/null
+++ b/changelogs/unreleased/18816-forward-an-e-mail-to-an-existing-issue-as-a-new-comment.yml
@@ -0,0 +1,5 @@
+---
+title: New user/issue specific email address for creating/forwarding to an issue
+merge_request: 49050
+author:
+type: added
diff --git a/changelogs/unreleased/205578-enable-collect_package_events_redis-feature.yml b/changelogs/unreleased/205578-enable-collect_package_events_redis-feature.yml
new file mode 100644
index 00000000000..5d922b3d579
--- /dev/null
+++ b/changelogs/unreleased/205578-enable-collect_package_events_redis-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Enable collect_package_events_redis by default
+merge_request: 50092
+author:
+type: changed
diff --git a/changelogs/unreleased/211962-allow-group-owners-to-bypass-sso-enforce.yml b/changelogs/unreleased/211962-allow-group-owners-to-bypass-sso-enforce.yml
new file mode 100644
index 00000000000..01e67f61bca
--- /dev/null
+++ b/changelogs/unreleased/211962-allow-group-owners-to-bypass-sso-enforce.yml
@@ -0,0 +1,5 @@
+---
+title: Allow group owners and auditors to login to SSO-enforced groups without SSO
+merge_request: 50199
+author:
+type: changed
diff --git a/changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml b/changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml
new file mode 100644
index 00000000000..fd5e13d8b64
--- /dev/null
+++ b/changelogs/unreleased/212925-power-icon-should-be-removed-from-the-integrations-list.yml
@@ -0,0 +1,5 @@
+---
+title: Remove inactive integrations indicator in index and show pages
+merge_request: 50753
+author:
+type: changed
diff --git a/changelogs/unreleased/215309-improve-the-error-message-username-has-already-been-taken-on-user-.yml b/changelogs/unreleased/215309-improve-the-error-message-username-has-already-been-taken-on-user-.yml
new file mode 100644
index 00000000000..b966d28a6ec
--- /dev/null
+++ b/changelogs/unreleased/215309-improve-the-error-message-username-has-already-been-taken-on-user-.yml
@@ -0,0 +1,5 @@
+---
+title: Improve error message when username and namespace conflict
+merge_request: 47537
+author:
+type: changed
diff --git a/changelogs/unreleased/21686_persist_squash_commit_sha.yml b/changelogs/unreleased/21686_persist_squash_commit_sha.yml
new file mode 100644
index 00000000000..c95028b8492
--- /dev/null
+++ b/changelogs/unreleased/21686_persist_squash_commit_sha.yml
@@ -0,0 +1,5 @@
+---
+title: Persist 'squash_commit_sha' when squashing
+merge_request: 51074
+author:
+type: added
diff --git a/changelogs/unreleased/21686_show_merge_request_for_squashed_commits.yml b/changelogs/unreleased/21686_show_merge_request_for_squashed_commits.yml
new file mode 100644
index 00000000000..cc59ac92fd9
--- /dev/null
+++ b/changelogs/unreleased/21686_show_merge_request_for_squashed_commits.yml
@@ -0,0 +1,5 @@
+---
+title: Extend MergeRequestFinder to search by squash and merge commits
+merge_request: 49968
+author:
+type: added
diff --git a/changelogs/unreleased/218624-roadmaps-conf-filter.yml b/changelogs/unreleased/218624-roadmaps-conf-filter.yml
new file mode 100644
index 00000000000..3f132a10842
--- /dev/null
+++ b/changelogs/unreleased/218624-roadmaps-conf-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Add confidentiality filtering to the epics REST API and GraphQL endpoints
+merge_request: 51105
+author:
+type: added
diff --git a/changelogs/unreleased/218997-fj-add-snippet-repository-moves-api-endpoints.yml b/changelogs/unreleased/218997-fj-add-snippet-repository-moves-api-endpoints.yml
new file mode 100644
index 00000000000..f757ffa8533
--- /dev/null
+++ b/changelogs/unreleased/218997-fj-add-snippet-repository-moves-api-endpoints.yml
@@ -0,0 +1,5 @@
+---
+title: Add snippet repository storage move API endpoints
+merge_request: 49228
+author:
+type: added
diff --git a/changelogs/unreleased/222970-207742-fix-500-webhooks-urls-not-encoded.yml b/changelogs/unreleased/222970-207742-fix-500-webhooks-urls-not-encoded.yml
new file mode 100644
index 00000000000..b837f204bba
--- /dev/null
+++ b/changelogs/unreleased/222970-207742-fix-500-webhooks-urls-not-encoded.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 500 errors entering a webhook URL not encoded
+merge_request: 51109
+author:
+type: fixed
diff --git a/changelogs/unreleased/223853-create-specialized-worker-for-refreshing-project-authorizations-du.yml b/changelogs/unreleased/223853-create-specialized-worker-for-refreshing-project-authorizations-du.yml
new file mode 100644
index 00000000000..2c62828f41c
--- /dev/null
+++ b/changelogs/unreleased/223853-create-specialized-worker-for-refreshing-project-authorizations-du.yml
@@ -0,0 +1,6 @@
+---
+title: During group deletion, only enqueue jobs for project_authorizations refresh
+ if the group being deleted has other groups shared with it
+merge_request: 50617
+author:
+type: performance
diff --git a/changelogs/unreleased/224698-fe-operations.yml b/changelogs/unreleased/224698-fe-operations.yml
new file mode 100644
index 00000000000..28e407979e2
--- /dev/null
+++ b/changelogs/unreleased/224698-fe-operations.yml
@@ -0,0 +1,5 @@
+---
+title: Add toggle to disable Operations in settings
+merge_request: 49919
+author:
+type: added
diff --git a/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-in-app-assets-javascripts-vue.yml b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-in-app-assets-javascripts-vue.yml
new file mode 100644
index 00000000000..97eb43901bb
--- /dev/null
+++ b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-in-app-assets-javascripts-vue.yml
@@ -0,0 +1,5 @@
+---
+title: "[Commit Page] Migrate to GlModal for revert commit"
+merge_request: 50522
+author:
+type: other
diff --git a/changelogs/unreleased/230728-nav-tabs-migration.yml b/changelogs/unreleased/230728-nav-tabs-migration.yml
new file mode 100644
index 00000000000..969e805ef2b
--- /dev/null
+++ b/changelogs/unreleased/230728-nav-tabs-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Convert navigation_tabs.vue to gl-tabs
+merge_request: 47841
+author:
+type: other
diff --git a/changelogs/unreleased/231073-apply-gitlab-ui-button-styles-to-buttons-in-ee-app-views-projects-.yml b/changelogs/unreleased/231073-apply-gitlab-ui-button-styles-to-buttons-in-ee-app-views-projects-.yml
new file mode 100644
index 00000000000..136cb180b70
--- /dev/null
+++ b/changelogs/unreleased/231073-apply-gitlab-ui-button-styles-to-buttons-in-ee-app-views-projects-.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate GitLab UI button for Merge Request Approvals settings
+merge_request: 51159
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/23109-add-wiki-edit-button.yml b/changelogs/unreleased/23109-add-wiki-edit-button.yml
new file mode 100644
index 00000000000..b5130d78b19
--- /dev/null
+++ b/changelogs/unreleased/23109-add-wiki-edit-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add button to edit custom Wiki sidebar
+merge_request: 50323
+author: Frank Li
+type: changed
diff --git a/changelogs/unreleased/231217-yo-gitlab-ui.yml b/changelogs/unreleased/231217-yo-gitlab-ui.yml
new file mode 100644
index 00000000000..af7bc280b69
--- /dev/null
+++ b/changelogs/unreleased/231217-yo-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in project wiki
+merge_request: 51780
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/23308-allow-commits-to-fork-from-maintainers.yml b/changelogs/unreleased/23308-allow-commits-to-fork-from-maintainers.yml
new file mode 100644
index 00000000000..98e0eb24395
--- /dev/null
+++ b/changelogs/unreleased/23308-allow-commits-to-fork-from-maintainers.yml
@@ -0,0 +1,5 @@
+---
+title: Allow collaboration on merge requests across forks by default
+merge_request: 49904
+author: Jonston Chan @JonstonChan
+type: changed
diff --git a/changelogs/unreleased/233423-fix-ide-commit-to-new-branch-errors.yml b/changelogs/unreleased/233423-fix-ide-commit-to-new-branch-errors.yml
new file mode 100644
index 00000000000..9ed40f1b7a1
--- /dev/null
+++ b/changelogs/unreleased/233423-fix-ide-commit-to-new-branch-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Fix issues when Web IDE commits to new branch
+merge_request: 51654
+author:
+type: fixed
diff --git a/changelogs/unreleased/233658-migrate-alert-on-new-branch-page.yml b/changelogs/unreleased/233658-migrate-alert-on-new-branch-page.yml
new file mode 100644
index 00000000000..801b45b2bf6
--- /dev/null
+++ b/changelogs/unreleased/233658-migrate-alert-on-new-branch-page.yml
@@ -0,0 +1,5 @@
+---
+title: Migrates the alert on the new branch page
+merge_request: 50307
+author:
+type: other
diff --git a/changelogs/unreleased/23531-change-needs-failure-message.yml b/changelogs/unreleased/23531-change-needs-failure-message.yml
new file mode 100644
index 00000000000..a9042a7b0ee
--- /dev/null
+++ b/changelogs/unreleased/23531-change-needs-failure-message.yml
@@ -0,0 +1,5 @@
+---
+title: Change failure message of missing job needs
+merge_request: 50492
+author:
+type: other
diff --git a/changelogs/unreleased/238854-fix-copy-sha-in-add-previous-commits-modal-doesnt-copy.yml b/changelogs/unreleased/238854-fix-copy-sha-in-add-previous-commits-modal-doesnt-copy.yml
new file mode 100644
index 00000000000..af86f3c7cf7
--- /dev/null
+++ b/changelogs/unreleased/238854-fix-copy-sha-in-add-previous-commits-modal-doesnt-copy.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 'copy sha' in 'add previous commits' modal doesn't copy
+merge_request: 50921
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/241267-swap-audit-events-migration.yml b/changelogs/unreleased/241267-swap-audit-events-migration.yml
new file mode 100644
index 00000000000..b3d52f87af8
--- /dev/null
+++ b/changelogs/unreleased/241267-swap-audit-events-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Add migration to swap partitioned audit_events
+merge_request: 47581
+author:
+type: added
diff --git a/changelogs/unreleased/24163-add-admin-filter-to-user-api.yml b/changelogs/unreleased/24163-add-admin-filter-to-user-api.yml
new file mode 100644
index 00000000000..3b9cf6b2d12
--- /dev/null
+++ b/changelogs/unreleased/24163-add-admin-filter-to-user-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to get admins via REST and GraphQL API
+merge_request: 46244
+author:
+type: added
diff --git a/changelogs/unreleased/243857-matrix-job-status-allow-failure.yml b/changelogs/unreleased/243857-matrix-job-status-allow-failure.yml
new file mode 100644
index 00000000000..13521b63173
--- /dev/null
+++ b/changelogs/unreleased/243857-matrix-job-status-allow-failure.yml
@@ -0,0 +1,5 @@
+---
+title: Correct status indicator for jobs groups when failure is allowed
+merge_request: 51478
+author: Sune Keller (sirlatrom)
+type: fixed
diff --git a/changelogs/unreleased/244274-boards-migrate-deleteboard-board_store-function-to-vuex-action.yml b/changelogs/unreleased/244274-boards-migrate-deleteboard-board_store-function-to-vuex-action.yml
new file mode 100644
index 00000000000..b3f06e2294e
--- /dev/null
+++ b/changelogs/unreleased/244274-boards-migrate-deleteboard-board_store-function-to-vuex-action.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate `deleteBoard` board_store function to GraphQL mutation
+merge_request: 51069
+author:
+type: changed
diff --git a/changelogs/unreleased/247184-instument-file-by-file-mrs.yml b/changelogs/unreleased/247184-instument-file-by-file-mrs.yml
new file mode 100644
index 00000000000..5be326c05a3
--- /dev/null
+++ b/changelogs/unreleased/247184-instument-file-by-file-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Instrument viewing merge request diffs file by file
+merge_request: 48470
+author:
+type: added
diff --git a/changelogs/unreleased/247477-fix-double-render-errors-in-rescue-from.yml b/changelogs/unreleased/247477-fix-double-render-errors-in-rescue-from.yml
new file mode 100644
index 00000000000..f6aa283b54b
--- /dev/null
+++ b/changelogs/unreleased/247477-fix-double-render-errors-in-rescue-from.yml
@@ -0,0 +1,5 @@
+---
+title: Correctly handle Gitaly being unavailable in more locations
+merge_request: 51222
+author:
+type: fixed
diff --git a/changelogs/unreleased/247936-fix-cut-off-file-blame-line-number.yml b/changelogs/unreleased/247936-fix-cut-off-file-blame-line-number.yml
new file mode 100644
index 00000000000..ba25f348cc1
--- /dev/null
+++ b/changelogs/unreleased/247936-fix-cut-off-file-blame-line-number.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cut off line number in file blame
+merge_request: 51259
+author:
+type: fixed
diff --git a/changelogs/unreleased/250659-allow-users-to-use-production-stage-end-event.yml b/changelogs/unreleased/250659-allow-users-to-use-production-stage-end-event.yml
new file mode 100644
index 00000000000..8690ddd60de
--- /dev/null
+++ b/changelogs/unreleased/250659-allow-users-to-use-production-stage-end-event.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users to use IssueDeployedToProduction VSA event
+merge_request: 51199
+author:
+type: added
diff --git a/changelogs/unreleased/250681_dont_unlink_forks_after_visibility_change.yml b/changelogs/unreleased/250681_dont_unlink_forks_after_visibility_change.yml
new file mode 100644
index 00000000000..150e27edd00
--- /dev/null
+++ b/changelogs/unreleased/250681_dont_unlink_forks_after_visibility_change.yml
@@ -0,0 +1,5 @@
+---
+title: Stop unlinking the fork when changing visibility
+merge_request: 49013
+author:
+type: added
diff --git a/changelogs/unreleased/250681_fix_incorrect_validation_for_forked_projects.yml b/changelogs/unreleased/250681_fix_incorrect_validation_for_forked_projects.yml
new file mode 100644
index 00000000000..16a679adeed
--- /dev/null
+++ b/changelogs/unreleased/250681_fix_incorrect_validation_for_forked_projects.yml
@@ -0,0 +1,5 @@
+---
+title: Fix visibility level validation for deep nested forks
+merge_request: 50081
+author:
+type: fixed
diff --git a/changelogs/unreleased/254325-remove-stages-from-dast-template.yml b/changelogs/unreleased/254325-remove-stages-from-dast-template.yml
new file mode 100644
index 00000000000..4df5ddfa5d2
--- /dev/null
+++ b/changelogs/unreleased/254325-remove-stages-from-dast-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add DAST.latest.gitlab-ci.yml
+merge_request: 50539
+author:
+type: added
diff --git a/changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml b/changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml
new file mode 100644
index 00000000000..bc608206847
--- /dev/null
+++ b/changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml
@@ -0,0 +1,5 @@
+---
+title: Index ci_pipelines on pipeline_schedule_id and id
+merge_request: 50478
+author:
+type: performance
diff --git a/changelogs/unreleased/256035-empty-changes-tab-on-merge-requests-should-not-show-file-browser-a.yml b/changelogs/unreleased/256035-empty-changes-tab-on-merge-requests-should-not-show-file-browser-a.yml
new file mode 100644
index 00000000000..6d721b9cbaa
--- /dev/null
+++ b/changelogs/unreleased/256035-empty-changes-tab-on-merge-requests-should-not-show-file-browser-a.yml
@@ -0,0 +1,5 @@
+---
+title: Remove diff display preferences and file tree from changes empty state
+merge_request: 43467
+author:
+type: fixed
diff --git a/changelogs/unreleased/258206-remove-gitpod-feature-flag.yml b/changelogs/unreleased/258206-remove-gitpod-feature-flag.yml
new file mode 100644
index 00000000000..1ca19a5431f
--- /dev/null
+++ b/changelogs/unreleased/258206-remove-gitpod-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Add configurable Gitpod button within projcet repository page
+merge_request: 51197
+author:
+type: added
diff --git a/changelogs/unreleased/262394-show-status-of-snippet-author.yml b/changelogs/unreleased/262394-show-status-of-snippet-author.yml
new file mode 100644
index 00000000000..e7ed85c99ee
--- /dev/null
+++ b/changelogs/unreleased/262394-show-status-of-snippet-author.yml
@@ -0,0 +1,5 @@
+---
+title: Show status of snippet author in header
+merge_request: 51030
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/262857-creation-rotation-graphql.yml b/changelogs/unreleased/262857-creation-rotation-graphql.yml
new file mode 100644
index 00000000000..02b0104a67a
--- /dev/null
+++ b/changelogs/unreleased/262857-creation-rotation-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL mutation to create on-call rotations
+merge_request: 49206
+author:
+type: added
diff --git a/changelogs/unreleased/262860-create-shifts-table.yml b/changelogs/unreleased/262860-create-shifts-table.yml
new file mode 100644
index 00000000000..d06440e7d18
--- /dev/null
+++ b/changelogs/unreleased/262860-create-shifts-table.yml
@@ -0,0 +1,5 @@
+---
+title: Add table for tracking on-call shifts
+merge_request: 49423
+author:
+type: added
diff --git a/changelogs/unreleased/263364-child-form-elements-should-be-indented.yml b/changelogs/unreleased/263364-child-form-elements-should-be-indented.yml
new file mode 100644
index 00000000000..bfe9b570175
--- /dev/null
+++ b/changelogs/unreleased/263364-child-form-elements-should-be-indented.yml
@@ -0,0 +1,5 @@
+---
+title: Indent child form elements in integrations form
+merge_request: 50929
+author:
+type: changed
diff --git a/changelogs/unreleased/263408-improve-delete-snippet-test.yml b/changelogs/unreleased/263408-improve-delete-snippet-test.yml
new file mode 100644
index 00000000000..86b57316786
--- /dev/null
+++ b/changelogs/unreleased/263408-improve-delete-snippet-test.yml
@@ -0,0 +1,5 @@
+---
+title: Improve delete snippet feature spec
+merge_request: 51020
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/270059-feature-flag-rollout-of-ci_pipeline_editor_page.yml b/changelogs/unreleased/270059-feature-flag-rollout-of-ci_pipeline_editor_page.yml
new file mode 100644
index 00000000000..1e50573f857
--- /dev/null
+++ b/changelogs/unreleased/270059-feature-flag-rollout-of-ci_pipeline_editor_page.yml
@@ -0,0 +1,5 @@
+---
+title: Enables the CI Pipeline Editor feature as a way to edit the GitLab CI/CD configuration
+merge_request: 51484
+author:
+type: added
diff --git a/changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml b/changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml
new file mode 100644
index 00000000000..8d902f8961c
--- /dev/null
+++ b/changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml
@@ -0,0 +1,5 @@
+---
+title: Fix LDAP override throws 404 when member has Minimal access
+merge_request: 50680
+author:
+type: fixed
diff --git a/changelogs/unreleased/273544-add-group-mr-approval-settings-api.yml b/changelogs/unreleased/273544-add-group-mr-approval-settings-api.yml
new file mode 100644
index 00000000000..6ea5f8e8ad0
--- /dev/null
+++ b/changelogs/unreleased/273544-add-group-mr-approval-settings-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add group MR approval settings table
+merge_request: 50256
+author:
+type: added
diff --git a/changelogs/unreleased/273555-move-time-tracker-help-state-to-the-sidebar-component.yml b/changelogs/unreleased/273555-move-time-tracker-help-state-to-the-sidebar-component.yml
new file mode 100644
index 00000000000..6701502585c
--- /dev/null
+++ b/changelogs/unreleased/273555-move-time-tracker-help-state-to-the-sidebar-component.yml
@@ -0,0 +1,5 @@
+---
+title: Fix text color for 'no estimate or time spent' message in time tracker component
+merge_request: 50558
+author:
+type: other
diff --git a/changelogs/unreleased/273657-remove-opsgenie-integration.yml b/changelogs/unreleased/273657-remove-opsgenie-integration.yml
new file mode 100644
index 00000000000..29a84fe2ccb
--- /dev/null
+++ b/changelogs/unreleased/273657-remove-opsgenie-integration.yml
@@ -0,0 +1,6 @@
+---
+title: 'Refactor(opsgenie): remove Opsgenie integration frontend code from Incident
+ management'
+merge_request: 50525
+author:
+type: deprecated
diff --git a/changelogs/unreleased/276018-provisoned-accounts-welcome-email.yml b/changelogs/unreleased/276018-provisoned-accounts-welcome-email.yml
new file mode 100644
index 00000000000..ef37187b061
--- /dev/null
+++ b/changelogs/unreleased/276018-provisoned-accounts-welcome-email.yml
@@ -0,0 +1,5 @@
+---
+title: Add one welcome email for account provisioned by group
+merge_request: 51271
+author:
+type: other
diff --git a/changelogs/unreleased/276882-maven-dupe-fix.yml b/changelogs/unreleased/276882-maven-dupe-fix.yml
new file mode 100644
index 00000000000..1402d7fb710
--- /dev/null
+++ b/changelogs/unreleased/276882-maven-dupe-fix.yml
@@ -0,0 +1,6 @@
+---
+title: Fix behavior of maven_duplicates_allowed setting so new Maven packages can
+ be uploaded
+merge_request: 51524
+author:
+type: fixed
diff --git a/changelogs/unreleased/276882-package-maven-dupe-settings.yml b/changelogs/unreleased/276882-package-maven-dupe-settings.yml
new file mode 100644
index 00000000000..949c64ce5ee
--- /dev/null
+++ b/changelogs/unreleased/276882-package-maven-dupe-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add namespace settings to allow or disallow duplicate Maven packages
+merge_request: 50104
+author:
+type: added
diff --git a/changelogs/unreleased/276882-use-package-settings-maven.yml b/changelogs/unreleased/276882-use-package-settings-maven.yml
new file mode 100644
index 00000000000..2e38081bb9a
--- /dev/null
+++ b/changelogs/unreleased/276882-use-package-settings-maven.yml
@@ -0,0 +1,5 @@
+---
+title: Check namespace package settings when creating Maven packages
+merge_request: 50691
+author:
+type: changed
diff --git a/changelogs/unreleased/276900-use-the-expiration_policy_cleanup_status-to-report-the-cleanup-pol.yml b/changelogs/unreleased/276900-use-the-expiration_policy_cleanup_status-to-report-the-cleanup-pol.yml
new file mode 100644
index 00000000000..d8d2e1c34d7
--- /dev/null
+++ b/changelogs/unreleased/276900-use-the-expiration_policy_cleanup_status-to-report-the-cleanup-pol.yml
@@ -0,0 +1,5 @@
+---
+title: Add tags count and cleanup status to registry details
+merge_request: 50756
+author:
+type: changed
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..b557644578c
--- /dev/null
+++ b/changelogs/unreleased/276917-remove-default_merge_ref_for_diffs-feature-flag.yml
@@ -0,0 +1,6 @@
+---
+title: Fix issue with the `default_merge_refs` feature flag removing version to version
+ diffs
+merge_request: 50671
+author:
+type: fixed
diff --git a/changelogs/unreleased/276965-allow-basic-auth-for-generic-packages.yml b/changelogs/unreleased/276965-allow-basic-auth-for-generic-packages.yml
new file mode 100644
index 00000000000..2a4c3356a51
--- /dev/null
+++ b/changelogs/unreleased/276965-allow-basic-auth-for-generic-packages.yml
@@ -0,0 +1,5 @@
+---
+title: "Allow HTTP Basic Auth and deploy token authentication for generic packages"
+merge_request: 48540
+author: Moshe Katz @kohenkatz
+type: added
diff --git a/changelogs/unreleased/277030-fix-error-tracking-mobile-layout.yml b/changelogs/unreleased/277030-fix-error-tracking-mobile-layout.yml
new file mode 100644
index 00000000000..66248123b56
--- /dev/null
+++ b/changelogs/unreleased/277030-fix-error-tracking-mobile-layout.yml
@@ -0,0 +1,5 @@
+---
+title: Fix mobile layout Error Tracking details page
+merge_request: 50970
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/277134_populate_finding_uuid_values_for_vulnerability_feedback.yml b/changelogs/unreleased/277134_populate_finding_uuid_values_for_vulnerability_feedback.yml
new file mode 100644
index 00000000000..dc84ff7cb4d
--- /dev/null
+++ b/changelogs/unreleased/277134_populate_finding_uuid_values_for_vulnerability_feedback.yml
@@ -0,0 +1,6 @@
+---
+title: Populate `finding_uuid` attribute for the existing `vulnerability_feedback`
+ records
+merge_request: 49807
+author:
+type: added
diff --git a/changelogs/unreleased/278469-docs-feedback-hard-to-understand-code-coverage-colouring.yml b/changelogs/unreleased/278469-docs-feedback-hard-to-understand-code-coverage-colouring.yml
new file mode 100644
index 00000000000..94463ee22dc
--- /dev/null
+++ b/changelogs/unreleased/278469-docs-feedback-hard-to-understand-code-coverage-colouring.yml
@@ -0,0 +1,6 @@
+---
+title: Visually enhance the difference between code that has and does not have test
+ coverage
+merge_request: 49724
+author:
+type: other
diff --git a/changelogs/unreleased/280535-fix-mr-analytics-query-error.yml b/changelogs/unreleased/280535-fix-mr-analytics-query-error.yml
new file mode 100644
index 00000000000..28a8ecea268
--- /dev/null
+++ b/changelogs/unreleased/280535-fix-mr-analytics-query-error.yml
@@ -0,0 +1,5 @@
+---
+title: Fix merge request analytics page filtering when multiple labels are given
+merge_request: 51060
+author:
+type: fixed
diff --git a/changelogs/unreleased/280545-improve-container-registry-client.yml b/changelogs/unreleased/280545-improve-container-registry-client.yml
new file mode 100644
index 00000000000..8eb4b848056
--- /dev/null
+++ b/changelogs/unreleased/280545-improve-container-registry-client.yml
@@ -0,0 +1,5 @@
+---
+title: Improve the reliability and observability of the container registry client
+merge_request: 50750
+author:
+type: changed
diff --git a/changelogs/unreleased/280847-reduce-lcp-in-container-registry-index-page.yml b/changelogs/unreleased/280847-reduce-lcp-in-container-registry-index-page.yml
new file mode 100644
index 00000000000..e02464632b6
--- /dev/null
+++ b/changelogs/unreleased/280847-reduce-lcp-in-container-registry-index-page.yml
@@ -0,0 +1,5 @@
+---
+title: Defer tagsCount & add startup.js to container registry
+merge_request: 50147
+author:
+type: changed
diff --git a/changelogs/unreleased/281688-database-query-timeout-for-expired-job-artifacts.yml b/changelogs/unreleased/281688-database-query-timeout-for-expired-job-artifacts.yml
new file mode 100644
index 00000000000..7b36f0173cb
--- /dev/null
+++ b/changelogs/unreleased/281688-database-query-timeout-for-expired-job-artifacts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix database timeout errors when removing expired job artifacts
+merge_request: 47496
+author:
+type: fixed
diff --git a/changelogs/unreleased/281824-convert-project-members-list-view-from-haml-to-vue-setup-tabs.yml b/changelogs/unreleased/281824-convert-project-members-list-view-from-haml-to-vue-setup-tabs.yml
new file mode 100644
index 00000000000..1c1e4c48bad
--- /dev/null
+++ b/changelogs/unreleased/281824-convert-project-members-list-view-from-haml-to-vue-setup-tabs.yml
@@ -0,0 +1,5 @@
+---
+title: Reorganize project member management into tabs
+merge_request: 49764
+author:
+type: changed
diff --git a/changelogs/unreleased/281912_remove_jira_connect_full_namespace_sync_feature_flag.yml b/changelogs/unreleased/281912_remove_jira_connect_full_namespace_sync_feature_flag.yml
new file mode 100644
index 00000000000..26f02d08f47
--- /dev/null
+++ b/changelogs/unreleased/281912_remove_jira_connect_full_namespace_sync_feature_flag.yml
@@ -0,0 +1,6 @@
+---
+title: Initially sync Merge Requests with Jira when a namespace is added through the
+ GitLab for Jira app
+merge_request: 51341
+author:
+type: added
diff --git a/changelogs/unreleased/282299-grouping-swimlanes-choice-should-persist-after-board-has-been-edit.yml b/changelogs/unreleased/282299-grouping-swimlanes-choice-should-persist-after-board-has-been-edit.yml
new file mode 100644
index 00000000000..0aeedc2530f
--- /dev/null
+++ b/changelogs/unreleased/282299-grouping-swimlanes-choice-should-persist-after-board-has-been-edit.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Grouping/swimlanes choice should persist after board has been edited
+merge_request: 51317
+author:
+type: changed
diff --git a/changelogs/unreleased/282458_remove_default_update_sequence_id_from_jira_connect_workers.yml b/changelogs/unreleased/282458_remove_default_update_sequence_id_from_jira_connect_workers.yml
new file mode 100644
index 00000000000..2f854003438
--- /dev/null
+++ b/changelogs/unreleased/282458_remove_default_update_sequence_id_from_jira_connect_workers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Jira MR status not syncing by making workers idempotent
+merge_request: 51006
+author:
+type: fixed
diff --git a/changelogs/unreleased/283874-followup-to-mr-47253.yml b/changelogs/unreleased/283874-followup-to-mr-47253.yml
new file mode 100644
index 00000000000..26b11ef3304
--- /dev/null
+++ b/changelogs/unreleased/283874-followup-to-mr-47253.yml
@@ -0,0 +1,5 @@
+---
+title: Update error message used in boards sidebar subscription
+merge_request: 50352
+author:
+type: other
diff --git a/changelogs/unreleased/283875_remove_reset_integrations_feature_flag.yml b/changelogs/unreleased/283875_remove_reset_integrations_feature_flag.yml
new file mode 100644
index 00000000000..8306d8a3e77
--- /dev/null
+++ b/changelogs/unreleased/283875_remove_reset_integrations_feature_flag.yml
@@ -0,0 +1,5 @@
+---
+title: Allow resetting group and instance level integrations
+merge_request: 51507
+author:
+type: added
diff --git a/changelogs/unreleased/284640-fix-newline-in-custom-server-hook-renders-improperly.yml b/changelogs/unreleased/284640-fix-newline-in-custom-server-hook-renders-improperly.yml
new file mode 100644
index 00000000000..ceda863f4db
--- /dev/null
+++ b/changelogs/unreleased/284640-fix-newline-in-custom-server-hook-renders-improperly.yml
@@ -0,0 +1,5 @@
+---
+title: Fix multiple errors in custom server hook render improperly
+merge_request: 51001
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/284686-fix-the-maven-packages-finder.yml b/changelogs/unreleased/284686-fix-the-maven-packages-finder.yml
new file mode 100644
index 00000000000..754fc605dbd
--- /dev/null
+++ b/changelogs/unreleased/284686-fix-the-maven-packages-finder.yml
@@ -0,0 +1,5 @@
+---
+title: Update the maven package finder
+merge_request: 50774
+author:
+type: changed
diff --git a/changelogs/unreleased/285112-reduce-table-column-layout-shift.yml b/changelogs/unreleased/285112-reduce-table-column-layout-shift.yml
new file mode 100644
index 00000000000..fe0ea1b2f8e
--- /dev/null
+++ b/changelogs/unreleased/285112-reduce-table-column-layout-shift.yml
@@ -0,0 +1,5 @@
+---
+title: Fix table columm shift with table-layout fixed
+merge_request: 51416
+author:
+type: fixed
diff --git a/changelogs/unreleased/285334-maven-cross-group-sort.yml b/changelogs/unreleased/285334-maven-cross-group-sort.yml
new file mode 100644
index 00000000000..6fd1929d3b4
--- /dev/null
+++ b/changelogs/unreleased/285334-maven-cross-group-sort.yml
@@ -0,0 +1,6 @@
+---
+title: Maven will return the most recent maven-metadata.xml file if there are multiple
+ matches accross different projects
+merge_request: 50700
+author:
+type: fixed
diff --git a/changelogs/unreleased/285467-package-registry-graphql-api.yml b/changelogs/unreleased/285467-package-registry-graphql-api.yml
new file mode 100644
index 00000000000..7bb0398e25f
--- /dev/null
+++ b/changelogs/unreleased/285467-package-registry-graphql-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add composer details GraphQL type and query
+merge_request: 51059
+author:
+type: added
diff --git a/changelogs/unreleased/285509-global-breadcrumb-on-container-girestry-explorer.yml b/changelogs/unreleased/285509-global-breadcrumb-on-container-girestry-explorer.yml
new file mode 100644
index 00000000000..9accd792029
--- /dev/null
+++ b/changelogs/unreleased/285509-global-breadcrumb-on-container-girestry-explorer.yml
@@ -0,0 +1,5 @@
+---
+title: Fix UI on global breadcrumb on Project/Group Container Registry
+merge_request: 48288
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/285634-Fix-confusion-button-text-when-importing-from-github.yml b/changelogs/unreleased/285634-Fix-confusion-button-text-when-importing-from-github.yml
new file mode 100644
index 00000000000..480a3a40964
--- /dev/null
+++ b/changelogs/unreleased/285634-Fix-confusion-button-text-when-importing-from-github.yml
@@ -0,0 +1,5 @@
+---
+title: Fix confusing button text when importing from GitHub
+merge_request: 49684
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/287636-auto-assign-author.yml b/changelogs/unreleased/287636-auto-assign-author.yml
new file mode 100644
index 00000000000..18e1f2f695c
--- /dev/null
+++ b/changelogs/unreleased/287636-auto-assign-author.yml
@@ -0,0 +1,5 @@
+---
+title: Auto-assign merge request author when creating from issue
+merge_request: 50263
+author:
+type: added
diff --git a/changelogs/unreleased/287762-fix-multiple-vulnerabilities-requests.yml b/changelogs/unreleased/287762-fix-multiple-vulnerabilities-requests.yml
new file mode 100644
index 00000000000..cdb088f9676
--- /dev/null
+++ b/changelogs/unreleased/287762-fix-multiple-vulnerabilities-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Fix multiple simultaneous requests for vulnerabilities on pipeline security tab
+merge_request: 48426
+author:
+type: fixed
diff --git a/changelogs/unreleased/288325-wiki-avatar.yml b/changelogs/unreleased/288325-wiki-avatar.yml
new file mode 100644
index 00000000000..02cf02c23d9
--- /dev/null
+++ b/changelogs/unreleased/288325-wiki-avatar.yml
@@ -0,0 +1,5 @@
+---
+title: 'Wiki: Add author avatar and link'
+merge_request: 51273
+author:
+type: changed
diff --git a/changelogs/unreleased/288327-wiki-edit-automatically-focus-on-the-title-field.yml b/changelogs/unreleased/288327-wiki-edit-automatically-focus-on-the-title-field.yml
new file mode 100644
index 00000000000..2f10939fc40
--- /dev/null
+++ b/changelogs/unreleased/288327-wiki-edit-automatically-focus-on-the-title-field.yml
@@ -0,0 +1,5 @@
+---
+title: 'Wiki edit: automatically focus on the content field'
+merge_request: 50941
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/288329-wiki-submit-btn.yml b/changelogs/unreleased/288329-wiki-submit-btn.yml
new file mode 100644
index 00000000000..2219e0807da
--- /dev/null
+++ b/changelogs/unreleased/288329-wiki-submit-btn.yml
@@ -0,0 +1,5 @@
+---
+title: Disable submit button on wiki if no title and content
+merge_request: 51272
+author:
+type: changed
diff --git a/changelogs/unreleased/288812-cleanup-policies-hard-limit-the-number-of-tags-to-delete.yml b/changelogs/unreleased/288812-cleanup-policies-hard-limit-the-number-of-tags-to-delete.yml
new file mode 100644
index 00000000000..1dae0d28e9f
--- /dev/null
+++ b/changelogs/unreleased/288812-cleanup-policies-hard-limit-the-number-of-tags-to-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Limit the number of container tags to delete when deleting them in bulk
+merge_request: 49961
+author:
+type: changed
diff --git a/changelogs/unreleased/288812-properly-catch-tags-delete-errors-and-mark-repository-as-cleanup-u.yml b/changelogs/unreleased/288812-properly-catch-tags-delete-errors-and-mark-repository-as-cleanup-u.yml
new file mode 100644
index 00000000000..8250ea8ce7e
--- /dev/null
+++ b/changelogs/unreleased/288812-properly-catch-tags-delete-errors-and-mark-repository-as-cleanup-u.yml
@@ -0,0 +1,5 @@
+---
+title: Add error handling in the container registry delete tags service
+merge_request: 50763
+author:
+type: changed
diff --git a/changelogs/unreleased/289803-enable-ci_rules_variables.yml b/changelogs/unreleased/289803-enable-ci_rules_variables.yml
new file mode 100644
index 00000000000..84febffd245
--- /dev/null
+++ b/changelogs/unreleased/289803-enable-ci_rules_variables.yml
@@ -0,0 +1,5 @@
+---
+title: Implement variables for pipeline job rules
+merge_request: 50501
+author:
+type: added
diff --git a/changelogs/unreleased/289972-remove-users-show-json-completely.yml b/changelogs/unreleased/289972-remove-users-show-json-completely.yml
new file mode 100644
index 00000000000..7b07c342213
--- /dev/null
+++ b/changelogs/unreleased/289972-remove-users-show-json-completely.yml
@@ -0,0 +1,5 @@
+---
+title: Remove users#show.json completely
+merge_request: 49670
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/290008-fix-background-migration-arguments.yml b/changelogs/unreleased/290008-fix-background-migration-arguments.yml
new file mode 100644
index 00000000000..a9b5a8a2b75
--- /dev/null
+++ b/changelogs/unreleased/290008-fix-background-migration-arguments.yml
@@ -0,0 +1,5 @@
+---
+title: Fix argument type for background migration
+merge_request: 51475
+author:
+type: fixed
diff --git a/changelogs/unreleased/290008-remove-duplicate-services.yml b/changelogs/unreleased/290008-remove-duplicate-services.yml
new file mode 100644
index 00000000000..fa9b2f60eec
--- /dev/null
+++ b/changelogs/unreleased/290008-remove-duplicate-services.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicate service records
+merge_request: 49463
+author:
+type: fixed
diff --git a/changelogs/unreleased/290288-composer-cache-prep.yml b/changelogs/unreleased/290288-composer-cache-prep.yml
new file mode 100644
index 00000000000..c6925a60910
--- /dev/null
+++ b/changelogs/unreleased/290288-composer-cache-prep.yml
@@ -0,0 +1,5 @@
+---
+title: Add version cache field to composer metadata
+merge_request: 50906
+author:
+type: other
diff --git a/changelogs/unreleased/290715-has_external_wiki_trigger.yml b/changelogs/unreleased/290715-has_external_wiki_trigger.yml
new file mode 100644
index 00000000000..fcc635e53f9
--- /dev/null
+++ b/changelogs/unreleased/290715-has_external_wiki_trigger.yml
@@ -0,0 +1,5 @@
+---
+title: Add PostgreSQL trigger to maintain projects.has_external_wiki
+merge_request: 49916
+author:
+type: changed
diff --git a/changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml b/changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml
new file mode 100644
index 00000000000..0fab286b2e5
--- /dev/null
+++ b/changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust container registry metadata during loading
+merge_request: 50181
+author:
+type: changed
diff --git a/changelogs/unreleased/291027-extend-diffs_metadata-with-project-and-user-names.yml b/changelogs/unreleased/291027-extend-diffs_metadata-with-project-and-user-names.yml
new file mode 100644
index 00000000000..8d47ba92593
--- /dev/null
+++ b/changelogs/unreleased/291027-extend-diffs_metadata-with-project-and-user-names.yml
@@ -0,0 +1,5 @@
+---
+title: Add additional fields to diff_metadata.json endpoint
+merge_request: 50666
+author:
+type: changed
diff --git a/changelogs/unreleased/292017-fj-fix-bug-when-cloning-snippet-different-from-master.yml b/changelogs/unreleased/292017-fj-fix-bug-when-cloning-snippet-different-from-master.yml
new file mode 100644
index 00000000000..87a2ccb388d
--- /dev/null
+++ b/changelogs/unreleased/292017-fj-fix-bug-when-cloning-snippet-different-from-master.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug with snippets in HEAD when default branch is not master
+merge_request: 50366
+author:
+type: fixed
diff --git a/changelogs/unreleased/292039-limit-rendering-of-commit-messages.yml b/changelogs/unreleased/292039-limit-rendering-of-commit-messages.yml
new file mode 100644
index 00000000000..7e1723810c0
--- /dev/null
+++ b/changelogs/unreleased/292039-limit-rendering-of-commit-messages.yml
@@ -0,0 +1,5 @@
+---
+title: Limit rendering of commit messages
+merge_request: 51485
+author:
+type: performance
diff --git a/changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml b/changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml
new file mode 100644
index 00000000000..a7e1f625817
--- /dev/null
+++ b/changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml
@@ -0,0 +1,5 @@
+---
+title: Show all quick actions in `/` autocomplete
+merge_request: 51239
+author:
+type: added
diff --git a/changelogs/unreleased/292498-webide-switch-before-closing.yml b/changelogs/unreleased/292498-webide-switch-before-closing.yml
new file mode 100644
index 00000000000..310dd76275c
--- /dev/null
+++ b/changelogs/unreleased/292498-webide-switch-before-closing.yml
@@ -0,0 +1,5 @@
+---
+title: In WebIDE switch files before closing the active one
+merge_request: 51483
+author:
+type: fixed
diff --git a/changelogs/unreleased/292516-daily-updates-for-devops-adoption.yml b/changelogs/unreleased/292516-daily-updates-for-devops-adoption.yml
new file mode 100644
index 00000000000..a4555b348bb
--- /dev/null
+++ b/changelogs/unreleased/292516-daily-updates-for-devops-adoption.yml
@@ -0,0 +1,5 @@
+---
+title: Add DevOps adoption end_time column
+merge_request: 50257
+author:
+type: added
diff --git a/changelogs/unreleased/292517-enlarge-timeline-view-btn.yml b/changelogs/unreleased/292517-enlarge-timeline-view-btn.yml
new file mode 100644
index 00000000000..44978d9c8f6
--- /dev/null
+++ b/changelogs/unreleased/292517-enlarge-timeline-view-btn.yml
@@ -0,0 +1,5 @@
+---
+title: Enlarge the timeline toggle button
+merge_request: 50284
+author:
+type: fixed
diff --git a/changelogs/unreleased/292603-compliance-aggregated-usage-ping-metric.yml b/changelogs/unreleased/292603-compliance-aggregated-usage-ping-metric.yml
new file mode 100644
index 00000000000..a8519308f24
--- /dev/null
+++ b/changelogs/unreleased/292603-compliance-aggregated-usage-ping-metric.yml
@@ -0,0 +1,5 @@
+---
+title: Add aggregate/union visit tracking for Compliance features
+merge_request: 50978
+author:
+type: added
diff --git a/changelogs/unreleased/292658-include-keyword-for-cilint-graphql.yml b/changelogs/unreleased/292658-include-keyword-for-cilint-graphql.yml
new file mode 100644
index 00000000000..752e47d2b40
--- /dev/null
+++ b/changelogs/unreleased/292658-include-keyword-for-cilint-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add project scope to ci clint graphql endpoint
+merge_request: 50418
+author:
+type: fixed
diff --git a/changelogs/unreleased/292679-add-users-request-specs.yml b/changelogs/unreleased/292679-add-users-request-specs.yml
new file mode 100644
index 00000000000..5e00390e470
--- /dev/null
+++ b/changelogs/unreleased/292679-add-users-request-specs.yml
@@ -0,0 +1,5 @@
+---
+title: Replace user controller spec with its request spec
+merge_request: 50435
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/292680-refactor-users_controller_spec-rb-ssh_keys.yml b/changelogs/unreleased/292680-refactor-users_controller_spec-rb-ssh_keys.yml
new file mode 100644
index 00000000000..8361383aff1
--- /dev/null
+++ b/changelogs/unreleased/292680-refactor-users_controller_spec-rb-ssh_keys.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor specs around ssh_keys in users_controller_spec.rb
+merge_request: 50338
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-2.yml b/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-2.yml
new file mode 100644
index 00000000000..91d50ba2ac6
--- /dev/null
+++ b/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-2.yml
@@ -0,0 +1,5 @@
+---
+title: Add metrics to creating, editing or removing multiline comments on merge requests
+merge_request: 51098
+author:
+type: other
diff --git a/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-3.yml b/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-3.yml
new file mode 100644
index 00000000000..18257fb475e
--- /dev/null
+++ b/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request-3.yml
@@ -0,0 +1,5 @@
+---
+title: Add metrics to starting and publishing a review
+merge_request: 51521
+author:
+type: other
diff --git a/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request.yml b/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request.yml
new file mode 100644
index 00000000000..7bd0b19b2f5
--- /dev/null
+++ b/changelogs/unreleased/292822-track-comment-related-metrics-for-a-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Add metrics to creating, editing or removing comments on merge requests
+merge_request: 50849
+author:
+type: other
diff --git a/changelogs/unreleased/292827-track-action-metrics-for-a-merge-request.yml b/changelogs/unreleased/292827-track-action-metrics-for-a-merge-request.yml
new file mode 100644
index 00000000000..8442b5838ba
--- /dev/null
+++ b/changelogs/unreleased/292827-track-action-metrics-for-a-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Add metrics to creating, closing, reopening and merging merge requests
+merge_request: 50654
+author:
+type: other
diff --git a/changelogs/unreleased/292902-move-to-createboard-mutation-instead-of-rest-api-call-updateboard.yml b/changelogs/unreleased/292902-move-to-createboard-mutation-instead-of-rest-api-call-updateboard.yml
new file mode 100644
index 00000000000..5dcbc79a54e
--- /dev/null
+++ b/changelogs/unreleased/292902-move-to-createboard-mutation-instead-of-rest-api-call-updateboard.yml
@@ -0,0 +1,6 @@
+---
+title: "[RUN-AS-IF-FOSS] Move to `createBoard` mutation instead of REST API call +
+ `updateBoard`"
+merge_request: 50171
+author:
+type: changed
diff --git a/changelogs/unreleased/293679_introduce_dismissal_reason_for_vulnerability_feedback.yml b/changelogs/unreleased/293679_introduce_dismissal_reason_for_vulnerability_feedback.yml
new file mode 100644
index 00000000000..edb39b80600
--- /dev/null
+++ b/changelogs/unreleased/293679_introduce_dismissal_reason_for_vulnerability_feedback.yml
@@ -0,0 +1,5 @@
+---
+title: Add `dismissal_reason` column into the `vulnerability_feedback` table
+merge_request: 50632
+author:
+type: added
diff --git a/changelogs/unreleased/293803-fix-jobs-admin-is-missing-CI-status-styles.yml b/changelogs/unreleased/293803-fix-jobs-admin-is-missing-CI-status-styles.yml
new file mode 100644
index 00000000000..3c5de786d31
--- /dev/null
+++ b/changelogs/unreleased/293803-fix-jobs-admin-is-missing-CI-status-styles.yml
@@ -0,0 +1,5 @@
+---
+title: Fix jobs admin is missing CI status styles
+merge_request: 51161
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/293927-package-event-counts-are-not-aggregated-correctly.yml b/changelogs/unreleased/293927-package-event-counts-are-not-aggregated-correctly.yml
new file mode 100644
index 00000000000..53508629561
--- /dev/null
+++ b/changelogs/unreleased/293927-package-event-counts-are-not-aggregated-correctly.yml
@@ -0,0 +1,5 @@
+---
+title: Fix package event metrics aggregation
+merge_request: 50108
+author:
+type: changed
diff --git a/changelogs/unreleased/293967-refactor-users_controller_spec-gpg_keys.yml b/changelogs/unreleased/293967-refactor-users_controller_spec-gpg_keys.yml
new file mode 100644
index 00000000000..856817005fb
--- /dev/null
+++ b/changelogs/unreleased/293967-refactor-users_controller_spec-gpg_keys.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor specs around gpg_keys in users_controller_spec.rb
+merge_request: 50337
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml b/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml
new file mode 100644
index 00000000000..2688be6609f
--- /dev/null
+++ b/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml
@@ -0,0 +1,5 @@
+---
+title: Change onboarding actions table to use one record per namespace
+merge_request: 50711
+author:
+type: changed
diff --git a/changelogs/unreleased/294202-updated-at.yml b/changelogs/unreleased/294202-updated-at.yml
new file mode 100644
index 00000000000..6ffbc55dab6
--- /dev/null
+++ b/changelogs/unreleased/294202-updated-at.yml
@@ -0,0 +1,5 @@
+---
+title: Persist updated_at value in state change events
+merge_request: 50272
+author:
+type: fixed
diff --git a/changelogs/unreleased/294422-follow-up-from-fire-webhook-when-updating-or-removing-a-group-memb.yml b/changelogs/unreleased/294422-follow-up-from-fire-webhook-when-updating-or-removing-a-group-memb.yml
new file mode 100644
index 00000000000..f1659f03ae2
--- /dev/null
+++ b/changelogs/unreleased/294422-follow-up-from-fire-webhook-when-updating-or-removing-a-group-memb.yml
@@ -0,0 +1,5 @@
+---
+title: Send email when group member expiry is updated
+merge_request: 50310
+author:
+type: added
diff --git a/changelogs/unreleased/295263-fork-icon-shrinks-if-branch-name-is-very-long.yml b/changelogs/unreleased/295263-fork-icon-shrinks-if-branch-name-is-very-long.yml
new file mode 100644
index 00000000000..1c73ef105c5
--- /dev/null
+++ b/changelogs/unreleased/295263-fork-icon-shrinks-if-branch-name-is-very-long.yml
@@ -0,0 +1,5 @@
+---
+title: Fix fork icon shrinks if branch name is very long
+merge_request: 50915
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/295494-fix-runner-admin-is-missing-ci-status-styles.yml b/changelogs/unreleased/295494-fix-runner-admin-is-missing-ci-status-styles.yml
new file mode 100644
index 00000000000..f8526b493eb
--- /dev/null
+++ b/changelogs/unreleased/295494-fix-runner-admin-is-missing-ci-status-styles.yml
@@ -0,0 +1,5 @@
+---
+title: Fix runner admin is missing CI status styles
+merge_request: 51158
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/295625-include-a-test-to-check-if-users-user-is-redirected-to-users-show.yml b/changelogs/unreleased/295625-include-a-test-to-check-if-users-user-is-redirected-to-users-show.yml
new file mode 100644
index 00000000000..74906109f23
--- /dev/null
+++ b/changelogs/unreleased/295625-include-a-test-to-check-if-users-user-is-redirected-to-users-show.yml
@@ -0,0 +1,5 @@
+---
+title: Add test to check if /users/User is redirected to /User
+merge_request: 50651
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/296380-update-docker-from-19-03-to-20-10-on-ci-cd-of-gitlab.yml b/changelogs/unreleased/296380-update-docker-from-19-03-to-20-10-on-ci-cd-of-gitlab.yml
new file mode 100644
index 00000000000..5765f032024
--- /dev/null
+++ b/changelogs/unreleased/296380-update-docker-from-19-03-to-20-10-on-ci-cd-of-gitlab.yml
@@ -0,0 +1,5 @@
+---
+title: Update Docker from 19.03.0 to 20.10.1 on CI/CD
+merge_request: 50732
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/296606-use-gl-badge-in-pipeline-url-component.yml b/changelogs/unreleased/296606-use-gl-badge-in-pipeline-url-component.yml
new file mode 100644
index 00000000000..bae97d7a576
--- /dev/null
+++ b/changelogs/unreleased/296606-use-gl-badge-in-pipeline-url-component.yml
@@ -0,0 +1,5 @@
+---
+title: Use GlBadge for badges in pipeline_url.vue
+merge_request: 51058
+author: Kev @KevSlashNull
+type: changed
diff --git a/changelogs/unreleased/296842-invalidate-reviewer-counter-on-create.yml b/changelogs/unreleased/296842-invalidate-reviewer-counter-on-create.yml
new file mode 100644
index 00000000000..c06a634706e
--- /dev/null
+++ b/changelogs/unreleased/296842-invalidate-reviewer-counter-on-create.yml
@@ -0,0 +1,5 @@
+---
+title: Invalidate reviews counter cache when MR gets created
+merge_request: 51316
+author:
+type: fixed
diff --git a/changelogs/unreleased/296842-review-requests-counter-cache-invalidation.yml b/changelogs/unreleased/296842-review-requests-counter-cache-invalidation.yml
new file mode 100644
index 00000000000..a92acd20c91
--- /dev/null
+++ b/changelogs/unreleased/296842-review-requests-counter-cache-invalidation.yml
@@ -0,0 +1,5 @@
+---
+title: Invalidate reviews counter cache when MR gets closed/merged/reopened
+merge_request: 51055
+author:
+type: fixed
diff --git a/changelogs/unreleased/297007-add-back-milestones-to-incidents.yml b/changelogs/unreleased/297007-add-back-milestones-to-incidents.yml
new file mode 100644
index 00000000000..a7587ad1daf
--- /dev/null
+++ b/changelogs/unreleased/297007-add-back-milestones-to-incidents.yml
@@ -0,0 +1,5 @@
+---
+title: 'Update Issue Incidents to allow the milestones feature to be used in the sidebar and quick actions'
+merge_request: 51456
+author:
+type: changed
diff --git a/changelogs/unreleased/297011-add-additional-aliases-for-reviewer-quick-commands.yml b/changelogs/unreleased/297011-add-additional-aliases-for-reviewer-quick-commands.yml
new file mode 100644
index 00000000000..6234ffe87ec
--- /dev/null
+++ b/changelogs/unreleased/297011-add-additional-aliases-for-reviewer-quick-commands.yml
@@ -0,0 +1,5 @@
+---
+title: Adding /reviewer and /remove_reviewer aliases and specs
+merge_request: 51384
+author:
+type: added
diff --git a/changelogs/unreleased/297503-cablett-remove-index.yml b/changelogs/unreleased/297503-cablett-remove-index.yml
new file mode 100644
index 00000000000..33d52edeac1
--- /dev/null
+++ b/changelogs/unreleased/297503-cablett-remove-index.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unneeded group label index
+merge_request: 51676
+author:
+type: other
diff --git a/changelogs/unreleased/297569-inline-code-coverage-visualization-not-displaying-in-inline-mr-dif.yml b/changelogs/unreleased/297569-inline-code-coverage-visualization-not-displaying-in-inline-mr-dif.yml
new file mode 100644
index 00000000000..1c368613fca
--- /dev/null
+++ b/changelogs/unreleased/297569-inline-code-coverage-visualization-not-displaying-in-inline-mr-dif.yml
@@ -0,0 +1,5 @@
+---
+title: Fix coverage not showing for inline diffs
+merge_request: 51652
+author:
+type: fixed
diff --git a/changelogs/unreleased/298884-fix-broken-foss.yml b/changelogs/unreleased/298884-fix-broken-foss.yml
new file mode 100644
index 00000000000..3200a827d33
--- /dev/null
+++ b/changelogs/unreleased/298884-fix-broken-foss.yml
@@ -0,0 +1,5 @@
+---
+title: Remove EE references from FOSS code
+merge_request: 51832
+author:
+type: fixed
diff --git a/changelogs/unreleased/30390-duplicate-group-label.yml b/changelogs/unreleased/30390-duplicate-group-label.yml
new file mode 100644
index 00000000000..116fee49b48
--- /dev/null
+++ b/changelogs/unreleased/30390-duplicate-group-label.yml
@@ -0,0 +1,5 @@
+---
+title: Deduplicate labels with identical title and group
+merge_request: 37148
+author:
+type: fixed
diff --git a/changelogs/unreleased/30477-vfazio-alert-transfer-error.yml b/changelogs/unreleased/30477-vfazio-alert-transfer-error.yml
new file mode 100644
index 00000000000..7cf2f9d3d0f
--- /dev/null
+++ b/changelogs/unreleased/30477-vfazio-alert-transfer-error.yml
@@ -0,0 +1,5 @@
+---
+title: Flash transfer errors in the admin project controller
+merge_request: 50541
+author: Vincent Fazio
+type: fixed
diff --git a/changelogs/unreleased/31343-remove-more-unnecessary-freeze.yml b/changelogs/unreleased/31343-remove-more-unnecessary-freeze.yml
new file mode 100644
index 00000000000..dce5f6a4c02
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-more-unnecessary-freeze.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of .freeze
+merge_request: 51073
+author: Adam Davies @adamd92
+type: other
diff --git a/changelogs/unreleased/31343-remove-unneccessary-freeze.yml b/changelogs/unreleased/31343-remove-unneccessary-freeze.yml
new file mode 100644
index 00000000000..2a4094e3515
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-unneccessary-freeze.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of .freeze
+merge_request: 50963
+author: Adam Davies @adamd92
+type: other
diff --git a/changelogs/unreleased/36423-nuget-group-level-project-api.yml b/changelogs/unreleased/36423-nuget-group-level-project-api.yml
new file mode 100644
index 00000000000..eaf72e7d9aa
--- /dev/null
+++ b/changelogs/unreleased/36423-nuget-group-level-project-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add the NuGet group level API
+merge_request: 48356
+author:
+type: added
diff --git a/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_index-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_index-html-haml.yml
new file mode 100644
index 00000000000..eaa3e1a803f
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Update button style of expand/collapse button on Deploy Tokens page
+merge_request: 51077
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_revoke_modal-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_revoke_modal-html-haml.yml
new file mode 100644
index 00000000000..578d4128ad6
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_revoke_modal-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Update button style of Revoke button on Deploy Tokens page
+merge_request: 51079
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsintrascations_show-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsintrascations_show-html-haml.yml
new file mode 100644
index 00000000000..73f4656f1ca
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsintrascations_show-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in transactions show.html.haml files
+merge_request: 51096
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Fix-alignment-of-protected-tag-labels-on-mobile.yml b/changelogs/unreleased/Fix-alignment-of-protected-tag-labels-on-mobile.yml
new file mode 100644
index 00000000000..46dcd4a36d5
--- /dev/null
+++ b/changelogs/unreleased/Fix-alignment-of-protected-tag-labels-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment of protected tag and branch labels on mobile
+merge_request: 51100
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/Fix-long-deploy-token-name-overflows-revocation-modal.yml b/changelogs/unreleased/Fix-long-deploy-token-name-overflows-revocation-modal.yml
new file mode 100644
index 00000000000..cd7f4ac2362
--- /dev/null
+++ b/changelogs/unreleased/Fix-long-deploy-token-name-overflows-revocation-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Fix long deploy token name overflows revocation modal
+merge_request: 51114
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml b/changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml
new file mode 100644
index 00000000000..1d8a0b1be74
--- /dev/null
+++ b/changelogs/unreleased/Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app-assets-javascri.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate-Bootstrap-dropdown-to-GitLab-UI-GlDropdown-in-app/assets/javascripts/vue_shared/components/pikaday.vue
+merge_request: 41458
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ab-drop-tmp-index.yml b/changelogs/unreleased/ab-drop-tmp-index.yml
new file mode 100644
index 00000000000..8be51fe4e0b
--- /dev/null
+++ b/changelogs/unreleased/ab-drop-tmp-index.yml
@@ -0,0 +1,5 @@
+---
+title: Drop temporary index on ci_builds
+merge_request: 50961
+author:
+type: other
diff --git a/changelogs/unreleased/add-api-command-to-delete-pending-invitation.yml b/changelogs/unreleased/add-api-command-to-delete-pending-invitation.yml
new file mode 100644
index 00000000000..c11d89900e1
--- /dev/null
+++ b/changelogs/unreleased/add-api-command-to-delete-pending-invitation.yml
@@ -0,0 +1,5 @@
+---
+title: Add API command to remove pending member invitation
+merge_request: 51134
+author:
+type: added
diff --git a/changelogs/unreleased/add-flutter-cicd-template.yml b/changelogs/unreleased/add-flutter-cicd-template.yml
new file mode 100644
index 00000000000..87ae7a3a50c
--- /dev/null
+++ b/changelogs/unreleased/add-flutter-cicd-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add flutter CI/CD template
+merge_request: 46968
+author:
+type: added
diff --git a/changelogs/unreleased/add-icons.yml b/changelogs/unreleased/add-icons.yml
new file mode 100644
index 00000000000..35f8befa15f
--- /dev/null
+++ b/changelogs/unreleased/add-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Add Icons to headings in system info on admin panel
+merge_request: 46618
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/add-terraform-state-api-usage-tracking.yml b/changelogs/unreleased/add-terraform-state-api-usage-tracking.yml
new file mode 100644
index 00000000000..f73bb82811c
--- /dev/null
+++ b/changelogs/unreleased/add-terraform-state-api-usage-tracking.yml
@@ -0,0 +1,5 @@
+---
+title: Track usage for Terraform State API
+merge_request: 50224
+author:
+type: added
diff --git a/changelogs/unreleased/add-user-id-to-user-webhook-data.yml b/changelogs/unreleased/add-user-id-to-user-webhook-data.yml
new file mode 100644
index 00000000000..712d3b5457c
--- /dev/null
+++ b/changelogs/unreleased/add-user-id-to-user-webhook-data.yml
@@ -0,0 +1,5 @@
+---
+title: Include the user id in the webhook payload
+merge_request: 50287
+author:
+type: added
diff --git a/changelogs/unreleased/add_access_request_endpoint.yml b/changelogs/unreleased/add_access_request_endpoint.yml
new file mode 100644
index 00000000000..e3eb6ade6ae
--- /dev/null
+++ b/changelogs/unreleased/add_access_request_endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Add access request endpoint to OpenAPI standard
+merge_request: 51000
+author: Jim Cser
+type: changed
diff --git a/changelogs/unreleased/add_annotation_to_cilium_network_policies.yml b/changelogs/unreleased/add_annotation_to_cilium_network_policies.yml
new file mode 100644
index 00000000000..6d5a8ba6924
--- /dev/null
+++ b/changelogs/unreleased/add_annotation_to_cilium_network_policies.yml
@@ -0,0 +1,5 @@
+---
+title: Adds annotations as part of metadata for CiliumNetworkPolicies wrapper
+merge_request: 50586
+author:
+type: changed
diff --git a/changelogs/unreleased/add_boards_url.yml b/changelogs/unreleased/add_boards_url.yml
new file mode 100644
index 00000000000..1342192ded2
--- /dev/null
+++ b/changelogs/unreleased/add_boards_url.yml
@@ -0,0 +1,5 @@
+---
+title: Exposed web_path and web_url fields in Board's GraphQL API
+merge_request: 50947
+author:
+type: added
diff --git a/changelogs/unreleased/add_codeowners_supersede_for_web_ide.yml b/changelogs/unreleased/add_codeowners_supersede_for_web_ide.yml
new file mode 100644
index 00000000000..87c3426edae
--- /dev/null
+++ b/changelogs/unreleased/add_codeowners_supersede_for_web_ide.yml
@@ -0,0 +1,5 @@
+---
+title: Fix codeowners superseding web ide and single file edit
+merge_request: 50608
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-297358-fix-preloaded-pagination.yml b/changelogs/unreleased/ajk-297358-fix-preloaded-pagination.yml
new file mode 100644
index 00000000000..a882c0ffd1e
--- /dev/null
+++ b/changelogs/unreleased/ajk-297358-fix-preloaded-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Generate page-info for connections of preloaded associations
+merge_request: 51642
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-ci-job-needs-type.yml b/changelogs/unreleased/ajk-ci-job-needs-type.yml
new file mode 100644
index 00000000000..55f3802fa6b
--- /dev/null
+++ b/changelogs/unreleased/ajk-ci-job-needs-type.yml
@@ -0,0 +1,5 @@
+---
+title: Change type of CiJob.needs
+merge_request: 50192
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-gql-ci-performance-improvements.yml b/changelogs/unreleased/ajk-gql-ci-performance-improvements.yml
new file mode 100644
index 00000000000..d10678dd4d0
--- /dev/null
+++ b/changelogs/unreleased/ajk-gql-ci-performance-improvements.yml
@@ -0,0 +1,5 @@
+---
+title: Performance improvements for CI GraphQL resources
+merge_request: 50386
+author:
+type: performance
diff --git a/changelogs/unreleased/ajk-gql-merge-request-reviewers.yml b/changelogs/unreleased/ajk-gql-merge-request-reviewers.yml
new file mode 100644
index 00000000000..69ad109aeb2
--- /dev/null
+++ b/changelogs/unreleased/ajk-gql-merge-request-reviewers.yml
@@ -0,0 +1,5 @@
+---
+title: Adds MergeRequest.reviewers to GraphQL API
+merge_request: 49707
+author:
+type: changed
diff --git a/changelogs/unreleased/ajk-group-member-policy-fix.yml b/changelogs/unreleased/ajk-group-member-policy-fix.yml
new file mode 100644
index 00000000000..61b1ead3cb1
--- /dev/null
+++ b/changelogs/unreleased/ajk-group-member-policy-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Allow more actions on group members
+merge_request: 50445
+author:
+type: fixed
diff --git a/changelogs/unreleased/align-admin-notes-label-to-the-left.yml b/changelogs/unreleased/align-admin-notes-label-to-the-left.yml
new file mode 100644
index 00000000000..26a747c942d
--- /dev/null
+++ b/changelogs/unreleased/align-admin-notes-label-to-the-left.yml
@@ -0,0 +1,5 @@
+---
+title: Align admin notes label to the left
+merge_request: 50992
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/allow-custom-rate-limiting-response.yml b/changelogs/unreleased/allow-custom-rate-limiting-response.yml
new file mode 100644
index 00000000000..059e2ac8caf
--- /dev/null
+++ b/changelogs/unreleased/allow-custom-rate-limiting-response.yml
@@ -0,0 +1,5 @@
+---
+title: Allow custom response to be set when rate limits are exceeded
+merge_request: 50693
+author:
+type: added
diff --git a/changelogs/unreleased/andr3-remove-sidebar-toggle-reviewers.yml b/changelogs/unreleased/andr3-remove-sidebar-toggle-reviewers.yml
new file mode 100644
index 00000000000..402369d201a
--- /dev/null
+++ b/changelogs/unreleased/andr3-remove-sidebar-toggle-reviewers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix duplicated toggle button showing on right sidebar when signed out
+merge_request: 50892
+author:
+type: fixed
diff --git a/changelogs/unreleased/aqualls-okr-autodevops.yml b/changelogs/unreleased/aqualls-okr-autodevops.yml
new file mode 100644
index 00000000000..df5f7dc6d03
--- /dev/null
+++ b/changelogs/unreleased/aqualls-okr-autodevops.yml
@@ -0,0 +1,5 @@
+---
+title: Update Auto DevOps UI text to match style guidelines
+merge_request: 50398
+author: Amy Qualls @aqualls
+type: other
diff --git a/changelogs/unreleased/aqualls-okr-protected-branches.yml b/changelogs/unreleased/aqualls-okr-protected-branches.yml
new file mode 100644
index 00000000000..981156e8774
--- /dev/null
+++ b/changelogs/unreleased/aqualls-okr-protected-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 50475
+author: Amy Qualls @aqualls
+type: other
diff --git a/changelogs/unreleased/aqualls-okr-protected-tags.yml b/changelogs/unreleased/aqualls-okr-protected-tags.yml
new file mode 100644
index 00000000000..b37a231a087
--- /dev/null
+++ b/changelogs/unreleased/aqualls-okr-protected-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 50476
+author:
+type: other
diff --git a/changelogs/unreleased/astoicescu-remove-limit-of-features-on-billing-page.yml b/changelogs/unreleased/astoicescu-remove-limit-of-features-on-billing-page.yml
new file mode 100644
index 00000000000..e965c8453c3
--- /dev/null
+++ b/changelogs/unreleased/astoicescu-remove-limit-of-features-on-billing-page.yml
@@ -0,0 +1,5 @@
+---
+title: Remove limit of four features per plan
+merge_request: 51264
+author:
+type: changed
diff --git a/changelogs/unreleased/board_api.yml b/changelogs/unreleased/board_api.yml
new file mode 100644
index 00000000000..9c0b2e88878
--- /dev/null
+++ b/changelogs/unreleased/board_api.yml
@@ -0,0 +1,5 @@
+---
+title: Expose hide_backlog_list and hide_closed_list to project and group boards REST API
+merge_request: 49815
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/cablett-issue-due.yml b/changelogs/unreleased/cablett-issue-due.yml
new file mode 100644
index 00000000000..82d433bdf93
--- /dev/null
+++ b/changelogs/unreleased/cablett-issue-due.yml
@@ -0,0 +1,5 @@
+---
+title: Add issue link to due date emails
+merge_request: 50642
+author:
+type: changed
diff --git a/changelogs/unreleased/cc-verbiage-sast-in-core.yml b/changelogs/unreleased/cc-verbiage-sast-in-core.yml
new file mode 100644
index 00000000000..5d286ce77e7
--- /dev/null
+++ b/changelogs/unreleased/cc-verbiage-sast-in-core.yml
@@ -0,0 +1,5 @@
+---
+title: Add verbiage + link sast to show it's in core.
+merge_request: 51935
+author:
+type: Other
diff --git a/changelogs/unreleased/change-clusters-helm-major-version-default-to-3.yml b/changelogs/unreleased/change-clusters-helm-major-version-default-to-3.yml
new file mode 100644
index 00000000000..10d20598955
--- /dev/null
+++ b/changelogs/unreleased/change-clusters-helm-major-version-default-to-3.yml
@@ -0,0 +1,5 @@
+---
+title: Change clusters.helm_major_version default to 3
+merge_request: 50399
+author:
+type: changed
diff --git a/changelogs/unreleased/chore-disable-admin-mode-in-lib.yml b/changelogs/unreleased/chore-disable-admin-mode-in-lib.yml
new file mode 100644
index 00000000000..6c04146472d
--- /dev/null
+++ b/changelogs/unreleased/chore-disable-admin-mode-in-lib.yml
@@ -0,0 +1,5 @@
+---
+title: Disable auto admin mode for lib specs
+merge_request: 50056
+author: Diego Louzán
+type: other
diff --git a/changelogs/unreleased/chore-disable-admin-mode-remains.yml b/changelogs/unreleased/chore-disable-admin-mode-remains.yml
new file mode 100644
index 00000000000..146a8b7e93b
--- /dev/null
+++ b/changelogs/unreleased/chore-disable-admin-mode-remains.yml
@@ -0,0 +1,5 @@
+---
+title: Fully disable auto admin mode and migrate remaining specs
+merge_request: 50331
+author: Diego Louzán
+type: other
diff --git a/changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml b/changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml
new file mode 100644
index 00000000000..44e439b80d7
--- /dev/null
+++ b/changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml
@@ -0,0 +1,5 @@
+---
+title: Control job status using exit codes
+merge_request: 51439
+author:
+type: added
diff --git a/changelogs/unreleased/ci-pipeline-artifacts-removal-cleanup.yml b/changelogs/unreleased/ci-pipeline-artifacts-removal-cleanup.yml
new file mode 100644
index 00000000000..e6f2ecbe09b
--- /dev/null
+++ b/changelogs/unreleased/ci-pipeline-artifacts-removal-cleanup.yml
@@ -0,0 +1,6 @@
+---
+title: Extract expired pipeline artifacts removal service into it's own background
+ worker
+merge_request: 51323
+author:
+type: changed
diff --git a/changelogs/unreleased/ci-project-config-path-variable.yml b/changelogs/unreleased/ci-project-config-path-variable.yml
new file mode 100644
index 00000000000..1945c93bdc7
--- /dev/null
+++ b/changelogs/unreleased/ci-project-config-path-variable.yml
@@ -0,0 +1,5 @@
+---
+title: Add project config path as a predefined project variable
+merge_request: 50301
+author:
+type: added
diff --git a/changelogs/unreleased/ci-setting-prevent-user-defined-ci-variables.yml b/changelogs/unreleased/ci-setting-prevent-user-defined-ci-variables.yml
new file mode 100644
index 00000000000..3ae1c06e04a
--- /dev/null
+++ b/changelogs/unreleased/ci-setting-prevent-user-defined-ci-variables.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent user-defined variables from being used by non-maintainers
+merge_request: 51682
+author:
+type: security
diff --git a/changelogs/unreleased/dblessing_ldap_rake_db_create_fix.yml b/changelogs/unreleased/dblessing_ldap_rake_db_create_fix.yml
new file mode 100644
index 00000000000..c24882915c6
--- /dev/null
+++ b/changelogs/unreleased/dblessing_ldap_rake_db_create_fix.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure Rake DB create doesn't fail when LDAP is enabled
+merge_request: 51132
+author:
+type: fixed
diff --git a/changelogs/unreleased/dblessing_redirect_deprecated_profile_paths.yml b/changelogs/unreleased/dblessing_redirect_deprecated_profile_paths.yml
new file mode 100644
index 00000000000..1b4f0694e32
--- /dev/null
+++ b/changelogs/unreleased/dblessing_redirect_deprecated_profile_paths.yml
@@ -0,0 +1,5 @@
+---
+title: Redirect deprecated profile paths to scoped path
+merge_request: 51646
+author:
+type: changed
diff --git a/changelogs/unreleased/debian_distribution_architectures.yml b/changelogs/unreleased/debian_distribution_architectures.yml
new file mode 100644
index 00000000000..0ab8b723a52
--- /dev/null
+++ b/changelogs/unreleased/debian_distribution_architectures.yml
@@ -0,0 +1,5 @@
+---
+title: Debian Group and Project Distribution Architectures
+merge_request: 51265
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/debian_distributions.yml b/changelogs/unreleased/debian_distributions.yml
new file mode 100644
index 00000000000..e552b33d83e
--- /dev/null
+++ b/changelogs/unreleased/debian_distributions.yml
@@ -0,0 +1,5 @@
+---
+title: Debian Group and Project Distributions
+merge_request: 49405
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/debian_file_metadatum.yml b/changelogs/unreleased/debian_file_metadatum.yml
new file mode 100644
index 00000000000..59ed2f261ba
--- /dev/null
+++ b/changelogs/unreleased/debian_file_metadatum.yml
@@ -0,0 +1,5 @@
+---
+title: Debian File Metadata
+merge_request: 49692
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/debian_package_file_upload.yml b/changelogs/unreleased/debian_package_file_upload.yml
new file mode 100644
index 00000000000..0b69f9bc0dc
--- /dev/null
+++ b/changelogs/unreleased/debian_package_file_upload.yml
@@ -0,0 +1,5 @@
+---
+title: Use a dynamic segment not depending on the package id for Debian files
+merge_request: 50433
+author: Mathieu Parent
+type: changed
diff --git a/changelogs/unreleased/default-enable-set-user-availability-status.yml b/changelogs/unreleased/default-enable-set-user-availability-status.yml
new file mode 100644
index 00000000000..2bce3a1605f
--- /dev/null
+++ b/changelogs/unreleased/default-enable-set-user-availability-status.yml
@@ -0,0 +1,5 @@
+---
+title: Default enable set_user_availability_status
+merge_request: 51668
+author:
+type: changed
diff --git a/changelogs/unreleased/default-enabled-reviewer-approval-rules.yml b/changelogs/unreleased/default-enabled-reviewer-approval-rules.yml
new file mode 100644
index 00000000000..9d0fef09c2b
--- /dev/null
+++ b/changelogs/unreleased/default-enabled-reviewer-approval-rules.yml
@@ -0,0 +1,5 @@
+---
+title: Enable reviewer_approval_rules by default
+merge_request: 51183
+author:
+type: changed
diff --git a/changelogs/unreleased/deprecate-prometheus-listen-address.yml b/changelogs/unreleased/deprecate-prometheus-listen-address.yml
new file mode 100644
index 00000000000..2c0c0b84663
--- /dev/null
+++ b/changelogs/unreleased/deprecate-prometheus-listen-address.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate prometheus.listen_address and prometheus.enable
+merge_request: 50500
+author:
+type: deprecated
diff --git a/changelogs/unreleased/disable-pipelines-explore.yml b/changelogs/unreleased/disable-pipelines-explore.yml
new file mode 100644
index 00000000000..649ae9a2441
--- /dev/null
+++ b/changelogs/unreleased/disable-pipelines-explore.yml
@@ -0,0 +1,5 @@
+---
+title: Remove pipeline status from /explore page
+merge_request: 51621
+author:
+type: performance
diff --git a/changelogs/unreleased/display-artifacts-dropdown-on-mr-widget.yml b/changelogs/unreleased/display-artifacts-dropdown-on-mr-widget.yml
new file mode 100644
index 00000000000..4f35e750434
--- /dev/null
+++ b/changelogs/unreleased/display-artifacts-dropdown-on-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Display Artifacts Dropdown on MR Pipeline Widget
+merge_request: 50998
+author:
+type: added
diff --git a/changelogs/unreleased/doc-218997-fj-add-doc-for-snippet-api-repository-moves.yml b/changelogs/unreleased/doc-218997-fj-add-doc-for-snippet-api-repository-moves.yml
new file mode 100644
index 00000000000..5d916009525
--- /dev/null
+++ b/changelogs/unreleased/doc-218997-fj-add-doc-for-snippet-api-repository-moves.yml
@@ -0,0 +1,5 @@
+---
+title: Add documentation for new Snippet repository storage move API
+merge_request: 50151
+author:
+type: other
diff --git a/changelogs/unreleased/docs-geo-update-patroni-support.yml b/changelogs/unreleased/docs-geo-update-patroni-support.yml
new file mode 100644
index 00000000000..097f8ab558a
--- /dev/null
+++ b/changelogs/unreleased/docs-geo-update-patroni-support.yml
@@ -0,0 +1,6 @@
+---
+title: Update documentation for setting up database replication with Patroni on a
+ Geo secondary node
+merge_request: 49986
+author:
+type: other
diff --git a/changelogs/unreleased/docs-make-patroni-recommended.yml b/changelogs/unreleased/docs-make-patroni-recommended.yml
new file mode 100644
index 00000000000..47e2bdf7e66
--- /dev/null
+++ b/changelogs/unreleased/docs-make-patroni-recommended.yml
@@ -0,0 +1,5 @@
+---
+title: Use Patroni as the default in the replication docs
+merge_request: 50101
+author:
+type: changed
diff --git a/changelogs/unreleased/drop-tmp-index-on-emails-again.yml b/changelogs/unreleased/drop-tmp-index-on-emails-again.yml
new file mode 100644
index 00000000000..a198bae26a7
--- /dev/null
+++ b/changelogs/unreleased/drop-tmp-index-on-emails-again.yml
@@ -0,0 +1,5 @@
+---
+title: Drop tmp_index_for_email_unconfirmation index from the emails table again
+merge_request: 51440
+author:
+type: other
diff --git a/changelogs/unreleased/dz-5-minute-prod-app-ci-template.yml b/changelogs/unreleased/dz-5-minute-prod-app-ci-template.yml
new file mode 100644
index 00000000000..f436dadf7e2
--- /dev/null
+++ b/changelogs/unreleased/dz-5-minute-prod-app-ci-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add 5-minute-production-app CI template
+merge_request: 49487
+author:
+type: added
diff --git a/changelogs/unreleased/eb-fix-cobertura-empty-sources.yml b/changelogs/unreleased/eb-fix-cobertura-empty-sources.yml
new file mode 100644
index 00000000000..422a2f6d38e
--- /dev/null
+++ b/changelogs/unreleased/eb-fix-cobertura-empty-sources.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cobertura parser when there is an empty sources node
+merge_request: 50971
+author:
+type: fixed
diff --git a/changelogs/unreleased/eb-remove-test-failure-history-flag.yml b/changelogs/unreleased/eb-remove-test-failure-history-flag.yml
new file mode 100644
index 00000000000..c91888d0177
--- /dev/null
+++ b/changelogs/unreleased/eb-remove-test-failure-history-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove test_failure_history flag
+merge_request: 51464
+author:
+type: changed
diff --git a/changelogs/unreleased/epic-5076-spec-controllers-jwks_controller_spec-rb.yml b/changelogs/unreleased/epic-5076-spec-controllers-jwks_controller_spec-rb.yml
new file mode 100644
index 00000000000..fedbf558097
--- /dev/null
+++ b/changelogs/unreleased/epic-5076-spec-controllers-jwks_controller_spec-rb.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate jwks_controller specs to request specs of them
+merge_request: 50767
+author: Takuya Noguchi @tnir
+type: other
diff --git a/changelogs/unreleased/epic-5076-spec-controllers-runner_setup_controller_spec-rb.yml b/changelogs/unreleased/epic-5076-spec-controllers-runner_setup_controller_spec-rb.yml
new file mode 100644
index 00000000000..8b5bff7f3d5
--- /dev/null
+++ b/changelogs/unreleased/epic-5076-spec-controllers-runner_setup_controller_spec-rb.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate runner_setup_controller_spec.rb to request spec
+merge_request: 50600
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/epic_boards_epic_list.yml b/changelogs/unreleased/epic_boards_epic_list.yml
new file mode 100644
index 00000000000..00cd47c4f31
--- /dev/null
+++ b/changelogs/unreleased/epic_boards_epic_list.yml
@@ -0,0 +1,5 @@
+---
+title: Added epic board position database index
+merge_request: 50277
+author:
+type: added
diff --git a/changelogs/unreleased/epic_boards_graphql_lists.yml b/changelogs/unreleased/epic_boards_graphql_lists.yml
new file mode 100644
index 00000000000..47c0887f566
--- /dev/null
+++ b/changelogs/unreleased/epic_boards_graphql_lists.yml
@@ -0,0 +1,5 @@
+---
+title: Add epic board list table
+merge_request: 49728
+author:
+type: added
diff --git a/changelogs/unreleased/eread-improve-badges-ui-text.yml b/changelogs/unreleased/eread-improve-badges-ui-text.yml
new file mode 100644
index 00000000000..15e32dac0e1
--- /dev/null
+++ b/changelogs/unreleased/eread-improve-badges-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Improve badges UI text
+merge_request: 50351
+author:
+type: other
diff --git a/changelogs/unreleased/eread-improve-service-desk-ui-text.yml b/changelogs/unreleased/eread-improve-service-desk-ui-text.yml
new file mode 100644
index 00000000000..fd8bf55ead7
--- /dev/null
+++ b/changelogs/unreleased/eread-improve-service-desk-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Improve service desk UI text
+merge_request: 50407
+author:
+type: other
diff --git a/changelogs/unreleased/expose-resolved_at-via-api.yml b/changelogs/unreleased/expose-resolved_at-via-api.yml
new file mode 100644
index 00000000000..df9904edc6b
--- /dev/null
+++ b/changelogs/unreleased/expose-resolved_at-via-api.yml
@@ -0,0 +1,5 @@
+---
+title: Expose notes resolved_at via API
+merge_request: 49821
+author: Lee Tickett
+type: added
diff --git a/changelogs/unreleased/extend-ci-minutes-reset-window.yml b/changelogs/unreleased/extend-ci-minutes-reset-window.yml
new file mode 100644
index 00000000000..1223c8e04c2
--- /dev/null
+++ b/changelogs/unreleased/extend-ci-minutes-reset-window.yml
@@ -0,0 +1,5 @@
+---
+title: Spread monthly CI minutes reset from 8 to 24 hours
+merge_request: 51084
+author:
+type: performance
diff --git a/changelogs/unreleased/feat-flag-copy-change.yml b/changelogs/unreleased/feat-flag-copy-change.yml
new file mode 100644
index 00000000000..48994845ee1
--- /dev/null
+++ b/changelogs/unreleased/feat-flag-copy-change.yml
@@ -0,0 +1,5 @@
+---
+title: Update copy on Feature Flags List view to be more descriptive for users
+merge_request: 50813
+author: Sarah Rosenshine
+type: other
diff --git a/changelogs/unreleased/feature-visibility-mismatch-warning.yml b/changelogs/unreleased/feature-visibility-mismatch-warning.yml
new file mode 100644
index 00000000000..a7c24a737f4
--- /dev/null
+++ b/changelogs/unreleased/feature-visibility-mismatch-warning.yml
@@ -0,0 +1,5 @@
+---
+title: Add visibility mismatch warning to the branch chooser
+merge_request: 51671
+author:
+type: changed
diff --git a/changelogs/unreleased/ff-enable-ci-vis-by_-default.yml b/changelogs/unreleased/ff-enable-ci-vis-by_-default.yml
new file mode 100644
index 00000000000..8ef535f3e4f
--- /dev/null
+++ b/changelogs/unreleased/ff-enable-ci-vis-by_-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable CI visualization by default
+merge_request: 51701
+author:
+type: added
diff --git a/changelogs/unreleased/fix-500-settings-when-repository-does-not-exist.yml b/changelogs/unreleased/fix-500-settings-when-repository-does-not-exist.yml
new file mode 100644
index 00000000000..ea347ece1af
--- /dev/null
+++ b/changelogs/unreleased/fix-500-settings-when-repository-does-not-exist.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 500 error on repository settings access when repository is empty
+merge_request: 50844
+author: Diego Louzán
+type: fixed
diff --git a/changelogs/unreleased/fix-abuse-reports-contains-html.yml b/changelogs/unreleased/fix-abuse-reports-contains-html.yml
new file mode 100644
index 00000000000..9d201cf296d
--- /dev/null
+++ b/changelogs/unreleased/fix-abuse-reports-contains-html.yml
@@ -0,0 +1,5 @@
+---
+title: Fix abuse reports contains html and does not show repoter
+merge_request: 50983
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-admin-project-overview-badge-alignment.yml b/changelogs/unreleased/fix-admin-project-overview-badge-alignment.yml
new file mode 100644
index 00000000000..f88f11bda54
--- /dev/null
+++ b/changelogs/unreleased/fix-admin-project-overview-badge-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix admin project overview badge alignment
+merge_request: 51066
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-brand_new_project_guidelines.yml b/changelogs/unreleased/fix-brand_new_project_guidelines.yml
new file mode 100644
index 00000000000..e8be2d2da78
--- /dev/null
+++ b/changelogs/unreleased/fix-brand_new_project_guidelines.yml
@@ -0,0 +1,5 @@
+---
+title: New project guidelines are no longer displayed
+merge_request: 50736
+author: Roger Meier
+type: fixed
diff --git a/changelogs/unreleased/fix-casing-of-ci-lint-on-jobs-page.yml b/changelogs/unreleased/fix-casing-of-ci-lint-on-jobs-page.yml
new file mode 100644
index 00000000000..5923c0e0aea
--- /dev/null
+++ b/changelogs/unreleased/fix-casing-of-ci-lint-on-jobs-page.yml
@@ -0,0 +1,5 @@
+---
+title: Rename button "CI lint" to "CI Lint" on jobs page
+merge_request: 50987
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml b/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml
new file mode 100644
index 00000000000..f968a43485f
--- /dev/null
+++ b/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix color of hamburger in dark mode
+merge_request: 51168
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-identicon-dark-mode.yml b/changelogs/unreleased/fix-identicon-dark-mode.yml
new file mode 100644
index 00000000000..98e2e59aa3b
--- /dev/null
+++ b/changelogs/unreleased/fix-identicon-dark-mode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix identicon text color in dark mode
+merge_request: 49785
+author: "@yo"
+type: fixed
diff --git a/changelogs/unreleased/fix-overflowing-branch-name-on-profile.yml b/changelogs/unreleased/fix-overflowing-branch-name-on-profile.yml
new file mode 100644
index 00000000000..6fce68b4893
--- /dev/null
+++ b/changelogs/unreleased/fix-overflowing-branch-name-on-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Fix branch name overflows in profile activity section
+merge_request: 50975
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-padding-of-user-admin-search-bar.yml b/changelogs/unreleased/fix-padding-of-user-admin-search-bar.yml
new file mode 100644
index 00000000000..90b424de1fc
--- /dev/null
+++ b/changelogs/unreleased/fix-padding-of-user-admin-search-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Fix padding of user admin search bar on mobile
+merge_request: 51170
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-secret-detection-template.yml b/changelogs/unreleased/fix-secret-detection-template.yml
new file mode 100644
index 00000000000..5d189cbc628
--- /dev/null
+++ b/changelogs/unreleased/fix-secret-detection-template.yml
@@ -0,0 +1,5 @@
+---
+title: "Fix script typo in secret detection template causing the detection to be skipped"
+merge_request: 51544
+author: Vicken Simonian @vicken.papaya
+type: fixed
diff --git a/changelogs/unreleased/fj-fix-n-plus-one-in-dashboard-snippets.yml b/changelogs/unreleased/fj-fix-n-plus-one-in-dashboard-snippets.yml
new file mode 100644
index 00000000000..7c2834d0c9f
--- /dev/null
+++ b/changelogs/unreleased/fj-fix-n-plus-one-in-dashboard-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 when rendering snippets in the dashboard
+merge_request: 50569
+author:
+type: performance
diff --git a/changelogs/unreleased/fj-forbid-push-when-snippet-read-only.yml b/changelogs/unreleased/fj-forbid-push-when-snippet-read-only.yml
new file mode 100644
index 00000000000..b6d0b1386fc
--- /dev/null
+++ b/changelogs/unreleased/fj-forbid-push-when-snippet-read-only.yml
@@ -0,0 +1,5 @@
+---
+title: Forbid snippet pushes when repo is read-only
+merge_request: 51318
+author:
+type: fixed
diff --git a/changelogs/unreleased/georgekoltsov-bulk-import-entity-worker.yml b/changelogs/unreleased/georgekoltsov-bulk-import-entity-worker.yml
new file mode 100644
index 00000000000..aea74fe9248
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-bulk-import-entity-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Move Group Migration entities import to individual sidekiq jobs
+merge_request: 50781
+author:
+type: changed
diff --git a/changelogs/unreleased/georgekoltsov-fix-bulk-import-graphql-extractor.yml b/changelogs/unreleased/georgekoltsov-fix-bulk-import-graphql-extractor.yml
new file mode 100644
index 00000000000..1d5b10ff284
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-fix-bulk-import-graphql-extractor.yml
@@ -0,0 +1,5 @@
+---
+title: Update GraphqlExtractor return value to be original hash
+merge_request: 51596
+author:
+type: fixed
diff --git a/changelogs/unreleased/georgekoltsov-limit-extractors-loaders-to-one.yml b/changelogs/unreleased/georgekoltsov-limit-extractors-loaders-to-one.yml
new file mode 100644
index 00000000000..8274cf0d4f9
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-limit-extractors-loaders-to-one.yml
@@ -0,0 +1,5 @@
+---
+title: Limit Group Migration extractors and loaders to 1 per pipeline
+merge_request: 50951
+author:
+type: changed
diff --git a/changelogs/unreleased/georgekoltsov-update-max-import-size-default-value.yml b/changelogs/unreleased/georgekoltsov-update-max-import-size-default-value.yml
new file mode 100644
index 00000000000..274456a8ad6
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-update-max-import-size-default-value.yml
@@ -0,0 +1,5 @@
+---
+title: Update default value of applications_settings.max_import_size to 0
+merge_request: 51229
+author:
+type: other
diff --git a/changelogs/unreleased/gitaly-client-identity.yml b/changelogs/unreleased/gitaly-client-identity.yml
new file mode 100644
index 00000000000..095f367fd07
--- /dev/null
+++ b/changelogs/unreleased/gitaly-client-identity.yml
@@ -0,0 +1,5 @@
+---
+title: Propagate client identity to gitaly
+merge_request: 50161
+author:
+type: other
diff --git a/changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml b/changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml
new file mode 100644
index 00000000000..08b3da1ca48
--- /dev/null
+++ b/changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml
@@ -0,0 +1,5 @@
+---
+title: Don't allow filtering by release tag on groups.
+merge_request: 50457
+author:
+type: fixed
diff --git a/changelogs/unreleased/id-bump-grape-helpers.yml b/changelogs/unreleased/id-bump-grape-helpers.yml
new file mode 100644
index 00000000000..f2b7c2673ac
--- /dev/null
+++ b/changelogs/unreleased/id-bump-grape-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Update grape-path-helpers gem version
+merge_request: 51320
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-net-ldap.yml b/changelogs/unreleased/id-bump-net-ldap.yml
new file mode 100644
index 00000000000..556b20c4309
--- /dev/null
+++ b/changelogs/unreleased/id-bump-net-ldap.yml
@@ -0,0 +1,5 @@
+---
+title: Update net-ldap gem version
+merge_request: 50888
+author:
+type: other
diff --git a/changelogs/unreleased/id-mark-optional_code_owners_sections-as-default.yml b/changelogs/unreleased/id-mark-optional_code_owners_sections-as-default.yml
new file mode 100644
index 00000000000..9f436e991a4
--- /dev/null
+++ b/changelogs/unreleased/id-mark-optional_code_owners_sections-as-default.yml
@@ -0,0 +1,5 @@
+---
+title: Designate optional sections in the codeowners file
+merge_request: 51643
+author:
+type: added
diff --git a/changelogs/unreleased/id-update-factory-bot.yml b/changelogs/unreleased/id-update-factory-bot.yml
new file mode 100644
index 00000000000..3a943237678
--- /dev/null
+++ b/changelogs/unreleased/id-update-factory-bot.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade factory_bot_rails to 6.1.0
+merge_request: 50875
+author:
+type: other
diff --git a/changelogs/unreleased/invisible-captcha-as-application-setting.yml b/changelogs/unreleased/invisible-captcha-as-application-setting.yml
new file mode 100644
index 00000000000..4d9153cfb8a
--- /dev/null
+++ b/changelogs/unreleased/invisible-captcha-as-application-setting.yml
@@ -0,0 +1,5 @@
+---
+title: Add setting to enable Invisible Captcha
+merge_request: 50650
+author:
+type: added
diff --git a/changelogs/unreleased/jdb-juptyer-notebooks-latex-support.yml b/changelogs/unreleased/jdb-juptyer-notebooks-latex-support.yml
new file mode 100644
index 00000000000..0d505c0f33c
--- /dev/null
+++ b/changelogs/unreleased/jdb-juptyer-notebooks-latex-support.yml
@@ -0,0 +1,5 @@
+---
+title: Add LaTeX support for Jupyter Notebooks
+merge_request: 49497
+author:
+type: fixed
diff --git a/changelogs/unreleased/jivanvl-keep-latest-artifact-project-level.yml b/changelogs/unreleased/jivanvl-keep-latest-artifact-project-level.yml
new file mode 100644
index 00000000000..da47ba0311f
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-keep-latest-artifact-project-level.yml
@@ -0,0 +1,5 @@
+---
+title: Add keep latest artifact option for projects
+merge_request: 49256
+author:
+type: added
diff --git a/changelogs/unreleased/jivanvl-remove-graphql-pipeline-analytics.yml b/changelogs/unreleased/jivanvl-remove-graphql-pipeline-analytics.yml
new file mode 100644
index 00000000000..ca3efa64a5e
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-graphql-pipeline-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Update pipeline graphs on CI/CD Analytics page to use GraphQL endpoint
+merge_request: 51504
+author:
+type: changed
diff --git a/changelogs/unreleased/jivanvl-remove-total-duration-ci-cd-analytics.yml b/changelogs/unreleased/jivanvl-remove-total-duration-ci-cd-analytics.yml
new file mode 100644
index 00000000000..0c3cb19a023
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-total-duration-ci-cd-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Remove total_pipeline_duration from project_type
+merge_request: 50093
+author:
+type: changed
diff --git a/changelogs/unreleased/jv-ci-refspec-sha.yml b/changelogs/unreleased/jv-ci-refspec-sha.yml
new file mode 100644
index 00000000000..c51eadb2624
--- /dev/null
+++ b/changelogs/unreleased/jv-ci-refspec-sha.yml
@@ -0,0 +1,5 @@
+---
+title: 'CI: use commit SHA in persistent refspec'
+merge_request: 51208
+author:
+type: performance
diff --git a/changelogs/unreleased/keep_n_int.yml b/changelogs/unreleased/keep_n_int.yml
new file mode 100644
index 00000000000..067308833a6
--- /dev/null
+++ b/changelogs/unreleased/keep_n_int.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure container_expiration_policy keep_n is an integer
+merge_request: 49805
+author: Mathieu Parent
+type: changed
diff --git a/changelogs/unreleased/ld-add-calls-gitaly-to-fields.yml b/changelogs/unreleased/ld-add-calls-gitaly-to-fields.yml
new file mode 100644
index 00000000000..50a46f7de96
--- /dev/null
+++ b/changelogs/unreleased/ld-add-calls-gitaly-to-fields.yml
@@ -0,0 +1,6 @@
+---
+title: Increase the complexity score of GraphQL MergeRequest#approved, MergeRequest#approvalsLeft
+ and Repository#exists fields as they can call Gitaly
+merge_request: 47039
+author:
+type: changed
diff --git a/changelogs/unreleased/ld-fix-typo-on-designs-lfs-notice.yml b/changelogs/unreleased/ld-fix-typo-on-designs-lfs-notice.yml
new file mode 100644
index 00000000000..1c63971a3cf
--- /dev/null
+++ b/changelogs/unreleased/ld-fix-typo-on-designs-lfs-notice.yml
@@ -0,0 +1,5 @@
+---
+title: Fix typo in notice displayed when Design Management requires LFS to be enabled
+merge_request: 51644
+author:
+type: fixed
diff --git a/changelogs/unreleased/lm-add-new-jobs-fields-graphql.yml b/changelogs/unreleased/lm-add-new-jobs-fields-graphql.yml
new file mode 100644
index 00000000000..20220a1d4be
--- /dev/null
+++ b/changelogs/unreleased/lm-add-new-jobs-fields-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Updates graphql gitlab-ci.yml linter implementation
+merge_request: 50664
+author:
+type: changed
diff --git a/changelogs/unreleased/lm-expose-errors-linter.yml b/changelogs/unreleased/lm-expose-errors-linter.yml
new file mode 100644
index 00000000000..20da98f4996
--- /dev/null
+++ b/changelogs/unreleased/lm-expose-errors-linter.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Exposes errors in lint endpoint'
+merge_request: 50891
+author:
+type: changed
diff --git a/changelogs/unreleased/lm-manual-bridge-support.yml b/changelogs/unreleased/lm-manual-bridge-support.yml
new file mode 100644
index 00000000000..eef59db409d
--- /dev/null
+++ b/changelogs/unreleased/lm-manual-bridge-support.yml
@@ -0,0 +1,5 @@
+---
+title: Add manual bridge support to api
+merge_request: 50634
+author:
+type: changed
diff --git a/changelogs/unreleased/lm-update-regex-group-ame.yml b/changelogs/unreleased/lm-update-regex-group-ame.yml
new file mode 100644
index 00000000000..34d0d7acbe0
--- /dev/null
+++ b/changelogs/unreleased/lm-update-regex-group-ame.yml
@@ -0,0 +1,5 @@
+---
+title: Updates regex for group_name to support numbers in job name
+merge_request: 51157
+author:
+type: changed
diff --git a/changelogs/unreleased/lm-update-w-connections-graphql.yml b/changelogs/unreleased/lm-update-w-connections-graphql.yml
new file mode 100644
index 00000000000..f858e50e814
--- /dev/null
+++ b/changelogs/unreleased/lm-update-w-connections-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Update ci config type for GraphQL to use connection_type
+merge_request: 50160
+author:
+type: changed
diff --git a/changelogs/unreleased/lmca-kotlin-native.yml b/changelogs/unreleased/lmca-kotlin-native.yml
new file mode 100644
index 00000000000..2959d0d95c7
--- /dev/null
+++ b/changelogs/unreleased/lmca-kotlin-native.yml
@@ -0,0 +1,5 @@
+---
+title: Project Template for Kotlin native
+merge_request: 50162
+author:
+type: added
diff --git a/changelogs/unreleased/lower-allocations-nav.yml b/changelogs/unreleased/lower-allocations-nav.yml
new file mode 100644
index 00000000000..f9ea2a20073
--- /dev/null
+++ b/changelogs/unreleased/lower-allocations-nav.yml
@@ -0,0 +1,5 @@
+---
+title: Lower allocations when building nav
+merge_request: 51628
+author:
+type: performance
diff --git a/changelogs/unreleased/lower-explore-pages.yml b/changelogs/unreleased/lower-explore-pages.yml
new file mode 100644
index 00000000000..222ab9461d3
--- /dev/null
+++ b/changelogs/unreleased/lower-explore-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Lower /explore page limit
+merge_request: 50233
+author:
+type: performance
diff --git a/changelogs/unreleased/maintenance-fast-mersenne-twister.yml b/changelogs/unreleased/maintenance-fast-mersenne-twister.yml
new file mode 100644
index 00000000000..1fb389e333b
--- /dev/null
+++ b/changelogs/unreleased/maintenance-fast-mersenne-twister.yml
@@ -0,0 +1,5 @@
+---
+title: Switch to 2x faster PRNG
+merge_request: 50811
+author:
+type: performance
diff --git a/changelogs/unreleased/make-todo-filter-sort-input-full-width-on-mobile.yml b/changelogs/unreleased/make-todo-filter-sort-input-full-width-on-mobile.yml
new file mode 100644
index 00000000000..45e2421b0c7
--- /dev/null
+++ b/changelogs/unreleased/make-todo-filter-sort-input-full-width-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Make todo filter sort input full width on mobile
+merge_request: 51171
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/mattkasa-downloadable-artifacts.yml b/changelogs/unreleased/mattkasa-downloadable-artifacts.yml
new file mode 100644
index 00000000000..db7912f0c38
--- /dev/null
+++ b/changelogs/unreleased/mattkasa-downloadable-artifacts.yml
@@ -0,0 +1,5 @@
+---
+title: Add artifacts:public boolean
+merge_request: 49775
+author:
+type: added
diff --git a/changelogs/unreleased/mc-backstage-create-artifact-expiry-backfill-migration.yml b/changelogs/unreleased/mc-backstage-create-artifact-expiry-backfill-migration.yml
new file mode 100644
index 00000000000..04c0a8dd3fb
--- /dev/null
+++ b/changelogs/unreleased/mc-backstage-create-artifact-expiry-backfill-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Backfill artifact expiry date.
+merge_request: 47723
+author:
+type: other
diff --git a/changelogs/unreleased/mc-feature-associate-restarted-pipeline-triggerer.yml b/changelogs/unreleased/mc-feature-associate-restarted-pipeline-triggerer.yml
new file mode 100644
index 00000000000..9fa9e0312f6
--- /dev/null
+++ b/changelogs/unreleased/mc-feature-associate-restarted-pipeline-triggerer.yml
@@ -0,0 +1,5 @@
+---
+title: When retrying jobs associate subsequent jobs with triggering user.
+merge_request: 49833
+author:
+type: changed
diff --git a/changelogs/unreleased/mjang-MR-approval-instance-level.yml b/changelogs/unreleased/mjang-MR-approval-instance-level.yml
new file mode 100644
index 00000000000..b0b9c73a221
--- /dev/null
+++ b/changelogs/unreleased/mjang-MR-approval-instance-level.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 49871
+author:
+type: other
diff --git a/changelogs/unreleased/mk-add-repo-checksum-task.yml b/changelogs/unreleased/mk-add-repo-checksum-task.yml
new file mode 100644
index 00000000000..8e8bf57bc60
--- /dev/null
+++ b/changelogs/unreleased/mk-add-repo-checksum-task.yml
@@ -0,0 +1,5 @@
+---
+title: Add rake gitlab:git:checksum_projects
+merge_request: 49965
+author:
+type: added
diff --git a/changelogs/unreleased/mk-bump-workhorse.yml b/changelogs/unreleased/mk-bump-workhorse.yml
new file mode 100644
index 00000000000..ed264181f5d
--- /dev/null
+++ b/changelogs/unreleased/mk-bump-workhorse.yml
@@ -0,0 +1,5 @@
+---
+title: Bump workhorse to 8.59.0
+merge_request: 51329
+author:
+type: changed
diff --git a/changelogs/unreleased/mk-configurable-sampling-intervals.yml b/changelogs/unreleased/mk-configurable-sampling-intervals.yml
new file mode 100644
index 00000000000..8292062acda
--- /dev/null
+++ b/changelogs/unreleased/mk-configurable-sampling-intervals.yml
@@ -0,0 +1,5 @@
+---
+title: Sampler intervals can now be configured via env vars
+merge_request: 50625
+author:
+type: other
diff --git a/changelogs/unreleased/mk-remove-extra-space.yml b/changelogs/unreleased/mk-remove-extra-space.yml
new file mode 100644
index 00000000000..baef661133b
--- /dev/null
+++ b/changelogs/unreleased/mk-remove-extra-space.yml
@@ -0,0 +1,5 @@
+---
+title: Remove extra space in API 403 Forbidden error message
+merge_request: 50016
+author:
+type: changed
diff --git a/changelogs/unreleased/mo-refactor-pipeline-artifact-coverage.yml b/changelogs/unreleased/mo-refactor-pipeline-artifact-coverage.yml
new file mode 100644
index 00000000000..02fccaaf4ab
--- /dev/null
+++ b/changelogs/unreleased/mo-refactor-pipeline-artifact-coverage.yml
@@ -0,0 +1,5 @@
+---
+title: Rename coverage report sidekiq queue
+merge_request: 50424
+author:
+type: changed
diff --git a/changelogs/unreleased/move_deployment_boards_to_core.yml b/changelogs/unreleased/move_deployment_boards_to_core.yml
new file mode 100644
index 00000000000..a75b9471dcb
--- /dev/null
+++ b/changelogs/unreleased/move_deployment_boards_to_core.yml
@@ -0,0 +1,5 @@
+---
+title: Move deploy boards to Core
+merge_request: 47147
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-remove-column-compliance-frameworks-group_id.yml b/changelogs/unreleased/mw-remove-column-compliance-frameworks-group_id.yml
new file mode 100644
index 00000000000..3c1f095d60e
--- /dev/null
+++ b/changelogs/unreleased/mw-remove-column-compliance-frameworks-group_id.yml
@@ -0,0 +1,5 @@
+---
+title: Drop group_id column from compliance_management_frameworks table
+merge_request: 50829
+author:
+type: removed
diff --git a/changelogs/unreleased/mw-replace-dropdown-input-fa-color-with-gray-500.yml b/changelogs/unreleased/mw-replace-dropdown-input-fa-color-with-gray-500.yml
new file mode 100644
index 00000000000..a37d16beb6a
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-dropdown-input-fa-color-with-gray-500.yml
@@ -0,0 +1,5 @@
+---
+title: Replace dropdown-input-fa-color with gray-500
+merge_request: 49213
+author:
+type: changed
diff --git a/changelogs/unreleased/nfriend-fix-release-milestone-order.yml b/changelogs/unreleased/nfriend-fix-release-milestone-order.yml
new file mode 100644
index 00000000000..1c1070ba9f1
--- /dev/null
+++ b/changelogs/unreleased/nfriend-fix-release-milestone-order.yml
@@ -0,0 +1,5 @@
+---
+title: Return release milestones in predictable order
+merge_request: 47700
+author:
+type: fixed
diff --git a/changelogs/unreleased/nfriend-remove-pagination-from-deployment-frequency-api.yml b/changelogs/unreleased/nfriend-remove-pagination-from-deployment-frequency-api.yml
new file mode 100644
index 00000000000..960f04a8741
--- /dev/null
+++ b/changelogs/unreleased/nfriend-remove-pagination-from-deployment-frequency-api.yml
@@ -0,0 +1,5 @@
+---
+title: Remove pagination from Deployment Frequency API endpoint
+merge_request: 51137
+author:
+type: changed
diff --git a/changelogs/unreleased/oauth-pkce.yml b/changelogs/unreleased/oauth-pkce.yml
new file mode 100644
index 00000000000..731df657f5b
--- /dev/null
+++ b/changelogs/unreleased/oauth-pkce.yml
@@ -0,0 +1,5 @@
+---
+title: Enable OAuth PKCE flow
+merge_request: 49756
+author:
+type: added
diff --git a/changelogs/unreleased/optimize-release-page-markdown-rendering.yml b/changelogs/unreleased/optimize-release-page-markdown-rendering.yml
new file mode 100644
index 00000000000..1fb6890fd6a
--- /dev/null
+++ b/changelogs/unreleased/optimize-release-page-markdown-rendering.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce per-page size in release index pages for loading faster
+merge_request: 50934
+author:
+type: performance
diff --git a/changelogs/unreleased/override-mix-blend-mode-tertiary-buttons-dark-mode.yml b/changelogs/unreleased/override-mix-blend-mode-tertiary-buttons-dark-mode.yml
new file mode 100644
index 00000000000..f55f523f96c
--- /dev/null
+++ b/changelogs/unreleased/override-mix-blend-mode-tertiary-buttons-dark-mode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tertiary button color in dark mode
+merge_request: 51349
+author:
+type: fixed
diff --git a/changelogs/unreleased/pages-migration-task.yml b/changelogs/unreleased/pages-migration-task.yml
new file mode 100644
index 00000000000..7038c16bbcf
--- /dev/null
+++ b/changelogs/unreleased/pages-migration-task.yml
@@ -0,0 +1,5 @@
+---
+title: Add rake task for migrating legacy pages storage to zip deployments
+merge_request: 50153
+author:
+type: added
diff --git a/changelogs/unreleased/pb-handle-git-errors-cleanup-refs.yml b/changelogs/unreleased/pb-handle-git-errors-cleanup-refs.yml
new file mode 100644
index 00000000000..f60593b8c5d
--- /dev/null
+++ b/changelogs/unreleased/pb-handle-git-errors-cleanup-refs.yml
@@ -0,0 +1,5 @@
+---
+title: Handle git errors when cleaning up MR refs
+merge_request: 50250
+author:
+type: fixed
diff --git a/changelogs/unreleased/pb-keep-latest-artifact-setting-ui.yml b/changelogs/unreleased/pb-keep-latest-artifact-setting-ui.yml
new file mode 100644
index 00000000000..15f2d403a47
--- /dev/null
+++ b/changelogs/unreleased/pb-keep-latest-artifact-setting-ui.yml
@@ -0,0 +1,5 @@
+---
+title: UI to opt out of keeping the artifacts from the last job at project level.
+merge_request: 49500
+author:
+type: added
diff --git a/changelogs/unreleased/peterhegman-hide-mobile-actions-field-with-no-buttons.yml b/changelogs/unreleased/peterhegman-hide-mobile-actions-field-with-no-buttons.yml
new file mode 100644
index 00000000000..00fb54d0049
--- /dev/null
+++ b/changelogs/unreleased/peterhegman-hide-mobile-actions-field-with-no-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Hide "Actions" label on group members view if no action buttons exist
+merge_request: 50304
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-285635-suggestionAppliedResolvedStatus.yml b/changelogs/unreleased/ph-285635-suggestionAppliedResolvedStatus.yml
new file mode 100644
index 00000000000..0a1e0b8aea4
--- /dev/null
+++ b/changelogs/unreleased/ph-285635-suggestionAppliedResolvedStatus.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed applied message showing before discussion gets resolved
+merge_request: 51605
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-290850-mrStatusBoxPoll.yml b/changelogs/unreleased/ph-290850-mrStatusBoxPoll.yml
new file mode 100644
index 00000000000..76bf9e6cd3e
--- /dev/null
+++ b/changelogs/unreleased/ph-290850-mrStatusBoxPoll.yml
@@ -0,0 +1,5 @@
+---
+title: Update merge request status box without reloading page
+merge_request: 50761
+author:
+type: changed
diff --git a/changelogs/unreleased/pipeline-error-message.yml b/changelogs/unreleased/pipeline-error-message.yml
new file mode 100644
index 00000000000..3999fbacf46
--- /dev/null
+++ b/changelogs/unreleased/pipeline-error-message.yml
@@ -0,0 +1,5 @@
+---
+title: Update pipeline alert text to be more readable
+merge_request: 49575
+author:
+type: other
diff --git a/changelogs/unreleased/pipeline-status-conciseness.yml b/changelogs/unreleased/pipeline-status-conciseness.yml
new file mode 100644
index 00000000000..6958c023caa
--- /dev/null
+++ b/changelogs/unreleased/pipeline-status-conciseness.yml
@@ -0,0 +1,5 @@
+---
+title: More concise pipeline notification emails.
+merge_request: 50405
+author:
+type: changed
diff --git a/changelogs/unreleased/ps-step-3-use-ide-files-change-to-update-clientside-preview.yml b/changelogs/unreleased/ps-step-3-use-ide-files-change-to-update-clientside-preview.yml
new file mode 100644
index 00000000000..51d29f3b65c
--- /dev/null
+++ b/changelogs/unreleased/ps-step-3-use-ide-files-change-to-update-clientside-preview.yml
@@ -0,0 +1,5 @@
+---
+title: Fix over-eagerly updating Web IDE Live Preview
+merge_request: 50255
+author:
+type: fixed
diff --git a/changelogs/unreleased/puma-nakayoshi_fork.yml b/changelogs/unreleased/puma-nakayoshi_fork.yml
new file mode 100644
index 00000000000..f282be7a56f
--- /dev/null
+++ b/changelogs/unreleased/puma-nakayoshi_fork.yml
@@ -0,0 +1,5 @@
+---
+title: Use Puma `nakayoshi_fork`
+merge_request: 51467
+author:
+type: performance
diff --git a/changelogs/unreleased/qmnguyen0711-731-add-ratelimit-headers-to-rackattack-responses.yml b/changelogs/unreleased/qmnguyen0711-731-add-ratelimit-headers-to-rackattack-responses.yml
new file mode 100644
index 00000000000..41f507092dd
--- /dev/null
+++ b/changelogs/unreleased/qmnguyen0711-731-add-ratelimit-headers-to-rackattack-responses.yml
@@ -0,0 +1,5 @@
+---
+title: Add RateLimit-* headers to RackAttack responses
+merge_request: 50833
+author: adam-moss
+type: fixed
diff --git a/changelogs/unreleased/remove-ci_pipelines_for_merge_request_finder_new_cte-feature-flag.yml b/changelogs/unreleased/remove-ci_pipelines_for_merge_request_finder_new_cte-feature-flag.yml
new file mode 100644
index 00000000000..06fdd8af084
--- /dev/null
+++ b/changelogs/unreleased/remove-ci_pipelines_for_merge_request_finder_new_cte-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Improve the database query performance on the pipeline loading in merge requests
+merge_request: 50818
+author:
+type: performance
diff --git a/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml b/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml
new file mode 100644
index 00000000000..6edfa7c9713
--- /dev/null
+++ b/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml
@@ -0,0 +1,5 @@
+---
+title: Add skipped status to deployments
+merge_request: 51068
+author:
+type: added
diff --git a/changelogs/unreleased/remove-group-release-filter.yml b/changelogs/unreleased/remove-group-release-filter.yml
new file mode 100644
index 00000000000..9625d5fe934
--- /dev/null
+++ b/changelogs/unreleased/remove-group-release-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Hide inoperable group search Releases filter
+merge_request: 50010
+author:
+type: fixed
diff --git a/changelogs/unreleased/remove-tmp-emails-index.yml b/changelogs/unreleased/remove-tmp-emails-index.yml
new file mode 100644
index 00000000000..55eeca9ad2d
--- /dev/null
+++ b/changelogs/unreleased/remove-tmp-emails-index.yml
@@ -0,0 +1,5 @@
+---
+title: Remove tmp_index_for_email_unconfirmation_migration index in the emails table
+merge_request: 50981
+author:
+type: other
diff --git a/changelogs/unreleased/rename-backlog-list-to-open-in-backend.yml b/changelogs/unreleased/rename-backlog-list-to-open-in-backend.yml
new file mode 100644
index 00000000000..70a4ed3e093
--- /dev/null
+++ b/changelogs/unreleased/rename-backlog-list-to-open-in-backend.yml
@@ -0,0 +1,5 @@
+---
+title: Rename Backlog list to Open in issue boards
+merge_request: 51562
+author:
+type: fixed
diff --git a/changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml b/changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml
new file mode 100644
index 00000000000..7878397fff9
--- /dev/null
+++ b/changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml
@@ -0,0 +1,5 @@
+---
+title: Update the DAST latest template to run when configured even if the user doesn't have sufficient permission
+merge_request: 51279
+author:
+type: changed
diff --git a/changelogs/unreleased/secret-detection-no-run-on-tag.yml b/changelogs/unreleased/secret-detection-no-run-on-tag.yml
new file mode 100644
index 00000000000..f9de2c7a826
--- /dev/null
+++ b/changelogs/unreleased/secret-detection-no-run-on-tag.yml
@@ -0,0 +1,5 @@
+---
+title: Skip secret_detection on tags
+merge_request: 51129
+author:
+type: changed
diff --git a/changelogs/unreleased/security-workhorse-prometheus.yml b/changelogs/unreleased/security-workhorse-prometheus.yml
new file mode 100644
index 00000000000..ab731831033
--- /dev/null
+++ b/changelogs/unreleased/security-workhorse-prometheus.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Workhorse to 8.58.2
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/selhorn-cleanup-uistrings-okr.yml b/changelogs/unreleased/selhorn-cleanup-uistrings-okr.yml
new file mode 100644
index 00000000000..c417ad966c5
--- /dev/null
+++ b/changelogs/unreleased/selhorn-cleanup-uistrings-okr.yml
@@ -0,0 +1,5 @@
+---
+title: Updated link text to match style guidelines
+merge_request: 50555
+author:
+type: other
diff --git a/changelogs/unreleased/selhorn-runner-lowercase-2.yml b/changelogs/unreleased/selhorn-runner-lowercase-2.yml
new file mode 100644
index 00000000000..6b4e6b7a591
--- /dev/null
+++ b/changelogs/unreleased/selhorn-runner-lowercase-2.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to make runner lowercase
+merge_request: 50477
+author:
+type: other
diff --git a/changelogs/unreleased/selhorn-runner-settings-okr.yml b/changelogs/unreleased/selhorn-runner-settings-okr.yml
new file mode 100644
index 00000000000..893f89c4e34
--- /dev/null
+++ b/changelogs/unreleased/selhorn-runner-settings-okr.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 50403
+author:
+type: other
diff --git a/changelogs/unreleased/sh-accelerate-s3-copy.yml b/changelogs/unreleased/sh-accelerate-s3-copy.yml
new file mode 100644
index 00000000000..4e8a35edeb2
--- /dev/null
+++ b/changelogs/unreleased/sh-accelerate-s3-copy.yml
@@ -0,0 +1,5 @@
+---
+title: Fix large S3 uploads failing to finalize
+merge_request: 50922
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-cache-license-data.yml b/changelogs/unreleased/sh-cache-license-data.yml
new file mode 100644
index 00000000000..b1683bdc0ee
--- /dev/null
+++ b/changelogs/unreleased/sh-cache-license-data.yml
@@ -0,0 +1,5 @@
+---
+title: Cache license data in a process-memory cache
+merge_request: 50318
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-disable-rebase-on-conflicts.yml b/changelogs/unreleased/sh-disable-rebase-on-conflicts.yml
new file mode 100644
index 00000000000..c0514929d2a
--- /dev/null
+++ b/changelogs/unreleased/sh-disable-rebase-on-conflicts.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent rebase from being run in quick action when there are conflicts
+merge_request: 51243
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-nplus-one-graphql-group-issues.yml b/changelogs/unreleased/sh-fix-nplus-one-graphql-group-issues.yml
new file mode 100644
index 00000000000..6f57234bb7b
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-nplus-one-graphql-group-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 queries with loading group issues with GraphQL
+merge_request: 50328
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-quick-action-rebase.yml b/changelogs/unreleased/sh-quick-action-rebase.yml
new file mode 100644
index 00000000000..a790d15228a
--- /dev/null
+++ b/changelogs/unreleased/sh-quick-action-rebase.yml
@@ -0,0 +1,5 @@
+---
+title: Add a quick action for /rebase
+merge_request: 49800
+author:
+type: added
diff --git a/changelogs/unreleased/sh-rebase-quick-action-feedback.yml b/changelogs/unreleased/sh-rebase-quick-action-feedback.yml
new file mode 100644
index 00000000000..288bd1f2315
--- /dev/null
+++ b/changelogs/unreleased/sh-rebase-quick-action-feedback.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid 409 StaleObjectError errors with /rebase
+merge_request: 50719
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-lfs-chunked-encoding-feature-flag.yml b/changelogs/unreleased/sh-remove-lfs-chunked-encoding-feature-flag.yml
new file mode 100644
index 00000000000..f39b7061925
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-lfs-chunked-encoding-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove lfs_chunked_encoding feature flag
+merge_request: 50557
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-upgrade-grape-1-5-0.yml b/changelogs/unreleased/sh-upgrade-grape-1-5-0.yml
new file mode 100644
index 00000000000..d0373cd8cc9
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-grape-1-5-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade to Grape v1.5.0
+merge_request: 44554
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-upgrade-webrick-1-6-1.yml b/changelogs/unreleased/sh-upgrade-webrick-1-6-1.yml
new file mode 100644
index 00000000000..72d6d9c9428
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-webrick-1-6-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update WEBrick to v1.6.1
+merge_request: 50720
+author:
+type: security
diff --git a/changelogs/unreleased/shl-267553-remove-pat-creation-api-feature-flag.yml b/changelogs/unreleased/shl-267553-remove-pat-creation-api-feature-flag.yml
new file mode 100644
index 00000000000..2762b4964da
--- /dev/null
+++ b/changelogs/unreleased/shl-267553-remove-pat-creation-api-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability for admins to create PAT for other users via API
+merge_request: 49222
+author:
+type: added
diff --git a/changelogs/unreleased/ss-copy-clipboard-email.yml b/changelogs/unreleased/ss-copy-clipboard-email.yml
new file mode 100644
index 00000000000..d366f716d40
--- /dev/null
+++ b/changelogs/unreleased/ss-copy-clipboard-email.yml
@@ -0,0 +1,5 @@
+---
+title: Add copy email to issue sidebar
+merge_request: 50127
+author:
+type: added
diff --git a/changelogs/unreleased/state-lock-delete-validation.yml b/changelogs/unreleased/state-lock-delete-validation.yml
new file mode 100644
index 00000000000..eb4c8337bf2
--- /dev/null
+++ b/changelogs/unreleased/state-lock-delete-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent locked Terraform states from being deleted
+merge_request: 50798
+author:
+type: changed
diff --git a/changelogs/unreleased/strip-newline-from-commit-description-on-project-overview.yml b/changelogs/unreleased/strip-newline-from-commit-description-on-project-overview.yml
new file mode 100644
index 00000000000..b276de09879
--- /dev/null
+++ b/changelogs/unreleased/strip-newline-from-commit-description-on-project-overview.yml
@@ -0,0 +1,5 @@
+---
+title: Strip newline from commit description on project overview
+merge_request: 51099
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/sy-remove-alerts-service.yml b/changelogs/unreleased/sy-remove-alerts-service.yml
new file mode 100644
index 00000000000..0ca8f108a38
--- /dev/null
+++ b/changelogs/unreleased/sy-remove-alerts-service.yml
@@ -0,0 +1,5 @@
+---
+title: Remove deprecated generic alert integration in favor of HTTP Integrations
+merge_request: 50913
+author:
+type: removed
diff --git a/changelogs/unreleased/terraform-0-14-cache.yml b/changelogs/unreleased/terraform-0-14-cache.yml
new file mode 100644
index 00000000000..af937293768
--- /dev/null
+++ b/changelogs/unreleased/terraform-0-14-cache.yml
@@ -0,0 +1,5 @@
+---
+title: Update Terraform Pipline templaes to support 0.14 lockfile cache
+merge_request: 50647
+author: Aurelian Shuttleworth
+type: fixed
diff --git a/changelogs/unreleased/tr-metric-image-delete.yml b/changelogs/unreleased/tr-metric-image-delete.yml
new file mode 100644
index 00000000000..a10625297ff
--- /dev/null
+++ b/changelogs/unreleased/tr-metric-image-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Add delete metric image REST API endpoint
+merge_request: 50043
+author:
+type: added
diff --git a/changelogs/unreleased/track-ci-template-usage-by-default.yml b/changelogs/unreleased/track-ci-template-usage-by-default.yml
new file mode 100644
index 00000000000..64d08d7aa51
--- /dev/null
+++ b/changelogs/unreleased/track-ci-template-usage-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Instrument CI template usage across projects
+merge_request: 51391
+author:
+type: added
diff --git a/changelogs/unreleased/unify-nuget-auth-1.yml b/changelogs/unreleased/unify-nuget-auth-1.yml
new file mode 100644
index 00000000000..e306f99994a
--- /dev/null
+++ b/changelogs/unreleased/unify-nuget-auth-1.yml
@@ -0,0 +1,6 @@
+---
+title: Add a new Ruby API for specifying allowed authentication mechanisms
+ for REST API endpoints
+merge_request: 38627
+author: Ethan Reesor (@firelizzard)
+type: other
diff --git a/changelogs/unreleased/unify-nuget-auth-2.yml b/changelogs/unreleased/unify-nuget-auth-2.yml
new file mode 100644
index 00000000000..862111dc1a6
--- /dev/null
+++ b/changelogs/unreleased/unify-nuget-auth-2.yml
@@ -0,0 +1,6 @@
+---
+title: The NuGet endpoints will no longer ignore an invalid username when a personal
+ access token or deploy token is passed via HTTP Basic authentication
+merge_request: 38627
+author: Ethan Reesor (@firelizzard)
+type: security
diff --git a/changelogs/unreleased/update-cluster-applications-to-0-37-0.yml b/changelogs/unreleased/update-cluster-applications-to-0-37-0.yml
new file mode 100644
index 00000000000..125b5dcaac4
--- /dev/null
+++ b/changelogs/unreleased/update-cluster-applications-to-0-37-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update cluster-applications to v0.37.0
+merge_request: 50548
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-dotnet-pj-archive.yml b/changelogs/unreleased/update-dotnet-pj-archive.yml
new file mode 100644
index 00000000000..c54aba4dde1
--- /dev/null
+++ b/changelogs/unreleased/update-dotnet-pj-archive.yml
@@ -0,0 +1,5 @@
+---
+title: Update .net Project Template Archive
+merge_request: 50321
+author:
+type: changed
diff --git a/changelogs/unreleased/update-express-pj-archive.yml b/changelogs/unreleased/update-express-pj-archive.yml
new file mode 100644
index 00000000000..a3655054350
--- /dev/null
+++ b/changelogs/unreleased/update-express-pj-archive.yml
@@ -0,0 +1,5 @@
+---
+title: Updated Express Project Template archive
+merge_request: 50326
+author:
+type: changed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-24-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-24-0.yml
new file mode 100644
index 00000000000..ce95e0400d4
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-24-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.24.0
+merge_request: 50377
+author:
+type: other
diff --git a/changelogs/unreleased/update-knative-for-helm-3.yml b/changelogs/unreleased/update-knative-for-helm-3.yml
new file mode 100644
index 00000000000..bf8abaaf26c
--- /dev/null
+++ b/changelogs/unreleased/update-knative-for-helm-3.yml
@@ -0,0 +1,5 @@
+---
+title: Fix installation of Knative under Helm 3
+merge_request: 49843
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-puma-to-v-5.yml b/changelogs/unreleased/update-puma-to-v-5.yml
new file mode 100644
index 00000000000..fa80a47718f
--- /dev/null
+++ b/changelogs/unreleased/update-puma-to-v-5.yml
@@ -0,0 +1,5 @@
+---
+title: Update puma & puma_worker_killer to upstream
+merge_request: 48897
+author:
+type: changed
diff --git a/changelogs/unreleased/update-rails-pj-archive.yml b/changelogs/unreleased/update-rails-pj-archive.yml
new file mode 100644
index 00000000000..3ee7495f797
--- /dev/null
+++ b/changelogs/unreleased/update-rails-pj-archive.yml
@@ -0,0 +1,5 @@
+---
+title: Update Rails Project Template archive
+merge_request: 50325
+author:
+type: changed
diff --git a/changelogs/unreleased/update-toast-position-set-status.yml b/changelogs/unreleased/update-toast-position-set-status.yml
new file mode 100644
index 00000000000..c833b5e228f
--- /dev/null
+++ b/changelogs/unreleased/update-toast-position-set-status.yml
@@ -0,0 +1,5 @@
+---
+title: Update toast position on set status
+merge_request: 50886
+author:
+type: fixed
diff --git a/changelogs/unreleased/upgrade-codequality-0-85-19.yml b/changelogs/unreleased/upgrade-codequality-0-85-19.yml
new file mode 100644
index 00000000000..ff6e56d6615
--- /dev/null
+++ b/changelogs/unreleased/upgrade-codequality-0-85-19.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade CodeQuality version in CI template to 0.85.19
+merge_request: 50118
+author:
+type: changed
diff --git a/changelogs/unreleased/use-dynamic-import-for-gapi.yml b/changelogs/unreleased/use-dynamic-import-for-gapi.yml
new file mode 100644
index 00000000000..811dfd7db67
--- /dev/null
+++ b/changelogs/unreleased/use-dynamic-import-for-gapi.yml
@@ -0,0 +1,5 @@
+---
+title: Dynamically load gapi on GKE cluster creation pages
+merge_request: 49512
+author:
+type: other
diff --git a/changelogs/unreleased/use-git-packages-from-buster-on-build-qa-image.yml b/changelogs/unreleased/use-git-packages-from-buster-on-build-qa-image.yml
new file mode 100644
index 00000000000..061b36021f3
--- /dev/null
+++ b/changelogs/unreleased/use-git-packages-from-buster-on-build-qa-image.yml
@@ -0,0 +1,5 @@
+---
+title: Use git packages from buster on build-qa-image
+merge_request: 50867
+author: Takuya Noguchi @tnir
+type: other
diff --git a/changelogs/unreleased/versionless-package-api-option.yml b/changelogs/unreleased/versionless-package-api-option.yml
new file mode 100644
index 00000000000..c929fe8c337
--- /dev/null
+++ b/changelogs/unreleased/versionless-package-api-option.yml
@@ -0,0 +1,5 @@
+---
+title: Add include_versionless param to the Package API
+merge_request: 50669
+author:
+type: added
diff --git a/changelogs/unreleased/webide-markdown-center.yml b/changelogs/unreleased/webide-markdown-center.yml
new file mode 100644
index 00000000000..095f6a81251
--- /dev/null
+++ b/changelogs/unreleased/webide-markdown-center.yml
@@ -0,0 +1,5 @@
+---
+title: Centered Markdown Preview in Web IDE with a set max width to limit the container size
+merge_request: 50291
+author: Mehul Sharma
+type: other
diff --git a/changelogs/unreleased/wiki-header-spacing.yml b/changelogs/unreleased/wiki-header-spacing.yml
new file mode 100644
index 00000000000..032332aa9c1
--- /dev/null
+++ b/changelogs/unreleased/wiki-header-spacing.yml
@@ -0,0 +1,5 @@
+---
+title: Standardize page title styles on all wiki pages
+merge_request: 49777
+author:
+type: changed
diff --git a/changelogs/unreleased/yo-align-no-schedules.yml b/changelogs/unreleased/yo-align-no-schedules.yml
new file mode 100644
index 00000000000..ac94361d233
--- /dev/null
+++ b/changelogs/unreleased/yo-align-no-schedules.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-mt-3 to no schedules nothing-here-block
+merge_request: 51551
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge-ci.yml b/changelogs/unreleased/yo-gl-badge-ci.yml
new file mode 100644
index 00000000000..811ed02880e
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge-ci.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge to CI badges
+merge_request: 51547
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge-runners.yml b/changelogs/unreleased/yo-gl-badge-runners.yml
new file mode 100644
index 00000000000..685e73c346b
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge-runners.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge to CI runners
+merge_request: 51548
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge.yml b/changelogs/unreleased/yo-gl-badge.yml
new file mode 100644
index 00000000000..0c214026b0c
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge to members list badges
+merge_request: 51546
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-feature-highlight.yml b/changelogs/unreleased/yo-gl-button-feature-highlight.yml
new file mode 100644
index 00000000000..8e0b9ad6fe2
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-feature-highlight.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button to dismiss feature highlight button
+merge_request: 51555
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-jaegar.yml b/changelogs/unreleased/yo-gl-button-jaegar.yml
new file mode 100644
index 00000000000..4b82ec7953c
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-jaegar.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button to Add Jaeger URL
+merge_request: 51553
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-members.yml b/changelogs/unreleased/yo-gl-button-members.yml
new file mode 100644
index 00000000000..5d67ad6b11f
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-members.yml
@@ -0,0 +1,5 @@
+---
+title: Update to new GitLab UI button in members invite page
+merge_request: 51300
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-master-patch-07160.yml b/changelogs/unreleased/yo-master-patch-07160.yml
new file mode 100644
index 00000000000..de1a072869d
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-07160.yml
@@ -0,0 +1,5 @@
+---
+title: Add margin to user chat settings
+merge_request: 51282
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-master-patch-19353.yml b/changelogs/unreleased/yo-master-patch-19353.yml
new file mode 100644
index 00000000000..b12133fdb9c
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-19353.yml
@@ -0,0 +1,5 @@
+---
+title: Update canary(next) badge style with new GitLab UI
+merge_request: 50965
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-master-patch-32789.yml b/changelogs/unreleased/yo-master-patch-32789.yml
new file mode 100644
index 00000000000..fe5291eaffa
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-32789.yml
@@ -0,0 +1,5 @@
+---
+title: Fix slack application helper card
+merge_request: 51034
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-master-patch-49524.yml b/changelogs/unreleased/yo-master-patch-49524.yml
new file mode 100644
index 00000000000..c857ea6e7ee
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-49524.yml
@@ -0,0 +1,5 @@
+---
+title: Add space and helper to the group members page
+merge_request: 50954
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/yo-master-patch-52337.yml b/changelogs/unreleased/yo-master-patch-52337.yml
new file mode 100644
index 00000000000..01578c618e2
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-52337.yml
@@ -0,0 +1,5 @@
+---
+title: Update toggle button in repo general settings
+merge_request: 51036
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-master-patch-63367.yml b/changelogs/unreleased/yo-master-patch-63367.yml
new file mode 100644
index 00000000000..25a8d860b08
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-63367.yml
@@ -0,0 +1,5 @@
+---
+title: Fix webhook badge color in darkmode
+merge_request: 50943
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-master-patch-66129.yml b/changelogs/unreleased/yo-master-patch-66129.yml
new file mode 100644
index 00000000000..b5aead2b52f
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-66129.yml
@@ -0,0 +1,5 @@
+---
+title: Remove margin top for snippets empty state
+merge_request: 51038
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-master-patch-67232.yml b/changelogs/unreleased/yo-master-patch-67232.yml
new file mode 100644
index 00000000000..f21fb9bd136
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-67232.yml
@@ -0,0 +1,5 @@
+---
+title: Align checkbox in system hooks page in admin
+merge_request: 50958
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-master-patch-74981.yml b/changelogs/unreleased/yo-master-patch-74981.yml
new file mode 100644
index 00000000000..7de75a89d2e
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-74981.yml
@@ -0,0 +1,5 @@
+---
+title: Fix import issues button style
+merge_request: 50969
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-master-patch-80251.yml b/changelogs/unreleased/yo-master-patch-80251.yml
new file mode 100644
index 00000000000..37bd8d7d705
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-80251.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce heading font size in validate CI lint page
+merge_request: 51042
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-master-patch-88070.yml b/changelogs/unreleased/yo-master-patch-88070.yml
new file mode 100644
index 00000000000..e4b3a71b06a
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-88070.yml
@@ -0,0 +1,5 @@
+---
+title: Remove border radius for sidekiq iframe card
+merge_request: 50955
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-move-issue-gl-button.yml b/changelogs/unreleased/yo-move-issue-gl-button.yml
new file mode 100644
index 00000000000..618b1455b8f
--- /dev/null
+++ b/changelogs/unreleased/yo-move-issue-gl-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add `gl-button` to move issue button in issue sidebar
+merge_request: 51285
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-remove-footer-members-list.yml b/changelogs/unreleased/yo-remove-footer-members-list.yml
new file mode 100644
index 00000000000..c0bc317a9af
--- /dev/null
+++ b/changelogs/unreleased/yo-remove-footer-members-list.yml
@@ -0,0 +1,5 @@
+---
+title: Conditionally show card footer in single group page in admin
+merge_request: 51426
+author: Yogi (@yo)
+type: fixed
diff --git a/config/application.rb b/config/application.rb
index 178a5c1d3dd..a8b6bc937cf 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -177,6 +177,7 @@ module Gitlab
config.assets.precompile << "mailers/*.css"
config.assets.precompile << "page_bundles/_mixins_and_variables_and_functions.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"
@@ -186,29 +187,29 @@ module Gitlab
config.assets.precompile << "page_bundles/epics.css"
config.assets.precompile << "page_bundles/error_tracking_details.css"
config.assets.precompile << "page_bundles/error_tracking_index.css"
- config.assets.precompile << "page_bundles/signup.css"
config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "page_bundles/import.css"
+ config.assets.precompile << "page_bundles/incident_management_list.css"
config.assets.precompile << "page_bundles/issues_list.css"
config.assets.precompile << "page_bundles/jira_connect.css"
config.assets.precompile << "page_bundles/jira_connect_users.css"
config.assets.precompile << "page_bundles/merge_conflicts.css"
config.assets.precompile << "page_bundles/merge_requests.css"
config.assets.precompile << "page_bundles/milestone.css"
+ config.assets.precompile << "page_bundles/oncall_schedules.css"
config.assets.precompile << "page_bundles/pipeline.css"
- config.assets.precompile << "page_bundles/pipelines.css"
config.assets.precompile << "page_bundles/pipeline_schedules.css"
+ config.assets.precompile << "page_bundles/pipelines.css"
config.assets.precompile << "page_bundles/productivity_analytics.css"
config.assets.precompile << "page_bundles/profile_two_factor_auth.css"
+ config.assets.precompile << "page_bundles/reports.css"
+ config.assets.precompile << "page_bundles/roadmap.css"
config.assets.precompile << "page_bundles/security_dashboard.css"
+ config.assets.precompile << "page_bundles/signup.css"
config.assets.precompile << "page_bundles/terminal.css"
config.assets.precompile << "page_bundles/todos.css"
- config.assets.precompile << "page_bundles/reports.css"
- config.assets.precompile << "page_bundles/roadmap.css"
config.assets.precompile << "page_bundles/wiki.css"
config.assets.precompile << "page_bundles/xterm.css"
- config.assets.precompile << "page_bundles/alert_management_settings.css"
- config.assets.precompile << "page_bundles/oncall_schedules.css"
config.assets.precompile << "lazy_bundles/cropper.css"
config.assets.precompile << "lazy_bundles/select2.css"
config.assets.precompile << "performance_bar.css"
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index 2b6f8fc51db..805cc3b50a3 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -9,7 +9,6 @@
---
- accessibility_testing
- advanced_deployments
-- analysis
- api
- attack_emulation
- audit_events
@@ -25,7 +24,6 @@
- code_quality
- code_review
- code_testing
-- collection
- compliance_management
- container_host_security
- container_network_security
@@ -83,6 +81,7 @@
- pages
- pipeline_authoring
- planning_analytics
+- privacy_control_center
- product_analytics
- projects
- provision
@@ -112,6 +111,7 @@
- time_tracking
- tracing
- usability_testing
+- usage_ping
- users
- value_stream_management
- vulnerability_database
diff --git a/config/feature_flags/development/cd_skipped_deployment_status.yml b/config/feature_flags/development/cd_skipped_deployment_status.yml
deleted file mode 100644
index 45d9538ebfc..00000000000
--- a/config/feature_flags/development/cd_skipped_deployment_status.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-name: cd_skipped_deployment_status
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46614
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/283884
-milestone: '13.6'
-type: development
-group: group::release
-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
index c2701705616..1d33a162445 100644
--- a/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
+++ b/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292024
milestone: '13.7'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_bridge_dependency_variables.yml b/config/feature_flags/development/ci_bridge_dependency_variables.yml
deleted file mode 100644
index 54670f93601..00000000000
--- a/config/feature_flags/development/ci_bridge_dependency_variables.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_bridge_dependency_variables
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46530
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273734
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_config_visualization_tab.yml b/config/feature_flags/development/ci_config_visualization_tab.yml
index 70e395d83e9..cdc7322b7fd 100644
--- a/config/feature_flags/development/ci_config_visualization_tab.yml
+++ b/config/feature_flags/development/ci_config_visualization_tab.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/290117
milestone: '13.7'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_include_multiple_files_from_project.yml b/config/feature_flags/development/ci_include_multiple_files_from_project.yml
deleted file mode 100644
index a291287bd4f..00000000000
--- a/config/feature_flags/development/ci_include_multiple_files_from_project.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_include_multiple_files_from_project
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45991
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/271560
-milestone: '13.6'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_editor_page.yml b/config/feature_flags/development/ci_pipeline_editor_page.yml
index 9870f419842..313126f3444 100644
--- a/config/feature_flags/development/ci_pipeline_editor_page.yml
+++ b/config/feature_flags/development/ci_pipeline_editor_page.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270059
milestone: '13.6'
type: development
group: group::pipeline authoring
-default_enabled: false
+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
index e3be9e7323d..7e2ae1edd34 100644
--- a/config/feature_flags/development/ci_pipeline_open_merge_requests.yml
+++ b/config/feature_flags/development/ci_pipeline_open_merge_requests.yml
@@ -2,6 +2,7 @@
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: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_pipelines_for_merge_request_finder_new_cte.yml b/config/feature_flags/development/ci_pipelines_for_merge_request_finder_new_cte.yml
deleted file mode 100644
index 84d45d51c78..00000000000
--- a/config/feature_flags/development/ci_pipelines_for_merge_request_finder_new_cte.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pipelines_for_merge_request_finder_new_cte
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49083
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/291006
-milestone: '13.7'
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/ci_rules_variables.yml b/config/feature_flags/development/ci_rules_variables.yml
index fdd9de19472..8ea2e21af14 100644
--- a/config/feature_flags/development/ci_rules_variables.yml
+++ b/config/feature_flags/development/ci_rules_variables.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289803
milestone: '13.7'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml b/config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml
deleted file mode 100644
index 6e030c3685a..00000000000
--- a/config/feature_flags/development/ci_seed_block_run_before_workflow_rules.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_seed_block_run_before_workflow_rules
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45674
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270439
-milestone: '13.6'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/collect_package_events_redis.yml b/config/feature_flags/development/collect_package_events_redis.yml
index bc440a44f84..54dcf7c1bc6 100644
--- a/config/feature_flags/development/collect_package_events_redis.yml
+++ b/config/feature_flags/development/collect_package_events_redis.yml
@@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46846
rollout_issue_url:
group: group::package
type: development
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/coverage_fuzzing_mr_widget.yml b/config/feature_flags/development/coverage_fuzzing_mr_widget.yml
deleted file mode 100644
index 589b7073b22..00000000000
--- a/config/feature_flags/development/coverage_fuzzing_mr_widget.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: coverage_fuzzing_mr_widget
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43545
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257839
-milestone: '13.6'
-type: development
-group: group::fuzz testing
-default_enabled: true
diff --git a/config/feature_flags/development/devops_adoption_feature.yml b/config/feature_flags/development/devops_adoption_feature.yml
index 34ade24cbc6..0b643b4e60e 100644
--- a/config/feature_flags/development/devops_adoption_feature.yml
+++ b/config/feature_flags/development/devops_adoption_feature.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46005
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/271568
milestone: '13.6'
type: development
-group: group::analytics
-default_enabled: true
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/diff_check_with_paths_changed_rpc.yml b/config/feature_flags/development/diff_check_with_paths_changed_rpc.yml
deleted file mode 100644
index d67624deb41..00000000000
--- a/config/feature_flags/development/diff_check_with_paths_changed_rpc.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: diff_check_with_paths_changed_rpc
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46116
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/288827
-milestone: '13.7'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/drag_comment_selection.yml b/config/feature_flags/development/drag_comment_selection.yml
new file mode 100644
index 00000000000..a34d2a6231b
--- /dev/null
+++ b/config/feature_flags/development/drag_comment_selection.yml
@@ -0,0 +1,8 @@
+---
+name: drag_comment_selection
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49875
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/293945
+milestone: '13.7'
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/development/feature_flags_legacy_read_only.yml b/config/feature_flags/development/feature_flags_legacy_read_only.yml
deleted file mode 100644
index b960d2df1fa..00000000000
--- a/config/feature_flags/development/feature_flags_legacy_read_only.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: feature_flags_legacy_read_only
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38353
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240985
-milestone: '13.3'
-type: development
-group: group::progressive delivery
-default_enabled: true
diff --git a/config/feature_flags/development/feature_flags_legacy_read_only_override.yml b/config/feature_flags/development/feature_flags_legacy_read_only_override.yml
deleted file mode 100644
index 28438a130f4..00000000000
--- a/config/feature_flags/development/feature_flags_legacy_read_only_override.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: feature_flags_legacy_read_only_override
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40431
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240985
-milestone: '13.4'
-type: development
-group: group::progressive delivery
-default_enabled: false
diff --git a/config/feature_flags/development/github_import_pull_request_reviews.yml b/config/feature_flags/development/github_import_pull_request_reviews.yml
deleted file mode 100644
index 38ff6b65eaa..00000000000
--- a/config/feature_flags/development/github_import_pull_request_reviews.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: github_import_pull_request_reviews
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48632
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289153
-milestone: '13.7'
-type: development
-group: group::import
-default_enabled: true
diff --git a/config/feature_flags/development/gitpod.yml b/config/feature_flags/development/gitpod.yml
deleted file mode 100644
index 616aae4be45..00000000000
--- a/config/feature_flags/development/gitpod.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitpod
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37985
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258206
-milestone: '13.4'
-type: development
-group: group::editor
-default_enabled: true
diff --git a/config/feature_flags/development/gl_tooltips.yml b/config/feature_flags/development/gl_tooltips.yml
new file mode 100644
index 00000000000..22c67019c33
--- /dev/null
+++ b/config/feature_flags/development/gl_tooltips.yml
@@ -0,0 +1,8 @@
+---
+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_logging.yml b/config/feature_flags/development/graphql_logging.yml
index 30f03a60a06..c3615215048 100644
--- a/config/feature_flags/development/graphql_logging.yml
+++ b/config/feature_flags/development/graphql_logging.yml
@@ -1,8 +1,8 @@
---
name: graphql_logging
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27885
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/35579
milestone: '12.0'
type: development
-group:
+group: group::project management
default_enabled: true
diff --git a/config/feature_flags/development/graphql_pipeline_analytics.yml b/config/feature_flags/development/graphql_pipeline_analytics.yml
deleted file mode 100644
index f91475fcbd7..00000000000
--- a/config/feature_flags/development/graphql_pipeline_analytics.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: graphql_pipeline_analytics
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48267
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/290153
-milestone: '13.7'
-type: development
-group: group::continuos integration
-default_enabled: false
diff --git a/config/feature_flags/development/group_members_filtered_search.yml b/config/feature_flags/development/group_members_filtered_search.yml
deleted file mode 100644
index 8a30bdd3d92..00000000000
--- a/config/feature_flags/development/group_members_filtered_search.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: group_members_filtered_search
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48272
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289911
-milestone: '13.7'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml b/config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml
deleted file mode 100644
index 0eda7b1ca4f..00000000000
--- a/config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: hide_jump_to_next_unresolved_in_threads
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37873
-rollout_issue_url:
-milestone: '13.3'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/invisible_captcha.yml b/config/feature_flags/development/invisible_captcha.yml
deleted file mode 100644
index bfe118c1826..00000000000
--- a/config/feature_flags/development/invisible_captcha.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invisible_captcha
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31625
-rollout_issue_url:
-milestone: '12.2'
-type: development
-group: group::acquisition
-default_enabled: false
diff --git a/config/feature_flags/development/jira_connect_full_namespace_sync.yml b/config/feature_flags/development/jira_connect_full_namespace_sync.yml
deleted file mode 100644
index 90fe97be409..00000000000
--- a/config/feature_flags/development/jira_connect_full_namespace_sync.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: jira_connect_full_namespace_sync
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43880
-rollout_issue_url:
-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
new file mode 100644
index 00000000000..8a644d43ba0
--- /dev/null
+++ b/config/feature_flags/development/jira_sync_deployments.yml
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 00000000000..c5925766919
--- /dev/null
+++ b/config/feature_flags/development/jira_sync_feature_flags.yml
@@ -0,0 +1,8 @@
+---
+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/lfs_chunked_encoding.yml b/config/feature_flags/development/lfs_chunked_encoding.yml
deleted file mode 100644
index 92f534d1000..00000000000
--- a/config/feature_flags/development/lfs_chunked_encoding.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: lfs_chunked_encoding
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48269
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285581
-milestone: '13.6'
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/merge_orchestration_service.yml b/config/feature_flags/development/merge_orchestration_service.yml
deleted file mode 100644
index 52de3b6e733..00000000000
--- a/config/feature_flags/development/merge_orchestration_service.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_orchestration_service
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28532
-rollout_issue_url:
-milestone: '12.10'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/merge_ref_auto_sync.yml b/config/feature_flags/development/merge_ref_auto_sync.yml
deleted file mode 100644
index 9fd1eecbe5a..00000000000
--- a/config/feature_flags/development/merge_ref_auto_sync.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_ref_auto_sync
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29569
-rollout_issue_url:
-milestone: '12.1'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/merge_ref_auto_sync_lock.yml b/config/feature_flags/development/merge_ref_auto_sync_lock.yml
deleted file mode 100644
index 3aec2b4e062..00000000000
--- a/config/feature_flags/development/merge_ref_auto_sync_lock.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_ref_auto_sync_lock
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31082
-rollout_issue_url:
-milestone: '12.2'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/mr_commit_neighbor_nav.yml b/config/feature_flags/development/mr_commit_neighbor_nav.yml
deleted file mode 100644
index 1605aaa80e4..00000000000
--- a/config/feature_flags/development/mr_commit_neighbor_nav.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: mr_commit_neighbor_nav
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28596
-rollout_issue_url:
-milestone: '13.0'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/multiple_todos.yml b/config/feature_flags/development/multiple_todos.yml
new file mode 100644
index 00000000000..6ac797b7e5e
--- /dev/null
+++ b/config/feature_flags/development/multiple_todos.yml
@@ -0,0 +1,8 @@
+---
+name: multiple_todos
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47629
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/28355
+milestone: '13.8'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/new_jira_connect_ui.yml b/config/feature_flags/development/new_jira_connect_ui.yml
new file mode 100644
index 00000000000..8783c1ed7fd
--- /dev/null
+++ b/config/feature_flags/development/new_jira_connect_ui.yml
@@ -0,0 +1,8 @@
+---
+name: new_jira_connect_ui
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50692
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/295647
+milestone: '13.8'
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/new_project_level_vsa_backend.yml b/config/feature_flags/development/new_project_level_vsa_backend.yml
deleted file mode 100644
index 988e5e39a03..00000000000
--- a/config/feature_flags/development/new_project_level_vsa_backend.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_project_level_vsa_backend
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282435
-milestone: '13.7'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/non_public_artifacts.yml b/config/feature_flags/development/non_public_artifacts.yml
new file mode 100644
index 00000000000..e2a2fd49df7
--- /dev/null
+++ b/config/feature_flags/development/non_public_artifacts.yml
@@ -0,0 +1,8 @@
+---
+name: non_public_artifacts
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49775
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294503
+milestone: '13.8'
+type: development
+group: group::configure
+default_enabled: false
diff --git a/config/feature_flags/development/optional_code_owners_sections.yml b/config/feature_flags/development/optional_code_owners_sections.yml
new file mode 100644
index 00000000000..a7933f42fc9
--- /dev/null
+++ b/config/feature_flags/development/optional_code_owners_sections.yml
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 00000000000..8712fa4895d
--- /dev/null
+++ b/config/feature_flags/development/packages_and_registries_group_settings.yml
@@ -0,0 +1,8 @@
+---
+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_migration_mark_as_not_deployed.yml b/config/feature_flags/development/pages_migration_mark_as_not_deployed.yml
new file mode 100644
index 00000000000..f8b28785a2d
--- /dev/null
+++ b/config/feature_flags/development/pages_migration_mark_as_not_deployed.yml
@@ -0,0 +1,8 @@
+---
+name: pages_migration_mark_as_not_deployed
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49473
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/295187
+milestone: '13.8'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/pat_creation_api_for_admin.yml b/config/feature_flags/development/pat_creation_api_for_admin.yml
deleted file mode 100644
index 246f7623cc9..00000000000
--- a/config/feature_flags/development/pat_creation_api_for_admin.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: pat_creation_api_for_admin
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45152
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267553
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/reset_integrations.yml b/config/feature_flags/development/reset_integrations.yml
deleted file mode 100644
index 332fbc96ef5..00000000000
--- a/config/feature_flags/development/reset_integrations.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: reset_integrations
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47546
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/283875
-milestone: '13.7'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/restrict_access_to_build_debug_mode.yml b/config/feature_flags/development/restrict_access_to_build_debug_mode.yml
deleted file mode 100644
index 6d195e03842..00000000000
--- a/config/feature_flags/development/restrict_access_to_build_debug_mode.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: restrict_access_to_build_debug_mode
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48932
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292661
-milestone: '13.7'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/reviewer_approval_rules.yml b/config/feature_flags/development/reviewer_approval_rules.yml
index 97181ef2a36..78bc52de5b3 100644
--- a/config/feature_flags/development/reviewer_approval_rules.yml
+++ b/config/feature_flags/development/reviewer_approval_rules.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/293742
milestone: '13.7'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/s3_multithreaded_uploads.yml b/config/feature_flags/development/s3_multithreaded_uploads.yml
new file mode 100644
index 00000000000..cab1925488a
--- /dev/null
+++ b/config/feature_flags/development/s3_multithreaded_uploads.yml
@@ -0,0 +1,8 @@
+---
+name: s3_multithreaded_uploads
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50922
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296772
+milestone: '13.8'
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/search_settings_in_page.yml b/config/feature_flags/development/search_settings_in_page.yml
new file mode 100644
index 00000000000..26db77ebdb7
--- /dev/null
+++ b/config/feature_flags/development/search_settings_in_page.yml
@@ -0,0 +1,8 @@
+---
+name: search_settings_in_page
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50207
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294025
+milestone: '13.7'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/security_on_demand_scans_site_validation.yml b/config/feature_flags/development/security_on_demand_scans_site_validation.yml
index 9085c22b773..bfe02a0bad7 100644
--- a/config/feature_flags/development/security_on_demand_scans_site_validation.yml
+++ b/config/feature_flags/development/security_on_demand_scans_site_validation.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241815
milestone: '13.4'
type: development
group: group::dynamic analysis
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/service_desk_custom_address.yml b/config/feature_flags/development/service_desk_custom_address.yml
deleted file mode 100644
index e7db2f10e2f..00000000000
--- a/config/feature_flags/development/service_desk_custom_address.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: service_desk_custom_address
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284656
-milestone:
-type: development
-group: group::certify
-default_enabled: true
diff --git a/config/feature_flags/development/set_user_availability_status.yml b/config/feature_flags/development/set_user_availability_status.yml
index be3ff522ccc..dd48ddef6d5 100644
--- a/config/feature_flags/development/set_user_availability_status.yml
+++ b/config/feature_flags/development/set_user_availability_status.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281073
milestone: '13.6'
type: development
group: group::optimize
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/show_inherited_labels.yml b/config/feature_flags/development/show_inherited_labels.yml
deleted file mode 100644
index 1ee1daaf0af..00000000000
--- a/config/feature_flags/development/show_inherited_labels.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: show_inherited_labels
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42960
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267547
-milestone: '13.5'
-type: development
-group: group::project management
-default_enabled: true
diff --git a/config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml b/config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml
new file mode 100644
index 00000000000..678a52ee613
--- /dev/null
+++ b/config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml
@@ -0,0 +1,8 @@
+---
+name: skip_dag_manual_and_delayed_jobs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50765
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297240
+milestone: '13.8'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/sourcegraph.yml b/config/feature_flags/development/sourcegraph.yml
new file mode 100644
index 00000000000..12170aec869
--- /dev/null
+++ b/config/feature_flags/development/sourcegraph.yml
@@ -0,0 +1,8 @@
+---
+name: sourcegraph
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16556
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292199
+milestone: '12.5'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/startup_css.yml b/config/feature_flags/development/startup_css.yml
deleted file mode 100644
index 88a1cd77c95..00000000000
--- a/config/feature_flags/development/startup_css.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: startup_css
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39713
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238718
-milestone: '13.3'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/suggestions_custom_commit.yml b/config/feature_flags/development/suggestions_custom_commit.yml
new file mode 100644
index 00000000000..e51e219ee1d
--- /dev/null
+++ b/config/feature_flags/development/suggestions_custom_commit.yml
@@ -0,0 +1,8 @@
+---
+name: suggestions_custom_commit
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297404
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/test_failure_history.yml b/config/feature_flags/development/test_failure_history.yml
deleted file mode 100644
index 4a0424aae9e..00000000000
--- a/config/feature_flags/development/test_failure_history.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: test_failure_history
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45027
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268249
-milestone: '13.6'
-type: development
-group: group::testing
-default_enabled: false
diff --git a/config/feature_flags/development/track_unique_wiki_page_views.yml b/config/feature_flags/development/track_unique_wiki_page_views.yml
index eb2bf1304d9..39d25352e73 100644
--- a/config/feature_flags/development/track_unique_wiki_page_views.yml
+++ b/config/feature_flags/development/track_unique_wiki_page_views.yml
@@ -4,5 +4,5 @@ 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::knowledge
+group: group::editor
default_enabled: true
diff --git a/config/feature_flags/development/unified_diff_components.yml b/config/feature_flags/development/unified_diff_components.yml
index 68a1cd8996f..0176d8c55ba 100644
--- a/config/feature_flags/development/unified_diff_components.yml
+++ b/config/feature_flags/development/unified_diff_components.yml
@@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44974
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268039
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/upload_middleware_jwt_params_handler.yml b/config/feature_flags/development/upload_middleware_jwt_params_handler.yml
deleted file mode 100644
index 60a68005235..00000000000
--- a/config/feature_flags/development/upload_middleware_jwt_params_handler.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: upload_middleware_jwt_params_handler
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33277
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233895
-milestone: '13.4'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_mr_diffs.yml b/config/feature_flags/development/usage_data_i_code_review_mr_diffs.yml
new file mode 100644
index 00000000000..a85ceaf2520
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_mr_diffs.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_mr_diffs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48470
+rollout_issue_url:
+milestone: '13.7'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_mr_single_file_diffs.yml b/config/feature_flags/development/usage_data_i_code_review_mr_single_file_diffs.yml
new file mode 100644
index 00000000000..cc9623f6cf4
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_mr_single_file_diffs.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_mr_single_file_diffs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48470
+rollout_issue_url:
+milestone: '13.7'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_close_mr.yml b/config/feature_flags/development/usage_data_i_code_review_user_close_mr.yml
new file mode 100644
index 00000000000..777914da403
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_close_mr.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_close_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50654
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_create_mr.yml b/config/feature_flags/development/usage_data_i_code_review_user_create_mr.yml
new file mode 100644
index 00000000000..beb211c6f35
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_create_mr.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_create_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50654
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_create_mr_comment.yml b/config/feature_flags/development/usage_data_i_code_review_user_create_mr_comment.yml
new file mode 100644
index 00000000000..1c727263a8e
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_create_mr_comment.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_create_mr_comment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50849
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_create_multiline_mr_comment.yml b/config/feature_flags/development/usage_data_i_code_review_user_create_multiline_mr_comment.yml
new file mode 100644
index 00000000000..4777926d4b1
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_create_multiline_mr_comment.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_create_multiline_mr_comment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51098
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_create_review_note.yml b/config/feature_flags/development/usage_data_i_code_review_user_create_review_note.yml
new file mode 100644
index 00000000000..fdc3b4569ef
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_create_review_note.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_create_review_note
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51521
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_edit_mr_comment.yml b/config/feature_flags/development/usage_data_i_code_review_user_edit_mr_comment.yml
new file mode 100644
index 00000000000..2280cfdd564
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_edit_mr_comment.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_edit_mr_comment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50849
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_edit_multiline_mr_comment.yml b/config/feature_flags/development/usage_data_i_code_review_user_edit_multiline_mr_comment.yml
new file mode 100644
index 00000000000..b4b34b4e166
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_edit_multiline_mr_comment.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_edit_multiline_mr_comment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51098
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_merge_mr.yml b/config/feature_flags/development/usage_data_i_code_review_user_merge_mr.yml
new file mode 100644
index 00000000000..0ef596ac915
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_merge_mr.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_merge_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50654
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_publish_review.yml b/config/feature_flags/development/usage_data_i_code_review_user_publish_review.yml
new file mode 100644
index 00000000000..079ceb023f4
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_publish_review.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_publish_review
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51351
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_remove_mr_comment.yml b/config/feature_flags/development/usage_data_i_code_review_user_remove_mr_comment.yml
new file mode 100644
index 00000000000..c7d462e9243
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_remove_mr_comment.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_remove_mr_comment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50849
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_remove_multiline_mr_comment.yml b/config/feature_flags/development/usage_data_i_code_review_user_remove_multiline_mr_comment.yml
new file mode 100644
index 00000000000..b8ec5984788
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_remove_multiline_mr_comment.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_remove_multiline_mr_comment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51098
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_reopen_mr.yml b/config/feature_flags/development/usage_data_i_code_review_user_reopen_mr.yml
new file mode 100644
index 00000000000..9a5c2ecc26a
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_reopen_mr.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_reopen_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50654
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_single_file_diffs.yml b/config/feature_flags/development/usage_data_i_code_review_user_single_file_diffs.yml
new file mode 100644
index 00000000000..f77b15f9442
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_single_file_diffs.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_single_file_diffs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48470
+rollout_issue_url:
+milestone: '13.7'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_full_code_quality_report_total.yml b/config/feature_flags/development/usage_data_i_testing_full_code_quality_report_total.yml
new file mode 100644
index 00000000000..38bce2529dd
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_full_code_quality_report_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_full_code_quality_report_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49079
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_group_code_coverage_visit_total.yml b/config/feature_flags/development/usage_data_i_testing_group_code_coverage_visit_total.yml
new file mode 100644
index 00000000000..720b94fcf6e
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_group_code_coverage_visit_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_group_code_coverage_visit_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51382
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_metrics_report_widget_total.yml b/config/feature_flags/development/usage_data_i_testing_metrics_report_widget_total.yml
new file mode 100644
index 00000000000..2c086b211ba
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_metrics_report_widget_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_metrics_report_widget_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50790
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_web_performance_widget_total.yml b/config/feature_flags/development/usage_data_i_testing_web_performance_widget_total.yml
new file mode 100644
index 00000000000..6efb6bea040
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_web_performance_widget_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_web_performance_widget_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46746
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_alerts_total_unique_counts.yml b/config/feature_flags/development/usage_data_incident_management_alerts_total_unique_counts.yml
deleted file mode 100644
index 38e94e74399..00000000000
--- a/config/feature_flags/development/usage_data_incident_management_alerts_total_unique_counts.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_incident_management_alerts_total_unique_counts
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48087
-rollout_issue_url:
-milestone: '13.7'
-type: development
-group: group::monitor
-default_enabled: false
diff --git a/config/feature_flags/development/usage_data_incident_management_incidents_total_unique_counts.yml b/config/feature_flags/development/usage_data_incident_management_incidents_total_unique_counts.yml
deleted file mode 100644
index 1bb602730e7..00000000000
--- a/config/feature_flags/development/usage_data_incident_management_incidents_total_unique_counts.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_incident_management_incidents_total_unique_counts
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48087
-rollout_issue_url:
-milestone: '13.7'
-type: development
-group: group::monitor
-default_enabled: false
diff --git a/config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml b/config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml
new file mode 100644
index 00000000000..e11fb0a8b25
--- /dev/null
+++ b/config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_p_terraform_state_api_unique_users
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50224
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::configure
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml b/config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml
new file mode 100644
index 00000000000..306e37ac308
--- /dev/null
+++ b/config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_track_ci_templates_unique_projects
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50481
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296880
+milestone: '13.8'
+type: development
+group: group::configure
+default_enabled: true
diff --git a/config/feature_flags/development/value_stream_analytics_extended_form.yml b/config/feature_flags/development/value_stream_analytics_extended_form.yml
new file mode 100644
index 00000000000..1cdb9111af4
--- /dev/null
+++ b/config/feature_flags/development/value_stream_analytics_extended_form.yml
@@ -0,0 +1,8 @@
+---
+name: value_stream_analytics_extended_form
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50229
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294190
+milestone: '13.7'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/variable_inside_variable.yml b/config/feature_flags/development/variable_inside_variable.yml
new file mode 100644
index 00000000000..1e75576a97a
--- /dev/null
+++ b/config/feature_flags/development/variable_inside_variable.yml
@@ -0,0 +1,8 @@
+---
+name: variable_inside_variable
+introduced_by_url:
+rollout_issue_url:
+milestone: '13.7'
+type: development
+group: group::runner
+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
new file mode 100644
index 00000000000..f6fc810e6f2
--- /dev/null
+++ b/config/feature_flags/development/variables_in_include_section_ci.yml
@@ -0,0 +1,8 @@
+---
+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_2fa_recovery_codes.yml b/config/feature_flags/development/vue_2fa_recovery_codes.yml
deleted file mode 100644
index 7995b00f9ab..00000000000
--- a/config/feature_flags/development/vue_2fa_recovery_codes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: vue_2fa_recovery_codes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49078
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/290113
-milestone: '13.7'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/vue_group_members_list.yml b/config/feature_flags/development/vue_group_members_list.yml
deleted file mode 100644
index d864f904992..00000000000
--- a/config/feature_flags/development/vue_group_members_list.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: vue_group_members_list
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40548
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241194
-milestone: '13.4'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/widget_visibility_polling.yml b/config/feature_flags/development/widget_visibility_polling.yml
deleted file mode 100644
index 3021388b17f..00000000000
--- a/config/feature_flags/development/widget_visibility_polling.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: widget_visibility_polling
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29318
-rollout_issue_url:
-milestone: '12.10'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/wiki.yml b/config/feature_flags/development/wiki.yml
index 5904e6838f3..008852d2c13 100644
--- a/config/feature_flags/development/wiki.yml
+++ b/config/feature_flags/development/wiki.yml
@@ -4,5 +4,5 @@ introduced_by_url:
rollout_issue_url:
milestone:
type: development
-group:
+group: group::editor
default_enabled: true
diff --git a/config/feature_flags/development/wiki_front_matter.yml b/config/feature_flags/development/wiki_front_matter.yml
index 66add349c44..39196440d17 100644
--- a/config/feature_flags/development/wiki_front_matter.yml
+++ b/config/feature_flags/development/wiki_front_matter.yml
@@ -1,8 +1,8 @@
---
name: wiki_front_matter
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27706
rollout_issue_url:
-milestone:
+milestone: '12.10'
type: development
-group:
+group: group::editor
default_enabled: false
diff --git a/config/feature_flags/experiment/ci_syntax_templates_experiment_percentage.yml b/config/feature_flags/experiment/ci_syntax_templates_experiment_percentage.yml
new file mode 100644
index 00000000000..3ed457acce8
--- /dev/null
+++ b/config/feature_flags/experiment/ci_syntax_templates_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: ci_syntax_templates_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48141
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281057
+milestone: '13.8'
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/customize_homepage_experiment_percentage.yml b/config/feature_flags/experiment/customize_homepage_experiment_percentage.yml
new file mode 100644
index 00000000000..eff0d2785eb
--- /dev/null
+++ b/config/feature_flags/experiment/customize_homepage_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: customize_homepage_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39348
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/187
+milestone: '13.4'
+type: experiment
+group: group::expansion
+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
new file mode 100644
index 00000000000..d4a695502f9
--- /dev/null
+++ b/config/feature_flags/experiment/default_to_issues_board_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+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/invite_members_empty_group_version_a_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_empty_group_version_a_experiment_percentage.yml
new file mode 100644
index 00000000000..6f8186a6888
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_empty_group_version_a_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_empty_group_version_a_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45689
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/280
+milestone: '13.6'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml
new file mode 100644
index 00000000000..8b91ec9526c
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_empty_project_version_a_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49588
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262014
+milestone: '13.7'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
new file mode 100644
index 00000000000..6fac63b381c
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+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
+milestone: '13.8'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml
new file mode 100644
index 00000000000..d20cb10fcda
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_version_a_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33210
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/299
+milestone: '13.1'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_version_b_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_version_b_experiment_percentage.yml
new file mode 100644
index 00000000000..069e740ba44
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_version_b_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_version_b_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43900
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/214
+milestone: '13.5'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml b/config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml
new file mode 100644
index 00000000000..33a15e28d44
--- /dev/null
+++ b/config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+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/null_hypothesis.yml b/config/feature_flags/experiment/null_hypothesis.yml
index 716b0711ef1..8ac76809842 100644
--- a/config/feature_flags/experiment/null_hypothesis.yml
+++ b/config/feature_flags/experiment/null_hypothesis.yml
@@ -2,6 +2,7 @@
name: null_hypothesis
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45840
rollout_issue_url:
+milestone: '13.7'
type: experiment
group: group::adoption
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
new file mode 100644
index 00000000000..7a8f3074d96
--- /dev/null
+++ b/config/feature_flags/experiment/onboarding_issues_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 00000000000..beb8e8a21c6
--- /dev/null
+++ b/config/feature_flags/experiment/pipelines_empty_state_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+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/explore_pipeline_status.yml b/config/feature_flags/ops/explore_pipeline_status.yml
new file mode 100644
index 00000000000..ace73a14d0c
--- /dev/null
+++ b/config/feature_flags/ops/explore_pipeline_status.yml
@@ -0,0 +1,8 @@
+---
+name: explore_pipeline_status
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51621
+rollout_issue_url:
+milestone: '13.8'
+type: ops
+group: group::source code
+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
new file mode 100644
index 00000000000..e8133f16072
--- /dev/null
+++ b/config/feature_flags/ops/scalability_ci_fetch_sha.yml
@@ -0,0 +1,8 @@
+---
+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 57788e55f8f..92e7501d49d 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -436,6 +436,9 @@ production: &base
# Remove expired build artifacts
expire_build_artifacts_worker:
cron: "*/7 * * * *"
+ # Remove expired pipeline artifacts
+ ci_pipelines_expire_artifacts_worker:
+ cron: "*/23 * * * *"
# Remove files from object storage
ci_schedule_delete_objects_worker:
cron: "*/16 * * * *"
@@ -477,7 +480,7 @@ production: &base
ee_cron_jobs:
# Schedule snapshots for all devops adoption segments
analytics_devops_adoption_create_all_snapshots_worker:
- cron: 0 0 1 * *
+ cron: 0 4 * * *
# Snapshot active users statistics
historical_data_worker:
@@ -1207,10 +1210,7 @@ production: &base
# yourself, and then update the values here.
# https://docs.gitlab.com/ee/administration/monitoring/prometheus/
prometheus:
- # Do not use `enable` and `listen_address` in any new code, as they are deprecated. Use `server_address` instead.
- # https://gitlab.com/gitlab-org/gitlab/-/issues/227111
- # enable: true
- # listen_address: 'localhost:9090'
+ # enabled: true
# server_address: 'localhost:9090'
## Consul settings
@@ -1499,8 +1499,8 @@ test:
group_base: 'ou=groups,dc=example,dc=com'
admin_group: ''
prometheus:
- enable: true
- listen_address: 'localhost:9090'
+ enabled: true
+ server_address: 'localhost:9090'
staging:
<<: *base
diff --git a/config/helpers/is_eslint.js b/config/helpers/is_eslint.js
index 55ec42e68c1..60528796962 100644
--- a/config/helpers/is_eslint.js
+++ b/config/helpers/is_eslint.js
@@ -1,7 +1,7 @@
/**
* Returns true if the given module is required from eslint
*/
-const isESLint = mod => {
+const isESLint = (mod) => {
let parent = mod.parent;
while (parent) {
diff --git a/config/helpers/vendor_dll_hash.js b/config/helpers/vendor_dll_hash.js
index cfd7be66ad3..2df97e7b95d 100644
--- a/config/helpers/vendor_dll_hash.js
+++ b/config/helpers/vendor_dll_hash.js
@@ -9,13 +9,9 @@ const CACHE_PATHS = [
'./yarn.lock',
];
-const resolvePath = file => path.resolve(__dirname, '../..', file);
-const readFile = file => fs.readFileSync(file);
-const fileHash = buffer =>
- crypto
- .createHash('md5')
- .update(buffer)
- .digest('hex');
+const resolvePath = (file) => path.resolve(__dirname, '../..', file);
+const readFile = (file) => fs.readFileSync(file);
+const fileHash = (buffer) => crypto.createHash('md5').update(buffer).digest('hex');
module.exports = () => {
const fileBuffers = CACHE_PATHS.map(resolvePath).map(readFile);
diff --git a/config/initializers/0_inject_feature_flags.rb b/config/initializers/0_inject_feature_flags.rb
index 74470a6cbfc..5b33b3bb4ea 100644
--- a/config/initializers/0_inject_feature_flags.rb
+++ b/config/initializers/0_inject_feature_flags.rb
@@ -4,42 +4,3 @@
Feature.register_feature_groups
Feature.register_definitions
Feature.register_hot_reloader unless Rails.configuration.cache_classes
-
-# This disallows usage of licensed feature names with the same name
-# as feature flags. This naming collision creates confusion and it was
-# decided to be removed in favor of explicit check.
-# https://gitlab.com/gitlab-org/gitlab/-/issues/259611
-if Gitlab.ee? && Gitlab.dev_or_test_env?
- # These are the names of feature flags that do violate the constraint of
- # being unique to licensed names. These feature flags should be reworked to
- # be "development" with explicit check
- IGNORED_FEATURE_FLAGS = %i[
- swimlanes
- ].to_set
-
- # First, we validate a list of overrides to ensure that these overrides
- # are removed if feature flag is gone
- missing_feature_flags = IGNORED_FEATURE_FLAGS.reject do |feature_flag|
- Feature::Definition.definitions[feature_flag]
- end
-
- if missing_feature_flags.any?
- raise "The following feature flags were added as an override for discovering licensed features. " \
- "Since these feature flags seems to be gone, ensure to remove them from \`IGNORED_FEATURE_FLAGS\` " \
- "in \`#{__FILE__}'`: #{missing_feature_flags.join(", ")}"
- end
-
- # Second, we validate that there's no feature flag under the name as licensed feature
- # flag, to ensure that the name used, is unique
- licensed_features = License::PLANS_BY_FEATURE.keys.select do |licensed_feature_name|
- IGNORED_FEATURE_FLAGS.exclude?(licensed_feature_name) &&
- Feature::Definition.definitions[licensed_feature_name]
- end
-
- if licensed_features.any?
- raise "The following feature flags do use a licensed feature. " \
- "To avoid the confusion between their usage it is disallowed to use feature flag " \
- "with exact the same name as licensed feature name. Use a different name to create " \
- "a distinction: #{licensed_features.join(", ")}"
- end
-end
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 97c0e051f1f..b3ea72fc7e5 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -420,6 +420,9 @@ Settings.cron_jobs['pipeline_schedule_worker']['job_class'] = 'PipelineScheduleW
Settings.cron_jobs['expire_build_artifacts_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['expire_build_artifacts_worker']['cron'] ||= '*/7 * * * *'
Settings.cron_jobs['expire_build_artifacts_worker']['job_class'] = 'ExpireBuildArtifactsWorker'
+Settings.cron_jobs['ci_pipelines_expire_artifacts_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['ci_pipelines_expire_artifacts_worker']['cron'] ||= '*/23 * * * *'
+Settings.cron_jobs['ci_pipelines_expire_artifacts_worker']['job_class'] = 'Ci::PipelineArtifacts::ExpireArtifactsWorker'
Settings.cron_jobs['ci_schedule_delete_objects_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['ci_schedule_delete_objects_worker']['cron'] ||= '*/16 * * * *'
Settings.cron_jobs['ci_schedule_delete_objects_worker']['job_class'] = 'Ci::ScheduleDeleteObjectsCronWorker'
@@ -543,7 +546,7 @@ Settings.cron_jobs['manage_evidence_worker']['job_class'] = 'Releases::ManageEvi
Gitlab.ee do
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['cron'] ||= '0 0 1 * *'
+ Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['cron'] ||= '0 4 * * *'
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['job_class'] = 'Analytics::DevopsAdoption::CreateAllSnapshotsWorker'
Settings.cron_jobs['active_user_count_threshold_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['active_user_count_threshold_worker']['cron'] ||= '0 12 * * *'
@@ -852,6 +855,18 @@ Settings.monitoring.web_exporter['address'] ||= 'localhost'
Settings.monitoring.web_exporter['port'] ||= 8083
#
+# Prometheus settings
+#
+Settings['prometheus'] ||= Settingslogic.new({})
+# TODO: Remove listen_address and enable in GitLab 14.0 and set default value
+# of server_address to be nil and enabled to be false -
+# https://gitlab.com/gitlab-org/gitlab/-/issues/296022
+Settings.prometheus['enable'] ||= false
+Settings.prometheus['listen_address'] ||= nil
+Settings.prometheus['enabled'] = Settings.prometheus['enable'] if Settings.prometheus['enabled'].nil?
+Settings.prometheus['server_address'] ||= Settings.prometheus['listen_address']
+
+#
# Shutdown settings
#
Settings['shutdown'] ||= Settingslogic.new({})
diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb
index b91a4622ce8..a4841a11a00 100644
--- a/config/initializers/8_devise.rb
+++ b/config/initializers/8_devise.rb
@@ -232,7 +232,7 @@ Devise.setup do |config|
end
if Gitlab::Auth::Ldap::Config.enabled?
- Gitlab::Auth::Ldap::Config.providers.each do |provider|
+ Gitlab::Auth::Ldap::Config.available_providers.each do |provider|
ldap_config = Gitlab::Auth::Ldap::Config.new(provider)
config.omniauth(provider, ldap_config.omniauth_options)
end
diff --git a/config/initializers/carrierwave_patch.rb b/config/initializers/carrierwave_patch.rb
index ad3ff36138f..c8c6f75949c 100644
--- a/config/initializers/carrierwave_patch.rb
+++ b/config/initializers/carrierwave_patch.rb
@@ -17,7 +17,24 @@ module CarrierWave
class Fog < Abstract
class File
def copy_to(new_path)
- connection.copy_object(@uploader.fog_directory, file.key, @uploader.fog_directory, new_path, copy_to_options)
+ # fog-aws needs multipart uploads to copy files above 5 GB,
+ # and it is currently the only Fog provider that supports
+ # multithreaded uploads (https://github.com/fog/fog-aws/pull/579).
+ # Multithreaded uploads are essential for copying large amounts of data
+ # within the request timeout.
+ if ::Feature.enabled?(:s3_multithreaded_uploads, default_enabled: true) && fog_provider == 'AWS'
+ # AWS SDK uses 10 threads by default and a multipart chunk size of 10 MB
+ file.concurrency = 10
+ file.multipart_chunk_size = 10485760
+ file.copy(@uploader.fog_directory, new_path, copy_to_options)
+ else
+ # Some Fog providers may issue a GET request (https://github.com/fog/fog-google/issues/512)
+ # instead of a HEAD request after the transfer completes,
+ # which might cause the file to be downloaded locally.
+ # We fallback to the original copy_object for non-AWS providers.
+ connection.copy_object(@uploader.fog_directory, file.key, @uploader.fog_directory, new_path, copy_to_options)
+ end
+
CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
end
diff --git a/config/initializers/grape_patch.rb b/config/initializers/grape_patch.rb
deleted file mode 100644
index a9ac0840541..00000000000
--- a/config/initializers/grape_patch.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-# Monkey patch for Grape v1.4.0: https://github.com/ruby-grape/grape/pull/2088
-
-require 'grape'
-
-# rubocop:disable Gitlab/ModuleWithInstanceVariables
-module Grape
- module DSL
- module InsideRoute
- def stream(value = nil)
- return if value.nil? && @stream.nil?
-
- header 'Content-Length', nil
- header 'Transfer-Encoding', nil
- header 'Cache-Control', 'no-cache' # Skips ETag generation (reading the response up front)
-
- if value.is_a?(String)
- file_body = Grape::ServeStream::FileBody.new(value)
- @stream = Grape::ServeStream::StreamResponse.new(file_body)
- elsif value.respond_to?(:each)
- @stream = Grape::ServeStream::StreamResponse.new(value)
- elsif !value.is_a?(NilClass)
- raise ArgumentError, 'Stream object must respond to :each.'
- else
- @stream
- end
- end
- end
- end
-end
-# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/config/initializers/postgres_partitioning.rb b/config/initializers/postgres_partitioning.rb
index b3f12c2ceb1..3cea8575cc7 100644
--- a/config/initializers/postgres_partitioning.rb
+++ b/config/initializers/postgres_partitioning.rb
@@ -3,7 +3,7 @@
# Make sure we have loaded partitioned models here
# (even with eager loading disabled).
-Gitlab::Database::Partitioning::PartitionCreator.register(AuditEventPartitioned)
+Gitlab::Database::Partitioning::PartitionCreator.register(AuditEvent)
begin
Gitlab::Database::Partitioning::PartitionCreator.new.create_partitions unless ENV['DISABLE_POSTGRES_PARTITION_CREATION_ON_STARTUP']
diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb
index 93c4d2b10cc..a4528020c06 100644
--- a/config/initializers/trusted_proxies.rb
+++ b/config/initializers/trusted_proxies.rb
@@ -30,4 +30,4 @@ module TrustedProxyMonkeyPatch
end
end
-ActionDispatch::Request.send(:include, TrustedProxyMonkeyPatch)
+ActionDispatch::Request.include TrustedProxyMonkeyPatch
diff --git a/config/karma.config.js b/config/karma.config.js
index 31fdd5bffd1..1d65e65ce2a 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -71,13 +71,13 @@ const createContext = (specFiles, regex, suffix) => {
if (specFilters.length) {
// resolve filters
- let filteredSpecFiles = specFilters.map(filter =>
+ let filteredSpecFiles = specFilters.map((filter) =>
glob
.sync(filter, {
root: ROOT_PATH,
matchBase: true,
})
- .filter(path => path.endsWith('spec.js')),
+ .filter((path) => path.endsWith('spec.js')),
);
// flatten
@@ -92,19 +92,19 @@ if (specFilters.length) {
exit('Your filter did not match any test files.', isError);
}
- if (!filteredSpecFiles.every(file => SPECS_PATH.test(file))) {
+ if (!filteredSpecFiles.every((file) => SPECS_PATH.test(file))) {
exitError('Test files must be located within /spec/javascripts.');
}
- const CE_FILES = filteredSpecFiles.filter(file => !file.startsWith('ee'));
+ const CE_FILES = filteredSpecFiles.filter((file) => !file.startsWith('ee'));
createContext(CE_FILES, /[^e]{2}[\\\/]spec[\\\/]javascripts$/, 'spec/javascripts');
- const EE_FILES = filteredSpecFiles.filter(file => file.startsWith('ee'));
+ const EE_FILES = filteredSpecFiles.filter((file) => file.startsWith('ee'));
createContext(EE_FILES, /ee[\\\/]spec[\\\/]javascripts$/, 'ee/spec/javascripts');
}
// Karma configuration
-module.exports = function(config) {
+module.exports = function (config) {
process.env.TZ = 'Etc/UTC';
const fixturesPath = `tmp/tests/frontend/fixtures${IS_EE ? '-ee' : ''}`;
diff --git a/config/known_invalid_graphql_queries.yml b/config/known_invalid_graphql_queries.yml
new file mode 100644
index 00000000000..8ea9b662aa7
--- /dev/null
+++ b/config/known_invalid_graphql_queries.yml
@@ -0,0 +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
diff --git a/config/locales/en.yml b/config/locales/en.yml
index fb024b7ba2a..4615c9a7390 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -169,6 +169,7 @@ en:
format: "%{attribute} %{message}"
messages:
label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
+ username_exists_as_a_different_namespace: A user, alias, or group already exists with that username.
wrong_size: "is the wrong size (should be %{file_size})"
size_too_small: "is too small (should be at least %{file_size})"
size_too_big: "is too big (should be at most %{file_size})"
diff --git a/config/metrics/counts_28d/deployments.yml b/config/metrics/counts_28d/deployments.yml
new file mode 100644
index 00000000000..dabd50ef5be
--- /dev/null
+++ b/config/metrics/counts_28d/deployments.yml
@@ -0,0 +1,15 @@
+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/g_project_management_issue_title_changed_weekly.yml b/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml
new file mode 100644
index 00000000000..997263f9e30
--- /dev/null
+++ b/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml
@@ -0,0 +1,16 @@
+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/deployments.yml b/config/metrics/counts_all/deployments.yml
new file mode 100644
index 00000000000..bb78e8d6144
--- /dev/null
+++ b/config/metrics/counts_all/deployments.yml
@@ -0,0 +1,15 @@
+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/recorded_at.yml b/config/metrics/license/recorded_at.yml
new file mode 100644
index 00000000000..5b2b3b37290
--- /dev/null
+++ b/config/metrics/license/recorded_at.yml
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 00000000000..38e0d74fc22
--- /dev/null
+++ b/config/metrics/license/uuid.yml
@@ -0,0 +1,17 @@
+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
new file mode 100644
index 00000000000..4d1120a7d8d
--- /dev/null
+++ b/config/metrics/schema.json
@@ -0,0 +1,66 @@
+{
+ "type": "object",
+ "required": ["name", "description", "value_type", "status", "default_generation", "full_path", "group", "time_frame", "data_source", "distribution", "tier"],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "value_type": {
+ "type": "string",
+ "enum": ["integer", "string", "number", "boolean"]
+ },
+ "product_category": {
+ "type": ["string", "null"]
+ },
+ "stage": {
+ "type": ["string", "null"]
+ },
+ "status": {
+ "type": ["string"],
+ "enum": ["data_available", "planned", "in_progress", "implmented"]
+ },
+ "default_generation": {
+ "type": "string"
+ },
+ "full_path": {
+ "type": "object"
+ },
+ "milestone": {
+ "type": ["number", "null"]
+ },
+ "milestone_removed": {
+ "type": ["number", "null"]
+ },
+ "introduced_by_url": {
+ "type": ["string", "null"]
+ },
+ "group": {
+ "type": "string"
+ },
+ "time_frame": {
+ "type": "string",
+ "enum": ["7d", "28d", "all", "none"]
+ },
+ "data_source": {
+ "type": "string",
+ "enum": ["database", "redis", "redis_hll", "prometheus", "ruby"]
+ },
+ "distribution": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["ee", "ce"]
+ }
+ },
+ "tier": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["free", "starter", "premium", "ultimate", "bronze", "silver", "gold"]
+ }
+ }
+ }
+}
diff --git a/config/metrics/settings/database_adapter.yml b/config/metrics/settings/database_adapter.yml
new file mode 100644
index 00000000000..b24fc933a08
--- /dev/null
+++ b/config/metrics/settings/database_adapter.yml
@@ -0,0 +1,14 @@
+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/plugins/monaco_webpack.js b/config/plugins/monaco_webpack.js
index 698d1b9b1fa..01d88ca37db 100644
--- a/config/plugins/monaco_webpack.js
+++ b/config/plugins/monaco_webpack.js
@@ -6,7 +6,7 @@ const { languagesArr } = require('monaco-editor-webpack-plugin/out/languages');
// a known issue in the library and this workaround was suggested here:
// https://github.com/pengx17/monaco-yaml/issues/20
-const yamlLang = languagesArr.find(t => t.label === 'yaml');
+const yamlLang = languagesArr.find((t) => t.label === 'yaml');
yamlLang.entry = [yamlLang.entry, '../../monaco-yaml/lib/esm/monaco.contribution'];
yamlLang.worker = {
diff --git a/config/puma.example.development.rb b/config/puma.example.development.rb
index ecbfac660c9..28c2af3acb3 100644
--- a/config/puma.example.development.rb
+++ b/config/puma.example.development.rb
@@ -79,6 +79,16 @@ tag 'gitlab-puma-worker'
#
worker_timeout 60
+# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#lower-latency-better-throughput
+if defined?(wait_for_less_busy_worker)
+ wait_for_less_busy_worker ENV.fetch('PUMA_WAIT_FOR_LESS_BUSY_WORKER', 0.001).to_f
+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'
+end
+
# Use json formatter
require_relative "/home/git/gitlab/lib/gitlab/puma_logging/json_formatter"
diff --git a/config/puma.rb.example b/config/puma.rb.example
index cd7adca157f..9fc354a8fe8 100644
--- a/config/puma.rb.example
+++ b/config/puma.rb.example
@@ -69,10 +69,20 @@ tag 'gitlab-puma-worker'
#
worker_timeout 60
+# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#lower-latency-better-throughput
+if defined?(wait_for_less_busy_worker)
+ wait_for_less_busy_worker ENV.fetch('PUMA_WAIT_FOR_LESS_BUSY_WORKER', 0.001).to_f
+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'
+end
+
# Use json formatter
require_relative "/home/git/gitlab/lib/gitlab/puma_logging/json_formatter"
json_formatter = Gitlab::PumaLogging::JSONFormatter.new
log_formatter do |str|
json_formatter.call(str)
-end \ No newline at end of file
+end
diff --git a/config/puma_actioncable.example.development.rb b/config/puma_actioncable.example.development.rb
index c975f9e4f9b..d0da3dcd8f2 100644
--- a/config/puma_actioncable.example.development.rb
+++ b/config/puma_actioncable.example.development.rb
@@ -79,6 +79,16 @@ tag 'gitlab-actioncable-puma-worker'
#
worker_timeout 60
+# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#lower-latency-better-throughput
+if defined?(wait_for_less_busy_worker)
+ wait_for_less_busy_worker ENV.fetch('PUMA_WAIT_FOR_LESS_BUSY_WORKER', 0.001).to_f
+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'
+end
+
# Use json formatter
require_relative "/home/git/gitlab/lib/gitlab/puma_logging/json_formatter"
diff --git a/config/routes.rb b/config/routes.rb
index 867e5c2ec46..91d1a817175 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -45,7 +45,12 @@ Rails.application.routes.draw do
# Sign up
scope path: '/users/sign_up', module: :registrations, as: :users_sign_up do
- resource :welcome, only: [:show, :update], controller: 'welcome'
+ resource :welcome, only: [:show, :update], controller: 'welcome' do
+ Gitlab.ee do
+ get :trial_getting_started, on: :collection
+ end
+ end
+
resource :experience_level, only: [:show, :update]
Gitlab.ee do
@@ -87,7 +92,10 @@ Rails.application.routes.draw do
# '/-/health' implemented by BasicHealthCheck middleware
get 'liveness' => 'health#liveness'
get 'readiness' => 'health#readiness'
- resources :metrics, only: [:index]
+ controller :metrics do
+ get 'metrics', action: :index
+ get 'metrics/system', action: :system
+ end
mount Peek::Railtie => '/peek', as: 'peek_routes'
get 'runner_setup/platforms' => 'runner_setup#platforms'
@@ -271,7 +279,8 @@ Rails.application.routes.draw do
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/210024
scope as: 'deprecated' do
draw :snippets
- draw :profile
+
+ Gitlab::Routing.redirect_legacy_paths(self, :profile)
end
Gitlab.ee do
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 38c04369d2f..012d5926872 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -49,6 +49,8 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
post :reset
end
end
+
+ resources :packages_and_registries, only: [:index]
end
resource :variables, only: [:show, :update]
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 6c99b0320de..5f94fb8d058 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -63,6 +63,7 @@ namespace :import do
resource :bulk_imports, only: [:create] do
post :configure
get :status
+ get :realtime_changes
end
resource :manifest, only: [:create, :new], controller: :manifest do
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 6f8c0b352fd..d5b3925131e 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -50,6 +50,8 @@
- 1
- - bulk_import
- 1
+- - bulk_imports_entity
+ - 1
- - chaos
- 2
- - chat_notification
@@ -122,6 +124,8 @@
- 2
- - error_tracking_issue_link
- 1
+- - experiments_record_conversion_event
+ - 1
- - expire_build_instance_artifacts
- 1
- - export_csv
@@ -198,6 +202,8 @@
- 1
- - namespaceless_project_destroy
- 1
+- - namespaces_onboarding_pipeline_created
+ - 1
- - namespaces_onboarding_user_added
- 1
- - new_epic
@@ -318,6 +324,10 @@
- 1
- - set_user_status_based_on_user_cap_setting
- 1
+- - snippet_schedule_bulk_repository_shard_moves
+ - 1
+- - snippet_update_repository_storage
+ - 1
- - status_page_publish
- 1
- - sync_seat_link_request
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 42e27ea1668..958b27d674d 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -63,13 +63,13 @@ function generateEntries() {
autoEntriesMap[chunkName] = `${prefix}/${path}`;
}
- pageEntries.forEach(path => generateAutoEntries(path));
+ pageEntries.forEach((path) => generateAutoEntries(path));
if (IS_EE) {
const eePageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
});
- eePageEntries.forEach(path => generateAutoEntries(path, 'ee'));
+ eePageEntries.forEach((path) => generateAutoEntries(path, 'ee'));
watchAutoEntries.push(path.join(ROOT_PATH, 'ee/app/assets/javascripts/pages/'));
}
@@ -77,7 +77,7 @@ function generateEntries() {
autoEntriesCount = autoEntryKeys.length;
// import ancestor entrypoints within their children
- autoEntryKeys.forEach(entry => {
+ autoEntryKeys.forEach((entry) => {
const entryPaths = [autoEntriesMap[entry]];
const segments = entry.split('.');
while (segments.pop()) {
@@ -188,7 +188,7 @@ module.exports = {
},
{
test: /\.js$/,
- exclude: path =>
+ exclude: (path) =>
/node_modules\/(?!tributejs)|node_modules|vendor[\\/]assets/.test(path) &&
!/\.vue\.js/.test(path),
loader: 'babel-loader',
@@ -344,7 +344,7 @@ module.exports = {
// webpack-rails only needs assetsByChunkName to function properly
new StatsWriterPlugin({
filename: 'manifest.json',
- transform: function(data, opts) {
+ transform: function (data, opts) {
const stats = opts.compiler.getStats().toJson({
chunkModules: false,
source: false,
@@ -448,7 +448,7 @@ module.exports = {
]),
!IS_EE &&
- new webpack.NormalModuleReplacementPlugin(/^ee_component\/(.*)\.vue/, resource => {
+ new webpack.NormalModuleReplacementPlugin(/^ee_component\/(.*)\.vue/, (resource) => {
resource.request = path.join(
ROOT_PATH,
'app/assets/javascripts/vue_shared/components/empty_component.js',
@@ -485,14 +485,14 @@ module.exports = {
const missingDeps = Array.from(compilation.missingDependencies);
const nodeModulesPath = path.join(ROOT_PATH, 'node_modules');
const hasMissingNodeModules = missingDeps.some(
- file => file.indexOf(nodeModulesPath) !== -1,
+ (file) => file.indexOf(nodeModulesPath) !== -1,
);
// watch for changes to missing node_modules
if (hasMissingNodeModules) compilation.contextDependencies.add(nodeModulesPath);
// watch for changes to automatic entrypoints
- watchAutoEntries.forEach(watchPath => compilation.contextDependencies.add(watchPath));
+ watchAutoEntries.forEach((watchPath) => compilation.contextDependencies.add(watchPath));
// report our auto-generated bundle count
console.log(
@@ -518,7 +518,7 @@ module.exports = {
);
}
const memoryUsage = process.memoryUsage().heapUsed;
- const toMB = bytes => Math.floor(bytes / 1024 / 1024);
+ const toMB = (bytes) => Math.floor(bytes / 1024 / 1024);
console.log(`Webpack heap size: ${toMB(memoryUsage)} MB`);
diff --git a/danger/frozen_string/Dangerfile b/danger/frozen_string/Dangerfile
index 7c4c4f2b17c..bc598b16463 100644
--- a/danger/frozen_string/Dangerfile
+++ b/danger/frozen_string/Dangerfile
@@ -1,15 +1,34 @@
# frozen_string_literal: true
FILE_EXTENSION = ".rb"
-MAGIC_COMMENT = "# frozen_string_literal: true"
+FROZEN_STRING_MAGIC_COMMENT = "# frozen_string_literal: true"
+SHEBANG_COMMENT = "#!"
def get_files_with_no_magic_comment(files)
- files.select do |file|
- file.end_with?(FILE_EXTENSION) &&
- !File.open(file, &:gets)&.start_with?(MAGIC_COMMENT)
+ 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?
@@ -20,7 +39,7 @@ if files_to_fix.any?
markdown(<<~MARKDOWN)
## Enable Frozen String Literal
- The following files should have `#{MAGIC_COMMENT}` on the first line:
+ The following files should have `#{FROZEN_STRING_MAGIC_COMMENT}` on the first line:
* #{files_to_fix.map { |path| "`#{path}`" }.join("\n* ")}
MARKDOWN
diff --git a/danger/product_analytics/Dangerfile b/danger/product_analytics/Dangerfile
deleted file mode 100644
index b2144e7f034..00000000000
--- a/danger/product_analytics/Dangerfile
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-PRODUCT_ANALYTICS_CHANGED_FILES_MESSAGE = <<~MSG
-For the following files, a review from the [Data team and Product Analytics team](https://gitlab.com/groups/gitlab-org/growth/product_analytics/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
-Please check the ~"product analytics" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<product_analytics_engineers_group>s group for a review.
-
-
-%<changed_files>s
-
-MSG
-
-UPDATE_METRICS_DEFINITIONS_MESSAGE = <<~MSG
- When adding, changing, or updating metrics, please update the [Event dictionary Usage Ping table](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary).
-
-MSG
-
-PRODUCT_ANALYTICS_ENGINEERS_GROUP = '@gitlab-org/growth/product_analytics/engineers'
-
-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'
-]
-
-usage_data_changed_files = helper.changed_files(/usage_data/)
-snowplow_events_changed_files = git.modified_files & tracking_files
-
-changed_files = (usage_data_changed_files + snowplow_events_changed_files)
-
-if changed_files.any?
-
- mention = if helper.draft_mr?
- "`#{PRODUCT_ANALYTICS_ENGINEERS_GROUP}`"
- else
- PRODUCT_ANALYTICS_ENGINEERS_GROUP
- end
-
- warn format(PRODUCT_ANALYTICS_CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(changed_files), product_analytics_engineers_group: mention)
- warn format(UPDATE_METRICS_DEFINITIONS_MESSAGE) unless helper.changed_files(/usage_ping\.md/).any?
-
- product_analytics_labels = ['product analytics']
- product_analytics_labels << 'product analytics::review pending' unless helper.mr_has_labels?('product analytics::reviewed')
-
- markdown(helper.prepare_labels_for_mr(product_analytics_labels))
-end
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
new file mode 100644
index 00000000000..ec432544977
--- /dev/null
+++ b/danger/product_intelligence/Dangerfile
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+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.
+
+
+%<changed_files>s
+
+MSG
+
+UPDATE_METRICS_DEFINITIONS_MESSAGE = <<~MSG
+ When adding, changing, or updating metrics, please update the [Event dictionary Usage Ping table](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary).
+
+MSG
+
+ENGINEERS_GROUP = '@gitlab-org/growth/product-intelligence/engineers'
+
+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'
+]
+
+usage_data_changed_files = helper.changed_files(/usage_data/)
+snowplow_events_changed_files = git.modified_files & tracking_files
+
+changed_files = (usage_data_changed_files + snowplow_events_changed_files)
+
+if changed_files.any?
+
+ mention = if helper.draft_mr?
+ "`#{ENGINEERS_GROUP}`"
+ else
+ 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?
+
+ labels = ['product intelligence']
+ labels << 'product intelligence::review pending' unless helper.mr_has_labels?('product intelligence::approved')
+
+ markdown(helper.prepare_labels_for_mr(labels))
+end
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index f49f6ad251c..424114a3d33 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -15,7 +15,8 @@ CATEGORY_TABLE_HEADER = <<MARKDOWN
To spread load more evenly across eligible reviewers, Danger has picked a candidate for each
review slot, based on their timezone. Feel free to
[override these selections](https://about.gitlab.com/handbook/engineering/projects/#gitlab)
-if you think someone else would be better-suited, or the chosen person is unavailable.
+if you think someone else would be better-suited
+or use the [GitLab Review Workload Dashboard](https://gitlab-org.gitlab.io/gitlab-roulette/) to find other available reviewers.
To read more on how to use the reviewer roulette, please take a look at the
[Engineering workflow](https://about.gitlab.com/handbook/engineering/workflow/#basics)
@@ -38,8 +39,8 @@ Please consider creating a merge request to
for them.
MARKDOWN
-OPTIONAL_REVIEW_TEMPLATE = "%{role} review is optional for %{category}".freeze
-NOT_AVAILABLE_TEMPLATE = 'No %{role} available'.freeze
+OPTIONAL_REVIEW_TEMPLATE = '%{role} review is optional for %{category}'
+NOT_AVAILABLE_TEMPLATE = 'No %{role} available'
def note_for_spins_role(spins, role)
spins.each do |spin|
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index 72e0c8e92f4..26b52f64f2e 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -7,12 +7,12 @@ NO_SPECS_LABELS = [
'documentation',
'QA'
].freeze
-NO_NEW_SPEC_MESSAGE = <<~MSG
+NO_NEW_SPEC_MESSAGE = <<~MSG.freeze
You've made some app changes, but didn't add any tests.
That's OK as long as you're refactoring existing code,
but please consider adding any of the %<labels>s labels.
MSG
-EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE = <<~MSG
+EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE = <<~MSG.freeze
You've made some EE-specific changes, but only made changes to FOSS tests.
This could be a sign that you're testing an EE-specific behavior in a FOSS test.
@@ -24,6 +24,14 @@ Please make sure the spec files pass in AS-IF-FOSS mode either:
MSG
+CONTROLLER_SPEC_DEPRECATION_MESSAGE = <<~MSG.freeze
+Do not add new controller specs. We are moving from controller specs to
+request specs (and/or feature specs). Please add request specs under
+`/spec/requests` and/or `/ee/spec/requests` instead.
+
+See https://gitlab.com/groups/gitlab-org/-/epics/5076 for information.
+MSG
+
has_app_changes = helper.all_changed_files.grep(%r{\A(app|lib|db/(geo/)?(post_)?migrate)/}).any?
has_ee_app_changes = helper.all_changed_files.grep(%r{\Aee/(app|lib|db/(geo/)?(post_)?migrate)/}).any?
spec_changes = helper.all_changed_files.grep(%r{\Aspec/})
@@ -39,3 +47,8 @@ end
if has_ee_app_changes && has_spec_changes && !(has_app_changes || has_ee_spec_changes)
warn format(EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE, spec_files: spec_changes.join(" "), mr_title: gitlab.mr_json['title']), sticky: false
end
+
+# Forbidding a new file addition under `/spec/controllers` or `/ee/spec/controllers`
+if git.added_files.grep(%r{^(ee/)?spec/controllers/}).any?
+ warn CONTROLLER_SPEC_DEPRECATION_MESSAGE
+end
diff --git a/data/whats_new/202009300001_13_04.yml b/data/whats_new/202009300001_13_04.yml
index 0c5642152ae..dc48b2fbf26 100644
--- a/data/whats_new/202009300001_13_04.yml
+++ b/data/whats_new/202009300001_13_04.yml
@@ -63,7 +63,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [starter, premium, ultimate]
+ 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
diff --git a/data/whats_new/202012160001_13_07.yml b/data/whats_new/202012160001_13_07.yml
new file mode 100644
index 00000000000..14ed04aa0f7
--- /dev/null
+++ b/data/whats_new/202012160001_13_07.yml
@@ -0,0 +1,51 @@
+---
+- title: Auto rollback in case of failure
+ body: |
+ If you have a critical problem with a deployment, manual actions to fix it often take too long and lead to a degradation in production that impacts your users. Now, you can leverage an automatic rollback mechanism that reverts your deployment back to the last successful deployment. Also, when GitLab finds problems in production it automatically notifies you with an alert. This gives you peace of mind and precious development time to debug, investigate, and fix problems without causing downtime.
+ stage: Release
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: https://docs.gitlab.com/ee/ci/environments/#auto-rollback
+ image_url: https://img.youtube.com/vi/G8fYYrxqF5E/hqdefault.jpg
+ published_at: 2020-12-22
+ release: 13.7
+- title: Reviewers for Merge Requests
+ body: |
+ Asking a colleague to review your code should be a routine part of contributing code, but it's often needlessly complex. A simple task like asking for a review can lead to confusion. For example, how should you ask? An email? Comment? Chat message? Without a formal process, reviews can be inconsistent and hard to keep track of. Previously, an option was to assign a reviewer to a merge request, but even with this formality, both the author and the reviewer appeared in the same assignee field, making it hard for other team members to know who was doing what.
+
+ GitLab 13.7 introduces reviewers for merge requests, which allows authors to request a review from someone. The new "Reviewers" field allows users to be designated as reviewers in a similar way to assignees. The reviewers receive a notification inviting them to review the merge request. This provides a formal process for requesting a review and clarifies the roles of each user in a merge request.
+
+ Future iterations will include showing the most relevant reviewers for a merge request as well as a streamlined merge request approval flow that puts reviewers at the center. You can follow along in the [merge request reviewer assignment epic](https://gitlab.com/groups/gitlab-org/-/epics/1823) for more details.
+ stage: Create
+ self-managed: true
+ gitlab-com: true
+ packages: [Core, Starter, 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
+ release: 13.7
+- title: Clone an issue with a quick action
+ body: |
+ To make generating similar issues more efficient, issues now support a `/clone` quick action, which creates a new issue in the same project, with an identical title, description, and metadata. The `/clone` quick action replaces a more cumbersome process, which involves multiple steps to create an issue, copy the ID or path of the source issue, and use the `copy_meta` quick action.
+
+ By default, issues are cloned into the same project and do not include system notes and comments, but you can also change the default behavior when cloning.
+ stage: Plan
+ self-managed: true
+ gitlab-com: true
+ packages: [Core, Starter, 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]
+ self-managed: true
+ gitlab-com: true
+ url: 'https://docs.gitlab.com/runner/install/openshift.html'
+ image_url: 'https://about.gitlab.com/images/13_7/runner-redhat-openshift.png'
+ stage: Verify
+ body: |
+ Available today is the GitLab Runner container image for the [Red Hat OpenShift Container Platform](https://www.openshift.com/products/container-platform). To install the runner on OpenShift, you can use the new [GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator) available from the beta channel in Red Hat's Operator Hub - a web console for OpenShift cluster administrators to discover and select Operators to install on their cluster. Operator Hub is deployed by default in the OpenShift Container Platform. We plan to transition the GitLab Runner Operator to the stable channel, and by extension [GA](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator/-/issues/6), in early 2021. Finally, we are also developing an operator for GitLab, so stay tuned to future release posts for those announcements.
+ published_at: 2020-12-22
+ release: 13.7
diff --git a/db/fixtures/development/03_project.rb b/db/fixtures/development/03_project.rb
index 596c5e81a2e..e879db84e68 100644
--- a/db/fixtures/development/03_project.rb
+++ b/db/fixtures/development/03_project.rb
@@ -113,6 +113,7 @@ class Gitlab::Seeder::Projects
group.save!
group.add_owner(User.first)
+ group.create_namespace_settings
end
project_path.gsub!(".git", "")
diff --git a/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb b/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb
index 073faf721ae..86de78b831b 100644
--- a/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb
+++ b/db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb
@@ -4,7 +4,7 @@ class RemovePartialIndexFromCiBuildsArtifactsFile < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'partial_index_ci_builds_on_id_with_legacy_artifacts'.freeze
+ INDEX_NAME = 'partial_index_ci_builds_on_id_with_legacy_artifacts'
disable_ddl_transaction!
diff --git a/db/migrate/20190402150158_backport_enterprise_schema.rb b/db/migrate/20190402150158_backport_enterprise_schema.rb
index dcf84d762a3..c4fbb4b2ab9 100644
--- a/db/migrate/20190402150158_backport_enterprise_schema.rb
+++ b/db/migrate/20190402150158_backport_enterprise_schema.rb
@@ -198,9 +198,9 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0]
# rubocop:enable Migration/DropTable
end
- def add_column_with_default_if_not_exists(table, name, *args)
+ def add_column_with_default_if_not_exists(table, name, type, **args)
unless column_exists?(table, name)
- add_column_with_default(table, name, *args) # rubocop:disable Migration/AddColumnWithDefault
+ add_column_with_default(table, name, type, **args) # rubocop:disable Migration/AddColumnWithDefault
end
end
@@ -226,10 +226,10 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0]
end
end
- def create_table_if_not_exists(name, *args, &block)
+ def create_table_if_not_exists(name, **args, &block)
return if table_exists?(name)
- create_table(name, *args, &block)
+ create_table(name, **args, &block)
end
def add_concurrent_foreign_key(source, target, column:, on_delete: nil, name: nil)
diff --git a/db/migrate/20190709220143_add_index_to_issues_relative_position.rb b/db/migrate/20190709220143_add_index_to_issues_relative_position.rb
index effab33ce4f..ec11c6d768f 100644
--- a/db/migrate/20190709220143_add_index_to_issues_relative_position.rb
+++ b/db/migrate/20190709220143_add_index_to_issues_relative_position.rb
@@ -8,7 +8,7 @@ class AddIndexToIssuesRelativePosition < ActiveRecord::Migration[5.1]
disable_ddl_transaction!
- INDEX_NAME = 'index_issues_on_project_id_and_state_and_rel_position_and_id'.freeze
+ INDEX_NAME = 'index_issues_on_project_id_and_state_and_rel_position_and_id'
def up
add_concurrent_index :issues, [:project_id, :state, :relative_position, :id], order: { id: :desc }, name: INDEX_NAME
diff --git a/db/migrate/20190716144222_create_analytics_cycle_analytics_project_stages.rb b/db/migrate/20190716144222_create_analytics_cycle_analytics_project_stages.rb
index c03191013dc..5723f6db0a3 100644
--- a/db/migrate/20190716144222_create_analytics_cycle_analytics_project_stages.rb
+++ b/db/migrate/20190716144222_create_analytics_cycle_analytics_project_stages.rb
@@ -11,19 +11,20 @@ class CreateAnalyticsCycleAnalyticsProjectStages < ActiveRecord::Migration[5.2]
t.integer :relative_position
t.integer :start_event_identifier, null: false
t.integer :end_event_identifier, null: false
- t.references(:project, {
+
+ t.references(:project,
null: false,
foreign_key: { to_table: :projects, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_project_id' }
- })
- t.references(:start_event_label, {
+ )
+ t.references(:start_event_label,
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_start_event_label_id' }
- })
- t.references(:end_event_label, {
+ )
+ t.references(:end_event_label,
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_end_event_label_id' }
- })
+ )
t.boolean :hidden, default: false, null: false
t.boolean :custom, default: true, null: false
t.string :name, null: false, limit: 255 # rubocop:disable Migration/PreventStrings
diff --git a/db/migrate/20190729062536_create_analytics_cycle_analytics_group_stages.rb b/db/migrate/20190729062536_create_analytics_cycle_analytics_group_stages.rb
index 4753a7684e7..d438ece9951 100644
--- a/db/migrate/20190729062536_create_analytics_cycle_analytics_group_stages.rb
+++ b/db/migrate/20190729062536_create_analytics_cycle_analytics_group_stages.rb
@@ -11,19 +11,20 @@ class CreateAnalyticsCycleAnalyticsGroupStages < ActiveRecord::Migration[5.2]
t.integer :relative_position
t.integer :start_event_identifier, null: false
t.integer :end_event_identifier, null: false
- t.references(:group, {
+
+ t.references(:group,
null: false,
foreign_key: { to_table: :namespaces, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_group_id' }
- })
- t.references(:start_event_label, {
+ )
+ t.references(:start_event_label,
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_start_event_label_id' }
- })
- t.references(:end_event_label, {
+ )
+ t.references(:end_event_label,
foreign_key: { to_table: :labels, on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_end_event_label_id' }
- })
+ )
t.boolean :hidden, default: false, null: false
t.boolean :custom, default: true, null: false
t.string :name, null: false, limit: 255 # rubocop:disable Migration/PreventStrings
diff --git a/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb b/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb
index 07da4c20d55..1fc9034655c 100644
--- a/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb
+++ b/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb
@@ -7,16 +7,15 @@ class CreateAnalyticsLanguageTrendRepositoryLanguages < ActiveRecord::Migration[
def change
create_table :analytics_language_trend_repository_languages, id: false do |t|
t.integer :file_count, null: false, default: 0
- t.references :programming_language, {
+
+ t.references :programming_language,
null: false,
foreign_key: { on_delete: :cascade },
index: false
- }
- t.references :project, {
+ t.references :project,
null: false,
foreign_key: { on_delete: :cascade },
index: { name: INDEX_PREFIX + 'on_project_id' }
- }
t.integer :loc, null: false, default: 0
t.integer :bytes, null: false, default: 0
# Storing percentage (with 2 decimal places), on 2 bytes.
diff --git a/db/migrate/20191118182722_add_index_to_environments_on_project_id_state_environment_type.rb b/db/migrate/20191118182722_add_index_to_environments_on_project_id_state_environment_type.rb
index b88a1f01d79..01272dfad44 100644
--- a/db/migrate/20191118182722_add_index_to_environments_on_project_id_state_environment_type.rb
+++ b/db/migrate/20191118182722_add_index_to_environments_on_project_id_state_environment_type.rb
@@ -4,8 +4,8 @@ class AddIndexToEnvironmentsOnProjectIdStateEnvironmentType < ActiveRecord::Migr
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- OLD_INDEX_NAME = 'index_environments_on_project_id_and_state'.freeze
- NEW_INDEX_NAME = 'index_environments_on_project_id_state_environment_type'.freeze
+ OLD_INDEX_NAME = 'index_environments_on_project_id_and_state'
+ NEW_INDEX_NAME = 'index_environments_on_project_id_state_environment_type'
disable_ddl_transaction!
diff --git a/db/migrate/20191121161018_add_project_id_name_version_package_type_index_to_packages_packages.rb b/db/migrate/20191121161018_add_project_id_name_version_package_type_index_to_packages_packages.rb
index 4511a2a0e49..4a34b9e791e 100644
--- a/db/migrate/20191121161018_add_project_id_name_version_package_type_index_to_packages_packages.rb
+++ b/db/migrate/20191121161018_add_project_id_name_version_package_type_index_to_packages_packages.rb
@@ -4,7 +4,7 @@ class AddProjectIdNameVersionPackageTypeIndexToPackagesPackages < ActiveRecord::
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'idx_packages_packages_on_project_id_name_version_package_type'.freeze
+ INDEX_NAME = 'idx_packages_packages_on_project_id_name_version_package_type'
disable_ddl_transaction!
diff --git a/db/migrate/20191129144631_add_index_to_resource_group_id.rb b/db/migrate/20191129144631_add_index_to_resource_group_id.rb
index 0e5a84f094d..01d56f417b5 100644
--- a/db/migrate/20191129144631_add_index_to_resource_group_id.rb
+++ b/db/migrate/20191129144631_add_index_to_resource_group_id.rb
@@ -4,7 +4,7 @@ class AddIndexToResourceGroupId < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'index_for_resource_group'.freeze
+ INDEX_NAME = 'index_for_resource_group'
disable_ddl_transaction!
diff --git a/db/migrate/20191214175727_add_indexes_to_deployments_on_project_id_and_ref.rb b/db/migrate/20191214175727_add_indexes_to_deployments_on_project_id_and_ref.rb
index 5dacc3c0c66..ea92f9cfd32 100644
--- a/db/migrate/20191214175727_add_indexes_to_deployments_on_project_id_and_ref.rb
+++ b/db/migrate/20191214175727_add_indexes_to_deployments_on_project_id_and_ref.rb
@@ -4,7 +4,7 @@ class AddIndexesToDeploymentsOnProjectIdAndRef < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'partial_index_deployments_for_project_id_and_tag'.freeze
+ INDEX_NAME = 'partial_index_deployments_for_project_id_and_tag'
disable_ddl_transaction!
diff --git a/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb b/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb
index ae0d6d31c42..c7f2354440b 100644
--- a/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb
+++ b/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb
@@ -4,7 +4,7 @@ class AddGroupIndexAndFkToImportFailures < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- GROUP_INDEX = 'index_import_failures_on_group_id_not_null'.freeze
+ GROUP_INDEX = 'index_import_failures_on_group_id_not_null'
disable_ddl_transaction!
diff --git a/db/migrate/20200117112554_update_project_index_to_import_failures.rb b/db/migrate/20200117112554_update_project_index_to_import_failures.rb
index 1e8347aad44..888a9bec778 100644
--- a/db/migrate/20200117112554_update_project_index_to_import_failures.rb
+++ b/db/migrate/20200117112554_update_project_index_to_import_failures.rb
@@ -5,8 +5,8 @@ class UpdateProjectIndexToImportFailures < ActiveRecord::Migration[5.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
- PROJECT_INDEX_OLD = 'index_import_failures_on_project_id'.freeze
- PROJECT_INDEX_NEW = 'index_import_failures_on_project_id_not_null'.freeze
+ PROJECT_INDEX_OLD = 'index_import_failures_on_project_id'
+ PROJECT_INDEX_NEW = 'index_import_failures_on_project_id_not_null'
disable_ddl_transaction!
diff --git a/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb b/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb
index 13b041d8f95..4ec514f7fca 100644
--- a/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb
+++ b/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb
@@ -2,8 +2,8 @@
class DropActivatePrometheusServicesBackgroundJobs < ActiveRecord::Migration[6.0]
DOWNTIME = false
- DROPPED_JOB_CLASS = 'ActivatePrometheusServicesForSharedClusterApplications'.freeze
- QUEUE = 'background_migration'.freeze
+ DROPPED_JOB_CLASS = 'ActivatePrometheusServicesForSharedClusterApplications'
+ QUEUE = 'background_migration'
def up
sidekiq_queues.each do |queue|
diff --git a/db/migrate/20200528054112_add_index_to_package_name.rb b/db/migrate/20200528054112_add_index_to_package_name.rb
index 4629c32ab3d..fa12088741d 100644
--- a/db/migrate/20200528054112_add_index_to_package_name.rb
+++ b/db/migrate/20200528054112_add_index_to_package_name.rb
@@ -7,7 +7,7 @@ class AddIndexToPackageName < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
- INDEX_NAME = 'package_name_index'.freeze
+ INDEX_NAME = 'package_name_index'
def up
add_concurrent_index(:packages_packages, :name, name: INDEX_NAME)
diff --git a/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb b/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb
index 24afe463684..4b3f5222399 100644
--- a/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb
+++ b/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb
@@ -13,11 +13,11 @@ class CreateAnalyticsCycleAnalyticsGroupValueStreams < ActiveRecord::Migration[6
with_lock_retries do
create_table :analytics_cycle_analytics_group_value_streams do |t|
t.timestamps_with_timezone
- t.references(:group, {
+ t.references(:group,
null: false,
index: false,
foreign_key: { to_table: :namespaces, on_delete: :cascade }
- })
+ )
t.text :name, null: false
t.index [:group_id, :name], unique: true, name: INDEX_NAME
end
diff --git a/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb b/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
index 94d2e5cb4ab..5938d3c8d3a 100644
--- a/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
+++ b/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
@@ -4,7 +4,7 @@ class AddProjectsIndexOnImportTypeCreatorIdCreatedAt < ActiveRecord::Migration[6
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'index_imported_projects_on_import_type_creator_id_created_at'.freeze
+ INDEX_NAME = 'index_imported_projects_on_import_type_creator_id_created_at'
disable_ddl_transaction!
diff --git a/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb b/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb
index 88c019c849e..dcbe48c03f9 100644
--- a/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb
+++ b/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb
@@ -4,7 +4,7 @@ class RemoveComplianceFrameworksGroupIdFk < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'index_compliance_management_frameworks_on_group_id_and_name'.freeze
+ INDEX_NAME = 'index_compliance_management_frameworks_on_group_id_and_name'
class TmpComplianceFramework < ActiveRecord::Base
self.table_name = 'compliance_management_frameworks'
diff --git a/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb b/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb
index ea45e82dcc4..c26636444af 100644
--- a/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb
+++ b/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb
@@ -2,8 +2,8 @@
class DropBackfillJiraTrackerDeploymentTypeJobs < ActiveRecord::Migration[6.0]
DOWNTIME = false
- DROPPED_JOB_CLASS = 'BackfillJiraTrackerDeploymentType'.freeze
- QUEUE = 'background_migration'.freeze
+ DROPPED_JOB_CLASS = 'BackfillJiraTrackerDeploymentType'
+ QUEUE = 'background_migration'
def up
sidekiq_queues.each do |queue|
diff --git a/db/migrate/20201112215132_swap_partitioned_audit_events.rb b/db/migrate/20201112215132_swap_partitioned_audit_events.rb
new file mode 100644
index 00000000000..8360dbd4aa5
--- /dev/null
+++ b/db/migrate/20201112215132_swap_partitioned_audit_events.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class SwapPartitionedAuditEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ replace_with_partitioned_table :audit_events
+ end
+
+ def down
+ rollback_replace_with_partitioned_table :audit_events
+ end
+end
diff --git a/db/migrate/20201204105300_create_packages_debian_file_metadata.rb b/db/migrate/20201204105300_create_packages_debian_file_metadata.rb
new file mode 100644
index 00000000000..2bba1b6f38e
--- /dev/null
+++ b/db/migrate/20201204105300_create_packages_debian_file_metadata.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianFileMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:packages_debian_file_metadata)
+ create_table :packages_debian_file_metadata, id: false do |t|
+ t.timestamps_with_timezone
+ t.references :package_file, primary_key: true, index: false, default: nil, null: false, foreign_key: { to_table: :packages_package_files, on_delete: :cascade }, type: :bigint
+ t.integer :file_type, limit: 2, null: false
+ t.text :component
+ t.text :architecture
+ t.jsonb :fields
+ end
+ end
+
+ add_text_limit :packages_debian_file_metadata, :component, 255
+ add_text_limit :packages_debian_file_metadata, :architecture, 255
+ end
+
+ def down
+ drop_table :packages_debian_file_metadata
+ end
+end
diff --git a/db/migrate/20201204110700_create_packages_debian_project_distributions.rb b/db/migrate/20201204110700_create_packages_debian_project_distributions.rb
new file mode 100644
index 00000000000..5fe45c6236f
--- /dev/null
+++ b/db/migrate/20201204110700_create_packages_debian_project_distributions.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianProjectDistributions < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ UNIQUE_CODENAME = 'uniq_pkgs_debian_project_distributions_project_id_and_codename'
+ UNIQUE_SUITE = 'uniq_pkgs_debian_project_distributions_project_id_and_suite'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:packages_debian_project_distributions)
+ create_table :packages_debian_project_distributions do |t|
+ t.timestamps_with_timezone
+ t.references :project, foreign_key: { to_table: :projects, on_delete: :restrict }, null: false
+ t.references :creator, foreign_key: { to_table: :users, on_delete: :nullify }
+ t.integer :valid_time_duration_seconds
+ t.integer :file_store, limit: 2, default: 1, null: false
+ t.boolean :automatic, default: true, null: false
+ t.boolean :automatic_upgrades, default: false, null: false
+ t.text :codename, null: false
+ t.text :suite
+ t.text :origin
+ t.text :label
+ t.text :version
+ t.text :description
+ t.text :encrypted_signing_keys
+ t.text :encrypted_signing_keys_iv
+ t.text :file
+ t.text :file_signature
+
+ t.index %w(project_id codename),
+ name: UNIQUE_CODENAME,
+ unique: true,
+ using: :btree
+ t.index %w(project_id suite),
+ name: UNIQUE_SUITE,
+ unique: true,
+ using: :btree
+ end
+ end
+ end
+
+ add_text_limit :packages_debian_project_distributions, :codename, 255
+ add_text_limit :packages_debian_project_distributions, :suite, 255
+ add_text_limit :packages_debian_project_distributions, :origin, 255
+ add_text_limit :packages_debian_project_distributions, :label, 255
+ add_text_limit :packages_debian_project_distributions, :version, 255
+ add_text_limit :packages_debian_project_distributions, :description, 255
+ add_text_limit :packages_debian_project_distributions, :encrypted_signing_keys, 2048
+ add_text_limit :packages_debian_project_distributions, :encrypted_signing_keys_iv, 255
+ add_text_limit :packages_debian_project_distributions, :file, 255
+ add_text_limit :packages_debian_project_distributions, :file_signature, 4096
+ end
+
+ def down
+ drop_table :packages_debian_project_distributions
+ end
+end
diff --git a/db/migrate/20201204110800_create_packages_debian_group_distributions.rb b/db/migrate/20201204110800_create_packages_debian_group_distributions.rb
new file mode 100644
index 00000000000..9ad9a59b3e9
--- /dev/null
+++ b/db/migrate/20201204110800_create_packages_debian_group_distributions.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianGroupDistributions < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ UNIQUE_CODENAME = 'uniq_pkgs_debian_group_distributions_group_id_and_codename'
+ UNIQUE_SUITE = 'uniq_pkgs_debian_group_distributions_group_id_and_suite'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:packages_debian_group_distributions)
+ create_table :packages_debian_group_distributions do |t|
+ t.timestamps_with_timezone
+ t.references :group, foreign_key: { to_table: :namespaces, on_delete: :restrict }, null: false
+ t.references :creator, foreign_key: { to_table: :users, on_delete: :nullify }
+ t.integer :valid_time_duration_seconds
+ t.integer :file_store, limit: 2, default: 1, null: false
+ t.boolean :automatic, default: true, null: false
+ t.boolean :automatic_upgrades, default: false, null: false
+ t.text :codename, null: false
+ t.text :suite
+ t.text :origin
+ t.text :label
+ t.text :version
+ t.text :description
+ t.text :encrypted_signing_keys
+ t.text :encrypted_signing_keys_iv
+ t.text :file
+ t.text :file_signature
+
+ t.index %w(group_id codename),
+ name: UNIQUE_CODENAME,
+ unique: true,
+ using: :btree
+ t.index %w(group_id suite),
+ name: UNIQUE_SUITE,
+ unique: true,
+ using: :btree
+ end
+ end
+ end
+
+ add_text_limit :packages_debian_group_distributions, :codename, 255
+ add_text_limit :packages_debian_group_distributions, :suite, 255
+ add_text_limit :packages_debian_group_distributions, :origin, 255
+ add_text_limit :packages_debian_group_distributions, :label, 255
+ add_text_limit :packages_debian_group_distributions, :version, 255
+ add_text_limit :packages_debian_group_distributions, :description, 255
+ add_text_limit :packages_debian_group_distributions, :encrypted_signing_keys, 2048
+ add_text_limit :packages_debian_group_distributions, :encrypted_signing_keys_iv, 255
+ add_text_limit :packages_debian_group_distributions, :file, 255
+ add_text_limit :packages_debian_group_distributions, :file_signature, 4096
+ end
+
+ def down
+ drop_table :packages_debian_group_distributions
+ end
+end
diff --git a/db/migrate/20201204111000_create_packages_debian_project_architectures.rb b/db/migrate/20201204111000_create_packages_debian_project_architectures.rb
new file mode 100644
index 00000000000..f684a413873
--- /dev/null
+++ b/db/migrate/20201204111000_create_packages_debian_project_architectures.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianProjectArchitectures < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'idx_pkgs_deb_proj_architectures_on_distribution_id'
+ UNIQUE_NAME = 'uniq_pkgs_deb_proj_architectures_on_distribution_id_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:packages_debian_project_architectures)
+ create_table :packages_debian_project_architectures do |t|
+ t.timestamps_with_timezone
+ t.references :distribution,
+ foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade },
+ null: false,
+ index: { name: INDEX_NAME }
+ t.text :name, null: false
+
+ t.index %w(distribution_id name),
+ name: UNIQUE_NAME,
+ unique: true,
+ using: :btree
+ end
+ end
+ end
+
+ add_text_limit :packages_debian_project_architectures, :name, 255
+ end
+
+ def down
+ drop_table :packages_debian_project_architectures
+ end
+end
diff --git a/db/migrate/20201204111100_create_packages_debian_group_architectures.rb b/db/migrate/20201204111100_create_packages_debian_group_architectures.rb
new file mode 100644
index 00000000000..8a001414c45
--- /dev/null
+++ b/db/migrate/20201204111100_create_packages_debian_group_architectures.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianGroupArchitectures < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'idx_pkgs_deb_grp_architectures_on_distribution_id'
+ UNIQUE_NAME = 'uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:packages_debian_group_architectures)
+ create_table :packages_debian_group_architectures do |t|
+ t.timestamps_with_timezone
+ t.references :distribution,
+ foreign_key: { to_table: :packages_debian_group_distributions, on_delete: :cascade },
+ null: false,
+ index: { name: INDEX_NAME }
+ t.text :name, null: false
+
+ t.index %w(distribution_id name),
+ name: UNIQUE_NAME,
+ unique: true,
+ using: :btree
+ end
+ end
+ end
+
+ add_text_limit :packages_debian_group_architectures, :name, 255
+ end
+
+ def down
+ drop_table :packages_debian_group_architectures
+ end
+end
diff --git a/db/migrate/20201204193952_keep_latest_artifact_project_level.rb b/db/migrate/20201204193952_keep_latest_artifact_project_level.rb
new file mode 100644
index 00000000000..3fc9fad1dc6
--- /dev/null
+++ b/db/migrate/20201204193952_keep_latest_artifact_project_level.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class KeepLatestArtifactProjectLevel < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :project_ci_cd_settings, :keep_latest_artifact, :boolean, default: true, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_ci_cd_settings, :keep_latest_artifact
+ end
+ end
+end
diff --git a/db/migrate/20201208210209_create_incident_management_oncall_shifts.rb b/db/migrate/20201208210209_create_incident_management_oncall_shifts.rb
new file mode 100644
index 00000000000..49cb32ffee0
--- /dev/null
+++ b/db/migrate/20201208210209_create_incident_management_oncall_shifts.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class CreateIncidentManagementOncallShifts < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ unless table_exists?(:incident_management_oncall_shifts)
+ with_lock_retries do
+ create_table :incident_management_oncall_shifts do |t|
+ t.references :rotation, null: false, foreign_key: { to_table: :incident_management_oncall_rotations, on_delete: :cascade }
+ t.references :participant, null: false, foreign_key: { to_table: :incident_management_oncall_participants, on_delete: :cascade }
+ t.datetime_with_timezone :starts_at, null: false
+ t.datetime_with_timezone :ends_at, null: false
+ end
+
+ execute <<~SQL
+ ALTER TABLE incident_management_oncall_shifts
+ ADD CONSTRAINT inc_mgmnt_no_overlapping_oncall_shifts
+ EXCLUDE USING gist
+ ( rotation_id WITH =,
+ tstzrange(starts_at, ends_at, '[)') WITH &&
+ )
+ SQL
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :incident_management_oncall_shifts
+ end
+ end
+end
diff --git a/db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb b/db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb
new file mode 100644
index 00000000000..48292cce55b
--- /dev/null
+++ b/db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class AddCodeChallengeToOauthAccessGrants < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column(:oauth_access_grants, :code_challenge, :text, null: true) unless column_exists?(:oauth_access_grants, :code_challenge)
+ # If `code_challenge_method` is 'plain' the length is at most 128 characters as per the spec
+ # https://tools.ietf.org/html/rfc7636#section-4.1
+ # Otherwise the max length of base64(SHA256(code_verifier)) is 44 characters
+ add_text_limit(:oauth_access_grants, :code_challenge, 128, constraint_name: 'oauth_access_grants_code_challenge')
+
+ add_column(:oauth_access_grants, :code_challenge_method, :text, null: true) unless column_exists?(:oauth_access_grants, :code_challenge_method)
+ # Values are either 'plain' or 'S256'
+ add_text_limit(:oauth_access_grants, :code_challenge_method, 5, constraint_name: 'oauth_access_grants_code_challenge_method')
+ end
+
+ def down
+ remove_column(:oauth_access_grants, :code_challenge)
+ remove_column(:oauth_access_grants, :code_challenge_method)
+ end
+end
diff --git a/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb b/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb
new file mode 100644
index 00000000000..62d0cdae8bc
--- /dev/null
+++ b/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddVersionShaCacheToComposerMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :packages_composer_metadata, :version_cache_sha, :binary, null: true
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :packages_composer_metadata, :version_cache_sha, :binary
+ 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
new file mode 100644
index 00000000000..0d97d54f3e4
--- /dev/null
+++ b/db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb
@@ -0,0 +1,17 @@
+class ChangeMrAllowMaintainerToPushDefault < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ change_column_default :merge_requests, :allow_maintainer_to_push, from: nil, to: true
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :merge_requests, :allow_maintainer_to_push, from: true, to: nil
+ end
+ end
+end
diff --git a/db/migrate/20201214032220_add_has_external_wiki_trigger.rb b/db/migrate/20201214032220_add_has_external_wiki_trigger.rb
new file mode 100644
index 00000000000..f6e066b75da
--- /dev/null
+++ b/db/migrate/20201214032220_add_has_external_wiki_trigger.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+class AddHasExternalWikiTrigger < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::SchemaHelpers
+
+ DOWNTIME = false
+ FUNCTION_NAME = 'set_has_external_wiki'.freeze
+ TRIGGER_ON_INSERT_NAME = 'trigger_has_external_wiki_on_insert'.freeze
+ TRIGGER_ON_UPDATE_NAME = 'trigger_has_external_wiki_on_update'.freeze
+ TRIGGER_ON_DELETE_NAME = 'trigger_has_external_wiki_on_delete'.freeze
+
+ def up
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ UPDATE projects SET has_external_wiki = COALESCE(NEW.active, FALSE)
+ 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.active = TRUE AND NEW.type = 'ExternalWikiService' 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.type = 'ExternalWikiService' 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.type = 'ExternalWikiService' 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/20201214111858_add_container_registry_cleanup_tags_service_max_list_size_to_application_settings.rb b/db/migrate/20201214111858_add_container_registry_cleanup_tags_service_max_list_size_to_application_settings.rb
new file mode 100644
index 00000000000..312220914c1
--- /dev/null
+++ b/db/migrate/20201214111858_add_container_registry_cleanup_tags_service_max_list_size_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddContainerRegistryCleanupTagsServiceMaxListSizeToApplicationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column(:application_settings, :container_registry_cleanup_tags_service_max_list_size, :integer, default: 200, null: false)
+ end
+end
diff --git a/db/migrate/20201214112752_add_app_settings_container_reg_cleanup_tags_service_max_list_size_constraint.rb b/db/migrate/20201214112752_add_app_settings_container_reg_cleanup_tags_service_max_list_size_constraint.rb
new file mode 100644
index 00000000000..935dd641b4c
--- /dev/null
+++ b/db/migrate/20201214112752_add_app_settings_container_reg_cleanup_tags_service_max_list_size_constraint.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddAppSettingsContainerRegCleanupTagsServiceMaxListSizeConstraint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ CONSTRAINT_NAME = 'app_settings_container_reg_cleanup_tags_max_list_size_positive'
+
+ disable_ddl_transaction!
+
+ def up
+ add_check_constraint :application_settings, 'container_registry_cleanup_tags_service_max_list_size >= 0', CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :application_settings, CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20201214184020_add_epic_board_list.rb b/db/migrate/20201214184020_add_epic_board_list.rb
new file mode 100644
index 00000000000..9c4e3280754
--- /dev/null
+++ b/db/migrate/20201214184020_add_epic_board_list.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class AddEpicBoardList < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:boards_epic_lists)
+ with_lock_retries do
+ create_table :boards_epic_lists do |t|
+ t.timestamps_with_timezone
+ t.references :epic_board, index: true, foreign_key: { to_table: :boards_epic_boards, on_delete: :cascade }, null: false
+ t.references :label, index: true, foreign_key: { on_delete: :cascade }
+ t.integer :position
+ t.integer :list_type, default: 1, limit: 2, null: false
+
+ t.index [:epic_board_id, :label_id], unique: true, where: 'list_type = 1', name: 'index_boards_epic_lists_on_epic_board_id_and_label_id'
+ end
+ end
+ end
+
+ add_check_constraint :boards_epic_lists, '(list_type <> 1) OR ("position" IS NOT NULL AND "position" >= 0)', 'boards_epic_lists_position_constraint'
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :boards_epic_lists
+ end
+ end
+end
diff --git a/db/migrate/20201215205404_create_namespace_package_settings.rb b/db/migrate/20201215205404_create_namespace_package_settings.rb
new file mode 100644
index 00000000000..d74b99597ce
--- /dev/null
+++ b/db/migrate/20201215205404_create_namespace_package_settings.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class CreateNamespacePackageSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ create_table :namespace_package_settings, if_not_exists: true, id: false do |t|
+ t.references :namespace, primary_key: true, index: false, default: nil, foreign_key: { to_table: :namespaces, on_delete: :cascade }, type: :bigint
+ t.boolean :maven_duplicates_allowed, null: false, default: true
+ t.text :maven_duplicate_exception_regex, null: false, default: ''
+ end
+ end
+
+ add_text_limit :namespace_package_settings, :maven_duplicate_exception_regex, 255
+ end
+
+ def down
+ drop_table :namespace_package_settings
+ end
+end
diff --git a/db/migrate/20201216151616_add_squash_commit_sha_index.rb b/db/migrate/20201216151616_add_squash_commit_sha_index.rb
new file mode 100644
index 00000000000..ac6d3fda2d2
--- /dev/null
+++ b/db/migrate/20201216151616_add_squash_commit_sha_index.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddSquashCommitShaIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = "index_merge_requests_on_target_project_id_and_squash_commit_sha"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests,
+ [:target_project_id, :squash_commit_sha],
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :merge_requests,
+ [:target_project_id, :squash_commit_sha],
+ name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201216154457_add_devops_adoption_snapshot_range_end.rb b/db/migrate/20201216154457_add_devops_adoption_snapshot_range_end.rb
new file mode 100644
index 00000000000..ada1bd9b346
--- /dev/null
+++ b/db/migrate/20201216154457_add_devops_adoption_snapshot_range_end.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddDevopsAdoptionSnapshotRangeEnd < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :analytics_devops_adoption_snapshots, :end_time, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20201217070530_add_group_merge_request_approval_settings.rb b/db/migrate/20201217070530_add_group_merge_request_approval_settings.rb
new file mode 100644
index 00000000000..dba9e6e440f
--- /dev/null
+++ b/db/migrate/20201217070530_add_group_merge_request_approval_settings.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class AddGroupMergeRequestApprovalSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ create_table :group_merge_request_approval_settings, id: false do |t|
+ t.timestamps_with_timezone null: false
+ t.references :group, references: :namespaces, primary_key: true, default: nil, index: false,
+ foreign_key: { to_table: :namespaces, on_delete: :cascade }
+ t.boolean :allow_author_approval, null: false, default: false
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :group_merge_request_approval_settings
+ end
+ end
+end
diff --git a/db/migrate/20201217132603_create_elastic_reindexing_subtasks.rb b/db/migrate/20201217132603_create_elastic_reindexing_subtasks.rb
new file mode 100644
index 00000000000..db084b885c2
--- /dev/null
+++ b/db/migrate/20201217132603_create_elastic_reindexing_subtasks.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class CreateElasticReindexingSubtasks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class ReindexingTask < ActiveRecord::Base
+ self.table_name = 'elastic_reindexing_tasks'
+ end
+
+ class ReindexingSubtask < ActiveRecord::Base
+ self.table_name = 'elastic_reindexing_subtasks'
+ end
+
+ def up
+ unless table_exists?(:elastic_reindexing_subtasks)
+ create_table :elastic_reindexing_subtasks do |t|
+ t.references :elastic_reindexing_task, foreign_key: { on_delete: :cascade }, null: false
+ t.text :alias_name, null: false
+ t.text :index_name_from, null: false
+ t.text :index_name_to, null: false
+ t.text :elastic_task, null: false
+ t.integer :documents_count_target
+ t.integer :documents_count
+ t.timestamps_with_timezone null: false
+ end
+ end
+
+ add_text_limit :elastic_reindexing_subtasks, :index_name_from, 255
+ add_text_limit :elastic_reindexing_subtasks, :index_name_to, 255
+ add_text_limit :elastic_reindexing_subtasks, :elastic_task, 255
+ add_text_limit :elastic_reindexing_subtasks, :alias_name, 255
+
+ ReindexingTask.find_each do |task|
+ next if task.index_name_from.blank? || task.index_name_to.blank? || task.elastic_task.blank?
+ next if ReindexingSubtask.where(elastic_reindexing_task_id: task.id).exists?
+
+ ReindexingSubtask.create(
+ elastic_reindexing_task_id: task.id,
+ documents_count_target: task.documents_count_target,
+ documents_count: task.documents_count,
+ alias_name: 'gitlab-production',
+ index_name_from: task.index_name_from,
+ index_name_to: task.index_name_to,
+ elastic_task: task.elastic_task
+ )
+ end
+ end
+
+ def down
+ drop_table :elastic_reindexing_subtasks
+ end
+end
diff --git a/db/migrate/20201221124036_add_devops_snapshot_index.rb b/db/migrate/20201221124036_add_devops_snapshot_index.rb
new file mode 100644
index 00000000000..85001e9abcf
--- /dev/null
+++ b/db/migrate/20201221124036_add_devops_snapshot_index.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddDevopsSnapshotIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_on_snapshots_segment_id_end_time'
+
+ def up
+ add_concurrent_index :analytics_devops_adoption_snapshots, [:segment_id, :end_time], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :analytics_devops_adoption_snapshots, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20201221213415_change_clusters_helm_major_version_default_to_3.rb b/db/migrate/20201221213415_change_clusters_helm_major_version_default_to_3.rb
new file mode 100644
index 00000000000..baec0da208b
--- /dev/null
+++ b/db/migrate/20201221213415_change_clusters_helm_major_version_default_to_3.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ChangeClustersHelmMajorVersionDefaultTo3 < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_column_default(:clusters, :helm_major_version, from: 2, to: 3)
+ end
+end
diff --git a/db/migrate/20201223114050_add_restrict_user_defined_variables_to_project_settings.rb b/db/migrate/20201223114050_add_restrict_user_defined_variables_to_project_settings.rb
new file mode 100644
index 00000000000..d04c6981bf9
--- /dev/null
+++ b/db/migrate/20201223114050_add_restrict_user_defined_variables_to_project_settings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddRestrictUserDefinedVariablesToProjectSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :project_ci_cd_settings, :restrict_user_defined_variables, :boolean, default: false, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_ci_cd_settings, :restrict_user_defined_variables
+ end
+ end
+end
diff --git a/db/migrate/20201224144948_migrate_coverage_report_worker.rb b/db/migrate/20201224144948_migrate_coverage_report_worker.rb
new file mode 100644
index 00000000000..a13e5e859e0
--- /dev/null
+++ b/db/migrate/20201224144948_migrate_coverage_report_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class MigrateCoverageReportWorker < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'ci_pipelines_create_artifact', to: 'ci_pipeline_artifacts_coverage_report'
+ end
+
+ def down
+ sidekiq_queue_migrate 'ci_pipeline_artifacts_coverage_report', to: 'ci_pipelines_create_artifact'
+ end
+end
diff --git a/db/migrate/20201228184500_add_dismissal_reason_into_vulnerability_feedback_table.rb b/db/migrate/20201228184500_add_dismissal_reason_into_vulnerability_feedback_table.rb
new file mode 100644
index 00000000000..92484aced4e
--- /dev/null
+++ b/db/migrate/20201228184500_add_dismissal_reason_into_vulnerability_feedback_table.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddDismissalReasonIntoVulnerabilityFeedbackTable < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :vulnerability_feedback, :dismissal_reason, :smallint
+ end
+
+ def down
+ remove_column :vulnerability_feedback, :dismissal_reason
+ end
+end
diff --git a/db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb b/db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb
new file mode 100644
index 00000000000..025fcba0729
--- /dev/null
+++ b/db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddInvisibleCaptchaEnabledToSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :invisible_captcha_enabled, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20201230161206_add_rate_limiting_response_text_to_application_settings.rb b/db/migrate/20201230161206_add_rate_limiting_response_text_to_application_settings.rb
new file mode 100644
index 00000000000..647455f5f88
--- /dev/null
+++ b/db/migrate/20201230161206_add_rate_limiting_response_text_to_application_settings.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddRateLimitingResponseTextToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20210101110640_set_limit_for_rate_limiting_response_text
+ def change
+ add_column :application_settings, :rate_limiting_response_text, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20201230180202_create_onboarding_progress.rb b/db/migrate/20201230180202_create_onboarding_progress.rb
new file mode 100644
index 00000000000..b9fe64eb19d
--- /dev/null
+++ b/db/migrate/20201230180202_create_onboarding_progress.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class CreateOnboardingProgress < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ create_table :onboarding_progresses do |t|
+ t.references :namespace, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
+ t.timestamps_with_timezone null: false
+ t.datetime_with_timezone :git_pull_at
+ t.datetime_with_timezone :git_write_at
+ t.datetime_with_timezone :merge_request_created_at
+ t.datetime_with_timezone :pipeline_created_at
+ t.datetime_with_timezone :user_added_at
+ t.datetime_with_timezone :trial_started_at
+ t.datetime_with_timezone :subscription_created_at
+ t.datetime_with_timezone :required_mr_approvals_enabled_at
+ t.datetime_with_timezone :code_owners_enabled_at
+ t.datetime_with_timezone :scoped_label_created_at
+ t.datetime_with_timezone :security_scan_enabled_at
+ t.datetime_with_timezone :issue_auto_closed_at
+ t.datetime_with_timezone :repository_imported_at
+ t.datetime_with_timezone :repository_mirrored_at
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :onboarding_progresses
+ end
+ end
+end
diff --git a/db/migrate/20210101110640_set_limit_for_rate_limiting_response_text.rb b/db/migrate/20210101110640_set_limit_for_rate_limiting_response_text.rb
new file mode 100644
index 00000000000..b72f2ae7d70
--- /dev/null
+++ b/db/migrate/20210101110640_set_limit_for_rate_limiting_response_text.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class SetLimitForRateLimitingResponseText < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :rate_limiting_response_text, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :rate_limiting_response_text
+ end
+end
diff --git a/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb b/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb
new file mode 100644
index 00000000000..0ecf194eb97
--- /dev/null
+++ b/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class DropTemporaryIndexOnCiBuilds < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX = 'tmp_build_stage_position_index'.freeze
+
+ def up
+ remove_concurrent_index_by_name :ci_builds, INDEX
+ end
+
+ def down
+ add_concurrent_index :ci_builds, [:stage_id, :stage_idx], where: 'stage_idx IS NOT NULL', name: INDEX
+ end
+end
diff --git a/db/migrate/20210104163218_add_epic_board_position_index.rb b/db/migrate/20210104163218_add_epic_board_position_index.rb
new file mode 100644
index 00000000000..32c829f0288
--- /dev/null
+++ b/db/migrate/20210104163218_add_epic_board_position_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddEpicBoardPositionIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_boards_epic_board_positions_on_scoped_relative_position'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :boards_epic_board_positions, [:epic_board_id, :epic_id, :relative_position], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :boards_epic_board_positions, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210106153021_drop_tmp_index_on_emails.rb b/db/migrate/20210106153021_drop_tmp_index_on_emails.rb
new file mode 100644
index 00000000000..94b4a5437af
--- /dev/null
+++ b/db/migrate/20210106153021_drop_tmp_index_on_emails.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class DropTmpIndexOnEmails < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ EMAIL_INDEX_NAME = 'tmp_index_for_email_unconfirmation_migration'
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal('WrongfullyConfirmedEmailUnconfirmer')
+
+ remove_concurrent_index_by_name(:emails, EMAIL_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:emails, :id, where: 'confirmed_at IS NOT NULL', name: EMAIL_INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210108161039_update_max_import_size_default.rb b/db/migrate/20210108161039_update_max_import_size_default.rb
new file mode 100644
index 00000000000..5f0591b2766
--- /dev/null
+++ b/db/migrate/20210108161039_update_max_import_size_default.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class UpdateMaxImportSizeDefault < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_column_default(:application_settings, :max_import_size, from: 50, to: 0)
+ end
+end
diff --git a/db/migrate/20210112084512_drop_tmp_index_on_emails_again.rb b/db/migrate/20210112084512_drop_tmp_index_on_emails_again.rb
new file mode 100644
index 00000000000..6c2f9cbcb32
--- /dev/null
+++ b/db/migrate/20210112084512_drop_tmp_index_on_emails_again.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class DropTmpIndexOnEmailsAgain < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ EMAIL_INDEX_NAME = 'tmp_index_for_email_unconfirmation_migration'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name(:emails, EMAIL_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:emails, :id, where: 'confirmed_at IS NOT NULL', name: EMAIL_INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210114033715_remove_group_id_title_index.rb b/db/migrate/20210114033715_remove_group_id_title_index.rb
new file mode 100644
index 00000000000..8d63da3d400
--- /dev/null
+++ b/db/migrate/20210114033715_remove_group_id_title_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveGroupIdTitleIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_labels_on_group_id_and_title_with_null_project_id'
+ LABELS_TABLE = :labels
+
+ def up
+ remove_concurrent_index_by_name LABELS_TABLE, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index LABELS_TABLE, [:group_id, :title], where: 'project_id IS NULL', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20190402224749_schedule_merge_request_assignees_migration_progress_check.rb b/db/post_migrate/20190402224749_schedule_merge_request_assignees_migration_progress_check.rb
index 6fb67deb834..8ec6a4a24ec 100644
--- a/db/post_migrate/20190402224749_schedule_merge_request_assignees_migration_progress_check.rb
+++ b/db/post_migrate/20190402224749_schedule_merge_request_assignees_migration_progress_check.rb
@@ -3,7 +3,7 @@
class ScheduleMergeRequestAssigneesMigrationProgressCheck < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
- MIGRATION = 'MergeRequestAssigneesMigrationProgressCheck'.freeze
+ MIGRATION = 'MergeRequestAssigneesMigrationProgressCheck'
DOWNTIME = false
diff --git a/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb b/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb
index cee99f7cf2e..845c855358b 100644
--- a/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb
+++ b/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb
@@ -20,8 +20,8 @@ class ScheduleSyncIssuablesStateIdWhereNil < ActiveRecord::Migration[5.1]
#
BATCH_SIZE = 5000
DELAY_INTERVAL = 120.seconds.to_i
- ISSUES_MIGRATION = 'SyncIssuesStateId'.freeze
- MERGE_REQUESTS_MIGRATION = 'SyncMergeRequestsStateId'.freeze
+ ISSUES_MIGRATION = 'SyncIssuesStateId'
+ MERGE_REQUESTS_MIGRATION = 'SyncMergeRequestsStateId'
disable_ddl_transaction!
diff --git a/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb b/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb
index 342e83d6322..5b9afbe128c 100644
--- a/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb
+++ b/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb
@@ -7,9 +7,9 @@ class AddIndexToEventsAndAuditEventsCreatedAtAuthorId < ActiveRecord::Migration[
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- INDEX_NAME = 'analytics_index_%s_on_created_at_and_author_id'.freeze
- EVENTS_INDEX_NAME = (INDEX_NAME % 'events').freeze
- AUDIT_EVENTS_INDEX_NAME = (INDEX_NAME % 'audit_events').freeze
+ INDEX_NAME = 'analytics_index_%s_on_created_at_and_author_id'
+ EVENTS_INDEX_NAME = (INDEX_NAME % 'events')
+ AUDIT_EVENTS_INDEX_NAME = (INDEX_NAME % 'audit_events')
disable_ddl_transaction!
diff --git a/db/post_migrate/20191030223057_backfill_version_author_and_created_at.rb b/db/post_migrate/20191030223057_backfill_version_author_and_created_at.rb
index 7a6d0b089a0..5fcec83bfc3 100644
--- a/db/post_migrate/20191030223057_backfill_version_author_and_created_at.rb
+++ b/db/post_migrate/20191030223057_backfill_version_author_and_created_at.rb
@@ -2,7 +2,7 @@
class BackfillVersionAuthorAndCreatedAt < ActiveRecord::Migration[5.2]
DOWNTIME = false
- MIGRATION = 'BackfillVersionDataFromGitaly'.freeze
+ MIGRATION = 'BackfillVersionDataFromGitaly'
BATCH_SIZE = 500
disable_ddl_transaction!
diff --git a/db/post_migrate/20191104142124_nullify_users_role.rb b/db/post_migrate/20191104142124_nullify_users_role.rb
index 540d58e95ba..ab8eae46745 100644
--- a/db/post_migrate/20191104142124_nullify_users_role.rb
+++ b/db/post_migrate/20191104142124_nullify_users_role.rb
@@ -4,7 +4,7 @@ class NullifyUsersRole < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
- INDEX_NAME = 'partial_index_users_updated_at_for_cleaning_mistaken_values'.freeze
+ INDEX_NAME = 'partial_index_users_updated_at_for_cleaning_mistaken_values'
DOWNTIME = false
diff --git a/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb b/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb
index 83ba56501dd..d25d6ed2dc7 100644
--- a/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb
+++ b/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb
@@ -5,7 +5,7 @@ class ScheduleFixOrphanPromotedIssues < ActiveRecord::Migration[5.2]
DOWNTIME = false
BATCH_SIZE = 100
- BACKGROUND_MIGRATION = 'FixOrphanPromotedIssues'.freeze
+ BACKGROUND_MIGRATION = 'FixOrphanPromotedIssues'
disable_ddl_transaction!
diff --git a/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb b/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb
index 7ef204ed9de..087c189f9fd 100644
--- a/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb
+++ b/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb
@@ -6,7 +6,7 @@ class ScheduleMigrateSecurityScans < ActiveRecord::Migration[5.2]
DOWNTIME = false
INTERVAL = 2.minutes.to_i
BATCH_SIZE = 10_000
- MIGRATION = 'MigrateSecurityScans'.freeze
+ MIGRATION = 'MigrateSecurityScans'
disable_ddl_transaction!
diff --git a/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb b/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
new file mode 100644
index 00000000000..f19a209092b
--- /dev/null
+++ b/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+class RemoveDuplicateLabelsFromGroup < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ CREATE = 1
+ RENAME = 2
+
+ disable_ddl_transaction!
+
+ class BackupLabel < ApplicationRecord
+ include EachBatch
+
+ self.table_name = 'backup_labels'
+ end
+
+ class Label < ApplicationRecord
+ self.table_name = 'labels'
+ end
+
+ class Group < ApplicationRecord
+ include EachBatch
+
+ self.table_name = 'namespaces'
+ end
+
+ BATCH_SIZE = 10_000
+
+ def up
+ # Split to smaller chunks
+ # Loop rather than background job, every 10,000
+ # there are ~1,800,000 groups in total (excluding personal namespaces, which can't have labels)
+ Group.where(type: 'Group').each_batch(of: BATCH_SIZE) do |batch|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ transaction do
+ remove_full_duplicates(*range)
+ end
+
+ transaction do
+ rename_partial_duplicates(*range)
+ end
+ end
+ end
+
+ DOWN_BATCH_SIZE = 1000
+
+ def down
+ BackupLabel.where('project_id IS NULL AND group_id IS NOT NULL').each_batch(of: DOWN_BATCH_SIZE) do |batch|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ restore_renamed_labels(*range)
+ restore_deleted_labels(*range)
+ end
+ end
+
+ def remove_full_duplicates(start_id, stop_id)
+ # Fields that are considered duplicate:
+ # group_id title template description type color
+
+ duplicate_labels = ApplicationRecord.connection.execute(<<-SQL.squish)
+WITH data AS (
+ SELECT labels.*,
+ row_number() OVER (PARTITION BY labels.group_id, labels.title, labels.template, labels.description, labels.type, labels.color ORDER BY labels.id) AS row_number,
+ #{CREATE} AS restore_action
+ FROM labels
+ WHERE labels.group_id BETWEEN #{start_id} AND #{stop_id}
+ AND NOT EXISTS (SELECT * FROM board_labels WHERE board_labels.label_id = labels.id)
+ AND NOT EXISTS (SELECT * FROM label_links WHERE label_links.label_id = labels.id)
+ AND NOT EXISTS (SELECT * FROM label_priorities WHERE label_priorities.label_id = labels.id)
+ AND NOT EXISTS (SELECT * FROM lists WHERE lists.label_id = labels.id)
+ AND NOT EXISTS (SELECT * FROM resource_label_events WHERE resource_label_events.label_id = labels.id)
+) SELECT * FROM data WHERE row_number > 1;
+ SQL
+
+ if duplicate_labels.any?
+ # create backup records
+ BackupLabel.insert_all!(duplicate_labels.map { |label| label.except("row_number") })
+
+ Label.unscoped.where(id: duplicate_labels.pluck("id")).delete_all
+ end
+ end
+
+ def rename_partial_duplicates(start_id, stop_id)
+ # We need to ensure that the new title (with `_duplicate#{ID}`) doesn't exceed the limit.
+ # Truncate the original title (if needed) to 245 characters minus the length of the ID
+ # then add `_duplicate#{ID}`
+
+ soft_duplicates = ApplicationRecord.connection.execute(<<-SQL.squish)
+WITH data AS (
+ SELECT
+ *,
+ substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text as new_title,
+ #{RENAME} AS restore_action,
+ row_number() OVER (PARTITION BY group_id, title ORDER BY id) AS row_number
+ FROM labels
+ WHERE group_id BETWEEN #{start_id} AND #{stop_id}
+) SELECT * FROM data WHERE row_number > 1;
+ SQL
+
+ if soft_duplicates.any?
+ # create backup records
+ BackupLabel.insert_all!(soft_duplicates.map { |label| label.except("row_number") })
+
+ ApplicationRecord.connection.execute(<<-SQL.squish)
+UPDATE labels SET title = substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text
+WHERE labels.id IN (#{soft_duplicates.map { |dup| dup["id"] }.join(", ")});
+ SQL
+ end
+ end
+
+ def restore_renamed_labels(start_id, stop_id)
+ # the backup label IDs are not incremental, they are copied directly from the Labels table
+ ApplicationRecord.connection.execute(<<-SQL.squish)
+WITH backups AS (
+ SELECT id, title
+ FROM backup_labels
+ WHERE id BETWEEN #{start_id} AND #{stop_id}
+ AND restore_action = #{RENAME}
+) UPDATE labels SET title = backups.title
+FROM backups
+WHERE labels.id = backups.id;
+ SQL
+ end
+
+ def restore_deleted_labels(start_id, stop_id)
+ ActiveRecord::Base.connection.execute(<<-SQL.squish)
+INSERT INTO labels
+SELECT id, title, color, group_id, created_at, updated_at, template, description, description_html, type, cached_markdown_version FROM backup_labels
+ WHERE backup_labels.id BETWEEN #{start_id} AND #{stop_id}
+ AND backup_labels.project_id IS NULL AND backup_labels.group_id IS NOT NULL
+ AND backup_labels.restore_action = #{CREATE}
+ SQL
+ end
+end
diff --git a/db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb b/db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb
new file mode 100644
index 00000000000..08bab811c00
--- /dev/null
+++ b/db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddUniquenessIndexToLabelTitleAndGroup < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ GROUP_AND_TITLE = [:group_id, :title]
+
+ def up
+ add_concurrent_index :labels, GROUP_AND_TITLE, where: "labels.project_id IS NULL", unique: true, name: "index_labels_on_group_id_and_title_unique"
+ remove_concurrent_index :labels, GROUP_AND_TITLE, name: "index_labels_on_group_id_and_title"
+ end
+
+ def down
+ add_concurrent_index :labels, GROUP_AND_TITLE, where: "labels.project_id IS NULL", unique: false, name: "index_labels_on_group_id_and_title"
+ remove_concurrent_index :labels, GROUP_AND_TITLE, name: "index_labels_on_group_id_and_title_unique"
+ end
+end
diff --git a/db/post_migrate/20201207165956_remove_duplicate_services.rb b/db/post_migrate/20201207165956_remove_duplicate_services.rb
new file mode 100644
index 00000000000..1659b9a2095
--- /dev/null
+++ b/db/post_migrate/20201207165956_remove_duplicate_services.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class RemoveDuplicateServices < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ # noop, replaced by 20210112143418_remove_duplicate_services.rb
+ end
+
+ def down
+ end
+end
diff --git a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
new file mode 100644
index 00000000000..f11c0bbe33a
--- /dev/null
+++ b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class ScheduleBackfillingArtifactExpiryMigration < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ SWITCH_DATE = Time.utc(2020, 6, 22).freeze
+ INDEX_NAME = 'expired_artifacts_temp_index'.freeze
+ INDEX_CONDITION = "expire_at IS NULL AND created_at < '#{SWITCH_DATE}'"
+
+ 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('created_at < ?', SWITCH_DATE) }
+ end
+
+ def up
+ # Create temporary index for expired artifacts
+ # Needs to be removed in a later migration
+ 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,
+ ::Gitlab::BackgroundMigration::BackfillArtifactExpiryDate,
+ 2.minutes,
+ batch_size: 200_000
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20201211090634_schedule_populate_finding_uuid_for_vulnerability_feedback.rb b/db/post_migrate/20201211090634_schedule_populate_finding_uuid_for_vulnerability_feedback.rb
new file mode 100644
index 00000000000..3ecb48dab0f
--- /dev/null
+++ b/db/post_migrate/20201211090634_schedule_populate_finding_uuid_for_vulnerability_feedback.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class SchedulePopulateFindingUuidForVulnerabilityFeedback < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION_CLASS = 'PopulateFindingUuidForVulnerabilityFeedback'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 1000
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback::VulnerabilityFeedback,
+ MIGRATION_CLASS,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20201216185336_add_devops_adoption_snapshot_not_null.rb b/db/post_migrate/20201216185336_add_devops_adoption_snapshot_not_null.rb
new file mode 100644
index 00000000000..1bb3c57f3cd
--- /dev/null
+++ b/db/post_migrate/20201216185336_add_devops_adoption_snapshot_not_null.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class AddDevopsAdoptionSnapshotNotNull < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute(
+ <<~SQL
+ LOCK TABLE analytics_devops_adoption_snapshots IN ACCESS EXCLUSIVE MODE;
+
+ UPDATE analytics_devops_adoption_snapshots SET end_time = date_trunc('month', recorded_at) - interval '1 millisecond';
+
+ ALTER TABLE analytics_devops_adoption_snapshots ALTER COLUMN end_time SET NOT NULL;
+ SQL
+ )
+ end
+ end
+
+ def down
+ with_lock_retries do
+ execute(<<~SQL)
+ ALTER TABLE analytics_devops_adoption_snapshots ALTER COLUMN end_time DROP NOT NULL;
+ SQL
+ end
+ end
+end
diff --git a/db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb b/db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb
new file mode 100644
index 00000000000..9ed1aea911a
--- /dev/null
+++ b/db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class ReindexCiPipelinesOnScheduleIdAndId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ OLD_INDEX_NAME = 'index_ci_pipelines_on_pipeline_schedule_id'
+ NEW_INDEX_NAME = 'index_ci_pipelines_on_pipeline_schedule_id_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipelines, [:pipeline_schedule_id, :id], name: NEW_INDEX_NAME
+ remove_concurrent_index_by_name :ci_pipelines, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :ci_pipelines, :pipeline_schedule_id, name: OLD_INDEX_NAME
+ remove_concurrent_index_by_name :ci_pipelines, NEW_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20210105103649_delete_column_group_id_on_compliance_framework.rb b/db/post_migrate/20210105103649_delete_column_group_id_on_compliance_framework.rb
new file mode 100644
index 00000000000..b13d2fe2d0a
--- /dev/null
+++ b/db/post_migrate/20210105103649_delete_column_group_id_on_compliance_framework.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class DeleteColumnGroupIdOnComplianceFramework < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ remove_column :compliance_management_frameworks, :group_id, :bigint
+ end
+end
diff --git a/db/post_migrate/20210107194543_remove_alerts_service_records.rb b/db/post_migrate/20210107194543_remove_alerts_service_records.rb
new file mode 100644
index 00000000000..51a2f96ac7f
--- /dev/null
+++ b/db/post_migrate/20210107194543_remove_alerts_service_records.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveAlertsServiceRecords < 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/20210112143418_remove_duplicate_services2.rb b/db/post_migrate/20210112143418_remove_duplicate_services2.rb
new file mode 100644
index 00000000000..83d92a78473
--- /dev/null
+++ b/db/post_migrate/20210112143418_remove_duplicate_services2.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+# This replaces the previous post-deployment migration 20201207165956_remove_duplicate_services_spec.rb,
+# we have to run this again due to a bug in how we were receiving the arguments in the background migration.
+class RemoveDuplicateServices2 < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 5_000
+ MIGRATION = 'RemoveDuplicateServices'
+
+ disable_ddl_transaction!
+
+ def up
+ project_ids_with_duplicates = Gitlab::BackgroundMigration::RemoveDuplicateServices::Service.project_ids_with_duplicates
+
+ project_ids_with_duplicates.each_batch(of: BATCH_SIZE, column: :project_id) do |batch, index|
+ migrate_in(
+ INTERVAL * index,
+ MIGRATION,
+ batch.pluck(:project_id)
+ )
+ end
+ end
+
+ def down
+ end
+end
diff --git a/db/schema_migrations/20200716234259 b/db/schema_migrations/20200716234259
new file mode 100644
index 00000000000..51916bdc8af
--- /dev/null
+++ b/db/schema_migrations/20200716234259
@@ -0,0 +1 @@
+9683f55a327b9579b9b0b9484dd11a07b7ea4244b126c46e0144662cb25da6bb \ No newline at end of file
diff --git a/db/schema_migrations/20200716234518 b/db/schema_migrations/20200716234518
new file mode 100644
index 00000000000..c5f438dcfbe
--- /dev/null
+++ b/db/schema_migrations/20200716234518
@@ -0,0 +1 @@
+71cd12e553b3acbb665770fe7478365f1f082e2d278c67b166f41461f689aa5e \ No newline at end of file
diff --git a/db/schema_migrations/20201112215132 b/db/schema_migrations/20201112215132
new file mode 100644
index 00000000000..e478dd0f9bf
--- /dev/null
+++ b/db/schema_migrations/20201112215132
@@ -0,0 +1 @@
+a436597e876a6d9efc2c1558e05dc576cbbc6f829dc8059d62fc231bbf0ce2fa \ No newline at end of file
diff --git a/db/schema_migrations/20201204105300 b/db/schema_migrations/20201204105300
new file mode 100644
index 00000000000..e54d4f939b9
--- /dev/null
+++ b/db/schema_migrations/20201204105300
@@ -0,0 +1 @@
+15f48c654c08b58c90e46ce6e6413efa14d5a6e8299f100fc65f09f38190132a \ No newline at end of file
diff --git a/db/schema_migrations/20201204110700 b/db/schema_migrations/20201204110700
new file mode 100644
index 00000000000..b69e93149c2
--- /dev/null
+++ b/db/schema_migrations/20201204110700
@@ -0,0 +1 @@
+986ffa5e3e168ce9acf9b346c94bdee05d85c71abe238b8aa21f95cc472faabc \ No newline at end of file
diff --git a/db/schema_migrations/20201204110800 b/db/schema_migrations/20201204110800
new file mode 100644
index 00000000000..de1fdf7442a
--- /dev/null
+++ b/db/schema_migrations/20201204110800
@@ -0,0 +1 @@
+aecf517402d3decf8f7323e8f43fdfe7160cbe7542a474e392996abd75b2d70f \ No newline at end of file
diff --git a/db/schema_migrations/20201204111000 b/db/schema_migrations/20201204111000
new file mode 100644
index 00000000000..be3078cf503
--- /dev/null
+++ b/db/schema_migrations/20201204111000
@@ -0,0 +1 @@
+e9ca7eb8a47f6c48667135eca26f729471f8bb4ffa91dfceea87d98c8f2a616b \ No newline at end of file
diff --git a/db/schema_migrations/20201204111100 b/db/schema_migrations/20201204111100
new file mode 100644
index 00000000000..db3832d5331
--- /dev/null
+++ b/db/schema_migrations/20201204111100
@@ -0,0 +1 @@
+b613f8654641948b2933910ebbfc926fd801b18c00a5d23b1c801a9ba9925520 \ No newline at end of file
diff --git a/db/schema_migrations/20201204193952 b/db/schema_migrations/20201204193952
new file mode 100644
index 00000000000..4dcea03722f
--- /dev/null
+++ b/db/schema_migrations/20201204193952
@@ -0,0 +1 @@
+39e5550b6ad6f718a51cf9838ac9148bcaa070aff60f6114bd96e4a76faf2ca1 \ No newline at end of file
diff --git a/db/schema_migrations/20201207165956 b/db/schema_migrations/20201207165956
new file mode 100644
index 00000000000..4bded1d3152
--- /dev/null
+++ b/db/schema_migrations/20201207165956
@@ -0,0 +1 @@
+1ad19d6b4bc37d24f61f158aa58e4ce6be75cc54722cdc59427c00522fd40b4c \ No newline at end of file
diff --git a/db/schema_migrations/20201208175117 b/db/schema_migrations/20201208175117
new file mode 100644
index 00000000000..caa1bcaedd8
--- /dev/null
+++ b/db/schema_migrations/20201208175117
@@ -0,0 +1 @@
+68971e7f9a722e98d9e611f614b5465de83ff3d4dc8c7a8078ed1db8f21e6590 \ No newline at end of file
diff --git a/db/schema_migrations/20201208210209 b/db/schema_migrations/20201208210209
new file mode 100644
index 00000000000..61679844170
--- /dev/null
+++ b/db/schema_migrations/20201208210209
@@ -0,0 +1 @@
+90b661656195e61c3b3ac43b8eebcdc06f462eb7e73a6201b2f2a8bc9dd519bf \ No newline at end of file
diff --git a/db/schema_migrations/20201209163958 b/db/schema_migrations/20201209163958
new file mode 100644
index 00000000000..081f12e64ea
--- /dev/null
+++ b/db/schema_migrations/20201209163958
@@ -0,0 +1 @@
+4bdd5eba48a76d8feab948857ec32ef7fe25e04e8633ee7d94fd059e73703472 \ No newline at end of file
diff --git a/db/schema_migrations/20201209193551 b/db/schema_migrations/20201209193551
new file mode 100644
index 00000000000..2eb96840500
--- /dev/null
+++ b/db/schema_migrations/20201209193551
@@ -0,0 +1 @@
+2278b1e4e19b5306e4b616eb87b622427ef2dcf73dae761739cb3106d5e64718 \ No newline at end of file
diff --git a/db/schema_migrations/20201211090634 b/db/schema_migrations/20201211090634
new file mode 100644
index 00000000000..0c11b8f85fb
--- /dev/null
+++ b/db/schema_migrations/20201211090634
@@ -0,0 +1 @@
+5117b71950bec3c6c746eaf4851c111a335bf2280075ddc2c73b60a30e23d907 \ No newline at end of file
diff --git a/db/schema_migrations/20201214000000 b/db/schema_migrations/20201214000000
new file mode 100644
index 00000000000..420b3f2768a
--- /dev/null
+++ b/db/schema_migrations/20201214000000
@@ -0,0 +1 @@
+58f2bd74adf8b4ef616c8f341053dbeaa8116430a0f4493cbf5f8456d7f4b907 \ No newline at end of file
diff --git a/db/schema_migrations/20201214032220 b/db/schema_migrations/20201214032220
new file mode 100644
index 00000000000..ec14b260583
--- /dev/null
+++ b/db/schema_migrations/20201214032220
@@ -0,0 +1 @@
+db23b5315386ad5d5fec5a14958769cc1e62a0a89ec3246edb9fc024607e917b \ No newline at end of file
diff --git a/db/schema_migrations/20201214111858 b/db/schema_migrations/20201214111858
new file mode 100644
index 00000000000..7d97a34eadf
--- /dev/null
+++ b/db/schema_migrations/20201214111858
@@ -0,0 +1 @@
+e3eb306d7956e396f038f07a20c674929fc4aae3e188b24e1087305b3fea8b4d \ No newline at end of file
diff --git a/db/schema_migrations/20201214112752 b/db/schema_migrations/20201214112752
new file mode 100644
index 00000000000..af432649dea
--- /dev/null
+++ b/db/schema_migrations/20201214112752
@@ -0,0 +1 @@
+59906a3528499dd9c0b4c30088539299c08383ad3b36be8c862a7cc9ef1d50b2 \ No newline at end of file
diff --git a/db/schema_migrations/20201214184020 b/db/schema_migrations/20201214184020
new file mode 100644
index 00000000000..5cf5065b251
--- /dev/null
+++ b/db/schema_migrations/20201214184020
@@ -0,0 +1 @@
+adce3c714064991e93f8a587da3d5892c47dbc14963fa49638ebbbf8b5489359 \ No newline at end of file
diff --git a/db/schema_migrations/20201215205404 b/db/schema_migrations/20201215205404
new file mode 100644
index 00000000000..147ede2064d
--- /dev/null
+++ b/db/schema_migrations/20201215205404
@@ -0,0 +1 @@
+b54cf8b75c5882f2dfca74b218a9eeac766ff65233d43de865717d3ab8c7a217 \ No newline at end of file
diff --git a/db/schema_migrations/20201216151616 b/db/schema_migrations/20201216151616
new file mode 100644
index 00000000000..a8b27610716
--- /dev/null
+++ b/db/schema_migrations/20201216151616
@@ -0,0 +1 @@
+f1c6927431895c6ce03fe7e0be30fcd0a1f4ccfeac8277ee0662d7434b97d257 \ No newline at end of file
diff --git a/db/schema_migrations/20201216154457 b/db/schema_migrations/20201216154457
new file mode 100644
index 00000000000..773218ff906
--- /dev/null
+++ b/db/schema_migrations/20201216154457
@@ -0,0 +1 @@
+c878874bbb9bf2314b90c1328d6e27846fe71513ba1ce688a262d36761b66665 \ No newline at end of file
diff --git a/db/schema_migrations/20201216185336 b/db/schema_migrations/20201216185336
new file mode 100644
index 00000000000..376429a2141
--- /dev/null
+++ b/db/schema_migrations/20201216185336
@@ -0,0 +1 @@
+3647e8b944aedeb58c41d9b3f08c8fb657fab231b0ff25c276f6d2aaa2ea93ae \ No newline at end of file
diff --git a/db/schema_migrations/20201217070530 b/db/schema_migrations/20201217070530
new file mode 100644
index 00000000000..c09f3b03e3b
--- /dev/null
+++ b/db/schema_migrations/20201217070530
@@ -0,0 +1 @@
+59e40a24e8422e64bc85c4d54e6da923512017bac6a167350affeff241046e9f \ No newline at end of file
diff --git a/db/schema_migrations/20201217132603 b/db/schema_migrations/20201217132603
new file mode 100644
index 00000000000..d1db386cbf5
--- /dev/null
+++ b/db/schema_migrations/20201217132603
@@ -0,0 +1 @@
+164bcc838beb7d51775f8b813b92d3ec7080d4c7937d6ad16cf973131b45359e \ No newline at end of file
diff --git a/db/schema_migrations/20201221124036 b/db/schema_migrations/20201221124036
new file mode 100644
index 00000000000..7a1049a7dd0
--- /dev/null
+++ b/db/schema_migrations/20201221124036
@@ -0,0 +1 @@
+15517956f3b5d7ce2c05d196a34881fa169df7b1bf5ccf0dbfbee74fb3143ba7 \ No newline at end of file
diff --git a/db/schema_migrations/20201221213415 b/db/schema_migrations/20201221213415
new file mode 100644
index 00000000000..74df483ac70
--- /dev/null
+++ b/db/schema_migrations/20201221213415
@@ -0,0 +1 @@
+8c123da6a380524c7269ffc67ea0e533a415d3c6eddf96cee4025ea152fc7582 \ No newline at end of file
diff --git a/db/schema_migrations/20201223012231 b/db/schema_migrations/20201223012231
new file mode 100644
index 00000000000..77813ca0655
--- /dev/null
+++ b/db/schema_migrations/20201223012231
@@ -0,0 +1 @@
+e845a6704ac92881926cca56bf7fb01c6252f1fe2b2d94fc9d6548144126d6a5 \ No newline at end of file
diff --git a/db/schema_migrations/20201223114050 b/db/schema_migrations/20201223114050
new file mode 100644
index 00000000000..25ac0eac211
--- /dev/null
+++ b/db/schema_migrations/20201223114050
@@ -0,0 +1 @@
+35acb5bbabfd12f97c988776aafa6ff380e2cbe2267e856b8f439f7102a6fbf2 \ No newline at end of file
diff --git a/db/schema_migrations/20201224144948 b/db/schema_migrations/20201224144948
new file mode 100644
index 00000000000..84e2816433c
--- /dev/null
+++ b/db/schema_migrations/20201224144948
@@ -0,0 +1 @@
+a83762c788d4ec007a26da386dc36bce16b60f5642ed3e6405482acfebefc1be \ No newline at end of file
diff --git a/db/schema_migrations/20201228184500 b/db/schema_migrations/20201228184500
new file mode 100644
index 00000000000..c6168e775b2
--- /dev/null
+++ b/db/schema_migrations/20201228184500
@@ -0,0 +1 @@
+9018fed4aab19642fafee3e50bf41be422fc3f8256d0b5d78c8a70fc96f4090f \ No newline at end of file
diff --git a/db/schema_migrations/20201229105948 b/db/schema_migrations/20201229105948
new file mode 100644
index 00000000000..73da30d5392
--- /dev/null
+++ b/db/schema_migrations/20201229105948
@@ -0,0 +1 @@
+cf391e617ef16f70c0daa4584959d36eda4b29c7e211f3f90ad74b4ebbc7ebbd \ No newline at end of file
diff --git a/db/schema_migrations/20201230161206 b/db/schema_migrations/20201230161206
new file mode 100644
index 00000000000..594ca5ea890
--- /dev/null
+++ b/db/schema_migrations/20201230161206
@@ -0,0 +1 @@
+b3fcc73c6b61469d770e9eb9a14c88bb86398db4ab4b6dc5283718a147db0ac0 \ No newline at end of file
diff --git a/db/schema_migrations/20201230180202 b/db/schema_migrations/20201230180202
new file mode 100644
index 00000000000..62a0e277a55
--- /dev/null
+++ b/db/schema_migrations/20201230180202
@@ -0,0 +1 @@
+c2766b50914c6b4d8c96fb958cdfb67f0d29e40df45654c35d62792c272e3d5a \ No newline at end of file
diff --git a/db/schema_migrations/20210101110640 b/db/schema_migrations/20210101110640
new file mode 100644
index 00000000000..e21e6768e7b
--- /dev/null
+++ b/db/schema_migrations/20210101110640
@@ -0,0 +1 @@
+8aac4108b658a7a0646ec230dc2568cb51fea0535b13dfba8b8c9e6edb401d07 \ No newline at end of file
diff --git a/db/schema_migrations/20210102164121 b/db/schema_migrations/20210102164121
new file mode 100644
index 00000000000..87f9b9e17f4
--- /dev/null
+++ b/db/schema_migrations/20210102164121
@@ -0,0 +1 @@
+d15dc3e57f050f037dd6b6b2b1efdafee49bf411580e35a7b4dbe14868c41e13 \ No newline at end of file
diff --git a/db/schema_migrations/20210104163218 b/db/schema_migrations/20210104163218
new file mode 100644
index 00000000000..c58a142f92e
--- /dev/null
+++ b/db/schema_migrations/20210104163218
@@ -0,0 +1 @@
+37aa0564d2ade1cab56a669facccbaaf08e4d9856c7a4cc120968d33cff161bd \ No newline at end of file
diff --git a/db/schema_migrations/20210105103649 b/db/schema_migrations/20210105103649
new file mode 100644
index 00000000000..9b00aa2524c
--- /dev/null
+++ b/db/schema_migrations/20210105103649
@@ -0,0 +1 @@
+0a318fbcf54860d9fe8b3e8372e10331d2b52df738e621f4b0eec5fd4f255739 \ No newline at end of file
diff --git a/db/schema_migrations/20210106153021 b/db/schema_migrations/20210106153021
new file mode 100644
index 00000000000..a00c59a8534
--- /dev/null
+++ b/db/schema_migrations/20210106153021
@@ -0,0 +1 @@
+71e005116082a59e40194fe5f9a500e31d67a011500d12aeecd59cb64d611848 \ No newline at end of file
diff --git a/db/schema_migrations/20210107194543 b/db/schema_migrations/20210107194543
new file mode 100644
index 00000000000..997bdd98b5a
--- /dev/null
+++ b/db/schema_migrations/20210107194543
@@ -0,0 +1 @@
+d72cf1c88a060ccadd9f90cbef5ae7d4ea6a4416a6263d11a870e01b02d1f935 \ No newline at end of file
diff --git a/db/schema_migrations/20210108161039 b/db/schema_migrations/20210108161039
new file mode 100644
index 00000000000..d60bab2ec5a
--- /dev/null
+++ b/db/schema_migrations/20210108161039
@@ -0,0 +1 @@
+7888a82e3bbc1f4c78badcbe8335ac823ebdedec843a9d90f91cf0d5c169a191 \ No newline at end of file
diff --git a/db/schema_migrations/20210112084512 b/db/schema_migrations/20210112084512
new file mode 100644
index 00000000000..3091c8e2542
--- /dev/null
+++ b/db/schema_migrations/20210112084512
@@ -0,0 +1 @@
+e8e26d49a8292e31ef0ea88a0262f0386b8deda83658ea4de7d464d79c5428e4 \ No newline at end of file
diff --git a/db/schema_migrations/20210112143418 b/db/schema_migrations/20210112143418
new file mode 100644
index 00000000000..3183c8cf220
--- /dev/null
+++ b/db/schema_migrations/20210112143418
@@ -0,0 +1 @@
+05d45e25ab9ef1565c04ca6515e0b01f2f98c5e98b1eeb09fa9dd43ebbe3c4d0 \ No newline at end of file
diff --git a/db/schema_migrations/20210114033715 b/db/schema_migrations/20210114033715
new file mode 100644
index 00000000000..6d25bd971e2
--- /dev/null
+++ b/db/schema_migrations/20210114033715
@@ -0,0 +1 @@
+69aae8d967fdb8af816a969fd818ed325b8d780b4faaa205c78a66c5d533ab2a \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 9bf6799dc85..de4218ed405 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -10,51 +10,62 @@ CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
+CREATE FUNCTION set_has_external_wiki() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+UPDATE projects SET has_external_wiki = COALESCE(NEW.active, FALSE)
+WHERE projects.id = COALESCE(NEW.project_id, OLD.project_id);
+RETURN NULL;
+
+END
+$$;
+
CREATE FUNCTION table_sync_function_2be879775d() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
- DELETE FROM audit_events_part_5fc467ac26 where id = OLD.id;
+ DELETE FROM audit_events_archived where id = OLD.id;
ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE audit_events_part_5fc467ac26
+ UPDATE audit_events_archived
SET author_id = NEW.author_id,
entity_id = NEW.entity_id,
entity_type = NEW.entity_type,
details = NEW.details,
+ created_at = NEW.created_at,
ip_address = NEW.ip_address,
author_name = NEW.author_name,
entity_path = NEW.entity_path,
target_details = NEW.target_details,
target_type = NEW.target_type,
- target_id = NEW.target_id,
- created_at = NEW.created_at
- WHERE audit_events_part_5fc467ac26.id = NEW.id;
+ target_id = NEW.target_id
+ WHERE audit_events_archived.id = NEW.id;
ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO audit_events_part_5fc467ac26 (id,
+ INSERT INTO audit_events_archived (id,
author_id,
entity_id,
entity_type,
details,
+ created_at,
ip_address,
author_name,
entity_path,
target_details,
target_type,
- target_id,
- created_at)
+ target_id)
VALUES (NEW.id,
NEW.author_id,
NEW.entity_id,
NEW.entity_type,
NEW.details,
+ NEW.created_at,
NEW.ip_address,
NEW.author_name,
NEW.entity_path,
NEW.target_details,
NEW.target_type,
- NEW.target_id,
- NEW.created_at);
+ NEW.target_id);
END IF;
RETURN NULL;
@@ -63,7 +74,7 @@ $$;
COMMENT ON FUNCTION table_sync_function_2be879775d() IS 'Partitioning migration: table sync for audit_events table';
-CREATE TABLE audit_events_part_5fc467ac26 (
+CREATE TABLE audit_events (
id bigint NOT NULL,
author_id integer NOT NULL,
entity_id integer NOT NULL,
@@ -9003,7 +9014,8 @@ CREATE TABLE analytics_devops_adoption_snapshots (
runner_configured boolean NOT NULL,
pipeline_succeeded boolean NOT NULL,
deploy_succeeded boolean NOT NULL,
- security_scan_succeeded boolean NOT NULL
+ security_scan_succeeded boolean NOT NULL,
+ end_time timestamp with time zone NOT NULL
);
CREATE SEQUENCE analytics_devops_adoption_snapshots_id_seq
@@ -9328,7 +9340,7 @@ CREATE TABLE application_settings (
spam_check_endpoint_enabled boolean DEFAULT false NOT NULL,
elasticsearch_pause_indexing boolean DEFAULT false NOT NULL,
repository_storages_weighted jsonb DEFAULT '{}'::jsonb NOT NULL,
- max_import_size integer DEFAULT 50 NOT NULL,
+ max_import_size integer DEFAULT 0 NOT NULL,
enforce_pat_expiration boolean DEFAULT true NOT NULL,
compliance_frameworks smallint[] DEFAULT '{}'::smallint[] NOT NULL,
notify_on_unknown_sign_in boolean DEFAULT true NOT NULL,
@@ -9375,12 +9387,17 @@ CREATE TABLE application_settings (
cloud_license_enabled boolean DEFAULT false NOT NULL,
disable_feed_token boolean DEFAULT false NOT NULL,
personal_access_token_prefix text,
+ 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,
+ 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)),
CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT check_57123c9593 CHECK ((char_length(help_page_documentation_base_url) <= 255)),
CONSTRAINT check_718b4458ae CHECK ((char_length(personal_access_token_prefix) <= 20)),
+ CONSTRAINT check_7227fad848 CHECK ((char_length(rate_limiting_response_text) <= 255)),
CONSTRAINT check_85a39b68ff CHECK ((char_length(encrypted_ci_jwt_signing_key_iv) <= 255)),
CONSTRAINT check_9a719834eb CHECK ((char_length(secret_detection_token_revocation_url) <= 255)),
CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
@@ -9623,7 +9640,7 @@ CREATE SEQUENCE atlassian_identities_user_id_seq
ALTER SEQUENCE atlassian_identities_user_id_seq OWNED BY atlassian_identities.user_id;
-CREATE TABLE audit_events (
+CREATE TABLE audit_events_archived (
id integer NOT NULL,
author_id integer NOT NULL,
entity_id integer NOT NULL,
@@ -9909,6 +9926,26 @@ CREATE SEQUENCE boards_epic_boards_id_seq
ALTER SEQUENCE boards_epic_boards_id_seq OWNED BY boards_epic_boards.id;
+CREATE TABLE boards_epic_lists (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ epic_board_id bigint NOT NULL,
+ label_id bigint,
+ "position" integer,
+ list_type smallint DEFAULT 1 NOT NULL,
+ CONSTRAINT boards_epic_lists_position_constraint CHECK (((list_type <> 1) OR (("position" IS NOT NULL) AND ("position" >= 0))))
+);
+
+CREATE SEQUENCE boards_epic_lists_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_lists_id_seq OWNED BY boards_epic_lists.id;
+
CREATE TABLE boards_epic_user_preferences (
id bigint NOT NULL,
board_id bigint NOT NULL,
@@ -11105,7 +11142,7 @@ CREATE TABLE clusters (
management_project_id integer,
cleanup_status smallint DEFAULT 1 NOT NULL,
cleanup_status_reason text,
- helm_major_version integer DEFAULT 2 NOT NULL
+ helm_major_version integer DEFAULT 3 NOT NULL
);
CREATE TABLE clusters_applications_cert_managers (
@@ -11395,7 +11432,6 @@ ALTER SEQUENCE commit_user_mentions_id_seq OWNED BY commit_user_mentions.id;
CREATE TABLE compliance_management_frameworks (
id bigint NOT NULL,
- group_id bigint,
name text NOT NULL,
description text NOT NULL,
color text NOT NULL,
@@ -11925,6 +11961,32 @@ CREATE SEQUENCE draft_notes_id_seq
ALTER SEQUENCE draft_notes_id_seq OWNED BY draft_notes.id;
+CREATE TABLE elastic_reindexing_subtasks (
+ id bigint NOT NULL,
+ elastic_reindexing_task_id bigint NOT NULL,
+ alias_name text NOT NULL,
+ index_name_from text NOT NULL,
+ index_name_to text NOT NULL,
+ elastic_task text NOT NULL,
+ documents_count_target integer,
+ documents_count integer,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT check_4910adc798 CHECK ((char_length(elastic_task) <= 255)),
+ CONSTRAINT check_88f56216a4 CHECK ((char_length(alias_name) <= 255)),
+ CONSTRAINT check_a1fbd9faa9 CHECK ((char_length(index_name_from) <= 255)),
+ CONSTRAINT check_f456494bd8 CHECK ((char_length(index_name_to) <= 255))
+);
+
+CREATE SEQUENCE elastic_reindexing_subtasks_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE elastic_reindexing_subtasks_id_seq OWNED BY elastic_reindexing_subtasks.id;
+
CREATE TABLE elastic_reindexing_tasks (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -12929,6 +12991,13 @@ CREATE SEQUENCE group_import_states_group_id_seq
ALTER SEQUENCE group_import_states_group_id_seq OWNED BY group_import_states.group_id;
+CREATE TABLE group_merge_request_approval_settings (
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ allow_author_approval boolean DEFAULT false NOT NULL
+);
+
CREATE TABLE group_wiki_repositories (
shard_id bigint NOT NULL,
group_id bigint NOT NULL,
@@ -13077,6 +13146,23 @@ CREATE SEQUENCE incident_management_oncall_schedules_id_seq
ALTER SEQUENCE incident_management_oncall_schedules_id_seq OWNED BY incident_management_oncall_schedules.id;
+CREATE TABLE incident_management_oncall_shifts (
+ id bigint NOT NULL,
+ rotation_id bigint NOT NULL,
+ participant_id bigint NOT NULL,
+ starts_at timestamp with time zone NOT NULL,
+ ends_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE incident_management_oncall_shifts_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_oncall_shifts_id_seq OWNED BY incident_management_oncall_shifts.id;
+
CREATE TABLE index_statuses (
id integer NOT NULL,
project_id integer NOT NULL,
@@ -13972,7 +14058,7 @@ CREATE TABLE merge_requests (
merge_jid character varying,
discussion_locked boolean,
latest_merge_request_diff_id integer,
- allow_maintainer_to_push boolean,
+ allow_maintainer_to_push boolean DEFAULT true,
state_id smallint DEFAULT 1 NOT NULL,
rebase_jid character varying,
squash_commit_sha bytea,
@@ -14127,6 +14213,13 @@ CREATE SEQUENCE namespace_onboarding_actions_id_seq
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,
+ maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
+ CONSTRAINT check_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255))
+);
+
CREATE TABLE namespace_root_storage_statistics (
namespace_id integer NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14336,7 +14429,11 @@ CREATE TABLE oauth_access_grants (
redirect_uri text NOT NULL,
created_at timestamp without time zone NOT NULL,
revoked_at timestamp without time zone,
- scopes character varying
+ scopes character varying,
+ code_challenge text,
+ code_challenge_method text,
+ CONSTRAINT oauth_access_grants_code_challenge CHECK ((char_length(code_challenge) <= 128)),
+ CONSTRAINT oauth_access_grants_code_challenge_method CHECK ((char_length(code_challenge_method) <= 5))
);
CREATE SEQUENCE oauth_access_grants_id_seq
@@ -14408,6 +14505,36 @@ CREATE SEQUENCE oauth_openid_requests_id_seq
ALTER SEQUENCE oauth_openid_requests_id_seq OWNED BY oauth_openid_requests.id;
+CREATE TABLE onboarding_progresses (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ git_pull_at timestamp with time zone,
+ git_write_at timestamp with time zone,
+ merge_request_created_at timestamp with time zone,
+ pipeline_created_at timestamp with time zone,
+ user_added_at timestamp with time zone,
+ trial_started_at timestamp with time zone,
+ subscription_created_at timestamp with time zone,
+ required_mr_approvals_enabled_at timestamp with time zone,
+ code_owners_enabled_at timestamp with time zone,
+ scoped_label_created_at timestamp with time zone,
+ security_scan_enabled_at timestamp with time zone,
+ issue_auto_closed_at timestamp with time zone,
+ repository_imported_at timestamp with time zone,
+ repository_mirrored_at timestamp with time zone
+);
+
+CREATE SEQUENCE onboarding_progresses_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE onboarding_progresses_id_seq OWNED BY onboarding_progresses.id;
+
CREATE TABLE open_project_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
@@ -14585,7 +14712,8 @@ ALTER SEQUENCE packages_build_infos_id_seq OWNED BY packages_build_infos.id;
CREATE TABLE packages_composer_metadata (
package_id bigint NOT NULL,
target_sha bytea NOT NULL,
- composer_json jsonb DEFAULT '{}'::jsonb NOT NULL
+ composer_json jsonb DEFAULT '{}'::jsonb NOT NULL,
+ version_cache_sha bytea
);
CREATE TABLE packages_conan_file_metadata (
@@ -14626,6 +14754,136 @@ CREATE SEQUENCE packages_conan_metadata_id_seq
ALTER SEQUENCE packages_conan_metadata_id_seq OWNED BY packages_conan_metadata.id;
+CREATE TABLE packages_debian_file_metadata (
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ package_file_id bigint NOT NULL,
+ file_type smallint NOT NULL,
+ component text,
+ architecture text,
+ fields jsonb,
+ CONSTRAINT check_2ebedda4b6 CHECK ((char_length(component) <= 255)),
+ CONSTRAINT check_e6e1fffcca CHECK ((char_length(architecture) <= 255))
+);
+
+CREATE TABLE packages_debian_group_architectures (
+ 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_ddb220164a CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_architectures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_architectures_id_seq OWNED BY packages_debian_group_architectures.id;
+
+CREATE TABLE packages_debian_group_distributions (
+ 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,
+ creator_id bigint,
+ valid_time_duration_seconds integer,
+ file_store smallint DEFAULT 1 NOT NULL,
+ automatic boolean DEFAULT true NOT NULL,
+ automatic_upgrades boolean DEFAULT false NOT NULL,
+ codename text NOT NULL,
+ suite text,
+ origin text,
+ label text,
+ version text,
+ description text,
+ encrypted_signing_keys text,
+ encrypted_signing_keys_iv text,
+ file text,
+ file_signature text,
+ CONSTRAINT check_310ac457b8 CHECK ((char_length(description) <= 255)),
+ CONSTRAINT check_3d6f87fc31 CHECK ((char_length(file_signature) <= 4096)),
+ CONSTRAINT check_3fdadf4a0c CHECK ((char_length(version) <= 255)),
+ CONSTRAINT check_590e18405a CHECK ((char_length(codename) <= 255)),
+ CONSTRAINT check_9b90bc0f07 CHECK ((char_length(encrypted_signing_keys_iv) <= 255)),
+ CONSTRAINT check_b057cd840a CHECK ((char_length(origin) <= 255)),
+ CONSTRAINT check_b811ec1218 CHECK ((char_length(encrypted_signing_keys) <= 2048)),
+ CONSTRAINT check_be5ed8d307 CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_d3244bfc0b CHECK ((char_length(label) <= 255)),
+ CONSTRAINT check_e7c928a24b CHECK ((char_length(suite) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_distributions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_distributions_id_seq OWNED BY packages_debian_group_distributions.id;
+
+CREATE TABLE packages_debian_project_architectures (
+ 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_9c2e1c99d8 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_architectures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_architectures_id_seq OWNED BY packages_debian_project_architectures.id;
+
+CREATE TABLE packages_debian_project_distributions (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ creator_id bigint,
+ valid_time_duration_seconds integer,
+ file_store smallint DEFAULT 1 NOT NULL,
+ automatic boolean DEFAULT true NOT NULL,
+ automatic_upgrades boolean DEFAULT false NOT NULL,
+ codename text NOT NULL,
+ suite text,
+ origin text,
+ label text,
+ version text,
+ description text,
+ encrypted_signing_keys text,
+ encrypted_signing_keys_iv text,
+ file text,
+ file_signature text,
+ CONSTRAINT check_6177ccd4a6 CHECK ((char_length(origin) <= 255)),
+ CONSTRAINT check_6f6b55a4c4 CHECK ((char_length(label) <= 255)),
+ CONSTRAINT check_834dabadb6 CHECK ((char_length(codename) <= 255)),
+ CONSTRAINT check_96965792c2 CHECK ((char_length(version) <= 255)),
+ CONSTRAINT check_a56ae58a17 CHECK ((char_length(suite) <= 255)),
+ CONSTRAINT check_a5a2ac6af2 CHECK ((char_length(file_signature) <= 4096)),
+ CONSTRAINT check_b93154339f CHECK ((char_length(description) <= 255)),
+ CONSTRAINT check_c25603a25b CHECK ((char_length(encrypted_signing_keys) <= 2048)),
+ CONSTRAINT check_cb4ac9599e CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_d488f8cce3 CHECK ((char_length(encrypted_signing_keys_iv) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_distributions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_distributions_id_seq OWNED BY packages_debian_project_distributions.id;
+
CREATE TABLE packages_dependencies (
id bigint NOT NULL,
name character varying(255) NOT NULL,
@@ -15313,7 +15571,9 @@ CREATE TABLE project_ci_cd_settings (
default_git_depth integer,
forward_deployment_enabled boolean,
merge_trains_enabled boolean DEFAULT false,
- auto_rollback_enabled boolean DEFAULT false NOT NULL
+ auto_rollback_enabled boolean DEFAULT false NOT NULL,
+ keep_latest_artifact boolean DEFAULT true NOT NULL,
+ restrict_user_defined_variables boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE project_ci_cd_settings_id_seq
@@ -17584,7 +17844,8 @@ CREATE TABLE vulnerability_feedback (
comment_author_id integer,
comment text,
comment_timestamp timestamp with time zone,
- finding_uuid uuid
+ finding_uuid uuid,
+ dismissal_reason smallint
);
CREATE SEQUENCE vulnerability_feedback_id_seq
@@ -18131,6 +18392,8 @@ ALTER TABLE ONLY boards_epic_board_positions ALTER COLUMN id SET DEFAULT nextval
ALTER TABLE ONLY boards_epic_boards ALTER COLUMN id SET DEFAULT nextval('boards_epic_boards_id_seq'::regclass);
+ALTER TABLE ONLY boards_epic_lists ALTER COLUMN id SET DEFAULT nextval('boards_epic_lists_id_seq'::regclass);
+
ALTER TABLE ONLY boards_epic_user_preferences ALTER COLUMN id SET DEFAULT nextval('boards_epic_user_preferences_id_seq'::regclass);
ALTER TABLE ONLY broadcast_messages ALTER COLUMN id SET DEFAULT nextval('broadcast_messages_id_seq'::regclass);
@@ -18315,6 +18578,8 @@ ALTER TABLE ONLY diff_note_positions ALTER COLUMN id SET DEFAULT nextval('diff_n
ALTER TABLE ONLY draft_notes ALTER COLUMN id SET DEFAULT nextval('draft_notes_id_seq'::regclass);
+ALTER TABLE ONLY elastic_reindexing_subtasks ALTER COLUMN id SET DEFAULT nextval('elastic_reindexing_subtasks_id_seq'::regclass);
+
ALTER TABLE ONLY elastic_reindexing_tasks ALTER COLUMN id SET DEFAULT nextval('elastic_reindexing_tasks_id_seq'::regclass);
ALTER TABLE ONLY emails ALTER COLUMN id SET DEFAULT nextval('emails_id_seq'::regclass);
@@ -18423,6 +18688,8 @@ ALTER TABLE ONLY incident_management_oncall_rotations ALTER COLUMN id SET DEFAUL
ALTER TABLE ONLY incident_management_oncall_schedules ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_schedules_id_seq'::regclass);
+ALTER TABLE ONLY incident_management_oncall_shifts ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_shifts_id_seq'::regclass);
+
ALTER TABLE ONLY index_statuses ALTER COLUMN id SET DEFAULT nextval('index_statuses_id_seq'::regclass);
ALTER TABLE ONLY insights ALTER COLUMN id SET DEFAULT nextval('insights_id_seq'::regclass);
@@ -18531,6 +18798,8 @@ ALTER TABLE ONLY oauth_applications ALTER COLUMN id SET DEFAULT nextval('oauth_a
ALTER TABLE ONLY oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('oauth_openid_requests_id_seq'::regclass);
+ALTER TABLE ONLY onboarding_progresses ALTER COLUMN id SET DEFAULT nextval('onboarding_progresses_id_seq'::regclass);
+
ALTER TABLE ONLY open_project_tracker_data ALTER COLUMN id SET DEFAULT nextval('open_project_tracker_data_id_seq'::regclass);
ALTER TABLE ONLY operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('operations_feature_flag_scopes_id_seq'::regclass);
@@ -18555,6 +18824,14 @@ ALTER TABLE ONLY packages_conan_file_metadata ALTER COLUMN id SET DEFAULT nextva
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_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_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_distributions_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);
@@ -19126,11 +19403,11 @@ ALTER TABLE ONLY ar_internal_metadata
ALTER TABLE ONLY atlassian_identities
ADD CONSTRAINT atlassian_identities_pkey PRIMARY KEY (user_id);
-ALTER TABLE ONLY audit_events_part_5fc467ac26
- ADD CONSTRAINT audit_events_part_5fc467ac26_pkey PRIMARY KEY (id, created_at);
+ALTER TABLE ONLY audit_events_archived
+ ADD CONSTRAINT audit_events_archived_pkey PRIMARY KEY (id);
ALTER TABLE ONLY audit_events
- ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id);
+ ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id, created_at);
ALTER TABLE ONLY authentication_events
ADD CONSTRAINT authentication_events_pkey PRIMARY KEY (id);
@@ -19174,6 +19451,9 @@ ALTER TABLE ONLY boards_epic_board_positions
ALTER TABLE ONLY boards_epic_boards
ADD CONSTRAINT boards_epic_boards_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY boards_epic_lists
+ ADD CONSTRAINT boards_epic_lists_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY boards_epic_user_preferences
ADD CONSTRAINT boards_epic_user_preferences_pkey PRIMARY KEY (id);
@@ -19471,6 +19751,9 @@ ALTER TABLE ONLY diff_note_positions
ALTER TABLE ONLY draft_notes
ADD CONSTRAINT draft_notes_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY elastic_reindexing_subtasks
+ ADD CONSTRAINT elastic_reindexing_subtasks_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY elastic_reindexing_tasks
ADD CONSTRAINT elastic_reindexing_tasks_pkey PRIMARY KEY (id);
@@ -19621,6 +19904,9 @@ ALTER TABLE ONLY group_group_links
ALTER TABLE ONLY group_import_states
ADD CONSTRAINT group_import_states_pkey PRIMARY KEY (group_id);
+ALTER TABLE ONLY group_merge_request_approval_settings
+ ADD CONSTRAINT group_merge_request_approval_settings_pkey PRIMARY KEY (group_id);
+
ALTER TABLE ONLY group_wiki_repositories
ADD CONSTRAINT group_wiki_repositories_pkey PRIMARY KEY (group_id);
@@ -19636,6 +19922,9 @@ ALTER TABLE ONLY import_export_uploads
ALTER TABLE ONLY import_failures
ADD CONSTRAINT import_failures_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT inc_mgmnt_no_overlapping_oncall_shifts EXCLUDE USING gist (rotation_id WITH =, tstzrange(starts_at, ends_at, '[)'::text) WITH &&);
+
ALTER TABLE ONLY incident_management_oncall_participants
ADD CONSTRAINT incident_management_oncall_participants_pkey PRIMARY KEY (id);
@@ -19645,6 +19934,9 @@ ALTER TABLE ONLY incident_management_oncall_rotations
ALTER TABLE ONLY incident_management_oncall_schedules
ADD CONSTRAINT incident_management_oncall_schedules_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT incident_management_oncall_shifts_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY index_statuses
ADD CONSTRAINT index_statuses_pkey PRIMARY KEY (id);
@@ -19813,6 +20105,9 @@ ALTER TABLE ONLY namespace_limits
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);
+
ALTER TABLE ONLY namespace_root_storage_statistics
ADD CONSTRAINT namespace_root_storage_statistics_pkey PRIMARY KEY (namespace_id);
@@ -19846,6 +20141,9 @@ ALTER TABLE ONLY oauth_applications
ALTER TABLE ONLY oauth_openid_requests
ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY onboarding_progresses
+ ADD CONSTRAINT onboarding_progresses_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY open_project_tracker_data
ADD CONSTRAINT open_project_tracker_data_pkey PRIMARY KEY (id);
@@ -19885,6 +20183,21 @@ ALTER TABLE ONLY packages_conan_file_metadata
ALTER TABLE ONLY packages_conan_metadata
ADD CONSTRAINT packages_conan_metadata_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_file_metadata
+ ADD CONSTRAINT packages_debian_file_metadata_pkey PRIMARY KEY (package_file_id);
+
+ALTER TABLE ONLY packages_debian_group_architectures
+ ADD CONSTRAINT packages_debian_group_architectures_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_distributions
+ ADD CONSTRAINT packages_debian_project_distributions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_dependencies
ADD CONSTRAINT packages_dependencies_pkey PRIMARY KEY (id);
@@ -20497,9 +20810,9 @@ CREATE INDEX product_analytics_events_experi_project_id_collector_tstamp_idx ON
CREATE INDEX active_billable_users ON users USING btree (id) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = ANY (ARRAY[NULL::integer, 6, 4]))) AND ((user_type IS NULL) OR (user_type <> ALL ('{2,6,1,3,7,8}'::smallint[]))));
-CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events USING btree (created_at, author_id);
+CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events_archived USING btree (created_at, author_id);
-CREATE INDEX analytics_index_audit_events_part_on_created_at_and_author_id ON ONLY audit_events_part_5fc467ac26 USING btree (created_at, author_id);
+CREATE INDEX analytics_index_audit_events_part_on_created_at_and_author_id ON ONLY audit_events USING btree (created_at, author_id);
CREATE INDEX analytics_index_events_on_created_at_and_author_id ON events USING btree (created_at, author_id);
@@ -20541,11 +20854,13 @@ 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 finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
-CREATE INDEX idx_audit_events_on_entity_id_desc_author_id_created_at ON audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+CREATE INDEX idx_audit_events_on_entity_id_desc_author_id_created_at ON audit_events_archived USING btree (entity_id, entity_type, id DESC, author_id, created_at);
-CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events_part_5fc467ac26 USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
CREATE INDEX idx_ci_pipelines_artifacts_locked ON ci_pipelines USING btree (ci_ref_id, id) WHERE (locked = 1);
@@ -20599,6 +20914,10 @@ CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USIN
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);
+
+CREATE INDEX idx_pkgs_deb_proj_architectures_on_distribution_id ON packages_debian_project_architectures USING btree (distribution_id);
+
CREATE UNIQUE INDEX idx_pkgs_dep_links_on_pkg_id_dependency_id_dependency_type ON packages_dependency_links USING btree (package_id, dependency_id, dependency_type);
CREATE INDEX idx_proj_feat_usg_on_jira_dvcs_cloud_last_sync_at_and_proj_id ON project_feature_usages USING btree (jira_dvcs_cloud_last_sync_at, project_id) WHERE (jira_dvcs_cloud_last_sync_at IS NOT NULL);
@@ -20823,8 +21142,16 @@ CREATE UNIQUE INDEX index_boards_epic_board_positions_on_epic_board_id_and_epic_
CREATE INDEX index_boards_epic_board_positions_on_epic_id ON boards_epic_board_positions USING btree (epic_id);
+CREATE INDEX index_boards_epic_board_positions_on_scoped_relative_position ON boards_epic_board_positions USING btree (epic_board_id, epic_id, relative_position);
+
CREATE INDEX index_boards_epic_boards_on_group_id ON boards_epic_boards USING btree (group_id);
+CREATE INDEX index_boards_epic_lists_on_epic_board_id ON boards_epic_lists USING btree (epic_board_id);
+
+CREATE UNIQUE INDEX index_boards_epic_lists_on_epic_board_id_and_label_id ON boards_epic_lists USING btree (epic_board_id, label_id) WHERE (list_type = 1);
+
+CREATE INDEX index_boards_epic_lists_on_label_id ON boards_epic_lists USING btree (label_id);
+
CREATE INDEX index_boards_epic_user_preferences_on_board_id ON boards_epic_user_preferences USING btree (board_id);
CREATE UNIQUE INDEX index_boards_epic_user_preferences_on_board_user_epic_unique ON boards_epic_user_preferences USING btree (board_id, user_id, epic_id);
@@ -20999,7 +21326,7 @@ CREATE INDEX index_ci_pipelines_on_external_pull_request_id ON ci_pipelines USIN
CREATE INDEX index_ci_pipelines_on_merge_request_id ON ci_pipelines USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
-CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id ON ci_pipelines USING btree (pipeline_schedule_id);
+CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id_and_id ON ci_pipelines USING btree (pipeline_schedule_id, id);
CREATE INDEX index_ci_pipelines_on_project_id_and_id_desc ON ci_pipelines USING btree (project_id, id DESC);
@@ -21295,6 +21622,8 @@ CREATE INDEX index_draft_notes_on_discussion_id ON draft_notes USING btree (disc
CREATE INDEX index_draft_notes_on_merge_request_id ON draft_notes USING btree (merge_request_id);
+CREATE INDEX index_elastic_reindexing_subtasks_on_elastic_reindexing_task_id ON elastic_reindexing_subtasks USING btree (elastic_reindexing_task_id);
+
CREATE UNIQUE INDEX index_elastic_reindexing_tasks_on_in_progress ON elastic_reindexing_tasks USING btree (in_progress) WHERE in_progress;
CREATE INDEX index_elastic_reindexing_tasks_on_state ON elastic_reindexing_tasks USING btree (state);
@@ -21595,6 +21924,10 @@ CREATE UNIQUE INDEX index_inc_mgmnt_oncall_rotations_on_oncall_schedule_id_and_n
CREATE INDEX index_incident_management_oncall_schedules_on_project_id ON incident_management_oncall_schedules USING btree (project_id);
+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);
@@ -21711,7 +22044,7 @@ CREATE UNIQUE INDEX index_label_priorities_on_project_id_and_label_id ON label_p
CREATE UNIQUE INDEX index_labels_on_group_id_and_project_id_and_title ON labels USING btree (group_id, project_id, title);
-CREATE INDEX index_labels_on_group_id_and_title_with_null_project_id ON labels USING btree (group_id, title) WHERE (project_id IS NULL);
+CREATE UNIQUE INDEX index_labels_on_group_id_and_title_unique ON labels USING btree (group_id, title) WHERE (project_id IS NULL);
CREATE INDEX index_labels_on_project_id ON labels USING btree (project_id);
@@ -21847,6 +22180,8 @@ CREATE INDEX index_merge_requests_on_target_project_id_and_iid_and_state_id ON m
CREATE INDEX index_merge_requests_on_target_project_id_and_iid_jira_title ON merge_requests USING btree (target_project_id, iid) WHERE ((title)::text ~ '[A-Z][A-Z_0-9]+-\d+'::text);
+CREATE INDEX index_merge_requests_on_target_project_id_and_squash_commit_sha ON merge_requests USING btree (target_project_id, squash_commit_sha);
+
CREATE INDEX index_merge_requests_on_target_project_id_and_target_branch ON merge_requests USING btree (target_project_id, target_branch) WHERE ((state_id = 1) AND (merge_when_pipeline_succeeds = true));
CREATE INDEX index_merge_requests_on_target_project_id_iid_jira_description ON merge_requests USING btree (target_project_id, iid) WHERE (description ~ '[A-Z][A-Z_0-9]+-\d+'::text);
@@ -22013,6 +22348,8 @@ CREATE UNIQUE INDEX index_on_segment_selections_project_id_segment_id ON analyti
CREATE INDEX index_on_segment_selections_segment_id ON analytics_devops_adoption_segment_selections USING btree (segment_id);
+CREATE INDEX index_on_snapshots_segment_id_end_time ON analytics_devops_adoption_snapshots USING btree (segment_id, end_time);
+
CREATE INDEX index_on_snapshots_segment_id_recorded_at ON analytics_devops_adoption_snapshots USING btree (segment_id, recorded_at);
CREATE INDEX index_on_users_lower_email ON users USING btree (lower((email)::text));
@@ -22021,6 +22358,8 @@ 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 UNIQUE INDEX index_onboarding_progresses_on_namespace_id ON onboarding_progresses USING btree (namespace_id);
+
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);
@@ -22051,6 +22390,14 @@ CREATE UNIQUE INDEX index_packages_conan_file_metadata_on_package_file_id ON pac
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_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_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 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);
@@ -23001,14 +23348,22 @@ 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_build_stage_position_index ON ci_builds USING btree (stage_id, stage_idx) WHERE (stage_idx IS NOT NULL);
-
-CREATE INDEX tmp_index_for_email_unconfirmation_migration ON emails USING btree (id) WHERE (confirmed_at IS NOT NULL);
-
CREATE INDEX tmp_index_oauth_applications_on_id_where_trusted ON oauth_applications USING btree (id) WHERE (trusted = true);
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_proj_architectures_on_distribution_id_and_name ON packages_debian_project_architectures 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);
+
+CREATE UNIQUE INDEX uniq_pkgs_debian_project_distributions_project_id_and_codename ON packages_debian_project_distributions USING btree (project_id, codename);
+
+CREATE UNIQUE INDEX uniq_pkgs_debian_project_distributions_project_id_and_suite ON packages_debian_project_distributions USING btree (project_id, suite);
+
CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
@@ -23273,6 +23628,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_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();
+
+CREATE TRIGGER trigger_has_external_wiki_on_update AFTER UPDATE ON services FOR EACH ROW WHEN ((((new.type)::text = 'ExternalWikiService'::text) AND (old.active <> new.active) AND (new.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_wiki();
+
ALTER TABLE ONLY chat_names
ADD CONSTRAINT fk_00797a2bf9 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
@@ -24011,6 +24372,9 @@ ALTER TABLE ONLY trending_projects
ALTER TABLE ONLY project_deploy_tokens
ADD CONSTRAINT fk_rails_0aca134388 FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_distributions
+ ADD CONSTRAINT fk_rails_0adf75c347 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY packages_conan_file_metadata
ADD CONSTRAINT fk_rails_0afabd9328 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
@@ -24032,6 +24396,9 @@ ALTER TABLE ONLY user_synced_attributes_metadata
ALTER TABLE ONLY project_authorizations
ADD CONSTRAINT fk_rails_0f84bb11f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_lists
+ ADD CONSTRAINT fk_rails_0f9c7f646f FOREIGN KEY (epic_board_id) REFERENCES boards_epic_boards(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_email_participants
ADD CONSTRAINT fk_rails_0fdfd8b811 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -24116,6 +24483,9 @@ ALTER TABLE ONLY incident_management_oncall_schedules
ALTER TABLE ONLY vulnerability_user_mentions
ADD CONSTRAINT fk_rails_1a41c485cd FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_file_metadata
+ ADD CONSTRAINT fk_rails_1ae85be112 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issuable_slas
ADD CONSTRAINT fk_rails_1b8768cd63 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -24137,6 +24507,9 @@ ALTER TABLE ONLY boards_epic_board_positions
ALTER TABLE ONLY geo_repository_created_events
ADD CONSTRAINT fk_rails_1f49e46a61 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_lists
+ ADD CONSTRAINT fk_rails_1fe6b54909 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_merge_request_rules_groups
ADD CONSTRAINT fk_rails_2020a7124a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -24206,6 +24579,9 @@ ALTER TABLE ONLY geo_repository_updated_events
ALTER TABLE ONLY boards_epic_board_labels
ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY onboarding_progresses
+ ADD CONSTRAINT fk_rails_2ccfd420cc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY protected_branch_unprotect_access_levels
ADD CONSTRAINT fk_rails_2d2aba21ef FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -24260,6 +24636,9 @@ ALTER TABLE ONLY merge_request_blocks
ALTER TABLE ONLY merge_request_reviewers
ADD CONSTRAINT fk_rails_3704a66140 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_merge_request_approval_settings
+ ADD CONSTRAINT fk_rails_37b6b4cdba FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT fk_rails_3829e49b66 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -24449,6 +24828,9 @@ ALTER TABLE ONLY issue_user_mentions
ALTER TABLE ONLY merge_request_assignees
ADD CONSTRAINT fk_rails_579d375628 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_architectures
+ ADD CONSTRAINT fk_rails_5808663adf FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY clusters_applications_cilium
ADD CONSTRAINT fk_rails_59dc12eea6 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
@@ -24785,6 +25167,9 @@ ALTER TABLE ONLY alert_management_alert_assignees
ALTER TABLE ONLY scim_identities
ADD CONSTRAINT fk_rails_9421a0bffb FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+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_pypi_metadata
ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
@@ -25145,6 +25530,12 @@ ALTER TABLE ONLY user_callouts
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT fk_rails_debd54e456 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_distributions
+ ADD CONSTRAINT fk_rails_df44271a30 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE RESTRICT;
+
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT fk_rails_df4feb286a FOREIGN KEY (rotation_id) REFERENCES incident_management_oncall_rotations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT fk_rails_dfb37c880d FOREIGN KEY (end_event_label_id) REFERENCES labels(id) ON DELETE CASCADE;
@@ -25184,6 +25575,9 @@ ALTER TABLE ONLY merge_request_metrics
ALTER TABLE ONLY draft_notes
ADD CONSTRAINT fk_rails_e753681674 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_package_settings
+ ADD CONSTRAINT fk_rails_e773444769 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY dast_site_tokens
ADD CONSTRAINT fk_rails_e84f721a8e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25214,12 +25608,18 @@ ALTER TABLE ONLY snippet_statistics
ALTER TABLE ONLY project_security_settings
ADD CONSTRAINT fk_rails_ed4abe1338 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_distributions
+ ADD CONSTRAINT fk_rails_ede0bb937f FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY experiment_subjects
ADD CONSTRAINT fk_rails_ede5754774 FOREIGN KEY (experiment_id) REFERENCES experiments(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_daily_build_group_report_results
ADD CONSTRAINT fk_rails_ee072d13b3 FOREIGN KEY (last_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_architectures
+ ADD CONSTRAINT fk_rails_ef667d1b03 FOREIGN KEY (distribution_id) REFERENCES packages_debian_group_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY label_priorities
ADD CONSTRAINT fk_rails_ef916d14fa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25241,6 +25641,9 @@ ALTER TABLE ONLY requirements
ALTER TABLE ONLY snippet_repositories
ADD CONSTRAINT fk_rails_f21f899728 FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY elastic_reindexing_subtasks
+ ADD CONSTRAINT fk_rails_f2cc190164 FOREIGN KEY (elastic_reindexing_task_id) REFERENCES elastic_reindexing_tasks(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_pipeline_chat_data
ADD CONSTRAINT fk_rails_f300456b63 FOREIGN KEY (chat_name_id) REFERENCES chat_names(id) ON DELETE CASCADE;
@@ -25256,6 +25659,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 incident_management_oncall_shifts
+ ADD CONSTRAINT fk_rails_f6eef06841 FOREIGN KEY (participant_id) REFERENCES incident_management_oncall_participants(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY design_user_mentions
ADD CONSTRAINT fk_rails_f7075a53c1 FOREIGN KEY (design_id) REFERENCES design_management_designs(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 2c28da972da..481da94c627 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -58,6 +58,7 @@ exceptions:
- GPL
- GUI
- HAML
+ - HEAD
- HIPAA
- HTML
- HTTP
@@ -90,6 +91,7 @@ exceptions:
- NGINX
- NOTE
- NPM
+ - NTP
- ONLY
- OWASP
- PAT
diff --git a/doc/.vale/gitlab/Admin.yml b/doc/.vale/gitlab/Admin.yml
index 6d01882138a..96325ad2ef4 100644
--- a/doc/.vale/gitlab/Admin.yml
+++ b/doc/.vale/gitlab/Admin.yml
@@ -1,7 +1,7 @@
---
# Warning: gitlab.Admin
#
-# You should not use "admin", but "Admin Area" is OK.
+# Checks for "admin" and recommends using the full word instead. "Admin Area" is OK.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
diff --git a/doc/.vale/gitlab/AlertBoxStyle.yml b/doc/.vale/gitlab/AlertBoxStyle.yml
index bdf66236ef2..92c3a16cab8 100644
--- a/doc/.vale/gitlab/AlertBoxStyle.yml
+++ b/doc/.vale/gitlab/AlertBoxStyle.yml
@@ -1,9 +1,8 @@
---
# Error: gitlab.AlertBoxStyle
#
-# Makes sure alert boxes are used with block quotes.
+# Makes sure alert boxes are used with block quotes. Checks for 3 formatting issues:
#
-# Checks for 3 formatting issues:
# - Alert boxes inside a block quote (">")
# - Alert boxes with the note text on the same line
# - Alert boxes using words other than "NOTE" or "WARNING"
@@ -17,5 +16,5 @@ nonword: true
scope: raw
raw:
- '(\n *\> *(?:NOTE|WARNING)|'
- - '\n(NOTE):[^\n]|' # Adding "WARNING" here causes a false positive
- - '\n *(?:> )?\**(Note|note|TIP|Tip|tip|CAUTION|Caution|caution|DANGER|Danger|danger|warning):.*)' ## Adding "Warning" here causes a false positive
+ - '\n\n(NOTE|WARNING):[^\n]|'
+ - '\n\n *(?:> )?\**(Note|note|TIP|Tip|tip|CAUTION|Caution|caution|DANGER|Danger|danger|Warning|warning):.*)'
diff --git a/doc/.vale/gitlab/British.yml b/doc/.vale/gitlab/British.yml
index 65842ad7aa5..152723ead26 100644
--- a/doc/.vale/gitlab/British.yml
+++ b/doc/.vale/gitlab/British.yml
@@ -1,7 +1,7 @@
---
# Error: gitlab.British
#
-# Checks that US spelling is used over British spelling.
+# Checks that US spelling is used instead of British spelling.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
diff --git a/doc/.vale/gitlab/CurlStringsQuoted.yml b/doc/.vale/gitlab/CurlStringsQuoted.yml
index e9fbabf5ffc..c0bc8c18c93 100644
--- a/doc/.vale/gitlab/CurlStringsQuoted.yml
+++ b/doc/.vale/gitlab/CurlStringsQuoted.yml
@@ -1,7 +1,7 @@
---
-# Warning: gitlab.CurlStringsQuoted
+# Error: gitlab.CurlStringsQuoted
#
-# Ensures all code blocks using curl quote any URL strings.
+# Ensures all code blocks using `curl` wrap URL strings in quotation marks.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
diff --git a/doc/.vale/gitlab/FutureTense.yml b/doc/.vale/gitlab/FutureTense.yml
index d7001d57899..fc414a9c0fd 100644
--- a/doc/.vale/gitlab/FutureTense.yml
+++ b/doc/.vale/gitlab/FutureTense.yml
@@ -1,8 +1,7 @@
---
# Suggestion: gitlab.FutureTense
#
-# Checks for use of future tense in sentences. Present tense is preferred as
-# much as possible.
+# Checks for use of future tense in sentences. Present tense is strongly preferred.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
diff --git a/doc/.vale/gitlab/OxfordComma.yml b/doc/.vale/gitlab/OxfordComma.yml
index 0425d9e1dd0..1716145b26a 100644
--- a/doc/.vale/gitlab/OxfordComma.yml
+++ b/doc/.vale/gitlab/OxfordComma.yml
@@ -1,8 +1,7 @@
---
# Warning: gitlab.OxfordComma
#
-# Checks for the lack of an Oxford comma. In some cases, will catch overly
-# complex sentence structures with lots of commas.
+# Checks for the lack of an Oxford comma. In some cases, will catch overly complex sentence structures with lots of commas.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
diff --git a/doc/.vale/gitlab/ReferenceLinks.yml b/doc/.vale/gitlab/ReferenceLinks.yml
index 0df1f359107..160ed2e8e14 100644
--- a/doc/.vale/gitlab/ReferenceLinks.yml
+++ b/doc/.vale/gitlab/ReferenceLinks.yml
@@ -1,7 +1,7 @@
---
# Error: gitlab.ReferenceLinks
#
-# Checks for the presence of reference-style links that must be inline.
+# Checks for reference-style links that should be converted to inline links.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
diff --git a/doc/.vale/gitlab/SentenceSpacing.yml b/doc/.vale/gitlab/SentenceSpacing.yml
index 884d4b57508..0288abe834f 100644
--- a/doc/.vale/gitlab/SentenceSpacing.yml
+++ b/doc/.vale/gitlab/SentenceSpacing.yml
@@ -1,10 +1,7 @@
---
# Error: gitlab.SentenceSpacing
#
-# Checks for the following in common content scenarios:
-#
-# - No spaces.
-# - More than one space.
+# Checks for incorrect spacing (no spaces, or more than one space) around punctuation.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
diff --git a/doc/.vale/gitlab/Spelling.yml b/doc/.vale/gitlab/Spelling.yml
index 602b7cd11e6..4ebaf7bfb70 100644
--- a/doc/.vale/gitlab/Spelling.yml
+++ b/doc/.vale/gitlab/Spelling.yml
@@ -1,8 +1,7 @@
---
# Warning: gitlab.Spelling
#
-# Checks for possible spelling mistakes in content, not code. May find false positives
-# due to links using angle brackets: <https://example.com>. These can be ignored.
+# Checks for possible spelling mistakes in content, not code. Results from links using angle brackets (<https://example.com>) should be corrected.
#
# If a word is flagged as a spelling mistake incorrectly, such as a product name,
# you can submit an MR to update `spelling-exceptions.txt` with the missing word.
diff --git a/doc/.vale/gitlab/SubstitutionSuggestions.yml b/doc/.vale/gitlab/SubstitutionSuggestions.yml
index 82e3e789864..ab6658f0943 100644
--- a/doc/.vale/gitlab/SubstitutionSuggestions.yml
+++ b/doc/.vale/gitlab/SubstitutionSuggestions.yml
@@ -1,8 +1,8 @@
---
# Suggestion: gitlab.SubstitutionSuggestions
#
-# Suggests better options for frequently misused terms at GitLab that are
-# often - but not always - incorrect.
+# Suggests better options for frequently misused terms that are often - but not always - incorrect.
+# SubstitutionWarning.yml and Substitutions.yml also exist.
#
# For a list of all options, see https://errata-ai.github.io/vale/styles/
extends: substitution
@@ -13,7 +13,7 @@ ignorecase: true
swap:
active user: '"billable user"'
active users: '"billable users"'
- docs: documentation
+ docs: '"documentation"'
once that: '"after that"'
once the: '"after the"'
once you: '"after you"'
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index ed0f8b498fe..61fd0148fd8 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -1,8 +1,8 @@
---
# Warning: gitlab.SubstitutionWarning
#
-# Warns against using common shorthand for terms.
-# For substitutions flagged as errors, see Substitutions.yml
+# Checks for misused terms or common shorthand that should never be used at GitLab, but can't be flagged as errors.
+# Substitutions.yml and SubstitionSuggestions.yml also exist.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index 0a56524e3f5..987785c7a22 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -1,8 +1,8 @@
---
# Error: gitlab.Substitutions
#
-# Checks for use of some of the top misused terms at GitLab.
-# For substitutions only flagged as warnings, see SubstitutionWarning.yml
+# Checks for misused terms that should never be used at GitLab.
+# SubstitutionWarning.yml and SubstitionSuggestions.yml also exist.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 3d8e9b1ef72..6ce0ced52b3 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -45,6 +45,7 @@ backtraces
backtracing
badging
Bamboo
+Bazel
Bitbucket
blockquote
blockquoted
@@ -94,6 +95,7 @@ crosslinking
crosslinks
Crossplane
CrowdIn
+CSV
Dangerfile
datetime
Debian
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index 7436661920a..27f6bbcd028 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -103,6 +103,8 @@ From there, you can see the following actions:
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)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2336) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.3.
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index 448922230e7..59d00265a1b 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -38,7 +38,7 @@ JWT will provide you with a secret key for you to use.
algorithm: 'HS256', # Supported algorithms: 'RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512'
uid_claim: 'email',
required_claims: ['name', 'email'],
- info_maps: { name: 'name', email: 'email' },
+ info_map: { name: 'name', email: 'email' },
auth_url: 'https://example.com/',
valid_within: 3600 # 1 hour
}
diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index dcfb77f277e..6fecf74d935 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -20,7 +20,7 @@ The steps below cover:
## Configuring Google LDAP client
-1. Navigate to <https://admin.google.com/Dashboard> and sign in as a GSuite domain administrator.
+1. Navigate to <https://admin.google.com/Dashboard> and sign in as a Google Workspace domain administrator.
1. Go to **Apps > LDAP > Add Client**.
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 4dedaba3754..de0f123acf1 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -201,9 +201,9 @@ LDAP attributes that GitLab uses to create an account for the LDAP user. The spe
| ------- | ----------- | -------- | -------- |
| `username` | The username is used in paths for the user's own projects (like `gitlab.example.com/username/project`) and when mentioning them in issues, merge request and comments (like `@username`). If the attribute specified for `username` contains an email address, the GitLab username is part of the email address before the `@`. | no | `['uid', 'userid', 'sAMAccountName']` |
| `email` | LDAP attribute for user email. | no | `['mail', 'email', 'userPrincipalName']` |
-| `name` | LDAP attribute for user display name. If no full name could be found at the attribute specified for `name`, the full name is determined using the attributes specified for `first_name` and `last_name`. | no | `'cn'` or `'displayName'` |
-| `first_name` | LDAP attribute for user first name. | no | `'givenName'` |
-| `last_name` | LDAP attribute for user last name. | no | `'sn'` |
+| `name` | LDAP attribute for user display name. If `name` is blank, the full name is taken from the `first_name` and `last_name`. | no | Attributes `'cn'`, or `'displayName'` commonly carry full names. Alternatively, you can force the use of `first_name` and `last_name` by specifying an absent attribute such as `'somethingNonExistent'`. |
+| `first_name` | LDAP attribute for user first name. Used when the attribute configured for `name` does not exist. | no | `'givenName'` |
+| `last_name` | LDAP attribute for user last name. Used when the attribute configured for `name` does not exist. | no | `'sn'` |
### LDAP Sync Configuration Settings **(STARTER ONLY)**
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 85b72d7b18f..6079e838ac6 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 |
-| ---------| :--------: | :-------: |
-|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+||
-|**[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+|✓|
-|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||
-|**[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+||
-|**[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+||
-|**[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+|✓|
-|**[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+||
-|**[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+||
-|**[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+||
-|**[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+||
-|**[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||
-|**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+||
+|Feature |GitLab tier |GitLab.com | 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|
+|**[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|
+|**[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|
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index be84b260127..2b0a3e2f114 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -15,7 +15,7 @@ See [Geo limitations](../index.md#limitations) for more information.
WARNING:
Disaster recovery for multi-secondary configurations is in **Alpha**.
-For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/590).
+For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/3574).
Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and
will cause downtime.
@@ -181,7 +181,7 @@ secondary. If the node is paused, be sure to resume before promoting. This
issue has been fixed in GitLab 13.4 and later.
WARNING:
- If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
+If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
Data that was created on the primary while the secondary was paused will be lost.
@@ -220,6 +220,75 @@ Data that was created on the primary while the secondary was paused will be lost
previously for the **secondary**.
1. Success! The **secondary** has now been promoted to **primary**.
+#### Promoting a **secondary** node with a Patroni standby cluster
+
+The `gitlab-ctl promote-to-primary-node` command cannot be used yet in
+conjunction with a Patroni standby cluster, as it can only
+perform changes on a **secondary** with only a single machine. Instead, you must
+do this manually.
+
+WARNING:
+In GitLab 13.2 and 13.3, 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. This
+issue has been fixed in GitLab 13.4 and later.
+
+WARNING:
+If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
+a point-in-time recovery to the last known state.
+Data that was created on the primary while the secondary was paused will be lost.
+
+1. SSH in to the Standby Leader database node in the **secondary** and trigger PostgreSQL to
+ promote to read-write:
+
+ ```shell
+ 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
+ ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
+ geo_secondary_role['enable'] = true
+
+ ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
+ roles ['geo_secondary_role']
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` on every Patroni node in the secondary to disable the standby cluster:
+
+ ```ruby
+ patroni['standby_cluster']['enable'] = false
+ ```
+
+1. Reconfigure GitLab on each machine for the changes to take effect:
+
+ ```shell
+ 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
+ sudo gitlab-rake geo:set_secondary_as_primary
+ ```
+
+1. Verify you can connect to the newly promoted **primary** using the URL used previously for the **secondary**.
+
+1. Success! The **secondary** has now been promoted to **primary**.
+
#### Promoting a **secondary** node with an external PostgreSQL database
The `gitlab-ctl promote-to-primary-node` command cannot be used in conjunction with
@@ -278,7 +347,7 @@ required:
1. Verify you can connect to the newly promoted **primary** site using the URL used
previously for the **secondary** site.
-Success! The **secondary** site has now been promoted to **primary**.
+1. Success! The **secondary** site has now been promoted to **primary**.
### Step 4. (Optional) Updating the primary domain DNS record
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 334f05ef3ce..1985ea2e04c 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -292,12 +292,6 @@ This list of limitations only reflects the latest version of GitLab. If you are
### Limitations on replication/verification
-You can keep track of the progress to implement the missing items in
-these epics/issues:
-
-- [Unreplicated Data Types](https://gitlab.com/groups/gitlab-org/-/epics/893)
-- [Verify all replicated data](https://gitlab.com/groups/gitlab-org/-/epics/1430)
-
There is a complete list of all GitLab [data types](replication/datatypes.md) and [existing support for replication and verification](replication/datatypes.md#limitations-on-replicationverification).
## Frequently Asked Questions
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 42501e16f5f..5adf256f6fa 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -170,6 +170,11 @@ keys must be manually replicated to the **secondary** node.
sudo service sshd reload
```
+1. Verify SSH is still functional.
+
+ SSH into your GitLab **secondary** server in a new terminal. If you are unable to connect,
+ verify the permissions are correct according to the previous steps.
+
### Step 3. Add the **secondary** node
1. SSH into your GitLab **secondary** server and login as root:
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 9778e08a30b..6e2ddfb812c 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -497,54 +497,135 @@ For instructions about how to set up Patroni on the primary node, see the
If you are currently using `repmgr` on your Geo primary, 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, and a similar configuration on the secondary nodes. Be sure to use
-password credentials and other database best practices.
+the primary site, and a similar configuration on the secondary sites. Be sure to
+use password credentials and other database best practices.
Similar to `repmgr`, using Patroni on a secondary node is optional.
-To set up database replication with Patroni on a secondary node, configure a
-_permanent replication slot_ on the primary node's Patroni cluster, and ensure
-password authentication is used.
-
-On Patroni instances for the primary node, add the following to the
-`/etc/gitlab/gitlab.rb` file:
-
-```ruby
-# You need one entry for each secondary, with a unique name following PostgreSQL slot_name constraints:
-#
-# Configuration syntax will be: 'unique_slotname' => { 'type' => 'physical' },
-# We don't support setting a permanent replication slot for logical replication type
-patroni['replication_slots'] = {
- 'geo_secondary' => { 'type' => 'physical' }
-}
-
-postgresql['md5_auth_cidr_addresses'] = [
- 'PATRONI_PRIMARY1_IP/32', 'PATRONI_PRIMARY2_IP/32', 'PATRONI_PRIMARY3_IP/32', 'PATRONI_PRIMARY_PGBOUNCER/32',
- 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32' # we list all secondary instances as they can all become a Standby Leader
- # any other instance that needs access to the database as per documentation
-]
-
-postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
-postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
-postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
-```
-
-On Patroni instances for the secondary node, add the following to the
-`/etc/gitlab/gitlab.rb` file:
-
-```ruby
-postgresql['md5_auth_cidr_addresses'] = [
- 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32',
- # any other instance that needs access to the database as per documentation
-]
-
-patroni['enable'] = true
-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']['primary_slot_name'] = 'geo_secondary' # or the unique replication slot name you setup before
-patroni['replication_password'] = 'PLAIN_TEXT_POSTGRESQL_REPLICATION_PASSWORD'
-```
+### Step 1. Configure Patroni permanent replication slot on the primary site
+
+To set up database replication with Patroni on a secondary node, we need to
+configure a _permanent replication slot_ on the primary node's Patroni cluster,
+and ensure password authentication is used.
+
+For each Patroni instance on the primary site **starting on the Patroni
+Leader instance**:
+
+1. SSH into your Patroni instance and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following:
+
+ ```ruby
+ consul['enable'] = true
+ consul['configuration'] = {
+ retry_join: %w[CONSUL_PRIMARY1_IP CONSULT_PRIMARY2_IP CONSULT_PRIMARY3_IP]
+ }
+
+ repmgr['enable'] = false
+
+ # You need one entry for each secondary, with a unique name following PostgreSQL slot_name constraints:
+ #
+ # Configuration syntax will be: 'unique_slotname' => { 'type' => 'physical' },
+ # We don't support setting a permanent replication slot for logical replication type
+ patroni['replication_slots'] = {
+ 'geo_secondary' => { 'type' => 'physical' }
+ }
+
+ patroni['use_pg_rewind'] = true
+ patroni['postgresql']['max_wal_senders'] = 8 # Use double of the amount of patroni/reserved slots (3 patronis + 1 reserved slot for a Geo secondary).
+ patroni['postgresql']['max_replication_slots'] = 8 # Use double of the amount of patroni/reserved slots (3 patronis + 1 reserved slot for a Geo secondary).
+
+ postgresql['md5_auth_cidr_addresses'] = [
+ 'PATRONI_PRIMARY1_IP/32', 'PATRONI_PRIMARY2_IP/32', 'PATRONI_PRIMARY3_IP/32', 'PATRONI_PRIMARY_PGBOUNCER/32',
+ 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32' # We list all secondary instances as they can all become a Standby Leader
+ ]
+
+ postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+ postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
+ postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+ ```
+
+1. Reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+### Step 2. Configure a Standby cluster on the secondary site
+
+NOTE:
+If you are converting a secondary site to a Patroni Cluster, you must start
+on the PostgreSQL instance. It will become the Patroni Standby Leader instance,
+and then you can switchover to another replica if you need.
+
+For each Patroni instance on the secondary site:
+
+1. SSH into your Patroni node and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following:
+
+ ```ruby
+ roles ['consul_role', 'postgres_role']
+
+ consul['enable'] = true
+ consul['configuration'] = {
+ retry_join: %w[CONSUL_SECONDARY1_IP CONSULT_SECONDARY2_IP CONSULT_SECONDARY3_IP]
+ }
+
+ repmgr['enable'] = false
+
+ postgresql['md5_auth_cidr_addresses'] = [
+ 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32',
+ # Any other instance that needs access to the database as per documentation
+ ]
+
+ patroni['enable'] = false
+ patroni['standby_cluster']['enable'] = true
+ patroni['standby_cluster']['host'] = 'PATRONI_PRIMARY_LEADER_IP' # This needs to be changed anytime the primary Leader changes
+ patroni['standby_cluster']['port'] = 5432
+ 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
+ patroni['postgresql']['max_wal_senders'] = 5 # A minimum of three for one replica, plus two for each additional replica
+ patroni['postgresql']['max_replication_slots'] = 5 # A minimum of three for one replica, plus two for each additional replica
+ ```
+
+1. Reconfigure GitLab for the changes to take effect.
+ This is required to bootstrap PostgreSQL users and settings:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. Remove the PostgreSQL data directory:
+
+ WARNING:
+ If you are converting a secondary site to a Patroni Cluster, you must skip
+ this step on the PostgreSQL instance.
+
+ ```shell
+ rm -rf /var/opt/gitlab/postgresql/data
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` to enable Patroni:
+
+ ```ruby
+ patroni['enable'] = true
+ ```
+
+1. Reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
## Migrating from repmgr to Patroni
diff --git a/doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png b/doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png
deleted file mode 100644
index 4d2c5cdb00c..00000000000
--- a/doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index e0b0d52fe3f..9577fb40abe 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -395,7 +395,7 @@ Gitaly makes the following assumptions:
You can't define Gitaly servers with some as a local Gitaly server
(without `gitaly_address`) and some as remote
-server (with `gitaly_address`) unless you setup with special
+server (with `gitaly_address`) unless you use
[mixed configuration](#mixed-configuration).
**For Omnibus GitLab**
@@ -502,8 +502,8 @@ 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, leaving it only running
+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.
Disabling Gitaly on the GitLab instance only makes sense when you run GitLab in a custom cluster configuration, where
@@ -1007,7 +1007,7 @@ When GitLab calls a function that has a "Rugged patch", it performs two checks:
- Is the feature flag for this patch set in the database? If so, the feature flag setting controls
the GitLab use of "Rugged patch" code.
-- If the feature flag is not set, GitLab tries accessing the filesystem underneath the
+- If the feature flag is not set, GitLab tries accessing the file system underneath the
Gitaly server directly. If it can, it uses the "Rugged patch":
- If using Unicorn.
- If using Puma and [thread count](../../install/requirements.md#puma-threads) is set
@@ -1015,9 +1015,9 @@ When GitLab calls a function that has a "Rugged patch", it performs two checks:
The result of these checks is cached.
-To see if GitLab can access the repository filesystem directly, we use the following heuristic:
+To see if GitLab can access the repository file system directly, we use the following heuristic:
-- Gitaly ensures that the filesystem has a metadata file in its root with a UUID in it.
+- 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.
- GitLab Rails tries to read the metadata file directly. If it exists, and if the UUID's match,
assume we have direct access.
@@ -1044,13 +1044,11 @@ The second facet presents the only real solution. For this, we developed
Check [Gitaly timeouts](../../user/admin_area/settings/gitaly_timeouts.md) when troubleshooting
Gitaly.
-### Checking versions when using standalone Gitaly servers
+### Check versions when using standalone Gitaly servers
When using standalone Gitaly servers, you must make sure they are the same version
-as GitLab to ensure full compatibility. Check **Admin Area > Gitaly Servers** on
-your GitLab instance and confirm all Gitaly Servers are `Up to date`.
-
-![Gitaly standalone software versions diagram](img/gitlab_gitaly_version_mismatch_v12_4.png)
+as GitLab to ensure full compatibility. Check **Admin Area > Overview > Gitaly Servers** on
+your GitLab instance and confirm all Gitaly servers indicate that they are up to date.
### `gitaly-debug`
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 6eaafae6015..fe8b3e5f566 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -5,17 +5,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Gitaly Cluster
+# Gitaly Cluster **(CORE ONLY)**
[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 shards) can be configured.
NOTE:
-Gitaly Clusters can be created using [GitLab Core](https://about.gitlab.com/pricing/#self-managed)
-and higher tiers. However, technical support is limited to GitLab Premium and Ultimate customers
-only. Not available in GitLab.com.
+Technical support for Gitaly clusters is limited to GitLab Premium and Ultimate
+customers.
Praefect is a router and transaction manager for Gitaly, and a required
component for running a Gitaly Cluster.
@@ -1364,7 +1363,7 @@ 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.
-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:
The Project repository storage moves API [cannot move all repository types](../../api/project_repository_storage_moves.md#limitations).
@@ -1388,6 +1387,8 @@ To move repositories to Gitaly Cluster:
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):
+
## Debugging Praefect
If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md
index 90d2f0d916d..178fc438df2 100644
--- a/doc/administration/housekeeping.md
+++ b/doc/administration/housekeeping.md
@@ -40,3 +40,20 @@ from your project on the same schedule as the `git gc` operation, freeing up sto
You can find this option under your project's **Settings > General > Advanced**.
![Housekeeping settings](img/housekeeping_settings.png)
+
+## How housekeeping handles pool repositories
+
+Housekeeping for pool repositories is handled differently from standard repositories.
+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::GitDeduplicationService#fetch_from_source`
+1. `ObjectPool#fetch`
+1. `ObjectPoolService#fetch`
+1. `Gitaly::FetchIntoObjectPoolRequest`
+
+To manually invoke it from a Rails console, if needed, you can call `project.pool_repository.object_pool.fetch`.
+This is a potentially long-running task, though Gitaly will timeout in about 8 hours.
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 7a49542f8bb..2eb5da7d9ab 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -251,7 +251,7 @@ incoming_email:
#### Gmail
-Example configuration for Gmail/G Suite. Assumes mailbox `gitlab-incoming@gmail.com`.
+Example configuration for Gmail/Google Workspace. Assumes mailbox `gitlab-incoming@gmail.com`.
NOTE:
`incoming_email_email` cannot be a Gmail alias account.
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 32c0b1b0712..f071fde2faa 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -33,14 +33,13 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Installing GitLab
- [Install](../install/README.md): Requirements, directory structures, and installation methods.
- - [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers. **(STARTER ONLY)**
- - [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only) **(STARTER ONLY)**
+ - [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.
- [Installing GitLab on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab on Amazon AWS.
-- [Geo](geo/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version. **(PREMIUM ONLY)**
-- [Disaster Recovery](geo/disaster_recovery/index.md): Quickly fail-over to a different site with minimal effort in a disaster situation. **(PREMIUM ONLY)**
-- [Pivotal Tile](../install/pivotal/index.md): Deploy GitLab as a preconfigured appliance using Ops Manager (BOSH) for Pivotal Cloud Foundry. **(PREMIUM ONLY)**
-- [Add License](../user/admin_area/license.md): Upload a license at install time to unlock features that are in paid tiers of GitLab. **(STARTER ONLY)**
+- [Geo](geo/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version.
+- [Disaster Recovery](geo/disaster_recovery/index.md): Quickly fail-over to a different site with minimal effort in a disaster situation.
+- [Add License](../user/admin_area/license.md): Upload a license at install time to unlock features that are in paid tiers of GitLab.
### Configuring GitLab
@@ -72,11 +71,9 @@ Learn how to install, configure, update, and maintain your GitLab instance.
to GitLab users through the UI.
- [Elasticsearch](../integration/elasticsearch.md): Enable Elasticsearch to
empower Advanced Search. Useful when you deal with a huge amount of data.
- **(STARTER ONLY)**
-- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md)
- **(PREMIUM ONLY)**
+- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md).
- [Upload a license](../user/admin_area/license.md): Upload a license to unlock
- features that are in paid tiers of GitLab. **(STARTER ONLY)**
+ features that are in paid tiers of GitLab.
- [Admin Area](../user/admin_area/index.md): for self-managed instance-wide
configuration and maintenance.
- [S/MIME Signing](smime_signing_email.md): how to sign all outgoing notification
@@ -90,7 +87,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Favicon](../user/admin_area/appearance.md#favicon): Change the default favicon to your own logo.
- [Branded login page](../user/admin_area/appearance.md#sign-in--sign-up-pages): Customize the login page with your own logo, title, and description.
- ["New Project" page](../user/admin_area/appearance.md#new-project-pages): Customize the text to be displayed on the page that opens whenever your users create a new project.
-- [Additional custom email text](../user/admin_area/settings/email.md#custom-additional-text): Add additional custom text to emails sent from GitLab. **(PREMIUM ONLY)**
+- [Additional custom email text](../user/admin_area/settings/email.md#custom-additional-text): Add additional custom text to emails sent from GitLab.
### Maintaining GitLab
@@ -127,15 +124,15 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Sign-up restrictions](../user/admin_area/settings/sign_up_restrictions.md): block email addresses of specific domains, or whitelist only specific domains.
- [Access restrictions](../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab (SSH, HTTP, HTTPS).
- [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS, and additional providers.
- - [Sync LDAP](auth/ldap/index.md) **(STARTER ONLY)**
- - [Kerberos authentication](../integration/kerberos.md) **(STARTER ONLY)**
+ - [Sync LDAP](auth/ldap/index.md).
+ - [Kerberos authentication](../integration/kerberos.md).
- See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA).
-- [Email users](../tools/email.md): Email GitLab users from within GitLab. **(STARTER ONLY)**
+- [Email users](../tools/email.md): Email GitLab users from within GitLab.
- [User Cohorts](../user/admin_area/analytics/user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
- [Audit events](audit_events.md): View the changes made within the GitLab server for:
- - Groups and projects. **(STARTER)**
- - Instances. **(PREMIUM ONLY)**
-- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance. **(PREMIUM ONLY)**
+ - Groups and projects.
+ - Instances.
+- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance.
- [Incoming email](incoming_email.md): Configure incoming emails to allow
users to [reply by email](reply_by_email.md), create [issues by email](../user/project/issues/managing_issues.md#new-issue-via-email) and
[merge requests by email](../user/project/merge_requests/creating_merge_requests.md#new-merge-request-by-email), and to enable [Service Desk](../user/project/service_desk.md).
@@ -143,7 +140,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
basic Postfix mail server with IMAP authentication on Ubuntu for incoming
emails.
- [Abuse reports](../user/admin_area/abuse_reports.md): View and resolve abuse reports from your users.
-- [Credentials Inventory](../user/admin_area/credentials_inventory.md): With Credentials inventory, GitLab administrators can keep track of the credentials used by their users in their GitLab self-managed instance. **(ULTIMATE ONLY)**
+- [Credentials Inventory](../user/admin_area/credentials_inventory.md): With Credentials inventory, GitLab administrators can keep track of the credentials used by their users in their GitLab self-managed instance.
## Project settings
@@ -151,7 +148,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Gitaly](gitaly/index.md): Configuring Gitaly, the Git repository storage service for GitLab.
- [Default labels](../user/admin_area/labels.md): Create labels that are automatically added to every new project.
- [Restrict the use of public or internal projects](../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects): Restrict the use of visibility levels for users when they create a project or a snippet.
-- [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project. **(PREMIUM ONLY)**
+- [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project.
## Package Registry administration
@@ -165,7 +162,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Repository storage paths](repository_storage_paths.md): Manage the paths used to store repositories.
- [Repository storage types](repository_storage_types.md): Information about the different repository storage types.
- [Repository storage Rake tasks](raketasks/storage.md): A collection of Rake tasks to list and migrate existing projects and attachments associated with it from Legacy storage to Hashed storage.
-- [Limit repository size](../user/admin_area/settings/account_and_limit_settings.md): Set a hard limit for your repositories' size. **(STARTER ONLY)**
+- [Limit repository size](../user/admin_area/settings/account_and_limit_settings.md): Set a hard limit for your repositories' size.
- [Static objects external storage](static_objects_external_storage.md): Set external storage for static objects in a repository.
## Continuous Integration settings
@@ -176,7 +173,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job logs](job_logs.md): Information about the job logs.
- [Register runners](../ci/runners/README.md#types-of-runners): Learn how to register and configure runners.
-- [Shared runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for shared runners. **(STARTER ONLY)**
+- [Shared runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for shared runners.
- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enablingdisabling-auto-devops): Enable or disable Auto DevOps for your instance.
## Snippet settings
@@ -213,7 +210,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Analytics
-- [Pseudonymizer](pseudonymizer.md): Export data from a GitLab database to CSV files in a secure way. **(ULTIMATE)**
+- [Pseudonymizer](pseudonymizer.md): Export data from a GitLab database to CSV files in a secure way.
## Troubleshooting
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index a7458999aaa..cd61dc9a2bf 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -37,7 +37,7 @@ A simple `docker-compose.yml` file would be:
version: "3"
services:
gitlab:
- image: 'gitlab/gitlab-ce:12.2.5-ce.0'
+ image: 'gitlab/gitlab-ee:12.2.5-ee.0'
environment:
GITLAB_OMNIBUS_CONFIG: |
nginx['custom_gitlab_server_config'] = "location /-/plantuml/ { \n proxy_cache off; \n proxy_pass http://plantuml:8080/; \n}\n"
@@ -90,8 +90,8 @@ the configuration below accordingly.
### Making local PlantUML accessible using custom GitLab setup
The PlantUML server runs locally on your server, so it is not accessible
-externally. As such, it is necessary to catch external PlantUML calls and
-redirect them to the local server.
+externally by default. As such, it is necessary to catch external PlantUML
+calls and redirect them to the local server.
The idea is to redirect each call to `https://gitlab.example.com/-/plantuml/`
to the local PlantUML server `http://plantuml:8080/` or `http://localhost:8080/plantuml/`, depending on your setup.
@@ -112,6 +112,12 @@ To activate the changes, run the following command:
sudo gitlab-ctl reconfigure
```
+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)
+do not load insecure HTTP resources on a page served over HTTPS.
+
### Security
PlantUML has features that allows fetching network resources.
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index 7af167de4ad..b2c6864e671 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -50,7 +50,7 @@ these steps to move the logs to a new location without losing any data.
Jobs in progress are not affected, based on how [data flow](#data-flow) works.
```ruby
- sidekiq['experimental_queue_selector'] = true
+ sidekiq['queue_selector'] = true
sidekiq['queue_groups'] = [
"feature_category!=continuous_integration"
]
@@ -185,7 +185,7 @@ Feature.enable(:ci_enable_live_trace)
```
NOTE:
-The transition period is handled gracefully. Upcoming logs are
+The transition period is handled gracefully. Upcoming logs are
generated with the incremental architecture, and on-going logs stay with the
legacy architecture, which means that on-going logs aren't forcibly
re-generated with the incremental architecture.
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index 5b82696ae4b..072baa16e29 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -61,3 +61,14 @@ half above the interval. For example, for a user defined interval of 15 seconds
the actual interval can be anywhere between 7.5 and 22.5. The interval is
re-generated for every sampling run instead of being generated one time and reused
for the duration of the process' lifetime.
+
+User defined intervals can be specified by means of environment variables.
+The following environment variables are recognized:
+
+- `RUBY_SAMPLER_INTERVAL_SECONDS`
+- `DATABASE_SAMPLER_INTERVAL_SECONDS`
+- `ACTION_CABLE_SAMPLER_INTERVAL_SECONDS`
+- `PUMA_SAMPLER_INTERVAL_SECONDS`
+- `UNICORN_SAMPLER_INTERVAL_SECONDS`
+- `THREADS_SAMPLER_INTERVAL_SECONDS`
+- `GLOBAL_SEARCH_SAMPLER_INTERVAL_SECONDS`
diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md
index 8e4d87cfa78..5add842bccc 100644
--- a/doc/administration/monitoring/prometheus/gitlab_exporter.md
+++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md
@@ -30,3 +30,27 @@ To enable the GitLab exporter in an Omnibus GitLab instance:
Prometheus automatically begins collecting performance data from
the GitLab exporter exposed at `localhost:9168`.
+
+## Use a different Rack server
+
+>- Introduced in [Omnibus GitLab 13.8](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4896).
+>- WEBrick is now the default Rack server instead of Puma.
+
+By default, the GitLab exporter runs on [WEBrick](https://github.com/ruby/webrick), a single-threaded Ruby web server.
+You can choose a different Rack server that better matches your performance needs.
+For instance, in multi-node setups that contain a large number of Prometheus scrapers
+but only a few monitoring nodes, you may decide to run a multi-threaded server such as Puma instead.
+
+To change the Rack server to Puma:
+
+1. Edit `/etc/gitlab/gitlab.rb`.
+1. Add, or find and uncomment, the following line, and set it to `puma`:
+
+ ```ruby
+ gitlab_exporter['server_name'] = 'puma'
+ ```
+
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ for the changes to take effect.
+
+The supported Rack servers are `webrick` and `puma`.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index c5e0570515d..4493c1677bc 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -210,6 +210,7 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
| `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)**
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index 1e2ac531329..bddf770180b 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -15,9 +15,10 @@ For data objects such as LFS, Uploads, Artifacts, etc., an [Object Storage servi
is recommended over NFS where possible, due to better performance.
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0,
-support for NFS for Git repositories is scheduled to be removed. Upgrade to
-[Gitaly Cluster](gitaly/praefect.md) as soon as possible.
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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
actions that read or write to Git repositories. For steps you can use to test
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index a89c50a8412..999d9b87363 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -61,10 +61,10 @@ must be enabled, only the following providers can be used:
- [Google Cloud Storage](#google-cloud-storage-gcs)
- [Azure Blob storage](#azure-blob-storage)
-Background upload isn't supported with the consolidated object storage
-configuration. We recommend enabling direct upload mode because it doesn't
-require a shared folder, and [this setting may become the
-default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331).
+When consolidated object storage is used, direct upload is enabled
+automatically. Background upload is not supported. For storage-specific
+configuration, [direct upload may become the default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331)
+because it does not require a shared folder.
Consolidated object storage configuration can't be used for backups or
Mattermost. See the [full table for a complete list](#storage-specific-configuration).
@@ -232,7 +232,7 @@ The connection settings match those provided by [fog-aws](https://github.com/fog
| `aws_secret_access_key` | AWS credentials, or compatible | |
| `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` |
| `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` |
-| `region` | AWS region | us-east-1 |
+| `region` | AWS region. | |
| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) |
| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false` |
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 1f611a50a53..1b7c0edab04 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -114,7 +114,7 @@ you list:
> - [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.
-> - [Marked as supported](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 13.6. Renamed from `experimental_queue_selector` to `queue_selector`.
+> - [Renamed from `experimental_queue_selector` to `queue_selector`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab 13.6.
In addition to selecting queues by name, as above, the `queue_selector`
option allows queue groups to be selected in a more general way using
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 7cc15f9cea4..029f3bb01ed 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -23,12 +23,14 @@ 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.
- [The API documentation](../../api/project_repository_storage_moves.md) details the endpoints for
- querying and scheduling repository moves.
+ 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.
- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
### Limitations
-Read more in the [API documentation](../../api/project_repository_storage_moves.md#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
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 633129e98bd..ab6202fef4c 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -600,6 +600,28 @@ on how to achieve that.
If you use an external container registry, some features associated with the
container registry may be unavailable or have [inherent risks](../../user/packages/container_registry/index.md#use-with-external-container-registries).
+For the integration to work, the external registry must be configured to
+use a JSON Web Token to authenticate with GitLab. The
+[external registry's runtime configuration](https://docs.docker.com/registry/configuration/#token)
+**must** have the following entries:
+
+```yaml
+auth:
+ token:
+ realm: https://gitlab.example.com/jwt/auth
+ service: container_registry
+ issuer: gitlab-issuer
+ rootcertbundle: /root/certs/certbundle
+```
+
+Without these entries, the registry logins cannot authenticate with GitLab.
+GitLab also remains unaware of
+[nested image names](../../user/packages/container_registry/#image-naming-convention)
+under the project hierarchy, like
+`registry.example.com/group/project/image-name:tag` or
+`registry.example.com/group/project/my/image-name:tag`, and only recognizes
+`registry.example.com/group/project:tag`.
+
**Omnibus GitLab**
You can use GitLab as an auth endpoint with an external container registry.
@@ -609,18 +631,23 @@ You can use GitLab as an auth endpoint with an external container registry.
```ruby
gitlab_rails['registry_enabled'] = true
gitlab_rails['registry_api_url'] = "http://localhost:5000"
- gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
+ gitlab_rails['registry_issuer'] = "gitlab-issuer"
```
`gitlab_rails['registry_enabled'] = true` is needed to enable GitLab
Container Registry features and authentication endpoint. The GitLab bundled
Container Registry service does not start, even with this enabled.
+ `gitlab_rails['registry_api_url'] = "http://localhost:5000"` can
+ carry a different hostname and port depending on where the external registry
+ is hosted. It must also specify `https` if the external registry is
+ configured to use TLS.
+
1. A certificate-key pair is required for GitLab and the external container
registry to communicate securely. You need to create a certificate-key
pair, configuring the external container registry with the public
- certificate and configuring GitLab with the private key. To do that, add
- the following to `/etc/gitlab/gitlab.rb`:
+ certificate (`rootcertbundle`) and configuring GitLab with the private key.
+ To do that, add the following to `/etc/gitlab/gitlab.rb`:
```ruby
# registry['internal_key'] should contain the contents of the custom key
@@ -664,7 +691,7 @@ You can use GitLab as an auth endpoint with an external container registry.
api_url: "http://localhost:5000"
path: /var/opt/gitlab/gitlab-rails/shared/registry
key: /var/opt/gitlab/gitlab-rails/certificate.key
- issuer: omnibus-gitlab-issuer
+ issuer: gitlab-issuer
```
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
@@ -840,6 +867,26 @@ understand the implications.
WARNING:
This is a destructive operation.
+When you run `registry-garbage-collect` with the -m flag, garbage collection unlinks manifests that
+are part of a multi-arch manifest, unless they're tagged in the same repository.
+See [this issue](https://gitlab.com/gitlab-org/container-registry/-/issues/149) for details.
+
+To work around this issue, instead of:
+
+```plaintext
+myrepo/multiarchmanifest:latest
+myrepo/manifest/amd-64:latest
+myrepo/manifest/arm:latest
+```
+
+Use:
+
+```plaintext
+myrepo/multiarchmanifest:latest
+myrepo/manifest:amd-64-latest
+myrepo/manifest:arm-latest
+```
+
The GitLab Container Registry follows the same default workflow as Docker Distribution:
retain untagged manifests and all layers, even ones that are not referenced directly. All content
can be accessed by using context addressable identifiers.
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index af0476b72e9..9e949468805 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -38,20 +38,20 @@ which you can set it up:
- Run the Pages daemon in the same server as GitLab, listening on a **secondary IP**.
- Run the Pages daemon in a [separate server](#running-gitlab-pages-on-a-separate-server). In that case, the
[Pages path](#change-storage-path) must also be present in the server that
- the Pages daemon is installed, so you will have to share it via network.
+ the Pages daemon is installed, so you must share it through the network.
- Run the Pages daemon in the same server as GitLab, listening on the same IP
- but on different ports. In that case, you will have to proxy the traffic with
+ but on different ports. In that case, you must proxy the traffic with
a load balancer. If you choose that route note that you should use TCP load
- balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing) the
- pages will not be able to be served with user provided certificates. For
+ balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing), the
+ pages can't be served with user-provided certificates. For
HTTP it's OK to use HTTP or TCP load balancing.
-In this document, we will proceed assuming the first option. If you are not
+In this document, we proceed assuming the first option. If you are not
supporting custom domains a secondary IP is not needed.
## Prerequisites
-Before proceeding with the Pages configuration, you will need to:
+Before proceeding with the Pages configuration, you must:
1. Have a domain for Pages that is not a subdomain of your GitLab instance domain.
@@ -69,7 +69,7 @@ Before proceeding with the Pages configuration, you will need to:
1. (Only for custom domains) Have a **secondary IP**.
NOTE:
-If your GitLab instance and the Pages daemon are deployed in a private network or behind a firewall, your GitLab Pages websites will only be accessible to devices/users that have access to the private network.
+If your GitLab instance and the Pages daemon are deployed in a private network or behind a firewall, your GitLab Pages websites are only accessible to devices/users that have access to the private network.
### Add the domain to the Public Suffix List
@@ -94,13 +94,34 @@ host that GitLab runs. For example, an entry would look like this:
```plaintext
*.example.io. 1800 IN A 192.0.2.1
-*.example.io. 1800 IN AAAA 2001::1
+*.example.io. 1800 IN AAAA 2001:db8::1
```
-where `example.io` is the domain under which GitLab Pages will be served
-and `192.0.2.1` is the IPv4 address of your GitLab instance and `2001::1` is the
+Where `example.io` is the domain GitLab Pages is served from,
+`192.0.2.1` is the IPv4 address of your GitLab instance, and `2001:db8::1` is the
IPv6 address. If you don't have IPv6, you can omit the AAAA record.
+#### Custom domains
+
+If support for custom domains is needed, the Pages root domain and its subdomains should point to
+the secondary IP (which is dedicated for the Pages daemon). `<namespace>.<pages root domain>` should
+point at Pages directly. Without this, users aren't able to use `CNAME` records to point their
+custom domains to their GitLab Pages.
+
+For example, an entry could look like this:
+
+```plaintext
+example.com 1800 IN A 192.0.2.1
+*.example.io. 1800 IN A 192.0.2.2
+```
+
+This example contains the following:
+
+- `example.com`: The GitLab domain.
+- `example.io`: The domain GitLab Pages is served from.
+- `192.0.2.1`: The primary IP of your GitLab instance.
+- `192.0.2.2`: The secondary IP, which is dedicated to GitLab Pages.
+
NOTE:
You should not use the GitLab domain to serve user pages. For more information see the [security section](#security).
@@ -123,7 +144,7 @@ since that is needed in all configurations.
URL scheme: `http://<namespace>.example.io/<project_slug>`
This is the minimum setup that you can use Pages with. It is the base for all
-other setups as described below. NGINX will proxy all requests to the daemon.
+other setups as described below. NGINX proxies all requests to the daemon.
The Pages daemon doesn't listen to the outside world.
1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`:
@@ -147,7 +168,7 @@ Watch the [video tutorial](https://youtu.be/dD8c7WNcc6s) for this configuration.
URL scheme: `https://<namespace>.example.io/<project_slug>`
-NGINX will proxy all requests to the daemon. Pages daemon doesn't listen to the
+NGINX proxies all requests to the daemon. Pages daemon doesn't listen to the
outside world.
1. Place the certificate and key inside `/etc/gitlab/ssl`
@@ -168,8 +189,8 @@ outside world.
### Additional configuration for Docker container
-The GitLab Pages daemon will not have permissions to bind mounts when it runs
-in a Docker container. To overcome this issue you'll need to change the chroot
+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
behavior:
1. Edit `/etc/gitlab/gitlab.rb`.
@@ -189,7 +210,7 @@ The [GitLab Pages README](https://gitlab.com/gitlab-org/gitlab-pages#caveats) ha
Below is a table of all configuration settings known to Pages in Omnibus GitLab,
and what they do. These options can be adjusted in `/etc/gitlab/gitlab.rb`,
-and will take effect after you [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+and take effect after you [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
Most of these settings don't need to be configured manually unless you need more granular
control over how the Pages daemon runs and serves content in your environment.
@@ -218,7 +239,7 @@ control over how the Pages daemon runs and serves content in your environment.
| `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.
| `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 will bind to these addresses' network socket and receives incoming requests from it. Sets the value of `proxy_pass` in `$nginx-dir/conf/gitlab-pages.conf`.
+| `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`.
| `log_directory` | Absolute path to a log directory.
| `log_format` | The log output format: `text` or `json`.
| `log_verbose` | Verbose logging, true/false.
@@ -250,7 +271,7 @@ control over how the Pages daemon runs and serves content in your environment.
In addition to the wildcard domains, you can also have the option to configure
GitLab Pages to work with custom domains. Again, there are two options here:
support custom domains with and without TLS certificates. The easiest setup is
-that without TLS certificates. In either case, you'll need a **secondary IP**. If
+that without TLS certificates. In either case, you need a **secondary IP**. If
you have IPv6 as well as IPv4 addresses, you can use them both.
### Custom domains
@@ -274,11 +295,11 @@ world. Custom domains are supported, but no TLS.
pages_external_url "http://example.io"
nginx['listen_addresses'] = ['192.0.2.1']
pages_nginx['enable'] = false
- gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80']
+ gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80']
```
where `192.0.2.1` is the primary IP address that GitLab is listening to and
- `192.0.2.2` and `2001::2` are the secondary IPs the GitLab Pages daemon
+ `192.0.2.2` and `2001:db8::2` are the secondary IPs the GitLab Pages daemon
listens on. If you don't have IPv6, you can omit the IPv6 address.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -307,12 +328,12 @@ world. Custom domains and TLS are supported.
pages_nginx['enable'] = false
gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt"
gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key"
- gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80']
- gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001::2]:443']
+ gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80']
+ gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001:db8::2]:443']
```
where `192.0.2.1` is the primary IP address that GitLab is listening to and
- `192.0.2.2` and `2001::2` are the secondary IPs where the GitLab Pages daemon
+ `192.0.2.2` and `2001:db8::2` are the secondary IPs where the GitLab Pages daemon
listens on. If you don't have IPv6, you can omit the IPv6 address.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -321,7 +342,7 @@ world. Custom domains and TLS are supported.
To prevent malicious users from hijacking domains that don't belong to them,
GitLab supports [custom domain verification](../../user/project/pages/custom_domains_ssl_tls_certification/index.md#steps).
-When adding a custom domain, users will be required to prove they own it by
+When adding a custom domain, users are required to prove they own it by
adding a GitLab-controlled verification code to the DNS records for that domain.
If your user base is private or otherwise trusted, you can disable the
@@ -337,11 +358,11 @@ This setting is enabled by default.
allows users to add Let's Encrypt SSL certificates for GitLab Pages
sites served under a custom domain.
-To enable it, you'll need to:
+To enable it, you must:
-1. Choose an email on which you will receive notifications about expiring domains.
+1. Choose an email address on which you want to receive notifications about expiring domains.
1. Navigate to your instance's **Admin Area > Settings > Preferences** and expand **Pages** settings.
-1. Enter the email for receiving notifications and accept Let's Encrypt's Terms of Service as shown below.
+1. Enter the email address for receiving notifications and accept Let's Encrypt's Terms of Service as shown below.
1. Click **Save changes**.
![Let's Encrypt settings](img/lets_encrypt_integration_v12_1.png)
@@ -384,7 +405,7 @@ all the App nodes and Sidekiq nodes.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32095) in GitLab 12.7.
You can enforce [Access Control](#access-control) for all GitLab Pages websites hosted
-on your GitLab instance. By doing so, only logged-in users will have access to them.
+on your GitLab instance. By doing so, only logged-in users have access to them.
This setting overrides Access Control set by users in individual projects.
This can be useful to preserve information published with Pages websites to the users
@@ -417,7 +438,7 @@ internet connectivity is gated by a proxy. To use a proxy for GitLab Pages:
When using certificates issued by a custom CA, [Access Control](../../user/project/pages/pages_access_control.md#gitlab-pages-access-control) and
the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#browsing-artifacts)
-will fail to work if the custom CA is not recognized.
+fails to work if the custom CA is not recognized.
This usually results in this error:
`Post /oauth/token: x509: certificate signed by unknown authority`.
@@ -501,7 +522,7 @@ the below steps to do a no downtime transfer to a new storage location.
1. Pause Pages deployments by setting the following in `/etc/gitlab/gitlab.rb`:
```ruby
- sidekiq['experimental_queue_selector'] = true
+ sidekiq['queue_selector'] = true
sidekiq['queue_groups'] = [
"feature_category!=pages"
]
@@ -602,7 +623,7 @@ database encryption. Proceed with caution.
changes to take effect. The `gitlab-secrets.json` file is now updated with the
new configuration.
-1. Set up a new server. This will become the **Pages server**.
+1. Set up a new server. This becomes the **Pages server**.
1. Create an [NFS share](../nfs.md)
on the **Pages server** and configure this share to
@@ -668,7 +689,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 will default to `auto`.
+The default value is `nil`. However, GitLab Pages defaults to `auto`.
```ruby
gitlab_pages['domain_config_source'] = nil
@@ -806,10 +827,10 @@ provided at `/etc/ssl/ca-bundle.pem`. It's
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 will also be wrong.
+If the permissions on the source file are incorrect (they should be `0644`), then
+the file inside the chroot jail is also wrong.
-Pages will log errors in `/var/log/gitlab/gitlab-pages/current` like:
+Pages logs errors in `/var/log/gitlab/gitlab-pages/current` like:
```plaintext
x509: failed to load system roots and no roots provided
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index c7c25f0f3a7..0aebeaf2ebe 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -17,8 +17,8 @@ You are encouraged to read the [Omnibus documentation](index.md) as it provides
some invaluable information to the configuration of GitLab Pages. Please proceed
to read it before going forward with this guide.
-We also highly recommend that you use the Omnibus GitLab packages, as we
-optimize them specifically for GitLab, and we will take care of upgrading GitLab
+We also highly recommend that you use the Omnibus GitLab packages. We
+optimize them specifically for GitLab, and we take care of upgrading GitLab
Pages to the latest supported version.
## Overview
@@ -38,22 +38,22 @@ which you can set it up:
1. Run the Pages daemon in the same server as GitLab, listening on a secondary IP.
1. Run the Pages daemon in a separate server. In that case, the
[Pages path](#change-storage-path) must also be present in the server that
- the Pages daemon is installed, so you will have to share it via network.
+ the Pages daemon is installed, so you must share it through the network.
1. Run the Pages daemon in the same server as GitLab, listening on the same IP
- but on different ports. In that case, you will have to proxy the traffic with
- a load balancer. If you choose that route note that you should use TCP load
- balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing) the
- pages will not be able to be served with user provided certificates. For
- HTTP it's OK to use HTTP or TCP load balancing.
+ but on different ports. In that case, you must proxy the traffic with
+ a load balancer. If you choose that route, note that you should use TCP load
+ balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing), the
+ pages aren't able to be served with user-provided certificates. For
+ HTTP, it's OK to use HTTP or TCP load balancing.
-In this document, we will proceed assuming the first option. If you are not
-supporting custom domains a secondary IP is not needed.
+In this document, we proceed assuming the first option. If you aren't
+supporting custom domains, a secondary IP isn't needed.
## Prerequisites
Before proceeding with the Pages configuration, make sure that:
-1. You have a separate domain under which GitLab Pages will be served. In
+1. You have a separate domain to serve GitLab Pages from. In
this document we assume that to be `example.io`.
1. You have configured a **wildcard DNS record** for that domain.
1. You have installed the `zip` and `unzip` packages in the same server that
@@ -74,7 +74,7 @@ host that GitLab runs. For example, an entry would look like this:
*.example.io. 1800 IN A 192.0.2.1
```
-where `example.io` is the domain under which GitLab Pages will be served
+Where `example.io` is the domain to serve GitLab Pages from,
and `192.0.2.1` is the IP address of your GitLab instance.
NOTE:
@@ -97,7 +97,7 @@ since that is needed in all configurations.
URL scheme: `http://<namespace>.example.io/<project_slug>`
This is the minimum setup that you can use Pages with. It is the base for all
-other setups as described below. NGINX will proxy all requests to the daemon.
+other setups as described below. NGINX proxies all requests to the daemon.
The Pages daemon doesn't listen to the outside world.
1. Install the Pages daemon:
@@ -117,7 +117,7 @@ The Pages daemon doesn't listen to the outside world.
```
1. Edit `gitlab.yml` and under the `pages` setting, set `enabled` to `true` and
- the `host` to the FQDN under which GitLab Pages will be served:
+ the `host` to the FQDN to serve GitLab Pages from:
```yaml
## GitLab Pages
@@ -159,7 +159,7 @@ The Pages daemon doesn't listen to the outside world.
URL scheme: `https://<namespace>.example.io/<project_slug>`
-NGINX will proxy all requests to the daemon. Pages daemon doesn't listen to the
+NGINX proxies all requests to the daemon. Pages daemon doesn't listen to the
outside world.
1. Install the Pages daemon:
@@ -238,8 +238,8 @@ world. Custom domains are supported, but no TLS.
```
1. Edit `gitlab.yml` to look like the example below. You need to change the
- `host` to the FQDN under which GitLab Pages will be served. Set
- `external_http` to the secondary IP on which the pages daemon will listen
+ `host` to the FQDN to serve GitLab Pages from. Set
+ `external_http` to the secondary IP on which the pages daemon listens
for connections:
```yaml
@@ -303,9 +303,9 @@ world. Custom domains and TLS are supported.
```
1. Edit `gitlab.yml` to look like the example below. You need to change the
- `host` to the FQDN under which GitLab Pages will be served. Set
+ `host` to the FQDN to serve GitLab Pages from. Set
`external_http` and `external_https` to the secondary IP on which the pages
- daemon will listen for connections:
+ daemon listens for connections:
```yaml
## GitLab Pages
diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md
index f09ac3052f4..951edfeaec2 100644
--- a/doc/administration/postgresql/pgbouncer.md
+++ b/doc/administration/postgresql/pgbouncer.md
@@ -66,6 +66,12 @@ This content has been moved to a [new location](replication_and_failover.md#conf
1. At this point, your instance should connect to the database through PgBouncer. If you are having issues, see the [Troubleshooting](#troubleshooting) section
+## Backups
+
+Do not backup or restore GitLab through a PgBouncer connection: this will cause a GitLab outage.
+
+[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer).
+
## Enable Monitoring
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0.
@@ -150,7 +156,10 @@ ote_pid | tls
## Procedure for bypassing PgBouncer
-Some database changes have to be done directly, and not through PgBouncer. This includes database restores and GitLab upgrades (because of the database migrations).
+Some database changes have to be done directly, and not through PgBouncer.
+
+Read more about the affected tasks: [database restores](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer)
+and [GitLab upgrades](https://docs.gitlab.com/omnibus/update/README.html#use-postgresql-ha).
1. To find the primary node, run the following on a database node:
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 303246c9c82..75d0c558962 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -46,22 +46,19 @@ Each database node runs three services:
`PostgreSQL` - The database itself.
-`repmgrd` - Communicates with other repmgrd services in the cluster and handles
-failover when issues with the master server occurs. The failover procedure
+`Patroni` - Communicates with other patroni services in the cluster and handles
+failover when issues with the leader server occurs. The failover procedure
consists of:
-- Selecting a new master for the cluster.
-- Promoting the new node to master.
-- Instructing remaining servers to follow the new master node.
-- The old master node is automatically evicted from the cluster and should be
- rejoined manually once recovered.
+- Selecting a new leader for the cluster.
+- Promoting the new node to leader.
+- Instructing remaining servers to follow the new leader node.
-`Consul` agent - Monitors the status of each node in the database cluster and
-tracks its health in a service definition on the Consul cluster.
+`Consul` agent - To communicate with Consul cluster which stores the current Patroni state. The agent monitors the status of each node in the database cluster and tracks its health in a service definition on the Consul cluster.
### Consul server node
-The Consul server node runs the Consul server service.
+The Consul server node runs the Consul server service. These nodes must have reached the quorum and elected a leader _before_ Patroni cluster bootstrap otherwise database nodes will wait until such Consul leader is elected.
### PgBouncer node
@@ -80,7 +77,7 @@ Each service in the package comes with a set of [default ports](https://docs.git
- Application servers connect to either PgBouncer directly via its [default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#pgbouncer) or via a configured Internal Load Balancer (TCP) that serves multiple PgBouncers.
- PgBouncer connects to the primary database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql)
-- Repmgr connects to the database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql)
+- Patroni actively manages the running PostgreSQL processes and configuration.
- PostgreSQL secondaries connect to the primary database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql)
- Consul servers and agents connect to each others [Consul default ports](https://docs.gitlab.com/omnibus/package-information/defaults.html#consul)
@@ -141,7 +138,7 @@ available database connections.
In this document we are assuming 3 database nodes, which makes this configuration:
```ruby
-postgresql['max_wal_senders'] = 4
+patroni['postgresql']['max_wal_senders'] = 4
```
As previously mentioned, you'll have to prepare the network subnets that will
@@ -186,18 +183,6 @@ Few notes on the service itself:
- `/etc/gitlab/gitlab.rb`: hashed, and in plain text
- `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
-#### Repmgr information
-
-When using default setup, you will only have to prepare the network subnets that will
-be allowed to authenticate with the service.
-
-Few notes on the service itself:
-
-- The service runs under the same system account as the database
- - In the package, this is by default `gitlab-psql`
-- The service will have a superuser database user account generated for it
- - This defaults to `gitlab_repmgr`
-
### Installing Omnibus GitLab
First, make sure to [download/install](https://about.gitlab.com/install/)
@@ -212,72 +197,80 @@ When installing the GitLab package, do not supply `EXTERNAL_URL` value.
1. Make sure to [configure the Consul nodes](../consul.md).
1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information), [`POSTGRESQL_PASSWORD_HASH`](#postgresql-information), the [number of db nodes](#postgresql-information), and the [network address](#network-information) before executing the next step.
-1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+#### Configuring Patroni cluster
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
+You must enable Patroni explicitly to be able to use it (with `patroni['enable'] = true`). When Patroni is enabled
+repmgr will be disabled automatically.
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+Any PostgreSQL configuration item that controls replication, for example `wal_level`, `max_wal_senders`, etc, are strictly
+controlled by Patroni and will override the original settings that you make with the `postgresql[...]` configuration key.
+Hence, they are all separated and placed under `patroni['postgresql'][...]`. This behavior is limited to replication.
+Patroni honours any other PostgreSQL configuration that was made with the `postgresql[...]` configuration key. For example,
+`max_wal_senders` by default is set to `5`. If you wish to change this you must set it with the `patroni['postgresql']['max_wal_senders']`
+configuration key.
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
+NOTE:
+The configuration of a Patroni node is very similar to a repmgr but shorter. When Patroni is enabled, first you can ignore
+any replication setting of PostgreSQL (it will be overwritten anyway). Then you can remove any `repmgr[...]` or
+repmgr-specific configuration as well. Especially, make sure that you remove `postgresql['shared_preload_libraries'] = 'repmgr_funcs'`.
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
+Here is an example similar to [the one that was done with repmgr](#configuring-repmgr-nodes):
- # START user configuration
- # Please set the real values as explained in Required Information section
- #
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
- # Replace X with value of number of db nodes + 1
- postgresql['max_wal_senders'] = X
- postgresql['max_replication_slots'] = X
+```ruby
+# Disable all components except PostgreSQL, Patroni (or Repmgr), and Consul
+roles['postgres_role']
- # Replace XXX.XXX.XXX.XXX/YY with Network Address
- postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 XXX.XXX.XXX.XXX/YY)
+# Enable Patroni (which automatically disables Repmgr).
+patroni['enable'] = true
- # Replace placeholders:
- #
- # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
- # with the addresses gathered for CONSUL_SERVER_NODES
- consul['configuration'] = {
- retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
- }
- #
- # END user configuration
- ```
+# PostgreSQL configuration
+postgresql['listen_address'] = '0.0.0.0'
- > `postgres_role` was introduced with GitLab 10.3
+# Disable automatic database migrations
+gitlab_rails['auto_migrate'] = false
-1. On secondary nodes, add all the configuration specified above for primary node
- to `/etc/gitlab/gitlab.rb`. In addition, append the following configuration
- to inform `gitlab-ctl` that they are standby nodes initially and it need not
- attempt to register them as primary node
+# Configure the Consul agent
+consul['services'] = %w(postgresql)
- ```ruby
- # Specify if a node should attempt to be master on initialization
- repmgr['master_on_initialization'] = false
- ```
+# START user configuration
+# Please set the real values as explained in Required Information section
+#
+# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
+postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. [Enable Monitoring](#enable-monitoring)
+# Replace X with value of number of db nodes + 1 (OPTIONAL the default value is 5)
+patroni['postgresql']['max_wal_senders'] = X
+patroni['postgresql']['max_replication_slots'] = X
-> Please note:
->
-> - If you want your database to listen on a specific interface, change the configuration:
-> `postgresql['listen_address'] = '0.0.0.0'`.
-> - If your PgBouncer service runs under a different user account,
-> you also need to specify: `postgresql['pgbouncer_user'] = PGBOUNCER_USERNAME` in
-> your configuration.
+# Replace XXX.XXX.XXX.XXX/YY with Network Address
+postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
+
+# Replace placeholders:
+#
+# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+# with the addresses gathered for CONSUL_SERVER_NODES
+consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
+}
+#
+# END user configuration
+```
+
+You do not need an additional or different configuration for replica nodes. As a matter of fact, you don't have to have
+a predetermined primary node. Therefore all database nodes use the same configuration.
+
+Once the configuration of a node is done, you must [reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
+on each node for the changes to take effect.
+
+Generally, when Consul cluster is ready, the first node that [reconfigures](../restart_gitlab.md#omnibus-gitlab-reconfigure)
+becomes the leader. You do not need to sequence the nodes reconfiguration. You can run them in parallel or in any order.
+If you choose an arbitrary order you do not have any predetermined master.
+
+NOTE:
+As opposed to repmgr, once the nodes are reconfigured you do not need any further action or additional command to join
+the replicas.
#### Enable Monitoring
@@ -298,129 +291,6 @@ If you enable Monitoring, it must be enabled on **all** database servers.
1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
-#### Database nodes post-configuration
-
-##### Primary node
-
-Select one node as a primary node.
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Enable the `pg_trgm` extension:
-
- ```shell
- CREATE EXTENSION pg_trgm;
- ```
-
-1. Enable the `btree_gist` extension:
-
- ```shell
- CREATE EXTENSION btree_gist;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
-
-1. Verify the cluster is initialized with one node:
-
- ```shell
- gitlab-ctl repmgr cluster show
- ```
-
- The output should be similar to the following:
-
- ```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `MASTER_NODE_NAME`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-##### Secondary nodes
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup MASTER_NODE_NAME
- ```
-
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- # gitlab-ctl repmgr standby setup MASTER_NODE_NAME
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
- ```
-
-1. Verify the node now appears in the cluster:
-
- ```shell
- gitlab-ctl repmgr cluster show
- ```
-
- The output should be similar to the following:
-
- ```plaintext
- Role | Name | Upstream | Connection String
- ----------+---------|-----------|------------------------------------------------
- * master | MASTER | | host=MASTER_NODE_NAME user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=STANDBY_HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-Repeat the above steps on all secondary nodes.
-
-#### Database checkpoint
-
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+--------------|--------------|--------------------------------------------------------------------
-* master | MASTER | | host=MASTER port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=STANDBY port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
-[Troubleshooting section](#troubleshooting) before proceeding.
-
-Also, check that the check master command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](#troubleshooting) before proceeding.
-
### Configuring the PgBouncer node
1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`CONSUL_PASSWORD_HASH`](#consul-information), and [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information) before executing the next step.
@@ -577,6 +447,12 @@ PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes.
[PgBouncer error `ERROR: pgbouncer cannot connect to server`](#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
in the Troubleshooting section before proceeding.
+### Backups
+
+Do not backup or restore GitLab through a PgBouncer connection: this will cause a GitLab outage.
+
+[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer).
+
### Ensure GitLab is running
At this point, your GitLab instance should be up and running. Verify you're able
@@ -605,9 +481,9 @@ Here is a list and description of each machine and the assigned IP:
- `10.6.0.21`: PgBouncer 1
- `10.6.0.22`: PgBouncer 2
- `10.6.0.23`: PgBouncer 3
-- `10.6.0.31`: PostgreSQL master
-- `10.6.0.32`: PostgreSQL secondary
-- `10.6.0.33`: PostgreSQL secondary
+- `10.6.0.31`: PostgreSQL 1
+- `10.6.0.32`: PostgreSQL 2
+- `10.6.0.33`: PostgreSQL 3
- `10.6.0.41`: GitLab application
All passwords are set to `toomanysecrets`, please do not use this password or derived hashes and the `external_url` for GitLab is `http://gitlab.example.com`.
@@ -667,29 +543,28 @@ An internal load balancer (TCP) is then required to be setup to serve each PgBou
#### Example recommended setup for PostgreSQL servers
-##### Primary node
-
-On primary node edit `/etc/gitlab/gitlab.rb`:
+On database nodes edit `/etc/gitlab/gitlab.rb`:
```ruby
-# Disable all components except PostgreSQL and Repmgr and Consul
+# Disable all components except PostgreSQL, Patroni (or Repmgr), and Consul
roles ['postgres_role']
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
postgresql['hot_standby'] = 'on'
postgresql['wal_level'] = 'replica'
-postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+# Enable Patroni (which automatically disables Repmgr).
+patroni['enable'] = true
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
-postgresql['max_wal_senders'] = 4
+patroni['postgresql']['max_wal_senders'] = 4
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
-repmgr['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
# Configure the Consul agent
consul['services'] = %w(postgresql)
@@ -702,85 +577,27 @@ consul['monitoring_service_discovery'] = true
[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-##### Secondary nodes
-
-On secondary nodes, edit `/etc/gitlab/gitlab.rb` and add all the configuration
-added to primary node, noted above. In addition, append the following
-configuration:
-
-```ruby
-# Specify if a node should attempt to be master on initialization
-repmgr['master_on_initialization'] = false
-```
-
-[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-###### Example recommended setup for application server
-
-On the server edit `/etc/gitlab/gitlab.rb`:
-
-```ruby
-external_url 'http://gitlab.example.com'
-
-gitlab_rails['db_host'] = '10.6.0.20' # Internal Load Balancer for PgBouncer nodes
-gitlab_rails['db_port'] = 6432
-gitlab_rails['db_password'] = 'toomanysecrets'
-gitlab_rails['auto_migrate'] = false
-
-postgresql['enable'] = false
-pgbouncer['enable'] = false
-consul['enable'] = true
-
-# Configure Consul agent
-consul['watchers'] = %w(postgresql)
-
-pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '5e0e3263571e3704ad655076301d6ebe'
- },
- 'pgbouncer': {
- password: '771a8625958a529132abe6f1a4acb19c'
- }
-}
-
-consul['configuration'] = {
- retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
-}
-```
-
-[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
#### Example recommended setup manual steps
After deploying the configuration follow these steps:
-1. On `10.6.0.31`, our primary database:
-
- Enable the `pg_trgm` and `btree_gist` extensions:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
+1. Find the primary database node:
```shell
- CREATE EXTENSION pg_trgm;
- CREATE EXTENSION btree_gist;
+ gitlab-ctl get-postgresql-primary
```
-1. On `10.6.0.32`, our first standby database:
+1. On the primary database node:
- Make this node a standby of the primary:
+ Enable the `pg_trgm` and `btree_gist` extensions:
```shell
- gitlab-ctl repmgr standby setup 10.6.0.21
+ gitlab-psql -d gitlabhq_production
```
-1. On `10.6.0.33`, our second standby database:
-
- Make this node a standby of the primary:
-
```shell
- gitlab-ctl repmgr standby setup 10.6.0.21
+ CREATE EXTENSION pg_trgm;
+ CREATE EXTENSION btree_gist;
```
1. On `10.6.0.41`, our application server:
@@ -802,15 +619,15 @@ After deploying the configuration follow these steps:
This example uses 3 PostgreSQL servers, and 1 application node (with PgBouncer setup alongside).
It differs from the [recommended setup](#example-recommended-setup) by moving the Consul servers into the same servers we use for PostgreSQL.
-The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#failover-procedure) and [restore](#restore-procedure) procedures in addition to [Consul outage recovery](../consul.md#outage-recovery) on the same set of machines.
+The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#manual-failover-procedure-for-patroni) procedures in addition to [Consul outage recovery](../consul.md#outage-recovery) on the same set of machines.
In this example we start with all servers on the same 10.6.0.0/16 private network range, they can connect to each freely other on those addresses.
Here is a list and description of each machine and the assigned IP:
-- `10.6.0.21`: PostgreSQL master
-- `10.6.0.22`: PostgreSQL secondary
-- `10.6.0.23`: PostgreSQL secondary
+- `10.6.0.21`: PostgreSQL 1
+- `10.6.0.22`: PostgreSQL 2
+- `10.6.0.23`: PostgreSQL 3
- `10.6.0.31`: GitLab application
All passwords are set to `toomanysecrets`, please do not use this password or derived hashes.
@@ -821,9 +638,7 @@ Please note that after the initial configuration, if a failover occurs, the Post
#### Example minimal configuration for database servers
-##### Primary node
-
-On primary database node edit `/etc/gitlab/gitlab.rb`:
+On database nodes edit `/etc/gitlab/gitlab.rb`:
```ruby
# Disable all components except PostgreSQL, Repmgr, and Consul
@@ -833,7 +648,9 @@ roles ['postgres_role']
postgresql['listen_address'] = '0.0.0.0'
postgresql['hot_standby'] = 'on'
postgresql['wal_level'] = 'replica'
-postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+# Enable Patroni (which automatically disables Repmgr).
+patroni['enable'] = true
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
@@ -843,10 +660,9 @@ consul['services'] = %w(postgresql)
postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
-postgresql['max_wal_senders'] = 4
+patroni['postgresql']['max_wal_senders'] = 4
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
-repmgr['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
consul['configuration'] = {
server: true,
@@ -856,16 +672,6 @@ consul['configuration'] = {
[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-##### Secondary nodes
-
-On secondary nodes, edit `/etc/gitlab/gitlab.rb` and add all the information added
-to primary node, noted above. In addition, append the following configuration
-
-```ruby
-# Specify if a node should attempt to be master on initialization
-repmgr['master_on_initialization'] = false
-```
-
#### Example minimal configuration for application server
On the server edit `/etc/gitlab/gitlab.rb`:
@@ -908,249 +714,10 @@ consul['configuration'] = {
The manual steps for this configuration are the same as for the [example recommended setup](#example-recommended-setup-manual-steps).
-### Failover procedure
-
-By default, if the master database fails, `repmgrd` should promote one of the
-standby nodes to master automatically, and Consul will update PgBouncer with
-the new master.
-
-If you need to failover manually, you have two options:
-
-**Shutdown the current master database**
-
-Run:
-
-```shell
-gitlab-ctl stop postgresql
-```
-
-The automated failover process will see this and failover to one of the
-standby nodes.
-
-**Or perform a manual failover**
-
-1. Ensure the old master node is not still active.
-1. Login to the server that should become the new master and run:
-
- ```shell
- gitlab-ctl repmgr standby promote
- ```
-
-1. If there are any other standby servers in the cluster, have them follow
- the new master server:
-
- ```shell
- gitlab-ctl repmgr standby follow NEW_MASTER
- ```
-
-### Restore procedure
-
-If a node fails, it can be removed from the cluster, or added back as a standby
-after it has been restored to service.
-
-#### Remove a standby from the cluster
-
- From any other node in the cluster, run:
-
- ```shell
- gitlab-ctl repmgr standby unregister --node=X
- ```
-
- where X is the value of node in `repmgr.conf` on the old server.
-
- To find this, you can use:
-
- ```shell
- awk -F = '$1 == "node" { print $2 }' /var/opt/gitlab/postgresql/repmgr.conf
- ```
-
- It will output something like:
-
- ```plaintext
- 959789412
- ```
-
- Then you will use this ID to unregister the node:
-
- ```shell
- gitlab-ctl repmgr standby unregister --node=959789412
- ```
-
-#### Add a node as a standby server
-
- From the standby node, run:
-
- ```shell
- gitlab-ctl repmgr standby follow NEW_MASTER
- gitlab-ctl restart repmgrd
- ```
-
- WARNING:
- When the server is brought back online, and before
- you switch it to a standby node, repmgr will report that there are two masters.
- If there are any clients that are still attempting to write to the old master,
- this will cause a split, and the old master will need to be resynced from
- scratch by performing a `gitlab-ctl repmgr standby setup NEW_MASTER`.
-
-#### Add a failed master back into the cluster as a standby node
-
- Once `repmgrd` and PostgreSQL are running, the node will need to follow the new
- as a standby node.
-
- ```shell
- gitlab-ctl repmgr standby follow NEW_MASTER
- ```
-
- Once the node is following the new master as a standby, the node needs to be
- [unregistered from the cluster on the new master node](#remove-a-standby-from-the-cluster).
-
- Once the old master node has been unregistered from the cluster, it will need
- to be setup as a new standby:
-
- ```shell
- gitlab-ctl repmgr standby setup NEW_MASTER
- ```
-
- Failure to unregister and read the old master node can lead to subsequent failovers
- not working.
-
-### Alternate configurations
-
-#### Database authorization
-
-By default, we give any host on the database network the permission to perform
-repmgr operations using PostgreSQL's `trust` method. If you do not want this
-level of trust, there are alternatives.
-
-You can trust only the specific nodes that will be database clusters, or you
-can require md5 authentication.
-
-#### Trust specific addresses
-
-If you know the IP address, or FQDN of all database and PgBouncer nodes in the
-cluster, you can trust only those nodes.
-
-In `/etc/gitlab/gitlab.rb` on all of the database nodes, set
-`repmgr['trust_auth_cidr_addresses']` to an array of strings containing all of
-the addresses.
-
-If setting to a node's FQDN, they must have a corresponding PTR record in DNS.
-If setting to a node's IP address, specify it as `XXX.XXX.XXX.XXX/32`.
-
-For example:
-
-```ruby
-repmgr['trust_auth_cidr_addresses'] = %w(192.168.1.44/32 db2.example.com)
-```
-
-#### MD5 Authentication
-
-If you are running on an untrusted network, repmgr can use md5 authentication
-with a [`.pgpass` file](https://www.postgresql.org/docs/11/libpq-pgpass.html)
-to authenticate.
-
-You can specify by IP address, FQDN, or by subnet, using the same format as in
-the previous section:
-
-1. On the current master node, create a password for the `gitlab` and
- `gitlab_repmgr` user:
-
- ```shell
- gitlab-psql -d template1
- template1=# \password gitlab_repmgr
- Enter password: ****
- Confirm password: ****
- template1=# \password gitlab
- ```
-
-1. On each database node:
-
- 1. Edit `/etc/gitlab/gitlab.rb`:
- 1. Ensure `repmgr['trust_auth_cidr_addresses']` is **not** set
- 1. Set `postgresql['md5_auth_cidr_addresses']` to the desired value
- 1. Set `postgresql['sql_replication_user'] = 'gitlab_repmgr'`
- 1. Reconfigure with `gitlab-ctl reconfigure`
- 1. Restart PostgreSQL with `gitlab-ctl restart postgresql`
-
- 1. Create a `.pgpass` file. Enter the `gitlab_repmgr` password twice to
- when asked:
-
- ```shell
- gitlab-ctl write-pgpass --user gitlab_repmgr --hostuser gitlab-psql --database '*'
- ```
-
-1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`:
- 1. Ensure `gitlab_rails['db_password']` is set to the plaintext password for
- the `gitlab` database user
- 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect
-
-## Troubleshooting
-
-### Consul and PostgreSQL changes not taking effect
-
-Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading.
-
-To restart either service, run `gitlab-ctl restart SERVICE`
-
-For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`.
-
-On the Consul server nodes, it is important to [restart the Consul service](../consul.md#restart-consul) in a controlled manner.
-
-### `gitlab-ctl repmgr-check-master` command produces errors
-
-If this command displays errors about database permissions it is likely that something failed during
-install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these
-steps to fix the problem:
-
-1. On the master database node, connect to the database prompt - `gitlab-psql -d template1`
-1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";`
-1. Exit the database prompt - `\q`
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions.
-1. Change to the `gitlab-consul` user - `su - gitlab-consul`
-1. Try the check command again - `gitlab-ctl repmgr-check-master`.
-
-Now there should not be errors. If errors still occur then there is another problem.
-
-### PgBouncer error `ERROR: pgbouncer cannot connect to server`
-
-You may get this error when running `gitlab-rake gitlab:db:configure` or you
-may see the error in the PgBouncer log file.
-
-```plaintext
-PG::ConnectionBad: ERROR: pgbouncer cannot connect to server
-```
-
-The problem may be that your PgBouncer node's IP address is not included in the
-`trust_auth_cidr_addresses` setting in `/etc/gitlab/gitlab.rb` on the database nodes.
-
-You can confirm that this is the issue by checking the PostgreSQL log on the master
-database node. If you see the following error then `trust_auth_cidr_addresses`
-is the problem.
-
-```plaintext
-2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off
-```
-
-To fix the problem, add the IP address to `/etc/gitlab/gitlab.rb`.
-
-```ruby
-postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
-```
-
-[Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-### Issues with other components
-
-If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page:
-
-- [Consul](../consul.md#troubleshooting-consul)
-- [PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting)
-
## Patroni
NOTE:
-Starting from GitLab 13.1, Patroni is available for **experimental** use to replace repmgr. Due to its
-experimental nature, Patroni support is **subject to change without notice.**
+Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12.
Patroni is an opinionated solution for PostgreSQL high-availability. It takes the control of PostgreSQL, overrides its
configuration and manages its lifecycle (start, stop, restart). This is a more active approach when compared to repmgr.
@@ -1174,80 +741,44 @@ functional or does not have a leader, Patroni and by extension PostgreSQL will n
API which can be accessed via its [default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#patroni)
on each node.
-### Configuring Patroni cluster
-
-You must enable Patroni explicitly to be able to use it (with `patroni['enable'] = true`). When Patroni is enabled
-repmgr will be disabled automatically.
+### Selecting the appropriate Patroni replication method
-Any PostgreSQL configuration item that controls replication, for example `wal_level`, `max_wal_senders`, etc, are strictly
-controlled by Patroni and will override the original settings that you make with the `postgresql[...]` configuration key.
-Hence, they are all separated and placed under `patroni['postgresql'][...]`. This behavior is limited to replication.
-Patroni honours any other PostgreSQL configuration that was made with the `postgresql[...]` configuration key. For example,
-`max_wal_senders` by default is set to `5`. If you wish to change this you must set it with the `patroni['postgresql']['max_wal_senders']`
-configuration key.
+[Review the Patroni documentation carefully](https://patroni.readthedocs.io/en/latest/SETTINGS.html#postgresql)
+before making changes as **_some of the options carry a risk of potential data
+loss if not fully understood_**. The [replication mode](https://patroni.readthedocs.io/en/latest/replication_modes.html)
+configured determines the amount of tolerable data loss.
-The configuration of Patroni node is very similar to a repmgr but shorter. When Patroni is enabled, first you can ignore
-any replication setting of PostgreSQL (it will be overwritten anyway). Then you can remove any `repmgr[...]` or
-repmgr-specific configuration as well. Especially, make sure that you remove `postgresql['shared_preload_libraries'] = 'repmgr_funcs'`.
+WARNING:
+Replication is not a backup strategy! There is no replacement for a well-considered and tested backup solution.
-Here is an example similar to [the one that was done with repmgr](#configuring-the-database-nodes):
+Omnibus GitLab defaults [`synchronous_commit`](https://www.postgresql.org/docs/11/runtime-config-wal.html#GUC-SYNCHRONOUS-COMMIT) to `on`.
```ruby
-# Disable all components except PostgreSQL and Repmgr and Consul
-roles['postgres_role']
+postgresql['synchronous_commit'] = 'on'
+gitlab['geo-postgresql']['synchronous_commit'] = 'on'
+```
-# Enable Patroni
-patroni['enable'] = true
+#### Customizing Patroni failover behavior
-# PostgreSQL configuration
-postgresql['listen_address'] = '0.0.0.0'
+Omnibus GitLab exposes several options allowing more control over the [Patroni restoration process](#recovering-the-patroni-cluster).
-# Disable automatic database migrations
-gitlab_rails['auto_migrate'] = false
+Each option is shown below with its default value in `/etc/gitlab/gitlab.rb`.
-# Configure the Consul agent
-consul['services'] = %w(postgresql)
-
-# START user configuration
-# Please set the real values as explained in Required Information section
-#
-# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
-postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
-# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
-postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
-
-# Replace X with value of number of db nodes + 1 (OPTIONAL the default value is 5)
-patroni['postgresql']['max_wal_senders'] = X
-patroni['postgresql']['max_replication_slots'] = X
-
-# Replace XXX.XXX.XXX.XXX/YY with Network Address
-postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
-
-# Replace placeholders:
-#
-# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
-# with the addresses gathered for CONSUL_SERVER_NODES
-consul['configuration'] = {
- retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
-}
-#
-# END user configuration
+```ruby
+patroni['use_pg_rewind'] = true
+patroni['remove_data_directory_on_rewind_failure'] = false
+patroni['remove_data_directory_on_diverged_timelines'] = false
```
-You do not need an additional or different configuration for replica nodes. As a matter of fact, you don't have to have
-a predetermined primary node. Therefore all database nodes use the same configuration.
+[The upstream documentation will always be more up to date](https://patroni.readthedocs.io/en/latest/SETTINGS.html#postgresql), but the table below should provide a minimal overview of functionality.
-Once the configuration of a node is done, you must [reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
-on each node for the changes to take effect.
+|Setting|Overview|
+|-|-|
+|`use_pg_rewind`|Try running `pg_rewind` on the former cluster leader before it rejoins the database cluster.|
+|`remove_data_directory_on_rewind_failure`|If `pg_rewind` fails, remove the local PostgreSQL data directory and re-replicate from the current cluster leader.|
+|`remove_data_directory_on_diverged_timelines`|If `pg_rewind` cannot be used and the former leader's timeline has diverged from the current one, then delete the local data directory and re-replicate from the current cluster leader.|
-Generally, when Consul cluster is ready, the first node that [reconfigures](../restart_gitlab.md#omnibus-gitlab-reconfigure)
-becomes the leader. You do not need to sequence the nodes reconfiguration. You can run them in parallel or in any order.
-If you choose an arbitrary order you do not have any predetermined master.
-
-As opposed to repmgr, once the nodes are reconfigured you do not need any further action or additional command to join
-the replicas.
-
-#### Database authorization for Patroni
+### Database authorization for Patroni
Patroni uses Unix socket to manage PostgreSQL instance. Therefore, the connection from the `local` socket must be trusted.
@@ -1297,6 +828,16 @@ a manual one, where you have two slightly different options:
For further details on this subject, see the
[Patroni documentation](https://patroni.readthedocs.io/en/latest/rest_api.html#switchover-and-failover-endpoints).
+#### Geo secondary site considerations
+
+Similar to `repmgr`, when a Geo secondary site is replicating from a primary site that uses `Patroni` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `Patroni` cluster. Therefore, when there is an automatic or manual failover in the `Patroni` cluster, you will need to manually re-point your secondary site to replicate from the new leader with:
+
+```shell
+sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name>
+```
+
+Otherwise, the replication will not happen anymore, even if the original node gets re-added as a follower node. This will re-sync your secondary site database and may take a long time depending on the amount of data to sync. You may also need to run `gitlab-ctl reconfigure` if replication is still not working after re-syncing.
+
### Recovering the Patroni cluster
To recover the old primary and rejoin it to the cluster as a replica, you can simply start Patroni with:
@@ -1363,9 +904,9 @@ You can switch an exiting database cluster to use Patroni instead of repmgr with
### Upgrading PostgreSQL major version in a Patroni cluster
-As of GitLab 13.3, PostgreSQL 11.7 and 12.3 are both shipped with Omnibus GitLab. GitLab still
-uses PostgreSQL 11 by default. Therefore `gitlab-ctl pg-upgrade` does not automatically upgrade
-to PostgreSQL 12. If you want to upgrade to PostgreSQL 12, you must ask for it explicitly.
+As of GitLab 13.3, PostgreSQL 11.7 and 12.3 are both shipped with Omnibus GitLab, and as of GitLab 13.7
+PostgreSQL 12 is used by default. If you want to upgrade to PostgreSQL 12 in versions prior to GitLab 13.7,
+you must ask for it explicitly.
WARNING:
The procedure for upgrading PostgreSQL in a Patroni cluster is different than when upgrading using repmgr.
@@ -1450,3 +991,448 @@ NOTE:
Reverting PostgreSQL upgrade with `gitlab-ctl revert-pg-upgrade` has the same considerations as
`gitlab-ctl pg-upgrade`. You should follow the same procedure by first stopping the replicas,
then reverting the leader, and finally reverting the replicas.
+
+## Repmgr
+
+NOTE:
+Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12.
+
+### Configuring Repmgr Nodes
+
+1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+
+ ```ruby
+ # Disable all components except PostgreSQL and Repmgr and Consul
+ roles ['postgres_role']
+
+ # PostgreSQL configuration
+ postgresql['listen_address'] = '0.0.0.0'
+ postgresql['hot_standby'] = 'on'
+ postgresql['wal_level'] = 'replica'
+ postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+ # Disable automatic database migrations
+ gitlab_rails['auto_migrate'] = false
+
+ # Configure the Consul agent
+ consul['services'] = %w(postgresql)
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ #
+ # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
+ postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+ # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+ # Replace X with value of number of db nodes + 1
+ postgresql['max_wal_senders'] = X
+ postgresql['max_replication_slots'] = X
+
+ # Replace XXX.XXX.XXX.XXX/YY with Network Address
+ postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
+ repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 XXX.XXX.XXX.XXX/YY)
+
+ # Replace placeholders:
+ #
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses gathered for CONSUL_SERVER_NODES
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
+ }
+ #
+ # END user configuration
+ ```
+
+ > `postgres_role` was introduced with GitLab 10.3
+
+1. On secondary nodes, add all the configuration specified above for primary node
+ to `/etc/gitlab/gitlab.rb`. In addition, append the following configuration
+ to inform `gitlab-ctl` that they are standby nodes initially and it need not
+ attempt to register them as primary node
+
+ ```ruby
+ # Specify if a node should attempt to be master on initialization
+ repmgr['master_on_initialization'] = false
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. [Enable Monitoring](#enable-monitoring)
+
+> Please note:
+>
+> - If you want your database to listen on a specific interface, change the configuration:
+> `postgresql['listen_address'] = '0.0.0.0'`.
+> - If your PgBouncer service runs under a different user account,
+> you also need to specify: `postgresql['pgbouncer_user'] = PGBOUNCER_USERNAME` in
+> your configuration.
+
+#### Database nodes post-configuration
+
+##### Primary node
+
+Select one node as a primary node.
+
+1. Open a database prompt:
+
+ ```shell
+ gitlab-psql -d gitlabhq_production
+ ```
+
+1. Enable the `pg_trgm` extension:
+
+ ```shell
+ CREATE EXTENSION pg_trgm;
+ ```
+
+1. Enable the `btree_gist` extension:
+
+ ```shell
+ CREATE EXTENSION btree_gist;
+ ```
+
+1. Exit the database prompt by typing `\q` and Enter.
+
+1. Verify the cluster is initialized with one node:
+
+ ```shell
+ gitlab-ctl repmgr cluster show
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ Role | Name | Upstream | Connection String
+ ----------+----------|----------|----------------------------------------
+ * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
+ ```
+
+1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
+ refer to the hostname in the next section as `MASTER_NODE_NAME`. If the value
+ is not an IP address, it will need to be a resolvable name (via DNS or
+ `/etc/hosts`)
+
+##### Secondary nodes
+
+1. Set up the repmgr standby:
+
+ ```shell
+ gitlab-ctl repmgr standby setup MASTER_NODE_NAME
+ ```
+
+ Do note that this will remove the existing data on the node. The command
+ has a wait time.
+
+ The output should be similar to the following:
+
+ ```console
+ # gitlab-ctl repmgr standby setup MASTER_NODE_NAME
+ Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
+ If this is not what you want, hit Ctrl-C now to exit
+ To skip waiting, rerun with the -w option
+ Sleeping for 30 seconds
+ Stopping the database
+ Removing the data
+ Cloning the data
+ Starting the database
+ Registering the node with the cluster
+ ok: run: repmgrd: (pid 19068) 0s
+ ```
+
+1. Verify the node now appears in the cluster:
+
+ ```shell
+ gitlab-ctl repmgr cluster show
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ Role | Name | Upstream | Connection String
+ ----------+---------|-----------|------------------------------------------------
+ * master | MASTER | | host=MASTER_NODE_NAME user=gitlab_repmgr dbname=gitlab_repmgr
+ standby | STANDBY | MASTER | host=STANDBY_HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
+ ```
+
+Repeat the above steps on all secondary nodes.
+
+#### Database checkpoint
+
+Before moving on, make sure the databases are configured correctly. Run the
+following command on the **primary** node to verify that replication is working
+properly:
+
+```shell
+gitlab-ctl repmgr cluster show
+```
+
+The output should be similar to:
+
+```plaintext
+Role | Name | Upstream | Connection String
+----------+--------------|--------------|--------------------------------------------------------------------
+* master | MASTER | | host=MASTER port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
+ standby | STANDBY | MASTER | host=STANDBY port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
+```
+
+If the 'Role' column for any node says "FAILED", check the
+[Troubleshooting section](#troubleshooting) before proceeding.
+
+Also, check that the check master command works successfully on each node:
+
+```shell
+su - gitlab-consul
+gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
+```
+
+This command relies on exit codes to tell Consul whether a particular node is a master
+or secondary. The most important thing here is that this command does not produce errors.
+If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
+Check the [Troubleshooting section](#troubleshooting) before proceeding.
+
+### Repmgr failover procedure
+
+By default, if the master database fails, `repmgrd` should promote one of the
+standby nodes to master automatically, and Consul will update PgBouncer with
+the new master.
+
+If you need to failover manually, you have two options:
+
+**Shutdown the current master database**
+
+Run:
+
+```shell
+gitlab-ctl stop postgresql
+```
+
+The automated failover process will see this and failover to one of the
+standby nodes.
+
+**Or perform a manual failover**
+
+1. Ensure the old master node is not still active.
+1. Login to the server that should become the new master and run:
+
+ ```shell
+ gitlab-ctl repmgr standby promote
+ ```
+
+1. If there are any other standby servers in the cluster, have them follow
+ the new master server:
+
+ ```shell
+ gitlab-ctl repmgr standby follow NEW_MASTER
+ ```
+
+#### Geo secondary site considerations
+
+When a Geo secondary site is replicating from a primary site that uses `repmgr` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `repmgr` cluster. Therefore, when there is a failover in the `repmgr` cluster, you will need to manually re-point your secondary site to replicate from the new leader with:
+
+```shell
+sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name>
+```
+
+Otherwise, the replication will not happen anymore, even if the original node gets re-added as a follower node. This will re-sync your secondary site database and may take a long time depending on the amount of data to sync. You may also need to run `gitlab-ctl reconfigure` if replication is still not working after re-syncing.
+
+### Repmgr Restore procedure
+
+If a node fails, it can be removed from the cluster, or added back as a standby
+after it has been restored to service.
+
+#### Remove a standby from the cluster
+
+ From any other node in the cluster, run:
+
+ ```shell
+ gitlab-ctl repmgr standby unregister --node=X
+ ```
+
+ where X is the value of node in `repmgr.conf` on the old server.
+
+ To find this, you can use:
+
+ ```shell
+ awk -F = '$1 == "node" { print $2 }' /var/opt/gitlab/postgresql/repmgr.conf
+ ```
+
+ It will output something like:
+
+ ```plaintext
+ 959789412
+ ```
+
+ Then you will use this ID to unregister the node:
+
+ ```shell
+ gitlab-ctl repmgr standby unregister --node=959789412
+ ```
+
+#### Add a node as a standby server
+
+ From the standby node, run:
+
+ ```shell
+ gitlab-ctl repmgr standby follow NEW_MASTER
+ gitlab-ctl restart repmgrd
+ ```
+
+ WARNING:
+ When the server is brought back online, and before
+ you switch it to a standby node, repmgr will report that there are two masters.
+ If there are any clients that are still attempting to write to the old master,
+ this will cause a split, and the old master will need to be resynced from
+ scratch by performing a `gitlab-ctl repmgr standby setup NEW_MASTER`.
+
+#### Add a failed master back into the cluster as a standby node
+
+ Once `repmgrd` and PostgreSQL are running, the node will need to follow the new
+ as a standby node.
+
+ ```shell
+ gitlab-ctl repmgr standby follow NEW_MASTER
+ ```
+
+ Once the node is following the new master as a standby, the node needs to be
+ [unregistered from the cluster on the new master node](#remove-a-standby-from-the-cluster).
+
+ Once the old master node has been unregistered from the cluster, it will need
+ to be setup as a new standby:
+
+ ```shell
+ gitlab-ctl repmgr standby setup NEW_MASTER
+ ```
+
+ Failure to unregister and read the old master node can lead to subsequent failovers
+ not working.
+
+### Alternate configurations
+
+#### Database authorization
+
+By default, we give any host on the database network the permission to perform
+repmgr operations using PostgreSQL's `trust` method. If you do not want this
+level of trust, there are alternatives.
+
+You can trust only the specific nodes that will be database clusters, or you
+can require md5 authentication.
+
+#### Trust specific addresses
+
+If you know the IP address, or FQDN of all database and PgBouncer nodes in the
+cluster, you can trust only those nodes.
+
+In `/etc/gitlab/gitlab.rb` on all of the database nodes, set
+`repmgr['trust_auth_cidr_addresses']` to an array of strings containing all of
+the addresses.
+
+If setting to a node's FQDN, they must have a corresponding PTR record in DNS.
+If setting to a node's IP address, specify it as `XXX.XXX.XXX.XXX/32`.
+
+For example:
+
+```ruby
+repmgr['trust_auth_cidr_addresses'] = %w(192.168.1.44/32 db2.example.com)
+```
+
+#### MD5 Authentication
+
+If you are running on an untrusted network, repmgr can use md5 authentication
+with a [`.pgpass` file](https://www.postgresql.org/docs/11/libpq-pgpass.html)
+to authenticate.
+
+You can specify by IP address, FQDN, or by subnet, using the same format as in
+the previous section:
+
+1. On the current master node, create a password for the `gitlab` and
+ `gitlab_repmgr` user:
+
+ ```shell
+ gitlab-psql -d template1
+ template1=# \password gitlab_repmgr
+ Enter password: ****
+ Confirm password: ****
+ template1=# \password gitlab
+ ```
+
+1. On each database node:
+
+ 1. Edit `/etc/gitlab/gitlab.rb`:
+ 1. Ensure `repmgr['trust_auth_cidr_addresses']` is **not** set
+ 1. Set `postgresql['md5_auth_cidr_addresses']` to the desired value
+ 1. Set `postgresql['sql_replication_user'] = 'gitlab_repmgr'`
+ 1. Reconfigure with `gitlab-ctl reconfigure`
+ 1. Restart PostgreSQL with `gitlab-ctl restart postgresql`
+
+ 1. Create a `.pgpass` file. Enter the `gitlab_repmgr` password twice to
+ when asked:
+
+ ```shell
+ gitlab-ctl write-pgpass --user gitlab_repmgr --hostuser gitlab-psql --database '*'
+ ```
+
+1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`:
+ 1. Ensure `gitlab_rails['db_password']` is set to the plaintext password for
+ the `gitlab` database user
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect
+
+## Troubleshooting
+
+### Consul and PostgreSQL changes not taking effect
+
+Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading.
+
+To restart either service, run `gitlab-ctl restart SERVICE`
+
+For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`.
+
+On the Consul server nodes, it is important to [restart the Consul service](../consul.md#restart-consul) in a controlled manner.
+
+### `gitlab-ctl repmgr-check-master` command produces errors
+
+If this command displays errors about database permissions it is likely that something failed during
+install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these
+steps to fix the problem:
+
+1. On the master database node, connect to the database prompt - `gitlab-psql -d template1`
+1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";`
+1. Exit the database prompt - `\q`
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions.
+1. Change to the `gitlab-consul` user - `su - gitlab-consul`
+1. Try the check command again - `gitlab-ctl repmgr-check-master`.
+
+Now there should not be errors. If errors still occur then there is another problem.
+
+### PgBouncer error `ERROR: pgbouncer cannot connect to server`
+
+You may get this error when running `gitlab-rake gitlab:db:configure` or you
+may see the error in the PgBouncer log file.
+
+```plaintext
+PG::ConnectionBad: ERROR: pgbouncer cannot connect to server
+```
+
+The problem may be that your PgBouncer node's IP address is not included in the
+`trust_auth_cidr_addresses` setting in `/etc/gitlab/gitlab.rb` on the database nodes.
+
+You can confirm that this is the issue by checking the PostgreSQL log on the master
+database node. If you see the following error then `trust_auth_cidr_addresses`
+is the problem.
+
+```plaintext
+2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off
+```
+
+To fix the problem, add the IP address to `/etc/gitlab/gitlab.rb`.
+
+```ruby
+postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
+```
+
+[Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+### Issues with other components
+
+If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page:
+
+- [Consul](../consul.md#troubleshooting-consul)
+- [PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting)
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index 25869fd425d..41defd89df5 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -51,6 +51,62 @@ sudo gitlab-rake gitlab:git:fsck
sudo -u git -H bundle exec rake gitlab:git:fsck RAILS_ENV=production
```
+## Checksum of repository refs
+
+One Git repository can be compared to another by checksumming all refs of each
+repository. If both repositories have the same refs, and if both repositories
+pass an integrity check, then we can be confident that both repositories are the
+same.
+
+For example, this can be used to compare a backup of a repository against the
+source repository.
+
+### Check all GitLab repositories
+
+This task loops through all repositories on the GitLab server and outputs
+checksums in the format `<PROJECT ID>,<CHECKSUM>`.
+
+- If a repository doesn't exist, the project ID will have a blank checksum.
+- If a repository exists but is empty, the output checksum is `0000000000000000000000000000000000000000`.
+- Projects which don't exist are skipped.
+
+**Omnibus Installation**
+
+```shell
+sudo gitlab-rake gitlab:git:checksum_projects
+```
+
+**Source Installation**
+
+```shell
+sudo -u git -H bundle exec rake gitlab:git:checksum_projects RAILS_ENV=production
+```
+
+For example, if:
+
+- Project with ID#2 doesn't exist, it will be skipped.
+- Project with ID#4 doesn't have a repository, its checksum will be blank.
+- Project with ID#5 has an empty repository, its checksum will be `0000000000000000000000000000000000000000`.
+
+The output would then look something like:
+
+```plaintext
+1,cfa3f06ba235c13df0bb28e079bcea62c5848af2
+3,3f3fb58a8106230e3a6c6b48adc2712fb3b6ef87
+4,
+5,0000000000000000000000000000000000000000
+6,6c6b48adc2712fb3b6ef87cfa3f06ba235c13df0
+```
+
+### Check specific GitLab repositories
+
+Optionally, specific project IDs can be checksummed by setting an environment
+variable `CHECKSUM_PROJECT_IDS` with a list of comma-separated integers, for example:
+
+```shell
+CHECKSUM_PROJECT_IDS="1,3" sudo gitlab-rake gitlab:git:checksum_projects
+```
+
## Uploaded files integrity
Various types of files can be uploaded to a GitLab installation by users.
@@ -158,7 +214,7 @@ If the issue persists, try triggering `gc` via the
```ruby
p = Project.find_by_path("project-name")
-Projects::HousekeepingService.new(p, :gc).execute
+Repositories::HousekeepingService.new(p, :gc).execute
```
### Delete references to missing remote uploads
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index 5c0bc721a9a..630570cb81f 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -19,7 +19,7 @@ before/after the brackets. Also, some shells (for example, `zsh`) can interpret
## Caveats
-If the GitHub [rate limit](https://developer.github.com/v3/#rate-limiting) is reached while importing,
+If the GitHub [rate limit](https://docs.github.com/v3/#rate-limiting) is reached while importing,
the importing process waits (`sleep()`) until it can continue importing.
## Importing multiple projects
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index c7afebf15bd..158b541b36b 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -82,8 +82,8 @@ Support for legacy storage will be removed in GitLab 14.0. If you're on GitLab
The option to choose between hashed and legacy storage in the admin area has
been disabled.
-This task must be run on any machine that has Rails/Sidekiq configured and will
-schedule all your existing projects and attachments associated with it to be
+This task must be run on any machine that has Rails/Sidekiq configured and will
+schedule all your existing projects and attachments associated with it to be
migrated to the **Hashed** storage type:
- **Omnibus installation**
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index 216d3867d0a..afa53b5efa8 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -422,9 +422,9 @@ 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.
-#### PostgreSQL primary node
+#### PostgreSQL nodes
-1. SSH in to the PostgreSQL primary node.
+1. SSH in to one of the PostgreSQL nodes.
1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default
username of `gitlab` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -452,23 +452,33 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 gitlab-consul
```
-1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
+ # Disable all components except PostgreSQL, Patroni, and Consul
roles ['postgres_role']
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+ # Enable Patroni
+ patroni['enable'] = true
+ # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # This is used to prevent replication from using up all of the
+ # available database connections.
+ patroni['postgresql']['max_wal_senders'] = 4
+ patroni['postgresql']['max_replication_slots'] = 4
+ # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ patroni['postgresql']['max_connections'] = 500
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
+ consul['enable'] = true
consul['services'] = %w(postgresql)
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
# START user configuration
# Please set the real values as explained in Required Information section
@@ -477,18 +487,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
# Replace XXX.XXX.XXX.XXX/YY with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['monitoring_service_discovery'] = true
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
@@ -503,70 +504,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
-
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-<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>
-
-#### PostgreSQL secondary nodes
-
-1. On both the secondary nodes, add the same configuration specified above for the primary node
- with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially
- and there's no need to attempt to register them as a primary node:
-
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
-
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
-
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
-
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
-
- # Specify if a node should attempt to be primary on initialization.
- repmgr['master_on_initialization'] = false
-
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
-
- # Replace with your network addresses
- postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['monitoring_service_discovery'] = true
-
- # 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),
- }
- ```
+PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
+Like most failover handling methods, this has a small chance of leading to data loss.
+Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
the file of the same name on this server. If that file is not on this server,
@@ -601,84 +541,25 @@ SSH in to the **primary node**:
1. Exit the database prompt by typing `\q` and Enter.
-1. Verify the cluster is initialized with one node:
+1. Check the status of the leader and cluster:
```shell
- gitlab-ctl repmgr cluster show
+ gitlab-ctl patroni members
```
The output should be similar to the following:
```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `<primary_node_name>`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-SSH in to the **secondary node**:
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup <primary_node_name>
+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart |
+ |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------|
+ | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.21 | Leader | running | 175 | | * |
+ | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.22 | | running | 175 | 0 | * |
+ | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.23 | | running | 175 | 0 | * |
```
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
- ```
-
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly and the secondary nodes appear in the cluster:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to the following:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+---------|-----------|------------------------------------------------
-* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
+If the 'State' column for any node doesn't say "running", check the
[Troubleshooting section](troubleshooting.md) before proceeding.
-Also, check that the `repmgr-check-master` command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](troubleshooting.md) before proceeding.
-
<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>
@@ -696,7 +577,7 @@ The following IPs will be used as an example:
1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace
`<consul_password_hash>` and `<pgbouncer_password_hash>` with the
- password hashes you [set up previously](#postgresql-primary-node):
+ password hashes you [set up previously](#postgresql-nodes):
```ruby
# Disable all components except Pgbouncer and Consul agent
@@ -704,15 +585,16 @@ The following IPs will be used as an example:
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
-
pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '<consul_password_hash>'
- },
- 'pgbouncer': {
- password: '<pgbouncer_password_hash>'
- }
+ 'gitlab-consul': {
+ password: '<consul_password_hash>'
+ },
+ 'pgbouncer': {
+ password: '<pgbouncer_password_hash>'
+ }
}
+ # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ pgbouncer['max_db_connections'] = 150
# Configure Consul agent
consul['watchers'] = %w(postgresql)
@@ -2125,6 +2007,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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.
+
<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>
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index 5b75c7ac9c4..161964353f5 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -16,7 +16,8 @@ requirements, a single-node solution with
many organizations .
> - **Supported users (approximate):** 1,000
-> - **High Availability:** No
+> - **High Availability:** No. For a highly-available environment, you can
+> follow the [3K reference architecture](3k_users.md).
| Users | Configuration | GCP | AWS | Azure |
|--------------|-------------------------|----------------|-----------------|----------------|
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index c5a8c3927c0..d96e93d4ab4 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -422,9 +422,9 @@ 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.
-#### PostgreSQL primary node
+#### PostgreSQL nodes
-1. SSH in to the PostgreSQL primary node.
+1. SSH in to one of the PostgreSQL nodes.
1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default
username of `gitlab` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -452,23 +452,33 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 gitlab-consul
```
-1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
+ # Disable all components except PostgreSQL, Patroni, and Consul
roles ['postgres_role']
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+ # Enable Patroni
+ patroni['enable'] = true
+ # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # This is used to prevent replication from using up all of the
+ # available database connections.
+ patroni['postgresql']['max_wal_senders'] = 4
+ patroni['postgresql']['max_replication_slots'] = 4
+ # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ patroni['postgresql']['max_connections'] = 500
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
+ consul['enable'] = true
consul['services'] = %w(postgresql)
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
# START user configuration
# Please set the real values as explained in Required Information section
@@ -477,18 +487,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
# Replace XXX.XXX.XXX.XXX/YY with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['monitoring_service_discovery'] = true
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
@@ -503,70 +504,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
-
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-<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>
-
-#### PostgreSQL secondary nodes
-
-1. On both the secondary nodes, add the same configuration specified above for the primary node
- with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially
- and there's no need to attempt to register them as a primary node:
-
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
-
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
-
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
-
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
-
- # Specify if a node should attempt to be primary on initialization.
- repmgr['master_on_initialization'] = false
-
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
-
- # Replace with your network addresses
- postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['monitoring_service_discovery'] = true
-
- # 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),
- }
- ```
+PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
+Like most failover handling methods, this has a small chance of leading to data loss.
+Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
the file of the same name on this server. If that file is not on this server,
@@ -601,84 +541,25 @@ SSH in to the **primary node**:
1. Exit the database prompt by typing `\q` and Enter.
-1. Verify the cluster is initialized with one node:
+1. Check the status of the leader and cluster:
```shell
- gitlab-ctl repmgr cluster show
+ gitlab-ctl patroni members
```
The output should be similar to the following:
```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `<primary_node_name>`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-SSH in to the **secondary node**:
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup <primary_node_name>
+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart |
+ |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------|
+ | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.21 | Leader | running | 175 | | * |
+ | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.22 | | running | 175 | 0 | * |
+ | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.23 | | running | 175 | 0 | * |
```
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
- ```
-
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly and the secondary nodes appear in the cluster:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to the following:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+---------|-----------|------------------------------------------------
-* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
+If the 'State' column for any node doesn't say "running", check the
[Troubleshooting section](troubleshooting.md) before proceeding.
-Also, check that the `repmgr-check-master` command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](troubleshooting.md) before proceeding.
-
<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>
@@ -696,7 +577,7 @@ The following IPs will be used as an example:
1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace
`<consul_password_hash>` and `<pgbouncer_password_hash>` with the
- password hashes you [set up previously](#postgresql-primary-node):
+ password hashes you [set up previously](#postgresql-nodes):
```ruby
# Disable all components except Pgbouncer and Consul agent
@@ -704,15 +585,16 @@ The following IPs will be used as an example:
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
-
pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '<consul_password_hash>'
- },
- 'pgbouncer': {
- password: '<pgbouncer_password_hash>'
- }
+ 'gitlab-consul': {
+ password: '<consul_password_hash>'
+ },
+ 'pgbouncer': {
+ password: '<pgbouncer_password_hash>'
+ }
}
+ # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ pgbouncer['max_db_connections'] = 150
# Configure Consul agent
consul['watchers'] = %w(postgresql)
@@ -2125,6 +2007,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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.
+
<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>
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index c341ff5baec..3d38586fa62 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -12,7 +12,8 @@ For a full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
> - **Supported users (approximate):** 2,000
-> - **High Availability:** No
+> - **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
| Service | Nodes | Configuration | GCP | AWS | Azure |
@@ -271,7 +272,7 @@ further configuration steps.
```ruby
# Disable all components except PostgreSQL
roles ['postgres_role']
- repmgr['enable'] = false
+ patroni['enable'] = false
consul['enable'] = false
prometheus['enable'] = false
alertmanager['enable'] = false
@@ -954,7 +955,13 @@ along with [Gitaly](#configure-gitaly), are recommended over using NFS whenever
possible. However, if you intend to use GitLab Pages,
[you must use NFS](troubleshooting.md#gitlab-pages-requires-nfs).
-For information about configuring NFS, see the [NFS documentation page](../nfs.md).
+See how to [configure NFS](../nfs.md).
+
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 370247ed856..648fac8025f 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -7,16 +7,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Reference architecture: up to 3,000 users **(PREMIUM ONLY)**
-This page describes GitLab reference architecture for up to 3,000 users. For a
-full list of reference architectures, see
-[Available reference architectures](index.md#available-reference-architectures).
-
-NOTE:
-This reference architecture is designed to help your organization achieve a
+This page describes GitLab reference architecture for up to 3,000 users.
+It is designed to help your organization achieve a
highly-available GitLab deployment. If you do not have the expertise or need to
maintain a highly-available environment, you can have a simpler and less
costly-to-operate environment by using the
[2,000-user reference architecture](2k_users.md).
+If you have fewer than 3,000 users and still want a highly-available GitLab deployment,
+you should still use this reference architecture but scale down the node sizes.
+
+For a full list of reference architectures, see
+[Available reference architectures](index.md#available-reference-architectures).
> - **Supported users (approximate):** 3,000
> - **High Availability:** Yes
@@ -670,9 +671,9 @@ 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.
-#### PostgreSQL primary node
+#### PostgreSQL nodes
-1. SSH in to the PostgreSQL primary node.
+1. SSH in to one of the PostgreSQL nodes.
1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default
username of `gitlab` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -700,114 +701,33 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 gitlab-consul
```
-1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
+ # Disable all components except PostgreSQL, Patroni, and Consul
roles ['postgres_role']
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
-
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
-
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
- # START user configuration
- # Please set the real values as explained in Required Information section
- #
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = '<postgresql_password_hash>'
+ # Enable Patroni
+ patroni['enable'] = true
# Set `max_wal_senders` to one more than the number of database nodes in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
-
- # Replace XXX.XXX.XXX.XXX/YY with Network Address
- postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['enable'] = true
- consul['monitoring_service_discovery'] = true
-
- # 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'
- postgres_exporter['dbname'] = 'gitlabhq_production'
- postgres_exporter['password'] = '<postgresql_password_hash>'
-
- ## 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. You can list the current PostgreSQL primary, secondary nodes status via:
-
- ```shell
- sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show
- ```
-
-1. Verify the GitLab services are running:
-
- ```shell
- sudo gitlab-ctl status
- ```
-
- The output should be similar to the following:
-
- ```plaintext
- run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s
- run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s
- run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s
- run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s
- run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s
- run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s
- ```
-
-<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>
-
-#### PostgreSQL secondary nodes
-
-1. On both the secondary nodes, add the same configuration specified above for the primary node
- with an additional setting that will inform `gitlab-ctl` that they are standby nodes initially
- and there's no need to attempt to register them as a primary node:
-
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
-
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+ patroni['postgresql']['max_wal_senders'] = 4
+ patroni['postgresql']['max_replication_slots'] = 4
+ # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ patroni['postgresql']['max_connections'] = 500
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
+ consul['enable'] = true
consul['services'] = %w(postgresql)
-
- # Specify if a node should attempt to be primary on initialization.
- repmgr['master_on_initialization'] = false
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
# START user configuration
# Please set the real values as explained in Required Information section
@@ -816,34 +736,31 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
# Replace XXX.XXX.XXX.XXX/YY with Network Address
- postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['enable'] = true
- consul['monitoring_service_discovery'] = true
+ 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'
- postgres_exporter['dbname'] = 'gitlabhq_production'
- postgres_exporter['password'] = '<postgresql_password_hash>'
## 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
```
+PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
+Like most failover handling methods, this has a small chance of leading to data loss.
+Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
+ the file of the same name on this server. If that file is not on this server,
+ add the file from your Consul server to this server.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html)
@@ -874,84 +791,25 @@ SSH in to the **primary node**:
1. Exit the database prompt by typing `\q` and Enter.
-1. Verify the cluster is initialized with one node:
+1. Check the status of the leader and cluster:
```shell
- gitlab-ctl repmgr cluster show
+ gitlab-ctl patroni members
```
The output should be similar to the following:
```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `<primary_node_name>`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-SSH in to the **secondary node**:
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup <primary_node_name>
- ```
-
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart |
+ |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------|
+ | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.31 | Leader | running | 175 | | * |
+ | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.32 | | running | 175 | 0 | * |
+ | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.33 | | running | 175 | 0 | * |
```
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly and the secondary nodes appear in the cluster:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to the following:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+---------|-----------|------------------------------------------------
-* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
+If the 'State' column for any node doesn't say "running", check the
[Troubleshooting section](troubleshooting.md) before proceeding.
-Also, check that the `repmgr-check-master` command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](troubleshooting.md) before proceeding.
-
<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>
@@ -969,7 +827,7 @@ The following IPs will be used as an example:
1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace
`<consul_password_hash>` and `<pgbouncer_password_hash>` with the
- password hashes you [set up previously](#postgresql-primary-node):
+ password hashes you [set up previously](#postgresql-nodes):
```ruby
# Disable all components except Pgbouncer and Consul agent
@@ -977,15 +835,16 @@ The following IPs will be used as an example:
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
-
pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '<consul_password_hash>'
- },
- 'pgbouncer': {
- password: '<pgbouncer_password_hash>'
- }
+ 'gitlab-consul': {
+ password: '<consul_password_hash>'
+ },
+ 'pgbouncer': {
+ password: '<pgbouncer_password_hash>'
+ }
}
+ # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ pgbouncer['max_db_connections'] = 150
# Configure Consul agent
consul['watchers'] = %w(postgresql)
@@ -1841,6 +1700,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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.
+
<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>
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index f76c8a8a877..093869d331b 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -422,9 +422,9 @@ 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.
-#### PostgreSQL primary node
+#### PostgreSQL nodes
-1. SSH in to the PostgreSQL primary node.
+1. SSH in to one of the PostgreSQL nodes.
1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default
username of `gitlab` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -452,23 +452,33 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 gitlab-consul
```
-1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
+ # Disable all components except PostgreSQL, Patroni, and Consul
roles ['postgres_role']
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+ # Enable Patroni
+ patroni['enable'] = true
+ # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # This is used to prevent replication from using up all of the
+ # available database connections.
+ patroni['postgresql']['max_wal_senders'] = 4
+ patroni['postgresql']['max_replication_slots'] = 4
+ # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ patroni['postgresql']['max_connections'] = 500
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
+ consul['enable'] = true
consul['services'] = %w(postgresql)
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
# START user configuration
# Please set the real values as explained in Required Information section
@@ -477,18 +487,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
# Replace XXX.XXX.XXX.XXX/YY with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['monitoring_service_discovery'] = true
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
@@ -503,70 +504,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
-
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-<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>
-
-#### PostgreSQL secondary nodes
-
-1. On both the secondary nodes, add the same configuration specified above for the primary node
- with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially
- and there's no need to attempt to register them as a primary node:
-
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
-
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
-
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
-
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
-
- # Specify if a node should attempt to be primary on initialization.
- repmgr['master_on_initialization'] = false
-
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
-
- # Replace with your network addresses
- postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['monitoring_service_discovery'] = true
-
- # 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),
- }
- ```
+PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
+Like most failover handling methods, this has a small chance of leading to data loss.
+Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
the file of the same name on this server. If that file is not on this server,
@@ -601,84 +541,25 @@ SSH in to the **primary node**:
1. Exit the database prompt by typing `\q` and Enter.
-1. Verify the cluster is initialized with one node:
+1. Check the status of the leader and cluster:
```shell
- gitlab-ctl repmgr cluster show
+ gitlab-ctl patroni members
```
The output should be similar to the following:
```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `<primary_node_name>`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-SSH in to the **secondary node**:
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup <primary_node_name>
+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart |
+ |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------|
+ | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.21 | Leader | running | 175 | | * |
+ | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.22 | | running | 175 | 0 | * |
+ | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.23 | | running | 175 | 0 | * |
```
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
- ```
-
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly and the secondary nodes appear in the cluster:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to the following:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+---------|-----------|------------------------------------------------
-* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
+If the 'State' column for any node doesn't say "running", check the
[Troubleshooting section](troubleshooting.md) before proceeding.
-Also, check that the `repmgr-check-master` command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](troubleshooting.md) before proceeding.
-
<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>
@@ -696,7 +577,7 @@ The following IPs will be used as an example:
1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace
`<consul_password_hash>` and `<pgbouncer_password_hash>` with the
- password hashes you [set up previously](#postgresql-primary-node):
+ password hashes you [set up previously](#postgresql-nodes):
```ruby
# Disable all components except Pgbouncer and Consul agent
@@ -704,15 +585,16 @@ The following IPs will be used as an example:
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
-
pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '<consul_password_hash>'
- },
- 'pgbouncer': {
- password: '<pgbouncer_password_hash>'
- }
+ 'gitlab-consul': {
+ password: '<consul_password_hash>'
+ },
+ 'pgbouncer': {
+ password: '<pgbouncer_password_hash>'
+ }
}
+ # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ pgbouncer['max_db_connections'] = 150
# Configure Consul agent
consul['watchers'] = %w(postgresql)
@@ -2125,6 +2007,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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.
+
<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>
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 6a0547aeaf9..16ad866a108 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -671,9 +671,9 @@ 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.
-#### PostgreSQL primary node
+#### PostgreSQL nodes
-1. SSH in to the PostgreSQL primary node.
+1. SSH in to one of the PostgreSQL nodes.
1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default
username of `gitlab` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -701,114 +701,33 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 gitlab-consul
```
-1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
+ # Disable all components except PostgreSQL, Patroni, and Consul
roles ['postgres_role']
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
-
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
-
- # START user configuration
- # Please set the real values as explained in Required Information section
- #
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = '<postgresql_password_hash>'
+ # Enable Patroni
+ patroni['enable'] = true
# Set `max_wal_senders` to one more than the number of database nodes in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
-
- # Replace XXX.XXX.XXX.XXX/YY with Network Address
- postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['enable'] = true
- consul['monitoring_service_discovery'] = true
-
- # 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'
- postgres_exporter['dbname'] = 'gitlabhq_production'
- postgres_exporter['password'] = '<postgresql_password_hash>'
-
- ## 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. You can list the current PostgreSQL primary, secondary nodes status via:
-
- ```shell
- sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show
- ```
-
-1. Verify the GitLab services are running:
-
- ```shell
- sudo gitlab-ctl status
- ```
-
- The output should be similar to the following:
-
- ```plaintext
- run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s
- run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s
- run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s
- run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s
- run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s
- run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s
- ```
-
-<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>
-
-#### PostgreSQL secondary nodes
-
-1. On both the secondary nodes, add the same configuration specified above for the primary node
- with an additional setting that will inform `gitlab-ctl` that they are standby nodes initially
- and there's no need to attempt to register them as a primary node:
-
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
-
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+ patroni['postgresql']['max_wal_senders'] = 4
+ patroni['postgresql']['max_replication_slots'] = 4
+ # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ patroni['postgresql']['max_connections'] = 500
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
+ consul['enable'] = true
consul['services'] = %w(postgresql)
-
- # Specify if a node should attempt to be primary on initialization.
- repmgr['master_on_initialization'] = false
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
# START user configuration
# Please set the real values as explained in Required Information section
@@ -817,34 +736,31 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
- # This is used to prevent replication from using up all of the
- # available database connections.
- postgresql['max_wal_senders'] = 4
- postgresql['max_replication_slots'] = 4
# Replace XXX.XXX.XXX.XXX/YY with Network Address
- postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
-
- ## Enable service discovery for Prometheus
- consul['enable'] = true
- consul['monitoring_service_discovery'] = true
+ 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'
- postgres_exporter['dbname'] = 'gitlabhq_production'
- postgres_exporter['password'] = '<postgresql_password_hash>'
## 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
```
+PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
+Like most failover handling methods, this has a small chance of leading to data loss.
+Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
+ the file of the same name on this server. If that file is not on this server,
+ add the file from your Consul server to this server.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html)
@@ -874,84 +790,25 @@ SSH in to the **primary node**:
1. Exit the database prompt by typing `\q` and Enter.
-1. Verify the cluster is initialized with one node:
+1. Check the status of the leader and cluster:
```shell
- gitlab-ctl repmgr cluster show
+ gitlab-ctl patroni members
```
The output should be similar to the following:
```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `<primary_node_name>`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-SSH in to the **secondary node**:
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup <primary_node_name>
+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart |
+ |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------|
+ | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.31 | Leader | running | 175 | | * |
+ | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.32 | | running | 175 | 0 | * |
+ | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.33 | | running | 175 | 0 | * |
```
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
- ```
-
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly and the secondary nodes appear in the cluster:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to the following:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+---------|-----------|------------------------------------------------
-* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
+If the 'State' column for any node doesn't say "running", check the
[Troubleshooting section](troubleshooting.md) before proceeding.
-Also, check that the `repmgr-check-master` command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](troubleshooting.md) before proceeding.
-
<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>
@@ -969,7 +826,7 @@ The following IPs will be used as an example:
1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace
`<consul_password_hash>` and `<pgbouncer_password_hash>` with the
- password hashes you [set up previously](#postgresql-primary-node):
+ password hashes you [set up previously](#postgresql-nodes):
```ruby
# Disable all components except Pgbouncer and Consul agent
@@ -977,15 +834,16 @@ The following IPs will be used as an example:
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
-
pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '<consul_password_hash>'
- },
- 'pgbouncer': {
- password: '<pgbouncer_password_hash>'
- }
+ 'gitlab-consul': {
+ password: '<consul_password_hash>'
+ },
+ 'pgbouncer': {
+ password: '<pgbouncer_password_hash>'
+ }
}
+ # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
+ pgbouncer['max_db_connections'] = 150
# Configure Consul agent
consul['watchers'] = %w(postgresql)
@@ -1841,6 +1699,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+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.
+
<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>
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 6b04dad9baf..b90b8d67b68 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -95,7 +95,6 @@ have more actual perceived uptime for your users.
> - Level of complexity: **Low**
> - Required domain knowledge: PostgreSQL, GitLab configurations, Git
-> - Supported tiers: [GitLab Core, Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/)
This solution is appropriate for many teams that have the default GitLab installation.
With automatic backups of the GitLab repositories, configuration, and the database,
@@ -107,7 +106,6 @@ is the least complex to setup. This provides a point-in-time recovery of a prede
> - Level of complexity: **Medium**
> - Required domain knowledge: HAProxy, shared storage, distributed systems
-> - Supported tiers: [GitLab Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/)
This requires separating out GitLab into multiple application nodes with an added
[load balancer](../load_balancer.md). The load balancer will distribute traffic
@@ -123,11 +121,13 @@ to the default installation:
- Enable zero-downtime upgrades.
- Increase availability.
+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)**
> - Level of complexity: **Medium**
> - Required domain knowledge: PostgreSQL, HAProxy, shared storage, distributed systems
-> - Supported tiers: [GitLab Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/)
GitLab supports [zero-downtime updates](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates).
Single GitLab nodes can be updated with only a [few minutes of downtime](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
@@ -138,7 +138,6 @@ As long as at least one of each component is online and capable of handling the
> - Level of complexity: **High**
> - Required domain knowledge: PgBouncer, Repmgr or Patroni, shared storage, distributed systems
-> - Supported tiers: [GitLab Premium and Ultimate](https://about.gitlab.com/pricing/)
By adding automatic failover for database systems, you can enable higher uptime
with additional database nodes. This extends the default database with
@@ -150,7 +149,6 @@ is recommended.
> - Level of complexity: **Very High**
> - Required domain knowledge: Storage replication
-> - Supported tiers: [GitLab Premium and Ultimate](https://about.gitlab.com/pricing/)
[GitLab Geo](../geo/index.md) allows you to replicate your GitLab
instance to other geographical locations as a read-only fully operational instance
diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md
index 406ff57c66d..835231ac584 100644
--- a/doc/administration/reference_architectures/troubleshooting.md
+++ b/doc/administration/reference_architectures/troubleshooting.md
@@ -23,12 +23,12 @@ with the Fog library that GitLab uses. Symptoms include:
### GitLab Pages requires NFS
If you intend to use [GitLab Pages](../../user/project/pages/index.md), this currently requires
-[NFS](../nfs.md). 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).
+[NFS](../nfs.md). There is [work in progress](https://gitlab.com/groups/gitlab-org/-/epics/3901)
+to remove this dependency. In the future, GitLab Pages will use
+object storage.
The dependency on disk storage also prevents Pages being deployed using the
-[GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37).
+[GitLab Helm chart](https://gitlab.com/groups/gitlab-org/-/epics/4283).
### Incremental logging is required for CI to use object storage
@@ -206,13 +206,8 @@ To make sure your configuration is correct:
## Troubleshooting Gitaly
-### Checking versions when using standalone Gitaly nodes
-
-When using standalone Gitaly nodes, you must make sure they are the same version
-as GitLab to ensure full compatibility. Check **Admin Area > Gitaly Servers** on
-your GitLab instance and confirm all Gitaly Servers are `Up to date`.
-
-![Gitaly standalone software versions diagram](../gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png)
+If you have any problems when using standalone Gitaly nodes, first
+[check all the versions are up to date](../gitaly/index.md#check-versions-when-using-standalone-gitaly-servers).
### `gitaly-debug`
@@ -514,39 +509,24 @@ See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.
See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-ip-mask-md5-name-or-service-not-known).
-## Troubleshooting PostgreSQL
+## Troubleshooting PostgreSQL with Patroni
-In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs:
+In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs for PostgreSQL (which is run through Patroni):
```shell
-sudo gitlab-ctl tail postgresql
+sudo gitlab-ctl tail patroni
```
-### Consul and PostgreSQL changes not taking effect
+### Consul and PostgreSQL with Patroni changes not taking effect
Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading.
-To restart either service, run `gitlab-ctl restart SERVICE`
+To restart either service, run `gitlab-ctl restart consul` or `gitlab-ctl restart patroni` respectively.
-For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`.
+For PostgreSQL with Patroni, to prevent the primary node from being failed over automatically, it's safest to stop all secondaries first, then restart the primary and finally restart the secondaries again.
On the Consul server nodes, it is important to restart the Consul service in a controlled fashion. Read our [Consul documentation](../consul.md#restart-consul) for instructions on how to restart the service.
-### `gitlab-ctl repmgr-check-master` command produces errors
-
-If this command displays errors about database permissions it is likely that something failed during
-install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these
-steps to fix the problem:
-
-1. On the master database node, connect to the database prompt - `gitlab-psql -d template1`
-1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";`
-1. Exit the database prompt - `\q`
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions.
-1. Change to the `gitlab-consul` user - `su - gitlab-consul`
-1. Try the check command again - `gitlab-ctl repmgr-check-master`.
-
-Now there should not be errors. If errors still occur then there is another problem.
-
### PgBouncer error `ERROR: pgbouncer cannot connect to server`
You may get this error when running `gitlab-rake gitlab:db:configure` or you
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index 090f95eca12..c71d1a5714c 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -122,3 +122,9 @@ weights are used to determine the storage location the repository is created on.
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
+
+To move a repository to a different repository path, use the
+[Project repository storage moves](../api/project_repository_storage_moves.md) API. Use
+the same process as [migrating existing repositories to Gitaly Cluster](gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index edd44380f30..be5647aa133 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -20,11 +20,8 @@ These locations can be configured using the options described below.
## Using local storage
-NOTE:
-This is the default configuration
-
-To change the location where Terraform state files are stored locally, follow the steps
-below.
+The default configuration uses local storage. To change the location where
+Terraform state files are stored locally, follow the steps below.
**In Omnibus installations:**
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index 755273eb06e..fb153adfeab 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -36,6 +36,7 @@ The type of problem will determine what steps to take. The possible troubleshoot
- Indexing.
- Integration.
- Performance.
+- Background Migrations.
### Search Results workflow
@@ -147,6 +148,30 @@ graph TD;
F7(Escalate to<br>GitLab support.)
```
+### Background Migrations workflow
+
+```mermaid
+graph TD;
+ D --> |No| D1
+ D --> |Yes| D2
+ D2 --> |No| D3
+ D2 --> |Yes| D4
+ D4 --> |No| D5
+ D4 --> |Yes| D6
+ D6 --> |No| D8
+ D6 --> |Yes| D7
+
+ D{Is there a halted migration?}
+ D1[Migrations run in the<br>background and will<br>stop when completed.]
+ D2{Does the elasticsearch.log<br>file contain errors?}
+ D3[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.]
+ D4{Have the errors<br>been addressed?}
+ D5[Have an Elasticsearch admin<br>review and address<br>the errors.]
+ D6{Has the migration<br>been retried?}
+ D7[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.]
+ D8[Retry the migration from<br>the Admin > Settings ><br>Advanced Search UI.]
+```
+
## Troubleshooting walkthrough
Most Elasticsearch troubleshooting can be broken down into 4 categories:
@@ -155,6 +180,7 @@ Most Elasticsearch troubleshooting can be broken down into 4 categories:
- [Troubleshooting indexing](#troubleshooting-indexing)
- [Troubleshooting integration](#troubleshooting-integration)
- [Troubleshooting performance](#troubleshooting-performance)
+- [Troubleshooting background migrations](#troubleshooting-background-migrations)
Generally speaking, if it does not fall into those four categories, it is either:
@@ -330,6 +356,18 @@ 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.
+### Troubleshooting background migrations
+
+Troubleshooting background migration failures can be difficult and may require contacting
+an Elasticsearch admin 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
+print information while a migration is in progress and any errors encountered.
+Apply fixes for any errors found in the log and retry the migration.
+
+If you still encounter issues after retrying the migration, reach out to GitLab support.
+
## Common issues
All common issues [should be documented](../../integration/elasticsearch.md#troubleshooting). If not,
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 2482a4fe7ad..4a112733bfa 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -384,7 +384,7 @@ project = Project.find_by_full_path('PROJECT_PATH')
Projects::ImportExport::ExportService.new(project, user).execute
```
-If the project you wish to export is available at `https://gitlab.example.com/baltig/pipeline-templates`, the value to use for `PROJECT_PATH` would be `baltig/pipeline-templates`.
+If the project you wish to export is available at `https://gitlab.example.com/baltig/pipeline-templates`, the value to use for `PROJECT_PATH` would be `baltig/pipeline-templates`.
If this all runs successfully, you will see output like the following before being returned to the Rails console prompt:
@@ -392,7 +392,7 @@ If this all runs successfully, you will see output like the following before bei
=> nil
```
-The exported project will be located within a `.tar.gz` file in `/var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/`.
+The exported project will be located within a `.tar.gz` file in `/var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/`.
## Repository
@@ -598,7 +598,7 @@ group = Group.find_by_path_or_name('group-name')
group.project_creation_level=0
```
-### Modify group - disable 2FA requirement
+### Modify group - disable 2FA requirement
WARNING:
When disabling the 2FA Requirement on a subgroup, the whole parent group (including all subgroups) is affected by this change.
@@ -743,7 +743,7 @@ m.project.try(:ci_service)
```ruby
project = Project.find_by_full_path 'group/project'
content = project.repository.gitlab_ci_yml_for(project.repository.root_ref_sha)
-Gitlab::Ci::YamlProcessor.validation_message(content, user: User.first)
+Gitlab::Ci::Lint.new(project: project, current_user: User.first).validate(content)
```
### Disable AutoDevOps on Existing Projects
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 7052b68370c..4ccae10e5b3 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -157,7 +157,7 @@ See current settings with:
```shell
sudo gitlab-rails runner "c = ApplicationRecord.connection ; puts c.execute('SHOW statement_timeout').to_a ;
-puts c.execute('SHOW lock_timeout').to_a ;
+puts c.execute('SHOW deadlock_timeout').to_a ;
puts c.execute('SHOW idle_in_transaction_session_timeout').to_a ;"
```
@@ -165,9 +165,19 @@ It may take a little while to respond.
```ruby
{"statement_timeout"=>"1min"}
-{"lock_timeout"=>"0"}
+{"deadlock_timeout"=>"0"}
{"idle_in_transaction_session_timeout"=>"1min"}
```
+These settings can be updated in `/etc/gitlab/gitlab.rb` with:
+
+```ruby
+postgresql['deadlock_timeout'] = '5s'
+postgresql['statement_timeout'] = '15s'
+postgresql['idle_in_transaction_session_timeout'] = '60s'
+```
+
+Once saved, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
NOTE:
These are Omnibus GitLab settings. If an external database, such as a customer's PostgreSQL installation or Amazon RDS is being used, these values don't get set, and would have to be set externally.
diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md
index 2981b9e1368..ad2b8586b8b 100644
--- a/doc/administration/troubleshooting/tracing_correlation_id.md
+++ b/doc/administration/troubleshooting/tracing_correlation_id.md
@@ -29,7 +29,7 @@ documentation for some popular browsers.
- [Network Monitor - Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor)
- [Inspect Network Activity In Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/network/)
- [Safari Web Development Tools](https://developer.apple.com/safari/tools/)
-- [Microsoft Edge Network panel](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/network#request-details)
+- [Microsoft Edge Network panel](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/network/)
To locate a relevant request and view its correlation ID:
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index 94e7bbe2cff..49af8358e29 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -8,46 +8,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
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.
-## Upload parameters
-
-> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/214785) in GitLab 13.5.
-> - 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. **(CORE ONLY)**
-
-In 13.5 and later, upload parameters are passed [between Workhorse and GitLab Rails](../development/architecture.md#simplified-component-overview) differently than they
-were before.
-
-This change is deployed behind a feature flag that is **enabled by default**.
-
-If you experience any issues with upload,
-[GitLab administrators with access to the GitLab Rails console](feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:upload_middleware_jwt_params_handler)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:upload_middleware_jwt_params_handler)
-```
-
## Using local storage
This is the default configuration. To change the location where the uploads are
stored locally, use the steps in this section based on your installation method:
-**In Omnibus GitLab installations:**
-
NOTE:
-For historical reasons, uploads are stored into a base directory, which by
-default is `uploads/-/system`. It's strongly discouraged to change this
-configuration option for an existing GitLab installation.
+For historical reasons, instance level uploads (for example the [favicon](../user/admin_area/appearance.md#favicon)) are stored into a base directory,
+which by default is `uploads/-/system`. It is strongly discouraged to change the base
+directory on an existing GitLab installation.
+
+**In Omnibus GitLab installations:**
_The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._
@@ -55,16 +26,17 @@ _The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._
`/etc/gitlab/gitlab.rb` and add the following line:
```ruby
- gitlab_rails['uploads_storage_path'] = "/mnt/storage/"
- gitlab_rails['uploads_base_dir'] = "uploads"
+ gitlab_rails['uploads_directory'] = "/mnt/storage/uploads"
```
+ This setting only applies if you haven't changed the `gitlab_rails['uploads_storage_path']` directory.
+
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
**In installations from source:**
_The uploads are stored by default in
-`/home/git/gitlab/public/uploads/-/system`._
+`/home/git/gitlab/public/uploads`._
1. To change the storage path for example to `/mnt/storage/uploads`, edit
`/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
@@ -93,7 +65,7 @@ This configuration relies on valid AWS credentials to be configured already.
We recommend using the [consolidated object storage settings](object_storage.md#consolidated-object-storage-configuration). The following instructions apply to the original configuration format.
-## Object Storage Settings
+### Object Storage Settings
For source installations the following settings are nested under `uploads:` and then `object_store:`. On Omnibus GitLab installs they are prefixed by `uploads_object_store_`.
@@ -106,14 +78,14 @@ For source installations the following settings are nested under `uploads:` and
| `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 | |
-### Connection settings
+#### Connection settings
See [the available connection settings for different providers](object_storage.md#connection-settings).
**In Omnibus installations:**
_The uploads are stored by default in
-`/var/opt/gitlab/gitlab-rails/public/uploads/-/system`._
+`/var/opt/gitlab/gitlab-rails/uploads`._
1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with
the values you want:
@@ -145,7 +117,7 @@ _The uploads are stored by default in
**In installations from source:**
_The uploads are stored by default in
-`/home/git/gitlab/public/uploads/-/system`._
+`/home/git/gitlab/public/uploads`._
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
lines:
@@ -165,12 +137,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.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
-### OpenStack example
+#### OpenStack example
**In Omnibus installations:**
_The uploads are stored by default in
-`/var/opt/gitlab/gitlab-rails/public/uploads/-/system`._
+`/var/opt/gitlab/gitlab-rails/uploads`._
1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with
the values you want:
@@ -196,7 +168,7 @@ _The uploads are stored by default in
**In installations from source:**
_The uploads are stored by default in
-`/home/git/gitlab/public/uploads/-/system`._
+`/home/git/gitlab/public/uploads`._
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
lines:
diff --git a/doc/api/README.md b/doc/api/README.md
index dced721b018..8fb3269d28b 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -23,9 +23,9 @@ For a list of the available resources and their endpoints, see
## SCIM **(SILVER ONLY)**
-[GitLab.com Silver and higher](https://about.gitlab.com/pricing/) provides an
-[SCIM API](scim.md) that both implements [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644)
-and provides the `/Users` endpoint. The base URL is: `/api/scim/v2/groups/:group_path/Users/`.
+GitLab provides an [SCIM API](scim.md) that both implements
+[the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides the
+`/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`.
## Road to GraphQL
@@ -186,9 +186,9 @@ curl --header "Authorization: Bearer <your_access_token>" "https://gitlab.exampl
### Session cookie
-When signing in to the main GitLab application, a `_gitlab_session` cookie is
-set. The API uses this cookie for authentication if it's present. Using the
-API to generate a new session cookie isn't supported.
+Signing in to the main GitLab application sets a `_gitlab_session` cookie. The
+API uses this cookie for authentication if it's present. Using the API to
+generate a new session cookie isn't supported.
The primary user of this authentication method is the web frontend of GitLab
itself, which can, for example, use the API as the authenticated user to get a
@@ -203,8 +203,7 @@ to authenticate with the API:
- [Composer Repository](../user/packages/composer_repository/index.md)
- [Conan Repository](../user/packages/conan_repository/index.md)
- [Container Registry](../user/packages/container_registry/index.md)
- (`$CI_REGISTRY_PASSWORD` is actually `$CI_JOB_TOKEN`, but this may change in
- the future)
+ (`$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)
@@ -221,12 +220,12 @@ The token is valid as long as the job is running.
### Impersonation tokens
Impersonation tokens are a type of [personal access token](../user/profile/personal_access_tokens.md)
-that can only be created by an administrator for a specific user. They are a great fit
-if you want to build applications or scripts that authenticate with the API as a
-specific user.
+that can be created only by an administrator for a specific user. They can be
+useful if you want to build applications or scripts that authenticate with the
+API as a specific user.
-They're an alternative to directly using the user's password or one of their
-personal access tokens, and to using the [Sudo](#sudo) feature, as the user's
+They're an alternative to directly using the user's password (or one of their
+personal access tokens), and to using the [Sudo](#sudo) feature, as the user's
(or administrator's in the case of Sudo) password or token may not be known, or may
change over time.
@@ -245,13 +244,13 @@ By default, impersonation is enabled. To disable impersonation:
**For Omnibus installations**
-1. Edit `/etc/gitlab/gitlab.rb`:
+1. Edit the `/etc/gitlab/gitlab.rb` file:
```ruby
gitlab_rails['impersonation_enabled'] = false
```
-1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+1. Save the file, and then [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
To re-enable impersonation, remove this configuration, and then reconfigure
@@ -259,14 +258,14 @@ GitLab.
**For installations from source**
-1. Edit `config/gitlab.yml`:
+1. Edit the `config/gitlab.yml` file:
```yaml
gitlab:
impersonation_enabled: false
```
-1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source)
+1. Save the file, and then [restart](../administration/restart_gitlab.md#installations-from-source)
GitLab for the changes to take effect.
To re-enable impersonation, remove this configuration, and then restart GitLab.
@@ -353,41 +352,41 @@ The following table shows the possible return codes for API requests.
| Return values | Description |
|--------------------------|-------------|
-| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON. |
-| `204 No Content` | The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. |
-| `201 Created` | The `POST` request was successful and the resource is returned as JSON. |
-| `304 Not Modified` | Indicates that the resource has not been modified since the last request. |
+| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, and the resource(s) itself is returned as JSON. |
+| `204 No Content` | The server has successfully fulfilled the request, and there is no additional content to send in the response payload body. |
+| `201 Created` | The `POST` request was successful, and the resource is returned as JSON. |
+| `304 Not Modified` | The resource hasn't been modified since the last request. |
| `400 Bad Request` | A required attribute of the API request is missing. For example, the title of an issue is not given. |
-| `401 Unauthorized` | The user is not authenticated, a valid [user token](#authentication) is necessary. |
-| `403 Forbidden` | The request is not allowed. For example, the user is not allowed to delete a project. |
-| `404 Not Found` | A resource could not be accessed. For example, an ID for a resource could not be found. |
-| `405 Method Not Allowed` | The request is not supported. |
+| `401 Unauthorized` | The user isn't authenticated. A valid [user token](#authentication) is necessary. |
+| `403 Forbidden` | The request isn't allowed. For example, the user isn't allowed to delete a project. |
+| `404 Not Found` | A resource couldn't be accessed. For example, an ID for a resource couldn't be found. |
+| `405 Method Not Allowed` | The request isn't supported. |
| `409 Conflict` | A conflicting resource already exists. For example, creating a project with a name that already exists. |
-| `412` | Indicates the request was denied. May happen if the `If-Unmodified-Since` header is provided when trying to delete a resource, which was modified in between. |
-| `422 Unprocessable` | The entity could not be processed. |
+| `412` | The request was denied. This can happen if the `If-Unmodified-Since` header is provided when trying to delete a resource, which was modified in between. |
+| `422 Unprocessable` | The entity couldn't be processed. |
| `429 Too Many Requests` | The user exceeded the [application rate limits](../administration/instance_limits.md#rate-limits). |
-| `500 Server Error` | While handling the request, something went wrong server-side. |
+| `500 Server Error` | While handling the request, something went wrong on the server. |
## Pagination
GitLab supports the following pagination methods:
-- Offset-based pagination. This is the default method and available on all endpoints.
+- Offset-based pagination. This is the default method and is available on all endpoints.
- Keyset-based pagination. Added to selected endpoints but being
[progressively rolled out](https://gitlab.com/groups/gitlab-org/-/epics/2039).
-For large collections, we recommend keyset pagination (when available) instead
-of offset pagination for performance reasons.
+For large collections, for performance reasons we recommend keyset pagination
+(when available) instead of offset pagination.
### Offset-based pagination
Sometimes, the returned result spans many pages. When listing resources, you can
pass the following parameters:
-| Parameter | Description |
-|-----------|-------------|
-| `page` | Page number (default: `1`). |
-| `per_page`| Number of items to list per page (default: `20`, max: `100`). |
+| Parameter | Description |
+|------------|-------------|
+| `page` | Page number (default: `1`). |
+| `per_page` | Number of items to list per page (default: `20`, max: `100`). |
In the following example, we list 50 [namespaces](namespaces.md) per page:
@@ -485,10 +484,10 @@ header was [added in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/merge_r
and should be used instead.
The link to the next page contains an additional filter `id_after=42` that
-excludes already-retrieved records. Note the type of filter depends on the
+excludes already-retrieved records. The type of filter depends on the
`order_by` option used, and we may have more than one additional filter.
-When the end of the collection has been reached and there are no additional
+When the end of the collection is reached and there are no additional
records to retrieve, the `Link` header is absent and the resulting array is
empty.
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index c6fd5b7c45c..029e434749f 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -158,6 +158,7 @@ The following API resources are available outside of project and group contexts
| [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` |
| [Statistics](statistics.md) | `/application/statistics` |
| [Sidekiq metrics](sidekiq_metrics.md) **(CORE ONLY)** | `/sidekiq` |
| [Suggestions](suggestions.md) | `/suggestions` |
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index b33e41cf271..d03fc94cfcf 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -60,8 +60,8 @@ PUT /application/appearance
| `favicon` | mixed | no | Instance favicon in `.ico` or `.png` format
| `new_project_guidelines` | string | no | Markdown text shown on the new project page
| `profile_image_guidelines` | string | no | Markdown text shown on the profile page below Public Avatar
-| `header_message` | string | no | Message within the system header bar
-| `footer_message` | string | no | Message within the system footer bar
+| `header_message` | string | no | Message in the system header bar
+| `footer_message` | string | no | Message in the system footer bar
| `message_background_color` | string | no | Background color for the system header / footer bar
| `message_font_color` | string | no | Font color for the system header / footer bar
| `email_header_and_footer_enabled` | boolean | no | Add header and footer to all outgoing emails if enabled
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 282c4ccfeea..5017c8defaf 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Compliance
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index 31f254c7986..ccaa50eedd8 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -30,7 +30,7 @@ Parameters:
| Attribute | Type | Required | Description |
|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
| `email` | string | yes | Public email address of the user. |
-| `size` | integer | no | Single pixel dimension (since images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server. |
+| `size` | integer | no | Single pixel dimension (because images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server. |
Example request:
diff --git a/doc/api/boards.md b/doc/api/boards.md
index aff82daa1bf..e86f0d846ed 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -426,7 +426,7 @@ POST /projects/:id/boards/:board_id/lists
NOTE:
Label, assignee and milestone arguments are mutually exclusive,
that is, only one of them are accepted in a request.
-Check the [Issue Board docs](../user/project/issue_board.md)
+Check the [Issue Board documentation](../user/project/issue_board.md)
for more information regarding the required license for each list type.
```shell
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index 5f3dbcb1ab0..f29f8aaf6e9 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55978) in GitLab 11.8.
-This is the API docs of the [GitLab Container Registry](../user/packages/container_registry/index.md).
+This is the API documentation of the [GitLab Container Registry](../user/packages/container_registry/index.md).
## List registry repositories
@@ -313,6 +313,13 @@ You can run this at most once an hour for a given container repository. This
action doesn't delete blobs. To delete them and recycle disk space,
[run the garbage collection](https://docs.gitlab.com/omnibus/maintenance/README.html#removing-unused-layers-not-referenced-by-manifests).
+WARNING:
+The number of tags deleted by this API is limited on GitLab.com
+because of the scale of the Container Registry there.
+If your Container Registry has a large number of tags to delete,
+only some of them will be deleted, and you might need to call this API multiple times.
+To schedule tags for automatic deletion, use a [cleanup policy](../user/packages/container_registry/index.md#cleanup-policy) instead.
+
NOTE:
In GitLab 12.4 and later, individual tags are deleted.
For more details, see the [discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/15737).
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 293f7218527..91046717c1d 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -109,8 +109,8 @@ Example response:
Creates a new deploy key for a project.
-If the deploy key already exists in another project, it will be joined to current
-project only if original one is accessible by the same user.
+If the deploy key already exists in another project, it's joined to the current
+project only if the original one is accessible by the same user.
```plaintext
POST /projects/:id/deploy_keys
@@ -171,7 +171,7 @@ Example response:
## Delete deploy key
-Removes a deploy key from the project. If the deploy key is used only for this project, it will be deleted from the system.
+Removes a deploy key from the project. If the deploy key is used only for this project, it's deleted from the system.
```plaintext
DELETE /projects/:id/deploy_keys/:key_id
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 4a937cd1818..b8865ecc614 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -379,7 +379,7 @@ This API retrieves the list of merge requests shipped with a given deployment:
GET /projects/:id/deployments/:deployment_id/merge_requests
```
-It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and will return a response using the same format:
+It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and returns a response using the same format:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42"
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 51ca2bea3ae..a7a53987fe9 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -687,7 +687,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/discussions
"noteable_iid": null,
"resolved": false,
"resolvable": true,
- "resolved_by": null
+ "resolved_by": null,
+ "resolved_at": null
},
{
"id": 1129,
diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md
index 319d1a1ee9b..cabab18ed71 100644
--- a/doc/api/epic_links.md
+++ b/doc/api/epic_links.md
@@ -76,7 +76,7 @@ Example response:
Creates an association between two epics, designating one as the parent epic and the other as the child epic. A parent epic can have multiple child epics. If the new child epic already belonged to another epic, it is unassigned from that previous parent.
```plaintext
-POST /groups/:id/epics/:epic_iid/epics
+POST /groups/:id/epics/:epic_iid/epics/:child_epic_id
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/epics.md b/doc/api/epics.md
index dc582808578..d501d61bfb8 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -11,9 +11,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Every API call to epic must be authenticated.
-If a user is not a member of a group and the group is private, a `GET` request on that group will result to 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.
-If epics feature is not available a `403` status code will be returned.
+If epics feature is not available a `403` status code is returned.
## Epic issues API
@@ -23,9 +23,10 @@ The [epic issues API](epic_issues.md) allows you to interact with issues associa
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448) in GitLab 11.3.
-Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission,
-additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`,
-and four date fields `start_date_fixed`, `start_date_from_inherited_source`, `due_date_fixed` and `due_date_from_inherited_source`.
+Because start date and due date can be dynamically sourced from related issue milestones,
+additional fields are shown when user has edit permission. These include two boolean
+fields `start_date_is_fixed` and `due_date_is_fixed`, and four date fields `start_date_fixed`,
+`start_date_from_inherited_source`, `due_date_fixed` and `due_date_from_inherited_source`.
- `end_date` has been deprecated in favor of `due_date`.
- `start_date_from_milestones` has been deprecated in favor of `start_date_from_inherited_source`
@@ -40,7 +41,7 @@ Read more on [pagination](README.md#pagination).
WARNING:
> `reference` attribute in response is deprecated in favour of `references`.
-> Introduced [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)
+> Introduced in [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)
NOTE:
> `references.relative` is relative to the group that the epic is being requested. When epic is fetched from its origin group
@@ -62,7 +63,7 @@ GET /groups/:id/epics?state=opened
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `author_id` | integer | no | Return epics created by the given user `id` |
| `labels` | string | no | Return epics matching a comma separated list of labels names. Label names from the epic group or a parent group can be used |
-| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)|
+| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Available in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) and later |
| `order_by` | string | no | Return epics ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search epics against their `title` and `description` |
@@ -73,7 +74,7 @@ GET /groups/:id/epics?state=opened
| `updated_before` | datetime | no | Return epics updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `include_ancestor_groups` | boolean | no | Include epics from the requested group's ancestors. Default is `false` |
| `include_descendant_groups` | boolean | no | Include epics from the requested group's descendants. Default is `true` |
-| `my_reaction_emoji` | string | no | Return epics reacted by the authenticated user by the given emoji. `None` returns epics not given a reaction. `Any` returns epics given at least one reaction. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479)|
+| `my_reaction_emoji` | string | no | Return epics reacted by the authenticated user by the given emoji. `None` returns epics not given a reaction. `Any` returns epics given at least one reaction. Available in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479) and later |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics"
@@ -267,12 +268,12 @@ POST /groups/:id/epics
| `labels` | string | no | The comma separated list of labels |
| `description` | string | no | The description of the epic. Limited to 1,048,576 characters. |
| `confidential` | boolean | no | Whether the epic should be confidential |
-| `created_at` | string | no | When the epic was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5) |
-| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) |
-| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) |
-| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) |
-| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) |
-| `parent_id` | integer/string | no | The ID of a parent epic (since 11.11) |
+| `created_at` | string | no | When the epic was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([available](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5 and later) |
+| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (in GitLab 11.3 and later) |
+| `start_date_fixed` | string | no | The fixed start date of an epic (in GitLab 11.3 and later) |
+| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (in GitLab 11.3 and later) |
+| `due_date_fixed` | string | no | The fixed due date of an epic (in GitLab 11.3 and later) |
+| `parent_id` | integer/string | no | The ID of a parent epic (in GitLab 11.11 and later) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description"
@@ -352,12 +353,12 @@ PUT /groups/:id/epics/:epic_iid
| `labels` | string | no | Comma-separated label names for an issue. Set to an empty string to unassign all labels. |
| `add_labels` | string | no | Comma-separated label names to add to an issue. |
| `remove_labels` | string | no | Comma-separated label names to remove from an issue. |
-| `updated_at` | string | no | When the epic was updated. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5) |
-| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) |
-| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) |
-| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) |
-| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) |
-| `state_event` | string | no | State event for an epic. Set `close` to close the epic and `reopen` to reopen it (since 11.4) |
+| `updated_at` | string | no | When the epic was updated. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([available](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5 and later) |
+| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (in GitLab 11.3 and later) |
+| `start_date_fixed` | string | no | The fixed start date of an epic (in GitLab 11.3 and later) |
+| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (in GitLab 11.3 and later) |
+| `due_date_fixed` | string | no | The fixed due date of an epic (in GitLab 11.3 and later) |
+| `state_event` | string | no | State event for an epic. Set `close` to close the epic and `reopen` to reopen it (in GitLab 11.4 and later) |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics/5?title=New%20Title"
diff --git a/doc/api/features.md b/doc/api/features.md
index 0582a4b9432..0ed0dec1b6d 100644
--- a/doc/api/features.md
+++ b/doc/api/features.md
@@ -111,8 +111,8 @@ Example response:
## Set or create a feature
-Set a feature's gate value. If a feature with the given name doesn't exist yet
-it will be created. The value can be a boolean, or an integer to indicate
+Set a feature's gate value. If a feature with the given name doesn't exist yet,
+it's created. The value can be a boolean, or an integer to indicate
percentage of time.
```plaintext
diff --git a/doc/api/graphql/img/users_query_example_v13_8.png b/doc/api/graphql/img/users_query_example_v13_8.png
new file mode 100644
index 00000000000..b4c2b4e999a
--- /dev/null
+++ 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 681130e82c1..45a327d323b 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -82,6 +82,10 @@ The process is as follows:
release post (at or prior to X.11 and X.5 releases).
1. Fields meeting criteria are removed in X.0 or X.6.
+NOTE:
+Fields behind a feature flag and disabled by default are exempt from the deprecation process,
+and can be removed at any time without notice.
+
### List of removed items
View the [fields, enums, and other items we removed](removed_items.md) from the GraphQL API.
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 8218d792fe8..94792a49933 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -30,7 +30,7 @@ Autogenerated input type of AddAwardEmoji
"""
input AddAwardEmojiInput {
"""
- The global ID of the awardable resource
+ The global ID of the awardable resource.
"""
awardableId: AwardableID!
@@ -50,7 +50,7 @@ Autogenerated return type of AddAwardEmoji
"""
type AddAwardEmojiPayload {
"""
- The award emoji after mutation
+ The award emoji after mutation.
"""
awardEmoji: AwardEmoji
@@ -75,7 +75,7 @@ input AddProjectToSecurityDashboardInput {
clientMutationId: String
"""
- ID of the project to be added to Instance Security Dashboard
+ ID of the project to be added to Instance Security Dashboard.
"""
id: ProjectID!
}
@@ -95,7 +95,7 @@ type AddProjectToSecurityDashboardPayload {
errors: [String!]!
"""
- Project that was added to the Instance Security Dashboard
+ Project that was added to the Instance Security Dashboard.
"""
project: Project
}
@@ -125,7 +125,7 @@ input AdminSidekiqQueuesDeleteJobsInput {
project: String
"""
- The name of the queue to delete jobs from
+ The name of the queue to delete jobs from.
"""
queueName: String!
@@ -135,6 +135,11 @@ input AdminSidekiqQueuesDeleteJobsInput {
relatedClass: String
"""
+ Delete jobs matching remote_ip in the context metadata
+ """
+ remoteIp: String
+
+ """
Delete jobs matching root_namespace in the context metadata
"""
rootNamespace: String
@@ -165,7 +170,7 @@ type AdminSidekiqQueuesDeleteJobsPayload {
errors: [String!]!
"""
- Information about the status of the deletion request
+ Information about the status of the deletion request.
"""
result: DeleteJobsResponse
}
@@ -349,7 +354,7 @@ type AlertManagementAlert implements Noteable {
"""
todos(
"""
- The action to be filtered
+ The action to be filtered.
"""
action: [TodoActionEnum!]
@@ -359,7 +364,7 @@ type AlertManagementAlert implements Noteable {
after: String
"""
- The ID of an author
+ The ID of an author.
"""
authorId: [ID!]
@@ -374,7 +379,7 @@ type AlertManagementAlert implements Noteable {
first: Int
"""
- The ID of a group
+ The ID of a group.
"""
groupId: [ID!]
@@ -384,17 +389,17 @@ type AlertManagementAlert implements Noteable {
last: Int
"""
- The ID of a project
+ The ID of a project.
"""
projectId: [ID!]
"""
- The state of the todo
+ The state of the todo.
"""
state: [TodoStateEnum!]
"""
- The type of the todo
+ The type of the todo.
"""
type: [TodoTargetEnum!]
): TodoConnection
@@ -595,7 +600,7 @@ Filters the alerts based on given domain
"""
enum AlertManagementDomainFilter {
"""
- Alerts for operations domain
+ Alerts for operations domain
"""
operations
@@ -738,6 +743,106 @@ enum AlertManagementIntegrationType {
}
"""
+Field that are available while modifying the custom mapping attributes for an HTTP integration
+"""
+input AlertManagementPayloadAlertFieldInput {
+ """
+ A GitLab alert field name.
+ """
+ fieldName: AlertManagementPayloadAlertFieldName!
+
+ """
+ Human-readable label of the payload path.
+ """
+ label: String
+
+ """
+ Path to value inside payload JSON.
+ """
+ path: [String!]!
+
+ """
+ Type of the parsed value.
+ """
+ type: AlertManagementPayloadAlertFieldType!
+}
+
+"""
+Values for alert field names used in the custom mapping
+"""
+enum AlertManagementPayloadAlertFieldName {
+ """
+ A high-level summary of the problem.
+ """
+ DESCRIPTION
+
+ """
+ The resolved time of the incident.
+ """
+ END_TIME
+
+ """
+ The unique identifier of the alert. This can be used to group occurrences of the same alert.
+ """
+ FINGERPRINT
+
+ """
+ The name of the associated GitLab environment.
+ """
+ GITLAB_ENVIRONMENT_NAME
+
+ """
+ One or more hosts, as to where this incident occurred.
+ """
+ HOSTS
+
+ """
+ The name of the associated monitoring tool.
+ """
+ MONITORING_TOOL
+
+ """
+ The affected service.
+ """
+ SERVICE
+
+ """
+ The severity of the alert.
+ """
+ SEVERITY
+
+ """
+ The time of the incident.
+ """
+ START_TIME
+
+ """
+ The title of the incident.
+ """
+ TITLE
+}
+
+"""
+Values for alert field types used in the custom mapping
+"""
+enum AlertManagementPayloadAlertFieldType {
+ """
+ Array field type
+ """
+ ARRAY
+
+ """
+ DateTime field type
+ """
+ DATETIME
+
+ """
+ String field type
+ """
+ STRING
+}
+
+"""
An endpoint and credentials used to accept Prometheus alerts for a project
"""
type AlertManagementPrometheusIntegration implements AlertManagementIntegration {
@@ -852,7 +957,7 @@ input AlertSetAssigneesInput {
clientMutationId: String
"""
- The IID of the alert to mutate
+ The IID of the alert to mutate.
"""
iid: String!
@@ -862,7 +967,7 @@ input AlertSetAssigneesInput {
operationMode: MutationOperationMode
"""
- The project the alert to mutate is in
+ The project the alert to mutate is in.
"""
projectPath: ID!
}
@@ -872,7 +977,7 @@ Autogenerated return type of AlertSetAssignees
"""
type AlertSetAssigneesPayload {
"""
- The alert after mutation
+ The alert after mutation.
"""
alert: AlertManagementAlert
@@ -887,12 +992,12 @@ type AlertSetAssigneesPayload {
errors: [String!]!
"""
- The issue created after mutation
+ The issue created after mutation.
"""
issue: Issue
"""
- The todo after mutation
+ The todo after mutation.
"""
todo: Todo
}
@@ -907,12 +1012,12 @@ input AlertTodoCreateInput {
clientMutationId: String
"""
- The IID of the alert to mutate
+ The IID of the alert to mutate.
"""
iid: String!
"""
- The project the alert to mutate is in
+ The project the alert to mutate is in.
"""
projectPath: ID!
}
@@ -922,7 +1027,7 @@ Autogenerated return type of AlertTodoCreate
"""
type AlertTodoCreatePayload {
"""
- The alert after mutation
+ The alert after mutation.
"""
alert: AlertManagementAlert
@@ -937,12 +1042,12 @@ type AlertTodoCreatePayload {
errors: [String!]!
"""
- The issue created after mutation
+ The issue created after mutation.
"""
issue: Issue
"""
- The todo after mutation
+ The todo after mutation.
"""
todo: Todo
}
@@ -1007,7 +1112,7 @@ Autogenerated input type of AwardEmojiAdd
"""
input AwardEmojiAddInput {
"""
- The global ID of the awardable resource
+ The global ID of the awardable resource.
"""
awardableId: AwardableID!
@@ -1027,7 +1132,7 @@ Autogenerated return type of AwardEmojiAdd
"""
type AwardEmojiAddPayload {
"""
- The award emoji after mutation
+ The award emoji after mutation.
"""
awardEmoji: AwardEmoji
@@ -1047,7 +1152,7 @@ Autogenerated input type of AwardEmojiRemove
"""
input AwardEmojiRemoveInput {
"""
- The global ID of the awardable resource
+ The global ID of the awardable resource.
"""
awardableId: AwardableID!
@@ -1067,7 +1172,7 @@ Autogenerated return type of AwardEmojiRemove
"""
type AwardEmojiRemovePayload {
"""
- The award emoji after mutation
+ The award emoji after mutation.
"""
awardEmoji: AwardEmoji
@@ -1087,7 +1192,7 @@ Autogenerated input type of AwardEmojiToggle
"""
input AwardEmojiToggleInput {
"""
- The global ID of the awardable resource
+ The global ID of the awardable resource.
"""
awardableId: AwardableID!
@@ -1107,7 +1212,7 @@ Autogenerated return type of AwardEmojiToggle
"""
type AwardEmojiTogglePayload {
"""
- The award emoji after mutation
+ The award emoji after mutation.
"""
awardEmoji: AwardEmoji
@@ -1275,7 +1380,7 @@ type Board {
first: Int
"""
- Filters applied when selecting issues on the board
+ Filters applied when selecting issues on the board.
"""
issueFilters: BoardIssueInput
@@ -1350,12 +1455,12 @@ type Board {
first: Int
"""
- Find a list by its global ID
+ Find a list by its global ID.
"""
id: ListID
"""
- Filters applied when getting issue metadata in the board list
+ Filters applied when getting issue metadata in the board list.
"""
issueFilters: BoardIssueInput
@@ -1376,6 +1481,16 @@ type Board {
name: String
"""
+ Web path of the board.
+ """
+ webPath: String!
+
+ """
+ Web URL of the board.
+ """
+ webUrl: String!
+
+ """
Weight of the board
"""
weight: Int
@@ -1435,7 +1550,7 @@ type BoardEpic implements CurrentUserTodos & Noteable {
after: String
"""
- Filter epics by author
+ Filter epics by author.
"""
authorUsername: String
@@ -1445,6 +1560,11 @@ type BoardEpic implements CurrentUserTodos & Noteable {
before: String
"""
+ Filter epics by given confidentiality.
+ """
+ confidential: Boolean
+
+ """
List items overlapping a time frame defined by startDate..endDate (if one
date is provided, both must be present) Deprecated in 13.5: Use timeframe.end.
"""
@@ -1456,27 +1576,27 @@ type BoardEpic implements CurrentUserTodos & Noteable {
first: Int
"""
- IID of the epic, e.g., "1"
+ IID of the epic, e.g., "1".
"""
iid: ID
"""
- Filter epics by IID for autocomplete
+ Filter epics by IID for autocomplete.
"""
iidStartsWith: String
"""
- List of IIDs of epics, e.g., [1, 2]
+ List of IIDs of epics, e.g., [1, 2].
"""
iids: [ID!]
"""
- Include epics from descendant groups
+ Include epics from descendant groups.
"""
includeDescendantGroups: Boolean = true
"""
- Filter epics by labels
+ Filter epics by labels.
"""
labelName: [String!]
@@ -1486,17 +1606,17 @@ type BoardEpic implements CurrentUserTodos & Noteable {
last: Int
"""
- Filter epics by milestone title, computed from epic's issues
+ Filter epics by milestone title, computed from epic's issues.
"""
milestoneTitle: String
"""
- Search query for epic title or description
+ Search query for epic title or description.
"""
search: String
"""
- List epics by sort order
+ List epics by sort order.
"""
sort: EpicSort
@@ -1508,12 +1628,12 @@ type BoardEpic implements CurrentUserTodos & Noteable {
startDate: Time
"""
- Filter epics by state
+ Filter epics by state.
"""
state: EpicState
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
): EpicConnection
@@ -2015,7 +2135,7 @@ type BoardList {
before: String
"""
- Filters applied when selecting issues in the board list
+ Filters applied when selecting issues in the board list.
"""
filters: BoardIssueInput
@@ -2036,6 +2156,11 @@ type BoardList {
issuesCount: Int
"""
+ Iteration of the list
+ """
+ iteration: Iteration
+
+ """
Label of the list
"""
label: Label
@@ -2106,17 +2231,17 @@ Autogenerated input type of BoardListCreate
"""
input BoardListCreateInput {
"""
- Global ID of an existing user
+ Global ID of an existing user.
"""
assigneeId: UserID
"""
- Create the backlog list
+ Create the backlog list.
"""
backlog: Boolean
"""
- Global ID of the issue board to mutate
+ Global ID of the issue board to mutate.
"""
boardId: BoardID!
@@ -2126,17 +2251,17 @@ input BoardListCreateInput {
clientMutationId: String
"""
- Global ID of an existing iteration
+ Global ID of an existing iteration.
"""
iterationId: IterationID
"""
- Global ID of an existing label
+ Global ID of an existing label.
"""
labelId: LabelID
"""
- Global ID of an existing milestone
+ Global ID of an existing milestone.
"""
milestoneId: MilestoneID
}
@@ -2156,7 +2281,7 @@ type BoardListCreatePayload {
errors: [String!]!
"""
- List of the issue board
+ List of the issue board.
"""
list: BoardList
}
@@ -2221,7 +2346,7 @@ type BoardListUpdateLimitMetricsPayload {
errors: [String!]!
"""
- The updated list
+ The updated list.
"""
list: BoardList
}
@@ -2231,6 +2356,11 @@ Identifier of Boards::EpicBoard
"""
scalar BoardsEpicBoardID
+"""
+Identifier of Boards::EpicList
+"""
+scalar BoardsEpicListID
+
type Branch {
"""
Commit for the branch
@@ -2273,6 +2403,83 @@ type BurnupChartDailyTotals {
scopeWeight: Int!
}
+type CiBuildNeed {
+ """
+ Name of the job we need to complete.
+ """
+ name: String
+}
+
+"""
+The connection type for CiBuildNeed.
+"""
+type CiBuildNeedConnection {
+ """
+ A list of edges.
+ """
+ edges: [CiBuildNeedEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CiBuildNeed]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CiBuildNeedEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CiBuildNeed
+}
+
+"""
+Autogenerated input type of CiCdSettingsUpdate
+"""
+input CiCdSettingsUpdateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Full Path of the project the settings belong to.
+ """
+ fullPath: ID!
+
+ """
+ Indicates if the latest artifact should be kept for this project.
+ """
+ keepLatestArtifact: Boolean
+}
+
+"""
+Autogenerated return type of CiCdSettingsUpdate
+"""
+type CiCdSettingsUpdatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
type CiConfig {
"""
Linting errors
@@ -2287,7 +2494,27 @@ type CiConfig {
"""
Stages of the pipeline
"""
- stages: [CiConfigStage!]
+ stages(
+ """
+ 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
+ ): CiConfigStageConnection
"""
Status of linting, can be either valid or invalid
@@ -2299,7 +2526,27 @@ type CiConfigGroup {
"""
Jobs in group
"""
- jobs: [CiConfigJob!]
+ jobs(
+ """
+ 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
+ ): CiConfigJobConnection
"""
Name of the job group
@@ -2312,26 +2559,168 @@ type CiConfigGroup {
size: Int
}
+"""
+The connection type for CiConfigGroup.
+"""
+type CiConfigGroupConnection {
+ """
+ A list of edges.
+ """
+ edges: [CiConfigGroupEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CiConfigGroup]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CiConfigGroupEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CiConfigGroup
+}
+
type CiConfigJob {
"""
- Name of the job group
+ Override a set of commands that are executed after the job.
+ """
+ afterScript: [String!]
+
+ """
+ Allow job to fail.
+ """
+ allowFailure: Boolean
+
+ """
+ Override a set of commands that are executed before the job.
+ """
+ beforeScript: [String!]
+
+ """
+ Name of an environment to which the job deploys.
+ """
+ environment: String
+
+ """
+ Limit when jobs are not created.
+ """
+ except: CiConfigJobRestriction
+
+ """
+ Name of the job group.
"""
groupName: String
"""
- Name of the job
+ Name of the job.
"""
name: String
"""
- Builds that must complete before the jobs run
+ Builds that must complete before the jobs run.
+ """
+ needs(
+ """
+ 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
+ ): CiConfigNeedConnection
+
+ """
+ Jobs are created when these conditions do not apply.
"""
- needs: [CiConfigNeed!]
+ only: CiConfigJobRestriction
"""
- Name of the job stage
+ Shell script that is executed by a runner.
+ """
+ script: [String!]
+
+ """
+ Name of the job stage.
"""
stage: String
+
+ """
+ List of tags that are used to select a runner.
+ """
+ tags: [String!]
+
+ """
+ When to run the job.
+ """
+ when: String
+}
+
+"""
+The connection type for CiConfigJob.
+"""
+type CiConfigJobConnection {
+ """
+ A list of edges.
+ """
+ edges: [CiConfigJobEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CiConfigJob]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CiConfigJobEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CiConfigJob
+}
+
+type CiConfigJobRestriction {
+ """
+ The Git refs the job restriction applies to.
+ """
+ refs: [String!]
}
type CiConfigNeed {
@@ -2341,11 +2730,66 @@ type CiConfigNeed {
name: String
}
+"""
+The connection type for CiConfigNeed.
+"""
+type CiConfigNeedConnection {
+ """
+ A list of edges.
+ """
+ edges: [CiConfigNeedEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CiConfigNeed]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CiConfigNeedEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CiConfigNeed
+}
+
type CiConfigStage {
"""
Groups of jobs for the stage
"""
- groups: [CiConfigGroup!]
+ groups(
+ """
+ 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
+ ): CiConfigGroupConnection
"""
Name of the stage
@@ -2354,6 +2798,41 @@ type CiConfigStage {
}
"""
+The connection type for CiConfigStage.
+"""
+type CiConfigStageConnection {
+ """
+ A list of edges.
+ """
+ edges: [CiConfigStageEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CiConfigStage]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CiConfigStageEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CiConfigStage
+}
+
+"""
Values for YAML processor result
"""
enum CiConfigStatus {
@@ -2482,7 +2961,7 @@ type CiJob {
name: String
"""
- Builds that must complete before the jobs run
+ References to builds that must complete before the jobs run
"""
needs(
"""
@@ -2504,7 +2983,7 @@ type CiJob {
Returns the last _n_ elements from the list.
"""
last: Int
- ): CiJobConnection
+ ): CiBuildNeedConnection
"""
Pipeline the job belongs to
@@ -2763,7 +3242,7 @@ input ClusterAgentDeleteInput {
clientMutationId: String
"""
- Global ID of the cluster agent that will be deleted
+ Global ID of the cluster agent that will be deleted.
"""
id: ClustersAgentID!
}
@@ -2850,7 +3329,7 @@ input ClusterAgentTokenCreateInput {
clientMutationId: String
"""
- Global ID of the cluster agent that will be associated with the new token
+ Global ID of the cluster agent that will be associated with the new token.
"""
clusterAgentId: ClustersAgentID!
}
@@ -2870,12 +3349,12 @@ type ClusterAgentTokenCreatePayload {
errors: [String!]!
"""
- Token secret value. Make sure you save it - you won't be able to access it again
+ Token secret value. Make sure you save it - you won't be able to access it again.
"""
secret: String
"""
- Token created after mutation
+ Token created after mutation.
"""
token: ClusterAgentToken
}
@@ -2890,7 +3369,7 @@ input ClusterAgentTokenDeleteInput {
clientMutationId: String
"""
- Global ID of the cluster agent token that will be deleted
+ Global ID of the cluster agent token that will be deleted.
"""
id: ClustersAgentTokenID!
}
@@ -3086,17 +3565,17 @@ type Commit {
last: Int
"""
- Filter pipelines by the ref they are run for
+ Filter pipelines by the ref they are run for.
"""
ref: String
"""
- Filter pipelines by the sha of the commit they are run for
+ Filter pipelines by the sha of the commit they are run for.
"""
sha: String
"""
- Filter pipelines by their status
+ Filter pipelines by their status.
"""
status: PipelineStatusEnum
): PipelineConnection
@@ -3229,12 +3708,12 @@ Autogenerated input type of CommitCreate
"""
input CommitCreateInput {
"""
- Array of action hashes to commit as a batch
+ Array of action hashes to commit as a batch.
"""
actions: [CommitAction!]!
"""
- Name of the branch to commit into, it can be a new branch
+ Name of the branch to commit into, it can be a new branch.
"""
branch: String!
@@ -3249,12 +3728,12 @@ input CommitCreateInput {
message: String!
"""
- Project full path the branch is associated with
+ Project full path the branch is associated with.
"""
projectPath: ID!
"""
- If on a new branch, name of the original branch
+ If on a new branch, name of the original branch.
"""
startBranch: String
}
@@ -3269,7 +3748,7 @@ type CommitCreatePayload {
clientMutationId: String
"""
- The commit after mutation
+ The commit after mutation.
"""
commit: Commit
@@ -3366,6 +3845,23 @@ type ComplianceFrameworkEdge {
node: ComplianceFramework
}
+input ComplianceFrameworkInput {
+ """
+ New color representation of the compliance framework in hex format. e.g. #FCA121.
+ """
+ color: String
+
+ """
+ New description for the compliance framework.
+ """
+ description: String
+
+ """
+ New name for the compliance framework.
+ """
+ name: String
+}
+
"""
Identifier of ComplianceManagement::Framework
"""
@@ -3381,12 +3877,12 @@ input ConfigureSastInput {
clientMutationId: String
"""
- SAST CI configuration for the project
+ SAST CI configuration for the project.
"""
configuration: SastCiConfigurationInput!
"""
- Full path of the project
+ Full path of the project.
"""
projectPath: ID!
}
@@ -3406,12 +3902,12 @@ type ConfigureSastPayload {
errors: [String!]!
"""
- Status of creating the commit for the supplied SAST CI configuration
+ Status of creating the commit for the supplied SAST CI configuration.
"""
status: String!
"""
- Redirect path to use when the response is successful
+ Redirect path to use when the response is successful.
"""
successPath: String
}
@@ -3877,12 +4373,12 @@ input CreateAlertIssueInput {
clientMutationId: String
"""
- The IID of the alert to mutate
+ The IID of the alert to mutate.
"""
iid: String!
"""
- The project the alert to mutate is in
+ The project the alert to mutate is in.
"""
projectPath: ID!
}
@@ -3892,7 +4388,7 @@ Autogenerated return type of CreateAlertIssue
"""
type CreateAlertIssuePayload {
"""
- The alert after mutation
+ The alert after mutation.
"""
alert: AlertManagementAlert
@@ -3907,12 +4403,12 @@ type CreateAlertIssuePayload {
errors: [String!]!
"""
- The issue created after mutation
+ The issue created after mutation.
"""
issue: Issue
"""
- The todo after mutation
+ The todo after mutation.
"""
todo: Todo
}
@@ -3927,32 +4423,32 @@ input CreateAnnotationInput {
clientMutationId: String
"""
- The global ID of the cluster to add an annotation to
+ The global ID of the cluster to add an annotation to.
"""
clusterId: ClustersClusterID
"""
- The path to a file defining the dashboard on which the annotation should be added
+ The path to a file defining the dashboard on which the annotation should be added.
"""
dashboardPath: String!
"""
- The description of the annotation
+ The description of the annotation.
"""
description: String!
"""
- Timestamp indicating ending moment to which the annotation relates
+ Timestamp indicating ending moment to which the annotation relates.
"""
endingAt: Time
"""
- The global ID of the environment to add an annotation to
+ The global ID of the environment to add an annotation to.
"""
environmentId: EnvironmentID
"""
- Timestamp indicating starting moment to which the annotation relates
+ Timestamp indicating starting moment to which the annotation relates.
"""
startingAt: Time!
}
@@ -3962,7 +4458,7 @@ Autogenerated return type of CreateAnnotation
"""
type CreateAnnotationPayload {
"""
- The created annotation
+ The created annotation.
"""
annotation: MetricsDashboardAnnotation
@@ -3982,12 +4478,17 @@ Autogenerated input type of CreateBoard
"""
input CreateBoardInput {
"""
+ The ID of user to be assigned to the board.
+ """
+ assigneeId: UserID
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
- The group full path the resource is associated with
+ The group full path the resource is associated with.
"""
groupPath: ID
@@ -4002,14 +4503,39 @@ input CreateBoardInput {
hideClosedList: Boolean
"""
+ The ID of iteration to be assigned to the board.
+ """
+ iterationId: IterationID
+
+ """
+ The IDs of labels to be added to the board.
+ """
+ labelIds: [LabelID!]
+
+ """
+ Labels of the issue
+ """
+ labels: [String!]
+
+ """
+ The ID of milestone to be assigned to the board.
+ """
+ milestoneId: MilestoneID
+
+ """
The board name.
"""
name: String
"""
- The project full path the resource is associated with
+ The project full path the resource is associated with.
"""
projectPath: ID
+
+ """
+ The weight value to be assigned to the board.
+ """
+ weight: Int
}
"""
@@ -4042,17 +4568,17 @@ input CreateBranchInput {
clientMutationId: String
"""
- Name of the branch
+ Name of the branch.
"""
name: String!
"""
- Project full path the branch is associated with
+ Project full path the branch is associated with.
"""
projectPath: ID!
"""
- Branch name or commit SHA to create branch from
+ Branch name or commit SHA to create branch from.
"""
ref: String!
}
@@ -4062,7 +4588,7 @@ Autogenerated return type of CreateBranch
"""
type CreateBranchPayload {
"""
- Branch after mutation
+ Branch after mutation.
"""
branch: Branch
@@ -4087,12 +4613,12 @@ input CreateClusterAgentInput {
clientMutationId: String
"""
- Name of the cluster agent
+ Name of the cluster agent.
"""
name: String!
"""
- Full path of the associated project for this cluster agent
+ Full path of the associated project for this cluster agent.
"""
projectPath: ID!
}
@@ -4107,7 +4633,7 @@ type CreateClusterAgentPayload {
clientMutationId: String
"""
- Cluster agent created after mutation
+ Cluster agent created after mutation.
"""
clusterAgent: ClusterAgent
@@ -4127,24 +4653,14 @@ input CreateComplianceFrameworkInput {
clientMutationId: String
"""
- Color to represent the compliance framework as a hexadecimal value. e.g. #ABC123.
- """
- color: String!
-
- """
- Description of the compliance framework.
- """
- description: String!
-
- """
- Name of the compliance framework.
+ Full path of the namespace to add the compliance framework to.
"""
- name: String!
+ namespacePath: ID!
"""
- Full path of the namespace to add the compliance framework to.
+ Parameters to update the compliance framework with.
"""
- namespacePath: ID!
+ params: ComplianceFrameworkInput!
}
"""
@@ -4177,17 +4693,17 @@ input CreateCustomEmojiInput {
clientMutationId: String
"""
- Namespace full path the emoji is associated with
+ Namespace full path the emoji is associated with.
"""
groupPath: ID!
"""
- Name of the emoji
+ Name of the emoji.
"""
name: String!
"""
- Location of the emoji file
+ Location of the emoji file.
"""
url: String!
}
@@ -4202,7 +4718,7 @@ type CreateCustomEmojiPayload {
clientMutationId: String
"""
- The new custom emoji
+ The new custom emoji.
"""
customEmoji: CustomEmoji
@@ -4222,12 +4738,12 @@ input CreateDevopsAdoptionSegmentInput {
clientMutationId: String
"""
- The array of group IDs to set for the segment
+ The array of group IDs to set for the segment.
"""
groupIds: [GroupID!]
"""
- Name of the segment
+ Name of the segment.
"""
name: String!
}
@@ -4247,7 +4763,7 @@ type CreateDevopsAdoptionSegmentPayload {
errors: [String!]!
"""
- The segment after mutation
+ The segment after mutation.
"""
segment: DevopsAdoptionSegment
}
@@ -4272,7 +4788,7 @@ input CreateDiffNoteInput {
confidential: Boolean
"""
- The global ID of the resource to add a note to
+ The global ID of the resource to add a note to.
"""
noteableId: NoteableID!
@@ -4297,7 +4813,7 @@ type CreateDiffNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -4317,27 +4833,27 @@ input CreateEpicInput {
clientMutationId: String
"""
- Indicates if the epic is confidential
+ Indicates if the epic is confidential.
"""
confidential: Boolean
"""
- The description of the epic
+ The description of the epic.
"""
description: String
"""
- The end date of the epic
+ The end date of the epic.
"""
dueDateFixed: String
"""
- Indicates end date should be sourced from due_date_fixed field not the issue milestones
+ Indicates end date should be sourced from due_date_fixed field not the issue milestones.
"""
dueDateIsFixed: Boolean
"""
- The group the epic to mutate is in
+ The group the epic to mutate is in.
"""
groupPath: ID!
@@ -4347,17 +4863,17 @@ input CreateEpicInput {
removeLabelIds: [ID!]
"""
- The start date of the epic
+ The start date of the epic.
"""
startDateFixed: String
"""
- Indicates start date should be sourced from start_date_fixed field not the issue milestones
+ Indicates start date should be sourced from start_date_fixed field not the issue milestones.
"""
startDateIsFixed: Boolean
"""
- The title of the epic
+ The title of the epic.
"""
title: String
}
@@ -4372,7 +4888,7 @@ type CreateEpicPayload {
clientMutationId: String
"""
- The created epic
+ The created epic.
"""
epic: Epic
@@ -4402,7 +4918,7 @@ input CreateImageDiffNoteInput {
confidential: Boolean
"""
- The global ID of the resource to add a note to
+ The global ID of the resource to add a note to.
"""
noteableId: NoteableID!
@@ -4427,7 +4943,7 @@ type CreateImageDiffNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -4437,7 +4953,7 @@ Autogenerated input type of CreateIssue
"""
input CreateIssueInput {
"""
- The array of user IDs to assign to the issue
+ The array of user IDs to assign to the issue.
"""
assigneeIds: [UserID!]
@@ -4452,7 +4968,7 @@ input CreateIssueInput {
confidential: Boolean
"""
- Timestamp when the issue was created. Available only for admins and project owners
+ Timestamp when the issue was created. Available only for admins and project owners.
"""
createdAt: Time
@@ -4462,7 +4978,7 @@ input CreateIssueInput {
description: String
"""
- The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`
+ The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`.
"""
discussionToResolve: String
@@ -4472,22 +4988,22 @@ input CreateIssueInput {
dueDate: ISO8601Date
"""
- The ID of an epic to associate the issue with
+ The ID of an epic to associate the issue with.
"""
epicId: EpicID
"""
- The desired health status
+ The desired health status.
"""
healthStatus: HealthStatus
"""
- The IID (internal ID) of a project issue. Only admins and project owners can modify
+ The IID (internal ID) of a project issue. Only admins and project owners can modify.
"""
iid: Int
"""
- The IDs of labels to be added to the issue
+ The IDs of labels to be added to the issue.
"""
labelIds: [LabelID!]
@@ -4502,17 +5018,17 @@ input CreateIssueInput {
locked: Boolean
"""
- The IID of a merge request for which to resolve discussions
+ The IID of a merge request for which to resolve discussions.
"""
mergeRequestToResolveDiscussionsOf: MergeRequestID
"""
- The ID of the milestone to assign to the issue. On update milestone will be removed if set to null
+ The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.
"""
milestoneId: MilestoneID
"""
- Project full path the issue is associated with
+ Project full path the issue is associated with.
"""
projectPath: ID!
@@ -4522,7 +5038,7 @@ input CreateIssueInput {
title: String!
"""
- The weight of the issue
+ The weight of the issue.
"""
weight: Int
}
@@ -4542,7 +5058,7 @@ type CreateIssuePayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -4557,32 +5073,32 @@ input CreateIterationInput {
clientMutationId: String
"""
- The description of the iteration
+ The description of the iteration.
"""
description: String
"""
- The end date of the iteration
+ The end date of the iteration.
"""
dueDate: String
"""
- The target group for the iteration
+ The target group for the iteration.
"""
groupPath: ID
"""
- The target project for the iteration
+ The target project for the iteration.
"""
projectPath: ID
"""
- The start date of the iteration
+ The start date of the iteration.
"""
startDate: String
"""
- The title of the iteration
+ The title of the iteration.
"""
title: String
}
@@ -4602,7 +5118,7 @@ type CreateIterationPayload {
errors: [String!]!
"""
- The created iteration
+ The created iteration.
"""
iteration: Iteration
}
@@ -4627,12 +5143,12 @@ input CreateNoteInput {
confidential: Boolean
"""
- The global ID of the discussion this note is in reply to
+ The global ID of the discussion this note is in reply to.
"""
discussionId: DiscussionID
"""
- The global ID of the resource to add a note to
+ The global ID of the resource to add a note to.
"""
noteableId: NoteableID!
}
@@ -4652,7 +5168,7 @@ type CreateNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -4667,17 +5183,17 @@ input CreateRequirementInput {
clientMutationId: String
"""
- Description of the requirement
+ Description of the requirement.
"""
description: String
"""
- Full project path the requirement is associated with
+ Full project path the requirement is associated with.
"""
projectPath: ID!
"""
- Title of the requirement
+ Title of the requirement.
"""
title: String
}
@@ -4697,7 +5213,7 @@ type CreateRequirementPayload {
errors: [String!]!
"""
- Requirement after mutation
+ Requirement after mutation.
"""
requirement: Requirement
}
@@ -4707,7 +5223,7 @@ Autogenerated input type of CreateSnippet
"""
input CreateSnippetInput {
"""
- Actions to perform over the snippet repository and blobs
+ Actions to perform over the snippet repository and blobs.
"""
blobActions: [SnippetBlobActionInputType!]
@@ -4717,27 +5233,27 @@ input CreateSnippetInput {
clientMutationId: String
"""
- Description of the snippet
+ Description of the snippet.
"""
description: String
"""
- The project full path the snippet is associated with
+ The project full path the snippet is associated with.
"""
projectPath: ID
"""
- Title of the snippet
+ Title of the snippet.
"""
title: String!
"""
- The paths to files uploaded in the snippet description
+ The paths to files uploaded in the snippet description.
"""
uploadedFiles: [String!]
"""
- The visibility level of the snippet
+ The visibility level of the snippet.
"""
visibilityLevel: VisibilityLevelsEnum!
}
@@ -4757,12 +5273,12 @@ type CreateSnippetPayload {
errors: [String!]!
"""
- The snippet after mutation
+ The snippet after mutation.
"""
snippet: Snippet
"""
- Indicates whether the operation returns a record detected as spam
+ Indicates whether the operation returns a record detected as spam.
"""
spam: Boolean
}
@@ -4777,7 +5293,7 @@ input CreateTestCaseInput {
clientMutationId: String
"""
- The test case description
+ The test case description.
"""
description: String
@@ -4787,12 +5303,12 @@ input CreateTestCaseInput {
labelIds: [ID!]
"""
- The project full path to create the test case
+ The project full path to create the test case.
"""
projectPath: ID!
"""
- The test case title
+ The test case title.
"""
title: String!
}
@@ -4812,7 +5328,7 @@ type CreateTestCasePayload {
errors: [String!]!
"""
- The test case created
+ The test case created.
"""
testCase: Issue
}
@@ -5672,6 +6188,96 @@ enum DastSiteValidationStrategyEnum {
}
"""
+Color of the data visualization palette
+"""
+enum DataVisualizationColorEnum {
+ """
+ Aqua color
+ """
+ AQUA
+
+ """
+ Blue color
+ """
+ BLUE
+
+ """
+ Green color
+ """
+ GREEN
+
+ """
+ Magenta color
+ """
+ MAGENTA
+
+ """
+ Orange color
+ """
+ ORANGE
+}
+
+"""
+Weight of the data visualization palette
+"""
+enum DataVisualizationWeightEnum {
+ """
+ 100 weight
+ """
+ WEIGHT_100
+
+ """
+ 200 weight
+ """
+ WEIGHT_200
+
+ """
+ 300 weight
+ """
+ WEIGHT_300
+
+ """
+ 400 weight
+ """
+ WEIGHT_400
+
+ """
+ 50 weight
+ """
+ WEIGHT_50
+
+ """
+ 500 weight
+ """
+ WEIGHT_500
+
+ """
+ 600 weight
+ """
+ WEIGHT_600
+
+ """
+ 700 weight
+ """
+ WEIGHT_700
+
+ """
+ 800 weight
+ """
+ WEIGHT_800
+
+ """
+ 900 weight
+ """
+ WEIGHT_900
+
+ """
+ 950 weight
+ """
+ WEIGHT_950
+}
+
+"""
Date represented in ISO 8601
"""
scalar Date
@@ -5686,7 +6292,7 @@ input DeleteAnnotationInput {
clientMutationId: String
"""
- Global ID of the annotation to delete
+ Global ID of the annotation to delete.
"""
id: MetricsDashboardAnnotationID!
}
@@ -5716,7 +6322,7 @@ input DeleteDevopsAdoptionSegmentInput {
clientMutationId: String
"""
- ID of the segment
+ ID of the segment.
"""
id: AnalyticsDevopsAdoptionSegmentID!
}
@@ -5905,12 +6511,12 @@ type Design implements CurrentUserTodos & DesignFields & Noteable {
before: String
"""
- The Global ID of the most recent acceptable version
+ The Global ID of the most recent acceptable version.
"""
earlierOrEqualToId: DesignManagementVersionID
"""
- The SHA256 of the most recent acceptable version
+ The SHA256 of the most recent acceptable version.
"""
earlierOrEqualToSha: String
@@ -6040,12 +6646,12 @@ type DesignCollection {
"""
design(
"""
- Find a design by its filename
+ Find a design by its filename.
"""
filename: String
"""
- Find a design by its ID
+ Find a design by its ID.
"""
id: DesignManagementDesignID
): Design
@@ -6055,7 +6661,7 @@ type DesignCollection {
"""
designAtVersion(
"""
- The Global ID of the design at this version
+ The Global ID of the design at this version.
"""
id: DesignManagementDesignAtVersionID!
): DesignAtVersion
@@ -6081,7 +6687,7 @@ type DesignCollection {
before: String
"""
- Filters designs by their filename
+ Filters designs by their filename.
"""
filenames: [String!]
@@ -6091,7 +6697,7 @@ type DesignCollection {
first: Int
"""
- Filters designs by their ID
+ Filters designs by their ID.
"""
ids: [DesignManagementDesignID!]
@@ -6116,12 +6722,12 @@ type DesignCollection {
"""
version(
"""
- The Global ID of the version
+ The Global ID of the version.
"""
id: DesignManagementVersionID
"""
- The SHA256 of a specific version
+ The SHA256 of a specific version.
"""
sha: String
): DesignVersion
@@ -6141,12 +6747,12 @@ type DesignCollection {
before: String
"""
- The Global ID of the most recent acceptable version
+ The Global ID of the most recent acceptable version.
"""
earlierOrEqualToId: DesignManagementVersionID
"""
- The SHA256 of the most recent acceptable version
+ The SHA256 of the most recent acceptable version.
"""
earlierOrEqualToSha: String
@@ -6275,7 +6881,7 @@ type DesignManagement {
"""
designAtVersion(
"""
- The Global ID of the design at this version
+ The Global ID of the design at this version.
"""
id: DesignManagementDesignAtVersionID!
): DesignAtVersion
@@ -6285,7 +6891,7 @@ type DesignManagement {
"""
version(
"""
- The Global ID of the version
+ The Global ID of the version.
"""
id: DesignManagementVersionID!
): DesignVersion
@@ -6301,17 +6907,17 @@ input DesignManagementDeleteInput {
clientMutationId: String
"""
- The filenames of the designs to delete
+ The filenames of the designs to delete.
"""
filenames: [String!]!
"""
- The IID of the issue to modify designs for
+ The IID of the issue to modify designs for.
"""
iid: ID!
"""
- The project where the issue is to upload designs for
+ The project where the issue is to upload designs for.
"""
projectPath: ID!
}
@@ -6331,7 +6937,7 @@ type DesignManagementDeletePayload {
errors: [String!]!
"""
- The new version in which the designs are deleted
+ The new version in which the designs are deleted.
"""
version: DesignVersion
}
@@ -6356,17 +6962,17 @@ input DesignManagementMoveInput {
clientMutationId: String
"""
- ID of the design to move
+ ID of the design to move.
"""
id: DesignManagementDesignID!
"""
- ID of the immediately following design
+ ID of the immediately following design.
"""
next: DesignManagementDesignID
"""
- ID of the immediately preceding design
+ ID of the immediately preceding design.
"""
previous: DesignManagementDesignID
}
@@ -6381,7 +6987,7 @@ type DesignManagementMovePayload {
clientMutationId: String
"""
- The current state of the collection
+ The current state of the collection.
"""
designCollection: DesignCollection
@@ -6401,17 +7007,17 @@ input DesignManagementUploadInput {
clientMutationId: String
"""
- The files to upload
+ The files to upload.
"""
files: [Upload!]!
"""
- The IID of the issue to modify designs for
+ The IID of the issue to modify designs for.
"""
iid: ID!
"""
- The project where the issue is to upload designs for
+ The project where the issue is to upload designs for.
"""
projectPath: ID!
}
@@ -6426,7 +7032,7 @@ type DesignManagementUploadPayload {
clientMutationId: String
"""
- The designs that were uploaded by the mutation
+ The designs that were uploaded by the mutation.
"""
designs: [Design!]!
@@ -6455,17 +7061,17 @@ type DesignVersion {
"""
designAtVersion(
"""
- The ID of a specific design
+ The ID of a specific design.
"""
designId: DesignManagementDesignID
"""
- The filename of a specific design
+ The filename of a specific design.
"""
filename: String
"""
- The ID of the DesignAtVersion
+ The ID of the DesignAtVersion.
"""
id: DesignManagementDesignAtVersionID
): DesignAtVersion!
@@ -6510,7 +7116,7 @@ type DesignVersion {
before: String
"""
- Filters designs by their filename
+ Filters designs by their filename.
"""
filenames: [String!]
@@ -6520,7 +7126,7 @@ type DesignVersion {
first: Int
"""
- Filters designs by their ID
+ Filters designs by their ID.
"""
ids: [DesignManagementDesignID!]
@@ -6611,7 +7217,7 @@ input DestroyBoardInput {
clientMutationId: String
"""
- The global ID of the board to destroy
+ The global ID of the board to destroy.
"""
id: BoardID!
}
@@ -6656,7 +7262,7 @@ Autogenerated return type of DestroyBoard
"""
type DestroyBoardPayload {
"""
- The board after mutation
+ The board after mutation.
"""
board: Board
@@ -6681,7 +7287,7 @@ input DestroyComplianceFrameworkInput {
clientMutationId: String
"""
- The global ID of the compliance framework to destroy
+ The global ID of the compliance framework to destroy.
"""
id: ComplianceManagementFrameworkID!
}
@@ -6766,7 +7372,7 @@ type DestroyContainerRepositoryTagsPayload {
clientMutationId: String
"""
- Deleted container repository tags
+ Deleted container repository tags.
"""
deletedTagNames: [String!]!
@@ -6786,7 +7392,7 @@ input DestroyNoteInput {
clientMutationId: String
"""
- The global ID of the note to destroy
+ The global ID of the note to destroy.
"""
id: NoteID!
}
@@ -6806,7 +7412,7 @@ type DestroyNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -6821,7 +7427,7 @@ input DestroySnippetInput {
clientMutationId: String
"""
- The global ID of the snippet to destroy
+ The global ID of the snippet to destroy.
"""
id: SnippetID!
}
@@ -6841,7 +7447,7 @@ type DestroySnippetPayload {
errors: [String!]!
"""
- The snippet after mutation
+ The snippet after mutation.
"""
snippet: Snippet
}
@@ -7340,12 +7946,12 @@ input DiscussionToggleResolveInput {
clientMutationId: String
"""
- The global ID of the discussion
+ The global ID of the discussion.
"""
id: DiscussionID!
"""
- Will resolve the discussion when true, and unresolve the discussion when false
+ Will resolve the discussion when true, and unresolve the discussion when false.
"""
resolve: Boolean!
}
@@ -7360,7 +7966,7 @@ type DiscussionToggleResolvePayload {
clientMutationId: String
"""
- The discussion after mutation
+ The discussion after mutation.
"""
discussion: Discussion
@@ -7380,12 +7986,17 @@ input DismissVulnerabilityInput {
clientMutationId: String
"""
- Reason why vulnerability should be dismissed
+ Comment why vulnerability should be dismissed.
"""
comment: String
"""
- ID of the vulnerability to be dismissed
+ Reason why vulnerability should be dismissed.
+ """
+ dismissalReason: VulnerabilityDismissalReason
+
+ """
+ ID of the vulnerability to be dismissed.
"""
id: VulnerabilityID!
}
@@ -7405,7 +8016,7 @@ type DismissVulnerabilityPayload {
errors: [String!]!
"""
- The vulnerability after dismissal
+ The vulnerability after dismissal.
"""
vulnerability: Vulnerability
}
@@ -7470,7 +8081,7 @@ type Environment {
"""
metricsDashboard(
"""
- Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'
+ Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'.
"""
path: String!
): MetricsDashboard
@@ -7541,12 +8152,12 @@ input EnvironmentsCanaryIngressUpdateInput {
clientMutationId: String
"""
- The global ID of the environment to update
+ The global ID of the environment to update.
"""
id: EnvironmentID!
"""
- The weight of the Canary Ingress
+ The weight of the Canary Ingress.
"""
weight: Int!
}
@@ -7585,7 +8196,7 @@ type Epic implements CurrentUserTodos & Noteable {
after: String
"""
- Filter epics by author
+ Filter epics by author.
"""
authorUsername: String
@@ -7595,6 +8206,11 @@ type Epic implements CurrentUserTodos & Noteable {
before: String
"""
+ Filter epics by given confidentiality.
+ """
+ confidential: Boolean
+
+ """
List items overlapping a time frame defined by startDate..endDate (if one
date is provided, both must be present) Deprecated in 13.5: Use timeframe.end.
"""
@@ -7606,27 +8222,27 @@ type Epic implements CurrentUserTodos & Noteable {
first: Int
"""
- IID of the epic, e.g., "1"
+ IID of the epic, e.g., "1".
"""
iid: ID
"""
- Filter epics by IID for autocomplete
+ Filter epics by IID for autocomplete.
"""
iidStartsWith: String
"""
- List of IIDs of epics, e.g., [1, 2]
+ List of IIDs of epics, e.g., [1, 2].
"""
iids: [ID!]
"""
- Include epics from descendant groups
+ Include epics from descendant groups.
"""
includeDescendantGroups: Boolean = true
"""
- Filter epics by labels
+ Filter epics by labels.
"""
labelName: [String!]
@@ -7636,17 +8252,17 @@ type Epic implements CurrentUserTodos & Noteable {
last: Int
"""
- Filter epics by milestone title, computed from epic's issues
+ Filter epics by milestone title, computed from epic's issues.
"""
milestoneTitle: String
"""
- Search query for epic title or description
+ Search query for epic title or description.
"""
search: String
"""
- List epics by sort order
+ List epics by sort order.
"""
sort: EpicSort
@@ -7658,12 +8274,12 @@ type Epic implements CurrentUserTodos & Noteable {
startDate: Time
"""
- Filter epics by state
+ Filter epics by state.
"""
state: EpicState
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
): EpicConnection
@@ -8019,22 +8635,22 @@ input EpicAddIssueInput {
clientMutationId: String
"""
- The group the epic to mutate belongs to
+ The group the epic to mutate belongs to.
"""
groupPath: ID!
"""
- The IID of the epic to mutate
+ The IID of the epic to mutate.
"""
iid: ID!
"""
- The IID of the issue to be added
+ The IID of the issue to be added.
"""
issueIid: String!
"""
- The full path of the project the issue belongs to
+ The full path of the project the issue belongs to.
"""
projectPath: ID!
}
@@ -8049,12 +8665,12 @@ type EpicAddIssuePayload {
clientMutationId: String
"""
- The epic after mutation
+ The epic after mutation.
"""
epic: Epic
"""
- The epic-issue relation
+ The epic-issue relation.
"""
epicIssue: EpicIssue
@@ -8069,12 +8685,42 @@ Represents an epic board
"""
type EpicBoard {
"""
- Global ID of the board
+ Global ID of the board.
"""
id: BoardsEpicBoardID!
"""
- Name of the board
+ Epic board lists.
+ """
+ lists(
+ """
+ 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
+
+ """
+ Find an epic board list by ID.
+ """
+ id: BoardsEpicListID
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EpicListConnection
+
+ """
+ Name of the board.
"""
name: String
}
@@ -8274,6 +8920,11 @@ type EpicIssue implements CurrentUserTodos & Noteable {
confidential: Boolean!
"""
+ User specific email address for the issue
+ """
+ createNoteEmail: String
+
+ """
Timestamp of when the issue was created
"""
createdAt: Time!
@@ -8670,6 +9321,96 @@ type EpicIssueEdge {
}
"""
+Represents an epic board list
+"""
+type EpicList {
+ """
+ List epics.
+ """
+ epics(
+ """
+ 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
+ ): EpicConnection
+
+ """
+ Global ID of the board list.
+ """
+ id: BoardsEpicListID!
+
+ """
+ Label of the list.
+ """
+ label: Label
+
+ """
+ Type of the list.
+ """
+ listType: String!
+
+ """
+ Position of the list within the board.
+ """
+ position: Int
+
+ """
+ Title of the list.
+ """
+ title: String!
+}
+
+"""
+The connection type for EpicList.
+"""
+type EpicListConnection {
+ """
+ A list of edges.
+ """
+ edges: [EpicListEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [EpicList]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type EpicListEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: EpicList
+}
+
+"""
Check permissions for the current user on an epic
"""
type EpicPermissions {
@@ -8724,17 +9465,17 @@ input EpicSetSubscriptionInput {
clientMutationId: String
"""
- The group the epic to mutate belongs to
+ The group the epic to mutate belongs to.
"""
groupPath: ID!
"""
- The IID of the epic to mutate
+ The IID of the epic to mutate.
"""
iid: ID!
"""
- The desired state of the subscription
+ The desired state of the subscription.
"""
subscribedState: Boolean!
}
@@ -8749,7 +9490,7 @@ type EpicSetSubscriptionPayload {
clientMutationId: String
"""
- The epic after mutation
+ The epic after mutation.
"""
epic: Epic
@@ -8838,7 +9579,7 @@ Autogenerated input type of EpicTreeReorder
"""
input EpicTreeReorderInput {
"""
- The ID of the base epic of the tree
+ The ID of the base epic of the tree.
"""
baseEpicId: EpicID!
@@ -8848,7 +9589,7 @@ input EpicTreeReorderInput {
clientMutationId: String
"""
- Parameters for updating the tree positions
+ Parameters for updating the tree positions.
"""
moved: EpicTreeNodeFieldsInputType!
}
@@ -8889,6 +9630,56 @@ enum EpicWildcardId {
}
"""
+Autogenerated input type of ExportRequirements
+"""
+input ExportRequirementsInput {
+ """
+ Filter requirements by author username.
+ """
+ authorUsername: [String!]
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Full project path the requirements are associated with.
+ """
+ projectPath: ID!
+
+ """
+ Search query for requirement title.
+ """
+ search: String
+
+ """
+ List requirements by sort order.
+ """
+ sort: Sort
+
+ """
+ Filter requirements by state.
+ """
+ state: RequirementState
+}
+
+"""
+Autogenerated return type of ExportRequirements
+"""
+type ExportRequirementsPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
Represents an external issue
"""
type ExternalIssue {
@@ -8974,7 +9765,7 @@ type GeoNode {
first: Int
"""
- Filters registries by their ID
+ Filters registries by their ID.
"""
ids: [ID!]
@@ -9014,7 +9805,7 @@ type GeoNode {
first: Int
"""
- Filters registries by their ID
+ Filters registries by their ID.
"""
ids: [ID!]
@@ -9089,7 +9880,7 @@ type GeoNode {
first: Int
"""
- Filters registries by their ID
+ Filters registries by their ID.
"""
ids: [ID!]
@@ -9124,7 +9915,7 @@ type GeoNode {
first: Int
"""
- Filters registries by their ID
+ Filters registries by their ID.
"""
ids: [ID!]
@@ -9203,7 +9994,7 @@ type Group {
"""
board(
"""
- The board's ID
+ The board's ID.
"""
id: BoardID!
): Board
@@ -9228,7 +10019,7 @@ type Group {
first: Int
"""
- Find a board by its ID
+ Find a board by its ID.
"""
id: BoardID
@@ -9263,13 +10054,13 @@ type Group {
last: Int
"""
- First day for which to fetch code coverage activity (maximum time window is set to 90 days)
+ First day for which to fetch code coverage activity (maximum time window is set to 90 days).
"""
startDate: Date!
): CodeCoverageActivityConnection
"""
- Compliance frameworks available to projects in this namespace Available only
+ Compliance frameworks available to projects in this namespace. Available only
when feature flag `ff_custom_compliance_frameworks` is enabled.
"""
complianceFrameworks(
@@ -9289,6 +10080,11 @@ type Group {
first: Int
"""
+ Global ID of a specific compliance framework to return.
+ """
+ id: ComplianceManagementFrameworkID
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
@@ -9319,7 +10115,7 @@ type Group {
last: Int
"""
- Filter the container repositories by their name
+ Filter the container repositories by their name.
"""
name: String
): ContainerRepositoryConnection
@@ -9379,53 +10175,58 @@ type Group {
"""
epic(
"""
- Filter epics by author
+ Filter epics by author.
"""
authorUsername: String
"""
+ Filter epics by given confidentiality.
+ """
+ confidential: Boolean
+
+ """
List items overlapping a time frame defined by startDate..endDate (if one
date is provided, both must be present) Deprecated in 13.5: Use timeframe.end.
"""
endDate: Time
"""
- IID of the epic, e.g., "1"
+ IID of the epic, e.g., "1".
"""
iid: ID
"""
- Filter epics by IID for autocomplete
+ Filter epics by IID for autocomplete.
"""
iidStartsWith: String
"""
- List of IIDs of epics, e.g., [1, 2]
+ List of IIDs of epics, e.g., [1, 2].
"""
iids: [ID!]
"""
- Include epics from descendant groups
+ Include epics from descendant groups.
"""
includeDescendantGroups: Boolean = true
"""
- Filter epics by labels
+ Filter epics by labels.
"""
labelName: [String!]
"""
- Filter epics by milestone title, computed from epic's issues
+ Filter epics by milestone title, computed from epic's issues.
"""
milestoneTitle: String
"""
- Search query for epic title or description
+ Search query for epic title or description.
"""
search: String
"""
- List epics by sort order
+ List epics by sort order.
"""
sort: EpicSort
@@ -9437,12 +10238,12 @@ type Group {
startDate: Time
"""
- Filter epics by state
+ Filter epics by state.
"""
state: EpicState
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
): Epic
@@ -9452,7 +10253,7 @@ type Group {
"""
epicBoard(
"""
- Find an epic board by ID
+ Find an epic board by ID.
"""
id: BoardsEpicBoardID!
): EpicBoard
@@ -9492,7 +10293,7 @@ type Group {
after: String
"""
- Filter epics by author
+ Filter epics by author.
"""
authorUsername: String
@@ -9502,6 +10303,11 @@ type Group {
before: String
"""
+ Filter epics by given confidentiality.
+ """
+ confidential: Boolean
+
+ """
List items overlapping a time frame defined by startDate..endDate (if one
date is provided, both must be present) Deprecated in 13.5: Use timeframe.end.
"""
@@ -9513,27 +10319,27 @@ type Group {
first: Int
"""
- IID of the epic, e.g., "1"
+ IID of the epic, e.g., "1".
"""
iid: ID
"""
- Filter epics by IID for autocomplete
+ Filter epics by IID for autocomplete.
"""
iidStartsWith: String
"""
- List of IIDs of epics, e.g., [1, 2]
+ List of IIDs of epics, e.g., [1, 2].
"""
iids: [ID!]
"""
- Include epics from descendant groups
+ Include epics from descendant groups.
"""
includeDescendantGroups: Boolean = true
"""
- Filter epics by labels
+ Filter epics by labels.
"""
labelName: [String!]
@@ -9543,17 +10349,17 @@ type Group {
last: Int
"""
- Filter epics by milestone title, computed from epic's issues
+ Filter epics by milestone title, computed from epic's issues.
"""
milestoneTitle: String
"""
- Search query for epic title or description
+ Search query for epic title or description.
"""
search: String
"""
- List epics by sort order
+ List epics by sort order.
"""
sort: EpicSort
@@ -9565,12 +10371,12 @@ type Group {
startDate: Time
"""
- Filter epics by state
+ Filter epics by state.
"""
state: EpicState
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
): EpicConnection
@@ -9615,12 +10421,12 @@ type Group {
last: Int
"""
- Filter members by the given member relations
+ Filter members by the given member relations.
"""
relations: [GroupMemberRelation!] = [DIRECT, INHERITED]
"""
- Search query
+ Search query.
"""
search: String
): GroupMemberConnection
@@ -9650,22 +10456,22 @@ type Group {
after: String
"""
- ID of a user assigned to the issues, "none" and "any" values are supported
+ ID of a user assigned to the issues, "none" and "any" values are supported.
"""
assigneeId: String
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
"""
- Usernames of users assigned to the issue
+ Usernames of users assigned to the issue.
"""
assigneeUsernames: [String!]
"""
- Username of the author of the issue
+ Username of the author of the issue.
"""
authorUsername: String
@@ -9675,27 +10481,27 @@ type Group {
before: String
"""
- Issues closed after this date
+ Issues closed after this date.
"""
closedAfter: Time
"""
- Issues closed before this date
+ Issues closed before this date.
"""
closedBefore: Time
"""
- Issues created after this date
+ Issues created after this date.
"""
createdAfter: Time
"""
- Issues created before this date
+ Issues created before this date.
"""
createdBefore: Time
"""
- ID of an epic associated with the issues, "none" and "any" values are supported
+ ID of an epic associated with the issues, "none" and "any" values are supported.
"""
epicId: String
@@ -9705,12 +10511,12 @@ type Group {
first: Int
"""
- IID of the issue. For example, "1"
+ IID of the issue. For example, "1".
"""
iid: String
"""
- List of IIDs of issues. For example, [1, 2]
+ List of IIDs of issues. For example, [1, 2].
"""
iids: [String!]
@@ -9720,12 +10526,12 @@ type Group {
includeSubgroups: Boolean = false
"""
- Iterations applied to the issue
+ Iterations applied to the issue.
"""
iterationId: [ID]
"""
- Labels applied to this issue
+ Labels applied to this issue.
"""
labelName: [String]
@@ -9735,37 +10541,37 @@ type Group {
last: Int
"""
- Milestone applied to this issue
+ Milestone applied to this issue.
"""
milestoneTitle: [String]
"""
- Search query for issue title or description
+ Search query for issue title or description.
"""
search: String
"""
- Sort issues by this criteria
+ Sort issues by this criteria.
"""
sort: IssueSort = created_desc
"""
- Current state of this issue
+ Current state of this issue.
"""
state: IssuableState
"""
- Filter issues by the given issue types
+ Filter issues by the given issue types.
"""
types: [IssueType!]
"""
- Issues updated after this date
+ Issues updated after this date.
"""
updatedAfter: Time
"""
- Issues updated before this date
+ Issues updated before this date.
"""
updatedBefore: Time
): IssueConnection
@@ -9828,7 +10634,7 @@ type Group {
state: IterationState
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
@@ -9898,12 +10704,12 @@ type Group {
after: String
"""
- Username of the assignee
+ Username of the assignee.
"""
assigneeUsername: String
"""
- Username of the author
+ Username of the author.
"""
authorUsername: String
@@ -9918,7 +10724,7 @@ type Group {
first: Int
"""
- Array of IIDs of merge requests, for example `[1, 2]`
+ Array of IIDs of merge requests, for example `[1, 2]`.
"""
iids: [String!]
@@ -9938,22 +10744,22 @@ type Group {
last: Int
"""
- Merge requests merged after this date
+ Merge requests merged after this date.
"""
mergedAfter: Time
"""
- Merge requests merged before this date
+ Merge requests merged before this date.
"""
mergedBefore: Time
"""
- Title of the milestone
+ Title of the milestone.
"""
milestoneTitle: String
"""
- Sort merge requests by this criteria
+ Sort merge requests by this criteria.
"""
sort: MergeRequestSort = created_desc
@@ -9988,7 +10794,7 @@ type Group {
before: String
"""
- A date that the milestone contains
+ A date that the milestone contains.
"""
containingDate: Time
@@ -10004,12 +10810,12 @@ type Group {
first: Int
"""
- Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1"
+ Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1".
"""
ids: [ID!]
"""
- Also return milestones in all subgroups and subprojects
+ Also return milestones in all subgroups and subprojects.
"""
includeDescendants: Boolean
@@ -10019,7 +10825,7 @@ type Group {
last: Int
"""
- A search string for the title
+ A search string for the title.
"""
searchTitle: String
@@ -10031,17 +10837,17 @@ type Group {
startDate: Time
"""
- Filter milestones by state
+ Filter milestones by state.
"""
state: MilestoneStateEnum
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
"""
- The title of the milestone
+ The title of the milestone.
"""
title: String
): MilestoneConnection
@@ -10052,6 +10858,11 @@ type Group {
name: String!
"""
+ The package settings for the namespace
+ """
+ packageSettings: PackageSettings
+
+ """
Parent group
"""
parent: Group
@@ -10086,12 +10897,12 @@ type Group {
first: Int
"""
- Returns only the projects which have vulnerabilities
+ Returns only the projects which have vulnerabilities.
"""
hasVulnerabilities: Boolean = false
"""
- Include also subgroup projects
+ Include also subgroup projects.
"""
includeSubgroups: Boolean = false
@@ -10101,12 +10912,12 @@ type Group {
last: Int
"""
- Search project with most similar names or paths
+ Search project with most similar names or paths.
"""
search: String = null
"""
- Sort projects by this criteria
+ Sort projects by this criteria.
"""
sort: NamespaceProjectSort = null
): ProjectConnection!
@@ -10171,12 +10982,12 @@ type Group {
before: String
"""
- List time logs within a date range where the logged date is equal to or before endDate
+ List time logs within a date range where the logged date is equal to or before endDate.
"""
endDate: Time
"""
- List time-logs within a time range where the logged time is equal to or before endTime
+ List time-logs within a time range where the logged time is equal to or before endTime.
"""
endTime: Time
@@ -10191,12 +11002,12 @@ type Group {
last: Int
"""
- List time logs within a date range where the logged date is equal to or after startDate
+ List time logs within a date range where the logged date is equal to or after startDate.
"""
startDate: Time
"""
- List time-logs within a time range where the logged time is equal to or after startTime
+ List time-logs within a time range where the logged time is equal to or after startTime.
"""
startTime: Time
): TimelogConnection!
@@ -10246,12 +11057,12 @@ type Group {
first: Int
"""
- Returns only the vulnerabilities which have linked issues
+ Returns only the vulnerabilities which have linked issues.
"""
hasIssues: Boolean
"""
- Returns only the vulnerabilities which have been resolved on default branch
+ Returns only the vulnerabilities which have been resolved on default branch.
"""
hasResolution: Boolean
@@ -10261,32 +11072,32 @@ type Group {
last: Int
"""
- Filter vulnerabilities by project
+ Filter vulnerabilities by project.
"""
projectId: [ID!]
"""
- Filter vulnerabilities by report type
+ Filter vulnerabilities by report type.
"""
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by VulnerabilityScanner.externalId.
"""
scanner: [String!]
"""
- Filter vulnerabilities by severity
+ Filter vulnerabilities by severity.
"""
severity: [VulnerabilitySeverity!]
"""
- List vulnerabilities by sort order
+ List vulnerabilities by sort order.
"""
sort: VulnerabilitySort = severity_desc
"""
- Filter vulnerabilities by state
+ Filter vulnerabilities by state.
"""
state: [VulnerabilityState!]
): VulnerabilityConnection
@@ -10306,7 +11117,7 @@ type Group {
before: String
"""
- Last day for which to fetch vulnerability history
+ Last day for which to fetch vulnerability history.
"""
endDate: ISO8601Date!
@@ -10321,7 +11132,7 @@ type Group {
last: Int
"""
- First day for which to fetch vulnerability history
+ First day for which to fetch vulnerability history.
"""
startDate: ISO8601Date!
): VulnerabilitiesCountByDayConnection
@@ -10342,7 +11153,7 @@ type Group {
before: String
"""
- Last day for which to fetch vulnerability history
+ Last day for which to fetch vulnerability history.
"""
endDate: ISO8601Date!
@@ -10357,7 +11168,7 @@ type Group {
last: Int
"""
- First day for which to fetch vulnerability history
+ First day for which to fetch vulnerability history.
"""
startDate: ISO8601Date!
): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3.")
@@ -10367,7 +11178,7 @@ type Group {
"""
vulnerabilityGrades(
"""
- Include grades belonging to subgroups
+ Include grades belonging to subgroups.
"""
includeSubgroups: Boolean = false
): [VulnerableProjectsByGrade!]!
@@ -10402,27 +11213,27 @@ type Group {
"""
vulnerabilitySeveritiesCount(
"""
- Filter vulnerabilities by project
+ Filter vulnerabilities by project.
"""
projectId: [ID!]
"""
- Filter vulnerabilities by report type
+ Filter vulnerabilities by report type.
"""
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by scanner.
"""
scanner: [String!]
"""
- Filter vulnerabilities by severity
+ Filter vulnerabilities by severity.
"""
severity: [VulnerabilitySeverity!]
"""
- Filter vulnerabilities by state
+ Filter vulnerabilities by state.
"""
state: [VulnerabilityState!]
): VulnerabilitySeveritiesCount
@@ -10591,7 +11402,7 @@ Autogenerated input type of HttpIntegrationCreate
"""
input HttpIntegrationCreateInput {
"""
- Whether the integration is receiving alerts
+ Whether the integration is receiving alerts.
"""
active: Boolean!
@@ -10601,12 +11412,22 @@ input HttpIntegrationCreateInput {
clientMutationId: String
"""
- The name of the integration
+ The name of the integration.
"""
name: String!
"""
- The project to create the integration in
+ The custom mapping of GitLab alert attributes to fields from the payload_example.
+ """
+ payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!]
+
+ """
+ The example of an alert payload.
+ """
+ payloadExample: JsonString
+
+ """
+ The project to create the integration in.
"""
projectPath: ID!
}
@@ -10626,7 +11447,7 @@ type HttpIntegrationCreatePayload {
errors: [String!]!
"""
- The HTTP integration
+ The HTTP integration.
"""
integration: AlertManagementHttpIntegration
}
@@ -10641,7 +11462,7 @@ input HttpIntegrationDestroyInput {
clientMutationId: String
"""
- The ID of the integration to remove
+ The ID of the integration to remove.
"""
id: AlertManagementHttpIntegrationID!
}
@@ -10661,7 +11482,7 @@ type HttpIntegrationDestroyPayload {
errors: [String!]!
"""
- The HTTP integration
+ The HTTP integration.
"""
integration: AlertManagementHttpIntegration
}
@@ -10676,7 +11497,7 @@ input HttpIntegrationResetTokenInput {
clientMutationId: String
"""
- The ID of the integration to mutate
+ The ID of the integration to mutate.
"""
id: AlertManagementHttpIntegrationID!
}
@@ -10696,7 +11517,7 @@ type HttpIntegrationResetTokenPayload {
errors: [String!]!
"""
- The HTTP integration
+ The HTTP integration.
"""
integration: AlertManagementHttpIntegration
}
@@ -10706,7 +11527,7 @@ Autogenerated input type of HttpIntegrationUpdate
"""
input HttpIntegrationUpdateInput {
"""
- Whether the integration is receiving alerts
+ Whether the integration is receiving alerts.
"""
active: Boolean
@@ -10716,12 +11537,12 @@ input HttpIntegrationUpdateInput {
clientMutationId: String
"""
- The ID of the integration to mutate
+ The ID of the integration to mutate.
"""
id: AlertManagementHttpIntegrationID!
"""
- The name of the integration
+ The name of the integration.
"""
name: String
}
@@ -10741,7 +11562,7 @@ type HttpIntegrationUpdatePayload {
errors: [String!]!
"""
- The HTTP integration
+ The HTTP integration.
"""
integration: AlertManagementHttpIntegration
}
@@ -10752,6 +11573,106 @@ An ISO 8601-encoded date
scalar ISO8601Date
"""
+Identifier of IncidentManagement::OncallParticipant
+"""
+scalar IncidentManagementOncallParticipantID
+
+"""
+Describes an incident management on-call rotation
+"""
+type IncidentManagementOncallRotation {
+ """
+ ID of the on-call rotation.
+ """
+ id: IncidentManagementOncallRotationID!
+
+ """
+ Length of the on-call schedule, in the units specified by lengthUnit.
+ """
+ length: Int
+
+ """
+ Unit of the on-call rotation length.
+ """
+ lengthUnit: OncallRotationUnitEnum
+
+ """
+ Name of the on-call rotation.
+ """
+ name: String!
+
+ """
+ Participants of the on-call rotation.
+ """
+ participants(
+ """
+ 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
+ ): OncallParticipantTypeConnection
+
+ """
+ Start date of the on-call rotation.
+ """
+ startsAt: Time
+}
+
+"""
+The connection type for IncidentManagementOncallRotation.
+"""
+type IncidentManagementOncallRotationConnection {
+ """
+ A list of edges.
+ """
+ edges: [IncidentManagementOncallRotationEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [IncidentManagementOncallRotation]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type IncidentManagementOncallRotationEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: IncidentManagementOncallRotation
+}
+
+"""
+Identifier of IncidentManagement::OncallRotation
+"""
+scalar IncidentManagementOncallRotationID
+
+"""
Describes an incident management on-call schedule
"""
type IncidentManagementOncallSchedule {
@@ -10771,6 +11692,31 @@ type IncidentManagementOncallSchedule {
name: String!
"""
+ On-call rotations for the on-call schedule
+ """
+ rotations(
+ """
+ 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
+ ): IncidentManagementOncallRotationConnection!
+
+ """
Time zone of the on-call schedule
"""
timezone: String!
@@ -10872,27 +11818,27 @@ type InstanceSecurityDashboard {
"""
vulnerabilitySeveritiesCount(
"""
- Filter vulnerabilities by project
+ Filter vulnerabilities by project.
"""
projectId: [ID!]
"""
- Filter vulnerabilities by report type
+ Filter vulnerabilities by report type.
"""
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by scanner.
"""
scanner: [String!]
"""
- Filter vulnerabilities by severity
+ Filter vulnerabilities by severity.
"""
severity: [VulnerabilitySeverity!]
"""
- Filter vulnerabilities by state
+ Filter vulnerabilities by state.
"""
state: [VulnerabilityState!]
): VulnerabilitySeveritiesCount
@@ -11050,6 +11996,11 @@ type Issue implements CurrentUserTodos & Noteable {
confidential: Boolean!
"""
+ User specific email address for the issue
+ """
+ createNoteEmail: String
+
+ """
Timestamp of when the issue was created
"""
createdAt: Time!
@@ -11450,17 +12401,17 @@ input IssueMoveInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
"""
- The project to move the issue to
+ The project to move the issue to.
"""
targetProjectPath: ID!
}
@@ -11470,7 +12421,7 @@ Autogenerated input type of IssueMoveList
"""
input IssueMoveListInput {
"""
- Global ID of the board that the issue is in
+ Global ID of the board that the issue is in.
"""
boardId: ID!
@@ -11480,37 +12431,37 @@ input IssueMoveListInput {
clientMutationId: String
"""
- The ID of the parent epic. NULL when removing the association
+ The ID of the parent epic. NULL when removing the association.
"""
epicId: EpicID
"""
- ID of the board list that the issue will be moved from
+ ID of the board list that the issue will be moved from.
"""
fromListId: ID
"""
- IID of the issue to mutate
+ IID of the issue to mutate.
"""
iid: String!
"""
- ID of issue that should be placed after the current issue
+ ID of issue that should be placed after the current issue.
"""
moveAfterId: ID
"""
- ID of issue that should be placed before the current issue
+ ID of issue that should be placed before the current issue.
"""
moveBeforeId: ID
"""
- Project the issue to mutate is in
+ Project the issue to mutate is in.
"""
projectPath: ID!
"""
- ID of the board list that the issue will be moved to
+ ID of the board list that the issue will be moved to.
"""
toListId: ID
}
@@ -11530,7 +12481,7 @@ type IssueMoveListPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11550,7 +12501,7 @@ type IssueMovePayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11615,7 +12566,7 @@ input IssueSetAssigneesInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
@@ -11625,7 +12576,7 @@ input IssueSetAssigneesInput {
operationMode: MutationOperationMode
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -11645,7 +12596,7 @@ type IssueSetAssigneesPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11665,12 +12616,12 @@ input IssueSetConfidentialInput {
confidential: Boolean!
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -11690,7 +12641,7 @@ type IssueSetConfidentialPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11705,17 +12656,17 @@ input IssueSetDueDateInput {
clientMutationId: String
"""
- The desired due date for the issue
+ The desired due date for the issue.
"""
dueDate: Time!
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -11735,7 +12686,7 @@ type IssueSetDueDatePayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11755,12 +12706,12 @@ input IssueSetEpicInput {
epicId: EpicID
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -11780,7 +12731,7 @@ type IssueSetEpicPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11795,7 +12746,7 @@ input IssueSetIterationInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
@@ -11805,7 +12756,7 @@ input IssueSetIterationInput {
iterationId: IterationID
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -11825,7 +12776,7 @@ type IssueSetIterationPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11840,17 +12791,17 @@ input IssueSetLockedInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- Whether or not to lock discussion on the issue
+ Whether or not to lock discussion on the issue.
"""
locked: Boolean!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -11870,7 +12821,7 @@ type IssueSetLockedPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11885,12 +12836,12 @@ input IssueSetSeverityInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
@@ -11915,7 +12866,7 @@ type IssueSetSeverityPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11930,17 +12881,17 @@ input IssueSetSubscriptionInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
"""
- The desired state of the subscription
+ The desired state of the subscription.
"""
subscribedState: Boolean!
}
@@ -11960,7 +12911,7 @@ type IssueSetSubscriptionPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -11975,17 +12926,17 @@ input IssueSetWeightInput {
clientMutationId: String
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
"""
- The desired weight for the issue
+ The desired weight for the issue.
"""
weight: Int!
}
@@ -12005,7 +12956,7 @@ type IssueSetWeightPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -12443,22 +13394,22 @@ input JiraImportStartInput {
clientMutationId: String
"""
- Project key of the importer Jira project
+ Project key of the importer Jira project.
"""
jiraProjectKey: String!
"""
- Project name of the importer Jira project
+ Project name of the importer Jira project.
"""
jiraProjectName: String
"""
- The project to import the Jira project into
+ The project to import the Jira project into.
"""
projectPath: ID!
"""
- The mapping of Jira to GitLab users
+ The mapping of Jira to GitLab users.
"""
usersMapping: [JiraUsersMappingInputType!]
}
@@ -12478,7 +13429,7 @@ type JiraImportStartPayload {
errors: [String!]!
"""
- The Jira import data after mutation
+ The Jira import data after mutation.
"""
jiraImport: JiraImport
}
@@ -12493,12 +13444,12 @@ input JiraImportUsersInput {
clientMutationId: String
"""
- The project to import the Jira users into
+ The project to import the Jira users into.
"""
projectPath: ID!
"""
- The index of the record the import should started at, default 0 (50 records returned)
+ The index of the record the import should started at, default 0 (50 records returned).
"""
startAt: Int
}
@@ -12606,7 +13557,7 @@ type JiraService implements Service {
last: Int
"""
- Project name or key
+ Project name or key.
"""
name: String
): JiraProjectConnection
@@ -12691,6 +13642,11 @@ enum JobArtifactFileType {
TRACE
}
+"""
+JSON object as raw string
+"""
+scalar JsonString
+
type Label {
"""
Background color of the label
@@ -12760,27 +13716,27 @@ input LabelCreateInput {
"""
The color of the label given in 6-digit hex notation with leading '#' sign
(e.g. #FFAABB) or one of the CSS color names in
- https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords.
"""
color: String = "#428BCA"
"""
- Description of the label
+ Description of the label.
"""
description: String
"""
- The group full path the resource is associated with
+ The group full path the resource is associated with.
"""
groupPath: ID
"""
- The project full path the resource is associated with
+ The project full path the resource is associated with.
"""
projectPath: ID
"""
- Title of the label
+ Title of the label.
"""
title: String!
}
@@ -12800,7 +13756,7 @@ type LabelCreatePayload {
errors: [String!]!
"""
- The label after mutation
+ The label after mutation.
"""
label: Label
}
@@ -12849,7 +13805,7 @@ input MarkAsSpamSnippetInput {
clientMutationId: String
"""
- The global ID of the snippet to update
+ The global ID of the snippet to update.
"""
id: SnippetID!
}
@@ -12869,7 +13825,7 @@ type MarkAsSpamSnippetPayload {
errors: [String!]!
"""
- The snippet after mutation
+ The snippet after mutation.
"""
snippet: Snippet
}
@@ -13083,6 +14039,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
autoMergeEnabled: Boolean!
"""
+ Selected auto merge strategy
+ """
+ autoMergeStrategy: String
+
+ """
Array of available auto merge strategies
"""
availableAutoMergeStrategies: [String!]
@@ -13168,6 +14129,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
defaultMergeCommitMessageWithDescription: String
"""
+ Default squash commit message of the merge request
+ """
+ defaultSquashCommitMessage: String
+
+ """
Description of the merge request (Markdown rendered as HTML for caching)
"""
description: String
@@ -13317,6 +14283,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
mergeTrainsCount: Int
"""
+ User who merged this merge request
+ """
+ mergeUser: User
+
+ """
Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS)
"""
mergeWhenPipelineSucceeds: Boolean
@@ -13367,7 +14338,7 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): NoteConnection!
"""
- Participants in the merge request
+ Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.
"""
participants(
"""
@@ -13417,17 +14388,17 @@ type MergeRequest implements CurrentUserTodos & Noteable {
last: Int
"""
- Filter pipelines by the ref they are run for
+ Filter pipelines by the ref they are run for.
"""
ref: String
"""
- Filter pipelines by the sha of the commit they are run for
+ Filter pipelines by the sha of the commit they are run for.
"""
sha: String
"""
- Filter pipelines by their status
+ Filter pipelines by their status.
"""
status: PipelineStatusEnum
): PipelineConnection
@@ -13463,6 +14434,31 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): String!
"""
+ Users from whom a review has been requested.
+ """
+ reviewers(
+ """
+ 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
+ ): UserConnection
+
+ """
Indicates if the merge request is created by @GitLab-Security-Bot.
"""
securityAutoFix: Boolean
@@ -13505,6 +14501,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
"""
Indicates if squash on merge is enabled
"""
+ squash: Boolean!
+
+ """
+ Indicates if squash on merge is enabled
+ """
squashOnMerge: Boolean!
"""
@@ -13648,7 +14649,7 @@ input MergeRequestCreateInput {
labels: [String!]
"""
- Project full path the merge request is associated with
+ Project full path the merge request is associated with.
"""
projectPath: ID!
@@ -13683,7 +14684,7 @@ type MergeRequestCreatePayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -13853,7 +14854,7 @@ input MergeRequestSetAssigneesInput {
clientMutationId: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
@@ -13863,7 +14864,7 @@ input MergeRequestSetAssigneesInput {
operationMode: MutationOperationMode
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
}
@@ -13883,7 +14884,7 @@ type MergeRequestSetAssigneesPayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -13898,7 +14899,7 @@ input MergeRequestSetLabelsInput {
clientMutationId: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
@@ -13913,7 +14914,7 @@ input MergeRequestSetLabelsInput {
operationMode: MutationOperationMode
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
}
@@ -13933,7 +14934,7 @@ type MergeRequestSetLabelsPayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -13948,7 +14949,7 @@ input MergeRequestSetLockedInput {
clientMutationId: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
@@ -13958,7 +14959,7 @@ input MergeRequestSetLockedInput {
locked: Boolean!
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
}
@@ -13978,7 +14979,7 @@ type MergeRequestSetLockedPayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -13993,7 +14994,7 @@ input MergeRequestSetMilestoneInput {
clientMutationId: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
@@ -14003,7 +15004,7 @@ input MergeRequestSetMilestoneInput {
milestoneId: MilestoneID
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
}
@@ -14023,7 +15024,7 @@ type MergeRequestSetMilestonePayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -14038,17 +15039,17 @@ input MergeRequestSetSubscriptionInput {
clientMutationId: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
"""
- The desired state of the subscription
+ The desired state of the subscription.
"""
subscribedState: Boolean!
}
@@ -14068,7 +15069,7 @@ type MergeRequestSetSubscriptionPayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -14083,12 +15084,12 @@ input MergeRequestSetWipInput {
clientMutationId: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
@@ -14113,7 +15114,7 @@ type MergeRequestSetWipPayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -14229,12 +15230,12 @@ input MergeRequestUpdateInput {
description: String
"""
- The IID of the merge request to mutate
+ The IID of the merge request to mutate.
"""
iid: String!
"""
- The project the merge request to mutate is in
+ The project the merge request to mutate is in.
"""
projectPath: ID!
@@ -14264,7 +15265,7 @@ type MergeRequestUpdatePayload {
errors: [String!]!
"""
- The merge request after mutation
+ The merge request after mutation.
"""
mergeRequest: MergeRequest
}
@@ -14332,7 +15333,7 @@ type MetricsDashboard {
first: Int
"""
- Timestamp marking date and time from which annotations need to be fetched
+ Timestamp marking date and time from which annotations need to be fetched.
"""
from: Time!
@@ -14342,7 +15343,7 @@ type MetricsDashboard {
last: Int
"""
- Timestamp marking date and time to which annotations need to be fetched
+ Timestamp marking date and time to which annotations need to be fetched.
"""
to: Time
): MetricsDashboardAnnotationConnection
@@ -14586,6 +15587,7 @@ type Mutation {
awardEmojiToggle(input: AwardEmojiToggleInput!): AwardEmojiTogglePayload
boardListCreate(input: BoardListCreateInput!): BoardListCreatePayload
boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload
+ ciCdSettingsUpdate(input: CiCdSettingsUpdateInput!): CiCdSettingsUpdatePayload
clusterAgentDelete(input: ClusterAgentDeleteInput!): ClusterAgentDeletePayload
clusterAgentTokenCreate(input: ClusterAgentTokenCreateInput!): ClusterAgentTokenCreatePayload
clusterAgentTokenDelete(input: ClusterAgentTokenDeleteInput!): ClusterAgentTokenDeletePayload
@@ -14643,6 +15645,7 @@ type Mutation {
epicAddIssue(input: EpicAddIssueInput!): EpicAddIssuePayload
epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload
epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload
+ exportRequirements(input: ExportRequirementsInput!): ExportRequirementsPayload
httpIntegrationCreate(input: HttpIntegrationCreateInput!): HttpIntegrationCreatePayload
httpIntegrationDestroy(input: HttpIntegrationDestroyInput!): HttpIntegrationDestroyPayload
httpIntegrationResetToken(input: HttpIntegrationResetTokenInput!): HttpIntegrationResetTokenPayload
@@ -14675,6 +15678,7 @@ type Mutation {
"""
mergeRequestUpdate(input: MergeRequestUpdateInput!): MergeRequestUpdatePayload
namespaceIncreaseStorageTemporarily(input: NamespaceIncreaseStorageTemporarilyInput!): NamespaceIncreaseStorageTemporarilyPayload
+ oncallRotationCreate(input: OncallRotationCreateInput!): OncallRotationCreatePayload
oncallScheduleCreate(input: OncallScheduleCreateInput!): OncallScheduleCreatePayload
oncallScheduleDestroy(input: OncallScheduleDestroyInput!): OncallScheduleDestroyPayload
oncallScheduleUpdate(input: OncallScheduleUpdateInput!): OncallScheduleUpdatePayload
@@ -14723,6 +15727,7 @@ type Mutation {
updateImageDiffNote(input: UpdateImageDiffNoteInput!): UpdateImageDiffNotePayload
updateIssue(input: UpdateIssueInput!): UpdateIssuePayload
updateIteration(input: UpdateIterationInput!): UpdateIterationPayload
+ updateNamespacePackageSettings(input: UpdateNamespacePackageSettingsInput!): UpdateNamespacePackageSettingsPayload
"""
Updates a Note. If the body of the Note contains only quick actions, the Note
@@ -14771,7 +15776,7 @@ type Namespace {
additionalPurchasedStorageSize: Float
"""
- Compliance frameworks available to projects in this namespace Available only
+ Compliance frameworks available to projects in this namespace. Available only
when feature flag `ff_custom_compliance_frameworks` is enabled.
"""
complianceFrameworks(
@@ -14791,6 +15796,11 @@ type Namespace {
first: Int
"""
+ Global ID of a specific compliance framework to return.
+ """
+ id: ComplianceManagementFrameworkID
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
@@ -14842,6 +15852,11 @@ type Namespace {
name: String!
"""
+ The package settings for the namespace
+ """
+ packageSettings: PackageSettings
+
+ """
Path of the namespace
"""
path: String!
@@ -14866,12 +15881,12 @@ type Namespace {
first: Int
"""
- Returns only the projects which have vulnerabilities
+ Returns only the projects which have vulnerabilities.
"""
hasVulnerabilities: Boolean = false
"""
- Include also subgroup projects
+ Include also subgroup projects.
"""
includeSubgroups: Boolean = false
@@ -14881,12 +15896,12 @@ type Namespace {
last: Int
"""
- Search project with most similar names or paths
+ Search project with most similar names or paths.
"""
search: String = null
"""
- Sort projects by this criteria
+ Sort projects by this criteria.
"""
sort: NamespaceProjectSort = null
): ProjectConnection!
@@ -14982,7 +15997,7 @@ input NamespaceIncreaseStorageTemporarilyInput {
clientMutationId: String
"""
- The global ID of the namespace to mutate
+ The global ID of the namespace to mutate.
"""
id: NamespaceID!
}
@@ -15002,7 +16017,7 @@ type NamespaceIncreaseStorageTemporarilyPayload {
errors: [String!]!
"""
- The namespace after mutation
+ The namespace after mutation.
"""
namespace: Namespace
}
@@ -15151,6 +16166,11 @@ type Note implements ResolvableInterface {
updatedAt: Time!
"""
+ URL to view this Note in the Web UI
+ """
+ url: String
+
+ """
Permissions for the current user on the resource
"""
userPermissions: NotePermissions!
@@ -15286,6 +16306,176 @@ Identifier of Noteable
scalar NoteableID
"""
+The rotation participant and color palette
+"""
+type OncallParticipantType {
+ """
+ The color palette to assign to the on-call user. For example "blue".
+ """
+ colorPalette: String
+
+ """
+ The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user.
+ """
+ colorWeight: String
+
+ """
+ ID of the on-call participant.
+ """
+ id: IncidentManagementOncallParticipantID!
+
+ """
+ The user who is participating.
+ """
+ user: User!
+}
+
+"""
+The connection type for OncallParticipantType.
+"""
+type OncallParticipantTypeConnection {
+ """
+ A list of edges.
+ """
+ edges: [OncallParticipantTypeEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [OncallParticipantType]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type OncallParticipantTypeEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: OncallParticipantType
+}
+
+"""
+Autogenerated input type of OncallRotationCreate
+"""
+input OncallRotationCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The name of the on-call rotation.
+ """
+ name: String!
+
+ """
+ The usernames of users participating in the on-call rotation.
+ """
+ participants: [OncallUserInputType!]!
+
+ """
+ The project to create the on-call schedule in.
+ """
+ projectPath: ID!
+
+ """
+ The rotation length of the on-call rotation.
+ """
+ rotationLength: OncallRotationLengthInputType!
+
+ """
+ The IID of the on-call schedule to create the on-call rotation in.
+ """
+ scheduleIid: String!
+
+ """
+ The start date and time of the on-call rotation, in the timezone of the on-call schedule.
+ """
+ startsAt: OncallRotationDateInputType!
+}
+
+"""
+Autogenerated return type of OncallRotationCreate
+"""
+type OncallRotationCreatePayload {
+ """
+ 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
+}
+
+"""
+Date input type for on-call rotation
+"""
+input OncallRotationDateInputType {
+ """
+ The date component of the date in YYYY-MM-DD format.
+ """
+ date: String!
+
+ """
+ The time component of the date in 24hr HH:MM format.
+ """
+ time: String!
+}
+
+"""
+The rotation length of the on-call rotation
+"""
+input OncallRotationLengthInputType {
+ """
+ The rotation length of the on-call rotation.
+ """
+ length: Int!
+
+ """
+ The unit of the rotation length of the on-call rotation.
+ """
+ unit: OncallRotationUnitEnum!
+}
+
+"""
+Rotation length unit of an on-call rotation
+"""
+enum OncallRotationUnitEnum {
+ """
+ Days
+ """
+ DAYS
+
+ """
+ Hours
+ """
+ HOURS
+
+ """
+ Weeks
+ """
+ WEEKS
+}
+
+"""
Autogenerated input type of OncallScheduleCreate
"""
input OncallScheduleCreateInput {
@@ -15295,22 +16485,22 @@ input OncallScheduleCreateInput {
clientMutationId: String
"""
- The description of the on-call schedule
+ The description of the on-call schedule.
"""
description: String
"""
- The name of the on-call schedule
+ The name of the on-call schedule.
"""
name: String!
"""
- The project to create the on-call schedule in
+ The project to create the on-call schedule in.
"""
projectPath: ID!
"""
- The timezone of the on-call schedule
+ The timezone of the on-call schedule.
"""
timezone: String!
}
@@ -15330,7 +16520,7 @@ type OncallScheduleCreatePayload {
errors: [String!]!
"""
- The on-call schedule
+ The on-call schedule.
"""
oncallSchedule: IncidentManagementOncallSchedule
}
@@ -15345,12 +16535,12 @@ input OncallScheduleDestroyInput {
clientMutationId: String
"""
- The on-call schedule internal ID to remove
+ The on-call schedule internal ID to remove.
"""
iid: String!
"""
- The project to remove the on-call schedule from
+ The project to remove the on-call schedule from.
"""
projectPath: ID!
}
@@ -15370,7 +16560,7 @@ type OncallScheduleDestroyPayload {
errors: [String!]!
"""
- The on-call schedule
+ The on-call schedule.
"""
oncallSchedule: IncidentManagementOncallSchedule
}
@@ -15385,27 +16575,27 @@ input OncallScheduleUpdateInput {
clientMutationId: String
"""
- The description of the on-call schedule
+ The description of the on-call schedule.
"""
description: String
"""
- The on-call schedule internal ID to update
+ The on-call schedule internal ID to update.
"""
iid: String!
"""
- The name of the on-call schedule
+ The name of the on-call schedule.
"""
name: String
"""
- The project to update the on-call schedule in
+ The project to update the on-call schedule in.
"""
projectPath: ID!
"""
- The timezone of the on-call schedule
+ The timezone of the on-call schedule.
"""
timezone: String
}
@@ -15425,44 +16615,304 @@ type OncallScheduleUpdatePayload {
errors: [String!]!
"""
- The on-call schedule
+ The on-call schedule.
"""
oncallSchedule: IncidentManagementOncallSchedule
}
"""
-Represents a package
+The rotation user and color palette
+"""
+input OncallUserInputType {
+ """
+ A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user.
+ """
+ colorPalette: DataVisualizationColorEnum
+
+ """
+ A value of DataVisualizationWeightEnum. The color weight to assign to for the on-call user.
+ """
+ colorWeight: DataVisualizationWeightEnum
+
+ """
+ The username of the user to participate in the on-call rotation, such as `user_one`.
+ """
+ username: String!
+}
+
+"""
+Represents a package in the Package Registry
"""
type Package {
"""
- The created date
+ The created date.
+ """
+ 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.
"""
createdAt: Time!
"""
- The ID of the package
+ The ID of the package.
"""
id: ID!
"""
- The name of the package
+ The name of the package.
"""
name: String!
"""
- The type of the package
+ The type of the package.
"""
packageType: PackageTypeEnum!
"""
- The update date
+ 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
+ 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
+}
+
+"""
+Represents a composer JSON file
+"""
+type PackageComposerJsonType {
+ """
+ The license set in the Composer JSON file.
+ """
+ license: String
+
+ """
+ The name set in the Composer JSON file.
+ """
+ name: String
+
+ """
+ The type set in the Composer JSON file.
+ """
+ type: String
+
+ """
+ The version set in the Composer JSON file.
+ """
+ version: String
+}
+
+"""
+Composer metadatum
+"""
+type PackageComposerMetadatumType {
+ """
+ Data of the Composer JSON file.
+ """
+ composerJson: PackageComposerJsonType!
+
+ """
+ Target SHA of the package.
+ """
+ targetSha: String!
}
"""
@@ -15580,6 +17030,82 @@ type PackageFileRegistryEdge {
node: PackageFileRegistry
}
+"""
+Namespace-level Package Registry settings
+"""
+type PackageSettings {
+ """
+ When maven_duplicates_allowed is false, you can publish duplicate packages
+ with names that match this regex. Otherwise, this setting has no effect.
+ """
+ mavenDuplicateExceptionRegex: UntrustedRegexp
+
+ """
+ Indicates whether duplicate Maven packages are allowed for this namespace.
+ """
+ mavenDuplicatesAllowed: Boolean!
+}
+
+"""
+Represents a package tag
+"""
+type PackageTag {
+ """
+ The created date.
+ """
+ createdAt: Time!
+
+ """
+ The ID of the tag.
+ """
+ id: ID!
+
+ """
+ The name of the tag.
+ """
+ name: String!
+
+ """
+ The updated date.
+ """
+ updatedAt: Time!
+}
+
+"""
+The connection type for PackageTag.
+"""
+type PackageTagConnection {
+ """
+ A list of edges.
+ """
+ edges: [PackageTagEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [PackageTag]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type PackageTagEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: PackageTag
+}
+
enum PackageTypeEnum {
"""
Packages from the Composer package manager
@@ -15628,6 +17154,11 @@ enum PackageTypeEnum {
}
"""
+Identifier of Packages::Package
+"""
+scalar PackagesPackageID
+
+"""
Information about pagination in a connection.
"""
type PageInfo {
@@ -15765,7 +17296,7 @@ type Pipeline {
last: Int
"""
- Filter jobs by the type of security report they produce
+ Filter jobs by the type of security report they produce.
"""
securityReportTypes: [SecurityReportTypeEnum!]
): CiJobConnection
@@ -15924,7 +17455,7 @@ input PipelineCancelInput {
clientMutationId: String
"""
- The ID of the pipeline to mutate
+ The ID of the pipeline to mutate.
"""
id: CiPipelineID!
}
@@ -15990,7 +17521,7 @@ input PipelineDestroyInput {
clientMutationId: String
"""
- The ID of the pipeline to mutate
+ The ID of the pipeline to mutate.
"""
id: CiPipelineID!
}
@@ -16052,7 +17583,7 @@ input PipelineRetryInput {
clientMutationId: String
"""
- The ID of the pipeline to mutate
+ The ID of the pipeline to mutate.
"""
id: CiPipelineID!
}
@@ -16072,7 +17603,7 @@ type PipelineRetryPayload {
errors: [String!]!
"""
- The pipeline after mutation
+ The pipeline after mutation.
"""
pipeline: Pipeline
}
@@ -16102,17 +17633,17 @@ type Project {
"""
alertManagementAlert(
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
"""
- Filter query for given domain
+ Filter query for given domain.
"""
domain: AlertManagementDomainFilter! = operations
"""
- IID of the alert. For example, "1"
+ IID of the alert. For example, "1".
"""
iid: String
@@ -16122,12 +17653,12 @@ type Project {
search: String
"""
- Sort alerts by this criteria
+ Sort alerts by this criteria.
"""
sort: AlertManagementAlertSort
"""
- Alerts with the specified statues. For example, [TRIGGERED]
+ Alerts with the specified statues. For example, [TRIGGERED].
"""
statuses: [AlertManagementStatus!]
): AlertManagementAlert
@@ -16137,7 +17668,7 @@ type Project {
"""
alertManagementAlertStatusCounts(
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
@@ -16157,7 +17688,7 @@ type Project {
after: String
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
@@ -16167,7 +17698,7 @@ type Project {
before: String
"""
- Filter query for given domain
+ Filter query for given domain.
"""
domain: AlertManagementDomainFilter! = operations
@@ -16177,7 +17708,7 @@ type Project {
first: Int
"""
- IID of the alert. For example, "1"
+ IID of the alert. For example, "1".
"""
iid: String
@@ -16192,12 +17723,12 @@ type Project {
search: String
"""
- Sort alerts by this criteria
+ Sort alerts by this criteria.
"""
sort: AlertManagementAlertSort
"""
- Alerts with the specified statues. For example, [TRIGGERED]
+ Alerts with the specified statues. For example, [TRIGGERED].
"""
statuses: [AlertManagementStatus!]
): AlertManagementAlertConnection
@@ -16253,7 +17784,7 @@ type Project {
"""
board(
"""
- The board's ID
+ The board's ID.
"""
id: BoardID!
): Board
@@ -16278,7 +17809,7 @@ type Project {
first: Int
"""
- Find a board by its ID
+ Find a board by its ID.
"""
id: BoardID
@@ -16298,7 +17829,7 @@ type Project {
"""
clusterAgent(
"""
- Name of the cluster agent
+ Name of the cluster agent.
"""
name: String!
): ClusterAgent
@@ -16393,7 +17924,7 @@ type Project {
last: Int
"""
- Filter the container repositories by their name
+ Filter the container repositories by their name.
"""
name: String
): ContainerRepositoryConnection
@@ -16438,7 +17969,7 @@ type Project {
"""
dastSiteProfile(
"""
- ID of the site profile
+ ID of the site profile.
"""
id: DastSiteProfileID!
): DastSiteProfile
@@ -16469,22 +18000,6 @@ type Project {
): DastSiteProfileConnection
"""
- DAST Site Validation associated with the project. Will always return `null` if
- `security_on_demand_scans_site_validation` is disabled
- """
- dastSiteValidation(
- """
- Normalized URL of the target to be scanned
- """
- normalizedTargetUrls: [String!]
-
- """
- URL of the target to be scanned
- """
- targetUrl: String!
- ): DastSiteValidation
-
- """
DAST Site Validations associated with the project. Will always return no nodes
if `security_on_demand_scans_site_validation` is disabled
"""
@@ -16510,7 +18025,7 @@ type Project {
last: Int
"""
- Normalized URL of the target to be scanned
+ Normalized URL of the target to be scanned.
"""
normalizedTargetUrls: [String!]
): DastSiteValidationConnection
@@ -16530,17 +18045,17 @@ type Project {
"""
environment(
"""
- Name of the environment
+ Name of the environment.
"""
name: String
"""
- Search query for environment name
+ Search query for environment name.
"""
search: String
"""
- States of environments that should be included in result
+ States of environments that should be included in result.
"""
states: [String!]
): Environment
@@ -16570,17 +18085,17 @@ type Project {
last: Int
"""
- Name of the environment
+ Name of the environment.
"""
name: String
"""
- Search query for environment name
+ Search query for environment name.
"""
search: String
"""
- States of environments that should be included in result
+ States of environments that should be included in result.
"""
states: [String!]
): EnvironmentConnection
@@ -16650,102 +18165,102 @@ type Project {
"""
issue(
"""
- ID of a user assigned to the issues, "none" and "any" values are supported
+ ID of a user assigned to the issues, "none" and "any" values are supported.
"""
assigneeId: String
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
"""
- Usernames of users assigned to the issue
+ Usernames of users assigned to the issue.
"""
assigneeUsernames: [String!]
"""
- Username of the author of the issue
+ Username of the author of the issue.
"""
authorUsername: String
"""
- Issues closed after this date
+ Issues closed after this date.
"""
closedAfter: Time
"""
- Issues closed before this date
+ Issues closed before this date.
"""
closedBefore: Time
"""
- Issues created after this date
+ Issues created after this date.
"""
createdAfter: Time
"""
- Issues created before this date
+ Issues created before this date.
"""
createdBefore: Time
"""
- ID of an epic associated with the issues, "none" and "any" values are supported
+ ID of an epic associated with the issues, "none" and "any" values are supported.
"""
epicId: String
"""
- IID of the issue. For example, "1"
+ IID of the issue. For example, "1".
"""
iid: String
"""
- List of IIDs of issues. For example, [1, 2]
+ List of IIDs of issues. For example, [1, 2].
"""
iids: [String!]
"""
- Iterations applied to the issue
+ Iterations applied to the issue.
"""
iterationId: [ID]
"""
- Labels applied to this issue
+ Labels applied to this issue.
"""
labelName: [String]
"""
- Milestone applied to this issue
+ Milestone applied to this issue.
"""
milestoneTitle: [String]
"""
- Search query for issue title or description
+ Search query for issue title or description.
"""
search: String
"""
- Sort issues by this criteria
+ Sort issues by this criteria.
"""
sort: IssueSort = created_desc
"""
- Current state of this issue
+ Current state of this issue.
"""
state: IssuableState
"""
- Filter issues by the given issue types
+ Filter issues by the given issue types.
"""
types: [IssueType!]
"""
- Issues updated after this date
+ Issues updated after this date.
"""
updatedAfter: Time
"""
- Issues updated before this date
+ Issues updated before this date.
"""
updatedBefore: Time
): Issue
@@ -16755,82 +18270,82 @@ type Project {
"""
issueStatusCounts(
"""
- ID of a user assigned to the issues, "none" and "any" values are supported
+ ID of a user assigned to the issues, "none" and "any" values are supported.
"""
assigneeId: String
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
"""
- Usernames of users assigned to the issue
+ Usernames of users assigned to the issue.
"""
assigneeUsernames: [String!]
"""
- Username of the author of the issue
+ Username of the author of the issue.
"""
authorUsername: String
"""
- Issues closed after this date
+ Issues closed after this date.
"""
closedAfter: Time
"""
- Issues closed before this date
+ Issues closed before this date.
"""
closedBefore: Time
"""
- Issues created after this date
+ Issues created after this date.
"""
createdAfter: Time
"""
- Issues created before this date
+ Issues created before this date.
"""
createdBefore: Time
"""
- IID of the issue. For example, "1"
+ IID of the issue. For example, "1".
"""
iid: String
"""
- List of IIDs of issues. For example, [1, 2]
+ List of IIDs of issues. For example, [1, 2].
"""
iids: [String!]
"""
- Labels applied to this issue
+ Labels applied to this issue.
"""
labelName: [String]
"""
- Milestone applied to this issue
+ Milestone applied to this issue.
"""
milestoneTitle: [String]
"""
- Search query for issue title or description
+ Search query for issue title or description.
"""
search: String
"""
- Filter issues by the given issue types
+ Filter issues by the given issue types.
"""
types: [IssueType!]
"""
- Issues updated after this date
+ Issues updated after this date.
"""
updatedAfter: Time
"""
- Issues updated before this date
+ Issues updated before this date.
"""
updatedBefore: Time
): IssueStatusCountsType
@@ -16845,22 +18360,22 @@ type Project {
after: String
"""
- ID of a user assigned to the issues, "none" and "any" values are supported
+ ID of a user assigned to the issues, "none" and "any" values are supported.
"""
assigneeId: String
"""
- Username of a user assigned to the issue
+ Username of a user assigned to the issue.
"""
assigneeUsername: String
"""
- Usernames of users assigned to the issue
+ Usernames of users assigned to the issue.
"""
assigneeUsernames: [String!]
"""
- Username of the author of the issue
+ Username of the author of the issue.
"""
authorUsername: String
@@ -16870,27 +18385,27 @@ type Project {
before: String
"""
- Issues closed after this date
+ Issues closed after this date.
"""
closedAfter: Time
"""
- Issues closed before this date
+ Issues closed before this date.
"""
closedBefore: Time
"""
- Issues created after this date
+ Issues created after this date.
"""
createdAfter: Time
"""
- Issues created before this date
+ Issues created before this date.
"""
createdBefore: Time
"""
- ID of an epic associated with the issues, "none" and "any" values are supported
+ ID of an epic associated with the issues, "none" and "any" values are supported.
"""
epicId: String
@@ -16900,22 +18415,22 @@ type Project {
first: Int
"""
- IID of the issue. For example, "1"
+ IID of the issue. For example, "1".
"""
iid: String
"""
- List of IIDs of issues. For example, [1, 2]
+ List of IIDs of issues. For example, [1, 2].
"""
iids: [String!]
"""
- Iterations applied to the issue
+ Iterations applied to the issue.
"""
iterationId: [ID]
"""
- Labels applied to this issue
+ Labels applied to this issue.
"""
labelName: [String]
@@ -16925,37 +18440,37 @@ type Project {
last: Int
"""
- Milestone applied to this issue
+ Milestone applied to this issue.
"""
milestoneTitle: [String]
"""
- Search query for issue title or description
+ Search query for issue title or description.
"""
search: String
"""
- Sort issues by this criteria
+ Sort issues by this criteria.
"""
sort: IssueSort = created_desc
"""
- Current state of this issue
+ Current state of this issue.
"""
state: IssuableState
"""
- Filter issues by the given issue types
+ Filter issues by the given issue types.
"""
types: [IssueType!]
"""
- Issues updated after this date
+ Issues updated after this date.
"""
updatedAfter: Time
"""
- Issues updated before this date
+ Issues updated before this date.
"""
updatedBefore: Time
): IssueConnection
@@ -17023,7 +18538,7 @@ type Project {
state: IterationState
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
@@ -17123,7 +18638,7 @@ type Project {
"""
mergeRequest(
"""
- IID of the merge request, for example `1`
+ IID of the merge request, for example `1`.
"""
iid: String!
): MergeRequest
@@ -17138,12 +18653,12 @@ type Project {
after: String
"""
- Username of the assignee
+ Username of the assignee.
"""
assigneeUsername: String
"""
- Username of the author
+ Username of the author.
"""
authorUsername: String
@@ -17158,7 +18673,7 @@ type Project {
first: Int
"""
- Array of IIDs of merge requests, for example `[1, 2]`
+ Array of IIDs of merge requests, for example `[1, 2]`.
"""
iids: [String!]
@@ -17173,27 +18688,27 @@ type Project {
last: Int
"""
- Merge requests merged after this date
+ Merge requests merged after this date.
"""
mergedAfter: Time
"""
- Merge requests merged before this date
+ Merge requests merged before this date.
"""
mergedBefore: Time
"""
- Title of the milestone
+ Title of the milestone.
"""
milestoneTitle: String
"""
- Username of the reviewer
+ Username of the reviewer.
"""
reviewerUsername: String
"""
- Sort merge requests by this criteria
+ Sort merge requests by this criteria.
"""
sort: MergeRequestSort = created_desc
@@ -17240,7 +18755,7 @@ type Project {
before: String
"""
- A date that the milestone contains
+ A date that the milestone contains.
"""
containingDate: Time
@@ -17256,12 +18771,12 @@ type Project {
first: Int
"""
- Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1"
+ Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1".
"""
ids: [ID!]
"""
- Also return milestones in the project's parent group and its ancestors
+ Also return milestones in the project's parent group and its ancestors.
"""
includeAncestors: Boolean
@@ -17271,7 +18786,7 @@ type Project {
last: Int
"""
- A search string for the title
+ A search string for the title.
"""
searchTitle: String
@@ -17283,17 +18798,17 @@ type Project {
startDate: Time
"""
- Filter milestones by state
+ Filter milestones by state.
"""
state: MilestoneStateEnum
"""
- List items overlapping the given timeframe
+ List items overlapping the given timeframe.
"""
timeframe: Timeframe
"""
- The title of the milestone
+ The title of the milestone.
"""
title: String
): MilestoneConnection
@@ -17363,7 +18878,7 @@ type Project {
"""
pipeline(
"""
- IID of the Pipeline, e.g., "1"
+ IID of the Pipeline, e.g., "1".
"""
iid: ID!
): Pipeline
@@ -17398,17 +18913,17 @@ type Project {
last: Int
"""
- Filter pipelines by the ref they are run for
+ Filter pipelines by the ref they are run for.
"""
ref: String
"""
- Filter pipelines by the sha of the commit they are run for
+ Filter pipelines by the sha of the commit they are run for.
"""
sha: String
"""
- Filter pipelines by their status
+ Filter pipelines by their status.
"""
status: PipelineStatusEnum
): PipelineConnection
@@ -17444,12 +18959,12 @@ type Project {
last: Int
"""
- Filter members by the given member relations
+ Filter members by the given member relations.
"""
relations: [ProjectMemberRelation!] = [DIRECT, INHERITED]
"""
- Search query
+ Search query.
"""
search: String
): MemberInterfaceConnection
@@ -17464,7 +18979,7 @@ type Project {
"""
release(
"""
- The name of the tag associated to the release
+ The name of the tag associated to the release.
"""
tagName: String!
): Release
@@ -17494,7 +19009,7 @@ type Project {
last: Int
"""
- Sort releases by this criteria
+ Sort releases by this criteria.
"""
sort: ReleaseSort = RELEASED_AT_DESC
): ReleaseConnection
@@ -17524,32 +19039,32 @@ type Project {
"""
requirement(
"""
- Filter requirements by author username
+ Filter requirements by author username.
"""
authorUsername: [String!]
"""
- IID of the requirement, e.g., "1"
+ IID of the requirement, e.g., "1".
"""
iid: ID
"""
- List of IIDs of requirements, e.g., [1, 2]
+ List of IIDs of requirements, e.g., [1, 2].
"""
iids: [ID!]
"""
- Search query for requirement title
+ Search query for requirement title.
"""
search: String
"""
- List requirements by sort order
+ List requirements by sort order.
"""
sort: Sort
"""
- Filter requirements by state
+ Filter requirements by state.
"""
state: RequirementState
): Requirement
@@ -17569,7 +19084,7 @@ type Project {
after: String
"""
- Filter requirements by author username
+ Filter requirements by author username.
"""
authorUsername: [String!]
@@ -17584,12 +19099,12 @@ type Project {
first: Int
"""
- IID of the requirement, e.g., "1"
+ IID of the requirement, e.g., "1".
"""
iid: ID
"""
- List of IIDs of requirements, e.g., [1, 2]
+ List of IIDs of requirements, e.g., [1, 2].
"""
iids: [ID!]
@@ -17599,17 +19114,17 @@ type Project {
last: Int
"""
- Search query for requirement title
+ Search query for requirement title.
"""
search: String
"""
- List requirements by sort order
+ List requirements by sort order.
"""
sort: Sort
"""
- Filter requirements by state
+ Filter requirements by state.
"""
state: RequirementState
): RequirementConnection
@@ -17634,7 +19149,7 @@ type Project {
"""
sentryDetailedError(
"""
- ID of the Sentry issue
+ ID of the Sentry issue.
"""
id: GitlabErrorTrackingDetailedErrorID!
): SentryDetailedError
@@ -17659,7 +19174,7 @@ type Project {
"""
services(
"""
- Indicates if the service is active
+ Indicates if the service is active.
"""
active: Boolean
@@ -17684,7 +19199,7 @@ type Project {
last: Int
"""
- Class name of the service
+ Class name of the service.
"""
type: ServiceType
): ServiceConnection
@@ -17714,7 +19229,7 @@ type Project {
first: Int
"""
- Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"
+ Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1".
"""
ids: [SnippetID!]
@@ -17724,7 +19239,7 @@ type Project {
last: Int
"""
- The visibility of the snippet
+ The visibility of the snippet.
"""
visibility: VisibilityScopesEnum
): SnippetConnection
@@ -17790,11 +19305,6 @@ type Project {
): TerraformStateConnection
"""
- Total pipeline duration for all of the pipelines in a project
- """
- totalPipelineDuration: Int
-
- """
Permissions for the current user on the resource
"""
userPermissions: ProjectPermissions!
@@ -17824,12 +19334,12 @@ type Project {
first: Int
"""
- Returns only the vulnerabilities which have linked issues
+ Returns only the vulnerabilities which have linked issues.
"""
hasIssues: Boolean
"""
- Returns only the vulnerabilities which have been resolved on default branch
+ Returns only the vulnerabilities which have been resolved on default branch.
"""
hasResolution: Boolean
@@ -17839,32 +19349,32 @@ type Project {
last: Int
"""
- Filter vulnerabilities by project
+ Filter vulnerabilities by project.
"""
projectId: [ID!]
"""
- Filter vulnerabilities by report type
+ Filter vulnerabilities by report type.
"""
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by VulnerabilityScanner.externalId.
"""
scanner: [String!]
"""
- Filter vulnerabilities by severity
+ Filter vulnerabilities by severity.
"""
severity: [VulnerabilitySeverity!]
"""
- List vulnerabilities by sort order
+ List vulnerabilities by sort order.
"""
sort: VulnerabilitySort = severity_desc
"""
- Filter vulnerabilities by state
+ Filter vulnerabilities by state.
"""
state: [VulnerabilityState!]
): VulnerabilityConnection
@@ -17884,7 +19394,7 @@ type Project {
before: String
"""
- Last day for which to fetch vulnerability history
+ Last day for which to fetch vulnerability history.
"""
endDate: ISO8601Date!
@@ -17899,7 +19409,7 @@ type Project {
last: Int
"""
- First day for which to fetch vulnerability history
+ First day for which to fetch vulnerability history.
"""
startDate: ISO8601Date!
): VulnerabilitiesCountByDayConnection
@@ -17934,27 +19444,27 @@ type Project {
"""
vulnerabilitySeveritiesCount(
"""
- Filter vulnerabilities by project
+ Filter vulnerabilities by project.
"""
projectId: [ID!]
"""
- Filter vulnerabilities by report type
+ Filter vulnerabilities by report type.
"""
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by scanner.
"""
scanner: [String!]
"""
- Filter vulnerabilities by severity
+ Filter vulnerabilities by severity.
"""
severity: [VulnerabilitySeverity!]
"""
- Filter vulnerabilities by state
+ Filter vulnerabilities by state.
"""
state: [VulnerabilityState!]
): VulnerabilitySeveritiesCount
@@ -17972,6 +19482,11 @@ type Project {
type ProjectCiCdSetting {
"""
+ Whether to keep the latest builds artifacts.
+ """
+ keepLatestArtifact: Boolean
+
+ """
Whether merge pipelines are enabled.
"""
mergePipelinesEnabled: Boolean
@@ -18416,12 +19931,12 @@ Autogenerated input type of PrometheusIntegrationCreate
"""
input PrometheusIntegrationCreateInput {
"""
- Whether the integration is receiving alerts
+ Whether the integration is receiving alerts.
"""
active: Boolean!
"""
- Endpoint at which prometheus can be queried
+ Endpoint at which prometheus can be queried.
"""
apiUrl: String!
@@ -18431,7 +19946,7 @@ input PrometheusIntegrationCreateInput {
clientMutationId: String
"""
- The project to create the integration in
+ The project to create the integration in.
"""
projectPath: ID!
}
@@ -18451,7 +19966,7 @@ type PrometheusIntegrationCreatePayload {
errors: [String!]!
"""
- The newly created integration
+ The newly created integration.
"""
integration: AlertManagementPrometheusIntegration
}
@@ -18466,7 +19981,7 @@ input PrometheusIntegrationResetTokenInput {
clientMutationId: String
"""
- The ID of the integration to mutate
+ The ID of the integration to mutate.
"""
id: PrometheusServiceID!
}
@@ -18486,7 +20001,7 @@ type PrometheusIntegrationResetTokenPayload {
errors: [String!]!
"""
- The newly created integration
+ The newly created integration.
"""
integration: AlertManagementPrometheusIntegration
}
@@ -18496,12 +20011,12 @@ Autogenerated input type of PrometheusIntegrationUpdate
"""
input PrometheusIntegrationUpdateInput {
"""
- Whether the integration is receiving alerts
+ Whether the integration is receiving alerts.
"""
active: Boolean
"""
- Endpoint at which prometheus can be queried
+ Endpoint at which prometheus can be queried.
"""
apiUrl: String
@@ -18511,7 +20026,7 @@ input PrometheusIntegrationUpdateInput {
clientMutationId: String
"""
- The ID of the integration to mutate
+ The ID of the integration to mutate.
"""
id: PrometheusServiceID!
}
@@ -18531,7 +20046,7 @@ type PrometheusIntegrationUpdatePayload {
errors: [String!]!
"""
- The newly created integration
+ The newly created integration.
"""
integration: AlertManagementPrometheusIntegration
}
@@ -18551,17 +20066,17 @@ input PromoteToEpicInput {
clientMutationId: String
"""
- The group the promoted epic will belong to
+ The group the promoted epic will belong to.
"""
groupPath: ID
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
}
@@ -18576,7 +20091,7 @@ type PromoteToEpicPayload {
clientMutationId: String
"""
- The epic after issue promotion
+ The epic after issue promotion.
"""
epic: Epic
@@ -18586,7 +20101,7 @@ type PromoteToEpicPayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -18597,9 +20112,19 @@ type Query {
"""
ciConfig(
"""
- Contents of .gitlab-ci.yml
+ Contents of '.gitlab-ci.yml'.
"""
content: String!
+
+ """
+ Run pipeline creation simulation, or only do static check.
+ """
+ dryRun: Boolean
+
+ """
+ The project of the CI config.
+ """
+ projectPath: ID!
): CiConfig
"""
@@ -18652,7 +20177,7 @@ type Query {
"""
echo(
"""
- Text to echo back
+ Text to echo back.
"""
text: String!
): String!
@@ -18672,7 +20197,7 @@ type Query {
"""
group(
"""
- The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss"
+ The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss".
"""
fullPath: ID!
): Group
@@ -18702,7 +20227,7 @@ type Query {
first: Int
"""
- The type of measurement/statistics to retrieve
+ The type of measurement/statistics to retrieve.
"""
identifier: MeasurementIdentifier!
@@ -18712,12 +20237,12 @@ type Query {
last: Int
"""
- Measurement recorded after this date
+ Measurement recorded after this date.
"""
recordedAfter: Time
"""
- Measurement recorded before this date
+ Measurement recorded before this date.
"""
recordedBefore: Time
): InstanceStatisticsMeasurementConnection
@@ -18762,17 +20287,27 @@ type Query {
"""
namespace(
"""
- The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss"
+ The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss".
"""
fullPath: ID!
): Namespace
"""
+ Find a composer package
+ """
+ packageComposerDetails(
+ """
+ The global ID of the package.
+ """
+ id: PackagesPackageID!
+ ): PackageComposerDetails
+
+ """
Find a project
"""
project(
"""
- The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss"
+ The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss".
"""
fullPath: ID!
): Project
@@ -18797,7 +20332,7 @@ type Query {
first: Int
"""
- Filter projects by IDs
+ Filter projects by IDs.
"""
ids: [ID!]
@@ -18807,22 +20342,22 @@ type Query {
last: Int
"""
- Limit projects that the current user is a member of
+ Limit projects that the current user is a member of.
"""
membership: Boolean
"""
- Search query for project name, path, or description
+ Search query for project name, path, or description.
"""
search: String
"""
- Include namespace in project search
+ Include namespace in project search.
"""
searchNamespaces: Boolean
"""
- Sort order of results
+ Sort order of results.
"""
sort: String
): ProjectConnection
@@ -18857,22 +20392,22 @@ type Query {
"""
runnerSetup(
"""
- Architecture to generate the instructions for
+ Architecture to generate the instructions for.
"""
architecture: String!
"""
- Group to register the runner for
+ Group to register the runner for.
"""
groupId: GroupID
"""
- Platform to generate the instructions for
+ Platform to generate the instructions for.
"""
platform: String!
"""
- Project to register the runner for
+ Project to register the runner for.
"""
projectId: ProjectID
): RunnerSetup
@@ -18887,7 +20422,7 @@ type Query {
after: String
"""
- The ID of an author
+ The ID of an author.
"""
authorId: UserID
@@ -18897,7 +20432,7 @@ type Query {
before: String
"""
- Explore personal snippets
+ Explore personal snippets.
"""
explore: Boolean
@@ -18907,7 +20442,7 @@ type Query {
first: Int
"""
- Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"
+ Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1".
"""
ids: [SnippetID!]
@@ -18917,17 +20452,17 @@ type Query {
last: Int
"""
- The ID of a project
+ The ID of a project.
"""
projectId: ProjectID
"""
- The type of snippet
+ The type of snippet.
"""
type: TypeEnum
"""
- The visibility of the snippet
+ The visibility of the snippet.
"""
visibility: VisibilityScopesEnum
): SnippetConnection
@@ -18937,12 +20472,12 @@ type Query {
"""
user(
"""
- ID of the User
+ ID of the User.
"""
id: UserID
"""
- Username of the User
+ Username of the User.
"""
username: String
): User
@@ -18952,6 +20487,11 @@ type Query {
"""
users(
"""
+ Return only admin users.
+ """
+ admins: Boolean = false
+
+ """
Returns the elements in the list that come after the specified cursor.
"""
after: String
@@ -18967,7 +20507,7 @@ type Query {
first: Int
"""
- List of user Global IDs
+ List of user Global IDs.
"""
ids: [ID!]
@@ -18982,12 +20522,12 @@ type Query {
search: String
"""
- Sort users by this criteria
+ Sort users by this criteria.
"""
sort: Sort = created_desc
"""
- List of usernames
+ List of usernames.
"""
usernames: [String!]
): UserConnection
@@ -19012,12 +20552,12 @@ type Query {
first: Int
"""
- Returns only the vulnerabilities which have linked issues
+ Returns only the vulnerabilities which have linked issues.
"""
hasIssues: Boolean
"""
- Returns only the vulnerabilities which have been resolved on default branch
+ Returns only the vulnerabilities which have been resolved on default branch.
"""
hasResolution: Boolean
@@ -19027,32 +20567,32 @@ type Query {
last: Int
"""
- Filter vulnerabilities by project
+ Filter vulnerabilities by project.
"""
projectId: [ID!]
"""
- Filter vulnerabilities by report type
+ Filter vulnerabilities by report type.
"""
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by VulnerabilityScanner.externalId.
"""
scanner: [String!]
"""
- Filter vulnerabilities by severity
+ Filter vulnerabilities by severity.
"""
severity: [VulnerabilitySeverity!]
"""
- List vulnerabilities by sort order
+ List vulnerabilities by sort order.
"""
sort: VulnerabilitySort = severity_desc
"""
- Filter vulnerabilities by state
+ Filter vulnerabilities by state.
"""
state: [VulnerabilityState!]
): VulnerabilityConnection
@@ -19072,7 +20612,7 @@ type Query {
before: String
"""
- Last day for which to fetch vulnerability history
+ Last day for which to fetch vulnerability history.
"""
endDate: ISO8601Date!
@@ -19087,7 +20627,7 @@ type Query {
last: Int
"""
- First day for which to fetch vulnerability history
+ First day for which to fetch vulnerability history.
"""
startDate: ISO8601Date!
): VulnerabilitiesCountByDayConnection
@@ -19109,7 +20649,7 @@ type Query {
before: String
"""
- Last day for which to fetch vulnerability history
+ Last day for which to fetch vulnerability history.
"""
endDate: ISO8601Date!
@@ -19124,7 +20664,7 @@ type Query {
last: Int
"""
- First day for which to fetch vulnerability history
+ First day for which to fetch vulnerability history.
"""
startDate: ISO8601Date!
): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3.")
@@ -19500,7 +21040,7 @@ Autogenerated input type of ReleaseCreate
"""
input ReleaseCreateInput {
"""
- Assets associated to the release
+ Assets associated to the release.
"""
assets: ReleaseAssetsInput
@@ -19510,7 +21050,7 @@ input ReleaseCreateInput {
clientMutationId: String
"""
- Description (also known as "release notes") of the release
+ Description (also known as "release notes") of the release.
"""
description: String
@@ -19520,17 +21060,17 @@ input ReleaseCreateInput {
milestones: [String!]
"""
- Name of the release
+ Name of the release.
"""
name: String
"""
- Full path of the project the release is associated with
+ Full path of the project the release is associated with.
"""
projectPath: ID!
"""
- The commit SHA or branch name to use if creating a new tag
+ The commit SHA or branch name to use if creating a new tag.
"""
ref: String
@@ -19540,7 +21080,7 @@ input ReleaseCreateInput {
releasedAt: Time
"""
- Name of the tag to associate with the release
+ Name of the tag to associate with the release.
"""
tagName: String!
}
@@ -19560,7 +21100,7 @@ type ReleaseCreatePayload {
errors: [String!]!
"""
- The release after mutation
+ The release after mutation.
"""
release: Release
}
@@ -19575,7 +21115,7 @@ input ReleaseDeleteInput {
clientMutationId: String
"""
- Full path of the project the release is associated with
+ Full path of the project the release is associated with.
"""
projectPath: ID!
@@ -19802,7 +21342,7 @@ input ReleaseUpdateInput {
clientMutationId: String
"""
- Description (release notes) of the release
+ Description (release notes) of the release.
"""
description: String
@@ -19812,22 +21352,22 @@ input ReleaseUpdateInput {
milestones: [String!]
"""
- Name of the release
+ Name of the release.
"""
name: String
"""
- Full path of the project the release is associated with
+ Full path of the project the release is associated with.
"""
projectPath: ID!
"""
- The release date
+ The release date.
"""
releasedAt: Time
"""
- Name of the tag associated with the release
+ Name of the tag associated with the release.
"""
tagName: String!
}
@@ -19857,7 +21397,7 @@ Autogenerated input type of RemoveAwardEmoji
"""
input RemoveAwardEmojiInput {
"""
- The global ID of the awardable resource
+ The global ID of the awardable resource.
"""
awardableId: AwardableID!
@@ -19877,7 +21417,7 @@ Autogenerated return type of RemoveAwardEmoji
"""
type RemoveAwardEmojiPayload {
"""
- The award emoji after mutation
+ The award emoji after mutation.
"""
awardEmoji: AwardEmoji
@@ -19902,7 +21442,7 @@ input RemoveProjectFromSecurityDashboardInput {
clientMutationId: String
"""
- ID of the project to remove from the Instance Security Dashboard
+ ID of the project to remove from the Instance Security Dashboard.
"""
id: ProjectID!
}
@@ -19932,7 +21472,7 @@ input RepositionImageDiffNoteInput {
clientMutationId: String
"""
- The global ID of the DiffNote to update
+ The global ID of the DiffNote to update.
"""
id: DiffNoteID!
@@ -19957,7 +21497,7 @@ type RepositionImageDiffNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -19983,17 +21523,17 @@ type Repository {
"""
tree(
"""
- The path to get the tree for. Default value is the root of the repository
+ The path to get the tree for. Default value is the root of the repository.
"""
path: String = ""
"""
- Used to get a recursive tree. Default is false
+ Used to get a recursive tree. Default is false.
"""
recursive: Boolean = false
"""
- The commit ref to get the tree for. Default value is HEAD
+ The commit ref to get the tree for. Default value is HEAD.
"""
ref: String = "head"
): Tree
@@ -20078,7 +21618,7 @@ type Requirement {
last: Int
"""
- List test reports by sort order
+ List test reports by sort order.
"""
sort: Sort
): TestReportConnection
@@ -20224,7 +21764,7 @@ input RevertVulnerabilityToDetectedInput {
clientMutationId: String
"""
- ID of the vulnerability to be reverted
+ ID of the vulnerability to be reverted.
"""
id: VulnerabilityID!
}
@@ -20244,7 +21784,7 @@ type RevertVulnerabilityToDetectedPayload {
errors: [String!]!
"""
- The vulnerability after revert
+ The vulnerability after revert.
"""
vulnerability: Vulnerability
}
@@ -21310,7 +22850,7 @@ type SentryErrorCollection {
"""
detailedError(
"""
- ID of the Sentry issue
+ ID of the Sentry issue.
"""
id: GitlabErrorTrackingDetailedErrorID!
): SentryDetailedError
@@ -21320,7 +22860,7 @@ type SentryErrorCollection {
"""
errorStackTrace(
"""
- ID of the Sentry issue
+ ID of the Sentry issue.
"""
id: GitlabErrorTrackingDetailedErrorID!
): SentryErrorStackTrace
@@ -21350,12 +22890,12 @@ type SentryErrorCollection {
last: Int
"""
- Search query for the Sentry error details
+ Search query for the Sentry error details.
"""
searchTerm: String
"""
- Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default
+ Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.
"""
sort: String
): SentryErrorConnection
@@ -21566,7 +23106,6 @@ type ServiceEdge {
}
enum ServiceType {
- ALERTS_SERVICE
ASANA_SERVICE
ASSEMBLA_SERVICE
BAMBOO_SERVICE
@@ -21644,7 +23183,7 @@ type Snippet implements Noteable {
last: Int
"""
- Paths of the blobs
+ Paths of the blobs.
"""
paths: [String!]
): SnippetBlobConnection
@@ -22333,7 +23872,7 @@ input TerraformStateDeleteInput {
clientMutationId: String
"""
- Global ID of the Terraform state
+ Global ID of the Terraform state.
"""
id: TerraformStateID!
}
@@ -22383,7 +23922,7 @@ input TerraformStateLockInput {
clientMutationId: String
"""
- Global ID of the Terraform state
+ Global ID of the Terraform state.
"""
id: TerraformStateID!
}
@@ -22413,7 +23952,7 @@ input TerraformStateUnlockInput {
clientMutationId: String
"""
- Global ID of the Terraform state
+ Global ID of the Terraform state.
"""
id: TerraformStateID!
}
@@ -22847,7 +24386,7 @@ input TodoCreateInput {
clientMutationId: String
"""
- The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported
+ The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported.
"""
targetId: TodoableID!
}
@@ -22867,7 +24406,7 @@ type TodoCreatePayload {
errors: [String!]!
"""
- The to-do created
+ The to-do created.
"""
todo: Todo
}
@@ -22902,7 +24441,7 @@ input TodoMarkDoneInput {
clientMutationId: String
"""
- The global ID of the todo to mark as done
+ The global ID of the todo to mark as done.
"""
id: TodoID!
}
@@ -22922,7 +24461,7 @@ type TodoMarkDonePayload {
errors: [String!]!
"""
- The requested todo
+ The requested todo.
"""
todo: Todo!
}
@@ -22937,7 +24476,7 @@ input TodoRestoreInput {
clientMutationId: String
"""
- The global ID of the todo to restore
+ The global ID of the todo to restore.
"""
id: TodoID!
}
@@ -22952,7 +24491,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 todos to restore (a maximum of 50 is supported at once).
"""
ids: [TodoID!]!
}
@@ -22972,12 +24511,12 @@ type TodoRestoreManyPayload {
errors: [String!]!
"""
- Updated todos
+ Updated todos.
"""
todos: [Todo!]!
"""
- The IDs of the updated todo items Deprecated in 13.2: Use todos.
+ The IDs of the updated todo items. Deprecated in 13.2: Use todos.
"""
updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2.")
}
@@ -22997,7 +24536,7 @@ type TodoRestorePayload {
errors: [String!]!
"""
- The requested todo
+ The requested todo.
"""
todo: Todo!
}
@@ -23069,12 +24608,12 @@ type TodosMarkAllDonePayload {
errors: [String!]!
"""
- Updated todos
+ Updated todos.
"""
todos: [Todo!]!
"""
- Ids of the updated todos Deprecated in 13.2: Use todos.
+ Ids of the updated todos. Deprecated in 13.2: Use todos.
"""
updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2.")
}
@@ -23084,7 +24623,7 @@ Autogenerated input type of ToggleAwardEmoji
"""
input ToggleAwardEmojiInput {
"""
- The global ID of the awardable resource
+ The global ID of the awardable resource.
"""
awardableId: AwardableID!
@@ -23104,7 +24643,7 @@ Autogenerated return type of ToggleAwardEmoji
"""
type ToggleAwardEmojiPayload {
"""
- The award emoji after mutation
+ The award emoji after mutation.
"""
awardEmoji: AwardEmoji
@@ -23306,17 +24845,17 @@ input UpdateAlertStatusInput {
clientMutationId: String
"""
- The IID of the alert to mutate
+ The IID of the alert to mutate.
"""
iid: String!
"""
- The project the alert to mutate is in
+ The project the alert to mutate is in.
"""
projectPath: ID!
"""
- The status to set the alert
+ The status to set the alert.
"""
status: AlertManagementStatus!
}
@@ -23326,7 +24865,7 @@ Autogenerated return type of UpdateAlertStatus
"""
type UpdateAlertStatusPayload {
"""
- The alert after mutation
+ The alert after mutation.
"""
alert: AlertManagementAlert
@@ -23341,12 +24880,12 @@ type UpdateAlertStatusPayload {
errors: [String!]!
"""
- The issue created after mutation
+ The issue created after mutation.
"""
issue: Issue
"""
- The todo after mutation
+ The todo after mutation.
"""
todo: Todo
}
@@ -23356,7 +24895,7 @@ Autogenerated input type of UpdateBoardEpicUserPreferences
"""
input UpdateBoardEpicUserPreferencesInput {
"""
- The board global ID
+ The board global ID.
"""
boardId: BoardID!
@@ -23366,12 +24905,12 @@ input UpdateBoardEpicUserPreferencesInput {
clientMutationId: String
"""
- Whether the epic should be collapsed in the board
+ Whether the epic should be collapsed in the board.
"""
collapsed: Boolean!
"""
- ID of an epic to set preferences for
+ ID of an epic to set preferences for.
"""
epicId: EpicID!
}
@@ -23386,7 +24925,7 @@ type UpdateBoardEpicUserPreferencesPayload {
clientMutationId: String
"""
- User preferences for the epic in the board after mutation
+ User preferences for the epic in the board after mutation.
"""
epicUserPreferences: BoardEpicUserPreferences
@@ -23401,6 +24940,11 @@ Autogenerated input type of UpdateBoard
"""
input UpdateBoardInput {
"""
+ The ID of user to be assigned to the board.
+ """
+ assigneeId: UserID
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -23421,9 +24965,34 @@ input UpdateBoardInput {
id: BoardID!
"""
+ The ID of iteration to be assigned to the board.
+ """
+ iterationId: IterationID
+
+ """
+ The IDs of labels to be added to the board.
+ """
+ labelIds: [LabelID!]
+
+ """
+ Labels of the issue
+ """
+ labels: [String!]
+
+ """
+ The ID of milestone to be assigned to the board.
+ """
+ milestoneId: MilestoneID
+
+ """
The board name.
"""
name: String
+
+ """
+ The weight value to be assigned to the board.
+ """
+ weight: Int
}
"""
@@ -23436,7 +25005,7 @@ input UpdateBoardListInput {
clientMutationId: String
"""
- Indicates if list is collapsed for this user
+ Indicates if list is collapsed for this user.
"""
collapsed: Boolean
@@ -23446,7 +25015,7 @@ input UpdateBoardListInput {
listId: ListID!
"""
- Position of list within the board
+ Position of list within the board.
"""
position: Int
}
@@ -23466,7 +25035,7 @@ type UpdateBoardListPayload {
errors: [String!]!
"""
- Mutated list
+ Mutated list.
"""
list: BoardList
}
@@ -23501,24 +25070,14 @@ input UpdateComplianceFrameworkInput {
clientMutationId: String
"""
- New color representation of the compliance framework in hex format. e.g. #FCA121
- """
- color: String
-
- """
- New description for the compliance framework
- """
- description: String
-
- """
- The global ID of the compliance framework to update
+ The global ID of the compliance framework to update.
"""
id: ComplianceManagementFrameworkID!
"""
- New name for the compliance framework
+ Parameters to update the compliance framework with.
"""
- name: String
+ params: ComplianceFrameworkInput!
}
"""
@@ -23531,7 +25090,7 @@ type UpdateComplianceFrameworkPayload {
clientMutationId: String
"""
- The compliance framework after mutation
+ The compliance framework after mutation.
"""
complianceFramework: ComplianceFramework
@@ -23581,7 +25140,7 @@ input UpdateContainerExpirationPolicyInput {
olderThan: ContainerExpirationPolicyOlderThanEnum
"""
- The project path where the container expiration policy is located
+ The project path where the container expiration policy is located.
"""
projectPath: ID!
}
@@ -23596,7 +25155,7 @@ type UpdateContainerExpirationPolicyPayload {
clientMutationId: String
"""
- The container expiration policy after mutation
+ The container expiration policy after mutation.
"""
containerExpirationPolicy: ContainerExpirationPolicy
@@ -23616,17 +25175,17 @@ input UpdateDevopsAdoptionSegmentInput {
clientMutationId: String
"""
- The array of group IDs to set for the segment
+ The array of group IDs to set for the segment.
"""
groupIds: [GroupID!]
"""
- ID of the segment
+ ID of the segment.
"""
id: AnalyticsDevopsAdoptionSegmentID!
"""
- Name of the segment
+ Name of the segment.
"""
name: String!
}
@@ -23646,7 +25205,7 @@ type UpdateDevopsAdoptionSegmentPayload {
errors: [String!]!
"""
- The segment after mutation
+ The segment after mutation.
"""
segment: DevopsAdoptionSegment
}
@@ -23688,32 +25247,32 @@ input UpdateEpicInput {
clientMutationId: String
"""
- Indicates if the epic is confidential
+ Indicates if the epic is confidential.
"""
confidential: Boolean
"""
- The description of the epic
+ The description of the epic.
"""
description: String
"""
- The end date of the epic
+ The end date of the epic.
"""
dueDateFixed: String
"""
- Indicates end date should be sourced from due_date_fixed field not the issue milestones
+ Indicates end date should be sourced from due_date_fixed field not the issue milestones.
"""
dueDateIsFixed: Boolean
"""
- The group the epic to mutate is in
+ The group the epic to mutate is in.
"""
groupPath: ID!
"""
- The IID of the epic to mutate
+ The IID of the epic to mutate.
"""
iid: ID!
@@ -23723,22 +25282,22 @@ input UpdateEpicInput {
removeLabelIds: [ID!]
"""
- The start date of the epic
+ The start date of the epic.
"""
startDateFixed: String
"""
- Indicates start date should be sourced from start_date_fixed field not the issue milestones
+ Indicates start date should be sourced from start_date_fixed field not the issue milestones.
"""
startDateIsFixed: Boolean
"""
- State event for the epic
+ State event for the epic.
"""
stateEvent: EpicStateEvent
"""
- The title of the epic
+ The title of the epic.
"""
title: String
}
@@ -23753,7 +25312,7 @@ type UpdateEpicPayload {
clientMutationId: String
"""
- The epic after mutation
+ The epic after mutation.
"""
epic: Epic
@@ -23778,7 +25337,7 @@ input UpdateImageDiffNoteInput {
clientMutationId: String
"""
- The global ID of the note to update
+ The global ID of the note to update.
"""
id: NoteID!
@@ -23803,7 +25362,7 @@ type UpdateImageDiffNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -23813,7 +25372,7 @@ Autogenerated input type of UpdateIssue
"""
input UpdateIssueInput {
"""
- The IDs of labels to be added to the issue
+ The IDs of labels to be added to the issue.
"""
addLabelIds: [ID!]
@@ -23838,17 +25397,17 @@ input UpdateIssueInput {
dueDate: ISO8601Date
"""
- The ID of the parent epic. NULL when removing the association
+ The ID of the parent epic. NULL when removing the association.
"""
epicId: EpicID
"""
- The desired health status
+ The desired health status.
"""
healthStatus: HealthStatus
"""
- The IID of the issue to mutate
+ The IID of the issue to mutate.
"""
iid: String!
@@ -23858,22 +25417,22 @@ input UpdateIssueInput {
locked: Boolean
"""
- The ID of the milestone to assign to the issue. On update milestone will be removed if set to null
+ The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.
"""
milestoneId: ID
"""
- The project the issue to mutate is in
+ The project the issue to mutate is in.
"""
projectPath: ID!
"""
- The IDs of labels to be removed from the issue
+ The IDs of labels to be removed from the issue.
"""
removeLabelIds: [ID!]
"""
- Close or reopen an issue
+ Close or reopen an issue.
"""
stateEvent: IssueStateEvent
@@ -23883,7 +25442,7 @@ input UpdateIssueInput {
title: String
"""
- The weight of the issue
+ The weight of the issue.
"""
weight: Int
}
@@ -23903,7 +25462,7 @@ type UpdateIssuePayload {
errors: [String!]!
"""
- The issue after mutation
+ The issue after mutation.
"""
issue: Issue
}
@@ -23969,6 +25528,52 @@ type UpdateIterationPayload {
}
"""
+Autogenerated input type of UpdateNamespacePackageSettings
+"""
+input UpdateNamespacePackageSettingsInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ When maven_duplicates_allowed is false, you can publish duplicate packages
+ with names that match this regex. Otherwise, this setting has no effect.
+ """
+ mavenDuplicateExceptionRegex: UntrustedRegexp
+
+ """
+ Indicates whether duplicate Maven packages are allowed for this namespace.
+ """
+ mavenDuplicatesAllowed: Boolean
+
+ """
+ The namespace path where the namespace package setting is located.
+ """
+ namespacePath: ID!
+}
+
+"""
+Autogenerated return type of UpdateNamespacePackageSettings
+"""
+type UpdateNamespacePackageSettingsPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The namespace package setting after mutation.
+ """
+ packageSettings: PackageSettings
+}
+
+"""
Autogenerated input type of UpdateNote
"""
input UpdateNoteInput {
@@ -23988,7 +25593,7 @@ input UpdateNoteInput {
confidential: Boolean
"""
- The global ID of the note to update
+ The global ID of the note to update.
"""
id: NoteID!
}
@@ -24008,7 +25613,7 @@ type UpdateNotePayload {
errors: [String!]!
"""
- The note after mutation
+ The note after mutation.
"""
note: Note
}
@@ -24023,32 +25628,32 @@ input UpdateRequirementInput {
clientMutationId: String
"""
- Description of the requirement
+ Description of the requirement.
"""
description: String
"""
- The IID of the requirement to update
+ The IID of the requirement to update.
"""
iid: String!
"""
- Creates a test report for the requirement with the given state
+ Creates a test report for the requirement with the given state.
"""
lastTestReportState: TestReportState
"""
- Full project path the requirement is associated with
+ Full project path the requirement is associated with.
"""
projectPath: ID!
"""
- State of the requirement
+ State of the requirement.
"""
state: RequirementState
"""
- Title of the requirement
+ Title of the requirement.
"""
title: String
}
@@ -24068,7 +25673,7 @@ type UpdateRequirementPayload {
errors: [String!]!
"""
- Requirement after mutation
+ Requirement after mutation.
"""
requirement: Requirement
}
@@ -24078,7 +25683,7 @@ Autogenerated input type of UpdateSnippet
"""
input UpdateSnippetInput {
"""
- Actions to perform over the snippet repository and blobs
+ Actions to perform over the snippet repository and blobs.
"""
blobActions: [SnippetBlobActionInputType!]
@@ -24088,22 +25693,22 @@ input UpdateSnippetInput {
clientMutationId: String
"""
- Description of the snippet
+ Description of the snippet.
"""
description: String
"""
- The global ID of the snippet to update
+ The global ID of the snippet to update.
"""
id: SnippetID!
"""
- Title of the snippet
+ Title of the snippet.
"""
title: String
"""
- The visibility level of the snippet
+ The visibility level of the snippet.
"""
visibilityLevel: VisibilityLevelsEnum
}
@@ -24123,12 +25728,12 @@ type UpdateSnippetPayload {
errors: [String!]!
"""
- The snippet after mutation
+ The snippet after mutation.
"""
snippet: Snippet
"""
- Indicates whether the operation returns a record detected as spam
+ Indicates whether the operation returns a record detected as spam.
"""
spam: Boolean
}
@@ -24146,7 +25751,7 @@ type User {
after: String
"""
- Username of the author
+ Username of the author.
"""
authorUsername: String
@@ -24161,7 +25766,7 @@ type User {
first: Int
"""
- Array of IIDs of merge requests, for example `[1, 2]`
+ Array of IIDs of merge requests, for example `[1, 2]`.
"""
iids: [String!]
@@ -24176,17 +25781,17 @@ type User {
last: Int
"""
- Merge requests merged after this date
+ Merge requests merged after this date.
"""
mergedAfter: Time
"""
- Merge requests merged before this date
+ Merge requests merged before this date.
"""
mergedBefore: Time
"""
- Title of the milestone
+ Title of the milestone.
"""
milestoneTitle: String
@@ -24201,12 +25806,12 @@ type User {
projectPath: String
"""
- Username of the reviewer
+ Username of the reviewer.
"""
reviewerUsername: String
"""
- Sort merge requests by this criteria
+ Sort merge requests by this criteria.
"""
sort: MergeRequestSort = created_desc
@@ -24236,7 +25841,7 @@ type User {
after: String
"""
- Username of the assignee
+ Username of the assignee.
"""
assigneeUsername: String
@@ -24251,7 +25856,7 @@ type User {
first: Int
"""
- Array of IIDs of merge requests, for example `[1, 2]`
+ Array of IIDs of merge requests, for example `[1, 2]`.
"""
iids: [String!]
@@ -24266,17 +25871,17 @@ type User {
last: Int
"""
- Merge requests merged after this date
+ Merge requests merged after this date.
"""
mergedAfter: Time
"""
- Merge requests merged before this date
+ Merge requests merged before this date.
"""
mergedBefore: Time
"""
- Title of the milestone
+ Title of the milestone.
"""
milestoneTitle: String
@@ -24291,12 +25896,12 @@ type User {
projectPath: String
"""
- Username of the reviewer
+ Username of the reviewer.
"""
reviewerUsername: String
"""
- Sort merge requests by this criteria
+ Sort merge requests by this criteria.
"""
sort: MergeRequestSort = created_desc
@@ -24411,12 +26016,12 @@ type User {
after: String
"""
- Username of the assignee
+ Username of the assignee.
"""
assigneeUsername: String
"""
- Username of the author
+ Username of the author.
"""
authorUsername: String
@@ -24431,7 +26036,7 @@ type User {
first: Int
"""
- Array of IIDs of merge requests, for example `[1, 2]`
+ Array of IIDs of merge requests, for example `[1, 2]`.
"""
iids: [String!]
@@ -24446,17 +26051,17 @@ type User {
last: Int
"""
- Merge requests merged after this date
+ Merge requests merged after this date.
"""
mergedAfter: Time
"""
- Merge requests merged before this date
+ Merge requests merged before this date.
"""
mergedBefore: Time
"""
- Title of the milestone
+ Title of the milestone.
"""
milestoneTitle: String
@@ -24471,7 +26076,7 @@ type User {
projectPath: String
"""
- Sort merge requests by this criteria
+ Sort merge requests by this criteria.
"""
sort: MergeRequestSort = created_desc
@@ -24511,7 +26116,7 @@ type User {
first: Int
"""
- Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1"
+ Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1".
"""
ids: [SnippetID!]
@@ -24521,12 +26126,12 @@ type User {
last: Int
"""
- The type of snippet
+ The type of snippet.
"""
type: TypeEnum
"""
- The visibility of the snippet
+ The visibility of the snippet.
"""
visibility: VisibilityScopesEnum
): SnippetConnection
@@ -24556,7 +26161,7 @@ type User {
last: Int
"""
- Search query
+ Search query.
"""
search: String
): ProjectConnection
@@ -24576,7 +26181,7 @@ type User {
"""
todos(
"""
- The action to be filtered
+ The action to be filtered.
"""
action: [TodoActionEnum!]
@@ -24586,7 +26191,7 @@ type User {
after: String
"""
- The ID of an author
+ The ID of an author.
"""
authorId: [ID!]
@@ -24601,7 +26206,7 @@ type User {
first: Int
"""
- The ID of a group
+ The ID of a group.
"""
groupId: [ID!]
@@ -24611,17 +26216,17 @@ type User {
last: Int
"""
- The ID of a project
+ The ID of a project.
"""
projectId: [ID!]
"""
- The state of the todo
+ The state of the todo.
"""
state: [TodoStateEnum!]
"""
- The type of the todo
+ The type of the todo.
"""
type: [TodoTargetEnum!]
): TodoConnection!
@@ -24898,6 +26503,11 @@ type Vulnerability implements Noteable {
confirmedAt: Time
"""
+ The user that confirmed the vulnerability.
+ """
+ confirmedBy: User
+
+ """
Description of the vulnerability
"""
description: String
@@ -24938,6 +26548,11 @@ type Vulnerability implements Noteable {
dismissedAt: Time
"""
+ The user that dismissed the vulnerability.
+ """
+ dismissedBy: User
+
+ """
List of external issue links related to the vulnerability
"""
externalIssueLinks(
@@ -25002,7 +26617,7 @@ type Vulnerability implements Noteable {
last: Int
"""
- Filter issue links by link type
+ Filter issue links by link type.
"""
linkType: VulnerabilityIssueLinkType
): VulnerabilityIssueLinkConnection!
@@ -25065,6 +26680,11 @@ type Vulnerability implements Noteable {
resolvedAt: Time
"""
+ The user that resolved the vulnerability.
+ """
+ resolvedBy: User
+
+ """
Indicates whether the vulnerability is fixed on the default branch or not
"""
resolvedOnDefaultBranch: Boolean!
@@ -25115,7 +26735,7 @@ input VulnerabilityConfirmInput {
clientMutationId: String
"""
- ID of the vulnerability to be confirmed
+ ID of the vulnerability to be confirmed.
"""
id: VulnerabilityID!
}
@@ -25135,7 +26755,7 @@ type VulnerabilityConfirmPayload {
errors: [String!]!
"""
- The vulnerability after state change
+ The vulnerability after state change.
"""
vulnerability: Vulnerability
}
@@ -25170,12 +26790,17 @@ input VulnerabilityDismissInput {
clientMutationId: String
"""
- Reason why vulnerability should be dismissed
+ Comment why vulnerability should be dismissed.
"""
comment: String
"""
- ID of the vulnerability to be dismissed
+ Reason why vulnerability should be dismissed.
+ """
+ dismissalReason: VulnerabilityDismissalReason
+
+ """
+ ID of the vulnerability to be dismissed.
"""
id: VulnerabilityID!
}
@@ -25195,12 +26820,42 @@ type VulnerabilityDismissPayload {
errors: [String!]!
"""
- The vulnerability after dismissal
+ The vulnerability after dismissal.
"""
vulnerability: Vulnerability
}
"""
+The dismissal reason of the Vulnerability
+"""
+enum VulnerabilityDismissalReason {
+ """
+ The likelihood of the Vulnerability occurring and its impact are deemed acceptable
+ """
+ ACCEPTABLE_RISK
+
+ """
+ The Vulnerability was incorrectly identified as being present
+ """
+ FALSE_POSITIVE
+
+ """
+ There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable
+ """
+ MITIGATING_CONTROL
+
+ """
+ Other reasons for dismissal
+ """
+ NOT_APPLICABLE
+
+ """
+ The Vulnerability is used in tests and does not pose an actual risk
+ """
+ USED_IN_TESTS
+}
+
+"""
An edge in a connection.
"""
type VulnerabilityEdge {
@@ -25697,7 +27352,7 @@ input VulnerabilityResolveInput {
clientMutationId: String
"""
- ID of the vulnerability to be resolved
+ ID of the vulnerability to be resolved.
"""
id: VulnerabilityID!
}
@@ -25717,7 +27372,7 @@ type VulnerabilityResolvePayload {
errors: [String!]!
"""
- The vulnerability after state change
+ The vulnerability after state change.
"""
vulnerability: Vulnerability
}
@@ -25732,7 +27387,7 @@ input VulnerabilityRevertToDetectedInput {
clientMutationId: String
"""
- ID of the vulnerability to be reverted
+ ID of the vulnerability to be reverted.
"""
id: VulnerabilityID!
}
@@ -25752,7 +27407,7 @@ type VulnerabilityRevertToDetectedPayload {
errors: [String!]!
"""
- The vulnerability after revert
+ The vulnerability after revert.
"""
vulnerability: Vulnerability
}
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 3494e0c8300..138530abb17 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -105,7 +105,7 @@
"inputFields": [
{
"name": "awardableId",
- "description": "The global ID of the awardable resource",
+ "description": "The global ID of the awardable resource.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -153,7 +153,7 @@
"fields": [
{
"name": "awardEmoji",
- "description": "The award emoji after mutation",
+ "description": "The award emoji after mutation.",
"args": [
],
@@ -221,7 +221,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the project to be added to Instance Security Dashboard",
+ "description": "ID of the project to be added to Instance Security Dashboard.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -295,7 +295,7 @@
},
{
"name": "project",
- "description": "Project that was added to the Instance Security Dashboard",
+ "description": "Project that was added to the Instance Security Dashboard.",
"args": [
],
@@ -372,6 +372,16 @@
"defaultValue": null
},
{
+ "name": "remoteIp",
+ "description": "Delete jobs matching remote_ip in the context metadata",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "relatedClass",
"description": "Delete jobs matching related_class in the context metadata",
"type": {
@@ -393,7 +403,7 @@
},
{
"name": "queueName",
- "description": "The name of the queue to delete jobs from",
+ "description": "The name of the queue to delete jobs from.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -467,7 +477,7 @@
},
{
"name": "result",
- "description": "Information about the status of the deletion request",
+ "description": "Information about the status of the deletion request.",
"args": [
],
@@ -947,7 +957,7 @@
"args": [
{
"name": "action",
- "description": "The action to be filtered",
+ "description": "The action to be filtered.",
"type": {
"kind": "LIST",
"name": null,
@@ -965,7 +975,7 @@
},
{
"name": "authorId",
- "description": "The ID of an author",
+ "description": "The ID of an author.",
"type": {
"kind": "LIST",
"name": null,
@@ -983,7 +993,7 @@
},
{
"name": "projectId",
- "description": "The ID of a project",
+ "description": "The ID of a project.",
"type": {
"kind": "LIST",
"name": null,
@@ -1001,7 +1011,7 @@
},
{
"name": "groupId",
- "description": "The ID of a group",
+ "description": "The ID of a group.",
"type": {
"kind": "LIST",
"name": null,
@@ -1019,7 +1029,7 @@
},
{
"name": "state",
- "description": "The state of the todo",
+ "description": "The state of the todo.",
"type": {
"kind": "LIST",
"name": null,
@@ -1037,7 +1047,7 @@
},
{
"name": "type",
- "description": "The type of the todo",
+ "description": "The type of the todo.",
"type": {
"kind": "LIST",
"name": null,
@@ -1490,7 +1500,7 @@
"enumValues": [
{
"name": "operations",
- "description": "Alerts for operations domain ",
+ "description": "Alerts for operations domain",
"isDeprecated": false,
"deprecationReason": null
},
@@ -1900,6 +1910,177 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "AlertManagementPayloadAlertFieldInput",
+ "description": "Field that are available while modifying the custom mapping attributes for an HTTP integration",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fieldName",
+ "description": "A GitLab alert field name.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AlertManagementPayloadAlertFieldName",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "path",
+ "description": "Path to value inside payload JSON.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "label",
+ "description": "Human-readable label of the payload path.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "type",
+ "description": "Type of the parsed value.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "AlertManagementPayloadAlertFieldType",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "AlertManagementPayloadAlertFieldName",
+ "description": "Values for alert field names used in the custom mapping",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "TITLE",
+ "description": "The title of the incident.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DESCRIPTION",
+ "description": "A high-level summary of the problem.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "START_TIME",
+ "description": "The time of the incident.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "END_TIME",
+ "description": "The resolved time of the incident.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "SERVICE",
+ "description": "The affected service.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MONITORING_TOOL",
+ "description": "The name of the associated monitoring tool.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "HOSTS",
+ "description": "One or more hosts, as to where this incident occurred.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "SEVERITY",
+ "description": "The severity of the alert.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "FINGERPRINT",
+ "description": "The unique identifier of the alert. This can be used to group occurrences of the same alert.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "GITLAB_ENVIRONMENT_NAME",
+ "description": "The name of the associated GitLab environment.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "AlertManagementPayloadAlertFieldType",
+ "description": "Values for alert field types used in the custom mapping",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "ARRAY",
+ "description": "Array field type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DATETIME",
+ "description": "DateTime field type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "STRING",
+ "description": "String field type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "AlertManagementPrometheusIntegration",
"description": "An endpoint and credentials used to accept Prometheus alerts for a project",
@@ -2112,7 +2293,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the alert to mutate is in",
+ "description": "The project the alert to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2126,7 +2307,7 @@
},
{
"name": "iid",
- "description": "The IID of the alert to mutate",
+ "description": "The IID of the alert to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2192,7 +2373,7 @@
"fields": [
{
"name": "alert",
- "description": "The alert after mutation",
+ "description": "The alert after mutation.",
"args": [
],
@@ -2246,7 +2427,7 @@
},
{
"name": "issue",
- "description": "The issue created after mutation",
+ "description": "The issue created after mutation.",
"args": [
],
@@ -2260,7 +2441,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation",
+ "description": "The todo after mutation.",
"args": [
],
@@ -2288,7 +2469,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the alert to mutate is in",
+ "description": "The project the alert to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2302,7 +2483,7 @@
},
{
"name": "iid",
- "description": "The IID of the alert to mutate",
+ "description": "The IID of the alert to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2336,7 +2517,7 @@
"fields": [
{
"name": "alert",
- "description": "The alert after mutation",
+ "description": "The alert after mutation.",
"args": [
],
@@ -2390,7 +2571,7 @@
},
{
"name": "issue",
- "description": "The issue created after mutation",
+ "description": "The issue created after mutation.",
"args": [
],
@@ -2404,7 +2585,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation",
+ "description": "The todo after mutation.",
"args": [
],
@@ -2586,7 +2767,7 @@
"inputFields": [
{
"name": "awardableId",
- "description": "The global ID of the awardable resource",
+ "description": "The global ID of the awardable resource.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2634,7 +2815,7 @@
"fields": [
{
"name": "awardEmoji",
- "description": "The award emoji after mutation",
+ "description": "The award emoji after mutation.",
"args": [
],
@@ -2702,7 +2883,7 @@
"inputFields": [
{
"name": "awardableId",
- "description": "The global ID of the awardable resource",
+ "description": "The global ID of the awardable resource.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2750,7 +2931,7 @@
"fields": [
{
"name": "awardEmoji",
- "description": "The award emoji after mutation",
+ "description": "The award emoji after mutation.",
"args": [
],
@@ -2818,7 +2999,7 @@
"inputFields": [
{
"name": "awardableId",
- "description": "The global ID of the awardable resource",
+ "description": "The global ID of the awardable resource.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2866,7 +3047,7 @@
"fields": [
{
"name": "awardEmoji",
- "description": "The award emoji after mutation",
+ "description": "The award emoji after mutation.",
"args": [
],
@@ -3356,7 +3537,7 @@
"args": [
{
"name": "issueFilters",
- "description": "Filters applied when selecting issues on the board",
+ "description": "Filters applied when selecting issues on the board.",
"type": {
"kind": "INPUT_OBJECT",
"name": "BoardIssueInput",
@@ -3532,7 +3713,7 @@
"args": [
{
"name": "id",
- "description": "Find a list by its global ID",
+ "description": "Find a list by its global ID.",
"type": {
"kind": "SCALAR",
"name": "ListID",
@@ -3542,7 +3723,7 @@
},
{
"name": "issueFilters",
- "description": "Filters applied when getting issue metadata in the board list",
+ "description": "Filters applied when getting issue metadata in the board list.",
"type": {
"kind": "INPUT_OBJECT",
"name": "BoardIssueInput",
@@ -3628,6 +3809,42 @@
"deprecationReason": null
},
{
+ "name": "webPath",
+ "description": "Web path of the board.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "webUrl",
+ "description": "Web URL of the board.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "weight",
"description": "Weight of the board",
"args": [
@@ -3810,7 +4027,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -3820,7 +4037,7 @@
},
{
"name": "iid",
- "description": "IID of the epic, e.g., \"1\"",
+ "description": "IID of the epic, e.g., \"1\".",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -3830,7 +4047,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of epics, e.g., [1, 2]",
+ "description": "List of IIDs of epics, e.g., [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -3848,7 +4065,7 @@
},
{
"name": "state",
- "description": "Filter epics by state",
+ "description": "Filter epics by state.",
"type": {
"kind": "ENUM",
"name": "EpicState",
@@ -3858,7 +4075,7 @@
},
{
"name": "search",
- "description": "Search query for epic title or description",
+ "description": "Search query for epic title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -3868,7 +4085,7 @@
},
{
"name": "sort",
- "description": "List epics by sort order",
+ "description": "List epics by sort order.",
"type": {
"kind": "ENUM",
"name": "EpicSort",
@@ -3878,7 +4095,7 @@
},
{
"name": "authorUsername",
- "description": "Filter epics by author",
+ "description": "Filter epics by author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -3888,7 +4105,7 @@
},
{
"name": "labelName",
- "description": "Filter epics by labels",
+ "description": "Filter epics by labels.",
"type": {
"kind": "LIST",
"name": null,
@@ -3906,7 +4123,7 @@
},
{
"name": "milestoneTitle",
- "description": "Filter epics by milestone title, computed from epic's issues",
+ "description": "Filter epics by milestone title, computed from epic's issues.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -3916,7 +4133,7 @@
},
{
"name": "iidStartsWith",
- "description": "Filter epics by IID for autocomplete",
+ "description": "Filter epics by IID for autocomplete.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -3926,7 +4143,7 @@
},
{
"name": "includeDescendantGroups",
- "description": "Include epics from descendant groups",
+ "description": "Include epics from descendant groups.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -3935,6 +4152,16 @@
"defaultValue": "true"
},
{
+ "name": "confidential",
+ "description": "Filter epics by given confidentiality.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -5290,7 +5517,7 @@
"args": [
{
"name": "filters",
- "description": "Filters applied when selecting issues in the board list",
+ "description": "Filters applied when selecting issues in the board list.",
"type": {
"kind": "INPUT_OBJECT",
"name": "BoardIssueInput",
@@ -5362,6 +5589,20 @@
"deprecationReason": null
},
{
+ "name": "iteration",
+ "description": "Iteration of the list",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Iteration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "label",
"description": "Label of the list",
"args": [
@@ -5578,7 +5819,7 @@
"inputFields": [
{
"name": "boardId",
- "description": "Global ID of the issue board to mutate",
+ "description": "Global ID of the issue board to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -5592,7 +5833,7 @@
},
{
"name": "backlog",
- "description": "Create the backlog list",
+ "description": "Create the backlog list.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -5602,7 +5843,7 @@
},
{
"name": "labelId",
- "description": "Global ID of an existing label",
+ "description": "Global ID of an existing label.",
"type": {
"kind": "SCALAR",
"name": "LabelID",
@@ -5612,7 +5853,7 @@
},
{
"name": "milestoneId",
- "description": "Global ID of an existing milestone",
+ "description": "Global ID of an existing milestone.",
"type": {
"kind": "SCALAR",
"name": "MilestoneID",
@@ -5622,7 +5863,7 @@
},
{
"name": "iterationId",
- "description": "Global ID of an existing iteration",
+ "description": "Global ID of an existing iteration.",
"type": {
"kind": "SCALAR",
"name": "IterationID",
@@ -5632,7 +5873,7 @@
},
{
"name": "assigneeId",
- "description": "Global ID of an existing user",
+ "description": "Global ID of an existing user.",
"type": {
"kind": "SCALAR",
"name": "UserID",
@@ -5702,7 +5943,7 @@
},
{
"name": "list",
- "description": "List of the issue board",
+ "description": "List of the issue board.",
"args": [
],
@@ -5879,7 +6120,7 @@
},
{
"name": "list",
- "description": "The updated list",
+ "description": "The updated list.",
"args": [
],
@@ -5911,6 +6152,16 @@
},
{
"kind": "SCALAR",
+ "name": "BoardsEpicListID",
+ "description": "Identifier of Boards::EpicList",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
"name": "Boolean",
"description": "Represents `true` or `false` values.",
"fields": null,
@@ -6069,6 +6320,243 @@
},
{
"kind": "OBJECT",
+ "name": "CiBuildNeed",
+ "description": null,
+ "fields": [
+ {
+ "name": "name",
+ "description": "Name of the job we need to complete.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CiBuildNeedConnection",
+ "description": "The connection type for CiBuildNeed.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiBuildNeedEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiBuildNeed",
+ "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": "CiBuildNeedEdge",
+ "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": "CiBuildNeed",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "CiCdSettingsUpdateInput",
+ "description": "Autogenerated input type of CiCdSettingsUpdate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "Full Path of the project the settings belong to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "keepLatestArtifact",
+ "description": "Indicates if the latest artifact should be kept for this project.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "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": "CiCdSettingsUpdatePayload",
+ "description": "Autogenerated return type of CiCdSettingsUpdate",
+ "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": "CiConfig",
"description": null,
"fields": [
@@ -6112,20 +6600,51 @@
"name": "stages",
"description": "Stages of the pipeline",
"args": [
-
- ],
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "CiConfigStage",
+ {
+ "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": "CiConfigStageConnection",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
@@ -6161,20 +6680,51 @@
"name": "jobs",
"description": "Jobs in group",
"args": [
-
- ],
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "CiConfigJob",
+ {
+ "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": "CiConfigJobConnection",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
@@ -6217,12 +6767,210 @@
},
{
"kind": "OBJECT",
+ "name": "CiConfigGroupConnection",
+ "description": "The connection type for CiConfigGroup.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigGroupEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigGroup",
+ "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": "CiConfigGroupEdge",
+ "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": "CiConfigGroup",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "CiConfigJob",
"description": null,
"fields": [
{
+ "name": "afterScript",
+ "description": "Override a set of commands that are executed after the job.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "allowFailure",
+ "description": "Allow job to fail.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "beforeScript",
+ "description": "Override a set of commands that are executed before the job.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "environment",
+ "description": "Name of an environment to which the job deploys.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "except",
+ "description": "Limit when jobs are not created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CiConfigJobRestriction",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "groupName",
- "description": "Name of the job group",
+ "description": "Name of the job group.",
"args": [
],
@@ -6236,7 +6984,7 @@
},
{
"name": "name",
- "description": "Name of the job",
+ "description": "Name of the job.",
"args": [
],
@@ -6250,7 +6998,74 @@
},
{
"name": "needs",
- "description": "Builds that must complete before the jobs run",
+ "description": "Builds that must complete before the jobs run.",
+ "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": "CiConfigNeedConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "only",
+ "description": "Jobs are created when these conditions do not apply.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CiConfigJobRestriction",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "script",
+ "description": "Shell script that is executed by a runner.",
"args": [
],
@@ -6261,8 +7076,8 @@
"kind": "NON_NULL",
"name": null,
"ofType": {
- "kind": "OBJECT",
- "name": "CiConfigNeed",
+ "kind": "SCALAR",
+ "name": "String",
"ofType": null
}
}
@@ -6272,7 +7087,43 @@
},
{
"name": "stage",
- "description": "Name of the job stage",
+ "description": "Name of the job stage.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "tags",
+ "description": "List of tags that are used to select a runner.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "when",
+ "description": "When to run the job.",
"args": [
],
@@ -6294,6 +7145,153 @@
},
{
"kind": "OBJECT",
+ "name": "CiConfigJobConnection",
+ "description": "The connection type for CiConfigJob.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigJobEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigJob",
+ "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": "CiConfigJobEdge",
+ "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": "CiConfigJob",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CiConfigJobRestriction",
+ "description": null,
+ "fields": [
+ {
+ "name": "refs",
+ "description": "The Git refs the job restriction applies to.",
+ "args": [
+
+ ],
+ "type": {
+ "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": "CiConfigNeed",
"description": null,
"fields": [
@@ -6321,12 +7319,12 @@
},
{
"kind": "OBJECT",
- "name": "CiConfigStage",
- "description": null,
+ "name": "CiConfigNeedConnection",
+ "description": "The connection type for CiConfigNeed.",
"fields": [
{
- "name": "groups",
- "description": "Groups of jobs for the stage",
+ "name": "edges",
+ "description": "A list of edges.",
"args": [
],
@@ -6334,14 +7332,157 @@
"kind": "LIST",
"name": null,
"ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "CiConfigGroup",
+ "kind": "OBJECT",
+ "name": "CiConfigNeedEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigNeed",
+ "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": "CiConfigNeedEdge",
+ "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": "CiConfigNeed",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CiConfigStage",
+ "description": null,
+ "fields": [
+ {
+ "name": "groups",
+ "description": "Groups of jobs for the stage",
+ "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": "CiConfigGroupConnection",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
@@ -6369,6 +7510,118 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "CiConfigStageConnection",
+ "description": "The connection type for CiConfigStage.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigStageEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CiConfigStage",
+ "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": "CiConfigStageEdge",
+ "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": "CiConfigStage",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "CiConfigStatus",
"description": "Values for YAML processor result",
@@ -6699,7 +7952,7 @@
},
{
"name": "needs",
- "description": "Builds that must complete before the jobs run",
+ "description": "References to builds that must complete before the jobs run",
"args": [
{
"name": "after",
@@ -6744,7 +7997,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "CiJobConnection",
+ "name": "CiBuildNeedConnection",
"ofType": null
},
"isDeprecated": false,
@@ -7500,7 +8753,7 @@
"inputFields": [
{
"name": "id",
- "description": "Global ID of the cluster agent that will be deleted",
+ "description": "Global ID of the cluster agent that will be deleted.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -7777,7 +9030,7 @@
"inputFields": [
{
"name": "clusterAgentId",
- "description": "Global ID of the cluster agent that will be associated with the new token",
+ "description": "Global ID of the cluster agent that will be associated with the new token.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -7851,7 +9104,7 @@
},
{
"name": "secret",
- "description": "Token secret value. Make sure you save it - you won't be able to access it again",
+ "description": "Token secret value. Make sure you save it - you won't be able to access it again.",
"args": [
],
@@ -7865,7 +9118,7 @@
},
{
"name": "token",
- "description": "Token created after mutation",
+ "description": "Token created after mutation.",
"args": [
],
@@ -7893,7 +9146,7 @@
"inputFields": [
{
"name": "id",
- "description": "Global ID of the cluster agent token that will be deleted",
+ "description": "Global ID of the cluster agent token that will be deleted.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -8415,7 +9668,7 @@
"args": [
{
"name": "status",
- "description": "Filter pipelines by their status",
+ "description": "Filter pipelines by their status.",
"type": {
"kind": "ENUM",
"name": "PipelineStatusEnum",
@@ -8425,7 +9678,7 @@
},
{
"name": "ref",
- "description": "Filter pipelines by the ref they are run for",
+ "description": "Filter pipelines by the ref they are run for.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -8435,7 +9688,7 @@
},
{
"name": "sha",
- "description": "Filter pipelines by the sha of the commit they are run for",
+ "description": "Filter pipelines by the sha of the commit they are run for.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -8819,7 +10072,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Project full path the branch is associated with",
+ "description": "Project full path the branch is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -8833,7 +10086,7 @@
},
{
"name": "branch",
- "description": "Name of the branch to commit into, it can be a new branch",
+ "description": "Name of the branch to commit into, it can be a new branch.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -8847,7 +10100,7 @@
},
{
"name": "startBranch",
- "description": "If on a new branch, name of the original branch",
+ "description": "If on a new branch, name of the original branch.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -8871,7 +10124,7 @@
},
{
"name": "actions",
- "description": "Array of action hashes to commit as a batch",
+ "description": "Array of action hashes to commit as a batch.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -8927,7 +10180,7 @@
},
{
"name": "commit",
- "description": "The commit after mutation",
+ "description": "The commit after mutation.",
"args": [
],
@@ -9239,6 +10492,47 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "ComplianceFrameworkInput",
+ "description": null,
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "name",
+ "description": "New name for the compliance framework.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "description",
+ "description": "New description for the compliance framework.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "color",
+ "description": "New color representation of the compliance framework in hex format. e.g. #FCA121.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "SCALAR",
"name": "ComplianceManagementFrameworkID",
"description": "Identifier of ComplianceManagement::Framework",
@@ -9256,7 +10550,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Full path of the project",
+ "description": "Full path of the project.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -9270,7 +10564,7 @@
},
{
"name": "configuration",
- "description": "SAST CI configuration for the project",
+ "description": "SAST CI configuration for the project.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -9344,7 +10638,7 @@
},
{
"name": "status",
- "description": "Status of creating the commit for the supplied SAST CI configuration",
+ "description": "Status of creating the commit for the supplied SAST CI configuration.",
"args": [
],
@@ -9362,7 +10656,7 @@
},
{
"name": "successPath",
- "description": "Redirect path to use when the response is successful",
+ "description": "Redirect path to use when the response is successful.",
"args": [
],
@@ -10602,7 +11896,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the alert to mutate is in",
+ "description": "The project the alert to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -10616,7 +11910,7 @@
},
{
"name": "iid",
- "description": "The IID of the alert to mutate",
+ "description": "The IID of the alert to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -10650,7 +11944,7 @@
"fields": [
{
"name": "alert",
- "description": "The alert after mutation",
+ "description": "The alert after mutation.",
"args": [
],
@@ -10704,7 +11998,7 @@
},
{
"name": "issue",
- "description": "The issue created after mutation",
+ "description": "The issue created after mutation.",
"args": [
],
@@ -10718,7 +12012,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation",
+ "description": "The todo after mutation.",
"args": [
],
@@ -10746,7 +12040,7 @@
"inputFields": [
{
"name": "environmentId",
- "description": "The global ID of the environment to add an annotation to",
+ "description": "The global ID of the environment to add an annotation to.",
"type": {
"kind": "SCALAR",
"name": "EnvironmentID",
@@ -10756,7 +12050,7 @@
},
{
"name": "clusterId",
- "description": "The global ID of the cluster to add an annotation to",
+ "description": "The global ID of the cluster to add an annotation to.",
"type": {
"kind": "SCALAR",
"name": "ClustersClusterID",
@@ -10766,7 +12060,7 @@
},
{
"name": "startingAt",
- "description": "Timestamp indicating starting moment to which the annotation relates",
+ "description": "Timestamp indicating starting moment to which the annotation relates.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -10780,7 +12074,7 @@
},
{
"name": "endingAt",
- "description": "Timestamp indicating ending moment to which the annotation relates",
+ "description": "Timestamp indicating ending moment to which the annotation relates.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -10790,7 +12084,7 @@
},
{
"name": "dashboardPath",
- "description": "The path to a file defining the dashboard on which the annotation should be added",
+ "description": "The path to a file defining the dashboard on which the annotation should be added.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -10804,7 +12098,7 @@
},
{
"name": "description",
- "description": "The description of the annotation",
+ "description": "The description of the annotation.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -10838,7 +12132,7 @@
"fields": [
{
"name": "annotation",
- "description": "The created annotation",
+ "description": "The created annotation.",
"args": [
],
@@ -10906,7 +12200,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project full path the resource is associated with",
+ "description": "The project full path the resource is associated with.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -10916,7 +12210,7 @@
},
{
"name": "groupPath",
- "description": "The group full path the resource is associated with",
+ "description": "The group full path the resource is associated with.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -10955,6 +12249,82 @@
"defaultValue": null
},
{
+ "name": "assigneeId",
+ "description": "The ID of user to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "UserID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "milestoneId",
+ "description": "The ID of milestone to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "MilestoneID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iterationId",
+ "description": "The ID of iteration to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "IterationID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "weight",
+ "description": "The weight value to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labels",
+ "description": "Labels of the issue",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labelIds",
+ "description": "The IDs of labels to be added to the board.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "LabelID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -11044,7 +12414,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Project full path the branch is associated with",
+ "description": "Project full path the branch is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11058,7 +12428,7 @@
},
{
"name": "name",
- "description": "Name of the branch",
+ "description": "Name of the branch.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11072,7 +12442,7 @@
},
{
"name": "ref",
- "description": "Branch name or commit SHA to create branch from",
+ "description": "Branch name or commit SHA to create branch from.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11106,7 +12476,7 @@
"fields": [
{
"name": "branch",
- "description": "Branch after mutation",
+ "description": "Branch after mutation.",
"args": [
],
@@ -11174,7 +12544,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Full path of the associated project for this cluster agent",
+ "description": "Full path of the associated project for this cluster agent.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11188,7 +12558,7 @@
},
{
"name": "name",
- "description": "Name of the cluster agent",
+ "description": "Name of the cluster agent.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11236,7 +12606,7 @@
},
{
"name": "clusterAgent",
- "description": "Cluster agent created after mutation",
+ "description": "Cluster agent created after mutation.",
"args": [
],
@@ -11303,42 +12673,14 @@
"defaultValue": null
},
{
- "name": "name",
- "description": "Name of the compliance framework.",
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "defaultValue": null
- },
- {
- "name": "description",
- "description": "Description of the compliance framework.",
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "defaultValue": null
- },
- {
- "name": "color",
- "description": "Color to represent the compliance framework as a hexadecimal value. e.g. #ABC123.",
+ "name": "params",
+ "description": "Parameters to update the compliance framework with.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
- "kind": "SCALAR",
- "name": "String",
+ "kind": "INPUT_OBJECT",
+ "name": "ComplianceFrameworkInput",
"ofType": null
}
},
@@ -11434,7 +12776,7 @@
"inputFields": [
{
"name": "groupPath",
- "description": "Namespace full path the emoji is associated with",
+ "description": "Namespace full path the emoji is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11448,7 +12790,7 @@
},
{
"name": "name",
- "description": "Name of the emoji",
+ "description": "Name of the emoji.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11462,7 +12804,7 @@
},
{
"name": "url",
- "description": "Location of the emoji file",
+ "description": "Location of the emoji file.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11510,7 +12852,7 @@
},
{
"name": "customEmoji",
- "description": "The new custom emoji",
+ "description": "The new custom emoji.",
"args": [
],
@@ -11564,7 +12906,7 @@
"inputFields": [
{
"name": "name",
- "description": "Name of the segment",
+ "description": "Name of the segment.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11578,7 +12920,7 @@
},
{
"name": "groupIds",
- "description": "The array of group IDs to set for the segment",
+ "description": "The array of group IDs to set for the segment.",
"type": {
"kind": "LIST",
"name": null,
@@ -11656,7 +12998,7 @@
},
{
"name": "segment",
- "description": "The segment after mutation",
+ "description": "The segment after mutation.",
"args": [
],
@@ -11684,7 +13026,7 @@
"inputFields": [
{
"name": "noteableId",
- "description": "The global ID of the resource to add a note to",
+ "description": "The global ID of the resource to add a note to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11796,7 +13138,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -11824,7 +13166,7 @@
"inputFields": [
{
"name": "groupPath",
- "description": "The group the epic to mutate is in",
+ "description": "The group the epic to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -11838,7 +13180,7 @@
},
{
"name": "title",
- "description": "The title of the epic",
+ "description": "The title of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -11848,7 +13190,7 @@
},
{
"name": "description",
- "description": "The description of the epic",
+ "description": "The description of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -11858,7 +13200,7 @@
},
{
"name": "confidential",
- "description": "Indicates if the epic is confidential",
+ "description": "Indicates if the epic is confidential.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -11868,7 +13210,7 @@
},
{
"name": "startDateFixed",
- "description": "The start date of the epic",
+ "description": "The start date of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -11878,7 +13220,7 @@
},
{
"name": "dueDateFixed",
- "description": "The end date of the epic",
+ "description": "The end date of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -11888,7 +13230,7 @@
},
{
"name": "startDateIsFixed",
- "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones",
+ "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -11898,7 +13240,7 @@
},
{
"name": "dueDateIsFixed",
- "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones",
+ "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -11978,7 +13320,7 @@
},
{
"name": "epic",
- "description": "The created epic",
+ "description": "The created epic.",
"args": [
],
@@ -12032,7 +13374,7 @@
"inputFields": [
{
"name": "noteableId",
- "description": "The global ID of the resource to add a note to",
+ "description": "The global ID of the resource to add a note to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -12144,7 +13486,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -12212,7 +13554,7 @@
},
{
"name": "projectPath",
- "description": "Project full path the issue is associated with",
+ "description": "Project full path the issue is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -12226,7 +13568,7 @@
},
{
"name": "iid",
- "description": "The IID (internal ID) of a project issue. Only admins and project owners can modify",
+ "description": "The IID (internal ID) of a project issue. Only admins and project owners can modify.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -12250,7 +13592,7 @@
},
{
"name": "milestoneId",
- "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null",
+ "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.",
"type": {
"kind": "SCALAR",
"name": "MilestoneID",
@@ -12278,7 +13620,7 @@
},
{
"name": "labelIds",
- "description": "The IDs of labels to be added to the issue",
+ "description": "The IDs of labels to be added to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -12296,7 +13638,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp when the issue was created. Available only for admins and project owners",
+ "description": "Timestamp when the issue was created. Available only for admins and project owners.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -12306,7 +13648,7 @@
},
{
"name": "mergeRequestToResolveDiscussionsOf",
- "description": "The IID of a merge request for which to resolve discussions",
+ "description": "The IID of a merge request for which to resolve discussions.",
"type": {
"kind": "SCALAR",
"name": "MergeRequestID",
@@ -12316,7 +13658,7 @@
},
{
"name": "discussionToResolve",
- "description": "The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`",
+ "description": "The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12326,7 +13668,7 @@
},
{
"name": "assigneeIds",
- "description": "The array of user IDs to assign to the issue",
+ "description": "The array of user IDs to assign to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -12344,7 +13686,7 @@
},
{
"name": "healthStatus",
- "description": "The desired health status",
+ "description": "The desired health status.",
"type": {
"kind": "ENUM",
"name": "HealthStatus",
@@ -12354,7 +13696,7 @@
},
{
"name": "weight",
- "description": "The weight of the issue",
+ "description": "The weight of the issue.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -12364,7 +13706,7 @@
},
{
"name": "epicId",
- "description": "The ID of an epic to associate the issue with",
+ "description": "The ID of an epic to associate the issue with.",
"type": {
"kind": "SCALAR",
"name": "EpicID",
@@ -12434,7 +13776,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -12462,7 +13804,7 @@
"inputFields": [
{
"name": "groupPath",
- "description": "The target group for the iteration",
+ "description": "The target group for the iteration.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -12472,7 +13814,7 @@
},
{
"name": "projectPath",
- "description": "The target project for the iteration",
+ "description": "The target project for the iteration.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -12482,7 +13824,7 @@
},
{
"name": "title",
- "description": "The title of the iteration",
+ "description": "The title of the iteration.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12492,7 +13834,7 @@
},
{
"name": "description",
- "description": "The description of the iteration",
+ "description": "The description of the iteration.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12502,7 +13844,7 @@
},
{
"name": "startDate",
- "description": "The start date of the iteration",
+ "description": "The start date of the iteration.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12512,7 +13854,7 @@
},
{
"name": "dueDate",
- "description": "The end date of the iteration",
+ "description": "The end date of the iteration.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12582,7 +13924,7 @@
},
{
"name": "iteration",
- "description": "The created iteration",
+ "description": "The created iteration.",
"args": [
],
@@ -12610,7 +13952,7 @@
"inputFields": [
{
"name": "noteableId",
- "description": "The global ID of the resource to add a note to",
+ "description": "The global ID of the resource to add a note to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -12648,7 +13990,7 @@
},
{
"name": "discussionId",
- "description": "The global ID of the discussion this note is in reply to",
+ "description": "The global ID of the discussion this note is in reply to.",
"type": {
"kind": "SCALAR",
"name": "DiscussionID",
@@ -12718,7 +14060,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -12746,7 +14088,7 @@
"inputFields": [
{
"name": "title",
- "description": "Title of the requirement",
+ "description": "Title of the requirement.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12756,7 +14098,7 @@
},
{
"name": "description",
- "description": "Description of the requirement",
+ "description": "Description of the requirement.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12766,7 +14108,7 @@
},
{
"name": "projectPath",
- "description": "Full project path the requirement is associated with",
+ "description": "Full project path the requirement is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -12840,7 +14182,7 @@
},
{
"name": "requirement",
- "description": "Requirement after mutation",
+ "description": "Requirement after mutation.",
"args": [
],
@@ -12868,7 +14210,7 @@
"inputFields": [
{
"name": "title",
- "description": "Title of the snippet",
+ "description": "Title of the snippet.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -12882,7 +14224,7 @@
},
{
"name": "description",
- "description": "Description of the snippet",
+ "description": "Description of the snippet.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -12892,7 +14234,7 @@
},
{
"name": "visibilityLevel",
- "description": "The visibility level of the snippet",
+ "description": "The visibility level of the snippet.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -12906,7 +14248,7 @@
},
{
"name": "projectPath",
- "description": "The project full path the snippet is associated with",
+ "description": "The project full path the snippet is associated with.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -12916,7 +14258,7 @@
},
{
"name": "uploadedFiles",
- "description": "The paths to files uploaded in the snippet description",
+ "description": "The paths to files uploaded in the snippet description.",
"type": {
"kind": "LIST",
"name": null,
@@ -12934,7 +14276,7 @@
},
{
"name": "blobActions",
- "description": "Actions to perform over the snippet repository and blobs",
+ "description": "Actions to perform over the snippet repository and blobs.",
"type": {
"kind": "LIST",
"name": null,
@@ -13012,7 +14354,7 @@
},
{
"name": "snippet",
- "description": "The snippet after mutation",
+ "description": "The snippet after mutation.",
"args": [
],
@@ -13026,7 +14368,7 @@
},
{
"name": "spam",
- "description": "Indicates whether the operation returns a record detected as spam",
+ "description": "Indicates whether the operation returns a record detected as spam.",
"args": [
],
@@ -13054,7 +14396,7 @@
"inputFields": [
{
"name": "title",
- "description": "The test case title",
+ "description": "The test case title.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13068,7 +14410,7 @@
},
{
"name": "description",
- "description": "The test case description",
+ "description": "The test case description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -13096,7 +14438,7 @@
},
{
"name": "projectPath",
- "description": "The project full path to create the test case",
+ "description": "The project full path to create the test case.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13170,7 +14512,7 @@
},
{
"name": "testCase",
- "description": "The test case created",
+ "description": "The test case created.",
"args": [
],
@@ -15596,6 +16938,124 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "DataVisualizationColorEnum",
+ "description": "Color of the data visualization palette",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "BLUE",
+ "description": "Blue color",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "ORANGE",
+ "description": "Orange color",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "AQUA",
+ "description": "Aqua color",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "GREEN",
+ "description": "Green color",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MAGENTA",
+ "description": "Magenta color",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "DataVisualizationWeightEnum",
+ "description": "Weight of the data visualization palette",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "WEIGHT_50",
+ "description": "50 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_100",
+ "description": "100 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_200",
+ "description": "200 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_300",
+ "description": "300 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_400",
+ "description": "400 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_500",
+ "description": "500 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_600",
+ "description": "600 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_700",
+ "description": "700 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_800",
+ "description": "800 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_900",
+ "description": "900 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEIGHT_950",
+ "description": "950 weight",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "SCALAR",
"name": "Date",
"description": "Date represented in ISO 8601",
@@ -15613,7 +17073,7 @@
"inputFields": [
{
"name": "id",
- "description": "Global ID of the annotation to delete",
+ "description": "Global ID of the annotation to delete.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -15701,7 +17161,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the segment",
+ "description": "ID of the segment.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -16204,7 +17664,7 @@
"args": [
{
"name": "earlierOrEqualToSha",
- "description": "The SHA256 of the most recent acceptable version",
+ "description": "The SHA256 of the most recent acceptable version.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -16214,7 +17674,7 @@
},
{
"name": "earlierOrEqualToId",
- "description": "The Global ID of the most recent acceptable version",
+ "description": "The Global ID of the most recent acceptable version.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementVersionID",
@@ -16663,7 +18123,7 @@
"args": [
{
"name": "id",
- "description": "Find a design by its ID",
+ "description": "Find a design by its ID.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementDesignID",
@@ -16673,7 +18133,7 @@
},
{
"name": "filename",
- "description": "Find a design by its filename",
+ "description": "Find a design by its filename.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -16696,7 +18156,7 @@
"args": [
{
"name": "id",
- "description": "The Global ID of the design at this version",
+ "description": "The Global ID of the design at this version.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -16723,7 +18183,7 @@
"args": [
{
"name": "ids",
- "description": "Filters designs by their ID",
+ "description": "Filters designs by their ID.",
"type": {
"kind": "LIST",
"name": null,
@@ -16741,7 +18201,7 @@
},
{
"name": "filenames",
- "description": "Filters designs by their filename",
+ "description": "Filters designs by their filename.",
"type": {
"kind": "LIST",
"name": null,
@@ -16862,7 +18322,7 @@
"args": [
{
"name": "sha",
- "description": "The SHA256 of a specific version",
+ "description": "The SHA256 of a specific version.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -16872,7 +18332,7 @@
},
{
"name": "id",
- "description": "The Global ID of the version",
+ "description": "The Global ID of the version.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementVersionID",
@@ -16895,7 +18355,7 @@
"args": [
{
"name": "earlierOrEqualToSha",
- "description": "The SHA256 of the most recent acceptable version",
+ "description": "The SHA256 of the most recent acceptable version.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -16905,7 +18365,7 @@
},
{
"name": "earlierOrEqualToId",
- "description": "The Global ID of the most recent acceptable version",
+ "description": "The Global ID of the most recent acceptable version.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementVersionID",
@@ -17324,7 +18784,7 @@
"args": [
{
"name": "id",
- "description": "The Global ID of the design at this version",
+ "description": "The Global ID of the design at this version.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17351,7 +18811,7 @@
"args": [
{
"name": "id",
- "description": "The Global ID of the version",
+ "description": "The Global ID of the version.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17388,7 +18848,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project where the issue is to upload designs for",
+ "description": "The project where the issue is to upload designs for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17402,7 +18862,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to modify designs for",
+ "description": "The IID of the issue to modify designs for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17416,7 +18876,7 @@
},
{
"name": "filenames",
- "description": "The filenames of the designs to delete",
+ "description": "The filenames of the designs to delete.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17498,7 +18958,7 @@
},
{
"name": "version",
- "description": "The new version in which the designs are deleted",
+ "description": "The new version in which the designs are deleted.",
"args": [
],
@@ -17546,7 +19006,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the design to move",
+ "description": "ID of the design to move.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17560,7 +19020,7 @@
},
{
"name": "previous",
- "description": "ID of the immediately preceding design",
+ "description": "ID of the immediately preceding design.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementDesignID",
@@ -17570,7 +19030,7 @@
},
{
"name": "next",
- "description": "ID of the immediately following design",
+ "description": "ID of the immediately following design.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementDesignID",
@@ -17614,7 +19074,7 @@
},
{
"name": "designCollection",
- "description": "The current state of the collection",
+ "description": "The current state of the collection.",
"args": [
],
@@ -17668,7 +19128,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project where the issue is to upload designs for",
+ "description": "The project where the issue is to upload designs for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17682,7 +19142,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to modify designs for",
+ "description": "The IID of the issue to modify designs for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17696,7 +19156,7 @@
},
{
"name": "files",
- "description": "The files to upload",
+ "description": "The files to upload.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -17752,7 +19212,7 @@
},
{
"name": "designs",
- "description": "The designs that were uploaded by the mutation",
+ "description": "The designs that were uploaded by the mutation.",
"args": [
],
@@ -17857,7 +19317,7 @@
"args": [
{
"name": "id",
- "description": "The ID of the DesignAtVersion",
+ "description": "The ID of the DesignAtVersion.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementDesignAtVersionID",
@@ -17867,7 +19327,7 @@
},
{
"name": "designId",
- "description": "The ID of a specific design",
+ "description": "The ID of a specific design.",
"type": {
"kind": "SCALAR",
"name": "DesignManagementDesignID",
@@ -17877,7 +19337,7 @@
},
{
"name": "filename",
- "description": "The filename of a specific design",
+ "description": "The filename of a specific design.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -17961,7 +19421,7 @@
"args": [
{
"name": "ids",
- "description": "Filters designs by their ID",
+ "description": "Filters designs by their ID.",
"type": {
"kind": "LIST",
"name": null,
@@ -17979,7 +19439,7 @@
},
{
"name": "filenames",
- "description": "Filters designs by their filename",
+ "description": "Filters designs by their filename.",
"type": {
"kind": "LIST",
"name": null,
@@ -18247,7 +19707,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the board to destroy",
+ "description": "The global ID of the board to destroy.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -18383,7 +19843,7 @@
"fields": [
{
"name": "board",
- "description": "The board after mutation",
+ "description": "The board after mutation.",
"args": [
],
@@ -18451,7 +19911,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the compliance framework to destroy",
+ "description": "The global ID of the compliance framework to destroy.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -18715,7 +20175,7 @@
},
{
"name": "deletedTagNames",
- "description": "Deleted container repository tags",
+ "description": "Deleted container repository tags.",
"args": [
],
@@ -18781,7 +20241,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the note to destroy",
+ "description": "The global ID of the note to destroy.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -18855,7 +20315,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -18883,7 +20343,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the snippet to destroy",
+ "description": "The global ID of the snippet to destroy.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -18957,7 +20417,7 @@
},
{
"name": "snippet",
- "description": "The snippet after mutation",
+ "description": "The snippet after mutation.",
"args": [
],
@@ -20492,7 +21952,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the discussion",
+ "description": "The global ID of the discussion.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -20506,7 +21966,7 @@
},
{
"name": "resolve",
- "description": "Will resolve the discussion when true, and unresolve the discussion when false",
+ "description": "Will resolve the discussion when true, and unresolve the discussion when false.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -20554,7 +22014,7 @@
},
{
"name": "discussion",
- "description": "The discussion after mutation",
+ "description": "The discussion after mutation.",
"args": [
],
@@ -20608,7 +22068,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the vulnerability to be dismissed",
+ "description": "ID of the vulnerability to be dismissed.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -20622,7 +22082,7 @@
},
{
"name": "comment",
- "description": "Reason why vulnerability should be dismissed",
+ "description": "Comment why vulnerability should be dismissed.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -20631,6 +22091,16 @@
"defaultValue": null
},
{
+ "name": "dismissalReason",
+ "description": "Reason why vulnerability should be dismissed.",
+ "type": {
+ "kind": "ENUM",
+ "name": "VulnerabilityDismissalReason",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -20692,7 +22162,7 @@
},
{
"name": "vulnerability",
- "description": "The vulnerability after dismissal",
+ "description": "The vulnerability after dismissal.",
"args": [
],
@@ -20919,7 +22389,7 @@
"args": [
{
"name": "path",
- "description": "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'",
+ "description": "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21132,7 +22602,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the environment to update",
+ "description": "The global ID of the environment to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21146,7 +22616,7 @@
},
{
"name": "weight",
- "description": "The weight of the Canary Ingress",
+ "description": "The weight of the Canary Ingress.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21275,7 +22745,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -21285,7 +22755,7 @@
},
{
"name": "iid",
- "description": "IID of the epic, e.g., \"1\"",
+ "description": "IID of the epic, e.g., \"1\".",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -21295,7 +22765,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of epics, e.g., [1, 2]",
+ "description": "List of IIDs of epics, e.g., [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -21313,7 +22783,7 @@
},
{
"name": "state",
- "description": "Filter epics by state",
+ "description": "Filter epics by state.",
"type": {
"kind": "ENUM",
"name": "EpicState",
@@ -21323,7 +22793,7 @@
},
{
"name": "search",
- "description": "Search query for epic title or description",
+ "description": "Search query for epic title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21333,7 +22803,7 @@
},
{
"name": "sort",
- "description": "List epics by sort order",
+ "description": "List epics by sort order.",
"type": {
"kind": "ENUM",
"name": "EpicSort",
@@ -21343,7 +22813,7 @@
},
{
"name": "authorUsername",
- "description": "Filter epics by author",
+ "description": "Filter epics by author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21353,7 +22823,7 @@
},
{
"name": "labelName",
- "description": "Filter epics by labels",
+ "description": "Filter epics by labels.",
"type": {
"kind": "LIST",
"name": null,
@@ -21371,7 +22841,7 @@
},
{
"name": "milestoneTitle",
- "description": "Filter epics by milestone title, computed from epic's issues",
+ "description": "Filter epics by milestone title, computed from epic's issues.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21381,7 +22851,7 @@
},
{
"name": "iidStartsWith",
- "description": "Filter epics by IID for autocomplete",
+ "description": "Filter epics by IID for autocomplete.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21391,7 +22861,7 @@
},
{
"name": "includeDescendantGroups",
- "description": "Include epics from descendant groups",
+ "description": "Include epics from descendant groups.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -21400,6 +22870,16 @@
"defaultValue": "true"
},
{
+ "name": "confidential",
+ "description": "Filter epics by given confidentiality.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -22390,7 +23870,7 @@
"inputFields": [
{
"name": "iid",
- "description": "The IID of the epic to mutate",
+ "description": "The IID of the epic to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -22404,7 +23884,7 @@
},
{
"name": "groupPath",
- "description": "The group the epic to mutate belongs to",
+ "description": "The group the epic to mutate belongs to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -22418,7 +23898,7 @@
},
{
"name": "projectPath",
- "description": "The full path of the project the issue belongs to",
+ "description": "The full path of the project the issue belongs to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -22432,7 +23912,7 @@
},
{
"name": "issueIid",
- "description": "The IID of the issue to be added",
+ "description": "The IID of the issue to be added.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -22480,7 +23960,7 @@
},
{
"name": "epic",
- "description": "The epic after mutation",
+ "description": "The epic after mutation.",
"args": [
],
@@ -22494,7 +23974,7 @@
},
{
"name": "epicIssue",
- "description": "The epic-issue relation",
+ "description": "The epic-issue relation.",
"args": [
],
@@ -22547,7 +24027,7 @@
"fields": [
{
"name": "id",
- "description": "Global ID of the board",
+ "description": "Global ID of the board.",
"args": [
],
@@ -22564,8 +24044,71 @@
"deprecationReason": null
},
{
+ "name": "lists",
+ "description": "Epic board lists.",
+ "args": [
+ {
+ "name": "id",
+ "description": "Find an epic board list by ID.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "BoardsEpicListID",
+ "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": "EpicListConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "name",
- "description": "Name of the board",
+ "description": "Name of the board.",
"args": [
],
@@ -23139,6 +24682,20 @@
"deprecationReason": null
},
{
+ "name": "createNoteEmail",
+ "description": "User specific email address for the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createdAt",
"description": "Timestamp of when the issue was created",
"args": [
@@ -24291,6 +25848,266 @@
},
{
"kind": "OBJECT",
+ "name": "EpicList",
+ "description": "Represents an epic board list",
+ "fields": [
+ {
+ "name": "epics",
+ "description": "List epics.",
+ "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": "EpicConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "Global ID of the board list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BoardsEpicListID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "label",
+ "description": "Label of the list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Label",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "listType",
+ "description": "Type of the list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "position",
+ "description": "Position of the list within the board.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "title",
+ "description": "Title of the list.",
+ "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": "EpicListConnection",
+ "description": "The connection type for EpicList.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "EpicListEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "EpicList",
+ "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": "EpicListEdge",
+ "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": "EpicList",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "EpicPermissions",
"description": "Check permissions for the current user on an epic",
"fields": [
@@ -24454,7 +26271,7 @@
"inputFields": [
{
"name": "iid",
- "description": "The IID of the epic to mutate",
+ "description": "The IID of the epic to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -24468,7 +26285,7 @@
},
{
"name": "groupPath",
- "description": "The group the epic to mutate belongs to",
+ "description": "The group the epic to mutate belongs to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -24482,7 +26299,7 @@
},
{
"name": "subscribedState",
- "description": "The desired state of the subscription",
+ "description": "The desired state of the subscription.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -24530,7 +26347,7 @@
},
{
"name": "epic",
- "description": "The epic after mutation",
+ "description": "The epic after mutation.",
"args": [
],
@@ -24726,7 +26543,7 @@
"inputFields": [
{
"name": "baseEpicId",
- "description": "The ID of the base epic of the tree",
+ "description": "The ID of the base epic of the tree.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -24740,7 +26557,7 @@
},
{
"name": "moved",
- "description": "Parameters for updating the tree positions",
+ "description": "Parameters for updating the tree positions.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -24854,6 +26671,142 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "ExportRequirementsInput",
+ "description": "Autogenerated input type of ExportRequirements",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "sort",
+ "description": "List requirements by sort order.",
+ "type": {
+ "kind": "ENUM",
+ "name": "Sort",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "state",
+ "description": "Filter requirements by state.",
+ "type": {
+ "kind": "ENUM",
+ "name": "RequirementState",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "search",
+ "description": "Search query for requirement title.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "authorUsername",
+ "description": "Filter requirements by author username.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "projectPath",
+ "description": "Full project path the requirements are associated with.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "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": "ExportRequirementsPayload",
+ "description": "Autogenerated return type of ExportRequirements",
+ "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": "ExternalIssue",
"description": "Represents an external issue",
@@ -25059,7 +27012,7 @@
"args": [
{
"name": "ids",
- "description": "Filters registries by their ID",
+ "description": "Filters registries by their ID.",
"type": {
"kind": "LIST",
"name": null,
@@ -25158,7 +27111,7 @@
"args": [
{
"name": "ids",
- "description": "Filters registries by their ID",
+ "description": "Filters registries by their ID.",
"type": {
"kind": "LIST",
"name": null,
@@ -25346,7 +27299,7 @@
"args": [
{
"name": "ids",
- "description": "Filters registries by their ID",
+ "description": "Filters registries by their ID.",
"type": {
"kind": "LIST",
"name": null,
@@ -25431,7 +27384,7 @@
"args": [
{
"name": "ids",
- "description": "Filters registries by their ID",
+ "description": "Filters registries by their ID.",
"type": {
"kind": "LIST",
"name": null,
@@ -25712,7 +27665,7 @@
"args": [
{
"name": "id",
- "description": "The board's ID",
+ "description": "The board's ID.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -25739,7 +27692,7 @@
"args": [
{
"name": "id",
- "description": "Find a board by its ID",
+ "description": "Find a board by its ID.",
"type": {
"kind": "SCALAR",
"name": "BoardID",
@@ -25802,7 +27755,7 @@
"args": [
{
"name": "startDate",
- "description": "First day for which to fetch code coverage activity (maximum time window is set to 90 days)",
+ "description": "First day for which to fetch code coverage activity (maximum time window is set to 90 days).",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -25865,7 +27818,7 @@
},
{
"name": "complianceFrameworks",
- "description": "Compliance frameworks available to projects in this namespace Available only when feature flag `ff_custom_compliance_frameworks` is enabled.",
+ "description": "Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled.",
"args": [
{
"name": "after",
@@ -25906,6 +27859,16 @@
"ofType": null
},
"defaultValue": null
+ },
+ {
+ "name": "id",
+ "description": "Global ID of a specific compliance framework to return.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ComplianceManagementFrameworkID",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"type": {
@@ -25922,7 +27885,7 @@
"args": [
{
"name": "name",
- "description": "Filter the container repositories by their name",
+ "description": "Filter the container repositories by their name.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26136,7 +28099,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -26146,7 +28109,7 @@
},
{
"name": "iid",
- "description": "IID of the epic, e.g., \"1\"",
+ "description": "IID of the epic, e.g., \"1\".",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -26156,7 +28119,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of epics, e.g., [1, 2]",
+ "description": "List of IIDs of epics, e.g., [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -26174,7 +28137,7 @@
},
{
"name": "state",
- "description": "Filter epics by state",
+ "description": "Filter epics by state.",
"type": {
"kind": "ENUM",
"name": "EpicState",
@@ -26184,7 +28147,7 @@
},
{
"name": "search",
- "description": "Search query for epic title or description",
+ "description": "Search query for epic title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26194,7 +28157,7 @@
},
{
"name": "sort",
- "description": "List epics by sort order",
+ "description": "List epics by sort order.",
"type": {
"kind": "ENUM",
"name": "EpicSort",
@@ -26204,7 +28167,7 @@
},
{
"name": "authorUsername",
- "description": "Filter epics by author",
+ "description": "Filter epics by author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26214,7 +28177,7 @@
},
{
"name": "labelName",
- "description": "Filter epics by labels",
+ "description": "Filter epics by labels.",
"type": {
"kind": "LIST",
"name": null,
@@ -26232,7 +28195,7 @@
},
{
"name": "milestoneTitle",
- "description": "Filter epics by milestone title, computed from epic's issues",
+ "description": "Filter epics by milestone title, computed from epic's issues.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26242,7 +28205,7 @@
},
{
"name": "iidStartsWith",
- "description": "Filter epics by IID for autocomplete",
+ "description": "Filter epics by IID for autocomplete.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26252,13 +28215,23 @@
},
{
"name": "includeDescendantGroups",
- "description": "Include epics from descendant groups",
+ "description": "Include epics from descendant groups.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": "true"
+ },
+ {
+ "name": "confidential",
+ "description": "Filter epics by given confidentiality.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"type": {
@@ -26275,7 +28248,7 @@
"args": [
{
"name": "id",
- "description": "Find an epic board by ID",
+ "description": "Find an epic board by ID.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -26375,7 +28348,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -26385,7 +28358,7 @@
},
{
"name": "iid",
- "description": "IID of the epic, e.g., \"1\"",
+ "description": "IID of the epic, e.g., \"1\".",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -26395,7 +28368,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of epics, e.g., [1, 2]",
+ "description": "List of IIDs of epics, e.g., [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -26413,7 +28386,7 @@
},
{
"name": "state",
- "description": "Filter epics by state",
+ "description": "Filter epics by state.",
"type": {
"kind": "ENUM",
"name": "EpicState",
@@ -26423,7 +28396,7 @@
},
{
"name": "search",
- "description": "Search query for epic title or description",
+ "description": "Search query for epic title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26433,7 +28406,7 @@
},
{
"name": "sort",
- "description": "List epics by sort order",
+ "description": "List epics by sort order.",
"type": {
"kind": "ENUM",
"name": "EpicSort",
@@ -26443,7 +28416,7 @@
},
{
"name": "authorUsername",
- "description": "Filter epics by author",
+ "description": "Filter epics by author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26453,7 +28426,7 @@
},
{
"name": "labelName",
- "description": "Filter epics by labels",
+ "description": "Filter epics by labels.",
"type": {
"kind": "LIST",
"name": null,
@@ -26471,7 +28444,7 @@
},
{
"name": "milestoneTitle",
- "description": "Filter epics by milestone title, computed from epic's issues",
+ "description": "Filter epics by milestone title, computed from epic's issues.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26481,7 +28454,7 @@
},
{
"name": "iidStartsWith",
- "description": "Filter epics by IID for autocomplete",
+ "description": "Filter epics by IID for autocomplete.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26491,7 +28464,7 @@
},
{
"name": "includeDescendantGroups",
- "description": "Include epics from descendant groups",
+ "description": "Include epics from descendant groups.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -26500,6 +28473,16 @@
"defaultValue": "true"
},
{
+ "name": "confidential",
+ "description": "Filter epics by given confidentiality.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -26604,7 +28587,7 @@
"args": [
{
"name": "search",
- "description": "Search query",
+ "description": "Search query.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26614,7 +28597,7 @@
},
{
"name": "relations",
- "description": "Filter members by the given member relations",
+ "description": "Filter members by the given member relations.",
"type": {
"kind": "LIST",
"name": null,
@@ -26735,7 +28718,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the issue. For example, \"1\"",
+ "description": "IID of the issue. For example, \"1\".",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26745,7 +28728,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of issues. For example, [1, 2]",
+ "description": "List of IIDs of issues. For example, [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -26763,7 +28746,7 @@
},
{
"name": "labelName",
- "description": "Labels applied to this issue",
+ "description": "Labels applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -26777,7 +28760,7 @@
},
{
"name": "milestoneTitle",
- "description": "Milestone applied to this issue",
+ "description": "Milestone applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -26791,7 +28774,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author of the issue",
+ "description": "Username of the author of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26801,7 +28784,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26811,7 +28794,7 @@
},
{
"name": "assigneeUsernames",
- "description": "Usernames of users assigned to the issue",
+ "description": "Usernames of users assigned to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -26829,7 +28812,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26839,7 +28822,7 @@
},
{
"name": "createdBefore",
- "description": "Issues created before this date",
+ "description": "Issues created before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -26849,7 +28832,7 @@
},
{
"name": "createdAfter",
- "description": "Issues created after this date",
+ "description": "Issues created after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -26859,7 +28842,7 @@
},
{
"name": "updatedBefore",
- "description": "Issues updated before this date",
+ "description": "Issues updated before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -26869,7 +28852,7 @@
},
{
"name": "updatedAfter",
- "description": "Issues updated after this date",
+ "description": "Issues updated after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -26879,7 +28862,7 @@
},
{
"name": "closedBefore",
- "description": "Issues closed before this date",
+ "description": "Issues closed before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -26889,7 +28872,7 @@
},
{
"name": "closedAfter",
- "description": "Issues closed after this date",
+ "description": "Issues closed after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -26899,7 +28882,7 @@
},
{
"name": "search",
- "description": "Search query for issue title or description",
+ "description": "Search query for issue title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -26909,7 +28892,7 @@
},
{
"name": "types",
- "description": "Filter issues by the given issue types",
+ "description": "Filter issues by the given issue types.",
"type": {
"kind": "LIST",
"name": null,
@@ -26927,7 +28910,7 @@
},
{
"name": "state",
- "description": "Current state of this issue",
+ "description": "Current state of this issue.",
"type": {
"kind": "ENUM",
"name": "IssuableState",
@@ -26937,7 +28920,7 @@
},
{
"name": "sort",
- "description": "Sort issues by this criteria",
+ "description": "Sort issues by this criteria.",
"type": {
"kind": "ENUM",
"name": "IssueSort",
@@ -26947,7 +28930,7 @@
},
{
"name": "iterationId",
- "description": "Iterations applied to the issue",
+ "description": "Iterations applied to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -26961,7 +28944,7 @@
},
{
"name": "epicId",
- "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27054,7 +29037,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -27285,7 +29268,7 @@
"args": [
{
"name": "iids",
- "description": "Array of IIDs of merge requests, for example `[1, 2]`",
+ "description": "Array of IIDs of merge requests, for example `[1, 2]`.",
"type": {
"kind": "LIST",
"name": null,
@@ -27367,7 +29350,7 @@
},
{
"name": "mergedAfter",
- "description": "Merge requests merged after this date",
+ "description": "Merge requests merged after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -27377,7 +29360,7 @@
},
{
"name": "mergedBefore",
- "description": "Merge requests merged before this date",
+ "description": "Merge requests merged before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -27387,7 +29370,7 @@
},
{
"name": "milestoneTitle",
- "description": "Title of the milestone",
+ "description": "Title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27397,7 +29380,7 @@
},
{
"name": "sort",
- "description": "Sort merge requests by this criteria",
+ "description": "Sort merge requests by this criteria.",
"type": {
"kind": "ENUM",
"name": "MergeRequestSort",
@@ -27417,7 +29400,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of the assignee",
+ "description": "Username of the assignee.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27427,7 +29410,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author",
+ "description": "Username of the author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27510,7 +29493,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -27520,7 +29503,7 @@
},
{
"name": "ids",
- "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\"",
+ "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\".",
"type": {
"kind": "LIST",
"name": null,
@@ -27538,7 +29521,7 @@
},
{
"name": "state",
- "description": "Filter milestones by state",
+ "description": "Filter milestones by state.",
"type": {
"kind": "ENUM",
"name": "MilestoneStateEnum",
@@ -27548,7 +29531,7 @@
},
{
"name": "title",
- "description": "The title of the milestone",
+ "description": "The title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27558,7 +29541,7 @@
},
{
"name": "searchTitle",
- "description": "A search string for the title",
+ "description": "A search string for the title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27568,7 +29551,7 @@
},
{
"name": "containingDate",
- "description": "A date that the milestone contains",
+ "description": "A date that the milestone contains.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -27578,7 +29561,7 @@
},
{
"name": "includeDescendants",
- "description": "Also return milestones in all subgroups and subprojects",
+ "description": "Also return milestones in all subgroups and subprojects.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -27654,6 +29637,20 @@
"deprecationReason": null
},
{
+ "name": "packageSettings",
+ "description": "The package settings for the namespace",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PackageSettings",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "parent",
"description": "Parent group",
"args": [
@@ -27705,7 +29702,7 @@
"args": [
{
"name": "includeSubgroups",
- "description": "Include also subgroup projects",
+ "description": "Include also subgroup projects.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -27715,7 +29712,7 @@
},
{
"name": "search",
- "description": "Search project with most similar names or paths",
+ "description": "Search project with most similar names or paths.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -27725,7 +29722,7 @@
},
{
"name": "sort",
- "description": "Sort projects by this criteria",
+ "description": "Sort projects by this criteria.",
"type": {
"kind": "ENUM",
"name": "NamespaceProjectSort",
@@ -27735,7 +29732,7 @@
},
{
"name": "hasVulnerabilities",
- "description": "Returns only the projects which have vulnerabilities",
+ "description": "Returns only the projects which have vulnerabilities.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -27932,7 +29929,7 @@
"args": [
{
"name": "startDate",
- "description": "List time logs within a date range where the logged date is equal to or after startDate",
+ "description": "List time logs within a date range where the logged date is equal to or after startDate.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -27942,7 +29939,7 @@
},
{
"name": "endDate",
- "description": "List time logs within a date range where the logged date is equal to or before endDate",
+ "description": "List time logs within a date range where the logged date is equal to or before endDate.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -27952,7 +29949,7 @@
},
{
"name": "startTime",
- "description": "List time-logs within a time range where the logged time is equal to or after startTime",
+ "description": "List time-logs within a time range where the logged time is equal to or after startTime.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -27962,7 +29959,7 @@
},
{
"name": "endTime",
- "description": "List time-logs within a time range where the logged time is equal to or before endTime",
+ "description": "List time-logs within a time range where the logged time is equal to or before endTime.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -28103,7 +30100,7 @@
"args": [
{
"name": "projectId",
- "description": "Filter vulnerabilities by project",
+ "description": "Filter vulnerabilities by project.",
"type": {
"kind": "LIST",
"name": null,
@@ -28121,7 +30118,7 @@
},
{
"name": "reportType",
- "description": "Filter vulnerabilities by report type",
+ "description": "Filter vulnerabilities by report type.",
"type": {
"kind": "LIST",
"name": null,
@@ -28139,7 +30136,7 @@
},
{
"name": "severity",
- "description": "Filter vulnerabilities by severity",
+ "description": "Filter vulnerabilities by severity.",
"type": {
"kind": "LIST",
"name": null,
@@ -28157,7 +30154,7 @@
},
{
"name": "state",
- "description": "Filter vulnerabilities by state",
+ "description": "Filter vulnerabilities by state.",
"type": {
"kind": "LIST",
"name": null,
@@ -28175,7 +30172,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by VulnerabilityScanner.externalId.",
"type": {
"kind": "LIST",
"name": null,
@@ -28193,7 +30190,7 @@
},
{
"name": "sort",
- "description": "List vulnerabilities by sort order",
+ "description": "List vulnerabilities by sort order.",
"type": {
"kind": "ENUM",
"name": "VulnerabilitySort",
@@ -28203,7 +30200,7 @@
},
{
"name": "hasResolution",
- "description": "Returns only the vulnerabilities which have been resolved on default branch",
+ "description": "Returns only the vulnerabilities which have been resolved on default branch.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -28213,7 +30210,7 @@
},
{
"name": "hasIssues",
- "description": "Returns only the vulnerabilities which have linked issues",
+ "description": "Returns only the vulnerabilities which have linked issues.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -28276,7 +30273,7 @@
"args": [
{
"name": "startDate",
- "description": "First day for which to fetch vulnerability history",
+ "description": "First day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -28290,7 +30287,7 @@
},
{
"name": "endDate",
- "description": "Last day for which to fetch vulnerability history",
+ "description": "Last day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -28357,7 +30354,7 @@
"args": [
{
"name": "startDate",
- "description": "First day for which to fetch vulnerability history",
+ "description": "First day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -28371,7 +30368,7 @@
},
{
"name": "endDate",
- "description": "Last day for which to fetch vulnerability history",
+ "description": "Last day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -28438,7 +30435,7 @@
"args": [
{
"name": "includeSubgroups",
- "description": "Include grades belonging to subgroups",
+ "description": "Include grades belonging to subgroups.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -28526,7 +30523,7 @@
"args": [
{
"name": "projectId",
- "description": "Filter vulnerabilities by project",
+ "description": "Filter vulnerabilities by project.",
"type": {
"kind": "LIST",
"name": null,
@@ -28544,7 +30541,7 @@
},
{
"name": "reportType",
- "description": "Filter vulnerabilities by report type",
+ "description": "Filter vulnerabilities by report type.",
"type": {
"kind": "LIST",
"name": null,
@@ -28562,7 +30559,7 @@
},
{
"name": "severity",
- "description": "Filter vulnerabilities by severity",
+ "description": "Filter vulnerabilities by severity.",
"type": {
"kind": "LIST",
"name": null,
@@ -28580,7 +30577,7 @@
},
{
"name": "state",
- "description": "Filter vulnerabilities by state",
+ "description": "Filter vulnerabilities by state.",
"type": {
"kind": "LIST",
"name": null,
@@ -28598,7 +30595,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by scanner.",
"type": {
"kind": "LIST",
"name": null,
@@ -29091,7 +31088,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to create the integration in",
+ "description": "The project to create the integration in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29105,7 +31102,7 @@
},
{
"name": "name",
- "description": "The name of the integration",
+ "description": "The name of the integration.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29119,7 +31116,7 @@
},
{
"name": "active",
- "description": "Whether the integration is receiving alerts",
+ "description": "Whether the integration is receiving alerts.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29132,6 +31129,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": {
@@ -29193,7 +31218,7 @@
},
{
"name": "integration",
- "description": "The HTTP integration",
+ "description": "The HTTP integration.",
"args": [
],
@@ -29221,7 +31246,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the integration to remove",
+ "description": "The ID of the integration to remove.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29295,7 +31320,7 @@
},
{
"name": "integration",
- "description": "The HTTP integration",
+ "description": "The HTTP integration.",
"args": [
],
@@ -29323,7 +31348,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the integration to mutate",
+ "description": "The ID of the integration to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29397,7 +31422,7 @@
},
{
"name": "integration",
- "description": "The HTTP integration",
+ "description": "The HTTP integration.",
"args": [
],
@@ -29425,7 +31450,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the integration to mutate",
+ "description": "The ID of the integration to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29439,7 +31464,7 @@
},
{
"name": "name",
- "description": "The name of the integration",
+ "description": "The name of the integration.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -29449,7 +31474,7 @@
},
{
"name": "active",
- "description": "Whether the integration is receiving alerts",
+ "description": "Whether the integration is receiving alerts.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -29519,7 +31544,7 @@
},
{
"name": "integration",
- "description": "The HTTP integration",
+ "description": "The HTTP integration.",
"args": [
],
@@ -29560,6 +31585,282 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "IncidentManagementOncallParticipantID",
+ "description": "Identifier of IncidentManagement::OncallParticipant",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallRotation",
+ "description": "Describes an incident management on-call rotation",
+ "fields": [
+ {
+ "name": "id",
+ "description": "ID of the on-call rotation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "IncidentManagementOncallRotationID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "length",
+ "description": "Length of the on-call schedule, in the units specified by lengthUnit.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lengthUnit",
+ "description": "Unit of the on-call rotation length.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "OncallRotationUnitEnum",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the on-call rotation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "participants",
+ "description": "Participants of the on-call rotation.",
+ "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": "OncallParticipantTypeConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "startsAt",
+ "description": "Start date of the on-call rotation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallRotationConnection",
+ "description": "The connection type for IncidentManagementOncallRotation.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallRotationEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallRotation",
+ "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": "IncidentManagementOncallRotationEdge",
+ "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": "IncidentManagementOncallRotation",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "IncidentManagementOncallRotationID",
+ "description": "Identifier of IncidentManagement::OncallRotation",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "IncidentManagementOncallSchedule",
"description": "Describes an incident management on-call schedule",
@@ -29615,6 +31916,63 @@
"deprecationReason": null
},
{
+ "name": "rotations",
+ "description": "On-call rotations for the on-call schedule",
+ "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": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallRotationConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "timezone",
"description": "Time zone of the on-call schedule",
"args": [
@@ -29899,7 +32257,7 @@
"args": [
{
"name": "projectId",
- "description": "Filter vulnerabilities by project",
+ "description": "Filter vulnerabilities by project.",
"type": {
"kind": "LIST",
"name": null,
@@ -29917,7 +32275,7 @@
},
{
"name": "reportType",
- "description": "Filter vulnerabilities by report type",
+ "description": "Filter vulnerabilities by report type.",
"type": {
"kind": "LIST",
"name": null,
@@ -29935,7 +32293,7 @@
},
{
"name": "severity",
- "description": "Filter vulnerabilities by severity",
+ "description": "Filter vulnerabilities by severity.",
"type": {
"kind": "LIST",
"name": null,
@@ -29953,7 +32311,7 @@
},
{
"name": "state",
- "description": "Filter vulnerabilities by state",
+ "description": "Filter vulnerabilities by state.",
"type": {
"kind": "LIST",
"name": null,
@@ -29971,7 +32329,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by scanner.",
"type": {
"kind": "LIST",
"name": null,
@@ -30420,6 +32778,20 @@
"deprecationReason": null
},
{
+ "name": "createNoteEmail",
+ "description": "User specific email address for the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createdAt",
"description": "Timestamp of when the issue was created",
"args": [
@@ -31560,7 +33932,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -31574,7 +33946,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -31588,7 +33960,7 @@
},
{
"name": "targetProjectPath",
- "description": "The project to move the issue to",
+ "description": "The project to move the issue to.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -31623,7 +33995,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Project the issue to mutate is in",
+ "description": "Project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -31637,7 +34009,7 @@
},
{
"name": "iid",
- "description": "IID of the issue to mutate",
+ "description": "IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -31651,7 +34023,7 @@
},
{
"name": "boardId",
- "description": "Global ID of the board that the issue is in",
+ "description": "Global ID of the board that the issue is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -31665,7 +34037,7 @@
},
{
"name": "fromListId",
- "description": "ID of the board list that the issue will be moved from",
+ "description": "ID of the board list that the issue will be moved from.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -31675,7 +34047,7 @@
},
{
"name": "toListId",
- "description": "ID of the board list that the issue will be moved to",
+ "description": "ID of the board list that the issue will be moved to.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -31685,7 +34057,7 @@
},
{
"name": "moveBeforeId",
- "description": "ID of issue that should be placed before the current issue",
+ "description": "ID of issue that should be placed before the current issue.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -31695,7 +34067,7 @@
},
{
"name": "moveAfterId",
- "description": "ID of issue that should be placed after the current issue",
+ "description": "ID of issue that should be placed after the current issue.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -31705,7 +34077,7 @@
},
{
"name": "epicId",
- "description": "The ID of the parent epic. NULL when removing the association",
+ "description": "The ID of the parent epic. NULL when removing the association.",
"type": {
"kind": "SCALAR",
"name": "EpicID",
@@ -31775,7 +34147,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -31842,7 +34214,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32027,7 +34399,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32041,7 +34413,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32147,7 +34519,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32175,7 +34547,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32189,7 +34561,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32277,7 +34649,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32305,7 +34677,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32319,7 +34691,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32333,7 +34705,7 @@
},
{
"name": "dueDate",
- "description": "The desired due date for the issue",
+ "description": "The desired due date for the issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32407,7 +34779,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32435,7 +34807,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32449,7 +34821,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32533,7 +34905,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32561,7 +34933,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32575,7 +34947,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32659,7 +35031,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32687,7 +35059,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32701,7 +35073,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32715,7 +35087,7 @@
},
{
"name": "locked",
- "description": "Whether or not to lock discussion on the issue",
+ "description": "Whether or not to lock discussion on the issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32789,7 +35161,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32817,7 +35189,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32831,7 +35203,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32919,7 +35291,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -32947,7 +35319,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32961,7 +35333,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -32975,7 +35347,7 @@
},
{
"name": "subscribedState",
- "description": "The desired state of the subscription",
+ "description": "The desired state of the subscription.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -33049,7 +35421,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -33077,7 +35449,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -33091,7 +35463,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -33105,7 +35477,7 @@
},
{
"name": "weight",
- "description": "The desired weight for the issue",
+ "description": "The desired weight for the issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -33179,7 +35551,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -34210,7 +36582,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to import the Jira project into",
+ "description": "The project to import the Jira project into.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -34224,7 +36596,7 @@
},
{
"name": "jiraProjectKey",
- "description": "Project key of the importer Jira project",
+ "description": "Project key of the importer Jira project.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -34238,7 +36610,7 @@
},
{
"name": "jiraProjectName",
- "description": "Project name of the importer Jira project",
+ "description": "Project name of the importer Jira project.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -34248,7 +36620,7 @@
},
{
"name": "usersMapping",
- "description": "The mapping of Jira to GitLab users",
+ "description": "The mapping of Jira to GitLab users.",
"type": {
"kind": "LIST",
"name": null,
@@ -34326,7 +36698,7 @@
},
{
"name": "jiraImport",
- "description": "The Jira import data after mutation",
+ "description": "The Jira import data after mutation.",
"args": [
],
@@ -34354,7 +36726,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to import the Jira users into",
+ "description": "The project to import the Jira users into.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -34368,7 +36740,7 @@
},
{
"name": "startAt",
- "description": "The index of the record the import should started at, default 0 (50 records returned)",
+ "description": "The index of the record the import should started at, default 0 (50 records returned).",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -34666,7 +37038,7 @@
"args": [
{
"name": "name",
- "description": "Project name or key",
+ "description": "Project name or key.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -35063,6 +37435,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "JsonString",
+ "description": "JSON object as raw string",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "Label",
"description": null,
@@ -35268,7 +37650,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project full path the resource is associated with",
+ "description": "The project full path the resource is associated with.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -35278,7 +37660,7 @@
},
{
"name": "groupPath",
- "description": "The group full path the resource is associated with",
+ "description": "The group full path the resource is associated with.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -35288,7 +37670,7 @@
},
{
"name": "title",
- "description": "Title of the label",
+ "description": "Title of the label.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -35302,7 +37684,7 @@
},
{
"name": "description",
- "description": "Description of the label",
+ "description": "Description of the label.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -35312,7 +37694,7 @@
},
{
"name": "color",
- "description": "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords",
+ "description": "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -35382,7 +37764,7 @@
},
{
"name": "label",
- "description": "The label after mutation",
+ "description": "The label after mutation.",
"args": [
],
@@ -35504,7 +37886,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the snippet to update",
+ "description": "The global ID of the snippet to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -35578,7 +37960,7 @@
},
{
"name": "snippet",
- "description": "The snippet after mutation",
+ "description": "The snippet after mutation.",
"args": [
],
@@ -36113,6 +38495,20 @@
"deprecationReason": null
},
{
+ "name": "autoMergeStrategy",
+ "description": "Selected auto merge strategy",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "availableAutoMergeStrategies",
"description": "Array of available auto merge strategies",
"args": [
@@ -36333,6 +38729,20 @@
"deprecationReason": null
},
{
+ "name": "defaultSquashCommitMessage",
+ "description": "Default squash commit message of the merge request",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "description",
"description": "Description of the merge request (Markdown rendered as HTML for caching)",
"args": [
@@ -36750,6 +39160,20 @@
"deprecationReason": null
},
{
+ "name": "mergeUser",
+ "description": "User who merged this merge request",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "mergeWhenPipelineSucceeds",
"description": "Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS)",
"args": [
@@ -36882,7 +39306,7 @@
},
{
"name": "participants",
- "description": "Participants in the merge request",
+ "description": "Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.",
"args": [
{
"name": "after",
@@ -36939,7 +39363,7 @@
"args": [
{
"name": "status",
- "description": "Filter pipelines by their status",
+ "description": "Filter pipelines by their status.",
"type": {
"kind": "ENUM",
"name": "PipelineStatusEnum",
@@ -36949,7 +39373,7 @@
},
{
"name": "ref",
- "description": "Filter pipelines by the ref they are run for",
+ "description": "Filter pipelines by the ref they are run for.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -36959,7 +39383,7 @@
},
{
"name": "sha",
- "description": "Filter pipelines by the sha of the commit they are run for",
+ "description": "Filter pipelines by the sha of the commit they are run for.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -37112,6 +39536,59 @@
"deprecationReason": null
},
{
+ "name": "reviewers",
+ "description": "Users from whom a review has been requested.",
+ "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": "UserConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "securityAutoFix",
"description": "Indicates if the merge request is created by @GitLab-Security-Bot.",
"args": [
@@ -37240,6 +39717,24 @@
"deprecationReason": null
},
{
+ "name": "squash",
+ "description": "Indicates if squash on merge is enabled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "squashOnMerge",
"description": "Indicates if squash on merge is enabled",
"args": [
@@ -37689,7 +40184,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Project full path the merge request is associated with",
+ "description": "Project full path the merge request is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -37833,7 +40328,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -38336,7 +40831,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38350,7 +40845,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38456,7 +40951,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -38484,7 +40979,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38498,7 +40993,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38604,7 +41099,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -38632,7 +41127,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38646,7 +41141,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38734,7 +41229,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -38762,7 +41257,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38776,7 +41271,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38860,7 +41355,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -38888,7 +41383,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38902,7 +41397,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38916,7 +41411,7 @@
},
{
"name": "subscribedState",
- "description": "The desired state of the subscription",
+ "description": "The desired state of the subscription.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -38990,7 +41485,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -39018,7 +41513,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -39032,7 +41527,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -39120,7 +41615,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -39296,7 +41791,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the merge request to mutate is in",
+ "description": "The project the merge request to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -39310,7 +41805,7 @@
},
{
"name": "iid",
- "description": "The IID of the merge request to mutate",
+ "description": "The IID of the merge request to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -39414,7 +41909,7 @@
},
{
"name": "mergeRequest",
- "description": "The merge request after mutation",
+ "description": "The merge request after mutation.",
"args": [
],
@@ -39589,7 +42084,7 @@
"args": [
{
"name": "from",
- "description": "Timestamp marking date and time from which annotations need to be fetched",
+ "description": "Timestamp marking date and time from which annotations need to be fetched.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -39603,7 +42098,7 @@
},
{
"name": "to",
- "description": "Timestamp marking date and time to which annotations need to be fetched",
+ "description": "Timestamp marking date and time to which annotations need to be fetched.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -40647,6 +43142,33 @@
"deprecationReason": null
},
{
+ "name": "ciCdSettingsUpdate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "CiCdSettingsUpdateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CiCdSettingsUpdatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "clusterAgentDelete",
"description": null,
"args": [
@@ -41970,6 +44492,33 @@
"deprecationReason": null
},
{
+ "name": "exportRequirements",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ExportRequirementsInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ExportRequirementsPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "httpIntegrationCreate",
"description": null,
"args": [
@@ -42726,6 +45275,33 @@
"deprecationReason": null
},
{
+ "name": "oncallRotationCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallRotationCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "OncallRotationCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "oncallScheduleCreate",
"description": null,
"args": [
@@ -43752,6 +46328,33 @@
"deprecationReason": null
},
{
+ "name": "updateNamespacePackageSettings",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "UpdateNamespacePackageSettingsInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "UpdateNamespacePackageSettingsPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updateNote",
"description": "Updates a Note. If the body of the Note contains only quick actions, the Note will be destroyed during the update, and no Note will be returned",
"args": [
@@ -44066,7 +46669,7 @@
},
{
"name": "complianceFrameworks",
- "description": "Compliance frameworks available to projects in this namespace Available only when feature flag `ff_custom_compliance_frameworks` is enabled.",
+ "description": "Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled.",
"args": [
{
"name": "after",
@@ -44107,6 +46710,16 @@
"ofType": null
},
"defaultValue": null
+ },
+ {
+ "name": "id",
+ "description": "Global ID of a specific compliance framework to return.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ComplianceManagementFrameworkID",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"type": {
@@ -44268,6 +46881,20 @@
"deprecationReason": null
},
{
+ "name": "packageSettings",
+ "description": "The package settings for the namespace",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PackageSettings",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "path",
"description": "Path of the namespace",
"args": [
@@ -44291,7 +46918,7 @@
"args": [
{
"name": "includeSubgroups",
- "description": "Include also subgroup projects",
+ "description": "Include also subgroup projects.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -44301,7 +46928,7 @@
},
{
"name": "search",
- "description": "Search project with most similar names or paths",
+ "description": "Search project with most similar names or paths.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -44311,7 +46938,7 @@
},
{
"name": "sort",
- "description": "Sort projects by this criteria",
+ "description": "Sort projects by this criteria.",
"type": {
"kind": "ENUM",
"name": "NamespaceProjectSort",
@@ -44321,7 +46948,7 @@
},
{
"name": "hasVulnerabilities",
- "description": "Returns only the projects which have vulnerabilities",
+ "description": "Returns only the projects which have vulnerabilities.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -44636,7 +47263,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the namespace to mutate",
+ "description": "The global ID of the namespace to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -44710,7 +47337,7 @@
},
{
"name": "namespace",
- "description": "The namespace after mutation",
+ "description": "The namespace after mutation.",
"args": [
],
@@ -45124,6 +47751,20 @@
"deprecationReason": null
},
{
+ "name": "url",
+ "description": "URL to view this Note in the Web UI",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
"args": [
@@ -45578,6 +48219,482 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "OncallParticipantType",
+ "description": "The rotation participant and color palette",
+ "fields": [
+ {
+ "name": "colorPalette",
+ "description": "The color palette to assign to the on-call user. For example \"blue\".",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "colorWeight",
+ "description": "The color weight to assign to for the on-call user, for example \"500\". Max 4 chars. For easy identification of the user.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the on-call participant.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "IncidentManagementOncallParticipantID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "user",
+ "description": "The user who is participating.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "OncallParticipantTypeConnection",
+ "description": "The connection type for OncallParticipantType.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "OncallParticipantTypeEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "OncallParticipantType",
+ "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": "OncallParticipantTypeEdge",
+ "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": "OncallParticipantType",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallRotationCreateInput",
+ "description": "Autogenerated input type of OncallRotationCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project to create the on-call schedule in.",
+ "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 create the on-call rotation in.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the on-call rotation.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "startsAt",
+ "description": "The start date and time of the on-call rotation, in the timezone of the on-call schedule.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallRotationDateInputType",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "rotationLength",
+ "description": "The rotation length of the on-call rotation.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallRotationLengthInputType",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "participants",
+ "description": "The usernames of users participating in the on-call rotation.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallUserInputType",
+ "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": "OncallRotationCreatePayload",
+ "description": "Autogenerated return type of OncallRotationCreate",
+ "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": "OncallRotationDateInputType",
+ "description": "Date input type for on-call rotation",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "date",
+ "description": "The date component of the date in YYYY-MM-DD format.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "time",
+ "description": "The time component of the date in 24hr HH:MM format.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallRotationLengthInputType",
+ "description": "The rotation length of the on-call rotation",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "length",
+ "description": "The rotation length of the on-call rotation.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "unit",
+ "description": "The unit of the rotation length of the on-call rotation.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "OncallRotationUnitEnum",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "OncallRotationUnitEnum",
+ "description": "Rotation length unit of an on-call rotation",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "HOURS",
+ "description": "Hours",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DAYS",
+ "description": "Days",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "WEEKS",
+ "description": "Weeks",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "OncallScheduleCreateInput",
"description": "Autogenerated input type of OncallScheduleCreate",
@@ -45585,7 +48702,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to create the on-call schedule in",
+ "description": "The project to create the on-call schedule in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45599,7 +48716,7 @@
},
{
"name": "name",
- "description": "The name of the on-call schedule",
+ "description": "The name of the on-call schedule.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45613,7 +48730,7 @@
},
{
"name": "description",
- "description": "The description of the on-call schedule",
+ "description": "The description of the on-call schedule.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -45623,7 +48740,7 @@
},
{
"name": "timezone",
- "description": "The timezone of the on-call schedule",
+ "description": "The timezone of the on-call schedule.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45697,7 +48814,7 @@
},
{
"name": "oncallSchedule",
- "description": "The on-call schedule",
+ "description": "The on-call schedule.",
"args": [
],
@@ -45725,7 +48842,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to remove the on-call schedule from",
+ "description": "The project to remove the on-call schedule from.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45739,7 +48856,7 @@
},
{
"name": "iid",
- "description": "The on-call schedule internal ID to remove",
+ "description": "The on-call schedule internal ID to remove.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45813,7 +48930,7 @@
},
{
"name": "oncallSchedule",
- "description": "The on-call schedule",
+ "description": "The on-call schedule.",
"args": [
],
@@ -45841,7 +48958,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to update the on-call schedule in",
+ "description": "The project to update the on-call schedule in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45855,7 +48972,7 @@
},
{
"name": "iid",
- "description": "The on-call schedule internal ID to update",
+ "description": "The on-call schedule internal ID to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -45869,7 +48986,7 @@
},
{
"name": "name",
- "description": "The name of the on-call schedule",
+ "description": "The name of the on-call schedule.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -45879,7 +48996,7 @@
},
{
"name": "description",
- "description": "The description of the on-call schedule",
+ "description": "The description of the on-call schedule.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -45889,7 +49006,7 @@
},
{
"name": "timezone",
- "description": "The timezone of the on-call schedule",
+ "description": "The timezone of the on-call schedule.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -45959,7 +49076,7 @@
},
{
"name": "oncallSchedule",
- "description": "The on-call schedule",
+ "description": "The on-call schedule.",
"args": [
],
@@ -45980,13 +49097,370 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "OncallUserInputType",
+ "description": "The rotation user and color palette",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "username",
+ "description": "The username of the user to participate in the on-call rotation, such as `user_one`.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "colorPalette",
+ "description": "A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user.",
+ "type": {
+ "kind": "ENUM",
+ "name": "DataVisualizationColorEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "colorWeight",
+ "description": "A value of DataVisualizationWeightEnum. The color weight to assign to for the on-call user.",
+ "type": {
+ "kind": "ENUM",
+ "name": "DataVisualizationWeightEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "Package",
- "description": "Represents a package",
+ "description": "Represents a package in the Package Registry",
+ "fields": [
+ {
+ "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.",
+ "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.",
+ "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",
+ "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",
+ "description": "The created date.",
"args": [
],
@@ -46004,7 +49478,7 @@
},
{
"name": "id",
- "description": "The ID of the package",
+ "description": "The ID of the package.",
"args": [
],
@@ -46022,7 +49496,7 @@
},
{
"name": "name",
- "description": "The name of the package",
+ "description": "The name of the package.",
"args": [
],
@@ -46040,7 +49514,7 @@
},
{
"name": "packageType",
- "description": "The type of the package",
+ "description": "The type of the package.",
"args": [
],
@@ -46057,8 +49531,132 @@
"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 update date",
+ "description": "The updated date.",
"args": [
],
@@ -46076,7 +49674,129 @@
},
{
"name": "version",
- "description": "The version of the package",
+ "description": "The version of the package.",
+ "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",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PackageComposerJsonType",
+ "description": "Represents a composer JSON file",
+ "fields": [
+ {
+ "name": "license",
+ "description": "The license set in the Composer JSON file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "The name set in the Composer JSON file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "type",
+ "description": "The type set in the Composer JSON file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "version",
+ "description": "The version set in the Composer JSON file.",
"args": [
],
@@ -46098,6 +49818,55 @@
},
{
"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": [
@@ -46454,6 +50223,248 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "PackageSettings",
+ "description": "Namespace-level Package Registry settings",
+ "fields": [
+ {
+ "name": "mavenDuplicateExceptionRegex",
+ "description": "When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "UntrustedRegexp",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "mavenDuplicatesAllowed",
+ "description": "Indicates whether duplicate Maven packages are allowed for this namespace.",
+ "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": "PackageTag",
+ "description": "Represents a package tag",
+ "fields": [
+ {
+ "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 tag.",
+ "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 tag.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "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
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PackageTagConnection",
+ "description": "The connection type for PackageTag.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PackageTagEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PackageTag",
+ "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": "PackageTagEdge",
+ "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": "PackageTag",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "PackageTypeEnum",
"description": null,
@@ -46519,6 +50530,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "PackagesPackageID",
+ "description": "Identifier of Packages::Package",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "PageInfo",
"description": "Information about pagination in a connection.",
@@ -46851,7 +50872,7 @@
"args": [
{
"name": "securityReportTypes",
- "description": "Filter jobs by the type of security report they produce",
+ "description": "Filter jobs by the type of security report they produce.",
"type": {
"kind": "LIST",
"name": null,
@@ -47428,7 +51449,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the pipeline to mutate",
+ "description": "The ID of the pipeline to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -47660,7 +51681,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the pipeline to mutate",
+ "description": "The ID of the pipeline to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -47860,7 +51881,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the pipeline to mutate",
+ "description": "The ID of the pipeline to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -47934,7 +51955,7 @@
},
{
"name": "pipeline",
- "description": "The pipeline after mutation",
+ "description": "The pipeline after mutation.",
"args": [
],
@@ -48056,7 +52077,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the alert. For example, \"1\"",
+ "description": "IID of the alert. For example, \"1\".",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -48066,7 +52087,7 @@
},
{
"name": "statuses",
- "description": "Alerts with the specified statues. For example, [TRIGGERED]",
+ "description": "Alerts with the specified statues. For example, [TRIGGERED].",
"type": {
"kind": "LIST",
"name": null,
@@ -48084,7 +52105,7 @@
},
{
"name": "sort",
- "description": "Sort alerts by this criteria",
+ "description": "Sort alerts by this criteria.",
"type": {
"kind": "ENUM",
"name": "AlertManagementAlertSort",
@@ -48094,7 +52115,7 @@
},
{
"name": "domain",
- "description": "Filter query for given domain",
+ "description": "Filter query for given domain.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -48118,7 +52139,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -48151,7 +52172,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -48174,7 +52195,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the alert. For example, \"1\"",
+ "description": "IID of the alert. For example, \"1\".",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -48184,7 +52205,7 @@
},
{
"name": "statuses",
- "description": "Alerts with the specified statues. For example, [TRIGGERED]",
+ "description": "Alerts with the specified statues. For example, [TRIGGERED].",
"type": {
"kind": "LIST",
"name": null,
@@ -48202,7 +52223,7 @@
},
{
"name": "sort",
- "description": "Sort alerts by this criteria",
+ "description": "Sort alerts by this criteria.",
"type": {
"kind": "ENUM",
"name": "AlertManagementAlertSort",
@@ -48212,7 +52233,7 @@
},
{
"name": "domain",
- "description": "Filter query for given domain",
+ "description": "Filter query for given domain.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -48236,7 +52257,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -48408,7 +52429,7 @@
"args": [
{
"name": "id",
- "description": "The board's ID",
+ "description": "The board's ID.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -48435,7 +52456,7 @@
"args": [
{
"name": "id",
- "description": "Find a board by its ID",
+ "description": "Find a board by its ID.",
"type": {
"kind": "SCALAR",
"name": "BoardID",
@@ -48512,7 +52533,7 @@
"args": [
{
"name": "name",
- "description": "Name of the cluster agent",
+ "description": "Name of the cluster agent.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -48687,7 +52708,7 @@
"args": [
{
"name": "name",
- "description": "Filter the container repositories by their name",
+ "description": "Filter the container repositories by their name.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -48835,7 +52856,7 @@
"args": [
{
"name": "id",
- "description": "ID of the site profile",
+ "description": "ID of the site profile.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -48910,57 +52931,12 @@
"deprecationReason": null
},
{
- "name": "dastSiteValidation",
- "description": "DAST Site Validation associated with the project. Will always return `null` if `security_on_demand_scans_site_validation` is disabled",
- "args": [
- {
- "name": "normalizedTargetUrls",
- "description": "Normalized URL of the target to be scanned",
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- }
- },
- "defaultValue": null
- },
- {
- "name": "targetUrl",
- "description": "URL of the target to be scanned",
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "defaultValue": null
- }
- ],
- "type": {
- "kind": "OBJECT",
- "name": "DastSiteValidation",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
"name": "dastSiteValidations",
"description": "DAST Site Validations associated with the project. Will always return no nodes if `security_on_demand_scans_site_validation` is disabled",
"args": [
{
"name": "normalizedTargetUrls",
- "description": "Normalized URL of the target to be scanned",
+ "description": "Normalized URL of the target to be scanned.",
"type": {
"kind": "LIST",
"name": null,
@@ -49059,7 +53035,7 @@
"args": [
{
"name": "name",
- "description": "Name of the environment",
+ "description": "Name of the environment.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49069,7 +53045,7 @@
},
{
"name": "search",
- "description": "Search query for environment name",
+ "description": "Search query for environment name.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49079,7 +53055,7 @@
},
{
"name": "states",
- "description": "States of environments that should be included in result",
+ "description": "States of environments that should be included in result.",
"type": {
"kind": "LIST",
"name": null,
@@ -49110,7 +53086,7 @@
"args": [
{
"name": "name",
- "description": "Name of the environment",
+ "description": "Name of the environment.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49120,7 +53096,7 @@
},
{
"name": "search",
- "description": "Search query for environment name",
+ "description": "Search query for environment name.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49130,7 +53106,7 @@
},
{
"name": "states",
- "description": "States of environments that should be included in result",
+ "description": "States of environments that should be included in result.",
"type": {
"kind": "LIST",
"name": null,
@@ -49364,7 +53340,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the issue. For example, \"1\"",
+ "description": "IID of the issue. For example, \"1\".",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49374,7 +53350,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of issues. For example, [1, 2]",
+ "description": "List of IIDs of issues. For example, [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -49392,7 +53368,7 @@
},
{
"name": "labelName",
- "description": "Labels applied to this issue",
+ "description": "Labels applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49406,7 +53382,7 @@
},
{
"name": "milestoneTitle",
- "description": "Milestone applied to this issue",
+ "description": "Milestone applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49420,7 +53396,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author of the issue",
+ "description": "Username of the author of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49430,7 +53406,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49440,7 +53416,7 @@
},
{
"name": "assigneeUsernames",
- "description": "Usernames of users assigned to the issue",
+ "description": "Usernames of users assigned to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49458,7 +53434,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49468,7 +53444,7 @@
},
{
"name": "createdBefore",
- "description": "Issues created before this date",
+ "description": "Issues created before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49478,7 +53454,7 @@
},
{
"name": "createdAfter",
- "description": "Issues created after this date",
+ "description": "Issues created after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49488,7 +53464,7 @@
},
{
"name": "updatedBefore",
- "description": "Issues updated before this date",
+ "description": "Issues updated before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49498,7 +53474,7 @@
},
{
"name": "updatedAfter",
- "description": "Issues updated after this date",
+ "description": "Issues updated after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49508,7 +53484,7 @@
},
{
"name": "closedBefore",
- "description": "Issues closed before this date",
+ "description": "Issues closed before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49518,7 +53494,7 @@
},
{
"name": "closedAfter",
- "description": "Issues closed after this date",
+ "description": "Issues closed after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49528,7 +53504,7 @@
},
{
"name": "search",
- "description": "Search query for issue title or description",
+ "description": "Search query for issue title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49538,7 +53514,7 @@
},
{
"name": "types",
- "description": "Filter issues by the given issue types",
+ "description": "Filter issues by the given issue types.",
"type": {
"kind": "LIST",
"name": null,
@@ -49556,7 +53532,7 @@
},
{
"name": "state",
- "description": "Current state of this issue",
+ "description": "Current state of this issue.",
"type": {
"kind": "ENUM",
"name": "IssuableState",
@@ -49566,7 +53542,7 @@
},
{
"name": "sort",
- "description": "Sort issues by this criteria",
+ "description": "Sort issues by this criteria.",
"type": {
"kind": "ENUM",
"name": "IssueSort",
@@ -49576,7 +53552,7 @@
},
{
"name": "iterationId",
- "description": "Iterations applied to the issue",
+ "description": "Iterations applied to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49590,7 +53566,7 @@
},
{
"name": "epicId",
- "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49613,7 +53589,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the issue. For example, \"1\"",
+ "description": "IID of the issue. For example, \"1\".",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49623,7 +53599,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of issues. For example, [1, 2]",
+ "description": "List of IIDs of issues. For example, [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -49641,7 +53617,7 @@
},
{
"name": "labelName",
- "description": "Labels applied to this issue",
+ "description": "Labels applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49655,7 +53631,7 @@
},
{
"name": "milestoneTitle",
- "description": "Milestone applied to this issue",
+ "description": "Milestone applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49669,7 +53645,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author of the issue",
+ "description": "Username of the author of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49679,7 +53655,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49689,7 +53665,7 @@
},
{
"name": "assigneeUsernames",
- "description": "Usernames of users assigned to the issue",
+ "description": "Usernames of users assigned to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49707,7 +53683,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49717,7 +53693,7 @@
},
{
"name": "createdBefore",
- "description": "Issues created before this date",
+ "description": "Issues created before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49727,7 +53703,7 @@
},
{
"name": "createdAfter",
- "description": "Issues created after this date",
+ "description": "Issues created after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49737,7 +53713,7 @@
},
{
"name": "updatedBefore",
- "description": "Issues updated before this date",
+ "description": "Issues updated before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49747,7 +53723,7 @@
},
{
"name": "updatedAfter",
- "description": "Issues updated after this date",
+ "description": "Issues updated after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49757,7 +53733,7 @@
},
{
"name": "closedBefore",
- "description": "Issues closed before this date",
+ "description": "Issues closed before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49767,7 +53743,7 @@
},
{
"name": "closedAfter",
- "description": "Issues closed after this date",
+ "description": "Issues closed after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49777,7 +53753,7 @@
},
{
"name": "search",
- "description": "Search query for issue title or description",
+ "description": "Search query for issue title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49787,7 +53763,7 @@
},
{
"name": "types",
- "description": "Filter issues by the given issue types",
+ "description": "Filter issues by the given issue types.",
"type": {
"kind": "LIST",
"name": null,
@@ -49818,7 +53794,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the issue. For example, \"1\"",
+ "description": "IID of the issue. For example, \"1\".",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49828,7 +53804,7 @@
},
{
"name": "iids",
- "description": "List of IIDs of issues. For example, [1, 2]",
+ "description": "List of IIDs of issues. For example, [1, 2].",
"type": {
"kind": "LIST",
"name": null,
@@ -49846,7 +53822,7 @@
},
{
"name": "labelName",
- "description": "Labels applied to this issue",
+ "description": "Labels applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49860,7 +53836,7 @@
},
{
"name": "milestoneTitle",
- "description": "Milestone applied to this issue",
+ "description": "Milestone applied to this issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49874,7 +53850,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author of the issue",
+ "description": "Username of the author of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49884,7 +53860,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of a user assigned to the issue",
+ "description": "Username of a user assigned to the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49894,7 +53870,7 @@
},
{
"name": "assigneeUsernames",
- "description": "Usernames of users assigned to the issue",
+ "description": "Usernames of users assigned to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -49912,7 +53888,7 @@
},
{
"name": "assigneeId",
- "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49922,7 +53898,7 @@
},
{
"name": "createdBefore",
- "description": "Issues created before this date",
+ "description": "Issues created before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49932,7 +53908,7 @@
},
{
"name": "createdAfter",
- "description": "Issues created after this date",
+ "description": "Issues created after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49942,7 +53918,7 @@
},
{
"name": "updatedBefore",
- "description": "Issues updated before this date",
+ "description": "Issues updated before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49952,7 +53928,7 @@
},
{
"name": "updatedAfter",
- "description": "Issues updated after this date",
+ "description": "Issues updated after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49962,7 +53938,7 @@
},
{
"name": "closedBefore",
- "description": "Issues closed before this date",
+ "description": "Issues closed before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49972,7 +53948,7 @@
},
{
"name": "closedAfter",
- "description": "Issues closed after this date",
+ "description": "Issues closed after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -49982,7 +53958,7 @@
},
{
"name": "search",
- "description": "Search query for issue title or description",
+ "description": "Search query for issue title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -49992,7 +53968,7 @@
},
{
"name": "types",
- "description": "Filter issues by the given issue types",
+ "description": "Filter issues by the given issue types.",
"type": {
"kind": "LIST",
"name": null,
@@ -50010,7 +53986,7 @@
},
{
"name": "state",
- "description": "Current state of this issue",
+ "description": "Current state of this issue.",
"type": {
"kind": "ENUM",
"name": "IssuableState",
@@ -50020,7 +53996,7 @@
},
{
"name": "sort",
- "description": "Sort issues by this criteria",
+ "description": "Sort issues by this criteria.",
"type": {
"kind": "ENUM",
"name": "IssueSort",
@@ -50030,7 +54006,7 @@
},
{
"name": "iterationId",
- "description": "Iterations applied to the issue",
+ "description": "Iterations applied to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -50044,7 +54020,7 @@
},
{
"name": "epicId",
- "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported",
+ "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50141,7 +54117,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -50453,7 +54429,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the merge request, for example `1`",
+ "description": "IID of the merge request, for example `1`.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -50480,7 +54456,7 @@
"args": [
{
"name": "iids",
- "description": "Array of IIDs of merge requests, for example `[1, 2]`",
+ "description": "Array of IIDs of merge requests, for example `[1, 2]`.",
"type": {
"kind": "LIST",
"name": null,
@@ -50562,7 +54538,7 @@
},
{
"name": "mergedAfter",
- "description": "Merge requests merged after this date",
+ "description": "Merge requests merged after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -50572,7 +54548,7 @@
},
{
"name": "mergedBefore",
- "description": "Merge requests merged before this date",
+ "description": "Merge requests merged before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -50582,7 +54558,7 @@
},
{
"name": "milestoneTitle",
- "description": "Title of the milestone",
+ "description": "Title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50592,7 +54568,7 @@
},
{
"name": "sort",
- "description": "Sort merge requests by this criteria",
+ "description": "Sort merge requests by this criteria.",
"type": {
"kind": "ENUM",
"name": "MergeRequestSort",
@@ -50602,7 +54578,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of the assignee",
+ "description": "Username of the assignee.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50612,7 +54588,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author",
+ "description": "Username of the author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50622,7 +54598,7 @@
},
{
"name": "reviewerUsername",
- "description": "Username of the reviewer",
+ "description": "Username of the reviewer.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50733,7 +54709,7 @@
},
{
"name": "timeframe",
- "description": "List items overlapping the given timeframe",
+ "description": "List items overlapping the given timeframe.",
"type": {
"kind": "INPUT_OBJECT",
"name": "Timeframe",
@@ -50743,7 +54719,7 @@
},
{
"name": "ids",
- "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\"",
+ "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\".",
"type": {
"kind": "LIST",
"name": null,
@@ -50761,7 +54737,7 @@
},
{
"name": "state",
- "description": "Filter milestones by state",
+ "description": "Filter milestones by state.",
"type": {
"kind": "ENUM",
"name": "MilestoneStateEnum",
@@ -50771,7 +54747,7 @@
},
{
"name": "title",
- "description": "The title of the milestone",
+ "description": "The title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50781,7 +54757,7 @@
},
{
"name": "searchTitle",
- "description": "A search string for the title",
+ "description": "A search string for the title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -50791,7 +54767,7 @@
},
{
"name": "containingDate",
- "description": "A date that the milestone contains",
+ "description": "A date that the milestone contains.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -50801,7 +54777,7 @@
},
{
"name": "includeAncestors",
- "description": "Also return milestones in the project's parent group and its ancestors",
+ "description": "Also return milestones in the project's parent group and its ancestors.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -51027,7 +55003,7 @@
"args": [
{
"name": "iid",
- "description": "IID of the Pipeline, e.g., \"1\"",
+ "description": "IID of the Pipeline, e.g., \"1\".",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -51068,7 +55044,7 @@
"args": [
{
"name": "status",
- "description": "Filter pipelines by their status",
+ "description": "Filter pipelines by their status.",
"type": {
"kind": "ENUM",
"name": "PipelineStatusEnum",
@@ -51078,7 +55054,7 @@
},
{
"name": "ref",
- "description": "Filter pipelines by the ref they are run for",
+ "description": "Filter pipelines by the ref they are run for.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -51088,7 +55064,7 @@
},
{
"name": "sha",
- "description": "Filter pipelines by the sha of the commit they are run for",
+ "description": "Filter pipelines by the sha of the commit they are run for.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -51165,7 +55141,7 @@
"args": [
{
"name": "search",
- "description": "Search query",
+ "description": "Search query.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -51175,7 +55151,7 @@
},
{
"name": "relations",
- "description": "Filter members by the given member relations",
+ "description": "Filter members by the given member relations.",
"type": {
"kind": "LIST",
"name": null,
@@ -51260,7 +55236,7 @@
"args": [
{
"name": "tagName",
- "description": "The name of the tag associated to the release",
+ "description": "The name of the tag associated to the release.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -51287,7 +55263,7 @@
"args": [
{
"name": "sort",
- "description": "Sort releases by this criteria",
+ "description": "Sort releases by this criteria.",
"type": {
"kind": "ENUM",
"name": "ReleaseSort",
@@ -51405,36 +55381,8 @@
"description": "Find a single requirement",
"args": [
{
- "name": "iid",
- "description": "IID of the requirement, e.g., \"1\"",
- "type": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "iids",
- "description": "List of IIDs of requirements, e.g., [1, 2]",
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- }
- }
- },
- "defaultValue": null
- },
- {
"name": "sort",
- "description": "List requirements by sort order",
+ "description": "List requirements by sort order.",
"type": {
"kind": "ENUM",
"name": "Sort",
@@ -51444,7 +55392,7 @@
},
{
"name": "state",
- "description": "Filter requirements by state",
+ "description": "Filter requirements by state.",
"type": {
"kind": "ENUM",
"name": "RequirementState",
@@ -51454,7 +55402,7 @@
},
{
"name": "search",
- "description": "Search query for requirement title",
+ "description": "Search query for requirement title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -51464,7 +55412,7 @@
},
{
"name": "authorUsername",
- "description": "Filter requirements by author username",
+ "description": "Filter requirements by author username.",
"type": {
"kind": "LIST",
"name": null,
@@ -51479,6 +55427,34 @@
}
},
"defaultValue": null
+ },
+ {
+ "name": "iid",
+ "description": "IID of the requirement, e.g., \"1\".",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iids",
+ "description": "List of IIDs of requirements, e.g., [1, 2].",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
}
],
"type": {
@@ -51508,36 +55484,8 @@
"description": "Find requirements",
"args": [
{
- "name": "iid",
- "description": "IID of the requirement, e.g., \"1\"",
- "type": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "iids",
- "description": "List of IIDs of requirements, e.g., [1, 2]",
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- }
- }
- },
- "defaultValue": null
- },
- {
"name": "sort",
- "description": "List requirements by sort order",
+ "description": "List requirements by sort order.",
"type": {
"kind": "ENUM",
"name": "Sort",
@@ -51547,7 +55495,7 @@
},
{
"name": "state",
- "description": "Filter requirements by state",
+ "description": "Filter requirements by state.",
"type": {
"kind": "ENUM",
"name": "RequirementState",
@@ -51557,7 +55505,7 @@
},
{
"name": "search",
- "description": "Search query for requirement title",
+ "description": "Search query for requirement title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -51567,7 +55515,7 @@
},
{
"name": "authorUsername",
- "description": "Filter requirements by author username",
+ "description": "Filter requirements by author username.",
"type": {
"kind": "LIST",
"name": null,
@@ -51584,6 +55532,34 @@
"defaultValue": null
},
{
+ "name": "iid",
+ "description": "IID of the requirement, e.g., \"1\".",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iids",
+ "description": "List of IIDs of requirements, e.g., [1, 2].",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -51680,7 +55656,7 @@
"args": [
{
"name": "id",
- "description": "ID of the Sentry issue",
+ "description": "ID of the Sentry issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -51749,7 +55725,7 @@
"args": [
{
"name": "active",
- "description": "Indicates if the service is active",
+ "description": "Indicates if the service is active.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -51759,7 +55735,7 @@
},
{
"name": "type",
- "description": "Class name of the service",
+ "description": "Class name of the service.",
"type": {
"kind": "ENUM",
"name": "ServiceType",
@@ -51836,7 +55812,7 @@
"args": [
{
"name": "ids",
- "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"",
+ "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\".",
"type": {
"kind": "LIST",
"name": null,
@@ -51854,7 +55830,7 @@
},
{
"name": "visibility",
- "description": "The visibility of the snippet",
+ "description": "The visibility of the snippet.",
"type": {
"kind": "ENUM",
"name": "VisibilityScopesEnum",
@@ -52071,20 +56047,6 @@
"deprecationReason": null
},
{
- "name": "totalPipelineDuration",
- "description": "Total pipeline duration for all of the pipelines in a project",
- "args": [
-
- ],
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
"args": [
@@ -52122,7 +56084,7 @@
"args": [
{
"name": "projectId",
- "description": "Filter vulnerabilities by project",
+ "description": "Filter vulnerabilities by project.",
"type": {
"kind": "LIST",
"name": null,
@@ -52140,7 +56102,7 @@
},
{
"name": "reportType",
- "description": "Filter vulnerabilities by report type",
+ "description": "Filter vulnerabilities by report type.",
"type": {
"kind": "LIST",
"name": null,
@@ -52158,7 +56120,7 @@
},
{
"name": "severity",
- "description": "Filter vulnerabilities by severity",
+ "description": "Filter vulnerabilities by severity.",
"type": {
"kind": "LIST",
"name": null,
@@ -52176,7 +56138,7 @@
},
{
"name": "state",
- "description": "Filter vulnerabilities by state",
+ "description": "Filter vulnerabilities by state.",
"type": {
"kind": "LIST",
"name": null,
@@ -52194,7 +56156,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by VulnerabilityScanner.externalId.",
"type": {
"kind": "LIST",
"name": null,
@@ -52212,7 +56174,7 @@
},
{
"name": "sort",
- "description": "List vulnerabilities by sort order",
+ "description": "List vulnerabilities by sort order.",
"type": {
"kind": "ENUM",
"name": "VulnerabilitySort",
@@ -52222,7 +56184,7 @@
},
{
"name": "hasResolution",
- "description": "Returns only the vulnerabilities which have been resolved on default branch",
+ "description": "Returns only the vulnerabilities which have been resolved on default branch.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -52232,7 +56194,7 @@
},
{
"name": "hasIssues",
- "description": "Returns only the vulnerabilities which have linked issues",
+ "description": "Returns only the vulnerabilities which have linked issues.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -52295,7 +56257,7 @@
"args": [
{
"name": "startDate",
- "description": "First day for which to fetch vulnerability history",
+ "description": "First day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -52309,7 +56271,7 @@
},
{
"name": "endDate",
- "description": "Last day for which to fetch vulnerability history",
+ "description": "Last day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -52429,7 +56391,7 @@
"args": [
{
"name": "projectId",
- "description": "Filter vulnerabilities by project",
+ "description": "Filter vulnerabilities by project.",
"type": {
"kind": "LIST",
"name": null,
@@ -52447,7 +56409,7 @@
},
{
"name": "reportType",
- "description": "Filter vulnerabilities by report type",
+ "description": "Filter vulnerabilities by report type.",
"type": {
"kind": "LIST",
"name": null,
@@ -52465,7 +56427,7 @@
},
{
"name": "severity",
- "description": "Filter vulnerabilities by severity",
+ "description": "Filter vulnerabilities by severity.",
"type": {
"kind": "LIST",
"name": null,
@@ -52483,7 +56445,7 @@
},
{
"name": "state",
- "description": "Filter vulnerabilities by state",
+ "description": "Filter vulnerabilities by state.",
"type": {
"kind": "LIST",
"name": null,
@@ -52501,7 +56463,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by scanner.",
"type": {
"kind": "LIST",
"name": null,
@@ -52568,6 +56530,20 @@
"description": null,
"fields": [
{
+ "name": "keepLatestArtifact",
+ "description": "Whether to keep the latest builds artifacts.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "mergePipelinesEnabled",
"description": "Whether merge pipelines are enabled.",
"args": [
@@ -54030,7 +58006,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project to create the integration in",
+ "description": "The project to create the integration in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54044,7 +58020,7 @@
},
{
"name": "active",
- "description": "Whether the integration is receiving alerts",
+ "description": "Whether the integration is receiving alerts.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54058,7 +58034,7 @@
},
{
"name": "apiUrl",
- "description": "Endpoint at which prometheus can be queried",
+ "description": "Endpoint at which prometheus can be queried.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54132,7 +58108,7 @@
},
{
"name": "integration",
- "description": "The newly created integration",
+ "description": "The newly created integration.",
"args": [
],
@@ -54160,7 +58136,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the integration to mutate",
+ "description": "The ID of the integration to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54234,7 +58210,7 @@
},
{
"name": "integration",
- "description": "The newly created integration",
+ "description": "The newly created integration.",
"args": [
],
@@ -54262,7 +58238,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the integration to mutate",
+ "description": "The ID of the integration to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54276,7 +58252,7 @@
},
{
"name": "active",
- "description": "Whether the integration is receiving alerts",
+ "description": "Whether the integration is receiving alerts.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -54286,7 +58262,7 @@
},
{
"name": "apiUrl",
- "description": "Endpoint at which prometheus can be queried",
+ "description": "Endpoint at which prometheus can be queried.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -54356,7 +58332,7 @@
},
{
"name": "integration",
- "description": "The newly created integration",
+ "description": "The newly created integration.",
"args": [
],
@@ -54394,7 +58370,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54408,7 +58384,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54422,7 +58398,7 @@
},
{
"name": "groupPath",
- "description": "The group the promoted epic will belong to",
+ "description": "The group the promoted epic will belong to.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -54466,7 +58442,7 @@
},
{
"name": "epic",
- "description": "The epic after issue promotion",
+ "description": "The epic after issue promotion.",
"args": [
],
@@ -54506,7 +58482,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -54536,8 +58512,22 @@
"description": "Get linted and processed contents of a CI config. Should not be requested more than once per request.",
"args": [
{
+ "name": "projectPath",
+ "description": "The project of the CI config.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "content",
- "description": "Contents of .gitlab-ci.yml",
+ "description": "Contents of '.gitlab-ci.yml'.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54548,6 +58538,16 @@
}
},
"defaultValue": null
+ },
+ {
+ "name": "dryRun",
+ "description": "Run pipeline creation simulation, or only do static check.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"type": {
@@ -54676,7 +58676,7 @@
"args": [
{
"name": "text",
- "description": "Text to echo back",
+ "description": "Text to echo back.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54730,7 +58730,7 @@
"args": [
{
"name": "fullPath",
- "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\"",
+ "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\".",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54771,7 +58771,7 @@
"args": [
{
"name": "identifier",
- "description": "The type of measurement/statistics to retrieve",
+ "description": "The type of measurement/statistics to retrieve.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54785,7 +58785,7 @@
},
{
"name": "recordedAfter",
- "description": "Measurement recorded after this date",
+ "description": "Measurement recorded after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -54795,7 +58795,7 @@
},
{
"name": "recordedBefore",
- "description": "Measurement recorded before this date",
+ "description": "Measurement recorded before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -54953,7 +58953,7 @@
"args": [
{
"name": "fullPath",
- "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\"",
+ "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\".",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54975,12 +58975,39 @@
"deprecationReason": null
},
{
+ "name": "packageComposerDetails",
+ "description": "Find a composer package",
+ "args": [
+ {
+ "name": "id",
+ "description": "The global ID of the package.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "PackagesPackageID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PackageComposerDetails",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "project",
"description": "Find a project",
"args": [
{
"name": "fullPath",
- "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\"",
+ "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\".",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -55007,7 +59034,7 @@
"args": [
{
"name": "membership",
- "description": "Limit projects that the current user is a member of",
+ "description": "Limit projects that the current user is a member of.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -55017,7 +59044,7 @@
},
{
"name": "search",
- "description": "Search query for project name, path, or description",
+ "description": "Search query for project name, path, or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -55027,7 +59054,7 @@
},
{
"name": "ids",
- "description": "Filter projects by IDs",
+ "description": "Filter projects by IDs.",
"type": {
"kind": "LIST",
"name": null,
@@ -55045,7 +59072,7 @@
},
{
"name": "searchNamespaces",
- "description": "Include namespace in project search",
+ "description": "Include namespace in project search.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -55055,7 +59082,7 @@
},
{
"name": "sort",
- "description": "Sort order of results",
+ "description": "Sort order of results.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -55171,7 +59198,7 @@
"args": [
{
"name": "platform",
- "description": "Platform to generate the instructions for",
+ "description": "Platform to generate the instructions for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -55185,7 +59212,7 @@
},
{
"name": "architecture",
- "description": "Architecture to generate the instructions for",
+ "description": "Architecture to generate the instructions for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -55199,7 +59226,7 @@
},
{
"name": "projectId",
- "description": "Project to register the runner for",
+ "description": "Project to register the runner for.",
"type": {
"kind": "SCALAR",
"name": "ProjectID",
@@ -55209,7 +59236,7 @@
},
{
"name": "groupId",
- "description": "Group to register the runner for",
+ "description": "Group to register the runner for.",
"type": {
"kind": "SCALAR",
"name": "GroupID",
@@ -55232,7 +59259,7 @@
"args": [
{
"name": "ids",
- "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"",
+ "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\".",
"type": {
"kind": "LIST",
"name": null,
@@ -55250,7 +59277,7 @@
},
{
"name": "visibility",
- "description": "The visibility of the snippet",
+ "description": "The visibility of the snippet.",
"type": {
"kind": "ENUM",
"name": "VisibilityScopesEnum",
@@ -55260,7 +59287,7 @@
},
{
"name": "authorId",
- "description": "The ID of an author",
+ "description": "The ID of an author.",
"type": {
"kind": "SCALAR",
"name": "UserID",
@@ -55270,7 +59297,7 @@
},
{
"name": "projectId",
- "description": "The ID of a project",
+ "description": "The ID of a project.",
"type": {
"kind": "SCALAR",
"name": "ProjectID",
@@ -55280,7 +59307,7 @@
},
{
"name": "type",
- "description": "The type of snippet",
+ "description": "The type of snippet.",
"type": {
"kind": "ENUM",
"name": "TypeEnum",
@@ -55290,7 +59317,7 @@
},
{
"name": "explore",
- "description": "Explore personal snippets",
+ "description": "Explore personal snippets.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -55353,7 +59380,7 @@
"args": [
{
"name": "id",
- "description": "ID of the User",
+ "description": "ID of the User.",
"type": {
"kind": "SCALAR",
"name": "UserID",
@@ -55363,7 +59390,7 @@
},
{
"name": "username",
- "description": "Username of the User",
+ "description": "Username of the User.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -55386,7 +59413,7 @@
"args": [
{
"name": "ids",
- "description": "List of user Global IDs",
+ "description": "List of user Global IDs.",
"type": {
"kind": "LIST",
"name": null,
@@ -55404,7 +59431,7 @@
},
{
"name": "usernames",
- "description": "List of usernames",
+ "description": "List of usernames.",
"type": {
"kind": "LIST",
"name": null,
@@ -55422,7 +59449,7 @@
},
{
"name": "sort",
- "description": "Sort users by this criteria",
+ "description": "Sort users by this criteria.",
"type": {
"kind": "ENUM",
"name": "Sort",
@@ -55441,6 +59468,16 @@
"defaultValue": null
},
{
+ "name": "admins",
+ "description": "Return only admin users.",
+ "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": {
@@ -55495,7 +59532,7 @@
"args": [
{
"name": "projectId",
- "description": "Filter vulnerabilities by project",
+ "description": "Filter vulnerabilities by project.",
"type": {
"kind": "LIST",
"name": null,
@@ -55513,7 +59550,7 @@
},
{
"name": "reportType",
- "description": "Filter vulnerabilities by report type",
+ "description": "Filter vulnerabilities by report type.",
"type": {
"kind": "LIST",
"name": null,
@@ -55531,7 +59568,7 @@
},
{
"name": "severity",
- "description": "Filter vulnerabilities by severity",
+ "description": "Filter vulnerabilities by severity.",
"type": {
"kind": "LIST",
"name": null,
@@ -55549,7 +59586,7 @@
},
{
"name": "state",
- "description": "Filter vulnerabilities by state",
+ "description": "Filter vulnerabilities by state.",
"type": {
"kind": "LIST",
"name": null,
@@ -55567,7 +59604,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by VulnerabilityScanner.externalId.",
"type": {
"kind": "LIST",
"name": null,
@@ -55585,7 +59622,7 @@
},
{
"name": "sort",
- "description": "List vulnerabilities by sort order",
+ "description": "List vulnerabilities by sort order.",
"type": {
"kind": "ENUM",
"name": "VulnerabilitySort",
@@ -55595,7 +59632,7 @@
},
{
"name": "hasResolution",
- "description": "Returns only the vulnerabilities which have been resolved on default branch",
+ "description": "Returns only the vulnerabilities which have been resolved on default branch.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -55605,7 +59642,7 @@
},
{
"name": "hasIssues",
- "description": "Returns only the vulnerabilities which have linked issues",
+ "description": "Returns only the vulnerabilities which have linked issues.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -55668,7 +59705,7 @@
"args": [
{
"name": "startDate",
- "description": "First day for which to fetch vulnerability history",
+ "description": "First day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -55682,7 +59719,7 @@
},
{
"name": "endDate",
- "description": "Last day for which to fetch vulnerability history",
+ "description": "Last day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -55749,7 +59786,7 @@
"args": [
{
"name": "startDate",
- "description": "First day for which to fetch vulnerability history",
+ "description": "First day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -55763,7 +59800,7 @@
},
{
"name": "endDate",
- "description": "Last day for which to fetch vulnerability history",
+ "description": "Last day for which to fetch vulnerability history.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -56743,7 +60780,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Full path of the project the release is associated with",
+ "description": "Full path of the project the release is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -56757,7 +60794,7 @@
},
{
"name": "tagName",
- "description": "Name of the tag to associate with the release",
+ "description": "Name of the tag to associate with the release.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -56771,7 +60808,7 @@
},
{
"name": "ref",
- "description": "The commit SHA or branch name to use if creating a new tag",
+ "description": "The commit SHA or branch name to use if creating a new tag.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -56781,7 +60818,7 @@
},
{
"name": "name",
- "description": "Name of the release",
+ "description": "Name of the release.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -56791,7 +60828,7 @@
},
{
"name": "description",
- "description": "Description (also known as \"release notes\") of the release",
+ "description": "Description (also known as \"release notes\") of the release.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -56829,7 +60866,7 @@
},
{
"name": "assets",
- "description": "Assets associated to the release",
+ "description": "Assets associated to the release.",
"type": {
"kind": "INPUT_OBJECT",
"name": "ReleaseAssetsInput",
@@ -56899,7 +60936,7 @@
},
{
"name": "release",
- "description": "The release after mutation",
+ "description": "The release after mutation.",
"args": [
],
@@ -56927,7 +60964,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Full path of the project the release is associated with",
+ "description": "Full path of the project the release is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -57572,7 +61609,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Full path of the project the release is associated with",
+ "description": "Full path of the project the release is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -57586,7 +61623,7 @@
},
{
"name": "tagName",
- "description": "Name of the tag associated with the release",
+ "description": "Name of the tag associated with the release.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -57600,7 +61637,7 @@
},
{
"name": "name",
- "description": "Name of the release",
+ "description": "Name of the release.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -57610,7 +61647,7 @@
},
{
"name": "description",
- "description": "Description (release notes) of the release",
+ "description": "Description (release notes) of the release.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -57620,7 +61657,7 @@
},
{
"name": "releasedAt",
- "description": "The release date",
+ "description": "The release date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -57736,7 +61773,7 @@
"inputFields": [
{
"name": "awardableId",
- "description": "The global ID of the awardable resource",
+ "description": "The global ID of the awardable resource.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -57784,7 +61821,7 @@
"fields": [
{
"name": "awardEmoji",
- "description": "The award emoji after mutation",
+ "description": "The award emoji after mutation.",
"args": [
],
@@ -57852,7 +61889,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the project to remove from the Instance Security Dashboard",
+ "description": "ID of the project to remove from the Instance Security Dashboard.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -57940,7 +61977,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the DiffNote to update",
+ "description": "The global ID of the DiffNote to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -58028,7 +62065,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -58109,7 +62146,7 @@
"args": [
{
"name": "path",
- "description": "The path to get the tree for. Default value is the root of the repository",
+ "description": "The path to get the tree for. Default value is the root of the repository.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -58119,7 +62156,7 @@
},
{
"name": "ref",
- "description": "The commit ref to get the tree for. Default value is HEAD",
+ "description": "The commit ref to get the tree for. Default value is HEAD.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -58129,7 +62166,7 @@
},
{
"name": "recursive",
- "description": "Used to get a recursive tree. Default is false",
+ "description": "Used to get a recursive tree. Default is false.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -58329,7 +62366,7 @@
"args": [
{
"name": "sort",
- "description": "List test reports by sort order",
+ "description": "List test reports by sort order.",
"type": {
"kind": "ENUM",
"name": "Sort",
@@ -58831,7 +62868,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the vulnerability to be reverted",
+ "description": "ID of the vulnerability to be reverted.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -58905,7 +62942,7 @@
},
{
"name": "vulnerability",
- "description": "The vulnerability after revert",
+ "description": "The vulnerability after revert.",
"args": [
],
@@ -62079,7 +66116,7 @@
"args": [
{
"name": "id",
- "description": "ID of the Sentry issue",
+ "description": "ID of the Sentry issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -62106,7 +66143,7 @@
"args": [
{
"name": "id",
- "description": "ID of the Sentry issue",
+ "description": "ID of the Sentry issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -62133,7 +66170,7 @@
"args": [
{
"name": "searchTerm",
- "description": "Search query for the Sentry error details",
+ "description": "Search query for the Sentry error details.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -62143,7 +66180,7 @@
},
{
"name": "sort",
- "description": "Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default",
+ "description": "Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -62845,12 +66882,6 @@
"interfaces": null,
"enumValues": [
{
- "name": "ALERTS_SERVICE",
- "description": null,
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
"name": "ASANA_SERVICE",
"description": null,
"isDeprecated": false,
@@ -63112,7 +67143,7 @@
"args": [
{
"name": "paths",
- "description": "Paths of the blobs",
+ "description": "Paths of the blobs.",
"type": {
"kind": "LIST",
"name": null,
@@ -65247,7 +69278,7 @@
"inputFields": [
{
"name": "id",
- "description": "Global ID of the Terraform state",
+ "description": "Global ID of the Terraform state.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -65390,7 +69421,7 @@
"inputFields": [
{
"name": "id",
- "description": "Global ID of the Terraform state",
+ "description": "Global ID of the Terraform state.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -65478,7 +69509,7 @@
"inputFields": [
{
"name": "id",
- "description": "Global ID of the Terraform state",
+ "description": "Global ID of the Terraform state.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -66878,7 +70909,7 @@
"inputFields": [
{
"name": "targetId",
- "description": "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported",
+ "description": "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -66952,7 +70983,7 @@
},
{
"name": "todo",
- "description": "The to-do created",
+ "description": "The to-do created.",
"args": [
],
@@ -67035,7 +71066,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the todo to mark as done",
+ "description": "The global ID of the todo to mark as done.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -67109,7 +71140,7 @@
},
{
"name": "todo",
- "description": "The requested todo",
+ "description": "The requested todo.",
"args": [
],
@@ -67141,7 +71172,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the todo to restore",
+ "description": "The global ID of the todo to restore.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -67176,7 +71207,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 todos to restore (a maximum of 50 is supported at once).",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -67258,7 +71289,7 @@
},
{
"name": "todos",
- "description": "Updated todos",
+ "description": "Updated todos.",
"args": [
],
@@ -67284,7 +71315,7 @@
},
{
"name": "updatedIds",
- "description": "The IDs of the updated todo items Deprecated in 13.2: Use todos.",
+ "description": "The IDs of the updated todo items. Deprecated in 13.2: Use todos.",
"args": [
],
@@ -67363,7 +71394,7 @@
},
{
"name": "todo",
- "description": "The requested todo",
+ "description": "The requested todo.",
"args": [
],
@@ -67535,7 +71566,7 @@
},
{
"name": "todos",
- "description": "Updated todos",
+ "description": "Updated todos.",
"args": [
],
@@ -67561,7 +71592,7 @@
},
{
"name": "updatedIds",
- "description": "Ids of the updated todos Deprecated in 13.2: Use todos.",
+ "description": "Ids of the updated todos. Deprecated in 13.2: Use todos.",
"args": [
],
@@ -67601,7 +71632,7 @@
"inputFields": [
{
"name": "awardableId",
- "description": "The global ID of the awardable resource",
+ "description": "The global ID of the awardable resource.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -67649,7 +71680,7 @@
"fields": [
{
"name": "awardEmoji",
- "description": "The award emoji after mutation",
+ "description": "The award emoji after mutation.",
"args": [
],
@@ -68231,7 +72262,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the alert to mutate is in",
+ "description": "The project the alert to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68245,7 +72276,7 @@
},
{
"name": "iid",
- "description": "The IID of the alert to mutate",
+ "description": "The IID of the alert to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68259,7 +72290,7 @@
},
{
"name": "status",
- "description": "The status to set the alert",
+ "description": "The status to set the alert.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68293,7 +72324,7 @@
"fields": [
{
"name": "alert",
- "description": "The alert after mutation",
+ "description": "The alert after mutation.",
"args": [
],
@@ -68347,7 +72378,7 @@
},
{
"name": "issue",
- "description": "The issue created after mutation",
+ "description": "The issue created after mutation.",
"args": [
],
@@ -68361,7 +72392,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation",
+ "description": "The todo after mutation.",
"args": [
],
@@ -68389,7 +72420,7 @@
"inputFields": [
{
"name": "boardId",
- "description": "The board global ID",
+ "description": "The board global ID.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68403,7 +72434,7 @@
},
{
"name": "epicId",
- "description": "ID of an epic to set preferences for",
+ "description": "ID of an epic to set preferences for.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68417,7 +72448,7 @@
},
{
"name": "collapsed",
- "description": "Whether the epic should be collapsed in the board",
+ "description": "Whether the epic should be collapsed in the board.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68465,7 +72496,7 @@
},
{
"name": "epicUserPreferences",
- "description": "User preferences for the epic in the board after mutation",
+ "description": "User preferences for the epic in the board after mutation.",
"args": [
],
@@ -68562,6 +72593,82 @@
"defaultValue": null
},
{
+ "name": "assigneeId",
+ "description": "The ID of user to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "UserID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "milestoneId",
+ "description": "The ID of milestone to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "MilestoneID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iterationId",
+ "description": "The ID of iteration to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "IterationID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "weight",
+ "description": "The weight value to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labels",
+ "description": "Labels of the issue",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labelIds",
+ "description": "The IDs of labels to be added to the board.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "LabelID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -68598,7 +72705,7 @@
},
{
"name": "position",
- "description": "Position of list within the board",
+ "description": "Position of list within the board.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -68608,7 +72715,7 @@
},
{
"name": "collapsed",
- "description": "Indicates if list is collapsed for this user",
+ "description": "Indicates if list is collapsed for this user.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -68678,7 +72785,7 @@
},
{
"name": "list",
- "description": "Mutated list",
+ "description": "Mutated list.",
"args": [
],
@@ -68773,7 +72880,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the compliance framework to update",
+ "description": "The global ID of the compliance framework to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -68786,32 +72893,16 @@
"defaultValue": null
},
{
- "name": "name",
- "description": "New name for the compliance framework",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "description",
- "description": "New description for the compliance framework",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "color",
- "description": "New color representation of the compliance framework in hex format. e.g. #FCA121",
+ "name": "params",
+ "description": "Parameters to update the compliance framework with.",
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ComplianceFrameworkInput",
+ "ofType": null
+ }
},
"defaultValue": null
},
@@ -68851,7 +72942,7 @@
},
{
"name": "complianceFramework",
- "description": "The compliance framework after mutation",
+ "description": "The compliance framework after mutation.",
"args": [
],
@@ -68905,7 +72996,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project path where the container expiration policy is located",
+ "description": "The project path where the container expiration policy is located.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69013,7 +73104,7 @@
},
{
"name": "containerExpirationPolicy",
- "description": "The container expiration policy after mutation",
+ "description": "The container expiration policy after mutation.",
"args": [
],
@@ -69067,7 +73158,7 @@
"inputFields": [
{
"name": "name",
- "description": "Name of the segment",
+ "description": "Name of the segment.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69081,7 +73172,7 @@
},
{
"name": "groupIds",
- "description": "The array of group IDs to set for the segment",
+ "description": "The array of group IDs to set for the segment.",
"type": {
"kind": "LIST",
"name": null,
@@ -69099,7 +73190,7 @@
},
{
"name": "id",
- "description": "ID of the segment",
+ "description": "ID of the segment.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69173,7 +73264,7 @@
},
{
"name": "segment",
- "description": "The segment after mutation",
+ "description": "The segment after mutation.",
"args": [
],
@@ -69252,7 +73343,7 @@
"inputFields": [
{
"name": "iid",
- "description": "The IID of the epic to mutate",
+ "description": "The IID of the epic to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69266,7 +73357,7 @@
},
{
"name": "groupPath",
- "description": "The group the epic to mutate is in",
+ "description": "The group the epic to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69280,7 +73371,7 @@
},
{
"name": "title",
- "description": "The title of the epic",
+ "description": "The title of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -69290,7 +73381,7 @@
},
{
"name": "description",
- "description": "The description of the epic",
+ "description": "The description of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -69300,7 +73391,7 @@
},
{
"name": "confidential",
- "description": "Indicates if the epic is confidential",
+ "description": "Indicates if the epic is confidential.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -69310,7 +73401,7 @@
},
{
"name": "startDateFixed",
- "description": "The start date of the epic",
+ "description": "The start date of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -69320,7 +73411,7 @@
},
{
"name": "dueDateFixed",
- "description": "The end date of the epic",
+ "description": "The end date of the epic.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -69330,7 +73421,7 @@
},
{
"name": "startDateIsFixed",
- "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones",
+ "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -69340,7 +73431,7 @@
},
{
"name": "dueDateIsFixed",
- "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones",
+ "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -69386,7 +73477,7 @@
},
{
"name": "stateEvent",
- "description": "State event for the epic",
+ "description": "State event for the epic.",
"type": {
"kind": "ENUM",
"name": "EpicStateEvent",
@@ -69430,7 +73521,7 @@
},
{
"name": "epic",
- "description": "The epic after mutation",
+ "description": "The epic after mutation.",
"args": [
],
@@ -69484,7 +73575,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the note to update",
+ "description": "The global ID of the note to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69578,7 +73669,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -69606,7 +73697,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project the issue to mutate is in",
+ "description": "The project the issue to mutate is in.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69620,7 +73711,7 @@
},
{
"name": "iid",
- "description": "The IID of the issue to mutate",
+ "description": "The IID of the issue to mutate.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -69684,7 +73775,7 @@
},
{
"name": "milestoneId",
- "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null",
+ "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -69694,7 +73785,7 @@
},
{
"name": "addLabelIds",
- "description": "The IDs of labels to be added to the issue",
+ "description": "The IDs of labels to be added to the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -69712,7 +73803,7 @@
},
{
"name": "removeLabelIds",
- "description": "The IDs of labels to be removed from the issue",
+ "description": "The IDs of labels to be removed from the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -69730,7 +73821,7 @@
},
{
"name": "stateEvent",
- "description": "Close or reopen an issue",
+ "description": "Close or reopen an issue.",
"type": {
"kind": "ENUM",
"name": "IssueStateEvent",
@@ -69740,7 +73831,7 @@
},
{
"name": "healthStatus",
- "description": "The desired health status",
+ "description": "The desired health status.",
"type": {
"kind": "ENUM",
"name": "HealthStatus",
@@ -69750,7 +73841,7 @@
},
{
"name": "weight",
- "description": "The weight of the issue",
+ "description": "The weight of the issue.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -69760,7 +73851,7 @@
},
{
"name": "epicId",
- "description": "The ID of the parent epic. NULL when removing the association",
+ "description": "The ID of the parent epic. NULL when removing the association.",
"type": {
"kind": "SCALAR",
"name": "EpicID",
@@ -69830,7 +73921,7 @@
},
{
"name": "issue",
- "description": "The issue after mutation",
+ "description": "The issue after mutation.",
"args": [
],
@@ -70008,13 +74099,135 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "UpdateNamespacePackageSettingsInput",
+ "description": "Autogenerated input type of UpdateNamespacePackageSettings",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "namespacePath",
+ "description": "The namespace path where the namespace package setting is located.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "mavenDuplicatesAllowed",
+ "description": "Indicates whether duplicate Maven packages are allowed for this namespace.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "mavenDuplicateExceptionRegex",
+ "description": "When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "UntrustedRegexp",
+ "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": "UpdateNamespacePackageSettingsPayload",
+ "description": "Autogenerated return type of UpdateNamespacePackageSettings",
+ "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": "packageSettings",
+ "description": "The namespace package setting after mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PackageSettings",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
"name": "UpdateNoteInput",
"description": "Autogenerated input type of UpdateNote",
"fields": null,
"inputFields": [
{
"name": "id",
- "description": "The global ID of the note to update",
+ "description": "The global ID of the note to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -70108,7 +74321,7 @@
},
{
"name": "note",
- "description": "The note after mutation",
+ "description": "The note after mutation.",
"args": [
],
@@ -70136,7 +74349,7 @@
"inputFields": [
{
"name": "title",
- "description": "Title of the requirement",
+ "description": "Title of the requirement.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70146,7 +74359,7 @@
},
{
"name": "description",
- "description": "Description of the requirement",
+ "description": "Description of the requirement.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70156,7 +74369,7 @@
},
{
"name": "projectPath",
- "description": "Full project path the requirement is associated with",
+ "description": "Full project path the requirement is associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -70170,7 +74383,7 @@
},
{
"name": "state",
- "description": "State of the requirement",
+ "description": "State of the requirement.",
"type": {
"kind": "ENUM",
"name": "RequirementState",
@@ -70180,7 +74393,7 @@
},
{
"name": "iid",
- "description": "The IID of the requirement to update",
+ "description": "The IID of the requirement to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -70194,7 +74407,7 @@
},
{
"name": "lastTestReportState",
- "description": "Creates a test report for the requirement with the given state",
+ "description": "Creates a test report for the requirement with the given state.",
"type": {
"kind": "ENUM",
"name": "TestReportState",
@@ -70264,7 +74477,7 @@
},
{
"name": "requirement",
- "description": "Requirement after mutation",
+ "description": "Requirement after mutation.",
"args": [
],
@@ -70292,7 +74505,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the snippet to update",
+ "description": "The global ID of the snippet to update.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -70306,7 +74519,7 @@
},
{
"name": "title",
- "description": "Title of the snippet",
+ "description": "Title of the snippet.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70316,7 +74529,7 @@
},
{
"name": "description",
- "description": "Description of the snippet",
+ "description": "Description of the snippet.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70326,7 +74539,7 @@
},
{
"name": "visibilityLevel",
- "description": "The visibility level of the snippet",
+ "description": "The visibility level of the snippet.",
"type": {
"kind": "ENUM",
"name": "VisibilityLevelsEnum",
@@ -70336,7 +74549,7 @@
},
{
"name": "blobActions",
- "description": "Actions to perform over the snippet repository and blobs",
+ "description": "Actions to perform over the snippet repository and blobs.",
"type": {
"kind": "LIST",
"name": null,
@@ -70414,7 +74627,7 @@
},
{
"name": "snippet",
- "description": "The snippet after mutation",
+ "description": "The snippet after mutation.",
"args": [
],
@@ -70428,7 +74641,7 @@
},
{
"name": "spam",
- "description": "Indicates whether the operation returns a record detected as spam",
+ "description": "Indicates whether the operation returns a record detected as spam.",
"args": [
],
@@ -70469,7 +74682,7 @@
"args": [
{
"name": "iids",
- "description": "Array of IIDs of merge requests, for example `[1, 2]`",
+ "description": "Array of IIDs of merge requests, for example `[1, 2]`.",
"type": {
"kind": "LIST",
"name": null,
@@ -70551,7 +74764,7 @@
},
{
"name": "mergedAfter",
- "description": "Merge requests merged after this date",
+ "description": "Merge requests merged after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -70561,7 +74774,7 @@
},
{
"name": "mergedBefore",
- "description": "Merge requests merged before this date",
+ "description": "Merge requests merged before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -70571,7 +74784,7 @@
},
{
"name": "milestoneTitle",
- "description": "Title of the milestone",
+ "description": "Title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70581,7 +74794,7 @@
},
{
"name": "sort",
- "description": "Sort merge requests by this criteria",
+ "description": "Sort merge requests by this criteria.",
"type": {
"kind": "ENUM",
"name": "MergeRequestSort",
@@ -70611,7 +74824,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author",
+ "description": "Username of the author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70621,7 +74834,7 @@
},
{
"name": "reviewerUsername",
- "description": "Username of the reviewer",
+ "description": "Username of the reviewer.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70684,7 +74897,7 @@
"args": [
{
"name": "iids",
- "description": "Array of IIDs of merge requests, for example `[1, 2]`",
+ "description": "Array of IIDs of merge requests, for example `[1, 2]`.",
"type": {
"kind": "LIST",
"name": null,
@@ -70766,7 +74979,7 @@
},
{
"name": "mergedAfter",
- "description": "Merge requests merged after this date",
+ "description": "Merge requests merged after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -70776,7 +74989,7 @@
},
{
"name": "mergedBefore",
- "description": "Merge requests merged before this date",
+ "description": "Merge requests merged before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -70786,7 +74999,7 @@
},
{
"name": "milestoneTitle",
- "description": "Title of the milestone",
+ "description": "Title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70796,7 +75009,7 @@
},
{
"name": "sort",
- "description": "Sort merge requests by this criteria",
+ "description": "Sort merge requests by this criteria.",
"type": {
"kind": "ENUM",
"name": "MergeRequestSort",
@@ -70826,7 +75039,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of the assignee",
+ "description": "Username of the assignee.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -70836,7 +75049,7 @@
},
{
"name": "reviewerUsername",
- "description": "Username of the reviewer",
+ "description": "Username of the reviewer.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -71111,7 +75324,7 @@
"args": [
{
"name": "iids",
- "description": "Array of IIDs of merge requests, for example `[1, 2]`",
+ "description": "Array of IIDs of merge requests, for example `[1, 2]`.",
"type": {
"kind": "LIST",
"name": null,
@@ -71193,7 +75406,7 @@
},
{
"name": "mergedAfter",
- "description": "Merge requests merged after this date",
+ "description": "Merge requests merged after this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -71203,7 +75416,7 @@
},
{
"name": "mergedBefore",
- "description": "Merge requests merged before this date",
+ "description": "Merge requests merged before this date.",
"type": {
"kind": "SCALAR",
"name": "Time",
@@ -71213,7 +75426,7 @@
},
{
"name": "milestoneTitle",
- "description": "Title of the milestone",
+ "description": "Title of the milestone.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -71223,7 +75436,7 @@
},
{
"name": "sort",
- "description": "Sort merge requests by this criteria",
+ "description": "Sort merge requests by this criteria.",
"type": {
"kind": "ENUM",
"name": "MergeRequestSort",
@@ -71253,7 +75466,7 @@
},
{
"name": "authorUsername",
- "description": "Username of the author",
+ "description": "Username of the author.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -71263,7 +75476,7 @@
},
{
"name": "assigneeUsername",
- "description": "Username of the assignee",
+ "description": "Username of the assignee.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -71326,7 +75539,7 @@
"args": [
{
"name": "ids",
- "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"",
+ "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\".",
"type": {
"kind": "LIST",
"name": null,
@@ -71344,7 +75557,7 @@
},
{
"name": "visibility",
- "description": "The visibility of the snippet",
+ "description": "The visibility of the snippet.",
"type": {
"kind": "ENUM",
"name": "VisibilityScopesEnum",
@@ -71354,7 +75567,7 @@
},
{
"name": "type",
- "description": "The type of snippet",
+ "description": "The type of snippet.",
"type": {
"kind": "ENUM",
"name": "TypeEnum",
@@ -71417,7 +75630,7 @@
"args": [
{
"name": "search",
- "description": "Search query",
+ "description": "Search query.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -71512,7 +75725,7 @@
"args": [
{
"name": "action",
- "description": "The action to be filtered",
+ "description": "The action to be filtered.",
"type": {
"kind": "LIST",
"name": null,
@@ -71530,7 +75743,7 @@
},
{
"name": "authorId",
- "description": "The ID of an author",
+ "description": "The ID of an author.",
"type": {
"kind": "LIST",
"name": null,
@@ -71548,7 +75761,7 @@
},
{
"name": "projectId",
- "description": "The ID of a project",
+ "description": "The ID of a project.",
"type": {
"kind": "LIST",
"name": null,
@@ -71566,7 +75779,7 @@
},
{
"name": "groupId",
- "description": "The ID of a group",
+ "description": "The ID of a group.",
"type": {
"kind": "LIST",
"name": null,
@@ -71584,7 +75797,7 @@
},
{
"name": "state",
- "description": "The state of the todo",
+ "description": "The state of the todo.",
"type": {
"kind": "LIST",
"name": null,
@@ -71602,7 +75815,7 @@
},
{
"name": "type",
- "description": "The type of the todo",
+ "description": "The type of the todo.",
"type": {
"kind": "LIST",
"name": null,
@@ -72530,6 +76743,20 @@
"deprecationReason": null
},
{
+ "name": "confirmedBy",
+ "description": "The user that confirmed the vulnerability.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "description",
"description": "Description of the vulnerability",
"args": [
@@ -72633,6 +76860,20 @@
"deprecationReason": null
},
{
+ "name": "dismissedBy",
+ "description": "The user that dismissed the vulnerability.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "externalIssueLinks",
"description": "List of external issue links related to the vulnerability",
"args": [
@@ -72753,7 +76994,7 @@
"args": [
{
"name": "linkType",
- "description": "Filter issue links by link type",
+ "description": "Filter issue links by link type.",
"type": {
"kind": "ENUM",
"name": "VulnerabilityIssueLinkType",
@@ -72956,6 +77197,20 @@
"deprecationReason": null
},
{
+ "name": "resolvedBy",
+ "description": "The user that resolved the vulnerability.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "resolvedOnDefaultBranch",
"description": "Indicates whether the vulnerability is fixed on the default branch or not",
"args": [
@@ -73099,7 +77354,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the vulnerability to be confirmed",
+ "description": "ID of the vulnerability to be confirmed.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -73173,7 +77428,7 @@
},
{
"name": "vulnerability",
- "description": "The vulnerability after state change",
+ "description": "The vulnerability after state change.",
"args": [
],
@@ -73268,7 +77523,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the vulnerability to be dismissed",
+ "description": "ID of the vulnerability to be dismissed.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -73282,7 +77537,7 @@
},
{
"name": "comment",
- "description": "Reason why vulnerability should be dismissed",
+ "description": "Comment why vulnerability should be dismissed.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -73291,6 +77546,16 @@
"defaultValue": null
},
{
+ "name": "dismissalReason",
+ "description": "Reason why vulnerability should be dismissed.",
+ "type": {
+ "kind": "ENUM",
+ "name": "VulnerabilityDismissalReason",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -73352,7 +77617,7 @@
},
{
"name": "vulnerability",
- "description": "The vulnerability after dismissal",
+ "description": "The vulnerability after dismissal.",
"args": [
],
@@ -73373,6 +77638,47 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "VulnerabilityDismissalReason",
+ "description": "The dismissal reason of the Vulnerability",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "ACCEPTABLE_RISK",
+ "description": "The likelihood of the Vulnerability occurring and its impact are deemed acceptable",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "FALSE_POSITIVE",
+ "description": "The Vulnerability was incorrectly identified as being present",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MITIGATING_CONTROL",
+ "description": "There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "USED_IN_TESTS",
+ "description": "The Vulnerability is used in tests and does not pose an actual risk",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "NOT_APPLICABLE",
+ "description": "Other reasons for dismissal",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "VulnerabilityEdge",
"description": "An edge in a connection.",
@@ -74857,7 +79163,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the vulnerability to be resolved",
+ "description": "ID of the vulnerability to be resolved.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -74931,7 +79237,7 @@
},
{
"name": "vulnerability",
- "description": "The vulnerability after state change",
+ "description": "The vulnerability after state change.",
"args": [
],
@@ -74959,7 +79265,7 @@
"inputFields": [
{
"name": "id",
- "description": "ID of the vulnerability to be reverted",
+ "description": "ID of the vulnerability to be reverted.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -75033,7 +79339,7 @@
},
{
"name": "vulnerability",
- "description": "The vulnerability after revert",
+ "description": "The vulnerability after revert.",
"args": [
],
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 4cb79d71ab5..c098de16ef6 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -50,7 +50,7 @@ Autogenerated return type of AddAwardEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `awardEmoji` | AwardEmoji | The award emoji after mutation |
+| `awardEmoji` | AwardEmoji | The award emoji after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -62,7 +62,7 @@ Autogenerated return type of AddProjectToSecurityDashboard.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `project` | Project | Project that was added to the Instance Security Dashboard |
+| `project` | Project | Project that was added to the Instance Security Dashboard. |
### AdminSidekiqQueuesDeleteJobsPayload
@@ -72,7 +72,7 @@ Autogenerated return type of AdminSidekiqQueuesDeleteJobs.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `result` | DeleteJobsResponse | Information about the status of the deletion request |
+| `result` | DeleteJobsResponse | Information about the status of the deletion request. |
### AlertManagementAlert
@@ -152,11 +152,11 @@ Autogenerated return type of AlertSetAssignees.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `alert` | AlertManagementAlert | The alert after mutation |
+| `alert` | AlertManagementAlert | The alert after mutation. |
| `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 |
+| `issue` | Issue | The issue created after mutation. |
+| `todo` | Todo | The todo after mutation. |
### AlertTodoCreatePayload
@@ -164,11 +164,11 @@ Autogenerated return type of AlertTodoCreate.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `alert` | AlertManagementAlert | The alert after mutation |
+| `alert` | AlertManagementAlert | The alert after mutation. |
| `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 |
+| `issue` | Issue | The issue created after mutation. |
+| `todo` | Todo | The todo after mutation. |
### AwardEmoji
@@ -189,7 +189,7 @@ Autogenerated return type of AwardEmojiAdd.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `awardEmoji` | AwardEmoji | The award emoji after mutation |
+| `awardEmoji` | AwardEmoji | The award emoji after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -199,7 +199,7 @@ Autogenerated return type of AwardEmojiRemove.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `awardEmoji` | AwardEmoji | The award emoji after mutation |
+| `awardEmoji` | AwardEmoji | The award emoji after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -209,7 +209,7 @@ Autogenerated return type of AwardEmojiToggle.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `awardEmoji` | AwardEmoji | The award emoji after mutation |
+| `awardEmoji` | AwardEmoji | The award emoji after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `toggledOn` | Boolean! | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. |
@@ -252,6 +252,8 @@ Represents a project or group 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 |
### BoardEpic
@@ -325,6 +327,7 @@ Represents a list for an issue board.
| `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 |
@@ -343,7 +346,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 | List of the issue board. |
### BoardListUpdateLimitMetricsPayload
@@ -353,7 +356,7 @@ Autogenerated return type of BoardListUpdateLimitMetrics.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `list` | BoardList | The updated list |
+| `list` | BoardList | The updated list. |
### Branch
@@ -374,20 +377,35 @@ Represents the total number of issues and their weights for a particular day.
| `scopeCount` | Int! | Number of issues as of this day |
| `scopeWeight` | Int! | Total weight of issues as of this day |
+### CiBuildNeed
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `name` | String | Name of the job we need to complete. |
+
+### CiCdSettingsUpdatePayload
+
+Autogenerated return type of CiCdSettingsUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
### CiConfig
| Field | Type | Description |
| ----- | ---- | ----------- |
| `errors` | String! => Array | Linting errors |
| `mergedYaml` | String | Merged CI config YAML |
-| `stages` | CiConfigStage! => Array | Stages of the pipeline |
+| `stages` | CiConfigStageConnection | Stages of the pipeline |
| `status` | CiConfigStatus | Status of linting, can be either valid or invalid |
### CiConfigGroup
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `jobs` | CiConfigJob! => Array | Jobs in group |
+| `jobs` | CiConfigJobConnection | Jobs in group |
| `name` | String | Name of the job group |
| `size` | Int | Size of the job group |
@@ -395,10 +413,25 @@ Represents the total number of issues and their weights for a particular day.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `groupName` | String | Name of the job group |
-| `name` | String | Name of the job |
-| `needs` | CiConfigNeed! => Array | Builds that must complete before the jobs run |
-| `stage` | String | Name of the job stage |
+| `afterScript` | String! => Array | Override a set of commands that are executed after the job. |
+| `allowFailure` | Boolean | Allow job to fail. |
+| `beforeScript` | String! => Array | Override a set of commands that are executed before the job. |
+| `environment` | String | Name of an environment to which the job deploys. |
+| `except` | CiConfigJobRestriction | Limit when jobs are not created. |
+| `groupName` | String | Name of the job group. |
+| `name` | String | Name of the job. |
+| `needs` | CiConfigNeedConnection | Builds that must complete before the jobs run. |
+| `only` | CiConfigJobRestriction | Jobs are created when these conditions do not apply. |
+| `script` | String! => Array | Shell script that is executed by a runner. |
+| `stage` | String | Name of the job stage. |
+| `tags` | String! => Array | List of tags that are used to select a runner. |
+| `when` | String | When to run the job. |
+
+### CiConfigJobRestriction
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `refs` | String! => Array | The Git refs the job restriction applies to. |
### CiConfigNeed
@@ -410,7 +443,7 @@ Represents the total number of issues and their weights for a particular day.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `groups` | CiConfigGroup! => Array | Groups of jobs for the stage |
+| `groups` | CiConfigGroupConnection | Groups of jobs for the stage |
| `name` | String | Name of the stage |
### CiGroup
@@ -429,7 +462,7 @@ Represents the total number of issues and their weights for a particular day.
| `artifacts` | CiJobArtifactConnection | Artifacts generated by the job |
| `detailedStatus` | DetailedStatus | Detailed status of the job |
| `name` | String | Name of the job |
-| `needs` | CiJobConnection | Builds that must complete before the jobs run |
+| `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 |
@@ -484,8 +517,8 @@ Autogenerated return type of ClusterAgentTokenCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `secret` | String | Token secret value. Make sure you save it - you won't be able to access it again |
-| `token` | ClusterAgentToken | Token created after mutation |
+| `secret` | String | Token secret value. Make sure you save it - you won't be able to access it again. |
+| `token` | ClusterAgentToken | Token created after mutation. |
### ClusterAgentTokenDeletePayload
@@ -545,7 +578,7 @@ Autogenerated return type of CommitCreate.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `commit` | Commit | The commit after mutation |
+| `commit` | Commit | The commit after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### ComplianceFramework
@@ -567,8 +600,8 @@ Autogenerated return type of ConfigureSast.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `status` | String! | Status of creating the commit for the supplied SAST CI configuration |
-| `successPath` | String | Redirect path to use when the response is successful |
+| `status` | String! | Status of creating the commit for the supplied SAST CI configuration. |
+| `successPath` | String | Redirect path to use when the response is successful. |
### ContainerExpirationPolicy
@@ -647,11 +680,11 @@ Autogenerated return type of CreateAlertIssue.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `alert` | AlertManagementAlert | The alert after mutation |
+| `alert` | AlertManagementAlert | The alert after mutation. |
| `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 |
+| `issue` | Issue | The issue created after mutation. |
+| `todo` | Todo | The todo after mutation. |
### CreateAnnotationPayload
@@ -659,7 +692,7 @@ Autogenerated return type of CreateAnnotation.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `annotation` | MetricsDashboardAnnotation | The created annotation |
+| `annotation` | MetricsDashboardAnnotation | The created annotation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -679,7 +712,7 @@ Autogenerated return type of CreateBranch.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `branch` | Branch | Branch after mutation |
+| `branch` | Branch | Branch after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -690,7 +723,7 @@ Autogenerated return type of CreateClusterAgent.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `clusterAgent` | ClusterAgent | Cluster agent created after mutation |
+| `clusterAgent` | ClusterAgent | Cluster agent created after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### CreateComplianceFrameworkPayload
@@ -710,7 +743,7 @@ Autogenerated return type of CreateCustomEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `customEmoji` | CustomEmoji | The new custom emoji |
+| `customEmoji` | CustomEmoji | The new custom emoji. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### CreateDevopsAdoptionSegmentPayload
@@ -721,7 +754,7 @@ Autogenerated return type of CreateDevopsAdoptionSegment.
| ----- | ---- | ----------- |
| `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 |
+| `segment` | DevopsAdoptionSegment | The segment after mutation. |
### CreateDiffNotePayload
@@ -731,7 +764,7 @@ Autogenerated return type of CreateDiffNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### CreateEpicPayload
@@ -740,7 +773,7 @@ Autogenerated return type of CreateEpic.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `epic` | Epic | The created epic |
+| `epic` | Epic | The created epic. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### CreateImageDiffNotePayload
@@ -751,7 +784,7 @@ Autogenerated return type of CreateImageDiffNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### CreateIssuePayload
@@ -761,7 +794,7 @@ Autogenerated return type of CreateIssue.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### CreateIterationPayload
@@ -771,7 +804,7 @@ Autogenerated return type of CreateIteration.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `iteration` | Iteration | The created iteration |
+| `iteration` | Iteration | The created iteration. |
### CreateNotePayload
@@ -781,7 +814,7 @@ Autogenerated return type of CreateNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### CreateRequirementPayload
@@ -791,7 +824,7 @@ Autogenerated return type of CreateRequirement.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `requirement` | Requirement | Requirement after mutation |
+| `requirement` | Requirement | Requirement after mutation. |
### CreateSnippetPayload
@@ -801,8 +834,8 @@ Autogenerated return type of CreateSnippet.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `snippet` | Snippet | The snippet after mutation |
-| `spam` | Boolean | Indicates whether the operation returns a record detected as spam |
+| `snippet` | Snippet | The snippet after mutation. |
+| `spam` | Boolean | Indicates whether the operation returns a record detected as spam. |
### CreateTestCasePayload
@@ -812,7 +845,7 @@ Autogenerated return type of CreateTestCase.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `testCase` | Issue | The test case created |
+| `testCase` | Issue | The test case created. |
### CustomEmoji
@@ -1063,7 +1096,7 @@ Autogenerated return type of DesignManagementDelete.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `version` | DesignVersion | The new version in which the designs are deleted |
+| `version` | DesignVersion | The new version in which the designs are deleted. |
### DesignManagementMovePayload
@@ -1072,7 +1105,7 @@ Autogenerated return type of DesignManagementMove.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `designCollection` | DesignCollection | The current state of the collection |
+| `designCollection` | DesignCollection | The current state of the collection. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### DesignManagementUploadPayload
@@ -1082,7 +1115,7 @@ Autogenerated return type of DesignManagementUpload.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `designs` | Design! => Array | The designs that were uploaded by the mutation |
+| `designs` | Design! => Array | The designs that were uploaded by the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `skippedDesigns` | Design! => Array | Any designs that were skipped from the upload due to there being no change to their content since their last version |
@@ -1114,7 +1147,7 @@ Autogenerated return type of DestroyBoard.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `board` | Board | The board after mutation |
+| `board` | Board | The board after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -1144,7 +1177,7 @@ Autogenerated return type of DestroyContainerRepositoryTags.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `deletedTagNames` | String! => Array | Deleted container repository tags |
+| `deletedTagNames` | String! => Array | Deleted container repository tags. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### DestroyNotePayload
@@ -1155,7 +1188,7 @@ Autogenerated return type of DestroyNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### DestroySnippetPayload
@@ -1165,7 +1198,7 @@ Autogenerated return type of DestroySnippet.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `snippet` | Snippet | The snippet after mutation |
+| `snippet` | Snippet | The snippet after mutation. |
### DetailedStatus
@@ -1274,7 +1307,7 @@ Autogenerated return type of DiscussionToggleResolve.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `discussion` | Discussion | The discussion after mutation |
+| `discussion` | Discussion | The discussion after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### DismissVulnerabilityPayload
@@ -1285,7 +1318,7 @@ Autogenerated return type of DismissVulnerability.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `vulnerability` | Vulnerability | The vulnerability after dismissal |
+| `vulnerability` | Vulnerability | The vulnerability after dismissal. |
### Environment
@@ -1367,8 +1400,8 @@ Autogenerated return type of EpicAddIssue.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `epic` | Epic | The epic after mutation |
-| `epicIssue` | EpicIssue | The epic-issue relation |
+| `epic` | Epic | The epic after mutation. |
+| `epicIssue` | EpicIssue | The epic-issue relation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### EpicBoard
@@ -1377,8 +1410,9 @@ Represents an epic board.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `id` | BoardsEpicBoardID! | Global ID of the board |
-| `name` | String | Name of the board |
+| `id` | BoardsEpicBoardID! | Global ID of the board. |
+| `lists` | EpicListConnection | Epic board lists. |
+| `name` | String | Name of the board. |
### EpicDescendantCount
@@ -1423,6 +1457,7 @@ Relationship between an epic and an issue.
| `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 |
@@ -1472,6 +1507,19 @@ Relationship between an epic and an issue.
| `webUrl` | String! | Web URL of the issue |
| `weight` | Int | Weight of the issue. |
+### EpicList
+
+Represents an epic board list.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `epics` | EpicConnection | List epics. |
+| `id` | BoardsEpicListID! | Global ID of the board list. |
+| `label` | Label | Label of the list. |
+| `listType` | String! | Type of the list. |
+| `position` | Int | Position of the list within the board. |
+| `title` | String! | Title of the list. |
+
### EpicPermissions
Check permissions for the current user on an epic.
@@ -1494,7 +1542,7 @@ Autogenerated return type of EpicSetSubscription.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `epic` | Epic | The epic after mutation |
+| `epic` | Epic | The epic after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### EpicTreeReorderPayload
@@ -1506,6 +1554,15 @@ 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. |
+### ExportRequirementsPayload
+
+Autogenerated return type of ExportRequirements.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
### ExternalIssue
Represents an external issue.
@@ -1565,7 +1622,7 @@ Represents an external issue.
| `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. |
+| `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 |
@@ -1593,6 +1650,7 @@ Represents an external issue.
| `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 |
@@ -1667,7 +1725,7 @@ Autogenerated return type of HttpIntegrationCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration. |
### HttpIntegrationDestroyPayload
@@ -1677,7 +1735,7 @@ Autogenerated return type of HttpIntegrationDestroy.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration. |
### HttpIntegrationResetTokenPayload
@@ -1687,7 +1745,7 @@ Autogenerated return type of HttpIntegrationResetToken.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration. |
### HttpIntegrationUpdatePayload
@@ -1697,7 +1755,20 @@ Autogenerated return type of HttpIntegrationUpdate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementHttpIntegration | The HTTP integration |
+| `integration` | AlertManagementHttpIntegration | The HTTP integration. |
+
+### IncidentManagementOncallRotation
+
+Describes an incident management on-call rotation.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `id` | IncidentManagementOncallRotationID! | ID of the on-call rotation. |
+| `length` | Int | Length of the on-call schedule, in the units specified by lengthUnit. |
+| `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. |
+| `startsAt` | Time | Start date of the on-call rotation. |
### IncidentManagementOncallSchedule
@@ -1708,6 +1779,7 @@ Describes an incident management 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 |
### InstanceSecurityDashboard
@@ -1740,6 +1812,7 @@ Represents a recorded measurement (object count) for the Admins.
| `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 |
@@ -1795,7 +1868,7 @@ Autogenerated return type of IssueMoveList.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueMovePayload
@@ -1805,7 +1878,7 @@ Autogenerated return type of IssueMove.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssuePermissions
@@ -1830,7 +1903,7 @@ Autogenerated return type of IssueSetAssignees.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetConfidentialPayload
@@ -1840,7 +1913,7 @@ Autogenerated return type of IssueSetConfidential.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetDueDatePayload
@@ -1850,7 +1923,7 @@ Autogenerated return type of IssueSetDueDate.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetEpicPayload
@@ -1860,7 +1933,7 @@ Autogenerated return type of IssueSetEpic.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetIterationPayload
@@ -1870,7 +1943,7 @@ Autogenerated return type of IssueSetIteration.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetLockedPayload
@@ -1880,7 +1953,7 @@ Autogenerated return type of IssueSetLocked.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetSeverityPayload
@@ -1890,7 +1963,7 @@ Autogenerated return type of IssueSetSeverity.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetSubscriptionPayload
@@ -1900,7 +1973,7 @@ Autogenerated return type of IssueSetSubscription.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueSetWeightPayload
@@ -1910,7 +1983,7 @@ Autogenerated return type of IssueSetWeight.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### IssueStatusCountsType
@@ -1964,7 +2037,7 @@ Autogenerated return type of JiraImportStart.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `jiraImport` | JiraImport | The Jira import data after mutation |
+| `jiraImport` | JiraImport | The Jira import data after mutation. |
### JiraImportUsersPayload
@@ -2022,7 +2095,7 @@ Autogenerated return type of LabelCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `label` | Label | The label after mutation |
+| `label` | Label | The label after mutation. |
### MarkAsSpamSnippetPayload
@@ -2032,7 +2105,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `snippet` | Snippet | The snippet after mutation |
+| `snippet` | Snippet | The snippet after mutation. |
### MergeRequest
@@ -2046,6 +2119,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `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 |
@@ -2054,6 +2128,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `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) |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `diffHeadSha` | String | Diff head SHA of the merge request |
@@ -2075,19 +2150,21 @@ Autogenerated return type of MarkAsSpamSnippet.
| `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 |
-| `participants` | UserConnection | Participants in the merge request |
+| `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 |
+| `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 |
@@ -2096,6 +2173,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `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 |
@@ -2124,7 +2202,7 @@ Autogenerated return type of MergeRequestCreate.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestDiffRegistry
@@ -2165,7 +2243,7 @@ Autogenerated return type of MergeRequestSetAssignees.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestSetLabelsPayload
@@ -2175,7 +2253,7 @@ Autogenerated return type of MergeRequestSetLabels.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestSetLockedPayload
@@ -2185,7 +2263,7 @@ Autogenerated return type of MergeRequestSetLocked.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestSetMilestonePayload
@@ -2195,7 +2273,7 @@ Autogenerated return type of MergeRequestSetMilestone.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestSetSubscriptionPayload
@@ -2205,7 +2283,7 @@ Autogenerated return type of MergeRequestSetSubscription.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestSetWipPayload
@@ -2215,7 +2293,7 @@ Autogenerated return type of MergeRequestSetWip.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### MergeRequestUpdatePayload
@@ -2225,7 +2303,7 @@ Autogenerated return type of MergeRequestUpdate.
| ----- | ---- | ----------- |
| `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 |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
### Metadata
@@ -2300,7 +2378,7 @@ Contains statistics about a milestone.
| ----- | ---- | ----------- |
| `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. |
+| `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 |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
@@ -2310,6 +2388,7 @@ Contains statistics about a milestone.
| `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 |
@@ -2329,7 +2408,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `namespace` | Namespace | The namespace after mutation |
+| `namespace` | Namespace | The namespace after mutation. |
### Note
@@ -2351,6 +2430,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| `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
@@ -2364,6 +2444,27 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| `repositionNote` | Boolean! | Indicates the user can perform `reposition_note` on this resource |
| `resolveNote` | Boolean! | Indicates the user can perform `resolve_note` on this resource |
+### OncallParticipantType
+
+The rotation participant and color palette.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `colorPalette` | String | The color palette to assign to the on-call user. For example "blue". |
+| `colorWeight` | String | The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user. |
+| `id` | IncidentManagementOncallParticipantID! | ID of the on-call participant. |
+| `user` | User! | The user who is participating. |
+
+### OncallRotationCreatePayload
+
+Autogenerated return type of OncallRotationCreate.
+
+| 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.
@@ -2372,7 +2473,7 @@ Autogenerated return type of OncallScheduleCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule |
+| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule. |
### OncallScheduleDestroyPayload
@@ -2382,7 +2483,7 @@ Autogenerated return type of OncallScheduleDestroy.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule |
+| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule. |
### OncallScheduleUpdatePayload
@@ -2392,20 +2493,62 @@ Autogenerated return type of OncallScheduleUpdate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule |
+| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule. |
### Package
-Represents a package.
+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. |
+| `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. |
+
+### PackageComposerJsonType
+
+Represents a composer JSON file.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `license` | String | The license set in the Composer JSON file. |
+| `name` | String | The name set in the 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 |
| ----- | ---- | ----------- |
-| `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 |
-| `updatedAt` | Time! | The update date |
-| `version` | String | The version of the package |
+| `composerJson` | PackageComposerJsonType! | Data of the Composer JSON file. |
+| `targetSha` | String! | Target SHA of the package. |
### PackageFileRegistry
@@ -2422,6 +2565,26 @@ Represents the Geo sync and verification state of a package file.
| `retryCount` | Int | Number of consecutive failed sync attempts of the PackageFileRegistry |
| `state` | RegistryState | Sync state of the PackageFileRegistry |
+### PackageSettings
+
+Namespace-level Package Registry settings.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `mavenDuplicateExceptionRegex` | UntrustedRegexp | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
+| `mavenDuplicatesAllowed` | Boolean! | Indicates whether duplicate Maven packages are allowed for this namespace. |
+
+### PackageTag
+
+Represents a package tag.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | Time! | The created date. |
+| `id` | ID! | The ID of the tag. |
+| `name` | String! | The name of the tag. |
+| `updatedAt` | Time! | The updated date. |
+
### PageInfo
Information about pagination in a connection..
@@ -2515,7 +2678,7 @@ Autogenerated return type of PipelineRetry.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `pipeline` | Pipeline | The pipeline after mutation |
+| `pipeline` | Pipeline | The pipeline after mutation. |
### Project
@@ -2545,7 +2708,6 @@ Autogenerated return type of PipelineRetry.
| `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 |
-| `dastSiteValidation` | DastSiteValidation | DAST Site Validation associated with the project. Will always return `null` if `security_on_demand_scans_site_validation` is disabled |
| `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 |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
@@ -2617,7 +2779,6 @@ Autogenerated return type of PipelineRetry.
| `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 |
-| `totalPipelineDuration` | Int | Total pipeline duration for all of the pipelines in a project |
| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource |
| `visibility` | String | Visibility of the project |
| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the project |
@@ -2631,6 +2792,7 @@ Autogenerated return type of PipelineRetry.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `keepLatestArtifact` | Boolean | Whether to keep the latest builds artifacts. |
| `mergePipelinesEnabled` | Boolean | Whether merge pipelines are enabled. |
| `mergeTrainsEnabled` | Boolean | Whether merge trains are enabled. |
| `project` | Project | Project the CI/CD settings belong to. |
@@ -2729,7 +2891,7 @@ Autogenerated return type of PrometheusIntegrationCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementPrometheusIntegration | The newly created integration |
+| `integration` | AlertManagementPrometheusIntegration | The newly created integration. |
### PrometheusIntegrationResetTokenPayload
@@ -2739,7 +2901,7 @@ Autogenerated return type of PrometheusIntegrationResetToken.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementPrometheusIntegration | The newly created integration |
+| `integration` | AlertManagementPrometheusIntegration | The newly created integration. |
### PrometheusIntegrationUpdatePayload
@@ -2749,7 +2911,7 @@ Autogenerated return type of PrometheusIntegrationUpdate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `integration` | AlertManagementPrometheusIntegration | The newly created integration |
+| `integration` | AlertManagementPrometheusIntegration | The newly created integration. |
### PromoteToEpicPayload
@@ -2758,9 +2920,9 @@ Autogenerated return type of PromoteToEpic.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `epic` | Epic | The epic after issue promotion |
+| `epic` | Epic | The epic after issue promotion. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `issue` | Issue | The issue after mutation |
+| `issue` | Issue | The issue after mutation. |
### Release
@@ -2814,7 +2976,7 @@ Autogenerated return type of ReleaseCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `release` | Release | The release after mutation |
+| `release` | Release | The release after mutation. |
### ReleaseDeletePayload
@@ -2874,7 +3036,7 @@ Autogenerated return type of RemoveAwardEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `awardEmoji` | AwardEmoji | The award emoji after mutation |
+| `awardEmoji` | AwardEmoji | The award emoji after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
@@ -2895,7 +3057,7 @@ Autogenerated return type of RepositionImageDiffNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### Repository
@@ -2957,7 +3119,7 @@ Autogenerated return type of RevertVulnerabilityToDetected.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `vulnerability` | Vulnerability | The vulnerability after revert |
+| `vulnerability` | Vulnerability | The vulnerability after revert. |
### RootStorageStatistics
@@ -3468,7 +3630,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 created. |
### TodoMarkDonePayload
@@ -3478,7 +3640,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 todo. |
### TodoRestoreManyPayload
@@ -3488,7 +3650,7 @@ 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 |
+| `todos` | Todo! => Array | Updated todos. |
| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2. |
### TodoRestorePayload
@@ -3499,7 +3661,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 todo. |
### TodosMarkAllDonePayload
@@ -3509,7 +3671,7 @@ 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 |
+| `todos` | Todo! => Array | Updated todos. |
| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2. |
### ToggleAwardEmojiPayload
@@ -3518,7 +3680,7 @@ Autogenerated return type of ToggleAwardEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `awardEmoji` | AwardEmoji | The award emoji after mutation |
+| `awardEmoji` | AwardEmoji | The award emoji after mutation. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `toggledOn` | Boolean! | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. |
@@ -3553,11 +3715,11 @@ Autogenerated return type of UpdateAlertStatus.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `alert` | AlertManagementAlert | The alert after mutation |
+| `alert` | AlertManagementAlert | The alert after mutation. |
| `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 |
+| `issue` | Issue | The issue created after mutation. |
+| `todo` | Todo | The todo after mutation. |
### UpdateBoardEpicUserPreferencesPayload
@@ -3566,7 +3728,7 @@ Autogenerated return type of UpdateBoardEpicUserPreferences.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `epicUserPreferences` | BoardEpicUserPreferences | User preferences for the epic in the board after mutation |
+| `epicUserPreferences` | BoardEpicUserPreferences | User preferences for the epic in the board after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### UpdateBoardListPayload
@@ -3577,7 +3739,7 @@ Autogenerated return type of UpdateBoardList.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `list` | BoardList | Mutated list |
+| `list` | BoardList | Mutated list. |
### UpdateBoardPayload
@@ -3596,7 +3758,7 @@ Autogenerated return type of UpdateComplianceFramework.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `complianceFramework` | ComplianceFramework | The compliance framework after mutation |
+| `complianceFramework` | ComplianceFramework | The compliance framework after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### UpdateContainerExpirationPolicyPayload
@@ -3606,7 +3768,7 @@ Autogenerated return type of UpdateContainerExpirationPolicy.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy after mutation |
+| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### UpdateDevopsAdoptionSegmentPayload
@@ -3617,7 +3779,7 @@ Autogenerated return type of UpdateDevopsAdoptionSegment.
| ----- | ---- | ----------- |
| `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 |
+| `segment` | DevopsAdoptionSegment | The segment after mutation. |
### UpdateEpicPayload
@@ -3626,7 +3788,7 @@ Autogenerated return type of UpdateEpic.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `epic` | Epic | The epic after mutation |
+| `epic` | Epic | The epic after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### UpdateImageDiffNotePayload
@@ -3637,7 +3799,7 @@ Autogenerated return type of UpdateImageDiffNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### UpdateIssuePayload
@@ -3647,7 +3809,7 @@ Autogenerated return type of UpdateIssue.
| ----- | ---- | ----------- |
| `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 after mutation |
+| `issue` | Issue | The issue after mutation. |
### UpdateIterationPayload
@@ -3659,6 +3821,16 @@ Autogenerated return type of UpdateIteration.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `iteration` | Iteration | Updated iteration. |
+### UpdateNamespacePackageSettingsPayload
+
+Autogenerated return type of UpdateNamespacePackageSettings.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `packageSettings` | PackageSettings | The namespace package setting after mutation. |
+
### UpdateNotePayload
Autogenerated return type of UpdateNote.
@@ -3667,7 +3839,7 @@ Autogenerated return type of UpdateNote.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `note` | Note | The note after mutation |
+| `note` | Note | The note after mutation. |
### UpdateRequirementPayload
@@ -3677,7 +3849,7 @@ Autogenerated return type of UpdateRequirement.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `requirement` | Requirement | Requirement after mutation |
+| `requirement` | Requirement | Requirement after mutation. |
### UpdateSnippetPayload
@@ -3687,8 +3859,8 @@ Autogenerated return type of UpdateSnippet.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `snippet` | Snippet | The snippet after mutation |
-| `spam` | Boolean | Indicates whether the operation returns a record detected as spam |
+| `snippet` | Snippet | The snippet after mutation. |
+| `spam` | Boolean | Indicates whether the operation returns a record detected as spam. |
### User
@@ -3763,10 +3935,12 @@ Represents a vulnerability.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `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 |
+| `dismissedBy` | User | The user that dismissed 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 |
@@ -3779,6 +3953,7 @@ Represents a vulnerability.
| `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 |
+| `resolvedBy` | User | The user that resolved the vulnerability. |
| `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) |
@@ -3796,7 +3971,7 @@ Autogenerated return type of VulnerabilityConfirm.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `vulnerability` | Vulnerability | The vulnerability after state change |
+| `vulnerability` | Vulnerability | The vulnerability after state change. |
### VulnerabilityDismissPayload
@@ -3806,7 +3981,7 @@ Autogenerated return type of VulnerabilityDismiss.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `vulnerability` | Vulnerability | The vulnerability after dismissal |
+| `vulnerability` | Vulnerability | The vulnerability after dismissal. |
### VulnerabilityExternalIssueLink
@@ -3948,7 +4123,7 @@ Autogenerated return type of VulnerabilityResolve.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `vulnerability` | Vulnerability | The vulnerability after state change |
+| `vulnerability` | Vulnerability | The vulnerability after state change. |
### VulnerabilityRevertToDetectedPayload
@@ -3958,7 +4133,7 @@ Autogenerated return type of VulnerabilityRevertToDetected.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `vulnerability` | Vulnerability | The vulnerability after revert |
+| `vulnerability` | Vulnerability | The vulnerability after revert. |
### VulnerabilityScanner
@@ -4068,7 +4243,7 @@ Filters the alerts based on given domain.
| Value | Description |
| ----- | ----------- |
-| `operations` | Alerts for operations domain |
+| `operations` | Alerts for operations domain |
| `threat_monitoring` | Alerts for threat monitoring domain |
### AlertManagementIntegrationType
@@ -4080,6 +4255,33 @@ Values of types of integrations.
| `HTTP` | Integration with any monitoring tool |
| `PROMETHEUS` | Prometheus integration |
+### AlertManagementPayloadAlertFieldName
+
+Values for alert field names used in the custom mapping.
+
+| Value | Description |
+| ----- | ----------- |
+| `DESCRIPTION` | A high-level summary of the problem. |
+| `END_TIME` | The resolved time of the incident. |
+| `FINGERPRINT` | The unique identifier of the alert. This can be used to group occurrences of the same alert. |
+| `GITLAB_ENVIRONMENT_NAME` | The name of the associated GitLab environment. |
+| `HOSTS` | One or more hosts, as to where this incident occurred. |
+| `MONITORING_TOOL` | The name of the associated monitoring tool. |
+| `SERVICE` | The affected service. |
+| `SEVERITY` | The severity of the alert. |
+| `START_TIME` | The time of the incident. |
+| `TITLE` | The title of the incident. |
+
+### AlertManagementPayloadAlertFieldType
+
+Values for alert field types used in the custom mapping.
+
+| Value | Description |
+| ----- | ----------- |
+| `ARRAY` | Array field type |
+| `DATETIME` | DateTime field type |
+| `STRING` | String field type |
+
### AlertManagementSeverity
Alert severity values.
@@ -4225,6 +4427,36 @@ Status of a container repository.
| `HEADER` | Header validation |
| `TEXT_FILE` | Text file validation |
+### DataVisualizationColorEnum
+
+Color of the data visualization palette.
+
+| Value | Description |
+| ----- | ----------- |
+| `AQUA` | Aqua color |
+| `BLUE` | Blue color |
+| `GREEN` | Green color |
+| `MAGENTA` | Magenta color |
+| `ORANGE` | Orange color |
+
+### DataVisualizationWeightEnum
+
+Weight of the data visualization palette.
+
+| Value | Description |
+| ----- | ----------- |
+| `WEIGHT_100` | 100 weight |
+| `WEIGHT_200` | 200 weight |
+| `WEIGHT_300` | 300 weight |
+| `WEIGHT_400` | 400 weight |
+| `WEIGHT_50` | 50 weight |
+| `WEIGHT_500` | 500 weight |
+| `WEIGHT_600` | 600 weight |
+| `WEIGHT_700` | 700 weight |
+| `WEIGHT_800` | 800 weight |
+| `WEIGHT_900` | 900 weight |
+| `WEIGHT_950` | 950 weight |
+
### DesignCollectionCopyState
Copy state of a DesignCollection.
@@ -4560,6 +4792,16 @@ Values for sorting projects.
| `SIMILARITY` | Most similar to the search query |
| `STORAGE` | Sort by storage size |
+### OncallRotationUnitEnum
+
+Rotation length unit of an on-call rotation.
+
+| Value | Description |
+| ----- | ----------- |
+| `DAYS` | Days |
+| `HOURS` | Hours |
+| `WEEKS` | Weeks |
+
### PackageTypeEnum
| Value | Description |
@@ -4707,7 +4949,6 @@ State of a Sentry error.
| Value | Description |
| ----- | ----------- |
-| `ALERTS_SERVICE` | |
| `ASANA_SERVICE` | |
| `ASSEMBLA_SERVICE` | |
| `BAMBOO_SERVICE` | |
@@ -4843,6 +5084,18 @@ Possible states of a user.
| `private` | |
| `public` | |
+### VulnerabilityDismissalReason
+
+The dismissal reason of the Vulnerability.
+
+| Value | Description |
+| ----- | ----------- |
+| `ACCEPTABLE_RISK` | The likelihood of the Vulnerability occurring and its impact are deemed acceptable |
+| `FALSE_POSITIVE` | The Vulnerability was incorrectly identified as being present |
+| `MITIGATING_CONTROL` | There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable |
+| `NOT_APPLICABLE` | Other reasons for dismissal |
+| `USED_IN_TESTS` | The Vulnerability is used in tests and does not pose an actual risk |
+
### VulnerabilityExternalIssueLinkExternalTracker
The external tracker of the external issue link related to a vulnerability.
diff --git a/doc/api/graphql/users_example.md b/doc/api/graphql/users_example.md
new file mode 100644
index 00000000000..e4a697d11fd
--- /dev/null
+++ b/doc/api/graphql/users_example.md
@@ -0,0 +1,109 @@
+---
+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
+---
+
+# Query users with GraphQL
+
+This page describes how you can use the GraphiQL explorer to query users.
+
+You can run the same query directly via a HTTP endpoint, using `cURL`. For more information, see our
+guidance on getting started from the [command line](getting_started.md#command-line).
+
+The [example users query](#set-up-the-graphiql-explorer) looks for a subset of users in
+o
+a GitLab instance either by username or
+[Global ID](../../development/api_graphql_styleguide.md#global-ids).
+The query includes:
+
+- [`pageInfo`](#pageinfo)
+- [`nodes`](#nodes)
+
+## pageInfo
+
+This contains the data needed to implement pagination. GitLab uses cursor-based
+[pagination](getting_started.md#pagination). For more information, see
+[Pagination](https://graphql.org/learn/pagination/) in the GraphQL documentation.
+
+## nodes
+
+In a GraphQL query, `nodes` is used to represent a collection of [`nodes` on a graph](https://en.wikipedia.org/wiki/Vertex_(graph_theory)).
+In this case, the collection of nodes is a collection of `User` objects. For each one,
+we output:
+
+- Their user's `id`.
+- The `membership` fragment, which represents a Project or Group membership belonging
+ to that user. Outputting a fragment is denoted with the `...memberships` notation.
+
+The GitLab GraphQL API is extensive and a large amount of data for a wide variety of entities can be output.
+See the official [reference documentation](reference/index.md) for the most up-to-date information.
+
+## Set up the GraphiQL explorer
+
+This procedure presents a substantive example that you can copy and paste into GraphiQL
+explorer. GraphiQL explorer is available for:
+
+- GitLab.com users at [https://gitlab.com/-/graphql-explorer](https://gitlab.com/-/graphql-explorer).
+- Self-managed users at `https://gitlab.example.com/-/graphql-explorer`.
+
+1. Copy the following code excerpt:
+
+ ```graphql
+ {
+ users(usernames: ["user1", "user3", "user4"]) {
+ pageInfo {
+ endCursor
+ startCursor
+ hasNextPage
+ }
+ nodes {
+ id
+ username,
+ publicEmail
+ location
+ webUrl
+ userPermissions {
+ createSnippet
+ }
+ }
+ }
+ }
+ ```
+
+1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer).
+1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
+1. Click Play to get the result shown here:
+
+![GraphiQL explorer search for boards](img/users_query_example_v13_8.png)
+
+NOTE:
+[The GraphQL API returns a GlobalID, rather than a standard ID.](getting_started.md#queries-and-mutations) It also expects a GlobalID as an input rather than
+a single integer.
+
+This GraphQL query returns the specified information for the three users with the listed username. Since the GraphiQL explorer uses the session token to authorize access to resources,
+the output is limited to the projects and groups accessible to the currently signed-in user.
+
+If you've signed in as an instance administrator, you would have access to all records, regardless of ownership.
+
+If you are signed in as an administrator, you can show just the matching administrators on the instance by adding the `admins: true` parameter to the query changing the second line to:
+
+```graphql
+ users(usernames: ["user1", "user3", "user4"], admins: true) {
+ ...
+ }
+```
+
+Or you can just get all of the administrators:
+
+```graphql
+ users(admins: true) {
+ ...
+ }
+```
+
+For more information on:
+
+- GraphQL specific entities, such as Fragments and Interfaces, see the official
+ [GraphQL documentation](https://graphql.org/learn/).
+- Individual attributes, see the [GraphQL API Resources](reference/index.md).
diff --git a/doc/api/group_boards.md b/doc/api/group_boards.md
index f982dad7962..722f3a76267 100644
--- a/doc/api/group_boards.md
+++ b/doc/api/group_boards.md
@@ -279,7 +279,7 @@ Example response:
}
```
-## Update a group issue board **(PREMIUM)**
+## Update a group issue board
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in GitLab 11.1.
@@ -289,15 +289,17 @@ Updates a Group Issue Board.
PUT /groups/:id/boards/:board_id
```
-| 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 |
-| `board_id` | integer | yes | The ID of a board |
-| `name` | string | no | The new name of the board |
-| `assignee_id` | integer | no | The assignee the board should be scoped to |
-| `milestone_id` | integer | no | The milestone the board should be scoped to |
-| `labels` | string | no | Comma-separated list of label names which the board should be scoped to |
-| `weight` | integer | no | The weight range from 0 to 9, to which the board should be scoped to |
+| 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 |
+| `board_id` | integer | yes | The ID of a board |
+| `name` | string | no | The new name of the board |
+| `hide_backlog_list` | boolean | no | Hide the Open list |
+| `hide_closed_list` | boolean | no | Hide the Closed list |
+| `assignee_id` **(PREMIUM)** | integer | no | The assignee the board should be scoped to |
+| `milestone_id` **(PREMIUM)** | integer | no | The milestone the board should be scoped to |
+| `labels` **(PREMIUM)** | string | no | Comma-separated list of label names which the board should be scoped to |
+| `weight` **(PREMIUM)** | integer | no | The weight range from 0 to 9, to which the board should be scoped to |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/boards/1?name=new_name&milestone_id=44&assignee_id=1&labels=GroupLabel&weight=4"
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index bf8c889b031..57670eff1ea 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -93,7 +93,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 50MB.
+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).
## Important notes
diff --git a/doc/api/groups.md b/doc/api/groups.md
index b4d36b568b8..eb255f8de00 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.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
---
@@ -766,7 +766,6 @@ Parameters:
| `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_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. |
### Options for `default_branch_protection`
@@ -778,16 +777,6 @@ The `default_branch_protection` attribute determines whether developers and main
| `1` | Partial protection. Developers and maintainers can: <br>- Push new commits |
| `2` | Full protection. Only maintainers can: <br>- Push new commits |
-### Options for `shared_runners_setting`
-
-The `shared_runners_setting` attribute determines whether shared runners are enabled for a group's subgroups and projects.
-
-| Value | Description |
-|-------|-------------------------------------------------------------------------------------------------------------|
-| `enabled` | Enables shared runners for all projects and subgroups in this group. |
-| `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. |
-
## New Subgroup
This is similar to creating a [New group](#new-group). You need the `parent_id` from the [List groups](#list-groups) call. You can then enter the desired:
@@ -852,6 +841,7 @@ PUT /groups/:id
| `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). |
| `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. |
NOTE:
The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).
@@ -941,6 +931,16 @@ with Rails console access to run the following command:
Feature.disable(:limit_projects_in_groups_api)
```
+### Options for `shared_runners_setting`
+
+The `shared_runners_setting` attribute determines whether shared runners are enabled for a group's subgroups and projects.
+
+| Value | Description |
+|-------|-------------------------------------------------------------------------------------------------------------|
+| `enabled` | Enables shared runners for all projects and subgroups in this group. |
+| `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. |
+
## Remove group
Only available to group owners and administrators.
diff --git a/doc/api/import.md b/doc/api/import.md
index 3a1edcb732d..2d978b7b6dd 100644
--- a/doc/api/import.md
+++ b/doc/api/import.md
@@ -73,7 +73,7 @@ POST /import/bitbucket_server
curl --request POST \
--url "https://gitlab.example.com/api/v4/import/bitbucket_server" \
--header "content-type: application/json" \
- --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
--data '{
"bitbucket_server_url": "http://bitbucket.example.com",
"bitbucket_server_username": "root",
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index 0891a343cce..7259dddec8c 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -106,3 +106,27 @@ Example response:
},
]
```
+
+## Delete an invitation to a group or project
+
+Deletes a pending invitation by email address.
+
+```plaintext
+DELETE /groups/:id/invitations/:email
+DELETE /projects/:id/invitations/:email
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `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 |
+| `email` | string | yes | The email address to which the invitation was previously sent |
+
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/55/invitations/email@example.org"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/55/invitations/email@example.org"
+```
+
+- Returns `204` and no content on success.
+- Returns `403` forbidden if unauthorized to delete the invitation.
+- Returns `404` not found if authorized and no invitation is found for that email address.
+- Returns `409` if the request was valid but the invitation could not be deleted.
diff --git a/doc/api/issues.md b/doc/api/issues.md
index f6bab9ce676..1abb4fe3b4a 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Issues API
-If a user is not a member of a project and the project is private, a `GET`
+If a user is not a member of a private project, a `GET`
request on that project results in a `404` status code.
## Issues pagination
@@ -22,8 +22,8 @@ Introduced in [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_request
NOTE:
The `references.relative` attribute is relative to the group or project of the issue being requested.
-When an issue is fetched from its project, the `relative` format is the same as the `short` format,
-and when requested across groups or projects it's expected to be the same as the `full` format.
+When an issue is fetched from its project, the `relative` format is the same as the `short` format.
+When requested across groups or projects, it's expected to be the same as the `full` format.
## List issues
@@ -57,7 +57,7 @@ GET /issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. 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))_ |
+| `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)_ |
@@ -239,7 +239,7 @@ GET /groups/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. 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))_ |
+| `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))_ |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `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. |
@@ -416,7 +416,7 @@ GET /projects/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. 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))_ |
+| `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))_ |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `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. |
@@ -424,7 +424,7 @@ GET /projects/:id/issues?state=opened
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ |
| `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` |
| `order_by` | string | no | Return issues ordered by `created_at`, `updated_at`, `priority`, `due_date`, `relative_position`, `label_priority`, `milestone_due`, `popularity`, `weight` fields. Default is `created_at` |
-| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ |
+| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ |
| `search` | string | no | Search project issues against their `title` and `description` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
@@ -721,7 +721,7 @@ The `assignee` column is deprecated. We now show it as a single-sized array `ass
to the GitLab EE API.
WARNING:
-The `epic_iid` attribute is deprecated, and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
+The `epic_iid` attribute is deprecated, and [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
Please use `iid` of the `epic` attribute instead.
NOTE:
@@ -882,7 +882,7 @@ WARNING:
The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
WARNING:
-The `epic_iid` attribute is deprecated and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
+The `epic_iid` attribute is deprecated and [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
Please use `iid` of the `epic` attribute instead.
NOTE:
@@ -904,9 +904,9 @@ POST /projects/:id/issues
| `created_at` | string | no | When the issue was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z`. Requires administrator or project/group owner rights. |
| `description` | string | no | The description of an issue. Limited to 1,048,576 characters. |
| `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This fills out the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. |
-| `due_date` | string | no | The due date. Date time string in the format YEAR-MONTH-DAY, for example `2016-03-11` |
+| `due_date` | string | no | The due date. Date time string in the format `YYYY-MM-DD`, for example `2016-03-11` |
| `epic_id` **(PREMIUM)** | integer | no | ID of the epic to add the issue to. Valid values are greater than or equal to 0. |
-| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) |
+| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `iid` | integer/string | no | The internal ID of the project's issue (requires administrator or project owner rights) |
| `labels` | string | no | Comma-separated label names for an issue |
@@ -1048,9 +1048,9 @@ PUT /projects/:id/issues/:issue_iid
| `confidential` | boolean | no | Updates an issue to be confidential |
| `description` | string | no | The description of an issue. Limited to 1,048,576 characters. |
| `discussion_locked` | boolean | no | Flag indicating if the issue's discussion is locked. If the discussion is locked only project members can add or edit comments. |
-| `due_date` | string | no | The due date. Date time string in the format YEAR-MONTH-DAY, for example `2016-03-11` |
+| `due_date` | string | no | The due date. Date time string in the format `YYYY-MM-DD`, for example `2016-03-11` |
| `epic_id` **(PREMIUM)** | integer | no | ID of the epic to add the issue to. Valid values are greater than or equal to 0. |
-| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) |
+| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `issue_iid` | integer | yes | The internal ID of a project's issue |
| `labels` | string | no | Comma-separated label names for an issue. Set to an empty string to unassign all labels. |
@@ -1168,7 +1168,7 @@ WARNING:
## Delete an issue
-Only for admins and project owners. Deletes the issue in question.
+Only for administrators and project owners. Deletes an issue.
```plaintext
DELETE /projects/:id/issues/:issue_iid
@@ -1207,8 +1207,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
## Move an issue
Moves an issue to a different project. If the target project
-equals the source project or the user has insufficient permissions to move an
-issue, status code `400` and an error message is returned.
+is the source project or the user has insufficient permissions,
+an error message with status code `400` is returned.
If a given label or milestone with the same name also exists in the target
project, it's then assigned to the issue being moved.
@@ -1987,9 +1987,9 @@ Example response:
]
```
-## List merge requests that will close issue on merge
+## List merge requests that close a particular issue on merge
-Get all the merge requests that will close an issue when merged.
+Get all merge requests that close a particular issue when merged.
If the project is private or the issue is confidential, you need to provide credentials to authorize.
The preferred way to do this, is by using [personal access tokens](../user/profile/personal_access_tokens.md).
@@ -2112,7 +2112,7 @@ Comments are done via the [notes](notes.md) resource.
## Get user agent details
-Available only for admins.
+Available only for administrators.
```plaintext
GET /projects/:id/issues/:issue_iid/user_agent_detail
@@ -2211,3 +2211,26 @@ Example response:
}
]
```
+
+## Delete metric image
+
+Available only for Incident issues.
+
+```plaintext
+DELETE /projects/:id/issues/:issue_iid/metric_images/:image_id
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `image_id` | integer | yes | The ID of the image |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/5/issues/93/metric_images/1"
+```
+
+Can return the following status codes:
+
+- `204 No Content`, if the image was deleted successfully.
+- `400 Bad Request`, if the image could not be deleted.
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index 229b90282f0..a6b5e9e4711 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -33,7 +33,7 @@ To use this in a [`script` definition](../ci/yaml/README.md#script) inside
- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
For example, the following job downloads the artifacts of the job with ID
- `42`. Note that the command is wrapped into single quotes since it contains a
+ `42`. Note that the command is wrapped into single quotes because it contains a
colon (`:`):
```yaml
@@ -99,7 +99,7 @@ To use this in a [`script` definition](../ci/yaml/README.md#script) inside
- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
For example, the following job downloads the artifacts of the `test` job
of the `master` branch. Note that the command is wrapped into single quotes
- since it contains a colon (`:`):
+ because it contains a colon (`:`):
```yaml
artifact_download:
@@ -130,7 +130,7 @@ Possible response status codes:
> Introduced in GitLab 10.0
-Download a single artifact file from a job with a specified ID from within
+Download a single artifact file from a job with a specified ID from inside
the job's artifacts zipped archive. The file is extracted from the archive and
streamed to the client.
@@ -165,7 +165,7 @@ Possible response status codes:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23538) in GitLab 11.5.
Download a single artifact file for a specific job of the latest successful
-pipeline for the given reference name from within the job's artifacts archive.
+pipeline for the given reference name from inside the job's artifacts archive.
The file is extracted from the archive and streamed to the client.
In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201784) and later, artifacts
diff --git a/doc/api/members.md b/doc/api/members.md
index 05914b50cd7..47b686d9275 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -398,7 +398,7 @@ POST /groups/:id/members/:user_id/override
| `user_id` | integer | yes | The user ID of the member |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override"
```
Example response:
@@ -435,7 +435,7 @@ DELETE /groups/:id/members/:user_id/override
| `user_id` | integer | yes | The user ID of the member |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override"
```
Example response:
@@ -468,7 +468,7 @@ DELETE /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 |
-| `unassign_issuables` | boolean | false | Flag indicating if the removed member should be unassigned from any issues or merge requests within given group or project |
+| `unassign_issuables` | boolean | false | Flag indicating if the removed member should be unassigned from any issues or merge requests inside a given group or project |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id"
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index d2144a2c0c5..c43ac96a42f 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -7,15 +7,43 @@ type: reference, api
# Merge requests API
-Every API call to merge requests must be authenticated.
+> - `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.
+> - For the `scope` attribute, `created-by-me` and `assigned-to-me` were [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in favor of `created_by_me` and `assigned_to_me` in GitLab 11.0.
+> - `with_labels_details` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7.
+> - `author_username` and `author_username` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10.
+> - `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.
-WARNING:
-> `reference` attribute in response is deprecated in favour of `references`.
-> Introduced [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)
+Every API call to merge requests must be authenticated.
-NOTE:
-> `references.relative` is relative to the group / project that the merge request is being requested. When merge request is fetched from its project
-> `relative` format would be the same as `short` format and when requested across groups / projects it is expected to be the same as `full` format.
+**Important notes:**
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29984) in GitLab 12.8, the mergeability (`merge_status`)
+of each merge request is checked asynchronously when a request is made to this endpoint. Poll this API endpoint
+to get updated status. This affects the `has_conflicts` property as it is dependent on the `merge_status`. It returns
+`false` unless `merge_status` is `cannot_be_merged`.
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0, listing merge requests may
+not proactively update `merge_status` (which also affects the `has_conflicts`), as this can be an expensive operation.
+If you need the value of these fields from this endpoint, set the `with_merge_status_recheck` parameter to
+`true` in the query.
+- `references.relative` is relative to the group or project that the merge request is being requested. When the merge request
+is fetched from its project, `relative` format would be the same as `short` format, and when requested across groups or projects, it is expected to be the same as `full` format.
+- If `approvals_before_merge` **(STARTER)** is not provided, it inherits the value from the target project. If provided, the following conditions must hold for it to take effect:
+
+ - The target project's `approvals_before_merge` must be greater than zero. A
+ value of zero disables approvals for that project.
+ - The provided value of `approvals_before_merge` must be greater than the
+ target project's `approvals_before_merge`.
+
+ This API returns `HTTP 201 Created` for a successful response.
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6,
+diffs associated with the set of changes have the same size limitations applied as other diffs
+returned by the API or viewed via the UI. When these limits impact the results, the `overflow`
+field contains a value of `true`. Diff data without these limits applied can be retrieved by
+adding the `access_raw_diffs` parameter, but it is slower and more resource-intensive.
## List merge requests
@@ -26,7 +54,7 @@ default it returns only merge requests created by the current user. To
get all merge requests, use parameter `scope=all`.
The `state` parameter can be used to get only merge requests with a
-given state (`opened`, `closed`, `locked`, or `merged`) or all of them (`all`). It should be noted that when searching by `locked` it will mostly return no results as it is a short-lived, transitional state.
+given state (`opened`, `closed`, `locked`, or `merged`) or all of them (`all`). It should be noted that when searching by `locked` it mostly returns no results as it is a short-lived, transitional state.
The pagination parameters `page` and `per_page` can be used to
restrict the list of merge requests.
@@ -47,50 +75,37 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------------------- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
-| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
-| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. |
+| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. |
+| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
-| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
+| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
-| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
-| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) |
+| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. |
+| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. |
| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead. |
-| `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`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | |
+| `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. |
-| `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 |
-| `search` | string | no | Search merge requests against their `title` and `description` |
-| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
-| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
-| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji` |
+| `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. |
+| `source_branch` | string | no | Return merge requests with the given source branch. |
+| `target_branch` | string | no | Return merge requests with the given target branch. |
+| `search` | string | no | Search merge requests against their `title` and `description`. |
+| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description`. |
+| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests. |
+| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. |
| `environment` | string | no | Returns merge requests deployed to the given environment. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `deployed_before` | datetime | no | Return merge requests deployed before the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `deployed_after` | datetime | no | Return merge requests deployed after the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-NOTE:
-[Starting in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890),
-listing merge requests may not proactively update the `merge_status` field
-(which also affects the `has_conflicts` field), as this can be an expensive
-operation. If you are interested in the value of these fields from this
-endpoint, set the `with_merge_status_recheck` parameter to `true` in the query.
-
-NOTE:
-[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/29984),
-the mergeability (`merge_status`) of each merge request will be checked
-asynchronously when a request is made to this endpoint. Poll this API endpoint
-to get updated status. This affects the `has_conflicts` property as it is
-dependent on the `merge_status`. It'll return `false` unless `merge_status` is
-`cannot_be_merged`.
-
```json
[
{
@@ -141,6 +156,14 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "id": 2,
+ "name": "Sam Bauch",
+ "username": "kenyatta_oconnell",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com//kenyatta_oconnell"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -193,7 +216,7 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -224,43 +247,47 @@ GET /projects/:id/merge_requests?my_reaction_emoji=star
```
`project_id` represents the ID of the project where the MR resides.
-`project_id` will always equal `target_project_id`.
+`project_id` always equals `target_project_id`.
In the case of a merge request from the same project,
`source_project_id`, `target_project_id` and `project_id`
-will be the same. In the case of a merge request from a fork,
-`target_project_id` and `project_id` will be the same and
-`source_project_id` will be the fork project's ID.
+are the same. In the case of a merge request from a fork,
+`target_project_id` and `project_id` are the same and
+`source_project_id` is the fork project's ID.
Parameters:
| Attribute | Type | Required | Description |
| ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
-| `id` | integer | yes | The ID of a project |
-| `iids[]` | integer array | no | Return the request having the given `iid` |
-| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
-| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `iids[]` | integer array | no | Return the request having the given `iid`. |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. |
+| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. |
+| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
-| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
+| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
-| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
-| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) |
+| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. |
+| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. |
| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ |
-| `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)_ |
+| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me`, or `all`. |
+| `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. |
-| `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 |
-| `search` | string | no | Search merge requests against their `title` and `description` |
-| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
+| `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. |
+| `source_branch` | string | no | Return merge requests with the given source branch. |
+| `target_branch` | string | no | Return merge requests with the given target branch. |
+| `search` | string | no | Search merge requests against their `title` and `description`. |
+| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests. |
+| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. |
```json
[
@@ -312,6 +339,14 @@ Parameters:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "id": 2,
+ "name": "Sam Bauch",
+ "username": "kenyatta_oconnell",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com//kenyatta_oconnell"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -366,7 +401,7 @@ Parameters:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -401,30 +436,33 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
-| `id` | integer | yes | The ID of a group |
-| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
-| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc` |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. |
+| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. |
+| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
-| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
+| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
-| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)|
-| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) |
-| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> |
-| `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)_ |
+| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413).|
+| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890). |
+| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. |
+| `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. |
-| `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 |
-| `search` | string | no | Search merge requests against their `title` and `description` |
-| `non_archived` | boolean | no | Return merge requests from non archived projects only. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809))_ |
+| `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`. |
+| `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. |
+| `search` | string | no | Search merge requests against their `title` and `description`. |
+| `non_archived` | boolean | no | Return merge requests from non archived projects only. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809))_. |
+| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. |
```json
[
@@ -476,6 +514,14 @@ Parameters:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "id": 2,
+ "name": "Sam Bauch",
+ "username": "kenyatta_oconnell",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com//kenyatta_oconnell"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -528,7 +574,7 @@ Parameters:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -548,7 +594,7 @@ Shows information about a single merge request.
**Note**: the `changes_count` value in the response is a string, not an
integer. This is because when an MR has too many changes to display and store,
-it will be capped at 1,000. In that case, the API will return the string
+it is capped at 1,000. In that case, the API returns the string
`"1000+"` for the changes count.
```plaintext
@@ -557,19 +603,13 @@ GET /projects/:id/merge_requests/:merge_request_iid
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
-- `render_html` (optional) - If `true` response includes rendered HTML for title and description
-- `include_diverged_commits_count` (optional) - If `true` response includes the commits behind the target branch
-- `include_rebase_in_progress` (optional) - If `true` response includes whether a rebase operation is in progress
-
-NOTE:
-[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/29984),
-the mergeability (`merge_status`) of a merge request will be checked
-asynchronously when a request is made to this endpoint. Poll this API endpoint
-to get updated status. This affects the `has_conflicts` property as it is
-dependent on the `merge_status`. It'll return `false` unless `merge_status` is
-`cannot_be_merged`.
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+| `render_html` | integer | no | If `true` response includes rendered HTML for title and description. |
+| `include_diverged_commits_count` | boolean | no | If `true` response includes the commits behind the target branch. |
+| `include_rebase_in_progress` | boolean | no | If `true` response includes whether a rebase operation is in progress. |
```json
{
@@ -612,6 +652,14 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "id": 2,
+ "name": "Sam Bauch",
+ "username": "kenyatta_oconnell",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com//kenyatta_oconnell"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -697,7 +745,7 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -719,8 +767,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/participants
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```json
[
@@ -753,8 +803,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/commits
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```json
[
@@ -787,17 +839,13 @@ Shows information about the merge request including its files and changes.
GET /projects/:id/merge_requests/:merge_request_iid/changes
```
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6,
-diffs associated with the set of changes will have the same size limitations applied as other diffs
-returned by the API or viewed via the UI. When these limits impact the results, the `overflow`
-field will contain a value of `true`. Diff data without these limits applied can be retrieved by
-adding the `access_raw_diffs` parameter, however, it will be slower and more resource-intensive.
-
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user.
-- `merge_request_iid` (required) - The internal ID of the merge request.
-- `access_raw_diffs` (optional) - Retrieve change diffs without size limitations.
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+| `access_raw_diffs` | boolean | no | Retrieve change diffs without size limitations. |
```json
{
@@ -898,7 +946,7 @@ Parameters:
## List MR pipelines
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) in GitLab 10.5.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) in GitLab 10.5.
Get a list of merge request pipelines.
@@ -908,8 +956,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/pipelines
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```json
[
@@ -926,7 +976,9 @@ Parameters:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31722) in GitLab 12.3.
-Create a new [pipeline for a merge request](../ci/merge_request_pipelines/index.md). A pipeline created via this endpoint will not run a regular branch/tag pipeline, it requires `.gitlab-ci.yml` to be configured with `only: [merge_requests]` to create jobs.
+Create a new [pipeline for a merge request](../ci/merge_request_pipelines/index.md).
+A pipeline created via this endpoint doesn't run a regular branch/tag pipeline.
+It requires `.gitlab-ci.yml` to be configured with `only: [merge_requests]` to create jobs.
The new pipeline can be:
@@ -940,8 +992,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/pipelines
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding)
-- `merge_request_iid` (required) - The internal ID of the merge request
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```json
{
@@ -993,29 +1047,19 @@ POST /projects/:id/merge_requests
| 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 |
-| `source_branch` | string | yes | The source branch |
-| `target_branch` | string | yes | The target branch |
-| `title` | string | yes | Title of MR |
-| `assignee_id` | integer | no | Assignee user ID |
+| `source_branch` | string | yes | The source branch. |
+| `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. |
| `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 |
-| `milestone_id` | integer | no | The global ID of a milestone |
-| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
-| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch |
-| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration |
-| `squash` | boolean | no | Squash commits into a single commit when merging |
-
-If `approvals_before_merge` **(STARTER)** is not provided, it inherits the value from the
-target project. If it is provided, then the following conditions must hold in
-order for it to take effect:
-
-1. The target project's `approvals_before_merge` must be greater than zero. A
- value of zero disables approvals for that project.
-1. The provided value of `approvals_before_merge` must be greater than the
- target project's `approvals_before_merge`.
-1. This API returns 201 (created) for a successful response.
+| `target_project_id` | integer | no | The target project (numeric ID). |
+| `labels` | string | no | Labels for MR as a comma-separated list. |
+| `milestone_id` | integer | no | The global ID of a milestone. |
+| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging. |
+| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch. |
+| `allow_maintainer_to_push` | boolean | no | Deprecated, see `allow_collaboration`. |
+| `squash` | boolean | no | Squash commits into a single commit when merging. |
```json
{
@@ -1128,7 +1172,7 @@ order for it to take effect:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -1150,10 +1194,10 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| 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 |
-| `merge_request_iid` | integer | yes | The ID of a merge request |
-| `target_branch` | string | no | The target branch |
-| `title` | string | no | Title of MR |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The ID of a merge request. |
+| `target_branch` | string | no | The target branch. |
+| `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. |
| `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.|
@@ -1161,12 +1205,12 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `add_labels` | string | no | Comma-separated label names to add to a merge request. |
| `remove_labels` | string | no | Comma-separated label names to remove from a merge request. |
| `description` | string | no | Description of MR. Limited to 1,048,576 characters. |
-| `state_event` | string | no | New state (close/reopen) |
-| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
-| `squash` | boolean | no | Squash commits into a single commit when merging |
+| `state_event` | string | no | New state (close/reopen). |
+| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging. |
+| `squash` | boolean | no | Squash commits into a single commit when merging. |
| `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. |
-| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch |
-| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration |
+| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch. |
+| `allow_maintainer_to_push` | boolean | no | Deprecated, see `allow_collaboration`. |
Must include at least one non-required attribute from above.
@@ -1289,7 +1333,7 @@ Must include at least one non-required attribute from above.
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -1303,7 +1347,7 @@ the `approvals_before_merge` parameter:
## Delete a merge request
-Only for admins and project owners. Deletes the merge request in question.
+Only for administrators and project owners. Deletes the merge request in question.
```plaintext
DELETE /projects/:id/merge_requests/:merge_request_iid
@@ -1311,8 +1355,8 @@ DELETE /projects/:id/merge_requests/:merge_request_iid
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/merge_requests/85"
@@ -1322,13 +1366,13 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
Merge changes submitted with MR using this API.
-If merge request is unable to be accepted (such as Draft, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you'll get a `405` and the error message 'Method Not Allowed'
+If a merge request is unable to be accepted (such as Draft, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you receive a `405` and the error message 'Method Not Allowed'
-If it has some conflicts and can not be merged - you'll get a `406` and the error message 'Branch cannot be merged'
+If it has some conflicts and can not be merged - you receive a `406` and the error message 'Branch cannot be merged'
-If the `sha` parameter is passed and does not match the HEAD of the source - you'll get a `409` and the error message 'SHA does not match HEAD of source branch'
+If the `sha` parameter is passed and does not match the HEAD of the source - you receive a `409` and the error message 'SHA does not match HEAD of source branch'
-If you don't have permissions to accept this merge request - you'll get a `401`
+If you don't have permissions to accept this merge request - you receive a `401`
```plaintext
PUT /projects/:id/merge_requests/:merge_request_iid/merge
@@ -1336,14 +1380,16 @@ PUT /projects/:id/merge_requests/:merge_request_iid/merge
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - Internal ID of MR
-- `merge_commit_message` (optional) - Custom merge commit message
-- `squash_commit_message` (optional) - Custom squash commit message
-- `squash` (optional) - if `true` the commits will be squashed into a single commit on merge
-- `should_remove_source_branch` (optional) - if `true` removes the source branch
-- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
-- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail
+| 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. |
+| `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. |
+| `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. |
```json
{
@@ -1464,7 +1510,7 @@ Parameters:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -1479,15 +1525,15 @@ the `approvals_before_merge` parameter:
## Merge to default merge ref path
Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge`
-ref, of the target project repository, if possible. This ref will have the state the target branch would have if
+ref, of the target project repository, if possible. This ref has the state the target branch would have if
a regular merge action was taken.
This is not a regular merge action given it doesn't change the merge request target branch state in any manner.
This ref (`refs/merge-requests/:iid/merge`) isn't necessarily overwritten when submitting
-requests to this API, though it'll make sure the ref has the latest possible state.
+requests to this API, though it makes sure the ref has the latest possible state.
-If the merge request has conflicts, is empty or already merged, you'll get a `400` and a descriptive error message.
+If the merge request has conflicts, is empty or already merged, you receive a `400` and a descriptive error message.
It returns the HEAD commit of `refs/merge-requests/:iid/merge` in the response body in case of `200`.
@@ -1497,8 +1543,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/merge_ref
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - Internal ID of MR
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```json
{
@@ -1508,11 +1556,9 @@ Parameters:
## Cancel Merge When Pipeline Succeeds
-If you don't have permissions to accept this merge request - you'll get a `401`
-
-If the merge request is already merged or closed - you get `405` and error message 'Method Not Allowed'
-
-In case the merge request is not set to be merged when the pipeline succeeds, you'll also get a `406` error.
+- If you don't have permissions to accept this merge request - you receive a `HTTP 401 Unauthorized`.
+- If the merge request is already merged or closed - you receive a `HTTP 405 Method Not Allowed` and the error message 'Method Not Allowed'.
+- In case the merge request is not set to be merged when the pipeline succeeds, you also receive a `HTTP 406 Not Acceptable` error.
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds
@@ -1520,8 +1566,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - Internal ID of MR
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```json
{
@@ -1642,7 +1690,7 @@ Parameters:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -1660,7 +1708,7 @@ Automatically rebase the `source_branch` of the merge request against its
`target_branch`.
If you don't have permissions to push to the merge request's source branch -
-you'll get a `403 Forbidden` response.
+you receive a `403 Forbidden` response.
```plaintext
PUT /projects/:id/merge_requests/:merge_request_iid/rebase
@@ -1668,15 +1716,15 @@ PUT /projects/:id/merge_requests/:merge_request_iid/rebase
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
-| `skip_ci` | boolean | no | Set to `true` to skip creating a CI pipeline |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+| `skip_ci` | boolean | no | Set to `true` to skip creating a CI pipeline. |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase"
```
-This is an asynchronous request. The API will return a `202 Accepted` response
+This is an asynchronous request. The API returns a `HTTP 202 Accepted` response
if the request is enqueued successfully, with a response containing:
```json
@@ -1689,7 +1737,7 @@ You can poll the [Get single MR](#get-single-mr) endpoint with the
`include_rebase_in_progress` parameter to check the status of the
asynchronous request.
-If the rebase operation is ongoing, the response will include the following:
+If the rebase operation is ongoing, the response includes the following:
```json
{
@@ -1698,7 +1746,7 @@ If the rebase operation is ongoing, the response will include the following:
}
```
-Once the rebase operation has completed successfully, the response will include
+After the rebase operation has completed successfully, the response includes
the following:
```json
@@ -1708,7 +1756,7 @@ the following:
}
```
-If the rebase operation fails, the response will include the following:
+If the rebase operation fails, the response includes the following:
```json
{
@@ -1721,7 +1769,7 @@ If the rebase operation fails, the response will include the following:
Comments are done via the [notes](notes.md) resource.
-## List issues that will close on merge
+## List issues that close on merge
Get all the issues that would be closed by merging the provided merge request.
@@ -1731,8 +1779,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/closes_issues
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues"
@@ -1785,7 +1833,7 @@ Example response when the GitLab issue tracker is used:
]
```
-Example response when an external issue tracker (e.g. Jira) is used:
+Example response when an external issue tracker (for example, Jira) is used:
```json
[
@@ -1799,7 +1847,7 @@ Example response when an external issue tracker (e.g. Jira) is used:
## Subscribe to a merge request
Subscribes the authenticated user to a merge request to receive notification. If the user is already subscribed to the merge request, the
-status code `304` is returned.
+status code `HTTP 304 Not Modified` is returned.
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/subscribe
@@ -1807,8 +1855,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/subscribe
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe"
@@ -1934,7 +1982,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -1950,7 +1998,7 @@ the `approvals_before_merge` parameter:
Unsubscribes the authenticated user from a merge request to not receive
notifications from that merge request. If the user is
-not subscribed to the merge request, the status code `304` is returned.
+not subscribed to the merge request, the status code `HTTP 304 Not Modified` is returned.
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe
@@ -1958,8 +2006,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe"
@@ -2085,7 +2133,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -2101,7 +2149,7 @@ the `approvals_before_merge` parameter:
Manually creates a to-do item for the current user on a merge request.
If there already exists a to-do item for the user on that merge request,
-status code `304` is returned.
+status code `HTTP 304 Not Modified` is returned.
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/todo
@@ -2109,8 +2157,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/todo
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo"
@@ -2226,8 +2274,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/versions
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | String | yes | The ID of the project |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | String | yes | The ID of the project. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions"
@@ -2267,9 +2315,9 @@ GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | String | yes | The ID of the project |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
-| `version_id` | integer | yes | The ID of the merge request diff version |
+| `id` | String | yes | The ID of the project. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+| `version_id` | integer | yes | The ID of the merge request diff version. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1"
@@ -2335,9 +2383,9 @@ POST /projects/:id/merge_requests/:merge_request_iid/time_estimate
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
-| `duration` | string | yes | The duration in human format. e.g: 3h30m |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+| `duration` | string | yes | The duration in human format, such as `3h30m`. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m"
@@ -2364,8 +2412,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate"
@@ -2384,7 +2432,7 @@ Example response:
## Add spent time for a merge request
-Adds spent time for this merge request
+Adds spent time for this merge request.
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time
@@ -2392,9 +2440,9 @@ POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
-| `duration` | string | yes | The duration in human format. e.g: 3h30m |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+| `duration` | string | yes | The duration in human format, such as `3h30m` |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h"
@@ -2421,8 +2469,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time"
@@ -2447,8 +2495,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/time_stats
| 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 |
-| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats"
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 621d8179d98..fe20d5ab353 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -11,7 +11,7 @@ Notes are comments on:
- Snippets
- Issues
- Merge requests
-- Epics **(ULTIMATE)**
+- Epics **(PREMIUM)**
This includes system notes, which are notes about changes to the object (for example, when an
assignee changes, GitLab posts a system note).
@@ -185,6 +185,8 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## Snippets
+The Snippets Notes API is intended for project-level snippets, and not for personal snippets.
+
### List all snippet notes
Gets a list of all notes for a single snippet. Snippet notes are comments users can post to a snippet.
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 50d063bdf71..a80a97890ba 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -2,7 +2,7 @@
type: reference, howto
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/technica l-writing/#designated-technical-writers
+info: 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
---
# GitLab as an OAuth2 provider
@@ -19,17 +19,26 @@ documentation. This functionality is based on the
GitLab currently supports the following authorization flows:
-- **Web application flow:** Most secure and common type of flow, designed for
- applications with secure server-side.
-- **Implicit grant flow:** This flow is designed for user-agent only apps (e.g., single
- page web application running on GitLab Pages).
-- **Resource owner password credentials flow:** To be used **only** for securely
- hosted, first-party services.
+- **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.
+- **Authorization code:** Secure and common flow. Recommended option for secure
+ server-side apps.
+- **Implicit grant:** Originally designed for user-agent only apps, such as
+ single page web apps running on GitLab Pages).
+ The [IETF](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-09#section-2.1.2)
+ recommends against Implicit grant flow.
+- **Resource owner password credentials:** To be used **only** for securely
+ hosted, first-party services. GitLab recommends against use of this flow.
+
+The draft specification for [OAuth 2.1](https://oauth.net/2.1/) specifically omits both the
+Implicit grant and Resource Owner Password Credentials flows.
+ it will be deprecated in the next OAuth specification version.
Refer to the [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out
how all those flows work and pick the right one for your use case.
-Both **web application** and **implicit grant** flows require `application` to be
+Both **authorization code** (with or without PKCE) and **implicit grant** flows require `application` to be
registered first via the `/profile/applications` page in your user's account.
During registration, by enabling proper scopes, you can limit the range of
resources which the `application` can access. Upon creation, you'll obtain the
@@ -57,19 +66,84 @@ These factors are particularly important when using the
In the following sections you will find detailed instructions on how to obtain
authorization with each flow.
-### Web application flow
+### Authorization code with Proof Key for Code Exchange (PKCE)
+
+The [PKCE RFC](https://tools.ietf.org/html/rfc7636#section-1.1) includes a
+detailed flow description, from authorization request through access token.
+The following steps describe our implementation of the flow.
+
+The Authorization code with PKCE flow, PKCE for short, makes it possible to securely perform
+the OAuth exchange of client credentials for access tokens on public clients.
+
+Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `CODE_CHALLENGE`.
+
+- The `STATE` 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.
+- The `CODE_VERIFIER` is a random string, between 43 and 128 characters in length,
+ which use the characters `A-Z`, `a-z`, `0-9`, `-`, `.`, `_`, and `~`.
+- The `CODE_CHALLENGE` is an URL-safe base64-encoded string of the SHA256 hash of the
+ `CODE_VERIFIER`
+ - In Ruby, you can set that up with `Base64.urlsafe_encode64(Digest::SHA256.digest(CODE_VERIFIER))`.
+
+1. Request authorization code. To do that, you should redirect the user to the
+ `/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
+ ```
+
+ 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=YOUR_UNIQUE_STATE_HASH
+ ```
+
+1. With the authorization `code` returned from the previous request (denoted 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&code_verifier=CODE_VERIFIER'
+ RestClient.post 'https://gitlab.example.com/oauth/token', parameters
+ ```
+
+ Example response:
+
+ ```json
+ {
+ "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
+ "token_type": "bearer",
+ "expires_in": 7200,
+ "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1",
+ "created_at": 1607635748
+ }
+ ```
+
+NOTE:
+The `redirect_uri` must match the `redirect_uri` used in the original
+authorization request.
+
+You can now make requests to the API with the access token.
+
+### Authorization code flow
NOTE:
Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.1) for a
detailed flow description.
-The web application flow is:
+The authorization code flow is essentially the same as
+[authorization code flow with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce),
1. Request authorization code. To do that, you should redirect the user to the
`/oauth/authorize` endpoint with the following GET 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
+ 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
@@ -80,12 +154,12 @@ The web application flow is:
include the GET `code` parameter, for example:
```plaintext
- https://example.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH
+ https://example.com/oauth/redirect?code=1234567890&state=STATE
```
You should then use `code` to request an access token.
-1. Once you have the authorization code you can request an `access_token` using the
+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`:
@@ -101,7 +175,8 @@ The web application flow is:
"access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
"token_type": "bearer",
"expires_in": 7200,
- "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
+ "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1",
+ "created_at": 1607635748
}
```
@@ -114,19 +189,20 @@ You can now make requests to the API with the access token returned.
### Implicit grant flow
NOTE:
-Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.2) for a
-detailed flow description.
+For a detailed flow diagram, see the [RFC specification](https://tools.ietf.org/html/rfc6749#section-4.2).
WARNING:
-Avoid using this flow for applications that store data outside of the GitLab
-instance. If you do, make sure to verify `application id` associated with the
-access token before granting access to the data
-(see [`/oauth/token/info`](#retrieving-the-token-information)).
-
-Unlike the web flow, the client receives an `access token` immediately as a
-result of the authorization request. The flow does not use the client secret
-or the authorization code because all of the application code and storage is
-easily accessible, therefore secrets can leak easily.
+The Implicit grant flow is inherently insecure. The IETF plans to remove it in
+[OAuth 2.1](https://oauth.net/2.1/).
+
+We recommend that you use [Authorization code with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce) instead. If you choose to use Implicit flow, be sure to verify the
+`application id` (or `client_id`) associated with the access token before granting
+access to the data, as described in [Retrieving the token information](#retrieving-the-token-information)).
+
+Unlike the authorization code flow, the client receives an `access token`
+immediately as a result of the authorization request. The flow does not use
+the client secret or the authorization code because all of the application code
+and storage is easily accessible on client browsers and mobile devices.
To request the access token, you should redirect the user to the
`/oauth/authorize` endpoint using `token` response type:
diff --git a/doc/api/openapi/openapi.yaml b/doc/api/openapi/openapi.yaml
index 8c46804d86f..1a80daf304c 100644
--- a/doc/api/openapi/openapi.yaml
+++ b/doc/api/openapi/openapi.yaml
@@ -1,8 +1,13 @@
-openapi: "3.0.0"
+openapi: 3.0.0
+tags:
+ - name: version
+ description: Version
+ - name: access_requests
+ description: Access requests for projects and groups
info:
description: |
An OpenAPI definition for the GitLab REST API.
- Only one API resource/endpoint is currently included.
+ Few API resources or endpoints are currently included.
The intent is to expand this to match the entire Markdown documentation of the API:
<https://docs.gitlab.com/ee/api/>. Contributions are welcome.
@@ -12,15 +17,46 @@ info:
so each request is made using your account.
Read more at <https://docs.gitlab.com/ee/development/documentation/restful_api_styleguide.html>.
- version: "v4"
- title: "GitLab API"
- termsOfService: "https://about.gitlab.com/terms/"
+ version: v4
+ title: GitLab API
+ termsOfService: 'https://about.gitlab.com/terms/'
license:
- name: "CC BY-SA 4.0"
- url: "https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE"
+ name: CC BY-SA 4.0
+ url: 'https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE'
servers:
- - url: "https://gitlab.com/api/"
+ - url: 'https://gitlab.com/api/'
+security:
+ - ApiKeyAuth: []
+
+components:
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ in: header
+ name: Private-Token
paths:
+ # VERSION
/v4/version:
- $ref: "v4/version.yaml"
+ $ref: 'v4/version.yaml'
+
+ # ACCESS REQUESTS (PROJECTS)
+ /v4/projects/{id}/access_requests:
+ $ref: 'v4/access_requests.yaml#/accessRequestsProjects'
+
+ /v4/projects/{id}/access_requests/{user_id}/approve:
+ $ref: 'v4/access_requests.yaml#/accessRequestsProjectsApprove'
+
+ /v4/projects/{id}/access_requests/{user_id}:
+ $ref: 'v4/access_requests.yaml#/accessRequestsProjectsDeny'
+
+ # ACCESS REQUESTS (GROUPS)
+ /v4/groups/{id}/access_requests:
+ $ref: 'v4/access_requests.yaml#/accessRequestsGroups'
+
+ /v4/groups/{id}/access_requests/{user_id}/approve:
+ $ref: 'v4/access_requests.yaml#/accessRequestsGroupsApprove'
+
+ /v4/groupss/{id}/access_requests/{user_id}:
+ $ref: 'v4/access_requests.yaml#/accessRequestsGroupsDeny'
+
diff --git a/doc/api/openapi/v4/access_requests.yaml b/doc/api/openapi/v4/access_requests.yaml
new file mode 100644
index 00000000000..157a0973e1e
--- /dev/null
+++ b/doc/api/openapi/v4/access_requests.yaml
@@ -0,0 +1,381 @@
+# Markdown documentation: https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/api/access_requests.md
+
+#/v4/projects/{id}/access_requests
+accessRequestsProjects:
+ get:
+ description: Lists access requests for a project
+ summary: List access requests for a project
+ operationId: accessRequestsProjects_get
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the project owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ responses:
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ title: ProjectAccessResponse
+ type: object
+ properties:
+ id:
+ type: integer
+ usename:
+ type: string
+ name:
+ type: string
+ state:
+ type: string
+ created_at:
+ type: string
+ requested_at:
+ type: string
+ example:
+ - "id": 1
+ "username": "raymond_smith"
+ "name": "Raymond Smith"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "requested_at": "2012-10-22T14:13:35Z"
+ - "id": 2
+ "username": "john_doe"
+ "name": "John Doe"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "requested_at": "2012-10-22T14:13:35Z"
+ post:
+ description: Requests access for the authenticated user to a project
+ summary: Requests access for the authenticated user to a project
+ operationId: accessRequestsProjects_post
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the project owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ responses:
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ title: ProjectAccessRequest
+ type: object
+ properties:
+ id:
+ type: integer
+ usename:
+ type: string
+ name:
+ type: string
+ state:
+ type: string
+ created_at:
+ type: string
+ requested_at:
+ type: string
+ example:
+ "id": 1
+ "username": "raymond_smith"
+ "name": "Raymond Smith"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "requested_at": "2012-10-22T14:13:35Z"
+
+#/v4/projects/{id}/access_requests/{user_id}/approve
+accessRequestsProjectsApprove:
+ put:
+ description: Approves access for the authenticated user to a project
+ summary: Approves access for the authenticated user to a project
+ operationId: accessRequestsProjectsApprove_put
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the project owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ - name: user_id
+ in: path
+ description: The userID of the access requester
+ required: true
+ schema:
+ type: integer
+ - name: access_level
+ in: query
+ description: A valid project access level. 0 = no access , 10 = guest, 20 = reporter, 30 = developer, 40 = Maintainer. Default is 30.'
+ required: false
+ schema:
+ enum: [0, 10, 20, 30, 40]
+ default: 30
+ type: integer
+ responses:
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ title: ProjectAccessApprove
+ type: object
+ properties:
+ id:
+ type: integer
+ usename:
+ type: string
+ name:
+ type: string
+ state:
+ type: string
+ created_at:
+ type: string
+ access_level:
+ type: integer
+ example:
+ "id": 1
+ "username": "raymond_smith"
+ "name": "Raymond Smith"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "access_level": 20
+
+#/v4/projects/{id}/access_requests/{user_id}
+accessRequestsProjectsDeny:
+ delete:
+ description: Denies a project access request for the given user
+ summary: Denies a project access request for the given user
+ operationId: accessRequestProjectsDeny_delete
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the project owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ - name: user_id
+ in: path
+ description: The user ID of the access requester
+ required: true
+ schema:
+ type: integer
+ responses: # Does anything go here? Markdown doc does not list a response.
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+
+#/v4/groups/{id}/access_requests
+accessRequestsGroups:
+ get:
+ description: List access requests for a group
+ summary: List access requests for a group
+ operationId: accessRequestsGroups_get
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the group owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ responses:
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ title: GroupAccessResponse
+ type: object
+ properties:
+ id:
+ type: integer
+ usename:
+ type: string
+ name:
+ type: string
+ state:
+ type: string
+ created_at:
+ type: string
+ requested_at:
+ type: string
+ example:
+ - "id": 1
+ "username": "raymond_smith"
+ "name": "Raymond Smith"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "requested_at": "2012-10-22T14:13:35Z"
+ - "id": 2
+ "username": "john_doe"
+ "name": "John Doe"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "requested_at": "2012-10-22T14:13:35Z"
+ post:
+ description: Requests access for the authenticated user to a group
+ summary: Requests access for the authenticated user to a group
+ operationId: accessRequestsGroups_post
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the group owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ responses:
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ title: GroupAccessRequest
+ type: object
+ properties:
+ id:
+ type: integer
+ usename:
+ type: string
+ name:
+ type: string
+ state:
+ type: string
+ created_at:
+ type: string
+ requested_at:
+ type: string
+ example:
+ "id": 1
+ "username": "raymond_smith"
+ "name": "Raymond Smith"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "requested_at": "2012-10-22T14:13:35Z"
+
+#/v4/groups/{id}/access_requests/{user_id}/approve
+accessRequestsGroupsApprove:
+ put:
+ description: Approves access for the authenticated user to a group
+ summary: Approves access for the authenticated user to a group
+ operationId: accessRequestsGroupsApprove_put
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the group owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ - name: user_id
+ in: path
+ description: The userID of the access requester
+ required: true
+ schema:
+ type: integer
+ - name: access_level
+ in: query
+ description: A valid group access level. 0 = no access , 10 = Guest, 20 = Reporter, 30 = Developer, 40 = Maintainer, 50 = Owner. Default is 30.
+ required: false
+ schema:
+ enum: [0, 10, 20, 30, 40, 50]
+ default: 30
+ type: integer
+ responses:
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ title: GroupAccessApprove
+ type: object
+ properties:
+ id:
+ type: integer
+ usename:
+ type: string
+ name:
+ type: string
+ state:
+ type: string
+ created_at:
+ type: string
+ access_level:
+ type: integer
+ example:
+ "id": 1
+ "username": "raymond_smith"
+ "name": "Raymond Smith"
+ "state": "active"
+ "created_at": "2012-10-22T14:13:35Z"
+ "access_level": 20
+
+#/v4/groups/{id}/access_requests/{user_id}
+accessRequestsGroupsDeny:
+ delete:
+ description: Denies a group access request for the given user
+ summary: Denies a group access request for the given user
+ operationId: accessRequestsGroupsDeny_delete
+ tags:
+ - access_requests
+ parameters:
+ - name: id
+ in: path
+ description: The ID or URL-encoded path of the group owned by the authenticated user.
+ required: true
+ schema:
+ oneOf:
+ - type: integer
+ - type: string
+ - name: user_id
+ in: path
+ description: The userID of the access requester
+ required: true
+ schema:
+ type: integer
+ responses: # Does anything go here? Markdown doc does not list a response.
+ '401':
+ description: Unauthorized operation
+ '200':
+ description: Successful operation
diff --git a/doc/api/packages.md b/doc/api/packages.md
index a52487e35a3..a0d966fdd88 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Packages API
-This is the API docs of [GitLab Packages](../administration/packages/index.md).
+This is the API documentation of [GitLab Packages](../administration/packages/index.md).
## List packages
@@ -28,6 +28,7 @@ GET /projects/:id/packages
| `sort` | string | no | The direction of the order, either `asc` (default) for ascending order or `desc` for descending order. |
| `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_)
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages"
@@ -67,7 +68,7 @@ Example response:
]
```
-By default, the `GET` request returns 20 results, since the API is [paginated](README.md#pagination).
+By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination).
### Within a group
@@ -88,6 +89,7 @@ GET /groups/:id/packages
| `sort` | string | no | The direction of the order, either `asc` (default) for ascending order or `desc` for descending order. |
| `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_)
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true"
@@ -157,7 +159,7 @@ Example response:
]
```
-By default, the `GET` request returns 20 results, since the API is [paginated](README.md#pagination).
+By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination).
The `_links` object contains the following properties:
@@ -314,7 +316,7 @@ Example response:
]
```
-By default, the `GET` request returns 20 results, since the API is [paginated](README.md#pagination).
+By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination).
## Delete a project package
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index b3e007308ba..ca0ac3522c3 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -70,7 +70,8 @@ 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.
+> - [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.
Revoke a personal access token.
@@ -96,4 +97,4 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## Create a personal access token (admin only)
-See the [Users API documentation](users.md#create-a-personal-access-token-admin-only) for information on creating a personal access token.
+See the [Users API documentation](users.md#create-a-personal-access-token) for information on creating a personal access token.
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index c5799a63c5c..0711cc8abd6 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -193,7 +193,7 @@ requests.post(url, headers=headers, data=data, files=files)
```
NOTE:
-The maximum import file size can be set by the Administrator, default is 50MB.
+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).
## Import status
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 8f6b9b83ca3..413d89950cd 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -80,9 +80,9 @@ POST /projects/:id/variables
| `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` |
-| `protected` | boolean | no | Whether the variable is protected |
-| `masked` | boolean | no | Whether the variable is masked |
-| `environment_scope` | string | no | The `environment_scope` of the variable |
+| `protected` | boolean | no | Whether the variable is protected. Default: `false` |
+| `masked` | boolean | no | Whether the variable is masked. Default: `false` |
+| `environment_scope` | string | no | The `environment_scope` of the variable. Default: `*` |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index 07743a48654..52c357ca32a 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -30,9 +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).
+
## Limitations
-- The repositories associated with snippets [can't be moved with the API](https://gitlab.com/groups/gitlab-org/-/epics/3393).
- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
## Retrieve all project repository storage moves
diff --git a/doc/api/projects.md b/doc/api/projects.md
index b9f6448085d..f9a4b3ba55e 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -160,6 +160,7 @@ When the user is authenticated and `simple` is not set this returns something li
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -253,6 +254,7 @@ When the user is authenticated and `simple` is not set this returns something li
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -297,7 +299,7 @@ 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/),
-the `marked_for_deletion_at` attribute has been deprecated, and will be removed
+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/)
@@ -418,6 +420,7 @@ GET /users/:user_id/projects
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -511,6 +514,7 @@ GET /users/:user_id/projects
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -640,6 +644,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -726,6 +731,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -881,6 +887,7 @@ GET /projects/:id
"repository_storage": "default",
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"printing_merge_requests_link_enabled": true,
@@ -1057,7 +1064,7 @@ POST /projects
| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time in minutes that a job is able run (in seconds). |
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
-| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
+| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
| `default_branch` | string | **{dotted-circle}** No | `master` by default. |
| `description` | string | **{dotted-circle}** No | Short project description. |
@@ -1206,7 +1213,7 @@ PUT /projects/:id
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone). |
| `ci_forward_deployment_enabled` | boolean | **{dotted-circle}** No | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending |
-| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
+| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
| `default_branch` | string | **{dotted-circle}** No | `master` by default. |
| `description` | string | **{dotted-circle}** No | Short project description. |
@@ -1234,6 +1241,7 @@ PUT /projects/:id
| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
+| `restrict_user_defined_variables` | boolean | **{dotted-circle}** No | Allow only maintainers to pass user-defined variables when triggering a pipeline. For example when the pipeline is triggered in the UI, with the API, or by a trigger token. |
| `path` | string | **{dotted-circle}** No | Custom repository name for the project. By default generated based on name. |
| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. |
| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
@@ -1356,6 +1364,7 @@ Example responses:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -1449,6 +1458,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -1540,6 +1550,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -1725,6 +1736,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -1837,6 +1849,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": false,
+ "restrict_user_defined_variables": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
@@ -2184,7 +2197,7 @@ POST /projects/:id/housekeeping
## Push Rules **(STARTER)**
-### Get project push rules
+### Get project push rules **(STARTER)**
Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a
project.
@@ -2230,7 +2243,7 @@ parameters:
}
```
-### Add project push rule
+### Add project push rule **(STARTER)**
Adds a push rule to a specified project.
@@ -2238,22 +2251,22 @@ Adds a push rule to a specified project.
POST /projects/:id/push_rule
```
-| Attribute | Type | Required | Description |
-|-----------------------------------------------|----------------|------------------------|-------------|
-| `author_email_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
-| `branch_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
-| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
-| `commit_message_negative_regex` **(STARTER)** | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. |
-| `commit_message_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
-| `deny_delete_tag` **(STARTER)** | boolean | **{dotted-circle}** No | Deny deleting a tag. |
-| `file_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
-| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
-| `max_file_size` **(STARTER)** | integer | **{dotted-circle}** No | Maximum file size (MB). |
-| `member_check` **(STARTER)** | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
-| `prevent_secrets` **(STARTER)** | boolean | **{dotted-circle}** No | GitLab will reject 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. |
+| Attribute | Type | Required | Description |
+|-----------------------------------------|----------------|------------------------|-------------|
+| `author_email_regex` | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
+| `branch_name_regex` | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
+| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
+| `commit_message_negative_regex` | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. |
+| `commit_message_regex` | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
+| `deny_delete_tag` | boolean | **{dotted-circle}** No | Deny deleting a tag. |
+| `file_name_regex` | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
+| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `max_file_size` | integer | **{dotted-circle}** No | Maximum file size (MB). |
+| `member_check` | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
+| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commit when it's not signed through GPG. |
-### Edit project push rule
+### Edit project push rule **(STARTER)**
Edits a push rule for a specified project.
@@ -2261,20 +2274,20 @@ Edits a push rule for a specified project.
PUT /projects/:id/push_rule
```
-| Attribute | Type | Required | Description |
-|-----------------------------------------------|----------------|------------------------|-------------|
-| `author_email_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
-| `branch_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
-| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
-| `commit_message_negative_regex` **(STARTER)** | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. |
-| `commit_message_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
-| `deny_delete_tag` **(STARTER)** | boolean | **{dotted-circle}** No | Deny deleting a tag. |
-| `file_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
-| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
-| `max_file_size` **(STARTER)** | integer | **{dotted-circle}** No | Maximum file size (MB). |
-| `member_check` **(STARTER)** | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
-| `prevent_secrets` **(STARTER)** | boolean | **{dotted-circle}** No | GitLab will reject any files that are likely to contain secrets. |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commits when they are not GPG signed. |
+| Attribute | Type | Required | Description |
+|-----------------------------------------|----------------|------------------------|-------------|
+| `author_email_regex` | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. |
+| `branch_name_regex` | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. |
+| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. |
+| `commit_message_negative_regex` | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. |
+| `commit_message_regex` | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
+| `deny_delete_tag` | boolean | **{dotted-circle}** No | Deny deleting a tag. |
+| `file_name_regex` | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
+| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `max_file_size` | integer | **{dotted-circle}** No | Maximum file size (MB). |
+| `member_check` | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
+| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commits when they are not GPG signed. |
### Delete project push rule
@@ -2397,6 +2410,7 @@ Example response:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": null,
+ "restrict_user_defined_variables": false,
"request_access_enabled": true,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": true,
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index 0cb11a2b586..a58d6246a63 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -28,7 +28,7 @@ GET /projects/:id/releases
Example request:
```shell
-curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases"
```
Example response:
@@ -233,7 +233,7 @@ GET /projects/:id/releases/:tag_name
Example request:
```shell
-curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
```
Example response:
@@ -360,21 +360,21 @@ POST /projects/:id/releases
| -------------------| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
| `name` | string | no | The release name. |
-| `tag_name` | string | yes | The tag where the release will be created from. |
+| `tag_name` | string | yes | The tag where the release is created from. |
| `description` | string | no | The description of the release. You can use [Markdown](../../user/markdown.md). |
-| `ref` | string | yes, if `tag_name` doesn't exist | If a tag specified in `tag_name` doesn't exist, the release will be created from `ref` and tagged with `tag_name`. It can be a commit SHA, another tag name, or a branch name. |
+| `ref` | string | yes, if `tag_name` doesn't exist | If a tag specified in `tag_name` doesn't exist, the release is created from `ref` and tagged with `tag_name`. It can be a commit SHA, another tag name, or a branch name. |
| `milestones` | array of string | no | The title of each milestone the release is associated with. [GitLab Premium](https://about.gitlab.com/pricing/) customers can specify group milestones. |
| `assets:links` | array of hash | no | An array of assets links. |
| `assets:links:name`| string | required by: `assets:links` | The name of the link. Link names must be unique within the release. |
| `assets:links:url` | string | required by: `assets:links` | The URL of the link. Link URLs must be unique within the release. |
| `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets).
| `assets:links:link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`.
-| `released_at` | datetime | no | The date when the release will be/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `released_at` | datetime | no | The date when the release is/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
Example request:
```shell
-curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \
+curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: <your_access_token>" \
--data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestones": ["v1.0", "v1.0-rc"], "assets": { "links": [{ "name": "hoge", "url": "https://google.com", "filepath": "/binaries/linux-amd64", "link_type":"other" }] } }' \
--request POST "https://gitlab.example.com/api/v4/projects/24/releases"
```
@@ -493,7 +493,7 @@ Example response:
Group milestones associated with the project may be specified in the `milestones`
array for [Create a release](#create-a-release) and [Update a release](#update-a-release)
API calls. Only milestones associated with the project's group may be specified, and
-adding milestones for ancestor groups will raise an error.
+adding milestones for ancestor groups raises an error.
## Collect release evidence **(PREMIUM ONLY)**
@@ -513,7 +513,7 @@ POST /projects/:id/releases/:tag_name/evidence
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/evidence"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/evidence"
```
Example response:
@@ -537,12 +537,12 @@ PUT /projects/:id/releases/:tag_name
| `name` | string | no | The release name. |
| `description` | string | no | The description of the release. You can use [Markdown](../../user/markdown.md). |
| `milestones` | array of string | no | The title of each milestone to associate with the release. [GitLab Premium](https://about.gitlab.com/pricing/) customers can specify group milestones. To remove all milestones from the release, specify `[]`. |
-| `released_at` | datetime | no | The date when the release will be/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `released_at` | datetime | no | The date when the release is/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
Example request:
```shell
-curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
+curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
```
Example response:
@@ -631,7 +631,7 @@ Example response:
## Delete a Release
-Delete a Release. Deleting a Release will not delete the associated tag.
+Delete a Release. Deleting a Release doesn't delete the associated tag.
```plaintext
DELETE /projects/:id/releases/:tag_name
@@ -645,7 +645,7 @@ DELETE /projects/:id/releases/:tag_name
Example request:
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
```
Example response:
@@ -717,6 +717,6 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) in GitLab 12.1.
-A release with a `released_at` attribute set to a future date will be labeled an **Upcoming Release** in the UI:
+A release with a `released_at` attribute set to a future date is labeled an **Upcoming Release** in the UI:
![Upcoming release](img/upcoming_release_v12_1.png)
diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md
index 88ce3f6ccb4..911aa8bbbd0 100644
--- a/doc/api/releases/links.md
+++ b/doc/api/releases/links.md
@@ -27,7 +27,7 @@ GET /projects/:id/releases/:tag_name/assets/links
Example request:
```shell
-curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links"
```
Example response:
@@ -68,7 +68,7 @@ GET /projects/:id/releases/:tag_name/assets/links/:link_id
Example request:
```shell
-curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
```
Example response:
@@ -104,7 +104,7 @@ Example request:
```shell
curl --request POST \
- --header "PRIVATE-TOKEN: tkhfG7HgG-LiZd3zfdDC" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
--data name="hellodarwin-amd64" \
--data url="https://gitlab.example.com/mynamespace/hello/-/jobs/688/artifacts/raw/bin/hello-darwin-amd64" \
--data filepath="/bin/hellodarwin-amd64" \
@@ -148,7 +148,7 @@ You have to specify at least one of `name` or `url`
Example request:
```shell
-curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
+curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
```
Example response:
@@ -180,7 +180,7 @@ DELETE /projects/:id/releases/:tag_name/assets/links/:link_id
Example request:
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
```
Example response:
diff --git a/doc/api/scim.md b/doc/api/scim.md
index a9622525478..6e67b6fbc2d 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -15,7 +15,7 @@ The SCIM API implements the [RFC7644 protocol](https://tools.ietf.org/html/rfc76
To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group.
This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities.
-## Get a list of SAML users
+## Get a list of SCIM provisioned users
This endpoint is used as part of the SCIM syncing mechanism. It only returns
a single user based on a unique ID which should match the `extern_uid` of the user.
@@ -74,7 +74,7 @@ Example response:
}
```
-## Get a single SAML user
+## Get a single SCIM provisioned user
```plaintext
GET /api/scim/v2/groups/:group_path/Users/:id
@@ -115,7 +115,7 @@ Example response:
}
```
-## Create a SAML user
+## Create a SCIM provisioned user
```plaintext
POST /api/scim/v2/groups/:group_path/Users/
@@ -161,7 +161,7 @@ Example response:
Returns a `201` status code if successful.
-## Update a single SAML user
+## Update a single SCIM provisioned user
Fields that can be updated are:
@@ -193,7 +193,7 @@ curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/te
Returns an empty response with a `204` status code if successful.
-## Remove a single SAML user
+## Remove a single SCIM provisioned user
Removes the user's SSO identity and group membership.
diff --git a/doc/api/search.md b/doc/api/search.md
index bfa5eb576dc..584b2cbb837 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -998,7 +998,9 @@ Example response:
]
```
-### Scope: notes
+### Scope: notes **(STARTER)**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/6/search?scope=notes&search=maxime"
@@ -1030,7 +1032,9 @@ Example response:
]
```
-### Scope: wiki_blobs
+### Scope: wiki_blobs **(STARTER)**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
Filters are available for this scope:
@@ -1074,7 +1078,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
+### Scope: commits **(STARTER)**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/6/search?scope=commits&search=bye"
@@ -1105,7 +1111,9 @@ Example response:
]
```
-### Scope: blobs
+### Scope: blobs **(STARTER)**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
Filters are available for this scope:
diff --git a/doc/api/services.md b/doc/api/services.md
index 68485d23557..d00ddb07a05 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+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
---
@@ -645,7 +645,7 @@ GET /projects/:id/services/github
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290) in GitLab 11.2.
-Google GSuite team collaboration tool.
+Google Workspace team collaboration tool.
### Create/Edit Hangouts Chat service
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 5680687e87e..264021b3a2d 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -83,7 +83,8 @@ Example response:
"raw_blob_request_limit": 300,
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
- "personal_access_token_prefix": "GL-"
+ "personal_access_token_prefix": "GL-",
+ "rate_limiting_response_text": null
}
```
@@ -176,7 +177,8 @@ Example response:
"raw_blob_request_limit": 300,
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
- "personal_access_token_prefix": "GL-"
+ "personal_access_token_prefix": "GL-",
+ "rate_limiting_response_text": null
}
```
@@ -298,13 +300,14 @@ 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. |
| `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 |
| `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 = 50 |
+| `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 0 (unlimited) |
| `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 |
| `metrics_method_call_threshold` | integer | no | A method call is only tracked when it takes longer than the given amount of milliseconds. |
@@ -330,6 +333,7 @@ listed in the descriptions of the relevant settings.
| `pseudonymizer_enabled` | boolean | no | **(PREMIUM)** When enabled, GitLab runs a background job that produces pseudonymized CSVs of the GitLab database to upload to your configured object storage directory.
| `push_event_activities_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push events are created. [Bulk push events are created](../user/admin_area/settings/push_event_activities_limit.md) if it surpasses that value. |
| `push_event_hooks_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether webhooks and services fire or not. Webhooks and services aren't submitted if it surpasses that value. |
+| `rate_limiting_response_text` | string | no | When rate limiting is enabled via the `throttle_*` settings, send this plain text response when a rate limit is exceeded. 'Retry later' is sent if this is blank. |
| `raw_blob_request_limit` | integer | no | Max number of requests per minute for each raw path. Default: 300. To disable throttling set to 0.|
| `recaptcha_enabled` | boolean | no | (**If enabled, requires:** `recaptcha_private_key` and `recaptcha_site_key`) Enable reCAPTCHA. |
| `recaptcha_private_key` | string | required by: `recaptcha_enabled` | Private key for reCAPTCHA. |
diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md
new file mode 100644
index 00000000000..f60b1dfb449
--- /dev/null
+++ b/doc/api/snippet_repository_storage_moves.md
@@ -0,0 +1,293 @@
+---
+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
+---
+
+# Snippet repository storage moves API **(CORE ONLY)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8.
+
+Snippet 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.
+
+As snippet 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, snippets 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.
+
+Project repositories can be moved using the [Project repository storage moves API](project_repository_storage_moves.md).
+
+## Limitations
+
+- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
+
+## Retrieve all snippet repository storage moves
+
+```plaintext
+GET /snippet_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/snippet_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",
+ "snippet": {
+ "id": 65,
+ "title": "Test Snippet",
+ "description": null,
+ "visibility": "internal",
+ "updated_at": "2020-12-01T11:15:50.385Z",
+ "created_at": "2020-12-01T11:15:50.385Z",
+ "project_id": null,
+ "web_url": "https://gitlab.example.com/-/snippets/65",
+ "raw_url": "https://gitlab.example.com/-/snippets/65/raw",
+ "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git",
+ "http_url_to_repo": "https://gitlab.example.com/snippets/65.git"
+ }
+ }
+]
+```
+
+## Retrieve all repository storage moves for a snippet
+
+```plaintext
+GET /snippets/:snippet_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 |
+| --------- | ---- | -------- | ----------- |
+| `snippet_id` | integer | yes | ID of the snippet. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippets/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",
+ "snippet": {
+ "id": 65,
+ "title": "Test Snippet",
+ "description": null,
+ "visibility": "internal",
+ "updated_at": "2020-12-01T11:15:50.385Z",
+ "created_at": "2020-12-01T11:15:50.385Z",
+ "project_id": null,
+ "web_url": "https://gitlab.example.com/-/snippets/65",
+ "raw_url": "https://gitlab.example.com/-/snippets/65/raw",
+ "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git",
+ "http_url_to_repo": "https://gitlab.example.com/snippets/65.git"
+ }
+ }
+]
+```
+
+## Get a single snippet repository storage move
+
+```plaintext
+GET /snippet_repository_storage_moves/:repository_storage_id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `repository_storage_id` | integer | yes | ID of the snippet repository storage move. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippet_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",
+ "snippet": {
+ "id": 65,
+ "title": "Test Snippet",
+ "description": null,
+ "visibility": "internal",
+ "updated_at": "2020-12-01T11:15:50.385Z",
+ "created_at": "2020-12-01T11:15:50.385Z",
+ "project_id": null,
+ "web_url": "https://gitlab.example.com/-/snippets/65",
+ "raw_url": "https://gitlab.example.com/-/snippets/65/raw",
+ "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git",
+ "http_url_to_repo": "https://gitlab.example.com/snippets/65.git"
+ }
+}
+```
+
+## Get a single repository storage move for a snippet
+
+```plaintext
+GET /snippets/:snippet_id/repository_storage_moves/:repository_storage_id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `snippet_id` | integer | yes | ID of the snippet. |
+| `repository_storage_id` | integer | yes | ID of the snippet repository storage move. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippets/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",
+ "snippet": {
+ "id": 65,
+ "title": "Test Snippet",
+ "description": null,
+ "visibility": "internal",
+ "updated_at": "2020-12-01T11:15:50.385Z",
+ "created_at": "2020-12-01T11:15:50.385Z",
+ "project_id": null,
+ "web_url": "https://gitlab.example.com/-/snippets/65",
+ "raw_url": "https://gitlab.example.com/-/snippets/65/raw",
+ "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git",
+ "http_url_to_repo": "https://gitlab.example.com/snippets/65.git"
+ }
+}
+```
+
+## Schedule a repository storage move for a snippet
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8.
+
+```plaintext
+POST /snippets/:snippet_id/repository_storage_moves
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `snippet_id` | integer | yes | ID of the snippet. |
+| `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/snippets/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",
+ "snippet": {
+ "id": 65,
+ "title": "Test Snippet",
+ "description": null,
+ "visibility": "internal",
+ "updated_at": "2020-12-01T11:15:50.385Z",
+ "created_at": "2020-12-01T11:15:50.385Z",
+ "project_id": null,
+ "web_url": "https://gitlab.example.com/-/snippets/65",
+ "raw_url": "https://gitlab.example.com/-/snippets/65/raw",
+ "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git",
+ "http_url_to_repo": "https://gitlab.example.com/snippets/65.git"
+ }
+}
+```
+
+## Schedule repository storage moves for all snippets on a storage shard
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8.
+
+Schedules repository storage moves for each snippet repository stored on the source storage shard.
+
+```plaintext
+POST /snippet_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/snippet_repository_storage_moves"
+```
+
+Example response:
+
+```json
+{
+ "message": "202 Accepted"
+}
+```
diff --git a/doc/api/users.md b/doc/api/users.md
index f73e1829024..ecfd8e26626 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -89,6 +89,7 @@ GET /users
| `sort` | string | no | Return users sorted in `asc` or `desc` order. Default is `desc` |
| `two_factor` | string | no | Filter users by Two-factor authentication. Filter values are `enabled` or `disabled`. By default it returns all users |
| `without_projects` | boolean | no | Filter users without projects. Default is `false` |
+| `admins` | boolean | no | Return only admin users. Default is `false` |
```json
[
@@ -1480,19 +1481,14 @@ 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 (admin only)
+## Create a personal access token **(CORE ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17176) in GitLab 13.6.
-> - It's [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-an-administrators-ability-to-use-the-api-to-create-personal-access-tokens). **(CORE)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267553) in GitLab 13.8.
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-> Requires admin permissions.
-> Token values are returned once. Make sure you save it - you can't access it again.
-
-It creates a new personal access token.
+Use this API to create a new personal access token. Token values are returned once so,
+make sure you save it as you can't access it again. This API can only be used by
+GitLab administrators.
```plaintext
POST /users/:user_id/personal_access_tokens
@@ -1632,22 +1628,3 @@ Example response:
},
]
```
-
-## Enable or disable an administrator's ability to use the API to create personal access tokens **(CORE)**
-
-An administrator's ability to create personal access tokens through the API 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(:pat_creation_api_for_admin)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:pat_creation_api_for_admin)
-```
diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
index 95ffcdd0b39..60ddfe8ce02 100644
--- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
+++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
@@ -121,9 +121,9 @@ DRIs:
| Role | Who
|------------------------------|------------------------|
-| Product | Jackie Porter |
+| Product | Orit Golowinski |
| Leadership | Daniel Croft |
-| Engineering | Kamil Trzciński |
+| Engineering | Vladimir Shushlin |
Domain Experts:
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index c92b4113465..6be582bb8af 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -119,9 +119,7 @@ This work is being done as part of dedicated epic: [Improve internal usage of
Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). This epic
describes a meta reasons for making these changes.
-## [Who](#who)
-
-### Blueprint
+## Who
Proposal:
@@ -142,24 +140,4 @@ DRIs:
| Leadership | Craig Gomes |
| Engineering | Kamil Trzciński |
-### [Stakeholders](#stakeholders)
-
-| Role | Person | Title
-|--------------------|-----------------------|--------------------------------------------------------------------|
-| Executive Sponsor | Christopher Lefelhocz | Senior Director of Development |
-| Facilitator | Darby Frey | Senior Engineering Manager, Verify |
-| DRI / Leadership | Craig Gomes | Backend Engineering Manager, Memory and Database |
-| DRI / Engineering | Kamil Trzciński | Distinguished Engineer, Ops and Enablement |
-| DRI / Product | Kenny Johnston | Senior Director of Product Management, Ops |
-| Functional Lead | Ricky Wiens | Backend Engineering Manager, Verify:Testing |
-| Functional Lead | Anthony Sandoval | Engineering Manager, Reliability |
-| Functional Lead | James Heimbuck | Senior Product Manager, Verify:Testing |
-| Member | Grzegorz Bizon | Staff Backend Engineer, Verify |
-| Member | Michelle Gill | Engineering Manager, Create:Source Code |
-| Member | Wayne Haber | Director of Engineering, Threat Management |
-| Member | Doug Stull | Senior Fullstack Engineer, Growth:Expansion |
-| Member | Andrew Fontaine | Senior Frontend Engineer, Release |
-| Member | Rémy Coutable | Staff Backend Engineer, Engineering Productivity |
-| Member | Marin Jankovski | Senior Engineering Manager, Infrastructure, Delivery & Scalability |
-
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 0bd97bcb425..740be7d1dbd 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -73,7 +73,7 @@ to your needs:
![Use a `.gitlab-ci.yml` template](img/add_file_template_11_10.png)
-While building your `.gitlab-ci.yml`, you can use the [CI/CD configuration visualization](yaml/visualization.md) to facilitate your writing experience.
+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.
@@ -141,8 +141,8 @@ Its feature set is listed on the table below according to DevOps stages.
| **Release** | |
| [Auto Deploy](../topics/autodevops/stages.md#auto-deploy) | Deploy your application to a production environment in a Kubernetes cluster. |
| [Building Docker images](docker/using_docker_build.md) | Maintain Docker-based projects using GitLab CI/CD. |
-| [Canary Deployments](../user/project/canary_deployments.md) **(PREMIUM)** | Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature. |
-| [Deploy Boards](../user/project/deploy_boards.md) **(PREMIUM)** | Check the current health and status of each CI/CD environment running on Kubernetes. |
+| [Canary Deployments](../user/project/canary_deployments.md) | Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature. |
+| [Deploy Boards](../user/project/deploy_boards.md) | Check the current health and status of each CI/CD environment running on Kubernetes. |
| [Feature Flags](../operations/feature_flags.md) **(PREMIUM)** | Deploy your features behind Feature Flags. |
| [GitLab Pages](../user/project/pages/index.md) | Deploy static websites. |
| [GitLab Releases](../user/project/releases/index.md) | Add release notes to Git tags. |
@@ -221,11 +221,3 @@ been necessary. These are:
#### 10.0
- No breaking changes.
-
-#### 9.0
-
-- [CI variables renaming for GitLab 9.0](variables/deprecated_variables.md#gitlab-90-renamed-variables). Read about the
- deprecated CI variables and what you should use for GitLab 9.0+.
-- [New CI job permissions model](../user/project/new_ci_build_permissions_model.md).
- See what changed in GitLab 8.12 and how that affects your jobs.
- There's a new way to access your Git submodules and LFS objects in jobs.
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index e8b22a24017..08a45714de3 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -316,6 +316,37 @@ rspec:
- rspec spec
```
+If you have jobs that each need a different selection of gems, use the `prefix`
+keyword in the global `cache` definition. This configuration generates a different
+cache for each job.
+
+For example, a testing job might not need the same gems as a job that deploys to
+production:
+
+```yaml
+cache:
+ key:
+ files:
+ - Gemfile.lock
+ prefix: ${CI_JOB_NAME}
+ paths:
+ - vendor/ruby
+
+test_job:
+ stage: test
+ before_script:
+ - bundle install --without production --path vendor/ruby
+ script:
+ - bundle exec rspec
+
+deploy_job:
+ stage: production
+ before_script:
+ - bundle install --without test --path vendor/ruby
+ script:
+ - bundle exec deploy
+```
+
### Caching Go dependencies
Assuming your project is using [Go Modules](https://github.com/golang/go/wiki/Modules) to install
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index 4706180688a..0be86527cb5 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -11,10 +11,9 @@ Interacting with a major cloud provider may have become a much needed task that'
part of your delivery process. With GitLab you can
[deploy your application anywhere](https://about.gitlab.com/stages-devops-lifecycle/deploy-targets/).
-For some specific deployment targets, GitLab makes this process less painful by providing Docker images
-that come with the needed libraries and tools pre-installed.
-By referencing them in your CI/CD pipeline, you'll be able to interact with your chosen
-cloud provider more easily.
+For some specific deployment targets, GitLab makes this process less painful by providing Docker
+images with the needed libraries and tools pre-installed. By referencing them in your
+CI/CD pipeline, you can interact with your chosen cloud provider more easily.
## AWS
@@ -36,7 +35,7 @@ Some credentials are required to be able to run `aws` commands:
1. Select your newly created user to access its details. Navigate to **Security credentials > Create a new access key**.
NOTE:
- A new **Access key ID** and **Secret access key** pair will be generated. Please take a note of them right away.
+ 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)
@@ -170,14 +169,14 @@ After you have these prerequisites ready, follow these steps:
1. Commit and push your updated `.gitlab-ci.yml` to your project's repository, and you're done!
- Your application Docker image will be rebuilt and pushed to the GitLab registry.
+ Your application Docker image is rebuilt and pushed to the GitLab registry.
If your image is located in a private registry, make sure your task definition is
[configured with a `repositoryCredentials` attribute](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html).
- Then the targeted task definition will be updated with the location of the new
- Docker image, and a new revision will be created in ECS as result.
+ Then the targeted task definition is updated with the location of the new
+ Docker image, and a new revision is created in ECS as result.
- Finally, your AWS ECS service will be updated with the new revision of the
+ Finally, your AWS ECS service is updated with the new revision of the
task definition, making the cluster pull the newest version of your
application.
@@ -190,7 +189,7 @@ and [`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blo
used along with the main template. They may move or change unexpectedly causing your
pipeline to fail if you didn't include the main template. Also, the job names within
these templates may change. Do not override these jobs names in your own pipeline,
-as the override will stop working when the name changes.
+as the override stops working when the name changes.
Alternatively, if you don't wish to use the `AWS/Deploy-ECS.gitlab-ci.yml` template
to deploy to AWS ECS, you can always use our
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 8e5ce2fb359..af88a006156 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -7,17 +7,17 @@ type: concepts, howto
# Building Docker images with GitLab CI/CD
-GitLab CI/CD allows you to use Docker Engine to build and test Docker-based projects.
+You can use GitLab CI/CD with Docker Engine to build and test Docker-based projects.
-One of the new trends in Continuous Integration/Deployment is to:
+For example, you might want to:
1. Create an application image.
1. Run tests against the created image.
1. Push image to a remote registry.
1. Deploy to a server from the pushed image.
-It's also useful when your application already has the `Dockerfile` that can be
-used to create and test an image:
+Or, if your application already has a `Dockerfile`, you can
+use it to create and test an image:
```shell
docker build -t my-image dockerfiles/
@@ -26,29 +26,37 @@ docker tag my-image my-registry:5000/my-image
docker push my-registry:5000/my-image
```
-This requires special configuration of GitLab Runner to enable `docker` support
-during jobs.
+To run Docker commands in your CI/CD jobs, you must configure
+GitLab Runner to enable `docker` support.
-## Runner Configuration
+## Enable Docker commands in your CI/CD jobs
-There are three methods to enable the use of `docker build` and `docker run`
-during jobs, each with their own tradeoffs.
+There are three ways to enable the use of `docker build` and `docker run`
+during jobs, each with their own tradeoffs. You can use:
-An alternative to using `docker build` is to [use kaniko](using_kaniko.md).
-This avoids having to execute a runner in privileged mode.
+- [The shell executor](#use-the-shell-executor)
+- [The Docker executor with the Docker image (Docker-in-Docker)](#use-the-docker-executor-with-the-docker-image-docker-in-docker)
+- [Docker socket binding](#use-docker-socket-binding)
-NOTE:
-To see how Docker and GitLab Runner are configured for shared runners on
-GitLab.com, see [GitLab.com shared
-runners](../../user/gitlab_com/index.md#shared-runners).
+If you don't want to execute a runner in privileged mode,
+but want to use `docker build`, you can also [use kaniko](using_kaniko.md).
+
+If you are using shared runners on GitLab.com, see
+[GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners)
+to learn more about how these runners are configured.
-### Use shell executor
+### Use the shell executor
-The simplest approach is to install GitLab Runner in `shell` execution mode.
-GitLab Runner then executes job scripts as the `gitlab-runner` user.
+One way to configure GitLab Runner for `docker` support is to use the
+`shell` executor.
-1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/#installation).
-1. During GitLab Runner installation select `shell` as method of executing job scripts or use command:
+After you register a runner and select the `shell` executor,
+your job scripts are executed as the `gitlab-runner` user.
+This user needs permission to run Docker commands.
+
+1. [Install](https://gitlab.com/gitlab-org/gitlab-runner/#installation) GitLab Runner.
+1. [Register](https://docs.gitlab.com/runner/register/) a runner.
+ Select the `shell` executor. For example:
```shell
sudo gitlab-runner register -n \
@@ -58,12 +66,10 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
--description "My Runner"
```
-1. Install Docker Engine on server.
-
- For more information how to install Docker Engine on different systems,
- check out the [Supported installations](https://docs.docker.com/engine/installation/).
+1. On the server where GitLab Runner is installed, install Docker Engine.
+ View a list of [supported platforms](https://docs.docker.com/engine/installation/).
-1. Add `gitlab-runner` user to `docker` group:
+1. Add the `gitlab-runner` user to the `docker` group:
```shell
sudo usermod -aG docker gitlab-runner
@@ -75,7 +81,7 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
sudo -u gitlab-runner -H docker info
```
- You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml`:
+1. In GitLab, to verify that everything works, add `docker info` to `.gitlab-ci.yml`:
```yaml
before_script:
@@ -87,28 +93,30 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
- docker run my-docker-image /script/to/run/tests
```
-1. You can now use `docker` command (and **install** `docker-compose` if needed).
+You can now use `docker` commands (and install `docker-compose` if needed).
+
+When you add `gitlab-runner` to the `docker` group, you are effectively granting `gitlab-runner` full root permissions.
+Learn more about the [security of the `docker` group](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/).
-By adding `gitlab-runner` to the `docker` group you are effectively granting `gitlab-runner` full root permissions.
-For more information please read [On Docker security: `docker` group considered harmful](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/).
+### Use the Docker executor with the Docker image (Docker-in-Docker)
-### Use Docker-in-Docker workflow with Docker executor
+Another way to configure GitLab Runner for `docker` support is to
+register a runner with the Docker executor and use the [Docker image](https://hub.docker.com/_/docker/)
+to run your job scripts. This configuration is referred to as "Docker-in-Docker."
-The second approach is to use the special Docker-in-Docker (dind)
-[Docker image](https://hub.docker.com/_/docker/) with all tools installed
-(`docker`) and run the job script in context of that
-image in privileged mode.
+The Docker image has all of the `docker` tools installed
+and can run the job script in context of the image in privileged mode.
-`docker-compose` is not part of Docker-in-Docker (dind). To use `docker-compose` in your
-CI builds, follow the `docker-compose`
+The `docker-compose` command is not available in this configuration by default.
+To use `docker-compose` in your job scripts, follow the `docker-compose`
[installation instructions](https://docs.docker.com/compose/install/).
WARNING:
-By enabling `--docker-privileged`, you are effectively disabling all of
+When you enable `--docker-privileged`, you are effectively disabling all of
the security mechanisms of containers and exposing your host to privilege
escalation which can lead to container breakout. For more information, check
out the official Docker documentation on
-[Runtime privilege and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).
+[runtime privilege and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).
Docker-in-Docker works well, and is the recommended configuration, but it is
not without its own challenges:
@@ -363,10 +371,11 @@ build:
- docker run my-docker-image /script/to/run/tests
```
-#### Use Docker socket binding
+### Use Docker socket binding
-The third approach is to bind-mount `/var/run/docker.sock` into the
-container so that Docker is available in the context of that image.
+Another way to configure GitLab Runner for `docker` support is to
+bind-mount `/var/run/docker.sock` into the
+container so that Docker is available in the context of the image.
NOTE:
If you bind the Docker socket and you are
@@ -395,7 +404,7 @@ To make Docker available in the context of the image:
commands are siblings of the runner rather than children of the runner.**
This may have complications and limitations that are unsuitable for your workflow.
- Your `config.toml` file should not have an entry like this:
+ Your `config.toml` file should now have an entry like this:
```toml
[[runners]]
@@ -854,13 +863,13 @@ After you've built a Docker image, you can push it up to the built-in
### `docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?`
This is a common error when you are using
-[Docker in Docker](#use-docker-in-docker-workflow-with-docker-executor)
+[Docker in Docker](#use-the-docker-executor-with-the-docker-image-docker-in-docker)
v19.03 or higher.
This occurs because Docker starts on TLS automatically, so you need to do some setup.
If:
- This is the first time setting it up, carefully read
- [using Docker in Docker workflow](#use-docker-in-docker-workflow-with-docker-executor).
+ [using Docker in Docker workflow](#use-the-docker-executor-with-the-docker-image-docker-in-docker).
- You are upgrading from v18.09 or earlier, read our
[upgrade guide](https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/).
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 7171269cf2d..630e106b72c 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -10,18 +10,18 @@ type: concepts, howto
GitLab CI/CD in conjunction with [GitLab Runner](../runners/README.md) can use
[Docker Engine](https://www.docker.com/) to test and build any application.
-Docker is an open-source project that allows you to use predefined images to
-run applications in independent "containers" that are run within a single Linux
-instance. [Docker Hub](https://hub.docker.com/) has a rich database of pre-built images that can be
-used to test and build your applications.
-
-When used with GitLab CI/CD, Docker runs each job in a separate and isolated
-container using the predefined image that's set up in
-[`.gitlab-ci.yml`](../yaml/README.md).
-
-This makes it easier to have a simple and reproducible build environment that
-can also run on your workstation. The added benefit is that you can test all
-the commands that we explore later from your shell, rather than having to
+Docker is an open-source project that has predefined images you can use to
+run applications in independent "containers." These containers run in a single Linux
+instance. [Docker Hub](https://hub.docker.com/) is a database of pre-built images you can
+use to test and build your applications.
+
+When you use Docker with GitLab CI/CD, Docker runs each job in a separate and isolated
+container. You specify the container image in the project's
+[`.gitlab-ci.yml`](../yaml/README.md) file.
+
+Docker containers provide a reproducible build environment that
+can run on your workstation. When a Docker container is running, you can test
+commands from your shell, rather than having to
test them on a dedicated CI server.
## Register Docker Runner
@@ -29,7 +29,7 @@ test them on a dedicated CI server.
To use GitLab Runner with Docker you need to [register a new runner](https://docs.gitlab.com/runner/register/)
to use the `docker` executor.
-An example can be seen below. First we set up a temporary template to supply the services:
+In this example, we first set up a temporary template to supply the services:
```shell
cat > /tmp/test-config.template.toml << EOF
@@ -42,7 +42,7 @@ name = "mysql:latest"
EOF
```
-Then we register the runner using the template that was just created:
+Then use this template to register the runner:
```shell
sudo gitlab-runner register \
@@ -63,25 +63,26 @@ accessible during the build process.
The `image` keyword is the name of the Docker image the Docker executor
runs to perform the CI tasks.
-By default, the executor only pulls images from [Docker Hub](https://hub.docker.com/),
-however this can be configured in the `gitlab-runner/config.toml` by setting
-the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work) to allow using local images.
+By default, the executor pulls images only from [Docker Hub](https://hub.docker.com/).
+However, you can configure the location in the `gitlab-runner/config.toml` file. For example,
+you can set the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work)
+to use local images.
-For more information about images and Docker Hub, please read
+For more information about images and Docker Hub, read
the [Docker Fundamentals](https://docs.docker.com/engine/understanding-docker/) documentation.
## What is a service
-The `services` keyword defines just another Docker image that's run during
-your job and is linked to the Docker image that the `image` keyword defines.
-This allows you to access the service image during build time.
+The `services` keyword defines another Docker image that's run during
+your job. It's linked to the Docker image that the `image` keyword defines,
+which 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, `mysql`. It's easier and faster to use an
-existing image and run it as an additional container than install `mysql` every
+existing image and run it as an additional container than to install `mysql` every
time the project is built.
-You're not limited to have only database services. You can add as many
+You're not limited to only database services. You can add as many
services you need to `.gitlab-ci.yml` or manually modify `config.toml`.
Any image found at [Docker Hub](https://hub.docker.com/) or your private Container Registry can be
used as a service.
@@ -94,56 +95,57 @@ You can see some widely used services examples in the relevant documentation of
### How services are linked to the job
-To better understand how the container linking works, read
+To better understand how container linking works, read
[Linking containers together](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/).
-To summarize, if you add `mysql` as service to your application, the image is
-then used to create a container that's linked to the job container.
+If you add `mysql` as service to your application, the image is
+used to create a container that's linked to the job container.
The service container for MySQL is accessible under the hostname `mysql`.
-So, in order to access your database service you have to connect to the host
-named `mysql` instead of a socket or `localhost`. Read more in [accessing the
-services](#accessing-the-services).
+To access your database service, connect to the host named `mysql` instead of a
+socket or `localhost`. Read more in [accessing the services](#accessing-the-services).
### How the health check of services works
-Services are designed to provide additional functionality which is **network accessible**.
-It may be a database like MySQL, or Redis, and even `docker:stable-dind` which
-allows you to use Docker in Docker. It can be practically anything that's
-required for the CI/CD job to proceed and is accessed by network.
+Services are designed to provide additional features which are **network accessible**.
+They may be a database like MySQL, or Redis, and even `docker:stable-dind` which
+allows you to use Docker-in-Docker. It can be practically anything that's
+required for the CI/CD job to proceed, and is accessed by network.
To make sure this works, the runner:
1. Checks which ports are exposed from the container by default.
1. Starts a special container that waits for these ports to be accessible.
-When the second stage of the check fails, either because there is no opened port in the
-service, or the service was not started properly before the timeout and the port is not
-responding, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`.
+If the second stage of the check fails, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`.
+This issue can occur because:
+
+- There is no opened port in the service.
+- The service was not started properly before the timeout, and the port is not
+ responding.
In most cases it affects the job, but there may be situations when the job
still succeeds even if that warning was printed. For example:
-- The service was started a little after the warning was raised, and the job is
+- The service was started shortly after the warning was raised, and the job is
not using the linked service from the beginning. In that case, when the
job needed to access the service, it may have been already there waiting for
connections.
- The service container is not providing any networking service, but it's doing
something with the job's directory (all services have the job directory mounted
as a volume under `/builds`). In that case, the service does its job, and
- since the job is not trying to connect to it, it does not fail.
+ because the job is not trying to connect to it, it does not fail.
### What services are not for
-As it was mentioned before, this feature is designed to provide **network accessible**
+As mentioned before, this feature is designed to provide **network accessible**
services. A database is the simplest example of such a service.
-The services feature is not designed to, and does not add any software from the
+The services feature is not designed to, and does not, add any software from the
defined `services` image(s) to the job's container.
For example, if you have the following `services` defined in your job, the `php`,
-`node` or `go` commands are **not** available for your script, and thus
-the job fails:
+`node` or `go` commands are **not** available for your script, and the job fails:
```yaml
job:
@@ -162,16 +164,15 @@ If you need to have `php`, `node` and `go` available for your script, you should
either:
- Choose an existing Docker image that contains all required tools.
-- Create your own Docker image, with all the required tools included
+- Create your own Docker image, with all the required tools included,
and use that in your job.
### Accessing the services
Let's say that you need a Wordpress instance to test some API integration with
-your application.
-
-You can then use for example the [tutum/wordpress](https://hub.docker.com/r/tutum/wordpress/) image in your
-`.gitlab-ci.yml`:
+your application. You can then use for example the
+[`tutum/wordpress`](https://hub.docker.com/r/tutum/wordpress/) image in your
+`.gitlab-ci.yml` file:
```yaml
services:
@@ -179,13 +180,13 @@ services:
```
If you don't [specify a service alias](#available-settings-for-services),
-when the job is run, `tutum/wordpress` is started and you have
-access to it from your build container under two hostnames to choose from:
+when the job runs, `tutum/wordpress` is started. You have
+access to it from your build container under two hostnames:
- `tutum-wordpress`
- `tutum__wordpress`
-Hostnames with underscores are not RFC valid and may cause problems in 3rd party
+Hostnames with underscores are not RFC valid and may cause problems in third-party
applications.
The default aliases for the service's hostname are created from its image name
@@ -202,7 +203,7 @@ To override the default behavior, you can
## Define `image` and `services` from `.gitlab-ci.yml`
-You can simply define an image that's used for all jobs and a list of
+You can define an image that's used for all jobs, and a list of
services that you want to use during build time:
```yaml
@@ -275,7 +276,7 @@ test:
You can also pass custom environment [variables](../variables/README.md)
to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml` file.
-For more information, see [custom environment variables](../variables/README.md#gitlab-ciyml-defined-variables)
+For more information, read [custom environment variables](../variables/README.md#gitlab-ciyml-defined-variables)
```yaml
# The following variables are automatically passed down to the Postgres container
@@ -314,11 +315,11 @@ test:
When configuring the `image` or `services` entries, you can use a string or a map as
options:
-- when using a string as an option, it must be the full name of the image to use
+- When using a string as an option, it must be the full name of the image to use
(including the Registry part if you want to download the image from a Registry
- other than Docker Hub)
-- when using a map as an option, then it must contain at least the `name`
- option, which is the same name of the image as used for the string setting
+ other than Docker Hub).
+- When using a map as an option, then it must contain at least the `name`
+ option, which is the same name of the image as used for the string setting.
For example, the following two definitions are equal:
@@ -350,8 +351,8 @@ For example, the following two definitions are equal:
| Setting | Required | GitLab version | Description |
|------------|----------|----------------| ----------- |
-| `name` | yes, when used with any other option | 9.4 |Full name of the image that should be used. It should contain the Registry part if needed. |
-| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
+| `name` | yes, when used with any other option | 9.4 |Full name of the image to use. It should contain the Registry part if needed. |
+| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
### Available settings for `services`
@@ -359,8 +360,8 @@ For example, the following two definitions are equal:
| Setting | Required | GitLab version | Description |
|------------|----------|----------------| ----------- |
-| `name` | yes, when used with any other option | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. |
-| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
+| `name` | yes, when used with any other option | 9.4 | Full name of the image to use. It should contain the Registry part if needed. |
+| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. |
| `alias` (1) | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
@@ -379,8 +380,8 @@ services:
- mysql:latest
```
-The runner would start two containers using the `mysql:latest` image, but both
-of them would be added to the job's container with the `mysql` alias based on
+The runner would start two containers, each that uses the `mysql:latest` image.
+However, both of them would be added to the job's container with the `mysql` alias, based on
the [default hostname naming](#accessing-the-services). This would end with one
of the services not being accessible.
@@ -404,31 +405,33 @@ in `.gitlab-ci.yml` file.
> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options).
Let's assume you have a `super/sql:latest` image with some SQL database
-inside it and you would like to use it as a service for your job. Let's also
+in it. You would like to use it as a service for your job. Let's also
assume that this image does not start the database process while starting
-the container and the user needs to manually use `/usr/bin/super-sql run` as
+the container. The user needs to manually use `/usr/bin/super-sql run` as
a command to start the database.
-Before the new extended Docker configuration options, you would need to create
-your own image based on the `super/sql:latest` image, add the default command,
-and then use it in job's configuration, like:
+Before the new extended Docker configuration options, you would need to:
-```dockerfile
-# my-super-sql:latest image's Dockerfile
+- Create your own image based on the `super/sql:latest` image.
+- Add the default command.
+- Use the image in the job's configuration:
-FROM super/sql:latest
-CMD ["/usr/bin/super-sql", "run"]
-```
+ ```dockerfile
+ # my-super-sql:latest image's Dockerfile
-```yaml
-# .gitlab-ci.yml
+ FROM super/sql:latest
+ CMD ["/usr/bin/super-sql", "run"]
+ ```
-services:
- - my-super-sql:latest
-```
+ ```yaml
+ # .gitlab-ci.yml
+
+ services:
+ - my-super-sql:latest
+ ```
-After the new extended Docker configuration options, you can now simply
-set a `command` in `.gitlab-ci.yml`, like:
+After the new extended Docker configuration options, you can
+set a `command` in the `.gitlab-ci.yml` file instead:
```yaml
# .gitlab-ci.yml
@@ -438,15 +441,15 @@ services:
command: ["/usr/bin/super-sql", "run"]
```
-As you can see, the syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd).
+The syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd).
### Overriding the entrypoint of an image
> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options).
-Before showing the available entrypoint override methods, let's describe shortly
-how the runner starts and uses a Docker image for the containers used in the
-CI jobs:
+Before showing the available entrypoint override methods, let's describe
+how the runner starts. It uses a Docker image for the containers used in the
+CI/CD jobs:
1. The runner starts a Docker container using the defined entrypoint (default
from `Dockerfile` that may be overridden in `.gitlab-ci.yml`)
@@ -455,32 +458,35 @@ CI jobs:
[`before_script`](../yaml/README.md#before_script),
[`script`](../yaml/README.md#script),
and [`after_script`](../yaml/README.md#after_script)).
-1. The runner sends the script to the container's shell STDIN and receives the
+1. The runner sends the script to the container's shell `stdin` and receives the
output.
-To override the entrypoint of a Docker image, the recommended solution is to
+To override the entrypoint of a Docker image, you should
define an empty `entrypoint` in `.gitlab-ci.yml`, so the runner does not start
a useless shell layer. However, that does not work for all Docker versions, and
-you should check which one your runner is using. Specifically:
+you should check which one your runner is using:
-- If Docker 17.06 or later is used, the `entrypoint` can be set to an empty value.
-- If Docker 17.03 or previous versions are used, the `entrypoint` can be set to
+- _If Docker 17.06 or later is used,_ the `entrypoint` can be set to an empty value.
+- _If Docker 17.03 or previous versions are used,_ the `entrypoint` can be set to
`/bin/sh -c`, `/bin/bash -c` or an equivalent shell available in the image.
The syntax of `image:entrypoint` is similar to [Dockerfile's `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint).
-Let's assume you have a `super/sql:experimental` image with some SQL database
-inside it and you would like to use it as a base image for your job because you
+Let's assume you have a `super/sql:experimental` image with a SQL database
+in it. You want to use it as a base image for your job because you
want to execute some tests with this database binary. Let's also assume that
-this image is configured with `/usr/bin/super-sql run` as an entrypoint. That
-means that when starting the container without additional options, it runs
-the database's process, while the runner expects that the image has no
+this image is configured with `/usr/bin/super-sql run` as an entrypoint. When
+the container starts without additional options, it runs
+the database's process. The runner expects that the image has no
entrypoint or that the entrypoint is prepared to start a shell command.
-With the extended Docker configuration options, instead of creating your
-own image based on `super/sql:experimental`, setting the `ENTRYPOINT`
-to a shell, and then using the new image in your CI job, you can now simply
-define an `entrypoint` in `.gitlab-ci.yml`.
+With the extended Docker configuration options, instead of:
+
+- Creating your own image based on `super/sql:experimental`.
+- Setting the `ENTRYPOINT` to a shell.
+- Using the new image in your CI job.
+
+You can now define an `entrypoint` in the `.gitlab-ci.yml` file.
**For Docker 17.06+:**
@@ -508,7 +514,7 @@ Look for the `[runners.docker]` section:
services = ["mysql:latest", "postgres:latest"]
```
-The image and services defined this way are added to all job run by
+The image and services defined this way are added to all jobs run by
that runner.
## Define an image from a private Container Registry
@@ -516,8 +522,8 @@ that runner.
To access private container registries, the GitLab Runner process can use:
- [Statically defined credentials](#using-statically-defined-credentials). That is, a username and password for a specific registry.
-- [Credentials Store](#using-credentials-store). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store).
-- [Credential Helpers](#using-credential-helpers). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers).
+- [Credentials Store](#using-credentials-store). For more information, read [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store).
+- [Credential Helpers](#using-credential-helpers). For more information, read [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers).
To define which should be used, the GitLab Runner process reads the configuration in the following order:
@@ -531,7 +537,7 @@ To define which should be used, the GitLab Runner process reads the configuratio
GitLab Runner reads this configuration **only** from `config.toml` and ignores it if
it's provided as an environment variable. This is because GitLab Runner uses **only**
-`config.toml` configuration and does not interpolate **ANY** environment variables at
+`config.toml` configuration and does not interpolate **any** environment variables at
runtime.
### Requirements and limitations
@@ -543,7 +549,7 @@ runtime.
at least version **1.8** if you want to use private registries.
- Available for [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html)
in GitLab Runner 13.1 and later.
-- [Credentials Store](#using-credentials-store) and [Credential Helpers](#using-credential-helpers) require binaries to be added to the GitLab Runner's `$PATH`, and require access to do so. Therefore, these features are not available on shared runners or any other runner where the user does not have access to the environment where the runner is installed.
+- [Credentials Store](#using-credentials-store) and [Credential Helpers](#using-credential-helpers) require binaries to be added to the GitLab Runner's `$PATH`, and require access to do so. Therefore, these features are not available on shared runners, or any other runner where the user does not have access to the environment where the runner is installed.
### Using statically-defined credentials
@@ -562,7 +568,7 @@ See below for examples of each.
#### Determining your `DOCKER_AUTH_CONFIG` data
As an example, let's assume you want to use the `registry.example.com:5000/private/image:latest`
-image, which is private and requires you to sign in to a private container
+image. This image is private and requires you to sign in to a private container
registry.
Let's also assume that these are the sign-in credentials:
@@ -592,7 +598,7 @@ Use one of the following methods to determine the value of `DOCKER_AUTH_CONFIG`:
- In some setups, it's possible that Docker client uses the available system key
store to store the result of `docker login`. In that case, it's impossible to
- read `~/.docker/config.json`, so you need to prepare the required
+ read `~/.docker/config.json`, so you must prepare the required
base64-encoded version of `${username}:${password}` and create the Docker
configuration JSON manually. Open a terminal and execute the following command:
@@ -691,7 +697,7 @@ To add `DOCKER_AUTH_CONFIG` to a runner:
To configure credentials store, follow these steps:
1. To use a credentials store, you need an external helper program to interact with a specific keychain or external store.
- Make sure helper program is available in GitLab Runner `$PATH`.
+ Make sure the helper program is available in GitLab Runner `$PATH`.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
@@ -710,16 +716,16 @@ To configure credentials store, follow these steps:
`${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner reads this configuration file
and uses the needed helper for this specific repository.
-`credsStore` is used to access ALL the registries.
-If you want to use both images from private registry and public images from Docker Hub,
-pulling from Docker Hub would fail, because Docker daemon tries to use the same credentials for **ALL** the registries.
+`credsStore` is used to access **all** the registries.
+If you use both images from a private registry and public images from Docker Hub,
+pulling from Docker Hub fails. Docker daemon tries to use the same credentials for **all** the registries.
### Using Credential Helpers
> Support for using Credential Helpers was added in GitLab Runner 12.0
As an example, let's assume that you want to use the `aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest`
-image which is private and requires you to log in into a private container registry.
+image. This image is private and requires you to log in into a private container registry.
To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow these steps:
@@ -750,7 +756,7 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
}
```
- This configures Docker to use the credential helper for all Amazon ECR registries.
+ This configures Docker to use the credential helper for all Amazon Elastic Container Registry (ECR) registries.
- Or, if you're running self-managed runners,
add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
@@ -772,13 +778,13 @@ registries to the `"credHelpers"` hash as described above.
## Configuring services
-Many services accept environment variables which allow you to easily change
-database names or set account names depending on the environment.
+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
service containers.
-For all possible configuration variables check the documentation of each image
+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
@@ -786,12 +792,12 @@ designed to distinguish which variable should go where.
### PostgreSQL service example
-See the specific documentation for
+Read the specific documentation for
[using PostgreSQL as a service](../services/postgres.md).
### MySQL service example
-See the specific documentation for
+Read the specific documentation for
[using MySQL as a service](../services/mysql.md).
## How Docker integration works
@@ -800,15 +806,15 @@ Below is a high level overview of the steps performed by Docker during job
time.
1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`.
-1. Create cache container to store all volumes as defined in `config.toml` and
+1. Create a cache container to store all volumes as defined in `config.toml` and
`Dockerfile` of build image (`ruby:2.6` as in above example).
-1. Create build container and link any service container to build container.
-1. Start build container and send job script to the container.
-1. Run job script.
+1. Create a build container and link any service container to build container.
+1. Start the build container, and send a job script to the container.
+1. Run the job script.
1. Checkout code in: `/builds/group-name/project-name/`.
1. Run any step defined in `.gitlab-ci.yml`.
-1. Check exit status of build script.
-1. Remove build container and all created service containers.
+1. Check the exit status of build script.
+1. Remove the build container and all created service containers.
## How to debug a job locally
@@ -827,8 +833,7 @@ EOF
Here we use as an example the GitLab Runner repository which contains a
Makefile, so running `make` executes the commands defined in the Makefile.
-Your mileage may vary, so instead of `make` you could run the command which
-is specific to your project.
+Instead of `make`, you could run the command which is specific to your project.
Then create some service containers:
@@ -850,7 +855,7 @@ docker run --name build -i --link=service-mysql:mysql --link=service-postgres:po
The above command creates a container named `build` that's spawned from
the `ruby:2.6` image and has two services linked to it. The `build_script` is
-piped using STDIN to the bash interpreter which in turn executes the
+piped using `stdin` to the bash interpreter which in turn executes the
`build_script` in the `build` container.
When you finish testing and no longer need the containers, you can remove them
@@ -861,5 +866,5 @@ docker rm -f -v build service-mysql service-postgres
```
This forcefully (`-f`) removes the `build` container, the two service
-containers as well as all volumes (`-v`) that were created with the container
+containers, and all volumes (`-v`) that were created with the container
creation.
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 13d3c607f8a..7eb2a8286c7 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -14,7 +14,7 @@ container images from a Dockerfile, inside a container or Kubernetes cluster.
kaniko solves two problems with using the
[Docker-in-Docker
-build](using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor) method:
+build](using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) method:
- Docker-in-Docker requires [privileged mode](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
to function, which is a significant security concern.
@@ -70,6 +70,39 @@ build:
- if: $CI_COMMIT_TAG
```
+### Building an image with kaniko behind a proxy
+
+If you use a custom GitLab Runner behind an http(s) proxy, kaniko needs to be set
+up accordingly. This means:
+
+- Adding the proxy to `/kaniko/.docker/config.json`
+- Passing the `http_proxy` environment variables as build args so the Dockerfile
+ instructions can use the proxy when building the image.
+
+The previous example can be extended as follows:
+
+```yaml
+build:
+ stage: build
+ image:
+ name: gcr.io/kaniko-project/executor:debug
+ entrypoint: [""]
+ script:
+ - mkdir -p /kaniko/.docker
+ - |-
+ KANIKOPROXYBUILDARGS=""
+ KANIKOCFG="{ \"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}"
+ if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then
+ KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}"
+ KANIKOPROXYBUILDARGS="--build-arg http_proxy=${http_proxy} --build-arg https_proxy=${https_proxy} --build-arg no_proxy=${no_proxy}"
+ fi
+ KANIKOCFG="${KANIKOCFG} }"
+ echo "${KANIKOCFG}" > /kaniko/.docker/config.json
+ - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile $KANIKOPROXYBUILDARGS --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
+ only:
+ - tags
+```
+
## Using a registry with a custom certificate
When trying to push to a Docker registry that uses a certificate that is signed
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 95419e58d36..4dac076ffb7 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -14,6 +14,9 @@ You can:
- [Restrict write-access to a critical environment](#restrict-write-access-to-a-critical-environment)
- [Prevent deployments during deploy freeze windows](#prevent-deployments-during-deploy-freeze-windows)
+- [Set appropriate roles to your project](#setting-appropriate-roles-to-your-project)
+- [Protect production secrets](#protect-production-secrets)
+- [Separate project for deployments](#separate-project-for-deployments)
If you are using a continuous deployment workflow and want to ensure that concurrent deployments to the same environment do not happen, you should enable the following options:
@@ -38,8 +41,8 @@ For example:
```yaml
deploy:
- script: deploy-to-prod
- resource_group: prod
+ script: deploy-to-prod
+ resource_group: prod
```
Example of a problematic pipeline flow **before** using the resource group:
@@ -89,6 +92,56 @@ If you want to prevent deployments for a particular period, for example during a
vacation period when most employees are out, you can set up a [Deploy Freeze](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze).
During a deploy freeze period, no deployment can be executed. This is helpful to
ensure that deployments do not happen unexpectedly.
+
+## Setting appropriate roles to your project
+
+GitLab supports several different roles that can be assigned to your project members. See
+[Project members permissions](../../user/permissions.md#project-members-permissions)
+for an explanation of these roles and the permissions of each.
+
+<div class="video-fallback">
+ See the video: <a href="https://www.youtube.com/watch?v=Mq3C1KveDc0">How to secure your CD pipelines</a>.
+</div>
+<figure class="video-container">
+ <iframe src="https://www.youtube.com/embed/Mq3C1KveDc0" frameborder="0" allowfullscreen="true"> </iframe>
+</figure>
+
+## Protect production secrets
+
+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)
+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
+[scope variables to specific environments](../variables/where_variables_can_be_used.md#variables-with-an-environment-scope).
+We recommend that you use protected variables on protected environments to make sure that the
+secrets aren't exposed unintentionally. You can also define production secrets on the
+[runner side](../runners/README.md#prevent-runners-from-revealing-sensitive-information).
+This prevents other maintainers from reading the secrets and makes sure that the runner only runs on
+protected branches.
+
+For more information, see [pipeline security](../pipelines/index.md#pipeline-security-on-protected-branches).
+
+## Separate project for deployments
+
+All project maintainers have access to production secrets. If you need to limit the number of users
+that can deploy to a production environment, you can create a separate project and configure a new
+permission model that isolates the CD permissions from the original project and prevents the
+original project's maintainers from accessing the production secret and CD configuration. You can
+connect the CD project to your development projects by using [multi-project pipelines](../multi_project_pipelines.md).
+
+## Protect `gitlab-ci.yml` from change
+
+A `.gitlab-ci.yml` may contain rules to deploy an application to the production server. This
+deployment usually runs automatically after pushing a merge request. To prevent developers from
+changing the `gitlab-ci.yml`, you can define it in a different repository. The configuration can
+reference a file in another project with a completely different set of permissions (similar to
+[separating a project for deployments](#separate-project-for-deployments)).
+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).
## Troubleshooting
@@ -99,14 +152,13 @@ If you have multiple jobs for the same environment (including non-deployment job
```yaml
build:service-a:
- environment:
- name: production
-
+ environment:
+ name: production
+
build:service-b:
- environment:
- name: production
+ environment:
+ name: production
```
-The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might not work well with this configuration, and will need to be disabled.
-
-There is a [plan to introduce a new annotation for environments](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) to address this issue.
+The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might
+not work well with this configuration, and must be disabled.
diff --git a/doc/ci/environments/incremental_rollouts.md b/doc/ci/environments/incremental_rollouts.md
index 81acc3a36e9..15eb4d2c526 100644
--- a/doc/ci/environments/incremental_rollouts.md
+++ b/doc/ci/environments/incremental_rollouts.md
@@ -44,8 +44,8 @@ allows more control over the this feature. The steps in an incremental rollout d
number of pods that are defined for the deployment, which are configured when the Kubernetes
cluster is created.
-For example, if your application has 10 pods and a 10% rollout job is run, the new instance of the
-application will be deployed to a single pod while the remaining 9 will present the previous instance.
+For example, if your application has 10 pods and a 10% rollout job runs, the new instance of the
+application is deployed to a single pod while the remaining nine are present the previous instance.
First we [define the template as manual](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L100-103):
@@ -65,7 +65,7 @@ rollout 10%:
ROLLOUT_PERCENTAGE: 10
```
-When the jobs are built, a **play** button will appear next to the job's name. Click the **play** button
+When the jobs are built, a **play** button appears next to the job's name. Click the **play** button
to release each stage of pods. You can also rollback by running a lower percentage job. Once 100%
is reached, you cannot roll back using this method. It is still possible to roll back by redeploying
the old version using the **Rollback** button on the environment page.
@@ -79,13 +79,13 @@ available, demonstrating manually triggered incremental rollouts.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) in GitLab 11.4.
-Timed rollouts behave in the same way as manual rollouts, except that each job is defined with a delay
-in minutes before it will deploy. Clicking on the job will reveal the countdown.
+Timed rollouts behave in the same way as manual rollouts, except that each job is defined with a
+delay in minutes before it deploys. Clicking the job reveals the countdown.
![Timed rollout](img/timed_rollout_v12_7.png)
-It is possible to combine this functionality with manual incremental rollouts so that the job will
-countdown and then deploy.
+It is possible to combine this functionality with manual incremental rollouts so that the job
+counts down and then deploys.
First we [define the template as timed](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-89):
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 10513e0797e..7bf30ef1b95 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -28,7 +28,7 @@ This helps find bugs in your software, and also in the deployment process as wel
GitLab CI/CD is capable of not only testing or building your projects, but also
deploying them in your infrastructure, with the added benefit of giving you a
-way to track your deployments. In other words, you will always know what is
+way to track your deployments. In other words, you always know what is
currently being deployed or has been deployed on your servers.
It's important to know that:
@@ -102,12 +102,12 @@ We have defined three [stages](../yaml/README.md#stages):
- `build`
- `deploy`
-The jobs assigned to these stages will run in this order. If any job fails, then
-the pipeline fails and jobs that are assigned to the next stage won't run.
+The jobs assigned to these stages run in this order. If any job fails, then
+the pipeline fails and jobs that are assigned to the next stage don't run.
In our case:
-- The `test` job will run first.
+- The `test` job runs first.
- Then the `build` job.
- Lastly the `deploy_staging` job.
@@ -127,13 +127,13 @@ numbers, spaces, and `-`, `_`, `/`, `{`, `}`, or `.`. Also, it must not start no
In summary, with the above `.gitlab-ci.yml` we have achieved the following:
-- All branches will run the `test` and `build` jobs.
-- The `deploy_staging` job will run [only](../yaml/README.md#onlyexcept-basic) on the `master`
+- All branches run the `test` and `build` jobs.
+- The `deploy_staging` job runs [only](../yaml/README.md#onlyexcept-basic) on the `master`
branch, which means all merge requests that are created from branches don't
get deployed to the staging server.
-- When a merge request is merged, all jobs will run and the `deploy_staging`
- job will deploy our code to a staging server while the deployment
- will be recorded in an environment named `staging`.
+- When a merge request is merged, all jobs run and the `deploy_staging`
+ job deploys our code to a staging server while the deployment
+ is recorded in an environment named `staging`.
#### Environment variables and runners
@@ -147,8 +147,8 @@ two forms:
If you change the name of an existing environment, the:
-- `$CI_ENVIRONMENT_NAME` variable will be updated with the new environment name.
-- `$CI_ENVIRONMENT_SLUG` variable will remain unchanged to prevent unintended side
+- `$CI_ENVIRONMENT_NAME` variable is updated with the new environment name.
+- `$CI_ENVIRONMENT_SLUG` variable remains unchanged to prevent unintended side
effects.
Starting with GitLab 9.3, the environment URL is exposed to the runner via
@@ -214,13 +214,13 @@ It parses the `deploy.env` report artifact, registers a list of variables as run
uses it for expanding `environment:url: $DYNAMIC_ENVIRONMENT_URL` and sets it to the environment URL.
You can also specify a static part of the URL at `environment:url:`, such as
`https://$DYNAMIC_ENVIRONMENT_URL`. If the value of `DYNAMIC_ENVIRONMENT_URL` is
-`example.com`, the final result will be `https://example.com`.
+`example.com`, the final result is `https://example.com`.
The assigned URL for the `review/your-branch-name` environment is [visible in the UI](#using-the-environment-url).
Note the following:
-- `stop_review` doesn't generate a dotenv report artifact, so it won't recognize the
+- `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
`stop_review` job.
- If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update
@@ -280,7 +280,7 @@ deploy_prod:
The `when: manual` action:
- Exposes a "play" button in the GitLab UI for that job.
-- Means the `deploy_prod` job will only be triggered when the "play" button is clicked.
+- Means the `deploy_prod` job is only triggered when the "play" button is clicked.
You can find the "play" button in the pipelines, environments, deployments, and jobs views.
@@ -330,7 +330,7 @@ For more information, see [Where variables can be used](../variables/where_varia
Runners expose various [environment variables](../variables/README.md) when a job runs, so
you can use them as environment names.
-In the following example, the job will deploy to all branches except `master`:
+In the following example, the job deploys to all branches except `master`:
```yaml
deploy_review:
@@ -363,7 +363,7 @@ For the value of:
may contain a `/` or other characters that would be invalid in a domain name or URL,
so we use `$CI_ENVIRONMENT_SLUG` to guarantee that we get a valid URL.
- For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL will be something
+ For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL is something
like `https://100-do-the-4f99a2.example.com`. Again, the way you set up
the web server to serve these requests is based on your setup.
@@ -396,7 +396,7 @@ The following configuration options are supported:
- [`namespace`](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
-In the following example, the job will deploy your application to the
+In the following example, the job deploys your application to the
`production` Kubernetes namespace.
```yaml
@@ -414,7 +414,7 @@ deploy:
```
When deploying to a Kubernetes cluster using the GitLab Kubernetes integration,
-information about the cluster and namespace will be displayed above the job
+information about the cluster and namespace is displayed above the job
trace on the deployment job page:
![Deployment cluster information](../img/environments_deployment_cluster_v12_8.png)
@@ -502,7 +502,7 @@ deploy_prod:
A more realistic example would also include copying files to a location where a
webserver (for example, NGINX) could then access and serve them.
-The example below will copy the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`:
+The example below copies the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`:
```yaml
review_app:
@@ -514,7 +514,7 @@ review_app:
url: https://$CI_COMMIT_REF_SLUG.example.com
```
-This example requires that NGINX and GitLab Runner are set up on the server this job will run on.
+This example requires that NGINX and GitLab Runner are set up on the server this job runs on.
See the [limitations](#limitations) section for some edge cases regarding the naming of your
branches and Review Apps.
@@ -526,10 +526,10 @@ The complete example provides the following workflow to developers:
- Push the branch to GitLab.
- Create a merge request.
-Behind the scenes, the runner will:
+Behind the scenes, the runner:
-- Pick up the changes and start running the jobs.
-- Run the jobs sequentially as defined in `stages`:
+- Picks up the changes and starts running the jobs.
+- Runs the jobs sequentially as defined in `stages`:
- First, run the tests.
- If the tests succeed, build the app.
- If the build succeeds, the app is deployed to an environment with a name specific to the
@@ -561,7 +561,7 @@ A list of environments and deployment statuses is available on each project's **
For example:
-![Environment view](../img/environments_available.png)
+![Environment view](../img/environments_available_13_7.png)
This example shows:
@@ -571,10 +571,16 @@ This example shows:
- The commit information of the last deployment, such as who committed it, to what
branch, and the Git SHA of the commit.
- The exact time the last deployment was performed.
+- The upcoming deployment, if a deployment for the environment is in progress.
+- When the environment stops automatically.
- A button that takes you to the URL that you defined under the `environment` keyword
in `.gitlab-ci.yml`.
-- A button that re-deploys the latest deployment, meaning it runs the job
- defined by the environment name for that specific commit.
+- A number of deployment actions, including:
+ - Prevent the environment from [stopping automatically](#automatically-stopping-an-environment).
+ - [Open the live environment](#using-the-environment-url).
+ - Trigger [a manual deployment to a different environment](#configuring-manual-deployments).
+ - [Retry the deployment](#retrying-and-rolling-back).
+ - [Stop the environment](#stopping-an-environment).
The information shown in the **Environments** page is limited to the latest
deployments, but an environment can have multiple deployments.
@@ -587,7 +593,7 @@ deployments, but an environment can have multiple deployments.
> - The environments page can only be viewed by users with [Reporter permission](../../user/permissions.md#project-members-permissions)
> and above. For more information on permissions, see the [permissions documentation](../../user/permissions.md).
> - Only deploys that happen after your `.gitlab-ci.yml` is properly configured
-> will show up in the **Environment** and **Last deployment** lists.
+> show up in the **Environment** and **Last deployment** lists.
### Viewing deployment history
@@ -619,7 +625,7 @@ To retry or rollback a deployment:
#### What to expect with a rollback
Pressing the **Rollback** button on a specific commit triggers a _new_ deployment with its own
-unique job ID. This means that you will see a new deployment that points to the commit you're
+unique job ID. This new deployment points to the commit you're
rolling back to.
Note that the defined deployment process in the job's `script` determines whether the rollback
@@ -633,7 +639,7 @@ places within GitLab:
- In a merge request widget as a link:
![Environment URL in merge request](../img/environments_mr_review_app.png)
- In the Environments view as a button:
- ![Environment URL in environments](../img/environments_available.png)
+ ![Environment URL in environments](../img/environments_available_13_7.png)
- In the Deployments view as a button:
![Environment URL in deployments](../img/deployments_view.png)
@@ -698,20 +704,20 @@ stop_review:
If you can't use [Pipelines for merge requests](../merge_request_pipelines/index.md),
setting the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` is necessary in the
-`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) won't
+`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) doesn't
try to check out the code after the branch is deleted.
When you have an environment that has a stop action defined (typically when
-the environment describes a Review App), GitLab will automatically trigger a
+the environment describes a Review App), GitLab automatically triggers a
stop action when the associated branch is deleted. The `stop_review` job must
be in the same `stage` as the `deploy_review` job in order for the environment
to automatically stop.
Additionally, both jobs should have matching [`rules`](../yaml/README.md#onlyexcept-basic)
or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. In the example
-above, if the configuration is not identical, the `stop_review` job might not be
-included in all pipelines that include the `deploy_review` job, and it will not be
-possible to trigger the `action: stop` to stop the environment automatically.
+above, if the configuration isn't identical, the `stop_review` job might not be
+included in all pipelines that include the `deploy_review` job, and it isn't
+possible to trigger `action: stop` to stop the environment automatically.
You can read more in the [`.gitlab-ci.yml` reference](../yaml/README.md#environmenton_stop).
@@ -767,7 +773,7 @@ stop_review_app:
```
As long as a merge request is active and keeps getting new commits,
-the review app will not stop, so developers don't need to worry about
+the review app doesn't stop, so developers don't need to worry about
re-initiating review app.
On the other hand, since `stop_review_app` is set to `auto_stop_in: 1 week`,
@@ -777,8 +783,8 @@ GitLab automatically triggers the `stop_review_app` job to stop the environment.
You can also check the expiration date of environments through the GitLab UI. To do so,
go to **Operations > Environments > Environment**. You can see the auto-stop period
at the left-top section and a pin-mark button at the right-top section. This pin-mark
-button can be used to prevent auto-stopping the environment. By clicking this button, the `auto_stop_in` setting is over-written
-and the environment will be active until it's stopped manually.
+button can be used to prevent auto-stopping the environment. By clicking this button, the
+`auto_stop_in` setting is overwritten and the environment is active until it's stopped manually.
![Environment auto stop](../img/environment_auto_stop_v12_8.png)
@@ -820,8 +826,8 @@ 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,
-you can use the `action: prepare` keyword to ensure deployments won't be created,
-and no builds would be canceled:
+you can use the `action: prepare` keyword to ensure deployments aren't created,
+and no builds are canceled:
```yaml
build:
@@ -929,13 +935,13 @@ dashboard to appear, you need to Configure Prometheus to collect at least one
In GitLab 9.2 and later, all deployments to an environment are shown directly on the monitoring dashboard.
-Once configured, GitLab will attempt to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md)
+Once configured, GitLab attempts to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md)
for any environment that has had a successful deployment. If monitoring data was
-successfully retrieved, a **Monitoring** button will appear for each environment.
+successfully retrieved, a **Monitoring** button appears for each environment.
![Environment Detail with Metrics](../img/deployments_view.png)
-Clicking on the **Monitoring** button will display a new page showing up to the last
+Clicking the **Monitoring** button displays a new page showing up to the last
8 hours of performance data. It may take a minute or two for data to appear
after initial deployment.
@@ -962,10 +968,10 @@ of your web browser. To enable it, follow the instructions given in the service
documentation.
Note that container-based deployments often lack basic tools (like an editor), and may
-be stopped or restarted at any time. If this happens, you will lose all your
+be stopped or restarted at any time. If this happens, you lose all your
changes. Treat this as a debugging tool, not a comprehensive online IDE.
-Once enabled, your environments will gain a "terminal" button:
+Once enabled, your environments gain a **Terminal** button:
![Terminal button on environment index](../img/environments_terminal_button_on_index.png)
@@ -973,12 +979,12 @@ You can also access the terminal button from the page for a specific environment
![Terminal button for an environment](../img/environments_terminal_button_on_show.png)
-Wherever you find it, clicking the button will take you to a separate page to
+Wherever you find it, clicking the button takes you to a separate page to
establish the terminal session:
![Terminal page](../img/environments_terminal_page.png)
-This works just like any other terminal. You'll be in the container created
+This works like any other terminal. You're in the container created
by your deployment so you can:
- Run shell commands and get responses in real time.
@@ -1008,9 +1014,8 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
You can limit the environment scope of a variable by
defining which environments it can be available for.
-Wildcards can be used, and the default environment scope is `*`, which means
-any jobs will have this variable, not matter if an environment is defined or
-not.
+Wildcards can be used and the default environment scope is `*`. This means that
+any jobs can have this variable regardless of whether an environment is defined.
For example, if the environment scope is `production`, then only the jobs
having the environment `production` defined would have this specific variable.
@@ -1057,7 +1062,7 @@ environment's operational health.
## Limitations
In the `environment: name`, you are limited to only the [predefined environment variables](../variables/predefined_variables.md).
-Re-using variables defined inside `script` as part of the environment name will not work.
+Re-using variables defined inside `script` as part of the environment name doesn't work.
## Further reading
@@ -1066,7 +1071,7 @@ Below are some links you may find interesting:
- [The `.gitlab-ci.yml` definition of environments](../yaml/README.md#environment)
- [A blog post on Deployments & Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)
- [Review Apps - Use dynamic environments to deploy your code for every branch](../review_apps/index.md)
-- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md) **(PREMIUM)**
+- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md)
<!-- ## Troubleshooting
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 94f9aac51d6..0e4ad1df65f 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -36,14 +36,14 @@ To protect an environment:
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:
- There are two roles to choose from:
- - **Maintainers**: will allow access to all maintainers in the project.
- - **Developers**: will allow access to all maintainers and all developers in the project.
+ - **Maintainers**: Allows access to all maintainers in the project.
+ - **Developers**: Allows access to all maintainers and all developers in the project.
- You can only select groups that are already associated with the project.
- - Only users that have at least Developer permission level will appear in
+ - Only users that have at least the Developer permission level appear in
the **Allowed to Deploy** dropdown menu.
1. Click the **Protect** button.
-The protected environment will now appear in the list of protected environments.
+The protected environment now appears in the list of protected environments.
### Use the API to protect an environment
@@ -79,7 +79,7 @@ Alternatively, you can use the API to protect an environment:
1. Use the API to add a user to the group as a reporter:
```shell
- $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members"
+ $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members"
{"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://assets.gitlab-static.net/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null}
```
@@ -87,7 +87,7 @@ Alternatively, you can use the API to protect an environment:
1. Use the API to add the group to the project as a reporter:
```shell
- $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20"
+ $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20"
{"id":1233335,"project_id":22034114,"group_id":9899826,"group_access":20,"expires_at":null}
```
@@ -95,7 +95,7 @@ Alternatively, you can use the API to protect an environment:
1. Use the API to add the group with protected environment access:
```shell
- curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: xxxxxxxxxxx" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
+ curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
```
The group now has access and can be seen in the UI.
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index e728941dd9d..9fa0bb080ac 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -20,32 +20,31 @@ Examples are available in several forms. As a collection of:
## CI/CD examples
-The following table lists examples with step-by-step tutorials that are contained in this section.
+The following table lists examples with step-by-step tutorials that are contained in this section:
-| Use case | Resource |
-|:------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| Use case | Resource |
+|:------------------------------|:---------|
| Browser performance testing | [Browser Performance Testing with the Sitespeed.io container](../../user/project/merge_requests/browser_performance_testing.md). |
-| Load performance testing | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_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). |
-| Elixir | [Testing a Phoenix application with GitLab CI/CD](test_phoenix_app_with_gitlab_ci_cd/index.md). |
-| 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). |
+| 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. |
-| Java with Spring Boot | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.md). |
-| Java with Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md). |
-| PHP with PHPunit, atoum | [Testing PHP projects](php.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 Laravel, Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.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). |
+| 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). |
+| 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). |
-| Secrets management with Vault | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.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). |
+| 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). |
-### Contributing examples
+### How to contributing examples
Contributions are welcome! You can help your favorite programming
language users and GitLab by sending a merge request with a guide for that language.
@@ -72,6 +71,7 @@ choose one of these templates:
- [dotNET (`dotNET.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml)
- [dotNET Core (`dotNET-Core.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET-Core.yml)
- [Elixir (`Elixir.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml)
+- [Flutter (`Flutter.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml)
- [goLang (`Go.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml)
- [Gradle (`Gradle.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml)
- [Grails (`Grails.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml)
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index e37bdcc9407..c1df21297e3 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -3,9 +3,14 @@ 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
---
+<!-- vale off -->
+
# How to deploy Maven projects to Artifactory with GitLab CI/CD
## Introduction
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index b7f59761889..fccc62a4ca0 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -19,14 +19,14 @@ To learn more, read [Using external secrets in CI](../../secrets/index.md).
This tutorial assumes you are familiar with GitLab CI/CD and Vault.
-To follow along, you will need:
+To follow along, you must have:
- An account on GitLab.
- A running Vault server and access to it is required to configure authentication and create roles
and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
NOTE:
-You will need to replace the `vault.example.com` URL below with the URL of your Vault server and `gitlab.example.com` with the URL of your GitLab instance.
+You must replace the `vault.example.com` URL below with the URL of your Vault server, and `gitlab.example.com` with the URL of your GitLab instance.
## How it works
@@ -47,6 +47,7 @@ The JWT's payload looks like this:
"project_id": "22", #
"project_path": "mygroup/myproject", #
"user_id": "42", # Id of the user executing the job
+ "user_login": "myuser" # GitLab @username
"user_email": "myuser@example.com", # Email of the user executing the job
"pipeline_id": "1212", #
"job_id": "1212", #
@@ -56,7 +57,7 @@ The JWT's payload looks like this:
}
```
-The JWT is encoded by using RS256 and signed with a dedicated private key. The expire time for the token will be set to job's timeout, if specified, or 5 minutes if it is not. The key used to sign this token may change without any notice. In such case retrying the job will generate new JWT using the current signing key.
+The JWT is encoded by using RS256 and signed with a dedicated private key. The expire time for the token is set to job's timeout, if specified, or 5 minutes if it is not. The key used to sign this token may change without any notice. In such case retrying the job generates new JWT using the current signing key.
You can use this JWT and your instance's JWKS endpoint (`https://gitlab.example.com/-/jwks`) to authenticate with a Vault server that is configured to allow the JWT Authentication method for authentication.
@@ -110,7 +111,7 @@ EOF
Success! Uploaded policy: myproject-production
```
-You'll also need roles that will link the JWT with these policies.
+You also need roles that link the JWT with these policies.
One for staging named `myproject-staging`:
@@ -150,7 +151,7 @@ $ vault write auth/jwt/role/myproject-production - <<EOF
EOF
```
-This example uses [bound_claims](https://www.vaultproject.io/api/auth/jwt#bound_claims) to specify that only a JWT with matching values for the specified claims will be allowed to authenticate.
+This example uses [bound_claims](https://www.vaultproject.io/api/auth/jwt#bound_claims) to specify that only a JWT with matching values for the specified claims is allowed to authenticate.
Combined with [protected branches](../../../user/project/protected_branches.md), you can restrict who is able to authenticate and read the secrets.
@@ -158,7 +159,7 @@ Combined with [protected branches](../../../user/project/protected_branches.md),
[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 will be 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).
@@ -177,7 +178,7 @@ $ vault write auth/jwt/config \
For the full list of available configuration options, see Vault's [API documentation](https://www.vaultproject.io/api/auth/jwt#configure).
-The following job, when run for the `master` branch, will be able to read secrets under `secret/myproject/staging/`, but not the secrets under `secret/myproject/production/`:
+The following job, when run for the `master` branch, is able to read secrets under `secret/myproject/staging/`, but not the secrets under `secret/myproject/production/`:
```yaml
read_secrets:
@@ -201,7 +202,7 @@ read_secrets:
![read_secrets staging](img/vault-read-secrets-staging.png)
-The following job will be able to authenticate using the `myproject-production` role and read secrets under `/secret/myproject/production/`:
+The following job is able to authenticate using the `myproject-production` role and read secrets under `/secret/myproject/production/`:
```yaml
read_secrets:
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 f4f3bf306ef..9c145677f6e 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
@@ -2,18 +2,23 @@
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"
---
+<!-- vale off -->
+
# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD
## Introduction
-In this article, we'll demonstrate how to deploy a [Spring
-Boot](https://projects.spring.io/spring-boot/) application to [Cloud
-Foundry (CF)](https://www.cloudfoundry.org/) with GitLab CI/CD using the [Continuous
-Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment)
-method.
+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).
@@ -25,17 +30,16 @@ using GitLab CI/CD, read through the blog post [Continuous Delivery of a Spring
This tutorial assumes you are familiar with Java, GitLab, Cloud Foundry, and GitLab CI/CD.
-To follow along, you will need:
+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:
-You will need to replace the `api.run.pivotal.io` URL in the all below
-commands with the [API
-URL](https://docs.cloudfoundry.org/running/cf-api-endpoint.html) of your CF
-instance if you're not deploying to PWS.
+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
@@ -46,9 +50,9 @@ GitLab when creating a new project:
## Configure the deployment to Cloud Foundry
-To deploy to Cloud Foundry we need to add a `manifest.yml` file. This
-is the configuration for the CF CLI we will use to deploy the application. We
-will create this in the root directory of our project with the following
+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
@@ -62,12 +66,12 @@ applications:
## Configure GitLab CI/CD to deploy your application
-Now we need to add the GitLab CI/CD configuration file
-([`.gitlab-ci.yml`](../../yaml/README.md)) to our
-project's root. This is how GitLab figures out what commands need to be run whenever
-code is pushed to our repository. We will add the following `.gitlab-ci.yml`
-file to the root directory of the repository, GitLab will detect it
-automatically and run the steps defined once we push our code:
+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
@@ -96,15 +100,13 @@ production:
- master
```
-We've used the `java:8` [Docker
-image](../../docker/using_docker_images.md) to build
-our application as it provides the up-to-date Java 8 JDK on [Docker
-Hub](https://hub.docker.com/). We've also added the [`only`
-clause](../../yaml/README.md#onlyexcept-basic)
-to ensure our deployments only happen when we push to the master branch.
+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'll need to add your CF credentials as
+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
@@ -122,8 +124,8 @@ 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
-on **Run Pipeline**. After the app is finished deploying, it will display the
-URL of your application in the logs for the `production` job like:
+**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
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index 386512af38b..958093364af 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -55,10 +55,10 @@ To use different provider take a look at long list of [Supported Providers](http
## Using Dpl with Docker
-In most cases, you will have configured [GitLab Runner](https://docs.gitlab.com/runner/) to use your server's shell commands.
+In most cases, you configured [GitLab Runner](https://docs.gitlab.com/runner/) to use your server's shell commands.
This means that all commands are run in the context of local user (e.g. `gitlab_runner` or `gitlab_ci_multi_runner`).
It also means that most probably in your Docker container you don't have the Ruby runtime installed.
-You will have to install it:
+You must install it:
```yaml
staging:
@@ -115,7 +115,7 @@ We also use two secure variables:
## Storing API keys
-Secure Variables can added by going to your project's
+To add secure variables, navigate to your project's
**Settings > CI / CD > Variables**. The variables that are defined
in the project settings are sent along with the build script to the runner.
The secure variables are stored out of the repository. Never store secrets in
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index 24990264f19..6bc96ae6c30 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -9,13 +9,13 @@ type: tutorial
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 will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and Node.js installed.
+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.
```yaml
image: tetraweb/php
```
-The next step is to install zip/unzip packages and make composer available. We will place these in the `before_script` section:
+The next step is to install zip/unzip packages and make composer available. We place these in the `before_script` section:
```yaml
before_script:
@@ -26,7 +26,7 @@ before_script:
- php -r "unlink('composer-setup.php');"
```
-This will make sure we have all requirements ready. Next, we want to run `composer install` to fetch all PHP dependencies and `npm install` to load Node.js packages, then run the `npm` script. We need to append them into `before_script` section:
+This makes sure we have all requirements ready. Next, run `composer install` to fetch all PHP dependencies and `npm install` to load Node.js packages. Then run the `npm` script. We need to append them into `before_script` section:
```yaml
before_script:
@@ -43,19 +43,19 @@ In this particular case, the `npm deploy` script is a Gulp script that does the
1. Copy various assets (images, fonts) around
1. Replace some strings
-All these operations will put all files into a `build` folder, which is ready to be deployed to a live server.
+All these operations put all files into a `build` folder, which is ready to be deployed to a live server.
## How to transfer files to a live server
-You have multiple options: rsync, SCP, SFTP, and so on. For now, we will use SCP.
+You have multiple options: rsync, SCP, SFTP, and so on. For now, use SCP.
-To make this work, you need to add a GitLab CI/CD Variable (accessible on `gitlab.example/your-project-name/variables`). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** SSH key of your server.
+To make this work, you must add a GitLab CI/CD Variable (accessible on `gitlab.example/your-project-name/variables`). Name this variable `STAGING_PRIVATE_KEY` and set it to the **private** SSH key of your server.
### Security tip
Create a user that has access **only** to the folder that needs to be updated.
-After you create that variable, you need to make sure that key will be added to the Docker container on run:
+After you create that variable, make sure that key is added to the Docker container on run:
```yaml
before_script:
@@ -71,7 +71,7 @@ In order, this means that:
1. We check if the `ssh-agent` is available and we install it if it's not.
1. We create the `~/.ssh` folder.
1. We make sure we're running bash.
-1. We disable host checking (we don't ask for user accept when we first connect to a server and since every job will equal a first connect, we kind of need this).
+1. We disable host checking (we don't ask for user accept when we first connect to a server, and since every job equals a first connect, we need this).
And this is basically all you need in the `before_script` section.
@@ -96,14 +96,14 @@ stage_deploy:
Here's the breakdown:
-1. `only:dev` means that this build will run only when something is pushed to the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want)
-1. `ssh-add ...` we will add that private key you added on the web UI to the Docker container
-1. We will connect via `ssh` and create a new `_tmp` folder
-1. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
-1. We will connect again via `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
-1. We connect to SSH and remove the `_old` folder
+1. `only:dev` means that this build runs only when something is pushed to the `dev` branch. You can remove this block completely and have everything run on every push (but probably this is something you don't want).
+1. `ssh-add ...` we add that private key you added on the web UI to the Docker container.
+1. We connect via `ssh` and create a new `_tmp` folder.
+1. We connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder.
+1. We connect again via `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
+1. We connect to SSH and remove the `_old` folder.
-What's the deal with the artifacts? We just tell GitLab CI/CD to keep the `build` directory (later on, you can download that as needed).
+What's the deal with the artifacts? We tell GitLab CI/CD to keep the `build` directory (later on, you can download that as needed).
### Why we do it this way
@@ -114,7 +114,7 @@ If you're using this only for stage server, you could do this in two steps:
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live
```
-The problem is that there will be a small period of time when you won't have the app on your server.
+The problem is that there's a small period of time when you don't have the app on your server.
Therefore, for a production environment we use additional steps to ensure that at any given time, a functional app is in place.
@@ -122,13 +122,13 @@ Therefore, for a production environment we use additional steps to ensure that a
Since this was a WordPress project, I gave real life code snippets. Some further ideas you can pursue:
-- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches.
+- Having a slightly different script for `master` branch allows you to deploy to a production server from that branch and to a stage server from any other branches.
- Instead of pushing it live, you can push it to WordPress official repository (with creating a SVN commit, etc.).
- You could generate i18n text domains on the fly.
---
-Our final `.gitlab-ci.yml` will look like this:
+Our final `.gitlab-ci.yml` looks like this:
```yaml
image: tetraweb/php
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 7abdcf1f9be..298ffff568a 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
@@ -2,9 +2,14 @@
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
---
+<!-- vale off -->
+
# DevOps and Game Dev with GitLab CI/CD
With advances in WebGL and WebSockets, browsers are extremely viable as game development
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 96183b040a2..4521c2ed52e 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -2,9 +2,15 @@
stage: Verify
group: Testing
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+author: Vincent Tunru
+author_gitlab: Vinnl
type: tutorial
+date: 2019-02-18
+description: 'Confidence checking your entire app every time a new feature is added can quickly become repetitive. Learn how to automate it with GitLab CI/CD.'
---
+<!-- vale off -->
+
# End-to-end testing with GitLab CI/CD and WebdriverIO
[Review Apps](../../review_apps/index.md) are great: for every merge request
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 490fb857942..c6ddeefb916 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -2,9 +2,15 @@
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/laravel_with_gitlab_and_envoy/index.html'
+author: Mehran Rasulian
+author_gitlab: mehranrasulian
type: tutorial
+date: 2017-08-31
---
+<!-- vale off -->
+
# Test and deploy Laravel applications with GitLab CI/CD and Envoy
## Introduction
diff --git a/doc/ci/examples/semantic-release.md b/doc/ci/examples/semantic-release.md
index 70d29b739b1..037faaf66a2 100644
--- a/doc/ci/examples/semantic-release.md
+++ b/doc/ci/examples/semantic-release.md
@@ -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`:
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 089d72852bb..1204a1ae837 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
@@ -28,16 +28,16 @@ test:
staging:
stage: deploy
script:
- - gem install dpl
- - dpl --provider=heroku --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY
+ - gem install dpl --pre
+ - dpl heroku api --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY
only:
- master
production:
stage: deploy
script:
- - gem install dpl
- - dpl --provider=heroku --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY
+ - gem install dpl --pre
+ - dpl heroku api --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY
only:
- tags
```
@@ -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**:
+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**:
- `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_app_with_gitlab_ci_cd/img/mix-phoenix-new.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-new.png
deleted file mode 100644
index 04d3dc40fa5..00000000000
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-new.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.png
deleted file mode 100644
index 63812b41c2c..00000000000
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.png
deleted file mode 100644
index c0daa1a6a91..00000000000
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.png
deleted file mode 100644
index c8c5e152a13..00000000000
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.png
deleted file mode 100644
index fafabb27bac..00000000000
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
index 90f04fb3615..057b6ec126f 100644
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
@@ -1,397 +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'
---
-# Testing a Phoenix application with GitLab CI/CD
+This example is no longer available. [View other examples](../README.md).
-[Phoenix](https://www.phoenixframework.org/) is a web development framework written in [Elixir](https://elixir-lang.org), which is a
-functional language designed for productivity and maintainability that runs on the
-[Erlang VM](https://www.erlang.org). Erlang VM is really fast and can handle very large numbers of
-simultaneous users.
-
-That's why we're hearing so much about Phoenix today.
-
-In this tutorial, we'll teach you how to set up [GitLab CI/CD](../../README.md) to build and test a Phoenix
-application.
-
-The tutorial assumes that you know how to create a Phoenix app, run tests locally, and how to work with Git
-and the GitLab UI.
-
-## Introduction
-
-### What is Phoenix?
-
-[Phoenix](https://www.phoenixframework.org/) is a web development framework written in [Elixir](https://elixir-lang.org). It's useful
- for building fast, reliable, and high-performance applications, as it uses [Erlang VM](https://www.erlang.org).
-
-Many components and concepts are similar to Ruby on Rails or Python's Django. High developer
-productivity and high application performance are only a few advantages on learning how to use it.
-Working on the MVC pattern, it's was designed to be modular and flexible. Easy to maintain a growing
-app is a plus.
-
-Phoenix can run in any OS where Erlang is supported:
-
-- Ubuntu
-- CentOS
-- Mac OS X
-- Debian
-- Windows
-- Fedora
-- Raspberry Pi OS
-
-Check the [Phoenix learning guide](https://hexdocs.pm/phoenix/overview.html) for more information.
-
-### What is Elixir?
-
-[Elixir](https://elixir-lang.org) is a dynamic, functional language created to use all the maturity of Erlang
-(30 years old!) in these days, in an easy way. It has similarities with Ruby, specially on syntax,
-so Ruby developers are quite excited with the rapid growing of Elixir. A full-stack Ruby developer
-can learn how to use Elixir and Phoenix in just a few weeks!
-
-In Elixir we have a command called `mix`, which is a helper to create projects, testing, run
-migrations and [much more](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix). We'll use it later on in this tutorial.
-
-Check the [Elixir documentation](https://elixir-lang.org/getting-started/introduction) for more information.
-
-## Requirements
-
-To follow this tutorial, you'll need to have installed:
-
-- Elixir [installation instructions](https://elixir-lang.org/install)
-- Phoenix Framework [installation instructions](https://hexdocs.pm/phoenix/installation.html)
-- PostgreSQL (if you need to use MySQL server, check [Phoenix instructions](https://hexdocs.pm/phoenix/ecto.html#using-mysql))
-
-### Create a new Phoenix project
-
-Open your terminal and go to the directory you wish to create your project.
-You don't need to create an empty directory for the project's files, because the `mix` command will
-do it for us.
-
-When we call `mix` command, we'll pass two arguments:
-
-- The task we want it to run: `phoenix.new`
-- And the parameter `phoenix.new` requires, which is the name of the new project. In this case,
- we're calling it `hello_gitlab_ci`, but you're free to set your own name:
-
-```shell
-mix phoenix.new hello_gitlab_ci
-```
-
-When asked, answer `Y` to fetch and install dependencies.
-
-If everything went fine, you'll get an output like this:
-
-![mix phoenix.new](img/mix-phoenix-new.png)
-
-Now, our project is located inside the directory with the same name we pass to `mix` command, for
-example, `~/GitLab/hello_gitlab_ci`.
-If we take a look at the directory, we'll see the Phoenix files and the dependencies needed to run.
-
-### Initialize the PostgreSQL database
-
-By default, Phoenix requires a PostgreSQL database to store whatever we need to store in our app. In
-this case, we'll only create an empty database.
-
-First, we need to navigate to our recently created project's directory, and then execute again
-`mix`. This time, `mix` will receive the parameter `ecto.create`, which is the task to create our
-new database. [Ecto](https://hexdocs.pm/ecto/Ecto.html) is the database wrapper for Elixir.
-
-When we do run `mix` the first time after creating our project, it will compile our files to
-bytecode, which will be interpreted by Erlang VM. In the next times, it will only compile our
-changes.
-
-Run the commands below to create our empty database:
-
-```shell
-cd hello_gitlab_ci
-mix ecto.create
-```
-
-We expect to see this output at the end of the command:
-
-```plaintext
-Generated hello_gitlab_ci app
-The database for HelloGitlabCi.Repo has been created
-```
-
-Phoenix assumes that our PostgreSQL database will have a `postgres` user account with the correct
-permissions and a password of `postgres`. If it's not your case, check
-[Ecto's instructions](https://hexdocs.pm/ecto/Ecto.html#module-repositories).
-
-### Start Phoenix server
-
-Now, it's time to see if everything we did until now went well. We'll call `mix` again, this time
-with `phoenix.server` parameter, which will start Phoenix's HTTP Server.
-
-```shell
-mix phoenix.server
-```
-
-This will be the output to this command:
-
-```plaintext
-[info] Running HelloGitlabCi.Endpoint with Cowboy using http://localhost:4000
-23 May 11:44:35 - info: compiling
-23 May 11:44:37 - info: compiled 6 files into 2 files, copied 3 in 9.8 sec
-```
-
-Now, we have our app running locally. We can preview it directly on our browser. Let's open
-[`localhost:4000`](http://localhost:4000) to see our Phoenix Framework welcome page. If the link do
-not work, open [`127.0.0.1:4000`](http://127.0.0.1:4000) instead and later, configure your OS to
-point `localhost` to `127.0.0.1`.
-
-![mix phoenix.server](img/mix-phoenix-server.png)
-
-Great, now we have a local Phoenix Server running our app.
-
-Locally, our application is running in an [`iex`](https://elixir-lang.org/getting-started/introduction.html#interactive-mode) session, which stands for Interactive Elixir.
-In this interactive mode, we can type any Elixir expression and get its result. To exit `iex`, we
-need to press `Ctrl+C` twice. So, when we need to stop the Phoenix server, we have to hit `Ctrl+C`
-twice.
-
-## Introducing GitLab CI/CD
-
-With GitLab, we can manage our development workflow, improve our productivity, track issues,
-perform code review, and much more from a single platform. With GitLab CI/CD, we can be much more
-productive, because every time we, or our co-workers push any code, GitLab CI/CD will build and
-test the changes, telling us in real time if anything goes wrong.
-
-Certainly, when our application starts to grow, we'll need more developers working on the same
-project and this process of building and testing can easily become a mess without proper management.
-That's also why GitLab CI/CD is so important to our application. Every time someone pushes its code to
-GitLab, we'll quickly know if their changes broke something or not. We don't need to stop everything
-we're doing to test manually and locally every change our team does.
-
-Let's see this in practice.
-
-## Adjusting Phoenix configuration
-
-Now, we need to adjust our Phoenix configuration before configuring GitLab CI/CD.
-There is a directory (`config`) in your Phoenix project that contains a configuration file for every
-environment it can run. Since we will work with a single environment, we'll edit just the test
-configuration file (`test.exs`).
-
-But, why do we need to adjust our configuration? Well, GitLab CI/CD builds and tests our code in one
-isolated virtual machine, called a [runner](../../runners/README.md), using Docker technology. In this runner,
-GitLab CI/CD has access to everything our Phoenix application need to run, exactly as we have in our
-`localhost`, but we have to tell GitLab CI/CD where to create and find this database using system
-variables. This way, GitLab CI/CD will create our test database inside the runner, just like we do
-when running our Phoenix in our `localhost`.
-
-- Open `hello_gitlab_ci/config/test.exs` on your favorite code editor
-- Go to **Configure your database** session and edit the block to include `System.get_env`:
-
- ```elixir
- # Configure your database
- config :hello_gitlab_ci, HelloGitlabCi.Repo,
- adapter: Ecto.Adapters.Postgres,
- username: System.get_env("POSTGRES_USER") || "postgres",
- password: System.get_env("POSTGRES_PASSWORD") || "postgres",
- database: System.get_env("POSTGRES_DB") || "hello_gitlab_ci_test",
- hostname: System.get_env("POSTGRES_HOST") || "localhost",
- pool: Ecto.Adapters.SQL.Sandbox
- ```
-
- We'll need these system variables later on.
-
-- Create an empty file named `.gitkeep` into `hello_gitlab_ci/priv/repo/migrations`
-
- As our project is still fresh, we don't have any data on our database, so, the `migrations`
- directory will be empty.
- Without `.gitkeep`, Git will not upload this empty directory and we'll got an error when running our
- test on GitLab.
-
- If we add a folder via the GitLab UI, GitLab itself will add the `.gitkeep` to that new dir.
-
-Now, let's run a local test and see if everything we did didn't break anything.
-
-## Testing
-
-Earlier, when we created our project, we ran `mix phoenix.new`.
-This task created everything a Phoenix application needed, including some unit tests into
-`hello_gitlab_ci/test` directory.
-
-Let's run a new task with `mix` to run those tests for us. This time, the parameter expected is
-`test`. We can add `--trace` parameter for debugging purposes.
-
-In your terminal, navigate to the directory `hello_gitlab_ci` and run:
-
-```shell
-mix test
-```
-
-Our expected result is this:
-
-```plaintext
-....
-
-Finished in 0.7 seconds
-4 tests, 0 failures
-
-Randomized with seed 610000
-```
-
-Our test was successful. It's time to push our files to GitLab.
-
-## Configuring CI/CD Pipeline
-
-The first step is to create a new file called `.gitlab-ci.yml` in `hello_gitlab_ci` directory of our
-project.
-
-- The easiest way to do this is to click on **Set up CI/CD** on project's main page:
-
- ![Set up CI](img/set_up_ci_v12_6.png)
-
-- On the next screen, we can use a template with Elixir tests already included. Click on **Apply a template** and select **Elixir**:
-
- ![Select template](img/select_template_v12_6.png)
-
- This template file tells GitLab CI/CD about what we wish to do every time a new commit is made.
- However, we have to adapt it slightly to run a Phoenix app.
-
-- The first line tells GitLab what Docker image will be used.
-
- Remember when we learned about runners, the isolated virtual machine where GitLab CI/CD builds and tests
- our application? This virtual machine must have all dependencies to run our application. This is
- where a Docker image is needed. The correct image will provide the entire system for us.
-
- As we are focusing on testing (not deploying), you can use the [elixir:latest](https://hub.docker.com/_/elixir) Docker image, which already has the
- dependencies for running Phoenix tests installed, such as Elixir and Erlang:
-
- ```yaml
- image: elixir:latest
- ```
-
-- We'll only use `postgres`, so we can delete the `mysql` and `redis` lines from the `services` section:
-
- ```yaml
- services:
- - postgres:latest
- ```
-
-- Now, we'll create a new section called `variables`, before the `before_script` section:
-
- ```yaml
- variables:
- POSTGRES_DB: hello_gitlab_ci_test
- POSTGRES_HOST: postgres
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: "postgres"
- MIX_ENV: "test"
- ```
-
- Above, we set up the values for GitLab CI/CD to authenticate into PostgreSQL, like we did in
- `config/test.exs` earlier. The `POSTGRES_USER` and `POSTGRES_PASSWORD` values
- are used by the `postgres` service to create a user with those credentials.
-
-- In the `before_script` section, we'll add some commands to prepare everything for the test:
-
- ```yaml
- before_script:
- - mix local.rebar --force
- - mix local.hex --force
- - mix deps.get --only test
- - mix ecto.create
- - mix ecto.migrate
- ```
-
- This ensures that [rebar3](https://rebar3.org) and [hex](https://hex.pm) are both installed
- before attempting to fetch the dependencies that are required to run the tests. Next, the `postgres` db
- is created and migrated with `ecto`, to ensure it's up-to-date.
-
-- Finally, we'll leave the `mix` section unchanged.
-
-Let's take a look at the updated file after the changes:
-
-```yaml
-image: elixir:latest
-
-services:
- - postgres:latest
-
-variables:
- POSTGRES_DB: hello_gitlab_ci_test
- POSTGRES_HOST: postgres
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: "postgres"
- MIX_ENV: "test"
-
-before_script:
- - mix local.rebar --force
- - mix local.hex --force
- - mix deps.get --only test
- - mix ecto.create
- - mix ecto.migrate
-
-mix:
- script:
- - mix test
-```
-
-For safety, we can check if we get any syntax errors before submitting this file to GitLab. Copy the
-contents of `.gitlab-ci.yml` and paste it on [GitLab CI/CD Lint tool](https://gitlab.com/ci/lint). Please note that
-this link will only work for logged in users.
-
-## Watching the build
-
-I don't know about you, but I love to watch that black screen being filled with compilation output.
-With this, I can feel the happiness of something I made working correctly. On `localhost` it's easy
-to watch our build, but on GitLab, is it possible? Yes!
-
-Let's go to **Pipelines** and see GitLab doing the job. Just click on **Pipelines** to find the
-actual running build job.
-
-![Pipelines](img/pipelines.png)
-
-Click on build's ID to watch the entire process. If everything went as expected, we can wait for the
-**Build succeeded** at the end of the process! :)
-
-```shell
-$ mix test
-....
-
-Finished in 0.3 seconds
-4 tests, 0 failures
-
-Randomized with seed 206909
-Build succeeded
-```
-
-If we take a look at the project's main page on the GitLab UI, we can see the status of the last
-build made by GitLab CI/CD.
-
-Time to show the world our green build badge! Navigate to your project's **Settings > CI/CD** and
-expand **General pipelines settings**. Scroll down to **Pipeline status** and copy the Markdown code
-for your badge. Paste it on the top of your `README.md` file, to let people outside of our project
-see if our latest code is running without errors.
-
-When we finish this edition, GitLab will start another build and show a **build running** badge. It
-is expected, after all we just configured GitLab CI/CD to do this for every push! But you may think
-"Why run build and tests for simple things like editing README.md?" and it is a good question.
-For changes that don't affect your application, you can add the keyword [`[ci skip]`](../../yaml/README.md#skip-pipeline)
-to commit message and the build related to that commit will be skipped.
-
-In the end, we finally got our pretty green build succeeded badge! By outputting the result on the
-README file, it shows to whoever lands on your project's page that your code is up-to-date and
-working properly.
-
-## Conclusion
-
-When we have a growing application with many developers working on it, or when we have an open
-source project being watched and contributed by the community, it is really important to have our
-code permanently working. GitLab CI/CD is a time saving powerful tool to help us maintain our code
-organized and working.
-
-As we could see in this post, GitLab CI/CD is really easy to configure and use. We have [many
-other reasons](https://about.gitlab.com/blog/2015/02/03/7-reasons-why-you-should-be-using-ci/) to keep
-using GitLab CI/CD. The benefits to our teams will be huge!
-
-## References
-
-- [GitLab CI/CD introductory guide](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
-- [GitLab CI/CD full Documentation](../../README.md)
-- [GitLab Runner documentation](../../runners/README.md)
-- [Using Docker images documentation](../../docker/using_docker_images.md)
+<!-- This redirect file can be deleted after <2021-04-05>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/img/environments_available.png b/doc/ci/img/environments_available.png
deleted file mode 100644
index 6c64e9398f7..00000000000
--- a/doc/ci/img/environments_available.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/img/environments_available_13_7.png b/doc/ci/img/environments_available_13_7.png
new file mode 100644
index 00000000000..2e1f56c5894
--- /dev/null
+++ b/doc/ci/img/environments_available_13_7.png
Binary files differ
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index 3fa427bc875..c04bcd6f549 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -147,10 +147,10 @@ according to each stage (Verify, Package, 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). **(PREMIUM)**
+ - 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). **(PREMIUM)**
+ - 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:
diff --git a/doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.png b/doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.png
new file mode 100644
index 00000000000..eb44290aa66
--- /dev/null
+++ b/doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index 220032eeab1..999d15eac24 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -177,6 +177,10 @@ coming from a fork:
- It's created and runs in the fork (source) project, not the parent (target) project.
- It uses the fork project's CI/CD configuration and resources.
+If a pipeline runs in a fork, the **fork** icon appears for the pipeline in the merge request.
+
+![Pipeline ran in fork](img/pipeline-fork_v13_7.png)
+
Sometimes parent project members want the pipeline to run in the parent
project. This could be to ensure that the post-merge pipeline passes in the parent project.
For example, a fork project could try to use a corrupted runner that doesn't execute
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md
index 1b9bade3b76..e83789efdbf 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md
@@ -50,6 +50,8 @@ To enable pipelines for merge results:
- You must not be using
[fast forward merges](../../../user/project/merge_requests/fast_forward_merge.md) yet.
To follow progress, see [#58226](https://gitlab.com/gitlab-org/gitlab/-/issues/26996).
+- Your repository must be a GitLab repository, not an
+ [external repository](../../ci_cd_for_external_repos/index.md).
## Enable pipelines for merged results
@@ -58,7 +60,7 @@ To enable pipelines for merged results for your project:
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.**.
+1. Check **Enable merged results pipelines**.
1. Click **Save changes**.
WARNING:
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 0b25b32b2a5..e5b9ad030d0 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
@@ -74,6 +74,8 @@ To enable merge trains:
- You must have maintainer [permissions](../../../../user/permissions.md).
- You must be using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or later.
- In GitLab 12.0 and later, you need [Redis](https://redis.io/) 3.2 or later.
+- Your repository must be a GitLab repository, not an
+ [external repository](../../../ci_cd_for_external_repos/index.md).
## Enable merge trains
@@ -177,9 +179,13 @@ for more information.
### Merge Train Pipeline cannot be retried
-A Merge Train pipeline cannot be retried because the merge request is dropped from the merge train upon failure. For this reason, the retry button does not appear next to the pipeline icon.
+When a pipeline for merge trains fails the merge request is dropped from the train and the pipeline can't be retried.
+Pipelines for merge trains run on the merged result of the changes in the merge request and
+the changes from other merge requests already on the train. If the merge request is dropped from the train,
+the merged result is out of date and the pipeline can't be retried.
-In the case of pipeline failure, you should [re-enqueue](#add-a-merge-request-to-a-merge-train) the merge request to the merge train, which then initiates a new pipeline.
+Instead, you should [add the merge request to the train](#add-a-merge-request-to-a-merge-train)
+again, which triggers a new pipeline.
### Unable to add to merge train with message "The pipeline for this merge request failed."
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index 1df196182c0..006d6bda0e0 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -13,6 +13,9 @@ type: reference
You can set up [GitLab CI/CD](README.md) across multiple projects, so that a pipeline
in one project can trigger a pipeline in another project.
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview see the [Multi-project pipelines demo](https://www.youtube.com/watch?v=g_PIwBM1J84).
+
GitLab CI/CD is a powerful continuous integration tool that works not only per project,
but also across projects with multi-project pipelines.
diff --git a/doc/ci/yaml/img/ci_config_visualization_hover_v13_7.png b/doc/ci/pipeline_editor/img/ci_config_visualization_hover_v13_7.png
index 9387fc6ccf4..9387fc6ccf4 100644
--- a/doc/ci/yaml/img/ci_config_visualization_hover_v13_7.png
+++ b/doc/ci/pipeline_editor/img/ci_config_visualization_hover_v13_7.png
Binary files differ
diff --git a/doc/ci/yaml/img/ci_config_visualization_v13_7.png b/doc/ci/pipeline_editor/img/ci_config_visualization_v13_7.png
index ef2aa6fe9e9..ef2aa6fe9e9 100644
--- a/doc/ci/yaml/img/ci_config_visualization_v13_7.png
+++ b/doc/ci/pipeline_editor/img/ci_config_visualization_v13_7.png
Binary files differ
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
new file mode 100644
index 00000000000..cc1f666f319
--- /dev/null
+++ b/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png
Binary files differ
diff --git a/doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.png b/doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.png
new file mode 100644
index 00000000000..28d21f71378
--- /dev/null
+++ b/doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.png
Binary files differ
diff --git a/doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.png b/doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.png
new file mode 100644
index 00000000000..a4140d5220a
--- /dev/null
+++ b/doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.png
Binary files differ
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
new file mode 100644
index 00000000000..61b8e289509
--- /dev/null
+++ b/doc/ci/pipeline_editor/index.md
@@ -0,0 +1,133 @@
+---
+stage: Verify
+group: Pipeline Authoring
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference
+---
+
+# Pipeline Editor **(CORE)**
+
+> - [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)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+The pipeline editor is the primary place to edit the GitLab CI/CD configuration in
+your `.gitlab-ci.yml` file. To access it, go to **CI/CD > Editor**.
+
+From the pipeline editor page you can:
+
+- [Validate](#validate-ci-configuration) your configuration syntax while editing the file.
+- 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.
+- [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.
+
+## Validate CI configuration
+
+As you edit your pipeline configuration, it is continually validated against the GitLab CI/CD
+pipeline schema. It checks the syntax of your CI YAML configuration, and also runs
+some basic logical validations.
+
+The result of this validation is shown at the top of the editor page. If your configuration
+is invalid, a tip is shown to help you fix the problem:
+
+![Errors in a CI configuration validation](img/pipeline_editor_validate_v13_8.png)
+
+## Lint CI configuration
+
+To test the validity of your GitLab CI/CD configuration before committing the changes,
+you can use the CI lint tool. To access it, go to **CI/CD > Editor** and select the **Lint** tab.
+
+This tool checks for syntax and logical errors but goes into more detail than the
+automatic [validation](#validate-ci-configuration) in the editor.
+
+The results are updated in real-time. Any changes you make to the configuration are
+reflected in the CI lint. It displays the same results as the existing [CI Lint tool](../lint.md).
+
+![Linting errors in a CI configuration](img/pipeline_editor_lint_v13_8.png)
+
+## Visualize CI configuration
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241722) in GitLab 13.5.
+> - [Moved to **CI/CD > Editor**](https://gitlab.com/gitlab-org/gitlab/-/issues/263141) in GitLab 13.7.
+> - 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)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+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:
+
+![CI configuration Visualization](img/ci_config_visualization_v13_7.png)
+
+Hovering on a job highlights 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)**
+
+CI/CD configuration visualization 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(:ci_config_visualization_tab)
+```
+
+To enable it:
+
+```ruby
+Feature.enable(: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
+your changes at any time.
+
+When you are satisfied with your changes, add a descriptive commit message and enter
+a branch. The branch field defaults to your project's default branch.
+
+If you enter a new branch name, the **Start a new merge request with these changes**
+checkbox appears. Select it to start a new merge request after you commit the changes.
+
+![The commit form with a new branch](img/pipeline_editor_commit_v13_8.png)
+
+## Enable or disable pipeline editor **(CORE ONLY)**
+
+The pipeline editor is under development and not 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_pipeline_editor_page)
+```
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_pipeline_editor_page)
+```
diff --git a/doc/ci/pipelines/img/job_artifacts_merge_request.png b/doc/ci/pipelines/img/job_artifacts_merge_request.png
new file mode 100644
index 00000000000..fa1ed9acbf8
--- /dev/null
+++ 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 22e331f2de0..7920a3bf7f3 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -89,9 +89,9 @@ This table lists the refspecs injected for each pipeline type:
| Pipeline type | Refspecs |
|--------------- |---------------------------------------- |
-| Pipeline for Branches | `+refs/pipelines/<id>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` |
-| pipeline for Tags | `+refs/pipelines/<id>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` |
-| [Pipeline for Merge Requests](../merge_request_pipelines/index.md) | `+refs/pipelines/<id>:refs/pipelines/<id>` |
+| Pipeline for Branches | `+<sha>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` |
+| pipeline for Tags | `+<sha>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` |
+| [Pipeline for Merge Requests](../merge_request_pipelines/index.md) | `+<sha>:refs/pipelines/<id>` |
The refs `refs/heads/<name>` and `refs/tags/<name>` exist in your
project repository. GitLab generates the special ref `refs/pipelines/<id>` during a
@@ -132,6 +132,10 @@ 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**.
@@ -345,18 +349,7 @@ Stages in pipeline mini graphs are collapsible. Hover your mouse over them and c
### Pipeline success and duration charts
-> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts.
-> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI / CD Analytics in GitLab 12.8.
-
-GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline ran. To view this information, go to **Analytics > CI / CD Analytics**.
-
-View successful pipelines:
-
-![Successful pipelines](img/pipelines_success_chart.png)
-
-View pipeline duration history:
-
-![Pipeline duration](img/pipelines_duration_chart.png)
+Pipeline analytics are available on the [**CI/CD Analytics** page](../../user/analytics/ci_cd_analytics.md#pipeline-success-and-duration-charts).
### Pipeline badges
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index 787ee8f8573..4c77a578aa4 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -155,9 +155,10 @@ as artifacts.
The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests.
-#### `artifacts:reports:sast` **(ULTIMATE)**
+#### `artifacts:reports:sast`
> - Introduced in GitLab 11.5.
+> - Made [available in all tiers](https://gitlab.com/groups/gitlab-org/-/epics/2098) in GitLab 13.3.
> - Requires GitLab Runner 11.5 and above.
The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md)
@@ -349,6 +350,11 @@ in the GitLab UI to do this:
![Job artifacts browser button](img/job_artifacts_browser_button.png)
+1. While on the details page of a merge request, you can see the download
+ icon for each job's artifacts on the right side of the merge request widget:
+
+ ![Job artifacts in Merge Request](img/job_artifacts_merge_request.png)
+
1. And finally, when browsing an archive you can see the download button at
the top right corner:
@@ -459,6 +465,23 @@ To retrieve a job artifact from a different project, you might need to use a
private token to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts)
the artifact.
+## Keep artifacts from most recent successful jobs
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4.
+> - [Made optional with a CI/CD setting](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8.
+
+By default, the latest artifacts from the most recent successful jobs are never deleted.
+If a job is configured with [`expire_in`](../yaml/README.md#artifactsexpire_in),
+its artifacts only expire if a more recent artifact exists.
+
+Keeping the latest artifacts can use a large amount of storage space in projects
+with a lot of jobs or large artifacts. If the latest artifacts are not needed in
+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**.
+
## Troubleshooting
### Error message `No files to upload`
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index 35a8888381f..cddfcb754ec 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -67,7 +67,7 @@ To configure a job to be executed only when the pipeline has been
scheduled (or the opposite), use
[only and except](../yaml/README.md#onlyexcept-basic) configuration keywords.
-For example:
+In the example below `make world` runs in scheduled pipelines, and `make build` runs in pipelines that are not scheduled:
```yaml
job:on-schedule:
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 7fd88d011b3..e9c85353db3 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -129,7 +129,7 @@ The pipeline starts when the commit is committed.
- 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](../yaml/visualization.md) to
+- 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).
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 31fcfe9d6e8..3512b77e4e2 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -69,7 +69,7 @@ The process of configuring Review Apps is as follows:
When configuring Review Apps for a project, you need to add a new job to `.gitlab-ci.yml`,
as mentioned above. To facilitate this and if you are using Kubernetes, you can click
-the **Enable Review Apps** button and GitLab will prompt you with a template code block that
+the **Enable Review Apps** button and GitLab prompts you with a template code block that
you can copy and paste into `.gitlab-ci.yml` as a starting point. To do so:
1. Go to the project your want to create a Review App job for.
@@ -115,7 +115,7 @@ and faster to preview proposed modifications.
Configuring Route Maps involves telling GitLab how the paths of files
in your repository map to paths of pages on your website using a Route Map.
-Once set, GitLab will display **View on ...** buttons, which will take you
+Once set, GitLab displays **View on ...** buttons, which take you
to the pages changed directly from merge requests.
To set up a route map, add a file inside the repository at `.gitlab/route-map.yml`,
@@ -165,15 +165,15 @@ The public path for a source path is determined by finding the first
In the example above, the fact that mappings are evaluated in order
of their definition is used to ensure that `source/index.html.haml`
-will match `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`,
-and will result in a public path of `index.html`, instead of
+matches `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`,
+and results in a public path of `index.html`, instead of
`index.html.haml`.
-After you have the route mapping set up, it will take effect in the following locations:
+After you have the route mapping set up, it takes effect in the following locations:
- In the merge request widget. The:
- - **View app** button will take you to the environment URL set in `.gitlab-ci.yml`.
- - Dropdown will list the first 5 matched items from the route map, but you can filter them if more
+ - **View app** button takes you to the environment URL set in `.gitlab-ci.yml`.
+ - Dropdown lists the first 5 matched items from the route map, but you can filter them if more
than 5 are available.
![View app file list in merge request widget](img/view_on_mr_widget.png)
@@ -221,7 +221,7 @@ To see Visual reviews in action, see the [Visual Reviews Walk through](https://y
The feedback form is served through a script you add to pages in your Review App.
If you have [Developer permissions](../../user/permissions.md) to the project,
you can access it by clicking the **Review** button in the **Pipeline** section
-of the merge request. The form modal will also show a dropdown for changed pages
+of the merge request. The form modal also shows a dropdown for changed pages
if [route maps](#route-maps) are configured in the project.
![review button](img/review_button.png)
@@ -251,13 +251,13 @@ to replace those values at runtime when each review app is created:
`CI_MERGE_REQUEST_IID` variable. `CI_MERGE_REQUEST_IID` is available only if
[`only: [merge_requests]`](../merge_request_pipelines/index.md)
is used and the merge request is created.
-- `data-mr-url` is the URL of the GitLab instance and will be the same for all
+- `data-mr-url` is the URL of the GitLab instance and is the same for all
review apps.
- `data-project-path` is the project's path, which can be found by `CI_PROJECT_PATH`.
-- `data-require-auth` is optional for public projects but required for [private and internal ones](#authentication-for-visual-reviews). If this is set to `true`, the user will be required to enter their [personal access token](../../user/profile/personal_access_tokens.md) instead of their name and email.
+- `data-require-auth` is optional for public projects but required for [private and internal ones](#authentication-for-visual-reviews). If this is set to `true`, the user is required to enter their [personal access token](../../user/profile/personal_access_tokens.md) instead of their name and email.
- `id` is always `review-app-toolbar-script`, you don't need to change that.
- `src` is the source of the review toolbar script, which resides in the
- respective GitLab instance and will be the same for all review apps.
+ respective GitLab instance and is the same for all review apps.
For example, in a Ruby application with code hosted on in a project GitLab.com, you would need to have this script:
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index c9a5f2f3899..d6ea4d83825 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -116,7 +116,7 @@ You can also enable shared runners for individual projects.
To enable shared runners:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Click **Allow shared runners**.
+1. Select **Enable shared runners for this project**.
#### Disable shared runners
@@ -126,7 +126,12 @@ You must have Owner permissions for the project or group.
To disable shared runners for a project:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared runners** area, click **Disable shared runners**.
+1. In the **Shared runners** area, select **Enable shared runners for this project** so the toggle is grayed-out.
+
+Shared runners are automatically disabled for a project:
+
+- If the shared runners setting for the parent group is disabled, and
+- If overriding this setting is not permitted at the project level.
To disable shared runners for a group:
@@ -264,6 +269,15 @@ by a project that has jobs with a long timeout (for example, one week).
When not configured, runners do not override the project timeout.
+On GitLab.com, you cannot override the job timeout for shared runners and must use the [project defined timeout](../pipelines/settings.md#timeout).
+
+To set the maximum job timeout:
+
+1. In a project, go to **Settings > CI/CD > Runners**.
+1. Select your specific runner to edit the settings.
+1. Enter a value under **Maximum job timeout**.
+1. Select **Save changes**.
+
How this feature works:
**Example 1 - Runner timeout bigger than project timeout**
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index 2505e56356d..1fec1f77bc3 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -68,36 +68,11 @@ execution time and the error output.
### Number of recent failures
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in GitLab 13.7.
-> - 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-number-of-recent-failures). **(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/268249) in GitLab 13.8.
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.
-#### Enable or disable the number of recent failures **(CORE ONLY)**
-
-Displaying the number of failures in the last 14 days 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(:test_failure_history)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:test_failure_history)
-```
-
## How to set it up
To enable the Unit test reports in merge requests, you need to add
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index f4ca51be151..5fca8e8c2b7 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -594,7 +594,35 @@ WARNING:
Variables with multi-line values are not supported due to
limitations with the Auto DevOps scripting environment.
-### Override a variable by manually running a pipeline
+### When you can override variables
+
+You can override the value of a variable when:
+
+1. [Manually running](#override-a-variable-by-manually-running-a-pipeline) pipelines in the UI.
+1. Manually creating pipelines [via API](../../api/pipelines.md#create-a-new-pipeline).
+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).
+
+These pipeline variables declared in these events take [priority over other variables](#priority-of-environment-variables).
+
+#### Restrict who can override variables
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8.
+
+To allow only users with Maintainer role to set these variables, you can use
+[the API](../../api/projects.md#edit-project) to enable the project setting `restrict_user_defined_variables`.
+When a user without Maintainer role tries to run a pipeline with overridden
+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),
+use this setting for strict control over all aspects of the environment
+the pipeline runs in.
+
+#### Override a variable by manually running a pipeline
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44059) in GitLab 10.8.
@@ -785,7 +813,9 @@ Feature.enable(:ci_if_parenthesis_enabled)
### Storing regular expressions in variables
-It is possible to store a regular expression in a variable, to be used for pattern matching:
+It is possible to store a regular expression in a variable, to be used for pattern matching.
+The following example tests whether `$RELEASE` contains either the
+string `staging0` or the string `staging1`:
```yaml
variables:
@@ -847,13 +877,7 @@ before making them visible again.
### Restricted access to debug logging
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) 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 recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-restricted-access-to-debug-logging). **(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/292661) in GitLab 13.8.
With restricted access to debug logging, only users with
[developer or higher permissions](../../user/permissions.md#project-members-permissions)
@@ -867,25 +891,6 @@ If you add `CI_DEBUG_TRACE` as a local variable to your runners, debug logs are
to all users with access to job logs. The permission levels are not checked by Runner,
so you should make use of the variable in GitLab only.
-#### Enable or disable Restricted access to debug logging **(CORE ONLY)**
-
-Restricted Access to Debug logging 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(:restrict_access_to_build_debug_mode)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:restrict_access_to_build_debug_mode)
-```
-
### Enable Debug logging
To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`:
diff --git a/doc/ci/variables/deprecated_variables.md b/doc/ci/variables/deprecated_variables.md
index 755e34fa5ca..8d23ec1fd97 100644
--- a/doc/ci/variables/deprecated_variables.md
+++ b/doc/ci/variables/deprecated_variables.md
@@ -1,36 +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: 'README.md'
---
-# Deprecated GitLab CI/CD variables
+This documentation page was removed. For information about variables, see [GitLab CI/CD environment variables](README.md)
-Read through this document to learn what predefined variables
-were deprecated and their new references.
-
-## GitLab 9.0 renamed variables
-
-To follow conventions of naming across GitLab, and to further move away from the
-`build` term and toward `job`, some [CI/CD environment variables](README.md#predefined-environment-variables) were renamed for GitLab 9.0
-release.
-
-Starting with GitLab 9.0, we have deprecated the `$CI_BUILD_*` variables. **You are
-strongly advised to use the new variables as we might remove the old ones in
-future GitLab releases.**
-
-| 8.x name | 9.0+ name |
-| --------------------- |------------------------ |
-| `CI_BUILD_BEFORE_SHA` | `CI_COMMIT_BEFORE_SHA` |
-| `CI_BUILD_ID` | `CI_JOB_ID` |
-| `CI_BUILD_MANUAL` | `CI_JOB_MANUAL` |
-| `CI_BUILD_NAME` | `CI_JOB_NAME` |
-| `CI_BUILD_REF` | `CI_COMMIT_SHA` |
-| `CI_BUILD_REF_NAME` | `CI_COMMIT_REF_NAME` |
-| `CI_BUILD_REF_SLUG` | `CI_COMMIT_REF_SLUG` |
-| `CI_BUILD_REPO` | `CI_REPOSITORY_URL` |
-| `CI_BUILD_STAGE` | `CI_JOB_STAGE` |
-| `CI_BUILD_TAG` | `CI_COMMIT_TAG` |
-| `CI_BUILD_TOKEN` | `CI_JOB_TOKEN` |
-| `CI_BUILD_TRIGGERED` | `CI_PIPELINE_TRIGGERED` |
+<!-- This redirect file can be deleted after 2021-04-14. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index ba0a5e8f461..701fe33b53f 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -14,138 +14,134 @@ Some of the predefined environment 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.
-NOTE:
-Starting with GitLab 9.0, we have deprecated some variables. Read the
-[9.0 Renaming](deprecated_variables.md#gitlab-90-renamed-variables) section to find out their replacements.
-**To avoid problems with deprecated and removed variables in future releases, you are strongly advised to use the new variables.**
-
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 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 |
-| `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. |
-| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in pipelines for merge requests. |
-| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit: the message without first line, if the title is shorter than 100 characters; full message in other case. |
-| `CI_COMMIT_MESSAGE` | 10.8 | all | The full commit message. |
-| `CI_COMMIT_REF_NAME` | 9.0 | all | The branch or tag name for which project is built |
-| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | `true` if the job is running on a protected reference, `false` if not |
-| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME` lowercased, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. |
-| `CI_COMMIT_SHA` | 9.0 | all | The commit revision for which project is built |
-| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA` |
-| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present in branch pipelines, including pipelines for the default branch. Not present in merge request pipelines or tag pipelines. |
-| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Present only when building tags. |
-| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit - the full first line of the message |
-| `CI_COMMIT_TIMESTAMP` | 13.4 | all | The timestamp of the commit in the ISO 8601 format. |
-| `CI_CONCURRENT_ID` | all | 11.10 | Unique ID of build execution within a single executor. |
-| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | Unique ID of build execution within a single executor and project. |
-| `CI_CONFIG_PATH` | 9.4 | 0.5 | The path to CI configuration file. Defaults to `.gitlab-ci.yml` |
-| `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug logging (tracing)](README.md#debug-logging) is enabled |
-| `CI_DEFAULT_BRANCH` | 12.4 | all | The name of the default branch for the project. |
-| `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` | 13.7 | all | The image prefix for pulling images through the Dependency Proxy. |
-| `CI_DEPENDENCY_PROXY_SERVER` | 13.7 | all | The server for logging in to the Dependency Proxy. This is equivelant to `$CI_SERVER_HOST:$CI_SERVER_PORT`. |
-| `CI_DEPENDENCY_PROXY_PASSWORD` | 13.7 | all | The password to use to pull images through the Dependency Proxy. |
-| `CI_DEPENDENCY_PROXY_USER` | 13.7 | all | The username to use to pull images through the Dependency Proxy. |
-| `CI_DEPLOY_FREEZE` | 13.2 | all | Included with the value `true` if the pipeline runs during a [deploy freeze window](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). |
-| `CI_DEPLOY_PASSWORD` | 10.8 | all | Authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. |
-| `CI_DEPLOY_USER` | 10.8 | all | Authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. |
-| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. |
-| `CI_ENVIRONMENT_NAME` | 8.15 | all | The name of the environment for this job. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. |
-| `CI_ENVIRONMENT_SLUG` | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. |
-| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Only present if [`environment:url`](../yaml/README.md#environmenturl) is set. |
-| `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | Pull Request ID from GitHub if the [pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY` | 13.3 | all | The source repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY` | 13.3 | all | The target repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | The source branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the source branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | The target branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the target branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
-| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Included with the value `true` only if the pipeline's project has any open [requirements](../../user/project/requirements/index.md). Not included if there are no open requirements for the pipeline's project. |
-| `CI_OPEN_MERGE_REQUESTS` | 13.7 | all | Contains a comma-delimited list of up to 4 Merge Requests from the current source project and branch in the form `gitlab-org/gitlab!333,gitlab-org/gitlab-foss!11` |
-| `CI_JOB_ID` | 9.0 | all | The unique ID of the current job that GitLab CI/CD uses internally |
-| `CI_JOB_IMAGE` | 12.9 | 12.9 | The name of the image running the CI job |
-| `CI_JOB_MANUAL` | 8.12 | all | The flag to indicate that job was manually started |
-| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
-| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
-| `CI_JOB_STATUS` | all | 13.5 | The state of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#after_script) where `CI_JOB_STATUS` can be either: `success`, `failed` or `canceled`. |
+| 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. |
+| `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. |
+| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in pipelines for merge requests. |
+| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit: the message without first line, if the title is shorter than 100 characters; full message in other case. |
+| `CI_COMMIT_MESSAGE` | 10.8 | all | The full commit message. |
+| `CI_COMMIT_REF_NAME` | 9.0 | all | The branch or tag name for which project is built. |
+| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | `true` if the job is running on a protected reference, `false` if not. |
+| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. |
+| `CI_COMMIT_SHA` | 9.0 | all | The commit revision for which project is built. |
+| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA`. |
+| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present in branch pipelines, including pipelines for the default branch. Not present in merge request pipelines or tag pipelines. |
+| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Present only when building tags. |
+| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit - the full first line of the message. |
+| `CI_COMMIT_TIMESTAMP` | 13.4 | all | The timestamp of the commit in the ISO 8601 format. |
+| `CI_CONCURRENT_ID` | all | 11.10 | Unique ID of build execution in a single executor. |
+| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | Unique ID of build execution in a single executor and project. |
+| `CI_CONFIG_PATH` | 9.4 | 0.5 | The path to CI configuration file. Defaults to `.gitlab-ci.yml`. |
+| `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug logging (tracing)](README.md#debug-logging) is enabled. |
+| `CI_DEFAULT_BRANCH` | 12.4 | all | The name of the default branch for the project. |
+| `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` | 13.7 | all | The image prefix for pulling images through the Dependency Proxy. |
+| `CI_DEPENDENCY_PROXY_SERVER` | 13.7 | all | The server for logging in to the Dependency Proxy. This is equivalent to `$CI_SERVER_HOST:$CI_SERVER_PORT`. |
+| `CI_DEPENDENCY_PROXY_PASSWORD` | 13.7 | all | The password to use to pull images through the Dependency Proxy. |
+| `CI_DEPENDENCY_PROXY_USER` | 13.7 | all | The username to use to pull images through the Dependency Proxy. |
+| `CI_DEPLOY_FREEZE` | 13.2 | all | Included with the value `true` if the pipeline runs during a [deploy freeze window](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). |
+| `CI_DEPLOY_PASSWORD` | 10.8 | all | Authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. |
+| `CI_DEPLOY_USER` | 10.8 | all | Authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. |
+| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. |
+| `CI_ENVIRONMENT_NAME` | 8.15 | all | The name of the environment for this job. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. |
+| `CI_ENVIRONMENT_SLUG` | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, and so on. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. |
+| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Only present if [`environment:url`](../yaml/README.md#environmenturl) is set. |
+| `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | Pull Request ID from GitHub if the [pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY` | 13.3 | all | The source repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY` | 13.3 | all | The target repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | The source branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the source branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | The target branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the target branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. |
+| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Included with the value `true` only if the pipeline's project has any open [requirements](../../user/project/requirements/index.md). Not included if there are no open requirements for the pipeline's project. |
+| `CI_OPEN_MERGE_REQUESTS` | 13.8 | all | Available in branch and merge request pipelines. Contains a comma-separated list of up to four merge requests that use the current branch and project as the merge request source. For example `gitlab-org/gitlab!333,gitlab-org/gitlab-foss!11`. |
+| `CI_JOB_ID` | 9.0 | all | The unique ID of the current job that GitLab CI/CD uses internally. |
+| `CI_JOB_IMAGE` | 12.9 | 12.9 | The name of the image running the CI job. |
+| `CI_JOB_MANUAL` | 8.12 | all | The flag to indicate that job was manually started. |
+| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml`. |
+| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml`. |
+| `CI_JOB_STATUS` | all | 13.5 | The state of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#after_script) where `CI_JOB_STATUS` can be either: `success`, `failed` or `canceled`. |
| `CI_JOB_TOKEN` | 9.0 | 1.2 | Token used for authenticating with [a few API endpoints](../../api/README.md#gitlab-ci-job-token) and downloading [dependent repositories](../../user/project/new_ci_build_permissions_model.md#dependent-repositories). The token is valid as long as the job is running. |
| `CI_JOB_JWT` | 12.10 | all | RS256 JSON web token that can be used for authenticating with third party systems that support JWT authentication, for example [HashiCorp's Vault](../secrets/index.md). |
-| `CI_JOB_URL` | 11.1 | 0.5 | Job details URL |
-| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.md#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.md#rulesif) |
-| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This is a unique ID across all projects on GitLab. |
-| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This ID is unique for the current project. |
-| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `http://192.168.10.15:3000/namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (e.g. `refs/merge-requests/1/head`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** |
-| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
-| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** |
-| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_JOB_URL` | 11.1 | 0.5 | Job details URL. |
+| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.md#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.md#rulesif). |
+| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This is a unique ID across all projects on GitLab. |
+| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This ID is unique for the current project. |
+| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (for example `namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (for example `http://192.168.10.15:3000/namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (for example `refs/merge-requests/1/head`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** |
+| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
+| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** |
+| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. |
| `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | The event type of the merge request, if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Can be `detached`, `merged_result` or `merge_train`. |
| `CI_MERGE_REQUEST_DIFF_ID` | 13.7 | all | The version of the merge request diff, if [the pipelines are for merge requests](../merge_request_pipelines/index.md). |
| `CI_MERGE_REQUEST_DIFF_BASE_SHA` | 13.7 | all | The base SHA of the merge request diff, if [the pipelines are for merge requests](../merge_request_pipelines/index.md). |
-| `CI_NODE_INDEX` | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. |
-| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
-| `CI_PAGES_DOMAIN` | 11.8 | all | The configured domain that hosts GitLab Pages. |
-| `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. |
-| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This is a unique ID across all projects on GitLab. |
-| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique for the current project. |
+| `CI_NODE_INDEX` | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. |
+| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
+| `CI_PAGES_DOMAIN` | 11.8 | all | The configured domain that hosts GitLab Pages. |
+| `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. |
+| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This is a unique ID across all projects on GitLab. |
+| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique for the current project. |
| `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/README.md#authentication-tokens). For pipelines created before GitLab 9.5, this is displayed as `unknown`. |
-| `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md) |
-| `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL |
+| `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md). |
+| `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL. |
+| `CI_PROJECT_CONFIG_PATH` | 13.8 | all | The CI configuration path for the project. |
| `CI_PROJECT_DIR` | all | all | The full path where the repository is cloned and where the job is run. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see [Advanced configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) for GitLab Runner. |
-| `CI_PROJECT_ID` | all | all | The unique ID of the current project that GitLab CI/CD uses internally |
-| `CI_PROJECT_NAME` | 8.10 | 0.5 | The name of the directory for the project that is currently being built. For example, if the project URL is `gitlab.example.com/group-name/project-1`, the `CI_PROJECT_NAME` would be `project-1`. |
-| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | The project namespace (username or group name) that is currently being built |
-| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | The **root** project namespace (username or group name) that is currently being built. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` would be `root-group`. |
-| `CI_PROJECT_PATH` | 8.10 | 0.5 | The namespace with project name |
-| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
-| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | Comma-separated, lowercased list of the languages used in the repository (e.g. `ruby,javascript,html,css`) |
-| `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. |
-| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project |
-| `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility (internal, private, public) |
-| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of the GitLab Container Registry. This variable includes a `:port` value if one has been specified in the registry configuration. |
-| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project |
-| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. |
-| `CI_REGISTRY_USER` | 9.0 | all | The username to use to push containers to the GitLab Container Registry, for the current project. |
-| `CI_REPOSITORY_URL` | 9.0 | all | The URL to clone the Git repository |
-| `CI_RUNNER_DESCRIPTION` | 8.10 | 0.5 | The description of the runner as saved in GitLab |
-| `CI_RUNNER_EXECUTABLE_ARCH` | all | 10.6 | The OS/architecture of the GitLab Runner executable (note that this is not necessarily the same as the environment of the executor) |
-| `CI_RUNNER_ID` | 8.10 | 0.5 | The unique ID of runner being used |
-| `CI_RUNNER_REVISION` | all | 10.6 | GitLab Runner revision that is executing the current job |
-| `CI_RUNNER_SHORT_TOKEN` | all | 12.3 | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID |
-| `CI_RUNNER_TAGS` | 8.10 | 0.5 | The defined runner tags |
-| `CI_RUNNER_VERSION` | all | 10.6 | GitLab Runner version that is executing the current job |
-| `CI_SERVER` | all | all | Mark that job is executed in CI environment |
-| `CI_SERVER_URL` | 12.7 | all | The base URL of the GitLab instance, including protocol and port (like `https://gitlab.example.com:8080`) |
-| `CI_SERVER_HOST` | 12.1 | all | Host component of the GitLab instance URL, without protocol and port (like `gitlab.example.com`) |
-| `CI_SERVER_PORT` | 12.8 | all | Port component of the GitLab instance URL, without host and protocol (like `3000`) |
-| `CI_SERVER_PROTOCOL` | 12.8 | all | Protocol component of the GitLab instance URL, without host and port (like `https`) |
-| `CI_SERVER_NAME` | all | all | The name of CI server that is used to coordinate jobs |
-| `CI_SERVER_REVISION` | all | all | GitLab revision that is used to schedule jobs |
-| `CI_SERVER_VERSION` | all | all | GitLab version that is used to schedule jobs |
-| `CI_SERVER_VERSION_MAJOR` | 11.4 | all | GitLab version major component |
-| `CI_SERVER_VERSION_MINOR` | 11.4 | all | GitLab version minor component |
-| `CI_SERVER_VERSION_PATCH` | 11.4 | all | GitLab version patch component |
-| `CI_SHARED_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. |
-| `GITLAB_CI` | all | all | Mark that job is executed in GitLab CI/CD environment |
-| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan |
-| `GITLAB_USER_EMAIL` | 8.12 | all | The email of the user who started the job |
-| `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 |
+| `CI_PROJECT_ID` | all | all | The unique ID of the current project that GitLab CI/CD uses internally. |
+| `CI_PROJECT_NAME` | 8.10 | 0.5 | The name of the directory for the project that is being built. For example, if the project URL is `gitlab.example.com/group-name/project-1`, the `CI_PROJECT_NAME` would be `project-1`. |
+| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | The project namespace (username or group name) that is being built. |
+| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | The **root** project namespace (username or group name) that is being built. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` would be `root-group`. |
+| `CI_PROJECT_PATH` | 8.10 | 0.5 | The namespace with project name. |
+| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH` in lowercase and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
+| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | Comma-separated, lowercase list of the languages used in the repository (for example `ruby,javascript,html,css`). |
+| `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. |
+| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project. |
+| `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility (internal, private, public). |
+| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of the GitLab Container Registry. This variable includes a `:port` value if one has been specified in the registry configuration. |
+| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project. |
+| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. |
+| `CI_REGISTRY_USER` | 9.0 | all | The username to use to push containers to the GitLab Container Registry, for the current project. |
+| `CI_REPOSITORY_URL` | 9.0 | all | The URL to clone the Git repository. |
+| `CI_RUNNER_DESCRIPTION` | 8.10 | 0.5 | The description of the runner as saved in GitLab. |
+| `CI_RUNNER_EXECUTABLE_ARCH` | all | 10.6 | The OS/architecture of the GitLab Runner executable (note that this is not necessarily the same as the environment of the executor). |
+| `CI_RUNNER_ID` | 8.10 | 0.5 | The unique ID of runner being used. |
+| `CI_RUNNER_REVISION` | all | 10.6 | GitLab Runner revision that is executing the current job. |
+| `CI_RUNNER_SHORT_TOKEN` | all | 12.3 | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
+| `CI_RUNNER_TAGS` | 8.10 | 0.5 | The defined runner tags. |
+| `CI_RUNNER_VERSION` | all | 10.6 | GitLab Runner version that is executing the current job. |
+| `CI_SERVER` | all | all | Mark that job is executed in CI environment. |
+| `CI_SERVER_URL` | 12.7 | all | The base URL of the GitLab instance, including protocol and port (like `https://gitlab.example.com:8080`). |
+| `CI_SERVER_HOST` | 12.1 | all | Host component of the GitLab instance URL, without protocol and port (like `gitlab.example.com`). |
+| `CI_SERVER_PORT` | 12.8 | all | Port component of the GitLab instance URL, without host and protocol (like `3000`). |
+| `CI_SERVER_PROTOCOL` | 12.8 | all | Protocol component of the GitLab instance URL, without host and port (like `https`). |
+| `CI_SERVER_NAME` | all | all | The name of CI server that is used to coordinate jobs. |
+| `CI_SERVER_REVISION` | all | all | GitLab revision that is used to schedule jobs. |
+| `CI_SERVER_VERSION` | all | all | GitLab version that is used to schedule jobs. |
+| `CI_SERVER_VERSION_MAJOR` | 11.4 | all | GitLab version major component. |
+| `CI_SERVER_VERSION_MINOR` | 11.4 | all | GitLab version minor component. |
+| `CI_SERVER_VERSION_PATCH` | 11.4 | all | GitLab version patch component. |
+| `CI_SHARED_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. |
+| `GITLAB_CI` | all | all | Mark that job is executed in GitLab CI/CD environment. |
+| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan. |
+| `GITLAB_USER_EMAIL` | 8.12 | all | The email of the user who started the job. |
+| `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. |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index f2dc58bc144..e84714f2a46 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -27,6 +27,7 @@ There are two places defined variables can be used. On the:
| `environment:url` | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.<br/><br/>Supported are all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules).<br/><br/>Not supported are variables defined in the GitLab Runner `config.toml` and variables created in the job's `script`. |
| `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
| `resource_group` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
+| `include` | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. <br/><br/>Predefined project variables are supported: `GITLAB_FEATURES`, `CI_DEFAULT_BRANCH`, and all variables that start with `CI_PROJECT_` (for example `CI_PROJECT_NAME`). |
| `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `image` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `services:[]` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 7ca74cdf2a2..19b8f0f1c89 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -363,8 +363,6 @@ 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. |
-The `include` methods do not support [variable expansion](../variables/where_variables_can_be_used.md#variables-usage).
-
`.gitlab-ci.yml` configuration included by all methods is evaluated at pipeline creation.
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.
@@ -379,6 +377,48 @@ NOTE:
Use merging to customize and override included CI/CD configurations with local
definitions. Local definitions in `.gitlab-ci.yml` override included definitions.
+#### Variables with `include`
+
+> - [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.
+
+You can [use some predefined variables in `include` sections](../variables/where_variables_can_be_used.md#gitlab-ciyml-file)
+in your `.gitlab-ci.yml`:
+
+```yaml
+include:
+ project: '$CI_PROJECT_PATH'
+ file: '.compliance-gitlab-ci.yml'
+```
+
+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)
+```
+
#### `include:local`
`include:local` includes a file from the same repository as `.gitlab-ci.yml`.
@@ -412,9 +452,10 @@ include: '.gitlab-ci-production.yml'
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) in GitLab 11.7.
-To include files from another private project under the same GitLab instance,
-use `include:file`. This file is referenced with full paths relative to the
-root directory (`/`). For example:
+To include files from another private project on the same GitLab instance,
+use `include:file`. You can use `include:file` in combination with `include:project` only.
+
+The included file is referenced with a full path, relative to the root directory (`/`). For example:
```yaml
include:
@@ -445,10 +486,7 @@ You can use local (relative to target project), project, remote, or template inc
##### Multiple files from a project
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26793) in GitLab 13.6.
-> - 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. **(CORE ONLY)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/271560) in GitLab 13.8.
You can include multiple files from the same project:
@@ -461,23 +499,6 @@ include:
- '/templates/.tests.yml'
```
-Including multiple files from the same project is under development but ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:ci_include_multiple_files_from_project)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_include_multiple_files_from_project)
-```
-
#### `include:remote`
`include:remote` can be used to include a file from a different location,
@@ -615,10 +636,33 @@ job:
```
Sometimes, `script` commands must be wrapped in single or double quotes.
-For example, commands that contain a colon (`:`) must be wrapped in quotes.
+For example, commands that contain a colon (`:`) must be wrapped in single quotes (`'`).
The YAML parser needs to interpret the text as a string rather than
-a "key: value" pair. Be careful when using special characters:
-`:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
+a "key: value" pair.
+
+For example, this script uses a colon:
+
+```yaml
+job:
+ script:
+ - curl --request POST --header 'Content-Type: application/json' "https://gitlab/api/v4/projects"
+```
+
+To be considered valid YAML, you must wrap the entire command in single quotes. If
+the command already uses single quotes, you should change them to double quotes (`"`)
+if possible:
+
+```yaml
+job:
+ script:
+ - 'curl --request POST --header "Content-Type: application/json" "https://gitlab/api/v4/projects"'
+```
+
+You can verify the syntax is valid with the [CI Lint](../lint.md) tool.
+
+Be careful when using these special characters as well:
+
+- `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
If any of the script commands return an exit code other than zero, the job
fails and further commands are not executed. Store the exit code in a variable to
@@ -1414,10 +1458,11 @@ In this example, if the first rule matches, then the job has `when: manual` and
#### `rules:variables`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209864) in GitLab 13.7.
-> - 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-rulesvariables). **(CORE ONLY)**
+> - 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/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)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -1444,10 +1489,10 @@ job:
##### Enable or disable rules:variables **(CORE ONLY)**
-rules:variables is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+rules:variables 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 enable it.
+can opt to disable it.
To enable it:
@@ -2270,6 +2315,58 @@ job3:
- deploy_to_staging
```
+#### `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.
+
+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
+for any other exit code:
+
+```yaml
+test_job_1:
+ script:
+ - echo "Run a script that results in exit code 1. This job fails."
+ - exit 1
+ allow_failure:
+ exit_codes: 137
+
+test_job_2:
+ script:
+ - echo "Run a script that results in exit code 137. This job is allowed to fail."
+ - exit 137
+ allow_failure:
+ exit_codes:
+ - 137
+ - 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
@@ -2961,8 +3058,6 @@ larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-ci
Job artifacts are only collected for successful jobs by default, and
artifacts are restored after [caches](#cache).
-[Not all executors can use caches](https://docs.gitlab.com/runner/executors/#compatibility-chart).
-
[Read more about artifacts](../pipelines/job_artifacts.md).
#### `artifacts:paths`
@@ -3266,7 +3361,7 @@ 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.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).
#### `artifacts:reports`
@@ -3386,6 +3481,10 @@ 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.
Leading zeros are removed.
+Coverage output from [child pipelines](../parent_child_pipelines.md) is not recorded
+or displayed. Check [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/280818)
+for more details.
+
### `retry`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3442) in GitLab 9.5.
@@ -3536,15 +3635,13 @@ job split into three separate jobs.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15356) in GitLab 13.3.
-Use `matrix:` to configure different variables for jobs that are running in parallel.
+Use `matrix:` to run a job multiple times in parallel in a single pipeline,
+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).
-[In GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) and later,
-you can have one-dimensional matrices with a single job.
-
Every job gets the same `CI_NODE_TOTAL` [environment variable](../variables/README.md#predefined-environment-variables) value, and a unique `CI_NODE_INDEX` value.
```yaml
@@ -3583,6 +3680,22 @@ deploystacks: [vultr, processing]
The job naming style was [improved in GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/230452).
+##### One-dimensional `matrix` jobs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) in GitLab 13.5.
+
+You can also have one-dimensional matrices with a single job:
+
+```yaml
+deploystacks:
+ stage: deploy
+ script:
+ - bin/deploy
+ parallel:
+ matrix:
+ - PROVIDER: [aws, ovh, gcp, vultr]
+```
+
### `trigger`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
@@ -3933,7 +4046,23 @@ The Release name. If omitted, it is populated with the value of `release: tag_na
#### `release:description`
-Specifies the longer description of the Release.
+Specifies the long description of the Release. You can also specify a file that contains the
+description.
+
+##### Read description from a file
+
+> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/67) in GitLab 13.7.
+
+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.
+
+```yaml
+job:
+ release:
+ tag_name: ${MAJOR}_${MINOR}_${REVISION}
+ description: './path/to/CHANGELOG.md'
+```
#### `release:ref`
diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md
index 602e02dbe6b..e4ede9cf699 100644
--- a/doc/ci/yaml/gitlab_ci_yaml.md
+++ b/doc/ci/yaml/gitlab_ci_yaml.md
@@ -27,7 +27,7 @@ The scripts are grouped into **jobs**, and jobs run as part of a larger
**pipeline**. You can group multiple independent jobs into **stages** that run in a defined order.
You should organize your jobs in a sequence that suits your application and is in accordance with
-the tests you wish to perform. To [visualize](visualization.md) the process, imagine
+the tests you wish to perform. To [visualize](../pipeline_editor/index.md#visualize-ci-configuration) the process, imagine
the scripts you add to jobs are the same as CLI commands you run on your computer.
When you add a `.gitlab-ci.yml` file to your
diff --git a/doc/ci/yaml/visualization.md b/doc/ci/yaml/visualization.md
index 59a92370c70..ff3b0456eca 100644
--- a/doc/ci/yaml/visualization.md
+++ b/doc/ci/yaml/visualization.md
@@ -1,52 +1,8 @@
---
-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
+redirect_to: '../pipeline_editor/index.md#visualize-ci-configuration'
---
-# Visualize your CI/CD configuration
+This document was moved to [another location](../pipeline_editor/index.md#visualize-ci-configuration).
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241722) in GitLab 13.5.
-> - [Moved to **CI/CD > Editor**](https://gitlab.com/gitlab-org/gitlab/-/issues/263141) in GitLab 13.7.
-> - 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-cicd-configuration-visualization). **(CORE ONLY)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-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`](README.md#needs) relationships are displayed as lines connecting jobs together, showing the hierarchy of execution:
-
-![CI Config Visualization](img/ci_config_visualization_v13_7.png)
-
-Hovering on a job highlights its `needs` relationships:
-
-![CI Config 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.
-
-You can only preview one `gitlab-ci.yml` file at a time. Configuration imported with
-[`includes`](README.md#include) is ignored and not included in the visualization.
-
-## Enable or disable CI/CD configuration visualization **(CORE ONLY)**
-
-CI/CD configuration visualization 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_config_visualization_tab)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_config_visualization_tab)
-```
+<!-- This redirect file can be deleted after 2021-04-13. -->
+<!-- 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 2e4674b5288..0d3c1b3cbe9 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -256,11 +256,11 @@ See [database guidelines](database/index.md).
- [Externalization](i18n/externalization.md)
- [Translation](i18n/translation.md)
-## Product Analytics guides
+## Product Intelligence guides
-- [Product Analytics guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
-- [Usage Ping guide](product_analytics/usage_ping.md)
-- [Snowplow guide](product_analytics/snowplow.md)
+- [Product Intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
+- [Usage Ping guide](usage_ping.md)
+- [Snowplow guide](snowplow.md)
## Experiment guide
@@ -292,6 +292,7 @@ See [database guidelines](database/index.md).
- [Reference processing](reference_processing.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)
## Other GitLab Development Kit (GDK) guides
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index 0991c4740cc..01904d37883 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -195,3 +195,34 @@ Without an explicit name argument, Rails can return a false positive
for `index_exists?`, causing a required index to not be created
properly. By always requiring a name for certain types of indexes, the
chance of error is greatly reduced.
+
+## Temporary indexes
+
+There may be times when an index is only needed temporarily.
+
+For example, in a migration, a column of a table might be conditionally
+updated. To query which columns need to be updated within the
+[query performance guidelines](query_performance.md), an index is needed that would otherwise
+not be used.
+
+In these cases, a temporary index should be considered. To specify a
+temporary index:
+
+1. Prefix the index name with `tmp_` and follow the [naming conventions](database/constraint_naming_convention.md) and [requirements for naming indexes](#requirements-for-naming-indexes) for the rest of the name.
+1. Create a follow-up issue to remove the index in the next (or future) milestone.
+1. Add a comment in the migration mentioning the removal issue.
+
+A temporary migration would look like:
+
+```ruby
+INDEX_NAME = 'tmp_index_projects_on_owner_where_emails_disabled'
+
+def up
+ # Temporary index to be removed in 13.9 https://gitlab.com/gitlab-org/gitlab/-/issues/1234
+ add_concurrent_index :projects, :creator_id, where: 'emails_disabled = false', name: INDEX_NAME
+end
+
+def down
+ remove_concurrent_index_by_name :projects, INDEX_NAME
+end
+```
diff --git a/doc/development/agent/identity.md b/doc/development/agent/identity.md
index 65de1a6f0c8..884ce015a02 100644
--- a/doc/development/agent/identity.md
+++ b/doc/development/agent/identity.md
@@ -37,9 +37,9 @@ has a different configuration. Some may enable features A and B, and some may
enable features B and C. This flexibility enables different groups of people to
use different features of the agent in the same cluster.
-For example, [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer)
+For example, [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#priyanka-platform-engineer)
may want to use cluster-wide features of the agent, while
-[Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sasha-software-developer)
+[Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#sasha-software-developer)
uses the agent that only has access to a particular namespace.
Each agent is likely running using a
diff --git a/doc/development/agent/local.md b/doc/development/agent/local.md
index 75d45366238..47246a6a6d3 100644
--- a/doc/development/agent/local.md
+++ b/doc/development/agent/local.md
@@ -38,7 +38,7 @@ You can run `kas` and `agentk` locally to test the [Kubernetes Agent](index.md)
gdk start
# Stop GDK's version of kas
gdk stop gitlab-k8s-agent
-
+
# Start kas
bazel run //cmd/kas -- --configuration-file="$(pwd)/cfg.yaml"
```
@@ -56,3 +56,45 @@ for more targets.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
To learn more about how the repository is structured, see
[GitLab Kubernetes Agent repository overview](https://www.youtube.com/watch?v=j8CyaCWroUY).
+
+## Run tests locally
+
+You can run all tests, or a subset of tests, locally.
+
+- **To run all tests**: Run the command `make test`.
+- **To run all test targets in the directory**: Run the command
+ `bazel test //internal/module/gitops/server:all`.
+
+ You can use `*` in the command, instead of `all`, but it must be quoted to
+ avoid shell expansion: `bazel test '//internal/module/gitops/server:*'`.
+- **To run all tests in a directory and its subdirectories**: Run the command
+ `bazel test //internal/module/gitops/server/...`.
+
+### Run specific test scenarios
+
+To run only a specific test scenario, you need the directory name and the target
+name of the test. For example, to run the tests at
+`internal/module/gitops/server/module_test.go`, the `BUILD.bazel` file that
+defines the test's target name lives at `internal/module/gitops/server/BUILD.bazel`.
+In the latter, the target name is defined like:
+
+```bazel
+go_test(
+ name = "server_test",
+ size = "small",
+ srcs = [
+ "module_test.go",
+```
+
+The target name is `server_test` and the directory is `internal/module/gitops/server/`.
+Run the test scenario with this command:
+
+```shell
+bazel test //internal/module/gitops/server:server_test
+```
+
+### Additional resources
+
+- Bazel documentation about [specifying targets to build](https://docs.bazel.build/versions/master/guide.html#specifying-targets-to-build).
+- [The Bazel query](https://docs.bazel.build/versions/master/query.html)
+- [Bazel query how to](https://docs.bazel.build/versions/master/query-how-to.html)
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 832a89ecac1..d73c3a8d6f6 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -760,7 +760,7 @@ To limit the amount of queries performed, we can use [BatchLoader](graphql_guide
### Writing resolvers
-Our code should aim to be thin declarative wrappers around finders and services. You can
+Our code should aim to be thin declarative wrappers around finders and [services](../development/reusing_abstractions.md#service-classes). You can
repeat lists of arguments, or extract them to concerns. Composition is preferred over
inheritance in most cases. Treat resolvers like controllers: resolvers should be a DSL
that compose other application abstractions.
@@ -1256,6 +1256,10 @@ single mutation when multiple are performed within a single request.
### The `resolve` method
+Similar to [writing resolvers](#writing-resolvers), the `resolve` method of a mutation
+should aim to be a thin declarative wrapper around a
+[service](../development/reusing_abstractions.md#service-classes).
+
The `resolve` method receives the mutation's arguments as keyword arguments.
From here, we can call the service that modifies the resource.
@@ -1352,6 +1356,7 @@ Key points:
- Errors may be reported to users either at `$root.errors` (top-level error) or at
`$root.data.mutationName.errors` (mutation errors). The location depends on what kind of error
this is, and what information it holds.
+- Mutation fields [must have `null: true`](https://graphql-ruby.org/mutations/mutation_errors#nullable-mutation-payload-fields)
Consider an example mutation `doTheThing` that returns a response with
two fields: `errors: [String]`, and `thing: ThingType`. The specific nature of
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 894ae5a1893..8fad32ed163 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -47,7 +47,7 @@ the `author` field. GitLab team members **should not**.
- 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.
- Performance improvements **should** have a changelog entry.
-- Changes that need to be documented in the Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary)
+- 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.
- _Any_ contribution from a community member, no matter how small, **may** have
a changelog entry regardless of these guidelines if the contributor wants one.
@@ -55,7 +55,7 @@ the `author` field. GitLab team members **should not**.
- Any docs-only changes **should not** have a changelog entry.
- Any change behind a disabled feature flag **should not** have a changelog entry.
- Any change behind an enabled feature flag **should** have a changelog entry.
-- Any change that adds new usage data metrics and changes that needs to be documented in Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary) **should** have a changelog entry.
+- Any change that adds new usage data metrics and changes that needs to be documented in Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary) **should** have a changelog entry.
- A change that adds snowplow events **should** have a changelog entry -
- A change that [removes a feature flag](feature_flags/development.md) **should** have a changelog entry -
only if the feature flag did not default to true already.
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index 1ab569ba0df..94b03634e25 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -34,7 +34,7 @@ Also, all templates must be named with the `*.gitlab-ci.yml` suffix.
### Backward compatibility
A template might be dynamically included with the `include:template:` keyword. If
-you make a change to an *existing* template, you **must** make sure that it won't break
+you make a change to an *existing* template, you **must** make sure that it doesn't break
CI/CD in existing projects.
For example, changing a job name in a template could break pipelines in an existing project.
@@ -59,12 +59,20 @@ performance:
```
If the job name `performance` in the template is renamed to `browser-performance`,
-user's `.gitlab-ci.yml` will immediately cause a lint error because there
+the user's `.gitlab-ci.yml` immediately causes a lint error because there
are no such jobs named `performance` in the included template anymore. Therefore,
users have to fix their `.gitlab-ci.yml` that could annoy their workflow.
Please read [versioning](#versioning) section for introducing breaking change safely.
+### Best practices
+
+- Avoid using [global keywords](../../ci/yaml/README.md#global-keywords),
+ such as `image`, `stages` and `variables` at top-level.
+ When a root `.gitlab-ci.yml` [includes](../../ci/yaml/README.md#include)
+ multiple templates, these global keywords could be overridden by the
+ others and cause an unexpected behavior.
+
## Versioning
Versioning allows you to introduce a new template without modifying the existing
@@ -103,7 +111,7 @@ If the `latest` template does not exist yet, you can copy [the stable template](
Users may want to use an older [stable template](#stable-version) that is not bundled
in the current GitLab package. For example, the stable templates in GitLab v13.0 and
-GitLab v14.0 could be so different that a user will want to continue using the v13.0 template even
+GitLab v14.0 could be so different that a user wants to continue using the v13.0 template even
after upgrading to GitLab 14.0.
You can add a note in the template or in documentation explaining how to use `include:remote`
@@ -152,7 +160,7 @@ When you add a template into one of those directories, make sure that it correct
### Write an RSpec test
-You should write an RSpec test to make sure that pipeline jobs will be generated correctly:
+You should write an RSpec test to make sure that pipeline jobs are generated correctly:
1. Add a test file at `spec/lib/gitlab/ci/templates/<template-category>/<template-name>_spec.rb`
1. Test that pipeline jobs are properly created via `Ci::CreatePipelineService`.
@@ -163,10 +171,10 @@ When you introduce a breaking change to [a `latest` template](#latest-version),
you must:
1. Test the upgrade path from [the stable template](#stable-version).
-1. Verify what kind of errors users will encounter.
+1. Verify what kind of errors users encounter.
1. Document it as a troubleshooting guide.
-This information will be important for users when [a stable template](#stable-version)
+This information is important for users when [a stable template](#stable-version)
is updated in a major version GitLab release.
## Security
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 00f4cf90481..fe395dc2304 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -24,6 +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.
You can read more about the importance of involving reviewer(s) in the section on the responsibility of the author below.
@@ -69,14 +70,17 @@ It picks reviewers and maintainers from the list at the
[engineering projects](https://about.gitlab.com/handbook/engineering/projects/)
page, with these behaviors:
-1. It doesn't pick people whose [GitLab status](../user/profile/index.md#current-status)
- contains the string 'OOO', or the emoji is `:palm_tree:` or `:beach:`.
+1. It doesn't pick people whose Slack or [GitLab status](../user/profile/index.md#current-status):
+ - contains the string 'OOO', 'PTO', 'Parental Leave', or 'Friends and Family'
+ - emoji is `:palm_tree:`, `:beach:`, `:beach_umbrella:`, `:beach_with_umbrella:`, `:ferris_wheel:`, `:thermometer:`, `:face_with_thermometer:`, `:red_circle:`, `:bulb:`, `:sun_with_face:`.
1. [Trainee maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer)
are three times as likely to be picked as other reviewers.
-1. People whose [GitLab status](../user/profile/index.md#current-status) emoji
- is `:large_blue_circle:` are more likely to be picked. This applies to both reviewers and trainee maintainers.
+1. Team members whose Slack or [GitLab status](../user/profile/index.md#current-status) emoji
+ is 🔵 `:large_blue_circle:` are more likely to be picked. This applies to both reviewers and trainee maintainers.
- Reviewers with `:large_blue_circle:` are two times as likely to be picked as other reviewers.
- Trainee maintainers with `:large_blue_circle:` are four times as likely to be picked as other reviewers.
+1. People whose [GitLab status](../user/profile/index.md#current-status) emoji
+ is 🔶 `:large_orange_diamond:` are half as likely to be picked. This applies to both reviewers and trainee maintainers.
1. It always picks the same reviewers and maintainers for the same
branch name (unless their OOO status changes, as in point 1). It
removes leading `ce-` and `ee-`, and trailing `-ce` and `-ee`, so
@@ -116,7 +120,7 @@ with [domain expertise](#domain-experts).
by a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)**.
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 Analytics (telemetry) changes, it should be reviewed and approved by a [Product analytics engineer](https://gitlab.com/gitlab-org/growth/product-analytics/engineers).
+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*): 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
@@ -336,6 +340,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.
- 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
@@ -505,7 +510,7 @@ and get on with their work quickly.
If you think you are at capacity and are unable to accept any more reviews until
some have been completed, communicate this through your GitLab status by setting
-the `:red_circle:` emoji and mentioning that you are at capacity in the status
+the 🔴 `:red_circle:` emoji and mentioning that you are at capacity in the status
text. This guides contributors to pick a different reviewer, helping us to
meet the SLO.
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index bfaee407cb8..c316d50c88c 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -112,14 +112,14 @@ the `.rubocop_todo.yml`. This also allows us greater visibility into the excepti
which are currently being resolved.
One way to generate the initial list is to run the todo auto generation,
-with `exclude limit` set to a high number.
+with `exclude limit` set to a high number.
```shell
bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit=10000
```
-You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively
-resolved and place it in the `.rubocop_manual_todo.yml`. In this scenario, do not commit auto generated
+You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively
+resolved and place it in the `.rubocop_manual_todo.yml`. In this scenario, do not commit auto generated
changes to the `.rubocop_todo.yml` as an `exclude limit` that is higher than 15 will make the
`.rubocop_todo.yml` hard to parse.
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 8b839e929c7..33a0fd2ebb7 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -11,11 +11,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
When adding new columns that will be used to store strings or other textual information:
1. We always use the `text` data type instead of the `string` data type.
-1. `text` columns should always have a limit set by using the `add_text_limit` migration helper.
+1. `text` columns should always have a limit set, either by using the `create_table_with_constraints` helper
+when creating a table, or by using the `add_text_limit` when altering an existing table.
-The `text` data type can not be defined with a limit, so `add_text_limit` is enforcing that by
-adding a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html) on the
-column and then validating it at a followup step.
+The `text` data type can not be defined with a limit, so `create_table_with_constraints` and `add_text_limit` enforce
+that by adding a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html) on the column.
## Background information
@@ -48,20 +48,15 @@ class CreateDbGuides < ActiveRecord::Migration[6.0]
DOWNTIME = false
- disable_ddl_transaction!
-
def up
- unless table_exists?(:db_guides)
- create_table :db_guides do |t|
- t.bigint :stars, default: 0, null: false
- t.text :title
- t.text :notes
- end
- end
+ create_table_with_constraints :db_guides do |t|
+ t.bigint :stars, default: 0, null: false
+ t.text :title
+ t.text :notes
- # The following add the constraints and validate them immediately (no data in the table)
- add_text_limit :db_guides, :title, 128
- add_text_limit :db_guides, :notes, 1024
+ t.text_limit :title, 128
+ t.text_limit :notes, 1024
+ end
end
def down
@@ -71,12 +66,8 @@ class CreateDbGuides < ActiveRecord::Migration[6.0]
end
```
-Adding a check constraint requires an exclusive lock while the `ALTER TABLE` that adds is running.
-As we don't want the exclusive lock to be held for the duration of a transaction, `add_text_limit`
-must always run in a migration with `disable_ddl_transaction!`.
-
-Also, note that we have to add a check that the table exists so that the migration can be repeated
-in case of a failure.
+Note that the `create_table_with_constraints` helper uses the `with_lock_retries` helper
+internally, so we don't need to manually wrap the method call in the migration.
## Add a text column to an existing table
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index f0c265df9ab..da2c93cc1fd 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -25,9 +25,9 @@ A database review is required for:
generally up to the author of a merge request to decide whether or
not complex queries are being introduced and if they require a
database review.
-- Changes in usage data metrics that use `count` and `distinct_count`.
+- Changes in usage data metrics that use `count`, `distinct_count` and `estimate_batch_distinct_count`.
These metrics could have complex queries over large tables.
- See the [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
+ See the [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
for implementation details.
A database reviewer is expected to look out for obviously complex
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index 59298c5345f..7547ec59fb2 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -37,12 +37,10 @@ therefore, it indicates that it cannot be done by regular users of GitLab.com.
### Features disabled by default
-For features disabled by default, if they cannot be used yet due to lack of
-completeness, or if they're still under internal evaluation (for example, for
-performance implications) do **not document them**: add (or merge) the docs
-only when the feature is safe and ready to use and test by end-users.
+For features disabled by default, add or improve the docs with every change in line with the
+[definition of done](../contributing/merge_request_workflow.md#definition-of-done).
-For feature flags disabled by default, if they can be used by end users:
+Include details of the feature flag in the documentation:
- Say that it's disabled by default.
- Say whether it's enabled on GitLab.com.
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 5fb5e9b433a..55f5d43b175 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -173,7 +173,7 @@ 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 <http://docs.gitlab.com>.
+ who view the docs on <https://docs.gitlab.com>.
To add a redirect:
@@ -201,6 +201,9 @@ To add a redirect:
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):
@@ -366,6 +369,19 @@ You can combine one or more of the following:
= link_to 'Help page', help_page_path('user/permissions')
```
+#### Linking to `/help` in JavaScript
+
+To link to the documentation from a JavaScript or a Vue component, use the `helpPagePath` function from [`help_page_helper.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/helpers/help_page_helper.js):
+
+```javascript
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+helpPagePath('user/permissions', { anchor: 'anchor-link' })
+// evaluates to '/help/user/permissions#anchor-link' for GitLab.com
+```
+
+This is preferred over static paths, as the helper also works on instances installed under a [relative URL](../../install/relative_url.md).
+
### GitLab `/help` tests
Several [RSpec tests](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/features/help_pages_spec.rb)
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 971652f76d3..bba94c7de7e 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -22,7 +22,7 @@ You can also view a list of [recent updates to this guide](https://gitlab.com/da
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 one of the following:
+- Refer to:
- [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/).
- [Google Developer Documentation Style Guide](https://developers.google.com/style).
@@ -161,7 +161,7 @@ Markdown rendering engine. For a complete Kramdown reference, see the
The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) Ruby gem
plans to support all [GitLab Flavored Markdown](../../../user/markdown.md) in the future, which is
all Markdown supported for display in the GitLab application itself. For now, use
-regular Markdown, following the rules in the linked style guide.
+regular Markdown and follow the rules in the linked style guide.
Kramdown-specific markup (for example, `{:.class}`) doesn't render
properly on GitLab instances under [`/help`](../index.md#gitlab-help).
@@ -207,9 +207,9 @@ Some examples fail if incorrect capitalization is used:
Additionally, commands, parameters, values, filenames, and so on must be
included in backticks. For example:
-- "Change the `needs` keyword in your `.gitlab.yml`..."
- - `needs` is a parameter, and `.gitlab.yml` is a file, so both need backticks.
- Additionally, `.gitlab.yml` without backticks fails markdownlint because it
+- "Change the `needs` keyword in your `.gitlab-ci.yml`..."
+ - `needs` is a parameter, and `.gitlab-ci.yml` is a file, so both need backticks.
+ Additionally, `.gitlab-ci.yml` without backticks fails markdownlint because it
does not have capital G or L.
- "Run `git clone` to clone a Git repository..."
- `git clone` is a command, so it must be lowercase, while Git is the product,
@@ -252,7 +252,7 @@ Put files for a specific product area into the related folder:
### Work with directories and files
-Refer to the following items when working with directories and files:
+When working with directories and files:
1. When you create a new directory, always start with an `index.md` file.
Don't use another filename and _do not_ create `README.md` files.
@@ -332,7 +332,7 @@ GitLab documentation should be clear and easy to understand.
### Trademark
Only use the GitLab name and trademarks in accordance with
-[GitLab Brand Guidelines](https://about.gitlab.com/handbook/marketing/inbound-marketing/digital-experience/brand-guidelines/#trademark).
+[GitLab Brand Guidelines](https://about.gitlab.com/handbook/marketing/corporate-marketing/brand-activation/brand-guidelines/#trademark).
Don't use the possessive form of the word GitLab (`GitLab's`).
@@ -412,7 +412,7 @@ references to user interface elements. For example:
### Inclusive language
We strive to create documentation that's inclusive. This section includes
-guidance and examples for the following categories:
+guidance and examples for these categories:
- [Gender-specific wording](#avoid-gender-specific-wording).
(Tested in [`InclusionGender.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionGender.yml).)
@@ -481,7 +481,7 @@ more precise and functional, such as `primary` and `secondary`.
<!-- vale gitlab.InclusionCultural = YES -->
-For more information see the following [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02).
+For more information see the [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02).
### Fake user information
@@ -499,7 +499,8 @@ addresses and names, do use:
When including sample URLs in the documentation, use:
- `example.com` when the domain name is generic.
-- `gitlab.example.com` when referring to self-managed instances of GitLab.
+- `gitlab.example.com` when referring only to self-managed GitLab instances.
+ Use `gitlab.com` for GitLab SaaS instances.
### Fake tokens
@@ -507,12 +508,11 @@ There may be times where a token is needed to demonstrate an API call using
cURL or a variable used in CI. It is strongly advised not to use real tokens in
documentation even if the probability of a token being exploited is low.
-You can use the following fake tokens as examples:
+You can use these fake tokens as examples:
| Token type | Token value |
|:----------------------|:-------------------------------------------------------------------|
-| Private user token | `<your_access_token>` |
-| Personal access token | `n671WNGecHugsdEDPsyo` |
+| Personal access token | `<your_access_token>` |
| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
| CI/CD variable | `Li8j-mLUVA3eZYjPfd_H` |
@@ -526,11 +526,14 @@ You can use the following fake tokens as examples:
### Usage list
<!-- vale off -->
-| Usage | Guidance |
-|-----------------------|-----|
-| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. |.
+| Usage | Guidance |
+|-----------------------|----------|
+| above | Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **previously** instead. |
+| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. ([Vale](../testing.md#vale) rule: [`Admin.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Admin.yml)) |
+| allow, enable | Try to avoid, unless you are talking about security-related features. For example, instead of "This feature allows you to create a pipeline," use "Use this feature to create a pipeline." This phrasing is more active and is from the user perspective, rather than the person who implemented the feature. [View details](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/allow-allows). |
| and/or | Use **or** instead, or another sensible construction. |
-| currently | Do not use when talking about the product or its features. The documentation describes the product as it is today. |
+| below | Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **following** instead. |
+| currently | Do not use when talking about the product or its features. The documentation describes the product as it is today. ([Vale](../testing.md#vale) rule: [`CurrentStatus.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/CurrentStatus.yml)) |
| easily | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
| e.g. | Do not use Latin abbreviations. Use **for example**, **such as**, **for instance**, or **like** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml)) |
| future tense | When possible, use present tense instead. For example, use `after you execute this command, GitLab displays the result` instead of `after you execute this command, GitLab will display the result`. ([Vale](../testing.md#vale) rule: [`FutureTense.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FutureTense.yml)) |
@@ -865,7 +868,7 @@ Consider installing a plugin or extension in your editor for formatting tables:
When creating tables of lists of features (such the features
available to each role on the [Permissions](../../../user/permissions.md#project-members-permissions)
-page), use the following phrases:
+page), use these phrases:
| Option | Markdown | Displayed result |
|--------|--------------------------|------------------------|
@@ -967,7 +970,7 @@ 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)
in GitLab documentation.
-We include guidance for links in the following categories:
+We include guidance for links in these categories:
- How to set up [anchor links](#anchor-links) for headings.
- How to set up [criteria](#basic-link-criteria) for configuring a link.
@@ -1137,14 +1140,14 @@ When documenting navigation through the user interface:
- Use the exact wording as shown in the UI, including any capital letters as-is.
- Use bold text for navigation items and the char "greater than" (`>`) as a
- separator. For example: `Navigate to your project's **Settings > CI/CD**`.
+ separator. For example: `From your project, go to **Settings > CI/CD**`.
- If there are any expandable menus, make sure to mention that the user needs to
expand the tab to find the settings you're referring to. For example:
- `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**`.
+ `From your group, go to **Settings > CI/CD** and expand **General pipelines**`.
### Navigational elements
-Use the following terms when referring to the main GitLab user interface
+Use these terms when referring to the main GitLab user interface
elements:
- **Top menu**: This is the top menu that spans the width of the user interface.
@@ -1183,7 +1186,7 @@ When you take screenshots:
- Save the image with a lowercase filename that's descriptive of the feature
or concept in the image. If the image is of the GitLab interface, append the
- GitLab version to the filename, based on the following format:
+ GitLab version to the filename, based on this format:
`image_name_vX_Y.png`. For example, for a screenshot taken from the pipelines
page of GitLab 11.1, a valid name is `pipelines_v11_1.png`. If you're adding an
illustration that doesn't include parts of the user interface, add the release
@@ -1365,7 +1368,7 @@ 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 the following table for the most common language classes,
+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)
of available language classes:
@@ -1433,15 +1436,15 @@ Usage examples:
Icons should be used sparingly, and only in ways that aid and do not hinder the
readability of the text.
-For example, the following adds little to the accompanying text:
+For example, this Markdown adds little to the accompanying text:
```markdown
-1. Go to **{home}** **Project overview > Details**
+1. Go to **{home}** **Project overview > Details**.
```
-1. Go to **{home}** **Project overview > Details**
+1. Go to **{home}** **Project overview > Details**.
-However, the following might help the reader connect the text to the user
+However, these tables might help the reader connect the text to the user
interface:
```markdown
@@ -1555,14 +1558,12 @@ It renders on the GitLab documentation site as:
## Terms
-To maintain consistency through GitLab documentation, the following guides
-documentation authors on agreed styles and usage of terms.
+To maintain consistency through GitLab documentation, use these styles and terms.
### Merge requests (MRs)
Merge requests allow you to exchange changes you made to source code and
-collaborate with other people on the same project. This term is used in
-the following ways:
+collaborate with other people on the same project.
- Use lowercase _merge requests_ regardless of whether referring to the feature
or individual merge requests.
@@ -1580,7 +1581,7 @@ Examples:
### Describe UI elements
-The following are styles to follow when describing user interface elements in an
+Follow these styles when you're describing user interface elements in an
application:
- For elements with a visible label, use that label in bold with matching case.
@@ -1590,7 +1591,7 @@ application:
### Verbs for UI elements
-The following are recommended verbs for specific uses with user interface
+Use these verbs for specific uses with user interface
elements:
| Recommended | Used for | Replaces |
@@ -1637,7 +1638,7 @@ displayed for the page or feature.
#### Version text in the **Version History**
-If all content in a section is related, add version text following the header
+If all content in a section is related, add version text after the header
for the section. The version information must be surrounded by blank lines, and
each entry should be on its own line.
@@ -1670,8 +1671,8 @@ the blockquote to use a bulleted list:
If a feature is moved to another tier:
```markdown
-> - [Moved](<link-to-issue>) from [GitLab Premium](https://about.gitlab.com/pricing/) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8.
-> - [Moved](<link-to-issue>) from [GitLab Starter](https://about.gitlab.com/pricing/) to GitLab Core in 12.0.
+> - [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.
```
If a feature is deprecated, include a link to a replacement (when available):
@@ -1709,7 +1710,7 @@ voters to agree.
#### End-of-life for features or products
When a feature or product enters its end-of-life, indicate its status by
-creating a [warning alert](#alert-boxes) directly following its relevant header.
+creating a [warning alert](#alert-boxes) directly after its relevant header.
If possible, link to its deprecation and removal issues.
For example:
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index d2e3f473532..561727648f0 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -183,7 +183,8 @@ 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.
+This configuration is also used within build pipelines, where
+[error-level rules](#vale-result-types) are enforced.
You can use Vale:
@@ -197,14 +198,17 @@ You can use Vale:
Vale returns three types of results: `suggestion`, `warning`, and `error`:
- **Suggestion**-level results are writing tips and aren't displayed in CI
- job output. Suggestions don't break CI.
+ job output. Suggestions don't break CI. See a list of
+ [suggestion-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Suggestion%3A&group_id=9970&project_id=278964).
- **Warning**-level results are [Style Guide](styleguide/index.md) violations, aren't displayed in CI
job output, and should contain clear explanations of how to resolve the warning.
Warnings may be technical debt, or can be future error-level test items
- (after the Technical Writing team completes its cleanup). Warnings don't break CI.
+ (after the Technical Writing team completes its cleanup). Warnings don't break CI. See a list of
+ [warning-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Warning%3A&group_id=9970&project_id=278964).
- **Error**-level results are Style Guide violations, and should contain clear explanations
about how to resolve the error. Errors break CI and are displayed in CI job output.
- of how to resolve the error. Errors break CI and are displayed in CI job output.
+ of how to resolve the error. Errors break CI and are displayed in CI job output. See a list of
+ [error-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Error%3A&group_id=9970&project_id=278964).
### Install linters
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 1c92601dde9..8bf8a5fccb8 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -216,6 +216,9 @@ cron worker sequentially.
Any update to the Elastic index mappings should be replicated in [`Elastic::Latest::Config`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/elastic/latest/config.rb).
+Migrations can be built with a retry limit and have the ability to be [failed and marked as halted](https://gitlab.com/gitlab-org/gitlab/-/blob/66e899b6637372a4faf61cfd2f254cbdd2fb9f6d/ee/lib/elastic/migration.rb#L40).
+Any data or index cleanup needed to support migration retries should be handled within the migration.
+
### Migration options supported by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
- `batched!` - Allow the migration to run in batches. If set, the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
@@ -337,3 +340,48 @@ cluster.routing.allocation.disk.watermark.high: 10gb
Restart Elasticsearch, and the `read_only_allow_delete` will clear on it's 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)_
+
+### Disaster recovery/data loss/backups
+
+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.
+
+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
+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
+useful for operators that are familiar with the GitLab codebase. It is
+documented here in case it is useful for others. The relevant logs that could
+theoretically be used to figure out what needs to be replayed are:
+
+1. All non-repository updates that were synced can be found in
+ [`elasticsearch.log`](../administration/logs.md#elasticsearchlog) by
+ searching for
+ [`track_items`](https://gitlab.com/gitlab-org/gitlab/-/blob/1e60ea99bd8110a97d8fc481e2f41cab14e63d31/ee/app/services/elastic/process_bookkeeping_service.rb#L25)
+ and these can be replayed by sending these items again through
+ `::Elastic::ProcessBookkeepingService.track!`
+1. All repository updates that occurred can be found in
+ [`elasticsearch.log`](../administration/logs.md#elasticsearchlog) by
+ searching for
+ [`indexing_commit_range`](https://gitlab.com/gitlab-org/gitlab/-/blob/6f9d75dd3898536b9ec2fb206e0bd677ab59bd6d/ee/lib/gitlab/elastic/indexer.rb#L41).
+ Replaying these requires resetting the
+ [`IndexStatus#last_commit/last_wiki_commit`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/index_status.rb)
+ to the oldest `from_sha` in the logs and then triggering another index of
+ the project using
+ [`ElasticCommitIndexerWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic_commit_indexer_worker.rb)
+1. All project deletes that occurred can be found in
+ [`sidekiq.log`](../administration/logs.md#sidekiqlog) by searching for
+ [`ElasticDeleteProjectWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic_delete_project_worker.rb).
+ These updates can be replayed by triggering another
+ `ElasticDeleteProjectWorker`.
+
+With the above methods and taking regular [Elasticsearch
+snapshots](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html)
+we should be able to recover from different kinds of data loss issues in a
+relatively short period of time compared to indexing everything from
+scratch.
diff --git a/doc/development/event_tracking/backend.md b/doc/development/event_tracking/backend.md
index 24e83ffc524..e8b8e0c4885 100644
--- a/doc/development/event_tracking/backend.md
+++ b/doc/development/event_tracking/backend.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/index.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../product_analytics/index.md).
+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. -->
+<!-- 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/event_tracking/frontend.md b/doc/development/event_tracking/frontend.md
index 24e83ffc524..e8b8e0c4885 100644
--- a/doc/development/event_tracking/frontend.md
+++ b/doc/development/event_tracking/frontend.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/index.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../product_analytics/index.md).
+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. -->
+<!-- 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/event_tracking/index.md b/doc/development/event_tracking/index.md
index 24e83ffc524..e8b8e0c4885 100644
--- a/doc/development/event_tracking/index.md
+++ b/doc/development/event_tracking/index.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/index.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../product_analytics/index.md).
+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. -->
+<!-- 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/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 35cd55b199c..a1899ab5f18 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -145,7 +145,7 @@ addressed.
To determine whether the experiment is a success or not, we must implement tracking events
to acquire data for analyzing. We can send events to Snowplow via either the backend or frontend.
-Read the [product analytics guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) for more details.
+Read the [product intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) for more details.
#### Track backend events
@@ -281,13 +281,19 @@ Note that this data is completely separate from the [events tracking data](#impl
#### Add context
-You can add arbitrary context data in a hash which gets stored as part of the experiment user record.
+You can add arbitrary context data in a hash which gets stored as part of the experiment user record. New calls to the `record_experiment_user` with newer contexts get merged deeply into the existing context.
+
This data can then be used by data analytics dashboards.
```ruby
before_action do
- record_experiment_user(:signup_flow, foo: 42)
+ record_experiment_user(:signup_flow, foo: 42, bar: { a: 22})
+ # context is { "foo" => 42, "bar" => { "a" => 22 }}
end
+
+# Additional contexts for newer record calls are merged deeply
+record_experiment_user(:signup_flow, foo: 40, bar: { b: 2 }, thor: 3)
+# context becomes { "foo" => 40, "bar" => { "a" => 22, "b" => 2 }, "thor" => 3}
```
### Record experiment conversion event
@@ -337,6 +343,27 @@ to the URL:
https://gitlab.com/<EXPERIMENT_ENTRY_URL>?force_experiment=<EXPERIMENT_KEY>
```
+### A cookie-based approach to force an experiment
+
+It's possible to force the current user to be in the experiment group for `<EXPERIMENT_KEY>`
+during the browser session by using your browser's developer tools:
+
+```javascript
+document.cookie = "force_experiment=<EXPERIMENT_KEY>; path=/";
+```
+
+Use a comma to list more than one experiment to be forced:
+
+```javascript
+document.cookie = "force_experiment=<EXPERIMENT_KEY>,<ANOTHER_EXPERIMENT_KEY>; path=/";
+```
+
+Clear the experiments by unsetting the `force_experiment` cookie:
+
+```javascript
+document.cookie = "force_experiment=; path=/";
+```
+
### Testing and test helpers
#### RSpec
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md
index 0ec10399ae0..b036819cde1 100644
--- a/doc/development/fe_guide/dependencies.md
+++ b/doc/development/fe_guide/dependencies.md
@@ -8,12 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Package manager
-We use [Yarn](https://yarnpkg.com/) to manage frontend dependencies. There are a few exceptions:
-
-- [FontAwesome](https://fontawesome.com/), installed via the `font-awesome-rails` gem: we are working to replace it with
- [GitLab SVGs](https://gitlab-org.gitlab.io/gitlab-svgs/) icons library.
-- [ACE](https://ace.c9.io/) editor, installed via the `ace-rails-ap` gem.
-- Other dependencies found under `vendor/assets/`.
+We use [Yarn](https://yarnpkg.com/) to manage frontend dependencies. There are a few exceptions, stored in `vendor/assets/`.
## Updating dependencies
diff --git a/doc/development/fe_guide/editor_lite.md b/doc/development/fe_guide/editor_lite.md
index 465d64ff63c..47ef85d8737 100644
--- a/doc/development/fe_guide/editor_lite.md
+++ b/doc/development/fe_guide/editor_lite.md
@@ -104,7 +104,14 @@ someActionFunction() {
## Extensions
-Editor Lite has been built to provide a universal, extensible editing tool to the whole product, which would not depend on any particular group. Even though the Editor Lite's core is owned by [Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor-fe/), 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 the Editor Lite changes.
+Editor Lite has been built to provide a universal, extensible editing tool to the whole product,
+which would not depend on any particular group. Even though the Editor Lite's core is owned by
+[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
+the Editor Lite changes.
Structurally, the complete implementation of Editor Lite could be presented as the following diagram:
diff --git a/doc/development/fe_guide/event_tracking.md b/doc/development/fe_guide/event_tracking.md
index 24e83ffc524..e8b8e0c4885 100644
--- a/doc/development/fe_guide/event_tracking.md
+++ b/doc/development/fe_guide/event_tracking.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/index.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../product_analytics/index.md).
+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. -->
+<!-- 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/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index b1896863af9..cbaa648570c 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -815,7 +815,7 @@ it('calls mutation on submitting form ', () => {
### Testing with mocked Apollo Client
-To test the logic of Apollo cache updates, we might want to mock an Apollo Client in our unit tests. We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client and [`createMockApollo` helper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/helpers/mock_apollo_helper.js) we created on top of it.
+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.
@@ -887,7 +887,7 @@ describe('Some component with Apollo mock', () => {
After this, we need to create a mock Apollo Client instance using a helper:
```javascript
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
describe('Some component', () => {
let wrapper;
@@ -1031,7 +1031,6 @@ the following Apollo Client warning when passing only handlers:
```shell
Unexpected call of console.warn() with:
-
Warning: mock-apollo-client - The query is entirely client-side (using @client directives) and resolvers have been configured. The request handler will not be called.
```
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index 1468e886220..af587a31bbb 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -18,8 +18,6 @@ We are using SVG Icons in GitLab with a SVG Sprite.
This means the icons are only loaded once, and are referenced through an ID.
The sprite SVG is located under `/assets/icons.svg`.
-Our goal is to replace one by one all inline SVG Icons (as those currently bloat the HTML) and also all Font Awesome icons.
-
### Usage in HAML/Rails
To use a sprite Icon in HAML or Rails we use a specific helper function:
@@ -90,11 +88,6 @@ Please use the following function inside JS to render an icon:
### Usage in HAML/Rails
-WARNING:
-Do not use the `spinner` or `icon('spinner spin')` rails helpers to insert
-loading icons. These helpers rely on the Font Awesome icon library which is
-deprecated.
-
To insert a loading spinner in HAML or Rails use the `loading_icon` helper:
```haml
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index 7825c89b7cf..aac2258f3a3 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -43,7 +43,7 @@ It takes several arguments of which the measurement’s name is the only one req
performance.measure('My component', 'my-component-start', 'my-component-end')
```
-- Duration between a mark and the moment the measurement is taken. The end mark is omitted in
+- Duration between a mark and the moment the measurement is taken. The end mark is omitted in
this case.
```javascript
@@ -197,7 +197,7 @@ app-*-end // for an end ‘mark’
app-* // for ‘measure’
```
-For example, `'webide-init-editor-start`, `mr-diffs-mark-file-tree-end`, and so on. We do it to
+For example, `'webide-init-editor-start`, `mr-diffs-mark-file-tree-end`, and so on. We do it to
help identify marks and measures coming from the different apps on the same page.
## Best Practices
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index 8e3538e891d..faf03a03101 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -7,7 +7,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/development/fe_guide/style_guide_
# JavaScript style guide
-We use [Airbnb's JavaScript Style Guide](https://github.com/airbnb/javascript) and it's accompanying
+We use [Airbnb's JavaScript Style Guide](https://github.com/airbnb/javascript) and its accompanying
linter to manage most of our JavaScript style guidelines.
In addition to the style guidelines set by Airbnb, we also have a few specific rules
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index b85c1b1de35..0288238a9e5 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -119,7 +119,8 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)
## Naming
-1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension ([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)).
+1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension
+([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)).
1. **Reference Naming**: Use PascalCase for their instances:
```javascript
@@ -402,7 +403,8 @@ When using `v-for` you need to provide a *unique* `:key` attribute for each item
</div>
```
-1. When using `v-for` with `template` and there is more than one child element, the `:key` values must be unique. It's advised to use `kebab-case` namespaces.
+1. When using `v-for` with `template` and there is more than one child element, the `:key` values
+must be unique. It's advised to use `kebab-case` namespaces.
```html
<template v-for="(item, index) in items">
@@ -468,9 +470,10 @@ Useful links:
## Vue testing
-Over time, a number of programming patterns and style preferences have emerged in our efforts to effectively test Vue components.
-The following guide describes some of these. **These are not strict guidelines**, but rather a collection of suggestions and
-good practices that aim to provide insight into how we write Vue tests at GitLab.
+Over time, a number of programming patterns and style preferences have emerged in our efforts to
+effectively test Vue components. The following guide describes some of these.
+**These are not strict guidelines**, but rather a collection of suggestions and good practices that
+aim to provide insight into how we write Vue tests at GitLab.
### Mounting a component
@@ -479,8 +482,10 @@ Typically, when testing a Vue component, the component should be "re-mounted" in
To achieve this:
1. Create a mutable `wrapper` variable inside the top-level `describe` block.
-1. Mount the component using [`mount`](https://vue-test-utils.vuejs.org/api/#mount)/[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount).
-1. Reassign the resulting [`Wrapper`](https://vue-test-utils.vuejs.org/api/wrapper/#wrapper) instance to our `wrapper` variable.
+1. Mount the component using [`mount`](https://vue-test-utils.vuejs.org/api/#mount)/
+[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount).
+1. Reassign the resulting [`Wrapper`](https://vue-test-utils.vuejs.org/api/wrapper/#wrapper)
+instance to our `wrapper` variable.
Creating a global, mutable wrapper provides a number of advantages, including the ability to:
@@ -497,14 +502,16 @@ Creating a global, mutable wrapper provides a number of advantages, including th
})
```
-- Use a `beforeEach` block to mount the component (see [the `createComponent` factory](#the-createcomponent-factory) for more information).
+- Use a `beforeEach` block to mount the component (see
+[the `createComponent` factory](#the-createcomponent-factory) for more information).
- Use an `afterEach` block to destroy the component, for example, `wrapper.destroy()`.
#### The `createComponent` factory
To avoid duplicating our mounting logic, it's useful to define a `createComponent` factory function
that we can reuse in each test block. This is a closure which should reassign our `wrapper` variable
-to the result of [`mount`](https://vue-test-utils.vuejs.org/api/#mount) and [`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount):
+to the result of [`mount`](https://vue-test-utils.vuejs.org/api/#mount) and
+[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount):
```javascript
import MyComponent from '~/path/to/my_component.vue';
@@ -568,7 +575,8 @@ describe('MyComponent', () => {
1. Consider using a single (or a limited number of) object arguments over many arguments.
Defining single parameters for common data like `props` is okay,
- but keep in mind our [JavaScript style guide](javascript.md#limit-number-of-parameters) and stay within the parameter number limit:
+ but keep in mind our [JavaScript style guide](javascript.md#limit-number-of-parameters) and
+ stay within the parameter number limit:
```javascript
// bad
@@ -591,6 +599,19 @@ the mounting function (`mount` or `shallowMount`) to be used to mount the compon
function createComponent({ mountFn = shallowMount } = {}) { }
```
+1. Wrap calls to `mount` and `shallowMount` in `extendedWrapper`, this exposes `wrapper.findByTestId()`:
+
+ ```javascript
+ import { shallowMount } from '@vue/test-utils';
+ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+ import { SomeComponent } from 'components/some_component.vue';
+
+ let wrapper;
+
+ const createWrapper = () => { wrapper = extendedWrapper(shallowMount(SomeComponent)); };
+ const someButton = () => wrapper.findByTestId('someButtonTestId');
+ ```
+
### Setting component state
1. Avoid using [`setProps`](https://vue-test-utils.vuejs.org/api/wrapper/#setprops) to set
@@ -609,12 +630,13 @@ component state wherever possible. Instead, set the component's
```
The exception here is when you wish to test component reactivity in some way.
- For example, you may want to test the output of a component when after a particular watcher has executed.
- Using `setProps` to test such behavior is okay.
+ For example, you may want to test the output of a component when after a particular watcher has
+ executed. Using `setProps` to test such behavior is okay.
### Accessing component state
-1. When accessing props or attributes, prefer the `wrapper.props('myProp')` syntax over `wrapper.props().myProp`:
+1. When accessing props or attributes, prefer the `wrapper.props('myProp')` syntax over
+`wrapper.props().myProp` or `wrapper.vm.myProp`:
```javascript
// good
@@ -626,7 +648,8 @@ component state wherever possible. Instead, set the component's
expect(wrapper.attributes('myAttr')).toBe(true);
```
-1. When asserting multiple props, check the deep equality of the `props()` object with [`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue):
+1. When asserting multiple props, check the deep equality of the `props()` object with
+[`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue):
```javascript
// good
@@ -642,8 +665,9 @@ component state wherever possible. Instead, set the component's
});
```
-1. If you are only interested in some of the props, you can use [`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject).
-Prefer `toMatchObject` over [`expect.objectContaining`](https://jestjs.io/docs/en/expect#expectobjectcontainingobject):
+1. If you are only interested in some of the props, you can use
+[`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject). Prefer `toMatchObject`
+over [`expect.objectContaining`](https://jestjs.io/docs/en/expect#expectobjectcontainingobject):
```javascript
// good
@@ -664,12 +688,24 @@ Prefer `toMatchObject` over [`expect.objectContaining`](https://jestjs.io/docs/e
The goal of this accord is to make sure we are all on the same page.
1. When writing Vue, you may not use jQuery in your application.
- 1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your application to grab data attributes using `dataset`. You can do this without jQuery.
+ 1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your
+ application to grab data attributes using `dataset`. You can do this without jQuery.
1. You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html).
- 1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use jQuery event listeners.
- 1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
-1. You may query the `window` object one time, while bootstrapping your application for application specific data (e.g. `scrollTo` is ok to access anytime). Do this access during the bootstrapping of your application.
-1. You may have a temporary but immediate need to create technical debt by writing code that does not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in the first place. An issue should be created for that tech debt to evaluate it further and discuss. In the coming months you should fix that tech debt, with its priority to be determined by maintainers.
-1. When creating tech debt you must write the tests for that code before hand and those tests may not be rewritten. e.g. jQuery tests rewritten to Vue tests.
-1. You may choose to use VueX as a centralized state management. If you choose not to use VueX, you must use the *store pattern* which can be found in the [Vue.js documentation](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch).
-1. Once you have chosen a centralized state-management solution you must use it for your entire application. i.e. Don't mix and match your state-management solutions.
+ 1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use
+ jQuery event listeners.
+ 1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery
+ events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
+1. You may query the `window` object one time, while bootstrapping your application for application
+specific data (for example, `scrollTo` is ok to access anytime). Do this access during the
+bootstrapping of your application.
+1. You may have a temporary but immediate need to create technical debt by writing code that does
+not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in
+the first place. An issue should be created for that tech debt to evaluate it further and discuss.
+In the coming months you should fix that tech debt, with its priority to be determined by maintainers.
+1. When creating tech debt you must write the tests for that code before hand and those tests may
+not be rewritten. For example, jQuery tests rewritten to Vue tests.
+1. You may choose to use VueX as a centralized state management. If you choose not to use VueX, you
+must use the *store pattern* which can be found in the
+[Vue.js documentation](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch).
+1. Once you have chosen a centralized state-management solution you must use it for your entire
+application. Don't mix and match your state-management solutions.
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 41fbd128631..b3fbb9556a9 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -22,7 +22,8 @@ All new features built with Vue.js must follow a [Flux architecture](https://fac
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).
-You can also read about this architecture in Vue docs about [state management](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)
+You can also read about this architecture in Vue docs 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).
### Components and Store
@@ -62,14 +63,15 @@ Be sure to read about [page-specific JavaScript](performance.md#page-specific-ja
While mounting a Vue application, you might need to provide data from Rails to JavaScript.
To do that, you can use the `data` attributes in the HTML element and query them while mounting the application.
-You should only do this while initializing the application, because the mounted element is replaced with a Vue-generated DOM.
+You should only do this while initializing the application, because the mounted element is replaced
+with a Vue-generated DOM.
-The advantage of providing data from the DOM to the Vue instance through `props` in the `render` 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.
+The advantage of providing data from the DOM to the Vue instance through `props` in the `render`
+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 additional
-information on why we explicitly declare the data being passed into the Vue app;
+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
// haml
@@ -94,13 +96,15 @@ return new Vue({
});
```
-> When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique across the codebase
+> When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique
+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 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:
+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
+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:
```javascript
return new Vue({
@@ -192,13 +196,18 @@ Check this [page](vuex.md) for more details.
In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
-> The data object for the Vue instance. Vue recursively converts its properties into getter/setters to make it “reactiveâ€. The object must be plain: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior.
+> The data object for the Vue instance. Vue recursively converts its properties into getter/setters
+to make it “reactiveâ€. The object must be plain: native objects such as browser API objects and
+prototype properties are ignored. A rule of thumb is that data should just be data - it is not
+recommended to observe objects with their own stateful behavior.
Based on the Vue guidance:
-- **Do not** use or create a JavaScript class in your [data function](https://vuejs.org/v2/api/#data), such as `user: new User()`.
+- **Do not** use or create a JavaScript class in your [data function](https://vuejs.org/v2/api/#data),
+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.
+- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if
+cannot use simple 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.
@@ -209,7 +218,8 @@ There are additional reasons why having a JavaScript class presents maintainabil
- Once a class is created, it is easy to extend it 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 harder to 'manage' component and class separately.
+- It makes it harder to test. Since 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.
## Style guide
@@ -231,6 +241,7 @@ Here's an example of a well structured unit test for [this Vue component](#appen
```javascript
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
@@ -263,19 +274,21 @@ describe('~/todos/app.vue', () => {
});
// It is very helpful to separate setting up the component from
- // its collaborators (i.e. Vuex, axios, etc.)
+ // its collaborators (for example, Vuex and axios).
const createWrapper = (props = {}) => {
- wrapper = shallowMount(App, {
- propsData: {
- path: TEST_TODO_PATH,
- ...props,
- },
- });
+ wrapper = extendedWrapper(
+ shallowMount(App, {
+ propsData: {
+ path: TEST_TODO_PATH,
+ ...props,
+ },
+ })
+ );
};
// Helper methods greatly help test maintainability and readability.
const findLoader = () => wrapper.find(GlLoadingIcon);
- const findAddButton = () => wrapper.find('[data-testid="add-button"]');
- const findTextInput = () => wrapper.find('[data-testid="text-input"]');
+ const findAddButton = () => wrapper.findByTestId('add-button');
+ const findTextInput = () => wrapper.findByTestId('text-input');
const findTodoData = () => wrapper.findAll('[data-testid="todo-item"]').wrappers.map(wrapper => ({ text: wrapper.text() }));
describe('when mounted and loading', () => {
@@ -323,11 +336,41 @@ describe('~/todos/app.vue', () => {
The main return value of a Vue component is the rendered output. In order to test the component we
need to test the rendered output. Visit the [Vue testing guide](https://vuejs.org/v2/guide/testing.html#Unit-Testing).
+### Child components
+
+1. Test any directive that defines if/how child component is rendered (for example, `v-if` and `v-for`).
+1. Test any props we are passing to child components (especially if the prop is calculated in the
+component under test, with the `computed` property, for example). Remember to use `.props()` and not `.vm.someProp`.
+1. Test we react correctly to any events emitted from child components:
+
+ ```javascript
+ const checkbox = wrapper.findByTestId('checkboxTestId');
+
+ expect(checkbox.attributes('disabled')).not.toBeDefined();
+
+ findChildComponent().vm.$emit('primary');
+ await nextTick();
+
+ expect(checkbox.attributes('disabled')).toBeDefined();
+ ```
+
+1. **Do not** test the internal implementation of the child components:
+
+ ```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 verify the correct events are being fired with the correct arguments.
+We should test for events emitted in response to an action within our component, this is useful 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) to fire out event.
+For any DOM events we should use [`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger)
+to fire out event.
```javascript
// Assuming SomeButton renders: <button>Some button</button>
@@ -342,7 +385,8 @@ it('should fire the click event', () => {
})
```
-When we need to fire a Vue event, we should use [`emit`](https://vuejs.org/v2/guide/components-custom-events.html) to fire our event.
+When we need to fire a Vue event, we should use [`emit`](https://vuejs.org/v2/guide/components-custom-events.html)
+to fire our event.
```javascript
wrapper = shallowMount(DropdownItem);
@@ -355,7 +399,8 @@ it('should fire the itemClicked event', () => {
})
```
-We should verify an event has been fired by asserting against the result of the [`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted) method
+We should verify an event has been fired by asserting against the result of the
+[`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted) method.
## Vue.js Expert Role
@@ -371,7 +416,8 @@ 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 the tech debt for the eventual migration:
+Currently, we recommend to minimize adding certain features to the codebase to prevent increasing
+the tech debt for the eventual migration:
- filters;
- event buses;
@@ -382,7 +428,8 @@ You can find more details on [Migration to Vue 3](vue3_migration.md)
## Appendix - Vue component subject under test
-This is the template for the example component which is tested in the [Testing Vue components](#testing-vue-components) section:
+This is the template for the example component which is tested in the
+[Testing Vue components](#testing-vue-components) section:
```html
<template>
diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md
index dd69d7bcf80..2f0f8101b53 100644
--- a/doc/development/feature_categorization/index.md
+++ b/doc/development/feature_categorization/index.md
@@ -122,7 +122,7 @@ the actions used in configuration still exist as routes.
## API endpoints
The [GraphQL API](../../api/graphql/index.md) is currently categorized
-as `not_owned`. For now, no extra specification is needed. For more
+as `not_owned`. For now, no extra specification is needed. For more
information, see
[`gitlab-com/gl-infra/scalability#583`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/583/).
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index 7551199aa58..adcf3175c45 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -250,6 +250,7 @@ Changes to the issue format can be submitted in the
Any feature flag change that affects any GitLab instance is automatically logged in
[features_json.log](../../administration/logs.md#features_jsonlog).
You can search the change history in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html).
+You can access the feature flag change history for GitLab.com [here](https://log.gprd.gitlab.net/goto/d060337c017723084c6d97e09e591fc6).
## Cleaning up
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index 7c5333c9aa6..dd732a08c72 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -378,6 +378,18 @@ You can also enable a feature flag for a given gate:
Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project"))
```
+### Removing a feature flag locally (in development)
+
+When manually enabling or disabling a feature flag from the Rails console, its default value gets overwritten.
+This can cause confusion when changing the flag's `default_enabled` attribute.
+
+To reset the feature flag to the default status, you can remove it in the rails console (`rails c`)
+as follows:
+
+```ruby
+Feature.remove(:feature_flag_name)
+```
+
## Feature flags in tests
Introducing a feature flag into the codebase creates an additional code path that should be tested.
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 270e07ed755..e93a5b3de1b 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -6,24 +6,34 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
# Feature flags in development of GitLab
+**NOTE**:
+The documentation below covers feature flags used by GitLab to deploy its own features, which **is not** the same
+as the [feature flags offered as part of the product](../../operations/feature_flags.md).
+
## When to use feature flags
-Starting with GitLab 11.4, developers are required to use feature flags for
-non-trivial changes. Such changes include:
+Developers are required to use feature flags for changes that could affect availability of existing GitLab functionality (if it only affects the new feature you're making that is probably acceptable).
+Such changes include:
+
+1. New features in high traffic areas (e.g. a new merge request widget, new option in issues/epics, new CI functionality).
+1. Complex performance improvements that may require additional testing in production (e.g. rewriting complex queries, changes to frequently used API endpoints).
+1. Invasive changes to the user interface (e.g. introducing a new navigation bar, removal of a sidebar, UI element change in issues or MR interface).
+1. Introducing dependencies on third-party services (e.g. adding support for importing projects).
+1. Changes to features that can cause data corruption or cause data loss (e.g. features processing repository data or user uploaded content).
+
+Situations where you might consider not using a feature flag:
+
+1. Adding a new API endpoint
+1. Introducing new features in low traffic areas (e.g. adding a new export functionality in the admin area/group settings/project settings)
+1. Non-invasive frontend changes (e.g. changing the color of a button, or moving a UI element in a low traffic area)
+
+In all cases, those working on the changes should ask themselves:
-- New features (e.g. a new merge request widget, epics, etc).
-- Complex performance improvements that may require additional testing in
- production, such as rewriting complex queries.
-- Invasive changes to the user interface, such as a new navigation bar or the
- removal of a sidebar.
-- Adding support for importing projects from a third-party service.
-- Risk of data loss
+> 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?
-In all cases, those working on the changes can best decide if a feature flag is
-necessary. For example, changing the color of a button doesn't need a feature
-flag, while changing the navigation bar definitely needs one. In case you are
-uncertain if a feature flag is necessary, simply ask about this in the merge
-request, and those reviewing the changes will likely provide you with an answer.
+For perspective on why we limit our use of feature flags please see the following [video](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.
When using a feature flag for UI elements, make sure to _also_ use a feature
flag for the underlying backend code, if there is any. This ensures there is
@@ -36,35 +46,29 @@ they are new features or performance improvements. By using feature flags,
you can determine the impact of GitLab-directed changes, while still being able
to disable those changes without having to revert an entire release.
-Before using feature flags for GitLab development, review the following development guides:
-
-NOTE:
-The feature flags used by GitLab to deploy its own features **are not** the same
-as the [feature flags offered as part of the product](../../operations/feature_flags.md).
-
For an overview about starting with feature flags in GitLab development,
use this [training template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/.gitlab/issue_templates/feature-flag-training.md).
-Development guides:
+Before using feature flags for GitLab development, review the following development guides:
-- [Process for using features flags](process.md): When you should use
+1. [Process for using features flags](process.md): When you should use
feature flags in the development of GitLab, what's the cost of using them,
and how to include them in a release.
-- [Developing with feature flags](development.md): Learn about the types of
+1. [Developing with feature flags](development.md): Learn about the types of
feature flags, their definition and validation, how to create them, frontend and
backend details, and other information.
-- [Documenting features deployed behind feature flags](../documentation/feature_flags.md):
+1. [Documenting features deployed behind feature flags](../documentation/feature_flags.md):
How to document features deployed behind feature flags, and how to update the
documentation for features' flags when their states change.
-- [Controlling feature flags](controls.md): Learn the process for deploying
+1. [Controlling feature flags](controls.md): Learn the process for deploying
a new feature, enabling it on GitLab.com, communicating the change,
logging, and cleaning up.
User guides:
-- [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.md):
+1. [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.md):
An explanation for GitLab administrators about how they can
enable or disable GitLab features behind feature flags.
-- [What "features deployed behind flags" means to the GitLab user](../../user/feature_flags.md):
+1. [What "features deployed behind flags" means to the GitLab user](../../user/feature_flags.md):
An explanation for GitLab users regarding how certain features
might not be available to them until they are enabled.
diff --git a/doc/development/feature_flags/process.md b/doc/development/feature_flags/process.md
index 2e3680bb103..7e6299c193c 100644
--- a/doc/development/feature_flags/process.md
+++ b/doc/development/feature_flags/process.md
@@ -148,3 +148,30 @@ they speed up the process as managing incidents now becomes _much_ easier. Once
continuous deployments are easier to perform, the time to iterate on a feature
is reduced even further, as you no longer need to wait weeks before your changes
are available on GitLab.com.
+
+### The benefits of feature flags
+
+It may seem like feature flags are configuration, which goes against our [convention-over-configuration](https://about.gitlab.com/handbook/product/product-principles/#convention-over-configuration)
+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.
+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
+first moment.
+
+Some of the benefits of using development-type feature flags are:
+
+1. It enables Continuous Delivery for GitLab.com.
+1. It significantly reduces Mean-Time-To-Recovery.
+1. It helps engineers to monitor and reduce the impact of their changes gradually, at any scale,
+ allowing us to be more metrics-driven and execute good DevOps practices, [shifting some responsibility "left"](https://devops.com/why-its-time-for-site-reliability-engineering-to-shift-left/).
+1. Controlled feature rollout timing: without feature flags, we would need to wait until a specific
+ deployment was complete (which at GitLab could be at any time).
+1. Increased psychological safety: when a feature flag is used, an engineer has the confidence that if anything goes wrong they can quickly disable the code and minimize the impact of a change that might be risky.
+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.
diff --git a/doc/development/foreign_keys.md b/doc/development/foreign_keys.md
index 0f100c6b66e..37764a12f97 100644
--- a/doc/development/foreign_keys.md
+++ b/doc/development/foreign_keys.md
@@ -105,6 +105,8 @@ create_table :user_configs, id: false do |t|
end
```
+Setting `default: nil` will ensure a primary key sequence is not created, and since the primary key
+will automatically get an index, we set `index: false` to avoid creating a duplicate.
You will also need to add the new primary key to the model:
```ruby
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index e4518ce1b57..148953dc418 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -287,7 +287,7 @@ For example, to add support for files referenced by a `Widget` model with a
t.datetime_with_timezone :created_at, null: false
t.text :last_sync_failure
- t.index :widget_id, name: :index_widget_registry_on_widget_id
+ t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true
t.index :retry_at
t.index :state
end
@@ -743,6 +743,8 @@ available in the Admin UI.
#### Releasing the feature
+1. In `ee/config/feature_flags/development/geo_widget_replication.yml`, set `default_enabled: true`
+
1. In `ee/app/replicators/geo/widget_replicator.rb`, delete the `self.replication_enabled_by_default?` method:
```ruby
@@ -770,3 +772,260 @@ available in the Admin UI.
description: 'Find widget registries on this Geo node',
feature_flag: :geo_widget_replication # REMOVE THIS LINE
```
+
+### Repository Replicator Strategy
+
+Models that refer to any repository on the disk
+can be easily supported by Geo with the `Geo::RepositoryReplicatorStrategy` module.
+
+For example, to add support for files referenced by a `Gizmos` model with a
+`gizmos` table, you would perform the following steps.
+
+#### Replication
+
+1. Include `Gitlab::Geo::ReplicableModel` in the `Gizmo` class, and specify
+ the Replicator class `with_replicator Geo::GizmoReplicator`.
+
+ At this point the `Gizmo` class should look like this:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class Gizmo < ApplicationRecord
+ include ::Gitlab::Geo::ReplicableModel
+
+ with_replicator Geo::GizmoReplicator
+
+ # @param primary_key_in [Range, Gizmo] arg to pass to primary_key_in scope
+ # @return [ActiveRecord::Relation<Gizmo>] everything that should be synced to this node, restricted by primary key
+ def self.replicables_for_current_secondary(primary_key_in)
+ # Should be implemented. The idea of the method is to restrict
+ # the set of synced items depending on synchronization settings
+ end
+
+ # Geo checks this method in FrameworkRepositorySyncService to avoid
+ # snapshotting repositories using object pools
+ def pool_repository
+ nil
+ end
+ ...
+ end
+ ```
+
+ Pay some attention to method `pool_repository`. Not every repository type uses
+ repository pooling. As Geo prefers to use repository snapshotting, it can lead to data loss.
+ Make sure to overwrite `pool_repository` so it returns nil for repositories that do not
+ have pools.
+
+ If there is a common constraint for records to be available for replication,
+ make sure to also overwrite the `available_replicables` scope.
+
+1. Create `ee/app/replicators/geo/gizmo_replicator.rb`. Implement the
+ `#repository` method which should return a `<Repository>` instance,
+ and implement the class method `.model` to return the `Gizmo` class:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Geo
+ class GizmoReplicator < Gitlab::Geo::Replicator
+ include ::Geo::RepositoryReplicatorStrategy
+
+ def self.model
+ ::Gizmo
+ end
+
+ def repository
+ model_record.repository
+ end
+
+ def self.git_access_class
+ ::Gitlab::GitAccessGizmo
+ end
+
+ # The feature flag follows the format `geo_#{replicable_name}_replication`,
+ # so here it would be `geo_gizmo_replication`
+ def self.replication_enabled_by_default?
+ false
+ end
+ end
+ end
+ ```
+
+1. Generate the feature flag definition file by running the feature flag command
+ and running through the steps:
+
+ ```shell
+ bin/feature-flag --ee geo_gizmo_replication --type development --group 'group::geo'
+ ```
+
+1. Make sure Geo push events are created. Usually it needs some
+ change in the `app/workers/post_receive.rb` file. Example:
+
+ ```ruby
+ def replicate_gizmo_changes(gizmo)
+ if ::Gitlab::Geo.primary?
+ gizmo.replicator.handle_after_update if gizmo
+ end
+ end
+ ```
+
+ See `app/workers/post_receive.rb` for more examples.
+
+1. Make sure the repository removal is also handled. You may need to add something
+ like the following in the destroy service of the repository:
+
+ ```ruby
+ gizmo.replicator.handle_after_destroy if gizmo.repository
+ ```
+
+1. Add this replicator class to the method `replicator_classes` in
+ `ee/lib/gitlab/geo.rb`:
+
+ ```ruby
+ REPLICATOR_CLASSES = [
+ ...
+ ::Geo::PackageFileReplicator,
+ ::Geo::GizmoReplicator
+ ]
+ end
+ ```
+
+1. Create `ee/spec/replicators/geo/gizmo_replicator_spec.rb` and perform
+ the necessary setup to define the `model_record` variable for the shared
+ examples:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::GizmoReplicator do
+ let(:model_record) { build(:gizmo) }
+
+ include_examples 'a repository replicator'
+ end
+ ```
+
+1. Create the `gizmo_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
+ verification state of each Gizmo. This migration belongs in `ee/db/geo/migrate`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CreateGizmoRegistry < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :gizmo_registry, id: :bigserial, force: :cascade do |t|
+ t.datetime_with_timezone :retry_at
+ t.datetime_with_timezone :last_synced_at
+ t.datetime_with_timezone :created_at, null: false
+ t.bigint :gizmo_id, null: false
+ t.integer :state, default: 0, null: false, limit: 2
+ t.integer :retry_count, default: 0, limit: 2
+ t.text :last_sync_failure
+ t.boolean :force_to_redownload
+ t.boolean :missing_on_primary
+
+ t.index :gizmo_id, name: :index_gizmo_registry_on_gizmo_id, unique: true
+ t.index :retry_at
+ t.index :state
+ end
+
+ add_text_limit :gizmo_registry, :last_sync_failure, 255
+ end
+
+ def down
+ drop_table :gizmo_registry
+ end
+ end
+ ```
+
+1. Create `ee/app/models/geo/gizmo_registry.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class Geo::GizmoRegistry < Geo::BaseRegistry
+ include Geo::ReplicableRegistry
+
+ MODEL_CLASS = ::Gizmo
+ MODEL_FOREIGN_KEY = :gizmo_id
+
+ belongs_to :gizmo, class_name: 'Gizmo'
+ end
+ ```
+
+1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
+1. Add `gizmo_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
+1. Create `ee/spec/factories/geo/gizmo_registry.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ FactoryBot.define do
+ factory :geo_gizmo_registry, class: 'Geo::GizmoRegistry' do
+ gizmo
+ state { Geo::GizmoRegistry.state_value(:pending) }
+
+ trait :synced do
+ state { Geo::GizmoRegistry.state_value(:synced) }
+ last_synced_at { 5.days.ago }
+ end
+
+ trait :failed do
+ state { Geo::GizmoRegistry.state_value(:failed) }
+ last_synced_at { 1.day.ago }
+ retry_count { 2 }
+ last_sync_failure { 'Random error' }
+ end
+
+ trait :started do
+ state { Geo::GizmoRegistry.state_value(:started) }
+ last_synced_at { 1.day.ago }
+ retry_count { 0 }
+ end
+ end
+ end
+ ```
+
+1. Create `ee/spec/models/geo/gizmo_registry_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::GizmoRegistry, :geo, type: :model do
+ let_it_be(:registry) { create(:geo_gizmo_registry) }
+
+ specify 'factory is valid' do
+ expect(registry).to be_valid
+ end
+
+ include_examples 'a Geo framework registry'
+ end
+ ```
+
+1. Make sure the newly added repository type can be accessed by a secondary.
+ You may need to make some changes to one of the Git access classes.
+
+ Gizmos should now be replicated by Geo.
+
+#### Metrics
+
+You need to make the same changes as for Blob Replicator Strategy.
+You need to make the same changes for the [metrics as in the Blob Replicator Strategy](#metrics).
+
+#### GraphQL API
+
+You need to make the same changes for the GraphQL API [as in the Blob Replicator Strategy](#graphql-api).
+
+#### Releasing the feature
+
+You need to make the same changes for [releasing the feature as in the Blob Replicator Strategy](#releasing-the-feature).
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 57a4e24679c..5d062d7404e 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -27,8 +27,9 @@ have changed since then, it should still serve as a good introduction.
## Beginner's guide
Start by reading the Gitaly repository's
-[Beginner's guide to Gitaly contributions](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/beginners_guide.md).
-It describes how to set up Gitaly, the various components of Gitaly and what they do, and how to run its test suites.
+[Beginner's guide to Gitaly contributions](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/beginners_guide.md).
+It describes how to set up Gitaly, the various components of Gitaly and what
+they do, and how to run its test suites.
## Developing new Git features
@@ -36,33 +37,17 @@ To read or write Git data, a request has to be made to Gitaly. This means that
if you're developing a new feature where you need data that's not yet available
in `lib/gitlab/git` changes have to be made to Gitaly.
-> This is a new process that is not clearly defined yet. If you want
-to contribute a Git feature and you're getting stuck, reach out to the
-Gitaly team or `@jacobvosmaer-gitlab`.
+There should be no new code that touches Git repositories via disk access (for example,
+Rugged, `git`, `rm -rf`) anywhere in the `gitlab` repository. Anything that
+needs direct access to the Git repository *must* be implemented in Gitaly, and
+exposed via an RPC.
-By 'new feature' we mean any method or class in `lib/gitlab/git` that is
-called from outside `lib/gitlab/git`. For new methods that are called
-from inside `lib/gitlab/git`, see 'Modifying existing Git features'
-below.
+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
+immediately after the Gitaly one. This allows you to test your changes before
+they are merged.
-There should be no new code that touches Git repositories via
-disk access (e.g. Rugged, `git`, `rm -rf`) anywhere outside
-`lib/gitlab/git`.
-
-The process for adding new Gitaly features is:
-
-- exploration / prototyping
-- design and create a new Gitaly RPC in [`gitaly-proto`](https://gitlab.com/gitlab-org/gitaly-proto)
-- release a new version of `gitaly-proto`
-- write implementation and tests for the RPC [in Gitaly](https://gitlab.com/gitlab-org/gitaly), in Go or Ruby
-- release a new version of Gitaly
-- write client code in GitLab CE/EE, GitLab Workhorse or GitLab Shell that calls the new Gitaly RPC
-
-These steps often overlap. It is possible to use an unreleased version
-of Gitaly and `gitaly-proto` during testing and development.
-
-- See the [Gitaly repository](https://gitlab.com/gitlab-org/gitaly/blob/master/CONTRIBUTING.md#development-and-testing-with-a-custom-gitaly-proto) for instructions on writing server side code with an unreleased protocol.
-- See [below](#running-tests-with-a-locally-modified-version-of-gitaly) for instructions on running GitLab CE tests with a modified version of Gitaly.
+- See [below](#running-tests-with-a-locally-modified-version-of-gitaly) for instructions on running GitLab tests with a modified version of Gitaly.
- In GDK run `gdk install` and restart `gdk run` (or `gdk run app`) to use a locally modified Gitaly version for development
### `gitaly-ruby`
@@ -208,7 +193,7 @@ to manually run `make` again.
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 paragraph.
+GITALY_SERVER_VERSION as described at the beginning of this section.
To use a different Gitaly repository, e.g., if your changes are present
on a fork, you can specify a `GITALY_REPO_URL` environment variable when
@@ -244,6 +229,9 @@ the branch with the changes (`new-feature-branch`, for example):
1. Run `bundle install` to use the modified RPC client.
+Re-run `bundle install` in the `gitlab` project each time the Gitaly branch
+changes to embed a new SHA in the `Gemfile.lock` file.
+
---
[Return to Development documentation](README.md)
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index b2405f4ce2a..68210c08a00 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -171,7 +171,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.
-[PQ](https://github.com/lib/pq) should be enough to interact with PostgreSQL
+[pgx](https://github.com/jackc/pgx) should be enough to interact with PostgreSQL
databases.
### Migrations
@@ -449,11 +449,10 @@ changes between minor versions can expose bugs or cause problems in our projects
Once you've picked a new Go version to use, the steps to update Omnibus and CNG
are:
-- [Create a merge request in the CNG project](https://gitlab.com/gitlab-org/build/CNG/edit/master/ci_files/variables.yml?branch_name=update-go-version),
+- [Create a merge request in the CNG project](https://gitlab.com/gitlab-org/build/CNG/-/edit/master/ci_files/variables.yml?branch_name=update-go-version),
updating the `GO_VERSION` in `ci_files/variables.yml`.
-- Create a merge request in the [`gitlab-omnibus-builder` project](https://gitlab.com/gitlab-org/gitlab-omnibus-builder),
- updating every file in the `docker/` directory so the `GO_VERSION` is set
- appropriately. [Here's an example](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/125/diffs).
+- [Create a merge request in the `gitlab-omnibus-builder` project](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/edit/master/docker/VERSIONS?branch_name=update-go-version),
+ updating the `GO_VERSION` in `docker/VERSIONS`.
- Tag a new release of `gitlab-omnibus-builder` containing the change.
- [Create a merge request in the `omnibus-gitlab` project](https://gitlab.com/gitlab-org/omnibus-gitlab/edit/master/.gitlab-ci.yml?branch_name=update-gitlab-omnibus-builder-version),
updating the `BUILDER_IMAGE_REVISION` to match the newly-created tag.
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index 2b34aedddf6..a506b67d89d 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -270,7 +270,7 @@ This problem disappears as soon as we upgrade to Rails 6 and use the Zeitwerk au
### Further reading
- Rails Guides: [Autoloading and Reloading Constants (Classic Mode)](https://guides.rubyonrails.org/autoloading_and_reloading_constants_classic_mode.html)
-- Ruby Constant lookup: [Everything you ever wanted to know about constant lookup in Ruby](http://cirw.in/blog/constant-lookup)
+- Ruby Constant lookup: [Everything you ever wanted to know about constant lookup in Ruby](https://cirw.in/blog/constant-lookup)
- Rails 6 and Zeitwerk autoloader: [Understanding Zeitwerk in Rails 6](https://medium.com/cedarcode/understanding-zeitwerk-in-rails-6-f168a9f09a1f)
## Storing assets that do not require pre-compiling
diff --git a/doc/development/img/snowplow_flow.png b/doc/development/img/snowplow_flow.png
index 5996cf01537..aae597edc13 100644
--- a/doc/development/img/snowplow_flow.png
+++ b/doc/development/img/snowplow_flow.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_annotation.png b/doc/development/img/stage_group_dashboards_annotation.png
new file mode 100644
index 00000000000..3776d87e5bb
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_annotation.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_debug_1.png b/doc/development/img/stage_group_dashboards_debug_1.png
new file mode 100644
index 00000000000..309fad89120
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_debug_1.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_debug_2.png b/doc/development/img/stage_group_dashboards_debug_2.png
new file mode 100644
index 00000000000..2aad9ab5592
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_debug_2.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_debug_3.png b/doc/development/img/stage_group_dashboards_debug_3.png
new file mode 100644
index 00000000000..38647410ffd
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_debug_3.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_filters.png b/doc/development/img/stage_group_dashboards_filters.png
new file mode 100644
index 00000000000..27a836bc36d
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_filters.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_metrics.png b/doc/development/img/stage_group_dashboards_metrics.png
new file mode 100644
index 00000000000..6b6faff6e3b
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_metrics.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_time_customization.png b/doc/development/img/stage_group_dashboards_time_customization.png
new file mode 100644
index 00000000000..49e61183b7c
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_time_customization.png
Binary files differ
diff --git a/doc/development/img/stage_group_dashboards_time_filter.png b/doc/development/img/stage_group_dashboards_time_filter.png
new file mode 100644
index 00000000000..81a3dc789f1
--- /dev/null
+++ b/doc/development/img/stage_group_dashboards_time_filter.png
Binary files differ
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index 8fb7f29c86c..94b56e10d9e 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -11,7 +11,7 @@ blocks of Ruby code. Method instrumentation is the primary form of
instrumentation with block-based instrumentation only being used when we want to
drill down to specific regions of code within a method.
-Please refer to [Product Analytics](https://about.gitlab.com/handbook/product/product-analytics-guide/) if you are tracking product usage patterns.
+Please refer to [Product Intelligence](https://about.gitlab.com/handbook/product/product-intelligence-guide/) if you are tracking product usage patterns.
## Instrumenting Methods
diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md
index 1641f4656a0..faa1ec0ee3f 100644
--- a/doc/development/integrations/codesandbox.md
+++ b/doc/development/integrations/codesandbox.md
@@ -1,7 +1,7 @@
# 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
+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
@@ -59,7 +59,7 @@ to use a locally-built module. To build and use a local `smooshpack` module:
yarn run start
```
- Now, in the GitLab project, you can run `yarn link "smooshpack"`. `yarn` looks
+ Now, in the GitLab project, you can run `yarn link "smooshpack"`. `yarn` looks
for `smooshpack` **on disk** as opposed to the one hosted remotely.
1. In the `gitlab` project directory, run:
@@ -110,7 +110,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
+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`:
```patch
@@ -125,7 +125,7 @@ index 6eed627b502..1824669e881 100644
- 'https://sandbox-prod.gitlab-static.net'
+ 'https://sandpack.local:8044'
end
-
+
private
```
diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md
index c87b15e192a..a9a1026f1a8 100644
--- a/doc/development/integrations/jenkins.md
+++ b/doc/development/integrations/jenkins.md
@@ -90,7 +90,7 @@ option because the Jenkins plugin updates the build status on GitLab. In a **Pip
## Configure your GitLab project
-To activate the Jenkins service you must have a Starter subscription or higher.
+To activate the Jenkins service:
1. Go to your project's page, then **Settings > Integrations > Jenkins CI**.
1. Check the **Active** checkbox and the triggers for **Push** and **Merge request**.
diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md
index 408b0e6068e..48beb526774 100644
--- a/doc/development/integrations/jira_connect.md
+++ b/doc/development/integrations/jira_connect.md
@@ -10,13 +10,20 @@ The following are required to install and test the app:
- A Jira Cloud instance. Atlassian provides [free instances for development and testing](https://developer.atlassian.com/platform/marketplace/getting-started/#free-developer-instances-to-build-and-test-your-app).
- A GitLab instance available over the internet. For the app to work, Jira Cloud should
- be able to connect to the GitLab instance through the internet. To easily expose your
- local development environment, you can use tools like:
- - [serveo](https://medium.com/automationmaster/how-to-forward-my-local-port-to-public-using-serveo-4979f352a3bf)
- - [ngrok](https://ngrok.com).
+ be able to connect to the GitLab instance through the internet. For this we
+ recommend using Gitpod or a similar cloud development environment. For more
+ information on using Gitpod with GDK, see the:
- These also take care of SSL for you because Jira requires all connections to the app
- host to be over SSL.
+ - [GDK in Gitpod](https://www.loom.com/share/9c9711d4876a40869b9294eecb24c54d)
+ video.
+ - [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
+ 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
+ your own environment, remember to enable SSL and an appropriate certificate.
## Install the app in Jira
@@ -38,7 +45,7 @@ To install the app in Jira:
For example:
```plaintext
- https://xxxx.serveo.net/-/jira_connect/app_descriptor.json
+ https://xxxx.gitpod.io/-/jira_connect/app_descriptor.json
```
1. Click **Upload**.
diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md
index 4971e4d629d..43655c37048 100644
--- a/doc/development/internal_api.md
+++ b/doc/development/internal_api.md
@@ -448,3 +448,22 @@ Example Request:
```shell
curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
```
+
+### Kubernetes agent alert metrics
+
+Called from GitLab Kubernetes Agent Server (KAS) to save alerts derived from Cilium on Kubernetes
+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). |
+
+```plaintext
+POST internal/kubernetes/modules/cilium_alert
+```
+
+Example Request:
+
+```shell
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
+```
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index 3953e7097dd..43d7f32ad7f 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -42,6 +42,29 @@ The API of this method is similar to `in_batches`, though it doesn't support
all of the arguments that `in_batches` supports. You should always use
`each_batch` _unless_ you have a specific need for `in_batches`.
+## Avoid iterating over non-unique columns
+
+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`
+matching rows
+
+```ruby
+[ gstg ] production> Ci::Build.where(user_id: (1..10_000)).size
+=> 1215178
+```
+
+This happens because built relation is translated into following query
+
+```ruby
+[ gstg ] production> puts Ci::Build.where(user_id: (1..10_000)).to_sql
+SELECT "ci_builds".* FROM "ci_builds" WHERE "ci_builds"."type" = 'Ci::Build' AND "ci_builds"."user_id" BETWEEN 1 AND 10000
+=> nil
+```
+
+And queries which filters non-unique column by range `WHERE "ci_builds"."user_id" BETWEEN ? AND ?`, even though the range size is limited to certain threshold (`10,000` in previous example) this threshold does not translates to the size of returned dataset. That happens because when taking `n` possible values of attributes,
+one can't tell for sure that the number of records that contains them will be less than `n`.
+
## Column definition
`EachBatch` uses the primary key of the model by default for the iteration. This works most of the cases, however in some cases, you might want to use a different column for the iteration.
@@ -55,7 +78,7 @@ end
The query above iterates over the project creators and prints them out without duplications.
NOTE:
-In case the column is not unique (no unique index definition), calling the `distinct` method on the relation is necessary.
+In case the column is not unique (no unique index definition), calling the `distinct` method on the relation is necessary. Using not unique column without `distinct` may result in `each_batch` falling into endless loop as described at following [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/285097)
## `EachBatch` in data migrations
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 8cdfbd558ca..e1205346585 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -516,12 +516,14 @@ class MyMigration < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
+ INDEX_NAME = 'index_name'
+
def up
- add_concurrent_index :table, :column
+ add_concurrent_index :table, :column, name: INDEX_NAME
end
def down
- remove_concurrent_index :table, :column, name: index_name
+ remove_concurrent_index :table, :column, name: INDEX_NAME
end
end
```
diff --git a/doc/development/new_fe_guide/development/accessibility.md b/doc/development/new_fe_guide/development/accessibility.md
index 81f3773dd5c..65485104efe 100644
--- a/doc/development/new_fe_guide/development/accessibility.md
+++ b/doc/development/new_fe_guide/development/accessibility.md
@@ -42,7 +42,7 @@ In forms we should use the `for` attribute in the label statement:
## Testing
-1. On MacOS you can use [VoiceOver](http://www.apple.com/accessibility/vision/) by pressing `cmd+F5`.
+1. On MacOS you can use [VoiceOver](https://www.apple.com/accessibility/vision/) by pressing `cmd+F5`.
1. On Windows you can use [Narrator](https://www.microsoft.com/en-us/accessibility/windows) by pressing Windows logo key + Control + Enter.
## Online resources
diff --git a/doc/development/packages.md b/doc/development/packages.md
index 689dc6b4141..aadd71c9ffa 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -242,6 +242,24 @@ create the package record. Workhorse provides a variety of file metadata such as
For testing purposes, you may want to [enable object storage](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/object_storage.md)
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.
+
+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
+expanded package rate limit.
+
+These route prefixes guarantee a higher rate limit:
+
+```plaintext
+/api/v4/packages/
+/api/v4/projects/:project_id/packages/
+/api/v4/groups/:group_id/-/packages/
+```
+
### Future Work
While working on the MVC, contributors might find features that are not mandatory for the MVC but can provide a better user experience. It's generally a good idea to keep an eye on those and open issues.
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 3243c7ec753..0354e703357 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -60,7 +60,7 @@ Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/135236627>
```mermaid
graph LR
subgraph "No needed jobs";
- 1-1["danger-review (3.5 minutes)"];
+ 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"
@@ -76,23 +76,23 @@ graph RL;
classDef criticalPath fill:#f66;
subgraph "No needed jobs";
- 1-1["danger-review (3.5 minutes)"];
+ 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-2["build-qa-image (2.4 minutes)"];
+ 1-2["build-qa-image (1.6 minutes)"];
click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0"
- 1-3["compile-test-assets (8.5 minutes)"];
+ 1-3["compile-test-assets (7 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
- 1-4["compile-test-assets as-if-foss (8.35 minutes)"];
+ 1-4["compile-test-assets as-if-foss (7 minutes)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
1-5["compile-production-assets (19 minutes)"];
click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0"
- 1-6["setup-test-env (7.4 minutes)"];
+ 1-6["setup-test-env (9 minutes)"];
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
1-7["review-stop-failed-deployment"];
1-8["dependency_scanning"];
1-9["qa:internal, qa:internal-as-if-foss"];
1-11["qa:selectors, qa:selectors-as-if-foss"];
- 1-14["retrieve-tests-metadata (1.9 minutes)"];
+ 1-14["retrieve-tests-metadata (1 minutes)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
1-15["code_quality"];
1-16["brakeman-sast"];
@@ -100,7 +100,7 @@ graph RL;
1-18["kubesec-sast"];
1-19["nodejs-scan-sast"];
1-20["secrets-sast"];
- 1-21["static-analysis (17 minutes)"];
+ 1-21["static-analysis (30 minutes)"];
click 1-21 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914471&udv=0"
class 1-3 criticalPath;
@@ -111,26 +111,26 @@ graph RL;
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"
- 2_1-3["run-dev-fixtures (5 minutes)"];
+ 2_1-3["run-dev-fixtures (6 minutes)"];
click 2_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356729&udv=0"
- 2_1-4["run-dev-fixtures-ee (5 minutes)"];
+ 2_1-4["run-dev-fixtures-ee (6.75 minutes)"];
click 2_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356731&udv=0"
subgraph "Needs `setup-test-env`";
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
end
- 2_2-2["frontend-fixtures (16.5 minutes)"];
+ 2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (12 minutes)"];
class 2_2-2 criticalPath;
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
- 2_2-4["memory-on-boot (7.19 minutes)"];
+ 2_2-4["memory-on-boot (6 minutes)"];
click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0"
- 2_2-5["webpack-dev-server (6.1 minutes)"];
+ 2_2-5["webpack-dev-server (4.5 minutes)"];
click 2_2-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8404303&udv=0"
subgraph "Needs `setup-test-env` & `compile-test-assets`";
2_2-2 & 2_2-4 & 2_2-5 --> 1-6 & 1-3;
end
- 2_3-1["build-assets-image (2.5 minutes)"];
+ 2_3-1["build-assets-image (1.6 minutes)"];
subgraph "Needs `compile-production-assets`";
2_3-1 --> 1-5
end
@@ -153,17 +153,17 @@ graph RL;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
3_1-2["karma (4 minutes)"];
click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0"
- subgraph "Needs `frontend-fixtures`";
+ subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
3_1-1 & 3_1-2 --> 2_2-2;
end
- 3_2-1["rspec:coverage (7.5 minutes)"];
+ 3_2-1["rspec:coverage (4.6 minutes)"];
subgraph "Depends on `rspec` jobs";
3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1;
click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0"
end
- 4_1-1["coverage-frontend (3.6 minutes)"];
+ 4_1-1["coverage-frontend (2.75 minutes)"];
subgraph "Needs `jest`";
4_1-1 --> 3_1-1;
class 4_1-1 criticalPath;
@@ -180,23 +180,23 @@ graph RL;
classDef criticalPath fill:#f66;
subgraph "No needed jobs";
- 1-1["danger-review (3.5 minutes)"];
+ 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-2["build-qa-image (2.4 minutes)"];
+ 1-2["build-qa-image (1.6 minutes)"];
click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0"
- 1-3["compile-test-assets (8.5 minutes)"];
+ 1-3["compile-test-assets (7 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
- 1-4["compile-test-assets as-if-foss (8.35 minutes)"];
+ 1-4["compile-test-assets as-if-foss (7 minutes)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
1-5["compile-production-assets (19 minutes)"];
click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0"
- 1-6["setup-test-env (7.4 minutes)"];
+ 1-6["setup-test-env (9 minutes)"];
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
1-7["review-stop-failed-deployment"];
1-8["dependency_scanning"];
1-9["qa:internal, qa:internal-as-if-foss"];
1-11["qa:selectors, qa:selectors-as-if-foss"];
- 1-14["retrieve-tests-metadata (1.9 minutes)"];
+ 1-14["retrieve-tests-metadata (1 minutes)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
1-15["code_quality"];
1-16["brakeman-sast"];
@@ -204,7 +204,7 @@ graph RL;
1-18["kubesec-sast"];
1-19["nodejs-scan-sast"];
1-20["secrets-sast"];
- 1-21["static-analysis (17 minutes)"];
+ 1-21["static-analysis (30 minutes)"];
click 1-21 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914471&udv=0"
class 1-3 criticalPath;
@@ -216,26 +216,26 @@ graph RL;
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"
- 2_1-3["run-dev-fixtures (5 minutes)"];
+ 2_1-3["run-dev-fixtures (6 minutes)"];
click 2_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356729&udv=0"
- 2_1-4["run-dev-fixtures-ee (5 minutes)"];
+ 2_1-4["run-dev-fixtures-ee (6.75 minutes)"];
click 2_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356731&udv=0"
subgraph "Needs `setup-test-env`";
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
end
- 2_2-2["frontend-fixtures (16.5 minutes)"];
+ 2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (12 minutes)"];
class 2_2-2 criticalPath;
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
- 2_2-4["memory-on-boot (7.19 minutes)"];
+ 2_2-4["memory-on-boot (6 minutes)"];
click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0"
- 2_2-5["webpack-dev-server (6.1 minutes)"];
+ 2_2-5["webpack-dev-server (4.5 minutes)"];
click 2_2-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8404303&udv=0"
subgraph "Needs `setup-test-env` & `compile-test-assets`";
2_2-2 & 2_2-4 & 2_2-5 --> 1-6 & 1-3;
end
- 2_3-1["build-assets-image (2.5 minutes)"];
+ 2_3-1["build-assets-image (1.6 minutes)"];
class 2_3-1 criticalPath;
subgraph "Needs `compile-production-assets`";
2_3-1 --> 1-5
@@ -266,17 +266,17 @@ graph RL;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
3_1-2["karma (4 minutes)"];
click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0"
- subgraph "Needs `frontend-fixtures`";
+ subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
3_1-1 & 3_1-2 --> 2_2-2;
end
- 3_2-1["rspec:coverage (7.5 minutes)"];
+ 3_2-1["rspec:coverage (4.6 minutes)"];
subgraph "Depends on `rspec` jobs";
3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1;
click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0"
end
- 4_1-1["coverage-frontend (3.6 minutes)"];
+ 4_1-1["coverage-frontend (2.75 minutes)"];
subgraph "Needs `jest`";
4_1-1 --> 3_1-1;
class 4_1-1 criticalPath;
@@ -311,23 +311,23 @@ graph RL;
classDef criticalPath fill:#f66;
subgraph "No needed jobs";
- 1-1["danger-review (3.5 minutes)"];
+ 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-2["build-qa-image (2.4 minutes)"];
+ 1-2["build-qa-image (1.6 minutes)"];
click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0"
- 1-3["compile-test-assets (8.5 minutes)"];
+ 1-3["compile-test-assets (7 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
- 1-4["compile-test-assets as-if-foss (8.35 minutes)"];
+ 1-4["compile-test-assets as-if-foss (7 minutes)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
1-5["compile-production-assets (19 minutes)"];
click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0"
- 1-6["setup-test-env (7.4 minutes)"];
+ 1-6["setup-test-env (9 minutes)"];
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
1-7["review-stop-failed-deployment"];
1-8["dependency_scanning"];
1-9["qa:internal, qa:internal-as-if-foss"];
1-11["qa:selectors, qa:selectors-as-if-foss"];
- 1-14["retrieve-tests-metadata (1.9 minutes)"];
+ 1-14["retrieve-tests-metadata (1 minutes)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
1-15["code_quality"];
1-16["brakeman-sast"];
@@ -335,7 +335,7 @@ graph RL;
1-18["kubesec-sast"];
1-19["nodejs-scan-sast"];
1-20["secrets-sast"];
- 1-21["static-analysis (17 minutes)"];
+ 1-21["static-analysis (30 minutes)"];
click 1-21 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914471&udv=0"
class 1-5 criticalPath;
@@ -347,13 +347,13 @@ graph RL;
2_1-1 --> 1-6;
end
- 2_3-1["build-assets-image (2.5 minutes)"];
+ 2_3-1["build-assets-image (1.6 minutes)"];
subgraph "Needs `compile-production-assets`";
2_3-1 --> 1-5
class 2_3-1 criticalPath;
end
- 2_4-1["package-and-qa (108 minutes)"];
+ 2_4-1["package-and-qa (105 minutes)"];
subgraph "Needs `build-qa-image` & `build-assets-image`";
2_4-1 --> 1-2 & 2_3-1;
class 2_4-1 criticalPath;
@@ -422,24 +422,29 @@ We are using a custom mapping between source file to test files, maintained in t
### PostgreSQL versions testing
+Even though [Omnibus defaults to PG12 for new installs and upgrades](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.md),
+our test suite is currently running against PG11, since GitLab.com still runs on PG11.
+
+We do run our test suite against PG12 on nightly scheduled pipelines as well as upon specific
+database library changes in MRs and `master` pipelines (with the `rspec db-library-code pg12` job).
+
#### Current versions testing
| Where? | PostgreSQL version |
-| ------ | ------ |
-| MRs | 11 |
-| `master` (non-scheduled pipelines) | 11 |
-| 2-hourly scheduled pipelines | 11 |
+| ------ | ------------------ |
+| MRs | 11, 12 for DB library changes |
+| `master` (non-scheduled pipelines) | 11, 12 for DB library changes |
+| 2-hourly scheduled pipelines | 11, 12 for DB library changes |
| `nightly` scheduled pipelines | 11, 12 |
#### Long-term plan
We follow the [PostgreSQL versions shipped with Omnibus GitLab](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.html):
-| PostgreSQL version | 13.0 (May 2020) | 13.1 (June 2020) | 13.2 (July 2020) | 13.3 (August 2020) | 13.4, 13.5 | [13.7 (December 2020)](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5722) | 14.0 (May 2021?) |
-| ------ | --------------- | ---------------- | ---------------- | ------------------ | ------------ | -------------------- | ---------------- |
-| PG11 | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | `nightly` | - |
-| PG12 | - | - | `nightly` | `2-hour`/`nightly` | `2-hour`/`nightly` | MRs/`2-hour`/`nightly` | `2-hour`/`nightly` |
-| PG13 | - | - | - | - | - | - | MRs/`2-hour`/`nightly` |
+| PostgreSQL version | 13.7 (December 2020) | 13.8 (January 2021) | 13.9 (February 2021) | 13.10 (March 2021) | 13.11 (April 2021) | 14.0 (May 2021?) |
+| -------------------| -------------------- | ------------------- | -------------------- | ------------------ | ------------------ | ---------------- |
+| PG11 | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` |
+| PG12 | `nightly` | `nightly` | `nightly` | `nightly` | `nightly` | `nightly` |
### Test jobs
@@ -504,6 +509,10 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
- `update-yarn-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
1. These jobs run in merge requests whose title include `UPDATE CACHE`.
+### Artifacts strategy
+
+We limit the artifacts that are saved and retrieved by jobs to the minimum in order to reduce the upload/download time and costs, as well as the artifacts storage.
+
### Pre-clone step
The `gitlab-org/gitlab` project on GitLab.com uses a [pre-clone step](https://gitlab.com/gitlab-org/gitlab/-/issues/39134)
@@ -671,7 +680,7 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch
| `if-master-refs` | Matches if the current branch is `master`. | |
| `if-master-push` | Matches if the current branch is `master` and pipeline source is `push`. | |
| `if-master-schedule-2-hourly` | Matches if the current branch is `master` and pipeline runs on a 2-hourly schedule. | |
-| `if-master-schedule-2-nightly` | Matches if the current branch is `master` and pipeline runs on a nightly schedule. | |
+| `if-master-schedule-nightly` | Matches if the current branch is `master` and pipeline runs on a nightly schedule. | |
| `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | |
| `if-master-or-tag` | Matches if the pipeline is for the `master` branch or for a tag. | |
| `if-merge-request` | Matches if the pipeline is for a merge request. | |
diff --git a/doc/development/product_analytics/event_dictionary.md b/doc/development/product_analytics/event_dictionary.md
index 9c363f08cb4..e8b8e0c4885 100644
--- a/doc/development/product_analytics/event_dictionary.md
+++ b/doc/development/product_analytics/event_dictionary.md
@@ -1,8 +1,8 @@
---
-redirect_to: 'https://about.gitlab.com/handbook/product/product-analytics-guide/'
+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-analytics-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. -->
+<!-- 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/index.md b/doc/development/product_analytics/index.md
index 9c363f08cb4..4d2168cf304 100644
--- a/doc/development/product_analytics/index.md
+++ b/doc/development/product_analytics/index.md
@@ -1,8 +1,13 @@
---
-redirect_to: 'https://about.gitlab.com/handbook/product/product-analytics-guide/'
+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-analytics-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. -->
+<!-- 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 48b816f0b83..bb056ffddfe 100644
--- a/doc/development/product_analytics/snowplow.md
+++ b/doc/development/product_analytics/snowplow.md
@@ -1,616 +1,8 @@
---
-stage: Growth
-group: Product Analytics
-info: To 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: '../snowplow.md'
---
-# Snowplow Guide
+This document was moved to [another location](../snowplow.md).
-This guide provides an overview of how Snowplow works, and implementation details.
-
-For more information about Product Analytics, see:
-
-- [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
-- [Usage Ping Guide](usage_ping.md)
-
-More useful links:
-
-- [Product Analytics Direction](https://about.gitlab.com/direction/product-analytics/)
-- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
-- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
-- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
-
-## What is Snowplow
-
-Snowplow is an enterprise-grade marketing and product analytics platform which helps track the way users engage with our website and application.
-
-[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems:
-
-- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT.
-- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis.
-- **Enrich** cleans up the raw Snowplow events, enriches them and puts them into storage. We have an Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process.
-- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases.
-- **Data modeling** is where event-level data is joined with other data sets and aggregated into smaller data sets, and business logic is applied. This produces a clean set of tables which make it easier to perform analysis on the data. We have data models for Redshift and Looker.
-- **Analytics** are performed on the Snowplow events or on the aggregate tables.
-
-![snowplow_flow](../img/snowplow_flow.png)
-
-## Snowplow schema
-
-We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions:
-
-- Frontend and backend taxonomy as listed below
-- [Structured event taxonomy](#structured-event-taxonomy)
-- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events)
-- [Iglu schema](https://gitlab.com/gitlab-org/iglu/)
-- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events)
-
-## Enabling Snowplow
-
-Tracking can be enabled at:
-
-- The instance level, which enables tracking on both the frontend and backend layers.
-- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
-
-We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
-
-- **Admin Area > Settings > General** in the UI.
-- `admin/application_settings/integrations` in your browser.
-
-The following configuration is required:
-
-| Name | Value |
-|---------------|---------------------------|
-| Collector | `snowplow.trx.gitlab.net` |
-| Site ID | `gitlab` |
-| Cookie domain | `.gitlab.com` |
-
-## Snowplow request flow
-
-The following example shows a basic request/response flow between the following components:
-
-- Snowplow JS / Ruby Trackers on GitLab.com
-- [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md)
-- The GitLab S3 Bucket
-- The GitLab Snowflake Data Warehouse
-- Sisense:
-
-```mermaid
-sequenceDiagram
- participant Snowplow JS (Frontend)
- participant Snowplow Ruby (Backend)
- participant GitLab.com Snowplow Collector
- participant S3 Bucket
- participant Snowflake DW
- participant Sisense Dashboards
- Snowplow JS (Frontend) ->> GitLab.com Snowplow Collector: FE Tracking event
- Snowplow Ruby (Backend) ->> GitLab.com Snowplow Collector: BE Tracking event
- loop Process using Kinesis Stream
- GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Log raw events
- GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Enrich events
- GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk
- end
- GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose
- S3 Bucket->>Snowflake DW: Import data
- Snowflake DW->>Snowflake DW: Transform data using dbt
- Snowflake DW->>Sisense Dashboards: Data available for querying
-```
-
-## Structured event taxonomy
-
-When adding new click events, we should add them in a way that's internally consistent. If we don't, it is very painful to perform analysis across features since each feature captures events differently.
-
-The current method provides several attributes that are sent on each click event. Please try to follow these guidelines when specifying events to capture:
-
-| 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. |
-| 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. |
-| 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). |
-
-### Web-specific parameters
-
-Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
-
-## Implementing Snowplow JS (Frontend) tracking
-
-GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. There are a few ways to use tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy).
-
-| field | type | default value | description |
-|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `category` | string | document.body.dataset.page | Page or subsection of a page that events are being captured within. |
-| `action` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
-| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-
-### Tracking in HAML (or Vue Templates)
-
-When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-event` attribute automatically have event tracking bound on clicks.
-
-Below is an example of `data-track-*` attributes assigned to a button:
-
-```haml
-%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } }
-```
-
-```html
-<button class="btn"
- data-track-event="click_button"
- data-track-label="template_preview"
- data-track-property="my-template"
-/>
-```
-
-Event listeners are bound at the document level to handle click events on or within elements with these data attributes. This allows them to be properly handled on re-rendering and changes to the DOM. Note that because of the way these events are bound, click events should not be stopped from propagating up the DOM tree. If for any reason click events are being stopped from propagating, you need to implement your own listeners and follow the instructions in [Tracking in raw JavaScript](#tracking-in-raw-javascript).
-
-Below is a list of supported `data-track-*` attributes:
-
-| attribute | required | description |
-|:----------------------|:---------|:------------|
-| `data-track-event` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. |
-| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. |
-| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-
-#### Caveats
-
-When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/898b286de322e5df6a38d257b10c94974d580df8/app/helpers/tab_helper.rb#L69) be sure to wrap `html_options` under the `html_options` keyword argument.
-Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options`
-
-`nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "groups_dropdown", track_event: "click_dropdown" } })`
-
-vs
-
-`link_to assigned_issues_dashboard_path, title: _('Issues'), data: { track_label: 'main_navigation', track_event: 'click_issues_link' }`
-
-### Tracking within Vue components
-
-There's a tracking Vue mixin that can be used in components if more complex tracking is required. To use it, first import the `Tracking` library and request a mixin.
-
-```javascript
-import Tracking from '~/tracking';
-const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
-```
-
-You can provide default options that are passed along whenever an event is tracked from within your component. For instance, if all events within a component should be tracked with a given `label`, you can provide one at this time. Available defaults are `category`, `label`, `property`, and `value`. If no category is specified, `document.body.dataset.page` is used as the default.
-
-You can then use the mixin normally in your component with the `mixin` Vue declaration. The mixin also provides the ability to specify tracking options in `data` or `computed`. These override any defaults and allow the values to be dynamic from props, or based on state.
-
-```javascript
-export default {
- mixins: [trackingMixin],
- // ...[component implementation]...
- data() {
- return {
- expanded: false,
- tracking: {
- label: 'left_sidebar'
- }
- };
- },
-}
-```
-
-The mixin provides a `track` method that can be called within the template, or from component methods. An example of the whole implementation might look like the following.
-
-```javascript
-export default {
- mixins: [Tracking.mixin({ label: 'right_sidebar' })],
- data() {
- return {
- expanded: false,
- };
- },
- methods: {
- toggle() {
- this.expanded = !this.expanded;
- this.track('click_toggle', { value: this.expanded })
- }
- }
-};
-```
-
-And if needed within the template, you can use the `track` method directly as well.
-
-```html
-<template>
- <div>
- <a class="toggle" @click.prevent="toggle">Toggle</a>
- <div v-if="expanded">
- <p>Hello world!</p>
- <a @click.prevent="track('click_action')">Track an event</a>
- </div>
- </div>
-</template>
-```
-
-### Tracking in raw JavaScript
-
-Custom event tracking and instrumentation can be added by directly calling the `Tracking.event` static function. The following example demonstrates tracking a click on a button by calling `Tracking.event` manually.
-
-```javascript
-import Tracking from '~/tracking';
-
-const button = document.getElementById('create_from_template_button');
-button.addEventListener('click', () => {
- Tracking.event('dashboard:projects:index', 'click_button', {
- label: 'create_from_template',
- property: 'template_preview',
- value: 'rails',
- });
-})
-```
-
-### Tests and test helpers
-
-In Jest particularly in Vue tests, you can use the following:
-
-```javascript
-import { mockTracking } from 'helpers/tracking_helper';
-
-describe('MyTracking', () => {
- let spy;
-
- beforeEach(() => {
- spy = mockTracking('_category_', wrapper.element, jest.spyOn);
- });
-
- it('tracks an event when clicked on feedback', () => {
- wrapper.find('.discover-feedback-icon').trigger('click');
-
- expect(spy).toHaveBeenCalledWith('_category_', 'click_button', {
- label: 'security-discover-feedback-cta',
- property: '0',
- });
- });
-});
-```
-
-In obsolete Karma tests it's used as below:
-
-```javascript
-import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
-
-describe('my component', () => {
- let trackingSpy;
-
- beforeEach(() => {
- trackingSpy = mockTracking('_category_', vm.$el, spyOn);
- });
-
- const triggerEvent = () => {
- // action which should trigger a event
- };
-
- it('tracks an event when toggled', () => {
- expect(trackingSpy).not.toHaveBeenCalled();
-
- triggerEvent('a.toggle');
-
- expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
- label: 'right_sidebar',
- property: 'confidentiality',
- });
- });
-});
-```
-
-## Implementing Snowplow Ruby (Backend) tracking
-
-GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events.
-
-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. |
-
-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.
-
-For example:
-
-```ruby
-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?
- )
- end
-end
-```
-
-### Unit testing
-
-Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices](
-https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details.
-
-### Performance
-
-We use the [AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development.
-
-## Developing and testing Snowplow
-
-There are several tools for developing and testing Snowplow Event
-
-| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment |
-|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------|
-| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
-| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
-| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** |
-| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** |
-
-**Legend**
-
-**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned
-
-### Preparing your MR for Review
-
-1. For frontend events, in the MR description section, add a screenshot of the event's relevant section using the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
-1. For backend events, please use Snowplow Micro and add the output of the Snowplow Micro good events `GET http://localhost:9090/micro/good`.
-
-### Snowplow Analytics Debugger Chrome Extension
-
-Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments.
-
-1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
-1. Open Chrome DevTools to the Snowplow Analytics Debugger tab.
-1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html).
-
-### Snowplow Inspector Chrome Extension
-
-Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments.
-
-1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en).
-1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar.
-1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window.
-
-### Snowplow Micro
-
-Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried.
-
-Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You need to modify GDK using the instructions below to set this up.
-
-- 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)
-
-1. Ensure Docker is installed and running.
-
-1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration):
-1. Navigate to the directory with the cloned project, and start the appropriate Docker
- container with the following script:
-
- ```shell
- ./snowplow-micro.sh
- ```
-
-1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector:
-
- ```shell
- gdk psql -d gitlabhq_development
- update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com';
- ```
-
-1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking.js` to remove `forceSecureTracker: true`:
-
- ```diff
- diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
- index 0a1211d0a76..3b98c8f28f2 100644
- --- a/app/assets/javascripts/tracking.js
- +++ b/app/assets/javascripts/tracking.js
- @@ -7,7 +7,6 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
- appId: '',
- userFingerprint: false,
- respectDoNotTrack: true,
- - forceSecureTracker: true,
- eventMethod: 'post',
- contexts: { webPage: true, performanceTiming: true },
- formTracking: false,
-
- ```
-
-1. Update `snowplow_options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`:
-
- ```diff
- diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
- index 618e359211b..e9084623c43 100644
- --- a/lib/gitlab/tracking.rb
- +++ b/lib/gitlab/tracking.rb
- @@ -41,7 +41,9 @@ def snowplow_options(group)
- cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
- app_id: Gitlab::CurrentSettings.snowplow_app_id,
- form_tracking: additional_features,
- - link_click_tracking: additional_features
- + link_click_tracking: additional_features,
- + protocol: 'http',
- + port: 9090
- }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
- end
- ```
-
-1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`:
-
- ```diff
- diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
- index 4fa844de325..5dd9d0eacfb 100644
- --- a/lib/gitlab/tracking/destinations/snowplow.rb
- +++ b/lib/gitlab/tracking/destinations/snowplow.rb
- @@ -40,7 +40,7 @@ def tracker
- def emitter
- SnowplowTracker::AsyncEmitter.new(
- Gitlab::CurrentSettings.snowplow_collector_hostname,
- - protocol: 'https'
- + protocol: 'http'
- )
- end
- end
-
- ```
-
-1. Restart GDK:
-
- ```shell
- `gdk restart`
- ```
-
-1. Send a test Snowplow event from the Rails console:
-
- ```ruby
- Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', data: { page_type: 'MY_TYPE' }, context: nil)
- ```
-
-1. Navigate to `localhost:9090/micro/good` to see the event.
-
-### Snowplow Mini
-
-[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow.
-
-Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment.
-
-For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
-
-## Snowplow Schemas
-
-### 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 |
+<!-- 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/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md
index 37363bbabbc..5fbdb508bb1 100644
--- a/doc/development/product_analytics/usage_ping.md
+++ b/doc/development/product_analytics/usage_ping.md
@@ -1,1059 +1,8 @@
---
-stage: Growth
-group: Product Analytics
-info: To 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: '../usage_ping.md'
---
-# Usage Ping Guide
+This document was moved to [another location](../usage_ping.md).
-> - 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.
-
-This guide describes Usage Ping's purpose and how it's implemented.
-
-For more information about Product Analytics, see:
-
-- [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/)
-- [Snowplow Guide](snowplow.md)
-
-More useful links:
-
-- [Product Analytics Direction](https://about.gitlab.com/direction/product-analytics/)
-- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
-- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
-- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
-
-## What is Usage Ping?
-
-- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics.
-- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features within the product. In addition to counts, other facts
- that help us classify and understand GitLab installations are collected.
-- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features.
-- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users.
-
-### Why should we enable Usage Ping?
-
-- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions.
-- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation.
-- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring.
-- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value)
-- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization?
-- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes.
-- Usage Ping is enabled by default. To disable it, see [Disable Usage Ping](#disable-usage-ping).
-
-### Limitations
-
-- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events.
-- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed.
-
-## Usage Ping payload
-
-You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload:
-
-1. Navigate to **Admin Area > Settings > Metrics and profiling**.
-1. Expand the **Usage statistics** section.
-1. Click the **Preview payload** button.
-
-For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload).
-
-## Disable Usage Ping
-
-To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox.
-
-To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
-
-```ruby
-gitlab_rails['usage_ping_enabled'] = false
-```
-
-Source installations can set the following in `gitlab.yml`:
-
-```yaml
-production: &base
- # ...
- gitlab:
- # ...
- usage_ping_enabled: false
-```
-
-## Usage Ping request flow
-
-The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, the GitLab S3 Bucket, the GitLab Snowflake Data Warehouse, and Sisense:
-
-```mermaid
-sequenceDiagram
- participant GitLab Instance
- participant Versions Application
- participant Licenses Application
- participant Salesforce
- participant S3 Bucket
- participant Snowflake DW
- participant Sisense Dashboards
- GitLab Instance->>Versions Application: Send Usage Ping
- loop Process usage data
- Versions Application->>Versions Application: Parse usage data
- Versions Application->>Versions Application: Write to database
- Versions Application->>Versions Application: Update license ping time
- end
- loop Process data for Salesforce
- Versions Application-xLicenses Application: Request Zuora subscription id
- Licenses Application-xVersions Application: Zuora subscription id
- Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id
- Salesforce-xVersions Application: Zuora account id
- Versions Application-xSalesforce: Usage data for the Zuora account
- end
- Versions Application->>S3 Bucket: Export Versions database
- S3 Bucket->>Snowflake DW: Import data
- Snowflake DW->>Snowflake DW: Transform data using dbt
- Snowflake DW->>Sisense Dashboards: Data available for querying
- Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index)
-```
-
-## How Usage Ping works
-
-1. The Usage Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30) is set in Sidekiq to run weekly.
-1. When the cron job runs, it calls [`GitLab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22).
-1. `GitLab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls.
-1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `GitLab::UsageData.to_json`.
-1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20)
- If a firewall exception is needed, the required URL depends on several things. If
- the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`,
- the required URL is <https://version.gitlab.com/>.
-
-## Implementing Usage Ping
-
-Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event
-happened over time, such as how many CI pipelines have run. They are monotonic and always trend up.
-Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no
-general guidelines around how to collect those, due to the individual nature of that data.
-
-There are several types of counters which are all found in `usage_data.rb`:
-
-- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation
-- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation on given column
-- **Sum Batch Counters:** Sum the values of a given ActiveRecord_Relation on given column
-- **Alternative Counters:** Used for settings and configurations
-- **Redis Counters:** Used for in-memory counts.
-
-NOTE:
-Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping.
-
-### Why batch counting
-
-For large tables, PostgreSQL can take a long time to count rows due to MVCC [(Multi-version Concurrency Control)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control). Batch counting is a counting method where a single large query is broken into multiple smaller queries. For example, instead of a single query querying 1,000,000 records, with batch counting, you can execute 100 queries of 10,000 records each. Batch counting is useful for avoiding database timeouts as each batch query is significantly shorter than one single long running query.
-
-For GitLab.com, there are extremely large tables with 15 second query timeouts, so we use batch counting to avoid encountering timeouts. Here are the sizes of some GitLab.com tables:
-
-| Table | Row counts in millions |
-|------------------------------|------------------------|
-| `merge_request_diff_commits` | 2280 |
-| `ci_build_trace_sections` | 1764 |
-| `merge_request_diff_files` | 1082 |
-| `events` | 514 |
-
-There are two batch counting methods provided, `Ordinary Batch Counters` and `Distinct Batch Counters`. Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases, a specialized index may need to be added on the columns involved in a counter.
-
-### Ordinary Batch Counters
-
-Handles `ActiveRecord::StatementInvalid` error
-
-Simple count of a given ActiveRecord_Relation, does a non-distinct batch count, smartly reduces batch_size and handles errors.
-
-Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)`
-
-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
-
-Examples:
-
-```ruby
-count(User.active)
-count(::Clusters::Cluster.aws_installed.enabled, :cluster_id)
-count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id))
-```
-
-### Distinct Batch Counters
-
-Handles `ActiveRecord::StatementInvalid` error
-
-Distinct count of a given ActiveRecord_Relation on given column, a distinct batch count, smartly reduces batch_size and handles errors.
-
-Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)`
-
-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_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
-
-Examples:
-
-```ruby
-distinct_count(::Project, :creator_id)
-distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id))
-distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id')
-```
-
-### Sum Batch Counters
-
-Handles `ActiveRecord::StatementInvalid` error
-
-Sum the values of a given ActiveRecord_Relation on given column and handles errors.
-
-Method: `sum(relation, column, batch_size: nil, start: nil, finish: nil)`
-
-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
-
-Examples:
-
-```ruby
-sum(JiraImportState.finished, :imported_issues_count)
-```
-
-### Grouping & Batch Operations
-
-The `count`, `distinct_count`, and `sum` batch counters can accept an `ActiveRecord::Relation`
-object, which groups by a specified column. With a grouped relation, the methods do batch counting,
-handle errors, and returns a hash table of key-value pairs.
-
-Examples:
-
-```ruby
-count(Namespace.group(:type))
-# returns => {nil=>179, "Group"=>54}
-
-distinct_count(Project.group(:visibility_level), :creator_id)
-# returns => {0=>1, 10=>1, 20=>11}
-
-sum(Issue.group(:state_id), :weight))
-# returns => {1=>3542, 2=>6820}
-```
-
-### Redis Counters
-
-Handles `::Redis::CommandError` and `Gitlab::UsageDataCounters::BaseCounter::UnknownEvent`
-returns -1 when a block is sent or hash with all values -1 when a `counter(Gitlab::UsageDataCounters)` is sent
-different behavior due to 2 different implementations of Redis counter
-
-Method: `redis_usage_data(counter, &block)`
-
-Arguments:
-
-- `counter`: a counter from `Gitlab::UsageDataCounters`, that has `fallback_totals` method implemented
-- or a `block`: which is evaluated
-
-#### Ordinary Redis Counters
-
-Examples of implementation:
-
-- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb)
-- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb)
-
-##### UsageData API Tracking
-
-<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. -->
-
-1. Track event using `UsageData` API
-
- Increment event count using ordinary Redis counter, for given event name.
-
- Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default.
-
- 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.
-
- ```plaintext
- POST /usage_data/increment_counter
- ```
-
- | Attribute | Type | Required | Description |
- | :-------- | :--- | :------- | :---------- |
- | `event` | string | yes | The event name it should be tracked |
-
- Response
-
- - `200` if event was tracked
- - `400 Bad request` if event parameter is missing
- - `401 Unauthorized` if user is not authenticated
- - `403 Forbidden` for invalid CSRF token provided
-
-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
-
- ```javascript
- import api from '~/api';
-
- api.trackRedisCounterEvent('my_already_defined_event_name'),
- ```
-
-#### Redis HLL Counters
-
-With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values.
-
-Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount).
-
-##### Adding new events
-
-1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/).
-
- Example event:
-
- ```yaml
- - name: i_compliance_credential_inventory
- category: compliance
- redis_slot: compliance
- expiry: 42 # 6 weeks
- aggregation: weekly
- ```
-
- Keys:
-
- - `name`: unique event name.
-
- Name format `<prefix>_<redis_slot>_name`.
-
- Use one of the following prefixes for the event's name:
-
- - `g_` for group, as an event which is tracked for group.
- - `p_` for project, as an event which is tracked for project.
- - `i_` for instance, as an event which is tracked for instance.
- - `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.
-
- Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`.
-
- - `category`: event category. Used for getting total counts for events in a category, for easier
- access to a group of events.
- - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals
- for a group of metrics. Ensure keys are in the same slot. For example:
- `i_compliance_credential_inventory` with `redis_slot: 'compliance'` builds Redis key
- `i_{compliance}_credential_inventory-2020-34`. If `redis_slot` is not defined the Redis key will
- be `{i_compliance_credential_inventory}-2020-34`.
- - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly
- 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.
-
-1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`.
-
- 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.
-
- Example usage:
-
- ```ruby
- # controller
- class ProjectsController < Projects::ApplicationController
- 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
-
- def index
- render html: 'index'
- end
-
- def new
- render html: 'new'
- end
-
- def show
- render html: 'show'
- end
- end
- ```
-
-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.
-
- Arguments:
-
- - `event_name`: event name.
- - `values`: values counted, one value or array of values.
-
- Example usage:
-
- ```ruby
- get ':id/registry/repositories' do
- repositories = ContainerRepositoriesFinder.new(
- user: current_user, subject: user_group
- ).execute
-
- increment_unique_values('i_list_repositories', current_user.id)
-
- present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count]
- end
- ```
-
-1. Track event using `track_usage_event(event_name, values) in services and graphql
-
- Increment unique values count using Redis HLL, for given event name.
-
- 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 graphql](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/alert_management/update_alert_status.rb)
-
- ```ruby
- track_usage_event(:incident_management_incident_created, current_user.id)
- ```
-
-<!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. -->
-
-1. Track event using `UsageData` API
-
- Increment unique users count using Redis HLL, for given event name.
-
- Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default.
-
- 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
- set to `default_enabled: true`. For more information, see
- [Feature flags in development of GitLab](../feature_flags/index.md).
-
- ```plaintext
- POST /usage_data/increment_unique_users
- ```
-
- | Attribute | Type | Required | Description |
- | :-------- | :--- | :------- | :---------- |
- | `event` | string | yes | The event name it should be tracked |
-
- Response
-
- Return 200 if tracking failed for any reason.
-
- - `200` if event was tracked or any errors
- - `400 Bad request` if event parameter is missing
- - `401 Unauthorized` if user is not authenticated
- - `403 Forbidden` for invalid CSRF token provided
-
-1. Track events using JavaScript/Vue API helper which calls the API above
-
- Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/):
-
- Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is
- now set to `default_enabled: true`.
-
- Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true`
-
- ```javascript
- import api from '~/api';
-
- api.trackRedisHllUserEvent('my_already_defined_event_name'),
- ```
-
-1. Track event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name)`.
-
- Arguments:
-
- - `values`: One value or array of values we count. For example: user_id, visitor_id, user_ids.
- - `event_name`: event name.
-
-1. Track event on context level using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event_in_context(entity_id, event_name, context)`.
-
- Arguments:
-
- - `entity_id`: value we count. For example: user_id, visitor_id.
- - `event_name`: event name.
- - `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:
-
- - `event_names`: the list of event names.
- - `start_date`: start date of the period for which we want to get event data.
- - `end_date`: end date of the period for which we want to get event data.
- - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`.
-
-1. Testing tracking and getting unique events
-
-Trigger events in rails console by using `track_event` method
-
- ```ruby
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(1, 'g_compliance_audit_events')
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(2, 'g_compliance_audit_events')
- ```
-
-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)
- ```
-
-##### Recommendations
-
-We have the following recommendations for [Adding new events](#adding-new-events):
-
-- Event aggregation: weekly.
-- Key expiry time:
- - Daily: 29 days.
- - Weekly: 42 days.
-- When adding new metrics, use a [feature flag](../../operations/feature_flags.md) to control the impact.
-- For feature flags triggered by another service, set `default_enabled: false`,
- - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change
-
-##### Enable/Disable Redis HLL tracking
-
-Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability.
-
-For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files.
-
-To enable or disable tracking for specific event within <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to
-[enable or disable the corresponding feature](../feature_flags/index.md).
-
-```shell
-/chatops run feature set <feature_name> true
-/chatops run feature set <feature_name> false
-```
-
-##### Known events in usage data payload
-
-All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209).
-For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable:
-
-- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events.
-- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events.
-- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric.
-- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric.
-
-Example of `redis_hll_counters` data:
-
-```ruby
-{:redis_hll_counters=>
- {"compliance"=>
- {"g_compliance_dashboard_weekly"=>0,
- "g_compliance_dashboard_monthly"=>0,
- "g_compliance_audit_events_weekly"=>0,
- "g_compliance_audit_events_monthly"=>0,
- "compliance_total_unique_counts_weekly"=>0,
- "compliance_total_unique_counts_monthly"=>0},
- "analytics"=>
- {"g_analytics_contribution_weekly"=>0,
- "g_analytics_contribution_monthly"=>0,
- "g_analytics_insights_weekly"=>0,
- "g_analytics_insights_monthly"=>0,
- "analytics_total_unique_counts_weekly"=>0,
- "analytics_total_unique_counts_monthly"=>0},
- "ide_edit"=>
- {"g_edit_by_web_ide_weekly"=>0,
- "g_edit_by_web_ide_monthly"=>0,
- "g_edit_by_sfe_weekly"=>0,
- "g_edit_by_sfe_monthly"=>0,
- "ide_edit_total_unique_counts_weekly"=>0,
- "ide_edit_total_unique_counts_monthly"=>0},
- "search"=>
- {"i_search_total_weekly"=>0, "i_search_total_monthly"=>0, "i_search_advanced_weekly"=>0, "i_search_advanced_monthly"=>0, "i_search_paid_weekly"=>0, "i_search_paid_monthly"=>0, "search_total_unique_counts_weekly"=>0, "search_total_unique_counts_monthly"=>0},
- "source_code"=>{"wiki_action_weekly"=>0, "wiki_action_monthly"=>0}
- }
-```
-
-Example usage:
-
-```ruby
-# Redis Counters
-redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
-redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
-
-# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml
-
-# Tracking events
-Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, 'expand_vulnerabilities')
-
-# Get unique events for metric
-redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'expand_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) }
-```
-
-### Alternative Counters
-
-Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception.
-Mainly used for settings and configurations.
-
-Method: `alt_usage_data(value = nil, fallback: -1, &block)`
-
-Arguments:
-
-- `value`: a simple static value in which case the value is simply returned.
-- or a `block`: which is evaluated
-- `fallback: -1`: the common value used for any metrics that are failing.
-
-Example of usage:
-
-```ruby
-alt_usage_data { Gitlab::VERSION }
-alt_usage_data { Gitlab::CurrentSettings.uuid }
-alt_usage_data(999)
-```
-
-### Prometheus Queries
-
-In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely
-to provide useful data. Instead, Prometheus might be more appropriate, since most GitLab architectural
-components publish metrics to it that can be queried back, aggregated, and included as usage data.
-
-NOTE:
-Prometheus as a data source for Usage Ping is currently only available for single-node Omnibus installations
-that are running the [bundled Prometheus](../../administration/monitoring/prometheus/index.md) instance.
-
-To query Prometheus for metrics, a helper method is available to `yield` a fully configured
-`PrometheusClient`, given it is available as per the note above:
-
-```ruby
-with_prometheus_client do |client|
- response = client.query('<your query>')
- ...
-end
-```
-
-Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb)
-for how to use its API to query for data.
-
-## Developing and testing Usage Ping
-
-### 1. Naming and placing the metrics
-
-Add the metric in one of the top level keys
-
-- `license`: for license related metrics.
-- `settings`: for settings related metrics.
-- `counts_weekly`: for counters that have data for the most recent 7 days.
-- `counts_monthly`: for counters that have data for the most recent 28 days.
-- `counts`: for counters that have data for all time.
-
-### 2. Use your Rails console to manually test counters
-
-```ruby
-# count
-Gitlab::UsageData.count(User.active)
-Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id)
-
-# count distinct
-Gitlab::UsageData.distinct_count(::Project, :creator_id)
-Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id))
-```
-
-### 3. Generate the SQL query
-
-Your Rails console returns the generated SQL queries.
-
-Example:
-
-```ruby
-pry(main)> Gitlab::UsageData.count(User.active)
- (2.6ms) SELECT "features"."key" FROM "features"
- (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4))
- (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4))
- (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000
-```
-
-### 4. Optimize queries with #database-lab
-
-Paste the SQL query into `#database-lab` to see how the query performs at scale.
-
-- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries.
-- GitLab.com’s production database has a 15 second timeout.
-- 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:
-
-- For counters that have a `time_period` test we add information for both cases:
- - `time_period = {}` for all time periods
- - `time_period = { created_at: 28.days.ago..Time.current }` for last 28 days period
-- Execution plan and query time before and after optimization
-- Query generated for the index and time
-- Migration output for up and down execution
-
-We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/). For more details, see the [database review guide](../database_review.md#preparation-when-adding-or-modifying-queries).
-
-#### Optimization recommendations and examples
-
-- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445).
-- Use defined `start` and `finish`, and simple queries, because these values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155).
-- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316).
-- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000).
-
-### 5. Add the metric definition
-
-When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary).
-
-### 6. Add new metric to Versions Application
-
-Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column.
-
-### 7. Add the feature label
-
-Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature.
-
-### 8. Add a changelog file
-
-Ensure you comply with the [Changelog entries guide](../changelog.md).
-
-### 9. Ask for a Product Analytics Review
-
-On GitLab.com, we have DangerBot setup to monitor Product Analytics related files and DangerBot recommends a Product Analytics review. Mention `@gitlab-org/growth/product_analytics/engineers` in your MR for a review.
-
-### 10. Verify your metric
-
-On GitLab.com, the Product Analytics team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "Saas" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric.
-
-### Optional: Test Prometheus based Usage Ping
-
-If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify,
-then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components
-are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action
-is necessary, since Usage Ping should degrade gracefully in the absence of a running Prometheus server.
-
-There are currently three kinds of components that may export data to Prometheus, and which are included in Usage Ping:
-
-- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine
-- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components
-- various GitLab services such as Sidekiq and the Rails server that export their own metrics
-
-#### Test with an Omnibus container
-
-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
-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
-[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. 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
-
-This is the less recommended approach, since it comes with a number of difficulties when emulating a real GitLab deployment.
-
-The [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) is not currently set up to run a Prometheus server or `node_exporter` alongside other GitLab components. If you would
-like to do so, [Monitoring the GDK with Prometheus](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) is a good start.
-
-The [GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit) has limited support for testing Prometheus based Usage Ping.
-By default, it already comes with a fully configured Prometheus service that is set up to scrape a number of components,
-but with the following limitations:
-
-- It does not currently run a `gitlab-exporter` instance, so several `process_*` metrics from services such as Gitaly may be missing.
-- While it runs a `node_exporter`, `docker-compose` services emulate hosts, meaning that it would normally report itself to not be associated
-with any of the other services that are running. That is not how node metrics are reported in a production setup, where `node_exporter`
-always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore
-appear to be associated to any of the services running, since they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Usage Ping.
-
-## Aggregated metrics
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6.
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - It's enabled on GitLab.com.
-
-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 into [`aggregated_metrics.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics.yml) file. 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:
- - `OR`: removes duplicates and counts all entries that triggered any of listed events
- - `AND`: removes duplicates and counts all elements that were observed triggering all of following events
-- events: list of events names (from [`known_events.yml`](#known-events-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes.
-- feature_flag: name of [development feature flag](../feature_flags/development.md#development-type) that is checked before
-metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`.
-`feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag is checked.
-
-Example aggregated metric entries:
-
-```yaml
-- name: product_analytics_test_metrics_union
- operator: OR
- events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
-- name: product_analytics_test_metrics_intersection_with_feautre_flag
- operator: AND
- events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
- feature_flag: example_aggregated_metric
-```
-
-Aggregated metrics are added under `aggregated_metrics` key in both `counts_weekly` and `counts_monthly` top level keys in Usage Ping payload.
-
-```ruby
-{
- :counts_monthly => {
- :deployments => 1003,
- :successful_deployments => 78,
- :failed_deployments => 275,
- :packages => 155,
- :personal_snippets => 2106,
- :project_snippets => 407,
- :promoted_issues => 719,
- :aggregated_metrics => {
- :product_analytics_test_metrics_union => 7,
- :product_analytics_test_metrics_intersection_with_feautre_flag => 2
- },
- :snippets => 2513
- }
-}
-```
-
-## Example Usage Ping payload
-
-The following is example content of the Usage Ping payload.
-
-```json
-{
- "uuid": "0000000-0000-0000-0000-000000000000",
- "hostname": "example.com",
- "version": "12.10.0-pre",
- "installation_type": "omnibus-gitlab",
- "active_user_count": 999,
- "recorded_at": "2020-04-17T07:43:54.162+00:00",
- "edition": "EEU",
- "license_md5": "00000000000000000000000000000000",
- "license_id": null,
- "historical_max_users": 999,
- "licensee": {
- "Name": "ABC, Inc.",
- "Email": "email@example.com",
- "Company": "ABC, Inc."
- },
- "license_user_count": 999,
- "license_starts_at": "2020-01-01",
- "license_expires_at": "2021-01-01",
- "license_plan": "ultimate",
- "license_add_ons": {
- },
- "license_trial": false,
- "counts": {
- "assignee_lists": 999,
- "boards": 999,
- "ci_builds": 999,
- ...
- },
- "container_registry_enabled": true,
- "dependency_proxy_enabled": false,
- "gitlab_shared_runners_enabled": true,
- "gravatar_enabled": true,
- "influxdb_metrics_enabled": true,
- "ldap_enabled": false,
- "mattermost_enabled": false,
- "omniauth_enabled": true,
- "prometheus_enabled": false,
- "prometheus_metrics_enabled": false,
- "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com",
- "signup_enabled": true,
- "web_ide_clientside_preview_enabled": true,
- "ingress_modsecurity_enabled": true,
- "projects_with_expiration_policy_disabled": 999,
- "projects_with_expiration_policy_enabled": 999,
- ...
- "elasticsearch_enabled": true,
- "license_trial_ends_on": null,
- "geo_enabled": false,
- "git": {
- "version": {
- "major": 2,
- "minor": 26,
- "patch": 1
- }
- },
- "gitaly": {
- "version": "12.10.0-rc1-93-g40980d40",
- "servers": 56,
- "clusters": 14,
- "filesystems": [
- "EXT_2_3_4"
- ]
- },
- "gitlab_pages": {
- "enabled": true,
- "version": "1.17.0"
- },
- "container_registry_server": {
- "vendor": "gitlab",
- "version": "2.9.1-gitlab"
- },
- "database": {
- "adapter": "postgresql",
- "version": "9.6.15",
- "pg_system_id": 6842684531675334351
- },
- "analytics_unique_visits": {
- "g_analytics_contribution": 999,
- ...
- },
- "usage_activity_by_stage": {
- "configure": {
- "project_clusters_enabled": 999,
- ...
- },
- "create": {
- "merge_requests": 999,
- ...
- },
- "manage": {
- "events": 999,
- ...
- },
- "monitor": {
- "clusters": 999,
- ...
- },
- "package": {
- "projects_with_packages": 999
- },
- "plan": {
- "issues": 999,
- ...
- },
- "release": {
- "deployments": 999,
- ...
- },
- "secure": {
- "user_container_scanning_jobs": 999,
- ...
- },
- "verify": {
- "ci_builds": 999,
- ...
- }
- },
- "usage_activity_by_stage_monthly": {
- "configure": {
- "project_clusters_enabled": 999,
- ...
- },
- "create": {
- "merge_requests": 999,
- ...
- },
- "manage": {
- "events": 999,
- ...
- },
- "monitor": {
- "clusters": 999,
- ...
- },
- "package": {
- "projects_with_packages": 999
- },
- "plan": {
- "issues": 999,
- ...
- },
- "release": {
- "deployments": 999,
- ...
- },
- "secure": {
- "user_container_scanning_jobs": 999,
- ...
- },
- "verify": {
- "ci_builds": 999,
- ...
- }
- },
- "topology": {
- "duration_s": 0.013836685999194742,
- "application_requests_per_hour": 4224,
- "query_apdex_weekly_average": 0.996,
- "failures": [],
- "nodes": [
- {
- "node_memory_total_bytes": 33269903360,
- "node_memory_utilization": 0.35,
- "node_cpus": 16,
- "node_cpu_utilization": 0.2,
- "node_uname_info": {
- "machine": "x86_64",
- "sysname": "Linux",
- "release": "4.19.76-linuxkit"
- },
- "node_services": [
- {
- "name": "web",
- "process_count": 16,
- "process_memory_pss": 233349888,
- "process_memory_rss": 788220927,
- "process_memory_uss": 195295487,
- "server": "puma"
- },
- {
- "name": "sidekiq",
- "process_count": 1,
- "process_memory_pss": 734080000,
- "process_memory_rss": 750051328,
- "process_memory_uss": 731533312
- },
- ...
- ],
- ...
- },
- ...
- ]
- }
-}
-```
-
-## Notable changes
-
-In GitLab 13.5, `pg_system_id` was added to send the [PostgreSQL system identifier](https://www.2ndquadrant.com/en/blog/support-for-postgresqls-system-identifier-in-barman/).
-
-## Exporting Usage Ping SQL queries and definitions
-
-Two Rake tasks exist to export Usage Ping definitions.
-
-- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`.
-- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`.
-- The Rake tasks calculate the `alt_usage_data` metrics.
-
-In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively:
-
-```shell
-# for YAML export
-bin/rake gitlab:usage_data:dump_sql_in_yaml
-
-# for JSON export
-bin/rake gitlab:usage_data:dump_sql_in_json
-
-# You may pipe the output into a file
-bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml
-```
-
-## Generating and troubleshooting usage ping
-
-To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping).
+<!-- 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/profiling.md b/doc/development/profiling.md
index 76c89d361fc..ce9c1191648 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -128,8 +128,66 @@ console.
As a follow up to finding `N+1` queries with Bullet, consider writing a [QueryRecoder test](query_recorder.md) to prevent a regression.
+## System stats
+
+During or after profiling, you may want to get detailed information about the Ruby virtual machine process,
+such as memory consumption, time spent on CPU, or garbage collector statistics. These are easy to produce individually
+through various tools, but for convenience, a summary endpoint has been added that exports this data as a JSON payload:
+
+```shell
+curl localhost:3000/-/metrics/system | jq
+```
+
+Example output:
+
+```json
+{
+ "version": "ruby 2.7.2p137 (2020-10-01 revision a8323b79eb) [x86_64-linux-gnu]",
+ "gc_stat": {
+ "count": 118,
+ "heap_allocated_pages": 11503,
+ "heap_sorted_length": 11503,
+ "heap_allocatable_pages": 0,
+ "heap_available_slots": 4688580,
+ "heap_live_slots": 3451712,
+ "heap_free_slots": 1236868,
+ "heap_final_slots": 0,
+ "heap_marked_slots": 3451450,
+ "heap_eden_pages": 11503,
+ "heap_tomb_pages": 0,
+ "total_allocated_pages": 11503,
+ "total_freed_pages": 0,
+ "total_allocated_objects": 32679478,
+ "total_freed_objects": 29227766,
+ "malloc_increase_bytes": 84760,
+ "malloc_increase_bytes_limit": 32883343,
+ "minor_gc_count": 88,
+ "major_gc_count": 30,
+ "compact_count": 0,
+ "remembered_wb_unprotected_objects": 114228,
+ "remembered_wb_unprotected_objects_limit": 228456,
+ "old_objects": 3185330,
+ "old_objects_limit": 6370660,
+ "oldmalloc_increase_bytes": 21838024,
+ "oldmalloc_increase_bytes_limit": 119181499
+ },
+ "memory_rss": 1326501888,
+ "memory_uss": 1048563712,
+ "memory_pss": 1139554304,
+ "time_cputime": 82.885264633,
+ "time_realtime": 1610459445.5579069,
+ "time_monotonic": 24001.23145713,
+ "worker_id": "puma_0"
+}
+```
+
+NOTE:
+This endpoint is only available for Rails web workers. Sidekiq workers can not be inspected this way.
+
## Settings that impact performance
+### Application settings
+
1. `development` environment by default works with hot-reloading enabled, this makes Rails to check file changes every request, and create a potential contention lock, as hot reload is single threaded.
1. `development` environment can load code lazily once the request is fired which results in first request to always be slow.
@@ -140,3 +198,34 @@ To disable those features for profiling/benchmarking set the `RAILS_PROFILE` env
- restart GDK with `gdk restart`
*This environment variable is only applicable for the development mode.*
+
+### GC settings
+
+Ruby's garbage collector (GC) can be tuned via a variety of environment variables that will directly impact application performance.
+
+The following table lists these variables along with their default values.
+
+| Environment variable | Default value |
+|--|--|
+| `RUBY_GC_HEAP_INIT_SLOTS` | `10000` |
+| `RUBY_GC_HEAP_FREE_SLOTS` | `4096` |
+| `RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO` | `0.20` |
+| `RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO` | `0.40` |
+| `RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO` | `0.65` |
+| `RUBY_GC_HEAP_GROWTH_FACTOR` | `1.8` |
+| `RUBY_GC_HEAP_GROWTH_MAX_SLOTS` | `0 (disable)` |
+| `RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR` | `2.0` |
+| `RUBY_GC_MALLOC_LIMIT(_MIN)` | `(16 * 1024 * 1024 /* 16MB */)` |
+| `RUBY_GC_MALLOC_LIMIT_MAX` | `(32 * 1024 * 1024 /* 32MB */)` |
+| `RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR` | `1.4` |
+| `RUBY_GC_OLDMALLOC_LIMIT(_MIN)` | `(16 * 1024 * 1024 /* 16MB */)` |
+| `RUBY_GC_OLDMALLOC_LIMIT_MAX` | `(128 * 1024 * 1024 /* 128MB */)` |
+| `RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR` | `1.2` |
+
+([Source](https://github.com/ruby/ruby/blob/45b29754cfba8435bc4980a87cd0d32c648f8a2e/gc.c#L254-L308))
+
+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
+out as CSV.
diff --git a/doc/development/query_performance.md b/doc/development/query_performance.md
index c61d2a0864f..3cb1b10c417 100644
--- a/doc/development/query_performance.md
+++ b/doc/development/query_performance.md
@@ -21,7 +21,7 @@ When you are optimizing your SQL queries, there are two dimensions to pay attent
| Queries in a migration | `100ms` | This is different than the total [migration time](database_review.md#timing-guidelines-for-migrations). |
| Concurrent operations in a migration | `5min` | Concurrent operations do not block the database, but they block the GitLab update. This includes operations such as `add_concurrent_index` and `add_concurrent_foreign_key`. |
| Background migrations | `1s` | |
-| Usage Ping | `1s` | See the [usage ping docs](product_analytics/usage_ping.md#developing-and-testing-usage-ping) for more details. |
+| Usage Ping | `1s` | See the [usage ping docs](usage_ping.md#developing-and-testing-usage-ping) for more details. |
- When analyzing your query's performance, pay attention to if the time you are seeing is on a [cold or warm cache](#cold-and-warm-cache). These guidelines apply for both cache types.
- When working with batched queries, change the range and batch size to see how it effects the query timing and caching.
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 44a95f6e820..bd98ea170e5 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -194,7 +194,7 @@ Go's [`regexp`](https://golang.org/pkg/regexp/) package uses `re2` and isn't vul
- [Rubular](https://rubular.com/) is a nice online tool to fiddle with Ruby Regexps.
- [Runaway Regular Expressions](https://www.regular-expressions.info/catastrophic.html)
-- [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](http://people.cs.vt.edu/~davisjam/downloads/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities.
+- [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](https://people.cs.vt.edu/~davisjam/downloads/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities.
- [Freezing the web: A study of redos vulnerabilities in JavaScript-based web servers](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-staicu.pdf). Another research paper about detecting ReDoS vulnerabilities.
## Server Side Request Forgery (SSRF)
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index e4f07f732cf..e290eaee7c2 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -825,7 +825,7 @@ For the same reasons that removing workers is dangerous, care should be taken
when renaming queues.
When renaming queues, use the `sidekiq_queue_migrate` helper migration method,
-as show in this example:
+as shown in this example:
```ruby
class MigrateTheRenamedSidekiqQueue < ActiveRecord::Migration[5.0]
diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md
new file mode 100644
index 00000000000..6b37936cd93
--- /dev/null
+++ b/doc/development/snowplow.md
@@ -0,0 +1,623 @@
+---
+stage: Growth
+group: Product Intelligence
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Snowplow Guide
+
+This guide provides an overview of how Snowplow works, and implementation details.
+
+For more information about Product Intelligence, see:
+
+- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
+- [Usage Ping Guide](usage_ping.md)
+
+More useful links:
+
+- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
+- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
+- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
+- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
+
+## What is Snowplow
+
+Snowplow is an enterprise-grade marketing and Product Intelligence platform which helps track the way users engage with our website and application.
+
+[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems:
+
+- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT.
+- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis.
+- **Enrich** cleans up the raw Snowplow events, enriches them and puts them into storage. We have an Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process.
+- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases.
+- **Data modeling** is where event-level data is joined with other data sets and aggregated into smaller data sets, and business logic is applied. This produces a clean set of tables which make it easier to perform analysis on the data. We have data models for Redshift and Looker.
+- **Analytics** are performed on the Snowplow events or on the aggregate tables.
+
+![snowplow_flow](img/snowplow_flow.png)
+
+## Snowplow schema
+
+We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions:
+
+- Frontend and backend taxonomy as listed below
+- [Structured event taxonomy](#structured-event-taxonomy)
+- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events)
+- [Iglu schema](https://gitlab.com/gitlab-org/iglu/)
+- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events)
+
+## Enabling Snowplow
+
+Tracking can be enabled at:
+
+- The instance level, which enables tracking on both the frontend and backend layers.
+- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
+
+We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
+
+- **Admin Area > Settings > General** in the UI.
+- `admin/application_settings/integrations` in your browser.
+
+The following configuration is required:
+
+| Name | Value |
+|---------------|---------------------------|
+| Collector | `snowplow.trx.gitlab.net` |
+| Site ID | `gitlab` |
+| Cookie domain | `.gitlab.com` |
+
+## Snowplow request flow
+
+The following example shows a basic request/response flow between the following components:
+
+- Snowplow JS / Ruby Trackers on GitLab.com
+- [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md)
+- The GitLab S3 Bucket
+- The GitLab Snowflake Data Warehouse
+- Sisense:
+
+```mermaid
+sequenceDiagram
+ participant Snowplow JS (Frontend)
+ participant Snowplow Ruby (Backend)
+ participant GitLab.com Snowplow Collector
+ participant S3 Bucket
+ participant Snowflake DW
+ participant Sisense Dashboards
+ Snowplow JS (Frontend) ->> GitLab.com Snowplow Collector: FE Tracking event
+ Snowplow Ruby (Backend) ->> GitLab.com Snowplow Collector: BE Tracking event
+ loop Process using Kinesis Stream
+ GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Log raw events
+ GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Enrich events
+ GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk
+ end
+ GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose
+ S3 Bucket->>Snowflake DW: Import data
+ Snowflake DW->>Snowflake DW: Transform data using dbt
+ Snowflake DW->>Sisense Dashboards: Data available for querying
+```
+
+## Structured event taxonomy
+
+When adding new click events, we should add them in a way that's internally consistent. If we don't, it is very painful to perform analysis across features since each feature captures events differently.
+
+The current method provides several attributes that are sent on each click event. Please try to follow these guidelines when specifying events to capture:
+
+| 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. |
+| 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. |
+| 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). |
+
+### Web-specific parameters
+
+Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
+
+## Implementing Snowplow JS (Frontend) tracking
+
+GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. There are a few ways to use tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy).
+
+| field | type | default value | description |
+|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `category` | string | document.body.dataset.page | Page or subsection of a page that events are being captured within. |
+| `action` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
+| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+
+### Tracking in HAML (or Vue Templates)
+
+When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-event` attribute automatically have event tracking bound on clicks.
+
+Below is an example of `data-track-*` attributes assigned to a button:
+
+```haml
+%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } }
+```
+
+```html
+<button class="btn"
+ data-track-event="click_button"
+ data-track-label="template_preview"
+ data-track-property="my-template"
+/>
+```
+
+Event listeners are bound at the document level to handle click events on or within elements with these data attributes. This allows them to be properly handled on re-rendering and changes to the DOM. Note that because of the way these events are bound, click events should not be stopped from propagating up the DOM tree. If for any reason click events are being stopped from propagating, you need to implement your own listeners and follow the instructions in [Tracking in raw JavaScript](#tracking-in-raw-javascript).
+
+Below is a list of supported `data-track-*` attributes:
+
+| attribute | required | description |
+|:----------------------|:---------|:------------|
+| `data-track-event` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. |
+| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. |
+| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+
+#### Caveats
+
+When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/898b286de322e5df6a38d257b10c94974d580df8/app/helpers/tab_helper.rb#L69) be sure to wrap `html_options` under the `html_options` keyword argument.
+Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options`
+
+`nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "groups_dropdown", track_event: "click_dropdown" } })`
+
+vs
+
+`link_to assigned_issues_dashboard_path, title: _('Issues'), data: { track_label: 'main_navigation', track_event: 'click_issues_link' }`
+
+### Tracking within Vue components
+
+There's a tracking Vue mixin that can be used in components if more complex tracking is required. To use it, first import the `Tracking` library and request a mixin.
+
+```javascript
+import Tracking from '~/tracking';
+const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
+```
+
+You can provide default options that are passed along whenever an event is tracked from within your component. For instance, if all events within a component should be tracked with a given `label`, you can provide one at this time. Available defaults are `category`, `label`, `property`, and `value`. If no category is specified, `document.body.dataset.page` is used as the default.
+
+You can then use the mixin normally in your component with the `mixin` Vue declaration. The mixin also provides the ability to specify tracking options in `data` or `computed`. These override any defaults and allow the values to be dynamic from props, or based on state.
+
+```javascript
+export default {
+ mixins: [trackingMixin],
+ // ...[component implementation]...
+ data() {
+ return {
+ expanded: false,
+ tracking: {
+ label: 'left_sidebar'
+ }
+ };
+ },
+}
+```
+
+The mixin provides a `track` method that can be called within the template, or from component methods. An example of the whole implementation might look like the following.
+
+```javascript
+export default {
+ mixins: [Tracking.mixin({ label: 'right_sidebar' })],
+ data() {
+ return {
+ expanded: false,
+ };
+ },
+ methods: {
+ toggle() {
+ this.expanded = !this.expanded;
+ this.track('click_toggle', { value: this.expanded })
+ }
+ }
+};
+```
+
+And if needed within the template, you can use the `track` method directly as well.
+
+```html
+<template>
+ <div>
+ <a class="toggle" @click.prevent="toggle">Toggle</a>
+ <div v-if="expanded">
+ <p>Hello world!</p>
+ <a @click.prevent="track('click_action')">Track an event</a>
+ </div>
+ </div>
+</template>
+```
+
+### Tracking in raw JavaScript
+
+Custom event tracking and instrumentation can be added by directly calling the `Tracking.event` static function. The following example demonstrates tracking a click on a button by calling `Tracking.event` manually.
+
+```javascript
+import Tracking from '~/tracking';
+
+const button = document.getElementById('create_from_template_button');
+button.addEventListener('click', () => {
+ Tracking.event('dashboard:projects:index', 'click_button', {
+ label: 'create_from_template',
+ property: 'template_preview',
+ value: 'rails',
+ });
+})
+```
+
+### Tests and test helpers
+
+In Jest particularly in Vue tests, you can use the following:
+
+```javascript
+import { mockTracking } from 'helpers/tracking_helper';
+
+describe('MyTracking', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ it('tracks an event when clicked on feedback', () => {
+ wrapper.find('.discover-feedback-icon').trigger('click');
+
+ expect(spy).toHaveBeenCalledWith('_category_', 'click_button', {
+ label: 'security-discover-feedback-cta',
+ property: '0',
+ });
+ });
+});
+```
+
+In obsolete Karma tests it's used as below:
+
+```javascript
+import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
+
+describe('my component', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking('_category_', vm.$el, spyOn);
+ });
+
+ const triggerEvent = () => {
+ // action which should trigger a event
+ };
+
+ it('tracks an event when toggled', () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ triggerEvent('a.toggle');
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
+ label: 'right_sidebar',
+ property: 'confidentiality',
+ });
+ });
+});
+```
+
+## Implementing Snowplow Ruby (Backend) tracking
+
+GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events.
+
+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. |
+
+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.
+
+For example:
+
+```ruby
+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?
+ )
+ end
+end
+```
+
+### Unit testing
+
+Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices](
+https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details.
+
+### Performance
+
+We use the [AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development.
+
+## Developing and testing Snowplow
+
+There are several tools for developing and testing Snowplow Event
+
+| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment |
+|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------|
+| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
+| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
+| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** |
+| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** |
+
+**Legend**
+
+**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned
+
+### Preparing your MR for Review
+
+1. For frontend events, in the MR description section, add a screenshot of the event's relevant section using the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
+1. For backend events, please use Snowplow Micro and add the output of the Snowplow Micro good events `GET http://localhost:9090/micro/good`.
+
+### Snowplow Analytics Debugger Chrome Extension
+
+Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments.
+
+1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
+1. Open Chrome DevTools to the Snowplow Analytics Debugger tab.
+1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html).
+
+### Snowplow Inspector Chrome Extension
+
+Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments.
+
+1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en).
+1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar.
+1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window.
+
+### Snowplow Micro
+
+Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried.
+
+Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You need to modify GDK using the instructions below to set this up.
+
+- 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)
+
+1. Ensure Docker is installed and running.
+
+1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration):
+1. Navigate to the directory with the cloned project, and start the appropriate Docker
+ container with the following script:
+
+ ```shell
+ ./snowplow-micro.sh
+ ```
+
+1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector:
+
+ ```shell
+ gdk psql -d gitlabhq_development
+ update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com';
+ ```
+
+1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking.js` to remove `forceSecureTracker: true`:
+
+ ```diff
+ diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
+ index 0a1211d0a76..3b98c8f28f2 100644
+ --- a/app/assets/javascripts/tracking.js
+ +++ b/app/assets/javascripts/tracking.js
+ @@ -7,7 +7,6 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
+ appId: '',
+ userFingerprint: false,
+ respectDoNotTrack: true,
+ - forceSecureTracker: true,
+ eventMethod: 'post',
+ contexts: { webPage: true, performanceTiming: true },
+ formTracking: false,
+
+ ```
+
+1. Update `snowplow_options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`:
+
+ ```diff
+ diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
+ index 618e359211b..e9084623c43 100644
+ --- a/lib/gitlab/tracking.rb
+ +++ b/lib/gitlab/tracking.rb
+ @@ -41,7 +41,9 @@ def snowplow_options(group)
+ cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
+ app_id: Gitlab::CurrentSettings.snowplow_app_id,
+ form_tracking: additional_features,
+ - link_click_tracking: additional_features
+ + link_click_tracking: additional_features,
+ + protocol: 'http',
+ + port: 9090
+ }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
+ end
+ ```
+
+1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`:
+
+ ```diff
+ diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
+ index 4fa844de325..5dd9d0eacfb 100644
+ --- a/lib/gitlab/tracking/destinations/snowplow.rb
+ +++ b/lib/gitlab/tracking/destinations/snowplow.rb
+ @@ -40,7 +40,7 @@ def tracker
+ def emitter
+ SnowplowTracker::AsyncEmitter.new(
+ Gitlab::CurrentSettings.snowplow_collector_hostname,
+ - protocol: 'https'
+ + protocol: 'http'
+ )
+ end
+ end
+
+ ```
+
+1. Restart GDK:
+
+ ```shell
+ `gdk restart`
+ ```
+
+1. Send a test Snowplow event from the Rails console:
+
+ ```ruby
+ Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', data: { page_type: 'MY_TYPE' }, context: nil)
+ ```
+
+1. Navigate to `localhost:9090/micro/good` to see the event.
+
+### Snowplow Mini
+
+[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow.
+
+Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment.
+
+For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
+
+## Snowplow Schemas
+
+### [gitlab_standard](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/1-0-0) Schema
+
+| 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 |
+
+### 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 |
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
new file mode 100644
index 00000000000..453d71411c3
--- /dev/null
+++ b/doc/development/stage_group_dashboards.md
@@ -0,0 +1,148 @@
+---
+stage: Enablement
+group: Infrastructure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Dashboards for stage groups
+
+## Introduction
+
+Observability is about bringing visibility into a system to see and understand the state of each component, with context, to support performance tuning and debugging. To run a SaaS platform at scale, a rich and detailed observability platform is a necessity. We have a set of monitoring dashboards designed for [each stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+
+These dashboards are designed to give an insight, to everyone working in a feature category, into how their code operates at GitLab.com scale. They are grouped per stage group to show the impact of feature/code changes, deployments, and feature-flag toggles.
+
+Each stage group has a dashboard consisting of metrics at the application level, such as Rails Web Requests, Rails API Requests, Sidekiq Jobs, and so on. The metrics in each dashboard are filtered and accumulated based on the [GitLab product categories](https://about.gitlab.com/handbook/product/categories/) and [feature categories](feature_categorization/index.md).
+
+The list of dashboards for each stage group is accessible at <https://dashboards.gitlab.net/dashboards/f/stage-groups/stage-groups> (GitLab team members only), or at [the public mirror](https://dashboards.gitlab.com/dashboards?tag=feature_category&tag=stage-groups) (accessible to everyone with a GitLab.com account, with some limitations).
+
+The dashboards for stage groups are at a very early stage. All contributions are welcome. If you have any questions or suggestions, please submit an issue in the [Scalability Team issues tracker](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/new).
+
+## Usage
+
+Inside a stage group dashboard, there are some notable components. Let's take the [Source Code group's dashboard](https://dashboards.gitlab.net/d/stage-groups-source_code/stage-groups-group-dashboard-create-source-code?orgId=1) as an example.
+
+### Time range controls
+
+![Default time filter](img/stage_group_dashboards_time_filter.png)
+
+- By default, all the times are in UTC timezone. [We use UTC when communicating in Engineering](https://about.gitlab.com/handbook/communication/#writing-style-guidelines).
+- All metrics recorded in the GitLab production system have [1-year retention](https://gitlab.com/gitlab-cookbooks/gitlab-prometheus/-/blob/31526b03fef823e2f9b3cda7c75dcd28a12418a3/attributes/prometheus.rb#L40).
+- Alternatively, you can zoom in or filter the time range directly on a graph. See the [Grafana Time Range Controls](https://grafana.com/docs/grafana/latest/dashboards/time-range-controls/) documentation for more information.
+
+### Filters and annotations
+
+In each dashboard, there are two filters and some annotations switches on the top of the page. [Grafana annotations](https://grafana.com/docs/grafana/latest/dashboards/annotations/) mark some special events, which are meaningful to development and operational activities, directly on the graphs.
+
+![Filters and annotations](img/stage_group_dashboards_filters.png)
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `PROMETHEUS_DS` | filter | Filter the selective [Prometheus data sources](https://about.gitlab.com/handbook/engineering/monitoring/#prometheus). The default value is `Global`, which aggregates the data from all available data sources. Most of the time, you don't need to care about this filter. |
+| `environment` | filter | Filter the environment the metrics are fetched from. The default setting is production (`gprd`). Check [Production Environment mapping](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#environments) for other possibilities. |
+| `deploy` | annotation | Mark a deployment event on the GitLab.com SaaS platform. |
+| `canary-deploy` | annotation | Mark a [canary deployment](https://about.gitlab.com/handbook/engineering/#canary-testing) event on the GitLab.com SaaS platform. |
+| `feature-flags` | annotation | Mark the time point where a feature flag is updated.|
+
+This is an example of a feature flag annotation displayed on a dashboard panel.
+
+![Annotations](img/stage_group_dashboards_annotation.png)
+
+### Metrics panels
+
+![Metrics panels](img/stage_group_dashboards_metrics.png)
+
+Although most of the metrics displayed in the panels are self-explanatory in their title and nearby description, note the following:
+
+- The events are counted, measured, accumulated, then collected, and stored as [time series](https://prometheus.io/docs/concepts/data_model/). The data are calculated using statistical methods to produce metrics. It means that metrics are approximately correct and meaningful over a time period. They help you have an overview of the stage of a system over time. They are not meant to give you precise numbers of a discrete event. If you need a higher level of accuracy, please look at another monitoring tool like [logs](https://about.gitlab.com/handbook/engineering/monitoring/#logs). Please read the following examples for more explanations.
+- All the rate metrics' units are `requests per second`. The default aggregate time frame is 1 minute. For example, a panel shows the requests per second number at `2020-12-25 00:42:00` is `34.13`. It means at the minute 42 (from `2020-12-25 00:42:00` to `2020-12-25 00:42:59` ), there are approximately `34.13 * 60 = ~ 2047` requests processed by the web servers.
+- You may encounter some gotchas related to decimal fraction and rounding up frequently, especially in low-traffic cases. For example, the error rate of `RepositoryUpdateMirrorWorker` at `2020-12-25 02:04:00` is `0.07`, equivalent to `4.2` jobs per minute. The raw result is `0.06666666667`, equivalent to 4 jobs per minute.
+- All the rate metrics are more accurate when the data is big enough. The default floating-point precision is 2. In some extremely low panels, you would see `0.00` although there is still some real traffic.
+
+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/).
+
+## How to debug with the dashboards
+
+- A team member in the Code Review group has merged an MR which got deployed to production.
+- To verify the deployment, we can check the [Code Review group's dashboard](https://dashboards.gitlab.net/d/stage-groups-code_review/stage-groups-group-dashboard-create-code-review?orgId=1).
+- Sidekiq Error Rate panel shows an elevated error rate, specifically `UpdateMergeRequestsWorker`.
+
+ ![Debug 1](img/stage_group_dashboards_debug_1.png)
+
+- If we click on `Kibana: Kibana Sidekiq failed request logs` link in the Extra links session, we can filter for `UpdateMergeRequestsWorker`, and read through the logs.
+
+ ![Debug 2](img/stage_group_dashboards_debug_2.png)
+
+- [Sentry](https://sentry.gitlab.net/gitlab/gitlabcom/) gives us a way to find the exception where we can filter by transaction type and correlation_id from a Kibana's result item.
+
+ ![Debug 3](img/stage_group_dashboards_debug_3.png)
+
+- A precise exception, including a stack trace, job arguments, and other information, should now appear. Happy debugging!
+
+## 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):
+
+```jsonnet
+// This file is autogenerated using scripts/update_stage_groups_dashboards.rb
+// Please feel free to customize this file.
+local stageGroupDashboards = import './stage-group-dashboards.libsonnet';
+
+stageGroupDashboards.dashboard('product_planning')
+.stageGroupDashboardTrailer()
+```
+
+We provide basic customization to filter out the components essential to your group's activities. By default, all components `web`, `api`, `git`, and `sidekiq` are available in the dashboard. We can change this to only show `web` and `api`, or only show `sidekiq`:
+
+```jsonnet
+stageGroupDashboards.dashboard('product_planning', components=['web', 'api']).stageGroupDashboardTrailer()
+# Or
+stageGroupDashboards.dashboard('product_planning', components=['sidekiq']).stageGroupDashboardTrailer()
+
+```
+
+You can also append further information or custom metrics to a dashboard. This is an example that adds some links and a total request rate on the top of the page:
+
+```jsonnet
+local stageGroupDashboards = import './stage-group-dashboards.libsonnet';
+local grafana = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet';
+local basic = import 'grafana/basic.libsonnet';
+
+stageGroupDashboards.dashboard('source_code')
+.addPanel(
+ grafana.text.new(
+ title='Group information',
+ mode='markdown',
+ content=|||
+ Useful link for the Source Code Management group dashboard:
+ - [Issue list](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name%5B%5D=repository)
+ - [Epic list](https://gitlab.com/groups/gitlab-org/-/epics?label_name[]=repository)
+ |||,
+ ),
+ gridPos={ x: 0, y: 0, w: 24, h: 4 }
+)
+.addPanel(
+ basic.timeseries(
+ title='Total Request Rate',
+ yAxisLabel='Requests per Second',
+ decimals=2,
+ query=|||
+ sum (
+ rate(gitlab_transaction_duration_seconds_count{
+ env='$environment',
+ environment='$environment',
+ feature_category=~'source_code_management',
+ }[$__interval])
+ )
+ |||
+ ),
+ gridPos={ x: 0, y: 0, w: 24, h: 7 }
+)
+.stageGroupDashboardTrailer()
+```
+
+![Stage Group Dashboard Customization](img/stage_group_dashboards_time_customization.png)
+
+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
index bc230a46441..b3b3b0b4fdd 100644
--- a/doc/development/telemetry/event_dictionary.md
+++ b/doc/development/telemetry/event_dictionary.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/event_dictionary.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../product_analytics/event_dictionary.md).
+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
index 24e83ffc524..b3b3b0b4fdd 100644
--- a/doc/development/telemetry/index.md
+++ b/doc/development/telemetry/index.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/index.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../product_analytics/index.md).
+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
index 7cd385be681..bb056ffddfe 100644
--- a/doc/development/telemetry/snowplow.md
+++ b/doc/development/telemetry/snowplow.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/snowplow.md'
+redirect_to: '../snowplow.md'
---
-This document was moved to [another location](../product_analytics/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
index c890353fe3b..5fbdb508bb1 100644
--- a/doc/development/telemetry/usage_ping.md
+++ b/doc/development/telemetry/usage_ping.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../product_analytics/usage_ping.md'
+redirect_to: '../usage_ping.md'
---
-This document was moved to [another location](../product_analytics/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_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index d1b7883451f..ac5f1a47f9b 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -842,6 +842,41 @@ Example:
expect(response).to have_gitlab_http_status(:ok)
```
+#### `match_schema` and `match_response_schema`
+
+The `match_schema` matcher allows validating that the subject matches a
+[JSON schema](https://json-schema.org/). The item inside `expect` can be
+a JSON string or a JSON-compatible data structure.
+
+`match_response_schema` is a convenience matcher for using with a
+response object. from a [request
+spec](testing_levels.md#integration-tests).
+
+Examples:
+
+```ruby
+# Matches against spec/fixtures/api/schemas/prometheus/additional_metrics_query_result.json
+expect(data).to match_schema('prometheus/additional_metrics_query_result')
+
+# Matches against ee/spec/fixtures/api/schemas/board.json
+expect(data).to match_schema('board', dir: 'ee')
+
+# Matches against a schema made up of Ruby data structures
+expect(data).to match_schema(Atlassian::Schemata.build_info)
+```
+
+#### `be_valid_json`
+
+`be_valid_json` allows validating that a string parses as JSON and gives
+a non-empty result. To combine it with the schema matching above, use
+`and`:
+
+```ruby
+expect(json_string).to be_valid_json
+
+expect(json_string).to be_valid_json.and match_schema(schema)
+```
+
### Testing query performance
Testing query performance allows us to:
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 8a49c333f9f..cd429a74a2a 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
@@ -403,3 +403,85 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r
- You can find the full image address from a pipeline by [following these instructions](https://about.gitlab.com/handbook/engineering/quality/guidelines/tips-and-tricks/#running-gitlab-qa-pipeline-against-a-specific-gitlab-release). You might be prompted to set the `GITLAB_QA_ACCESS_TOKEN` variable if you specify the full image address.
- You can increase the wait time for replication by setting `GEO_MAX_FILE_REPLICATION_TIME` and `GEO_MAX_DB_REPLICATION_TIME`. The default is 120 seconds.
- To save time during tests, create a Personal Access Token with API access on the Geo primary node, and pass that value in as `GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_ADMIN_ACCESS_TOKEN`.
+
+## LDAP Tests
+
+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
+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).
+
+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"
+```
+
+The OpenLDAP container also uses its [auto-generated TLS certificates](https://github.com/osixia/docker-openldap#use-auto-generated-certificate).
+
+### Running LDAP tests with TLS enabled
+
+To run the LDAP tests on your local with TLS enabled, follow these steps:
+
+1. Include the following entry in your `/etc/hosts` file:
+
+ `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.
+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
+ docker network create test && docker run --name ldap-server --net test --hostname ldap-server.test --volume /path/to/gitlab-qa/fixtures/ldap:/container/service/slapd/assets/config/bootstrap/ldif/custom:Z --env LDAP_TLS_CRT_FILENAME="ldap-server.test.crt" --env LDAP_TLS_KEY_FILENAME="ldap-server.test.key" --env LDAP_TLS_ENFORCE="true" --env LDAP_TLS_VERIFY_CLIENT="never" osixia/openldap:latest --copy-service
+ ```
+
+1. Run the GitLab container with TLS enabled. Change the path to [`gitlab-qa/tls_certificates/gitlab`](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab) directory to your local checkout path:
+
+ ```shell
+ sudo docker run \
+ --hostname gitlab.test \
+ --net test \
+ --publish 443:443 --publish 80:80 --publish 22:22 \
+ --name gitlab \
+ --volume /path/to/gitlab-qa/tls_certificates/gitlab:/etc/gitlab/ssl \
+ --env GITLAB_OMNIBUS_CONFIG="gitlab_rails['ldap_enabled'] = true; gitlab_rails['ldap_servers'] = {\"main\"=>{\"label\"=>\"LDAP\", \"host\"=>\"ldap-server.test\", \"port\"=>636, \"uid\"=>\"uid\", \"bind_dn\"=>\"cn=admin,dc=example,dc=org\", \"password\"=>\"admin\", \"encryption\"=>\"simple_tls\", \"verify_certificates\"=>false, \"base\"=>\"dc=example,dc=org\", \"user_filter\"=>\"\", \"group_base\"=>\"ou=Global Groups,dc=example,dc=org\", \"admin_group\"=>\"AdminGroup\", \"external_groups\"=>\"\", \"sync_ssh_keys\"=>false}}; letsencrypt['enable'] = false; external_url 'https://gitlab.test'; gitlab_rails['ldap_sync_worker_cron'] = '* * * * *'; gitlab_rails['ldap_group_sync_worker_cron'] = '* * * * *'; " \
+ gitlab/gitlab-ee:latest
+ ```
+
+1. Run an LDAP test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory:
+
+ ```shell
+ GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true CHROME_HEADLESS=false bin/qa Test::Instance::All https://gitlab.test qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
+ ```
+
+### Running LDAP tests with TLS disabled
+
+To run the LDAP tests on your local with TLS disabled, follow these steps:
+
+1. Run OpenLDAP container with TLS disabled. 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
+ docker network create test && docker run --net test --publish 389:389 --publish 636:636 --name ldap-server --hostname ldap-server.test --volume /path/to/gitlab-qa/fixtures/ldap:/container/service/slapd/assets/config/bootstrap/ldif/custom:Z --env LDAP_TLS="false" osixia/openldap:latest --copy-service
+ ```
+
+1. Run the GitLab container:
+
+ ```shell
+ sudo docker run \
+ --hostname localhost \
+ --net test \
+ --publish 443:443 --publish 80:80 --publish 22:22 \
+ --name gitlab \
+ --env GITLAB_OMNIBUS_CONFIG="gitlab_rails['ldap_enabled'] = true; gitlab_rails['ldap_servers'] = {\"main\"=>{\"label\"=>\"LDAP\", \"host\"=>\"ldap-server.test\", \"port\"=>389, \"uid\"=>\"uid\", \"bind_dn\"=>\"cn=admin,dc=example,dc=org\", \"password\"=>\"admin\", \"encryption\"=>\"plain\", \"verify_certificates\"=>false, \"base\"=>\"dc=example,dc=org\", \"user_filter\"=>\"\", \"group_base\"=>\"ou=Global Groups,dc=example,dc=org\", \"admin_group\"=>\"AdminGroup\", \"external_groups\"=>\"\", \"sync_ssh_keys\"=>false}}; gitlab_rails['ldap_sync_worker_cron'] = '* * * * *'; gitlab_rails['ldap_group_sync_worker_cron'] = '* * * * *'; " \
+ gitlab/gitlab-ee:latest
+ ```
+
+1. Run an LDAP test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory:
+
+ ```shell
+ GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true CHROME_HEADLESS=false bin/qa Test::Instance::All http://localhost qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
+ ```
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index d83d58d14dd..94bc80abcdb 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -89,7 +89,7 @@ If your test exceeds that time, it fails.
If you cannot improve the performance of the tests, you can increase the timeout
for a specific test using
-[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/helpers/timeout.js).
+[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/__helpers__/timeout.js).
```javascript
import { setTestTimeout } from 'helpers/timeout';
@@ -834,12 +834,50 @@ The `response` variable gets automatically set if the test is marked as `type: :
When creating a new fixture, it often makes sense to take a look at the corresponding tests for the
endpoint in `(ee/)spec/controllers/` or `(ee/)spec/requests/`.
+##### GraphQL query fixtures
+
+You can create a fixture that represents the result of a GraphQL query using the `get_graphql_query_as_string`
+helper method. For example:
+
+```ruby
+# spec/frontend/fixtures/releases.rb
+
+describe GraphQL::Query, type: :request do
+ include GraphqlHelpers
+
+ all_releases_query_path = 'releases/queries/all_releases.query.graphql'
+ fragment_paths = ['releases/queries/release.fragment.graphql']
+
+ before(:all) do
+ clean_frontend_fixtures('graphql/releases/')
+ end
+
+ it "graphql/#{all_releases_query_path}.json" do
+ query = get_graphql_query_as_string(all_releases_query_path, fragment_paths)
+
+ post_graphql(query, current_user: admin, variables: { fullPath: project.full_path })
+
+ expect_graphql_errors_to_be_empty
+ end
+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.
+`get_graphql_query_as_string` reads all of the provided file paths and returns
+the result as a single, concatenated string.
+
+You can import the JSON fixture in a Jest test using the `getJSONFixture` method
+[as described below](#use-fixtures).
+
### Use fixtures
Jest and Karma test suites import fixtures in different ways:
- The Karma test suite are served by [jasmine-jquery](https://github.com/velesin/jasmine-jquery).
-- Jest use `spec/frontend/helpers/fixtures.js`.
+- Jest use `spec/frontend/__helpers__/fixtures.js`.
The following are examples of tests that work for both Karma and Jest:
@@ -1024,6 +1062,9 @@ 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.
+
### Vuex Helper: `testAction`
We have a helper available to make testing actions easier, as per [official documentation](https://vuex.vuejs.org/guide/testing.html):
@@ -1065,7 +1106,7 @@ By doing so, the `wrapper` provides you with the ability to perform a `findByTes
which is a shortcut to the more verbose `wrapper.find('[data-testid="my-test-id"]');`
```javascript
-import { extendedWrapper } from 'jest/helpers/vue_test_utils_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('FooComponent', () => {
const wrapper = extendedWrapper(shallowMount({
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 14d4ee82f75..abacb9a0c87 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -230,7 +230,7 @@ They're useful to test permissions, redirections, what view is rendered etc.
| Code path | Tests path | Testing engine | Notes |
| --------- | ---------- | -------------- | ----- |
-| `app/controllers/` | `spec/controllers/` | RSpec | For N+1 tests, use [request specs](../query_recorder.md#use-request-specs-instead-of-controller-specs) |
+| `app/controllers/` | `spec/requests/`, `spec/controllers` | RSpec | Request specs are preferred over legacy controller specs. |
| `app/mailers/` | `spec/mailers/` | RSpec | |
| `lib/api/` | `spec/requests/api/` | RSpec | |
| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | Karma & Jest | [More details below](#frontend-integration-tests) |
@@ -310,6 +310,8 @@ graph RL
### About controller tests
+GitLab is [transitioning from controller specs to request specs](https://gitlab.com/groups/gitlab-org/-/epics/5076).
+
In an ideal world, controllers should be thin. However, when this is not the
case, it's acceptable to write a system or feature test without JavaScript instead
of a controller test. Testing a fat controller usually involves a lot of stubbing, such as:
@@ -318,7 +320,7 @@ of a controller test. Testing a fat controller usually involves a lot of stubbin
controller.instance_variable_set(:@user, user)
```
-and use methods which are deprecated in Rails 5 ([#23768](https://gitlab.com/gitlab-org/gitlab/-/issues/16260)).
+and use methods [deprecated in Rails 5](https://gitlab.com/gitlab-org/gitlab/-/issues/16260).
### About Karma
diff --git a/doc/development/usage_ping.md b/doc/development/usage_ping.md
new file mode 100644
index 00000000000..10c3de2f0a1
--- /dev/null
+++ b/doc/development/usage_ping.md
@@ -0,0 +1,1151 @@
+---
+stage: Growth
+group: Product Intelligence
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# 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.
+
+This guide describes Usage Ping's purpose and how it's implemented.
+
+For more information about Product Intelligence, see:
+
+- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
+- [Snowplow Guide](snowplow.md)
+
+More useful links:
+
+- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
+- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
+- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
+- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
+
+## What is Usage Ping?
+
+- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics.
+- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features within the product. In addition to counts, other facts
+ that help us classify and understand GitLab installations are collected.
+- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features.
+- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users.
+
+### Why should we enable Usage Ping?
+
+- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions.
+- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation.
+- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring.
+- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value)
+- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization?
+- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes.
+- Usage Ping is enabled by default. To disable it, see [Disable Usage Ping](#disable-usage-ping).
+
+### Limitations
+
+- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events.
+- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed.
+
+## Usage Ping payload
+
+You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload:
+
+1. Navigate to **Admin Area > Settings > Metrics and profiling**.
+1. Expand the **Usage statistics** section.
+1. Click the **Preview payload** button.
+
+For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload).
+
+## Disable Usage Ping
+
+To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox.
+
+To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
+
+```ruby
+gitlab_rails['usage_ping_enabled'] = false
+```
+
+Source installations can set the following in `gitlab.yml`:
+
+```yaml
+production: &base
+ # ...
+ gitlab:
+ # ...
+ usage_ping_enabled: false
+```
+
+## Usage Ping request flow
+
+The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, the GitLab S3 Bucket, the GitLab Snowflake Data Warehouse, and Sisense:
+
+```mermaid
+sequenceDiagram
+ participant GitLab Instance
+ participant Versions Application
+ participant Licenses Application
+ participant Salesforce
+ participant S3 Bucket
+ participant Snowflake DW
+ participant Sisense Dashboards
+ GitLab Instance->>Versions Application: Send Usage Ping
+ loop Process usage data
+ Versions Application->>Versions Application: Parse usage data
+ Versions Application->>Versions Application: Write to database
+ Versions Application->>Versions Application: Update license ping time
+ end
+ loop Process data for Salesforce
+ Versions Application-xLicenses Application: Request Zuora subscription id
+ Licenses Application-xVersions Application: Zuora subscription id
+ Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id
+ Salesforce-xVersions Application: Zuora account id
+ Versions Application-xSalesforce: Usage data for the Zuora account
+ end
+ Versions Application->>S3 Bucket: Export Versions database
+ S3 Bucket->>Snowflake DW: Import data
+ Snowflake DW->>Snowflake DW: Transform data using dbt
+ Snowflake DW->>Sisense Dashboards: Data available for querying
+ Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index)
+```
+
+## How Usage Ping works
+
+1. The Usage Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30) is set in Sidekiq to run weekly.
+1. When the cron job runs, it calls [`Gitlab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22).
+1. `Gitlab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls.
+1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `Gitlab::UsageData.to_json`.
+1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20)
+ If a firewall exception is needed, the required URL depends on several things. If
+ the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`,
+ the required URL is <https://version.gitlab.com/>.
+
+## Implementing Usage Ping
+
+Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event
+happened over time, such as how many CI pipelines have run. They are monotonic and always trend up.
+Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no
+general guidelines around how to collect those, due to the individual nature of that data.
+
+There are several types of counters which are all found in `usage_data.rb`:
+
+- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation
+- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation in a given column
+- **Sum Batch Counters:** Sum the values of a given ActiveRecord_Relation in a given column
+- **Alternative Counters:** Used for settings and configurations
+- **Redis Counters:** Used for in-memory counts.
+
+NOTE:
+Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping.
+
+### Why batch counting
+
+For large tables, PostgreSQL can take a long time to count rows due to MVCC [(Multi-version Concurrency Control)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control). Batch counting is a counting method where a single large query is broken into multiple smaller queries. For example, instead of a single query querying 1,000,000 records, with batch counting, you can execute 100 queries of 10,000 records each. Batch counting is useful for avoiding database timeouts as each batch query is significantly shorter than one single long running query.
+
+For GitLab.com, there are extremely large tables with 15 second query timeouts, so we use batch counting to avoid encountering timeouts. Here are the sizes of some GitLab.com tables:
+
+| Table | Row counts in millions |
+|------------------------------|------------------------|
+| `merge_request_diff_commits` | 2280 |
+| `ci_build_trace_sections` | 1764 |
+| `merge_request_diff_files` | 1082 |
+| `events` | 514 |
+
+We have several batch counting methods available:
+
+- `Ordinary Batch Counters`
+- `Distinct Batch Counters`
+- `Sum Batch Counters`
+- `Estimated Batch Counters`
+
+Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases,
+you may need to add a specialized index on the columns involved in a counter.
+
+### Ordinary Batch Counters
+
+Handles `ActiveRecord::StatementInvalid` error
+
+Simple count of a given ActiveRecord_Relation, does a non-distinct batch count, smartly reduces batch_size and handles errors.
+
+Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)`
+
+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
+
+Examples:
+
+```ruby
+count(User.active)
+count(::Clusters::Cluster.aws_installed.enabled, :cluster_id)
+count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id))
+```
+
+### Distinct Batch Counters
+
+Handles `ActiveRecord::StatementInvalid` error
+
+Distinct count of a given ActiveRecord_Relation on given column, a distinct batch count, smartly reduces batch_size and handles errors.
+
+Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)`
+
+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_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
+
+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.
+
+Examples:
+
+```ruby
+distinct_count(::Project, :creator_id)
+distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id))
+distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id')
+```
+
+### Sum Batch Counters
+
+Handles `ActiveRecord::StatementInvalid` error
+
+Sum the values of a given ActiveRecord_Relation on given column and handles errors.
+
+Method: `sum(relation, column, batch_size: nil, start: nil, finish: nil)`
+
+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
+
+Examples:
+
+```ruby
+sum(JiraImportState.finished, :imported_issues_count)
+```
+
+### Grouping & Batch Operations
+
+The `count`, `distinct_count`, and `sum` batch counters can accept an `ActiveRecord::Relation`
+object, which groups by a specified column. With a grouped relation, the methods do batch counting,
+handle errors, and returns a hash table of key-value pairs.
+
+Examples:
+
+```ruby
+count(Namespace.group(:type))
+# returns => {nil=>179, "Group"=>54}
+
+distinct_count(Project.group(:visibility_level), :creator_id)
+# returns => {0=>1, 10=>1, 20=>11}
+
+sum(Issue.group(:state_id), :weight))
+# returns => {1=>3542, 2=>6820}
+```
+
+### Estimated Batch Counters
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7.
+
+Estimated batch counter functionality handles `ActiveRecord::StatementInvalid` errors
+when used through the provided `estimate_batch_distinct_count` method.
+Errors return a value of `-1`.
+
+WARNING:
+This functionality estimates a distinct count of a specific ActiveRecord_Relation in a given column,
+which uses the [HyperLogLog](http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf) algorithm.
+As the HyperLogLog algorithm is probabilistic, the **results always include error**.
+The highest encountered error rate is 4.9%.
+
+When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over
+columns that contain non-unique values, which can not be assured by other counters.
+
+Method: [`estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/usage_data.rb#L63)
+
+The method includes the following arguments:
+
+- `relation`: The ActiveRecord_Relation to perform the count.
+- `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.
+
+The method includes the following prerequisites:
+
+1. The supplied `relation` must include the primary key defined as the numeric column.
+ For example: `id bigint NOT NULL`.
+1. The `estimate_batch_distinct_count` can handle a joined relation. To use its ability to
+ count non-unique columns, the joined relation **must NOT** have a one-to-many relationship,
+ such as `has_many :boards`.
+1. Both `start` and `finish` arguments should always represent primary key relationship values,
+ even if the estimated count refers to another column, for example:
+
+ ```ruby
+ estimate_batch_distinct_count(::Note, :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id))
+ ```
+
+Examples:
+
+1. Simple execution of estimated batch counter, with only relation provided,
+ returned value represents estimated number of unique values in `id` column
+ (which is the primary key) of `Project` relation:
+
+ ```ruby
+ estimate_batch_distinct_count(::Project)
+ ```
+
+1. Execution of estimated batch counter, where provided relation has applied
+ additional filter (`.where(time_period)`), number of unique values estimated
+ in custom column (`:author_id`), and parameters: `start` and `finish` together
+ apply boundaries that defines range of provided relation to analyze:
+
+ ```ruby
+ estimate_batch_distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id))
+ ```
+
+1. Execution of estimated batch counter with joined relation (`joins(:cluster)`),
+ for a custom column (`'clusters.user_id'`):
+
+ ```ruby
+ estimate_batch_distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id')
+ ```
+
+When instrumenting metric with usage of estimated batch counter please add
+`_estimated` suffix to its name, for example:
+
+```ruby
+ "counts": {
+ "ci_builds_estimated": estimate_batch_distinct_count(Ci::Build),
+ ...
+```
+
+### Redis Counters
+
+Handles `::Redis::CommandError` and `Gitlab::UsageDataCounters::BaseCounter::UnknownEvent`
+returns -1 when a block is sent or hash with all values -1 when a `counter(Gitlab::UsageDataCounters)` is sent
+different behavior due to 2 different implementations of Redis counter
+
+Method: `redis_usage_data(counter, &block)`
+
+Arguments:
+
+- `counter`: a counter from `Gitlab::UsageDataCounters`, that has `fallback_totals` method implemented
+- or a `block`: which is evaluated
+
+#### Ordinary Redis Counters
+
+Examples of implementation:
+
+- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb)
+- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb)
+
+##### UsageData API Tracking
+
+<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. -->
+
+1. Track event using `UsageData` API
+
+ Increment event count using ordinary Redis counter, for given event name.
+
+ Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default.
+
+ 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.
+
+ ```plaintext
+ POST /usage_data/increment_counter
+ ```
+
+ | Attribute | Type | Required | Description |
+ | :-------- | :--- | :------- | :---------- |
+ | `event` | string | yes | The event name it should be tracked |
+
+ Response
+
+ - `200` if event was tracked
+ - `400 Bad request` if event parameter is missing
+ - `401 Unauthorized` if user is not authenticated
+ - `403 Forbidden` for invalid CSRF token provided
+
+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
+
+ ```javascript
+ import api from '~/api';
+
+ api.trackRedisCounterEvent('my_already_defined_event_name'),
+ ```
+
+#### Redis HLL Counters
+
+WARNING:
+HyperLogLog (HLL) is a probabilistic algorithm and its **results always includes some small error**. According to [Redis documentation](https://redis.io/commands/pfcount), data from
+used HLL implementation is "approximated with a standard error of 0.81%".
+
+With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values.
+
+Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount).
+
+##### Adding new events
+
+1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/).
+
+ Example event:
+
+ ```yaml
+ - name: i_compliance_credential_inventory
+ category: compliance
+ redis_slot: compliance
+ expiry: 42 # 6 weeks
+ aggregation: weekly
+ ```
+
+ Keys:
+
+ - `name`: unique event name.
+
+ Name format `<prefix>_<redis_slot>_name`.
+
+ Use one of the following prefixes for the event's name:
+
+ - `g_` for group, as an event which is tracked for group.
+ - `p_` for project, as an event which is tracked for project.
+ - `i_` for instance, as an event which is tracked for instance.
+ - `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.
+
+ Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`.
+
+ - `category`: event category. Used for getting total counts for events in a category, for easier
+ access to a group of events.
+ - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals
+ for a group of metrics. Ensure keys are in the same slot. For example:
+ `i_compliance_credential_inventory` with `redis_slot: 'compliance'` builds Redis key
+ `i_{compliance}_credential_inventory-2020-34`. If `redis_slot` is not defined the Redis key will
+ be `{i_compliance_credential_inventory}-2020-34`.
+ - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly
+ 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.
+
+1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`.
+
+ 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.
+
+ Example usage:
+
+ ```ruby
+ # controller
+ class ProjectsController < Projects::ApplicationController
+ 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
+
+ def index
+ render html: 'index'
+ end
+
+ def new
+ render html: 'new'
+ end
+
+ def show
+ render html: 'show'
+ end
+ end
+ ```
+
+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.
+
+ Arguments:
+
+ - `event_name`: event name.
+ - `values`: values counted, one value or array of values.
+
+ Example usage:
+
+ ```ruby
+ get ':id/registry/repositories' do
+ repositories = ContainerRepositoriesFinder.new(
+ user: current_user, subject: user_group
+ ).execute
+
+ increment_unique_values('i_list_repositories', current_user.id)
+
+ present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count]
+ end
+ ```
+
+1. Track event using `track_usage_event(event_name, values) in services and GraphQL
+
+ Increment unique values count using Redis HLL, for given event name.
+
+ 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 GraphQL](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/alert_management/update_alert_status.rb)
+
+ ```ruby
+ track_usage_event(:incident_management_incident_created, current_user.id)
+ ```
+
+<!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. -->
+
+1. Track event using `UsageData` API
+
+ Increment unique users count using Redis HLL, for given event name.
+
+ Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default.
+
+ 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
+ set to `default_enabled: true`. For more information, see
+ [Feature flags in development of GitLab](feature_flags/index.md).
+
+ ```plaintext
+ POST /usage_data/increment_unique_users
+ ```
+
+ | Attribute | Type | Required | Description |
+ | :-------- | :--- | :------- | :---------- |
+ | `event` | string | yes | The event name it should be tracked |
+
+ Response
+
+ Return 200 if tracking failed for any reason.
+
+ - `200` if event was tracked or any errors
+ - `400 Bad request` if event parameter is missing
+ - `401 Unauthorized` if user is not authenticated
+ - `403 Forbidden` for invalid CSRF token provided
+
+1. Track events using JavaScript/Vue API helper which calls the API above
+
+ Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/):
+
+ Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is
+ now set to `default_enabled: true`.
+
+ Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true`
+
+ ```javascript
+ import api from '~/api';
+
+ 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:
+
+ - `event_names`: the list of event names.
+ - `start_date`: start date of the period for which we want to get event data.
+ - `end_date`: end date of the period for which we want to get event data.
+ - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`.
+
+1. Testing tracking and getting unique events
+
+Trigger events in rails console by using `track_event` method
+
+ ```ruby
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: 1)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: [2, 3])
+ ```
+
+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)
+ ```
+
+##### Recommendations
+
+We have the following recommendations for [Adding new events](#adding-new-events):
+
+- Event aggregation: weekly.
+- Key expiry time:
+ - Daily: 29 days.
+ - Weekly: 42 days.
+- When adding new metrics, use a [feature flag](../operations/feature_flags.md) to control the impact.
+- For feature flags triggered by another service, set `default_enabled: false`,
+ - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change
+
+##### Enable/Disable Redis HLL tracking
+
+Events are tracked behind [feature flags](feature_flags/index.md) due to concerns for Redis performance and scalability.
+
+For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files.
+
+To enable or disable tracking for specific event within <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to
+[enable or disable the corresponding feature](feature_flags/index.md).
+
+```shell
+/chatops run feature set <feature_name> true
+/chatops run feature set <feature_name> false
+```
+
+##### Known events are added automatically in usage data payload
+
+All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209).
+For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable:
+
+- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events.
+- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events.
+
+Redis HLL implementation calculates automatic total metrics, if there are more than one metric for the same category, aggregation and Redis slot.
+
+- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric.
+- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric.
+
+Example of `redis_hll_counters` data:
+
+```ruby
+{:redis_hll_counters=>
+ {"compliance"=>
+ {"g_compliance_dashboard_weekly"=>0,
+ "g_compliance_dashboard_monthly"=>0,
+ "g_compliance_audit_events_weekly"=>0,
+ "g_compliance_audit_events_monthly"=>0,
+ "compliance_total_unique_counts_weekly"=>0,
+ "compliance_total_unique_counts_monthly"=>0},
+ "analytics"=>
+ {"g_analytics_contribution_weekly"=>0,
+ "g_analytics_contribution_monthly"=>0,
+ "g_analytics_insights_weekly"=>0,
+ "g_analytics_insights_monthly"=>0,
+ "analytics_total_unique_counts_weekly"=>0,
+ "analytics_total_unique_counts_monthly"=>0},
+ "ide_edit"=>
+ {"g_edit_by_web_ide_weekly"=>0,
+ "g_edit_by_web_ide_monthly"=>0,
+ "g_edit_by_sfe_weekly"=>0,
+ "g_edit_by_sfe_monthly"=>0,
+ "ide_edit_total_unique_counts_weekly"=>0,
+ "ide_edit_total_unique_counts_monthly"=>0},
+ "search"=>
+ {"i_search_total_weekly"=>0, "i_search_total_monthly"=>0, "i_search_advanced_weekly"=>0, "i_search_advanced_monthly"=>0, "i_search_paid_weekly"=>0, "i_search_paid_monthly"=>0, "search_total_unique_counts_weekly"=>0, "search_total_unique_counts_monthly"=>0},
+ "source_code"=>{"wiki_action_weekly"=>0, "wiki_action_monthly"=>0}
+ }
+```
+
+Example usage:
+
+```ruby
+# Redis Counters
+redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
+redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
+
+# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml
+
+# Tracking events
+Gitlab::UsageDataCounters::HLLRedisCounter.track_event('expand_vulnerabilities', values: visitor_id)
+
+# Get unique events for metric
+redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'expand_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) }
+```
+
+### Alternative Counters
+
+Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception.
+Mainly used for settings and configurations.
+
+Method: `alt_usage_data(value = nil, fallback: -1, &block)`
+
+Arguments:
+
+- `value`: a simple static value in which case the value is simply returned.
+- or a `block`: which is evaluated
+- `fallback: -1`: the common value used for any metrics that are failing.
+
+Example of usage:
+
+```ruby
+alt_usage_data { Gitlab::VERSION }
+alt_usage_data { Gitlab::CurrentSettings.uuid }
+alt_usage_data(999)
+```
+
+### Prometheus Queries
+
+In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely
+to provide useful data. Instead, Prometheus might be more appropriate, since most GitLab architectural
+components publish metrics to it that can be queried back, aggregated, and included as usage data.
+
+NOTE:
+Prometheus as a data source for Usage Ping is currently only available for single-node Omnibus installations
+that are running the [bundled Prometheus](../administration/monitoring/prometheus/index.md) instance.
+
+To query Prometheus for metrics, a helper method is available to `yield` a fully configured
+`PrometheusClient`, given it is available as per the note above:
+
+```ruby
+with_prometheus_client do |client|
+ response = client.query('<your query>')
+ ...
+end
+```
+
+Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb)
+for how to use its API to query for data.
+
+## Developing and testing Usage Ping
+
+### 1. Naming and placing the metrics
+
+Add the metric in one of the top level keys
+
+- `license`: for license related metrics.
+- `settings`: for settings related metrics.
+- `counts_weekly`: for counters that have data for the most recent 7 days.
+- `counts_monthly`: for counters that have data for the most recent 28 days.
+- `counts`: for counters that have data for all time.
+
+### 2. Use your Rails console to manually test counters
+
+```ruby
+# count
+Gitlab::UsageData.count(User.active)
+Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id)
+
+# count distinct
+Gitlab::UsageData.distinct_count(::Project, :creator_id)
+Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id))
+```
+
+### 3. Generate the SQL query
+
+Your Rails console returns the generated SQL queries.
+
+Example:
+
+```ruby
+pry(main)> Gitlab::UsageData.count(User.active)
+ (2.6ms) SELECT "features"."key" FROM "features"
+ (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4))
+ (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4))
+ (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000
+```
+
+### 4. Optimize queries with #database-lab
+
+Paste the SQL query into `#database-lab` to see how the query performs at scale.
+
+- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries.
+- GitLab.com’s production database has a 15 second timeout.
+- 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:
+
+- For counters that have a `time_period` test we add information for both cases:
+ - `time_period = {}` for all time periods
+ - `time_period = { created_at: 28.days.ago..Time.current }` for last 28 days period
+- Execution plan and query time before and after optimization
+- Query generated for the index and time
+- Migration output for up and down execution
+
+We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/). For more details, see the [database review guide](database_review.md#preparation-when-adding-or-modifying-queries).
+
+#### Optimization recommendations and examples
+
+- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445).
+- Use defined `start` and `finish`, and simple queries, because these values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155).
+- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316).
+- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000).
+
+### 5. Add the metric definition
+
+When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary).
+
+### 6. Add new metric to Versions Application
+
+Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column.
+
+### 7. Add the feature label
+
+Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature.
+
+### 8. Add a changelog file
+
+Ensure you comply with the [Changelog entries guide](changelog.md).
+
+### 9. Ask for a Product Intelligence Review
+
+On GitLab.com, we have DangerBot setup to monitor Product Intelligence related files and DangerBot recommends a Product Intelligence review. Mention `@gitlab-org/growth/product_intelligence/engineers` in your MR for a review.
+
+### 10. Verify your metric
+
+On GitLab.com, the Product Intelligence team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric.
+
+### Optional: Test Prometheus based Usage Ping
+
+If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify,
+then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components
+are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action
+is necessary, since Usage Ping should degrade gracefully in the absence of a running Prometheus server.
+
+There are currently three kinds of components that may export data to Prometheus, and which are included in Usage Ping:
+
+- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine
+- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components
+- various GitLab services such as Sidekiq and the Rails server that export their own metrics
+
+#### Test with an Omnibus container
+
+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
+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
+[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. 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
+
+This is the less recommended approach, since it comes with a number of difficulties when emulating a real GitLab deployment.
+
+The [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) is not currently set up to run a Prometheus server or `node_exporter` alongside other GitLab components. If you would
+like to do so, [Monitoring the GDK with Prometheus](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) is a good start.
+
+The [GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit) has limited support for testing Prometheus based Usage Ping.
+By default, it already comes with a fully configured Prometheus service that is set up to scrape a number of components,
+but with the following limitations:
+
+- It does not currently run a `gitlab-exporter` instance, so several `process_*` metrics from services such as Gitaly may be missing.
+- While it runs a `node_exporter`, `docker-compose` services emulate hosts, meaning that it would normally report itself to not be associated
+with any of the other services that are running. That is not how node metrics are reported in a production setup, where `node_exporter`
+always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore
+appear to be associated to any of the services running, since they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Usage Ping.
+
+## Aggregated metrics
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6.
+
+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:
+
+- 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:
+ - `OR`: removes duplicates and counts all entries that triggered any of listed events
+ - `AND`: removes duplicates and counts all elements that were observed triggering all of following events
+- events: list of events names (from [`known_events/`](#known-events-are-added-automatically-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes.
+- feature_flag: name of [development feature flag](feature_flags/development.md#development-type) that is checked before
+metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`.
+`feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag is checked.
+
+Example aggregated metric entries:
+
+```yaml
+- name: product_analytics_test_metrics_union
+ operator: OR
+ events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
+- name: product_analytics_test_metrics_intersection_with_feautre_flag
+ operator: AND
+ events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
+ feature_flag: example_aggregated_metric
+```
+
+Aggregated metrics are added under `aggregated_metrics` key in both `counts_weekly` and `counts_monthly` top level keys in Usage Ping payload.
+
+```ruby
+{
+ :counts_monthly => {
+ :deployments => 1003,
+ :successful_deployments => 78,
+ :failed_deployments => 275,
+ :packages => 155,
+ :personal_snippets => 2106,
+ :project_snippets => 407,
+ :promoted_issues => 719,
+ :aggregated_metrics => {
+ :product_analytics_test_metrics_union => 7,
+ :product_analytics_test_metrics_intersection_with_feautre_flag => 2
+ },
+ :snippets => 2513
+ }
+}
+```
+
+## Example Usage Ping payload
+
+The following is example content of the Usage Ping payload.
+
+```json
+{
+ "uuid": "0000000-0000-0000-0000-000000000000",
+ "hostname": "example.com",
+ "version": "12.10.0-pre",
+ "installation_type": "omnibus-gitlab",
+ "active_user_count": 999,
+ "recorded_at": "2020-04-17T07:43:54.162+00:00",
+ "edition": "EEU",
+ "license_md5": "00000000000000000000000000000000",
+ "license_id": null,
+ "historical_max_users": 999,
+ "licensee": {
+ "Name": "ABC, Inc.",
+ "Email": "email@example.com",
+ "Company": "ABC, Inc."
+ },
+ "license_user_count": 999,
+ "license_starts_at": "2020-01-01",
+ "license_expires_at": "2021-01-01",
+ "license_plan": "ultimate",
+ "license_add_ons": {
+ },
+ "license_trial": false,
+ "counts": {
+ "assignee_lists": 999,
+ "boards": 999,
+ "ci_builds": 999,
+ ...
+ },
+ "container_registry_enabled": true,
+ "dependency_proxy_enabled": false,
+ "gitlab_shared_runners_enabled": true,
+ "gravatar_enabled": true,
+ "influxdb_metrics_enabled": true,
+ "ldap_enabled": false,
+ "mattermost_enabled": false,
+ "omniauth_enabled": true,
+ "prometheus_enabled": false,
+ "prometheus_metrics_enabled": false,
+ "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com",
+ "signup_enabled": true,
+ "web_ide_clientside_preview_enabled": true,
+ "ingress_modsecurity_enabled": true,
+ "projects_with_expiration_policy_disabled": 999,
+ "projects_with_expiration_policy_enabled": 999,
+ ...
+ "elasticsearch_enabled": true,
+ "license_trial_ends_on": null,
+ "geo_enabled": false,
+ "git": {
+ "version": {
+ "major": 2,
+ "minor": 26,
+ "patch": 1
+ }
+ },
+ "gitaly": {
+ "version": "12.10.0-rc1-93-g40980d40",
+ "servers": 56,
+ "clusters": 14,
+ "filesystems": [
+ "EXT_2_3_4"
+ ]
+ },
+ "gitlab_pages": {
+ "enabled": true,
+ "version": "1.17.0"
+ },
+ "container_registry_server": {
+ "vendor": "gitlab",
+ "version": "2.9.1-gitlab"
+ },
+ "database": {
+ "adapter": "postgresql",
+ "version": "9.6.15",
+ "pg_system_id": 6842684531675334351
+ },
+ "analytics_unique_visits": {
+ "g_analytics_contribution": 999,
+ ...
+ },
+ "usage_activity_by_stage": {
+ "configure": {
+ "project_clusters_enabled": 999,
+ ...
+ },
+ "create": {
+ "merge_requests": 999,
+ ...
+ },
+ "manage": {
+ "events": 999,
+ ...
+ },
+ "monitor": {
+ "clusters": 999,
+ ...
+ },
+ "package": {
+ "projects_with_packages": 999
+ },
+ "plan": {
+ "issues": 999,
+ ...
+ },
+ "release": {
+ "deployments": 999,
+ ...
+ },
+ "secure": {
+ "user_container_scanning_jobs": 999,
+ ...
+ },
+ "verify": {
+ "ci_builds": 999,
+ ...
+ }
+ },
+ "usage_activity_by_stage_monthly": {
+ "configure": {
+ "project_clusters_enabled": 999,
+ ...
+ },
+ "create": {
+ "merge_requests": 999,
+ ...
+ },
+ "manage": {
+ "events": 999,
+ ...
+ },
+ "monitor": {
+ "clusters": 999,
+ ...
+ },
+ "package": {
+ "projects_with_packages": 999
+ },
+ "plan": {
+ "issues": 999,
+ ...
+ },
+ "release": {
+ "deployments": 999,
+ ...
+ },
+ "secure": {
+ "user_container_scanning_jobs": 999,
+ ...
+ },
+ "verify": {
+ "ci_builds": 999,
+ ...
+ }
+ },
+ "topology": {
+ "duration_s": 0.013836685999194742,
+ "application_requests_per_hour": 4224,
+ "query_apdex_weekly_average": 0.996,
+ "failures": [],
+ "nodes": [
+ {
+ "node_memory_total_bytes": 33269903360,
+ "node_memory_utilization": 0.35,
+ "node_cpus": 16,
+ "node_cpu_utilization": 0.2,
+ "node_uname_info": {
+ "machine": "x86_64",
+ "sysname": "Linux",
+ "release": "4.19.76-linuxkit"
+ },
+ "node_services": [
+ {
+ "name": "web",
+ "process_count": 16,
+ "process_memory_pss": 233349888,
+ "process_memory_rss": 788220927,
+ "process_memory_uss": 195295487,
+ "server": "puma"
+ },
+ {
+ "name": "sidekiq",
+ "process_count": 1,
+ "process_memory_pss": 734080000,
+ "process_memory_rss": 750051328,
+ "process_memory_uss": 731533312
+ },
+ ...
+ ],
+ ...
+ },
+ ...
+ ]
+ }
+}
+```
+
+## Notable changes
+
+In GitLab 13.5, `pg_system_id` was added to send the [PostgreSQL system identifier](https://www.2ndquadrant.com/en/blog/support-for-postgresqls-system-identifier-in-barman/).
+
+## Exporting Usage Ping SQL queries and definitions
+
+Two Rake tasks exist to export Usage Ping definitions.
+
+- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`.
+- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`.
+- The Rake tasks calculate the `alt_usage_data` metrics.
+
+In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively:
+
+```shell
+# for YAML export
+bin/rake gitlab:usage_data:dump_sql_in_yaml
+
+# for JSON export
+bin/rake gitlab:usage_data:dump_sql_in_json
+
+# You may pipe the output into a file
+bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml
+```
+
+## Generating and troubleshooting usage ping
+
+To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping).
diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md
new file mode 100644
index 00000000000..bae79689f3b
--- /dev/null
+++ b/doc/development/usage_ping/metrics_dictionary.md
@@ -0,0 +1,73 @@
+---
+stage: Growth
+group: Product Intelligence
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Metrics Dictionary Guide
+
+This guide describes Metrics Dictionary and how it's implemented
+
+## Metrics Definition and validation
+
+We are using [JSON Schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/schema.json) to validate the metrics definition.
+
+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` .
+- 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:
+
+| Field | Required | Additional information |
+|---------------------|----------|----------------------------------------------------------------|
+| `name` | yes | |
+| `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. |
+| `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. |
+| `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)
+YAML file includes an example metric definition, where the `uuid` metric is the GitLab
+instance unique identifier.
+
+```yaml
+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 intelligence
+time_frame: none
+data_source: database
+distribution: [ee, ce]
+tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
+```
diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md
index c971ff7cb52..3697ae34bf9 100644
--- a/doc/gitlab-basics/create-branch.md
+++ b/doc/gitlab-basics/create-branch.md
@@ -9,7 +9,7 @@ type: howto
A branch is an independent line of development in a [project](../user/project/index.md).
-When you create a new branch (in your [terminal](start-using-git.md) or with
+When you create a new branch (in your [terminal](start-using-git.md#create-a-branch) or with
[the web interface](../user/project/repository/web_editor.md#create-a-new-branch)),
you are creating a snapshot of a certain branch, usually the main `master` branch,
at its current state. From there, you can start to make your own changes without
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index 30f467c2b12..c4fe522e6a2 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -145,6 +145,8 @@ git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git
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:
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 22b10c32434..7f3e90dc6bd 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -167,14 +167,13 @@ original repository if you'd like.
### Download vs clone
-To create a copy of a remote repository files on your computer, you can either
-**download** or **clone** it. If you download it, you cannot sync it with the
+To create a copy of a remote repository's files on your computer, you can either
+**download** or **clone**. If you download, you cannot sync it with the
remote repository on GitLab.
-On the other hand, by cloning a repository, you'll download a copy of its
-files to your local computer, but preserve the Git connection with the remote
-repository, so that you can work on the its files on your computer and then
-upload the changes to GitLab.
+Cloning a repository is the same as downloading, except it preserves the Git connection
+with the remote repository. This allows you to modify the files locally and
+upload the changes to the remote repository on GitLab.
### Pull and push
diff --git a/doc/install/README.md b/doc/install/README.md
index f0aee9b6927..7ed478439e0 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -17,7 +17,7 @@ troubleshooting), and the cost of hosting.
Depending on your platform, select from the following available methods to
install GitLab:
-- [_Omnibus GitLab_](#installing-gitlab-using-the-omnibus-gitlab-package-recommended):
+- [_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):
@@ -42,16 +42,24 @@ Before you install GitLab, be sure to review the [system requirements](requireme
The system requirements include details about the minimum hardware, software,
database, and additional requirements to support GitLab.
-## Installing GitLab using the Omnibus GitLab package (recommended)
+## 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 flexibility and resilience, we recommend deploying
+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
@@ -79,9 +87,10 @@ package.
## Installing GitLab from source
-If the Omnibus GitLab package is not available in your distribution, you can
-install GitLab from source: Useful for unsupported systems like \*BSD. For an
-overview of the directory structure, read the [structure documentation](installation.md#gitlab-directory-structure).
+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)
@@ -94,8 +103,7 @@ the above methods, provided the cloud provider supports it.
- [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 DC/OS](https://d2iq.com/blog/gitlab-dcos): Install GitLab on Mesosphere DC/OS via the [GitLab-Mesosphere integration](https://about.gitlab.com/blog/2016/09/16/announcing-gitlab-and-mesosphere/).
-- [Install GitLab on DigitalOcean](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/): Install Omnibus GitLab on DigitalOcean.
+- [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.
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 28f04c1a7a7..8a8e3a053b6 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -8,7 +8,7 @@ type: howto
# Installing GitLab on Amazon Web Services (AWS)
This page offers a walkthrough of a common configuration
-for GitLab on AWS. You should customize it to accommodate your needs.
+for GitLab on AWS using the official GitLab Linux package. You should customize it to accommodate your needs.
NOTE:
For organizations with 1,000 users or less, the recommended AWS installation method is to launch an EC2 single box [Omnibus Installation](https://about.gitlab.com/install/) and implement a snapshot strategy for backing up the data. See the [1,000 user reference architecture](../../administration/reference_architectures/1k_users.md) for more.
@@ -44,22 +44,21 @@ Below is a diagram of the recommended architecture.
## AWS costs
-Here's a list of the AWS services we will use, with links to pricing information:
-
-- **EC2**: GitLab will deployed on shared hardware which means
- [on-demand pricing](https://aws.amazon.com/ec2/pricing/on-demand/)
- will apply. If you want to run it on a dedicated or reserved instance,
- consult the [EC2 pricing page](https://aws.amazon.com/ec2/pricing/) for more
- information on the cost.
-- **S3**: We will use S3 to store backups, artifacts, LFS objects, etc. See the
- [Amazon S3 pricing](https://aws.amazon.com/s3/pricing/).
-- **ELB**: A Classic Load Balancer will be used to route requests to the
- GitLab instances. See the [Amazon ELB pricing](https://aws.amazon.com/elasticloadbalancing/pricing/).
-- **RDS**: An Amazon Relational Database Service using PostgreSQL will be used. See the
- [Amazon RDS pricing](https://aws.amazon.com/rds/postgresql/pricing/).
-- **ElastiCache**: An in-memory cache environment will be used to provide a
- Redis configuration. See the
- [Amazon ElastiCache pricing](https://aws.amazon.com/elasticache/pricing/).
+GitLab uses the following AWS services, with links to pricing information:
+
+- **EC2**: GitLab is deployed on shared hardware, for which
+ [on-demand pricing](https://aws.amazon.com/ec2/pricing/on-demand/) applies.
+ If you want to run GitLab on a dedicated or reserved instance, see the
+ [EC2 pricing page](https://aws.amazon.com/ec2/pricing/) for information about
+ its cost.
+- **S3**: GitLab uses S3 ([pricing page](https://aws.amazon.com/s3/pricing/)) to
+ store backups, artifacts, and LFS objects.
+- **ELB**: A Classic Load Balancer ([pricing page](https://aws.amazon.com/elasticloadbalancing/pricing/)),
+ used to route requests to the GitLab instances.
+- **RDS**: An Amazon Relational Database Service using PostgreSQL
+ ([pricing page](https://aws.amazon.com/rds/postgresql/pricing/)).
+- **ElastiCache**: An in-memory cache environment ([pricing page](https://aws.amazon.com/elasticache/pricing/)),
+ used to provide a Redis configuration.
## Create an IAM EC2 instance role and profile
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index 22f32d69c02..d579e214efc 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -8,7 +8,7 @@ type: howto
# Installing GitLab on Google Cloud Platform
-This guide will help you install GitLab on a [Google Cloud Platform (GCP)](https://cloud.google.com/) instance.
+This guide will help you install GitLab on a [Google Cloud Platform (GCP)](https://cloud.google.com/) using the official GitLab Linux package. You should customize it to accommodate your needs.
NOTE:
Google provides a whitepaper for [deploying production-ready GitLab on
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 983c7ed577f..80f3f6ab092 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -271,10 +271,22 @@ sudo adduser --disabled-login --gecos 'GitLab' git
NOTE:
In GitLab 12.1 and later, only PostgreSQL is supported. In GitLab 13.0 and later, we [require PostgreSQL 11+](requirements.md#postgresql-requirements).
-1. Install the database packages:
+1. Install the database packages.
+
+ For Ubuntu 20.04 and later:
+
+ ```shell
+ sudo apt install -y postgresql postgresql-client libpq-dev postgresql-contrib
+ ```
+
+ For Ubuntu 18.04 and earlier, the available PostgreSQL doesn't meet the minimum
+ version requirement. You need to add PostgreSQL's repository:
```shell
- sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib
+ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
+ RELEASE=$(lsb_release -cs) echo "deb http://apt.postgresql.org/pub/repos/apt/ ${RELEASE}"-pgdg main | sudo tee /etc/apt/sources.list.d/pgdg.list
+ sudo apt update
+ sudo apt -y install postgresql-11 postgresql-client-11 libpq-dev
```
1. Verify the PostgreSQL version you have is supported by the version of GitLab you're
@@ -426,7 +438,7 @@ Clone Enterprise Edition:
```shell
# Clone GitLab repository
-sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab.git -b <X-Y-stable> gitlab
+sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab.git -b <X-Y-stable-ee> gitlab
```
Make sure to replace `<X-Y-stable>` with the stable branch that matches the
@@ -1041,3 +1053,34 @@ On RedHat/CentOS:
```shell
sudo yum groupinstall 'Development Tools'
```
+
+### Error compiling GitLab assets
+
+While compiling assets, you may receive the following error message:
+
+```plaintext
+Killed
+error Command failed with exit code 137.
+```
+
+This can occur when Yarn kills a container that runs out of memory. To fix this:
+
+1. Increase your system's memory to at least 8 GB.
+
+1. Run this command to clean the assets:
+
+ ```shell
+ sudo -u git -H bundle exec rake gitlab:assets:clean RAILS_ENV=production NODE_ENV=production
+ ```
+
+1. Run the `yarn` command again to resolve any conflicts:
+
+ ```shell
+ sudo -u git -H yarn install --production --pure-lockfile
+ ```
+
+1. Recompile the assets:
+
+ ```shell
+ sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+ ```
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index cced6d0a3f6..69983edc383 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -16,7 +16,7 @@ as the hardware requirements that are needed to install and use GitLab.
- Ubuntu (16.04/18.04/20.04)
- Debian (9/10)
-- CentOS (6/7/8)
+- CentOS (7/8)
- openSUSE (Leap 15.1/Enterprise Server 12.2)
- Red Hat Enterprise Linux (please use the CentOS packages and instructions)
- Scientific Linux (please use the CentOS packages and instructions)
@@ -35,6 +35,9 @@ For the installation options, see [the main installation page](README.md).
Installation of GitLab on these operating systems is possible, but not supported.
Please see the [installation from source guide](installation.md) and the [installation guides](https://about.gitlab.com/install/) for more information.
+Please see [OS versions that are no longer supported](https://docs.gitlab.com/omnibus/package-information/deprecated_os.html) for Omnibus installs page
+for a list of supported and unsupported OS versions as well as the last support GitLab version for that OS.
+
### Microsoft Windows
GitLab is developed for Linux-based operating systems.
@@ -163,11 +166,11 @@ Support for [PostgreSQL 9.6 and 10 has been removed in GitLab 13.0](https://abou
#### Additional requirements for GitLab Geo
-If you're using [GitLab Geo](../administration/geo/index.md):
-
-- We strongly recommend running Omnibus-managed instances as they are actively
- developed and tested. We aim to be compatible with most external (not managed
- by Omnibus) databases (for example, [AWS Relational Database Service (RDS)](https://aws.amazon.com/rds/)) but we don't guarantee compatibility.
+If you're using [GitLab Geo](../administration/geo/index.md), we strongly
+recommend running Omnibus GitLab-managed instances, as we actively develop and
+test based on those. We try to be compatible with most external (not managed by
+Omnibus GitLab) databases (for example, [AWS Relational Database Service (RDS)](https://aws.amazon.com/rds/)),
+but we can't guarantee compatibility.
## Puma settings
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index 81cbc42cf45..4bc9d39ae3f 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -104,14 +104,13 @@ you to use.
url: 'https://bitbucket.org/' }
```
- ---
-
Where `BITBUCKET_APP_KEY` is the Key and `BITBUCKET_APP_SECRET` the Secret
from the Bitbucket application page.
1. Save the configuration file.
-1. For the changes to take effect, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) if you installed via
- Omnibus GitLab, or [restart](../administration/restart_gitlab.md#installations-from-source) if installed from source.
+1. For the changes to take effect, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+ if you installed using Omnibus GitLab, or [restart](../administration/restart_gitlab.md#installations-from-source)
+ if you installed from source.
On the sign-in page there should now be a Bitbucket icon below the regular
sign-in form. Click the icon to begin the authentication process. Bitbucket asks
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 52275649a67..b1fc2573bb0 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -175,7 +175,7 @@ instances](#indexing-large-instances) below.
To enable Advanced Search, you need to have admin access to GitLab:
-1. Navigate to **Admin Area** (wrench icon), then **Settings > General**
+1. Navigate to **Admin Area**, then **Settings > General**
and expand the **Advanced Search** section.
NOTE:
@@ -205,6 +205,12 @@ To enable Advanced Search, you need to have admin access to GitLab:
**Admin Area > Settings > General > Advanced Search** and click **Save
changes**.
+NOTE:
+When your Elasticsearch cluster is down while Elasticsearch is enabled,
+you might have problems updating documents such as issues because your
+instance queues a job to index the change, but cannot find a valid
+Elasticsearch cluster.
+
### Advanced Search configuration
The following Elasticsearch settings are available:
@@ -259,7 +265,7 @@ You can improve the language support for Chinese and Japanese languages by utili
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** (wrench icon), then **Settings > General**..
+1. Navigate to the **Admin Area**, then **Settings > General**..
1. Expand the **Advanced Search** section and locate **Custom analyzers: language support**.
1. Enable plugin(s) support for **Indexing**.
1. Click **Save changes** for the changes to take effect.
@@ -279,11 +285,11 @@ For guidance on what to install, see the following Elasticsearch language plugin
To disable the Elasticsearch integration:
-1. Navigate to the **Admin Area** (wrench icon), then **Settings > General**.
+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. Click **Save changes** for the changes to take effect.
-1. (Optional) Delete the existing index:
+1. (Optional) Delete the existing indexes:
```shell
# Omnibus installations
@@ -311,10 +317,11 @@ used by the GitLab Advanced Search integration.
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:
@@ -346,7 +353,8 @@ To reclaim the `gitlab-production` index name, you need to first create a `secon
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`:
+alias, which would conflict with the existing index under `$PRIMARY_INDEX`, and will
+not create a separate Issue index:
```shell
# Omnibus installation
@@ -506,6 +514,15 @@ This should return something similar to:
In order to debug issues with the migrations you can check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog).
+### Retry a halted migration
+
+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
+in the background.
+
## GitLab Advanced Search Rake tasks
Rake tasks are available to:
@@ -522,8 +539,8 @@ 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 an empty index and assigns an alias for it 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 index and alias (if exists) on the Elasticsearch instance. |
+| [`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: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. |
@@ -979,3 +996,11 @@ 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
+
+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.
diff --git a/doc/integration/github.md b/doc/integration/github.md
index c65027e3585..858614a0571 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -12,7 +12,7 @@ with your GitHub account.
## Enabling GitHub OAuth
-To enable the GitHub OmniAuth provider, you need an OAuth 2 Client ID and Client Secret from GitHub. To get these credentials, sign into GitHub and follow their procedure for [Creating an OAuth App](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/).
+To enable the GitHub OmniAuth provider, you need an OAuth 2 Client ID and Client Secret from GitHub. To get these credentials, sign into GitHub and follow their procedure for [Creating an OAuth App](https://docs.github.com/apps/building-oauth-apps/creating-an-oauth-app/).
When you create an OAuth 2 app in GitHub, you need the following information:
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index 37c91aedb15..3bd3099e390 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -75,15 +75,20 @@ GitLab.com generates an application ID and secret key for you to use.
args: { scope: 'api' } }
```
-1. Change 'YOUR_APP_ID' to the Application ID from the GitLab.com application page.
+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. Change `'YOUR_APP_SECRET'` to the secret from the GitLab.com application page.
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. Based on how GitLab was installed, implement these changes by using
+ the appropriate method:
-On the sign in page there should now be a GitLab.com icon below the regular sign in form.
-Click the icon to begin the authentication process. GitLab.com asks the user to sign in and authorize the GitLab application.
-If everything goes well the user is returned to your GitLab instance and is signed in.
+ - 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.
+GitLab.com asks the user to sign in and authorize the GitLab application. If
+everything goes well, the user is returned to your GitLab instance and is
+signed in.
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index 04274c1c015..05f129e6049 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -8,14 +8,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
# Gitpod Integration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228893) in GitLab 13.4.
-> - It was [deployed behind a feature flag](#enable-or-disable-the-gitpod-integration), disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/258206) in GitLab 13.5.
-> - 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](#configure-your-gitlab-instance-with-gitpod). **(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/-/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
@@ -48,28 +41,14 @@ can follow the same steps once the integration has been enabled and configured b
## Configure your GitLab instance with Gitpod **(CORE ONLY)**
-If you are new to Gitpod, head over to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/)
-and get your instance up and running.
+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.
+
+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:
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`).
-
-## Enable or disable the Gitpod integration **(CORE ONLY)**
-
-The Gitpod integration is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
-can enable or disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:gitpod)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:gitpod)
-```
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index 7488df3580e..1c0b2bdc85e 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -211,7 +211,8 @@ The requested scope is invalid, unknown, or malformed.
Potential resolutions:
-- Verify the URL includes `scope=api` on the end of the URL.
+- 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.
+- 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
@@ -272,7 +273,13 @@ The GitLab user only needs access when adding a new namespace. For syncing with
![Configure namespace on GitLab Jira App](img/jira_dev_panel_setup_com_3.png)
-After a namespace is added, all future commits, branches, and merge requests of all projects under that namespace are synced to Jira. Past data cannot be synced at the moment.
+After a namespace is added:
+
+- All future commits, branches, and merge requests of all projects under that namespace
+ are synced to Jira.
+- From GitLab 13.8, past merge request data is synced to Jira.
+
+Support for syncing past branch and commit data [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/263240).
For more information, see [Usage](#usage).
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index 7f81fd3a7da..3c49cd47509 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -13,12 +13,12 @@ type: reference, howto
It allows you to store and manage sensitive information such as secret environment variables, encryption keys, and authentication tokens.
Vault offers Identity-based Access, which means Vault users can authenticate through several of their preferred cloud providers.
-In this document, we'll explain how Vault users can authenticate themselves through GitLab by utilizing our OpenID authentication feature.
+This document explains how Vault users can authenticate themselves through GitLab by utilizing our OpenID authentication feature.
The following assumes you already have Vault installed and running.
1. **Get the OpenID Connect client ID and secret from GitLab:**
- First you'll need to 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:
+ 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),
@@ -71,7 +71,7 @@ The following assumes you already have Vault installed and running.
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:
- This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we'll show how you can access this role through the Vault CLI.
+ This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we show how you can access this role through the Vault CLI.
```shell
vault write auth/oidc/role/demo \
@@ -88,11 +88,11 @@ The following assumes you already have Vault installed and running.
1. Go to your Vault UI (example: [http://127.0.0.1:8200/ui/vault/auth?with=oidc](http://127.0.0.1:8200/ui/vault/auth?with=oidc)).
1. If the `OIDC` method is not currently selected, open the dropdown and select it.
- 1. Click the **Sign in With GitLab** button, which will open a modal window:
+ 1. Click the **Sign in With GitLab** button, which opens a modal window:
![Sign into Vault with GitLab](img/sign_into_vault_with_gitlab_v12_6.png)
- 1. Click **Authorize** on the modal to allow Vault to sign in through GitLab. This will redirect you back to your Vault UI as a signed-in user.
+ 1. Click **Authorize** on the modal to allow Vault to sign in through GitLab. This redirects you back to your Vault UI as a signed-in user.
![Authorize Vault to connect with GitLab](img/authorize_vault_with_gitlab_v12_6.png)
@@ -116,12 +116,12 @@ The following assumes you already have Vault installed and running.
another port number that matches the port given to GitLab when listing
[Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
- After running the command, it will present a link in the terminal.
- Click the link in the terminal and a tab will open in the browser confirming you're signed into Vault via OIDC:
+ After running the command, it presents a link in the terminal.
+ Click the link in the terminal and a browser tab opens that confirms you're signed into Vault via OIDC:
![Signed into Vault via OIDC](img/signed_into_vault_via_oidc_v12_6.png)
- The terminal will output:
+ The terminal outputs:
```plaintext
Success! You are now authenticated. The token information displayed below
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index e22a45fc18c..9ce7eb0ede2 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -226,9 +226,9 @@ To remove users from a user list:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) in GitLab 12.2.
> - [Made read-only](https://gitlab.com/gitlab-org/gitlab/-/issues/220228) in GitLab 13.4.
-In GitLab 13.0 and earlier, the **Rollout strategy** setting affects which users will experience
-the feature as enabled. Choose the percentage of users that the feature will be enabled
-for. The rollout strategy will have no effect if the environment spec is disabled.
+In GitLab 13.0 and earlier, the **Rollout strategy** setting affects which users experience
+the feature as enabled. Choose the percentage of users that the feature is enabled
+for. The rollout strategy has no effect if the environment spec is disabled.
It can be set to:
@@ -282,7 +282,7 @@ To get the access credentials that your application needs to communicate with Gi
could be `production` or similar. This value is used for the environment spec evaluation.
Note that the meaning of these fields might change over time. For example, we're not sure if
-**Instance ID** will be single token or multiple tokens, assigned to the **Environment**. Also,
+**Instance ID** is a single token or multiple tokens, assigned to the **Environment**. Also,
**Application name** could describe the application version instead of the running environment.
### Choose a client library
diff --git a/doc/operations/incident_management/alert_integrations.md b/doc/operations/incident_management/alert_integrations.md
index 70c4e7f2f29..0f695e7a6c9 100644
--- a/doc/operations/incident_management/alert_integrations.md
+++ b/doc/operations/incident_management/alert_integrations.md
@@ -79,11 +79,11 @@ 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 other than `title` are optional:
+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. Required. |
+| `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. |
@@ -170,13 +170,14 @@ If the existing alert is already `resolved`, GitLab creates a new alert instead.
## 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 within
+[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 scheduled for deprecation following the 13.7 release on December 22, 2020.
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+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).
diff --git a/doc/operations/incident_management/img/incident_metrics_tab_v13_8.png b/doc/operations/incident_management/img/incident_metrics_tab_v13_8.png
new file mode 100644
index 00000000000..27345b09419
--- /dev/null
+++ b/doc/operations/incident_management/img/incident_metrics_tab_v13_8.png
Binary files differ
diff --git a/doc/operations/incident_management/img/metric_image_url_dialog_v13_8.png b/doc/operations/incident_management/img/metric_image_url_dialog_v13_8.png
new file mode 100644
index 00000000000..732921bbb9f
--- /dev/null
+++ b/doc/operations/incident_management/img/metric_image_url_dialog_v13_8.png
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 074cacd2e30..3f6522b3f90 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -10,6 +10,9 @@ Incidents are critical entities in incident management workflows. They represent
a service disruption or outage that needs to be restored urgently. GitLab provides
tools for the triage, response, and remediation of incidents.
+Users with at least Guest [permissions](../../user/permissions.md) can access
+incidents [on public projects](../../user/permissions.md#project-members-permissions).
+
## Incident Creation
You can create an incident manually or automatically.
@@ -126,7 +129,7 @@ For a live example of the incident list in action, visit this
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230847) in GitLab 13.4.
-Users with at least Reporter [permissions](../../user/permissions.md) can view
+Users with at least Guest [permissions](../../user/permissions.md) can view
the Incident Details page. Navigate to **Operations > Incidents** in your project's
sidebar, and select an incident from the list.
@@ -160,6 +163,19 @@ Beneath the highlight bar, GitLab displays a summary that includes the following
Comments are displayed in threads, but can be displayed chronologically
[in a timeline view](#timeline-view).
+### Metrics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235994) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.8.
+
+In many cases, incidents are associated to metrics. You can upload screenshots of metric
+charts in the **Metrics** tab:
+
+![Incident Metrics tab](img/incident_metrics_tab_v13_8.png)
+
+When you upload an image, you can associate it with a URL to the original graph. Users can access the original graph by clicking the image:
+
+![Metric image URL dialog](img/metric_image_url_dialog_v13_8.png)
+
### Alert details
Incidents show the details of linked alerts in a separate tab. To populate this
diff --git a/doc/public_access/img/project_visibility_confirmation_v12_6.png b/doc/public_access/img/project_visibility_confirmation_v12_6.png
deleted file mode 100644
index 8fba57f353b..00000000000
--- a/doc/public_access/img/project_visibility_confirmation_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index 8d751d10aa5..5d07095ac3e 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -92,16 +92,6 @@ by accident. The restricted visibility settings do not apply to admin users.
For details, see [Restricted visibility levels](../user/admin_area/settings/visibility_and_access_controls.md#restricted-visibility-levels).
-## Reducing visibility
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33358) in GitLab 12.6.
-
-Reducing a project's visibility level removes the fork relationship between the project and
-any forked project. This is a potentially destructive action which requires confirmation before
-this can be saved.
-
-![Project visibility change confirmation](img/project_visibility_confirmation_v12_6.png)
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 99a5ac8ed3b..4f902382fd5 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -84,21 +84,21 @@ override them in a project's settings. They can be also set on a [group level](.
1. Set the rule you want
1. Click **Save Push Rules** for the changes to take effect
-The following options are available.
-
-| Push rule | GitLab version | Description |
-| --------- | :------------: | ----------- |
-| Removal of tags with `git push` | **Starter** 7.10 | 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 | **Starter** 7.10 | Restrict commits by author (email) to existing GitLab users. |
-| Committer restriction | **Premium** 10.2 | GitLab will reject any commit that was not committed by the current authenticated user |
-| Check whether commit is signed through GPG | **Premium** 10.1 | 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 | **Starter** 8.12 | 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 | **Starter** 7.10 | 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)| **Starter** 11.1 | 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 | **Starter** 9.3 | 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 | **Starter** 7.10 | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. |
-| Prohibited file names | **Starter** 7.10 | 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). |
-| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
+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. |
+| 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)`. |
+| 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). |
+| Maximum file size | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
NOTE:
GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/).
@@ -174,15 +174,15 @@ id_ecdsa
#####################
# Any file ending with _history or .history extension
#####################
-pry.history
-bash_history
+*.history
+*_history
```
## Prohibited file names
> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 7.10.
-Each file name 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.
+Each filename contained in a Git push is compared to the regular expression in this field. Filenames in Git consist of both the file's name and any directory that may precede it. A singular regular expression can contain multiple independent matches used as exclusions. File names can be broadly matched to any location in the repository, or restricted to specific locations. Filenames can also be partial matches used to exclude file types by extension.
The following examples make use of regex string boundary characters which match the beginning of a string (`^`), and the end (`$`). They also include instances where either the directory path or the filename can include `.` or `/`. Both of these special regex characters have to be escaped with a backslash `\\` to be used as normal characters in a match condition.
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index a42bf2a5d91..e119563fd25 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -42,7 +42,7 @@ The following are available Rake tasks:
| [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/product_analytics/usage_ping.md).|
+| [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/backup_restore.md b/doc/raketasks/backup_restore.md
index 03ffd6bd6ad..8a01975f771 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -61,6 +61,7 @@ including:
- Container Registry images
- GitLab Pages content
- Snippets
+- Group wikis **(PREMIUM)**
WARNING:
GitLab does not back up any configuration files, SSL certificates, or system
@@ -890,7 +891,7 @@ Restoring repositories:
Deleting tmp directories...[DONE]
```
-Next, restore `/home/git/gitlab/.secret` if necessary, as previously mentioned.
+Next, restore `/home/git/gitlab/.secret` if necessary, [as previously mentioned](#restore-prerequisites).
Restart GitLab:
@@ -943,8 +944,16 @@ permissions on your Registry directory. This is a [known issue](https://gitlab.c
On GitLab 12.2 or later, you can use `gitlab-backup restore` to avoid this
issue.
-Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary, as previously
-mentioned.
+If there's a GitLab version mismatch between your backup tar file and the
+installed version of GitLab, the restore command aborts with an error
+message. Install the [correct GitLab version](https://packages.gitlab.com/gitlab/),
+and then try again.
+
+NOTE:
+There is a known issue with restore not working with `pgbouncer`. [Read more about backup and restore with `pgbouncer`](#backup-and-restore-for-installations-using-pgbouncer).
+
+Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary,
+[as previously mentioned](#restore-prerequisites).
Reconfigure, restart and check GitLab:
@@ -954,13 +963,13 @@ sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true
```
-If there's a GitLab version mismatch between your backup tar file and the
-installed version of GitLab, the restore command aborts with an error
-message. Install the [correct GitLab version](https://packages.gitlab.com/gitlab/),
-and then try again.
+On GitLab 13.1 and later, check [database values can be decrypted](../administration/raketasks/doctor.md)
+especially if `/etc/gitlab/gitlab-secrets.json` was restored, or if a different server is
+the target for the restore.
-NOTE:
-There is a known issue with restore not working with `pgbouncer`. [Read more about backup and restore with `pgbouncer`](#backup-and-restore-for-installations-using-pgbouncer).
+```shell
+sudo gitlab-rake gitlab:doctor:secrets
+```
### Restore for Docker image and GitLab Helm chart installations
@@ -1068,6 +1077,13 @@ following error message is shown:
ActiveRecord::StatementInvalid: PG::UndefinedTable
```
+Each time the GitLab backup runs, GitLab will start generating 500 errors and errors about missing
+tables will [be logged by PostgreSQL](../administration/logs.md#postgresql-logs):
+
+```plaintext
+ERROR: relation "tablename" does not exist at character 123
+```
+
This happens because the task uses `pg_dump`, which [sets a null search
path and explicitly includes the schema in every SQL query](https://gitlab.com/gitlab-org/gitlab/-/issues/23211)
to address [CVE-2018-1058](https://www.postgresql.org/about/news/postgresql-103-968-9512-9417-and-9322-released-1834/).
diff --git a/doc/raketasks/migrate_snippets.md b/doc/raketasks/migrate_snippets.md
index 8050a8a38e5..244ff4f2b56 100644
--- a/doc/raketasks/migrate_snippets.md
+++ b/doc/raketasks/migrate_snippets.md
@@ -14,7 +14,7 @@ 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 file name used in the snippet
+to the repository inside a file whose name is the filename used in the snippet
as well.
GitLab performs this migration through a [Background Migration](../development/background_migrations.md)
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index f159b4f8e21..d80de92501e 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -54,11 +54,7 @@ By default, protected paths are:
- `/import/github/personal_access_token`
- `/admin/session`
-This header is included in responses to blocked requests:
-
-```plaintext
-Retry-After: 60
-```
+See [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests.
For example, the following are limited to a maximum 10 requests per minute:
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index 0bb8e90d38f..bed998a5c84 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -26,7 +26,7 @@ sent.
Webhook requests are made by the GitLab server itself and use a single
(optional) secret token per hook for authorization (instead of a user or
-repo-specific token). As a result, these may have broader access than
+repository-specific token). As a result, these may have broader access than
intended to everything running on the server hosting the webhook (which
may include the GitLab server or API itself, e.g., `http://localhost:123`).
Depending on the called webhook, this may also result in network access
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index 7dd08da74f9..aef1c1127c5 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -1,6 +1,6 @@
---
-stage: fulfillment
-group: fulfillment
+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
type: index, reference
---
@@ -106,15 +106,46 @@ to the **Billing** section of the relevant namespace:
The following table describes details of your subscription for groups:
- | Field | Description |
- |-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
- | **Seats in subscription** | If this is a paid plan, represents the number of seats you've paid to support in your group. |
- | **Seats currently in use** | Number of seats in use. |
- | **Max seats used** | Highest number of seats you've used. If this exceeds the seats in subscription, you may owe an additional fee for the additional users. |
- | **Seats owed** | If your maximum seats used exceeds the seats in your subscription, you owe an additional fee for the users you've added. |
- | **Subscription start date** | Date your subscription started. If this is for a Free plan, is the date you transitioned off your group's paid plan. |
- | **Subscription end date** | Date your current subscription ends. Does not apply to Free plans. |
- | **Billable users list** | List of users that belong to your group subscription. 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
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216899) in GitLab 13.5.
+> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/292086) in GitLab 13.8 to include public
+ email address.
+
+The **Seat usage** page lists all users occupying seats. Details for each user include:
+
+- Full name
+- Username
+- Public email address (if they have provided one in their [profile settings](../../user/profile/index.md#profile-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
+and the billing page.
+
+### Search seat usage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/262875) in GitLab 13.8.
+
+To search users in the **Seat usage** page, enter a string in the search field. A minimum of 3
+characters are required.
+
+The search returns those users whose first name, last name, or username contain the search string.
+
+For example:
+
+| First name | Search string | Match ? |
+|:-----------|:--------------|:--------|
+| Amir | `ami` | Yes |
+| Amir | `amr` | No |
## Renew your GitLab.com subscription
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index d80a2ebe179..383ba471df4 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+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
type: index, reference
---
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 301d78b708a..a9c0337509a 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+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
type: index, reference
---
@@ -11,6 +11,16 @@ You can install, administer, and maintain your own GitLab instance.
This page covers the details of your GitLab self-managed subscription.
+GitLab subscription management requires access to the Customers Portal.
+
+## Customers Portal
+
+GitLab provides the [Customers Portal](../index.md#customers-portal) where you can
+manage your subscriptions and your account details.
+
+Customers of resellers do not have access to this portal and should contact their reseller for any
+changes to their subscription.
+
## Subscription
The cost of a GitLab self-managed subscription is determined by the following:
@@ -43,7 +53,7 @@ billable user, with the following exceptions:
count toward overages in the subscribed seat count.
- Users who are [pending approval](../../user/admin_area/approving_users.md).
- Members with Guest permissions on an Ultimate subscription.
-- GitLab-created service accounts: `Ghost User` and bots (`Support Bot`, [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and so on).
+- GitLab-created service accounts: `Ghost User` and bots [(`Support Bot`](../../user/project/service_desk.md#support-bot-user), [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and so on).
### Tips for managing users and subscription seats
@@ -95,10 +105,10 @@ It also displays the following important statistics:
| Field | Description |
|:-------------------|:------------|
-| Users in License | The number of users you've paid for in the current license loaded on the system. This does not include the amount you've paid for `Users over license` during renewal. |
-| Billable users | The daily count of billable users on your system. |
-| Maximum users | The highest number of billable users on your system during the term of the loaded license. If this number exceeds your users in license count at any point, you incur users over license. |
-| Users over license | The number of users that exceed the `Users in License` for the current license term. Charges for this number of users are incurred at the next renewal. |
+| Users in License | The number of users you've paid for in the current license loaded on the system. The number does not change unless you [add seats](#add-seats-to-a-subscription) during your current subscription period. |
+| Billable users | The daily count of billable users on your system. The count may change as you block or add users to your instance. |
+| Maximum users | The highest number of billable users on your system during the term of the loaded license. |
+| Users over license | Calculated as `Maximum users` - `Users in License` for the current license term. This number incurs a retroactive charge that needs to be paid for at renewal. |
## Renew your subscription
@@ -122,28 +132,38 @@ the contact person who manages your subscription.
It's important to regularly review your user accounts, because:
-- A GitLab subscription is based on the number of users. You pay more than you should if you renew
- for too many users, while the renewal fails if you attempt to renew a subscription for too few
- users.
+- Stale user accounts that are not blocked count as billable users. You may pay more than you should
+ if you renew for too many users.
- Stale user accounts can be a security risk. A regular review helps reduce this risk.
#### Users over License
-A GitLab subscription is valid for a specific number of users. For details, see
-[Billable users](#billable-users). If the billable user
-count 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 as the _true up_ process.
+A GitLab subscription is valid for a specific number of seats. The number of users over license
+is the number of _Maximum users_ that exceed the _Users in License_ for the current license term.
+You must pay for this number of users either before renewal, or at the time of renewal. This is
+known as the _true up_ process.
+
+To view the number of _users over license_ go to the **Admin Area**.
-To view the number of _Users over License_ go to the **Admin Area**.
+##### Users over license example
-### Add users to a subscription
+You purchase a license for 10 users.
-Self-managed instances can add users to a subscription any time during the
-subscription period. The cost of additional users added during the subscription
+| Event | Billable members | Maximum users |
+|:---------------------------------------------------|:-----------------|:--------------|
+| Ten people (users) occupy all 10 seats. | 10 | 10 |
+| Two new people join. | 12 | 12 |
+| Three people leave and their accounts are removed. | 9 | 12 |
+
+Users over license = 12 - 10 (Maximum users - users in license)
+
+### Add seats to a subscription
+
+The users in license count can be increased by adding seats to a subscription any time during the
+subscription period. The cost of seats added during the subscription
period is prorated from the date of purchase through the end of the subscription period.
-To add users to a subscription:
+To add seats to a subscription:
1. Log in to the [Customers Portal](https://customers.gitlab.com/).
1. Navigate to the **Manage Purchases** page.
@@ -185,7 +205,7 @@ An invoice is generated for the renewal and available for viewing or download on
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 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.
+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 provides **only** the following information to GitLab:
@@ -312,11 +332,6 @@ only.
However, if you remove the license, you immediately revert to Core
features, and the instance become read / write again.
-## Customers Portal
-
-GitLab provides the [Customers Portal](../index.md#customers-portal) where you can
-manage your subscriptions and your account details.
-
## Contact Support
Learn more about:
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index b3a74e62ba8..7e4d274f21b 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -535,9 +535,11 @@ X-Gitlab-Event: System Hook
{
"object_kind": "merge_request",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "email": "admin@example.com"
},
"project": {
"name": "Example",
diff --git a/doc/telemetry/index.md b/doc/telemetry/index.md
index 57740672fb4..b3b3b0b4fdd 100644
--- a/doc/telemetry/index.md
+++ b/doc/telemetry/index.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../development/product_analytics/index.md'
+redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
---
-This document was moved to [another location](../development/product_analytics/index.md).
+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
index ac157a8e639..709c61b9e64 100644
--- a/doc/telemetry/snowplow.md
+++ b/doc/telemetry/snowplow.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../development/product_analytics/snowplow.md'
+redirect_to: '../development/snowplow.md'
---
-This document was moved to [another location](../development/product_analytics/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/autodevops/index.md b/doc/topics/autodevops/index.md
index 7234bca8e12..78be67a5196 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -30,9 +30,12 @@ configuration. Automation enables consistency across your projects, seamless
management of processes, and faster creation of new projects: push your code,
and GitLab does the rest, improving your productivity and efficiency.
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an introduction to Auto DevOps, watch [AutoDevOps in GitLab 11.0](https://youtu.be/0Tc0YYBxqi4).
-For requirements, see [Requirements for Auto DevOps](requirements.md) for more information.
+For requirements, read [Requirements for Auto DevOps](requirements.md) for more information.
+
+For a developer's guide, read [Auto DevOps development guide](../../development/auto_devops.md).
## Enabled by default
@@ -307,6 +310,11 @@ and verifying your application is deployed as a Review App in the Kubernetes
cluster with the `review/*` environment scope. Similarly, you can check the
other environments.
+[Cluster environment scope isn't respected](https://gitlab.com/gitlab-org/gitlab/-/issues/20351)
+when checking for active Kubernetes clusters. For multi-cluster setup to work with Auto DevOps,
+create a fallback cluster with **Cluster environment scope** set to `*`. A new cluster isn't
+required. You can use any of the clusters already added.
+
## Limitations
The following restrictions apply.
@@ -481,7 +489,7 @@ that works for this problem. Follow these steps to use the tool in Auto DevOps:
### Error: error initializing: Looks like "https://kubernetes-charts.storage.googleapis.com" is not a valid chart repository or cannot be reached
-As [announced in the official CNCF blogpost](https://www.cncf.io/blog/2020/10/07/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/),
+As [announced in the official CNCF blog post](https://www.cncf.io/blog/2020/10/07/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/),
the stable Helm chart repository was deprecated and removed on November 13th, 2020.
You may encounter this error after that date.
@@ -526,7 +534,7 @@ To fix your custom chart:
it's used to verify the integrity of the downloaded dependencies.
You can find more information in
-[issue #263778, "Migrate PostgreSQL from stable Helm repo"](https://gitlab.com/gitlab-org/gitlab/-/issues/263778).
+[issue #263778, "Migrate PostgreSQL from stable Helm repository"](https://gitlab.com/gitlab-org/gitlab/-/issues/263778).
### Error: release .... failed: timed out waiting for the condition
@@ -545,7 +553,7 @@ page of the deployed application on port 5000. If your application isn't configu
to serve anything at the root page, or is configured to run on a specific port
*other* than 5000, this check fails.
-If it fails, you should see these failures within the events for the relevant
+If it fails, you should see these failures in the events for the relevant
Kubernetes namespace. These events look like the following example:
```plaintext
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 5c3b296fdea..effdb4d7b75 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -25,7 +25,7 @@ Sign in with an existing Google account, such as the one you use to access Gmail
or Google Drive, or create a new one.
1. Follow the steps described in the ["Before you begin" section](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)
- of the Kubernetes Engine docs to enable the required APIs and related services.
+ of the Kubernetes Engine documentation to enable the required APIs and related services.
1. Ensure you've created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account)
with Google Cloud Platform.
@@ -101,30 +101,41 @@ to deploy this project to.
After a couple of minutes, the cluster is created. You can also see its
status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
-Next, install some applications on your cluster that are needed
-to take full advantage of Auto DevOps.
+## Install Ingress
-## Install Ingress and Prometheus
+After your cluster is running, you must install NGINX Ingress Controller as a
+load balancer, to route traffic from the internet to your application. Because
+you've created a Google GKE cluster in this guide, you can install NGINX Ingress Controller
+with Google Cloud Shell:
-After your cluster is running, you can install your first applications,
-Ingress and Prometheus:
+1. Go to your cluster's details page, and click the **Advanced Settings** tab.
+1. Click the link to Google Kubernetes Engine to visit the cluster on Google Cloud Console.
+1. On the GKE cluster page, select **Connect**, then click **Run in Cloud Shell**.
+1. After the Cloud Shell starts, run these commands to install NGINX Ingress Controller:
-- Ingress - Provides load balancing, SSL termination, and name-based virtual hosting,
- using NGINX behind the scenes.
-- Prometheus - An open-source monitoring and alerting system used to supervise the
- deployed application.
+ ```shell
+ helm repo add nginx-stable https://helm.nginx.com/stable
+ helm repo update
+ helm install nginx-ingress nginx-stable/nginx-ingress
-We aren't installing GitLab Runner in this quick start guide, as this guide uses the
-shared runners provided by GitLab.com.
+ # Check that the ingress controller is installed successfully
+ kubectl get service nginx-ingress-nginx-ingress
+ ```
+
+1. A few minutes after you install NGINX, the load balancer obtains an IP address, and you can
+ get the external IP address with this command:
+
+ ```shell
+ kubectl get service nginx-ingress-nginx-ingress -ojson | jq -r '.status.loadBalancer.ingress[].ip'
+ ```
-To install the applications:
+ Copy this IP address, as you need it in the next step.
-- Click the **Install** button for **Ingress**.
-- When the **Ingress Endpoint** is displayed, copy the IP address.
-- Add your **Base domain**. For this guide, use the domain suggested by GitLab.
-- Click **Save changes**.
+1. Go back to the cluster page on GitLab, and go to the **Details** tab.
+ - Add your **Base domain**. For this guide, use the domain `<IP address>.nip.io`.
+ - Click **Save changes**.
-![Cluster Base Domain](img/guide_base_domain_v12_3.png)
+ ![Cluster Base Domain](img/guide_base_domain_v12_3.png)
## Enable Auto DevOps (optional)
@@ -290,7 +301,7 @@ and then deploys the application to production.
After implementing this project, you should have a solid understanding of the basics of Auto DevOps.
You started from building and testing, to deploying and monitoring an application
-all within GitLab. Despite its automatic nature, Auto DevOps can also be configured
+all in GitLab. Despite its automatic nature, Auto DevOps can also be configured
and customized to fit your workflow. Here are some helpful resources for further reading:
1. [Auto DevOps](index.md)
diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
index c45390e935d..663060bf59d 100644
--- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
+++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
@@ -161,7 +161,7 @@ For example, if the template is bundled in GitLab v13.3, change your `.gitlab-ci
```yaml
include:
- template: Auto-DevOps.gitlab-ci.yml
- - remote: https://gitlab.com/gitlab-org/gitlab/-/blob/v13.3.0-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+ - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.3.0-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
```
### Ignore warnings and continue deploying
@@ -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/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+ - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/master/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
```
WARNING:
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index f6e0cdee2cf..6179175b4cd 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -96,7 +96,7 @@ 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.
-### Migrate an existing repo to Git LFS
+### Migrate an existing repository to Git LFS
Read the documentation on how to [migrate an existing Git repository with Git LFS](migrate_to_git_lfs.md).
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 30be9c42f01..3bd754aabfb 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
@@ -71,7 +71,7 @@ Fire up a terminal, navigate to your Git repository and:
git push
```
-### Disabling Git Annex in your repo
+### 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
@@ -164,7 +164,7 @@ 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
the next section.
-### Enabling Git LFS in your repo
+### Enabling Git LFS in your repository
Git LFS is enabled by default on all GitLab products (GitLab CE, GitLab EE,
GitLab.com), therefore, you don't need to do anything server-side.
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index 941fc281e4c..ef2675db6d4 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: "How to migrate an existing Git repository to Git LFS with BFG."
---
-# Migrate a Git repo into Git LFS with BFG
+# Migrate a Git repository into Git LFS with BFG
Using Git LFS can help you to reduce the size of your Git
repository and improve its performance.
@@ -38,7 +38,6 @@ Before beginning, make sure:
Storage is required for the entire history of all files.
- All the team members you share the repository with have pushed all changes.
Branches based on the repository before applying this method cannot be merged.
- Branches based on the repo before applying this method cannot be merged.
To follow this tutorial, you need:
@@ -74,7 +73,7 @@ Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs-
1. Clone `--mirror` the repository:
Cloning with the mirror flag creates a bare repository.
- This ensures you get all the branches within the repo.
+ This ensures you get all the branches within the repository.
It creates a directory called `<repo-name>.git`
(in our example, `test-git-lfs-repo-migration.git`),
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 8fc2259c83e..f6571c7b277 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -493,6 +493,8 @@ An alternative is the open source community-maintained tool [BFG](https://rtyley
Keep in mind that these tools are faster because they do not provide the same
feature set as `git filter-branch` does, but focus on specific use cases.
+Refer [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) page to know more about purging files from repository history & GitLab storage.
+
## Conclusion
There are various options of undoing your work with any version control system, but
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index 590a37d0128..fa42cfd6e5b 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -229,7 +229,7 @@ remove filtering:
`pack-<SHA1>.promisor` file, which should be empty and should be deleted.
1. Remove partial clone configuration. The partial clone-related configuration
- variables should be removed from Git config files. Usually only the following
+ variables should be removed from Git configuration files. Usually only the following
configuration must be removed:
- `remote.origin.promisor`.
- `remote.origin.partialclonefilter`.
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 292e35922d6..87d8129dc7f 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -22,7 +22,7 @@ It offers a simple, transparent, and effective way to work with Git.
When converting to Git, you have to get used to the fact that it takes three steps to share a commit with colleagues.
Most version control systems have only one step: committing from the working copy to a shared server.
-In Git, you add files from the working copy to the staging area. After that, you commit them to your local repo.
+In Git, you add files from the working copy to the staging area. After that, you commit them to your local repository.
The third step is pushing to a shared remote repository.
After getting used to these three steps, the next challenge is the branching model.
diff --git a/doc/topics/web_application_firewall/index.md b/doc/topics/web_application_firewall/index.md
index 1c1728d9277..297b2f7eaaa 100644
--- a/doc/topics/web_application_firewall/index.md
+++ b/doc/topics/web_application_firewall/index.md
@@ -1,97 +1,8 @@
---
-stage: Protect
-group: Container Security
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../user/project/clusters/protect/web_application_firewall/index.md'
---
+This document was moved to [another location](../../user/project/clusters/protect/web_application_firewall/index.md).
-# Web Application Firewall - ModSecurity
-
-A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to
-and from a web application. By inspecting HTTP traffic, it can prevent attacks
-stemming from web application security flaws. It can be used to detect SQL injection,
-Cross-Site Scripting (XSS), Remote File Inclusion, Security Misconfigurations, and
-much more.
-
-## Overview
-
-GitLab provides a WAF out of the box after Ingress is deployed. All you need to do is deploy your
-application along with a service and Ingress resource. In the GitLab [Ingress](../../user/clusters/applications.md#ingress)
-deployment, the [ModSecurity](https://modsecurity.org/)
-module is loaded into Ingress-NGINX by default and monitors the traffic to the applications
-which have an Ingress. The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/)
-by default. The OWASP CRS detects and logs a wide range of common attacks.
-
-By default, the WAF is deployed in Detection-only mode and only logs attack attempts.
-
-## Requirements
-
-The Web Application Firewall requires:
-
-- **Kubernetes**
-
- To enable the WAF, you need:
-
- - Kubernetes 1.12+.
- - A load balancer. You can use NGINX-Ingress by deploying it to your
- Kubernetes cluster by either:
- - Using the [`nginx-ingress` Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress).
- - Installing the [Ingress GitLab Managed App](../../user/clusters/applications.md#ingress) with WAF enabled.
-
-- **Configured Kubernetes objects**
-
- To use the WAF on an application, you need to deploy the following Kubernetes resources:
-
- - [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- - [Service](https://kubernetes.io/docs/concepts/services-networking/service/)
- - [Ingress Resource](https://kubernetes.io/docs/concepts/services-networking/ingress/)
-
-## Quick start
-
-If you are using GitLab.com, see the [quick start guide](quick_start_guide.md) for
-how to use the WAF with GitLab.com and a Kubernetes cluster on Google Kubernetes Engine (GKE).
-
-If you are using a self-managed instance of GitLab, you need to configure the
-[Google OAuth2 OmniAuth Provider](../../integration/google.md) before
-you can configure a cluster on GKE. Once this is set up, you can follow the steps on the [quick start guide](quick_start_guide.md) to get started.
-
-NOTE:
-This guide shows how the WAF can be deployed using Auto DevOps. The WAF
-is available by default to all applications no matter how they are deployed,
-as long as they are using Ingress.
-
-## Network firewall vs. Web Application Firewall
-
-A network firewall or packet filter looks at traffic at the Network (L3) and Transport (L4) layers
-of the [OSI Model](https://en.wikipedia.org/wiki/OSI_model), and denies packets from entry based on
-a set of rules regarding the network in general.
-
-A Web Application Firewall operates at the Application (L7) layer of the OSI Model and can
-examine all the packets traveling to and from a specific application. A WAF can set
-more advanced rules around threat detection.
-
-## Features
-
-ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://github.com/coreruleset/coreruleset/) by
-default. The OWASP CRS logs attempts to the following attacks:
-
-- [SQL Injection](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_SQL_Injection)
-- [Cross-Site Scripting](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Cross-Site_Scripting_(XSS))
-- [Local File Inclusion](https://wiki.owasp.org/index.php/Testing_for_Local_File_Inclusion)
-- [Remote File Inclusion](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Remote_File_Inclusion)
-- [Code Injection](https://wiki.owasp.org/index.php/Code_Injection)
-- [Session Fixation](https://wiki.owasp.org/index.php/Session_fixation)
-- [Scanner Detection](https://wiki.owasp.org/index.php/Category:Vulnerability_Scanning_Tools)
-- [Metadata/Error Leakages](https://wiki.owasp.org/index.php/Improper_Error_Handling)
-
-It is good to have a basic knowledge of the following:
-
-- [Kubernetes](https://kubernetes.io/docs/home/)
-- [Ingress](https://kubernetes.github.io/ingress-nginx/)
-- [ModSecurity](https://www.modsecurity.org/)
-- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
-
-## Roadmap
-
-You can find more information on the product direction of the WAF in
-[Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/).
+<!-- This redirect file can be deleted after <2021-04-01>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/topics/web_application_firewall/quick_start_guide.md b/doc/topics/web_application_firewall/quick_start_guide.md
index df355ff2413..4d7244f88fa 100644
--- a/doc/topics/web_application_firewall/quick_start_guide.md
+++ b/doc/topics/web_application_firewall/quick_start_guide.md
@@ -1,258 +1,8 @@
---
-stage: Protect
-group: Container Security
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../user/project/clusters/protect/web_application_firewall/quick_start_guide.md'
---
-# Getting started with the Web Application Firewall
+This document was moved to [another location](../../user/project/clusters/protect/web_application_firewall/quick_start_guide.md).
-This is a step-by-step guide to help you use the GitLab [Web Application Firewall](index.md) after
-deploying a project hosted on GitLab.com to Google Kubernetes Engine using [Auto DevOps](../autodevops/index.md).
-
-The GitLab native Kubernetes integration is used, so you do not need
-to create a Kubernetes cluster manually using the Google Cloud Platform console.
-A simple application is created and deployed based on a GitLab template.
-
-These instructions also work for a self-managed GitLab instance. However, you
-need to ensure your own [runners are configured](../../ci/runners/README.md) and
-[Google OAuth is enabled](../../integration/google.md).
-
-The GitLab Web Application Firewall is deployed with [Ingress](../../user/clusters/applications.md#ingress),
-so it is available to your applications no matter how you deploy them to Kubernetes.
-
-## Configuring your Google account
-
-Before creating and connecting your Kubernetes cluster to your GitLab project,
-you need a Google Cloud Platform account. If you do not already have one,
-sign up at <https://console.cloud.google.com>. You need to either sign in with an existing
-Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one.
-
-1. To enable the required APIs and related services, follow the steps in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin).
-1. Make sure you have created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account).
-
-NOTE:
-Every new Google Cloud Platform (GCP) account receives [$300 in credit](https://console.cloud.google.com/freetrial),
-and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with the GitLab
-Google Kubernetes Engine integration. All you have to do is [follow this link](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) and apply for credit.
-
-## Creating a new project from a template
-
-We use a GitLab project templates to get started. As the name suggests,
-those projects provide a barebones application built on some well-known frameworks.
-
-1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select
- **New project**.
-1. Go to the **Create from template** tab where you can choose for example a Ruby on
- Rails, Spring, or NodeJS Express project.
- Use the Ruby on Rails template.
-
- ![Select project template](../autodevops/img/guide_project_template_v12_3.png)
-
-1. Give your project a name, optionally a description, and make it public so that
- you can take advantage of the features available in the
- [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com).
-
- ![Create project](../autodevops/img/guide_create_project_v12_3.png)
-
-1. Click **Create project**.
-
-Now that the project is created, the next step is to create the Kubernetes cluster
-to deploy this application under.
-
-## Creating a Kubernetes cluster from within GitLab
-
-1. On the project's landing page, click **Add Kubernetes cluster**
- (note that this option is also available when you navigate to **Operations > Kubernetes**).
-
- ![Project landing page](../autodevops/img/guide_project_landing_page_v12_10.png)
-
-1. On the **Create new cluster on GKE** tab, click **Sign in with Google**.
-
- ![Google sign in](../autodevops/img/guide_google_signin_v12_3.png)
-
-1. Connect with your Google account and click **Allow** when asked (this
- appears only the first time you connect GitLab with your Google account).
-
- ![Google auth](../autodevops/img/guide_google_auth_v12_3.png)
-
-1. The last step is to provide the cluster details.
- 1. Give it a name, leave the environment scope as is, and choose the GCP project under which to create the cluster.
- (Per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you.)
- 1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) to create the cluster in.
- 1. Enter the number of nodes you want it to have.
- 1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types).
-
- ![GitLab GKE cluster details](../autodevops/img/guide_gitlab_gke_details_v12_3.png)
-
-1. Click **Create Kubernetes cluster**.
-
-After a couple of minutes, the cluster is created. You can also see its
-status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
-
-The next step is to install some applications on your cluster that are needed
-to take full advantage of Auto DevOps.
-
-## Install Ingress
-
-The GitLab Kubernetes integration comes with some
-[pre-defined applications](../../user/project/clusters/index.md#installing-applications)
-for you to install.
-
-![Cluster applications](../autodevops/img/guide_cluster_apps_v12_3.png)
-
-For this guide, we need to install Ingress. Ingress provides load balancing,
-SSL termination, and name-based virtual hosting, using NGINX behind
-the scenes. Make sure to switch the toggle to the enabled position before installing.
-
-Both logging and blocking modes are available for WAF. While logging mode is useful for
-auditing anomalous traffic, blocking mode ensures the traffic doesn't reach past Ingress.
-
-![Cluster applications](img/guide_waf_ingress_installation_v12_10.png)
-
-After Ingress is installed, wait a few seconds and copy the IP address that
-is displayed in order to add in your base **Domain** at the top of the page. For
-the purpose of this guide, we use the one suggested by GitLab. Once you have
-filled in the domain, click **Save changes**.
-
-![Cluster Base Domain](../autodevops/img/guide_base_domain_v12_3.png)
-
-Prometheus should also be installed. It is an open-source monitoring and
-alerting system that is used to supervise the deployed application.
-Installing GitLab Runner is not required as we use the shared runners that
-GitLab.com provides.
-
-## Enabling Auto DevOps (optional)
-
-Starting with GitLab 11.3, Auto DevOps is enabled by default. However, it is possible to disable
-Auto DevOps at both the instance-level (for self-managed instances) and the group-level.
-Follow these steps if Auto DevOps has been manually disabled:
-
-1. Navigate to **Settings > CI/CD > Auto DevOps**.
-1. Select **Default to Auto DevOps pipeline**.
-1. Select the [continuous deployment strategy](../autodevops/index.md#deployment-strategy)
- which automatically deploys the application to production once the pipeline
- successfully runs on the `master` branch.
-1. Click **Save changes**.
-
- ![Auto DevOps settings](../autodevops/img/guide_enable_autodevops_v12_3.png)
-
-Once you complete all the above and save your changes, a new pipeline is
-automatically created. To view the pipeline, go to **CI/CD > Pipelines**.
-
-![First pipeline](../autodevops/img/guide_first_pipeline_v12_3.png)
-
-The next section explains what each pipeline job does.
-
-## Deploying the application
-
-By now you should see the pipeline running, but what is it running exactly?
-
-To navigate inside the pipeline, click its status badge (its status should be "Running").
-The pipeline is split into a few stages, each running a couple of jobs.
-
-![Pipeline stages](../autodevops/img/guide_pipeline_stages_v13_0.png)
-
-In the **build** stage, the application is built into a Docker image and then
-uploaded to your project's [Container Registry](../../user/packages/container_registry/index.md) ([Auto Build](../autodevops/stages.md#auto-build)).
-
-In the **test** stage, GitLab runs various checks on the application.
-
-The **production** stage is run after the tests and checks finish, and it automatically
-deploys the application in Kubernetes ([Auto Deploy](../autodevops/stages.md#auto-deploy)).
-
-The **production** stage creates Kubernetes objects
-like a Deployment, Service, and Ingress resource. The
-application is monitored by the WAF automatically.
-
-## Validating Ingress is running ModSecurity
-
-Now we can make sure that Ingress is running properly with ModSecurity and send
-a request to ensure our application is responding correctly. You must connect to
-your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install).
-
-1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled.
-
- This is done by running the following commands:
-
- ```shell
- $ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller'
- ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running
-
- $ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;'
- modsecurity on;
- ```
-
-1. Verify the Rails application has been installed properly.
-
- ```shell
- $ kubectl get ns
- auto-devv-2-16730183-production Active
-
- $ kubectl get pods -n auto-devv-2-16730183-production
- NAME READY STATUS RESTARTS
- production-5778cfcfcd-nqjcm 1/1 Running 0
- production-postgres-6449f8cc98-r7xgg 1/1 Running 0
- ```
-
-1. To make sure the Rails application is responding, send a request to it by running:
-
- ```shell
- $ kubectl get ing -n auto-devv-2-16730183-production
- NAME HOSTS PORTS
- production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443
-
- $ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" | grep 'Rails!' --after 2 --before 2
- <body>
- <p>You're on Rails!</p>
- </body>
- ```
-
-Now that we have confirmed our system is properly setup, we can go ahead and test
-the WAF with OWASP CRS!
-
-## Testing out the OWASP Core Rule Set
-
-Now let's send a potentially malicious request, as if we were a scanner,
-checking for vulnerabilities within our application and examine the ModSecurity logs:
-
-```shell
-$ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" --header "User-Agent: absinthe" | grep 'Rails!' --after 2 --before 2
-<body>
- <p>You're on Rails!</p>
-</body>
-
-$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /var/log/modsec/audit.log | grep 'absinthe'
-{
- "message": "Found User-Agent associated with security scanner",
- "details": {
- "match": "Matched \"Operator `PmFromFile' with parameter `scanners-user-agents.data' against variable `REQUEST_HEADERS:user-agent' (Value: `absinthe' )",
- "reference": "o0,8v84,8t:lowercase",
- "ruleId": "913100",
- "file": "/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf",
- "lineNumber": "33",
- "data": "Matched Data: absinthe found within REQUEST_HEADERS:user-agent: absinthe",
- "severity": "2",
- "ver": "OWASP_CRS/3.2.0",
- "rev": "",
- "tags": ["application-multi", "language-multi", "platform-multi", "attack-reputation-scanner", "OWASP_CRS", "OWASP_CRS/AUTOMATION/SECURITY_SCANNER", "WASCTC/WASC-21", "OWASP_TOP_10/A7", "PCI/6.5.10"],
- "maturity": "0",
- "accuracy": "0"
- }
-}
-```
-
-You can see that ModSecurity logs the suspicious behavior. By sending a request
-with the `User Agent: absinthe` header, which [absinthe](https://github.com/cameronhotchkies/Absinthe), a tool for testing for SQL injections uses, we can detect that someone was
-searching for vulnerabilities on our system. Detecting scanners is useful, because we
-can learn if someone is trying to exploit our system.
-
-## Conclusion
-
-You can now see the benefits of a using a Web Application Firewall.
-ModSecurity and the OWASP Core Rule Set, offer many more benefits.
-You can explore them in more detail:
-
-- [Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/)
-- [ModSecurity](https://www.modsecurity.org/)
-- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
-- [AutoDevOps](../autodevops/index.md)
+<!-- This redirect file can be deleted after <2021-04-01>. -->
+<!-- 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 f5c91b94813..fd600624a25 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -25,7 +25,7 @@ comments: false
- To instantiate a central repository a `--bare` flag is required.
- Bare repositories don't allow file editing or committing changes.
-- Create a bare repo with:
+- Create a bare repository with:
```shell
git init --bare project-name.git
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
index 7e7530aba75..30d26854135 100644
--- a/doc/university/training/topics/unstage.md
+++ b/doc/university/training/topics/unstage.md
@@ -19,7 +19,7 @@ comments: false
git checkout -- <file>
```
-- To remove a file from disk and repo use `git rm` and to remove a directory use the `-r` flag:
+- To remove a file from disk and repository, use `git rm`. To remove a directory, use the `-r` flag:
```shell
git rm '*.txt'
diff --git a/doc/update/README.md b/doc/update/README.md
index 45cac3ec8ca..958beeeb321 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -195,7 +195,7 @@ However, for this to work there are the following requirements:
9.3.
- You have to use [post-deployment
migrations](../development/post_deployment_migrations.md) (included in
- zero downtime update steps below).
+ [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).
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 613df2c3a84..fb1335acd7d 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 754265a23cf..71c8c701775 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.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
comments: false
---
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index 0625cc5a68f..64e92c802f2 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.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/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index 9a75326009c..7f190a310b0 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.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
comments: false
---
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 770eade6542..93aefb60f61 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.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
comments: false
---
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index 89df7090977..c5dd6cf16b7 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index 8f629fd4250..80108fba060 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -38,7 +38,7 @@ collected before this feature is available.
## DevOps Adoption **(ULTIMATE)**
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247112) in GitLab 13.7.
+[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:
@@ -50,7 +50,9 @@ 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.
+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.
DevOps Adoption allows you to:
@@ -62,18 +64,18 @@ DevOps Adoption allows you to:
### Disable or enable DevOps Adoption
-DevOps Adoption is deployed behind a feature flag that is **enabled by default**.
+DevOps Adoption 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 disable it.
+can opt to enable it.
-To disable it:
+To enable it:
```ruby
-Feature.disable(:devops_adoption_feature)
+Feature.enable(:devops_adoption_feature)
```
-To enable it:
+To disable it:
```ruby
-Feature.enable(:devops_adoption_feature)
+Feature.disable(:devops_adoption_feature)
```
diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md
index 1d2d0029860..7adc9ad59a5 100644
--- a/doc/user/admin_area/analytics/user_cohorts.md
+++ b/doc/user/admin_area/analytics/user_cohorts.md
@@ -6,32 +6,31 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Cohorts **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23361) in GitLab 9.1.
-
As a benefit of having the [usage ping active](../settings/usage_statistics.md),
-GitLab lets you analyze the users' activities over time of your GitLab installation.
+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 > Analytics > Cohorts**.
## Overview
-How do we read the user cohorts table? Let's take an example with the following
-user cohorts.
+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)
-For the cohort of March 2020, three users have been added on this server and have
-been active since this month. One month later, in April 2020, two users are
-still active. Five months later (August), we can see that one user from this cohort
-is active, or 33% of the original cohort of three that joined in March.
+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
+active. Five months later (August 2020), one user from this cohort is still
+active, or 33% of the original cohort of three that joined in March.
-The Inactive users column shows the number of users who have been added during
-the month, but who have never actually had any activity in the instance.
+The **Inactive users** column shows the number of users who were added during
+the month, but who never had any activity in the instance.
How do we measure the activity of users? GitLab considers a user active if:
- The user signs in.
- The user has Git activity (whether push or pull).
-- The user visits pages related to Dashboards, Projects, Issues, and Merge Requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8).
-- The user uses the API
-- The user uses the GraphQL API
+- The user visits pages related to dashboards, projects, issues, or merge
+ requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8).
+- The user uses the API.
+- The user uses the GraphQL API.
diff --git a/doc/user/admin_area/img/license_admin_area.png b/doc/user/admin_area/img/license_admin_area.png
deleted file mode 100644
index b5662b81c5e..00000000000
--- a/doc/user/admin_area/img/license_admin_area.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/license_upload.png b/doc/user/admin_area/img/license_upload.png
deleted file mode 100644
index 29d55175a2d..00000000000
--- a/doc/user/admin_area/img/license_upload.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/license_upload_v13_8.png b/doc/user/admin_area/img/license_upload_v13_8.png
new file mode 100644
index 00000000000..c15bc2bfa02
--- /dev/null
+++ b/doc/user/admin_area/img/license_upload_v13_8.png
Binary files differ
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index d7710c362e5..d06b0c844ec 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -32,7 +32,7 @@ is locked.
## Uploading your license
-The very first time you visit your GitLab EE installation signed in as an administrator,
+The first time you visit your GitLab EE installation signed in as an administrator,
you should see a note urging you to upload a license with a link that takes you
to **Admin Area > License**.
@@ -42,18 +42,21 @@ Otherwise, you can:
1. Navigate to the **License** tab, and click **Upload New License**.
- ![License Admin Area](img/license_admin_area.png)
+ - *If you've received a `.gitlab-license` file:*
+ 1. Download the license file to your local machine.
+ 1. Select **Upload `.gitlab-license` file**.
+ 1. Select **Choose File** and select the license file.
+ In this example the license file is named `GitLab.gitlab-license`.
+ 1. Check the **Subscription Agreement** checkbox.
+ 1. Select **Upload License**.
- - *If you've received a `.gitlab-license` file,* you should have already downloaded
- it in your local machine. You can then upload it directly by choosing the
- license file and clicking the **Upload license** button. In the image below,
- the selected license file is named `GitLab.gitlab-license`.
+ ![Upload license](img/license_upload_v13_8.png)
- ![Upload license](img/license_upload.png)
-
- - *If you've received your license as plain text,* select the
- **Enter license key** option, copy the license, paste it into the **License key**
- field, and click **Upload license**.
+ - *If you've received your license as plain text:*
+ 1. Select **Enter license key**.
+ 1. Copy the license and paste it into the **License key** field.
+ 1. Check the **Subscription Agreement** checkbox.
+ 1. Select **Upload License**.
## Add your license at install time
@@ -120,6 +123,11 @@ You can upload and view more than one license, but only the latest license in th
range is used as the active license. When you upload a future-dated license, it
doesn't take effect until its applicable date.
+NOTE:
+In GitLab 13.6 and earlier, a notification banner about an expiring license may continue to be displayed even after a new license has been uploaded.
+This happens when the newly uploaded license's start date is in the future and the expiring one is still active.
+The banner disappears after the new license becomes active.
+
## Troubleshooting
### There is no License tab in the Admin Area
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 bc266216714..028858c96f6 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -7,10 +7,18 @@ type: reference
# Account and limit settings **(CORE ONLY)**
+## Default projects limit
+
+You can change the default maximum number of projects that users can create in their personal namespace.
+Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
+You can increase or decrease that `Default projects limit` value.
+
+- 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.
+
## Max attachment size
You can change the maximum file size for attachments in comments and replies in GitLab.
-Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**.
+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:
@@ -21,13 +29,13 @@ details.
## Max push size
You can change the maximum push size for your repository.
-Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**.
+Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
From here, you can increase or decrease by changing the value in `Maximum push size (MB)`.
## Max import size
You can change the maximum file size for imports in GitLab.
-Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**.
+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:
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index ef2eb046c21..6418be13ee9 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -174,7 +174,7 @@ but commented out to help encourage others to add to it in the future. -->
WARNING:
This feature is being re-evaluated in favor of a different
-[compliance solution](https://gitlab.com/gitlab-org/gitlab/-/issues/34830).
+[compliance solution](https://gitlab.com/groups/gitlab-org/-/epics/3156).
We recommend that users who haven't yet implemented this feature wait for
the new solution.
@@ -187,6 +187,12 @@ sourced from:
- The [instance template repository](instance_template_repository.md).
- GitLab-supplied configuration.
+NOTE:
+When you use a configuration defined in an instance template repository,
+nested [`include:`](../../../ci/yaml/README.md#include) keywords
+(including `include:file`, `include:local`, `include:remote`, and `include:template`)
+[do not work](https://gitlab.com/gitlab-org/gitlab/-/issues/35345).
+
To set required pipeline configuration:
1. Go to **Admin Area > Settings > CI/CD**.
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index a7641ec22ca..9a661fa9716 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -38,7 +38,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [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). |
| [Third party offers](third_party_offers.md) | Control the display of third party offers. |
-| [Snowplow](../../../development/product_analytics/snowplow.md) | Configure the Snowplow integration. |
+| [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. |
| [Amazon EKS](../../project/clusters/add_eks_clusters.md) | Amazon EKS integration allows you to provision EKS clusters from GitLab. |
diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md
index fe4e84b98ac..adb192f5b4a 100644
--- a/doc/user/admin_area/settings/project_integration_management.md
+++ b/doc/user/admin_area/settings/project_integration_management.md
@@ -51,6 +51,14 @@ is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allo
administrators to update settings inherited by groups and projects without enabling the
integration on all non-configured groups and projects by default.
+### Remove an instance-level default setting
+
+1. Navigate to **Admin Area > Settings > Integrations**.
+1. Select an integration.
+1. Click **Reset** and confirm.
+
+Resetting an instance-level default setting removes the integration from all projects that have the integration set to use default settings.
+
## Manage group-level default settings for a project integration
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6.
@@ -86,6 +94,14 @@ is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allo
administrators to update settings inherited by subgroups and projects without enabling the
integration on all non-configured groups and projects by default.
+### Remove a group-level default setting
+
+1. Navigate to the group's **Settings > Integrations**.
+1. Select an integration.
+1. Click **Reset** and confirm.
+
+Resetting a group-level default setting removes integrations that use default settings and belong to a project or subgroup of the group.
+
## Use instance-level or group-level default settings for a project integration
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level settings.
diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md
index 870735f5be7..a03156511e2 100644
--- a/doc/user/admin_area/settings/protected_paths.md
+++ b/doc/user/admin_area/settings/protected_paths.md
@@ -28,11 +28,7 @@ GitLab rate limits the following paths with Rack Attack by default:
GitLab responds with HTTP status code `429` to POST requests at protected paths
that exceed 10 requests per minute per IP address.
-This header is included in responses to blocked requests:
-
-```plaintext
-Retry-After: 60
-```
+See [User and IP rate limits](../../admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests.
For example, the following are limited to a maximum 10 requests per minute:
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 02b1428177f..06b39d67228 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -61,13 +61,12 @@ sequenceDiagram
## Usage Ping **(CORE ONLY)**
-See [Usage Ping guide](../../../development/product_analytics/usage_ping.md).
+See [Usage Ping guide](../../../development/usage_ping.md).
-## Instance-level statistics **(CORE ONLY)**
+## Instance-level analytics availability
After usage ping is enabled, GitLab gathers data from other instances and
-can show [usage statistics](../analytics/index.md)
-of your instance to your admins in **Admin Area > Analytics**.
+enables certain [instance-level analytics features](../analytics/index.md) that are dependent on usage ping.
<!-- ## Troubleshooting
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 3f0d75dc682..e2040ef19d6 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
@@ -20,8 +20,42 @@ IP rate limits**:
These limits are disabled by default.
+NOTE:
+By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations
+may trigger the rate limits configured for unauthenticated requests.
+
![user-and-ip-rate-limits](img/user_and_ip_rate_limits.png)
+## Response text
+
+A request that exceeds a rate limit returns a 429 response code and a
+plain-text body, which by default is:
+
+```plaintext
+Retry later
+```
+
+It is possible to customize this response text in the Admin Area.
+
+## Response headers
+
+> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/731) in GitLab 13.8, the `Rate-Limit` headers. `Retry-After` was introduced in an earlier version.
+
+When a client exceeds the associated rate limit, the following requests are
+blocked. The server may respond with rate-limiting information allowing the
+requester to retry after a specific period of time. These information are
+attached into the response headers.
+
+| Header | Example | Description |
+|:----------------------|:--------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `RateLimit-Limit` | `60` | The request quota for the client **each minute**. If the rate limit period set in the admin area is different from 1 minute, the value of this header is adjusted to approximately the nearest 60-minute period. |
+| `RateLimit-Name` | `throttle_authenticated_web` | Name of the throttle blocking the requests. |
+| `RateLimit-Observed` | `67` | Number of requests associated to the client in the time window. |
+| `RateLimit-Remaining` | `0` | Remaining quota in the time window. The result of `RateLimit-Limit` - `RateLimit-Remaining`. |
+| `RateLimit-Reset` | `1609844400` | [Unix time](https://en.wikipedia.org/wiki/Unix_time)-formatted time when the request quota is reset. |
+| `RateLimit-ResetTime` | `Tue, 05 Jan 2021 11:00:00 GMT` | [RFC2616](https://tools.ietf.org/html/rfc2616#section-3.3.1)-formatted date and time when the request quota is reset. |
+| `Retry-After` | `30` | Remaining duration **in seconds** until the quota is reset. This is a [standard HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After). |
+
## Use an HTTP header to bypass rate limiting
> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/622) in GitLab 13.6.
@@ -47,7 +81,7 @@ GitLab. For example:
in `/etc/default/gitlab`.
It is important that your load balancer erases or overwrites the bypass
-header on all incoming traffic, because otherwise you must trust your
+header on all incoming traffic. Otherwise, you must trust your
users to not set that header and bypass the GitLab rate limiter.
Note that the bypass only works if the header is set to `1`.
@@ -59,7 +93,9 @@ are marked with `"throttle_safelist":"throttle_bypass_header"` in
To disable the bypass mechanism, make sure the environment variable
`GITLAB_THROTTLE_BYPASS_HEADER` is unset or empty.
-## Allowing specific users to bypass authenticated request rate limiting
+## Allow specific users to bypass authenticated request rate limiting
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49127) in GitLab 13.7.
Similarly to the bypass header described above, it is possible to allow
a certain set of users to bypass the rate limiter. This only applies
@@ -82,13 +118,12 @@ are marked with `"throttle_safelist":"throttle_user_allowlist"` in
At application startup, the allowlist is logged in [`auth.log`](../../../administration/logs.md#authlog).
-## Trying out throttling settings before enforcing them
+## Try out throttling settings before enforcing them
> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/629) in GitLab 13.6.
-Trying out throttling settings can be done by setting the
-`GITLAB_THROTTLE_DRY_RUN` environment variable to a comma-separated
-list of throttle names.
+You can try out throttling settings by setting the `GITLAB_THROTTLE_DRY_RUN` environment variable to
+a comma-separated list of throttle names.
The possible names are:
@@ -99,21 +134,19 @@ The possible names are:
- `throttle_authenticated_protected_paths_api`
- `throttle_authenticated_protected_paths_web`
-For example: trying out throttles for all authenticated requests to
-non-protected paths could be done by setting
+For example, to try out throttles for all authenticated requests to
+non-protected paths can be done by setting
`GITLAB_THROTTLE_DRY_RUN='throttle_authenticated_web,throttle_authenticated_api'`.
-To enable the dry-run mode for all throttles, the variable can be set
-to `*`.
+To enable dry run mode for all throttles, the variable can be set to `*`.
-Setting a throttle to dry-run mode will log a message to the
-[`auth.log`](../../../administration/logs.md#authlog) when it would
-hit the limit, while letting the request continue as normal. The log
-message will contain an `env` field set to `track`. The `matched`
-field will contain the name of throttle that was hit.
+Setting a throttle to dry run mode logs a message to the
+[`auth.log`](../../../administration/logs.md#authlog) when it would hit the limit, while letting the
+request continue as normal. The log message contains an `env` field set to `track`. The `matched`
+field contains the name of throttle that was hit.
It is important to set the environment variable **before** enabling
-the rate limiting in the settings. The settings in the admin panel
+the rate limiting in the settings. The settings in the Admin Area
take effect immediately, while setting the environment variable
requires a restart of all the Puma processes.
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
new file mode 100644
index 00000000000..beb2cbfdc58
--- /dev/null
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -0,0 +1,33 @@
+---
+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
+---
+
+# CI/CD Analytics
+
+## Pipeline success and duration charts **(CORE)**
+
+> - 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.
+
+GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline
+ran. To view this information, go to **Analytics > CI/CD Analytics**.
+
+View successful pipelines:
+
+![Successful pipelines](img/pipelines_success_chart.png)
+
+View pipeline duration history:
+
+![Pipeline duration](img/pipelines_duration_chart.png)
+
+## Deployment frequency charts **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.8.
+
+The **Analytics > CI/CD Analytics** page shows information about the deployment frequency to the
+`production` environment. The environment **must** be named `production` for its deployment
+information to appear on the graphs.
+
+![Deployment frequency](img/deployment_frequency_chart_v13_8.png)
diff --git a/doc/user/analytics/img/deployment_frequency_chart_v13_8.png b/doc/user/analytics/img/deployment_frequency_chart_v13_8.png
new file mode 100644
index 00000000000..40dd2fa0321
--- /dev/null
+++ b/doc/user/analytics/img/deployment_frequency_chart_v13_8.png
Binary files differ
diff --git a/doc/ci/pipelines/img/pipelines_duration_chart.png b/doc/user/analytics/img/pipelines_duration_chart.png
index 12ec262dadb..12ec262dadb 100644
--- a/doc/ci/pipelines/img/pipelines_duration_chart.png
+++ b/doc/user/analytics/img/pipelines_duration_chart.png
Binary files differ
diff --git a/doc/ci/pipelines/img/pipelines_success_chart.png b/doc/user/analytics/img/pipelines_success_chart.png
index f44dc25ff1c..f44dc25ff1c 100644
--- a/doc/ci/pipelines/img/pipelines_success_chart.png
+++ b/doc/user/analytics/img/pipelines_success_chart.png
Binary files differ
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index adfd09d8526..caa8972b220 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -33,7 +33,7 @@ The following analytics features are available at the group level:
The following analytics features are available at the project level:
-- [CI/CD](../../ci/pipelines/index.md#pipeline-success-and-duration-charts). **(STARTER)**
+- [CI/CD](ci_cd_analytics.md). **(CORE)**
- [Code Review](code_review_analytics.md). **(STARTER)**
- [Insights](../project/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 09e38d5048f..674afcb29ee 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -157,6 +157,7 @@ You can use various tools to generate HAR files:
- [Insomnia Core](https://insomnia.rest/): API client
- [Chrome](https://www.google.com/chrome/): Browser
- [Firefox](https://www.mozilla.org/en-US/firefox/): Browser
+- [GitLab HAR Recorder](https://gitlab.com/gitlab-org/security-products/har-recorder): Command line
WARNING:
HAR files may contain sensitive information such as authentication tokens, API keys, and session
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 0a5a0c3a565..469945246c1 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -29,8 +29,10 @@ Docker image with the fuzz engine to run your app.
| 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) |
| 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 | [JQF](https://github.com/rohanpadhye/JQF) | [java-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/java-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) |
## Configuration
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index f4401fa6445..395a8702d1b 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -86,6 +86,20 @@ variables:
DAST_WEBSITE: https://example.com
```
+### Latest template
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254325) in GitLab 13.8
+
+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)
+on template versioning for more information.
+
+Please note that the latest version may include breaking changes. Check the
+[DAST troubleshooting guide](#troubleshooting) if you experience problems.
+
+### Template options
+
There are two ways to define the URL to be scanned by DAST:
1. Set the `DAST_WEBSITE` [variable](../../../ci/yaml/README.md#variables).
@@ -183,6 +197,10 @@ To create masked variables for the username and password, see [Create a custom v
Note that the key of the username variable must be `DAST_USERNAME`
and the key of the password variable must be `DAST_PASSWORD`.
+After DAST has authenticated with the application, all cookies are collected from the web browser.
+For each cookie a matching session token is created for use by ZAP. This ensures ZAP is recognized
+by the application as correctly authenticated.
+
Other variables that are related to authenticated scans are:
```yaml
@@ -196,7 +214,8 @@ variables:
DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
DAST_SUBMIT_FIELD: login # the `id` or `name` of the element that when clicked will submit the login form or the password form of a multi-page login process
DAST_FIRST_SUBMIT_FIELD: next # the `id` or `name` of the element that when clicked will submit the username form of a multi-page login process
- DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between
+ DAST_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between
+ DAST_AUTH_VALIDATION_URL: http://example.com/loggedin_page # optional, a URL only accessible to logged in users that DAST can use to confirm successful authentication
```
The results are saved as a
@@ -544,12 +563,14 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia
| `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_AUTH_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_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_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` |
@@ -701,6 +722,49 @@ 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.
+## 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.
+
+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.
+- Is associated with your project's default branch.
+
+### On-demand scan modes
+
+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).
+
+### Run an on-demand DAST scan
+
+NOTE:
+You must have permission to run an on-demand DAST scan against a protected branch.
+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:
+
+- 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.
+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**.
+
+The on-demand DAST scan runs and the project's dashboard shows the results.
+
## Site profile
A site profile describes the attributes of a web site to scan on demand with DAST. A site profile is
@@ -711,31 +775,115 @@ 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
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233020) in GitLab 13.8.
+
+Site profile validation reduces the risk of running an active scan against the wrong website. A site
+must be validated before an active scan can run against it. The site validation methods are as
+follows:
+
+- _Text file validation_ requires a text file be uploaded to the target site. The text file is
+ allocated a name and content that is unique to the project. The validation process checks the
+ file's content.
+- _Header validation_ requires the header `Gitlab-On-Demand-DAST` be added to the target site,
+ with a value unique to the project. The validation process checks that the header is present, and
+ checks its value.
+
+Both methods are equivalent in functionality. Use whichever is feasible.
+
### Create a site profile
To create a site 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 > Site Profile**.
-1. Type in a unique **Profile name** and **Target URL** then click **Save profile**.
+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**.
### Edit a site profile
To edit an existing site 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 row of the profile to edit.
-1. Edit the **Profile name** and **Target URL**, then click **Save profile**.
+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**.
### Delete a site profile
To delete an existing site 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 row of the profile to delete.
+1. Select **Manage** in the **DAST Profiles** row.
+1. Select **{remove}** (Delete profile) in the row of the profile to delete.
+
+### Validate 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. 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
+ **Step 3** or any location you prefer.
+ 1. Select **Validate**.
+ 1. For **Header validation**:
+ 1. Select the clipboard icon in **Step 2**.
+ 1. Edit the header of the site to validate, and paste the clipboard content.
+ 1. Select the input field in **Step 3** and enter the location of the header.
+ 1. Select **Validate**.
+
+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.
+
+#### Validated site profile headers
+
+The following are code samples of how you could provide the required site profile header in your
+application.
+
+##### Ruby on Rails example for on-demand scan
+
+Here's how you can add a custom header in a Ruby on Rails application:
+
+```ruby
+class DastWebsiteTargetController < ActionController::Base
+ def dast_website_target
+ response.headers['Gitlab-On-Demand-DAST'] = '0dd79c9a-7b29-4e26-a815-eaaf53fcab1c'
+ head :ok
+ end
+end
+```
+
+##### Django example for on-demand scan
+
+Here's how you can add a
+[custom header in Django](https://docs.djangoproject.com/en/2.2/ref/request-response/#setting-header-fields):
+
+```python
+class DastWebsiteTargetView(View):
+ def head(self, *args, **kwargs):
+ response = HttpResponse()
+ response['Gitlab-On-Demand-DAST'] = '0dd79c9a-7b29-4e26-a815-eaaf53fcab1c'
+
+ return response
+```
+
+##### Node (with Express) example for on-demand scan
+
+Here's how you can add a
+[custom header in Node (with Express)](http://expressjs.com/en/5x/api.html#res.append):
+
+```javascript
+app.get('/dast-website-target', function(req, res) {
+ res.append('Gitlab-On-Demand-DAST', '0dd79c9a-7b29-4e26-a815-eaaf53fcab1c')
+ res.send('Respond to DAST ping')
+})
+```
## Scanner profile
@@ -779,40 +927,6 @@ To delete a scanner profile:
1. Click **Manage** in the **DAST Profiles** row.
1. Click **{remove}** (Delete profile) in the scanner profile's row.
-## 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.
-
-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.
-- Is associated with your project's default branch.
-
-### Run an on-demand DAST scan
-
-NOTE:
-You must have permission to run an on-demand DAST scan against a protected branch.
-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:
-
-- A [scanner profile](#create-a-scanner-profile).
-- A [site profile](#create-a-site-profile).
-
-1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left sidebar.
-1. Click **Create new DAST scan**.
-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**.
-
-The on-demand DAST scan runs and the project's dashboard shows the results.
-
## Reports
The DAST tool outputs a report file in JSON format by default. However, this tool can also generate reports in
@@ -940,6 +1054,25 @@ If your DAST job exceeds the job timeout and you need to reduce the scan duratio
For information on this, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload).
+### Getting error `dast job: chosen stage does not exist` when including DAST CI template
+
+Newer versions of the DAST CI template do not define stages in order to avoid
+overwriting stages from other CI files. If you've recently started using
+`DAST.latest.gitlab-ci.yml` or upgraded to a new major release of GitLab and
+began receiving this error, you will need to define a `dast` stage with your
+other stages. Please note that you must have a running application for DAST to
+scan. If your application is set up in your pipeline, it must be deployed
+ in a stage _before_ the `dast` stage:
+
+```yaml
+stages:
+ - deploy # DAST needs a running application to scan
+ - dast
+
+include:
+ - template: DAST.latest.gitlab-ci.yml
+```
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 07774f51958..cecf818edfc 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -64,16 +64,19 @@ The following languages and dependency managers are supported:
| [Conan](https://conan.io/) | C, C++ | [`conan.lock`](https://docs.conan.io/en/latest/versioning/lockfiles.html) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [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), [Retire.js](https://retirejs.github.io/retire.js/) |
+| [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/) |
| [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/) | Python | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile` | [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) |
+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.
+
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 |
| ------------------- | --------- | --------------- | ---------- | ----- |
-| [Pipenv](https://pipenv.pypa.io/en/latest/) | Python | `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#11756](https://gitlab.com/gitlab-org/gitlab/-/issues/11756) |
| [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) |
@@ -115,7 +118,7 @@ include:
- template: Dependency-Scanning.gitlab-ci.yml
variables:
- DS_PYTHON_VERSION: 2
+ SECURE_LOG_LEVEL: error
```
Because template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline
@@ -489,7 +492,7 @@ ensure that it can reach your private repository. Here is an example configurati
### Referencing local dependencies using a path in JavaScript projects
The [Retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js) analyzer
-doesn't support dependency references made with [local paths](https://docs.npmjs.com/files/package.json#local-paths)
+doesn't support dependency references made with [local paths](https://docs.npmjs.com/cli/v6/configuring-npm/package-json#local-paths)
in the `package.json` of JavaScript projects. The dependency scan outputs the following error for
such references:
@@ -504,7 +507,7 @@ As a workaround, remove the [`retire.js`](analyzers.md#selecting-specific-analyz
### `Error response from daemon: error processing tar file: docker-tar: relocation error`
-This error occurs when the Docker version that runs the dependency scanning job is `19.03.00`.
+This error occurs when the Docker version that runs the dependency scanning job is `19.03.0`.
Consider updating to Docker `19.03.1` or greater. Older versions are not
affected. Read more in
[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/13830#note_211354992 "Current SAST container fails").
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 15412473ab1..1f0b461c91b 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -68,6 +68,10 @@ the official analyzers.
### Selecting specific analyzers
+WARNING:
+`SAST_DEFAULT_ANALYZERS` is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50872) in GitLab 13.8,
+and is scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777).
+
You can select the official analyzers you want to run. Here's how to enable
`bandit` and `flawfinder` while disabling all the other default ones.
In `.gitlab-ci.yml` define:
@@ -83,9 +87,9 @@ variables:
`bandit` runs first. When merging the reports, SAST
removes the duplicates and keeps the `bandit` entries.
-### Disabling default analyzers
+### Disabling all default analyzers
-Setting `SAST_DEFAULT_ANALYZERS` to an empty string disables all the official
+Setting `SAST_DISABLED` to `true` disables all the official
default analyzers. In `.gitlab-ci.yml` define:
```yaml
@@ -93,11 +97,25 @@ include:
- template: Security/SAST.gitlab-ci.yml
variables:
- SAST_DEFAULT_ANALYZERS: ""
+ SAST_DISABLED: true
```
That's needed when one totally relies on [custom analyzers](#custom-analyzers).
+### Disabling specific default analyzers
+
+Set `SAST_EXCLUDED_ANALYZERS` to a comma-delimited string that includes the official
+default analyzers that you want to avoid running. In `.gitlab-ci.yml` define the
+following to prevent the `eslint` analyzer from running:
+
+```yaml
+include:
+ - template: Security/SAST.gitlab-ci.yml
+
+variables:
+ SAST_EXCLUDED_ANALYZERS: "eslint"
+```
+
## Custom Analyzers
You can provide your own analyzers by
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index fb3bc256e11..59887c95c67 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -431,7 +431,8 @@ The following are Docker image-related variables.
|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `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` | Override the names of default images. Read more about [customizing analyzers](analyzers.md). |
+| `SAST_DEFAULT_ANALYZERS` | **DEPRECATED:** Override the names of default images. Scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777). |
+| `SAST_EXCLUDED_ANALYZERS` | Names of default images that should never run. Read more about [customizing analyzers](analyzers.md). |
#### Vulnerability filters
@@ -511,7 +512,7 @@ The SAST tool emits a JSON report file. For more information, see the
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json).
The JSON report file can be downloaded from the CI pipelines page, or the
-pipelines tab on merge requests. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
+pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/pipelines/job_artifacts.md#defining-artifacts-in-gitlab-ciyml) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
Here's an example SAST report:
@@ -727,3 +728,25 @@ against the given glob pattern. If the number of matches exceeds the maximum, th
parameter returns `true`. Depending on the number of files in your repository, a SAST job might be
triggered even if the scanner doesn't support your project. For more details about this issue, see
the [`rules:exists` documentation](../../../ci/yaml/README.md#rulesexists).
+
+### SpotBugs UTF-8 unmappable character errors
+
+These errors occur when UTF-8 encoding isn't enabled on a SpotBugs build and there are UTF-8
+characters in the source code. To fix this error, enable UTF-8 for your project's build tool.
+
+For Gradle builds, add the following to your `build.gradle` file:
+
+```gradle
+compileJava.options.encoding = 'UTF-8'
+tasks.withType(JavaCompile) {
+ options.encoding = 'UTF-8'
+}
+```
+
+For Maven builds, add the following to your `pom.xml` file:
+
+```xml
+<properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+</properties>
+```
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 8f57e2c5535..0ae038924ec 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -53,6 +53,7 @@ The [default ruleset provided by Gitleaks](https://gitlab.com/gitlab-org/securit
- Twitter API
- Cloud SaaS vendors:
- GitHub API
+ - Shopify API
- Slack Token
- Slack Webhook
- Stripe API
diff --git a/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png b/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png
index b9b228c9430..5184ad85fa9 100644
--- a/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png
+++ b/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 2750aa81872..10bf6202a92 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -92,7 +92,8 @@ 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,
-and description. Clicking a vulnerability takes you to its [Vulnerability Details](../vulnerabilities)
+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)
diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md
new file mode 100644
index 00000000000..ce2297f7a1a
--- /dev/null
+++ b/doc/user/application_security/vulnerabilities/severities.md
@@ -0,0 +1,70 @@
+---
+type: reference
+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
+---
+
+# Vulnerability severity levels
+
+GitLab vulnerability analyzers attempt to return vulnerability severity level values whenever
+possible. The following is a list of available GitLab vulnerability severity levels, ranked from
+most to least severe:
+
+- `Critical`
+- `High`
+- `Medium`
+- `Low`
+- `Info`
+- `Unknown`
+
+Most GitLab vulnerability analyzers are wrappers around popular open source scanning tools. Each
+open source scanning tool provides their own native vulnerability severity level value. These values
+can be one of the following:
+
+| Native vulnerability severity level type | Examples |
+|-----------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|
+| String | `WARNING`, `ERROR`, `Critical`, `Negligible` |
+| Integer | `1`, `2`, `5` |
+| [CVSS v2.0 Rating](https://nvd.nist.gov/vuln-metrics/cvss) | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)` |
+| [CVSS v3.1 Qualitative Severity Rating](https://www.first.org/cvss/v3.1/specification-document#Qualitative-Severity-Rating-Scale) | `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` |
+
+To provide consistent vulnerability severity level values, the GitLab vulnerability analyzers
+convert from the above values to a standardized GitLab vulnerability severity level, as outlined in
+the following tables:
+
+## SAST
+
+| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
+|--------------------------------------------------------------------------------------------------------|--------------------------|----------------------------|------------------------------------|
+| [security-code-scan](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) | **{dotted-circle}** No | N/A | N/A |
+| [brakeman](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) | **{dotted-circle}** No | N/A | N/A |
+| [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` |
+
+## 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` |
+
+## Fuzz Testing
+
+All fuzz testing results are reported as Unknown. They should be reviewed and triaged manually to find exploitable faults to prioritize for fixing.
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 5963485aebc..2c0d9b6c9ce 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -20,9 +20,10 @@ tasks in a secure and cloud-native way. It enables:
(network address translation).
- Pull-based GitOps deployments by leveraging the
[GitOps Engine](https://github.com/argoproj/gitops-engine).
-- Real-time access to API endpoints within a cluster.
+- Real-time access to API endpoints in a cluster.
-Many more features are planned. Please [review our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329).
+Many more features are planned. Please review [our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329)
+and [our development documentation](../../../development/agent/index.md).
## GitLab Agent GitOps workflow
@@ -169,7 +170,7 @@ gitops:
GitLab [versions 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) also
supports manifest projects containing
multiple directories (or subdirectories) of YAML files. For more information see our
-documentation on the [Kubernetes Agent configuration respository](repository.md).
+documentation on the [Kubernetes Agent configuration repository](repository.md).
### Create an Agent record in GitLab
@@ -266,7 +267,7 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways
[Support TLS for gRPC communication issue](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7)
for progress updates.
- When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the `kas-address` for `wss` and `ws` schemes to whatever you need.
- Check the [chart's KAS Ingress docs](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
+ Check the [chart's KAS Ingress documentation](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
to learn more about it.
- In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
- If you defined your own secret name, replace `gitlab-agent-token` with your
@@ -436,12 +437,9 @@ spec:
The following example projects can help you get started with the Kubernetes Agent.
-### Simple NGINX deployment
-
-This basic GitOps example deploys NGINX:
-
- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
-- [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
+- 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
diff --git a/doc/user/clusters/agent/runner.md b/doc/user/clusters/agent/runner.md
new file mode 100644
index 00000000000..715b27f951a
--- /dev/null
+++ b/doc/user/clusters/agent/runner.md
@@ -0,0 +1,452 @@
+---
+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
+---
+
+# Install GitLab Runner with Kubernetes Agent **(PREMIUM ONLY)**
+
+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
+```
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 53be7e995d5..b03dfb79ae0 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -100,7 +100,7 @@ include:
- template: Managed-Cluster-Applications.gitlab-ci.yml
apply:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.34.1"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.37.0"
```
### Use the template with a custom environment
@@ -1268,6 +1268,11 @@ record.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21966) in GitLab 12.7.
+WARNING:
+The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276)
+in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349)
+in GitLab 14.0.
+
A Web Application Firewall (WAF) examines traffic being sent or received,
and can block malicious traffic before it reaches your application. The benefits
of a WAF are:
@@ -1296,7 +1301,7 @@ To enable WAF, switch its respective toggle to the enabled position when install
or updating [Ingress application](#ingress).
If this is your first time using the GitLab WAF, we recommend you follow the
-[quick start guide](../../topics/web_application_firewall/quick_start_guide.md).
+[quick start guide](../project/clusters/protect/web_application_firewall/quick_start_guide.md).
There is a small performance overhead by enabling ModSecurity. If this is
considered significant for your application, you can disable ModSecurity's
@@ -1308,7 +1313,7 @@ rule engine for your deployed application in any of the following ways:
1. Switch its respective toggle to the disabled position, and then apply changes
by selecting **Save changes** to reinstall Ingress with the recent changes.
-![Disabling WAF](../../topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png)
+![Disabling WAF](../project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png)
##### Logging and blocking modes
@@ -1321,7 +1326,7 @@ To help you tune your WAF rules, you can globally set your WAF to either
To change your WAF's mode:
1. If you haven't already done so,
- [install ModSecurity](../../topics/web_application_firewall/quick_start_guide.md).
+ [install ModSecurity](../project/clusters/protect/web_application_firewall/quick_start_guide.md).
1. Navigate to **Operations > Kubernetes**.
1. In **Applications**, scroll to **Ingress**.
1. Under **Global default**, select your desired mode.
@@ -1337,12 +1342,12 @@ The **ModSecurity** user interface controls are disabled if the version deployed
differs from the one available in GitLab. However, actions at the [Ingress](#ingress)
level, such as uninstalling, can still be performed:
-![WAF settings disabled](../../topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png)
+![WAF settings disabled](../project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png)
Update [Ingress](#ingress) to the most recent version to take advantage of bug
fixes, security fixes, and performance improvements. To update the
[Ingress application](#ingress), you must first uninstall it, and then re-install
-it as described in [Install ModSecurity](../../topics/web_application_firewall/quick_start_guide.md).
+it as described in [Install ModSecurity](../project/clusters/protect/web_application_firewall/quick_start_guide.md).
##### Viewing Web Application Firewall traffic
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index f78b6115623..1428a0d4e80 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -76,7 +76,7 @@ The reported licenses might be incomplete or inaccurate.
| Elixir | [Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) |
| C++/C | [Conan](https://conan.io/) |
| Scala | [sbt](https://www.scala-sbt.org/) |
-| Rust | [Cargo](https://crates.io) |
+| Rust | [Cargo](https://crates.io/) |
| PHP | [Composer](https://getcomposer.org/) |
## Requirements
diff --git a/doc/user/discussions/img/threads_resolved.png b/doc/user/discussions/img/threads_resolved.png
deleted file mode 100644
index ffb1233f2ee..00000000000
--- a/doc/user/discussions/img/threads_resolved.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 945c082bba9..bf3e907bd24 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -90,27 +90,6 @@ When a link of a commit reference is found in a thread inside a merge
request, it will be automatically converted to a link in the context of the
current merge request.
-### Jumping between unresolved threads (deprecated)
-
-> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/199718) in GitLab 13.3.
-> - This button's removal is behind a feature flag enabled by default.
-> - For GitLab self-managed instances, GitLab administrators with access to the
- [GitLab Rails console](../../administration/feature_flags.md) can opt to disable it by running
- `Feature.disable(:hide_jump_to_next_unresolved_in_threads)` (for the instance) or
- `Feature.disable(:hide_jump_to_next_unresolved_in_threads, Project.find(<project id>))`
- (per project.) **(CORE ONLY)**
-
-When a merge request has a large number of comments it can be difficult to track
-what remains unresolved. You can jump between unresolved threads with the
-Jump button next to the Reply field on a thread.
-
-You can also use keyboard shortcuts to navigate among threads:
-
-- Use <kbd>n</kbd> to jump to the next unresolved thread.
-- Use <kbd>p</kbd> to jump to the previous unresolved thread.
-
-!["8/9 threads resolved"](img/threads_resolved.png)
-
### Marking a comment or thread as resolved
You can mark a thread as resolved by clicking the **Resolve thread**
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 7aafa52799d..611c1105961 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -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 | 50 MB |
+| Maximum import size | 5 GB | Unlimited |
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.
@@ -132,6 +132,23 @@ 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).
+## Hostname list
+
+To configure allow-lists in local HTTP(S) proxies, or other
+web-blocking software that govern end-user machines,
+pages on GitLab.com will attempt to load content from
+the following hostnames:
+
+- `gitlab.com`
+- `*.gitlab.com`
+- `*.gitlab-static.net`
+- `*.gitlab.io`
+- `*.gitlab.net`
+
+Documentation and Company pages served over `docs.gitlab.com`
+and `about.gitlab.com` will attempt to also load certain page
+content directly from common public CDN hostnames.
+
## Webhooks
A limit of:
@@ -532,13 +549,10 @@ endpoints](../../user/admin_area/settings/rate_limits_on_raw_endpoints.md).
### Rate limiting responses
-The [`Retry-After`
-header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After)
-indicates when the client should retry.
+For information on rate limiting responses, see:
-Rate limits applied by HAProxy (instead of Cloudflare or the
-GitLab application) have `RateLimit-Reset` and `RateLimit-ResetTime`
-headers.
+- [List of headers on responses to blocked requests](../admin_area/settings/user_and_ip_rate_limits.md#response-headers).
+- [Customizable response text](../admin_area/settings/user_and_ip_rate_limits.md#response-text).
### Protected paths throttle
@@ -548,11 +562,7 @@ paths that exceed 10 requests per **minute** per IP address.
See the source below for which paths are protected. This includes user creation,
user confirmation, user sign in, and password reset.
-This header is included in responses to blocked requests:
-
-```plaintext
-Retry-After: 60
-```
+[User and IP rate limits](../admin_area/settings/user_and_ip_rate_limits.md#response-headers) includes a list of the headers responded to blocked requests.
See [Protected Paths](../admin_area/settings/protected_paths.md) for more details.
diff --git a/doc/user/group/import/img/bulk_imports_v13_8.png b/doc/user/group/import/img/bulk_imports_v13_8.png
new file mode 100644
index 00000000000..31234f9fcea
--- /dev/null
+++ 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
new file mode 100644
index 00000000000..1fb7fbad291
--- /dev/null
+++ b/doc/user/group/import/img/import_panel_v13_8.png
Binary files differ
diff --git a/doc/user/group/import/img/new_group_navigation_v13_8.png b/doc/user/group/import/img/new_group_navigation_v13_8.png
new file mode 100644
index 00000000000..307175727c7
--- /dev/null
+++ b/doc/user/group/import/img/new_group_navigation_v13_8.png
Binary files differ
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
new file mode 100644
index 00000000000..d051a134af1
--- /dev/null
+++ b/doc/user/group/import/index.md
@@ -0,0 +1,91 @@
+---
+type: reference, howto
+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
+---
+
+# Import groups from another instance of GitLab **(CORE)**
+
+> - [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.
+> - It's enabled on GitLab.com.
+
+## Overview
+
+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.
+
+The following resources are migrated to the target instance:
+
+- Groups
+ - description
+ - attributes
+ - subgroups
+- Epics
+ - title
+ - description
+ - state (open / closed)
+ - start date
+ - due date
+ - epic order on boards
+ - confidentiality
+
+Any other items are **not** migrated.
+
+## Enable or disable GitLab Group Migration
+
+Support for GitLab Group Migration 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(:bulk_import)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:bulk_import)
+```
+
+## Import your groups into GitLab
+
+Before you begin, ensure that the target instance of GitLab can communicate with the source
+over HTTPS (HTTP is not supported).
+
+NOTE:
+This might involve reconfiguring your firewall to prevent blocking connection on the side of self-managed instance.
+
+### Connect to the remote GitLab instance
+
+1. Navigate to the New Group page, either via the `+` button in the top navigation bar, or the **New subgroup** button
+on an existing group's page.
+
+ ![Navigation paths to create a new group](img/new_group_navigation_v13_8.png)
+
+1. On the New Group page, select the **Import group** tab.
+
+ ![Fill in import details](img/import_panel_v13_8.png)
+
+1. Fill in source URL of your GitLab.
+1. Fill in [personal access token](../../../user/profile/personal_access_tokens.md) for remote GitLab instance.
+1. Click "Connect instance".
+
+### Selecting which groups to import
+
+After you have authorized access to GitLab instance, you are redirected to the GitLab Group Migration importer page and your remote GitLab groups are listed.
+
+1. By default, the proposed group namespaces match the names as they exist in remote instance, but based on your permissions, you can choose to edit these names before you proceed to import any of them.
+
+1. Select the **Import** button next to any number of groups.
+
+1. The **Status** column shows the import status of each group. You can choose to leave the page open and it will update in real-time.
+
+1. Once a group has been imported, click its GitLab path to open its GitLab URL.
+
+![Group Importer page](img/bulk_imports_v13_8.png)
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index a0884461da1..069dea40ba5 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -215,10 +215,7 @@ To remove a member from a group:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) in GitLab 12.6.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7.
-> - 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-the-ability-to-filter-and-sort-group-members). **(CORE ONLY)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289911) in GitLab 13.8.
The following sections illustrate how you can filter and sort members in a group. To view these options,
navigate to your desired group, go to **Members**, and include the noted search terms.
@@ -269,30 +266,6 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last
![Group members sort](img/group_members_sort_13_7.png)
-### Enable or disable improvements to the ability to filter and sort group members **(CORE ONLY)**
-
-Group member filtering and sorting 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(:group_members_filtered_search)
-# For a single group
-Feature.disable(:group_members_filtered_search, Group.find(<group id>))
-```
-
-To enable them:
-
-```ruby
-# For the instance
-Feature.enable(:group_members_filtered_search)
-# For a single group
-Feature.enable(:group_members_filtered_search, Group.find(<group id>))
-```
-
## Changing the default branch protection of a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9.
@@ -487,7 +460,7 @@ and above.
There are a few limitations compared to project wikis:
- Git LFS is not supported.
-- Group wikis are not included in global search, group exports, backups, and Geo replication.
+- Group wikis are not included in global search, group exports, 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.
@@ -664,6 +637,12 @@ request to add a new user to a project through API will not be possible.
> - [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.
+NOTE:
+IP Access Restrictions are currently not functioning as expected on GitLab.com. Some users
+may experience blocked Git operations or have difficulties accessing projects. Please
+review the [following bug report](https://gitlab.com/gitlab-org/gitlab/-/issues/271673) for
+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
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index a06c7a8f325..65d3129a825 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -88,6 +88,22 @@ similar to how they appear when viewing a [milestone](../../project/milestones/i
Burndown charts help track completion progress of total scope, and burnup charts track the daily
total count and weight of issues added to and completed in a given timebox.
+### Group issues by label
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225500) in GitLab 13.8.
+
+You can group the list of issues by label.
+This can help you view issues that have your team's label,
+and get a more accurate understanding of scope attributable to each label.
+
+To group issues by label:
+
+1. In the **Group by** dropdown, select **Label**.
+1. Select the **Filter by label** dropdown.
+1. Select the labels you want to group by in the labels dropdown.
+ 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)**
GitLab Iterations feature is deployed with a feature flag that is **enabled by default**.
diff --git a/doc/user/group/roadmap/img/roadmap_filters_v13_7.png b/doc/user/group/roadmap/img/roadmap_filters_v13_7.png
deleted file mode 100644
index 00505a7f34f..00000000000
--- a/doc/user/group/roadmap/img/roadmap_filters_v13_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_filters_v13_8.png b/doc/user/group/roadmap/img/roadmap_filters_v13_8.png
new file mode 100644
index 00000000000..d826909b022
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_filters_v13_8.png
Binary files differ
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 6dfa7641dbb..f3b7be536ae 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -67,8 +67,9 @@ You can also filter epics in the Roadmap view by:
- Author
- Label
- Milestone
+- Confidentiality of epics
-![roadmap date range in weeks](img/roadmap_filters_v13_7.png)
+![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).
diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md
index 15dd91bece2..7158b7bc86b 100644
--- a/doc/user/group/saml_sso/group_managed_accounts.md
+++ b/doc/user/group/saml_sso/group_managed_accounts.md
@@ -52,11 +52,13 @@ assertions to be able to create a user.
## Feature flag **(PREMIUM ONLY)**
-The group-managed accounts feature is behind a feature flag: `group_managed_accounts`. The flag is disabled by default.
+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:
```ruby
Feature.enable(:group_managed_accounts)
+Feature.enable(:sign_up_on_sso)
+Feature.enable(:convert_user_to_group_managed_accounts)
```
## Project restrictions for Group-managed accounts
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 62431747911..0ce92eac1a3 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -80,10 +80,14 @@ Please note that the certificate [fingerprint algorithm](#additional-providers-a
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5291) in GitLab 11.8.
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) in GitLab 11.11 with ongoing enforcement in the GitLab UI.
+- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience.
+- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO.
With this option enabled, users must go through your group's GitLab single sign-on URL. They may also be added via SCIM, if configured. Users can't be added manually, and may only access project/group resources via the UI by signing in through the SSO URL.
-However, users are not prompted to sign in through SSO on each visit. GitLab checks whether a user has authenticated through SSO, and only prompts the user to sign in via SSO if the session has expired.
+However, users are not prompted to sign in through SSO on each visit. GitLab checks whether a user
+has authenticated through SSO. If it's been more than 7 days since the last sign-in, GitLab
+prompts the user to sign in again through SSO.
You can see more information about how long a session is valid in our [user profile documentation](../../profile/#why-do-i-keep-getting-signed-out).
We intend to add a similar SSO requirement for [Git and API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152).
@@ -93,11 +97,10 @@ When SSO enforcement is enabled for a group, users can't share a project in the
## Providers
NOTE:
-GitLab is unable to provide support for IdPs that are not listed here.
+GitLab is unable to provide full support for integrating identify providers that are not listed here.
| Provider | Documentation |
|----------|---------------|
-| ADFS (Active Directory Federation Services) | [Create a Relying Party Trust](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) |
| Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) |
| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) |
| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) |
@@ -164,8 +167,9 @@ For more information, see our [discussion on providers](#providers).
Your identity provider may have relevant documentation. It may be generic SAML documentation, or specifically targeted for GitLab. Examples:
+- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
- [Auth0](https://auth0.com/docs/protocols/saml-configuration-options/configure-auth0-as-saml-identity-provider)
-- [G Suite](https://support.google.com/a/answer/6087519?hl=en)
+- [Google Workspace](https://support.google.com/a/answer/6087519?hl=en)
- [JumpCloud](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47)
- [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html)
@@ -209,7 +213,7 @@ When a user tries to sign in with Group SSO, GitLab attempts to find or create a
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 Admin 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. 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. 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.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 40c036e1fc0..cd3e99ae541 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -232,7 +232,7 @@ It is important that this SCIM `id` and SCIM `externalId` are configured to the
Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page.
-A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-of-saml-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`.
+A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`.
To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](index.md#saml-debugging-tools).
@@ -251,7 +251,7 @@ you can address the problem in the following ways:
- You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](index.md#message-saml-authentication-failed-user-has-already-been-taken) section.
- You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on.
-- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-saml-user) to manually correct the `externalId` stored for users to match the SAML `NameId`.
+- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`.
To look up a user, you'll need to know the desired value that matches the `NameId` as well as the current `externalId`.
It is important not to update these to incorrect values, since this will cause users to be unable to sign in. It is also important not to assign a value to the wrong user, as this would cause users to get signed into the wrong account.
@@ -269,7 +269,7 @@ Changing the SAML or SCIM configuration or provider can cause the following prob
| Problem | Solution |
|------------------------------------------------------------------------------|--------------------|
| SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). |
-| SCIM identity mismatch between GitLab and the Identify Provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../api/scim.md#update-a-single-saml-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md#update-a-single-saml-user) to update the SCIM `id` for the user on GitLab.com. |
+| SCIM identity mismatch between GitLab and the Identify Provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. |
### Azure
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 2aee8706194..6b95388bf2e 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -76,7 +76,7 @@ For more details on the specific data persisted in a group export, see the
file from there by clicking **Download export**, or generate a new file by clicking **Regenerate export**.
NOTE:
-The maximum import file size can be set by the Administrator, default is 50MB.
+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).
### Between CE and EE
diff --git a/doc/user/group/subgroups/img/group_members_filter_v12_6.png b/doc/user/group/subgroups/img/group_members_filter_v12_6.png
deleted file mode 100644
index 692fdfe00a1..00000000000
--- a/doc/user/group/subgroups/img/group_members_filter_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 8af075fc0c0..59812fc2b2f 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -117,7 +117,7 @@ Follow the same process to create any subsequent groups.
## Membership
When you add a member to a group, that member is also added to all subgroups.
-Permission level is inherited from the group’s parent. This model allows access to
+Permission level is inherited from the group’s parent. This model allows access to
subgroups if you have membership in one of its parents.
Jobs for pipelines in subgroups can use [runners](../../../ci/runners/README.md) registered to the parent group(s).
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 0f9afdef995..438769872c0 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -316,15 +316,6 @@ To delete a custom value stream:
![Delete value stream](img/delete_value_stream_v13.4.png "Deleting a custom value stream")
-### Disabling custom value streams
-
-Custom value streams are enabled by default. If you have a self-managed instance, an
-administrator can open a Rails console and disable them with the following command:
-
-```ruby
-Feature.disable(:value_stream_analytics_create_multiple_value_streams)
-```
-
## Days to completion chart
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6.
diff --git a/doc/user/infrastructure/img/terraform_list_view_actions_v13_8.png b/doc/user/infrastructure/img/terraform_list_view_actions_v13_8.png
new file mode 100644
index 00000000000..7d619b6ad7e
--- /dev/null
+++ b/doc/user/infrastructure/img/terraform_list_view_actions_v13_8.png
Binary files differ
diff --git a/doc/user/infrastructure/img/terraform_list_view_v13_5.png b/doc/user/infrastructure/img/terraform_list_view_v13_5.png
deleted file mode 100644
index b23dfa6289e..00000000000
--- a/doc/user/infrastructure/img/terraform_list_view_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/infrastructure/img/terraform_list_view_v13_8.png b/doc/user/infrastructure/img/terraform_list_view_v13_8.png
new file mode 100644
index 00000000000..6eb85285e81
--- /dev/null
+++ b/doc/user/infrastructure/img/terraform_list_view_v13_8.png
Binary files differ
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index 4c012fbf1d9..60453b007ba 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -8,11 +8,37 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Motivation
-The Terraform integration features within GitLab enable your GitOps / Infrastructure-as-Code (IaC)
+The Terraform integration features in GitLab enable your GitOps / Infrastructure-as-Code (IaC)
workflows to tie into GitLab authentication and authorization. These features focus on
-lowering the barrier to entry for teams to adopt Terraform, collaborate effectively within
+lowering the barrier to entry for teams to adopt Terraform, collaborate effectively in
GitLab, and support Terraform best practices.
+## Quick Start
+
+Use the following `.gitlab-ci.yml` to set up a basic Terraform project integration
+for GitLab versions 13.5 and later:
+
+```yaml
+include:
+ - template: Terraform.latest.gitlab-ci.yml
+
+variables:
+ # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
+ TF_STATE_NAME: default
+ TF_CACHE_KEY: default
+```
+
+This template uses `.latest.`, instead of stable, and may include breaking changes.
+This template also includes some opinionated decisions, which you can override:
+
+- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images).
+- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as
+ the Terraform state storage backend.
+- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml):
+ `init`, `validate`, `build`, and `deploy`. These stages
+ [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
+ `init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
+
## GitLab Managed Terraform state
[Terraform remote backends](https://www.terraform.io/docs/backends/index.html)
@@ -22,7 +48,7 @@ to securely store the state files in local storage (the default) or
[the remote store of your choice](../../administration/terraform_state.md).
The GitLab managed Terraform state backend can store your Terraform state easily and
-securely, and spares you from setting up additional remote resources like
+securely. It spares you from setting up additional remote resources like
Amazon S3 or Google Cloud Storage. Its features include:
- Supporting encryption of the state file both in transit and at rest.
@@ -39,32 +65,23 @@ recommends encrypting plan output or modifying the project visibility settings.
## Terraform integration in Merge Requests
-Collaborating around Infrastructure as Code (IaC) changes requires both code changes and expected infrastructure changes to be checked and approved. GitLab provides a solution to help collaboration around Terraform code changes and their expected effects using the Merge Request pages. This way users don't have to build custom tools or rely on 3rd party solutions to streamline their IaC workflows.
+Collaborating around Infrastructure as Code (IaC) changes requires both code changes
+and expected infrastructure changes to be checked and approved. GitLab provides a
+solution to help collaboration around Terraform code changes and their expected
+effects using the Merge Request pages. This way users don't have to build custom
+tools or rely on 3rd party solutions to streamline their IaC workflows.
Read more on setting up and [using the merge request integrations](mr_integration.md).
-## Quick Start
-
-Use the following `.gitlab-ci.yml` to set up a simple Terraform project integration
-for GitLab versions 13.5 and greater:
+## The GitLab terraform provider
-```yaml
-include:
- - template: Terraform.latest.gitlab-ci.yml
-
-variables:
- # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
- TF_STATE_NAME: default
- TF_CACHE_KEY: default
-```
+WARNING:
+The GitLab Terraform provider is released separately from GitLab.
+We are working on migrating the GitLab Terraform provider for GitLab.com.
-This template uses `.latest.`, instead of stable, and may include breaking changes.
-This template also includes some opinionated decisions, which you can override:
+You can use the [GitLab Terraform provider](https://github.com/gitlabhq/terraform-provider-gitlab)
+to manage various aspects of GitLab using Terraform. The provider is an open source project,
+owned by GitLab, where everyone can contribute.
-- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images).
-- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as
- the Terraform state storage backend.
-- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml):
- `init`, `validate`, `build`, and `deploy`. These stages
- [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
- `init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
+The [documentation of the provider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs)
+is available as part of the official Terraform provider documentations.
diff --git a/doc/user/infrastructure/mr_integration.md b/doc/user/infrastructure/mr_integration.md
index c86e5ddf1db..2704e7b7c8d 100644
--- a/doc/user/infrastructure/mr_integration.md
+++ b/doc/user/infrastructure/mr_integration.md
@@ -72,10 +72,10 @@ To manually configure a GitLab Terraform Report artifact requires the following
terraform: $PLAN_JSON
```
- For a full example using the pre-built image, see [Example `.gitlab-ci.yaml`
- file](#example-gitlab-ciyaml-file).
+ For a full example using the pre-built image, see [Example `.gitlab-ci.yml`
+ file](#example-gitlab-ciyml-file).
- For an example displaying multiple reports, see [`.gitlab-ci.yaml` multiple reports file](#multiple-terraform-plan-reports).
+ For an example displaying multiple reports, see [`.gitlab-ci.yml` multiple reports file](#multiple-terraform-plan-reports).
1. Running the pipeline displays the widget in the merge request, like this:
@@ -86,7 +86,7 @@ To manually configure a GitLab Terraform Report artifact requires the following
![Terraform plan logs](img/terraform_plan_log_v13_0.png)
-### Example `.gitlab-ci.yaml` file
+### Example `.gitlab-ci.yml` file
```yaml
default:
diff --git a/doc/user/infrastructure/terraform_state.md b/doc/user/infrastructure/terraform_state.md
index cbd2a63524d..30838b1cabd 100644
--- a/doc/user/infrastructure/terraform_state.md
+++ b/doc/user/infrastructure/terraform_state.md
@@ -62,7 +62,7 @@ local machine, this is a simple way to get started:
1. On your local machine, run `terraform init`, passing in the following options,
replacing `<YOUR-STATE-NAME>`, `<YOUR-PROJECT-ID>`, `<YOUR-USERNAME>` and
`<YOUR-ACCESS-TOKEN>` with the relevant values. This command initializes your
- Terraform state, and stores that state within your GitLab project. The name of
+ Terraform state, and stores that state in your GitLab project. The name of
your state can contain only uppercase and lowercase letters, decimal digits,
hyphens, and underscores. This example uses `gitlab.com`:
@@ -104,7 +104,7 @@ and the CI YAML file:
```
1. In the root directory of your project repository, configure a
- `.gitlab-ci.yaml` file. This example uses a pre-built image which includes a
+ `.gitlab-ci.yml` file. This example uses a pre-built image which includes a
`gitlab-terraform` helper. For supported Terraform versions, see the [GitLab
Terraform Images project](https://gitlab.com/gitlab-org/terraform-images).
@@ -112,7 +112,7 @@ and the CI YAML file:
image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
```
-1. In the `.gitlab-ci.yaml` file, define some environment variables to ease
+1. In the `.gitlab-ci.yml` file, define some environment variables to ease
development. In this example, `TF_ROOT` is the directory where the Terraform
commands must be executed, `TF_ADDRESS` is the URL to the state on the GitLab
instance where this pipeline runs, and the final path segment in `TF_ADDRESS`
@@ -194,7 +194,7 @@ recommends encrypting plan output or modifying the project visibility settings.
### Example project
-See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 within a custom VPC.
+See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 in a custom VPC.
## Using a GitLab managed Terraform state backend as a remote data source
@@ -234,7 +234,7 @@ An example setup is shown below:
}
```
-Outputs from the data source can now be referenced within your Terraform resources
+Outputs from the data source can now be referenced in your Terraform resources
using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`.
You need at least [developer access](../permissions.md) to the target project
@@ -340,21 +340,76 @@ commands will detect it and remind you to do so if necessary.
```
If you type `yes`, it copies your state from the old location to the new
-location. You can then go back to running it from within GitLab CI.
+location. You can then go back to running it in GitLab CI/CD.
## Managing state files
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273592) in GitLab 13.8.
+
+Users with Developer and greater [permissions](../permissions.md) can view the
+state files attached to a project at **Operations > Terraform**. Users with
+Maintainer permissions can perform commands on the state files. The user interface
+contains these fields:
+
+![Terraform state list](img/terraform_list_view_v13_8.png)
+
+- **Name**: The name of the environment, with a locked (**{lock}**) icon if the
+ state file is locked.
+- **Pipeline**: A link to the most recent pipeline and its status.
+- **Details**: Information about when the state file was created or changed.
+- **Actions**: Actions you can take on the state file, including downloading,
+ locking, unlocking, or [removing](#remove-a-state-file) the state file and versions:
+
+ ![Terraform state list](img/terraform_list_view_actions_v13_8.png)
+
NOTE:
-We are currently working on [providing a graphical interface for managing state files](https://gitlab.com/groups/gitlab-org/-/epics/4563).
+Additional improvements to the
+[graphical interface for managing state files](https://gitlab.com/groups/gitlab-org/-/epics/4563)
+are planned.
+
+## Remove a state file
+
+Users with Maintainer and greater [permissions](../permissions.md) can use the
+following options to remove a state file:
-![Terraform state list](img/terraform_list_view_v13_5.png)
+- **GitLab UI**: Go to **Operations > Terraform**. In the **Actions** column,
+ click the vertical ellipsis (**{ellipsis_v}**) button and select
+ **Remove state file and versions**.
+- **GitLab REST API**: You can remove a state file by making a request to the
+ REST API. For example:
-The state files attached to a project can be found under Operations / Terraform.
+ ```shell
+ curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>"
+ ```
-## Removing a State file
+- [GitLab GraphQL API](#remove-a-state-file-with-the-gitlab-graphql-api).
-You can only remove a state file by making a request to the API, like the following example:
+### Remove a state file with the GitLab GraphQL API
+
+You can remove a state file by making a GraphQL API request. For example:
+
+```shell
+mutation deleteState {
+ terraformStateDelete(input: { id: "<global_id_for_the_state>" }) {
+ errors
+ }
+}
+```
+
+You can obtain the `<global_id_for_the_state>` by querying the list of states:
```shell
-curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>"
+query ProjectTerraformStates {
+ project(fullPath: "<your_project_path>") {
+ terraformStates {
+ nodes {
+ id
+ name
+ }
+ }
+ }
+}
```
+
+For those new to the GitLab GraphQL API, read
+[Getting started with GitLab GraphQL API](../../api/graphql/getting_started.md).
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 751915f84a0..6159ea395fa 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -21,6 +21,11 @@ If you do not have a Composer package, create one and check it in to
a repository. This example shows a GitLab repository, but the repository
can be any public or private repository.
+WARNING:
+If you are using a GitLab repository, the project must have been created from
+a group's namespace, rather than a user's namespace. Composer packages
+[can't be published to projects created from a user's namespace](https://gitlab.com/gitlab-org/gitlab/-/issues/235467).
+
1. Create a directory called `my-composer-package` and change to that directory:
```shell
@@ -72,8 +77,8 @@ Prerequisites:
- A package in a GitLab repository. Composer packages should be versioned based on
the [Composer specification](https://getcomposer.org/doc/04-schema.md#version).
- If the version is not valid, for example, it has three dots (`1.0.0.0`), an
- error (`Validation failed: Version is invalid`) occurs when you publish.
+ If the version is not valid, for example, it has three dots (`1.0.0.0`), an
+ error (`Validation failed: Version is invalid`) occurs when you publish.
- A valid `composer.json` file.
- The Packages feature is enabled in a GitLab repository.
- The project ID, which is on the project's home page.
@@ -132,6 +137,13 @@ A more detailed Composer CI/CD file is also available as a `.gitlab-ci.yml` temp
WARNING:
Do not save unless you want to overwrite the existing CI/CD file.
+## Publishing packages with the same name or version
+
+When you publish:
+
+- The same package with different data, it overwrites the existing package.
+- The same package with the same data, a `404 Bad request` error occurs.
+
## Install a Composer package
Install a package from the Package Registry so you can use it as a dependency.
@@ -260,6 +272,6 @@ 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-with-satis.md#authentication) tool with your personal access token
+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
[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 73798d363af..f90c220a622 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -47,7 +47,7 @@ Conan version 1.20.5
### Install CMake
When you develop with C++ and Conan, you can select from many available
-compilers. This example uses the CMake compiler.
+compilers. This example uses the CMake build system generator.
To install CMake:
@@ -283,6 +283,9 @@ Additional Conan images to use as the basis of your CI file are available in the
Install a Conan package from the Package Registry so you can use it as a
dependency.
+WARNING:
+Project-level packages [cannot be downloaded currently](https://gitlab.com/gitlab-org/gitlab/-/issues/270129).
+
Conan packages are often installed as dependencies by using the `conanfile.txt`
file.
@@ -384,3 +387,16 @@ The GitLab Conan repository supports the following Conan CLI commands:
packages you have permission to view.
- `conan info`: View the information on a given package from the Package Registry.
- `conan remove`: Delete the package from the Package Registry.
+
+## Troubleshooting Conan packages
+
+### `ERROR: <package> was not found in remote <remote>`
+
+When you attempt to install a Conan package, you might receive a `404` error
+like `ERROR: <package> was not found in remote <remote>`.
+
+This issue occurs when you request a download from the project-level Conan API.
+The resulting URL is missing is project's `/<id>` and Conan commands, like
+`conan install`, fail.
+
+For more information, see [issue 270129](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 4e8d105adfa..8c284ccb9a3 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -305,7 +305,7 @@ is set to `always`.
To use your own Docker images for Docker-in-Docker, follow these steps
in addition to the steps in the
-[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor) section:
+[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) section:
1. Update the `image` and `service` to point to your registry.
1. Add a service [alias](../../../ci/yaml/README.md#servicesalias).
@@ -666,6 +666,23 @@ For example, you may have two individual images, one for `amd64` and another for
As a workaround, you should include the architecture in the tag name of individual images. For example, use `mygroup/myapp:1.0.0-amd64` instead of using sub repositories, like `mygroup/myapp/amd64:1.0.0`. You can then tag the manifest list with `mygroup/myapp:1.0.0`.
+### The cleanup policy doesn't delete any tags
+
+In GitLab 13.6 and earlier, when you run the cleanup policy,
+you may expect it to delete tags and it does not.
+
+This issue occurs when the cleanup policy was saved without
+editing the value in the **Remove tags matching** field.
+
+This field had a grayed out `.*` value as a placeholder.
+Unless `.*` (or other regex pattern) was entered explicitly into the
+field, a `nil` value was submitted. This value prevents the
+saved cleanup policy from matching any tags.
+
+As a workaround, edit the cleanup policy. In the **Remove tags matching**
+field, enter `.*` and save. This value indicates that all tags should
+be removed.
+
### Troubleshoot as a GitLab server admin
Troubleshooting the GitLab Container Registry, most of the times, requires
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index fbede6d13b7..5e5aadfae2b 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -141,11 +141,10 @@ You can use the Dependency Proxy to pull your base image.
bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
```
- This can also be other credentials such as:
+ 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
- echo -n "deploy_token_username:deploy_token" | base64
```
1. Create a [custom environment variables](../../../ci/variables/README.md#custom-environment-variables)
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index c9859840c9c..82c72481984 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -20,16 +20,24 @@ Publish generic files, like release binaries, in your project’s Package Regist
## Authenticate to the Package Registry
-To authenticate to the Package Registry, you need either a [personal access token](../../../api/README.md#personalproject-access-tokens)
-or [CI job token](../../../api/README.md#gitlab-ci-job-token).
+To authenticate to the Package Registry, you need either a [personal access token](../../../api/README.md#personalproject-access-tokens),
+[CI job token](../../../api/README.md#gitlab-ci-job-token), or [deploy token](../../project/deploy_tokens/index.md).
+
+In addition to the standard API authentication mechanisms, the generic package
+API allows authentication with HTTP Basic authentication for use with tools that
+do not support the other available mechanisms. The `user-id` is not checked and
+may be any value, and the `password` must be either a [personal access token](../../../api/README.md#personalproject-access-tokens),
+a [CI job token](../../../api/README.md#gitlab-ci-job-token), or a [deploy token](../../project/deploy_tokens/index.md).
## Publish a package file
When you publish a package file, if the package does not exist, it is created.
+If a package with the same name, version, and filename already exists, it is also created. It does not overwrite the existing package.
+
Prerequisites:
-- You need to [authenticate with the API](../../../api/README.md#authentication).
+- You need to [authenticate with the API](../../../api/README.md#authentication). If authenticating with a deploy token, it must be configured with the `write_package_registry` scope.
```plaintext
PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name
@@ -62,11 +70,13 @@ Example response:
## Download package file
-Install a package file.
+Download a package file.
+
+If multiple packages have the same name, version, and filename, then the most recent one is retrieved.
Prerequisites:
-- You need to [authenticate with the API](../../../api/README.md#authentication).
+- You need to [authenticate with the API](../../../api/README.md#authentication). If authenticating with a deploy token, it must be configured with the `read_package_registry` and/or `write_package_registry` scope.
```plaintext
GET /projects/:id/packages/generic/:package_name/:package_version/:file_name
@@ -88,6 +98,13 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
```
+Example request that uses HTTP Basic authentication:
+
+```shell
+curl --user "user:<your_access_token>" \
+ https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt
+```
+
## Publish a generic package by using CI/CD
To work with generic packages in [GitLab CI/CD](../../../ci/README.md), you can use
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index 51b41b842fa..c16fea1d00a 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -94,7 +94,10 @@ Some features such as [publishing](#publish-an-npm-package) a package is only av
## Authenticate to the Package Registry
-To authenticate to the Package Registry, you must use one of the following:
+You must authenticate with the Package Registry when the project
+is private. Public projects do not require authentication.
+
+To authenticate, use one of the following:
- A [personal access token](../../../user/profile/personal_access_tokens.md)
(required for two-factor authentication (2FA)), with the scope set to `api`.
@@ -102,7 +105,7 @@ To authenticate to the Package Registry, you must use one of the following:
- It's not recommended, but you can use [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow).
Standard OAuth tokens cannot authenticate to the GitLab NPM Registry. You must use a personal access token with OAuth headers.
- A [CI job token](#authenticate-with-a-ci-job-token).
-- Your NPM package name must be in the format of [@scope:package-name](#package-naming-convention). It must match exactly, including the case.
+- Your NPM package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case.
### Authenticate with a personal access token or deploy token
@@ -201,7 +204,7 @@ Then, you can run `npm publish` either locally or by using GitLab CI/CD.
## 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.
@@ -241,7 +244,7 @@ Prerequisites:
- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
- Set a [project-level NPM endpoint](#use-the-gitlab-endpoint-for-npm-packages).
-- Your NPM package name must be in the format of [@scope:package-name](#package-naming-convention). 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.
To upload an NPM package to your project, run this command:
@@ -461,7 +464,30 @@ If you get this error, ensure that:
### `npm publish` returns `npm ERR! 400 Bad Request`
If you get this error, your package name may not meet the
-[@scope:package-name package naming convention](#package-naming-convention).
+[@scope/package-name package naming convention](#package-naming-convention).
Ensure the name meets the convention exactly, including the case.
Then try to publish again.
+
+### `npm publish` returns `npm ERR! 500 Internal Server Error - PUT`
+
+This is a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/238950) in GitLab
+13.3.x and later. The error in the logs will appear as:
+
+```plaintext
+>NoMethodError - undefined method `preferred_language' for #<Rack::Response
+```
+
+This might be accompanied by another error:
+
+```plaintext
+>Errno::EACCES","exception.message":"Permission denied
+```
+
+This is usually a permissions issue with either:
+
+- `'packages_storage_path'` default `/var/opt/gitlab/gitlab-rails/shared/packages/`.
+- The remote bucket if [object storage](../../../administration/packages/#using-object-storage)
+ is used.
+
+In the latter case, ensure the bucket exists and the GitLab has write access to it.
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index bdf50ecef0b..35172663cc1 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -60,6 +60,21 @@ NuGet CLI.
mono nuget.exe
```
+## Use the GitLab endpoint for NuGet Packages
+
+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
+ same GitLab group.
+
+Some features such as [publishing](#publish-a-nuget-package) a package are only available on the project-level endpoint.
+
+WARNING:
+Because of how NuGet handles credentials, the Package Registry rejects anonymous requests on the group-level endpoint.
+To work around this limitation, set up [authentication](#add-the-package-registry-as-a-source-for-nuget-packages).
+
## Add the Package Registry as a source for NuGet packages
To publish and install packages to the Package Registry, you must add the
@@ -75,7 +90,9 @@ Prerequisites:
with the scope set to `read_package_registry`, `write_package_registry`, or
both.
- A name for your source.
-- Your project ID, which is found on your project's home page.
+- Depending on the [endpoint level](#use-the-gitlab-endpoint-for-nuget-packages) you use, either:
+ - Your project ID, which is found on your project's home page.
+ - Your group ID, which is found on your group's home page.
You can now add a new source to NuGet with:
@@ -85,7 +102,9 @@ You can now add a new source to NuGet with:
### Add a source with the NuGet CLI
-To add the Package Registry as a source with `nuget`:
+#### Project-level endpoint
+
+To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with `nuget`:
```shell
nuget source Add -Name <source_name> -Source "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" -UserName <gitlab_username or deploy_token_username> -Password <gitlab_personal_access_token or deploy_token>
@@ -99,9 +118,27 @@ For example:
nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" -UserName carol -Password 12345678asdf
```
+#### 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
+nuget source Add -Name <source_name> -Source "https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json" -UserName <gitlab_username or deploy_token_username> -Password <gitlab_personal_access_token or deploy_token>
+```
+
+- `<source_name>` is the desired source name.
+
+For example:
+
+```shell
+nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/groups/23/-/packages/nuget/index.json" -UserName carol -Password 12345678asdf
+```
+
### Add a source with Visual Studio
-To add the Package Registry as a source with Visual Studio:
+#### Project-level endpoint
+
+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/).
1. In Windows, select **File > Options**. On macOS, select **Visual Studio > Preferences**.
@@ -126,9 +163,38 @@ The source is displayed in your list.
If you get a warning, ensure that the **Location**, **Username**, and
**Password** are correct.
+#### 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/).
+1. In Windows, select **File > Options**. On macOS, select **Visual Studio > Preferences**.
+1. In the **NuGet** section, select **Sources** to view a list of all your NuGet sources.
+1. Select **Add**.
+1. Complete the following fields:
+ - **Name**: Name for the source.
+ - **Location**: `https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json`,
+ where `<your_group_id>` is your group ID, and `gitlab.example.com` is
+ your domain name.
+ - **Username**: Your GitLab username or deploy token username.
+ - **Password**: Your personal access token or deploy token.
+
+ ![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png)
+
+1. Click **Save**.
+
+The source is displayed in your list.
+
+![Visual Studio NuGet source added](img/visual_studio_nuget_source_added.png)
+
+If you get a warning, ensure that the **Location**, **Username**, and
+**Password** are correct.
+
### Add a source with the .NET CLI
-To add the Package Registry as a source for .NET:
+#### Project-level endpoint
+
+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`.
1. Add this content:
@@ -138,7 +204,30 @@ To add the Package Registry as a source for .NET:
<configuration>
<packageSources>
<clear />
- <add key="gitlab" value="https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" />
+ <add key="gitlab" value="https://gitlab.example.com/api/v4/project/<your_project_id>/packages/nuget/index.json" />
+ </packageSources>
+ <packageSourceCredentials>
+ <gitlab>
+ <add key="Username" value="<gitlab_username or deploy_token_username>" />
+ <add key="ClearTextPassword" value="<gitlab_personal_access_token or deploy_token>" />
+ </gitlab>
+ </packageSourceCredentials>
+ </configuration>
+ ```
+
+#### 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`.
+1. Add this content:
+
+ ```xml
+ <?xml version="1.0" encoding="utf-8"?>
+ <configuration>
+ <packageSources>
+ <clear />
+ <add key="gitlab" value="https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json" />
</packageSources>
<packageSourceCredentials>
<gitlab>
@@ -151,6 +240,10 @@ To add the Package Registry as a source for .NET:
## Publish a NuGet package
+Prerequisite:
+
+- Set up the [source](#https://docs.gitlab.com/ee/user/packages/nuget_repository/#add-the-package-registry-as-a-source-for-nuget-packages) with a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages).
+
When publishing packages:
- The Package Registry on GitLab.com can store up to 500 MB of content.
@@ -164,9 +257,10 @@ When publishing packages:
### Publish a package with the NuGet CLI
-Prerequisite:
+Prerequisites:
- [A NuGet package created with NuGet CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package).
+- Set a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages).
Publish a package by running this command:
@@ -179,9 +273,10 @@ nuget push <package_file> -Source <source_name>
### Publish a package with the .NET CLI
-Prerequisite:
+Prerequisites:
- [A NuGet package created with .NET CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli).
+- Set a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages).
Publish a package by running this command:
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index e78224f89d1..376c0439f32 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -233,11 +233,16 @@ password = ${env.CI_JOB_TOKEN}
## Publish a PyPI package
-When publishing packages, note that:
+Prerequisites:
-- The maximum allowed size is 50 MB.
+- You must [authenticate with the Package Registry](#authenticate-with-the-package-registry).
+- Your [version string must be valid](#ensure-your-version-string-is-valid).
+- The maximum allowed package size is 5 GB.
- You can't upload the same version of a package multiple times. If you try,
- you receive the error `Validation failed: File name has already been taken`.
+ you receive the error `400 Bad Request`.
+- You cannot publish PyPI packages to a group, only to a project.
+
+You can then [publish a package by using twine](#publish-a-pypi-package-by-using-twine).
### Ensure your version string is valid
@@ -301,6 +306,12 @@ python -m twine upload --repository <source_name> dist/<package_file>
- `<package_file>` is your package filename, ending in `.tar.gz` or `.whl`.
- `<source_name>` is the [source name used during setup](#authenticate-with-the-package-registry).
+### Publishing packages with the same name or version
+
+You cannot publish a package if a package of the same name and version already exists.
+You must delete the existing package first. If you attempt to publish the same package
+more than once, a `404 Bad Request` error occurs.
+
## Install a PyPI package
To install the latest version of a package, use the following command:
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index aea1238b9da..d20c75e2d7a 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -68,7 +68,7 @@ For Conan, you need to add GitLab as a Conan registry remote. Follow the instruc
Then, create your package using the plus-separated (`+`) project path as your Conan user. For example,
if your project is located at `https://gitlab.com/foo/bar/my-proj`,
[create your Conan package](../conan_repository/index.md) using `conan create . foo+bar+my-proj/channel`.
-`channel` is your package channel (such as `stable` or `beta`).
+`channel` is your package channel (such as `stable` or `beta`).
After you create your package, you're ready to [publish your package](../conan_repository/index.md#publish-a-conan-package),
depending on your final package recipe. For example:
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 0dd7d6f7696..3dbae78ccc4 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -75,6 +75,7 @@ The following table depicts the various user permission levels in a project.
| Manage user-starred metrics dashboards (*7*) | ✓ | ✓ | ✓ | ✓ | ✓ |
| View confidential issues | (*2*) | ✓ | ✓ | ✓ | ✓ |
| Assign issues | | ✓ | ✓ | ✓ | ✓ |
+| Assign reviewers | | ✓ | ✓ | ✓ | ✓ |
| Label issues | | ✓ | ✓ | ✓ | ✓ |
| Set issue weight | | ✓ | ✓ | ✓ | ✓ |
| Lock issue threads | | ✓ | ✓ | ✓ | ✓ |
@@ -94,7 +95,7 @@ The following table depicts the various user permission levels in a project.
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
| Archive/reopen requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| Create/edit requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| Import requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| Import/export requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| Create new [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Archive [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Move [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
@@ -322,7 +323,7 @@ project and should only have access to that project.
External users:
-- Cannot create groups, projects, or personal snippets.
+- Cannot create projects (including forks), groups, or personal snippets.
- Can only access public projects and projects to which they are explicitly granted access,
thus hiding all other internal or private ones from them (like being
logged out).
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index c25535cbf65..6cdd2d6f161 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -245,7 +245,7 @@ Search for `security.webauth.u2f` and double click on it to toggle to `true`.
To set up 2FA with a U2F device:
-1. Log in to your GitLab account.
+1. Sign in to your GitLab account.
1. Go to your [**Profile settings**](../index.md#profile-settings).
1. Go to **Account**.
1. Click **Enable Two-Factor Authentication**.
@@ -298,11 +298,11 @@ NOTE:
Recovery codes are not generated for U2F / WebAuthn devices.
WARNING:
-Each code can be used only once to log in to your account.
+Each code can be used only once to sign in to your account.
Immediately after successfully enabling two-factor authentication, you're
prompted to download a set of generated recovery codes. Should you ever lose access
-to your one-time password authenticator, you can use one of these recovery codes to log in to
+to your one-time password authenticator, you can use one of these recovery codes to sign in to
your account. We suggest copying and printing them, or downloading them using
the **Download codes** button for storage in a safe place. If you choose to
download them, the file is called `gitlab-recovery-codes.txt`.
@@ -314,41 +314,41 @@ If you lose the recovery codes or just want to generate new ones, you can do so
from the [two-factor authentication account settings page](#regenerate-2fa-recovery-codes) or
[using SSH](#generate-new-recovery-codes-using-ssh).
-## Logging in with 2FA Enabled
+## Signing in with 2FA Enabled
-Logging in with 2FA enabled is only slightly different than a normal login.
+Signing in with 2FA enabled is only slightly different than the normal sign-in process.
Enter your username and password credentials as you normally would, and you're
presented with a second prompt, depending on which type of 2FA you've enabled.
-### Log in via a one-time password
+### Sign in by using a one-time password
When asked, enter the pin from your one time password authenticator's application or a
-recovery code to log in.
+recovery code to sign in.
-### Log in via U2F device
+### Sign in by using a U2F device
-To log in via a U2F device:
+To sign in by using a U2F device:
1. Click **Login via U2F Device**.
1. A light begins blinking on your device. Activate it by touching/pressing
its button.
A message displays, indicating that your device responded to the authentication
-request, and you're automatically logged in.
+request, and you're automatically signed in.
-### Log in via WebAuthn device
+### Sign in by using a WebAuthn device
In supported browsers you should be automatically prompted to activate your WebAuthn device
(e.g. by touching/pressing its button) after entering your credentials.
A message displays, indicating that your device responded to the authentication
-request and you're automatically logged in.
+request and you're automatically signed in.
## Disabling 2FA
If you ever need to disable 2FA:
-1. Log in to your GitLab account.
+1. Sign in to your GitLab account.
1. Go to your [**Profile settings**](../index.md#profile-settings).
1. Go to **Account**.
1. Click **Disable**, under **Two-Factor Authentication**.
@@ -356,6 +356,9 @@ If you ever need to disable 2FA:
This clears all your two-factor authentication registrations, including mobile
applications and U2F / WebAuthn devices.
+Support for disabling 2FA is limited, depending on your subscription level. For more information, see the
+[Account Recovery](https://about.gitlab.com/support/#account-recovery) section of our website.
+
## Personal access tokens
When 2FA is enabled, you can no longer use your normal account password to
@@ -393,9 +396,13 @@ a new set of recovery codes with SSH:
1. Run:
```shell
- ssh git@gitlab.example.com 2fa_recovery_codes
+ ssh git@gitlab.com 2fa_recovery_codes
```
+ NOTE:
+ On self-managed instances, replace **`gitlab.com`** in the command above
+ with the GitLab server hostname (`gitlab.example.com`).
+
1. You are prompted to confirm that you want to generate new codes.
Continuing this process invalidates previously saved codes:
@@ -465,9 +472,9 @@ Sign in and re-enable two-factor authentication as soon as possible.
For example, if a user is trying to access a GitLab instance from `first.host.xyz` and `second.host.xyz`:
- - The user logs in via `first.host.xyz` and registers their U2F key.
- - The user logs out and attempts to log in via `first.host.xyz` - U2F authentication succeeds.
- - The user logs out and attempts to log in via `second.host.xyz` - U2F authentication fails, because
+ - The user signs in by using `first.host.xyz` and registers their U2F key.
+ - The user signs out and attempts to sign in by using `first.host.xyz` - U2F authentication succeeds.
+ - The user signs out and attempts to sign in by using `second.host.xyz` - U2F authentication fails, because
the U2F key has only been registered on `first.host.xyz`.
- To enforce 2FA at the system or group levels see [Enforce Two-factor Authentication](../../../security/two_factor_authentication.md).
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index d60fb528499..a96975fea92 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -203,11 +203,12 @@ If you previously selected the "Busy" checkbox, remember to deselect it when you
## Busy status indicator
-> - Introduced in GitLab 13.6.
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259649) in GitLab 13.6.
+> - It was [deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/281073) 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-busy-status-feature).
+> - 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
@@ -228,10 +229,16 @@ To set the busy status indicator, either:
1. Click **Edit profile** (**{pencil}**).
1. Select the **Busy** checkbox
-### Enable busy status feature
+### Disable busy status feature
-The busy status feature 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).
+The busy status feature is deployed behind a feature flag and is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) can disable it for your instance from the [rails console](../../administration/feature_flags.md#start-the-gitlab-rails-console).
+
+To disable it:
+
+```ruby
+Feature.disable(:set_user_availability_status)
+```
To enable it:
@@ -288,7 +295,7 @@ git config --global user.email <your email address>
When signing in to the main GitLab application, a `_gitlab_session` cookie is
set. `_gitlab_session` is cleared client-side when you close your browser
and expires after "Application settings -> Session duration (minutes)"/`session_expire_delay`
-(defaults to `10080` minutes = 7 days).
+(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`
@@ -316,7 +323,9 @@ The `remember_user_token` lifetime of a cookie can now extend beyond the deadlin
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 expiration date.
+- 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.
By default, the server sets a time-to-live (TTL) of 1-week on any session that is used.
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 8974505cf02..38ef01b7537 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -146,13 +146,15 @@ Users are notified of the following events:
| New email added | User | Security email, always sent. |
| Email changed | User | Security email, always sent. |
| Password changed | User | Security email, always sent when user changes their own password |
-| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user |
+| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user |
| Two-factor authentication disabled | User | Security email, always sent. |
| New user created | User | Sent on user creation, except for OmniAuth (LDAP)|
| User added to project | User | Sent when user is added to project |
| Project access level changed | User | Sent when user project access level is changed |
| User added to group | User | Sent when user is added to group |
| Group access level changed | User | Sent when user group access level is changed |
+| Personal Access Tokens expiring soon <!-- Do not delete or lint this instance of future tense --> | User | Security email, always sent. |
+| Personal Access Tokens have expired | User | Security email, always sent. |
| Project moved | Project members (1) | (1) not disabled |
| New release | Project members | Custom notification |
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index cfc70c5a6f0..49889cd3017 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -112,7 +112,7 @@ token = PersonalAccessToken.find_by_token('token-string-here123')
token.revoke!
```
-This can be shorted into a single-line shell command using the
+This can be shortened into a single-line shell command using the
[Rails runner](../../administration/troubleshooting/debug.md#using-the-rails-runner):
```shell
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index 52c825932fa..85ac641f6e4 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -4,9 +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 **(PREMIUM)**
+# Canary Deployments **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1.
+> - [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.
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
@@ -71,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.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to Core 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/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index 4fae10c58eb..9047e564598 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -122,6 +122,7 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
"iam:CreateInstanceProfile",
"iam:CreateServiceLinkedRole",
"iam:GetRole",
+ "iam:listAttachedRolePolicies",
"iam:ListRoles",
"iam:PassRole",
"ssm:GetParameters"
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 8ee9b1f37dd..beb8b71b917 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -189,7 +189,7 @@ To add a Kubernetes cluster to your project, group, or instance:
Get the API URL by running this command:
```shell
- kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}'
+ kubectl cluster-info | grep -E 'Kubernetes master|Kubernetes control plane' | awk '/http/ {print $NF}'
```
1. **CA certificate** (required) - A valid Kubernetes certificate is needed to authenticate to the cluster. We use the certificate created by default.
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 55467c8a468..a06846e33a6 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -20,7 +20,7 @@ Using the GitLab project Kubernetes integration, you can:
- Detect and [monitor Kubernetes](#monitoring-your-kubernetes-cluster).
- Use it with [Auto DevOps](#auto-devops).
- Use [Web terminals](#web-terminals).
-- Use [Deploy Boards](#deploy-boards). **(PREMIUM)**
+- Use [Deploy Boards](#deploy-boards).
- Use [Canary Deployments](#canary-deployments). **(PREMIUM)**
- Use [deployment variables](#deployment-variables).
- Use [role-based or attribute-based access controls](add_remove_clusters.md#access-controls).
@@ -248,9 +248,17 @@ Deployment variables require a valid [Deploy Token](../deploy_tokens/index.md) n
[`gitlab-deploy-token`](../deploy_tokens/index.md#gitlab-deploy-token), and the
following command in your deployment job script, for Kubernetes to access the registry:
-```plaintext
-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 -
-```
+- Using Kubernetes 1.18+:
+
+ ```shell
+ 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=client | kubectl apply -f -
+ ```
+
+- Using Kubernetes <1.18:
+
+ ```shell
+ 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
@@ -308,7 +316,7 @@ combined with either
### Integrations
-#### Canary Deployments **(PREMIUM)**
+#### Canary Deployments
Leverage [Kubernetes' Canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)
and visualize your canary deployments right inside the Deploy Board, without
@@ -316,7 +324,7 @@ the need to leave GitLab.
[Read more about Canary Deployments](../canary_deployments.md)
-#### Deploy Boards **(PREMIUM)**
+#### 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,
diff --git a/doc/user/project/clusters/protect/container_host_security/index.md b/doc/user/project/clusters/protect/container_host_security/index.md
new file mode 100644
index 00000000000..102001d4f87
--- /dev/null
+++ b/doc/user/project/clusters/protect/container_host_security/index.md
@@ -0,0 +1,59 @@
+---
+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
+---
+
+# Container Host Security
+
+Container Host Security in GitLab provides Intrusion Detection and Prevention capabilities that can
+monitor and (optionally) block activity inside the containers themselves. This is done by leveraging
+an integration with Falco to provide the monitoring capabilities and an integration with Pod
+Security Policies and AppArmor to provide blocking capabilities.
+
+## Overview
+
+Container Host Security can be used to monitor and block activity inside a container as well as to
+enforce security policies across the entire Kubernetes cluster. Falco profiles allow for users to
+define the activity they want to monitor for and detect. Among other things, this can include system
+log entries, process starts, file activity, and network ports opened. AppArmor is used to block any
+undesired activity via AppArmor profiles. These profiles are loaded into the cluster when
+referenced by Pod Security Policies.
+
+By default, Container Host Security is deployed into the cluster in monitor mode only, with no
+default profiles or rules running out-of-the-box. Activity monitoring and blocking begins only when
+users define profiles for these technologies.
+
+## Installation
+
+See the [installation guide](quick_start_guide.md) for the recommended steps to install the
+Container Host Security capabilities. This guide shows the recommended way of installing Container
+Host Security through GMAv2. However, it's also possible to do a manual installation through our
+Helm chart.
+
+## Features
+
+- Prevent containers from starting as root.
+- Limit the privileges and system calls available to containers.
+- Monitor system logs, process starts, files read/written/deleted, and network ports opened.
+- Optionally block processes from starting or files from being read/written/deleted.
+
+## Supported container orchestrators
+
+Kubernetes v1.14+ is the only supported container orchestrator. OpenShift and other container
+orchestrators aren't supported.
+
+## Supported Kubernetes providers
+
+The following cloud providers are supported:
+
+- Amazon EKS
+- Google GKE
+
+Although Container Host Security may function on Azure or self-managed Kubernetes instances, it isn't
+officially tested and supported on those providers.
+
+## Roadmap
+
+See the [Category Direction page](https://about.gitlab.com/direction/protect/container_host_security/)
+for more information on the product direction of Container Host Security.
diff --git a/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
new file mode 100644
index 00000000000..0c4ec72ed5b
--- /dev/null
+++ b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
@@ -0,0 +1,81 @@
+---
+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
+---
+
+# Getting started with Container Host Security
+
+The following steps are recommended for installing Container Host Security. Although you can install
+some capabilities through GMAv1, we [recommend](#using-gmav1-with-gmav2) that you install
+applications through GMAv2 exclusively when using Container Network Security.
+
+## Installation steps
+
+The following steps are recommended to install and use Container Host Security through GitLab:
+
+1. [Install at least one runner and connect it to GitLab](https://docs.gitlab.com/runner/).
+1. [Create a group](../../../../group/#create-a-new-group).
+1. [Connect a Kubernetes cluster to the group](../../add_remove_clusters.md).
+1. [Create a cluster management project and associate it with the Kubernetes cluster](../../../../clusters/management_project.md).
+
+1. Install and configure an Ingress node:
+
+ - [Install the Ingress node via CI/CD (GMAv2)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd).
+ - [Determine the external endpoint via the manual method](../../../../clusters/applications.md#determining-the-external-endpoint-manually).
+ - Navigate to the Kubernetes page and enter the [DNS address for the external endpoint](../../index.md#base-domain)
+ into the **Base domain** field on the **Details** tab. Save the changes to the Kubernetes
+ cluster.
+
+1. [Install and configure Falco](../../../../clusters/applications.md#install-falco-using-gitlab-cicd)
+ for activity monitoring.
+1. [Install and configure AppArmor](../../../../clusters/applications.md#install-apparmor-using-gitlab-cicd)
+ for activity blocking.
+1. [Configure Pod Security Policies](../../../../clusters/applications.md#using-podsecuritypolicy-in-your-deployments)
+ (required to be able to load AppArmor profiles).
+
+It's possible to install and manage Falco and AppArmor in other ways, such as installing them
+manually in a Kubernetes cluster and then connecting it back to GitLab. These methods aren't
+supported or documented.
+
+## Viewing the logs
+
+Falco logs can be viewed by running the following command in your Kubernetes cluster:
+
+```shell
+kubectl -n gitlab-managed-apps logs -l app=falco
+```
+
+## Troubleshooting
+
+### Trouble connecting to the cluster
+
+Your CI/CD pipeline may occasionally fail or have trouble connecting to the cluster. Here are some
+initial troubleshooting steps that resolve the most common problems:
+
+1. [Clear the cluster cache](../../index.md#clearing-the-cluster-cache)
+1. If things still aren't working, a more assertive set of actions may help get things back to a
+ good state:
+
+ - Stop and [delete the problematic environment](../../../../../ci/environments/#delete-environments-through-the-ui)
+ in GitLab.
+ - Delete the relevant namespace in Kubernetes by running
+ `kubectl delete namespaces <insert-some-namespace-name>` in your Kubernetes cluster.
+ - Rerun the application project pipeline to redeploy the application.
+
+### Using GMAv1 with GMAv2
+
+When GMAv1 and GMAv2 are used together on the same cluster, users may experience problems with
+applications being uninstalled or removed from the cluster. This is because GMAv2 actively
+uninstalls applications that are installed with GMAv1 and not configured to be installed with GMAv2.
+It's possible to use a mixture of applications installed with GMAv1 and GMAv2 by ensuring that the
+GMAv1 applications are installed **after** the GMAv2 cluster management project pipeline runs. GMAv1
+applications must be reinstalled after each run of that pipeline. This approach isn't recommended as
+it's error-prone and can lead to downtime as applications are uninstalled and later reinstalled.
+When using Container Network Security, the preferred and recommended path is to install all
+necessary components with GMAv2 and the cluster management project.
+
+**Related documentation links:**
+
+- [GitLab Managed Apps v1 (GMAv1)](../../../../clusters/applications.md#install-with-one-click)
+- [GitLab Managed Apps v2 (GMAv2)](../../../../clusters/management_project.md)
diff --git a/doc/user/project/clusters/protect/container_network_security/index.md b/doc/user/project/clusters/protect/container_network_security/index.md
new file mode 100644
index 00000000000..8299844e511
--- /dev/null
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -0,0 +1,70 @@
+---
+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
+---
+
+# Container Network Security
+
+Container Network Security in GitLab provides basic firewall functionality by leveraging Cilium
+NetworkPolicies to filter traffic going in and out of the cluster as well as traffic between pods
+inside the cluster. Container Network Security can be used to enforce L3, L4, and L7 policies and
+can prevent an attacker with control over one pod from spreading laterally to access other pods in
+the same cluster. Both Ingress and Egress rules are supported.
+
+By default, Cilium is deployed in Detection-only mode and only logs attack attempts. GitLab provides
+a set of out-of-the-box policies as examples and to help users get started. These policies are
+disabled by default, as they must usually be customized to match application-specific needs.
+
+## Installation
+
+See the [installation guide](quick_start_guide.md) for the recommended steps to install GitLab
+Container Network Security. This guide shows the recommended way of installing Container Network
+Security through GMAv2. However, it's also possible to install Cilium manually through our Helm
+chart.
+
+## Features
+
+- 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).
+- 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).
+
+## Supported container orchestrators
+
+Kubernetes v1.14+ is the only supported container orchestrator. OpenShift and other container
+orchestrators aren't supported.
+
+## Supported Kubernetes providers
+
+The following cloud providers are supported:
+
+- Amazon EKS
+- Google GKE
+
+Although Container Network Security may function on Azure or self-managed Kubernetes instances, it
+isn't officially tested and supported on those providers.
+
+## Supported NetworkPolicies
+
+GitLab only supports the use of CiliumNetworkPolicies. Although generic Kubernetes NetworkPolicies
+or other kinds of NetworkPolicies may work, GitLab doesn't test or support them.
+
+## Managing NetworkPolicies through GitLab vs your cloud provider
+
+Some cloud providers offer integrations with Cilium or offer other ways to manage NetworkPolicies in
+Kubernetes. GitLab Container Network Security doesn't support deployments that have NetworkPolicies
+managed by an external provider. By choosing to manage NetworkPolicies through GitLab, you can take
+advantage of the following benefits:
+
+- Support for handling NetworkPolicy infrastructure as code.
+- Full revision history and audit log of all changes made.
+- Ability to revert back to a previous version at any time.
+
+## Roadmap
+
+See the [Category Direction page](https://about.gitlab.com/direction/protect/container_network_security/)
+for more information on the product direction of Container Network Security.
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
new file mode 100644
index 00000000000..10f9380a1f2
--- /dev/null
+++ b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
@@ -0,0 +1,153 @@
+---
+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
+---
+
+# Getting started with Container Network Security
+
+The following steps are recommended for installing Container Network Security. Although you can
+install some capabilities through GMAv1, we [recommend](#using-gmav1-with-gmav2) that you install
+applications through GMAv2 exclusively when using Container Network Security.
+
+## Installation steps
+
+The following steps are recommended to install and use Container Network Security through GitLab:
+
+1. [Install at least one runner and connect it to GitLab](https://docs.gitlab.com/runner/).
+1. [Create a group](../../../../group/#create-a-new-group).
+1. [Connect a Kubernetes cluster to the group](../../add_remove_clusters.md).
+1. [Create a cluster management project and associate it with the Kubernetes cluster](../../../../clusters/management_project.md).
+
+1. Install and configure an Ingress node:
+
+ - [Install the Ingress node via CI/CD (GMAv2)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd).
+ - [Determine the external endpoint via the manual method](../../../../clusters/applications.md#determining-the-external-endpoint-manually).
+ - Navigate to the Kubernetes page and enter the [DNS address for the external endpoint](../../index.md#base-domain)
+ into the **Base domain** field on the **Details** tab. Save the changes to the Kubernetes
+ cluster.
+
+1. [Install and configure Cilium](../../../../clusters/applications.md#install-cilium-using-gitlab-cicd).
+1. Be sure to restart all pods that were running before Cilium was installed by running this command
+ in your cluster:
+
+ `kubectl get pods --all-namespaces -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOSTNETWORK:.spec.hostNetwork --no-headers=true | grep '<none>' | awk '{print "-n "$1" "$2}' | xargs -L 1 -r kubectl delete pod`
+
+It's possible to install and manage Cilium in other ways. For example, you could use the GitLab Helm
+chart to install Cilium manually in a Kubernetes cluster, and then connect it back to GitLab.
+However, such methods aren't documented or officially supported by GitLab.
+
+## Managing Network Policies
+
+Managing NetworkPolicies through GitLab is advantageous over managing the policies in Kubernetes
+directly. Kubernetes doesn't provide a GUI editor, a change control process, or a revision history.
+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).
+
+Each method has benefits and drawbacks:
+
+| | YAML method | UI method (Ultimate/Gold 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. |
+
+Users are encouraged to choose one of the two methods to manage their policies. If users attempt to
+use both methods simultaneously, when the application project pipeline runs the contents of the
+NetworkPolicy in the `auto-deploy-values.yaml` file may override policies configured in the UI
+editor.
+
+## Monitoring throughput `**(ULTIMATE)**`
+
+To view statistics for Container Network Security, you must follow the installation steps above and
+configure GitLab integration with Prometheus. Also, if you use custom Helm values for Cilium, you
+must enable Hubble with flow metrics for each namespace by adding the following lines to
+your [Cilium values](../../../../clusters/applications.md#install-cilium-using-gitlab-cicd):
+your [Cilium values](../../../../clusters/applications.md#install-cilium-using-gitlab-cicd):
+
+```yaml
+global:
+ hubble:
+ enabled: true
+ metrics:
+ enabled:
+ - 'flow:sourceContext=namespace;destinationContext=namespace'
+```
+
+Additional information about the statistics page is available in the
+[documentation that describes the Threat Management UI](../../../../application_security/threat_monitoring/index.md#container-network-policy).
+
+## Forwarding logs to a SIEM
+
+Cilium logs can be forwarded to a SIEM or an external logging system through syslog protocol by
+installing and configuring Fluentd. Fluentd can be installed through GitLab in two ways:
+
+- The [GMAv1 method](../../../../clusters/applications.md#fluentd)
+- The [GMAv2 method](../../../../clusters/applications.md#install-fluentd-using-gitlab-cicd)
+
+GitLab strongly encourages using only the GMAv2 method to install Fluentd.
+
+## Viewing the logs
+
+Cilium logs can be viewed by running the following command in your Kubernetes cluster:
+
+```shell
+kubectl -n gitlab-managed-apps logs -l k8s-app=cilium -c cilium-monitor
+```
+
+## Troubleshooting
+
+### Traffic is not being blocked as expected
+
+By default, Cilium is installed in Audit mode only, meaning that NetworkPolicies log policy
+violations but don't block any traffic. To set Cilium to Blocking mode, you must add the following
+lines to the `.gitlab/managed-apps/cilium/values.yaml` file in your cluster management project:
+
+```yaml
+config:
+ policyAuditMode: false
+
+agent:
+ monitor:
+ eventTypes: ["drop"]
+```
+
+### Traffic is not being allowed as expected
+
+Keep in mind that when Cilium is set to blocking mode (rather than Audit mode), NetworkPolicies
+operate on an allow-list basis. If one or more NetworkPolicies apply to a node, then all traffic
+that doesn't match at least one Policy is blocked. To resolve, add NetworkPolicies defining the
+traffic that you want to allow in the node.
+
+### Trouble connecting to the cluster
+
+Occasionally, your CI/CD pipeline may fail or have trouble connecting to the cluster. Here are some
+initial troubleshooting steps that resolve the most common problems:
+
+1. [Clear the cluster cache](../../index.md#clearing-the-cluster-cache).
+1. If things still aren't working, a more assertive set of actions may help get things back into a
+ good state:
+
+ - Stop and [delete the problematic environment](../../../../../ci/environments/index.md#delete-environments-through-the-ui) in GitLab.
+ - Delete the relevant namespace in Kubernetes by running `kubectl delete namespaces <insert-some-namespace-name>` in your Kubernetes cluster.
+ - Rerun the application project pipeline to redeploy the application.
+
+### Using GMAv1 with GMAv2
+
+When GMAv1 and GMAv2 are used together on the same cluster, users may experience problems with
+applications being uninstalled or removed from the cluster. This is because GMAv2 actively
+uninstalls applications that are installed with GMAv1 and not configured to be installed with GMAv2.
+It's possible to use a mixture of applications installed with GMAv1 and GMAv2 by ensuring that the
+GMAv1 applications are installed **after** the GMAv2 cluster management project pipeline runs. GMAv1
+applications must be reinstalled after each run of that pipeline. This approach isn't recommended as
+it's error-prone and can lead to downtime as applications are uninstalled and later reinstalled.
+When using Container Network Security, the preferred and recommended path is to install all
+necessary components with GMAv2 and the cluster management project.
+
+**Related documentation links:**
+
+- [GitLab Managed Apps v1 (GMAv1)](../../../../clusters/applications.md#install-with-one-click)
+- [GitLab Managed Apps v2 (GMAv2)](../../../../clusters/management_project.md)
diff --git a/doc/user/project/clusters/protect/index.md b/doc/user/project/clusters/protect/index.md
new file mode 100644
index 00000000000..c489a0ddd30
--- /dev/null
+++ b/doc/user/project/clusters/protect/index.md
@@ -0,0 +1,29 @@
+---
+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
+---
+
+# Protecting your deployed applications
+
+GitLab makes it straightforward to protect applications deployed in [connected Kubernetes clusters](index.md).
+These protections are available in the Kubernetes network layer and in the container itself. At
+the network layer, the Container Network Security capabilities in GitLab provide basic firewall
+functionality by leveraging Cilium NetworkPolicies to filter traffic going in and out of the cluster
+and traffic between pods inside the cluster. Inside the container, Container Host Security provides
+Intrusion Detection and Prevention capabilities that can monitor and block activity inside the
+containers themselves.
+
+## Capabilities
+
+The following capabilities are available to protect deployed applications in Kubernetes:
+
+- Web Application Firewall
+ - [Overview](web_application_firewall/index.md)
+ - [Installation guide](web_application_firewall/quick_start_guide.md)
+- Container Network Security
+ - [Overview](container_network_security/index.md)
+ - [Installation guide](container_network_security/quick_start_guide.md)
+- Container Host Security
+ - [Overview](container_host_security/index.md)
+ - [Installation guide](container_host_security/quick_start_guide.md)
diff --git a/doc/topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png
index 2dd6df3d37b..2dd6df3d37b 100644
--- a/doc/topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png
+++ b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png
Binary files differ
diff --git a/doc/topics/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png
index e88f62a2eba..e88f62a2eba 100644
--- a/doc/topics/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png
+++ b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png
Binary files differ
diff --git a/doc/topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png
index 1c99d4f7f96..1c99d4f7f96 100644
--- a/doc/topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png
+++ b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png
Binary files differ
diff --git a/doc/user/project/clusters/protect/web_application_firewall/index.md b/doc/user/project/clusters/protect/web_application_firewall/index.md
new file mode 100644
index 00000000000..6e2e71c6ced
--- /dev/null
+++ b/doc/user/project/clusters/protect/web_application_firewall/index.md
@@ -0,0 +1,103 @@
+---
+stage: Protect
+group: Container Security
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Web Application Firewall
+
+WARNING:
+The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276)
+in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349)
+in GitLab 14.0.
+
+A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to
+and from a web application. By inspecting HTTP traffic, it can prevent attacks
+stemming from web application security flaws. It can be used to detect SQL injection,
+Cross-Site Scripting (XSS), Remote File Inclusion, Security Misconfigurations, and
+much more.
+
+## Overview
+
+GitLab provides a WAF out of the box after Ingress is deployed. All you need to do is deploy your
+application along with a service and Ingress resource. In the GitLab [Ingress](../../../../clusters/applications.md#ingress)
+deployment, the [ModSecurity](https://modsecurity.org/)
+module is loaded into Ingress-NGINX by default and monitors the traffic to the applications
+which have an Ingress. The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/)
+by default. The OWASP CRS detects and logs a wide range of common attacks.
+
+By default, the WAF is deployed in Detection-only mode and only logs attack attempts.
+
+## Requirements
+
+The Web Application Firewall requires:
+
+- **Kubernetes**
+
+ To enable the WAF, you need:
+
+ - Kubernetes 1.12+.
+ - A load balancer. You can use NGINX-Ingress by deploying it to your
+ Kubernetes cluster by either:
+ - Using the [`nginx-ingress` Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress).
+ - Installing the [Ingress GitLab Managed App](../../../../clusters/applications.md#ingress) with WAF enabled.
+
+- **Configured Kubernetes objects**
+
+ To use the WAF on an application, you need to deploy the following Kubernetes resources:
+
+ - [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
+ - [Service](https://kubernetes.io/docs/concepts/services-networking/service/)
+ - [Ingress Resource](https://kubernetes.io/docs/concepts/services-networking/ingress/)
+
+## Quick start
+
+If you are using GitLab.com, see the [quick start guide](quick_start_guide.md) for
+how to use the WAF with GitLab.com and a Kubernetes cluster on Google Kubernetes Engine (GKE).
+
+If you are using a self-managed instance of GitLab, you must configure the
+[Google OAuth2 OmniAuth Provider](../../../../../integration/google.md) before
+you can configure a cluster on GKE. Once this is set up, you can follow the steps on the
+[quick start guide](quick_start_guide.md)
+to get started.
+
+NOTE:
+This guide shows how the WAF can be deployed using Auto DevOps. The WAF
+is available by default to all applications no matter how they are deployed,
+as long as they are using Ingress.
+
+## Network firewall vs. Web Application Firewall
+
+A network firewall or packet filter looks at traffic at the Network (L3) and Transport (L4) layers
+of the [OSI Model](https://en.wikipedia.org/wiki/OSI_model), and denies packets from entry based on
+a set of rules regarding the network in general.
+
+A Web Application Firewall operates at the Application (L7) layer of the OSI Model and can
+examine all the packets traveling to and from a specific application. A WAF can set
+more advanced rules around threat detection.
+
+## Features
+
+ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://github.com/coreruleset/coreruleset/) by
+default. The OWASP CRS logs attempts to the following attacks:
+
+- [SQL Injection](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_SQL_Injection)
+- [Cross-Site Scripting](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Cross-Site_Scripting_(XSS))
+- [Local File Inclusion](https://wiki.owasp.org/index.php/Testing_for_Local_File_Inclusion)
+- [Remote File Inclusion](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Remote_File_Inclusion)
+- [Code Injection](https://wiki.owasp.org/index.php/Code_Injection)
+- [Session Fixation](https://wiki.owasp.org/index.php/Session_fixation)
+- [Scanner Detection](https://wiki.owasp.org/index.php/Category:Vulnerability_Scanning_Tools)
+- [Metadata/Error Leakages](https://wiki.owasp.org/index.php/Improper_Error_Handling)
+
+It is good to have a basic knowledge of the following:
+
+- [Kubernetes](https://kubernetes.io/docs/home/)
+- [Ingress](https://kubernetes.github.io/ingress-nginx/)
+- [ModSecurity](https://www.modsecurity.org/)
+- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
+
+## Roadmap
+
+You can find more information on the product direction of the WAF in
+[Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/).
diff --git a/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
new file mode 100644
index 00000000000..e9a05b58fec
--- /dev/null
+++ b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
@@ -0,0 +1,265 @@
+---
+stage: Protect
+group: Container Security
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Getting started with the Web Application Firewall
+
+WARNING:
+The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276)
+in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349)
+in GitLab 14.0.
+
+This is a step-by-step guide to help you use the GitLab [Web Application Firewall](index.md) after
+deploying a project hosted on GitLab.com to Google Kubernetes Engine using [Auto DevOps](../../../../../topics/autodevops/index.md).
+
+The GitLab native Kubernetes integration is used, so you do not need
+to create a Kubernetes cluster manually using the Google Cloud Platform console.
+A simple application is created and deployed based on a GitLab template.
+
+These instructions also work for a self-managed GitLab instance. However, you
+need to ensure your own [runners are configured](../../../../../ci/runners/README.md) and
+[Google OAuth is enabled](../../../../../integration/google.md).
+
+The GitLab Web Application Firewall is deployed with [Ingress](../../../../clusters/applications.md#ingress),
+so it is available to your applications no matter how you deploy them to Kubernetes.
+
+## Configuring your Google account
+
+Before creating and connecting your Kubernetes cluster to your GitLab project,
+you need a Google Cloud Platform account. If you do not already have one,
+sign up at <https://console.cloud.google.com>. You need to either sign in with an existing
+Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one.
+
+1. To enable the required APIs and related services, follow the steps in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin).
+1. Make sure you have created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account).
+
+NOTE:
+Every new Google Cloud Platform (GCP) account receives [$300 in credit](https://console.cloud.google.com/freetrial),
+and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with the GitLab
+Google Kubernetes Engine integration. All you have to do is [follow this link](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) and apply for credit.
+
+## Creating a new project from a template
+
+We use a GitLab project templates to get started. As the name suggests,
+those projects provide a barebones application built on some well-known frameworks.
+
+1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select
+ **New project**.
+1. Go to the **Create from template** tab where you can choose for example a Ruby on
+ Rails, Spring, or NodeJS Express project.
+ Use the Ruby on Rails template.
+
+ ![Select project template](../../../../../topics/autodevops/img/guide_project_template_v12_3.png)
+
+1. Give your project a name, optionally a description, and make it public so that
+ you can take advantage of the features available in the
+ [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com).
+
+ ![Create project](../../../../../topics/autodevops/img/guide_create_project_v12_3.png)
+
+1. Click **Create project**.
+
+Now that the project is created, the next step is to create the Kubernetes cluster
+to deploy this application under.
+
+## Creating a Kubernetes cluster from within GitLab
+
+1. On the project's landing page, click **Add Kubernetes cluster**
+ (note that this option is also available when you navigate to **Operations > Kubernetes**).
+
+ ![Project landing page](../../../../../topics/autodevops/img/guide_project_landing_page_v12_10.png)
+
+1. On the **Create new cluster on GKE** tab, click **Sign in with Google**.
+
+ ![Google sign in](../../../../../topics/autodevops/img/guide_google_signin_v12_3.png)
+
+1. Connect with your Google account and click **Allow** when asked (this
+ appears only the first time you connect GitLab with your Google account).
+
+ ![Google auth](../../../../../topics/autodevops/img/guide_google_auth_v12_3.png)
+
+1. The last step is to provide the cluster details.
+ 1. Give it a name, leave the environment scope as is, and choose the GCP project under which to create the cluster.
+ (Per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you.)
+ 1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) to create the cluster in.
+ 1. Enter the number of nodes you want it to have.
+ 1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types).
+
+ ![GitLab GKE cluster details](../../../../../topics/autodevops/img/guide_gitlab_gke_details_v12_3.png)
+
+1. Click **Create Kubernetes cluster**.
+
+After a couple of minutes, the cluster is created. You can also see its
+status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
+
+The next step is to install some applications on your cluster that are needed
+to take full advantage of Auto DevOps.
+
+## Install Ingress
+
+The GitLab Kubernetes integration comes with some
+[pre-defined applications](../../index.md#installing-applications)
+for you to install.
+
+![Cluster applications](../../../../../topics/autodevops/img/guide_cluster_apps_v12_3.png)
+
+For this guide, we need to install Ingress. Ingress provides load balancing,
+SSL termination, and name-based virtual hosting, using NGINX behind
+the scenes. Make sure to switch the toggle to the enabled position before installing.
+
+Both logging and blocking modes are available for WAF. While logging mode is useful for
+auditing anomalous traffic, blocking mode ensures the traffic doesn't reach past Ingress.
+
+![Cluster applications](img/guide_waf_ingress_installation_v12_10.png)
+
+After Ingress is installed, wait a few seconds and copy the IP address that
+is displayed in order to add in your base **Domain** at the top of the page. For
+the purpose of this guide, we use the one suggested by GitLab. Once you have
+filled in the domain, click **Save changes**.
+
+![Cluster Base Domain](../../../../../topics/autodevops/img/guide_base_domain_v12_3.png)
+
+Prometheus should also be installed. It is an open-source monitoring and
+alerting system that is used to supervise the deployed application.
+Installing GitLab Runner is not required as we use the shared runners that
+GitLab.com provides.
+
+## Enabling Auto DevOps (optional)
+
+Starting with GitLab 11.3, Auto DevOps is enabled by default. However, it is possible to disable
+Auto DevOps at both the instance-level (for self-managed instances) and the group-level.
+Follow these steps if Auto DevOps has been manually disabled:
+
+1. Navigate to **Settings > CI/CD > Auto DevOps**.
+1. Select **Default to Auto DevOps pipeline**.
+1. Select the [continuous deployment strategy](../../../../../topics/autodevops/index.md#deployment-strategy)
+ which automatically deploys the application to production once the pipeline
+ successfully runs on the `master` branch.
+1. Click **Save changes**.
+
+ ![Auto DevOps settings](../../../../../topics/autodevops/img/guide_enable_autodevops_v12_3.png)
+
+Once you complete all the above and save your changes, a new pipeline is
+automatically created. To view the pipeline, go to **CI/CD > Pipelines**.
+
+![First pipeline](../../../../../topics/autodevops/img/guide_first_pipeline_v12_3.png)
+
+The next section explains what each pipeline job does.
+
+## Deploying the application
+
+By now you should see the pipeline running, but what is it running exactly?
+
+To navigate inside the pipeline, click its status badge (its status should be "Running").
+The pipeline is split into a few stages, each running a couple of jobs.
+
+![Pipeline stages](../../../../../topics/autodevops/img/guide_pipeline_stages_v13_0.png)
+
+In the **build** stage, the application is built into a Docker image and then
+uploaded to your project's [Container Registry](../../../../packages/container_registry/index.md)
+([Auto Build](../../../../../topics/autodevops/stages.md#auto-build)).
+
+In the **test** stage, GitLab runs various checks on the application.
+
+The **production** stage is run after the tests and checks finish, and it automatically
+deploys the application in Kubernetes ([Auto Deploy](../../../../../topics/autodevops/stages.md#auto-deploy)).
+
+The **production** stage creates Kubernetes objects
+like a Deployment, Service, and Ingress resource. The
+application is monitored by the WAF automatically.
+
+## Validating Ingress is running ModSecurity
+
+Now we can make sure that Ingress is running properly with ModSecurity and send
+a request to ensure our application is responding correctly. You must connect to
+your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install).
+
+1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled.
+
+ This is done by running the following commands:
+
+ ```shell
+ $ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller'
+ ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running
+
+ $ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;'
+ modsecurity on;
+ ```
+
+1. Verify the Rails application has been installed properly.
+
+ ```shell
+ $ kubectl get ns
+ auto-devv-2-16730183-production Active
+
+ $ kubectl get pods -n auto-devv-2-16730183-production
+ NAME READY STATUS RESTARTS
+ production-5778cfcfcd-nqjcm 1/1 Running 0
+ production-postgres-6449f8cc98-r7xgg 1/1 Running 0
+ ```
+
+1. To make sure the Rails application is responding, send a request to it by running:
+
+ ```shell
+ $ kubectl get ing -n auto-devv-2-16730183-production
+ NAME HOSTS PORTS
+ production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443
+
+ $ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" | grep 'Rails!' --after 2 --before 2
+ <body>
+ <p>You're on Rails!</p>
+ </body>
+ ```
+
+Now that we have confirmed our system is properly setup, we can go ahead and test
+the WAF with OWASP CRS!
+
+## Testing out the OWASP Core Rule Set
+
+Now let's send a potentially malicious request, as if we were a scanner,
+checking for vulnerabilities within our application and examine the ModSecurity logs:
+
+```shell
+$ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" --header "User-Agent: absinthe" | grep 'Rails!' --after 2 --before 2
+<body>
+ <p>You're on Rails!</p>
+</body>
+
+$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /var/log/modsec/audit.log | grep 'absinthe'
+{
+ "message": "Found User-Agent associated with security scanner",
+ "details": {
+ "match": "Matched \"Operator `PmFromFile' with parameter `scanners-user-agents.data' against variable `REQUEST_HEADERS:user-agent' (Value: `absinthe' )",
+ "reference": "o0,8v84,8t:lowercase",
+ "ruleId": "913100",
+ "file": "/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf",
+ "lineNumber": "33",
+ "data": "Matched Data: absinthe found within REQUEST_HEADERS:user-agent: absinthe",
+ "severity": "2",
+ "ver": "OWASP_CRS/3.2.0",
+ "rev": "",
+ "tags": ["application-multi", "language-multi", "platform-multi", "attack-reputation-scanner", "OWASP_CRS", "OWASP_CRS/AUTOMATION/SECURITY_SCANNER", "WASCTC/WASC-21", "OWASP_TOP_10/A7", "PCI/6.5.10"],
+ "maturity": "0",
+ "accuracy": "0"
+ }
+}
+```
+
+You can see that ModSecurity logs the suspicious behavior. By sending a request
+with the `User Agent: absinthe` header, which [absinthe](https://github.com/cameronhotchkies/Absinthe),
+a tool for testing for SQL injections uses, we can detect that someone was
+searching for vulnerabilities on our system. Detecting scanners is useful, because we
+can learn if someone is trying to exploit our system.
+
+## Conclusion
+
+You can now see the benefits of a using a Web Application Firewall.
+ModSecurity and the OWASP Core Rule Set, offer many more benefits.
+You can explore them in more detail:
+
+- [Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/)
+- [ModSecurity](https://www.modsecurity.org/)
+- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
+- [AutoDevOps](../../../../../topics/autodevops/index.md)
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index 332c1f35d89..8572ab850e4 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -103,7 +103,7 @@ the components outlined above and the pre-loaded demo runbook.
Enter these values, maintaining the single quotes as follows:
```sql
- PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo'
+ PRIVATE_TOKEN = '<your_access_token>'
PROJECT_ID = '1234567'
```
diff --git a/doc/user/project/clusters/securing.md b/doc/user/project/clusters/securing.md
index fa80bd6423b..d734db6bac9 100644
--- a/doc/user/project/clusters/securing.md
+++ b/doc/user/project/clusters/securing.md
@@ -1,155 +1,8 @@
---
-stage: Protect
-group: Container Security
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'protect/index.md'
---
-# Securing your deployed applications
+This document was moved to [another location](protect/index.md).
-GitLab makes it easy to secure applications deployed in [connected Kubernetes clusters](index.md).
-You can benefit from the protection of a [Web Application Firewall](../../../topics/web_application_firewall/quick_start_guide.md),
-[Network Policies](../../../topics/autodevops/stages.md#network-policy),
-and [Container Host Security](../../clusters/applications.md#install-falco-using-gitlab-cicd).
-
-This page contains full end-to-end steps and instructions to connect your cluster to GitLab and
-install these features, whether or not your applications are deployed through GitLab CI/CD. If you
-use [Auto DevOps](../../../topics/autodevops/index.md)
-to build and deploy your application with GitLab, see the documentation for the respective
-[GitLab Managed Applications](../../clusters/applications.md)
-above.
-
-## Overview
-
-At a high level, the required steps include the following:
-
-- Connect the cluster to GitLab.
-- Set up one or more runners.
-- Set up a cluster management project.
-- Install a Web Application Firewall, and/or Network Policies, and/or Container Host
- Security.
-- Install Prometheus to get statistics and metrics in the
- [threat monitoring](../../application_security/threat_monitoring/)
- dashboard.
-
-### Requirements
-
-Minimum requirements (depending on the GitLab Manage Application you want to install):
-
-- Your cluster is connected to GitLab (ModSecurity, Cilium, and Falco).
-- At least one runner is installed (Cilium and Falco only).
-
-### Understanding how GitLab Managed Apps are installed
-
-NOTE:
-These diagrams use the term _Kubernetes_ for simplicity. In practice, Sidekiq connects to a Helm
-command runner pod in the cluster.
-
-You install GitLab Managed Apps from the GitLab web interface with a one-click setup process. GitLab
-uses Sidekiq (a background processing service) to facilitate this.
-
-```mermaid
- sequenceDiagram
- autonumber
- GitLab->>+Sidekiq: Install a GitLab Managed App
- Sidekiq->>+Kubernetes: Helm install
- Kubernetes-->>-Sidekiq: Installation complete
- Sidekiq-->>-GitLab: Refresh UI
-```
-
-Although this installation method is easier because it's a point-and-click action in the user
-interface, it's inflexible and harder to debug. If something goes wrong, you can't see the
-deployment logs. The Web Application Firewall feature uses this installation method.
-
-However, the next generation of GitLab Managed Apps V2 ([CI/CD-based GitLab Managed Apps](https://gitlab.com/groups/gitlab-org/-/epics/2103))
-don't use Sidekiq to deploy. All the applications are deployed using a GitLab CI/CD pipeline and
-therefore, by runners.
-
-```mermaid
-sequenceDiagram
- autonumber
- GitLab->>+GitLab: Trigger pipeline
- GitLab->>+Runner: Run deployment job
- Runner->>+Kubernetes: Helm install
- Kubernetes-->>-Runner: Installation is complete
- Runner-->>-GitLab: Report job status and update pipeline
-```
-
-Debugging is easier because you have access to the raw logs of these jobs (the Helm Tiller output is
-available as an artifact in case of failure), and the flexibility is much better. Since these
-deployments are only triggered when a pipeline is running (most likely when there's a new commit in
-the cluster management repository), every action has a paper trail and follows the classic merge
-request workflow (approvals, merge, deploy). The Network Policy (Cilium) Managed App, and Container
-Host Security (Falco) are deployed with this model.
-
-## Connect the cluster to GitLab
-
-To deploy GitLab Managed Apps to your cluster, you must first
-[add your cluster](add_remove_clusters.md)
-to GitLab. Then [install](../../clusters/applications.md#install-with-one-click)
-the Web Application Firewall from the project or group Kubernetes page.
-
-Note that your project doesn't have to be hosted or deployed through GitLab. You can manage a
-cluster independent of the applications that use the cluster.
-
-## Set up a runner
-
-To install CI/CD-based GitLab Managed Apps, a pipeline using a runner must be running in
-GitLab. You can [install a runner](../../clusters/applications.md#gitlab-runner)
-in the Kubernetes cluster added in the previous step, or use one of the shared runners provided by
-GitLab if you're using GitLab.com.
-
-With your cluster connected to GitLab and a runner in place, you can proceed to the next
-steps and start installing the Cilium and Falco GitLab Managed Apps to secure your applications
-hosted on this cluster.
-
-## Create a Cluster Management Project
-
-A [Cluster Management Project](../../clusters/management_project.md)
-is a GitLab project that contains a `.gitlab-ci.yml` file to deploy GitLab Managed Apps to your
-cluster. This project runs the required charts with the Kubernetes
-[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
-privileges.
-
-The creation of this project starts like any other GitLab project. Use an empty
-project and add a `gitlab-ci.yml` file at the root, containing this template:
-
-```yaml
-include:
- - template: Managed-Cluster-Applications.gitlab-ci.yml
-```
-
-To make this project a Cluster Management Project, follow these
-[instructions](../../clusters/management_project.md#selecting-a-cluster-management-project).
-This project can be designated as such even if your application isn't hosted on GitLab. In this
-case, create a new empty project where you can select your newly created Cluster Management Project.
-
-## Install GitLab Container Network Policy
-
-GitLab Container Network Policy is based on [Cilium](https://cilium.io/). To
-install the Cilium GitLab Managed App, add a
-`.gitlab/managed-apps/config.yaml` file to your Cluster Management project:
-
-```yaml
-# possible values are gke, eks or you can leave it blank
-clusterType: gke
-
-cilium:
- installed: true
-```
-
-Your application doesn't have to be managed or deployed by GitLab to leverage this feature.
-[Read more](../../clusters/applications.md#install-cilium-using-gitlab-cicd)
-about configuring Container Network Policy.
-
-## Install GitLab Container Host Security
-
-Similarly, you can install Container Host Security, based on
-[Falco](https://falco.org/), in your `.gitlab/managed-apps/config.yaml`:
-
-```yaml
-falco:
- installed: true
-```
-
-[Read more](../../clusters/applications.md#install-falco-using-gitlab-cicd)
-about configuring Container Host Security.
+<!-- This redirect file can be deleted after <2021-04-01>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index fcbf85121b2..043c5e4ca79 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -560,7 +560,6 @@ Or:
By default, a GitLab serverless deployment is served over `http`. To serve
over `https`, you must manually obtain and install TLS certificates.
-12345678901234567890123456789012345678901234567890123456789012345678901234567890
The simplest way to accomplish this is to use Certbot to
[manually obtain Let's Encrypt certificates](https://knative.dev/docs/serving/using-a-tls-cert/#using-certbot-to-manually-obtain-let-s-encrypt-certificates).
Certbot is a free, open source software tool for automatically using Let’s Encrypt
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index d0e89400d88..63ea84e42c9 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -225,6 +225,52 @@ the rules for "Groups" and "Documentation" sections:
![MR widget - Sectional Code Owners](img/sectional_code_owners_v13.2.png)
+#### 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.
+
+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:
+
+```plaintext
+[Documentation]
+*.md @root
+
+[Ruby]
+*.rb @root
+
+^[Go]
+*.go @root
+```
+
+The optional code owners section will be displayed 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.
+
+For example, the code owners of the "Documentation" section below will still be required to approve merge requests:
+
+```plaintext
+[Documentation]
+*.md @root
+
+[Ruby]
+*.rb @root
+
+^[Go]
+*.go @root
+
+^[Documentation]
+*.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
+[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.
+
## Example `CODEOWNERS` file
```plaintext
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 33bec99767a..831a8803622 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -5,9 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto, reference
---
-# Deploy Boards **(PREMIUM)**
+# Deploy Boards **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
+> - [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.
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
@@ -53,8 +54,8 @@ specific environment, there are a lot of use cases. To name a few:
- You want to promote what's running in staging, to production. You go to the
environments list, verify that what's running in staging is what you think is
running, then click on the [manual action](../../ci/yaml/README.md#whenmanual) to deploy to production.
-- You trigger a deploy, and you've got lots of containers to upgrade so you know
- it'll take a while (you've also throttled your deploy to only take down X
+- You trigger a deploy, and you have many containers to upgrade so you know
+ this takes a while (you've also throttled your deploy to only take down X
containers at a time). But you need to tell someone when it's deployed, so you
go to the environments list, look at the production environment to see what
the progress is in real-time as each pod is rolled.
@@ -75,8 +76,8 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
1. Have a Kubernetes cluster up and running.
NOTE:
- If you are using OpenShift, ensure that you're using the `Deployment` resource
- instead of `DeploymentConfiguration`. Otherwise, the Deploy Boards won't render
+ If you're using OpenShift, ensure that you're using the `Deployment` resource
+ instead of `DeploymentConfiguration`. Otherwise, the Deploy Boards don't render
correctly. For more information, read the
[OpenShift docs](https://docs.openshift.com/container-platform/3.7/dev_guide/deployments/kubernetes_deployments.html#kubernetes-deployments-vs-deployment-configurations)
and [GitLab issue #4584](https://gitlab.com/gitlab-org/gitlab/-/issues/4584).
@@ -84,7 +85,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
1. [Configure GitLab Runner](../../ci/runners/README.md) with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html) or
[`kubernetes`](https://docs.gitlab.com/runner/executors/kubernetes.html) executor.
1. Configure the [Kubernetes integration](clusters/index.md) in your project for the
- cluster. The Kubernetes namespace is of particular note as you will need it
+ cluster. The Kubernetes namespace is of particular note as you need it
for your deployment scripts (exposed by the `KUBE_NAMESPACE` environment variable).
1. Ensure Kubernetes annotations of `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG`
and `app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` are applied to the
@@ -94,7 +95,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
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`
template which has predefined stages and commands to use, and automatically
- applies the annotations. Each project will need to have a unique namespace in
+ applies the annotations. Each project must have a unique namespace in
Kubernetes as well. The image below demonstrates how this is shown inside
Kubernetes.
@@ -105,7 +106,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
re-deploy your application. If you are using Auto DevOps, this will
be done automatically and no action is necessary.
- If you are using GCP to manage clusters, you can see the deployment details in GCP itself by going to **Workloads > deployment name > Details**:
+ If you use GCP to manage clusters, you can see the deployment details in GCP itself by navigating to **Workloads > deployment name > Details**:
![Deploy Boards Kubernetes Label](img/deploy_boards_kubernetes_label.png)
@@ -141,7 +142,7 @@ spec:
app.gitlab.com/env: ${CI_ENVIRONMENT_SLUG}
```
-The annotations will be applied to the deployments, replica sets, and pods. By changing the number of replicas, like `kubectl scale --replicas=3 deploy APPLICATION_NAME -n ${KUBE_NAMESPACE}`, you can follow the instances' pods from the board.
+The annotations are applied to the deployments, replica sets, and pods. By changing the number of replicas, like `kubectl scale --replicas=3 deploy APPLICATION_NAME -n ${KUBE_NAMESPACE}`, you can follow the instances' pods from the board.
NOTE:
The YAML file is static. If you apply it using `kubectl apply`, you must
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index 39b790544c1..93ed1030e1f 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -92,7 +92,7 @@ There are three lists of Project Deploy Keys:
![Deploy Keys section](img/deploy_keys_v13_0.png)
-After you add a key, it will be enabled for this project by default, and it'll appear
+After you add a key, it's enabled for this project by default and it appears
in the **Enabled deploy keys** tab.
In the **Privately accessible deploy keys** tab, you can enable a private key which
@@ -111,7 +111,7 @@ and `read-write` access.
NOTE:
If you have enabled a privately or publicly accessible or deploy key for your
project, and if you then update the access level for this key from `read-only` to
-`read-write`, the change will be only for the **current project**.
+`read-write`, the change is only for the **current project**.
### Public deploy keys
@@ -131,7 +131,7 @@ Instance administrators can add public deploy keys:
![Public Deploy Keys section](img/public_deploy_key_v13_0.png)
-After adding a key, it will be available to any shared systems. Project maintainers
+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.
NOTE:
@@ -155,8 +155,8 @@ until a project maintainer chooses to make use of it.
### Deploy Key cannot push to a protected branch
-If the owner of this deploy key does not have access to a [protected
-branch](../protected_branches.md), then this deploy key won't have access to
+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
the branch either. In addition to this, choosing the **No one** value in
[the "Allowed to push" section](../protected_branches.md#configuring-protected-branches)
means that no users **and** no services using deploy keys can push to that selected branch.
diff --git a/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png b/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png
index 83f59b8f6f0..4ab6a45aee1 100644
--- a/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png
+++ b/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png
Binary files differ
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index ac19c44c58a..5a62730d989 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -36,7 +36,7 @@ project. Alternatively, you can also create [group-scoped deploy tokens](#group-
1. Choose the [desired scopes](#limiting-scopes-of-a-deploy-token).
1. Select **Create deploy token**.
1. Save the deploy token somewhere safe. After you leave or refresh
- the page, **you won't be able to access it again**.
+ the page, **you can't access it again**.
![Personal access tokens page](img/deploy_tokens_ui.png)
@@ -89,7 +89,7 @@ Replace `<username>` and `<deploy_token>` with the proper values.
### Read Container Registry images
-To read the container registry images, you'll need to:
+To read the container registry images, you must:
1. Create a Deploy Token with `read_registry` as a scope.
1. Take note of your `username` and `token`.
@@ -106,7 +106,7 @@ pull images from your Container Registry.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) in GitLab 12.10.
-To push the container registry images, you'll need to:
+To push the container registry images, you must:
1. Create a Deploy Token with `write_registry` as a scope.
1. Take note of your `username` and `token`.
@@ -123,7 +123,7 @@ push images to your Container Registry.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
-To pull packages in the GitLab package registry, you'll need to:
+To pull packages in the GitLab package registry, you must:
1. Create a Deploy Token with `read_package_registry` as a scope.
1. Take note of your `username` and `token`.
@@ -134,7 +134,7 @@ To pull packages in the GitLab package registry, you'll need to:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
-To upload packages in the GitLab package registry, you'll need to:
+To upload packages in the GitLab package registry, you must:
1. Create a Deploy Token with `write_package_registry` as a scope.
1. Take note of your `username` and `token`.
@@ -160,7 +160,7 @@ To use a group deploy token:
1. Use it the same way you use a project deploy token when
[cloning a repository](#git-clone-a-repository).
-The scopes applied to a group deploy token (such as `read_repository`) will
+The scopes applied to a group deploy token (such as `read_repository`)
apply consistently when cloning the repository of related projects.
### GitLab Deploy Token
@@ -168,7 +168,7 @@ apply consistently when cloning the repository of related projects.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18414) in GitLab 10.8.
There's a special case when it comes to Deploy Tokens. If a user creates one
-named `gitlab-deploy-token`, the username and token of the Deploy Token will be
+named `gitlab-deploy-token`, the username and token of the Deploy Token is
automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER`
and `CI_DEPLOY_PASSWORD`, respectively.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index db2631f9596..3108bdda7a0 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -108,7 +108,7 @@ you should be fine.
![Default issue description templates](img/description_templates_issue_settings.png)
After you add the description, hit **Save changes** for the settings to take
-effect. Now, every time a new merge request or issue is created, it is
+effect. Now, every time a new merge request or issue is created, it is
pre-filled with the text you entered in the template(s).
## Description template example
diff --git a/doc/user/project/img/canary_weight.png b/doc/user/project/img/canary_weight.png
index e6544358c15..fe17c62bdea 100644
--- a/doc/user/project/img/canary_weight.png
+++ b/doc/user/project/img/canary_weight.png
Binary files differ
diff --git a/doc/user/project/img/description_templates_issue_settings.png b/doc/user/project/img/description_templates_issue_settings.png
index 657b6ae1269..7f354f7c288 100644
--- a/doc/user/project/img/description_templates_issue_settings.png
+++ b/doc/user/project/img/description_templates_issue_settings.png
Binary files differ
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
new file mode 100644
index 00000000000..7a5a2fab6e3
--- /dev/null
+++ b/doc/user/project/img/optional_code_owners_sections_v13_8.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_deploy_keys_v13_5.png b/doc/user/project/img/protected_branches_deploy_keys_v13_5.png
index 6eda7a671b2..ccd23dbe160 100644
--- a/doc/user/project/img/protected_branches_deploy_keys_v13_5.png
+++ b/doc/user/project/img/protected_branches_deploy_keys_v13_5.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_custom_email_address_v13_0.png b/doc/user/project/img/service_desk_custom_email_address_v13_0.png
deleted file mode 100644
index 3789e039904..00000000000
--- a/doc/user/project/img/service_desk_custom_email_address_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/service_desk_enabled.png b/doc/user/project/img/service_desk_enabled.png
deleted file mode 100644
index 33d51227e5f..00000000000
--- a/doc/user/project/img/service_desk_enabled.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 8b6d86b14c9..c135b1be54a 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -63,7 +63,7 @@ must meet one of the following conditions prior to the import:
- Have previously logged in to a GitLab account using the GitHub icon.
- Have a GitHub account with a publicly visible
[primary email address](https://docs.github.com/en/free-pro-team@latest/rest/reference/users#get-a-user)
- on their profile that matches their GitLab account's email address.
+ on their profile that matches their GitLab account's primary or secondary email address.
If a user referenced in the project is not found in the GitLab database, the project creator (typically the user
that initiated the import process) is set as the author/assignee, but a note on the issue mentioning the original
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
index 8344baebd82..ccf4b6cb303 100644
--- a/doc/user/project/integrations/gitlab_slack_application.md
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -37,7 +37,7 @@ integration settings.
Keep in mind that you need to have the appropriate permissions for your Slack
team in order to be able to install a new application, read more in Slack's
-docs on [Adding an app to your workspace](https://slack.com/help/articles/202035138-Add-an-app-to-your-workspace).
+docs on [Adding an app to your workspace](https://slack.com/help/articles/202035138-Add-apps-to-your-Slack-workspace).
To enable the GitLab service for your Slack team:
diff --git a/doc/user/project/integrations/img/webhooks_ssl.png b/doc/user/project/integrations/img/webhooks_ssl.png
deleted file mode 100644
index e5777a2e99b..00000000000
--- a/doc/user/project/integrations/img/webhooks_ssl.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/jira_integrations.md b/doc/user/project/integrations/jira_integrations.md
index f15a5ee4429..3c91fd3549f 100644
--- a/doc/user/project/integrations/jira_integrations.md
+++ b/doc/user/project/integrations/jira_integrations.md
@@ -30,6 +30,6 @@ The following Jira integrations allow different types of cross-referencing betwe
| 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. |
| Mention of Jira issue ID in GitLab branch names is reflected in Jira issue | No | Yes, in the issue’s Development panel |
-| Record Jira time tracking info against an issue | No | Yes. Time can be specified via Jira Smart Commits. |
+| 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 |
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 9d7960790ff..959c4cc623b 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -199,7 +199,6 @@ to integrate with.
### Precedence with multiple Prometheus configurations
-12345678901234567890123456789012345678901234567890123456789012345678901234567890
Although you can enable both a [manual configuration](#manual-configuration-of-prometheus)
and [auto configuration](#managed-prometheus-on-kubernetes) of Prometheus, you
can use only one:
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index d8b51e8b777..47a44e53b47 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Webhooks
-Project webhooks allow you to trigger a URL if for example new code is pushed or
+Project webhooks allow you to trigger a percent-encoded 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. GitLab sends a POST request with data
to the webhook URL.
@@ -28,32 +28,15 @@ notify bug tracking systems.
Webhooks can be used to update an external issue tracker, trigger CI jobs,
update a backup mirror, or even deploy to your production server.
-They are available **per project** for GitLab Community Edition,
-and **per project and per group** for **GitLab Enterprise Edition**.
-Navigate to the webhooks page at your project's **Settings > Webhooks**.
+Webhooks are available:
+
+- Per project, at a project's **Settings > Webhooks** menu. **(CORE)**
+- Additionally per group, at a group's **Settings > Webhooks** menu. **(PREMIUM)**
NOTE:
On GitLab.com, the [maximum number of webhooks and their size](../../../user/gitlab_com/index.md#webhooks) per project, and per group, is limited.
-## Version history
-
-Starting from GitLab 8.5:
-
-- the `repository` key is deprecated in favor of the `project` key
-- the `project.ssh_url` key is deprecated in favor of the `project.git_ssh_url` key
-- the `project.http_url` key is deprecated in favor of the `project.git_http_url` key
-
-Starting from GitLab 11.1, the logs of webhooks are automatically removed after
-one month.
-
-Starting from GitLab 11.2:
-
-- The `description` field for issues, merge requests, comments, and wiki pages
- is rewritten so that simple Markdown image references (like
- `![](/uploads/...)`) have their target URL changed to an absolute URL. See
- [image URL rewriting](#image-url-rewriting) for more details.
-
## Possible uses for webhooks
- You can set up a webhook in GitLab to send a notification to
@@ -91,8 +74,6 @@ be self-signed.
You can turn this off in the webhook settings in your GitLab projects.
-![SSL Verification](img/webhooks_ssl.png)
-
## Branch filtering
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) in GitLab 11.3.
@@ -115,6 +96,10 @@ attribute only contains the first 20 for performance reasons. Loading
detailed commit data is expensive. Note that despite only 20 commits being
present in the `commits` attribute, the `total_commits_count` attribute contains the actual total.
+NOTE:
+If a branch creation push event is generated without new commits being introduced, the
+`commits` attribute in the payload is empty.
+
Also, if a single push includes changes for more than three (by default, depending on
[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls))
branches, this hook isn't executed.
@@ -276,6 +261,7 @@ X-Gitlab-Event: Issue Hook
"object_kind": "issue",
"event_type": "issue",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
@@ -439,9 +425,11 @@ X-Gitlab-Event: Note Hook
{
"object_kind": "note",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
+ "email": "admin@example.com"
},
"project_id": 5,
"project":{
@@ -519,9 +507,11 @@ X-Gitlab-Event: Note Hook
{
"object_kind": "note",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
+ "email": "admin@example.com"
},
"project_id": 5,
"project":{
@@ -646,9 +636,11 @@ X-Gitlab-Event: Note Hook
{
"object_kind": "note",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
+ "email": "admin@example.com"
},
"project_id": 5,
"project":{
@@ -752,9 +744,11 @@ X-Gitlab-Event: Note Hook
{
"object_kind": "note",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
+ "email": "admin@example.com"
},
"project_id": 5,
"project":{
@@ -828,9 +822,11 @@ X-Gitlab-Event: Merge Request Hook
{
"object_kind": "merge_request",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
+ "email": "admin@example.com"
},
"project": {
"id": 1,
@@ -989,9 +985,11 @@ X-Gitlab-Event: Wiki Page Hook
{
"object_kind": "wiki_page",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"project": {
"id": 1,
@@ -1080,6 +1078,7 @@ X-Gitlab-Event: Pipeline Hook
"url": "http://192.168.64.1:3005/gitlab-org/gitlab-test/merge_requests/1"
},
"user":{
+ "id": 1,
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
@@ -1121,9 +1120,11 @@ X-Gitlab-Event: Pipeline Hook
"manual": true,
"allow_failure": false,
"user":{
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"runner": null,
"artifacts_file":{
@@ -1143,9 +1144,11 @@ X-Gitlab-Event: Pipeline Hook
"manual": false,
"allow_failure": false,
"user":{
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"runner": {
"id":380987,
@@ -1170,9 +1173,11 @@ X-Gitlab-Event: Pipeline Hook
"manual": false,
"allow_failure": false,
"user":{
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"runner": {
"id":380987,
@@ -1197,9 +1202,11 @@ X-Gitlab-Event: Pipeline Hook
"manual": false,
"allow_failure": false,
"user":{
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"runner": {
"id":380987,
@@ -1224,9 +1231,11 @@ X-Gitlab-Event: Pipeline Hook
"manual": false,
"allow_failure": false,
"user":{
+ "id": 1,
"name": "Administrator",
"username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"runner": null,
"artifacts_file":{
@@ -1273,7 +1282,8 @@ X-Gitlab-Event: Job Hook
"id": 3,
"name": "User",
"email": "user@gitlab.com",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
},
"commit": {
"id": 2366,
@@ -1349,6 +1359,7 @@ X-Gitlab-Event: Deployment Hook
},
"short_sha": "279484c0",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
@@ -1362,11 +1373,18 @@ X-Gitlab-Event: Deployment Hook
Note that `deployable_id` is the ID of the CI job.
-### Member events
+### Group member events **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260347) in GitLab 13.7.
-Triggered when a user is added as a group member.
+Member events are triggered when:
+
+- A user is added as a group member
+- The access level of a user has changed
+- The expiration date for user access has been updated
+- A user has been removed from the group
+
+#### Add member to group
**Request Header**:
@@ -1394,6 +1412,62 @@ X-Gitlab-Event: Member Hook
}
```
+#### Update member access level or expiration date
+
+**Request Header**:
+
+```plaintext
+X-Gitlab-Event: Member Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "created_at": "2020-12-11T04:57:22Z",
+ "updated_at": "2020-12-12T08:48:19Z",
+ "group_name": "webhook-test",
+ "group_path": "webhook-test",
+ "group_id": 100,
+ "user_username": "test_user",
+ "user_name": "Test User",
+ "user_email": "testuser@webhooktest.com",
+ "user_id": 64,
+ "group_access": "Developer",
+ "group_plan": null,
+ "expires_at": "2020-12-20T00:00:00Z",
+ "event_name": "user_update_for_group"
+}
+```
+
+#### Remove member from group
+
+**Request Header**:
+
+```plaintext
+X-Gitlab-Event: Member Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "created_at": "2020-12-11T04:57:22Z",
+ "updated_at": "2020-12-12T08:52:34Z",
+ "group_name": "webhook-test",
+ "group_path": "webhook-test",
+ "group_id": 100,
+ "user_username": "test_user",
+ "user_name": "Test User",
+ "user_email": "testuser@webhooktest.com",
+ "user_id": 64,
+ "group_access": "Guest",
+ "group_plan": null,
+ "expires_at": "2020-12-14T00:00:00Z",
+ "event_name": "user_remove_from_group"
+}
+```
+
### Feature Flag events
Triggered when a feature flag is turned on or off.
@@ -1428,6 +1502,7 @@ X-Gitlab-Event: Feature Flag Hook
"http_url":"http://example.com/gitlabhq/gitlab-test.git"
},
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
@@ -1554,7 +1629,7 @@ Markdown features, like link labels.
## Testing webhooks
You can trigger the webhook manually. Sample data from the project is used.
-> For example: for triggering `Push Events` your project should have at least one commit.
+For example, for triggering `Push Events` your project should have at least one commit.
![Webhook testing](img/webhook_testing.png)
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index e0f66013454..7119970fca0 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.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
---
-# Issue Boards
+# 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).
@@ -233,17 +233,18 @@ advanced functionality is present in [higher tiers only](https://about.gitlab.co
### Configurable issue boards **(STARTER)**
-> [Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
+> - [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.
-An issue board can be associated with a GitLab [Milestone](milestones/index.md#milestones),
-[Labels](labels.md), Assignee and Weight
+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),
which automatically filter the board issues accordingly.
This allows you to create unique boards according to your team's need.
![Create scoped board](img/issue_board_creation_v13_6.png)
You can define the scope of your board when creating it or by clicking the **Edit board** button.
-After a milestone, assignee or weight is assigned to an issue board, you can no longer
+After a milestone, iteration, assignee, or weight is assigned to an issue board, you can no longer
filter through these in the search bar. In order to do that, you need to remove the desired scope
(for example, milestone, assignee, or weight) from the issue board.
@@ -320,7 +321,8 @@ As in other list types, click the trash icon to remove a list.
### Group issues in swimlanes **(PREMIUM)**
-> Grouping by epic [introduced](https://gitlab.com/groups/gitlab-org/-/epics/3352) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+> - Grouping by epic [introduced](https://gitlab.com/groups/gitlab-org/-/epics/3352) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+> - Editing issue titles in the issue sidebar [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232745) in GitLab 13.8.
With swimlanes you can visualize issues grouped by epic.
Your issue board keeps all the other features, but with a different visual organization of issues.
@@ -336,6 +338,19 @@ To group issues by epic in an issue board:
![Epics Swimlanes](img/epics_swimlanes_v13.6.png)
+To edit an issue without leaving this view, select the issue card (not its title), and a sidebar
+appears on the right. There you can see and edit the issue's:
+
+- Title
+- Assignees
+- Epic **PREMIUM**
+- Milestone
+- Time tracking value (view only)
+- Due date
+- Labels
+- Weight
+- Notifications setting
+
You can also [drag issues](#drag-issues-between-lists) to change their position and epic assignment:
- To reorder an issue, drag it to the new position within a list.
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index 02cb0313a74..d4fbc4fb10b 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -29,8 +29,8 @@ confidential checkbox and hit **Save changes**.
There are two ways to change an issue's confidentiality.
-The first way is to edit the issue and mark/unmark the confidential checkbox.
-Once you save the issue, it will change the confidentiality of the issue.
+The first way is to edit the issue and toggle the confidentiality checkbox.
+After you save the issue, the confidentiality of the issue is updated.
The second way is to locate the Confidentiality section in the sidebar and click
**Edit**. A popup should appear and give you the option to turn on or turn off confidentiality.
@@ -46,20 +46,19 @@ system note in the issue's comments.
## Indications of a confidential issue
-NOTE:
-If you don't have [enough permissions](#permissions-and-access-to-confidential-issues),
-you won't be able to see the confidential issues at all.
-
There are a few things that visually separate a confidential issue from a
regular one. In the issues index page view, you can see the eye-slash icon
next to the issues that are marked as confidential.
![Confidential issues index page](img/confidential_issues_index_page.png)
+If you don't have [enough permissions](#permissions-and-access-to-confidential-issues),
+you cannot see confidential issues at all.
+
---
Likewise, while inside the issue, you can see the eye-slash icon right next to
-the issue number, but there is also an indicator in the comment area that the
+the issue number. There is also an indicator in the comment area that the
issue you are commenting on is confidential.
![Confidential issue page](img/confidential_issues_issue_page.png)
@@ -83,7 +82,7 @@ project's search results respectively.
| Maintainer access | Guest access |
| :-----------: | :----------: |
-| ![Confidential issues search master](img/confidential_issues_search_master.png) | ![Confidential issues search guest](img/confidential_issues_search_guest.png) |
+| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
## Merge Requests for Confidential Issues
@@ -93,24 +92,24 @@ To help prevent confidential information being leaked from a public project
in the process of resolving a confidential issue, confidential issues can be
resolved by creating a merge request from a private fork.
-The merge request created will target the default branch of the private fork,
+The created merge request targets the default branch of the private fork,
not the default branch of the public upstream project. This prevents the merge
request, branch, and commits entering the public repository, and revealing
-confidential information prematurely. When the confidential commits are ready
-to be made public, this can be done by opening a merge request from the private
-fork to the public upstream project.
+confidential information prematurely. To make a confidential commit public,
+open a merge request from the private fork to the public upstream project.
-NOTE:
-If you create a long-lived private fork in the same group or in a sub-group of
-the original upstream, all the users with Developer membership to the public
-project will also have the same permissions in the private project. This way,
-all the Developers, who have access to view confidential issues, will have a
-streamlined workflow for fixing them.
+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
+Permissions are inherited from parent groups. When private forks are created
+in the same group or sub-group 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.
### How it works
On a confidential issue, a **Create confidential merge request** button is
-available. Clicking on it will open a dropdown where you can choose to
+available. Clicking on it opens a dropdown where you can choose to
**Create confidential merge request and branch** or **Create branch**:
| Create confidential merge request | Create branch |
@@ -121,12 +120,12 @@ The **Project** dropdown includes the list of private forks the user is a member
of as at least a Developer and merge requests are enabled.
Whenever the **Branch name** and **Source (branch or tag)** fields change, the
-availability of the target or source branch will be checked. Both branches should
-be available in the private fork selected.
+availability of the target and source branch are checked. Both branches should
+be available in the selected private fork.
-By clicking the **Create confidential merge request** button, GitLab will create
+By clicking the **Create confidential merge request** button, GitLab creates
the branch and merge request in the private fork. When you choose
-**Create branch**, GitLab will only create the branch.
+**Create branch**, GitLab creates only the branch.
-Once the branch is created in the private fork, developers can now push code to
+After the branch is created in the private fork, developers can push code to
that branch to fix the confidential issue.
diff --git a/doc/user/project/issues/crosslinking_issues.md b/doc/user/project/issues/crosslinking_issues.md
index b5d3b71e679..250fa618dd8 100644
--- a/doc/user/project/issues/crosslinking_issues.md
+++ b/doc/user/project/issues/crosslinking_issues.md
@@ -31,10 +31,9 @@ git commit -m "this is my commit message. Related to https://gitlab.com/<usernam
Of course, you can replace `gitlab.com` with the URL of your own GitLab instance.
-NOTE:
-Linking your first commit to your issue is going to be relevant
+Linking your first commit to your issue is relevant
for tracking your process with [GitLab Value Stream Analytics](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/).
-It will measure the time taken for planning the implementation of that issue,
+It measures the time taken for planning the implementation of that issue,
which is the time between creating an issue and making the first commit.
## From Related Issues
@@ -45,7 +44,7 @@ issues regarding the same topic.
You do that as explained above, when [mentioning an issue from a commit message](#from-commit-messages).
-When mentioning issue `#111` in issue `#222`, issue `#111` will also display a notification
+When mentioning issue `#111` in issue `#222`, issue `#111` also displays a notification
in its tracker. That is, you only need to mention the relationship once for it to
display in both issues. The same is valid when mentioning issues in [merge requests](#from-merge-requests).
@@ -56,8 +55,8 @@ display in both issues. The same is valid when mentioning issues in [merge reque
Mentioning issues in merge request comments works exactly the same way as
they do for [related issues](#from-related-issues).
-When you mention an issue in a merge request description, it will simply
-[link the issue and merge request together](#from-related-issues). Additionally,
+When you mention an issue in a merge request description, it
+[links the issue and merge request together](#from-related-issues). Additionally,
you can also [set an issue to close automatically](managing_issues.md#closing-issues-automatically)
as soon as the merge request is merged.
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index 023a8ee57bc..e7cd1377603 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -53,7 +53,7 @@ Exported issues are always sorted by `Issue ID`.
>
> **Weight** and **Locked** columns were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5300) in GitLab Starter 10.8.
-Data wis 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:
+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/due_dates.md b/doc/user/project/issues/due_dates.md
index 63cd784333a..34e9340067c 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -11,14 +11,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
Due dates can be used in issues to keep track of deadlines and make sure features are
-shipped on time. Users must have at least [Reporter permissions](../../permissions.md)
-to be able to edit them, but they can be seen by everybody with permission to view
-the issue.
+shipped on time. Users need at least [Reporter permissions](../../permissions.md)
+to be able to edit the due date. All users with permission to view
+the issue can view the due date.
## Setting a due date
-When creating or editing an issue, you can click in the **due date** field and a calendar
-will appear to help you choose the date you want. To remove the date, select the date
+When creating an issue, select the **Due date** field to make a calendar
+appear for choosing the date. To remove the date, select the date
text and delete it. The date is related to the server's timezone, not the timezone of
the user setting the due date.
@@ -37,18 +37,17 @@ The last way to set a due date is by using [quick actions](../quick_actions.md),
## Making use of due dates
-Issues that have a due date can be easily seen in the issue tracker,
-displaying a date next to them. Issues where the date is overdue will have
-the icon and the date colored red. You can sort issues by those that are
-`Due soon` or `Due later` from the dropdown menu on the right.
-
-![Issues with due dates in the issues index page](img/due_dates_issues_index_page.png)
+You can see issues with their due dates in the [issues list](index.md#issues-list).
+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}**).
Due dates also appear in your [to-do list](../../todos.md).
![Issues with due dates in the to dos](img/due_dates_todos.png)
-The day before an open issue is due, an email will be sent to all participants
+The day before an open issue is due, an email is sent to all participants
of the issue. Like the due date, the "day before the due date" is determined by the
server's timezone.
diff --git a/doc/user/project/issues/img/due_dates_issues_index_page.png b/doc/user/project/issues/img/due_dates_issues_index_page.png
deleted file mode 100644
index 94679436b32..00000000000
--- a/doc/user/project/issues/img/due_dates_issues_index_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 05e7eb3021a..74311eefd83 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -22,8 +22,8 @@ their implementation between:
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, but if you have multiple projects in a group,
-you can also view all the issues collectively at the group level.
+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:**
@@ -91,9 +91,13 @@ must be set.
## Viewing and managing issues
-While you can view and manage the full details of an issue on the [issue page](#issue-page),
-you can also work with multiple issues at a time using the [Issues List](#issues-list),
-[Issue Boards](#issue-boards), Issue references, and [Epics](#epics). **(PREMIUM)**
+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)**.
Key actions for issues include:
@@ -117,14 +121,17 @@ and modify them if you have the necessary [permissions](../../permissions.md).
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).
-### Issues list
+### Issues List
+
+![Project Issues List view](img/project_issues_list_view.png)
+
+On the Issues List, you can:
-![Project issues list view](img/project_issues_list_view.png)
+- 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.
-On the Issues List, you can view all issues in the current project, or from multiple
-projects when opening the Issues List from the higher-level group context. Filter the
-issue list with a [search query](../../search/index.md#filtering-issue-and-merge-request-lists),
-including specific metadata, such as label(s), assignees(s), status, and more. From this
+You can filter the Issues List with a [search query](../../search/index.md#filtering-issue-and-merge-request-lists),
+including specific metadata, such as labels, assignees, status, and more. From this
view, you can also make certain changes [in bulk](../bulk_editing.md) to the displayed issues.
For more information, see the [Issue Data and Actions](issue_data_and_actions.md) page
@@ -140,21 +147,21 @@ You can sort a list of issues in several ways, for example by issue creation dat
labels or their assignees**(PREMIUM)**. They offer the flexibility to manage issues using
highly customizable workflows.
-You can reorder issues within a column. If you drag an issue card to another column, its
-associated label or assignee will change to match that of the new column. The entire
+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.
### Design Management
With [Design Management](design_management.md), you can upload design
-assets to issues and view them all together to easily share and
-collaborate with your team.
+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 by tracking groups of issues that share a theme, across
+efficiently and with less effort. Epics track groups of issues that share a theme, across
projects and milestones.
### Related issues
@@ -179,10 +186,10 @@ message in the Activity stream about the reference, with a link to the other iss
To prevent duplication of issues for the same topic, GitLab searches for similar issues
when new issues are being created.
-When typing in the title in the **New Issue** page, GitLab searches titles and descriptions
-across all issues the user has access to in the current project. Up to five similar issues,
-sorted by most recently updated, are displayed below the title box. Note that this feature
-requires [GraphQL](../../../api/graphql/index.md) to be enabled.
+As you type in the title field of the **New Issue** page, GitLab searches titles and descriptions
+across all issues to in the current project. Only issues you have access to are returned.
+Up to five similar issues, sorted by most recently updated, are displayed below the title box.
+[GraphQL](../../../api/graphql/index.md) must be enabled to use this feature.
![Similar issues](img/similar_issues.png)
@@ -193,8 +200,8 @@ requires [GraphQL](../../../api/graphql/index.md) to be enabled.
> - Issue health status visible in issue lists [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45141) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/213567) in GitLab 13.7.
-To help you track the status of your issues, you can assign a status to each issue to flag work
-that's progressing as planned or needs attention to keep on schedule:
+To help you track issue statuses, you can assign a status to each issue.
+This marks issues as progressing as planned or needs attention to keep on schedule:
- **On track** (green)
- **Needs attention** (amber)
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 2520a562f1e..4c8630581f5 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -35,6 +35,7 @@ The numbers in the image correspond to the following features:
- **12.** [Participants](#participants)
- **13.** [Notifications](#notifications)
- **14.** [Reference](#reference)
+- [Issue email](#email)
- **15.** [Edit](#edit)
- **16.** [Description](#description)
- **17.** [Mentions](#mentions)
@@ -174,6 +175,13 @@ for the issue. Notifications are automatically enabled after you participate in
`foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar` is the
`project-name`, and `xxx` is the issue number.
+### Email
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18816) in GitLab 13.8.
+
+Guest users can see a button in the right sidebar to copy the email address for the issue.
+Sending an email to this address creates a comment containing the email body.
+
### Edit
Clicking this icon opens the issue for editing. All the fields which
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index 03060ca720c..ef860df054e 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -19,16 +19,16 @@ Key actions for issues include:
## Create a new issue
-When you create a new issue, you'll be prompted to fill in the [data and fields of the issue](issue_data_and_actions.md),
+When you create a new issue, you are prompted to fill in the [data and fields of the issue](issue_data_and_actions.md),
as illustrated below. If you know the values you want to assign to an issue, you can use the
-[Quick actions](../quick_actions.md) feature to input values, instead of selecting them from lists.
+[Quick actions](../quick_actions.md) feature to input values.
While creating an issue, you can associate it to an existing epic from current group by
selecting it using **Epic** dropdown.
### Accessing the New Issue form
-There are many ways to get to the New Issue form from within a project:
+There are many ways to get to the New Issue form from a project's page:
- Navigate to your **Project's Dashboard** > **Issues** > **New Issue**:
@@ -75,9 +75,8 @@ using the dropdown button at the top-right of the page.
![Select project to create issue](img/select_project_from_group_level_issue_tracker.png)
-We'll keep track of the project you selected most recently, and use it as the default
-for your next visit. This should save you a lot of time and clicks, if you mostly
-create issues for the same project.
+The project you selected most recently becomes the default for your next visit.
+This should save you a lot of time and clicks, if you mostly create issues for the same project.
![Create issue from group-level issue tracker](img/create_issue_from_group_level_issue_tracker.png)
@@ -90,22 +89,22 @@ the appropriate project and followed up from there.
### New issue via email
A link to **Email a new issue to this project** is displayed at the bottom of a project's
-**Issues List** page, if your GitLab instance has [incoming email](../../../administration/incoming_email.md)
-configured.
+**Issues List** page. The link is shown only if your GitLab instance has [incoming email](../../../administration/incoming_email.md)
+configured and there is at least one issue in the issue list.
![Bottom of a project issues page](img/new_issue_from_email.png)
When you click this link, an email address is generated and displayed, which should be used
by **you only**, to create issues in this project. You can save this address as a
-contact in your email client for easy access.
+contact in your email client for quick access.
WARNING:
This is a private email address, generated just for you. **Keep it to yourself**,
as anyone who knows it can create issues or merge requests as if they
-were you. If the address is compromised, or you'd like it to be regenerated for
-any reason, click **Email a new issue to this project** again and click the reset link.
+were you. If the address is compromised, or you want to regenerate it,
+click **Email a new issue to this project**, followed by **reset it**.
-Sending an email to this address will create a new issue in your name for
+Sending an email to this address creates a new issue associated with your account for
this project, where:
- The email subject becomes the issue title.
@@ -118,15 +117,15 @@ older format is still supported, allowing existing aliases or contacts to contin
### New issue via URL with prefilled fields
-You can link directly to the new issue page for a given project, with prefilled
-field values using query string parameters in a URL. This is useful for embedding
-a URL in an external HTML page, and also certain scenarios where you want the user to
-create an issue with certain fields prefilled.
+To link directly to the new issue page with prefilled fields, use query
+string parameters in a URL. You can embed a URL in an external
+HTML page, or create issues with certain
+fields prefilled.
The title, description, description template, and confidential fields can be prefilled
using this method. You cannot pre-fill both the description and description template
-fields in the same URL (since a description template also populates the description
-field).
+fields in the same URL because a description template also populates the description
+field.
| Field | URL Parameter Name | Notes |
|----------------------|-----------------------|-------------------------------------------------------|
@@ -147,9 +146,9 @@ Follow these examples to form your new issue URL with prefilled fields.
## Moving Issues
-Moving an issue will copy it to a new location (project), and close it in the old project,
-but it will not be deleted. There will also be a system note added to both issues
-indicating where it came from and went to.
+Moving an issue copies it to the target project, and closes it in the originating project.
+The original issue is not deleted. A system note, which indicates
+where it came from and went to, is added to both issues.
The "Move issue" button is at the bottom of the right-sidebar when viewing the issue.
@@ -157,7 +156,9 @@ The "Move issue" button is at the bottom of the right-sidebar when viewing the i
### Moving Issues in Bulk
-If you have advanced technical skills you can also bulk move all the issues from one project to another in the rails console. The below script will move all the issues from one project to another that are not in status **closed**.
+If you have advanced technical skills you can also bulk move all the issues from
+one project to another in the rails console. The below script moves all issues
+that are not in status **closed** from one project to another.
To access rails console run `sudo gitlab-rails console` on the GitLab server and run the below
script. Please be sure to change `project`, `admin_user`, and `target_project` to your values.
@@ -193,23 +194,18 @@ from its list and dropping it into the **Closed** list.
### Closing issues automatically
-NOTE:
-For performance reasons, automatic issue closing is disabled for the very first
-push from an existing repository.
-
-When a commit or merge request resolves one or more issues, it is possible to have
-these issues closed automatically when the commit or merge request reaches the project's
-default branch.
+When a commit or merge request resolves issues, the issues
+can be closed automatically when the commit reaches the project's default branch.
If a commit message or merge request description contains text matching a [defined pattern](#default-closing-pattern),
-all issues referenced in the matched text will be closed. This happens when the commit
+all issues referenced in the matched text are closed. This happens when the commit
is pushed to a project's [**default** branch](../repository/branches/index.md#default-branch),
or when a commit or merge request is merged into it.
For example, if `Closes #4, #6, Related to #5` is included in a Merge Request
-description, issues `#4` and `#6` will close automatically when the MR is merged, but not `#5`.
+description, issues `#4` and `#6` are closed automatically when the MR is merged, but not `#5`.
Using `Related to` flags `#5` as a [related issue](related_issues.md),
-but it will not close automatically.
+but is not closed automatically.
![merge request closing issue when merged](img/merge_request_closes_issue.png)
@@ -219,9 +215,12 @@ If the issue is in a different repository than the MR, add the full URL for the
Closes #4, #6, and https://gitlab.com/<username>/<projectname>/issues/<xxx>
```
+For performance reasons, automatic issue closing is disabled for the very first
+push from an existing repository.
+
#### Default closing pattern
-When not specified, the default issue closing pattern as shown below will be used:
+When not specified, this default issue closing pattern is used:
```shell
\b((?:[Cc]los(?:e[sd]?|ing)|\b[Ff]ix(?:e[sd]|ing)?|\b[Rr]esolv(?:e[sd]?|ing)|\b[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+)
@@ -251,8 +250,8 @@ This commit is also related to #17 and fixes #18, #19
and https://gitlab.example.com/group/otherproject/issues/23.
```
-will close `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to,
-as well as `#22` and `#23` in `group/otherproject`. `#17` won't be closed as it does
+closes `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to,
+as well as `#22` and `#23` in `group/otherproject`. `#17` is not closed as it does
not match the pattern. It works with multi-line commit messages as well as one-liners
when used from the command line with `git commit -m`.
@@ -261,14 +260,14 @@ when used from the command line with `git commit -m`.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/19754) in GitLab 12.7.
The automatic issue closing feature can be disabled on a per-project basis
-within the [project's repository settings](../settings/index.md). Referenced
-issues will still be displayed as such but won't be closed automatically.
+in the [project's repository settings](../settings/index.md). Referenced
+issues are still displayed, but are not closed automatically.
![disable issue auto close - settings](img/disable_issue_auto_close.png)
This only applies to issues affected by new merge requests or commits. Already
closed issues remain as-is. Disabling automatic issue closing only affects merge
-requests *within* the project and won't prevent other projects from closing it
+requests *in* the project and does not prevent other projects from closing it
via cross-project issues.
#### Customizing the issue closing pattern **(CORE ONLY)**
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 2f8603e1db0..22dfd3a8719 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -57,7 +57,7 @@ and edit labels.
### Project labels
-> Showing all inherited labels [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241990) in 13.5.
+> 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
@@ -228,7 +228,7 @@ to label notifications for the project only, or the whole group.
> - Priority sorting is based on the highest priority label only. [This discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/14523) considers changing this.
Labels can have relative priorities, which are used in the **Label priority** and
-**Priority** sort orders of the epic, issue, and merge request list pages. Prioritization
+**Priority** sort orders of issues and merge request list pages. Prioritization
for both group and project labels happens at the project level, and cannot be done
from the group label list.
@@ -241,7 +241,7 @@ means higher priority.
![Drag to change label priority](img/labels_drag_priority_v12_1.gif)
-On the epic, merge request, and issue list pages (for both groups and projects) you
+On the merge request and issue list pages (for both groups and projects) you
can sort by `Label priority` or `Priority`.
If you sort by `Label priority`, GitLab uses this sort comparison order:
diff --git a/doc/user/project/members/img/access_requests_management.png b/doc/user/project/members/img/access_requests_management.png
deleted file mode 100644
index 9a1c9621e41..00000000000
--- a/doc/user/project/members/img/access_requests_management.png
+++ /dev/null
Binary files differ
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
new file mode 100644
index 00000000000..950ef4dec01
--- /dev/null
+++ b/doc/user/project/members/img/access_requests_management_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_accept.png b/doc/user/project/members/img/add_user_email_accept.png
deleted file mode 100644
index cbee9e08c70..00000000000
--- a/doc/user/project/members/img/add_user_email_accept.png
+++ /dev/null
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
new file mode 100644
index 00000000000..ed980036af5
--- /dev/null
+++ b/doc/user/project/members/img/add_user_email_accept_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_ready.png b/doc/user/project/members/img/add_user_email_ready.png
deleted file mode 100644
index 0066eb3427b..00000000000
--- a/doc/user/project/members/img/add_user_email_ready.png
+++ /dev/null
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_13_8.png
new file mode 100644
index 00000000000..a610b46a176
--- /dev/null
+++ b/doc/user/project/members/img/add_user_email_ready_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_search.png b/doc/user/project/members/img/add_user_email_search.png
deleted file mode 100644
index 66bcd6aad80..00000000000
--- a/doc/user/project/members/img/add_user_email_search.png
+++ /dev/null
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_13_8.png
new file mode 100644
index 00000000000..934cf19bd3d
--- /dev/null
+++ b/doc/user/project/members/img/add_user_email_search_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_give_permissions.png b/doc/user/project/members/img/add_user_give_permissions.png
deleted file mode 100644
index 376a3eefccc..00000000000
--- a/doc/user/project/members/img/add_user_give_permissions.png
+++ /dev/null
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_13_8.png
new file mode 100644
index 00000000000..1916d056a52
--- /dev/null
+++ b/doc/user/project/members/img/add_user_give_permissions_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_import_members_from_another_project.png b/doc/user/project/members/img/add_user_import_members_from_another_project.png
deleted file mode 100644
index cb3b70bd4b5..00000000000
--- a/doc/user/project/members/img/add_user_import_members_from_another_project.png
+++ /dev/null
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_13_8.png
new file mode 100644
index 00000000000..a6dddec3fb7
--- /dev/null
+++ b/doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_imported_members.png b/doc/user/project/members/img/add_user_imported_members.png
deleted file mode 100644
index 51fd7688890..00000000000
--- a/doc/user/project/members/img/add_user_imported_members.png
+++ /dev/null
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
new file mode 100644
index 00000000000..725e447604f
--- /dev/null
+++ b/doc/user/project/members/img/add_user_imported_members_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_list_members.png b/doc/user/project/members/img/add_user_list_members.png
deleted file mode 100644
index e0fa404288d..00000000000
--- a/doc/user/project/members/img/add_user_list_members.png
+++ /dev/null
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
new file mode 100644
index 00000000000..b8c0160c6d8
--- /dev/null
+++ b/doc/user/project/members/img/add_user_list_members_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_search_people.png b/doc/user/project/members/img/add_user_search_people.png
deleted file mode 100644
index 41767a9167c..00000000000
--- a/doc/user/project/members/img/add_user_search_people.png
+++ /dev/null
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_13_8.png
new file mode 100644
index 00000000000..e9aa58512ab
--- /dev/null
+++ b/doc/user/project/members/img/add_user_search_people_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/other_group_sees_shared_project_v13_6.png b/doc/user/project/members/img/other_group_sees_shared_project_v13_6.png
deleted file mode 100644
index e6e3f8f043b..00000000000
--- a/doc/user/project/members/img/other_group_sees_shared_project_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/other_group_sees_shared_project_v13_8.png b/doc/user/project/members/img/other_group_sees_shared_project_v13_8.png
new file mode 100644
index 00000000000..aa2aaf071e1
--- /dev/null
+++ b/doc/user/project/members/img/other_group_sees_shared_project_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
new file mode 100644
index 00000000000..5d7948f0761
--- /dev/null
+++ b/doc/user/project/members/img/project_groups_tab_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/project_members.png b/doc/user/project/members/img/project_members.png
deleted file mode 100644
index 218f5a24d2e..00000000000
--- a/doc/user/project/members/img/project_members.png
+++ /dev/null
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
new file mode 100644
index 00000000000..9120d471b3b
--- /dev/null
+++ b/doc/user/project/members/img/project_members_13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/share_project_with_groups_tab_v13_6.png b/doc/user/project/members/img/share_project_with_groups_tab_v13_6.png
deleted file mode 100644
index 7d83659ef7a..00000000000
--- a/doc/user/project/members/img/share_project_with_groups_tab_v13_6.png
+++ /dev/null
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
new file mode 100644
index 00000000000..6cbbb386396
--- /dev/null
+++ b/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/share_project_with_groups_v13_6.png b/doc/user/project/members/img/share_project_with_groups_v13_6.png
deleted file mode 100644
index 121e77671a3..00000000000
--- a/doc/user/project/members/img/share_project_with_groups_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 85cb139c45b..cccb998fc31 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -21,7 +21,7 @@ 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.png)
+![Project members page](img/project_members_13_8.png)
From the image above, we can deduce the following things:
@@ -46,17 +46,17 @@ using the dropdown on the right side:
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.png)
+![Search for people](img/add_user_search_people_13_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.png)
+![Give user permissions](img/add_user_give_permissions_13_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.png)
+![List members](img/add_user_list_members_13_8.png)
From there on, you can either remove an existing user or change their access
level to the project.
@@ -68,14 +68,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.png)
+![Import members from another project](img/add_user_import_members_from_another_project_13_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.png)
+![Members list of new members](img/add_user_imported_members_13_8.png)
## Invite people using their e-mail address
@@ -83,18 +83,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.png)
+![Invite user by mail](img/add_user_email_search_13_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.png)
+![Invite user by mail ready to submit](img/add_user_email_ready_13_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.png)
+![Invite user members list](img/add_user_email_accept_13_8.png)
While unaccepted, the system automatically sends reminder emails on the second, fifth,
and tenth day after the invitation was initially sent.
@@ -130,7 +130,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.png)
+![Manage access requests](img/access_requests_management_13_8.png)
If you change your mind before your request is approved, just click the
**Withdraw Access Request** button.
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index edfe8ae3b5b..d17717fb29c 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -26,19 +26,20 @@ 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_6.png)
+ ![share project with groups](img/share_project_with_groups_tab_v13_8.png)
1. Select the **Invite group** tab.
1. Add the 'Engineering' group with the maximum access level of your choice.
1. Optionally, select an expiring date.
1. Click **Invite**.
+1. After sharing 'Project Acme' with 'Engineering':
+ - The group is listed in the **Groups** tab.
- ![share project with groups tab](img/share_project_with_groups_tab_v13_6.png)
+ !['Engineering' group is listed in Groups tab](img/project_groups_tab_13_8.png)
-1. After sharing 'Project Acme' with 'Engineering', the project is listed
- on the group dashboard
+ - The project is listed on the group dashboard.
- !['Project Acme' is listed as a shared project for 'Engineering'](img/other_group_sees_shared_project_v13_6.png)
+ !['Project Acme' is listed as a shared project for 'Engineering'](img/other_group_sees_shared_project_v13_8.png)
Note that you can only share a project with:
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index 8eabef982c8..8adaae3b2ef 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -23,10 +23,10 @@ of the merge request.
## Enabling commit edits from upstream members
-The feature can only be enabled by users who already have push access to the
-source project and only lasts while the merge request is open. Once enabled,
-upstream members will also be able to retry the pipelines and jobs of the
-merge request:
+From [GitLab 13.7 onwards](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:
1. While creating or editing a merge request, select the checkbox **Allow
commits from members who can merge to the target branch**.
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
index 04114968c80..6fa2340c7a4 100644
--- a/doc/user/project/merge_requests/browser_performance_testing.md
+++ b/doc/user/project/merge_requests/browser_performance_testing.md
@@ -60,7 +60,7 @@ on your code by using GitLab CI/CD and [sitespeed.io](https://www.sitespeed.io)
using Docker-in-Docker.
1. First, set up GitLab Runner with a
- [Docker-in-Docker build](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
+ [Docker-in-Docker build](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker).
1. Configure the default Browser Performance Testing CI job as follows in your `.gitlab-ci.yml` file:
```yaml
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 5a98338a81b..ca15ec154fc 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -72,10 +72,10 @@ It requires GitLab 11.11 or later, and GitLab Runner 11.5 or later. If you are u
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).
-First, you need GitLab Runner configured:
+- 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.
-- For the [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
-- With 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 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.
Once you set up GitLab Runner, include the Code Quality template in your CI configuration:
@@ -140,6 +140,99 @@ definition they could execute privileged Docker commands on the runner
host. Having proper access control policies mitigates this attack vector by
allowing access only to trusted actors.
+### Set up a private runner for code quality without Docker-in-Docker
+
+It's possible to configure your own runners and avoid Docker-in-Docker. You can use a
+configuration that may greatly speed up job execution without requiring your runners
+to operate in privileged mode.
+
+This alternative configuration uses socket binding to share the Runner's Docker daemon
+with the job environment. Be aware that this configuration [has significant considerations](../../../ci/docker/using_docker_build.md#use-docker-socket-binding)
+to be consider, but may be preferable depending on your use case.
+
+1. Register a new runner:
+
+ ```shell
+ $ gitlab-runner register --executor "docker" \
+ --docker-image="docker:stable" \
+ --url "https://gitlab.com/" \
+ --description "cq-sans-dind" \
+ --tag-list "cq-sans-dind" \
+ --locked="false" \
+ --access-level="not_protected" \
+ --docker-volumes "/cache"\
+ --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
+ --registration-token="<project_token>" \
+ --non-interactive
+ ```
+
+1. **Optional, but recommended:** Set the builds directory to `/tmp/builds`,
+ so job artifacts are periodically purged from the runner host. If you skip
+ this step, you must clean up the default builds directory (`/builds`) yourself.
+ You can do this by adding the following two flags to `gitlab-runner register`
+ in the previous step.
+
+ ```shell
+ --builds-dir /tmp/builds
+ --docker-volumes /tmp/builds:/tmp/builds
+ ```
+
+ The resulting configuration:
+
+ ```toml
+ [[runners]]
+ name = "cq-sans-dind"
+ url = "https://gitlab.com/"
+ token = "<project_token>"
+ executor = "docker"
+ builds_dir = "/tmp/builds"
+ [runners.docker]
+ tls_verify = false
+ image = "docker:stable"
+ privileged = false
+ disable_entrypoint_overwrite = false
+ oom_kill_disable = false
+ disable_cache = false
+ volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock", "/tmp/builds:/tmp/builds"]
+ shm_size = 0
+ [runners.cache]
+ [runners.cache.s3]
+ [runners.cache.gcs]
+ ```
+
+1. Apply two overrides to the `code_quality` job created by the template:
+
+ ```yaml
+ include:
+ - template: Code-Quality.gitlab-ci.yml
+
+ code_quality:
+ services: # Shut off Docker-in-Docker
+ tags:
+ - cq-sans-dind # Set this job to only run on our new specialized runner
+ ```
+
+The end result is that:
+
+- Privileged mode is not used.
+- Docker-in-Docker is not used.
+- 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)
+running Code Quality analysis ran significantly faster the second time:
+
+![Code Quality sequential runs without DinD](img/code_quality_host_bound_sequential.png)
+
+This configuration is not possible on `gitlab.com` shared runners. Shared runners
+are configured with `privileged=true`, and they do not expose `docker.sock` into
+the job container. As a result, socket binding cannot be used to make `docker` available
+in the context of the job script.
+
+[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker)
+was chosen as an operational decision by the runner team, instead of exposing `docker.sock`.
+
### Disabling the code quality job
The `code_quality` job doesn't run if the `$CODE_QUALITY_DISABLED` environment
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index cb95daa2cab..bc718ae867f 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -62,7 +62,7 @@ request's page at the top-right side:
- 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.
- Set the merge request as a [**Draft**](work_in_progress_merge_requests.md) to avoid accidental merges before it is ready.
-Once you have created the merge request, you can also:
+After you have created the merge request, you can also:
- [Discuss](../../discussions/index.md) your implementation with your team in the merge request thread.
- [Perform inline code reviews](reviewing_and_managing_merge_requests.md#perform-inline-code-reviews).
@@ -70,7 +70,7 @@ Once you have created the merge request, you can also:
- Preview continuous integration [pipelines on the merge request widget](reviewing_and_managing_merge_requests.md#pipeline-status-in-merge-requests-widgets).
- Preview how your changes look directly on your deployed application with [Review Apps](reviewing_and_managing_merge_requests.md#live-preview-with-review-apps).
- [Allow collaboration on merge requests across forks](allow_collaboration.md).
-- Perform a [Review](../../discussions/index.md#merge-request-reviews) in order to create multiple comments on a diff and publish them once you're ready.
+- Perform a [Review](../../discussions/index.md#merge-request-reviews) to create multiple comments on a diff and publish them when you're ready.
- Add [code suggestions](../../discussions/index.md#suggest-changes) to change the content of merge requests directly into merge request threads, and easily apply them to the codebase directly from the UI.
- Add a time estimation and the time spent with that merge request with [Time Tracking](../time_tracking.md#time-tracking).
@@ -115,9 +115,10 @@ It is also possible to manage multiple assignees:
> - [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.1.
+> - [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)**
WARNING:
@@ -160,6 +161,53 @@ Feature.disable(:merge_request_reviewers)
Feature.disable(:merge_request_reviewers, Project.find(<project id>))
```
+#### Reviewer approval rules
+
+> - [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-reviewer-approval-rules). **(CORE ONLY)**
+
+When editing the **Reviewers** field in a new or existing merge request, this feature
+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 `Codeowner` without group detail. We intend to iterate on this feature in future releases.
+
+This example shows reviewers and approval rules when creating a new merge request:
+
+![Reviewer approval rules in new/edit form](img/reviewer_approval_rules_form_v13_8.png)
+
+This example shows reviewers and approval rules in a merge request sidebar:
+
+![Reviewer approval rules in sidebar](img/reviewer_approval_rules_sidebar_v13_8.png)
+
+##### Enable or disable Reviewer Approval Rules **(CORE ONLY)**
+
+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>))
+```
+
### Merge requests to close issues
If the merge request is being created to resolve an issue, you can
@@ -199,5 +247,5 @@ is set for deletion, the merge request widget displays the
at once. By doing so, you save pipeline minutes.
- Delete feature branches on merge or after merging them to keep your repository clean.
- Take one thing at a time and ship the smallest changes possible. By doing so,
- you'll have faster reviews and your changes will be less prone to errors.
+ reviews are faster and your changes are less prone to errors.
- Do not use capital letters nor special chars in branch names.
diff --git a/doc/user/project/merge_requests/img/code_quality_host_bound_sequential.png b/doc/user/project/merge_requests/img/code_quality_host_bound_sequential.png
new file mode 100644
index 00000000000..2b31f3b42ee
--- /dev/null
+++ b/doc/user/project/merge_requests/img/code_quality_host_bound_sequential.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png b/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png
new file mode 100644
index 00000000000..c2aa0689d65
--- /dev/null
+++ b/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png b/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png
new file mode 100644
index 00000000000..3828868965b
--- /dev/null
+++ b/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index 82b5d67ba2b..9154897d42d 100644
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -103,7 +103,7 @@ job.
An example configuration workflow:
1. Set up GitLab Runner to run Docker containers, like the
- [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
+ [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker).
1. Configure the default Load Performance Testing CI job in your `.gitlab-ci.yml` file.
You need to include the template and configure it with variables:
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 5c466654b31..93b85ce8669 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -8,7 +8,7 @@ type: reference, concepts
# Squash and merge
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1024) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.17.
-> - [Ported](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) to GitLab Core 11.0.
+> - [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.
With squash and merge you can combine all your merge request's commits into one
and retain a clean history.
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index c38b28f7718..3960f916f9b 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -33,7 +33,7 @@ This format was originally developed for Java, but most coverage analysis framew
for other languages have plugins to add support for it, like:
- [simplecov-cobertura](https://rubygems.org/gems/simplecov-cobertura) (Ruby)
-- [gocover-cobertura](https://github.com/t-yuki/gocover-cobertura) (Golang)
+- [gocover-cobertura](https://github.com/boumenot/gocover-cobertura) (Golang)
Other coverage analysis frameworks support the format out of the box, for example:
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index fd7c58f12b9..4910751ece1 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -72,10 +72,26 @@ Let's consider the following scenario:
## Job token
-A unique job token is generated for each job and provides the user read
-access all projects that would be normally accessible to the user creating that
-job. The unique job token does not have any write permissions, but there
-is a [proposal to add support](https://gitlab.com/groups/gitlab-org/-/epics/3559).
+When a pipeline job is about to run, GitLab generates a unique token and injects it as the
+[`CI_JOB_TOKEN` predefined variable](../../ci/variables/predefined_variables.md).
+This token can authenticate [API requests](../../api/README.md)
+from the job script (Runner) that needs to access the project's resources (for example, when
+fetching a job artifact).
+
+Once the token is authenticated, GitLab identifies the user who triggered the job and uses this user
+to authorize access to the resource. Therefore, this user must be assigned to
+[a role that has the required privileges](../permissions.md).
+
+The job token has these limitations:
+
+- Not all APIs allow job tokens for authentication. See [this list](../../api/README.md#gitlab-ci-job-token)
+ for available endpoints.
+- The token is valid only while the pipeline job runs. Once the job finishes, the token can't be
+ used for authentication.
+
+Although a job token is handy to quickly access a project's resources without any configuration, it
+sometimes gives extra permissions that aren't necessary. There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559)
+to redesign the feature for more strategic control of the access permissions.
If you need your CI pipeline to push to the Package Registry, consider using [deploy tokens](deploy_tokens/index.md).
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
index 4aa89ec6f8d..f02697a3cd5 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
@@ -24,7 +24,7 @@ GitLab Pages site.
Note that **how to** add DNS records depends on which server your domain
is hosted on. Every control panel has its own place to do it. If you are
not an administrator of your domain, and don't have access to your registrar,
-you'll need to ask for the technical support of your hosting service
+you must ask the technical support of your hosting service
to do it for you.
To help you out, we've gathered some instructions on how to do that
@@ -67,7 +67,7 @@ Example:
- `www` => `CNAME` => `example.com`
-This way, visitors visiting `www.example.com` will be redirected to
+This way, visitors visiting `www.example.com` are redirected to
`example.com`.
## MX record
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
index f8173b4c004..8ed0ef82893 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
@@ -47,7 +47,8 @@ Click **Create New Domain**.
#### 2. Get the verification code
-Once you have added a new domain to Pages, the verification code will be prompted to you. Copy the values from GitLab and paste them in your domain's control panel as a TXT record on the next step.
+After you add a new domain to Pages, the verification code prompts you. Copy the values from GitLab
+and paste them in your domain's control panel as a TXT record on the next step.
![Get the verification code](img/get_domain_verification_code_v12_0.png)
@@ -91,7 +92,7 @@ add a DNS apex `CNAME` record instead of an `A` record. The main
advantage of doing so is that when GitLab Pages IP on GitLab.com
changes for whatever reason, you don't need to update your `A` record.
There may be a few exceptions, but **this method is not recommended**
-as it most likely won't work if you set an [`MX` record](dns_concepts.md#mx-record) for your root domain.
+as it most likely doesn't work if you set an [`MX` record](dns_concepts.md#mx-record) for your root domain.
##### For subdomains
@@ -154,12 +155,11 @@ Once you have added all the DNS records:
![Verify your domain](img/retry_domain_verification_v12_0.png)
-As soon as your domain becomes active, your website will be available
-through your domain name.
+As soon as your domain becomes active, your website is available through your domain name.
WARNING:
Considering GitLab instances with domain verification enabled,
-if the domain cannot be verified for 7 days, it will be removed
+if the domain can't be verified for 7 days, it's removed
from the GitLab project.
> **Notes:**
@@ -169,9 +169,9 @@ from the GitLab project.
to [disabled custom domain verification](../../../../administration/pages/index.md#custom-domain-verification).
> - [DNS propagation may take some time (up to 24h)](https://www.inmotionhosting.com/support/domain-names/dns-nameserver-changes/complete-guide-to-dns-records/),
although it's usually a matter of minutes to complete. Until it does, verification
- will fail and attempts to visit your domain will respond with a 404.
+ fails, and attempts to visit your domain result in a 404.
> - Once your domain has been verified, leave the verification record
- in place: your domain will be periodically reverified, and may be
+ in place. Your domain is periodically reverified, and may be
disabled if the record is removed.
##### Troubleshooting Pages domain verification
@@ -211,7 +211,7 @@ For a subdomain:
You can add more than one alias (custom domains and subdomains) to the same project.
An alias can be understood as having many doors leading to the same room.
-All the aliases you've set to your site will be listed on **Setting > Pages**.
+All the aliases you've set to your site are listed on **Setting > Pages**.
From that page, you can view, add, and remove them.
### Redirecting `www.domain.com` to `domain.com` with Cloudflare
@@ -294,7 +294,7 @@ Sublime Text, Atom, Dreamweaver, Brackets, etc).
To make your website's visitors even more secure, you can choose to
force HTTPS for GitLab Pages. By doing so, all attempts to visit your
-website via HTTP will be automatically redirected to HTTPS via 301.
+website through HTTP are automatically redirected to HTTPS through 301.
It works with both the GitLab default domain and with your custom
domain (as long as you've set a valid certificate for it).
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 3dea35153e4..aa06a15a8c0 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
@@ -50,15 +50,15 @@ Once you've met the requirements, enable Let's Encrypt integration:
1. Click **Save changes**.
-Once enabled, GitLab will obtain a LE certificate and add it to the
-associated Pages domain. It also will be renewed automatically by GitLab.
+Once enabled, GitLab obtains a LE certificate and add it to the
+associated Pages domain. GitLab also renews it automatically.
> **Notes:**
>
> - Issuing the certificate and updating Pages configuration
> **can take up to an hour**.
-> - If you already have SSL certificate in domain settings it
-> will continue to work until it will be replaced by Let's Encrypt's certificate.
+> - If you already have an SSL certificate in domain settings it
+> continues to work until replaced by the Let's Encrypt's certificate.
## Troubleshooting
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 dc73a664324..e8c6305dbab 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
@@ -10,10 +10,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
_Read this document for a brief overview of SSL/TLS certificates in
the scope of GitLab Pages, for beginners in web development._
-Every GitLab Pages project on GitLab.com will be available under
+Every GitLab Pages project on GitLab.com is available under
HTTPS for the default Pages domain (`*.gitlab.io`). Once you set
up your Pages project with your custom (sub)domain, if you want
-it secured by HTTPS, you will have to issue a certificate for that
+it secured by HTTPS, you must issue a certificate for that
(sub)domain and install it on your project.
NOTE:
@@ -41,9 +41,6 @@ the connection between the **client** (you, me, your visitors)
and the **server** (where you site lives), through a keychain of
authentications and validations.
-How about taking Josh's advice and protecting our sites too? We will be
-well supported, and we'll contribute to a safer internet.
-
## Organizations supporting HTTPS
There is a huge movement in favor of securing all the web. W3C fully
@@ -62,8 +59,8 @@ GitLab Pages accepts certificates provided in the [PEM](https://knowledge.digice
for public websites for security reasons and to ensure that browsers trust your site's certificate.
There are various kinds of certificates, each one
-with a certain security level. A static personal website will
-not require the same security level as an online banking web app,
+with a certain security level. A static personal website doesn't
+require the same security level as an online banking web app,
for instance.
There are some certificate authorities that
diff --git a/doc/user/project/pages/getting_started/pages_ci_cd_template.md b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
index 6dd431e02b0..e0d5e8be535 100644
--- a/doc/user/project/pages/getting_started/pages_ci_cd_template.md
+++ b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
@@ -41,7 +41,7 @@ configuration for the Pages site to generate properly.
If everything is configured correctly, the site can take approximately 30 minutes to deploy.
-You can watch the pipeline run by going to **CI / CD > Pipelines**.
+You can watch the pipeline run by navigating to **CI / CD > Pipelines**.
When the pipeline is finished, go to **Settings > Pages** to find the link to
your Pages website.
diff --git a/doc/user/project/pages/getting_started/pages_forked_sample_project.md b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
index 525bbde4671..c7916b7c01e 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
@@ -17,7 +17,7 @@ configured to generate a Pages site.
To fork a sample project and create a Pages website:
-1. View the sample projects by going to the [GitLab Pages examples](https://gitlab.com/pages) group.
+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. 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**.
@@ -50,7 +50,7 @@ You can take some **optional** further steps:
If you set the repository path to `gitlab-tests.gitlab.io`,
the resulting URL for your Pages website is `https://gitlab-tests.gitlab.io`.
- ![Change repo's path](../img/change_path_v12_10.png)
+ ![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)
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/pages_from_scratch.md b/doc/user/project/pages/getting_started/pages_from_scratch.md
index 230e88f35f5..3f2df634e3a 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Create a GitLab Pages website from scratch
-This tutorial shows you how to create a Pages site from scratch. You will start with
+This tutorial shows you how to create a Pages site from scratch. You start with
a blank project and create your own CI file, which gives instruction to
a [runner](https://docs.gitlab.com/runner/). When your CI/CD
[pipeline](../../../../ci/pipelines/index.md) runs, the Pages site is created.
@@ -218,7 +218,7 @@ There are three default stages for GitLab CI/CD: build, test,
and deploy.
If you want to test your script and check the built site before deploying
-to production, you can run the test exactly as it will run when you
+to production, you can run the test exactly as it runs when you
push to `master`.
To specify a stage for your job to run in,
@@ -376,7 +376,7 @@ test:
In this case, you need to exclude the `/vendor`
directory from the list of folders Jekyll builds. Otherwise, Jekyll
-will try to build the directory contents along with the site.
+tries to build the directory contents along with the site.
In the root directory, create a file called `_config.yml`
and add this content:
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index f549c4e6e7d..801fe0c7ef0 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -16,7 +16,7 @@ wildcard domain with your sysadmin. This guide is valid for any GitLab instance,
replace the Pages wildcard domain on GitLab.com (`*.gitlab.io`) with your own.
If you set up a GitLab Pages project on GitLab,
-it will automatically be accessible under a
+it's automatically accessible under a
subdomain of `namespace.example.io`.
The [`namespace`](../../group/index.md#namespaces)
is defined by your username on GitLab.com,
@@ -45,35 +45,35 @@ To understand Pages domains clearly, read the examples below.
- You created a project called `blog` under your username `john`,
therefore your project URL is `https://gitlab.com/john/blog/`.
Once you enable GitLab Pages for this project, and build your site,
- it will be available under `https://john.gitlab.io/blog/`.
+ you can access it at `https://john.gitlab.io/blog/`.
- You created a group for all your websites called `websites`,
and a project within this group is called `blog`. Your project
URL is `https://gitlab.com/websites/blog/`. Once you enable
- GitLab Pages for this project, the site will live under
+ GitLab Pages for this project, the site is available at
`https://websites.gitlab.io/blog/`.
- You created a group for your engineering department called `engineering`,
a subgroup for all your documentation websites called `docs`,
and a project within this subgroup is called `workflows`. Your project
URL is `https://gitlab.com/engineering/docs/workflows/`. Once you enable
- GitLab Pages for this project, the site will live under
+ GitLab Pages for this project, the site is available at
`https://engineering.gitlab.io/docs/workflows`.
### User and Group website examples
- Under your username, `john`, you created a project called
- `john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`.
+ `john.gitlab.io`. Your project URL is `https://gitlab.com/john/john.gitlab.io`.
Once you enable GitLab Pages for your project, your website
- will be published under `https://john.gitlab.io`.
+ is published under `https://john.gitlab.io`.
- Under your group `websites`, you created a project called
- `websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`.
+ `websites.gitlab.io`. Your project's URL is `https://gitlab.com/websites/websites.gitlab.io`.
Once you enable GitLab Pages for your project,
- your website will be published under `https://websites.gitlab.io`.
+ your website is published under `https://websites.gitlab.io`.
**General example:**
-- On GitLab.com, a project site will always be available under
+- On GitLab.com, a project site is always available under
`https://namespace.gitlab.io/project-name`
-- On GitLab.com, a user or group website will be available under
+- On GitLab.com, a user or group website is available under
`https://namespace.gitlab.io/`
- On your GitLab instance, replace `gitlab.io` above with your
Pages server domain. Ask your sysadmin for this information.
@@ -87,7 +87,7 @@ Every Static Site Generator (SSG) default configuration expects
to find your website under a (sub)domain (`example.com`), not
in a subdirectory of that domain (`example.com/subdir`). Therefore,
whenever you publish a project website (`namespace.gitlab.io/project-name`),
-you'll have to look for this configuration (base URL) on your SSG's
+you must look for this configuration (base URL) on your SSG's
documentation and set it up to reflect this pattern.
For example, for a Jekyll site, the `baseurl` is defined in the Jekyll
@@ -99,11 +99,11 @@ baseurl: "/blog"
```
On the contrary, if you deploy your website after forking one of
-our [default examples](https://gitlab.com/pages), the `baseurl` will
-already be configured this way, as all examples there are project
-websites. If you decide to make yours a user or group website, you'll
-have to remove this configuration from your project. For the Jekyll
-example we've just mentioned, you'd have to change Jekyll's `_config.yml` to:
+our [default examples](https://gitlab.com/pages), the `baseurl` is
+already configured this way, as all examples there are project
+websites. If you decide to make yours a user or group website, you
+must remove this configuration from your project. For the Jekyll
+example we just mentioned, you must change Jekyll's `_config.yml` to:
```yaml
baseurl: ""
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 846d30e898c..c9e28bf15c2 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -81,10 +81,12 @@ becomes available automatically.
To deploy your site, GitLab uses its built-in tool called [GitLab CI/CD](../../../ci/README.md)
to build your site and publish it to the GitLab Pages server. The sequence of
scripts that GitLab CI/CD runs to accomplish this task is created from a file named
-`.gitlab-ci.yml`, which you can [create and modify](getting_started/pages_from_scratch.md) at will. A specific `job` called `pages` in the configuration file will make GitLab aware that you are deploying a GitLab Pages website.
+`.gitlab-ci.yml`, which you can [create and modify](getting_started/pages_from_scratch.md).
+A specific `job` called `pages` in the configuration file makes GitLab aware that you're deploying a
+GitLab Pages website.
You can either use the GitLab [default domain for GitLab Pages websites](getting_started_part_one.md#gitlab-pages-default-domain-names),
-`*.gitlab.io`, or your own domain (`example.com`). In that case, you'll
+`*.gitlab.io`, or your own domain (`example.com`). In that case, you
need administrator access to your domain's registrar (or control panel) to set it up with Pages.
The following diagrams show the workflows you might follow to get started with Pages.
@@ -94,15 +96,15 @@ The following diagrams show the workflows you might follow to get started with P
## Access to your Pages site
If you're using GitLab Pages default domain (`.gitlab.io`),
-your website will be automatically secure and available under
+your website is automatically secure and available under
HTTPS. If you're using your own custom domain, you can
optionally secure it with SSL/TLS certificates.
-If you're using GitLab.com, your website will be publicly available to the internet.
+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),
-your websites will be published on your own server, according to the
+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 5a284bf57c3..8380f367212 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -44,19 +44,19 @@ Visit the [GitLab Pages group](https://gitlab.com/groups/pages) for a complete l
You can provide your own 403 and 404 error pages by creating the `403.html` and
`404.html` files respectively in the root directory of the `public/` directory
-that will be included in the artifacts. Usually this is the root directory of
+that are included in the artifacts. Usually this is the root directory of
your project, but that may differ depending on your static generator
configuration.
If the case of `404.html`, there are different scenarios. For example:
- If you use project Pages (served under `/projectname/`) and try to access
- `/projectname/non/existing_file`, GitLab Pages will try to serve first
+ `/projectname/non/existing_file`, GitLab Pages tries to serve first
`/projectname/404.html`, and then `/404.html`.
- If you use user/group Pages (served under `/`) and try to access
- `/non/existing_file` GitLab Pages will try to serve `/404.html`.
+ `/non/existing_file` GitLab Pages tries to serve `/404.html`.
- If you use a custom domain and try to access `/non/existing_file`, GitLab
- Pages will try to serve only `/404.html`.
+ Pages tries to serve only `/404.html`.
## Redirects in GitLab Pages
@@ -71,8 +71,8 @@ To restrict access to your website, enable [GitLab Pages Access Control](pages_a
If you ever feel the need to purge your Pages content, you can do so by going
to your project's settings through the gear icon in the top right, and then
-navigating to **Pages**. Hit the **Remove pages** button and your Pages website
-will be deleted.
+navigating to **Pages**. Click the **Remove pages** button to delete your Pages
+website.
![Remove pages](img/remove_pages.png)
@@ -81,9 +81,9 @@ will be deleted.
When using Pages under the general domain of a GitLab instance (`*.example.io`),
you _cannot_ use HTTPS with sub-subdomains. That means that if your
username or group name contains a dot, for example `foo.bar`, the domain
-`https://foo.bar.example.io` will _not_ work. This is a limitation of the
-[HTTP Over TLS protocol](https://tools.ietf.org/html/rfc2818#section-3.1). HTTP pages will continue to work provided you
-don't redirect HTTP to HTTPS.
+`https://foo.bar.example.io` does _not_ work. This is a limitation of the
+[HTTP Over TLS protocol](https://tools.ietf.org/html/rfc2818#section-3.1).
+HTTP pages continue to work provided you don't redirect HTTP to HTTPS.
GitLab Pages [does **not** support group websites for subgroups](../../group/subgroups/index.md#limitations).
You can only create the highest-level group website.
@@ -130,11 +130,11 @@ See this document for a [step-by-step guide](getting_started/pages_from_scratch.
Remember that GitLab Pages are by default branch/tag agnostic and their
deployment relies solely on what you specify in `.gitlab-ci.yml`. You can limit
the `pages` job with the [`only` parameter](../../../ci/yaml/README.md#onlyexcept-basic),
-whenever a new commit is pushed to a branch that will be used specifically for
-your pages.
+whenever a new commit is pushed to a branch used specifically for your
+pages.
That way, you can have your project's code in the `master` branch and use an
-orphan branch (let's name it `pages`) that will host your static generator site.
+orphan branch (let's name it `pages`) to host your static generator site.
You can create a new empty branch like this:
@@ -142,9 +142,9 @@ You can create a new empty branch like this:
git checkout --orphan pages
```
-The first commit made on this new branch will have no parents and it will be
-the root of a new history totally disconnected from all the other branches and
-commits. Push the source files of your static generator in the `pages` branch.
+The first commit made on this new branch has no parents and is the root of a
+new history totally disconnected from all the other branches and commits.
+Push the source files of your static generator in the `pages` branch.
Below is a copy of `.gitlab-ci.yml` where the most significant line is the last
one, specifying to execute everything in the `pages` branch:
@@ -172,9 +172,9 @@ also includes `.gitlab-ci.yml`.
Most modern browsers support downloading files in a compressed format. This
speeds up downloads by reducing the size of files.
-Before serving an uncompressed file, Pages will check whether the same file
-exists with a `.br` or `.gz` extension. If it does, and the browser supports receiving
-compressed files, it will serve that version instead of the uncompressed one.
+Before serving an uncompressed file, Pages checks if the same file exists with
+a `.br` or `.gz` extension. If it does, and the browser supports receiving
+compressed files, it serves that version instead of the uncompressed one.
To take advantage of this feature, the artifact you upload to the Pages should
have this structure:
@@ -236,10 +236,10 @@ public/
```
Pages supports reaching each of these files through several different URLs. In
-particular, it will always look for an `index.html` file if the URL only
+particular, it always looks for an `index.html` file if the URL only
specifies the directory. If the URL references a file that doesn't exist, but
-adding `.html` to the URL leads to a file that *does* exist, it will be served
-instead. Here are some examples of what will happen given the above Pages site:
+adding `.html` to the URL leads to a file that *does* exist, it's served
+instead. Here are some examples of what happens given the above Pages site:
| URL path | HTTP response | File served |
| -------------------- | ------------- | ----------- |
@@ -275,7 +275,7 @@ to private, internal or public.
### Do I need to create a user/group website before creating a project website?
-No, you don't. You can create your project first and it will be accessed under
+No, you don't. You can create your project first and access it under
`http(s)://namespace.example.io/projectname`.
## Known issues
diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
index f2b75354bf8..b5932fc8766 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -61,7 +61,7 @@ might be slightly different. Follow the
```
Alternatively, you can register without adding an e-mail account,
- but you won't be notified about the certificate expiration's date:
+ but you aren't notified about the certificate expiration's date:
```shell
sudo certbot certonly -a manual -d example.com --register-unsafely-without-email
@@ -71,10 +71,10 @@ might be slightly different. Follow the
Read through CertBot's documentation on their
[command line options](https://certbot.eff.org/docs/using.html#certbot-command-line-options).
-1. You'll be prompted with a message to agree with their terms.
+1. You're prompted with a message to agree with their terms.
Press `A` to agree and `Y` to let they log your IP.
- CertBot will then prompt you with the following message:
+ CertBot then prompts you with the following message:
```shell
Create a file containing just this data:
@@ -88,7 +88,7 @@ might be slightly different. Follow the
Press Enter to Continue
```
-1. **Do not press Enter yet.** Let's Encrypt will need to verify your
+1. **Do not press Enter yet.** Let's Encrypt needs to verify your
domain ownership before issuing the certificate. To do so, create 3
consecutive directories under your website's root:
`/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP/`
@@ -103,11 +103,11 @@ might be slightly different. Follow the
`http://example.com/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP`
to allow Let's Encrypt to verify the ownership of your domain,
therefore, it needs to be part of the website content under the
- repo's [`public`](index.md#how-it-works) folder.
+ repository's [`public`](index.md#how-it-works) folder.
1. Add, commit, and push the file into your repository in GitLab. Once the pipeline
passes, press **Enter** on your terminal to continue issuing your
- certificate. CertBot will then prompt you with the following message:
+ certificate. CertBot then prompts you with the following message:
```shell
Waiting for verification...
@@ -157,7 +157,7 @@ valid certificates)**.
## Renewal
-Let's Encrypt certificates expire every 90 days and you'll have to
+Let's Encrypt certificates expire every 90 days and you must
renew them periodically. To renew all your certificates at once, run:
```shell
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
index 9d17277fe9e..a2a17a4f2ca 100644
--- a/doc/user/project/pages/pages_access_control.md
+++ b/doc/user/project/pages/pages_access_control.md
@@ -28,20 +28,20 @@ For a demonstration, see [Pages access controls](https://www.youtube.com/watch?v
with GitLab Pages, depending on your project's visibility:
- If your project is private:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - **Only project members**: Only project members are able to browse the website.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, is able to browse the website, no matter their project membership.
- If your project is internal:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership.
- - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - **Only project members**: Only project members are able to browse the website.
+ - **Everyone with access**: Everyone logged into GitLab is able to browse the website, no matter their project membership.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, is able to browse the website, no matter their project membership.
- If your project is public:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - **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**.
The next time someone tries to access your website and the access control is
-enabled, they will be presented with a page to sign into GitLab and verify they
+enabled, they're presented with a page to sign into GitLab and verify they
can access the website.
## Terminating a Pages session
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 9f849051f40..64be3182dab 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -9,8 +9,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Introduced in [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26672):
> once an action is executed, an alert appears when a quick action is successfully applied.
-> - In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877) and later, you can use
+> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877): you can use
> quick actions when updating the description of issues, epics, and merge requests.
+> - Introduced in [GitLab 13.8](https://gitlab.com/gitlab-org/gitlab/-/issues/292393): when you enter
+> `/` into a description or comment field, all available quick actions are displayed in a scrollable list.
+> - The rebase quick action was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49800) in GitLab 13.8.
Quick actions are textual shortcuts for common actions on issues, epics, merge requests,
and commits that are usually done by clicking buttons or dropdowns in the GitLab UI.
@@ -31,6 +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. |
| `/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)** |
@@ -56,6 +62,8 @@ 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. |
+| `/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)** |
| `/remove_child_epic <epic>` | | | ✓ | Remove child epic from `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). **(ULTIMATE)** |
@@ -78,7 +86,9 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/title <new title>` | ✓ | ✓ | ✓ | Change title. |
| `/todo` | ✓ | ✓ | ✓ | Add a to-do item. |
| `/unassign @user1 @user2` | ✓ | ✓ | | Remove specific assignees. **(STARTER)** |
-| `/unassign` | ✓ | ✓ | | Remove all assignees. |
+| `/unassign` | | ✓ | | Remove all assignees. |
+| `/unassign_reviewer @user1 @user2` | | ✓ | | Remove specific reviewers. **(STARTER)** |
+| `/unassign_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/index.md b/doc/user/project/releases/index.md
index 7b412270938..90d7ac0a3c2 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -200,7 +200,7 @@ If the job that's executing is within a freeze period, GitLab CI/CD creates an e
variable named `$CI_DEPLOY_FREEZE`.
To prevent the deployment job from executing, create a `rules` entry in your
-`gitlab-ci.yaml`, for example:
+`gitlab-ci.yml`, for example:
```yaml
deploy_to_production:
@@ -274,14 +274,11 @@ Release note descriptions are unrelated. Description supports [Markdown](../../m
### Release assets
-You can currently add the following types of assets to each release:
+You can add the following types of assets to each release:
- [Source code](#source-code)
- [Links](#links)
-GitLab will support more asset types in the future, including objects such
-as pre-built packages, compliance/security evidence, or container images.
-
#### Permanent links to release assets
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27300) in GitLab 12.9.
@@ -336,8 +333,8 @@ The four types of links are "Runbook," "Package," "Image," and "Other."
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) in GitLab 12.6.
Each time a release is created, GitLab takes a snapshot of data that's related to it.
-This data is saved in a JSON file and called *release evidence*. The feature currently
-includes test artifacts and linked milestones (and will include issues) to facilitate
+This data is saved in a JSON file and called *release evidence*. The feature
+includes test artifacts and linked milestones to facilitate
internal processes, like external audits.
To access the release evidence, on the Releases page, click the link to the JSON file that's listed
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index 75e1aea632f..f7da3629c23 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -34,10 +34,6 @@ Forking a project is, in most cases, a two-step process.
The fork is created. The permissions you have in the namespace are the permissions you will have in the fork.
WARNING:
-In GitLab 12.6 and later, when project owners [reduce a project's visibility](../../../public_access/public_access.md#reducing-visibility),
-it **removes the relationship** between a project and all its forks.
-
-WARNING:
When a public project with the repository feature set to "Members
only" is forked, the repository will be public in the fork. The owner
of the fork will need to manually change the visibility. This is being
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index e1d84baec4d..c4f5d330f63 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -31,7 +31,7 @@ that you [connect with GitLab via SSH](../../../ssh/README.md).
## Files
Use a repository to store your files in GitLab. In [GitLab 12.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33806),
-you'll see on the repository's file tree an icon next to the file name
+you'll see on the repository's file tree an icon next to the filename
according to its extension:
![Repository file icons](img/file_ext_icons_repo_v12_10.png)
@@ -236,18 +236,24 @@ lock your files to prevent any conflicting changes.
You can access your repositories via [repository API](../../../api/repositories.md).
-## Clone in Apple Xcode
+## Clone a repository
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0
+Learn how to [clone a repository through the command line](../../../gitlab-basics/start-using-git.md#clone-a-repository).
+
+Alternatively, clone directly into a code editor as documented below.
+
+### Clone to 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
-in Xcode using the new **Open in Xcode** button, located next to the Git URL
+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.
## Download Source Code
-> Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704) in GitLab 11.11.
-> Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
+> - Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704) in GitLab 11.11.
+> - Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
The source code stored in a repository can be downloaded from the UI.
By clicking the download icon, a dropdown will open with links to download the following:
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index 96694a9e954..4a7f75ba1ac 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -8,19 +8,16 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.htm
# Repository mirroring
Repository mirroring allows for mirroring of repositories to and from external sources. It can be
-used to mirror branches, tags, and commits between repositories.
+used to mirror branches, tags, and commits between repositories. It is useful when you want to use
+a repository outside of GitLab.
A repository mirror at GitLab will be updated automatically. You can also manually trigger an update
at most once every 5 minutes on GitLab.com with [the limit set by the administrator on self-managed instances](../../../administration/instance_limits.md#pull-mirroring-interval).
-## Overview
-
-Repository mirroring is useful when you want to use a repository outside of GitLab.
-
There are two kinds of repository mirroring supported by GitLab:
-- Push: for mirroring a GitLab repository to another location.
-- Pull: for mirroring a repository from another location to GitLab. **(STARTER)**
+- [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)**
When the mirror repository is updated, all new branches, tags, and commits will be visible in the
project's activity feed.
@@ -31,8 +28,7 @@ immediate update, unless:
- The mirror is already being updated.
- The [limit for pull mirroring interval seconds](../../../administration/instance_limits.md#pull-mirroring-interval) has not elapsed since its last update.
-For security reasons, in [GitLab 12.10 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27166),
-the URL to the original repository is only displayed to users with
+For security reasons, the URL to the original repository is only displayed to users with
Maintainer or Owner permissions to the mirrored project.
## Use cases
@@ -62,7 +58,8 @@ For an existing project, you can set up push mirroring as follows:
1. Navigate to your project's **Settings > Repository** and expand the **Mirroring repositories** section.
1. Enter a repository URL.
1. Select **Push** from the **Mirror direction** dropdown.
-1. Select an authentication method from the **Authentication method** dropdown, if necessary.
+1. Select an authentication method from the **Authentication method** dropdown.
+ You can authenticate with either a password or an [SSH key](#ssh-authentication).
1. Check the **Only mirror protected branches** box, if necessary.
1. Check the **Keep divergent refs** box, if desired.
1. Click the **Mirror repository** button to save the configuration.
@@ -88,17 +85,7 @@ section.
You can also create and modify project push mirrors through the
[remote mirrors API](../../../api/remote_mirrors.md).
-### Push only protected branches **(CORE)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3350) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
-> - [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) in 10.8.
-
-You can choose to only push your protected branches from GitLab to your remote repository.
-
-To use this option, check the **Only mirror protected branches** box when creating a repository
-mirror.
-
-### Keep divergent refs **(CORE)**
+### Keep divergent refs
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208828) in GitLab 13.0.
@@ -119,7 +106,7 @@ update.
NOTE:
After the mirror is created, this option can currently only be modified via the [API](../../../api/remote_mirrors.md).
-## Setting up a push mirror from GitLab to GitHub **(CORE)**
+### Setting up a push mirror from GitLab to GitHub
To set up a mirror from GitLab to GitHub, you need to follow these steps:
@@ -132,7 +119,7 @@ The mirrored repository will be listed. For example, `https://*****:*****@github
The repository will push soon. To force a push, click the **Update now** (**{retry}**) button.
-## Setting up a push mirror from GitLab to AWS CodeCommit
+### Setting up a push mirror from GitLab to AWS CodeCommit
AWS CodeCommit push mirroring is currently the best way to connect GitLab repositories to AWS CodePipeline, as GitLab is not yet supported as one of their Source Code Management (SCM) providers.
@@ -210,7 +197,7 @@ To test mirroring by forcing a push, click the half-circle arrows button (hover
If **Last successful update** shows a date, you have configured mirroring correctly.
If it is not working correctly a red `error` tag appears and shows the error message as hover text.
-## Setting up a push mirror to another GitLab instance with 2FA activated
+### Setting up a push mirror to another GitLab instance with 2FA activated
1. On the destination GitLab instance, create a [personal access token](../../profile/personal_access_tokens.md) with `write_repository` scope.
1. On the source GitLab instance:
@@ -249,8 +236,8 @@ To configure mirror pulling for an existing project:
![Repository mirroring pull settings screen - lower part](img/repository_mirroring_pull_settings_lower.png)
Because GitLab is now set to pull changes from the upstream repository, you should not push commits
-directly to the repository on GitLab. Instead, any commits should be pushed to the upstream repository.
-Changes pushed to the upstream repository will be pulled into the GitLab repository, either:
+directly to the repository on GitLab. Instead, any commits should be pushed to the remote repository.
+Changes pushed to the remote repository will be pulled into the GitLab repository, either:
- Automatically within a certain period of time.
- When a [forced update](#forcing-an-update) is initiated.
@@ -275,10 +262,62 @@ 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.
-### SSH authentication
+### Overwrite diverged branches **(STARTER)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+
+You can choose to always update your local branches with remote versions, even if they have
+diverged from the remote.
+
+WARNING:
+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)**
+
+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
+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)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
+
+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:
+
+- Project's main dashboard.
+- Pull mirror settings page.
+
+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)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
+
+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),
+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)**
+
+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.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551) for Pull mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) for Push mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6
+## 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.
SSH authentication is mutual:
@@ -367,50 +406,6 @@ NOTE:
The generated keys are stored in the GitLab database, not in the filesystem. Therefore,
SSH public key authentication for mirrors cannot be used in a pre-receive hook.
-### Overwrite diverged branches **(STARTER)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
-
-You can choose to always update your local branches with remote versions, even if they have
-diverged from the remote.
-
-WARNING:
-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.
-
-### Only mirror protected branches **(STARTER)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3326) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
-
-You can choose to pull mirror only the protected branches from your remote repository to GitLab.
-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.
-
-### Hard failure **(STARTER)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
-
-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:
-
-- Project's main dashboard.
-- Pull mirror settings page.
-
-When a project is hard failed, it will no longer get picked up for mirroring. A user can resume the
-project mirroring again by [Forcing an update](#forcing-an-update).
-
-### Trigger update using API **(STARTER)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
-
-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),
-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).
-
## Forcing an update **(CORE)**
While mirrors are scheduled to update automatically, you can always force an update by using the
@@ -429,10 +424,7 @@ bidirectional mirroring, you should prepare for the likely conflicts by deciding
them and how they will be resolved.
Rewriting any mirrored commit on either remote will cause conflicts and mirroring to fail. This can
-be prevented by:
-
-- [Pulling only protected branches](#only-mirror-protected-branches).
-- [Pushing only protected branches](#push-only-protected-branches).
+be prevented by [mirroring only protected branches](#mirror-only-protected-branches).
You should [protect the branches](../protected_branches.md) you wish to mirror on both
remotes to prevent conflicts caused by rewriting history.
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 24bfeee5e7f..b9477da3937 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -19,7 +19,7 @@ From a project's files page, click the '+' button to the right of the branch sel
Choose **New file** from the dropdown.
![New file dropdown menu](img/web_editor_new_file_dropdown.png)
-Enter a file name in the **Filename** box. Then, add file content in the editor
+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
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index 9d75c4ab071..c99b0d91523 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -34,7 +34,7 @@ Users with Reporter or higher [permissions](../../permissions.md) can create req
To create a requirement:
-1. From your project page, go to **Requirements**.
+1. In a project, go to **Requirements**.
1. Select **New requirement**.
1. Enter a title and description and select **Create requirement**.
@@ -200,10 +200,10 @@ requirements_confirmation:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/246857) in GitLab 13.7.
-You can import requirements to a project by uploading a CSV file with the columns
-`title` and `description`.
+You can import requirements to a project by uploading a [CSV file](https://en.wikipedia.org/wiki/Comma-separated_values)
+with the columns `title` and `description`.
-The user uploading the CSV file will be set as the author of the imported requirements.
+After the import, the user uploading the CSV file is set as the author of the imported requirements.
Users with Reporter or higher [permissions](../../permissions.md) can import requirements.
@@ -213,20 +213,20 @@ Before you import your file:
- Consider importing a test file containing only a few requirements. There is no way to undo a large
import without using the GitLab API.
-- Ensure your CSV file meets the [file format](#csv-file-format) requirements.
+- Ensure your CSV file meets the [file format](#imported-csv-file-format) requirements.
To import requirements:
-1. Navigate to a project's Requirements page.
- - If the project already has existing requirements, click the import icon (**{import}**) at the
+1. In a project, go to **Requirements**.
+ - If the project already has existing requirements, select the import icon (**{import}**) in the
top right.
- - For a project without any requirements, click **Import CSV** in the middle of the page.
-1. Select the file and click **Import requirements**.
+ - For a project without any requirements, select **Import CSV** in the middle of the page.
+1. Select the file and select **Import requirements**.
The file is processed in the background and a notification email is sent
to you after the import is complete.
-### CSV file format
+### Imported CSV file format
When importing requirements from a CSV file, it must be formatted in a certain way:
@@ -257,3 +257,37 @@ Another Title,"A description, with a comma"
The limit depends on the configuration value of Max Attachment Size for the GitLab instance.
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.
+
+You can export GitLab requirements to a
+[CSV file](https://en.wikipedia.org/wiki/Comma-separated_values) sent to your default notification
+email as an attachment.
+
+By exporting requirements, you and your team can import them into another tool or share them with
+your customers. Exporting requirements can aid collaboration with higher-level systems, as well as
+audit and regulatory compliance tasks.
+
+Users with Reporter or higher [permissions](../../permissions.md) can export requirements.
+
+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. Select **Export requirements**. The exported CSV file is sent to the email address associated with your user.
+
+### Exported CSV file format
+
+You can preview the exported CSV file in a spreadsheet editor, such as Microsoft Excel,
+OpenOffice Calc, or Google Sheets.
+
+The exported CSV file contains the following columns:
+
+- Requirement ID
+- Title
+- Description
+- Author Username
+- Latest Test Report State
+- Latest Test Report Created At (UTC)
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 4f3ca12c582..76156690fe7 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -10,32 +10,38 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [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.
-Service Desk is a module that allows your team to connect directly
-with any external party through email right inside of GitLab; no external tools required.
-An ongoing conversation right where your software is built ensures that user feedback ends
-up directly where it's needed, helping you build the right features to solve your users'
-real problems.
+Service Desk is a module that allows your team to connect
+with any external party through email, without any external tools.
+An ongoing conversation in the same place as where your software
+is built ensures user feedback ends up where it's needed.
-With Service Desk, you can provide efficient email support to your customers, who can now
-email you bug reports, feature requests, or general feedback that will all end up in your
-GitLab project as new issues. In turn, your team can respond straight from the project.
+With Service Desk, you can provide efficient email support to your customers. They can
+email you bug reports, feature requests, or general feedback. They all end up in your
+GitLab project as new issues. In turn, your team can respond directly from the project.
As Service Desk is built right into GitLab itself, the complexity and inefficiencies
-of multiple tools and external integrations are eliminated, significantly shortening
+of multiple tools and external integrations are eliminated. This significantly shortens
the cycle time from feedback to software update.
For an overview, check the video demonstration on [GitLab Service Desk](https://about.gitlab.com/blog/2017/05/09/demo-service-desk/).
-## Use cases
+## How it works
+
+GitLab Service Desk enables people to create issues in your
+GitLab instance without needing their own user account.
+
+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.
The codebase is hosted in your GitLab instance, built and deployed
with GitLab CI/CD.
-Here's how Service Desk will work for you:
+Here's how Service Desk works for you:
1. You provide a project-specific email address to your paying customers, who can email you directly
- from within the app.
+ from the application.
1. Each email they send creates an issue in the appropriate project.
1. Your team members navigate to the Service Desk issue tracker, where they can see new support
requests and respond inside associated issues.
@@ -43,61 +49,54 @@ Here's how Service Desk will work for you:
1. Your team starts working on implementing code to solve your customer's problem.
1. When your team finishes the implementation, whereupon the merge request is merged and the issue
is closed automatically.
-1. The customer will have been attended successfully via email, without having real access to your
+1. The customer's requests are handled through email, without ever having access to your
GitLab instance.
1. Your team saved time by not having to leave GitLab (or setup any integrations) to follow up with
your customer.
-## How it works
-
-GitLab Service Desk is a simple way to allow people to create issues in your
-GitLab instance without needing their own user account.
-
-It provides a unique email address for end users to create issues in a project,
-and replies can be sent either through the GitLab interface or by email. End
-users will only see the thread through email.
-
## 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.
-If you have project maintainer access you have the option to set up Service Desk.
-Follow these steps to do so:
+If you have project maintainer access you have the option to set up Service Desk. Follow these steps:
1. [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).
+ 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.
1. Enable the **Activate Service Desk** toggle. This reveals a unique email address to email issues
- to the project. These issues will be [confidential](issues/confidential_issues.md), so they will
- only be visible to project members. Note that in GitLab 11.7, we updated the generated email
+ 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.
WARNING:
- This email address can be used by anyone to create an issue on this project, whether or not they
- have access to your GitLab instance. We recommend **putting this behind an alias** so it can be
- changed if needed, and **[enabling Akismet](../../integration/akismet.md)** on your GitLab
+ 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.
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.
- ![Service Desk enabled](img/service_desk_enabled.png)
-
-Service Desk is now enabled for this project! You should be able to access it from your project
-navigation's **Issues** menu.
+Service Desk is now enabled for this project! You should be able to access it from your project's
+**Issues** menu.
![Service Desk Navigation Item](img/service_desk_nav_item.png)
### Using customized email templates
- > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7.
+> - [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.
+
+An email is sent to the author when:
-When a user submits a new issue using Service Desk, or when a new note is created on a Service Desk issue, an email is sent to the author.
+- 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/`
@@ -106,39 +105,46 @@ directory in your repository. Commit and push to your default branch.
#### Thank you email
The **Thank you email** is the email sent to a user after they submit an issue.
-The file name of the template has to be `thank_you.md`.
-You can use `%{ISSUE_ID}` placeholder which will be replaced by an issue IID in the email and
-`%{ISSUE_PATH}` placeholder which will be replaced by project path and the issue IID.
+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:
+
+- `%{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.
#### New note email
-The **New note email** is the email sent to a user when the issue they submitted has a new comment.
-The file name of the template has to be `new_note.md`.
-You can use `%{ISSUE_ID}` placeholder which will be replaced by an issue IID
-in the email, `%{ISSUE_PATH}` placeholder which will be replaced by
- project path and the issue IID and `%{NOTE_TEXT}` placeholder which will be replaced by the note text.
+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:
+
+- `%{ISSUE_ID}`: issue IID
+- `%{ISSUE_PATH}`: project path appended with the issue IID
+- `%{NOTE_TEXT}`: note text
### Using custom email display name
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7529) in GitLab 12.8.
-You can customize the email display name. Emails sent from Service Desk will have
+You can customize the email display name. Emails sent from Service Desk have
this name in the `From` header. The default display name is `GitLab Support Bot`.
-### Using custom email address **(CORE ONLY)**
+To edit the custom email display name:
+
+1. In a project, go to **Settings > General > Service Desk**.
+1. Enter a new name in **Email display name**.
+1. Select **Save Changes**.
+
+### Using custom email address
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
-> - It was [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) on GitLab 13.7.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-custom-email-address). **(CORE ONLY)**
-
-If the `service_desk_email` feature flag is enabled in your configuration,
-then it's possible to create Service Desk issues by sending emails to the
-custom Service Desk email address, which should have the following format:
+> - [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
+issues by sending emails to the Service Desk email address. The default
+address has the following format:
`project_contact+%{key}@example.com`.
The `%{key}` part is used to find the project where the issue should be created. The
@@ -148,53 +154,57 @@ The `%{key}` part is used to find the project where the issue should be created.
You can set the project name suffix in your project's Service Desk settings.
It can contain only lowercase letters (`a-z`), numbers (`0-9`), or underscores (`_`).
-![Setting custom Service Desk email address](img/service_desk_custom_email_address_v13_0.png)
+NOTE:
+The `service_desk_email` and `incoming_email` configurations should
+always use separate mailboxes. This is important, because emails picked from
+`service_desk_email` mailbox are processed by a different worker and it would
+not recognize `incoming_email` emails.
-You can add the following snippets to your configuration.
+To configure a custom email address for Service Desk, add the following snippets to your configuration file:
-Example for installations from source:
+- Example for installations from source:
-```yaml
-service_desk_email:
- enabled: true
- address: "project_contact+%{key}@example.com"
- user: "project_support@example.com"
- password: "[REDACTED]"
- host: "imap.gmail.com"
- port: 993
- ssl: true
- start_tls: false
- log_path: "log/mailroom.log"
- mailbox: "inbox"
- idle_timeout: 60
- expunge_deleted: true
-```
+ ```yaml
+ service_desk_email:
+ enabled: true
+ address: "project_contact+%{key}@example.com"
+ user: "project_support@example.com"
+ password: "[REDACTED]"
+ host: "imap.gmail.com"
+ port: 993
+ ssl: true
+ start_tls: false
+ log_path: "log/mailroom.log"
+ mailbox: "inbox"
+ idle_timeout: 60
+ expunge_deleted: true
+ ```
-Example for Omnibus GitLab installations:
+- Example for Omnibus GitLab installations:
-```ruby
-gitlab_rails['service_desk_email_enabled'] = true
+ ```ruby
+ gitlab_rails['service_desk_email_enabled'] = true
-gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com"
+ gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com"
-gitlab_rails['service_desk_email_email'] = "project_support@gmail.com"
+ gitlab_rails['service_desk_email_email'] = "project_support@gmail.com"
-gitlab_rails['service_desk_email_password'] = "[REDACTED]"
+ gitlab_rails['service_desk_email_password'] = "[REDACTED]"
-gitlab_rails['service_desk_email_mailbox_name'] = "inbox"
+ gitlab_rails['service_desk_email_mailbox_name'] = "inbox"
-gitlab_rails['service_desk_email_idle_timeout'] = 60
+ gitlab_rails['service_desk_email_idle_timeout'] = 60
-gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log"
+ gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log"
-gitlab_rails['service_desk_email_host'] = "imap.gmail.com"
+ gitlab_rails['service_desk_email_host'] = "imap.gmail.com"
-gitlab_rails['service_desk_email_port'] = 993
+ gitlab_rails['service_desk_email_port'] = 993
-gitlab_rails['service_desk_email_ssl'] = true
+ gitlab_rails['service_desk_email_ssl'] = true
-gitlab_rails['service_desk_email_start_tls'] = false
-```
+ gitlab_rails['service_desk_email_start_tls'] = false
+ ```
In this case, suppose the `mygroup/myproject` project Service Desk settings has the project name
suffix set to `support`, and a user sends an email to `project_contact+mygroup-myproject-support@example.com`.
@@ -203,27 +213,10 @@ As a result, a new Service Desk issue is created from this email in the `mygroup
The configuration options are the same as for configuring
[incoming email](../../administration/incoming_email.md#set-it-up).
-#### Disable custom email address **(CORE ONLY)**
-
-Service Desk custom email 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(:service_desk_custom_address)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:service_desk_custom_address)
-```
-
## Using Service Desk
+There are a few ways Service Desk can be used.
+
### As an end user (issue creator)
To create a Service Desk issue, an end user does not need to know anything about
@@ -235,29 +228,30 @@ receive an email back confirming receipt:
This also gives the end user an option to unsubscribe.
If they don't choose to unsubscribe, then any new comments added to the issue
-will be sent as emails:
+are sent as emails:
![Service Desk reply email](img/service_desk_reply.png)
-And any responses they send will be displayed in the issue itself.
+Any responses they send via email are displayed in the issue itself.
### As a responder to the issue
-For responders to the issue, everything works as usual. They will see a familiar looking
-issue tracker, where they can see issues created via customer support requests and
-filter and interact with them just like other GitLab issues.
+For responders to the issue, everything works just like other GitLab issues.
+GitLab displays a familiar-looking issue tracker where responders can see
+issues created through customer support requests, and filter or interact with them.
![Service Desk Issue tracker](img/service_desk_issue_tracker.png)
-Messages from the end user will show as coming from the special Support Bot user, but apart from that,
-you can read and write comments as you normally do:
+Messages from the end user are shown as coming from the special
+[Support Bot user](../../subscriptions/self_managed/index.md#billable-users).
+You can read and write comments as you normally do in GitLab:
![Service Desk issue thread](img/service_desk_thread.png)
Note that:
- The project's visibility (private, internal, public) does not affect Service Desk.
-- The path to the project, including its group or namespace, will be shown on emails.
+- The path to the project, including its group or namespace, are shown in emails.
### Support Bot user
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 53233cc347e..27727890383 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -179,7 +179,7 @@ If use of the `Internal` visibility level
all imported projects are given the visibility of `Private`.
NOTE:
-The maximum import file size can be set by the Administrator, default is 50MB.
+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).
### Project import status
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 41f404de4f2..26ef5e2260a 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -52,10 +52,6 @@ If you set **Project Visibility** to public, you can limit access to some featur
to **Only Project Members**. In addition, you can select the option to
[Allow users to request access](../members/index.md#project-membership-and-requesting-access).
-WARNING:
-If you [reduce a project's visibility level](../../../public_access/public_access.md#reducing-visibility),
-that action unlinks all forks of that project.
-
Use the switches to enable or disable the following features:
| Option | More access limit options | Description |
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index 494f0b725e3..39de9ab9ca2 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -38,8 +38,10 @@ For examples of how you can use a project access token to authenticate with the
## Project bot users
-For each project access token created, a bot user will also be created and added to the project with
-["Maintainer" level permissions](../../permissions.md#project-members-permissions).
+Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users) and do not count as licensed seats.
+
+For each project access token created, a bot user is created and added to the project with
+[Maintainer level permissions](../../permissions.md#project-members-permissions).
For the bot:
@@ -49,15 +51,15 @@ For the bot:
API calls made with a project access token are associated with the corresponding bot user.
-These users will appear in **Members** but can not be modified.
-Furthermore, the bot user can not be added to any other project.
+These bot users are included in a project's **Members** list but cannot be modified. Also, a bot
+user cannot be added to any other project.
- The username is set to `project_{project_id}_bot` for the first access token, such as `project_123_bot`.
- The username is set to `project_{project_id}_bot{bot_count}` for further access tokens, such as `project_123_bot1`.
-When the project access token is [revoked](#revoking-a-project-access-token) the bot user is then deleted and all records are moved to a system-wide user with the username "Ghost User". For more information, see [Associated Records](../../profile/account/delete_account.md#associated-records).
-
-Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users) and do not count as licensed seats.
+When the project access token is [revoked](#revoking-a-project-access-token) the bot user is deleted
+and all records are moved to a system-wide user with the username "Ghost User". For more
+information, see [Associated Records](../../profile/account/delete_account.md#associated-records).
## Revoking a project access token
@@ -72,7 +74,7 @@ the following table.
| Scope | Description |
| ------------------ | ----------- |
-| `api` | Grants complete read/write access to the scoped project API, including the Package Registry](../../packages/package_registry/index.md). |
+| `api` | Grants complete read/write access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). |
| `read_api` | Grants read access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). |
| `read_registry` | Allows read-access (pull) to [container registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. |
| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). |
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 29b24028e48..af8e78afb28 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -33,8 +33,8 @@ start seeing results.
## Command palette
You can see all available commands for manipulating editor content by pressing
-the <kbd>F1</kbd> key when the editor is in focus. After that,
-you'll see a complete list of available commands for
+the <kbd>F1</kbd> key when the editor is in focus. After that, the editor displays
+a complete list of available commands for
manipulating editor content. The editor supports commands for multi-cursor
editing, code block folding, commenting, searching and replacing, navigating
editor warnings and suggestions, and more.
@@ -47,7 +47,7 @@ the command without having to select it in the command palette.
## Syntax highlighting
-As expected from an IDE, syntax highlighting for many languages within
+As expected from an IDE, syntax highlighting for many languages in
the Web IDE makes your direct editing even easier.
The Web IDE currently provides:
@@ -78,7 +78,7 @@ All the themes GitLab supports for syntax highlighting are added to the Web IDE'
You can pick a theme from your [profile preferences](../../profile/preferences.md).
The themes are available only in the Web IDE file editor, except for the [dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/209808) and
-the [solarized dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/219228),
+the [Solarized dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/219228),
which apply to the entire Web IDE screen.
| Solarized Light Theme | Solarized Dark Theme | Dark Theme |
@@ -144,12 +144,13 @@ schemas:
Each schema entry supports two properties:
-- `uri`: please provide an absolute URL for the schema definition file here. The schema from this URL
-is loaded when a matching file is open.
-- `match`: a list of matching paths or glob expressions. If a schema matches a particular path pattern,
-it will be applied to that file. Please enclose the pattern in quotes if it begins with an asterisk (`*`),
-it's be applied to that file. If a pattern begins with an asterisk (`*`), enclose it in quotation
-marks. Otherwise, the configuration file is not valid YAML.
+- `uri`: please provide an absolute URL for the schema definition file here.
+ The schema from this URL is loaded when a matching file is open.
+- `match`: a list of matching paths or glob expressions. If a schema matches a
+ particular path pattern, it is applied to that file. Please enclose the pattern
+ in quotes if it begins with an asterisk (`*`), it's be applied to that file.
+ If a pattern begins with an asterisk (`*`), enclose it in quotation marks.
+ Otherwise, the configuration file is not valid YAML.
## Configure the Web IDE
@@ -180,7 +181,7 @@ The Web IDE currently supports the following `.editorconfig` settings:
After making your changes, click the **Commit** button on the bottom-left to
review the list of changed files.
-Once you have finalized your changes, you can add a commit message, commit the
+After you have finalized your changes, you can add a commit message, commit the
changes and directly create a merge request. In case you don't have write
access to the selected branch, you see a warning, but can still create
a new branch and start a merge request.
@@ -268,7 +269,7 @@ GitLab.com
![Administrator Live Preview setting](img/admin_live_preview_v13_0.png)
-Once you have done that, you can preview projects with a `package.json` file and
+After you have done that, you can preview projects with a `package.json` file and
a `main` entry point inside the Web IDE. An example `package.json` is shown
below.
@@ -325,7 +326,7 @@ In order to enable the Web IDE terminals you need to create the file
file is fairly similar to the [CI configuration file](../../../ci/yaml/README.md)
syntax but with some restrictions:
-- No global blocks can be defined (i.e., `before_script` or `after_script`)
+- No global blocks (such as `before_script` or `after_script`) can be defined.
- Only one job named `terminal` can be added to this file.
- Only the keywords `image`, `services`, `tags`, `before_script`, `script`, and
`variables` are allowed to be used to configure the job.
@@ -350,7 +351,7 @@ terminal:
NODE_ENV: "test"
```
-Once the terminal has started, the console is displayed and we could access
+After the terminal has started, the console is displayed and we could access
the project repository files.
**Important**. The terminal job is branch dependent. This means that the
@@ -364,7 +365,7 @@ If there is no configuration file in a branch, an error message is shown.
If Interactive Terminals are available for the current user, the **Terminal** button is visible in the right sidebar of the Web IDE. Click this button to open
or close the terminal tab.
-Once open, the tab shows the **Start Web Terminal** button. This button may
+After opening, the tab shows the **Start Web Terminal** button. This button may
be disabled if the environment is not configured correctly. If so, a status
message describes the issue. Here are some reasons why **Start Web Terminal**
may be disabled:
@@ -378,7 +379,7 @@ can be closed and reopened and the state of the terminal is not affected.
When the terminal is started and is successfully connected to the runner, then the
runner's shell prompt appears in the terminal. From here, you can enter
-commands executed within the runner's environment. This is similar
+commands executed in the runner's environment. This is similar
to running commands in a local terminal or through SSH.
While the terminal is running, it can be stopped by clicking **Stop Terminal**.
@@ -426,7 +427,7 @@ terminal:
[predefined environment variable](../../../ci/variables/predefined_variables.md)
for GitLab Runners. This is where your project's repository resides.
-Once you have configured the web terminal for file syncing, then when the web
+After you have configured the web terminal for file syncing, then when the web
terminal is started, a **Terminal** status is visible in the status bar.
![Web IDE Client Side Evaluation](img/terminal_status.png)
@@ -434,7 +435,7 @@ terminal is started, a **Terminal** status is visible in the status bar.
Changes made to your files via the Web IDE sync to the running terminal
when:
-- <kbd>Ctrl</kbd> + <kbd>S</kbd> (or <kbd>Cmd</kbd> + <kbd>S</kbd> on Mac)
+- <kbd>Control</kbd> + <kbd>S</kbd> (or <kbd>Command</kbd> + <kbd>S</kbd> on Mac)
is pressed while editing a file.
- Anything outside the file editor is clicked after editing a file.
- A file or folder is created, deleted, or renamed.
@@ -446,7 +447,7 @@ The Web IDE has a few limitations:
- Interactive Terminals is in a beta phase and continues to be improved in upcoming releases. In the meantime, please note that the user is limited to having only one
active terminal at a time.
-- LFS files can be rendered and displayed but they cannot be updated and committed using the Web IDE. If an LFS file is modified and pushed to the repository, the LFS pointer in the repository will be overwritten with the modified LFS file content.
+- LFS files can be rendered and displayed but they cannot be updated and committed using the Web IDE. If an LFS file is modified and pushed to the repository, the LFS pointer in the repository is overwritten with the modified LFS file content.
### Troubleshooting
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 7802f2ba95e..779179a6665 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -204,13 +204,11 @@ otherwise they will not display when pushed to GitLab:
## Customizing sidebar
-On the project's Wiki page, there is a right side navigation that renders the full Wiki pages list by default, with hierarchy.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23109) in GitLab 13.8, the sidebar can be customized by clicking the **Edit sidebar** button.
-To customize the sidebar, you can create a file named `_sidebar` to fully replace the default navigation.
+To customize the Wiki's navigation sidebar, you need Developer permissions to the project.
-WARNING:
-Unless you link the `_sidebar` file from your custom nav, to edit it you'll have to access it directly
-from the browser's address bar by typing: `https://gitlab.com/<namespace>/<project_name>/-/wikis/_sidebar` (for self-managed GitLab instances, replace `gitlab.com` with your instance's URL).
+On the top-right, click **Edit sidebar** and make your changes. This creates a wiki page named `_sidebar` which fully replaces the default sidebar navigation.
Example for `_sidebar` (using Markdown format):
diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md
index fe2371947b4..e3501be8e8e 100644
--- a/doc/user/search/advanced_search_syntax.md
+++ b/doc/user/search/advanced_search_syntax.md
@@ -52,14 +52,17 @@ The Advanced Search Syntax also supports the use of filters. The available filte
- blob: Filters by Git `object ID`. Exact match only.
To use them, add them to your keyword in the format `<filter_name>:<value>` without
-any spaces between the colon (`:`) and the value. A keyword or an asterisk (`*`) is required for filter searches and has to be added in front of the filter separated by a space.
+any spaces between the colon (`:`) and the value. When no keyword is provided, an asterisk (`*`) will be used as the keyword.
Examples:
- Finding a file with any content named `search_results.rb`: [`* filename:search_results.rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=*+filename%3Asearch_results.rb&group_id=9970&project_id=278964)
-- Finding a file named `found_blob_spec.rb` with the text `CHANGELOG` inside of it: [`CHANGELOG filename:found_blob_spec.rb](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=CHANGELOG+filename%3Afound_blob_spec.rb&group_id=9970&project_id=278964)
+- The leading asterisk (`*`) can be ignored in the case above: [`filename:search_results.rb`](https://gitlab.com/search?group_id=9970&project_id=278964&scope=blobs&search=filename%3Asearch_results.rb)
+- Finding a file named `found_blob_spec.rb` with the text `CHANGELOG` inside of it: [`CHANGELOG filename:found_blob_spec.rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=CHANGELOG+filename%3Afound_blob_spec.rb&group_id=9970&project_id=278964)
- Finding the text `EpicLinks` inside files with the `.rb` extension: [`EpicLinks extension:rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=EpicLinks+extension%3Arb&group_id=9970&project_id=278964)
+- Finding any file with the `.yaml` extension: [`extension:yaml`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=extension%3Ayaml&group_id=9970&project_id=278964)
- Finding the text `Sidekiq` in a file, when that file is in a path that includes `elastic`: [`Sidekiq path:elastic`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=Sidekiq+path%3Aelastic&group_id=9970&project_id=278964)
+- Finding any file in a path that includes `elasticsearch`: [`path:elasticsearch`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=path%3Aelasticsearch&group_id=9970&project_id=278964)
- Finding the files represented by the Git object ID `998707b421c89bd9a3063333f9f728ef3e43d101`: [`* blob:998707b421c89bd9a3063333f9f728ef3e43d101`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=false&scope=blobs&repository_ref=&search=*+blob%3A998707b421c89bd9a3063333f9f728ef3e43d101&group_id=9970)
- Syntax filters can be combined for complex filtering. Finding any file starting with `search` containing `eventHub` and with the `.js` extension: [`eventHub filename:search* extension:js`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=eventHub+filename%3Asearch*+extension%3Ajs&group_id=9970&project_id=278964)
diff --git a/doc/user/search/img/project_search_general_settings_v13_8.png b/doc/user/search/img/project_search_general_settings_v13_8.png
new file mode 100644
index 00000000000..08395e0d4f9
--- /dev/null
+++ b/doc/user/search/img/project_search_general_settings_v13_8.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 8c3d941192c..d229c27b608 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -18,7 +18,7 @@ The number displayed on their right represents the number of issues and merge re
![issues and MRs dashboard links](img/dashboard_links.png)
-When you click **Issues**, you'll see the opened issues assigned to you straight away:
+When you click **Issues**, the opened issues assigned to you are shown straight away:
![Issues assigned to you](img/issues_assigned_to_you.png)
@@ -29,14 +29,18 @@ You can also filter the results using the search and filter field, as described
### Issues and MRs assigned to you or created by you
-You'll also find shortcuts to issues and merge requests created by you or assigned to 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:
![shortcut to your issues and merge requests](img/issues_mrs_shortcut.png)
### Filtering issue and merge request lists
-Follow these steps to filter the **Issues** and **Merge Requests** list pages within projects and
+> - 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.
+
+Follow these steps to filter the **Issues** and **Merge Requests** list pages in projects and
groups:
1. Click in the field **Search or filter results...**.
@@ -44,15 +48,12 @@ groups:
- Author
- Assignee
- [Milestone](../project/milestones/index.md)
- - [Iteration](../group/iterations/index.md) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)
+ - [Iteration](../group/iterations/index.md)
- Release
- [Label](../project/labels.md)
- My-reaction
- Confidential
- - Epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9),
- including [child epic](../group/epics/index.md#multi-level-child-epics)
- ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in
- [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0)
+ - [Epic and child Epic](../group/epics/index.md) (available only for the group the Epic was created, not for [higher group levels](https://gitlab.com/gitlab-org/gitlab/-/issues/233729)).
- Search for this text
1. Select or type the operator to use for filtering the attribute. The following operators are
available:
@@ -73,7 +74,7 @@ Some filter fields like milestone and assignee, allow you to filter by **None**
![filter by none any](img/issues_filter_none_any.png)
-Selecting **None** returns results that have an empty value for that field. E.g.: no milestone, no assignee.
+Selecting **None** returns results that have an empty value for that field. For example: no milestone, no assignee.
Selecting **Any** does the opposite. It returns results that have a non-empty value for that field.
@@ -82,11 +83,11 @@ Selecting **Any** does the opposite. It returns results that have a non-empty va
You can filter issues and merge requests by specific terms included in titles or descriptions.
- Syntax
- - Searches look for all the words in a query, in any order. E.g.: searching
- issues for `display bug` will return all issues matching both those words, in any order.
+ - Searches look for all the words in a query, in any order. For example: searching
+ issues for `display bug` returns all issues matching both those words, in any order.
- To find the exact term, use double quotes: `"display bug"`
- Limitation
- - For performance reasons, terms shorter than 3 chars are ignored. E.g.: searching
+ - For performance reasons, terms shorter than 3 chars are ignored. For example: searching
issues for `included in titles` is same as `included titles`
- Search is limited to 4096 characters and 64 terms per query.
@@ -118,6 +119,13 @@ 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)**
+
+> [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)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6.
@@ -149,7 +157,7 @@ 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'll need to type at
+issues that have the assignee "Simone Presley", you must type at
least "Sim" before autocomplete gives any relevant results.
## Search history
@@ -162,11 +170,11 @@ You can view recent searches by clicking on the little arrow-clock icon, which i
Individual filters can be removed by clicking on the filter's (x) button or backspacing. The entire search filter can be cleared by clicking on the search box's (x) button or via <kbd>⌘</kbd> (Mac) + <kbd>⌫</kbd>.
-To delete filter tokens one at a time, the <kbd>⌥</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>⌫</kbd> keyboard combination can be used.
+To delete filter tokens one at a time, the <kbd>⌥</kbd> (Mac) / <kbd>Control</kbd> + <kbd>⌫</kbd> keyboard combination can be used.
## 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 will only include 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)
@@ -182,7 +190,7 @@ author, type, and action. Also, you can sort them by
You can search through your projects from the left menu, by clicking the menu bar, then **Projects**.
On the field **Filter by name**, type the project or group name you want to find, and GitLab
-will filter them for you as you type.
+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,
@@ -199,7 +207,7 @@ Similarly to [projects search](#projects), you can search through your groups fr
the left menu, by clicking the menu bar, then **Groups**.
On the field **Filter by name**, type the group name you want to find, and GitLab
-will filter them for you as you type.
+filters them for you as you type.
You can also **Explore** all public and internal groups available in GitLab.com,
and sort them by **Last created**, **Oldest created**, **Last updated**, or **Oldest updated**.
@@ -211,15 +219,15 @@ You can also filter them by name (issue title), from the field **Filter by name*
When you want 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'll be able to, besides filtering them by **Name**, **Author**, **Assignee**, **Milestone**,
+you can, besides filtering them by **Name**, **Author**, **Assignee**, **Milestone**,
and **Labels**, select multiple issues to add to a list of your choice:
![search and select issues to add to board](img/search_issues_board.png)
## Shortcut
-You'll find 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 within that project:
+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:
![search per project - shortcut](img/project_search.png)
@@ -234,12 +242,12 @@ You can also type in this search bar to see autocomplete suggestions for:
- Recently viewed issues (try and type some word from the title of a recently viewed issue)
- Recently viewed merge requests (try and type some word from the title of a recently viewed merge request)
- Recently viewed epics (try and type some word from the title of a recently viewed epic)
-- [GitLab Flavored Markdown](../markdown.md#special-gitlab-references) (GFM) for issues within a project (try and type a GFM reference for an issue)
+- [GitLab Flavored Markdown](../markdown.md#special-gitlab-references) (GFM) for issues in a project (try and type a GFM reference for an issue)
## Basic search
The Basic search in GitLab is a global search service that allows you to search
-across the entire GitLab instance, within a group, or a single project. Basic search is
+across the entire GitLab instance, in a group, or in a single project. Basic search is
backed by the database and allows searching in:
- Projects
@@ -254,12 +262,12 @@ backed by the database and allows searching in:
- Wiki (Project only)
To start a search, type into the search bar on the top-right of the screen. You can always search
-in all GitLab and may also see the options to search within a group or project if you are in the
+in all GitLab and may also see the options to search in a group or project if you are in the
group or project dashboard.
![basic search](img/basic_search.png)
-Once the results are returned, you can modify the search, select a different type of data to
+After the results are returned, you can modify the search, select a different type of data to
search, or choose a specific group or project.
![basic_search_results](img/basic_search_results.png)
@@ -274,11 +282,11 @@ the search field on the top-right of your screen while the project page is open.
### SHA search
-You can quickly access a commit from within the project dashboard by entering the SHA
-into the search field on the top right of the screen. If a single result is found, you will be
+You can quickly access a commit from the project dashboard by entering the SHA
+into the search field on the top right of the screen. If a single result is found, you are
redirected to the commit result and given the option to return to the search results page.
-![project sha search redirect](img/project_search_sha_redirect.png)
+![project SHA search redirect](img/project_search_sha_redirect.png)
## Advanced Search **(STARTER)**
@@ -292,3 +300,39 @@ GitLab instance.
Use advanced queries for more targeted search results.
[Learn how to use the Advanced Search Syntax.](advanced_search_syntax.md)
+
+## Search project settings
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8.
+> - 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)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+You can search inside the project’s settings sections by entering a search
+term in the search box located at the top of the page. The search results
+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)**
+
+Search project settings 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(:search_settings_in_page)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:search_settings_in_page)
+```
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index 33aa0bd253b..af499221da6 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -53,7 +53,7 @@ From there, add the **Title**, **Description**, and a **File** name with the
appropriate extension (for example, `example.rb`, `index.html`).
WARNING:
-Make sure to add the file name to get code highlighting and to avoid this
+Make sure to add the filename to get code highlighting and to avoid this
[copy-pasting bug](https://gitlab.com/gitlab-org/gitlab/-/issues/22870).
## Versioned Snippets
@@ -69,10 +69,10 @@ 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 will be automatically migrated in 13.0. Their current
-content will be saved as the initial commit to the snippets' repository.
+Existing snippets are automatically migrated in 13.0. Their current
+content is saved as the initial commit to the snippets' repository.
-### File names
+### Filenames
Snippets support syntax highlighting based on the filename and
extension provided for them. While it is possible to submit a snippet
@@ -86,10 +86,10 @@ number increases incrementally when more snippets without an attributed
filename are added.
When upgrading from an earlier version of GitLab to 13.0, existing snippets
-without a supported filename will be renamed to a compatible format. For
-example, if the snippet's filename is `http://a-weird-filename.me` it will
-be changed to `http-a-weird-filename-me` to be included in the snippet's
-repository. As snippets are stored by ID, changing their filenames will not break
+without a supported filename are renamed to a compatible format. For
+example, if the snippet's filename is `http://a-weird-filename.me` it is
+changed to `http-a-weird-filename-me` to be included in the snippet's
+repository. As snippets are stored by ID, changing their filenames breaks
direct or embedded links to the snippet.
### Multiple files by Snippet
@@ -105,8 +105,8 @@ to a certain context. For example:
- 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.
-Snippets support between 1 and 10 files. They can be managed via Git (since they're [versioned](#versioned-snippets)
-by a Git repository), through the [Snippets API](../api/snippets.md), or within the GitLab UI.
+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.
![Multi-file Snippet](img/gitlab_snippet_v13_5.png)
@@ -122,7 +122,7 @@ To delete a file from your snippet through the GitLab UI:
1. Go to your snippet in the GitLab UI.
1. Click **Edit** in the top right.
-1. Select **Delete file** alongside the file name of each file
+1. Select **Delete file** alongside the filename of each file
you wish to delete.
1. Click **Save changes**.
@@ -139,7 +139,7 @@ master branch.
### Reduce snippets repository size
-Since versioned Snippets are considered as part of the [namespace storage size](../user/admin_area/settings/account_and_limit_settings.md),
+Because versioned Snippets are considered as part of the [namespace storage size](../user/admin_area/settings/account_and_limit_settings.md),
it's recommended to keep snippets' repositories as compact as possible.
For more information about tools to compact repositories,
@@ -151,7 +151,7 @@ see the documentation on [reducing repository size](../user/project/repository/r
- 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 will result in an error.
+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.
@@ -187,9 +187,9 @@ facilitating the collaboration among users.
You can download the raw content of a snippet.
-By default snippets will be downloaded with Linux-style line endings (`LF`). If
+By default snippets are downloaded with Linux-style line endings (`LF`). If
you want to preserve the original line endings you need to add a parameter `line_ending=raw`
-(e.g., `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw`). In case a
+(For example: `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw`). In case a
snippet was created using the GitLab web interface the original line ending is Windows-like (`CRLF`).
## Embedded snippets
@@ -207,7 +207,7 @@ To embed a snippet, first make sure that:
- In **Project > Settings > Permissions**, the snippets permissions are
set to **Everyone with access**
-Once the above conditions are met, the "Embed" section will appear in your
+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.
@@ -221,6 +221,6 @@ Here's how 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 file name if it's defined,
+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.
diff --git a/doc/user/todos.md b/doc/user/todos.md
index 7d5a66a1632..27a849719c5 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -72,7 +72,7 @@ prevent data loss, in the case where a user's access is accidentally revoked.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) in GitLab 9.0.
-If you're mentioned at the start of a line, the to-do item you receive is
+If you're mentioned at the start of a line, the to-do item you receive is
listed as *directly addressed*. For example, in the following comment:
```markdown
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 5f637c8d5cb..8662efc03a7 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -22,7 +22,6 @@ To help manage storage, a namespace's owner can view:
- Total storage used in the namespace
- Total storage used per project
-- Breakdown of storage use per project, by storage type.
To view storage usage, from the namespace's page go to **Settings > Usage Quotas** and select the
**Storage** tab. The Usage Quotas statistics are updated every 90 minutes.
diff --git a/fixtures/lib/gitlab/graphql/queries/author.fragment.graphql b/fixtures/lib/gitlab/graphql/queries/author.fragment.graphql
new file mode 100644
index 00000000000..a10af1b3217
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/author.fragment.graphql
@@ -0,0 +1,4 @@
+fragment AuthorF on Author {
+ name
+ handle
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/bad.fragment.graphql b/fixtures/lib/gitlab/graphql/queries/bad.fragment.graphql
new file mode 100644
index 00000000000..00d868792d2
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/bad.fragment.graphql
@@ -0,0 +1,4 @@
+fragment BadF on Blog {
+ wibble
+ wobble
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/bad_argument.graphql b/fixtures/lib/gitlab/graphql/queries/bad_argument.graphql
new file mode 100644
index 00000000000..0b704d717dd
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/bad_argument.graphql
@@ -0,0 +1,5 @@
+query($bad: String) {
+ blog(title: $bad) {
+ description
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/client.query.graphql b/fixtures/lib/gitlab/graphql/queries/client.query.graphql
new file mode 100644
index 00000000000..dabe9735064
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/client.query.graphql
@@ -0,0 +1,3 @@
+query {
+ thingy @client
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/client_unused_fragment.graphql b/fixtures/lib/gitlab/graphql/queries/client_unused_fragment.graphql
new file mode 100644
index 00000000000..2beba1812c9
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/client_unused_fragment.graphql
@@ -0,0 +1,7 @@
+#import "./thingy.fragment.graphql"
+
+query($slug: String!, $foo: String) {
+ thingy(someArg: $foo) @client {
+ ...ThingyF
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/connection.query.graphql b/fixtures/lib/gitlab/graphql/queries/connection.query.graphql
new file mode 100644
index 00000000000..eec3f9b867b
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/connection.query.graphql
@@ -0,0 +1,9 @@
+query($slug: String!) {
+ post(slug: $slug) {
+ author {
+ posts @connection(key: "posts") {
+ title
+ }
+ }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/deeply/nested/bad_import.graphql b/fixtures/lib/gitlab/graphql/queries/deeply/nested/bad_import.graphql
new file mode 100644
index 00000000000..2a83b9dd42c
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/deeply/nested/bad_import.graphql
@@ -0,0 +1,7 @@
+# import "../author.fragment.graphql"
+
+query($slug: String!) {
+ post(slug: $slug) {
+ author { ...AuthorF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/deeply/nested/query.graphql b/fixtures/lib/gitlab/graphql/queries/deeply/nested/query.graphql
new file mode 100644
index 00000000000..451d3c25f25
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/deeply/nested/query.graphql
@@ -0,0 +1,7 @@
+# import "../../author.fragment.graphql"
+
+query($slug: String!) {
+ post(slug: $slug) {
+ author { ...AuthorF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/duplicate_imports.graphql b/fixtures/lib/gitlab/graphql/queries/duplicate_imports.graphql
new file mode 100644
index 00000000000..de3ac9fa833
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/duplicate_imports.graphql
@@ -0,0 +1,10 @@
+# import "./author.fragment.graphql"
+# import "./post.fragment.graphql"
+
+query($title: String!) {
+ blog(title: $title) {
+ description
+ mainAuthor { ...AuthorF }
+ posts { ...PostF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/ee/author.fragment.graphql b/fixtures/lib/gitlab/graphql/queries/ee/author.fragment.graphql
new file mode 100644
index 00000000000..884b683c563
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/ee/author.fragment.graphql
@@ -0,0 +1,5 @@
+fragment AuthorF on Author {
+ name
+ handle
+ verified
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/ee_else_ce.import.graphql b/fixtures/lib/gitlab/graphql/queries/ee_else_ce.import.graphql
new file mode 100644
index 00000000000..5a4d0320eb6
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/ee_else_ce.import.graphql
@@ -0,0 +1,9 @@
+#import "ee_else_ce/author.fragment.graphql"
+
+query {
+ post(slug: "validating-queries") {
+ title
+ content
+ author { ...AuthorF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/missing_argument.graphql b/fixtures/lib/gitlab/graphql/queries/missing_argument.graphql
new file mode 100644
index 00000000000..499495d9363
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/missing_argument.graphql
@@ -0,0 +1,8 @@
+query {
+ blog {
+ title
+ posts {
+ title
+ }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/mixed_client.query.graphql b/fixtures/lib/gitlab/graphql/queries/mixed_client.query.graphql
new file mode 100644
index 00000000000..f98d070958c
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/mixed_client.query.graphql
@@ -0,0 +1,7 @@
+query {
+ thingy @client
+ post(slug: "validating-queries") {
+ title
+ otherThing @client
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/mixed_client_invalid.query.graphql b/fixtures/lib/gitlab/graphql/queries/mixed_client_invalid.query.graphql
new file mode 100644
index 00000000000..e97c133c5ca
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/mixed_client_invalid.query.graphql
@@ -0,0 +1,7 @@
+query {
+ thingy @client
+ post(slug: "validating-queries") {
+ titlz
+ otherThing @client
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/mixed_client_skipped_argument.graphql b/fixtures/lib/gitlab/graphql/queries/mixed_client_skipped_argument.graphql
new file mode 100644
index 00000000000..a54890085f1
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/mixed_client_skipped_argument.graphql
@@ -0,0 +1,11 @@
+query($slug: String!, $foo: String) {
+ thingy(someArg: $foo) @client {
+ x
+ y
+ z
+ }
+ post(slug: $slug) {
+ title
+ otherThing @client
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/mixed_client_unused_fragment.graphql b/fixtures/lib/gitlab/graphql/queries/mixed_client_unused_fragment.graphql
new file mode 100644
index 00000000000..0f4e92319ab
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/mixed_client_unused_fragment.graphql
@@ -0,0 +1,11 @@
+#import "./thingy.fragment.graphql"
+
+query($slug: String!, $foo: String) {
+ thingy(someArg: $foo) @client {
+ ...ThingyF
+ }
+ post(slug: $slug) {
+ title
+ otherThing @client
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/post.fragment.graphql b/fixtures/lib/gitlab/graphql/queries/post.fragment.graphql
new file mode 100644
index 00000000000..0049964cfa5
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/post.fragment.graphql
@@ -0,0 +1,8 @@
+# import "./author.fragment.graphql"
+
+fragment PostF on Post {
+ name
+ title
+ content
+ author { ...AuthorF }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/post_by_slug.graphql b/fixtures/lib/gitlab/graphql/queries/post_by_slug.graphql
new file mode 100644
index 00000000000..a7febc39e81
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/post_by_slug.graphql
@@ -0,0 +1,7 @@
+query {
+ post(slug: "validating-queries") {
+ title
+ content
+ author { name }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.graphql b/fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.graphql
new file mode 100644
index 00000000000..fef763c4283
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.graphql
@@ -0,0 +1,9 @@
+#import "./author.fragment.graphql"
+
+query {
+ post(slug: "validating-queries") {
+ title
+ content
+ author { ...AuthorF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.misspelled.graphql b/fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.misspelled.graphql
new file mode 100644
index 00000000000..4b205860e6e
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/post_by_slug.with_import.misspelled.graphql
@@ -0,0 +1,9 @@
+# import "./auther.fragment.graphql"
+
+query {
+ post(slug: "validating-queries") {
+ title
+ content
+ author { ...AuthorF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/syntax-error.graphql b/fixtures/lib/gitlab/graphql/queries/syntax-error.graphql
new file mode 100644
index 00000000000..f7d2730951d
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/syntax-error.graphql
@@ -0,0 +1,5 @@
+query }
+ blog(title: "boom") {
+ description
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/thingy.fragment.graphql b/fixtures/lib/gitlab/graphql/queries/thingy.fragment.graphql
new file mode 100644
index 00000000000..2f95d647eb3
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/thingy.fragment.graphql
@@ -0,0 +1,3 @@
+fragment ThingyF on Thingy {
+ x y z
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/transitive_bad_import.fragment.graphql b/fixtures/lib/gitlab/graphql/queries/transitive_bad_import.fragment.graphql
new file mode 100644
index 00000000000..1a0769279ef
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/transitive_bad_import.fragment.graphql
@@ -0,0 +1,6 @@
+# import "does-not-exist.graphql"
+
+fragment AuthorF on Author {
+ name
+ handle
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/transitive_bad_import.graphql b/fixtures/lib/gitlab/graphql/queries/transitive_bad_import.graphql
new file mode 100644
index 00000000000..6520fd8d412
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/transitive_bad_import.graphql
@@ -0,0 +1,9 @@
+# import "./transitive_bad_import.fragment.graphql"
+
+query($slug: String!) {
+ post(slug: $slug) {
+ title
+ content
+ author { ...AuthorF }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/typedefs.graphql b/fixtures/lib/gitlab/graphql/queries/typedefs.graphql
new file mode 100644
index 00000000000..e25298661fd
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/typedefs.graphql
@@ -0,0 +1,3 @@
+type Author {
+ name: String
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/unused_import.graphql b/fixtures/lib/gitlab/graphql/queries/unused_import.graphql
new file mode 100644
index 00000000000..19e9de90e81
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/unused_import.graphql
@@ -0,0 +1,8 @@
+# import "./author.fragment.graphql"
+
+query($slug: String!) {
+ post(slug: $slug) {
+ title
+ content
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/wrong_field.graphql b/fixtures/lib/gitlab/graphql/queries/wrong_field.graphql
new file mode 100644
index 00000000000..7903854c84e
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/wrong_field.graphql
@@ -0,0 +1,7 @@
+query {
+ blog(title: "A history of GraphQL") {
+ title
+ createdAt
+ categories { name }
+ }
+}
diff --git a/fixtures/lib/gitlab/graphql/queries/wrong_field.import.graphql b/fixtures/lib/gitlab/graphql/queries/wrong_field.import.graphql
new file mode 100644
index 00000000000..534154e2877
--- /dev/null
+++ b/fixtures/lib/gitlab/graphql/queries/wrong_field.import.graphql
@@ -0,0 +1,7 @@
+# import "./bad.fragment.graphql"
+
+query($title: String!) {
+ blog(title: $title) {
+ ...BadF
+ }
+}
diff --git a/jest.config.base.js b/jest.config.base.js
index 939c05985f5..98c70735d92 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -1,7 +1,7 @@
const IS_EE = require('./config/helpers/is_ee_env');
const isESLint = require('./config/helpers/is_eslint');
-module.exports = path => {
+module.exports = (path) => {
const reporters = ['default'];
// To have consistent date time parsing both in local and CI environments we set
@@ -27,7 +27,7 @@ module.exports = path => {
// workaround for eslint-import-resolver-jest only resolving in test files
// see https://github.com/JoinColony/eslint-import-resolver-jest#note
if (isESLint(module)) {
- testMatch = testMatch.map(path => path.replace('_spec.js', ''));
+ testMatch = testMatch.map((path) => path.replace('_spec.js', ''));
}
const TEST_FIXTURES_PATTERN = 'test_fixtures(/.*)$';
@@ -38,12 +38,12 @@ module.exports = path => {
'<rootDir>/app/assets/javascripts/vue_shared/components/empty_component.js',
'^shared_queries(/.*)$': '<rootDir>/app/graphql/queries$1',
'^ee_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1',
- '^helpers(/.*)$': '<rootDir>/spec/frontend/helpers$1',
+ '^helpers(/.*)$': '<rootDir>/spec/frontend/__helpers__$1',
'^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1',
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1',
'\\.(jpg|jpeg|png|svg|css)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
- '^spec/test_constants$': '<rootDir>/spec/frontend/helpers/test_constants',
+ '^spec/test_constants$': '<rootDir>/spec/frontend/__helpers__/test_constants',
'^jest/(.*)$': '<rootDir>/spec/frontend/$1',
'test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
};
@@ -91,7 +91,7 @@ module.exports = path => {
'^.+\\.(md|zip|png)$': 'jest-raw-loader',
},
transformIgnorePatterns: [
- 'node_modules/(?!(@gitlab/ui|bootstrap-vue|three|monaco-editor|monaco-yaml)/)',
+ 'node_modules/(?!(@gitlab/ui|@gitlab/favicon-overlay|bootstrap-vue|three|monaco-editor|monaco-yaml|fast-mersenne-twister)/)',
],
timers: 'fake',
testEnvironment: '<rootDir>/spec/frontend/environment.js',
diff --git a/jest.config.js b/jest.config.js
index 4627462c730..cfc8e254791 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -4,7 +4,7 @@ module.exports = {
...baseConfig('spec/frontend'),
};
-const karmaTestFile = process.argv.find(arg => arg.includes('spec/javascripts/'));
+const karmaTestFile = process.argv.find((arg) => arg.includes('spec/javascripts/'));
if (karmaTestFile) {
console.error(`
Files in spec/javascripts/ and ee/spec/javascripts need to be run with Karma.
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 06c2b46a2f2..ada0da28749 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -59,6 +59,7 @@ module API
project: -> { @project },
namespace: -> { @group },
caller_id: route.origin,
+ remote_ip: request.ip,
feature_category: feature_category
)
end
@@ -212,6 +213,7 @@ module API
mount ::API::GroupPackages
mount ::API::PackageFiles
mount ::API::NugetProjectPackages
+ mount ::API::NugetGroupPackages
mount ::API::PypiPackages
mount ::API::ComposerPackages
mount ::API::ConanProjectPackages
@@ -251,6 +253,7 @@ module API
mount ::API::Services
mount ::API::Settings
mount ::API::SidekiqMetrics
+ mount ::API::SnippetRepositoryStorageMoves
mount ::API::Snippets
mount ::API::Statistics
mount ::API::Submodules
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 0a486307653..8641271f2df 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -69,10 +69,15 @@ module API
def find_user_from_sources
strong_memoize(:find_user_from_sources) do
- deploy_token_from_request ||
- find_user_from_bearer_token ||
- find_user_from_job_token ||
- user_from_warden
+ if try(:namespace_inheritable, :authentication)
+ user_from_namespace_inheritable ||
+ user_from_warden
+ else
+ deploy_token_from_request ||
+ find_user_from_bearer_token ||
+ find_user_from_job_token ||
+ user_from_warden
+ end
end
end
diff --git a/lib/api/boards.rb b/lib/api/boards.rb
index e2d30dd7c2b..5fd4ca3546c 100644
--- a/lib/api/boards.rb
+++ b/lib/api/boards.rb
@@ -7,10 +7,10 @@ module API
prepend_if_ee('EE::API::BoardsResponses') # rubocop: disable Cop/InjectEnterpriseEditionModule
- before { authenticate! }
-
feature_category :boards
+ before { authenticate! }
+
helpers do
def board_parent
user_project
diff --git a/lib/api/boards_responses.rb b/lib/api/boards_responses.rb
index 89355c84401..5a30de1f766 100644
--- a/lib/api/boards_responses.rb
+++ b/lib/api/boards_responses.rb
@@ -80,10 +80,20 @@ module API
requires :label_id, type: Integer, desc: 'The ID of an existing label'
end
- params :update_params do
+ params :update_params_ce do
+ optional :name, type: String, desc: 'The board name'
+ optional :hide_backlog_list, type: Grape::API::Boolean, desc: 'Hide the Open list'
+ optional :hide_closed_list, type: Grape::API::Boolean, desc: 'Hide the Closed list'
+ end
+
+ params :update_params_ee do
# Configurable issue boards are not available in CE/EE Core.
# https://docs.gitlab.com/ee/user/project/issue_board.html#configurable-issue-boards
- optional :name, type: String, desc: 'The board name'
+ end
+
+ params :update_params do
+ use :update_params_ce
+ use :update_params_ee
end
end
end
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 86e1a939df1..5cfb65e1fbb 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -180,6 +180,7 @@ module API
optional :checksum, type: String, desc: %q(Job's trace CRC32 checksum)
optional :bytesize, type: Integer, desc: %q(Job's trace size in bytes)
end
+ optional :exit_code, type: Integer, desc: %q(Job's exit code)
end
put '/:id' do
job = authenticate_job!
diff --git a/lib/api/concerns/packages/nuget_endpoints.rb b/lib/api/concerns/packages/nuget_endpoints.rb
index 1a03a6a6dad..53b778875fc 100644
--- a/lib/api/concerns/packages/nuget_endpoints.rb
+++ b/lib/api/concerns/packages/nuget_endpoints.rb
@@ -19,44 +19,49 @@ module API
included do
helpers do
- def find_packages
- packages = package_finder.execute
+ def find_packages(package_name)
+ packages = package_finder(package_name).execute
not_found!('Packages') unless packages.exists?
packages
end
- def find_package
- package = package_finder(package_version: params[:package_version]).execute
- .first
+ def find_package(package_name, package_version)
+ package = package_finder(package_name, package_version).execute
+ .first
not_found!('Package') unless package
package
end
- def package_finder(finder_params = {})
+ def package_finder(package_name, package_version = nil)
::Packages::Nuget::PackageFinder.new(
- authorized_user_project,
- **finder_params.merge(package_name: params[:package_name])
+ current_user,
+ project_or_group,
+ package_name: package_name,
+ package_version: package_version
)
end
+
+ def search_packages(search_term, search_options)
+ ::Packages::Nuget::SearchService
+ .new(current_user, project_or_group, params[:q], search_options)
+ .execute
+ end
end
# https://docs.microsoft.com/en-us/nuget/api/service-index
desc 'The NuGet Service Index' do
detail 'This feature was introduced in GitLab 12.6'
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
get 'index', format: :json do
- authorize_read_package!(authorized_user_project)
+ authorize_read_package!(project_or_group)
track_package_event('cli_metadata', :nuget, category: 'API::NugetPackages')
- present ::Packages::Nuget::ServiceIndexPresenter.new(authorized_user_project),
- with: ::API::Entities::Nuget::ServiceIndex
+ present ::Packages::Nuget::ServiceIndexPresenter.new(project_or_group),
+ with: ::API::Entities::Nuget::ServiceIndex
end
# https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
@@ -64,18 +69,15 @@ module API
requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX
end
namespace '/metadata/*package_name' do
- before do
- authorize_read_package!(authorized_user_project)
+ after_validation do
+ authorize_read_package!(project_or_group)
end
desc 'The NuGet Metadata Service - Package name level' do
detail 'This feature was introduced in GitLab 12.8'
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
get 'index', format: :json do
- present ::Packages::Nuget::PackagesMetadataPresenter.new(find_packages),
+ present ::Packages::Nuget::PackagesMetadataPresenter.new(find_packages(params[:package_name])),
with: ::API::Entities::Nuget::PackagesMetadata
end
@@ -85,11 +87,8 @@ module API
params do
requires :package_version, type: String, desc: 'The NuGet package version', regexp: API::NO_SLASH_URL_PART_REGEX
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
get '*package_version', format: :json do
- present ::Packages::Nuget::PackageMetadataPresenter.new(find_package),
+ present ::Packages::Nuget::PackageMetadataPresenter.new(find_package(params[:package_name], params[:package_version])),
with: ::API::Entities::Nuget::PackageMetadata
end
end
@@ -102,30 +101,26 @@ module API
optional :prerelease, type: ::Grape::API::Boolean, desc: 'Include prerelease versions', default: true
end
namespace '/query' do
- before do
- authorize_read_package!(authorized_user_project)
+ after_validation do
+ authorize_read_package!(project_or_group)
end
desc 'The NuGet Search Service' do
detail 'This feature was introduced in GitLab 12.8'
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
get format: :json do
search_options = {
include_prerelease_versions: params[:prerelease],
per_page: params[:take],
padding: params[:skip]
}
- search = ::Packages::Nuget::SearchService
- .new(authorized_user_project, params[:q], search_options)
- .execute
+
+ results = search_packages(params[:q], search_options)
track_package_event('search_package', :nuget, category: 'API::NugetPackages')
- present ::Packages::Nuget::SearchResultsPresenter.new(search),
- with: ::API::Entities::Nuget::SearchResults
+ present ::Packages::Nuget::SearchResultsPresenter.new(results),
+ with: ::API::Entities::Nuget::SearchResults
end
end
end
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index bcb4e8c8cbc..f8129c18dff 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -21,6 +21,8 @@ module API
end
namespace 'incoming/: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
params do
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
@@ -42,10 +44,9 @@ module API
# 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
- post 'authorize' do
+ put 'authorize' do
authorize_workhorse!(
subject: authorized_user_project,
- has_length: false,
maximum_size: authorized_user_project.actual_limits.debian_max_file_size
)
end
diff --git a/lib/api/entities/basic_repository_storage_move.rb b/lib/api/entities/basic_repository_storage_move.rb
new file mode 100644
index 00000000000..3ee112fb9a2
--- /dev/null
+++ b/lib/api/entities/basic_repository_storage_move.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class BasicRepositoryStorageMove < Grape::Entity
+ expose :id
+ expose :created_at
+ expose :human_state_name, as: :state
+ expose :source_storage_name
+ expose :destination_storage_name
+ end
+ end
+end
diff --git a/lib/api/entities/basic_snippet.rb b/lib/api/entities/basic_snippet.rb
new file mode 100644
index 00000000000..26297514798
--- /dev/null
+++ b/lib/api/entities/basic_snippet.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class BasicSnippet < Grape::Entity
+ expose :id, :title, :description, :visibility
+ expose :updated_at, :created_at
+ expose :project_id
+ expose :web_url do |snippet|
+ Gitlab::UrlBuilder.build(snippet)
+ end
+ expose :raw_url do |snippet|
+ Gitlab::UrlBuilder.build(snippet, raw: true)
+ end
+ expose :ssh_url_to_repo, :http_url_to_repo, if: ->(snippet) { snippet.repository_exists? }
+ end
+ end
+end
diff --git a/lib/api/entities/board.rb b/lib/api/entities/board.rb
index b7a50408313..fe0182ad772 100644
--- a/lib/api/entities/board.rb
+++ b/lib/api/entities/board.rb
@@ -5,6 +5,8 @@ module API
class Board < Grape::Entity
expose :id
expose :name
+ expose :hide_backlog_list
+ expose :hide_closed_list
expose :project, using: Entities::BasicProjectDetails
expose :lists, using: Entities::List do |board|
diff --git a/lib/api/entities/note.rb b/lib/api/entities/note.rb
index 9a60c04220d..a597aa7bb4a 100644
--- a/lib/api/entities/note.rb
+++ b/lib/api/entities/note.rb
@@ -23,6 +23,7 @@ module API
expose :resolvable?, as: :resolvable
expose :resolved?, as: :resolved, if: ->(note, options) { note.resolvable? }
expose :resolved_by, using: Entities::UserBasic, if: ->(note, options) { note.resolvable? }
+ expose :resolved_at, if: ->(note, options) { note.resolvable? }
expose :confidential?, as: :confidential
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 317caefe0a1..6ad6123a20e 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -100,6 +100,7 @@ module API
end
expose :only_allow_merge_if_pipeline_succeeds
expose :allow_merge_on_skipped_pipeline
+ expose :restrict_user_defined_variables
expose :request_access_enabled
expose :only_allow_merge_if_all_discussions_are_resolved
expose :remove_source_branch_after_merge
diff --git a/lib/api/entities/project_repository_storage_move.rb b/lib/api/entities/project_repository_storage_move.rb
index 25643651a14..191bbaf19d7 100644
--- a/lib/api/entities/project_repository_storage_move.rb
+++ b/lib/api/entities/project_repository_storage_move.rb
@@ -2,12 +2,7 @@
module API
module Entities
- class ProjectRepositoryStorageMove < Grape::Entity
- expose :id
- expose :created_at
- expose :human_state_name, as: :state
- expose :source_storage_name
- expose :destination_storage_name
+ class ProjectRepositoryStorageMove < BasicRepositoryStorageMove
expose :project, using: Entities::ProjectIdentity
end
end
diff --git a/lib/api/entities/release.rb b/lib/api/entities/release.rb
index 44a46c5861e..f6c3dd5a509 100644
--- a/lib/api/entities/release.rb
+++ b/lib/api/entities/release.rb
@@ -16,7 +16,12 @@ module API
expose :author, using: Entities::UserBasic, if: -> (release, _) { release.author.present? }
expose :commit, using: Entities::Commit, if: ->(_, _) { can_download_code? }
expose :upcoming_release?, as: :upcoming_release
- expose :milestones, using: Entities::MilestoneWithStats, if: -> (release, _) { release.milestones.present? && can_read_milestone? }
+ expose :milestones,
+ using: Entities::MilestoneWithStats,
+ if: -> (release, _) { release.milestones.present? && can_read_milestone? } do |release, _|
+ release.milestones.order_by_dates_and_title
+ end
+
expose :commit_path, expose_nil: false
expose :tag_path, expose_nil: false
diff --git a/lib/api/entities/snippet.rb b/lib/api/entities/snippet.rb
index 85148c03d18..f05e593a302 100644
--- a/lib/api/entities/snippet.rb
+++ b/lib/api/entities/snippet.rb
@@ -2,18 +2,8 @@
module API
module Entities
- class Snippet < Grape::Entity
- expose :id, :title, :description, :visibility
+ class Snippet < BasicSnippet
expose :author, using: Entities::UserBasic
- expose :updated_at, :created_at
- expose :project_id
- expose :web_url do |snippet|
- Gitlab::UrlBuilder.build(snippet)
- end
- expose :raw_url do |snippet|
- Gitlab::UrlBuilder.build(snippet, raw: true)
- end
- expose :ssh_url_to_repo, :http_url_to_repo, if: ->(snippet) { snippet.repository_exists? }
expose :file_name do |snippet|
snippet.file_name_on_repo || snippet.file_name
end
diff --git a/lib/api/entities/snippet_repository_storage_move.rb b/lib/api/entities/snippet_repository_storage_move.rb
new file mode 100644
index 00000000000..ee86816bd14
--- /dev/null
+++ b/lib/api/entities/snippet_repository_storage_move.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class SnippetRepositoryStorageMove < BasicRepositoryStorageMove
+ expose :snippet, using: Entities::BasicSnippet
+ end
+ end
+end
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index 3e1dd044c8d..167531fdaec 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -21,7 +21,7 @@ module API
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
namespace ':id/packages/generic' do
namespace ':package_name/*package_version/:file_name', requirements: GENERIC_PACKAGES_REQUIREMENTS do
@@ -29,7 +29,7 @@ module API
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
params do
requires :package_name, type: String, desc: 'Package name', regexp: Gitlab::Regex.generic_package_name_regex, file_path: true
@@ -52,7 +52,7 @@ module API
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
put do
authorize_upload!(project)
@@ -82,7 +82,7 @@ module API
requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.generic_package_file_name_regex, file_path: true
end
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
get do
authorize_read_package!(project)
diff --git a/lib/api/group_boards.rb b/lib/api/group_boards.rb
index 2bfd98a5b69..7425e1bd145 100644
--- a/lib/api/group_boards.rb
+++ b/lib/api/group_boards.rb
@@ -9,9 +9,7 @@ module API
feature_category :boards
- before do
- authenticate!
- end
+ before { authenticate! }
helpers do
def board_parent
@@ -22,28 +20,40 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
-
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
segment ':id/boards' do
+ desc 'Get all group boards' do
+ detail 'This feature was introduced in 10.6'
+ success Entities::Board
+ end
+ params do
+ use :pagination
+ end
+ get '/' do
+ authorize!(:read_board, user_group)
+ present paginate(board_parent.boards.with_associations), with: Entities::Board
+ end
+
desc 'Find a group board' do
detail 'This feature was introduced in 10.6'
- success ::API::Entities::Board
+ success Entities::Board
end
get '/:board_id' do
authorize!(:read_board, user_group)
- present board, with: ::API::Entities::Board
+ present board, with: Entities::Board
end
- desc 'Get all group boards' do
- detail 'This feature was introduced in 10.6'
+ desc 'Update a group board' do
+ detail 'This feature was introduced in 11.0'
success Entities::Board
end
params do
- use :pagination
+ use :update_params
end
- get '/' do
- authorize!(:read_board, user_group)
- present paginate(board_parent.boards.with_associations), with: Entities::Board
+ put '/:board_id' do
+ authorize!(:admin_board, board_parent)
+
+ update_board
end
end
diff --git a/lib/api/group_packages.rb b/lib/api/group_packages.rb
index 31b28c3990f..d482f4d0585 100644
--- a/lib/api/group_packages.rb
+++ b/lib/api/group_packages.rb
@@ -31,12 +31,14 @@ module API
desc: 'Return packages of a certain type'
optional :package_name, type: String,
desc: 'Return packages with this name'
+ optional :include_versionless, type: Boolean,
+ desc: 'Returns packages without a version'
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)
+ declared(params).slice(:exclude_subgroups, :order_by, :sort, :package_type, :package_name, :include_versionless)
).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 6fe25471289..79af9c37378 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -220,6 +220,10 @@ module API
user_project.builds.find(id.to_i)
end
+ def find_job!(id)
+ user_project.processables.find(id.to_i)
+ end
+
def authenticate!
unauthorized! unless current_user
end
@@ -275,6 +279,10 @@ module API
authorize! :read_build_trace, build
end
+ def authorize_read_job_artifacts!(build)
+ authorize! :read_job_artifacts, build
+ end
+
def authorize_destroy_artifacts!
authorize! :destroy_artifacts, user_project
end
@@ -364,7 +372,7 @@ module API
def forbidden!(reason = nil)
message = ['403 Forbidden']
- message << " - #{reason}" if reason
+ message << "- #{reason}" if reason
render_api_error!(message.join(' '), 403)
end
@@ -513,7 +521,7 @@ module API
case headers['X-Sendfile-Type']
when 'X-Sendfile'
header['X-Sendfile'] = path
- body
+ body '' # to avoid an error from API::APIGuard::ResponseCoercerMiddleware
else
sendfile path
end
@@ -529,7 +537,7 @@ module API
else
header(*Gitlab::Workhorse.send_url(file.url))
status :ok
- body ""
+ body '' # to avoid an error from API::APIGuard::ResponseCoercerMiddleware
end
end
@@ -562,7 +570,7 @@ module API
return unless Feature.enabled?(feature_flag, default_enabled: true)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: values)
rescue => error
Gitlab::AppLogger.warn("Redis tracking event failed for event: #{event_name}, message: #{error.message}")
end
diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb
new file mode 100644
index 00000000000..a6cfe930190
--- /dev/null
+++ b/lib/api/helpers/authentication.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module Authentication
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def authenticate_with(&block)
+ strategies = ::Gitlab::APIAuthentication::Builder.new.build(&block)
+ namespace_inheritable :authentication, strategies
+ end
+ end
+
+ included do
+ helpers ::Gitlab::Utils::StrongMemoize
+
+ helpers do
+ def token_from_namespace_inheritable
+ strong_memoize(:token_from_namespace_inheritable) do
+ strategies = namespace_inheritable(:authentication)
+ next unless strategies&.any?
+
+ # Extract credentials from the request
+ found = strategies.to_h { |location, _| [location, ::Gitlab::APIAuthentication::TokenLocator.new(location).extract(current_request)] }
+ found.filter! { |location, raw| raw }
+ next unless found.any?
+
+ # Specifying multiple credentials is an error
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_475984136
+ bad_request!('Found more than one set of credentials') if found.size > 1
+
+ location, raw = found.first
+ find_token_from_raw_credentials(strategies[location], raw)
+ end
+
+ rescue ::Gitlab::Auth::UnauthorizedError
+ # TODO: this should be rescued and converted by the exception handling middleware
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_475174516
+ unauthorized!
+ end
+
+ def access_token_from_namespace_inheritable
+ token = token_from_namespace_inheritable
+ token if token.is_a? PersonalAccessToken
+ end
+
+ def user_from_namespace_inheritable
+ token = token_from_namespace_inheritable
+ return token if token.is_a? DeployToken
+
+ token&.user
+ end
+
+ private
+
+ def find_token_from_raw_credentials(token_types, raw)
+ token_types.each do |token_type|
+ # Resolve a token from the raw credentials
+ token = ::Gitlab::APIAuthentication::TokenResolver.new(token_type).resolve(raw)
+ return token if token
+ end
+
+ # If a request provides credentials via an allowed transport, the
+ # credentials must be valid. If we reach this point, the credentials
+ # must not be valid credentials of an allowed type.
+ raise ::Gitlab::Auth::UnauthorizedError
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/merge_requests_helpers.rb b/lib/api/helpers/merge_requests_helpers.rb
index 9b38eeb1e72..f8fe40f7135 100644
--- a/lib/api/helpers/merge_requests_helpers.rb
+++ b/lib/api/helpers/merge_requests_helpers.rb
@@ -21,6 +21,9 @@ module API
coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
desc: 'Return merge requests which are assigned to the user with the given username'
mutually_exclusive :assignee_id, :assignee_username
+ optional :reviewer_username,
+ type: String,
+ desc: 'Return merge requests which have the user as a reviewer with the given username'
optional :labels,
type: Array[String],
@@ -32,6 +35,11 @@ module API
params :merge_requests_base_params do
use :merge_requests_negatable_params
+ optional :reviewer_id,
+ types: [Integer, String],
+ integer_none_any: true,
+ desc: 'Return merge requests which have the user as a reviewer with the given ID'
+ mutually_exclusive :reviewer_id, :reviewer_username
optional :state,
type: String,
values: %w[opened closed locked merged all],
@@ -72,6 +80,10 @@ module API
optional :wip, type: String, values: %w[yes no], desc: 'Search merge requests for WIP in the title'
optional :not, type: Hash, desc: 'Parameters to negate' do
use :merge_requests_negatable_params
+ optional :reviewer_id,
+ types: Integer,
+ desc: 'Return merge requests which have the user as a reviewer with the given ID'
+ mutually_exclusive :reviewer_id, :reviewer_username
end
optional :deployed_before,
diff --git a/lib/api/helpers/packages/basic_auth_helpers.rb b/lib/api/helpers/packages/basic_auth_helpers.rb
index 0784efc11d6..c32ce199dd6 100644
--- a/lib/api/helpers/packages/basic_auth_helpers.rb
+++ b/lib/api/helpers/packages/basic_auth_helpers.rb
@@ -12,6 +12,7 @@ module API
end
include Constants
+ include Gitlab::Utils::StrongMemoize
def unauthorized_user_project
@unauthorized_user_project ||= find_project(params[:id])
@@ -35,6 +36,18 @@ module API
project
end
+ def find_authorized_group!
+ strong_memoize(:authorized_group) do
+ group = find_group(params[:id])
+
+ unless group && can?(current_user, :read_group, group)
+ next unauthorized_or! { not_found! }
+ end
+
+ group
+ end
+ end
+
def authorize!(action, subject = :global, reason = nil)
return if can?(current_user, action, subject)
diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb
index 227aec224e5..48618e7d26d 100644
--- a/lib/api/helpers/pagination.rb
+++ b/lib/api/helpers/pagination.rb
@@ -3,8 +3,8 @@
module API
module Helpers
module Pagination
- def paginate(*args)
- Gitlab::Pagination::OffsetPagination.new(self).paginate(*args)
+ def paginate(*args, **kwargs)
+ Gitlab::Pagination::OffsetPagination.new(self).paginate(*args, **kwargs)
end
end
end
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index f5f45cf7351..cf2bcace33b 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -87,6 +87,7 @@ module API
params :optional_update_params_ce do
optional :ci_forward_deployment_enabled, type: Boolean, desc: 'Skip older deployment jobs that are still pending'
+ optional :restrict_user_defined_variables, type: Boolean, desc: 'Restrict use of user-defined variables when triggering a pipeline'
end
params :optional_update_params_ee do
@@ -99,7 +100,7 @@ module API
params :optional_container_expiration_policy_params do
optional :cadence, type: String, desc: 'Container expiration policy cadence for recurring job'
- optional :keep_n, type: String, desc: 'Container expiration policy number of images to keep'
+ optional :keep_n, type: Integer, desc: 'Container expiration policy number of images to keep'
optional :older_than, type: String, desc: 'Container expiration policy remove images older than value'
optional :name_regex, type: String, desc: 'Container expiration policy regex for image removal'
optional :name_regex_keep, type: String, desc: 'Container expiration policy regex for image retention'
@@ -141,6 +142,7 @@ module API
:repository_access_level,
:request_access_enabled,
:resolve_outdated_diff_discussions,
+ :restrict_user_defined_variables,
:shared_runners_enabled,
:snippets_access_level,
:tag_list,
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index 9d2fd9978d9..6101a8d307e 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -161,7 +161,6 @@ module API
def self.services
{
- 'alerts' => [],
'asana' => [
{
required: true,
@@ -807,7 +806,6 @@ module API
def self.service_classes
[
- ::AlertsService,
::AsanaService,
::AssemblaService,
::BambooService,
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 332f2f1986f..12bb6e77c3e 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -16,6 +16,7 @@ module API
user: -> { actor&.user },
project: -> { project },
caller_id: route.origin,
+ remote_ip: request.ip,
feature_category: feature_category
)
end
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
index be8147908e9..2ab1f97afe6 100644
--- a/lib/api/invitations.rb
+++ b/lib/api/invitations.rb
@@ -48,6 +48,24 @@ module API
present_member_invitations invitations
end
+
+ desc 'Removes an invitation from a group or project.'
+ params do
+ requires :email, type: String, desc: 'The email address of the invitation'
+ end
+ delete ":id/invitations/:email", requirements: { email: /[^\/]+/ } do
+ source = find_source(source_type, params[:id])
+ invite_email = params[:email]
+ authorize_admin_source!(source_type, source)
+
+ invite = retrieve_member_invitations(source, invite_email).first
+ not_found! unless invite
+
+ destroy_conditionally!(invite) do
+ ::Members::DestroyService.new(current_user, params).execute(invite)
+ unprocessable_entity! unless invite.destroyed?
+ end
+ end
end
end
end
diff --git a/lib/api/job_artifacts.rb b/lib/api/job_artifacts.rb
index 1faa28d6f07..28737f61f61 100644
--- a/lib/api/job_artifacts.rb
+++ b/lib/api/job_artifacts.rb
@@ -32,6 +32,7 @@ module API
authorize_download_artifacts!
latest_build = user_project.latest_successful_build_for_ref!(params[:job], params[:ref_name])
+ authorize_read_job_artifacts!(latest_build)
present_carrierwave_file!(latest_build.artifacts_file)
end
@@ -50,6 +51,7 @@ module API
authorize_download_artifacts!
build = user_project.latest_successful_build_for_ref!(params[:job], params[:ref_name])
+ authorize_read_job_artifacts!(build)
path = Gitlab::Ci::Build::Artifacts::Path
.new(params[:artifact_path])
@@ -70,6 +72,7 @@ module API
authorize_download_artifacts!
build = find_build!(params[:job_id])
+ authorize_read_job_artifacts!(build)
present_carrierwave_file!(build.artifacts_file)
end
@@ -82,9 +85,11 @@ module API
requires :artifact_path, type: String, desc: 'Artifact path'
end
get ':id/jobs/:job_id/artifacts/*artifact_path', format: false do
- authorize_read_builds!
+ authorize_download_artifacts!
build = find_build!(params[:job_id])
+ authorize_read_job_artifacts!(build)
+
not_found! unless build.artifacts?
path = Gitlab::Ci::Build::Artifacts::Path
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 44751b3d76c..e14a4a5e680 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -138,25 +138,32 @@ module API
present build, with: Entities::Ci::Job
end
- desc 'Trigger a actionable job (manual, delayed, etc)' do
- success Entities::Ci::Job
+ desc 'Trigger an actionable job (manual, delayed, etc)' do
+ success Entities::Ci::JobBasic
detail 'This feature was added in GitLab 8.11'
end
params do
requires :job_id, type: Integer, desc: 'The ID of a Job'
end
+
post ":id/jobs/:job_id/play" do
authorize_read_builds!
- build = find_build!(params[:job_id])
+ job = find_job!(params[:job_id])
- authorize!(:update_build, build)
- bad_request!("Unplayable Job") unless build.playable?
+ authorize!(:play_job, job)
- build.play(current_user)
+ bad_request!("Unplayable Job") unless job.playable?
+
+ job.play(current_user)
status 200
- present build, with: Entities::Ci::Job
+
+ if job.is_a?(::Ci::Build)
+ present job, with: Entities::Ci::Job
+ else
+ present job, with: Entities::Ci::Bridge
+ end
end
end
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index 58181adaa93..f1f34622187 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -12,14 +12,13 @@ module API
end
post '/lint' do
result = Gitlab::Ci::YamlProcessor.new(params[:content], user: current_user).execute
- error = result.errors.first
status 200
- response = if error.blank?
+ response = if result.errors.empty?
{ status: 'valid', errors: [], warnings: result.warnings }
else
- { status: 'invalid', errors: [error], warnings: result.warnings }
+ { status: 'invalid', errors: result.errors, warnings: result.warnings }
end
response.tap do |response|
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index 7b4e52d18e8..4a5b2ead163 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -220,9 +220,13 @@ module API
file_name, format = extract_format(params[:file_name])
- package = ::Packages::Maven::FindOrCreatePackageService
+ result = ::Packages::Maven::FindOrCreatePackageService
.new(user_project, current_user, params.merge(build: current_authenticated_job)).execute
+ bad_request!(result.errors.first) if result.error?
+
+ package = result.payload[:package]
+
case format
when 'sha1'
# After uploading a file, Maven tries to upload a sha1 and md5 version of it.
diff --git a/lib/api/nuget_group_packages.rb b/lib/api/nuget_group_packages.rb
new file mode 100644
index 00000000000..e373f051b24
--- /dev/null
+++ b/lib/api/nuget_group_packages.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+# NuGet Package Manager Client API
+#
+# These API endpoints are not meant to be consumed directly by users. They are
+# called by the NuGet package manager client when users run commands
+# like `nuget install` or `nuget push`.
+#
+# This is the group level API.
+module API
+ class NugetGroupPackages < ::API::Base
+ helpers ::API::Helpers::PackagesHelpers
+ helpers ::API::Helpers::Packages::BasicAuthHelpers
+ include ::API::Helpers::Authentication
+
+ feature_category :package_registry
+
+ default_format :json
+
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_basic_auth)
+ end
+
+ rescue_from ArgumentError do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ after_validation do
+ require_packages_enabled!
+ end
+
+ helpers do
+ def project_or_group
+ find_authorized_group!
+ end
+
+ def require_authenticated!
+ unauthorized! unless current_user
+ end
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of a group', regexp: ::API::Concerns::Packages::NugetEndpoints::POSITIVE_INTEGER_REGEX
+ end
+
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ namespace ':id/-/packages/nuget' do
+ after_validation do
+ # This API can't be accessed anonymously
+ require_authenticated!
+ end
+
+ include ::API::Concerns::Packages::NugetEndpoints
+ end
+ end
+ end
+end
diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb
index b2516cc91f8..2146f4d4b78 100644
--- a/lib/api/nuget_project_packages.rb
+++ b/lib/api/nuget_project_packages.rb
@@ -5,10 +5,13 @@
# These API endpoints are not meant to be consumed directly by users. They are
# called by the NuGet package manager client when users run commands
# like `nuget install` or `nuget push`.
+#
+# This is the project level API.
module API
class NugetProjectPackages < ::API::Base
- helpers ::API::Helpers::PackagesManagerClientsHelpers
+ helpers ::API::Helpers::PackagesHelpers
helpers ::API::Helpers::Packages::BasicAuthHelpers
+ include ::API::Helpers::Authentication
feature_category :package_registry
@@ -16,25 +19,29 @@ module API
default_format :json
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_basic_auth)
+ end
+
rescue_from ArgumentError do |e|
render_api_error!(e.message, 400)
end
- before do
+ after_validation do
require_packages_enabled!
end
+ helpers do
+ def project_or_group
+ authorized_user_project
+ end
+ end
+
params do
requires :id, type: String, desc: 'The ID of a project', regexp: ::API::Concerns::Packages::NugetEndpoints::POSITIVE_INTEGER_REGEX
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- before do
- authorized_user_project
- end
-
namespace ':id/packages/nuget' do
include ::API::Concerns::Packages::NugetEndpoints
@@ -46,28 +53,20 @@ module API
params do
requires :package, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
put do
- authorize_upload!(authorized_user_project)
- bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:nuget_max_file_size, params[:package].size)
+ authorize_upload!(project_or_group)
+ bad_request!('File is too large') if project_or_group.actual_limits.exceeded?(:nuget_max_file_size, params[:package].size)
file_params = params.merge(
file: params[:package],
file_name: PACKAGE_FILENAME
)
- package = ::Packages::Nuget::CreatePackageService.new(
- authorized_user_project,
- current_user,
- declared_params.merge(build: current_authenticated_job)
- ).execute
+ package = ::Packages::Nuget::CreatePackageService.new(project_or_group, current_user, declared_params.merge(build: current_authenticated_job))
+ .execute
- package_file = ::Packages::CreatePackageFileService.new(
- package,
- file_params.merge(build: current_authenticated_job)
- ).execute
+ package_file = ::Packages::CreatePackageFileService.new(package, file_params.merge(build: current_authenticated_job))
+ .execute
track_package_event('push_package', :nuget, category: 'API::NugetPackages')
@@ -75,18 +74,15 @@ module API
created!
rescue ObjectStorage::RemoteStoreError => e
- Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: authorized_user_project.id })
+ Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: project_or_group.id })
forbidden!
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
put 'authorize' do
authorize_workhorse!(
- subject: authorized_user_project,
+ subject: project_or_group,
has_length: false,
- maximum_size: authorized_user_project.actual_limits.nuget_max_file_size
+ maximum_size: project_or_group.actual_limits.nuget_max_file_size
)
end
@@ -95,18 +91,15 @@ module API
requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX
end
namespace '/download/*package_name' do
- before do
- authorize_read_package!(authorized_user_project)
+ after_validation do
+ authorize_read_package!(project_or_group)
end
desc 'The NuGet Content Service - index request' do
detail 'This feature was introduced in GitLab 12.8'
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
get 'index', format: :json do
- present ::Packages::Nuget::PackagesVersionsPresenter.new(find_packages),
+ present ::Packages::Nuget::PackagesVersionsPresenter.new(find_packages(params[:package_name])),
with: ::API::Entities::Nuget::PackagesVersions
end
@@ -117,12 +110,9 @@ module API
requires :package_version, type: String, desc: 'The NuGet package version', regexp: API::NO_SLASH_URL_PART_REGEX
requires :package_filename, type: String, desc: 'The NuGet package filename', regexp: API::NO_SLASH_URL_PART_REGEX
end
-
- route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
-
get '*package_version/*package_filename', format: :nupkg do
filename = "#{params[:package_filename]}.#{params[:format]}"
- package_file = ::Packages::PackageFileFinder.new(find_package, filename, with_file_name_like: true)
+ package_file = ::Packages::PackageFileFinder.new(find_package(params[:package_name], params[:package_version]), filename, with_file_name_like: true)
.execute
not_found!('Package') unless package_file
diff --git a/lib/api/project_packages.rb b/lib/api/project_packages.rb
index 56e94333433..32636662987 100644
--- a/lib/api/project_packages.rb
+++ b/lib/api/project_packages.rb
@@ -30,11 +30,13 @@ module API
desc: 'Return packages of a certain type'
optional :package_name, type: String,
desc: 'Return packages with this name'
+ optional :include_versionless, type: Boolean,
+ desc: 'Returns packages without a version'
end
get ':id/packages' do
packages = ::Packages::PackagesFinder.new(
user_project,
- declared_params.slice(:order_by, :sort, :package_type, :package_name)
+ declared_params.slice(:order_by, :sort, :package_type, :package_name, :include_versionless)
).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 af5d96969ef..19244ed697f 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -4,7 +4,7 @@ module API
class ProjectTemplates < ::API::Base
include PaginationParams
- TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses metrics_dashboard_ymls issues merge_requests].freeze
+ TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls gitlab_ci_syntax_ymls licenses metrics_dashboard_ymls issues merge_requests].freeze
# The regex is needed to ensure a period (e.g. agpl-3.0)
# isn't confused with a format type. We also need to allow encoded
# values (e.g. C%2B%2B for C++), so allow % and + as well.
@@ -16,7 +16,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
- requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses|metrics_dashboard_ymls|issues|merge_requests) of the template'
+ requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|gitlab_ci_syntax_ymls|licenses|metrics_dashboard_ymls|issues|merge_requests) of the template'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of templates available to this project' do
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 2012c348cd1..2d09ad01757 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -566,8 +566,8 @@ module API
authorize_admin_project
begin
- ::Projects::HousekeepingService.new(user_project, :gc).execute
- rescue ::Projects::HousekeepingService::LeaseTaken => error
+ ::Repositories::HousekeepingService.new(user_project, :gc).execute
+ rescue ::Repositories::HousekeepingService::LeaseTaken => error
conflict!(error.message)
end
end
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index b3f09b431b0..f329a94adf2 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -91,6 +91,7 @@ module API
optional :import_sources, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce,
values: %w[github bitbucket bitbucket_server gitlab google_code fogbugz git gitlab_project gitea manifest phabricator],
desc: 'Enabled sources for code import during project creation. OmniAuth must be configured for GitHub, Bitbucket, and GitLab.com'
+ optional :invisible_captcha_enabled, type: Boolean, desc: 'Enable Invisible Captcha spam detection during signup.'
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts"
optional :max_attachment_size, type: Integer, desc: 'Maximum attachment size in MB'
optional :max_import_size, type: Integer, desc: 'Maximum import size in MB'
diff --git a/lib/api/snippet_repository_storage_moves.rb b/lib/api/snippet_repository_storage_moves.rb
new file mode 100644
index 00000000000..1a5b41eb1ec
--- /dev/null
+++ b/lib/api/snippet_repository_storage_moves.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+module API
+ class SnippetRepositoryStorageMoves < ::API::Base
+ include PaginationParams
+
+ before { authenticated_as_admin! }
+
+ feature_category :gitaly
+
+ resource :snippet_repository_storage_moves do
+ desc 'Get a list of all snippet repository storage moves' do
+ detail 'This feature was introduced in GitLab 13.8.'
+ success Entities::SnippetRepositoryStorageMove
+ end
+ params do
+ use :pagination
+ end
+ get do
+ storage_moves = SnippetRepositoryStorageMove.order_created_at_desc
+
+ present paginate(storage_moves), with: Entities::SnippetRepositoryStorageMove, current_user: current_user
+ end
+
+ desc 'Get a snippet repository storage move' do
+ detail 'This feature was introduced in GitLab 13.8.'
+ success Entities::SnippetRepositoryStorageMove
+ end
+ params do
+ requires :repository_storage_move_id, type: Integer, desc: 'The ID of a snippet repository storage move'
+ end
+ get ':repository_storage_move_id' do
+ storage_move = SnippetRepositoryStorageMove.find(params[:repository_storage_move_id])
+
+ present storage_move, with: Entities::SnippetRepositoryStorageMove, current_user: current_user
+ end
+
+ desc 'Schedule bulk snippet repository storage moves' do
+ detail 'This feature was introduced in GitLab 13.8.'
+ end
+ params do
+ requires :source_storage_name, type: String, desc: 'The source storage shard', values: -> { Gitlab.config.repositories.storages.keys }
+ optional :destination_storage_name, type: String, desc: 'The destination storage shard', values: -> { Gitlab.config.repositories.storages.keys }
+ end
+ post do
+ ::Snippets::ScheduleBulkRepositoryShardMovesService.enqueue(
+ declared_params[:source_storage_name],
+ declared_params[:destination_storage_name]
+ )
+
+ accepted!
+ end
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of a snippet'
+ end
+ resource :snippets do
+ helpers do
+ def user_snippet
+ Snippet.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+ desc 'Get a list of all snippets repository storage moves' do
+ detail 'This feature was introduced in GitLab 13.8.'
+ success Entities::SnippetRepositoryStorageMove
+ end
+ params do
+ use :pagination
+ end
+ get ':id/repository_storage_moves' do
+ storage_moves = user_snippet.repository_storage_moves.order_created_at_desc
+
+ present paginate(storage_moves), with: Entities::SnippetRepositoryStorageMove, current_user: current_user
+ end
+
+ desc 'Get a snippet repository storage move' do
+ detail 'This feature was introduced in GitLab 13.8.'
+ success Entities::SnippetRepositoryStorageMove
+ end
+ params do
+ requires :repository_storage_move_id, type: Integer, desc: 'The ID of a snippet repository storage move'
+ end
+ get ':id/repository_storage_moves/:repository_storage_move_id' do
+ storage_move = user_snippet.repository_storage_moves.find(params[:repository_storage_move_id])
+
+ present storage_move, with: Entities::SnippetRepositoryStorageMove, current_user: current_user
+ end
+
+ desc 'Schedule a snippet repository storage move' do
+ detail 'This feature was introduced in GitLab 13.8.'
+ success Entities::SnippetRepositoryStorageMove
+ end
+ params do
+ optional :destination_storage_name, type: String, desc: 'The destination storage shard'
+ end
+ post ':id/repository_storage_moves' do
+ storage_move = user_snippet.repository_storage_moves.build(
+ declared_params.merge(source_storage_name: user_snippet.repository_storage)
+ )
+
+ if storage_move.schedule
+ present storage_move, with: Entities::SnippetRepositoryStorageMove, current_user: current_user
+ else
+ render_validation_error!(storage_move)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index b7fb35eac03..bc1e427bcaa 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -13,6 +13,9 @@ module API
gitlab_ci_ymls: {
gitlab_version: 8.9
},
+ gitlab_ci_syntax_ymls: {
+ gitlab_version: 13.8
+ },
dockerfiles: {
gitlab_version: 8.15
}
diff --git a/lib/api/terraform/state.rb b/lib/api/terraform/state.rb
index c664c0a4590..f6dfbcafbb6 100644
--- a/lib/api/terraform/state.rb
+++ b/lib/api/terraform/state.rb
@@ -14,6 +14,8 @@ module API
before do
authenticate!
authorize! :read_terraform_state, user_project
+
+ increment_unique_values('p_terraform_state_api_unique_users', current_user.id)
end
params do
diff --git a/lib/api/usage_data.rb b/lib/api/usage_data.rb
index cad2f52e951..c7d63f8d6ac 100644
--- a/lib/api/usage_data.rb
+++ b/lib/api/usage_data.rb
@@ -4,7 +4,7 @@ module API
class UsageData < ::API::Base
before { authenticate! }
- feature_category :collection
+ feature_category :usage_ping
namespace 'usage_data' do
before do
diff --git a/lib/api/user_counts.rb b/lib/api/user_counts.rb
index 3071f08e1de..31c923a219a 100644
--- a/lib/api/user_counts.rb
+++ b/lib/api/user_counts.rb
@@ -12,7 +12,9 @@ module API
unauthorized! unless current_user
{
- merge_requests: current_user.assigned_open_merge_requests_count
+ merge_requests: current_user.assigned_open_merge_requests_count, # @deprecated
+ assigned_merge_requests: current_user.assigned_open_merge_requests_count,
+ review_requested_merge_requests: current_user.review_requested_open_merge_requests_count
}
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 8b9b82877f7..cee09f60a2b 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -87,6 +87,7 @@ module API
optional :created_before, type: DateTime, desc: 'Return users created before the specified time'
optional :without_projects, type: Boolean, default: false, desc: 'Filters only users without projects'
optional :exclude_internal, as: :non_internal, type: Boolean, default: false, desc: 'Filters only non internal users'
+ optional :admins, type: Boolean, default: false, desc: 'Filters only admin users'
all_or_none_of :extern_uid, :provider
use :sort_params
@@ -745,8 +746,6 @@ module API
optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token'
end
post feature_category: :authentication_and_authorization do
- not_found! unless Feature.enabled?(:pat_creation_api_for_admin)
-
response = ::PersonalAccessTokens::CreateService.new(
current_user: current_user, target_user: target_user, params: declared_params(include_missing: false)
).execute
diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb
index da24d0e20ee..c67fe24d456 100644
--- a/lib/atlassian/jira_connect/client.rb
+++ b/lib/atlassian/jira_connect/client.rb
@@ -16,11 +16,15 @@ module Atlassian
common = { project: project, update_sequence_id: update_sequence_id }
dev_info = args.slice(:commits, :branches, :merge_requests)
build_info = args.slice(:pipelines)
+ deploy_info = args.slice(:deployments)
+ ff_info = args.slice(:feature_flags)
responses = []
responses << store_dev_info(**common, **dev_info) if dev_info.present?
responses << store_build_info(**common, **build_info) if build_info.present?
+ responses << store_deploy_info(**common, **deploy_info) if deploy_info.present?
+ responses << store_ff_info(**common, **ff_info) if ff_info.present?
raise ArgumentError, 'Invalid arguments' if responses.empty?
responses.compact
@@ -28,11 +32,47 @@ 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? }
+
+ return if items.empty?
+
+ r = post('/rest/featureflags/0.1/bulk', {
+ flags: items,
+ properties: { projectId: "project-#{project.id}" }
+ })
+
+ handle_response(r, 'feature flags') do |data|
+ failed = data['failedFeatureFlags']
+ if failed.present?
+ errors = failed.flat_map do |k, errs|
+ errs.map { |e| "#{k}: #{e['message']}" }
+ end
+ { 'errorMessages' => errors }
+ end
+ end
+ 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? }
+
+ return if items.empty?
+
+ r = post('/rest/deployments/0.1/bulk', { deployments: items })
+ handle_response(r, 'deployments') { |data| errors(data, 'rejectedDeployments') }
+ 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 = Serializers::BuildEntity.represent(
+ build = ::Atlassian::JiraConnect::Serializers::BuildEntity.represent(
pipeline,
update_sequence_id: update_sequence_id
)
@@ -42,7 +82,8 @@ module Atlassian
end.compact
return if builds.empty?
- post('/rest/builds/0.1/bulk', { builds: builds })
+ r = post('/rest/builds/0.1/bulk', { builds: builds })
+ handle_response(r, 'builds') { |data| errors(data, 'rejectedBuilds') }
end
def store_dev_info(project:, commits: nil, branches: nil, merge_requests: nil, update_sequence_id: nil)
@@ -75,6 +116,34 @@ module Atlassian
{ providerMetadata: { product: "GitLab #{Gitlab::VERSION}" } }
end
+ def handle_response(response, name, &block)
+ data = response.parsed_response
+
+ case response.code
+ when 200 then yield data
+ when 400 then { 'errorMessages' => data.map { |e| e['message'] } }
+ when 401 then { 'errorMessages' => ['Invalid JWT'] }
+ when 403 then { 'errorMessages' => ["App does not support #{name}"] }
+ when 413 then { 'errorMessages' => ['Data too large'] + data.map { |e| e['message'] } }
+ when 429 then { 'errorMessages' => ['Rate limit exceeded'] }
+ when 503 then { 'errorMessages' => ['Service unavailable'] }
+ else
+ { 'errorMessages' => ['Unknown error'], 'response' => data }
+ end
+ end
+
+ def errors(data, key)
+ messages = if data[key].present?
+ data[key].flat_map do |rejection|
+ rejection['errors'].map { |e| e['message'] }
+ end
+ else
+ []
+ end
+
+ { 'errorMessages' => messages }
+ end
+
def user_notes_count(merge_requests)
return unless merge_requests
diff --git a/lib/atlassian/jira_connect/serializers/build_entity.rb b/lib/atlassian/jira_connect/serializers/build_entity.rb
index 3eb8b1f1978..8372d2a62da 100644
--- a/lib/atlassian/jira_connect/serializers/build_entity.rb
+++ b/lib/atlassian/jira_connect/serializers/build_entity.rb
@@ -25,8 +25,10 @@ module Atlassian
# extract Jira issue keys from either the source branch/ref or the
# merge request title.
@issue_keys ||= begin
- src = "#{pipeline.source_ref} #{pipeline.merge_request&.title}"
- JiraIssueKeyExtractor.new(src).issue_keys
+ pipeline.all_merge_requests.flat_map do |mr|
+ src = "#{mr.source_branch} #{mr.title}"
+ JiraIssueKeyExtractor.new(src).issue_keys
+ end.uniq
end
end
diff --git a/lib/atlassian/jira_connect/serializers/deployment_entity.rb b/lib/atlassian/jira_connect/serializers/deployment_entity.rb
new file mode 100644
index 00000000000..9ef1666b61c
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/deployment_entity.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class DeploymentEntity < Grape::Entity
+ include Gitlab::Routing
+
+ format_with(:iso8601, &:iso8601)
+
+ expose :schema_version, as: :schemaVersion
+ expose :iid, as: :deploymentSequenceNumber
+ expose :update_sequence_id, as: :updateSequenceNumber
+ expose :display_name, as: :displayName
+ expose :description
+ expose :associations
+ expose :url
+ expose :label
+ expose :state
+ expose :updated_at, as: :lastUpdated, format_with: :iso8601
+ expose :pipeline_entity, as: :pipeline
+ expose :environment_entity, as: :environment
+
+ def issue_keys
+ return [] unless build&.pipeline.present?
+
+ @issue_keys ||= BuildEntity.new(build.pipeline).issue_keys
+ end
+
+ private
+
+ delegate :project, :deployable, :environment, :iid, :ref, :short_sha, to: :object
+ alias_method :deployment, :object
+ alias_method :build, :deployable
+
+ def associations
+ keys = issue_keys
+
+ [{ associationType: :issueKeys, values: keys }] if keys.present?
+ end
+
+ def display_name
+ "Deployment #{iid} (#{ref}@#{short_sha}) to #{environment.name}"
+ end
+
+ def label
+ "#{project.full_path}-#{environment.name}-#{iid}-#{short_sha}"
+ end
+
+ def description
+ "Deployment #{deployment.iid} of #{project.name} at #{short_sha} (#{build&.name}) to #{environment.name}"
+ end
+
+ def url
+ # There is no controller action to show a single deployment, so we
+ # link to the build instead
+ project_job_url(project, build) if build
+ end
+
+ def state
+ case deployment.status
+ when 'created' then 'pending'
+ when 'running' then 'in_progress'
+ when 'success' then 'successful'
+ when 'failed' then 'failed'
+ when 'canceled', 'skipped' then 'cancelled'
+ else
+ 'unknown'
+ end
+ end
+
+ def schema_version
+ '1.0'
+ end
+
+ def pipeline_entity
+ PipelineEntity.new(build.pipeline) if build&.pipeline.present?
+ end
+
+ def environment_entity
+ EnvironmentEntity.new(environment)
+ end
+
+ def update_sequence_id
+ options[:update_sequence_id] || Client.generate_update_sequence_id
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/environment_entity.rb b/lib/atlassian/jira_connect/serializers/environment_entity.rb
new file mode 100644
index 00000000000..f3699e4d0ee
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/environment_entity.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class EnvironmentEntity < Grape::Entity
+ format_with(:string, &:to_s)
+
+ expose :id, format_with: :string
+ expose :display_name, as: :displayName
+ expose :type
+
+ private
+
+ alias_method :environment, :object
+ delegate :project, to: :object
+
+ def display_name
+ "#{project.name}/#{environment.name}"
+ end
+
+ def type
+ case environment.name
+ when /prod/i
+ 'production'
+ when /test/i
+ 'testing'
+ when /staging/i
+ 'staging'
+ when /(dev|review)/i
+ 'development'
+ else
+ 'unmapped'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb b/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb
new file mode 100644
index 00000000000..e17c150aacb
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class FeatureFlagEntity < Grape::Entity
+ include Gitlab::Routing
+
+ alias_method :flag, :object
+
+ format_with(:string, &:to_s)
+
+ expose :schema_version, as: :schemaVersion
+ expose :id, format_with: :string
+ expose :name, as: :key
+ expose :update_sequence_id, as: :updateSequenceId
+ expose :name, as: :displayName
+ expose :summary
+ expose :details
+ expose :issue_keys, as: :issueKeys
+
+ def issue_keys
+ @issue_keys ||= JiraIssueKeyExtractor.new(flag.description).issue_keys
+ end
+
+ def schema_version
+ '1.0'
+ end
+
+ def update_sequence_id
+ options[:update_sequence_id] || Client.generate_update_sequence_id
+ end
+
+ STRATEGY_NAMES = {
+ ::Operations::FeatureFlags::Strategy::STRATEGY_DEFAULT => 'All users',
+ ::Operations::FeatureFlags::Strategy::STRATEGY_GITLABUSERLIST => 'User List',
+ ::Operations::FeatureFlags::Strategy::STRATEGY_GRADUALROLLOUTUSERID => 'Percent of users',
+ ::Operations::FeatureFlags::Strategy::STRATEGY_FLEXIBLEROLLOUT => 'Percent rollout',
+ ::Operations::FeatureFlags::Strategy::STRATEGY_USERWITHID => 'User IDs'
+ }.freeze
+
+ private
+
+ # The summary does not map very well to our FeatureFlag model.
+ #
+ # We allow feature flags to have multiple strategies, depending
+ # on the environment. Jira expects a single rollout strategy.
+ #
+ # Also, we don't actually support showing a single flag, so we use the
+ # edit path as an interim solution.
+ def summary(strategies = flag.strategies)
+ {
+ url: project_url(flag.project) + "/-/feature_flags/#{flag.id}/edit",
+ lastUpdated: flag.updated_at.iso8601,
+ status: {
+ enabled: flag.active,
+ defaultValue: '',
+ rollout: {
+ percentage: strategies.map do |s|
+ s.parameters['rollout'] || s.parameters['percentage']
+ end.compact.first&.to_f,
+ text: strategies.map { |s| STRATEGY_NAMES[s.name] }.compact.join(', ')
+ }.compact
+ }
+ }
+ end
+
+ def details
+ envs = flag.strategies.flat_map do |s|
+ s.scopes.map do |es|
+ env_type = es.environment_scope.scan(/development|testing|staging|production/).first
+ [es.environment_scope, env_type, s]
+ end
+ end
+
+ envs.map do |env_name, env_type, strat|
+ summary([strat]).merge(environment: { name: env_name, type: env_type }.compact)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/pipeline_entity.rb b/lib/atlassian/jira_connect/serializers/pipeline_entity.rb
new file mode 100644
index 00000000000..e67cf1a7229
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/pipeline_entity.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ # Both this an BuildEntity represent a Ci::Pipeline
+ class PipelineEntity < Grape::Entity
+ include Gitlab::Routing
+
+ format_with(:string, &:to_s)
+
+ expose :id, format_with: :string
+ expose :display_name, as: :displayName
+ expose :url
+
+ private
+
+ alias_method :pipeline, :object
+ delegate :project, to: :object
+
+ def display_name
+ "#{project.name} pipeline #{pipeline.iid}"
+ end
+
+ def url
+ project_pipeline_url(project, pipeline)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/backup/repositories.rb b/lib/backup/repositories.rb
index 4248a86dc7c..d15114a72a3 100644
--- a/lib/backup/repositories.rb
+++ b/lib/backup/repositories.rb
@@ -40,31 +40,42 @@ module Backup
end
def restore
+ restore_project_repositories
+ restore_snippets
+
+ restore_object_pools
+ end
+
+ private
+
+ def restore_project_repositories
Project.find_each(batch_size: 1000) do |project|
restore_repository(project, Gitlab::GlRepository::PROJECT)
restore_repository(project, Gitlab::GlRepository::WIKI)
restore_repository(project, Gitlab::GlRepository::DESIGN)
end
+ end
+ def restore_snippets
invalid_ids = Snippet.find_each(batch_size: 1000)
.map { |snippet| restore_snippet_repository(snippet) }
.compact
cleanup_snippets_without_repositories(invalid_ids)
-
- restore_object_pools
end
- private
-
def check_valid_storages!
- [ProjectRepository, SnippetRepository].each do |klass|
+ repository_storage_klasses.each do |klass|
if klass.excluding_repository_storage(Gitlab.config.repositories.storages.keys).exists?
raise Error, "repositories.storages in gitlab.yml does not include all storages used by #{klass}"
end
end
end
+ def repository_storage_klasses
+ [ProjectRepository, SnippetRepository]
+ end
+
def backup_repos_path
@backup_repos_path ||= File.join(Gitlab.config.backup.path, 'repositories')
end
@@ -103,12 +114,7 @@ module Backup
end
begin
- case container
- when Project
- dump_project(container)
- when Snippet
- dump_snippet(container)
- end
+ dump_container(container)
rescue => e
errors << e
break
@@ -130,6 +136,15 @@ module Backup
end
end
+ def dump_container(container)
+ case container
+ when Project
+ dump_project(container)
+ when Snippet
+ dump_snippet(container)
+ end
+ end
+
def dump_project(project)
backup_repository(project, Gitlab::GlRepository::PROJECT)
backup_repository(project, Gitlab::GlRepository::WIKI)
@@ -308,3 +323,5 @@ module Backup
end
end
end
+
+Backup::Repositories.prepend_if_ee('EE::Backup::Repositories')
diff --git a/lib/banzai/filter/ascii_doc_sanitization_filter.rb b/lib/banzai/filter/ascii_doc_sanitization_filter.rb
index 11762c3bfb4..67f5baf4635 100644
--- a/lib/banzai/filter/ascii_doc_sanitization_filter.rb
+++ b/lib/banzai/filter/ascii_doc_sanitization_filter.rb
@@ -27,7 +27,7 @@ module Banzai
TABLE_GRID_CLASSES = %w(grid-all grid-rows grid-cols grid-none).freeze
TABLE_STRIPES_CLASSES = %w(stripes-all stripes-odd stripes-even stripes-hover stripes-none).freeze
- ELEMENT_CLASSES_WHITELIST = {
+ ELEMENT_CLASSES_ALLOWLIST = {
span: %w(big small underline overline line-through).freeze,
div: ALIGNMENT_BUILTINS_CLASSES + ['admonitionblock'].freeze,
td: ['icon'].freeze,
@@ -38,35 +38,35 @@ module Banzai
table: TABLE_FRAME_CLASSES + TABLE_GRID_CLASSES + TABLE_STRIPES_CLASSES
}.freeze
- def customize_whitelist(whitelist)
+ def customize_allowlist(allowlist)
# Allow marks
- whitelist[:elements].push('mark')
+ allowlist[:elements].push('mark')
# Allow any classes in `span`, `i`, `div`, `td`, `ul`, `ol` and `a` elements
# but then remove any unknown classes
- whitelist[:attributes]['span'] = %w(class)
- whitelist[:attributes]['div'].push('class')
- whitelist[:attributes]['td'] = %w(class)
- whitelist[:attributes]['i'] = %w(class)
- whitelist[:attributes]['ul'] = %w(class)
- whitelist[:attributes]['ol'] = %w(class)
- whitelist[:attributes]['a'].push('class')
- whitelist[:attributes]['table'] = %w(class)
- whitelist[:transformers].push(self.class.remove_element_classes)
+ allowlist[:attributes]['span'] = %w(class)
+ allowlist[:attributes]['div'].push('class')
+ allowlist[:attributes]['td'] = %w(class)
+ allowlist[:attributes]['i'] = %w(class)
+ allowlist[:attributes]['ul'] = %w(class)
+ allowlist[:attributes]['ol'] = %w(class)
+ allowlist[:attributes]['a'].push('class')
+ allowlist[:attributes]['table'] = %w(class)
+ allowlist[:transformers].push(self.class.remove_element_classes)
# Allow `id` in anchor and footnote elements
- whitelist[:attributes]['a'].push('id')
- whitelist[:attributes]['div'].push('id')
+ allowlist[:attributes]['a'].push('id')
+ allowlist[:attributes]['div'].push('id')
# Allow `id` in heading elements for section anchors
SECTION_HEADINGS.each do |header|
- whitelist[:attributes][header] = %w(id)
+ allowlist[:attributes][header] = %w(id)
end
# Remove ids that are not explicitly allowed
- whitelist[:transformers].push(self.class.remove_disallowed_ids)
+ allowlist[:transformers].push(self.class.remove_disallowed_ids)
- whitelist
+ allowlist
end
class << self
@@ -91,11 +91,11 @@ module Banzai
lambda do |env|
node = env[:node]
- return unless (classes_whitelist = ELEMENT_CLASSES_WHITELIST[node.name.to_sym])
+ return unless (classes_allowlist = ELEMENT_CLASSES_ALLOWLIST[node.name.to_sym])
return unless node.has_attribute?('class')
classes = node['class'].strip.split(' ')
- allowed_classes = (classes & classes_whitelist)
+ allowed_classes = (classes & classes_allowlist)
if allowed_classes.empty?
node.remove_attribute('class')
else
diff --git a/lib/banzai/filter/asset_proxy_filter.rb b/lib/banzai/filter/asset_proxy_filter.rb
index 8acd3917d81..55dc426edaf 100644
--- a/lib/banzai/filter/asset_proxy_filter.rb
+++ b/lib/banzai/filter/asset_proxy_filter.rb
@@ -15,7 +15,7 @@ module Banzai
needs(:asset_proxy, :asset_proxy_secret_key) if asset_proxy_enabled?
end
- def asset_host_whitelisted?(host)
+ def asset_host_allowed?(host)
context[:asset_proxy_domain_regexp] ? context[:asset_proxy_domain_regexp].match?(host) : false
end
@@ -44,21 +44,21 @@ module Banzai
Gitlab.config.asset_proxy['enabled'] = application_settings.asset_proxy_enabled
Gitlab.config.asset_proxy['url'] = application_settings.asset_proxy_url
Gitlab.config.asset_proxy['secret_key'] = application_settings.asset_proxy_secret_key
- Gitlab.config.asset_proxy['whitelist'] = determine_whitelist(application_settings)
- Gitlab.config.asset_proxy['domain_regexp'] = compile_whitelist(Gitlab.config.asset_proxy.whitelist)
+ Gitlab.config.asset_proxy['allowlist'] = determine_allowlist(application_settings)
+ Gitlab.config.asset_proxy['domain_regexp'] = compile_allowlist(Gitlab.config.asset_proxy.allowlist)
else
Gitlab.config.asset_proxy['enabled'] = ::ApplicationSetting.defaults[:asset_proxy_enabled]
end
end
- def self.compile_whitelist(domain_list)
+ def self.compile_allowlist(domain_list)
return if domain_list.empty?
escaped = domain_list.map { |domain| Regexp.escape(domain).gsub('\*', '.*?') }
Regexp.new("^(#{escaped.join('|')})$", Regexp::IGNORECASE)
end
- def self.determine_whitelist(application_settings)
+ def self.determine_allowlist(application_settings)
application_settings.asset_proxy_whitelist.presence || [Gitlab.config.gitlab.host]
end
end
diff --git a/lib/banzai/filter/base_sanitization_filter.rb b/lib/banzai/filter/base_sanitization_filter.rb
index 4f9e8cffd11..c63453f94ca 100644
--- a/lib/banzai/filter/base_sanitization_filter.rb
+++ b/lib/banzai/filter/base_sanitization_filter.rb
@@ -16,42 +16,42 @@ module Banzai
UNSAFE_PROTOCOLS = %w(data javascript vbscript).freeze
- def whitelist
- strong_memoize(:whitelist) do
- whitelist = super.deep_dup
+ def allowlist
+ strong_memoize(:allowlist) do
+ allowlist = super.deep_dup
# Allow span elements
- whitelist[:elements].push('span')
+ allowlist[:elements].push('span')
# Allow data-math-style attribute in order to support LaTeX formatting
- whitelist[:attributes]['code'] = %w(data-math-style)
- whitelist[:attributes]['pre'] = %w(data-math-style data-mermaid-style data-kroki-style)
+ allowlist[:attributes]['code'] = %w(data-math-style)
+ allowlist[:attributes]['pre'] = %w(data-math-style data-mermaid-style data-kroki-style)
# Allow html5 details/summary elements
- whitelist[:elements].push('details')
- whitelist[:elements].push('summary')
+ allowlist[:elements].push('details')
+ allowlist[:elements].push('summary')
# Allow abbr elements with title attribute
- whitelist[:elements].push('abbr')
- whitelist[:attributes]['abbr'] = %w(title)
+ allowlist[:elements].push('abbr')
+ allowlist[:attributes]['abbr'] = %w(title)
# Disallow `name` attribute globally, allow on `a`
- whitelist[:attributes][:all].delete('name')
- whitelist[:attributes]['a'].push('name')
+ allowlist[:attributes][:all].delete('name')
+ allowlist[:attributes]['a'].push('name')
# Allow any protocol in `a` elements
# and then remove links with unsafe protocols
- whitelist[:protocols].delete('a')
- whitelist[:transformers].push(self.class.method(:remove_unsafe_links))
+ allowlist[:protocols].delete('a')
+ allowlist[:transformers].push(self.class.method(:remove_unsafe_links))
# Remove `rel` attribute from `a` elements
- whitelist[:transformers].push(self.class.remove_rel)
+ allowlist[:transformers].push(self.class.remove_rel)
- customize_whitelist(whitelist)
+ customize_allowlist(allowlist)
end
end
- def customize_whitelist(whitelist)
+ def customize_allowlist(allowlist)
raise NotImplementedError
end
diff --git a/lib/banzai/filter/broadcast_message_sanitization_filter.rb b/lib/banzai/filter/broadcast_message_sanitization_filter.rb
index 042293170c8..183908d02a9 100644
--- a/lib/banzai/filter/broadcast_message_sanitization_filter.rb
+++ b/lib/banzai/filter/broadcast_message_sanitization_filter.rb
@@ -6,14 +6,14 @@ module Banzai
#
# Extends Banzai::Filter::BaseSanitizationFilter with specific rules.
class BroadcastMessageSanitizationFilter < Banzai::Filter::BaseSanitizationFilter
- def customize_whitelist(whitelist)
- whitelist[:elements].push('br')
+ def customize_allowlist(allowlist)
+ allowlist[:elements].push('br')
- whitelist[:attributes]['a'].push('class', 'style')
+ allowlist[:attributes]['a'].push('class', 'style')
- whitelist[:css] = { properties: %w(color border background padding margin text-decoration) }
+ allowlist[:css] = { properties: %w(color border background padding margin text-decoration) }
- whitelist
+ allowlist
end
end
end
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index f57e57890f8..f6314040f28 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -9,26 +9,26 @@ module Banzai
# Styles used by Markdown for table alignment
TABLE_ALIGNMENT_PATTERN = /text-align: (?<alignment>center|left|right)/.freeze
- def customize_whitelist(whitelist)
- # Allow table alignment; we whitelist specific text-align values in a
+ def customize_allowlist(allowlist)
+ # Allow table alignment; we allow specific text-align values in a
# transformer below
- whitelist[:attributes]['th'] = %w(style)
- whitelist[:attributes]['td'] = %w(style)
- whitelist[:css] = { properties: ['text-align'] }
+ allowlist[:attributes]['th'] = %w(style)
+ allowlist[:attributes]['td'] = %w(style)
+ allowlist[:css] = { properties: ['text-align'] }
# Allow the 'data-sourcepos' from CommonMark on all elements
- whitelist[:attributes][:all].push('data-sourcepos')
+ allowlist[:attributes][:all].push('data-sourcepos')
# Remove any `style` properties not required for table alignment
- whitelist[:transformers].push(self.class.remove_unsafe_table_style)
+ allowlist[:transformers].push(self.class.remove_unsafe_table_style)
# Allow `id` in a and li elements for footnotes
# and remove any `id` properties not matching for footnotes
- whitelist[:attributes]['a'].push('id')
- whitelist[:attributes]['li'] = %w(id)
- whitelist[:transformers].push(self.class.remove_non_footnote_ids)
+ allowlist[:attributes]['a'].push('id')
+ allowlist[:attributes]['li'] = %w(id)
+ allowlist[:transformers].push(self.class.remove_non_footnote_ids)
- whitelist
+ allowlist
end
class << self
diff --git a/lib/banzai/filter/truncate_source_filter.rb b/lib/banzai/filter/truncate_source_filter.rb
new file mode 100644
index 00000000000..c903b83d868
--- /dev/null
+++ b/lib/banzai/filter/truncate_source_filter.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class TruncateSourceFilter < HTML::Pipeline::TextFilter
+ def call
+ return text unless context.key?(:limit)
+
+ text.truncate_bytes(context[:limit])
+ end
+ end
+ end
+end
diff --git a/lib/banzai/pipeline/description_pipeline.rb b/lib/banzai/pipeline/description_pipeline.rb
index d5ff9b025cc..8f8ce1cbd41 100644
--- a/lib/banzai/pipeline/description_pipeline.rb
+++ b/lib/banzai/pipeline/description_pipeline.rb
@@ -3,14 +3,14 @@
module Banzai
module Pipeline
class DescriptionPipeline < FullPipeline
- WHITELIST = Banzai::Filter::SanitizationFilter::LIMITED.deep_dup.merge(
+ ALLOWLIST = Banzai::Filter::SanitizationFilter::LIMITED.deep_dup.merge(
elements: Banzai::Filter::SanitizationFilter::LIMITED[:elements] - %w(pre code img ol ul li)
)
def self.transform_context(context)
super(context).merge(
# SanitizationFilter
- whitelist: WHITELIST
+ allowlist: ALLOWLIST
)
end
end
diff --git a/lib/banzai/pipeline/pre_process_pipeline.rb b/lib/banzai/pipeline/pre_process_pipeline.rb
index 1f7cb437fcd..eb6f35b0e2a 100644
--- a/lib/banzai/pipeline/pre_process_pipeline.rb
+++ b/lib/banzai/pipeline/pre_process_pipeline.rb
@@ -6,6 +6,7 @@ module Banzai
def self.filters
FilterArray[
Filter::NormalizeSourceFilter,
+ Filter::TruncateSourceFilter,
Filter::FrontMatterFilter,
Filter::BlockquoteFenceFilter,
]
diff --git a/lib/bulk_imports/common/extractors/graphql_extractor.rb b/lib/bulk_imports/common/extractors/graphql_extractor.rb
index c0cef61d2b2..af274ee1299 100644
--- a/lib/bulk_imports/common/extractors/graphql_extractor.rb
+++ b/lib/bulk_imports/common/extractors/graphql_extractor.rb
@@ -11,14 +11,10 @@ module BulkImports
def extract(context)
client = graphql_client(context)
- Enumerator.new do |yielder|
- result = client.execute(
- client.parse(query.to_s),
- query.variables(context.entity)
- )
-
- yielder << result.original_hash.deep_dup
- end
+ client.execute(
+ client.parse(query.to_s),
+ query.variables(context.entity)
+ ).original_hash.deep_dup
end
private
diff --git a/lib/bulk_imports/importers/group_importer.rb b/lib/bulk_imports/importers/group_importer.rb
index 82cb1ca03a2..6e1b86e9515 100644
--- a/lib/bulk_imports/importers/group_importer.rb
+++ b/lib/bulk_imports/importers/group_importer.rb
@@ -8,7 +8,6 @@ module BulkImports
end
def execute
- entity.start!
bulk_import = entity.bulk_import
configuration = bulk_import.configuration
@@ -18,9 +17,7 @@ module BulkImports
configuration: configuration
)
- BulkImports::Groups::Pipelines::GroupPipeline.new.run(context)
- 'BulkImports::EE::Groups::Pipelines::EpicsPipeline'.constantize.new.run(context) if Gitlab.ee?
- BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline.new.run(context)
+ pipelines.each { |pipeline| pipeline.new.run(context) }
entity.finish!
end
@@ -28,6 +25,15 @@ module BulkImports
private
attr_reader :entity
+
+ def pipelines
+ [
+ BulkImports::Groups::Pipelines::GroupPipeline,
+ BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline
+ ]
+ end
end
end
end
+
+BulkImports::Importers::GroupImporter.prepend_if_ee('EE::BulkImports::Importers::GroupImporter')
diff --git a/lib/bulk_imports/importers/groups_importer.rb b/lib/bulk_imports/importers/groups_importer.rb
deleted file mode 100644
index 8641577ff47..00000000000
--- a/lib/bulk_imports/importers/groups_importer.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Importers
- class GroupsImporter
- def initialize(bulk_import_id)
- @bulk_import = BulkImport.find(bulk_import_id)
- end
-
- def execute
- bulk_import.start! unless bulk_import.started?
-
- if entities_to_import.empty?
- bulk_import.finish!
- else
- entities_to_import.each do |entity|
- BulkImports::Importers::GroupImporter.new(entity).execute
- end
-
- # A new BulkImportWorker job is enqueued to either
- # - Process the new BulkImports::Entity created for the subgroups
- # - Or to mark the `bulk_import` as finished.
- BulkImportWorker.perform_async(bulk_import.id)
- end
- end
-
- private
-
- attr_reader :bulk_import
-
- def entities_to_import
- @entities_to_import ||= bulk_import.entities.with_status(:created)
- end
- end
- end
-end
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
index a44f8fc7193..06b81b5da14 100644
--- a/lib/bulk_imports/pipeline.rb
+++ b/lib/bulk_imports/pipeline.rb
@@ -10,16 +10,16 @@ module BulkImports
private
- def extractors
- @extractors ||= self.class.extractors.map(&method(:instantiate))
+ def extractor
+ @extractor ||= instantiate(self.class.get_extractor)
end
def transformers
@transformers ||= self.class.transformers.map(&method(:instantiate))
end
- def loaders
- @loaders ||= self.class.loaders.map(&method(:instantiate))
+ def loader
+ @loaders ||= instantiate(self.class.get_loader)
end
def after_run
@@ -41,7 +41,7 @@ module BulkImports
class_methods do
def extractor(klass, options = nil)
- add_attribute(:extractors, klass, options)
+ class_attributes[:extractor] = { klass: klass, options: options }
end
def transformer(klass, options = nil)
@@ -49,23 +49,23 @@ module BulkImports
end
def loader(klass, options = nil)
- add_attribute(:loaders, klass, options)
+ class_attributes[:loader] = { klass: klass, options: options }
end
def after_run(&block)
class_attributes[:after_run] = block
end
- def extractors
- class_attributes[:extractors]
+ def get_extractor
+ class_attributes[:extractor]
end
def transformers
class_attributes[:transformers]
end
- def loaders
- class_attributes[:loaders]
+ def get_loader
+ class_attributes[:loader]
end
def after_run_callback
diff --git a/lib/bulk_imports/pipeline/runner.rb b/lib/bulk_imports/pipeline/runner.rb
index 88b96f0ab6e..11fb9722173 100644
--- a/lib/bulk_imports/pipeline/runner.rb
+++ b/lib/bulk_imports/pipeline/runner.rb
@@ -12,25 +12,15 @@ module BulkImports
info(context, message: 'Pipeline started', pipeline_class: pipeline)
- extractors.each do |extractor|
- data = run_pipeline_step(:extractor, extractor.class.name, context) do
- extractor.extract(context)
+ Array.wrap(extracted_data_from(context)).each do |entry|
+ transformers.each do |transformer|
+ entry = run_pipeline_step(:transformer, transformer.class.name, context) do
+ transformer.transform(context, entry)
+ end
end
- if data && data.respond_to?(:each)
- data.each do |entry|
- transformers.each do |transformer|
- entry = run_pipeline_step(:transformer, transformer.class.name, context) do
- transformer.transform(context, entry)
- end
- end
-
- loaders.each do |loader|
- run_pipeline_step(:loader, loader.class.name, context) do
- loader.load(context, entry)
- end
- end
- end
+ run_pipeline_step(:loader, loader.class.name, context) do
+ loader.load(context, entry)
end
end
@@ -55,6 +45,12 @@ module BulkImports
mark_as_failed(context) if abort_on_failure?
end
+ def extracted_data_from(context)
+ run_pipeline_step(:extractor, extractor.class.name, context) do
+ extractor.extract(context)
+ end
+ end
+
def mark_as_failed(context)
warn(context, message: 'Pipeline failed', pipeline_class: pipeline)
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index 35f299c17e4..6f5acabe81f 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -22,6 +22,23 @@ module ContainerRegistry
# Taken from: FaradayMiddleware::FollowRedirects
REDIRECT_CODES = Set.new [301, 302, 303, 307]
+ RETRY_EXCEPTIONS = [Faraday::Request::Retry::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed].flatten.freeze
+ RETRY_OPTIONS = {
+ max: 1,
+ interval: 5,
+ exceptions: RETRY_EXCEPTIONS
+ }.freeze
+
+ ERROR_CALLBACK_OPTIONS = {
+ callback: -> (env, exception) do
+ Gitlab::ErrorTracking.log_exception(
+ exception,
+ class: name,
+ url: env[:url]
+ )
+ end
+ }.freeze
+
def self.supports_tag_delete?
registry_config = Gitlab.config.registry
return false unless registry_config.enabled && registry_config.api_url.present?
@@ -97,12 +114,12 @@ module ContainerRegistry
end
def upload_blob(name, content, digest)
- upload = faraday.post("/v2/#{name}/blobs/uploads/")
+ upload = faraday(timeout_enabled: false).post("/v2/#{name}/blobs/uploads/")
return upload unless upload.success?
location = URI(upload.headers['location'])
- faraday.put("#{location.path}?#{location.query}") do |req|
+ faraday(timeout_enabled: false).put("#{location.path}?#{location.query}") do |req|
req.params['digest'] = digest
req.headers['Content-Type'] = 'application/octet-stream'
req.body = content
@@ -137,7 +154,7 @@ module ContainerRegistry
end
def put_tag(name, reference, manifest)
- response = faraday.put("/v2/#{name}/manifests/#{reference}") do |req|
+ response = faraday(timeout_enabled: false).put("/v2/#{name}/manifests/#{reference}") do |req|
req.headers['Content-Type'] = DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE
req.body = Gitlab::Json.pretty_generate(manifest)
end
@@ -158,6 +175,8 @@ module ContainerRegistry
yield(conn) if block_given?
+ conn.request(:retry, RETRY_OPTIONS)
+ conn.request(:gitlab_error_callback, ERROR_CALLBACK_OPTIONS)
conn.adapter :net_http
end
@@ -188,8 +207,8 @@ module ContainerRegistry
faraday_redirect.get(uri)
end
- def faraday
- @faraday ||= faraday_base do |conn|
+ def faraday(timeout_enabled: true)
+ @faraday ||= faraday_base(timeout_enabled: timeout_enabled) do |conn|
initialize_connection(conn, @options, &method(:accept_manifest))
end
end
@@ -205,12 +224,22 @@ module ContainerRegistry
def faraday_redirect
@faraday_redirect ||= faraday_base do |conn|
conn.request :json
+
+ conn.request(:retry, RETRY_OPTIONS)
+ conn.request(:gitlab_error_callback, ERROR_CALLBACK_OPTIONS)
conn.adapter :net_http
end
end
- def faraday_base(&block)
- Faraday.new(@base_uri, headers: { user_agent: "GitLab/#{Gitlab::VERSION}" }, &block)
+ def faraday_base(timeout_enabled: true, &block)
+ request_options = timeout_enabled ? Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS : nil
+
+ Faraday.new(
+ @base_uri,
+ headers: { user_agent: "GitLab/#{Gitlab::VERSION}" },
+ request: request_options,
+ &block
+ )
end
def delete_if_exists(path)
diff --git a/lib/declarative_enum.rb b/lib/declarative_enum.rb
new file mode 100644
index 00000000000..f3c8c181c73
--- /dev/null
+++ b/lib/declarative_enum.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+# Extending this module will give you the ability of defining
+# enum values in a declarative way.
+#
+# module DismissalReasons
+# extend DeclarativeEnum
+#
+# key :dismissal_reason
+# name 'DismissalReasonOfVulnerability'
+#
+# description <<~TEXT
+# This enum holds the user selected dismissal reason
+# when they are dismissing the vulnerabilities
+# TEXT
+#
+# define do
+# acceptable_risk value: 0, description: 'The vulnerability is known but is considered to be an acceptable business risk.'
+# false_positive value: 1, description: 'An error in reporting the presence of a vulnerability in a system when the vulnerability is not present.'
+# used_in_tests value: 2, description: 'The finding is not a vulnerability because it is part of a test or is test data.'
+# end
+#
+# Then we can use this module to register enums for our Active Record models like so,
+#
+# class VulnerabilityFeedback
+# declarative_enum DismissalReasons
+# end
+#
+# Also we can use this module to create GraphQL Enum types like so,
+#
+# module Types
+# module Vulnerabilities
+# class DismissalReasonEnum < BaseEnum
+# declarative_enum DismissalReasons
+# end
+# end
+# end
+#
+# rubocop:disable Gitlab/ModuleWithInstanceVariables
+module DeclarativeEnum
+ # This `prepended` hook will merge the enum definition
+ # of the prepended module into the base module to be
+ # used by `prepend_if_ee` helper method.
+ def prepended(base)
+ base.definition.merge!(definition)
+ end
+
+ def key(new_key = nil)
+ @key = new_key if new_key
+
+ @key
+ end
+
+ def name(new_name = nil)
+ @name = new_name if new_name
+
+ @name
+ end
+
+ def description(new_description = nil)
+ @description = new_description if new_description
+
+ @description
+ end
+
+ def define(&block)
+ raise LocalJumpError.new('No block given') unless block
+
+ @definition = Builder.new(definition, block).build
+ end
+
+ # We can use this method later to apply some sanity checks
+ # but for now, returning a Hash without any check is enough.
+ def definition
+ @definition.to_h
+ end
+
+ class Builder
+ KeyCollisionError = Class.new(StandardError)
+
+ def initialize(definition, block)
+ @definition = definition
+ @block = block
+ end
+
+ def build
+ instance_exec(&@block)
+
+ @definition
+ end
+
+ private
+
+ def method_missing(name, *arguments, value: nil, description: nil, &block)
+ key = name.downcase.to_sym
+ raise KeyCollisionError, "'#{key}' collides with an existing enum key!" if @definition[key]
+
+ @definition[key] = {
+ value: value,
+ description: description
+ }
+ end
+ end
+end
+# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/lib/expand_variables.rb b/lib/expand_variables.rb
index dc8f9d0c970..06cebab8f0a 100644
--- a/lib/expand_variables.rb
+++ b/lib/expand_variables.rb
@@ -16,6 +16,12 @@ module ExpandVariables
end
end
+ def possible_var_reference?(value)
+ return unless value
+
+ %w[$ %].any? { |symbol| value.include?(symbol) }
+ end
+
private
def replace_with(value, variables)
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index 17dfe26bd82..5ad9af6ff7d 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -53,10 +53,12 @@ class Feature
description: 'Short lived, used specifically to run A/B/n experiments.',
optional: true,
rollout_issue: true,
- ee_only: true,
+ ee_only: false,
default_enabled: false,
example: <<-EOS
experiment(:my_experiment, project: project, actor: current_user) { ...variant code... }
+ # or
+ Gitlab::Experimentation.in_experiment_group?(:my_experiment, subject: current_user)
EOS
}
}.freeze
diff --git a/lib/gitlab/analytics/cycle_analytics/default_stages.rb b/lib/gitlab/analytics/cycle_analytics/default_stages.rb
index 22aa680cbc1..43683ae174e 100644
--- a/lib/gitlab/analytics/cycle_analytics/default_stages.rb
+++ b/lib/gitlab/analytics/cycle_analytics/default_stages.rb
@@ -30,6 +30,10 @@ module Gitlab
all.map { |stage| stage[:name] }
end
+ def self.symbolized_stage_names
+ names.map(&:to_sym)
+ end
+
def self.params_for_issue_stage
{
name: 'issue',
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events.rb b/lib/gitlab/analytics/cycle_analytics/stage_events.rb
index 39dc706dff5..27fc8bd9a1a 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events.rb
@@ -11,6 +11,7 @@ module Gitlab
ENUM_MAPPING = {
StageEvents::IssueCreated => 1,
StageEvents::IssueFirstMentionedInCommit => 2,
+ StageEvents::IssueDeployedToProduction => 3,
StageEvents::MergeRequestCreated => 100,
StageEvents::MergeRequestFirstDeployedToProduction => 101,
StageEvents::MergeRequestLastBuildFinished => 102,
@@ -18,8 +19,7 @@ module Gitlab
StageEvents::MergeRequestMerged => 104,
StageEvents::CodeStageStart => 1_000,
StageEvents::IssueStageEnd => 1_001,
- StageEvents::PlanStageStart => 1_002,
- StageEvents::ProductionStageEnd => 1_003
+ StageEvents::PlanStageStart => 1_002
}.freeze
EVENTS = ENUM_MAPPING.keys.freeze
@@ -27,8 +27,7 @@ module Gitlab
INTERNAL_EVENTS = [
StageEvents::CodeStageStart,
StageEvents::IssueStageEnd,
- StageEvents::PlanStageStart,
- StageEvents::ProductionStageEnd
+ StageEvents::PlanStageStart
].freeze
# Defines which start_event and end_event pairs are allowed
@@ -41,7 +40,7 @@ module Gitlab
],
StageEvents::IssueCreated => [
StageEvents::IssueStageEnd,
- StageEvents::ProductionStageEnd
+ StageEvents::IssueDeployedToProduction
],
StageEvents::MergeRequestCreated => [
StageEvents::MergeRequestMerged
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production.rb
new file mode 100644
index 00000000000..3e93e60e686
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module StageEvents
+ class IssueDeployedToProduction < StageEvent
+ def self.name
+ _("Issue first deployed to production")
+ end
+
+ def self.identifier
+ :issue_deployed_to_production
+ end
+
+ def object_type
+ Issue
+ end
+
+ def timestamp_projection
+ mr_metrics_table[:first_deployed_to_production_at]
+ end
+
+ override :column_list
+ def column_list
+ [timestamp_projection]
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def apply_query_customization(query)
+ query.joins(merge_requests_closing_issues: { merge_request: [:metrics] }).where(mr_metrics_table[:first_deployed_to_production_at].gteq(mr_table[:created_at]))
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
deleted file mode 100644
index b778364a917..00000000000
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Analytics
- module CycleAnalytics
- module StageEvents
- class ProductionStageEnd < StageEvent
- def self.name
- _("Issue first deployed to production")
- end
-
- def self.identifier
- :production_stage_end
- end
-
- def object_type
- Issue
- end
-
- def timestamp_projection
- mr_metrics_table[:first_deployed_to_production_at]
- end
-
- override :column_list
- def column_list
- [timestamp_projection]
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def apply_query_customization(query)
- query.joins(merge_requests_closing_issues: { merge_request: [:metrics] }).where(mr_metrics_table[:first_deployed_to_production_at].gteq(mr_table[:created_at]))
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/analytics/unique_visits.rb b/lib/gitlab/analytics/unique_visits.rb
index 292048dcad9..e367d33d743 100644
--- a/lib/gitlab/analytics/unique_visits.rb
+++ b/lib/gitlab/analytics/unique_visits.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
class UniqueVisits
def track_visit(visitor_id, target_id, time = Time.zone.now)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, target_id, time)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(target_id, values: visitor_id, time: time)
end
# Returns number of unique visitors for given targets in given time frame
diff --git a/lib/gitlab/api_authentication/builder.rb b/lib/gitlab/api_authentication/builder.rb
new file mode 100644
index 00000000000..717c664826a
--- /dev/null
+++ b/lib/gitlab/api_authentication/builder.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# Authentication Strategies Builder
+#
+# AuthBuilder and its child classes, TokenType and SentThrough, support
+# declaring allowed authentication strategies with patterns like
+# `accept.token_type(:job_token).sent_through(:http_basic)`.
+module Gitlab
+ module APIAuthentication
+ class Builder
+ def build
+ strategies = Hash.new([])
+ yield ::Gitlab::APIAuthentication::TokenTypeBuilder.new(strategies)
+ strategies
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/api_authentication/sent_through_builder.rb b/lib/gitlab/api_authentication/sent_through_builder.rb
new file mode 100644
index 00000000000..f66e5960019
--- /dev/null
+++ b/lib/gitlab/api_authentication/sent_through_builder.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# See Gitlab::APIAuthentication::Builder
+module Gitlab
+ module APIAuthentication
+ class SentThroughBuilder
+ def initialize(strategies, resolvers)
+ @strategies = strategies
+ @resolvers = resolvers
+ end
+
+ def sent_through(*locators)
+ locators.each do |locator|
+ @strategies[locator] |= @resolvers
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/api_authentication/token_locator.rb b/lib/gitlab/api_authentication/token_locator.rb
new file mode 100644
index 00000000000..32a98908e5b
--- /dev/null
+++ b/lib/gitlab/api_authentication/token_locator.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module APIAuthentication
+ class TokenLocator
+ UsernameAndPassword = Struct.new(:username, :password)
+
+ include ActiveModel::Validations
+ include ActionController::HttpAuthentication::Basic
+
+ attr_reader :location
+
+ validates :location, inclusion: { in: %i[http_basic_auth] }
+
+ def initialize(location)
+ @location = location
+ validate!
+ end
+
+ def extract(request)
+ case @location
+ when :http_basic_auth
+ extract_from_http_basic_auth request
+ end
+ end
+
+ private
+
+ def extract_from_http_basic_auth(request)
+ username, password = user_name_and_password(request)
+ return unless username.present? && password.present?
+
+ UsernameAndPassword.new(username, password)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/api_authentication/token_resolver.rb b/lib/gitlab/api_authentication/token_resolver.rb
new file mode 100644
index 00000000000..5b30777b6ec
--- /dev/null
+++ b/lib/gitlab/api_authentication/token_resolver.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module APIAuthentication
+ class TokenResolver
+ include ActiveModel::Validations
+
+ attr_reader :token_type
+
+ validates :token_type, inclusion: { in: %i[personal_access_token job_token deploy_token] }
+
+ def initialize(token_type)
+ @token_type = token_type
+ validate!
+ end
+
+ # Existing behavior is known to be inconsistent across authentication
+ # methods with regards to whether to silently ignore present but invalid
+ # credentials or to raise an error/respond with 401.
+ #
+ # If a token can be located from the provided credentials, but the token
+ # or credentials are in some way invalid, this implementation opts to
+ # raise an error.
+ #
+ # For example, if the raw credentials include a username and password, and
+ # a token is resolved from the password, but the username does not match
+ # the token, an error will be raised.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/246569
+
+ def resolve(raw)
+ case @token_type
+ when :personal_access_token
+ resolve_personal_access_token raw
+
+ when :job_token
+ resolve_job_token raw
+
+ when :deploy_token
+ resolve_deploy_token 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
+
+ # 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
+ end
+
+ def resolve_job_token(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
+
+ # 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
+
+ job
+ end
+
+ def resolve_deploy_token(raw)
+ # Check if the password is a deploy token
+ 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
+
+ token
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/api_authentication/token_type_builder.rb b/lib/gitlab/api_authentication/token_type_builder.rb
new file mode 100644
index 00000000000..4a57cdc2742
--- /dev/null
+++ b/lib/gitlab/api_authentication/token_type_builder.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# See Gitlab::Auth::AuthBuilder
+module Gitlab
+ module APIAuthentication
+ class TokenTypeBuilder
+ def initialize(strategies)
+ @strategies = strategies
+ end
+
+ def token_types(*resolvers)
+ ::Gitlab::APIAuthentication::SentThroughBuilder.new(@strategies, resolvers)
+ end
+
+ alias_method :token_type, :token_types
+ end
+ end
+end
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index 84fe3d1c959..cefe983848c 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -12,6 +12,7 @@ module Gitlab
Attribute.new(:namespace, Namespace),
Attribute.new(:user, User),
Attribute.new(:caller_id, String),
+ Attribute.new(:remote_ip, String),
Attribute.new(:related_class, String),
Attribute.new(:feature_category, String)
].freeze
@@ -45,6 +46,7 @@ module Gitlab
hash[:project] = -> { project_path } if set_values.include?(:project)
hash[:root_namespace] = -> { root_namespace_path } if include_namespace?
hash[:caller_id] = caller_id if set_values.include?(:caller_id)
+ hash[:remote_ip] = remote_ip if set_values.include?(:remote_ip)
hash[:related_class] = related_class if set_values.include?(:related_class)
hash[:feature_category] = feature_category if set_values.include?(:feature_category)
end
diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb
index caa881eeeab..4c6254c9e69 100644
--- a/lib/gitlab/auth/auth_finders.rb
+++ b/lib/gitlab/auth/auth_finders.rb
@@ -92,10 +92,10 @@ module Gitlab
# We only allow Private Access Tokens with `api` scope to be used by web
# requests on RSS feeds or ICS files for backwards compatibility.
# It is also used by GraphQL/API requests.
- def find_user_from_web_access_token(request_format)
+ def find_user_from_web_access_token(request_format, scopes: [:api])
return unless access_token && valid_web_access_format?(request_format)
- validate_access_token!(scopes: [:api])
+ validate_access_token!(scopes: scopes)
::PersonalAccessTokens::LastUsedService.new(access_token).execute
@@ -194,11 +194,15 @@ module Gitlab
def access_token
strong_memoize(:access_token) do
- # The token can be a PAT or an OAuth (doorkeeper) token
- # It is also possible that a PAT is encapsulated in a `Bearer` OAuth token
- # (e.g. NPM client registry auth), this case will be properly handled
- # by find_personal_access_token
- find_oauth_access_token || find_personal_access_token
+ if try(:namespace_inheritable, :authentication)
+ access_token_from_namespace_inheritable
+ else
+ # The token can be a PAT or an OAuth (doorkeeper) token
+ # It is also possible that a PAT is encapsulated in a `Bearer` OAuth token
+ # (e.g. NPM client registry auth), this case will be properly handled
+ # by find_personal_access_token
+ find_oauth_access_token || find_personal_access_token
+ end
end
end
diff --git a/lib/gitlab/auth/ldap/config.rb b/lib/gitlab/auth/ldap/config.rb
index f5931a1d5eb..97e4f921228 100644
--- a/lib/gitlab/auth/ldap/config.rb
+++ b/lib/gitlab/auth/ldap/config.rb
@@ -28,7 +28,7 @@ module Gitlab
end
def self.servers
- Gitlab.config.ldap['servers']&.values || []
+ Gitlab.config.ldap.servers&.values || []
end
def self.available_servers
@@ -42,9 +42,18 @@ module Gitlab
end
def self.providers
- servers.map { |server| server['provider_name'] }
+ provider_names_from_servers(servers)
end
+ def self.available_providers
+ provider_names_from_servers(available_servers)
+ end
+
+ def self.provider_names_from_servers(servers)
+ servers&.map { |server| server['provider_name'] } || []
+ end
+ private_class_method :provider_names_from_servers
+
def self.valid_provider?(provider)
providers.include?(provider)
end
diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb
index d28ee54cfbc..504265a83ef 100644
--- a/lib/gitlab/auth/request_authenticator.rb
+++ b/lib/gitlab/auth/request_authenticator.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def find_sessionless_user(request_format)
- find_user_from_web_access_token(request_format) ||
+ find_user_from_web_access_token(request_format, scopes: [:api, :read_api]) ||
find_user_from_feed_token(request_format) ||
find_user_from_static_object_token(request_format) ||
find_user_from_basic_auth_job ||
diff --git a/lib/gitlab/background_migration/backfill_artifact_expiry_date.rb b/lib/gitlab/background_migration/backfill_artifact_expiry_date.rb
new file mode 100644
index 00000000000..0a8c203421b
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_artifact_expiry_date.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfill expire_at for a range of Ci::JobArtifact
+ class BackfillArtifactExpiryDate
+ include Gitlab::Utils::StrongMemoize
+
+ BATCH_SIZE = 1_000
+ DEFAULT_EXPIRATION_SWITCH_DATE = Date.new(2020, 6, 22).freeze
+ OLD_ARTIFACT_AGE = 15.months
+ OLD_ARTIFACT_EXPIRY_OFFSET = 3.months
+ RECENT_ARTIFACT_EXPIRY_OFFSET = 1.year
+
+ # Ci::JobArtifact model
+ class Ci::JobArtifact < ActiveRecord::Base
+ include ::EachBatch
+
+ self.table_name = 'ci_job_artifacts'
+
+ scope :between, -> (start_id, end_id) { where(id: start_id..end_id) }
+ scope :before_default_expiration_switch, -> { where('created_at < ?', DEFAULT_EXPIRATION_SWITCH_DATE) }
+ scope :without_expiry_date, -> { where(expire_at: nil) }
+ scope :old, -> { where(self.arel_table[:created_at].lt(OLD_ARTIFACT_AGE.ago)) }
+ scope :recent, -> { where(self.arel_table[:created_at].gt(OLD_ARTIFACT_AGE.ago)) }
+ end
+
+ def perform(start_id, end_id)
+ Ci::JobArtifact.between(start_id, end_id)
+ .without_expiry_date.before_default_expiration_switch
+ .each_batch(of: BATCH_SIZE) do |batch|
+ batch.old.update_all(expire_at: old_artifact_expiry_date)
+ batch.recent.update_all(expire_at: recent_artifact_expiry_date)
+ end
+ end
+
+ private
+
+ def offset_date
+ strong_memoize(:offset_date) do
+ current_date = Time.current
+ target_date = Time.zone.local(current_date.year, current_date.month, 22, 0, 0, 0)
+
+ current_date.day < 22 ? target_date : target_date.next_month
+ end
+ end
+
+ def old_artifact_expiry_date
+ offset_date + OLD_ARTIFACT_EXPIRY_OFFSET
+ end
+
+ def recent_artifact_expiry_date
+ offset_date + RECENT_ARTIFACT_EXPIRY_OFFSET
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
new file mode 100644
index 00000000000..16c0de39a3b
--- /dev/null
+++ b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Background migration that extends CopyColumn to update the value of a
+ # column using the value of another column in the same table.
+ #
+ # - The {start_id, end_id} arguments are at the start so that it can be used
+ # with `queue_background_migration_jobs_by_range_at_intervals`
+ # - Provides support for background job tracking through the use of
+ # Gitlab::Database::BackgroundMigrationJob
+ # - Uses sub-batching so that we can keep each update's execution time at
+ # low 100s ms, while being able to update more records per 2 minutes
+ # that we allow background migration jobs to be scheduled one after the other
+ # - We skip the NULL checks as they may result in not using an index scan
+ # - The table that is migrated does _not_ need `id` as the primary key
+ # We use the provided primary_key column to perform the update.
+ class CopyColumnUsingBackgroundMigrationJob
+ include Gitlab::Database::DynamicModelHelpers
+
+ PAUSE_SECONDS = 0.1
+
+ # start_id - The start ID of the range of rows to update.
+ # end_id - The end ID of the range of rows to update.
+ # table - The name of the table that contains the columns.
+ # primary_key - The primary key column of the table.
+ # copy_from - The column containing the data to copy.
+ # copy_to - The column to copy the data to.
+ # sub_batch_size - We don't want updates to take more than ~100ms
+ # This allows us to run multiple smaller batches during
+ # the minimum 2.minute interval that we can schedule jobs
+ def perform(start_id, end_id, table, primary_key, copy_from, copy_to, sub_batch_size)
+ quoted_copy_from = connection.quote_column_name(copy_from)
+ quoted_copy_to = connection.quote_column_name(copy_to)
+
+ parent_batch_relation = relation_scoped_to_range(table, primary_key, start_id, end_id)
+
+ parent_batch_relation.each_batch(column: primary_key, of: sub_batch_size) do |sub_batch|
+ sub_batch.update_all("#{quoted_copy_to}=#{quoted_copy_from}")
+
+ sleep(PAUSE_SECONDS)
+ end
+
+ # We have to add all arguments when marking a job as succeeded as they
+ # are all used to track the job by `queue_background_migration_jobs_by_range_at_intervals`
+ mark_job_as_succeeded(start_id, end_id, table, primary_key, copy_from, copy_to, sub_batch_size)
+ end
+
+ private
+
+ def connection
+ ActiveRecord::Base.connection
+ end
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(self.class.name, arguments)
+ end
+
+ def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
+ define_batchable_model(source_table).where(source_key_column => start_id..stop_id)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb b/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb
new file mode 100644
index 00000000000..52b09e07fd5
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class populates the `finding_uuid` attribute for
+ # the existing `vulnerability_feedback` records.
+ class PopulateFindingUuidForVulnerabilityFeedback
+ REPORT_TYPES = {
+ sast: 0,
+ dependency_scanning: 1,
+ container_scanning: 2,
+ dast: 3,
+ secret_detection: 4,
+ coverage_fuzzing: 5,
+ api_fuzzing: 6
+ }.freeze
+
+ class VulnerabilityFeedback < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include EachBatch
+
+ self.table_name = 'vulnerability_feedback'
+
+ enum category: REPORT_TYPES
+
+ scope :in_range, -> (start, stop) { where(id: start..stop) }
+ scope :without_uuid, -> { where(finding_uuid: nil) }
+
+ def self.load_vulnerability_findings
+ all.to_a.tap { |collection| collection.each(&:vulnerability_finding) }
+ end
+
+ def set_finding_uuid
+ return unless vulnerability_finding.present? && vulnerability_finding.primary_identifier.present?
+
+ update_column(:finding_uuid, calculated_uuid)
+ rescue StandardError => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
+ end
+
+ def vulnerability_finding
+ BatchLoader.for(finding_key).batch(replace_methods: false) do |finding_keys, loader|
+ project_ids = finding_keys.map { |key| key[:project_id] }
+ categories = finding_keys.map { |key| key[:category] }
+ fingerprints = finding_keys.map { |key| key[:project_fingerprint] }
+
+ findings = Finding.with_primary_identifier.where(
+ project_id: project_ids.uniq,
+ report_type: categories.uniq,
+ project_fingerprint: fingerprints.uniq
+ ).to_a
+
+ finding_keys.each do |finding_key|
+ loader.call(
+ finding_key,
+ findings.find { |f| finding_key == f.finding_key }
+ )
+ end
+ end
+ end
+
+ private
+
+ def calculated_uuid
+ Gitlab::UUID.v5(uuid_components)
+ end
+
+ def uuid_components
+ [
+ category,
+ vulnerability_finding.primary_identifier.fingerprint,
+ vulnerability_finding.location_fingerprint,
+ project_id
+ ].join('-')
+ end
+
+ def finding_key
+ {
+ project_id: project_id,
+ category: category,
+ project_fingerprint: project_fingerprint
+ }
+ end
+ end
+
+ class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include ShaAttribute
+
+ self.table_name = 'vulnerability_occurrences'
+
+ sha_attribute :project_fingerprint
+ sha_attribute :location_fingerprint
+
+ belongs_to :primary_identifier, class_name: 'Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback::Identifier'
+
+ enum report_type: REPORT_TYPES
+
+ scope :with_primary_identifier, -> { includes(:primary_identifier) }
+
+ def finding_key
+ {
+ project_id: project_id,
+ category: report_type,
+ project_fingerprint: project_fingerprint
+ }
+ end
+ end
+
+ class Identifier < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'vulnerability_identifiers'
+ end
+
+ def perform(*range)
+ feedback = VulnerabilityFeedback.without_uuid.in_range(*range).load_vulnerability_findings
+ feedback.each(&:set_finding_uuid)
+
+ log_info(feedback.count)
+ end
+
+ def log_info(feedback_count)
+ ::Gitlab::BackgroundMigration::Logger.info(
+ migrator: self.class.name,
+ message: '`finding_uuid` attributes has been set',
+ count: feedback_count
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/remove_duplicate_services.rb b/lib/gitlab/background_migration/remove_duplicate_services.rb
new file mode 100644
index 00000000000..59fb9143a72
--- /dev/null
+++ b/lib/gitlab/background_migration/remove_duplicate_services.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Remove duplicated service records with the same project and type.
+ # These were created in the past for unknown reasons, and should be blocked
+ # now by the uniqueness validation in the Service model.
+ class RemoveDuplicateServices
+ # See app/models/service
+ class Service < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'services'
+ self.inheritance_column = :_type_disabled
+
+ scope :project_ids_with_duplicates, -> do
+ select(:project_id)
+ .distinct
+ .where.not(project_id: nil)
+ .group(:project_id, :type)
+ .having('count(*) > 1')
+ end
+
+ scope :types_with_duplicates, -> (project_ids) do
+ select(:project_id, :type)
+ .where(project_id: project_ids)
+ .group(:project_id, :type)
+ .having('count(*) > 1')
+ end
+ end
+
+ def perform(*project_ids)
+ types_with_duplicates = Service.types_with_duplicates(project_ids).pluck(:project_id, :type)
+
+ types_with_duplicates.each do |project_id, type|
+ remove_duplicates(project_id, type)
+ end
+ end
+
+ private
+
+ def remove_duplicates(project_id, type)
+ scope = Service.where(project_id: project_id, type: type)
+
+ # Build a subquery to determine which service record is actually in use,
+ # by querying for it without specifying an order.
+ #
+ # This should match the record returned by `Project#find_service`,
+ # and the `has_one` service associations on `Project`.
+ correct_service = scope.select(:id).limit(1)
+
+ # Delete all other services with the same `project_id` and `type`
+ duplicate_services = scope.where.not(id: correct_service)
+ duplicate_services.delete_all
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/diff_check.rb b/lib/gitlab/checks/diff_check.rb
index c0b228dee59..b146fea66b9 100644
--- a/lib/gitlab/checks/diff_check.rb
+++ b/lib/gitlab/checks/diff_check.rb
@@ -6,37 +6,20 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
LOG_MESSAGES = {
- validate_file_paths: "Validating diffs' file paths...",
- diff_content_check: "Validating diff contents..."
+ validate_file_paths: "Validating diffs' file paths..."
}.freeze
def validate!
return if deletion?
- return unless should_run_diff_validations?
+ return unless should_run_validations?
return if commits.empty?
- file_paths = []
-
- if ::Feature.enabled?(:diff_check_with_paths_changed_rpc, project, default_enabled: true)
- paths = project.repository.find_changed_paths(commits.map(&:sha))
- paths.each do |path|
- file_paths.concat([path.path])
-
- validate_diff(path)
- end
- else
- process_commits do |commit|
- validate_once(commit) do
- commit.raw_deltas.each do |diff|
- file_paths.concat([diff.new_path, diff.old_path].compact)
-
- validate_diff(diff)
- end
- end
- end
+ paths = project.repository.find_changed_paths(commits.map(&:sha))
+ paths.each do |path|
+ validate_path(path)
end
- validate_file_paths(file_paths.uniq)
+ validate_file_paths(paths.map(&:path).uniq)
end
private
@@ -47,43 +30,30 @@ module Gitlab
end
end
- def should_run_diff_validations?
- validations_for_diff.present? || path_validations.present?
+ def should_run_validations?
+ validations_for_path.present? || file_paths_validations.present?
end
- def validate_diff(diff)
- validations_for_diff.each do |validation|
- if error = validation.call(diff)
+ def validate_path(path)
+ validations_for_path.each do |validation|
+ if error = validation.call(path)
raise ::Gitlab::GitAccess::ForbiddenError, error
end
end
end
# Method overwritten in EE to inject custom validations
- def validations_for_diff
+ def validations_for_path
[]
end
- def path_validations
+ def file_paths_validations
validate_lfs_file_locks? ? [lfs_file_locks_validation] : []
end
- def process_commits
- logger.log_timed(LOG_MESSAGES[:diff_content_check]) do
- # n+1: https://gitlab.com/gitlab-org/gitlab/issues/3593
- ::Gitlab::GitalyClient.allow_n_plus_1_calls do
- commits.each do |commit|
- logger.check_timeout_reached
-
- yield(commit)
- end
- end
- end
- end
-
def validate_file_paths(file_paths)
logger.log_timed(LOG_MESSAGES[__method__]) do
- path_validations.each do |validation|
+ file_paths_validations.each do |validation|
if error = validation.call(file_paths)
raise ::Gitlab::GitAccess::ForbiddenError, error
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 071a8ef830f..8ed4dc61920 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -70,6 +70,10 @@ module Gitlab
@normalized_jobs ||= Ci::Config::Normalizer.new(jobs).normalize_jobs
end
+ def included_templates
+ @context.expandset.filter_map { |i| i[:template] }
+ end
+
private
def expand_config(config)
@@ -98,7 +102,8 @@ module Gitlab
project: project,
sha: sha || project&.repository&.root_ref_sha,
user: user,
- parent_pipeline: parent_pipeline)
+ parent_pipeline: parent_pipeline,
+ variables: project&.predefined_variables&.to_runner_variables)
end
def track_and_raise_for_dev_exception(error)
diff --git a/lib/gitlab/ci/config/entry/artifacts.rb b/lib/gitlab/ci/config/entry/artifacts.rb
index 206dbaea272..6118ff49928 100644
--- a/lib/gitlab/ci/config/entry/artifacts.rb
+++ b/lib/gitlab/ci/config/entry/artifacts.rb
@@ -12,7 +12,7 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[name untracked paths reports when expire_in expose_as exclude].freeze
+ ALLOWED_KEYS = %i[name untracked paths reports when expire_in expose_as exclude public].freeze
EXPOSE_AS_REGEX = /\A\w[-\w ]*\z/.freeze
EXPOSE_AS_ERROR_MESSAGE = "can contain only letters, digits, '-', '_' and spaces"
@@ -27,6 +27,7 @@ module Gitlab
with_options allow_nil: true do
validates :name, type: String
+ validates :public, boolean: true
validates :untracked, boolean: true
validates :paths, array_of_strings: true
validates :paths, array_of_strings: {
diff --git a/lib/gitlab/ci/config/external/context.rb b/lib/gitlab/ci/config/external/context.rb
index cf6c2961ee7..e0adb1b19c2 100644
--- a/lib/gitlab/ci/config/external/context.rb
+++ b/lib/gitlab/ci/config/external/context.rb
@@ -7,14 +7,15 @@ module Gitlab
class Context
TimeoutError = Class.new(StandardError)
- attr_reader :project, :sha, :user, :parent_pipeline
+ attr_reader :project, :sha, :user, :parent_pipeline, :variables
attr_reader :expandset, :execution_deadline
- def initialize(project: nil, sha: nil, user: nil, parent_pipeline: nil)
+ def initialize(project: nil, sha: nil, user: nil, parent_pipeline: nil, variables: [])
@project = project
@sha = sha
@user = user
@parent_pipeline = parent_pipeline
+ @variables = variables
@expandset = Set.new
@execution_deadline = 0
diff --git a/lib/gitlab/ci/config/external/file/local.rb b/lib/gitlab/ci/config/external/file/local.rb
index e74f5b33de7..fdb3e1b00f9 100644
--- a/lib/gitlab/ci/config/external/file/local.rb
+++ b/lib/gitlab/ci/config/external/file/local.rb
@@ -41,7 +41,8 @@ module Gitlab
project: context.project,
sha: context.sha,
user: context.user,
- parent_pipeline: context.parent_pipeline
+ parent_pipeline: context.parent_pipeline,
+ variables: context.variables
}
end
end
diff --git a/lib/gitlab/ci/config/external/file/project.rb b/lib/gitlab/ci/config/external/file/project.rb
index be479741784..114d493381c 100644
--- a/lib/gitlab/ci/config/external/file/project.rb
+++ b/lib/gitlab/ci/config/external/file/project.rb
@@ -72,7 +72,8 @@ module Gitlab
project: project,
sha: sha,
user: context.user,
- parent_pipeline: context.parent_pipeline
+ parent_pipeline: context.parent_pipeline,
+ variables: context.variables
}
end
end
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index 90692eafc3f..4d91cfd4c57 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -34,6 +34,7 @@ module Gitlab
.compact
.map(&method(:normalize_location))
.flat_map(&method(:expand_project_files))
+ .map(&method(:expand_variables))
.each(&method(:verify_duplicates!))
.map(&method(:select_first_matching))
end
@@ -47,14 +48,14 @@ module Gitlab
# convert location if String to canonical form
def normalize_location(location)
if location.is_a?(String)
- normalize_location_string(location)
+ expanded_location = expand_variables(location)
+ normalize_location_string(expanded_location)
else
location.deep_symbolize_keys
end
end
def expand_project_files(location)
- return location unless ::Feature.enabled?(:ci_include_multiple_files_from_project, context.project, default_enabled: true)
return location unless location[:project]
Array.wrap(location[:file]).map do |file|
@@ -96,6 +97,33 @@ module Gitlab
matching.first
end
+
+ def expand_variables(data)
+ return data unless ::Feature.enabled?(:variables_in_include_section_ci)
+
+ if data.is_a?(String)
+ expand(data)
+ else
+ transform(data)
+ end
+ end
+
+ def transform(data)
+ data.transform_values do |values|
+ case values
+ when Array
+ values.map { |value| expand(value.to_s) }
+ when String
+ expand(values)
+ else
+ values
+ end
+ end
+ end
+
+ def expand(data)
+ ExpandVariables.expand(data, context.variables)
+ end
end
end
end
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index af1df933b36..7956cf14203 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -56,23 +56,19 @@ module Gitlab
end
def self.pipeline_open_merge_requests?(project)
- ::Feature.enabled?(:ci_pipeline_open_merge_requests, project, default_enabled: false)
- end
-
- def self.seed_block_run_before_workflow_rules_enabled?(project)
- ::Feature.enabled?(:ci_seed_block_run_before_workflow_rules, project, default_enabled: true)
+ ::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: false)
+ ::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)
+ ::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: false)
+ ::Feature.enabled?(:ci_rules_variables, project, default_enabled: true)
end
end
end
diff --git a/lib/gitlab/ci/lint.rb b/lib/gitlab/ci/lint.rb
index fb795152abe..364e67db02b 100644
--- a/lib/gitlab/ci/lint.rb
+++ b/lib/gitlab/ci/lint.rb
@@ -18,9 +18,10 @@ module Gitlab
end
end
- def initialize(project:, current_user:)
+ def initialize(project:, current_user:, sha: nil)
@project = project
@current_user = current_user
+ @sha = sha || project.repository.commit.sha
end
def validate(content, dry_run: false)
@@ -51,7 +52,7 @@ module Gitlab
content,
project: @project,
user: @current_user,
- sha: @project.repository.commit.sha
+ sha: @sha
).execute
Result.new(
@@ -99,7 +100,8 @@ module Gitlab
except: job[:except],
environment: job[:environment],
when: job[:when],
- allow_failure: job[:allow_failure]
+ allow_failure: job[:allow_failure],
+ needs: job.dig(:needs_attributes)
}
end
end
diff --git a/lib/gitlab/ci/parsers.rb b/lib/gitlab/ci/parsers.rb
index 57f73c265b2..985639982aa 100644
--- a/lib/gitlab/ci/parsers.rb
+++ b/lib/gitlab/ci/parsers.rb
@@ -15,8 +15,8 @@ module Gitlab
}
end
- def self.fabricate!(file_type)
- parsers.fetch(file_type.to_sym).new
+ def self.fabricate!(file_type, *args)
+ parsers.fetch(file_type.to_sym).new(*args)
rescue KeyError
raise ParserNotFoundError, "Cannot find any parser matching file type '#{file_type}'"
end
diff --git a/lib/gitlab/ci/parsers/coverage/cobertura.rb b/lib/gitlab/ci/parsers/coverage/cobertura.rb
index 1edcbac2f25..eb3adf713d4 100644
--- a/lib/gitlab/ci/parsers/coverage/cobertura.rb
+++ b/lib/gitlab/ci/parsers/coverage/cobertura.rb
@@ -36,7 +36,7 @@ module Gitlab
end
def parse_node(key, value, coverage_report, context)
- if key == 'sources' && value['source'].present?
+ if key == 'sources' && value && value['source'].present?
parse_sources(value['source'], context)
elsif key == 'package'
Array.wrap(value).each do |item|
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index 9662209f88e..f0548284001 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -5,6 +5,9 @@ module Gitlab
module Pipeline
module Chain
class Build < Chain::Base
+ include Gitlab::Allowable
+ include Chain::Helpers
+
def perform!
@pipeline.assign_attributes(
source: @command.source,
@@ -20,12 +23,34 @@ module Gitlab
pipeline_schedule: @command.schedule,
merge_request: @command.merge_request,
external_pull_request: @command.external_pull_request,
- variables_attributes: Array(@command.variables_attributes)
+ locked: @command.project.latest_pipeline_locked,
+ variables_attributes: variables_attributes
)
end
def break?
- false
+ @pipeline.errors.any?
+ end
+
+ private
+
+ def variables_attributes
+ variables = Array(@command.variables_attributes)
+
+ # We allow parent pipelines to pass variables to child pipelines since
+ # these variables are coming from internal configurations. We will check
+ # permissions to :set_pipeline_variables when those are injected upstream,
+ # to the parent pipeline.
+ # In other scenarios (e.g. multi-project pipelines or run pipeline via UI)
+ # the variables are provided from the outside and those should be guarded.
+ return variables if @command.creates_child_pipeline?
+
+ if variables.present? && !can?(@command.current_user, :set_pipeline_variables, @command.project)
+ error("Insufficient permissions to set pipeline variables")
+ variables = []
+ end
+
+ variables
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index d05be54267c..815fe6bac6d 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -79,6 +79,10 @@ module Gitlab
bridge&.parent_pipeline
end
+ def creates_child_pipeline?
+ bridge&.triggers_child_pipeline?
+ end
+
def metrics
@metrics ||= ::Gitlab::Ci::Pipeline::Metrics.new
end
diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb
index 083f0bec1df..7b537125b9b 100644
--- a/lib/gitlab/ci/pipeline/chain/seed.rb
+++ b/lib/gitlab/ci/pipeline/chain/seed.rb
@@ -19,13 +19,6 @@ module Gitlab
# Build to prevent erroring out on ambiguous refs.
pipeline.protected = @command.protected_ref?
- unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project)
- ##
- # Populate pipeline with block argument of CreatePipelineService#execute.
- #
- @command.seeds_block&.call(pipeline)
- end
-
##
# Gather all runtime build/stage errors
#
diff --git a/lib/gitlab/ci/pipeline/chain/seed_block.rb b/lib/gitlab/ci/pipeline/chain/seed_block.rb
index f8e62949bea..67424635603 100644
--- a/lib/gitlab/ci/pipeline/chain/seed_block.rb
+++ b/lib/gitlab/ci/pipeline/chain/seed_block.rb
@@ -9,8 +9,6 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
def perform!
- return unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project)
-
##
# Populate pipeline with block argument of CreatePipelineService#execute.
#
@@ -20,8 +18,6 @@ module Gitlab
end
def break?
- return false unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project)
-
pipeline.errors.any?
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/template_usage.rb b/lib/gitlab/ci/pipeline/chain/template_usage.rb
new file mode 100644
index 00000000000..c1a7b4ed453
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/template_usage.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class TemplateUsage < Chain::Base
+ def perform!
+ included_templates.each do |template|
+ track_event(template)
+ end
+ end
+
+ def break?
+ false
+ end
+
+ private
+
+ def track_event(template)
+ Gitlab::UsageDataCounters::CiTemplateUniqueCounter
+ .track_unique_project_event(project_id: pipeline.project_id, template: template)
+ end
+
+ def included_templates
+ command.yaml_processor_result.included_templates
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/abilities.rb b/lib/gitlab/ci/pipeline/chain/validate/abilities.rb
index 8f1e690c081..e68d9020a21 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/abilities.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/abilities.rb
@@ -19,7 +19,7 @@ module Gitlab
end
unless allowed_to_write_ref?
- error("Insufficient permissions for protected ref '#{command.ref}'")
+ error("You do not have sufficient permission to run a pipeline on '#{command.ref}'. Please select a different branch or contact your administrator for assistance. <a href=https://docs.gitlab.com/ee/ci/pipelines/#pipeline-security-on-protected-branches>Learn more</a>".html_safe)
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 2271915a72b..fe3c2bca551 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -134,7 +134,7 @@ module Gitlab
stage.seeds_names.include?(need[:name])
end
- "#{name}: needs '#{need[:name]}'" unless result
+ "'#{name}' job needs '#{need[:name]}' job, but it was not added to the pipeline" unless result
end.compact
end
diff --git a/lib/gitlab/ci/reports/test_failure_history.rb b/lib/gitlab/ci/reports/test_failure_history.rb
index beceac5423a..c024e794ad5 100644
--- a/lib/gitlab/ci/reports/test_failure_history.rb
+++ b/lib/gitlab/ci/reports/test_failure_history.rb
@@ -12,8 +12,6 @@ module Gitlab
end
def load!
- return unless Feature.enabled?(:test_failure_history, project)
-
recent_failures_count.each do |key_hash, count|
failed_test_cases[key_hash].set_recent_failures(count, project.default_branch_or_master)
end
diff --git a/lib/gitlab/ci/status/group/factory.rb b/lib/gitlab/ci/status/group/factory.rb
index ee785856fdd..37e2b7320e2 100644
--- a/lib/gitlab/ci/status/group/factory.rb
+++ b/lib/gitlab/ci/status/group/factory.rb
@@ -8,6 +8,10 @@ module Gitlab
def self.common_helpers
Status::Group::Common
end
+
+ def self.extended_statuses
+ [[Status::SuccessWarning]]
+ end
end
end
end
diff --git a/lib/gitlab/ci/syntax_templates/Artifacts example.gitlab-ci.yml b/lib/gitlab/ci/syntax_templates/Artifacts example.gitlab-ci.yml
new file mode 100644
index 00000000000..7182b96594d
--- /dev/null
+++ b/lib/gitlab/ci/syntax_templates/Artifacts example.gitlab-ci.yml
@@ -0,0 +1,52 @@
+#
+# You can use artifacts to pass data to jobs in later stages.
+# For more information, see https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html
+#
+
+stages:
+ - build
+ - test
+ - deploy
+
+build-job:
+ stage: build
+ script:
+ - echo "This job might build an important file, and pass it to later jobs."
+ - echo "This is the content of the important file" > important-file.txt
+ artifacts:
+ paths:
+ - important-file.txt
+
+test-job-with-artifacts:
+ stage: test
+ script:
+ - echo "This job uses the artifact from the job in the earlier stage."
+ - cat important-file.txt
+ - echo "It creates another file, and adds it to the artifacts."
+ - echo "This is a second important file" > important-file2.txt
+ artifacts:
+ paths:
+ - important-file2.txt
+
+test-job-with-no-artifacts:
+ stage: test
+ dependencies: [] # Use to skip downloading any artifacts
+ script:
+ - echo "This job does not get the artifacts from other jobs."
+ - cat important-file.txt || exit 0
+
+deploy-job-with-all-artifacts:
+ stage: deploy
+ script:
+ - echo "By default, jobs download all available artifacts."
+ - cat important-file.txt
+ - cat important-file2.txt
+
+deploy-job-with-1-artifact:
+ stage: deploy
+ dependencies:
+ - build-job # Download artifacts from only this job
+ script:
+ - echo "You can configure a job to download artifacts from only certain jobs."
+ - cat important-file.txt
+ - cat important-file2.txt || exit 0
diff --git a/lib/gitlab/ci/syntax_templates/Before_script and after_script example.gitlab-ci.yml b/lib/gitlab/ci/syntax_templates/Before_script and after_script example.gitlab-ci.yml
new file mode 100644
index 00000000000..382bac09ed7
--- /dev/null
+++ b/lib/gitlab/ci/syntax_templates/Before_script and after_script example.gitlab-ci.yml
@@ -0,0 +1,36 @@
+#
+# You can define common tasks and run them before or after the main scripts in jobs.
+# For more information, see:
+# - https://docs.gitlab.com/ee/ci/yaml/README.html#before_script
+# - https://docs.gitlab.com/ee/ci/yaml/README.html#after_script
+#
+
+stages:
+ - test
+
+default:
+ before_script:
+ - echo "This script runs before the main script in every job, unless the job overrides it."
+ - echo "It may set up common dependencies, for example."
+ after_script:
+ - echo "This script runs after the main script in every job, unless the job overrides it."
+ - echo "It may do some common final clean up tasks"
+
+job-standard:
+ stage: test
+ script:
+ - echo "This job uses both of the globally defined before and after scripts."
+
+job-override-before:
+ stage: test
+ before_script:
+ - echo "Use a different before_script in this job."
+ script:
+ - echo "This job uses its own before_script, and the global after_script."
+
+job-override-after:
+ stage: test
+ after_script:
+ - echo "Use a different after_script in this job."
+ script:
+ - echo "This job uses its own after_script, and the global before_script."
diff --git a/lib/gitlab/ci/syntax_templates/Manual jobs example.gitlab-ci.yml b/lib/gitlab/ci/syntax_templates/Manual jobs example.gitlab-ci.yml
new file mode 100644
index 00000000000..5f27def74c9
--- /dev/null
+++ b/lib/gitlab/ci/syntax_templates/Manual jobs example.gitlab-ci.yml
@@ -0,0 +1,53 @@
+#
+# A manual job is a type of job that is not executed automatically and must be explicitly started by a user.
+# To make a job manual, add when: manual to its configuration.
+# For more information, see https://docs.gitlab.com/ee/ci/yaml/README.html#whenmanual
+#
+
+stages:
+ - build
+ - test
+ - deploy
+
+build-job:
+ stage: build
+ script:
+ - echo "This job is not a manual job"
+
+manual-build:
+ stage: build
+ script:
+ - echo "This manual job passes after you trigger it."
+ when: manual
+
+manual-build-allowed-to-fail:
+ stage: build
+ script:
+ - echo "This manual job fails after you trigger it."
+ - echo "It is allowed to fail, so the pipeline does not fail.
+ when: manual
+ allow_failure: true # Default behavior
+
+test-job:
+ stage: test
+ script:
+ - echo "This is a normal test job"
+ - echo "It runs when the when the build stage completes."
+ - echo "It does not need to wait for the manual jobs in the build stage to run."
+
+manual-test-not-allowed-to-fail:
+ stage: test
+ script:
+ - echo "This manual job fails after you trigger it."
+ - echo "It is NOT allowed to fail, so the pipeline is marked as failed
+ - echo "when this job completes."
+ - exit 1
+ when: manual
+ allow_failure: false # Optional behavior
+
+deploy-job:
+ stage: deploy
+ script:
+ - echo "This is a normal deploy job"
+ - echo "If a manual job that isn't allowed to fail ran in an earlier stage and failed,
+ - echo "this job does not run".
diff --git a/lib/gitlab/ci/syntax_templates/Multi-stage pipeline example.gitlab-ci.yml b/lib/gitlab/ci/syntax_templates/Multi-stage pipeline example.gitlab-ci.yml
new file mode 100644
index 00000000000..aced628aacb
--- /dev/null
+++ b/lib/gitlab/ci/syntax_templates/Multi-stage pipeline example.gitlab-ci.yml
@@ -0,0 +1,33 @@
+#
+# A pipeline is composed of independent jobs that run scripts, grouped into stages.
+# Stages run in sequential order, but jobs within stages run in parallel.
+# For more information, see: https://docs.gitlab.com/ee/ci/yaml/README.html#stages
+#
+
+stages:
+ - build
+ - test
+ - deploy
+
+build-job:
+ stage: build
+ script:
+ - echo "This job runs in the build stage, which runs first."
+
+test-job1:
+ stage: test
+ script:
+ - echo "This job runs in the test stage."
+ - echo "It only starts when the job in the build stage completes successfully."
+
+test-job2:
+ stage: test
+ script:
+ - echo "This job also runs in the test stage."
+ - echo "This job can run at the same time as test-job2."
+
+deploy-job:
+ stage: deploy
+ script:
+ - echo "This job runs in the deploy stage."
+ - echo "It only runs when both jobs in the test stage complete successfully"
diff --git a/lib/gitlab/ci/syntax_templates/Variables example.gitlab-ci.yml b/lib/gitlab/ci/syntax_templates/Variables example.gitlab-ci.yml
new file mode 100644
index 00000000000..2b8cf7bab44
--- /dev/null
+++ b/lib/gitlab/ci/syntax_templates/Variables example.gitlab-ci.yml
@@ -0,0 +1,47 @@
+#
+# Variables can be used to for more dynamic behavior in jobs and scripts.
+# For more information, see https://docs.gitlab.com/ee/ci/variables/README.html
+#
+
+stages:
+ - test
+
+variables:
+ VAR1: "Variable 1 defined globally"
+
+use-a-variable:
+ stage: test
+ script:
+ - echo "You can use variables in jobs."
+ - echo "The content of 'VAR1' is = $VAR1"
+
+override-a-variable:
+ stage: test
+ variables:
+ VAR1: "Variable 1 was overriden in in the job."
+ script:
+ - echo "You can override global variables in jobs."
+ - echo "The content of 'VAR1' is = $VAR1"
+
+define-a-new-variable:
+ stage: test
+ variables:
+ VAR2: "Variable 2 is new and defined in the job only."
+ script:
+ - echo "You can mix global variables with variables defined in jobs."
+ - echo "The content of 'VAR1' is = $VAR1"
+ - echo "The content of 'VAR2' is = $VAR2"
+
+incorrect-variable-usage:
+ stage: test
+ script:
+ - echo "You can't use variables only defined in other jobs."
+ - echo "The content of 'VAR2' is = $VAR2"
+
+predefined-variables:
+ stage: test
+ script:
+ - echo "Some variables are predefined by GitLab CI/CD, for example:"
+ - echo "The commit author's username is $GITLAB_USER_LOGIN"
+ - echo "The commit branch is $CI_COMMIT_BRANCH"
+ - echo "The project path is $CI_PROJECT_PATH"
diff --git a/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml b/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml
new file mode 100644
index 00000000000..c06ef83c180
--- /dev/null
+++ b/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml
@@ -0,0 +1,84 @@
+# This template is on early stage of development.
+# Use it with caution. For usage instruction please read
+# https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/blob/v2.3.0/README.md
+
+include:
+ # workflow rules to prevent duplicate detached pipelines
+ - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
+ # auto devops build
+ - template: 'Jobs/Build.gitlab-ci.yml'
+
+stages:
+ - build
+ - test
+ - provision
+ - deploy
+ - destroy
+
+variables:
+ TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_COMMIT_REF_SLUG}
+ TF_VAR_ENVIRONMENT_NAME: ${CI_PROJECT_PATH_SLUG}_${CI_PROJECT_ID}_${CI_COMMIT_REF_SLUG}
+ TF_VAR_SERVICE_DESK_EMAIL: incoming+${CI_PROJECT_PATH_SLUG}-${CI_PROJECT_ID}-issue-@incoming.gitlab.com
+ TF_VAR_SHORT_ENVIRONMENT_NAME: ${CI_PROJECT_ID}-${CI_COMMIT_REF_SLUG}
+ TF_VAR_SMTP_FROM: ${SMTP_FROM}
+
+cache:
+ paths:
+ - .terraform
+
+.needs_aws_vars:
+ rules:
+ - if: '$AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY && $AWS_DEFAULT_REGION'
+ when: on_success
+ - when: never
+
+terraform_apply:
+ stage: provision
+ image: registry.gitlab.com/gitlab-org/5-minute-production-app/deploy-template/stable
+ extends: .needs_aws_vars
+ resource_group: terraform
+ before_script:
+ - cp /*.tf .
+ - cp /deploy.sh .
+ script:
+ - gitlab-terraform init
+ - gitlab-terraform plan
+ - gitlab-terraform plan-json
+ - gitlab-terraform apply
+
+deploy:
+ stage: deploy
+ image: registry.gitlab.com/gitlab-org/5-minute-production-app/deploy-template/stable
+ extends: .needs_aws_vars
+ resource_group: deploy
+ before_script:
+ - cp /*.tf .
+ - cp /deploy.sh .
+ - cp /conf.nginx .
+ script:
+ - ./deploy.sh
+ artifacts:
+ reports:
+ dotenv: deploy.env
+ environment:
+ name: $CI_COMMIT_REF_SLUG
+ url: $DYNAMIC_ENVIRONMENT_URL
+ on_stop: terraform_destroy
+
+terraform_destroy:
+ variables:
+ GIT_STRATEGY: none
+ stage: destroy
+ image: registry.gitlab.com/gitlab-org/5-minute-production-app/deploy-template/stable
+ before_script:
+ - cp /*.tf .
+ - cp /deploy.sh .
+ script:
+ - gitlab-terraform destroy -auto-approve
+ environment:
+ name: $CI_COMMIT_REF_SLUG
+ action: stop
+ rules:
+ - if: '$AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY && $AWS_DEFAULT_REGION && $CI_COMMIT_REF_PROTECTED == "false"'
+ when: manual
+ - when: never
diff --git a/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml b/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
new file mode 100644
index 00000000000..504ece611ca
--- /dev/null
+++ b/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
@@ -0,0 +1,29 @@
+code_quality:
+ stage: test
+ image: "cirrusci/flutter:1.22.5"
+ before_script:
+ - pub global activate dart_code_metrics
+ - export PATH="$PATH":"$HOME/.pub-cache/bin"
+ script:
+ - metrics lib -r codeclimate > gl-code-quality-report.json
+ artifacts:
+ reports:
+ codequality: gl-code-quality-report.json
+
+test:
+ stage: test
+ image: "cirrusci/flutter:1.22.5"
+ before_script:
+ - pub global activate junitreport
+ - export PATH="$PATH":"$HOME/.pub-cache/bin"
+ script:
+ - flutter test --machine --coverage | tojunit -o report.xml
+ - lcov --summary coverage/lcov.info
+ - genhtml coverage/lcov.info --output=coverage
+ coverage: '/lines\.*: \d+\.\d+\%/'
+ artifacts:
+ name: coverage
+ paths:
+ - $CI_PROJECT_DIR/coverage
+ reports:
+ junit: report.xml
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 2ae9730ec1a..501d8737acd 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.18-gitlab.1"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.19"
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 23dfeda31cc..192b1509fdc 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.36.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.37.0"
environment:
name: production
variables:
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..fc1acd09714
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -0,0 +1,43 @@
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/
+
+# Configure the scanning tool through the environment variables.
+# List of the variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
+# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+
+variables:
+ DAST_VERSION: 1
+ # Setting this variable will affect all Security templates
+ # (SAST, Dependency Scanning, ...)
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+
+dast:
+ stage: dast
+ image:
+ name: "$SECURE_ANALYZERS_PREFIX/dast:$DAST_VERSION"
+ variables:
+ GIT_STRATEGY: none
+ allow_failure: true
+ script:
+ - export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
+ - if [ -z "$DAST_WEBSITE$DAST_API_SPECIFICATION" ]; then echo "Either DAST_WEBSITE or DAST_API_SPECIFICATION must be set. See https://docs.gitlab.com/ee/user/application_security/dast/#configuration for more details." && exit 1; fi
+ - /analyze
+ artifacts:
+ reports:
+ dast: gl-dast-report.json
+ rules:
+ - if: $DAST_DISABLED
+ when: never
+ - if: $DAST_DISABLED_FOR_DEFAULT_BRANCH &&
+ $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
+ when: never
+ - if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME &&
+ $REVIEW_DISABLED && $DAST_WEBSITE == null &&
+ $DAST_API_SPECIFICATION == null
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $CI_KUBERNETES_ACTIVE &&
+ $GITLAB_FEATURES =~ /\bdast\b/
+ - if: $CI_COMMIT_BRANCH &&
+ $DAST_WEBSITE
+ - if: $CI_COMMIT_BRANCH &&
+ $DAST_API_SPECIFICATION
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index f4ee8ebd47e..56c6fbd96bc 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -10,6 +10,7 @@ variables:
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_EXCLUDED_ANALYZERS: ""
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SAST_ANALYZER_IMAGE_TAG: 2
SCAN_KUBERNETES_MANIFESTS: "false"
@@ -44,6 +45,8 @@ bandit-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /bandit/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /bandit/
exists:
@@ -58,6 +61,8 @@ brakeman-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /brakeman/
exists:
@@ -72,6 +77,8 @@ eslint-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /eslint/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /eslint/
exists:
@@ -90,6 +97,8 @@ flawfinder-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /flawfinder/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /flawfinder/
exists:
@@ -105,6 +114,8 @@ kubesec-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /kubesec/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /kubesec/ &&
$SCAN_KUBERNETES_MANIFESTS == 'true'
@@ -118,6 +129,8 @@ gosec-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /gosec/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /gosec/
exists:
@@ -136,6 +149,8 @@ mobsf-android-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /mobsf/ &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
@@ -155,6 +170,8 @@ mobsf-ios-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /mobsf/ &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
@@ -170,6 +187,8 @@ nodejs-scan-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /nodejs-scan/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /nodejs-scan/
exists:
@@ -184,6 +203,8 @@ phpcs-security-audit-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /phpcs-security-audit/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /phpcs-security-audit/
exists:
@@ -198,6 +219,8 @@ pmd-apex-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /pmd-apex/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /pmd-apex/
exists:
@@ -212,6 +235,8 @@ security-code-scan-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /security-code-scan/
exists:
@@ -227,6 +252,8 @@ sobelow-sast:
rules:
- if: $SAST_DISABLED
when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /sobelow/
+ when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /sobelow/
exists:
@@ -239,6 +266,8 @@ spotbugs-sast:
variables:
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
rules:
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /spotbugs/
+ when: never
- if: $SAST_DEFAULT_ANALYZERS =~ /mobsf/ &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
diff --git a/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
index 8ca1d2e08ba..d2a6fa06dd8 100644
--- a/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
@@ -37,6 +37,7 @@ secret_detection:
when: never
- if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
script:
+ - if [[ $CI_COMMIT_TAG ]]; then echo "Skipping Secret Detection for tags. No code changes have occurred."; exit 0; fi
- git fetch origin $CI_DEFAULT_BRANCH $CI_COMMIT_REF_NAME
- git log --left-right --cherry-pick --pretty=format:"%H" refs/remotes/origin/$CI_DEFAULT_BRANCH...refs/remotes/origin/$CI_COMMIT_REF_NAME > "$CI_COMMIT_SHA"_commit_list.txt
- export SECRET_DETECTION_COMMITS_FILE="$CI_COMMIT_SHA"_commit_list.txt
diff --git a/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
index 377c72e8031..7e2828d010f 100644
--- a/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
@@ -17,6 +17,7 @@ variables:
cache:
paths:
- .terraform
+ - .terraform.lock.hcl
before_script:
- alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
diff --git a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
index 910e711f046..c2db0fc44f1 100644
--- a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
@@ -19,6 +19,7 @@ cache:
key: "${TF_ROOT}"
paths:
- ${TF_ROOT}/.terraform/
+ - ${TF_ROOT}/.terraform.lock.hcl
.init: &init
stage: init
diff --git a/lib/gitlab/ci/variables/collection/sorted.rb b/lib/gitlab/ci/variables/collection/sorted.rb
new file mode 100644
index 00000000000..6abc6a5644f
--- /dev/null
+++ b/lib/gitlab/ci/variables/collection/sorted.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Variables
+ class Collection
+ class Sorted
+ include TSort
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(variables)
+ @variables = variables
+ end
+
+ def valid?
+ errors.nil?
+ end
+
+ # 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)
+
+ strong_memoize(:errors) do
+ # Check for cyclic dependencies and build error message in that case
+ errors = each_strongly_connected_component.filter_map do |component|
+ component.map { |v| v[:key] }.inspect if component.size > 1
+ end
+
+ "circular variable reference detected: #{errors.join(', ')}" if errors.any?
+ end
+ end
+
+ # 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 errors
+
+ tsort
+ end
+
+ private
+
+ def tsort_each_node(&block)
+ @variables.each(&block)
+ end
+
+ def tsort_each_child(variable, &block)
+ each_variable_reference(variable[:value], &block)
+ end
+
+ def input_vars
+ strong_memoize(:input_vars) do
+ @variables.index_by { |env| env.fetch(:key) }
+ end
+ end
+
+ def walk_references(value)
+ return unless ExpandVariables.possible_var_reference?(value)
+
+ value.scan(ExpandVariables::VARIABLES_REGEXP) do |var_ref|
+ yield(input_vars, var_ref.first)
+ end
+ end
+
+ def each_variable_reference(value)
+ walk_references(value) do |vars_hash, ref_var_name|
+ variable = vars_hash.dig(ref_var_name)
+ yield variable if variable
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb
index ee55eb8b22a..dc4951f76bb 100644
--- a/lib/gitlab/ci/yaml_processor.rb
+++ b/lib/gitlab/ci/yaml_processor.rb
@@ -10,12 +10,6 @@ module Gitlab
class YamlProcessor
ValidationError = Class.new(StandardError)
- def self.validation_message(content, opts = {})
- result = new(content, opts).execute
-
- result.errors.first
- end
-
def initialize(config_content, opts = {})
@config_content = config_content
@opts = opts
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index cd7d781a574..86749cda9c7 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -53,6 +53,10 @@ module Gitlab
@stages ||= @ci_config.stages
end
+ def included_templates
+ @included_templates ||= @ci_config.included_templates
+ end
+
def build_attributes(name)
job = jobs.fetch(name.to_sym, {})
diff --git a/lib/gitlab/composer/version_index.rb b/lib/gitlab/composer/version_index.rb
new file mode 100644
index 00000000000..de9a17a453f
--- /dev/null
+++ b/lib/gitlab/composer/version_index.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Composer
+ class VersionIndex
+ include API::Helpers::RelatedResourcesHelpers
+
+ def initialize(packages)
+ @packages = packages
+ end
+
+ def as_json(_options = nil)
+ { 'packages' => { @packages.first.name => package_versions_map } }
+ end
+
+ def sha
+ Digest::SHA256.hexdigest(to_json)
+ end
+
+ private
+
+ def package_versions_map
+ @packages.each_with_object({}) do |package, map|
+ map[package.version] = package_metadata(package)
+ end
+ end
+
+ def package_metadata(package)
+ json = package.composer_metadatum.composer_json
+
+ json.merge('dist' => package_dist(package), 'uid' => package.id, 'version' => package.version)
+ end
+
+ def package_dist(package)
+ sha = package.composer_metadatum.target_sha
+ archive_api_path = api_v4_projects_packages_composer_archives_package_name_path({ id: package.project_id, package_name: package.name, format: '.zip' }, true)
+
+ {
+ 'type' => 'zip',
+ 'url' => expose_url(archive_api_path) + "?sha=#{sha}",
+ 'reference' => sha,
+ 'shasum' => ''
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
index 4d7590a8e38..fbf021345ca 100644
--- a/lib/gitlab/conflict/file.rb
+++ b/lib/gitlab/conflict/file.rb
@@ -9,9 +9,13 @@ module Gitlab
CONTEXT_LINES = 3
+ CONFLICT_MARKER_OUR = 'conflict_marker_our'
+ CONFLICT_MARKER_THEIR = 'conflict_marker_their'
+ CONFLICT_MARKER_SEPARATOR = 'conflict_marker'
+
CONFLICT_TYPES = {
- "old" => "conflict_marker_their",
- "new" => "conflict_marker_our"
+ "old" => "conflict_their",
+ "new" => "conflict_our"
}.freeze
attr_reader :merge_request
@@ -59,18 +63,25 @@ module Gitlab
if section[:conflict]
lines = []
- initial_type = nil
+ lines << create_separator_line(section[:lines].first, CONFLICT_MARKER_OUR)
+
+ current_type = section[:lines].first.type
section[:lines].each do |line|
- if line.type != initial_type
- lines << create_separator_line(line)
- initial_type = line.type
+ if line.type != current_type # insert a separator between our changes and theirs
+ lines << create_separator_line(line, CONFLICT_MARKER_SEPARATOR)
+ current_type = line.type
end
line.type = CONFLICT_TYPES[line.type]
+
+ # Swap the positions around due to conflicts/diffs display inconsistency
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/291989
+ line.old_pos, line.new_pos = line.new_pos, line.old_pos
+
lines << line
end
- lines << create_separator_line(lines.last)
+ lines << create_separator_line(lines.last, CONFLICT_MARKER_THEIR)
lines
else
@@ -156,8 +167,8 @@ module Gitlab
Gitlab::Diff::Line.new('', 'match', line.index, line.old_pos, line.new_pos)
end
- def create_separator_line(line)
- Gitlab::Diff::Line.new('', 'conflict_marker', line.index, nil, nil)
+ def create_separator_line(line, type)
+ Gitlab::Diff::Line.new('', type, line.index, nil, nil)
end
# Any line beginning with a letter, an underscore, or a dollar can be used in a
diff --git a/lib/gitlab/cycle_analytics/base_event_fetcher.rb b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
deleted file mode 100644
index 6c6dd90e450..00000000000
--- a/lib/gitlab/cycle_analytics/base_event_fetcher.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class BaseEventFetcher
- include BaseQuery
- include GroupProjectsProvider
-
- attr_reader :projections, :query, :stage, :options
-
- MAX_EVENTS = 50
-
- def initialize(stage:, options:)
- @stage = stage
- @options = options
- end
-
- def fetch
- update_author!
-
- event_result.map do |event|
- serialize(event) if has_permission?(event['id'])
- end.compact
- end
-
- def order
- @order || default_order
- end
-
- private
-
- def update_author!
- return unless event_result.any? && event_result.first['author_id']
-
- Updater.update!(event_result, from: 'author_id', to: 'author', klass: User)
- end
-
- def event_result
- @event_result ||= ActiveRecord::Base.connection.exec_query(events_query.to_sql).to_a
- end
-
- def events_query
- diff_fn = subtract_datetimes_diff(base_query, options[:start_time_attrs], options[:end_time_attrs])
-
- base_query.project(extract_diff_epoch(diff_fn).as('total_time'), *projections).order(order.desc).take(MAX_EVENTS)
- end
-
- def default_order
- [options[:start_time_attrs]].flatten.first
- end
-
- def serialize(_event)
- raise NotImplementedError.new("Expected #{self.name} to implement serialize(event)")
- end
-
- def has_permission?(id)
- allowed_ids.nil? || allowed_ids.include?(id.to_i)
- end
-
- def allowed_ids
- @allowed_ids ||= allowed_ids_finder_class
- .new(options[:current_user], allowed_ids_source)
- .execute.where(id: event_result_ids).pluck(:id)
- end
-
- def event_result_ids
- event_result.map { |event| event['id'] }
- end
-
- def allowed_ids_source
- group ? { group_id: group.id, include_subgroups: true } : { project_id: project.id }
- end
-
- def serialization_context
- {}
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/base_query.rb b/lib/gitlab/cycle_analytics/base_query.rb
deleted file mode 100644
index 6aedbf64f26..00000000000
--- a/lib/gitlab/cycle_analytics/base_query.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module BaseQuery
- include MetricsTables
- include Gitlab::Database::Median
- include Gitlab::Database::DateTime
-
- private
-
- def base_query
- @base_query ||= stage_query(projects.map(&:id))
- end
-
- def stage_query(project_ids)
- query = mr_closing_issues_table.join(issue_table).on(issue_table[:id].eq(mr_closing_issues_table[:issue_id]))
- .join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
- .join(projects_table).on(issue_table[:project_id].eq(projects_table[:id]))
- .join(routes_table).on(projects_table[:namespace_id].eq(routes_table[:source_id]))
- .project(issue_table[:project_id].as("project_id"))
- .project(projects_table[:path].as("project_path"))
- .project(routes_table[:path].as("namespace_path"))
-
- query = limit_query(query, project_ids)
- query = limit_query_by_date_range(query)
-
- # Load merge_requests
-
- query = load_merge_requests(query)
-
- query
- end
-
- def limit_query(query, project_ids)
- query.where(issue_table[:project_id].in(project_ids))
- .where(routes_table[:source_type].eq('Namespace'))
- end
-
- def limit_query_by_date_range(query)
- query = query.where(issue_table[:created_at].gteq(options[:from]))
- query = query.where(issue_table[:created_at].lteq(options[:to])) if options[:to]
- query
- end
-
- def load_merge_requests(query)
- query.join(mr_table, Arel::Nodes::OuterJoin)
- .on(mr_table[:id].eq(mr_closing_issues_table[:merge_request_id]))
- .join(mr_metrics_table)
- .on(mr_table[:id].eq(mr_metrics_table[:merge_request_id]))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/base_stage.rb b/lib/gitlab/cycle_analytics/base_stage.rb
deleted file mode 100644
index 06f0cbed147..00000000000
--- a/lib/gitlab/cycle_analytics/base_stage.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class BaseStage
- include BaseQuery
- include GroupProjectsProvider
-
- attr_reader :options
-
- def initialize(options:)
- @options = options
- end
-
- def events
- event_fetcher.fetch
- end
-
- def as_json(serializer: AnalyticsStageSerializer)
- serializer.new.represent(self)
- end
-
- def title
- raise NotImplementedError.new("Expected #{self.name} to implement title")
- end
-
- def project_median
- return if project.nil?
-
- BatchLoader.for(project.id).batch(key: name) do |project_ids, loader|
- if project_ids.one?
- loader.call(project.id, median_query(project_ids))
- else
- begin
- median_datetimes(cte_table, interval_query(project_ids), name, :project_id)&.each do |project_id, median|
- loader.call(project_id, median)
- end
- rescue NotSupportedError
- {}
- end
- end
- end
- end
-
- def group_median
- median_query(projects.map(&:id))
- end
-
- def median_query(project_ids)
- # Build a `SELECT` query. We find the first of the `end_time_attrs` that isn't `NULL` (call this end_time).
- # Next, we find the first of the start_time_attrs that isn't `NULL` (call this start_time).
- # We compute the (end_time - start_time) interval, and give it an alias based on the current
- # value stream analytics stage.
-
- median_datetime(cte_table, interval_query(project_ids), name)
- end
-
- def name
- raise NotImplementedError.new("Expected #{self.name} to implement name")
- end
-
- def cte_table
- Arel::Table.new("cte_table_for_#{name}")
- end
-
- def interval_query(project_ids)
- Arel::Nodes::As.new(cte_table,
- subtract_datetimes(stage_query(project_ids), start_time_attrs, end_time_attrs, name.to_s))
- end
-
- private
-
- def event_fetcher
- @event_fetcher ||= Gitlab::CycleAnalytics::EventFetcher[name].new(stage: name,
- options: event_options)
- end
-
- def event_options
- options.merge(start_time_attrs: start_time_attrs, end_time_attrs: end_time_attrs)
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/builds_event_helper.rb b/lib/gitlab/cycle_analytics/builds_event_helper.rb
deleted file mode 100644
index c39d41578e9..00000000000
--- a/lib/gitlab/cycle_analytics/builds_event_helper.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module BuildsEventHelper
- def initialize(...)
- @projections = [build_table[:id]]
- @order = build_table[:created_at]
-
- super(...)
- end
-
- def fetch
- Updater.update!(event_result, from: 'id', to: 'build', klass: ::Ci::Build)
-
- super
- end
-
- def events_query
- base_query.join(build_table).on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
-
- super
- end
-
- private
-
- def allowed_ids
- nil
- end
-
- def serialize(event)
- AnalyticsBuildSerializer.new.represent(event['build'])
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/code_event_fetcher.rb b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
deleted file mode 100644
index 790bf32c6c7..00000000000
--- a/lib/gitlab/cycle_analytics/code_event_fetcher.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class CodeEventFetcher < BaseEventFetcher
- include CodeHelper
-
- def initialize(...)
- @projections = [mr_table[:title],
- mr_table[:iid],
- mr_table[:id],
- mr_table[:created_at],
- mr_table[:state_id],
- mr_table[:author_id]]
- @order = mr_table[:created_at]
-
- super(...)
- end
-
- private
-
- def serialize(event)
- AnalyticsMergeRequestSerializer.new(serialization_context).represent(event)
- end
-
- def allowed_ids_finder_class
- MergeRequestsFinder
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/code_helper.rb b/lib/gitlab/cycle_analytics/code_helper.rb
deleted file mode 100644
index 8f28bdd2502..00000000000
--- a/lib/gitlab/cycle_analytics/code_helper.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module CodeHelper
- def stage_query(project_ids)
- super(project_ids).where(mr_table[:created_at].gteq(issue_metrics_table[:first_mentioned_in_commit_at]))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/code_stage.rb b/lib/gitlab/cycle_analytics/code_stage.rb
deleted file mode 100644
index 89a6430221c..00000000000
--- a/lib/gitlab/cycle_analytics/code_stage.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class CodeStage < BaseStage
- include CodeHelper
-
- def start_time_attrs
- @start_time_attrs ||= issue_metrics_table[:first_mentioned_in_commit_at]
- end
-
- def end_time_attrs
- @end_time_attrs ||= mr_table[:created_at]
- end
-
- def name
- :code
- end
-
- def title
- s_('CycleAnalyticsStage|Code')
- end
-
- def legend
- _("Related Merge Requests")
- end
-
- def description
- _("Time until first merge request")
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/event_fetcher.rb b/lib/gitlab/cycle_analytics/event_fetcher.rb
deleted file mode 100644
index 04f4b4f053f..00000000000
--- a/lib/gitlab/cycle_analytics/event_fetcher.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module EventFetcher
- def self.[](stage_name)
- CycleAnalytics.const_get("#{stage_name.to_s.camelize}EventFetcher", false)
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
deleted file mode 100644
index fd04ec090b3..00000000000
--- a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class IssueEventFetcher < BaseEventFetcher
- include IssueHelper
-
- def initialize(...)
- @projections = [issue_table[:title],
- issue_table[:iid],
- issue_table[:id],
- issue_table[:created_at],
- issue_table[:author_id]]
-
- super(...)
- end
-
- private
-
- def serialize(event)
- AnalyticsIssueSerializer.new(serialization_context).represent(event)
- end
-
- def allowed_ids_finder_class
- IssuesFinder
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/issue_helper.rb b/lib/gitlab/cycle_analytics/issue_helper.rb
deleted file mode 100644
index f6f85b84ed8..00000000000
--- a/lib/gitlab/cycle_analytics/issue_helper.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module IssueHelper
- def stage_query(project_ids)
- query = issue_table.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
- .join(projects_table).on(issue_table[:project_id].eq(projects_table[:id]))
- .join(routes_table).on(projects_table[:namespace_id].eq(routes_table[:source_id]))
- .project(issue_table[:project_id].as("project_id"))
- .project(projects_table[:path].as("project_path"))
- .project(routes_table[:path].as("namespace_path"))
-
- query = limit_query(query, project_ids)
- limit_query_by_date_range(query)
- end
-
- def limit_query(query, project_ids)
- query.where(issue_table[:project_id].in(project_ids))
- .where(routes_table[:source_type].eq('Namespace'))
- .where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/issue_stage.rb b/lib/gitlab/cycle_analytics/issue_stage.rb
deleted file mode 100644
index 738cb3eba03..00000000000
--- a/lib/gitlab/cycle_analytics/issue_stage.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class IssueStage < BaseStage
- include IssueHelper
-
- def start_time_attrs
- @start_time_attrs ||= issue_table[:created_at]
- end
-
- def end_time_attrs
- @end_time_attrs ||= [issue_metrics_table[:first_associated_with_milestone_at],
- issue_metrics_table[:first_added_to_board_at]]
- end
-
- def name
- :issue
- end
-
- def title
- s_('CycleAnalyticsStage|Issue')
- end
-
- def legend
- _("Related Issues")
- end
-
- def description
- _("Time before an issue gets scheduled")
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/permissions.rb b/lib/gitlab/cycle_analytics/permissions.rb
index 0e094fabb01..9164c8b1bff 100644
--- a/lib/gitlab/cycle_analytics/permissions.rb
+++ b/lib/gitlab/cycle_analytics/permissions.rb
@@ -23,7 +23,7 @@ module Gitlab
end
def get
- ::CycleAnalytics::LevelBase::STAGES.each do |stage|
+ Gitlab::Analytics::CycleAnalytics::DefaultStages.symbolized_stage_names.each do |stage|
@stage_permission_hash[stage] = authorized_stage?(stage)
end
diff --git a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
deleted file mode 100644
index 4d98d589e46..00000000000
--- a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class PlanEventFetcher < BaseEventFetcher
- include PlanHelper
-
- def initialize(...)
- @projections = [issue_table[:title],
- issue_table[:iid],
- issue_table[:id],
- issue_table[:created_at],
- issue_table[:author_id]]
-
- super(...)
- end
-
- private
-
- def serialize(event)
- AnalyticsIssueSerializer.new(serialization_context).represent(event)
- end
-
- def allowed_ids_finder_class
- IssuesFinder
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/plan_helper.rb b/lib/gitlab/cycle_analytics/plan_helper.rb
deleted file mode 100644
index af4bf6ed3eb..00000000000
--- a/lib/gitlab/cycle_analytics/plan_helper.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module PlanHelper
- def stage_query(project_ids)
- query = issue_table.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
- .join(projects_table).on(issue_table[:project_id].eq(projects_table[:id]))
- .join(routes_table).on(projects_table[:namespace_id].eq(routes_table[:source_id]))
- .project(issue_table[:project_id].as("project_id"))
- .project(projects_table[:path].as("project_path"))
- .project(routes_table[:path].as("namespace_path"))
- .where(issue_table[:project_id].in(project_ids))
- .where(routes_table[:source_type].eq('Namespace'))
- query = limit_query(query)
-
- limit_query_by_date_range(query)
- end
-
- def limit_query(query)
- query.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
- .where(issue_metrics_table[:first_mentioned_in_commit_at].not_eq(nil))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/plan_stage.rb b/lib/gitlab/cycle_analytics/plan_stage.rb
deleted file mode 100644
index 0b27d114f52..00000000000
--- a/lib/gitlab/cycle_analytics/plan_stage.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class PlanStage < BaseStage
- include PlanHelper
-
- def start_time_attrs
- @start_time_attrs ||= [issue_metrics_table[:first_associated_with_milestone_at],
- issue_metrics_table[:first_added_to_board_at]]
- end
-
- def end_time_attrs
- @end_time_attrs ||= issue_metrics_table[:first_mentioned_in_commit_at]
- end
-
- def name
- :plan
- end
-
- def title
- s_('CycleAnalyticsStage|Plan')
- end
-
- def legend
- _("Related Issues")
- end
-
- def description
- _("Time before an issue starts implementation")
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/production_event_fetcher.rb b/lib/gitlab/cycle_analytics/production_event_fetcher.rb
deleted file mode 100644
index 5fa286bd3df..00000000000
--- a/lib/gitlab/cycle_analytics/production_event_fetcher.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class ProductionEventFetcher < BaseEventFetcher
- include ProductionHelper
-
- def initialize(...)
- @projections = [issue_table[:title],
- issue_table[:iid],
- issue_table[:id],
- issue_table[:created_at],
- issue_table[:author_id],
- routes_table[:path]]
-
- super(...)
- end
-
- private
-
- def serialize(event)
- AnalyticsIssueSerializer.new(serialization_context).represent(event)
- end
-
- def allowed_ids_finder_class
- IssuesFinder
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/production_helper.rb b/lib/gitlab/cycle_analytics/production_helper.rb
deleted file mode 100644
index 778757a9ede..00000000000
--- a/lib/gitlab/cycle_analytics/production_helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module ProductionHelper
- def stage_query(project_ids)
- super(project_ids)
- .where(mr_metrics_table[:first_deployed_to_production_at]
- .gteq(options[:from]))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/review_event_fetcher.rb b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
deleted file mode 100644
index 0b7d160c7de..00000000000
--- a/lib/gitlab/cycle_analytics/review_event_fetcher.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class ReviewEventFetcher < BaseEventFetcher
- include ReviewHelper
-
- def initialize(...)
- @projections = [mr_table[:title],
- mr_table[:iid],
- mr_table[:id],
- mr_table[:created_at],
- mr_table[:state_id],
- mr_table[:author_id]]
-
- super(...)
- end
-
- private
-
- def serialize(event)
- AnalyticsMergeRequestSerializer.new(serialization_context).represent(event)
- end
-
- def allowed_ids_finder_class
- MergeRequestsFinder
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/review_helper.rb b/lib/gitlab/cycle_analytics/review_helper.rb
deleted file mode 100644
index c53249652b5..00000000000
--- a/lib/gitlab/cycle_analytics/review_helper.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module ReviewHelper
- def stage_query(project_ids)
- super(project_ids).where(mr_metrics_table[:merged_at].not_eq(nil))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/review_stage.rb b/lib/gitlab/cycle_analytics/review_stage.rb
deleted file mode 100644
index e9df8cd5a05..00000000000
--- a/lib/gitlab/cycle_analytics/review_stage.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class ReviewStage < BaseStage
- include ReviewHelper
-
- def start_time_attrs
- @start_time_attrs ||= mr_table[:created_at]
- end
-
- def end_time_attrs
- @end_time_attrs ||= mr_metrics_table[:merged_at]
- end
-
- def name
- :review
- end
-
- def title
- s_('CycleAnalyticsStage|Review')
- end
-
- def legend
- _("Related Merged Requests")
- end
-
- def description
- _("Time between merge request creation and merge/close")
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/stage.rb b/lib/gitlab/cycle_analytics/stage.rb
deleted file mode 100644
index 5cfd9ea4730..00000000000
--- a/lib/gitlab/cycle_analytics/stage.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module Stage
- def self.[](stage_name)
- CycleAnalytics.const_get("#{stage_name.to_s.camelize}Stage", false)
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
deleted file mode 100644
index 1454a1a33eb..00000000000
--- a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class StagingEventFetcher < BaseEventFetcher
- include ProductionHelper
- include BuildsEventHelper
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/staging_stage.rb b/lib/gitlab/cycle_analytics/staging_stage.rb
deleted file mode 100644
index e03627c6cd1..00000000000
--- a/lib/gitlab/cycle_analytics/staging_stage.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class StagingStage < BaseStage
- include ProductionHelper
-
- def start_time_attrs
- @start_time_attrs ||= mr_metrics_table[:merged_at]
- end
-
- def end_time_attrs
- @end_time_attrs ||= mr_metrics_table[:first_deployed_to_production_at]
- end
-
- def name
- :staging
- end
-
- def title
- s_('CycleAnalyticsStage|Staging')
- end
-
- def legend
- _("Related Deployed Jobs")
- end
-
- def description
- _("From merge request merge until deploy to production")
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/test_event_fetcher.rb b/lib/gitlab/cycle_analytics/test_event_fetcher.rb
deleted file mode 100644
index 2fa44b1b364..00000000000
--- a/lib/gitlab/cycle_analytics/test_event_fetcher.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class TestEventFetcher < BaseEventFetcher
- include TestHelper
- include BuildsEventHelper
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/test_helper.rb b/lib/gitlab/cycle_analytics/test_helper.rb
deleted file mode 100644
index d9124d62c7c..00000000000
--- a/lib/gitlab/cycle_analytics/test_helper.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- module TestHelper
- def stage_query(project_ids)
- if branch
- super(project_ids).where(build_table[:ref].eq(branch))
- else
- super(project_ids)
- end
- end
-
- private
-
- def branch
- @branch ||= options[:branch]
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/test_stage.rb b/lib/gitlab/cycle_analytics/test_stage.rb
deleted file mode 100644
index 4787a906c07..00000000000
--- a/lib/gitlab/cycle_analytics/test_stage.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class TestStage < BaseStage
- include TestHelper
-
- def start_time_attrs
- @start_time_attrs ||= mr_metrics_table[:latest_build_started_at]
- end
-
- def end_time_attrs
- @end_time_attrs ||= mr_metrics_table[:latest_build_finished_at]
- end
-
- def name
- :test
- end
-
- def title
- s_('CycleAnalyticsStage|Test')
- end
-
- def legend
- _("Related Jobs")
- end
-
- def description
- _("Total test time for all commits/merges")
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/base_linter.rb b/lib/gitlab/danger/base_linter.rb
index df2e9e745aa..898434724bd 100644
--- a/lib/gitlab/danger/base_linter.rb
+++ b/lib/gitlab/danger/base_linter.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
+require_relative 'title_linting'
+
module Gitlab
module Danger
class BaseLinter
MIN_SUBJECT_WORDS_COUNT = 3
MAX_LINE_LENGTH = 72
- WIP_PREFIX = 'WIP: '
attr_reader :commit, :problems
@@ -58,7 +59,7 @@ module Gitlab
private
def subject
- message_parts[0].delete_prefix(WIP_PREFIX)
+ TitleLinting.remove_draft_flag(message_parts[0])
end
def subject_too_short?
diff --git a/lib/gitlab/danger/changelog.rb b/lib/gitlab/danger/changelog.rb
index 92af6849b2f..4b85775ed98 100644
--- a/lib/gitlab/danger/changelog.rb
+++ b/lib/gitlab/danger/changelog.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative 'title_linting'
+
module Gitlab
module Danger
module Changelog
@@ -75,7 +77,7 @@ module Gitlab
end
def sanitized_mr_title
- helper.sanitize_mr_title(gitlab.mr_json["title"])
+ TitleLinting.sanitize_mr_title(gitlab.mr_json["title"])
end
def categories_need_changelog?
diff --git a/lib/gitlab/danger/commit_linter.rb b/lib/gitlab/danger/commit_linter.rb
index 7e2e0fb0acb..e23f5900433 100644
--- a/lib/gitlab/danger/commit_linter.rb
+++ b/lib/gitlab/danger/commit_linter.rb
@@ -1,9 +1,15 @@
# frozen_string_literal: true
-require_relative 'base_linter'
-
emoji_checker_path = File.expand_path('emoji_checker', __dir__)
-defined?(Rails) ? require_dependency(emoji_checker_path) : require_relative(emoji_checker_path)
+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
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
index d22f28ff7f2..09e013e24b8 100644
--- a/lib/gitlab/danger/helper.rb
+++ b/lib/gitlab/danger/helper.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
require_relative 'teammate'
+require_relative 'title_linting'
module Gitlab
module Danger
module Helper
RELEASE_TOOLS_BOT = 'gitlab-release-tools-bot'
- DRAFT_REGEX = /\A*#{Regexp.union(/(?i)(\[WIP\]\s*|WIP:\s*|WIP$)/, /(?i)(\[draft\]|\(draft\)|draft:|draft\s\-\s|draft$)/)}+\s*/i.freeze
# Returns a list of all files that have been added, modified or renamed.
# `git.modified_files` might contain paths that already have been renamed,
@@ -128,7 +128,7 @@ module Gitlab
}.freeze
# First-match win, so be sure to put more specific regex at the top...
CATEGORIES = {
- [%r{usage_data\.rb}, %r{^(\+|-).*(count|distinct_count)\(.*\)(.*)$}] => [:database, :backend],
+ [%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,
@@ -216,14 +216,10 @@ module Gitlab
usernames.map { |u| Gitlab::Danger::Teammate.new('username' => u) }
end
- def sanitize_mr_title(title)
- title.gsub(DRAFT_REGEX, '').gsub(/`/, '\\\`')
- end
-
def draft_mr?
return false unless gitlab_helper
- DRAFT_REGEX.match?(gitlab_helper.mr_json['title'])
+ TitleLinting.has_draft_flag?(gitlab_helper.mr_json['title'])
end
def security_mr?
diff --git a/lib/gitlab/danger/merge_request_linter.rb b/lib/gitlab/danger/merge_request_linter.rb
index d401d332aa7..ed354bfc68d 100644
--- a/lib/gitlab/danger/merge_request_linter.rb
+++ b/lib/gitlab/danger/merge_request_linter.rb
@@ -1,6 +1,12 @@
# frozen_string_literal: true
-require_relative 'base_linter'
+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
diff --git a/lib/gitlab/danger/roulette.rb b/lib/gitlab/danger/roulette.rb
index 328083f7002..21feda2cf20 100644
--- a/lib/gitlab/danger/roulette.rb
+++ b/lib/gitlab/danger/roulette.rb
@@ -2,6 +2,8 @@
require_relative 'teammate'
require_relative 'request_helper' unless defined?(Gitlab::Danger::RequestHelper)
+require_relative 'weightage/reviewers'
+require_relative 'weightage/maintainers'
module Gitlab
module Danger
@@ -151,20 +153,14 @@ module Gitlab
%i[reviewer traintainer maintainer].map do |role|
spin_role_for_category(team, role, project, category)
end
- hungry_reviewers = reviewers.select { |member| member.hungry }
- hungry_traintainers = traintainers.select { |member| member.hungry }
-
- # TODO: take CODEOWNERS into account?
- # https://gitlab.com/gitlab-org/gitlab/issues/26723
random = new_random(mr_source_branch)
- # Make hungry traintainers have 4x the chance to be picked as a reviewer
- # Make traintainers have 3x the chance to be picked as a reviewer
- # Make hungry reviewers have 2x the chance to be picked as a reviewer
- weighted_reviewers = reviewers + hungry_reviewers + traintainers + traintainers + traintainers + hungry_traintainers
+ 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(maintainers, 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
diff --git a/lib/gitlab/danger/teammate.rb b/lib/gitlab/danger/teammate.rb
index 4481977db15..911b84d93ec 100644
--- a/lib/gitlab/danger/teammate.rb
+++ b/lib/gitlab/danger/teammate.rb
@@ -3,7 +3,7 @@
module Gitlab
module Danger
class Teammate
- attr_reader :options, :username, :name, :role, :projects, :available, :hungry, :tz_offset_hours
+ 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 = {})
@@ -15,6 +15,7 @@ module Gitlab
@projects = options['projects']
@available = options['available']
@hungry = options['hungry']
+ @reduced_capacity = options['reduced_capacity']
@tz_offset_hours = options['tz_offset_hours']
end
@@ -94,6 +95,7 @@ module Gitlab
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
diff --git a/lib/gitlab/danger/title_linting.rb b/lib/gitlab/danger/title_linting.rb
new file mode 100644
index 00000000000..db1ccaaf9a9
--- /dev/null
+++ b/lib/gitlab/danger/title_linting.rb
@@ -0,0 +1,23 @@
+# 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
new file mode 100644
index 00000000000..67fade27573
--- /dev/null
+++ b/lib/gitlab/danger/weightage.rb
@@ -0,0 +1,10 @@
+# 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
new file mode 100644
index 00000000000..cc0eb370e7a
--- /dev/null
+++ b/lib/gitlab/danger/weightage/maintainers.rb
@@ -0,0 +1,33 @@
+# 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
new file mode 100644
index 00000000000..c8019be716e
--- /dev/null
+++ b/lib/gitlab/danger/weightage/reviewers.rb
@@ -0,0 +1,65 @@
+# 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/database/median.rb b/lib/gitlab/database/median.rb
deleted file mode 100644
index 603b125d8b4..00000000000
--- a/lib/gitlab/database/median.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: true
-
-# https://www.periscopedata.com/blog/medians-in-sql.html
-module Gitlab
- module Database
- module Median
- NotSupportedError = Class.new(StandardError)
-
- def median_datetime(arel_table, query_so_far, column_sym)
- extract_median(execute_queries(arel_table, query_so_far, column_sym)).presence
- end
-
- def median_datetimes(arel_table, query_so_far, column_sym, partition_column)
- extract_medians(execute_queries(arel_table, query_so_far, column_sym, partition_column)).presence
- end
-
- def extract_median(results)
- result = results.compact.first
-
- result = result.first.presence
-
- result['median']&.to_f if result
- end
-
- def extract_medians(results)
- median_values = results.compact.first.values
-
- median_values.each_with_object({}) do |(id, median), hash|
- hash[id.to_i] = median&.to_f
- end
- end
-
- def pg_median_datetime_sql(arel_table, query_so_far, column_sym, partition_column = nil)
- # Create a CTE with the column we're operating on, row number (after sorting by the column
- # we're operating on), and count of the table we're operating on (duplicated across) all rows
- # of the CTE. For example, if we're looking to find the median of the `projects.star_count`
- # column, the CTE might look like this:
- #
- # star_count | row_id | ct
- # ------------+--------+----
- # 5 | 1 | 3
- # 9 | 2 | 3
- # 15 | 3 | 3
- #
- # If a partition column is used we will do the same operation but for separate partitions,
- # when that happens the CTE might look like this:
- #
- # project_id | star_count | row_id | ct
- # ------------+------------+--------+----
- # 1 | 5 | 1 | 2
- # 1 | 9 | 2 | 2
- # 2 | 10 | 1 | 3
- # 2 | 15 | 2 | 3
- # 2 | 20 | 3 | 3
- cte_table = Arel::Table.new("ordered_records")
-
- cte = Arel::Nodes::As.new(
- cte_table,
- arel_table.project(*rank_rows(arel_table, column_sym, partition_column)).
- # Disallow negative values
- where(arel_table[column_sym].gteq(zero_interval)))
-
- # From the CTE, select either the middle row or the middle two rows (this is accomplished
- # by 'where cte.row_id between cte.ct / 2.0 AND cte.ct / 2.0 + 1'). Find the average of the
- # selected rows, and this is the median value.
- result =
- cte_table
- .project(*median_projections(cte_table, column_sym, partition_column))
- .where(
- Arel::Nodes::Between.new(
- cte_table[:row_id],
- Arel::Nodes::And.new(
- [(cte_table[:ct] / Arel.sql('2.0')),
- (cte_table[:ct] / Arel.sql('2.0') + 1)]
- )
- )
- )
- .with(query_so_far, cte)
-
- result.group(cte_table[partition_column]).order(cte_table[partition_column]) if partition_column
-
- result.to_sql
- end
-
- private
-
- def execute_queries(arel_table, query_so_far, column_sym, partition_column = nil)
- queries = pg_median_datetime_sql(arel_table, query_so_far, column_sym, partition_column)
-
- Array.wrap(queries).map { |query| ActiveRecord::Base.connection.execute(query) }
- end
-
- def average(args, as)
- Arel::Nodes::NamedFunction.new("AVG", args, as)
- end
-
- def rank_rows(arel_table, column_sym, partition_column)
- column_row = arel_table[column_sym].as(column_sym.to_s)
-
- if partition_column
- partition_row = arel_table[partition_column]
- row_id =
- Arel::Nodes::Over.new(
- Arel::Nodes::NamedFunction.new('rank', []),
- Arel::Nodes::Window.new.partition(arel_table[partition_column])
- .order(arel_table[column_sym])
- ).as('row_id')
-
- count = arel_table.from.from(arel_table.alias)
- .project('COUNT(*)')
- .where(arel_table[partition_column].eq(arel_table.alias[partition_column]))
- .as('ct')
-
- [partition_row, column_row, row_id, count]
- else
- row_id =
- Arel::Nodes::Over.new(
- Arel::Nodes::NamedFunction.new('row_number', []),
- Arel::Nodes::Window.new.order(arel_table[column_sym])
- ).as('row_id')
-
- count = arel_table.where(arel_table[column_sym].gteq(zero_interval)).project("COUNT(1)").as('ct')
-
- [column_row, row_id, count]
- end
- end
-
- def median_projections(table, column_sym, partition_column)
- projections = []
- projections << table[partition_column] if partition_column
- projections << average([extract_epoch(table[column_sym])], "median")
- projections
- end
-
- def extract_epoch(arel_attribute)
- Arel.sql(%Q{EXTRACT(EPOCH FROM "#{arel_attribute.relation.name}"."#{arel_attribute.name}")})
- end
-
- def extract_diff_epoch(diff)
- Arel.sql(%Q{EXTRACT(EPOCH FROM (#{diff.to_sql}))})
- end
-
- # Need to cast '0' to an INTERVAL before we can check if the interval is positive
- def zero_interval
- Arel::Nodes::NamedFunction.new("CAST", [Arel.sql("'0' AS INTERVAL")])
- end
- end
- end
-end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 164fce5a5a3..6b169a504f3 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -70,6 +70,61 @@ module Gitlab
end
end
+ #
+ # Creates a new table, optionally allowing the caller to add check constraints to the table.
+ # Aside from that addition, this method should behave identically to Rails' `create_table` method.
+ #
+ # Example:
+ #
+ # create_table_with_constraints :some_table do |t|
+ # t.integer :thing, null: false
+ # t.text :other_thing
+ #
+ # t.check_constraint :thing_is_not_null, 'thing IS NOT NULL'
+ # t.text_limit :other_thing, 255
+ # end
+ #
+ # See Rails' `create_table` for more info on the available arguments.
+ def create_table_with_constraints(table_name, **options, &block)
+ helper_context = self
+ check_constraints = []
+
+ with_lock_retries do
+ create_table(table_name, **options) do |t|
+ t.define_singleton_method(:check_constraint) do |name, definition|
+ helper_context.send(:validate_check_constraint_name!, name) # rubocop:disable GitlabSecurity/PublicSend
+
+ check_constraints << { name: name, definition: definition }
+ end
+
+ t.define_singleton_method(:text_limit) do |column_name, limit, name: nil|
+ # rubocop:disable GitlabSecurity/PublicSend
+ name = helper_context.send(:text_limit_name, table_name, column_name, name: name)
+ helper_context.send(:validate_check_constraint_name!, name)
+ # rubocop:enable GitlabSecurity/PublicSend
+
+ column_name = helper_context.quote_column_name(column_name)
+ definition = "char_length(#{column_name}) <= #{limit}"
+
+ check_constraints << { name: name, definition: definition }
+ end
+
+ t.instance_eval(&block) unless block.nil?
+ end
+
+ next if check_constraints.empty?
+
+ constraint_clauses = check_constraints.map do |constraint|
+ "ADD CONSTRAINT #{quote_table_name(constraint[:name])} CHECK (#{constraint[:definition]})"
+ end
+
+ execute(<<~SQL)
+ ALTER TABLE #{quote_table_name(table_name)}
+ #{constraint_clauses.join(",\n")}
+ SQL
+ end
+ end
+
# Creates a new index, concurrently
#
# Example:
@@ -858,6 +913,120 @@ module Gitlab
end
end
+ # Initializes the conversion of an integer column to bigint
+ #
+ # It can be used for converting both a Primary Key and any Foreign Keys
+ # that may reference it or any other integer column that we may want to
+ # upgrade (e.g. columns that store IDs, but are not set as FKs).
+ #
+ # - For primary keys and Foreign Keys (or other columns) defined as NOT NULL,
+ # the new bigint column is added with a hardcoded NOT NULL DEFAULT 0
+ # which allows us to skip a very costly verification step once we
+ # are ready to switch it.
+ # This is crucial for Primary Key conversions, because setting a column
+ # as the PK converts even check constraints to NOT NULL constraints
+ # and forces an inline re-verification of the whole table.
+ # - It backfills the new column with the values of the existing primary key
+ # by scheduling background jobs.
+ # - It tracks the scheduled background jobs through the use of
+ # Gitlab::Database::BackgroundMigrationJob
+ # which allows a more thorough check that all jobs succeeded in the
+ # cleanup migration and is way faster for very large tables.
+ # - It sets up a trigger to keep the two columns in sync
+ # - It does not schedule a cleanup job: we have to do that with followup
+ # post deployment migrations in the next release.
+ #
+ # This needs to be done manually by using the
+ # `cleanup_initialize_conversion_of_integer_to_bigint`
+ # (not yet implemented - check #288005)
+ #
+ # table - The name of the database table containing the column
+ # column - The name of the column that we want to convert to bigint.
+ # primary_key - The name of the primary key column (most often :id)
+ # batch_size - The number of rows to schedule in a single background migration
+ # sub_batch_size - The smaller batches that will be used by each scheduled job
+ # to update the table. Useful to keep each update at ~100ms while executing
+ # more updates per interval (2.minutes)
+ # Note that each execution of a sub-batch adds a constant 100ms sleep
+ # time in between the updates, which must be taken into account
+ # while calculating the batch, sub_batch and interval values.
+ # interval - The time interval between every background migration
+ #
+ # example:
+ # Assume that we have figured out that updating 200 records of the events
+ # table takes ~100ms on average.
+ # We can set the sub_batch_size to 200, leave the interval to the default
+ # and set the batch_size to 50_000 which will require
+ # ~50s = (50000 / 200) * (0.1 + 0.1) to complete and leaves breathing space
+ # between the scheduled jobs
+ def initialize_conversion_of_integer_to_bigint(
+ table,
+ column,
+ primary_key: :id,
+ batch_size: 20_000,
+ sub_batch_size: 1000,
+ interval: 2.minutes
+ )
+
+ if transaction_open?
+ raise 'initialize_conversion_of_integer_to_bigint can not be run inside a transaction'
+ end
+
+ unless table_exists?(table)
+ raise "Table #{table} does not exist"
+ end
+
+ unless column_exists?(table, primary_key)
+ raise "Column #{primary_key} does not exist on #{table}"
+ end
+
+ unless column_exists?(table, column)
+ raise "Column #{column} does not exist on #{table}"
+ end
+
+ check_trigger_permissions!(table)
+
+ old_column = column_for(table, column)
+ tmp_column = "#{column}_convert_to_bigint"
+
+ with_lock_retries do
+ if (column.to_s == primary_key.to_s) || !old_column.null
+ # If the column to be converted is either a PK or is defined as NOT NULL,
+ # set it to `NOT NULL DEFAULT 0` and we'll copy paste the correct values bellow
+ # That way, we skip the expensive validation step required to add
+ # a NOT NULL constraint at the end of the process
+ add_column(table, tmp_column, :bigint, default: old_column.default || 0, null: false)
+ else
+ add_column(table, tmp_column, :bigint, default: old_column.default)
+ end
+
+ install_rename_triggers(table, column, tmp_column)
+ end
+
+ source_model = Class.new(ActiveRecord::Base) do
+ include EachBatch
+
+ self.table_name = table
+ self.inheritance_column = :_type_disabled
+ end
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ source_model,
+ 'CopyColumnUsingBackgroundMigrationJob',
+ interval,
+ batch_size: batch_size,
+ other_job_arguments: [table, primary_key, column, tmp_column, sub_batch_size],
+ track_jobs: true,
+ primary_column_name: primary_key
+ )
+
+ if perform_background_migration_inline?
+ # To ensure the schema is up to date immediately we perform the
+ # migration inline in dev / test environments.
+ Gitlab::BackgroundMigration.steal('CopyColumnUsingBackgroundMigrationJob')
+ end
+ end
+
# Performs a concurrent column rename when using PostgreSQL.
def install_rename_triggers_for_postgresql(trigger, table, old, new)
execute <<-EOF.strip_heredoc
@@ -996,9 +1165,9 @@ module Gitlab
Arel::Nodes::SqlLiteral.new(replace.to_sql)
end
- def remove_foreign_key_if_exists(*args)
- if foreign_key_exists?(*args)
- remove_foreign_key(*args)
+ def remove_foreign_key_if_exists(...)
+ if foreign_key_exists?(...)
+ remove_foreign_key(...)
end
end
diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb
index 36073844765..12dcf68da2f 100644
--- a/lib/gitlab/database/migrations/background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/background_migration_helpers.rb
@@ -100,6 +100,7 @@ module Gitlab
end
final_delay = 0
+ batch_counter = 0
model_class.each_batch(of: batch_size) do |relation, index|
start_id, end_id = relation.pluck(Arel.sql("MIN(#{primary_column_name}), MAX(#{primary_column_name})")).first
@@ -112,8 +113,17 @@ module Gitlab
track_in_database(job_class_name, full_job_arguments) if track_jobs
migrate_in(final_delay, job_class_name, full_job_arguments)
+
+ batch_counter += 1
end
+ duration = initial_delay + delay_interval * batch_counter
+ say <<~SAY
+ Scheduled #{batch_counter} #{job_class_name} jobs with a maximum of #{batch_size} records per batch and an interval of #{delay_interval} seconds.
+
+ The migration is expected to take at least #{duration} seconds. Expect all jobs to have completed after #{Time.zone.now + duration}."
+ SAY
+
final_delay
end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
index f367292f4b0..0bc1343acca 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
@@ -32,7 +32,7 @@ module Gitlab
return
end
- partitioned_table.postgres_partitions.each do |partition|
+ partitioned_table.postgres_partitions.order(:name).each do |partition|
partition_index_name = generated_index_name(partition.identifier, options[:name])
partition_options = options.merge(name: partition_index_name)
diff --git a/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb b/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
index 33faa2ef1b0..62dfaeeaae3 100644
--- a/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
+++ b/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
@@ -16,9 +16,9 @@ module Gitlab
# Grouped relations are NOT supported yet.
#
# @example Usage
- # ::Gitlab::Database::PostgresHllBatchDistinctCount.new(::Project, :creator_id).estimate_distinct_count
+ # ::Gitlab::Database::PostgresHllBatchDistinctCount.new(::Project, :creator_id).execute
# ::Gitlab::Database::PostgresHllBatchDistinctCount.new(::Project.with_active_services.service_desk_enabled.where(time_period))
- # .estimate_distinct_count(
+ # .execute(
# batch_size: 1_000,
# start: ::Project.with_active_services.service_desk_enabled.where(time_period).minimum(:id),
# finish: ::Project.with_active_services.service_desk_enabled.where(time_period).maximum(:id)
@@ -30,7 +30,6 @@ module Gitlab
# for the most of a cases this value is lower. However, if the exact value is necessary other tools has to be used.
class BatchDistinctCounter
ERROR_RATE = 4.9 # max encountered empirical error rate, used in tests
- FALLBACK = -1
MIN_REQUIRED_BATCH_SIZE = 750
SLEEP_TIME_IN_SECONDS = 0.01 # 10 msec sleep
MAX_DATA_VOLUME = 4_000_000_000
@@ -38,8 +37,10 @@ module Gitlab
# Each query should take < 500ms https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22705
DEFAULT_BATCH_SIZE = 10_000
+ ZERO_OFFSET = 1
+ BUCKET_ID_MASK = (Buckets::TOTAL_BUCKETS - ZERO_OFFSET).to_s(2)
BIT_31_MASK = "B'0#{'1' * 31}'"
- BIT_9_MASK = "B'#{'0' * 23}#{'1' * 9}'"
+ BIT_32_NORMALIZED_BUCKET_ID_MASK = "B'#{'0' * (32 - BUCKET_ID_MASK.size)}#{BUCKET_ID_MASK}'"
# @example source_query
# SELECT CAST(('X' || md5(CAST(%{column} as text))) as bit(32)) attr_hash_32_bits
# FROM %{relation}
@@ -48,73 +49,58 @@ module Gitlab
# AND %{column} IS NOT NULL
BUCKETED_DATA_SQL = <<~SQL
WITH hashed_attributes AS (%{source_query})
- SELECT (attr_hash_32_bits & #{BIT_9_MASK})::int AS bucket_num,
+ SELECT (attr_hash_32_bits & #{BIT_32_NORMALIZED_BUCKET_ID_MASK})::int AS bucket_num,
(31 - floor(log(2, min((attr_hash_32_bits & #{BIT_31_MASK})::int))))::int as bucket_hash
FROM hashed_attributes
GROUP BY 1
SQL
- TOTAL_BUCKETS_NUMBER = 512
+ WRONG_CONFIGURATION_ERROR = Class.new(ActiveRecord::StatementInvalid)
def initialize(relation, column = nil)
@relation = relation
@column = column || relation.primary_key
end
- def unwanted_configuration?(finish, batch_size, start)
- batch_size <= MIN_REQUIRED_BATCH_SIZE ||
- (finish - start) >= MAX_DATA_VOLUME ||
- start > finish
- end
-
- def estimate_distinct_count(batch_size: nil, start: nil, finish: nil)
+ # Executes counter that iterates over database source and return Gitlab::Database::PostgresHll::Buckets
+ # that can be used to estimation of number of uniq elements in analysed set
+ #
+ # @param batch_size maximal number of rows that will be analysed by single database query
+ # @param start initial pkey range
+ # @param finish final pkey range
+ # @return [Gitlab::Database::PostgresHll::Buckets] HyperLogLog data structure instance that can estimate number of unique elements
+ def execute(batch_size: nil, start: nil, finish: nil)
raise 'BatchCount can not be run inside a transaction' if ActiveRecord::Base.connection.transaction_open?
batch_size ||= DEFAULT_BATCH_SIZE
-
start = actual_start(start)
finish = actual_finish(finish)
- raise "Batch counting expects positive values only for #{@column}" if start < 0 || finish < 0
- return FALLBACK if unwanted_configuration?(finish, batch_size, start)
+ raise WRONG_CONFIGURATION_ERROR if unwanted_configuration?(start, finish, batch_size)
batch_start = start
- hll_blob = {}
+ hll_buckets = Buckets.new
while batch_start <= finish
begin
- hll_blob.merge!(hll_blob_for_batch(batch_start, batch_start + batch_size)) {|_key, old, new| new > old ? new : old }
+ hll_buckets.merge_hash!(hll_buckets_for_batch(batch_start, batch_start + batch_size))
batch_start += batch_size
end
sleep(SLEEP_TIME_IN_SECONDS)
end
- estimate_cardinality(hll_blob)
+ hll_buckets
end
private
- # arbitrary values that are present in #estimate_cardinality
- # are sourced from https://www.sisense.com/blog/hyperloglog-in-pure-sql/
- # article, they are not representing any entity and serves as tune value
- # for the whole equation
- def estimate_cardinality(hll_blob)
- num_zero_buckets = TOTAL_BUCKETS_NUMBER - hll_blob.size
-
- num_uniques = (
- ((TOTAL_BUCKETS_NUMBER**2) * (0.7213 / (1 + 1.079 / TOTAL_BUCKETS_NUMBER))) /
- (num_zero_buckets + hll_blob.values.sum { |bucket_hash| 2**(-1 * bucket_hash)} )
- ).to_i
-
- if num_zero_buckets > 0 && num_uniques < 2.5 * TOTAL_BUCKETS_NUMBER
- ((0.7213 / (1 + 1.079 / TOTAL_BUCKETS_NUMBER)) * (TOTAL_BUCKETS_NUMBER *
- Math.log2(TOTAL_BUCKETS_NUMBER.to_f / num_zero_buckets)))
- else
- num_uniques
- end
+ def unwanted_configuration?(start, finish, batch_size)
+ batch_size <= MIN_REQUIRED_BATCH_SIZE ||
+ (finish - start) >= MAX_DATA_VOLUME ||
+ start > finish || start < 0 || finish < 0
end
- def hll_blob_for_batch(start, finish)
+ def hll_buckets_for_batch(start, finish)
@relation
.connection
.execute(BUCKETED_DATA_SQL % { source_query: source_query(start, finish) })
diff --git a/lib/gitlab/database/postgres_hll/buckets.rb b/lib/gitlab/database/postgres_hll/buckets.rb
new file mode 100644
index 00000000000..429e823379f
--- /dev/null
+++ b/lib/gitlab/database/postgres_hll/buckets.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module PostgresHll
+ # Bucket class represent data structure build with HyperLogLog algorithm
+ # that models data distribution in analysed set. This representation than can be used
+ # for following purposes
+ # 1. Estimating number of unique elements that this structure represents
+ # 2. Merging with other Buckets structure to later estimate number of unique elements in sum of two
+ # represented data sets
+ # 3. Serializing Buckets structure to json format, that can be stored in various persistence layers
+ #
+ # @example Usage
+ # ::Gitlab::Database::PostgresHll::Buckets.new(141 => 1, 56 => 1).estimated_distinct_count
+ # ::Gitlab::Database::PostgresHll::Buckets.new(141 => 1, 56 => 1).merge_hash!(141 => 1, 56 => 5).estimated_distinct_count
+ # ::Gitlab::Database::PostgresHll::Buckets.new(141 => 1, 56 => 1).to_json
+
+ # @note HyperLogLog is an PROBABILISTIC algorithm that ESTIMATES distinct count of given attribute value for supplied relation
+ # Like all probabilistic algorithm is has ERROR RATE margin, that can affect values,
+ # for given implementation no higher value was reported (https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45673#accuracy-estimation) than 5.3%
+ # for the most of a cases this value is lower. However, if the exact value is necessary other tools has to be used.
+ class Buckets
+ TOTAL_BUCKETS = 512
+
+ def initialize(buckets = {})
+ @buckets = buckets
+ end
+
+ # Based on HyperLogLog structure estimates number of unique elements in analysed set.
+ #
+ # @return [Float] Estimate number of unique elements
+ def estimated_distinct_count
+ @estimated_distinct_count ||= estimate_cardinality
+ end
+
+ # Updates instance underlying HyperLogLog structure by merging it with other HyperLogLog structure
+ #
+ # @param other_buckets_hash hash with HyperLogLog structure representation
+ def merge_hash!(other_buckets_hash)
+ buckets.merge!(other_buckets_hash) {|_key, old, new| new > old ? new : old }
+ end
+
+ # Serialize instance underlying HyperLogLog structure to JSON format, that can be stored in various persistence layers
+ #
+ # @return [String] HyperLogLog data structure serialized to JSON
+ def to_json(_ = nil)
+ buckets.to_json
+ end
+
+ private
+
+ attr_accessor :buckets
+
+ # arbitrary values that are present in #estimate_cardinality
+ # are sourced from https://www.sisense.com/blog/hyperloglog-in-pure-sql/
+ # article, they are not representing any entity and serves as tune value
+ # for the whole equation
+ def estimate_cardinality
+ num_zero_buckets = TOTAL_BUCKETS - buckets.size
+
+ num_uniques = (
+ ((TOTAL_BUCKETS**2) * (0.7213 / (1 + 1.079 / TOTAL_BUCKETS))) /
+ (num_zero_buckets + buckets.values.sum { |bucket_hash| 2**(-1 * bucket_hash)} )
+ ).to_i
+
+ if num_zero_buckets > 0 && num_uniques < 2.5 * TOTAL_BUCKETS
+ ((0.7213 / (1 + 1.079 / TOTAL_BUCKETS)) * (TOTAL_BUCKETS *
+ Math.log2(TOTAL_BUCKETS.to_f / num_zero_buckets)))
+ else
+ num_uniques
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb
index 832f7438cf9..0cfad690283 100644
--- a/lib/gitlab/database/reindexing.rb
+++ b/lib/gitlab/database/reindexing.rb
@@ -8,9 +8,9 @@ module Gitlab
# candidate_indexes: Array of Gitlab::Database::PostgresIndex
def self.perform(candidate_indexes, how_many: DEFAULT_INDEXES_PER_INVOCATION)
- indexes = IndexSelection.new(candidate_indexes).take(how_many)
-
- Coordinator.new(indexes).perform
+ IndexSelection.new(candidate_indexes).take(how_many).each do |index|
+ Coordinator.new(index).perform
+ end
end
def self.candidate_indexes
diff --git a/lib/gitlab/database/reindexing/coordinator.rb b/lib/gitlab/database/reindexing/coordinator.rb
index 0957f43e166..7a7d17ca196 100644
--- a/lib/gitlab/database/reindexing/coordinator.rb
+++ b/lib/gitlab/database/reindexing/coordinator.rb
@@ -12,26 +12,44 @@ module Gitlab
# statement timeouts).
TIMEOUT_PER_ACTION = 1.day
- attr_reader :indexes
+ attr_reader :index, :notifier
- def initialize(indexes)
- @indexes = indexes
+ def initialize(index, notifier = GrafanaNotifier.new)
+ @index = index
+ @notifier = notifier
end
def perform
- indexes.each do |index|
- # This obtains a global lease such that there's
- # only one live reindexing process at a time.
- try_obtain_lease do
- ReindexAction.keep_track_of(index) do
- ConcurrentReindex.new(index).perform
- end
+ # This obtains a global lease such that there's
+ # only one live reindexing process at a time.
+ try_obtain_lease do
+ action = ReindexAction.create_for(index)
+
+ with_notifications(action) do
+ perform_for(index, action)
end
end
end
private
+ def with_notifications(action)
+ notifier.notify_start(action)
+ yield
+ ensure
+ notifier.notify_end(action)
+ end
+
+ def perform_for(index, action)
+ ConcurrentReindex.new(index).perform
+ rescue
+ action.state = :failed
+
+ raise
+ ensure
+ action.finish
+ end
+
def lease_timeout
TIMEOUT_PER_ACTION
end
diff --git a/lib/gitlab/database/reindexing/grafana_notifier.rb b/lib/gitlab/database/reindexing/grafana_notifier.rb
new file mode 100644
index 00000000000..b1e5ecb9ade
--- /dev/null
+++ b/lib/gitlab/database/reindexing/grafana_notifier.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Reindexing
+ # This can be used to send annotations for reindexing to a Grafana API
+ class GrafanaNotifier
+ def initialize(api_key = ENV['GITLAB_GRAFANA_API_KEY'], api_url = ENV['GITLAB_GRAFANA_API_URL'], additional_tag = ENV['GITLAB_REINDEXING_GRAFANA_TAG'] || Rails.env)
+ @api_key = api_key
+ @api_url = api_url
+ @additional_tag = additional_tag
+ end
+
+ def notify_start(action)
+ return unless enabled?
+
+ payload = base_payload(action).merge(
+ text: "Started reindexing of #{action.index.name} on #{action.index.tablename}"
+ )
+
+ annotate(payload)
+ end
+
+ def notify_end(action)
+ return unless enabled?
+
+ payload = base_payload(action).merge(
+ text: "Finished reindexing of #{action.index.name} on #{action.index.tablename} (#{action.state})",
+ timeEnd: (action.action_end.utc.to_f * 1000).to_i,
+ isRegion: true
+ )
+
+ annotate(payload)
+ end
+
+ private
+
+ def base_payload(action)
+ {
+ time: (action.action_start.utc.to_f * 1000).to_i,
+ tags: ['reindex', @additional_tag, action.index.tablename, action.index.name].compact
+ }
+ end
+
+ def annotate(payload)
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": "Bearer #{@api_key}"
+ }
+
+ success = Gitlab::HTTP.post("#{@api_url}/api/annotations", body: payload.to_json, headers: headers, allow_local_requests: true).success?
+
+ log_error("Response code #{response.code}") unless success
+
+ success
+ rescue => err
+ log_error(err)
+
+ false
+ end
+
+ def log_error(err)
+ Gitlab::AppLogger.warn("Unable to notify Grafana from #{self.class}: #{err}")
+ end
+
+ def enabled?
+ !(@api_url.blank? || @api_key.blank?)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/reindexing/reindex_action.rb b/lib/gitlab/database/reindexing/reindex_action.rb
index 8c59cffe5fb..7e58201889f 100644
--- a/lib/gitlab/database/reindexing/reindex_action.rb
+++ b/lib/gitlab/database/reindexing/reindex_action.rb
@@ -14,27 +14,23 @@ module Gitlab
scope :recent, -> { where(state: :finished).where('action_end > ?', Time.zone.now - RECENT_THRESHOLD) }
- def self.keep_track_of(index, &block)
- action = create!(
+ def self.create_for(index)
+ create!(
index_identifier: index.identifier,
action_start: Time.zone.now,
ondisk_size_bytes_start: index.ondisk_size_bytes,
bloat_estimate_bytes_start: index.bloat_size
)
+ end
- yield
-
- action.state = :finished
- rescue
- action.state = :failed
- raise
- ensure
+ def finish
index.reload # rubocop:disable Cop/ActiveRecordAssociationReload
- action.action_end = Time.zone.now
- action.ondisk_size_bytes_end = index.ondisk_size_bytes
+ self.state = :finished unless failed?
+ self.action_end = Time.zone.now
+ self.ondisk_size_bytes_end = index.ondisk_size_bytes
- action.save!
+ save!
end
end
end
diff --git a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
index b1093b2fca4..d1ada8c723e 100644
--- a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
+++ b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
@@ -75,7 +75,7 @@ module Gitlab
if response
# In the add_prometheus_manual_configuration method, the Prometheus
- # listen_address config is saved as an api_url in the PrometheusService
+ # server_address config is saved as an api_url in the PrometheusService
# model. There are validates hooks in the PrometheusService model that
# check if the project associated with the PrometheusService is the
# self_monitoring project. It checks
@@ -105,7 +105,7 @@ module Gitlab
def add_prometheus_manual_configuration(result)
return success(result) unless prometheus_enabled?
- return success(result) unless prometheus_listen_address.present?
+ return success(result) unless prometheus_server_address.present?
service = result[:project].find_or_initialize_service('prometheus')
@@ -132,8 +132,8 @@ module Gitlab
::Gitlab::Prometheus::Internal.prometheus_enabled?
end
- def prometheus_listen_address
- ::Gitlab::Prometheus::Internal.listen_address
+ def prometheus_server_address
+ ::Gitlab::Prometheus::Internal.server_address
end
def docs_path
@@ -152,13 +152,13 @@ module Gitlab
}
end
- def internal_prometheus_listen_address_uri
+ def internal_prometheus_server_address_uri
::Gitlab::Prometheus::Internal.uri
end
def prometheus_service_attributes
{
- api_url: internal_prometheus_listen_address_uri,
+ api_url: internal_prometheus_server_address_uri,
manual_configuration: true,
active: true
}
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index af9140215f0..98ed2400d82 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -8,9 +8,9 @@ module Gitlab
#
SERIALIZE_KEYS = %i(line_code rich_text text type index old_pos new_pos).freeze
- attr_reader :line_code, :old_pos, :new_pos
+ attr_reader :line_code
attr_writer :rich_text
- attr_accessor :text, :index, :type
+ attr_accessor :text, :index, :type, :old_pos, :new_pos
def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil, rich_text: nil)
@text, @type, @index = text, type, index
diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb
index e43f301c280..74c33c46598 100644
--- a/lib/gitlab/diff/position.rb
+++ b/lib/gitlab/diff/position.rb
@@ -19,6 +19,7 @@ module Gitlab
:height,
:x,
:y,
+ :line_range,
:position_type, to: :formatter
# A position can belong to a text line or to an image coordinate
@@ -167,6 +168,12 @@ module Gitlab
end
end
+ def multiline?
+ return unless on_text? && line_range
+
+ line_range['start'] != line_range['end']
+ end
+
private
def find_diff_file(repository)
diff --git a/lib/gitlab/email/handler.rb b/lib/gitlab/email/handler.rb
index 1b8421d34f3..e71ea154355 100644
--- a/lib/gitlab/email/handler.rb
+++ b/lib/gitlab/email/handler.rb
@@ -11,6 +11,7 @@ module Gitlab
[
CreateNoteHandler,
CreateIssueHandler,
+ CreateNoteOnIssuableHandler,
UnsubscribeHandler,
CreateMergeRequestHandler,
ServiceDeskHandler
diff --git a/lib/gitlab/email/handler/create_note_on_issuable_handler.rb b/lib/gitlab/email/handler/create_note_on_issuable_handler.rb
new file mode 100644
index 00000000000..aed3647744a
--- /dev/null
+++ b/lib/gitlab/email/handler/create_note_on_issuable_handler.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'gitlab/email/handler/base_handler'
+
+# Handles comment creation emails when sent/forwarded by an authorized
+# user. Attachments are allowed. Quoted material is _not_ stripped, just like
+# create issue emails
+# Supports these formats:
+# incoming+gitlab-org-gitlab-ce-20-Author_Token12345678-issue-34@incoming.gitlab.com
+module Gitlab
+ module Email
+ module Handler
+ class CreateNoteOnIssuableHandler < BaseHandler
+ include ReplyProcessing
+
+ attr_reader :issuable_iid
+
+ HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-(?<incoming_email_token>.+)-issue-(?<issuable_iid>\d+)\z/.freeze
+
+ def initialize(mail, mail_key)
+ super(mail, mail_key)
+
+ if (matched = HANDLER_REGEX.match(mail_key.to_s))
+ @project_slug = matched[:project_slug]
+ @project_id = matched[:project_id]&.to_i
+ @incoming_email_token = matched[:incoming_email_token]
+ @issuable_iid = matched[:issuable_iid]&.to_i
+ end
+ end
+
+ def can_handle?
+ incoming_email_token && project_id && issuable_iid
+ end
+
+ def execute
+ raise ProjectNotFound unless project
+
+ validate_permission!(:create_note)
+
+ raise NoteableNotFoundError unless noteable
+ raise EmptyEmailError if message_including_reply.blank?
+
+ verify_record!(
+ record: create_note,
+ invalid_exception: InvalidNoteError,
+ record_name: 'comment')
+ end
+
+ def metrics_event
+ :receive_email_create_note_issuable
+ end
+
+ def noteable
+ return unless issuable_iid
+
+ @noteable ||= project&.issues&.find_by_iid(issuable_iid)
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def author
+ @author ||= User.find_by(incoming_email_token: incoming_email_token)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def create_note
+ Notes::CreateService.new(project, author, note_params).execute
+ end
+
+ def note_params
+ {
+ noteable_type: noteable.class.to_s,
+ noteable_id: noteable.id,
+ note: message_including_reply
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index 0bbe3980f67..f66e8a8794f 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -68,7 +68,7 @@ module Gitlab
end
def valid_project_key?(project, slug)
- project.present? && slug == project.full_path_slug && Feature.enabled?(:service_desk_custom_address, project, default_enabled: true)
+ project.present? && slug == project.full_path_slug
end
def create_issue!
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index a5ace2be773..1a8e5aaf07a 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -111,8 +111,8 @@ module Gitlab
private
def before_send(event, hint)
- event = add_context_from_exception_type(event, hint)
- event = custom_fingerprinting(event, hint)
+ inject_context_for_exception(event, hint[:exception])
+ custom_fingerprinting(event, hint[:exception])
event
end
@@ -123,7 +123,6 @@ module Gitlab
end
extra = sanitize_request_parameters(extra)
- inject_sql_query_into_extra(exception, extra)
if sentry && Raven.configuration.server
Raven.capture_exception(exception, tags: default_tags, extra: extra)
@@ -150,12 +149,6 @@ module Gitlab
filter.filter(parameters)
end
- def inject_sql_query_into_extra(exception, extra)
- return unless exception.is_a?(ActiveRecord::StatementInvalid)
-
- extra[:sql] = PgQuery.normalize(exception.sql.to_s)
- end
-
def sentry_dsn
return unless Rails.env.production? || Rails.env.development?
return unless Gitlab.config.sentry.enabled
@@ -183,31 +176,21 @@ module Gitlab
{}
end
- # Debugging for https://gitlab.com/gitlab-org/gitlab-foss/issues/57727
- def add_context_from_exception_type(event, hint)
- if ActiveModel::MissingAttributeError === hint[:exception]
- columns_hash = ActiveRecord::Base
- .connection
- .schema_cache
- .instance_variable_get(:@columns_hash)
- .transform_values { |v| v.map(&:first) }
-
- event.extra.merge!(columns_hash)
- end
-
- event
- end
-
# Group common, mostly non-actionable exceptions by type and message,
# rather than cause
- def custom_fingerprinting(event, hint)
- ex = hint[:exception]
-
+ def custom_fingerprinting(event, ex)
return event unless CUSTOM_FINGERPRINTING.include?(ex.class.name)
event.fingerprint = [ex.class.name, ex.message]
+ end
- event
+ def inject_context_for_exception(event, ex)
+ case ex
+ when ActiveRecord::StatementInvalid
+ event.extra[:sql] = PgQuery.normalize(ex.sql.to_s)
+ else
+ inject_context_for_exception(event, ex.cause) if ex.cause.present?
+ end
end
end
end
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 94523813662..196203211ed 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -87,6 +87,24 @@ module Gitlab
},
invite_members_empty_project_version_a: {
tracking_category: 'Growth::Expansion::Experiment::InviteMembersEmptyProjectVersionA'
+ },
+ trial_during_signup: {
+ tracking_category: 'Growth::Conversion::Experiment::TrialDuringSignup'
+ },
+ ci_syntax_templates: {
+ tracking_category: 'Growth::Activation::Experiment::CiSyntaxTemplates'
+ },
+ pipelines_empty_state: {
+ tracking_category: 'Growth::Activation::Experiment::PipelinesEmptyState'
+ },
+ invite_members_new_dropdown: {
+ tracking_category: 'Growth::Expansion::Experiment::InviteMembersNewDropdown'
+ },
+ show_trial_status_in_sidebar: {
+ tracking_category: 'Growth::Conversion::Experiment::ShowTrialStatusInSidebar'
+ },
+ trial_onboarding_issues: {
+ tracking_category: 'Growth::Conversion::Experiment::TrialOnboardingIssues'
}
}.freeze
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
index c85d3f4eee6..e43f3c8c007 100644
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -15,7 +15,7 @@ module Gitlab
included do
before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
- helper_method :experiment_enabled?, :experiment_tracking_category_and_group
+ helper_method :experiment_enabled?, :experiment_tracking_category_and_group, :tracking_label
end
def set_experimentation_subject_id_cookie
@@ -130,7 +130,10 @@ module Gitlab
end
def forced_enabled?(experiment_key)
- params.has_key?(:force_experiment) && params[:force_experiment] == experiment_key.to_s
+ return true if params.has_key?(:force_experiment) && params[:force_experiment] == experiment_key.to_s
+ return false if cookies[:force_experiment].blank?
+
+ cookies[:force_experiment].to_s.split(',').any? { |experiment| experiment.strip == experiment_key.to_s }
end
def tracking_label(subject)
diff --git a/lib/gitlab/experimentation/experiment.rb b/lib/gitlab/experimentation/experiment.rb
index e594c3bedeb..36cd673a38f 100644
--- a/lib/gitlab/experimentation/experiment.rb
+++ b/lib/gitlab/experimentation/experiment.rb
@@ -3,17 +3,21 @@
module Gitlab
module Experimentation
class Experiment
+ FEATURE_FLAG_SUFFIX = "_experiment_percentage"
+
attr_reader :key, :tracking_category, :use_backwards_compatible_subject_index
def initialize(key, **params)
@key = key
@tracking_category = params[:tracking_category]
@use_backwards_compatible_subject_index = params[:use_backwards_compatible_subject_index]
-
- @experiment_percentage = Feature.get(:"#{key}_experiment_percentage").percentage_of_time_value # rubocop:disable Gitlab/AvoidFeatureGet
end
def active?
+ # TODO: just touch a feature flag
+ # Temporary change, we will change `experiment_percentage` in future to `Feature.enabled?
+ Feature.enabled?(feature_flag_name, type: :experiment, default_enabled: :yaml)
+
::Gitlab.dev_env_or_com? && experiment_percentage > 0
end
@@ -25,7 +29,17 @@ module Gitlab
private
- attr_reader :experiment_percentage
+ def experiment_percentage
+ feature_flag.percentage_of_time_value
+ end
+
+ def feature_flag
+ Feature.get(feature_flag_name) # rubocop:disable Gitlab/AvoidFeatureGet
+ end
+
+ def feature_flag_name
+ :"#{key}#{FEATURE_FLAG_SUFFIX}"
+ end
end
end
end
diff --git a/lib/gitlab/faraday.rb b/lib/gitlab/faraday.rb
new file mode 100644
index 00000000000..f92392ec1a9
--- /dev/null
+++ b/lib/gitlab/faraday.rb
@@ -0,0 +1,7 @@
+# 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/faraday/error_callback.rb b/lib/gitlab/faraday/error_callback.rb
new file mode 100644
index 00000000000..f99be5b4d04
--- /dev/null
+++ b/lib/gitlab/faraday/error_callback.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Faraday
+ # Simple Faraday Middleware that catches any error risen during the request and run the configured callback.
+ # (https://lostisland.github.io/faraday/middleware/)
+ #
+ # By default, a no op callback is setup.
+ #
+ # Note that the error is not swallowed: it will be rerisen again. In that regard, this callback acts more
+ # like an error spy than anything else.
+ #
+ # The callback has access to the request `env` and the exception instance. For more details, see
+ # https://lostisland.github.io/faraday/middleware/custom
+ #
+ # Faraday.new do |conn|
+ # conn.request(
+ # :error_callback,
+ # callback: -> (env, exception) { Rails.logger.debug("Error #{exception.class.name} when trying to contact #{env[:url]}" ) }
+ # )
+ # conn.adapter(:net_http)
+ # end
+ class ErrorCallback < ::Faraday::Middleware
+ def initialize(app, options = nil)
+ super(app)
+ @options = ::Gitlab::Faraday::ErrorCallback::Options.from(options) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def call(env)
+ @app.call(env)
+ rescue => e
+ @options.callback&.call(env, e)
+
+ raise
+ end
+
+ class Options < ::Faraday::Options.new(:callback)
+ def callback
+ self[:callback]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/changed_path.rb b/lib/gitlab/git/changed_path.rb
new file mode 100644
index 00000000000..033779466f6
--- /dev/null
+++ b/lib/gitlab/git/changed_path.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ class ChangedPath
+ attr_reader :status, :path
+
+ def initialize(status:, path:)
+ @status = status
+ @path = path
+ end
+
+ def new_file?
+ status == :ADDED
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 8df4bc3de05..19462e6cb02 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -13,7 +13,7 @@ module Gitlab
def self.default_limits(project: nil)
if Feature.enabled?(:increased_diff_limits, project)
- { max_files: 200, max_lines: 7500 }
+ { max_files: 300, max_lines: 10000 }
else
{ max_files: 100, max_lines: 5000 }
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index f6601379202..e316d52ac05 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -801,7 +801,8 @@ module Gitlab
# forced - should we use --force flag?
# no_tags - should we use --no-tags flag?
# prune - should we use --prune flag?
- def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, prune: true)
+ # check_tags_changed - should we ask gitaly to calculate whether any tags changed?
+ def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false)
wrapped_gitaly_errors do
gitaly_repository_client.fetch_remote(
remote,
@@ -809,6 +810,7 @@ module Gitlab
forced: forced,
no_tags: no_tags,
prune: prune,
+ check_tags_changed: check_tags_changed,
timeout: GITLAB_PROJECTS_TIMEOUT
)
end
diff --git a/lib/gitlab/git/wiki_page_version.rb b/lib/gitlab/git/wiki_page_version.rb
index 475a9d4d1b9..efe39fa852c 100644
--- a/lib/gitlab/git/wiki_page_version.rb
+++ b/lib/gitlab/git/wiki_page_version.rb
@@ -10,7 +10,12 @@ module Gitlab
@format = format
end
- delegate :message, :sha, :id, :author_name, :authored_date, to: :commit
+ delegate :message, :sha, :id, :author_name, :author_email, :authored_date, to: :commit
+
+ def author_url
+ user = ::User.find_by_any_email(author_email)
+ user.nil? ? "mailto:#{author_email}" : Gitlab::UrlBuilder.build(user)
+ end
end
end
end
diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb
index 854bf6e9c9e..88a75f72840 100644
--- a/lib/gitlab/git_access_snippet.rb
+++ b/lib/gitlab/git_access_snippet.rb
@@ -30,7 +30,10 @@ module Gitlab
def check(cmd, changes)
check_snippet_accessibility!
- super
+ super.tap do |_|
+ # Ensure HEAD points to the default branch in case it is not master
+ snippet.change_head_to_default_branch
+ end
end
override :download_ability
@@ -56,7 +59,7 @@ module Gitlab
# TODO: Investigate if expanding actor/authentication types are needed.
# https://gitlab.com/gitlab-org/gitlab/issues/202190
if actor && !allowed_actor?
- raise ForbiddenError, ERROR_MESSAGES[:authentication_mechanism]
+ raise ForbiddenError, error_message(:authentication_mechanism)
end
super
@@ -68,14 +71,18 @@ module Gitlab
override :check_push_access!
def check_push_access!
- raise ForbiddenError, ERROR_MESSAGES[:update_snippet] unless user
+ raise ForbiddenError, error_message(:update_snippet) unless user
+
+ if snippet&.repository_read_only?
+ raise ForbiddenError, error_message(:read_only)
+ end
check_change_access!
end
def check_snippet_accessibility!
if snippet.blank?
- raise NotFoundError, ERROR_MESSAGES[:snippet_not_found]
+ raise NotFoundError, error_message(:snippet_not_found)
end
end
@@ -91,14 +98,14 @@ module Gitlab
passed = guest_can_download_code? || user_can_download_code?
unless passed
- raise ForbiddenError, ERROR_MESSAGES[:read_snippet]
+ raise ForbiddenError, error_message(:read_snippet)
end
end
override :check_change_access!
def check_change_access!
unless user_can_push?
- raise ForbiddenError, ERROR_MESSAGES[:update_snippet]
+ raise ForbiddenError, error_message(:update_snippet)
end
check_size_before_push!
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index e1324530412..31734abe77f 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -215,12 +215,16 @@ module Gitlab
'client_name' => CLIENT_NAME
}
+ context_data = Labkit::Context.current&.to_h
+
feature_stack = Thread.current[:gitaly_feature_stack]
feature = feature_stack && feature_stack[0]
metadata['call_site'] = feature.to_s if feature
metadata['gitaly-servers'] = address_metadata(remote_storage) if remote_storage
metadata['x-gitlab-correlation-id'] = Labkit::Correlation::CorrelationId.current_id if Labkit::Correlation::CorrelationId.current_id
metadata['gitaly-session-id'] = session_id
+ 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)
deadline_info = request_deadline(timeout)
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 599bce176c9..ea940150941 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -225,7 +225,7 @@ module Gitlab
response = GitalyClient.call(@repository.storage, :diff_service, :find_changed_paths, request, timeout: GitalyClient.medium_timeout)
response.flat_map do |msg|
msg.paths.map do |path|
- OpenStruct.new(
+ Gitlab::Git::ChangedPath.new(
status: path.status,
path: EncodingHelper.encode!(path.path)
)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index e41a406ebd3..bd450249355 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -70,10 +70,11 @@ module Gitlab
end.join
end
- def fetch_remote(remote, ssh_auth:, forced:, no_tags:, timeout:, prune: true)
+ def fetch_remote(remote, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false)
request = Gitaly::FetchRemoteRequest.new(
repository: @gitaly_repo, remote: remote, force: forced,
- no_tags: no_tags, timeout: timeout, no_prune: !prune
+ no_tags: no_tags, timeout: timeout, no_prune: !prune,
+ check_tags_changed: check_tags_changed
)
if ssh_auth&.ssh_mirror_url?
diff --git a/lib/gitlab/github_import/importer/repository_importer.rb b/lib/gitlab/github_import/importer/repository_importer.rb
index 7ae91912b8a..1401c92a44e 100644
--- a/lib/gitlab/github_import/importer/repository_importer.rb
+++ b/lib/gitlab/github_import/importer/repository_importer.rb
@@ -56,7 +56,7 @@ module Gitlab
# The initial fetch can bring in lots of loose refs and objects.
# Running a `git gc` will make importing pull requests faster.
- Projects::HousekeepingService.new(project, :gc).execute
+ Repositories::HousekeepingService.new(project, :gc).execute
true
rescue Gitlab::Git::Repository::NoRepository, Gitlab::Shell::Error => e
diff --git a/lib/gitlab/gitpod.rb b/lib/gitlab/gitpod.rb
deleted file mode 100644
index e35fb8fed02..00000000000
--- a/lib/gitlab/gitpod.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class Gitpod
- class << self
- def feature_available?
- # The gitpod_bundle feature could be conditionally applied, so check if `!off?`
- !feature.off? || feature_enabled?
- end
-
- def feature_enabled?(actor = nil)
- Feature.enabled?(:gitpod, actor, default_enabled: true)
- end
-
- def feature_and_settings_enabled?(actor = nil)
- feature_enabled?(actor) && Gitlab::CurrentSettings.gitpod_enabled
- end
-
- private
-
- def feature
- Feature.get(:gitpod) # rubocop:disable Gitlab/AvoidFeatureGet
- end
- end
- end
-end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 362da8ea53e..0ba535b500e 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -4,7 +4,6 @@
module Gitlab
module GonHelper
- include StartupCssHelper
include WebpackHelper
def add_gon_variables
@@ -48,9 +47,7 @@ module Gitlab
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)
-
- # Startup CSS feature is a special one as it can be enabled by means of cookies and params
- gon.push({ features: { 'startupCss' => use_startup_css? } }, true)
+ 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/batch_key.rb b/lib/gitlab/graphql/batch_key.rb
new file mode 100644
index 00000000000..51203af5a43
--- /dev/null
+++ b/lib/gitlab/graphql/batch_key.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ class BatchKey
+ attr_reader :object
+ delegate :hash, to: :object
+
+ def initialize(object, lookahead = nil, object_name: nil)
+ @object = object
+ @lookahead = lookahead
+ @object_name = object_name
+ end
+
+ def requires?(path)
+ return false unless @lookahead
+ return false unless path.present?
+
+ field = path.pop
+
+ path
+ .reduce(@lookahead) { |q, f| q.selection(f) }
+ .selects?(field)
+ end
+
+ def eql?(other)
+ other.is_a?(self.class) && object == other.object
+ end
+ alias_method :==, :eql?
+
+ def method_missing(method_name, *args, **kwargs)
+ return @object if method_name.to_sym == @object_name
+ return @object.public_send(method_name) if args.empty? && kwargs.empty? # rubocop: disable GitlabSecurity/PublicSend
+
+ super
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/lazy.rb b/lib/gitlab/graphql/lazy.rb
index 54013cf4790..3563504226c 100644
--- a/lib/gitlab/graphql/lazy.rb
+++ b/lib/gitlab/graphql/lazy.rb
@@ -17,6 +17,14 @@ module Gitlab
self.class.new { yield force }
end
+ def catch(error_class = StandardError, &block)
+ self.class.new do
+ force
+ rescue error_class => e
+ yield e
+ end
+ end
+
# Force evaluation of a (possibly) lazy value
def self.force(value)
case value
diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb
index 2ad8d2f7ab7..f95c91c5706 100644
--- a/lib/gitlab/graphql/pagination/keyset/connection.rb
+++ b/lib/gitlab/graphql/pagination/keyset/connection.rb
@@ -67,9 +67,14 @@ module Gitlab
# next page
true
elsif first
- # If we count the number of requested items plus one (`limit_value + 1`),
- # then if we get `limit_value + 1` then we know there is a next page
- relation_count(set_limit(sliced_nodes, limit_value + 1)) == limit_value + 1
+ case sliced_nodes
+ when Array
+ sliced_nodes.size > limit_value
+ else
+ # If we count the number of requested items plus one (`limit_value + 1`),
+ # then if we get `limit_value + 1` then we know there is a next page
+ relation_count(set_limit(sliced_nodes, limit_value + 1)) == limit_value + 1
+ end
else
false
end
@@ -157,8 +162,8 @@ module Gitlab
list = OrderInfo.build_order_list(items)
- if loaded?(items)
- @order_list = list.presence || [items.primary_key]
+ if loaded?(items) && !before.present? && !after.present?
+ @order_list = list.presence || [OrderInfo.new(items.primary_key)]
# already sorted, or trivially sorted
next items if list.present? || items.size <= 1
@@ -194,7 +199,7 @@ module Gitlab
ordering = { 'id' => node[:id].to_s }
order_list.each do |field|
- field_name = field.attribute_name
+ field_name = field.try(:attribute_name) || field
field_value = node[field_name]
ordering[field_name] = if field_value.is_a?(Time)
field_value.strftime('%Y-%m-%d %H:%M:%S.%N %Z')
diff --git a/lib/gitlab/graphql/pagination/keyset/query_builder.rb b/lib/gitlab/graphql/pagination/keyset/query_builder.rb
index 331981ce723..29169449843 100644
--- a/lib/gitlab/graphql/pagination/keyset/query_builder.rb
+++ b/lib/gitlab/graphql/pagination/keyset/query_builder.rb
@@ -40,7 +40,10 @@ module Gitlab
# "issues"."id" > 500
#
def conditions
- attr_values = order_list.map { |field| decoded_cursor[field.attribute_name] }
+ attr_values = order_list.map do |field|
+ name = field.try(:attribute_name) || field
+ decoded_cursor[name]
+ end
if order_list.count == 1 && attr_values.first.nil?
raise Gitlab::Graphql::Errors::ArgumentError.new('Before/after cursor invalid: `nil` was provided as only sortable value')
diff --git a/lib/gitlab/graphql/queries.rb b/lib/gitlab/graphql/queries.rb
new file mode 100644
index 00000000000..de971743490
--- /dev/null
+++ b/lib/gitlab/graphql/queries.rb
@@ -0,0 +1,286 @@
+# frozen_string_literal: true
+
+require 'find'
+
+module Gitlab
+ module Graphql
+ module Queries
+ IMPORT_RE = /^#\s*import "(?<path>[^"]+)"$/m.freeze
+ EE_ELSE_CE = /^ee_else_ce/.freeze
+ HOME_RE = /^~/.freeze
+ HOME_EE = %r{^ee/}.freeze
+ DOTS_RE = %r{^(\.\./)+}.freeze
+ DOT_RE = %r{^\./}.freeze
+ IMPLICIT_ROOT = %r{^app/}.freeze
+ CONN_DIRECTIVE = /@connection\(key: "\w+"\)/.freeze
+
+ class WrappedError
+ delegate :message, to: :@error
+
+ def initialize(error)
+ @error = error
+ end
+
+ def path
+ []
+ end
+ end
+
+ class FileNotFound
+ def initialize(file)
+ @file = file
+ end
+
+ def message
+ "File not found: #{@file}"
+ end
+
+ def path
+ []
+ end
+ end
+
+ # We need to re-write queries to remove all @client fields. Ideally we
+ # would do that as a source-to-source transformation of the AST, but doing it using a
+ # printer is much simpler.
+ class ClientFieldRedactor < GraphQL::Language::Printer
+ attr_reader :fields_printed, :skipped_arguments, :printed_arguments, :used_fragments
+
+ def initialize(skips = true)
+ @skips = skips
+ @fields_printed = 0
+ @in_operation = false
+ @skipped_arguments = [].to_set
+ @printed_arguments = [].to_set
+ @used_fragments = [].to_set
+ @skipped_fragments = [].to_set
+ @used_fragments = [].to_set
+ end
+
+ def print_variable_identifier(variable_identifier)
+ @printed_arguments << variable_identifier.name
+ super
+ end
+
+ def print_fragment_spread(fragment_spread, indent: "")
+ @used_fragments << fragment_spread.name
+ super
+ end
+
+ def print_operation_definition(op, indent: "")
+ @in_operation = true
+ out = +"#{indent}#{op.operation_type}"
+ out << " #{op.name}" if op.name
+
+ # Do these first, so that we detect any skipped arguments
+ dirs = print_directives(op.directives)
+ sels = print_selections(op.selections, indent: indent)
+
+ # remove variable definitions only used in skipped (client) fields
+ vars = op.variables.reject do |v|
+ @skipped_arguments.include?(v.name) && !@printed_arguments.include?(v.name)
+ end
+
+ if vars.any?
+ out << "(#{vars.map { |v| print_variable_definition(v) }.join(", ")})"
+ end
+
+ out + dirs + sels
+ ensure
+ @in_operation = false
+ end
+
+ def print_field(field, indent: '')
+ if skips? && field.directives.any? { |d| d.name == 'client' }
+ skipped = self.class.new(false)
+
+ skipped.print_node(field)
+ @skipped_fragments |= skipped.used_fragments
+ @skipped_arguments |= skipped.printed_arguments
+
+ return ''
+ end
+
+ ret = super
+
+ @fields_printed += 1 if @in_operation && ret != ''
+
+ ret
+ end
+
+ def print_fragment_definition(fragment_def, indent: "")
+ if skips? && @skipped_fragments.include?(fragment_def.name) && !@used_fragments.include?(fragment_def.name)
+ return ''
+ end
+
+ super
+ end
+
+ def skips?
+ @skips
+ end
+ end
+
+ class Definition
+ attr_reader :file, :imports
+
+ def initialize(path, fragments)
+ @file = path
+ @fragments = fragments
+ @imports = []
+ @errors = []
+ @ee_else_ce = []
+ end
+
+ def text(mode: :ce)
+ qs = [query] + all_imports(mode: mode).uniq.sort.map { |p| fragment(p).query }
+ t = qs.join("\n\n").gsub(/\n\n+/, "\n\n")
+
+ return t unless /@client/.match?(t)
+
+ doc = ::GraphQL.parse(t)
+ printer = ClientFieldRedactor.new
+ redacted = doc.dup.to_query_string(printer: printer)
+
+ return redacted if printer.fields_printed > 0
+ end
+
+ def query
+ return @query if defined?(@query)
+
+ # CONN_DIRECTIVEs are purely client-side constructs
+ @query = File.read(file).gsub(CONN_DIRECTIVE, '').gsub(IMPORT_RE) do
+ path = $~[:path]
+
+ if EE_ELSE_CE.match?(path)
+ @ee_else_ce << path.gsub(EE_ELSE_CE, '')
+ else
+ @imports << fragment_path(path)
+ end
+
+ ''
+ end
+ rescue Errno::ENOENT
+ @errors << FileNotFound.new(file)
+ @query = nil
+ end
+
+ def all_imports(mode: :ce)
+ return [] if query.nil?
+
+ home = mode == :ee ? @fragments.home_ee : @fragments.home
+ eithers = @ee_else_ce.map { |p| home + p }
+
+ (imports + eithers).flat_map { |p| [p] + @fragments.get(p).all_imports(mode: mode) }
+ end
+
+ def all_errors
+ return @errors.to_set if query.nil?
+
+ paths = imports + @ee_else_ce.flat_map { |p| [@fragments.home + p, @fragments.home_ee + p] }
+
+ paths.map { |p| fragment(p).all_errors }.reduce(@errors.to_set) { |a, b| a | b }
+ end
+
+ def validate(schema)
+ return [:client_query, []] if query.present? && text.nil?
+
+ errs = all_errors.presence || schema.validate(text)
+ if @ee_else_ce.present?
+ errs += schema.validate(text(mode: :ee))
+ end
+
+ [:validated, errs]
+ rescue ::GraphQL::ParseError => e
+ [:validated, [WrappedError.new(e)]]
+ end
+
+ private
+
+ def fragment(path)
+ @fragments.get(path)
+ end
+
+ def fragment_path(import_path)
+ frag_path = import_path.gsub(HOME_RE, @fragments.home)
+ frag_path = frag_path.gsub(HOME_EE, @fragments.home_ee + '/')
+ frag_path = frag_path.gsub(DOT_RE) do
+ Pathname.new(file).parent.to_s + '/'
+ end
+ frag_path = frag_path.gsub(DOTS_RE) do |dots|
+ rel_dir(dots.split('/').count)
+ end
+ frag_path = frag_path.gsub(IMPLICIT_ROOT) do
+ (Rails.root / 'app').to_s + '/'
+ end
+
+ frag_path
+ end
+
+ def rel_dir(n_steps_up)
+ path = Pathname.new(file).parent
+ while n_steps_up > 0
+ path = path.parent
+ n_steps_up -= 1
+ end
+
+ path.to_s + '/'
+ end
+ end
+
+ class Fragments
+ def initialize(root, dir = 'app/assets/javascripts')
+ @root = root
+ @store = {}
+ @dir = dir
+ end
+
+ def home
+ @home ||= (@root / @dir).to_s
+ end
+
+ def home_ee
+ @home_ee ||= (@root / 'ee' / @dir).to_s
+ end
+
+ def get(frag_path)
+ @store[frag_path] ||= Definition.new(frag_path, self)
+ end
+ end
+
+ def self.find(root)
+ definitions = []
+
+ ::Find.find(root.to_s) do |path|
+ definitions << Definition.new(path, fragments) if query?(path)
+ end
+
+ definitions
+ rescue Errno::ENOENT
+ [] # root does not exist
+ end
+
+ def self.fragments
+ @fragments ||= Fragments.new(Rails.root)
+ end
+
+ def self.all
+ ['.', 'ee'].flat_map do |prefix|
+ find(Rails.root / prefix / 'app/assets/javascripts')
+ end
+ end
+
+ def self.known_failure?(path)
+ @known_failures ||= YAML.safe_load(File.read(Rails.root.join('config', 'known_invalid_graphql_queries.yml')))
+
+ @known_failures.fetch('filenames', []).any? { |known_failure| path.to_s.ends_with?(known_failure) }
+ end
+
+ def self.query?(path)
+ path.ends_with?('.graphql') &&
+ !path.ends_with?('.fragment.graphql') &&
+ !path.ends_with?('typedefs.graphql')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/hashed_storage/rake_helper.rb b/lib/gitlab/hashed_storage/rake_helper.rb
index 7965f165683..d3468569e5e 100644
--- a/lib/gitlab/hashed_storage/rake_helper.rb
+++ b/lib/gitlab/hashed_storage/rake_helper.rb
@@ -65,6 +65,7 @@ module Gitlab
def self.projects_list(relation_name, relation)
listing(relation_name, relation.with_route) do |project|
$stdout.puts " - #{project.full_path} (id: #{project.id})".color(:red)
+ $stdout.puts " #{project.repository.disk_path}"
end
end
@@ -92,6 +93,37 @@ module Gitlab
end
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def self.prune(relation_name, relation, dry_run: true, root: nil)
+ root ||= '../repositories'
+
+ known_paths = Set.new
+ listing(relation_name, relation) { |p| known_paths << "#{root}/#{p.repository.disk_path}" }
+
+ marked_for_deletion = Set.new(Dir["#{root}/@hashed/*/*/*"])
+ marked_for_deletion.reject! do |path|
+ base = path.gsub(/\.(\w+\.)?git$/, '')
+ known_paths.include?(base)
+ end
+
+ if marked_for_deletion.empty?
+ $stdout.puts "No orphaned directories found. Nothing to do!"
+ else
+ n = marked_for_deletion.size
+ $stdout.puts "Found #{n} orphaned #{'directory'.pluralize(n)}"
+ $stdout.puts "Dry run. (Run again with FORCE=1 to delete). We would have deleted:" if dry_run
+ end
+
+ marked_for_deletion.each do |p|
+ p = Pathname.new(p)
+ if dry_run
+ $stdout.puts " - #{p}"
+ else
+ $stdout.puts "Removing #{p}"
+ p.rmtree
+ end
+ end
+ end
end
end
end
diff --git a/lib/gitlab/jira/http_client.rb b/lib/gitlab/jira/http_client.rb
index c09d8170d17..f0b08bb6b6a 100644
--- a/lib/gitlab/jira/http_client.rb
+++ b/lib/gitlab/jira/http_client.rb
@@ -4,7 +4,7 @@ module Gitlab
module Jira
# Gitlab JIRA HTTP client to be used with jira-ruby gem, this subclasses JIRA::HTTPClient.
# Uses Gitlab::HTTP to make requests to JIRA REST API.
- # The parent class implementation can be found at: https://github.com/sumoheavy/jira-ruby/blob/v1.7.0/lib/jira/http_client.rb
+ # The parent class implementation can be found at: https://github.com/sumoheavy/jira-ruby/blob/master/lib/jira/http_client.rb
class HttpClient < JIRA::HttpClient
extend ::Gitlab::Utils::Override
@@ -43,6 +43,8 @@ module Gitlab
result
end
+ private
+
def auth_params
return {} unless @options[:username] && @options[:password]
@@ -54,8 +56,6 @@ module Gitlab
}
end
- private
-
def get_cookies
cookie_array = @cookies.values.map { |cookie| "#{cookie.name}=#{cookie.value[0]}" }
cookie_array += Array(@options[:additional_cookies]) if @options.key?(:additional_cookies)
diff --git a/lib/gitlab/kubernetes/cilium_network_policy.rb b/lib/gitlab/kubernetes/cilium_network_policy.rb
index 9043932bbe5..f77b3e8de99 100644
--- a/lib/gitlab/kubernetes/cilium_network_policy.rb
+++ b/lib/gitlab/kubernetes/cilium_network_policy.rb
@@ -12,7 +12,7 @@ module Gitlab
# We are modeling existing kubernetes resource and don't have
# control over amount of parameters.
# rubocop:disable Metrics/ParameterLists
- def initialize(name:, namespace:, selector:, ingress:, resource_version: nil, description: nil, labels: nil, creation_timestamp: nil, egress: nil)
+ def initialize(name:, namespace:, selector:, ingress:, resource_version: nil, description: nil, labels: nil, creation_timestamp: nil, egress: nil, annotations: nil)
@name = name
@description = description
@namespace = namespace
@@ -22,6 +22,7 @@ module Gitlab
@resource_version = resource_version
@ingress = ingress
@egress = egress
+ @annotations = annotations
end
# rubocop:enable Metrics/ParameterLists
@@ -37,6 +38,7 @@ module Gitlab
name: metadata[:name],
description: policy[:description],
namespace: metadata[:namespace],
+ annotations: metadata[:annotations],
resource_version: metadata[:resourceVersion],
labels: metadata[:labels],
selector: spec[:endpointSelector],
@@ -57,6 +59,7 @@ module Gitlab
name: metadata[:name],
description: resource[:description],
namespace: metadata[:namespace],
+ annotations: metadata[:annotations]&.to_h,
resource_version: metadata[:resourceVersion],
labels: metadata[:labels]&.to_h,
creation_timestamp: metadata[:creationTimestamp],
@@ -80,7 +83,7 @@ module Gitlab
private
- attr_reader :name, :description, :namespace, :labels, :creation_timestamp, :resource_version, :ingress, :egress
+ attr_reader :name, :description, :namespace, :labels, :creation_timestamp, :resource_version, :ingress, :egress, :annotations
def selector
@selector ||= {}
@@ -90,6 +93,7 @@ module Gitlab
meta = { name: name, namespace: namespace }
meta[:labels] = labels if labels
meta[:resourceVersion] = resource_version if resource_version
+ meta[:annotations] = annotations if annotations
meta
end
diff --git a/lib/gitlab/kubernetes/kubectl_cmd.rb b/lib/gitlab/kubernetes/kubectl_cmd.rb
index e8fde28b44d..f3ac19e210a 100644
--- a/lib/gitlab/kubernetes/kubectl_cmd.rb
+++ b/lib/gitlab/kubernetes/kubectl_cmd.rb
@@ -17,7 +17,7 @@ module Gitlab
def delete_crds_from_group(group)
api_resources_args = %w(-o name --api-group).push(group)
- api_resources(*api_resources_args) + " | xargs " + delete('--ignore-not-found', 'crd')
+ PodCmd.retry_command(api_resources(*api_resources_args) + " | xargs -r " + delete('--ignore-not-found', 'crd'))
end
def api_resources(*args)
diff --git a/lib/gitlab/kubernetes/pod_cmd.rb b/lib/gitlab/kubernetes/pod_cmd.rb
new file mode 100644
index 00000000000..e4c25424e69
--- /dev/null
+++ b/lib/gitlab/kubernetes/pod_cmd.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ # Miscellaneous commands that run in the helm-install-image pod, tuned to
+ # the idiosynchrasies of the default shell of helm-install-image
+ module PodCmd
+ class << self
+ def retry_command(command, times: 3)
+ "for i in $(seq 1 #{times.to_i}); do #{command} && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/samplers/action_cable_sampler.rb b/lib/gitlab/metrics/samplers/action_cable_sampler.rb
index 9f4979fa673..043d2ae84cc 100644
--- a/lib/gitlab/metrics/samplers/action_cable_sampler.rb
+++ b/lib/gitlab/metrics/samplers/action_cable_sampler.rb
@@ -4,9 +4,9 @@ module Gitlab
module Metrics
module Samplers
class ActionCableSampler < BaseSampler
- SAMPLING_INTERVAL_SECONDS = 5
+ DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
- def initialize(interval = SAMPLING_INTERVAL_SECONDS, action_cable: ::ActionCable.server)
+ def initialize(interval = nil, action_cable: ::ActionCable.server)
super(interval)
@action_cable = action_cable
end
diff --git a/lib/gitlab/metrics/samplers/base_sampler.rb b/lib/gitlab/metrics/samplers/base_sampler.rb
index 39a49187e45..7f9055fed5d 100644
--- a/lib/gitlab/metrics/samplers/base_sampler.rb
+++ b/lib/gitlab/metrics/samplers/base_sampler.rb
@@ -9,7 +9,9 @@ module Gitlab
attr_reader :interval
# interval - The sampling interval in seconds.
- def initialize(interval = self.class::SAMPLING_INTERVAL_SECONDS)
+ def initialize(interval = nil)
+ interval ||= ENV[interval_env_key]&.to_i
+ interval ||= self.class::DEFAULT_SAMPLING_INTERVAL_SECONDS
interval_half = interval.to_f / 2
@interval = interval
@@ -50,6 +52,14 @@ module Gitlab
attr_reader :running
+ def sampler_class
+ self.class.name.demodulize
+ end
+
+ def interval_env_key
+ "#{sampler_class.underscore.upcase}_INTERVAL_SECONDS"
+ end
+
def start_working
@running = true
diff --git a/lib/gitlab/metrics/samplers/database_sampler.rb b/lib/gitlab/metrics/samplers/database_sampler.rb
index 9ee4b0960c5..60ae22df607 100644
--- a/lib/gitlab/metrics/samplers/database_sampler.rb
+++ b/lib/gitlab/metrics/samplers/database_sampler.rb
@@ -4,7 +4,7 @@ module Gitlab
module Metrics
module Samplers
class DatabaseSampler < BaseSampler
- SAMPLING_INTERVAL_SECONDS = 5
+ DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
METRIC_PREFIX = 'gitlab_database_connection_pool_'
diff --git a/lib/gitlab/metrics/samplers/puma_sampler.rb b/lib/gitlab/metrics/samplers/puma_sampler.rb
index d295beb59f1..848a55e59ff 100644
--- a/lib/gitlab/metrics/samplers/puma_sampler.rb
+++ b/lib/gitlab/metrics/samplers/puma_sampler.rb
@@ -4,7 +4,7 @@ module Gitlab
module Metrics
module Samplers
class PumaSampler < BaseSampler
- SAMPLING_INTERVAL_SECONDS = 5
+ DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
def metrics
@metrics ||= init_metrics
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index dac9fbd1247..76175b465e4 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -6,7 +6,7 @@ module Gitlab
module Metrics
module Samplers
class RubySampler < BaseSampler
- SAMPLING_INTERVAL_SECONDS = 60
+ DEFAULT_SAMPLING_INTERVAL_SECONDS = 60
GC_REPORT_BUCKETS = [0.005, 0.01, 0.02, 0.04, 0.07, 0.1, 0.5].freeze
def initialize(*)
diff --git a/lib/gitlab/metrics/samplers/threads_sampler.rb b/lib/gitlab/metrics/samplers/threads_sampler.rb
index 05acef7ce0c..a460594fb59 100644
--- a/lib/gitlab/metrics/samplers/threads_sampler.rb
+++ b/lib/gitlab/metrics/samplers/threads_sampler.rb
@@ -4,7 +4,7 @@ module Gitlab
module Metrics
module Samplers
class ThreadsSampler < BaseSampler
- SAMPLING_INTERVAL_SECONDS = 5
+ DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
KNOWN_PUMA_THREAD_NAMES = ['puma worker check pipe', 'puma server',
'puma threadpool reaper', 'puma threadpool trimmer',
'puma worker check pipe', 'puma stat payload'].freeze
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
index d7935d65e12..2fa324f3fea 100644
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
@@ -4,6 +4,8 @@ module Gitlab
module Metrics
module Samplers
class UnicornSampler < BaseSampler
+ DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
+
def metrics
@metrics ||= init_metrics
end
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index 43005303dec..9bbcd1e056c 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -17,6 +17,20 @@ module Gitlab
RSS_PATTERN = /VmRSS:\s+(?<value>\d+)/.freeze
MAX_OPEN_FILES_PATTERN = /Max open files\s*(?<value>\d+)/.freeze
+ def self.summary
+ proportional_mem = memory_usage_uss_pss
+ {
+ version: RUBY_DESCRIPTION,
+ gc_stat: GC.stat,
+ memory_rss: memory_usage_rss,
+ memory_uss: proportional_mem[:uss],
+ memory_pss: proportional_mem[:pss],
+ time_cputime: cpu_time,
+ time_realtime: real_time,
+ time_monotonic: monotonic_time
+ }
+ end
+
# Returns the current process' RSS (resident set size) in bytes.
def self.memory_usage_rss
sum_matches(PROC_STATUS_PATH, rss: RSS_PATTERN)[:rss].kilobytes
diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb
index a6d8a778e05..79f1abe820f 100644
--- a/lib/gitlab/middleware/multipart.rb
+++ b/lib/gitlab/middleware/multipart.rb
@@ -41,7 +41,7 @@ module Gitlab
end
def with_open_files
- @rewritten_fields.each do |field, tmp_path|
+ @rewritten_fields.keys.each do |field|
raise "invalid field: #{field.inspect}" unless valid_field_name?(field)
parsed_field = Rack::Utils.parse_nested_query(field)
@@ -51,10 +51,10 @@ module Gitlab
if value.nil? # we have a top level param, eg. field = 'foo' and not 'foo[bar]'
raise "invalid field: #{field.inspect}" if field != key
- value = open_file(@request.params, key, tmp_path.presence)
+ value = open_file(extract_upload_params_from(@request.params, with_prefix: key))
@open_files << value
else
- value = decorate_params_value(value, @request.params[key], tmp_path.presence)
+ value = decorate_params_value(value, @request.params[key])
end
update_param(key, value)
@@ -67,12 +67,12 @@ module Gitlab
end
# This function calls itself recursively
- def decorate_params_value(path_hash, value_hash, path_override = nil)
- unless path_hash.is_a?(Hash) && path_hash.count == 1
- raise "invalid path: #{path_hash.inspect}"
+ def decorate_params_value(hash_path, value_hash)
+ unless hash_path.is_a?(Hash) && hash_path.count == 1
+ raise "invalid path: #{hash_path.inspect}"
end
- path_key, path_value = path_hash.first
+ path_key, path_value = hash_path.first
unless value_hash.is_a?(Hash) && value_hash[path_key]
raise "invalid value hash: #{value_hash.inspect}"
@@ -80,19 +80,19 @@ module Gitlab
case path_value
when nil
- value_hash[path_key] = open_file(value_hash.dig(path_key), '', path_override)
+ value_hash[path_key] = open_file(extract_upload_params_from(value_hash[path_key]))
@open_files << value_hash[path_key]
value_hash
when Hash
- decorate_params_value(path_value, value_hash[path_key], path_override)
+ decorate_params_value(path_value, value_hash[path_key])
value_hash
else
raise "unexpected path value: #{path_value.inspect}"
end
end
- def open_file(params, key, path_override = nil)
- ::UploadedFile.from_params(params, key, allowed_paths, path_override)
+ def open_file(params)
+ ::UploadedFile.from_params(params, allowed_paths)
end
# update_params ensures that both rails controllers and rack middleware can find
@@ -111,6 +111,20 @@ module Gitlab
private
+ def extract_upload_params_from(params, with_prefix: '')
+ param_key = "#{with_prefix}#{JWT_PARAM_SUFFIX}"
+ jwt_token = params[param_key]
+ raise "Empty JWT param: #{param_key}" if jwt_token.blank?
+
+ payload = Gitlab::Workhorse.decode_jwt(jwt_token).first
+ raise "Invalid JWT payload: not a Hash" unless payload.is_a?(Hash)
+
+ upload_params = payload.fetch(JWT_PARAM_FIXED_KEY, {})
+ raise "Empty params for: #{param_key}" if upload_params.empty?
+
+ upload_params
+ end
+
def valid_field_name?(name)
# length validation
return false if name.size >= REWRITTEN_FIELD_NAME_MAX_LENGTH
@@ -149,82 +163,6 @@ module Gitlab
end
end
- # TODO this class is meant to replace Handler when the feature flag
- # upload_middleware_jwt_params_handler is removed
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/233895#roll-out-steps
- class HandlerForJWTParams < Handler
- def with_open_files
- @rewritten_fields.keys.each do |field|
- raise "invalid field: #{field.inspect}" unless valid_field_name?(field)
-
- parsed_field = Rack::Utils.parse_nested_query(field)
- raise "unexpected field: #{field.inspect}" unless parsed_field.count == 1
-
- key, value = parsed_field.first
- if value.nil? # we have a top level param, eg. field = 'foo' and not 'foo[bar]'
- raise "invalid field: #{field.inspect}" if field != key
-
- value = open_file(extract_upload_params_from(@request.params, with_prefix: key))
- @open_files << value
- else
- value = decorate_params_value(value, @request.params[key])
- end
-
- update_param(key, value)
- end
-
- yield
- ensure
- @open_files.compact
- .each(&:close)
- end
-
- # This function calls itself recursively
- def decorate_params_value(hash_path, value_hash)
- unless hash_path.is_a?(Hash) && hash_path.count == 1
- raise "invalid path: #{hash_path.inspect}"
- end
-
- path_key, path_value = hash_path.first
-
- unless value_hash.is_a?(Hash) && value_hash[path_key]
- raise "invalid value hash: #{value_hash.inspect}"
- end
-
- case path_value
- when nil
- value_hash[path_key] = open_file(extract_upload_params_from(value_hash[path_key]))
- @open_files << value_hash[path_key]
- value_hash
- when Hash
- decorate_params_value(path_value, value_hash[path_key])
- value_hash
- else
- raise "unexpected path value: #{path_value.inspect}"
- end
- end
-
- def open_file(params)
- ::UploadedFile.from_params_without_field(params, allowed_paths)
- end
-
- private
-
- def extract_upload_params_from(params, with_prefix: '')
- param_key = "#{with_prefix}#{JWT_PARAM_SUFFIX}"
- jwt_token = params[param_key]
- raise "Empty JWT param: #{param_key}" if jwt_token.blank?
-
- payload = Gitlab::Workhorse.decode_jwt(jwt_token).first
- raise "Invalid JWT payload: not a Hash" unless payload.is_a?(Hash)
-
- upload_params = payload.fetch(JWT_PARAM_FIXED_KEY, {})
- raise "Empty params for: #{param_key}" if upload_params.empty?
-
- upload_params
- end
- end
-
def initialize(app)
@app = app
end
@@ -235,22 +173,12 @@ module Gitlab
message = ::Gitlab::Workhorse.decode_jwt(encoded_message)[0]
- handler_class.new(env, message).with_open_files do
+ ::Gitlab::Middleware::Multipart::Handler.new(env, message).with_open_files do
@app.call(env)
end
rescue UploadedFile::InvalidPathError => e
[400, { 'Content-Type' => 'text/plain' }, e.message]
end
-
- private
-
- def handler_class
- if Feature.enabled?(:upload_middleware_jwt_params_handler, default_enabled: true)
- ::Gitlab::Middleware::Multipart::HandlerForJWTParams
- else
- ::Gitlab::Middleware::Multipart::Handler
- end
- end
end
end
end
diff --git a/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb b/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb
index bf8d4b202b6..133d777fc32 100644
--- a/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb
+++ b/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb
@@ -15,23 +15,39 @@ module Gitlab
# schedules a job which parses peek profile data and adds them
# to a structured log
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def enqueue_stats_job(request_id)
return unless gather_stats?
- @client.sadd(GitlabPerformanceBarStatsWorker::STATS_KEY, request_id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @client.sadd(GitlabPerformanceBarStatsWorker::STATS_KEY, request_id)
return unless uuid = Gitlab::ExclusiveLease.new(
GitlabPerformanceBarStatsWorker::LEASE_KEY,
timeout: GitlabPerformanceBarStatsWorker::LEASE_TIMEOUT
).try_obtain
- GitlabPerformanceBarStatsWorker.perform_in(GitlabPerformanceBarStatsWorker::WORKER_DELAY, uuid)
+ # stats key should be periodically processed and deleted by
+ # GitlabPerformanceBarStatsWorker but if it doesn't happen for
+ # some reason, we set expiration for the stats key to avoid
+ # keeping millions of request ids which would be already expired
+ # anyway
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @client.expire(
+ GitlabPerformanceBarStatsWorker::STATS_KEY,
+ GitlabPerformanceBarStatsWorker::STATS_KEY_EXPIRE
+ )
+
+ GitlabPerformanceBarStatsWorker.perform_in(
+ GitlabPerformanceBarStatsWorker::WORKER_DELAY,
+ uuid
+ )
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def gather_stats?
return unless Feature.enabled?(:performance_bar_stats)
- Gitlab.com? || !Rails.env.production?
+ Gitlab.com? || Gitlab.staging? || !Rails.env.production?
end
end
end
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 6ba36fadfa3..56eeea6e746 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -63,7 +63,8 @@ module Gitlab
ProjectTemplate.new('salesforcedx', 'SalesforceDX', _('A project boilerplate for Salesforce App development with Salesforce Developer tools'), 'https://gitlab.com/gitlab-org/project-templates/salesforcedx'),
ProjectTemplate.new('serverless_framework', 'Serverless Framework/JS', _('A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages'), 'https://gitlab.com/gitlab-org/project-templates/serverless-framework', 'illustrations/logos/serverless_framework.svg'),
ProjectTemplate.new('jsonnet', 'Jsonnet for Dynamic Child Pipelines', _('An example showing how to use Jsonnet with GitLab dynamic child pipelines'), 'https://gitlab.com/gitlab-org/project-templates/jsonnet'),
- ProjectTemplate.new('cluster_management', 'GitLab Cluster Management', _('An example project for managing Kubernetes clusters integrated with GitLab'), 'https://gitlab.com/gitlab-org/project-templates/cluster-management')
+ ProjectTemplate.new('cluster_management', 'GitLab Cluster Management', _('An example project for managing Kubernetes clusters integrated with GitLab'), 'https://gitlab.com/gitlab-org/project-templates/cluster-management'),
+ ProjectTemplate.new('kotlin_native_linux', 'Kotlin Native Linux', _('A basic template for developing Linux programs using Kotlin Native'), 'https://gitlab.com/gitlab-org/project-templates/kotlin-native-linux')
].freeze
end
diff --git a/lib/gitlab/prometheus/internal.rb b/lib/gitlab/prometheus/internal.rb
index c2f4035821e..fe06b97add6 100644
--- a/lib/gitlab/prometheus/internal.rb
+++ b/lib/gitlab/prometheus/internal.rb
@@ -4,43 +4,39 @@ module Gitlab
module Prometheus
class Internal
def self.uri
- return if listen_address.blank?
+ return if server_address.blank?
- if listen_address.starts_with?('0.0.0.0:')
+ if server_address.starts_with?('0.0.0.0:')
# 0.0.0.0:9090
- port = ':' + listen_address.split(':').second
+ port = ':' + server_address.split(':').second
'http://localhost' + port
- elsif listen_address.starts_with?(':')
+ elsif server_address.starts_with?(':')
# :9090
- 'http://localhost' + listen_address
+ 'http://localhost' + server_address
- elsif listen_address.starts_with?('http')
+ elsif server_address.starts_with?('http')
# https://localhost:9090
- listen_address
+ server_address
else
# localhost:9090
- 'http://' + listen_address
+ 'http://' + server_address
end
end
def self.server_address
- uri&.strip&.sub(/^http[s]?:\/\//, '')
- end
-
- def self.listen_address
- Gitlab.config.prometheus.listen_address.to_s if Gitlab.config.prometheus
+ Gitlab.config.prometheus.server_address.to_s if Gitlab.config.prometheus
rescue Settingslogic::MissingSetting
- Gitlab::AppLogger.error('Prometheus listen_address is not present in config/gitlab.yml')
+ Gitlab::AppLogger.error('Prometheus server_address is not present in config/gitlab.yml')
nil
end
def self.prometheus_enabled?
- Gitlab.config.prometheus.enable if Gitlab.config.prometheus
+ Gitlab.config.prometheus.enabled if Gitlab.config.prometheus
rescue Settingslogic::MissingSetting
- Gitlab::AppLogger.error('prometheus.enable is not present in config/gitlab.yml')
+ Gitlab::AppLogger.error('prometheus.enabled is not present in config/gitlab.yml')
false
end
diff --git a/lib/gitlab/quick_actions/issue_actions.rb b/lib/gitlab/quick_actions/issue_actions.rb
index 1822b0c8bd5..c162ee545c6 100644
--- a/lib/gitlab/quick_actions/issue_actions.rb
+++ b/lib/gitlab/quick_actions/issue_actions.rb
@@ -170,7 +170,8 @@ module Gitlab
end
types Issue
condition do
- !quick_action_target.confidential? &&
+ quick_action_target.issue_type_supports?(:confidentiality) &&
+ !quick_action_target.confidential? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", quick_action_target)
end
command :confidential do
diff --git a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
index 6607c73a5c3..4934c12a339 100644
--- a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
@@ -26,7 +26,7 @@ module Gitlab
end
types Issue, MergeRequest
condition do
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ quick_action_target.supports_assignee? && current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
parse_params do |assignee_param|
extract_users(assignee_param)
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index 1986b7a1789..b56fd8278a1 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -9,53 +9,72 @@ module Gitlab
included do
# MergeRequest only quick actions definitions
desc do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
- _("Merge automatically (%{strategy})") % { strategy: preferred_strategy.humanize }
- else
- _("Merge immediately")
- end
+ if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
+ _("Merge automatically (%{strategy})") % { strategy: preferred_strategy.humanize }
else
- _('Merge (when the pipeline succeeds)')
+ _("Merge immediately")
end
end
explanation do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
- _("Schedules to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
- else
- _('Merges this merge request immediately.')
- end
+ if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
+ _("Schedules to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
else
- _('Merges this merge request when the pipeline succeeds.')
+ _('Merges this merge request immediately.')
end
end
execution_message do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
- _("Scheduled to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
- else
- _('Merged this merge request.')
- end
+ if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
+ _("Scheduled to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
else
- _('Scheduled to merge this merge request when the pipeline succeeds.')
+ _('Merged this merge request.')
end
end
types MergeRequest
condition do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- quick_action_target.persisted? &&
- merge_orchestration_service.can_merge?(quick_action_target)
- else
- last_diff_sha = params && params[:merge_request_diff_head_sha]
- quick_action_target.persisted? &&
- quick_action_target.mergeable_with_quick_action?(current_user, autocomplete_precheck: !last_diff_sha, last_diff_sha: last_diff_sha)
- end
+ quick_action_target.persisted? &&
+ merge_orchestration_service.can_merge?(quick_action_target)
end
command :merge do
@updates[:merge] = params[:merge_request_diff_head_sha]
end
+ types MergeRequest
+ desc do
+ _('Rebase source branch')
+ end
+ explanation do
+ _('Rebase source branch on the target branch.')
+ end
+ condition do
+ merge_request = quick_action_target
+
+ next false unless merge_request.open?
+ next false unless merge_request.source_branch_exists?
+
+ access_check = ::Gitlab::UserAccess
+ .new(current_user, container: merge_request.source_project)
+
+ access_check.can_push_to_branch?(merge_request.source_branch)
+ end
+ command :rebase do
+ if quick_action_target.cannot_be_merged?
+ @execution_message[:rebase] = _('This merge request cannot be rebased while there are conflicts.')
+ next
+ end
+
+ if quick_action_target.rebase_in_progress?
+ @execution_message[:rebase] = _('A rebase is already in progress.')
+ next
+ end
+
+ # This will be used to avoid simultaneous "/merge" and "/rebase" actions
+ @updates[:rebase] = true
+
+ branch = quick_action_target.source_branch
+
+ @execution_message[:rebase] = _('Scheduled a rebase of branch %{branch}.') % { branch: branch }
+ end
+
desc 'Toggle the Draft status'
explanation do
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
@@ -135,6 +154,112 @@ module Gitlab
@execution_message[:approve] = _('Approved the current merge request.')
end
+
+ desc do
+ if quick_action_target.allows_multiple_reviewers?
+ _('Assign reviewer(s)')
+ else
+ _('Assign reviewer')
+ end
+ end
+ explanation do |users|
+ reviewers = reviewers_to_add(users)
+ _('Assigns %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users),
+ reviewer_text: 'reviewer'.pluralize(reviewers.size) }
+ end
+ execution_message do |users = nil|
+ reviewers = reviewers_to_add(users)
+ if reviewers.blank?
+ _("Failed to assign a reviewer because no user was found.")
+ else
+ _('Assigned %{reviewer_users_sentence} as %{reviewer_text}.') % { reviewer_users_sentence: reviewer_users_sentence(users),
+ reviewer_text: 'reviewer'.pluralize(reviewers.size) }
+ end
+ end
+ params do
+ quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : '@user'
+ 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)
+ end
+ parse_params do |reviewer_param|
+ extract_users(reviewer_param)
+ end
+ command :assign_reviewer, :reviewer do |users|
+ next if users.empty?
+
+ if quick_action_target.allows_multiple_reviewers?
+ @updates[:reviewer_ids] ||= quick_action_target.reviewers.map(&:id)
+ @updates[:reviewer_ids] |= users.map(&:id)
+ else
+ @updates[:reviewer_ids] = [users.first.id]
+ end
+ end
+
+ desc do
+ if quick_action_target.allows_multiple_reviewers?
+ _('Remove all or specific reviewer(s)')
+ else
+ _('Remove reviewer')
+ end
+ end
+ explanation do |users = nil|
+ reviewers = reviewers_for_removal(users)
+ _("Removes %{reviewer_text} %{reviewer_references}.") %
+ { reviewer_text: 'reviewer'.pluralize(reviewers.size), reviewer_references: reviewers.map(&:to_reference).to_sentence }
+ end
+ execution_message do |users = nil|
+ reviewers = reviewers_for_removal(users)
+ _("Removed %{reviewer_text} %{reviewer_references}.") %
+ { reviewer_text: 'reviewer'.pluralize(reviewers.size), reviewer_references: reviewers.map(&:to_reference).to_sentence }
+ end
+ params do
+ quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : ''
+ end
+ 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
+ parse_params do |unassign_reviewer_param|
+ # When multiple users are assigned, all will be unassigned if multiple reviewers are no longer allowed
+ extract_users(unassign_reviewer_param) if quick_action_target.allows_multiple_reviewers?
+ end
+ command :unassign_reviewer, :remove_reviewer do |users = nil|
+ if quick_action_target.allows_multiple_reviewers? && users&.any?
+ @updates[:reviewer_ids] ||= quick_action_target.reviewers.map(&:id)
+ @updates[:reviewer_ids] -= users.map(&:id)
+ else
+ @updates[:reviewer_ids] = []
+ end
+ end
+ end
+
+ def reviewer_users_sentence(users)
+ reviewers_to_add(users).map(&:to_reference).to_sentence
+ end
+
+ def reviewers_for_removal(users)
+ reviewers = quick_action_target.reviewers
+ if users.present? && quick_action_target.allows_multiple_reviewers?
+ users
+ else
+ reviewers
+ end
+ end
+
+ def reviewers_to_add(users)
+ return if users.blank?
+
+ if quick_action_target.allows_multiple_reviewers?
+ users
+ else
+ [users.first]
+ end
end
def merge_orchestration_service
diff --git a/lib/gitlab/rack_attack.rb b/lib/gitlab/rack_attack.rb
index 7c336153e32..2a94fb91880 100644
--- a/lib/gitlab/rack_attack.rb
+++ b/lib/gitlab/rack_attack.rb
@@ -10,14 +10,70 @@ module Gitlab
def self.configure(rack_attack)
# This adds some methods used by our throttles to the `Rack::Request`
rack_attack::Request.include(Gitlab::RackAttack::Request)
- # Send the Retry-After header so clients (e.g. python-gitlab) can make good choices about delays
- Rack::Attack.throttled_response_retry_after_header = true
+
+ # This is Rack::Attack::DEFAULT_THROTTLED_RESPONSE, modified to allow a custom response
+ 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
+
# Configure the throttles
configure_throttles(rack_attack)
configure_user_allowlist
end
+ # Rate Limit HTTP headers are not standardized anywhere. This is the latest
+ # draft submitted to IETF:
+ # https://github.com/ietf-wg-httpapi/ratelimit-headers/blob/main/draft-ietf-httpapi-ratelimit-headers.md
+ #
+ # This method implement the most viable parts of the headers. Those headers
+ # will be sent back to the client when it gets throttled.
+ #
+ # - RateLimit-Limit: indicates the request quota associated to the client
+ # in 60 seconds. The time window for the quota here is supposed to be
+ # mirrored to throttle_*_period_in_seconds application settings. However,
+ # our HAProxy as well as some ecosystem libraries are using a fixed
+ # 60-second window. Therefore, the returned limit is approximately rounded
+ # up to fit into that window.
+ #
+ # - RateLimit-Observed: indicates the current request amount associated to
+ # the client within the time window.
+ #
+ # - RateLimit-Remaining: indicates the remaining quota within the time
+ # window. It is the result of RateLimit-Limit - RateLimit-Remaining
+ #
+ # - Retry-After: the remaining duration in seconds until the quota is
+ # reset. This is a standardized HTTP header:
+ # https://tools.ietf.org/html/rfc7231#page-69
+ #
+ # - RateLimit-Reset: the point of time that the request quota is reset, in Unix time
+ #
+ # - RateLimit-ResetTime: the point of time that the request quota is reset, in HTTP date format
+ def self.throttled_response_headers(matched, match_data)
+ # Match data example:
+ # {:discriminator=>"127.0.0.1", :count=>12, :period=>60 seconds, :limit=>1, :epoch_time=>1609833930}
+ # Source: https://github.com/rack/rack-attack/blob/v6.3.0/lib/rack/attack/throttle.rb#L33
+ period = match_data[:period]
+ limit = match_data[:limit]
+ rounded_limit = (limit.to_f * 1.minute / match_data[:period]).ceil
+ observed = match_data[:count]
+ now = match_data[:epoch_time]
+ retry_after = period - (now % period)
+ reset_time = Time.at(now + retry_after) # rubocop:disable Rails/TimeZone
+ {
+ 'RateLimit-Name' => matched.to_s,
+ 'RateLimit-Limit' => rounded_limit.to_s,
+ 'RateLimit-Observed' => observed.to_s,
+ 'RateLimit-Remaining' => (limit > observed ? limit - observed : 0).to_s,
+ 'RateLimit-Reset' => reset_time.to_i.to_s,
+ 'RateLimit-ResetTime' => reset_time.httpdate,
+ 'Retry-After' => retry_after.to_s
+ }
+ end
+
def self.configure_user_allowlist
@user_allowlist = nil
user_allowlist
diff --git a/lib/gitlab/sourcegraph.rb b/lib/gitlab/sourcegraph.rb
index 231d5aea129..7ef6ab32bd4 100644
--- a/lib/gitlab/sourcegraph.rb
+++ b/lib/gitlab/sourcegraph.rb
@@ -13,7 +13,8 @@ module Gitlab
end
def feature_enabled?(actor = nil)
- feature.enabled?(actor)
+ # Some CI jobs grep for Feature.enabled? in our codebase, so it is important this reference stays around.
+ Feature.enabled?(:sourcegraph, actor)
end
private
diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb
index e84937ec4ad..b659bff52ad 100644
--- a/lib/gitlab/template/base_template.rb
+++ b/lib/gitlab/template/base_template.rb
@@ -23,7 +23,12 @@ module Gitlab
end
def content
- @finder.read(@path)
+ blob = @finder.read(@path)
+ [description, blob].compact.join("\n")
+ end
+
+ def description
+ # override with a comment to be placed at the top of the blob.
end
# Present for compatibility with license templates, which can replace text
diff --git a/lib/gitlab/template/dockerfile_template.rb b/lib/gitlab/template/dockerfile_template.rb
index 3b516bb862a..09643cfb619 100644
--- a/lib/gitlab/template/dockerfile_template.rb
+++ b/lib/gitlab/template/dockerfile_template.rb
@@ -3,9 +3,8 @@
module Gitlab
module Template
class DockerfileTemplate < BaseTemplate
- def content
- explanation = "# This file is a template, and might need editing before it works on your project."
- [explanation, super].join("\n")
+ def description
+ "# This file is a template, and might need editing before it works on your project."
end
class << self
diff --git a/lib/gitlab/template/gitlab_ci_syntax_yml_template.rb b/lib/gitlab/template/gitlab_ci_syntax_yml_template.rb
new file mode 100644
index 00000000000..3bf3a28d3c5
--- /dev/null
+++ b/lib/gitlab/template/gitlab_ci_syntax_yml_template.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Template
+ class GitlabCiSyntaxYmlTemplate < BaseTemplate
+ class << self
+ def extension
+ '.gitlab-ci.yml'
+ end
+
+ def categories
+ {
+ 'General' => ''
+ }
+ end
+
+ def base_dir
+ Rails.root.join('lib/gitlab/ci/syntax_templates')
+ end
+
+ def finder(project = nil)
+ Gitlab::Template::Finders::GlobalTemplateFinder.new(
+ self.base_dir, self.extension, self.categories
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index e12af6bf0a4..c295cc75da5 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -5,9 +5,8 @@ module Gitlab
class GitlabCiYmlTemplate < BaseTemplate
BASE_EXCLUDED_PATTERNS = [%r{\.latest\.}].freeze
- def content
- explanation = "# This file is a template, and might need editing before it works on your project."
- [explanation, super].join("\n")
+ def description
+ "# This file is a template, and might need editing before it works on your project."
end
class << self
diff --git a/lib/gitlab/template/metrics_dashboard_template.rb b/lib/gitlab/template/metrics_dashboard_template.rb
index 88fc3007b63..469f97d7cb1 100644
--- a/lib/gitlab/template/metrics_dashboard_template.rb
+++ b/lib/gitlab/template/metrics_dashboard_template.rb
@@ -3,9 +3,8 @@
module Gitlab
module Template
class MetricsDashboardTemplate < BaseTemplate
- def content
- explanation = "# This file is a template, and might need editing before it works on your project."
- [explanation, super].join("\n")
+ def description
+ "# This file is a template, and might need editing before it works on your project."
end
class << self
diff --git a/lib/gitlab/throttle.rb b/lib/gitlab/throttle.rb
index aebf8d92cb3..520075012e8 100644
--- a/lib/gitlab/throttle.rb
+++ b/lib/gitlab/throttle.rb
@@ -2,6 +2,8 @@
module Gitlab
class Throttle
+ DEFAULT_RATE_LIMITING_RESPONSE_TEXT = 'Retry later'
+
def self.settings
Gitlab::CurrentSettings.current_application_settings
end
@@ -46,5 +48,9 @@ module Gitlab
{ limit: limit_proc, period: period_proc }
end
+
+ def self.rate_limiting_response_text
+ (settings.rate_limiting_response_text.presence || DEFAULT_RATE_LIMITING_RESPONSE_TEXT) + "\n"
+ end
end
end
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index 618e359211b..ca4afb4c19c 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -24,7 +24,9 @@ module Gitlab
Gitlab::CurrentSettings.snowplow_enabled?
end
- def event(category, action, label: nil, property: nil, value: nil, context: nil)
+ def event(category, action, label: nil, property: nil, value: nil, context: [], standard_context: nil)
+ context.push(standard_context.to_context) if standard_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)
end
diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb
new file mode 100644
index 00000000000..71dfe27dd5a
--- /dev/null
+++ b/lib/gitlab/tracking/standard_context.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracking
+ class StandardContext
+ GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-1'.freeze
+
+ def initialize(namespace: nil, project: nil, **data)
+ @namespace = namespace
+ @project = project
+ @data = data
+ end
+
+ def namespace_id
+ namespace&.id
+ end
+
+ def project_id
+ @project&.id
+ end
+
+ def to_context
+ SnowplowTracker::SelfDescribingJson.new(GITLAB_STANDARD_SCHEMA_URL, to_h)
+ 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)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index ce59e10241e..f98c488bbe5 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -18,6 +18,8 @@ module Gitlab
def build(object, **options)
# Objects are sometimes wrapped in a BatchLoader instance
case object.itself
+ when Board
+ board_url(object, **options)
when ::Ci::Build
instance.project_job_url(object.project, object, **options)
when Commit
@@ -52,6 +54,14 @@ module Gitlab
end
# rubocop:enable Metrics/CyclomaticComplexity
+ def board_url(board, **options)
+ if board.project_board?
+ instance.project_board_url(board.resource_parent, board, **options)
+ else
+ instance.group_board_url(board.resource_parent, board, **options)
+ end
+ end
+
def commit_url(commit, **options)
return '' unless commit.project
diff --git a/lib/gitlab/usage/metric.rb b/lib/gitlab/usage/metric.rb
new file mode 100644
index 00000000000..e1648c78168
--- /dev/null
+++ b/lib/gitlab/usage/metric.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ class Metric
+ include ActiveModel::Model
+
+ InvalidMetricError = Class.new(RuntimeError)
+
+ attr_accessor :default_generation_path, :value
+
+ validates :default_generation_path, presence: true
+
+ def definition
+ self.class.definitions[default_generation_path]
+ end
+
+ def unflatten_default_path
+ unflatten(default_generation_path.split('.'), value)
+ end
+
+ class << self
+ def definitions
+ @definitions ||= Gitlab::Usage::MetricDefinition.definitions
+ end
+
+ def dictionary
+ definitions.map { |key, definition| definition.to_dictionary }
+ end
+ end
+
+ private
+
+ def unflatten(keys, value)
+ loop do
+ value = { keys.pop.to_sym => value }
+ break if keys.blank?
+ end
+ value
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb
new file mode 100644
index 00000000000..96e572bb3db
--- /dev/null
+++ b/lib/gitlab/usage/metric_definition.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ class MetricDefinition
+ METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema.json')
+
+ attr_reader :path
+ attr_reader :attributes
+
+ def initialize(path, opts = {})
+ @path = path
+ @attributes = opts
+ end
+
+ # The key is defined by default_generation and full_path
+ def key
+ full_path[default_generation.to_sym]
+ end
+
+ def to_h
+ attributes
+ 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}`"))
+ end
+ end
+
+ alias_method :to_dictionary, :to_h
+
+ class << self
+ def paths
+ @paths ||= [Rails.root.join('config', 'metrics', '**', '*.yml')]
+ end
+
+ def definitions
+ @definitions ||= load_all!
+ end
+
+ def schemer
+ @schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH))
+ end
+
+ private
+
+ def load_all!
+ paths.each_with_object({}) do |glob_path, definitions|
+ load_all_from_path!(definitions, glob_path)
+ end
+ end
+
+ def load_from_file(path)
+ definition = File.read(path)
+ definition = YAML.safe_load(definition)
+ definition.deep_symbolize_keys!
+
+ self.new(path, definition).tap(&:validate!)
+ rescue => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new(e.message))
+ end
+
+ def load_all_from_path!(definitions, glob_path)
+ Dir.glob(glob_path).each do |path|
+ definition = load_from_file(path)
+
+ if previous = definitions[definition.key]
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new("Metric '#{definition.key}' is already defined in '#{previous.path}'"))
+ end
+
+ definitions[definition.key] = definition
+ end
+ end
+ end
+
+ private
+
+ def method_missing(method, *args)
+ attributes[method] || super
+ end
+ end
+ end
+end
+
+Gitlab::Usage::MetricDefinition.prepend_if_ee('EE::Gitlab::Usage::MetricDefinition')
diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb
index ca7699e64e1..ed9dad37f3e 100644
--- a/lib/gitlab/usage_data_counters.rb
+++ b/lib/gitlab/usage_data_counters.rb
@@ -3,7 +3,7 @@
module Gitlab
module UsageDataCounters
COUNTERS = [
- GuestPackageEventCounter,
+ PackageEventCounter,
WikiPageCounter,
WebIdeCounter,
NoteCounter,
diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
index b7c0abae227..4966afd534a 100644
--- a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
+++ b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
@@ -8,6 +8,9 @@
# 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
+ 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
events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
@@ -22,7 +25,6 @@
'incident_management_alert_todo',
'incident_management_alert_create_incident'
]
- feature_flag: usage_data_incident_management_alerts_total_unique_counts
- name: incident_management_incidents_total_unique_counts
operator: OR
events: [
@@ -38,4 +40,3 @@
'incident_management_incident_unrelate',
'incident_management_incident_change_confidential'
]
- feature_flag: usage_data_incident_management_incidents_total_unique_counts
diff --git a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
new file mode 100644
index 00000000000..572ad866895
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab::UsageDataCounters
+ class CiTemplateUniqueCounter
+ REDIS_SLOT = 'ci_templates'.freeze
+
+ TEMPLATE_TO_EVENT = {
+ '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',
+ 'Jobs/Build.gitlab-ci.yml' => 'auto_devops_build',
+ 'Jobs/Deploy.gitlab-ci.yml' => 'auto_devops_deploy',
+ 'Jobs/Deploy.latest.gitlab-ci.yml' => 'auto_devops_deploy_latest',
+ 'Security/SAST.gitlab-ci.yml' => 'security_sast',
+ 'Security/Secret-Detection.gitlab-ci.yml' => 'security_secret_detection',
+ 'Terraform/Base.latest.gitlab-ci.yml' => 'terraform_base_latest'
+ }.freeze
+
+ class << self
+ def track_unique_project_event(project_id:, template:)
+ return if Feature.disabled?(:usage_data_track_ci_templates_unique_projects, default_enabled: :yaml)
+
+ if event = unique_project_event(template)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event, values: project_id)
+ end
+ end
+
+ private
+
+ def unique_project_event(template)
+ if name = TEMPLATE_TO_EVENT[template]
+ "p_#{REDIS_SLOT}_#{name}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/counter_events/guest_package_events.yml b/lib/gitlab/usage_data_counters/counter_events/guest_package_events.yml
deleted file mode 100644
index a9b9f8ea235..00000000000
--- a/lib/gitlab/usage_data_counters/counter_events/guest_package_events.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-- i_package_composer_guest_delete
-- i_package_composer_guest_pull
-- i_package_composer_guest_push
-- i_package_conan_guest_delete
-- i_package_conan_guest_pull
-- i_package_conan_guest_push
-- i_package_container_guest_delete
-- i_package_container_guest_pull
-- i_package_container_guest_push
-- i_package_debian_guest_delete
-- i_package_debian_guest_pull
-- i_package_debian_guest_push
-- i_package_generic_guest_delete
-- i_package_generic_guest_pull
-- i_package_generic_guest_push
-- i_package_golang_guest_delete
-- i_package_golang_guest_pull
-- i_package_golang_guest_push
-- i_package_maven_guest_delete
-- i_package_maven_guest_pull
-- i_package_maven_guest_push
-- i_package_npm_guest_delete
-- i_package_npm_guest_pull
-- i_package_npm_guest_push
-- i_package_nuget_guest_delete
-- i_package_nuget_guest_pull
-- i_package_nuget_guest_push
-- i_package_pypi_guest_delete
-- i_package_pypi_guest_pull
-- i_package_pypi_guest_push
-- i_package_tag_guest_delete
-- i_package_tag_guest_pull
-- i_package_tag_guest_push
diff --git a/lib/gitlab/usage_data_counters/counter_events/package_events.yml b/lib/gitlab/usage_data_counters/counter_events/package_events.yml
new file mode 100644
index 00000000000..f6bddabdd44
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/counter_events/package_events.yml
@@ -0,0 +1,46 @@
+---
+- i_package_composer_delete_package
+- i_package_composer_pull_package
+- i_package_composer_push_package
+- i_package_conan_delete_package
+- i_package_conan_pull_package
+- i_package_conan_push_package
+- i_package_container_delete_package
+- i_package_container_pull_package
+- i_package_container_push_package
+- i_package_debian_delete_package
+- i_package_debian_pull_package
+- i_package_debian_push_package
+- i_package_delete_package
+- i_package_delete_package_by_deploy_token
+- i_package_delete_package_by_guest
+- i_package_delete_package_by_user
+- i_package_generic_delete_package
+- i_package_generic_pull_package
+- i_package_generic_push_package
+- i_package_golang_delete_package
+- i_package_golang_pull_package
+- i_package_golang_push_package
+- i_package_maven_delete_package
+- i_package_maven_pull_package
+- i_package_maven_push_package
+- i_package_npm_delete_package
+- i_package_npm_pull_package
+- i_package_npm_push_package
+- i_package_nuget_delete_package
+- i_package_nuget_pull_package
+- i_package_nuget_push_package
+- i_package_pull_package
+- i_package_pull_package_by_deploy_token
+- i_package_pull_package_by_guest
+- i_package_pull_package_by_user
+- i_package_push_package
+- i_package_push_package_by_deploy_token
+- i_package_push_package_by_guest
+- i_package_push_package_by_user
+- i_package_pypi_delete_package
+- i_package_pypi_pull_package
+- i_package_pypi_push_package
+- i_package_tag_delete_package
+- i_package_tag_pull_package
+- i_package_tag_push_package
diff --git a/lib/gitlab/usage_data_counters/editor_unique_counter.rb b/lib/gitlab/usage_data_counters/editor_unique_counter.rb
index eeb26c11bfa..bef3fc7b504 100644
--- a/lib/gitlab/usage_data_counters/editor_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/editor_unique_counter.rb
@@ -53,7 +53,7 @@ module Gitlab
return unless Feature.enabled?(:track_editor_edit_actions, default_enabled: true)
return unless author
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author.id, action, time)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id, time: time)
end
def count_unique(actions, date_from, date_to)
diff --git a/lib/gitlab/usage_data_counters/guest_package_event_counter.rb b/lib/gitlab/usage_data_counters/guest_package_event_counter.rb
deleted file mode 100644
index a9bcbfadda2..00000000000
--- a/lib/gitlab/usage_data_counters/guest_package_event_counter.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module UsageDataCounters
- class GuestPackageEventCounter < BaseCounter
- KNOWN_EVENTS_PATH = File.expand_path('counter_events/guest_package_events.yml', __dir__)
- KNOWN_EVENTS = YAML.safe_load(File.read(KNOWN_EVENTS_PATH)).freeze
- PREFIX = 'package_guest'
- 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 b61720c7638..47361d831b2 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -39,20 +39,31 @@ module Gitlab
#
# Usage:
#
- # * Track event: Gitlab::UsageDataCounters::HLLRedisCounter.track_event(user_id, 'g_compliance_dashboard')
+ # * Track event: Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_dashboard', values: user_id)
# * Get unique counts per user: Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_dashboard', start_date: 28.days.ago, end_date: Date.current)
class << self
include Gitlab::Utils::UsageData
- def track_event(value, event_name, time = Time.zone.now)
- track(value, event_name, time: time)
- end
-
- def track_event_in_context(value, event_name, context, time = Time.zone.now)
+ # Track unique events
+ #
+ # event_name - The event name.
+ # values - One or multiple values counted.
+ # time - Time of the action, set to Time.current.
+ def track_event(event_name, values:, time: Time.current)
+ track(values, event_name, time: time)
+ end
+
+ # Track unique events
+ #
+ # event_name - The event name.
+ # values - One or multiple values counted.
+ # context - Event context, plan level tracking.
+ # time - Time of the action, set to Time.current.
+ def track_event_in_context(event_name, values:, context:, time: Time.zone.now)
return if context.blank?
return unless context.in?(valid_context_list)
- track(value, event_name, context: context, time: time)
+ track(values, event_name, context: context, time: time)
end
def unique_events(event_names:, start_date:, end_date:, context: '')
@@ -114,16 +125,16 @@ module Gitlab
private
- def track(value, event_name, context: '', time: Time.zone.now)
+ def track(values, event_name, context: '', time: Time.zone.now)
return unless Gitlab::CurrentSettings.usage_ping_enabled?
event = event_for(event_name)
raise UnknownEvent, "Unknown event #{event_name}" unless event.present?
- Gitlab::Redis::HLL.add(key: redis_key(event, time, context), value: value, expiry: expiry(event))
+ Gitlab::Redis::HLL.add(key: redis_key(event, time, context), value: values, expiry: expiry(event))
end
- # The aray of valid context on which we allow tracking
+ # The array of valid context on which we allow tracking
def valid_context_list
Plan.all_plans
end
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 0fed8e1c211..f649e7f407d 100644
--- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -148,7 +148,7 @@ module Gitlab
return unless Feature.enabled?(:track_issue_activity_actions, default_enabled: true)
return unless author
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author.id, action, time)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id, time: time)
end
end
end
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index 25cf388aedf..4cbde0c0372 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -248,6 +248,26 @@
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_i_testing_test_case_parsed
+- name: i_testing_metrics_report_widget_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_metrics_report_widget_total
+- name: i_testing_group_code_coverage_visit_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_group_code_coverage_visit_total
+- name: i_testing_full_code_quality_report_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_full_code_quality_report_total
+- name: i_testing_web_performance_widget_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_web_performance_widget_total
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit
@@ -425,3 +445,126 @@
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
diff --git a/lib/gitlab/usage_data_counters/known_events/package_events.yml b/lib/gitlab/usage_data_counters/known_events/package_events.yml
index 4c3138dc000..78a2a587b34 100644
--- a/lib/gitlab/usage_data_counters/known_events/package_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/package_events.yml
@@ -1,331 +1,111 @@
---
-- name: i_package_composer_deploy_token_delete
- category: composer_packages
+- name: i_package_composer_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_composer_deploy_token_pull
- category: composer_packages
+- name: i_package_composer_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_composer_deploy_token_push
- category: composer_packages
+- name: i_package_conan_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_composer_user_delete
- category: composer_packages
+- name: i_package_conan_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_composer_user_pull
- category: composer_packages
+- name: i_package_container_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_composer_user_push
- category: composer_packages
+- name: i_package_container_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_conan_deploy_token_delete
- category: conan_packages
+- name: i_package_debian_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_conan_deploy_token_pull
- category: conan_packages
+- name: i_package_debian_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_conan_deploy_token_push
- category: conan_packages
+- name: i_package_generic_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_conan_user_delete
- category: conan_packages
+- name: i_package_generic_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_conan_user_pull
- category: conan_packages
+- name: i_package_golang_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_conan_user_push
- category: conan_packages
+- name: i_package_golang_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_container_deploy_token_delete
- category: container_packages
+- name: i_package_maven_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_container_deploy_token_pull
- category: container_packages
+- name: i_package_maven_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_container_deploy_token_push
- category: container_packages
+- name: i_package_npm_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_container_user_delete
- category: container_packages
+- name: i_package_npm_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_container_user_pull
- category: container_packages
+- name: i_package_nuget_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_container_user_push
- category: container_packages
+- name: i_package_nuget_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_debian_deploy_token_delete
- category: debian_packages
+- name: i_package_pypi_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_debian_deploy_token_pull
- category: debian_packages
+- name: i_package_pypi_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_debian_deploy_token_push
- category: debian_packages
+- name: i_package_tag_deploy_token
+ category: deploy_token_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
-- name: i_package_debian_user_delete
- category: debian_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_debian_user_pull
- category: debian_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_debian_user_push
- category: debian_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_generic_deploy_token_delete
- category: generic_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_generic_deploy_token_pull
- category: generic_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_generic_deploy_token_push
- category: generic_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_generic_user_delete
- category: generic_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_generic_user_pull
- category: generic_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_generic_user_push
- category: generic_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_golang_deploy_token_delete
- category: golang_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_golang_deploy_token_pull
- category: golang_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_golang_deploy_token_push
- category: golang_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_golang_user_delete
- category: golang_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_golang_user_pull
- category: golang_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_golang_user_push
- category: golang_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_maven_deploy_token_delete
- category: maven_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_maven_deploy_token_pull
- category: maven_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_maven_deploy_token_push
- category: maven_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_maven_user_delete
- category: maven_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_maven_user_pull
- category: maven_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_maven_user_push
- category: maven_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_npm_deploy_token_delete
- category: npm_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_npm_deploy_token_pull
- category: npm_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_npm_deploy_token_push
- category: npm_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_npm_user_delete
- category: npm_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_npm_user_pull
- category: npm_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_npm_user_push
- category: npm_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_nuget_deploy_token_delete
- category: nuget_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_nuget_deploy_token_pull
- category: nuget_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_nuget_deploy_token_push
- category: nuget_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_nuget_user_delete
- category: nuget_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_nuget_user_pull
- category: nuget_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_nuget_user_push
- category: nuget_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_pypi_deploy_token_delete
- category: pypi_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_pypi_deploy_token_pull
- category: pypi_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_pypi_deploy_token_push
- category: pypi_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_pypi_user_delete
- category: pypi_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_pypi_user_pull
- category: pypi_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_pypi_user_push
- category: pypi_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_tag_deploy_token_delete
- category: tag_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_tag_deploy_token_pull
- category: tag_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_tag_deploy_token_push
- category: tag_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_tag_user_delete
- category: tag_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_tag_user_pull
- category: tag_packages
- aggregation: weekly
- redis_slot: package
- feature_flag: collect_package_events_redis
-- name: i_package_tag_user_push
- category: tag_packages
+- name: i_package_tag_user
+ category: user_packages
aggregation: weekly
redis_slot: package
feature_flag: collect_package_events_redis
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
new file mode 100644
index 00000000000..11d59257ed9
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module MergeRequestActivityUniqueCounter
+ MR_DIFFS_ACTION = 'i_code_review_mr_diffs'
+ MR_DIFFS_SINGLE_FILE_ACTION = 'i_code_review_mr_single_file_diffs'
+ MR_DIFFS_USER_SINGLE_FILE_ACTION = 'i_code_review_user_single_file_diffs'
+ MR_CREATE_ACTION = 'i_code_review_user_create_mr'
+ 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_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'
+ MR_CREATE_REVIEW_NOTE_ACTION = 'i_code_review_user_create_review_note'
+ MR_PUBLISH_REVIEW_ACTION = 'i_code_review_user_publish_review'
+ 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'
+
+ class << self
+ def track_mr_diffs_action(merge_request:)
+ track_unique_action_by_merge_request(MR_DIFFS_ACTION, merge_request)
+ end
+
+ def track_mr_diffs_single_file_action(merge_request:, user:)
+ track_unique_action_by_merge_request(MR_DIFFS_SINGLE_FILE_ACTION, merge_request)
+ track_unique_action_by_user(MR_DIFFS_USER_SINGLE_FILE_ACTION, user)
+ end
+
+ def track_create_mr_action(user:)
+ track_unique_action_by_user(MR_CREATE_ACTION, user)
+ end
+
+ def track_close_mr_action(user:)
+ track_unique_action_by_user(MR_CLOSE_ACTION, user)
+ end
+
+ def track_merge_mr_action(user:)
+ track_unique_action_by_user(MR_MERGE_ACTION, user)
+ end
+
+ def track_reopen_mr_action(user:)
+ track_unique_action_by_user(MR_REOPEN_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)
+ end
+
+ def track_edit_comment_action(note:)
+ track_unique_action_by_user(MR_EDIT_COMMENT_ACTION, note.author)
+ track_multiline_unique_action(MR_EDIT_MULTILINE_COMMENT_ACTION, note)
+ end
+
+ def track_remove_comment_action(note:)
+ track_unique_action_by_user(MR_REMOVE_COMMENT_ACTION, note.author)
+ track_multiline_unique_action(MR_REMOVE_MULTILINE_COMMENT_ACTION, note)
+ end
+
+ def track_create_review_note_action(user:)
+ track_unique_action_by_user(MR_CREATE_REVIEW_NOTE_ACTION, user)
+ end
+
+ def track_publish_review_action(user:)
+ track_unique_action_by_user(MR_PUBLISH_REVIEW_ACTION, user)
+ end
+
+ private
+
+ def track_unique_action_by_merge_request(action, merge_request)
+ track_unique_action(action, merge_request.id)
+ end
+
+ 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
+
+ def track_multiline_unique_action(action, note)
+ return unless note.is_a?(DiffNote) && note.multiline?
+
+ track_unique_action_by_user(action, note.author)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/package_event_counter.rb b/lib/gitlab/usage_data_counters/package_event_counter.rb
new file mode 100644
index 00000000000..700b518eae3
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/package_event_counter.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ class PackageEventCounter < BaseCounter
+ KNOWN_EVENTS_PATH = File.expand_path('counter_events/package_events.yml', __dir__)
+ KNOWN_EVENTS = YAML.safe_load(File.read(KNOWN_EVENTS_PATH)).freeze
+ PREFIX = 'package_events'
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/track_unique_events.rb b/lib/gitlab/usage_data_counters/track_unique_events.rb
index 95380ae0b1d..20da9665876 100644
--- a/lib/gitlab/usage_data_counters/track_unique_events.rb
+++ b/lib/gitlab/usage_data_counters/track_unique_events.rb
@@ -43,7 +43,7 @@ module Gitlab
return unless Gitlab::UsageDataCounters::HLLRedisCounter.known_event?(transformed_action.to_s)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, transformed_action.to_s, time)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(transformed_action.to_s, values: author_id, time: time)
track_git_write_action(author_id, transformed_action, time)
end
@@ -73,7 +73,7 @@ module Gitlab
def track_git_write_action(author_id, transformed_action, time)
return unless GIT_WRITE_ACTIONS.include?(transformed_action)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, GIT_WRITE_ACTION, time)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(GIT_WRITE_ACTION, values: author_id, time: time)
end
end
end
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index 3df54e74b4f..29f02a5912a 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -174,6 +174,18 @@ module Gitlab
rescue IPAddr::InvalidAddressError
end
+ # A safe alternative to String#downcase!
+ #
+ # This will make copies of frozen strings but downcase unfrozen
+ # strings in place, reducing allocations.
+ def safe_downcase!(str)
+ if str.frozen?
+ str.downcase
+ else
+ str.downcase! || str
+ end
+ end
+
# Converts a string to an Addressable::URI object.
# If the string is not a valid URI, it returns nil.
# Param uri_string should be a String object.
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 0d28a1cd035..baccadd9594 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -61,7 +61,10 @@ module Gitlab
end
def estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)
- Gitlab::Database::PostgresHll::BatchDistinctCounter.new(relation, column).estimate_distinct_count(batch_size: batch_size, start: start, finish: finish)
+ Gitlab::Database::PostgresHll::BatchDistinctCounter
+ .new(relation, column)
+ .execute(batch_size: batch_size, start: start, finish: finish)
+ .estimated_distinct_count
rescue ActiveRecord::StatementInvalid
FALLBACK
# catch all rescue should be removed as a part of feature flag rollout issue
@@ -119,7 +122,7 @@ module Gitlab
def track_usage_event(event_name, values)
return unless Feature.enabled?(:"usage_data_#{event_name}", default_enabled: true)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name.to_s)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name.to_s, values: values)
end
private
@@ -142,7 +145,8 @@ module Gitlab
def prometheus_server_address
if Gitlab::Prometheus::Internal.prometheus_enabled?
- Gitlab::Prometheus::Internal.server_address
+ # Stripping protocol from URI
+ Gitlab::Prometheus::Internal.uri&.strip&.sub(%r{^https?://}, '')
elsif Gitlab::Consul::Internal.api_url
Gitlab::Consul::Internal.discover_prometheus_server_address
end
diff --git a/lib/gitlab/uuid.rb b/lib/gitlab/uuid.rb
index 12a4efabc44..80caf2c6788 100644
--- a/lib/gitlab/uuid.rb
+++ b/lib/gitlab/uuid.rb
@@ -9,6 +9,7 @@ module Gitlab
production: "58dc0f06-936c-43b3-93bb-71693f1b6570"
}.freeze
+ UUID_V5_PATTERN = /\h{8}-\h{4}-5\h{3}-\h{4}-\h{4}\h{8}/.freeze
NAMESPACE_REGEX = /(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/.freeze
PACK_PATTERN = "NnnnnN".freeze
@@ -17,6 +18,10 @@ module Gitlab
Digest::UUID.uuid_v5(namespace_id, name)
end
+ def v5?(string)
+ string.match(UUID_V5_PATTERN).present?
+ end
+
private
def default_namespace_id
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index a22740ab9b7..76cf769d041 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -123,14 +123,6 @@ module Gitlab
end
end
- def visibility_level_decreased?
- return false unless visibility_level_previous_changes
-
- before, after = visibility_level_previous_changes
-
- before && after && after < before
- end
-
def visibility_level_previous_changes
previous_changes[:visibility_level]
end
diff --git a/lib/gitlab/webpack/manifest.rb b/lib/gitlab/webpack/manifest.rb
index 5873d9c2b99..9c967d99e3a 100644
--- a/lib/gitlab/webpack/manifest.rb
+++ b/lib/gitlab/webpack/manifest.rb
@@ -69,8 +69,8 @@ module Gitlab
def manifest
if Gitlab.config.webpack.dev_server.enabled
- # Don't cache if we're in dev server mode, manifest may change ...
- load_manifest
+ # Only cache at request level if we're in dev server mode, manifest may change ...
+ Gitlab::SafeRequestStore.fetch('manifest.json') { load_manifest }
else
# ... otherwise cache at class level, as JSON loading/parsing can be expensive
strong_memoize(:manifest) { load_manifest }
diff --git a/lib/gitlab_danger.rb b/lib/gitlab_danger.rb
index ec9dd20ccc0..b0974e02edd 100644
--- a/lib/gitlab_danger.rb
+++ b/lib/gitlab_danger.rb
@@ -11,7 +11,7 @@ class GitlabDanger
karma
database
commit_messages
- product_analytics
+ product_intelligence
utility_css
pajamas
pipeline
diff --git a/lib/release_highlights/validator.rb b/lib/release_highlights/validator.rb
new file mode 100644
index 00000000000..6f3f90b5f30
--- /dev/null
+++ b/lib/release_highlights/validator.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module ReleaseHighlights
+ class Validator
+ attr_reader :errors, :file
+
+ def initialize(file:)
+ @file = file
+ @errors = []
+ end
+
+ def valid?
+ document = YAML.parse(File.read(file))
+
+ document.root.children.each do |entry|
+ entry = ReleaseHighlights::Validator::Entry.new(entry)
+
+ errors.push(entry.errors.full_messages) unless entry.valid?
+ end
+
+ errors.none?
+ end
+
+ def self.validate_all!
+ @all_errors = []
+
+ ReleaseHighlight.file_paths.each do |file_path|
+ instance = self.new(file: file_path)
+
+ @all_errors.push([instance.errors, instance.file]) unless instance.valid?
+ end
+
+ @all_errors.none?
+ end
+
+ def self.error_message
+ io = StringIO.new
+
+ @all_errors.each do |errors, file|
+ message = "Validation failed for #{file}"
+ line = -> { io.puts "-" * message.length }
+
+ line.call
+ io.puts message
+ line.call
+
+ errors.flatten.each { |error| io.puts "* #{error}" }
+ io.puts
+ end
+
+ io.string
+ end
+ end
+end
diff --git a/lib/release_highlights/validator/entry.rb b/lib/release_highlights/validator/entry.rb
new file mode 100644
index 00000000000..0dbe0cdf882
--- /dev/null
+++ b/lib/release_highlights/validator/entry.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module ReleaseHighlights
+ class Validator::Entry
+ include ActiveModel::Validations
+ include ActiveModel::Validations::Callbacks
+
+ PACKAGES = %w(Core Starter Premium Ultimate).freeze
+
+ attr_reader :entry
+
+ validates :title, :body, :stage, presence: true
+ validates :'self-managed', :'gitlab-com', inclusion: { in: [true, false], message: "must be a boolean" }
+ validates :url, :image_url, format: { with: URI::DEFAULT_PARSER.make_regexp, message: 'must be a URL' }
+ validates :release, numericality: true
+ validate :validate_published_at
+ validate :validate_packages
+
+ after_validation :add_line_numbers_to_errors!
+
+ def initialize(entry)
+ @entry = entry
+ end
+
+ def validate_published_at
+ published_at = value_for('published_at')
+
+ return if published_at.is_a?(Date)
+
+ errors.add(:published_at, 'must be valid Date')
+ end
+
+ def validate_packages
+ packages = value_for('packages')
+
+ if !packages.is_a?(Array) || packages.empty? || packages.any? { |p| PACKAGES.exclude?(p) }
+ errors.add(:packages, "must be one of #{PACKAGES}")
+ end
+ end
+
+ def read_attribute_for_validation(key)
+ value_for(key)
+ end
+
+ private
+
+ def add_line_numbers_to_errors!
+ errors.messages.each do |attribute, messages|
+ messages.map! { |m| "#{m} (line #{line_number_for(attribute)})" }
+ end
+ end
+
+ def line_number_for(key)
+ node = find_node(key)
+
+ (node&.start_line || @entry.start_line) + 1
+ end
+
+ def value_for(key)
+ node = find_node(key)
+
+ return if node.nil?
+
+ index = entry.children.find_index(node)
+
+ next_node = entry.children[index + 1]
+ next_node&.to_ruby
+ end
+
+ def find_node(key)
+ entry.children.find {|node| node.try(:value) == key.to_s }
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/git.rake b/lib/tasks/gitlab/git.rake
index 8a53b51d4fe..abb15f29328 100644
--- a/lib/tasks/gitlab/git.rake
+++ b/lib/tasks/gitlab/git.rake
@@ -21,5 +21,39 @@ namespace :gitlab do
failures.each { |f| puts "- #{f}" }
end
end
+
+ # Example for all projects:
+ #
+ # $ bin/rake gitlab:git:checksum_projects
+ # 1,cfa3f06ba235c13df0bb28e079bcea62c5848af2
+ # 2,
+ # 3,3f3fb58a8106230e3a6c6b48adc2712fb3b6ef87
+ # 4,0000000000000000000000000000000000000000
+ #
+ # Example with a list of project IDs:
+ #
+ # $ CHECKSUM_PROJECT_IDS="1,3" bin/rake gitlab:git:checksum_projects
+ # 1,cfa3f06ba235c13df0bb28e079bcea62c5848af2
+ # 3,3f3fb58a8106230e3a6c6b48adc2712fb3b6ef87
+ #
+ # - If a repository does not exist, the project ID is output with a blank checksum
+ # - If a repository exists but is empty, the output checksum is `0000000000000000000000000000000000000000`
+ # - If given specific IDs, projects which do not exist are skipped
+ desc 'GitLab | Git | Generate checksum of project repository refs'
+ task checksum_projects: :environment do
+ project_ids = ENV['CHECKSUM_PROJECT_IDS']&.split(',')
+ relation = Project
+ relation = relation.where(id: project_ids) if project_ids.present?
+
+ relation.find_each(batch_size: 100) do |project|
+ next unless project.repo_exists?
+
+ result = project.repository.checksum
+ rescue => e
+ result = "Ignored error: #{e.message}".squish.truncate(255)
+ ensure
+ puts "#{project.id},#{result}"
+ end
+ end
end
end
diff --git a/lib/tasks/gitlab/graphql.rake b/lib/tasks/gitlab/graphql.rake
index 5a583183924..f708114c226 100644
--- a/lib/tasks/gitlab/graphql.rake
+++ b/lib/tasks/gitlab/graphql.rake
@@ -33,6 +33,44 @@ namespace :gitlab do
)
namespace :graphql do
+ 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) }
+ else
+ Gitlab::Graphql::Queries.all
+ end
+
+ failed = queries.flat_map do |defn|
+ summary, errs = defn.validate(GitlabSchema)
+
+ case summary
+ when :client_query
+ warn("SKIP #{defn.file}: client query")
+ else
+ warn("OK #{defn.file}") if errs.empty?
+ errs.each do |err|
+ warn(<<~MSG)
+ ERROR #{defn.file}: #{err.message} (at #{err.path.join('.')})
+ MSG
+ end
+ end
+
+ errs.empty? ? [] : [defn.file]
+ end
+
+ if failed.present?
+ format_output(
+ "#{failed.count} GraphQL #{'query'.pluralize(failed.count)} out of #{queries.count} failed validation:",
+ *failed.map do |name|
+ known_failure = Gitlab::Graphql::Queries.known_failure?(name)
+ "- #{name}" + (known_failure ? ' (known failure)' : '')
+ end
+ )
+ abort unless failed.all? { |name| Gitlab::Graphql::Queries.known_failure?(name) }
+ end
+ end
+
desc 'GitLab | GraphQL | Generate GraphQL docs'
task compile_docs: [:environment, :enable_feature_flags] do
renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema.graphql_definition, render_options)
@@ -78,11 +116,11 @@ def render_options
}
end
-def format_output(str)
+def format_output(*strs)
heading = '#' * 10
puts heading
puts '#'
- puts "# #{str}"
+ strs.each { |str| puts "# #{str}" }
puts '#'
puts heading
end
diff --git a/lib/tasks/gitlab/packages/events.rake b/lib/tasks/gitlab/packages/events.rake
index ca507fb5320..cfe97984dda 100644
--- a/lib/tasks/gitlab/packages/events.rake
+++ b/lib/tasks/gitlab/packages/events.rake
@@ -5,18 +5,18 @@ namespace :gitlab do
namespace :packages do
namespace :events do
task generate: :environment do
- Rake::Task["gitlab:packages:events:generate_guest"].invoke
+ Rake::Task["gitlab:packages:events:generate_counts"].invoke
Rake::Task["gitlab:packages:events:generate_unique"].invoke
rescue => e
logger.error("Error building events list: #{e}")
end
- task generate_guest: :environment do
+ task generate_counts: :environment do
logger = Logger.new(STDOUT)
logger.info('Building list of package events...')
- path = Gitlab::UsageDataCounters::GuestPackageEventCounter::KNOWN_EVENTS_PATH
- File.open(path, "w") { |file| file << guest_events_list.to_yaml }
+ path = Gitlab::UsageDataCounters::PackageEventCounter::KNOWN_EVENTS_PATH
+ File.open(path, "w") { |file| file << counter_events_list.to_yaml }
logger.info("Events file `#{path}` generated successfully")
rescue => e
@@ -43,26 +43,32 @@ namespace :gitlab do
def generate_unique_events_list
events = event_pairs.each_with_object([]) do |(event_type, event_scope), events|
- Packages::Event.originator_types.keys.excluding('guest').each do |originator|
- if name = Packages::Event.allowed_event_name(event_scope, event_type, originator)
- events << {
- "name" => name,
- "category" => "#{event_scope}_packages",
+ Packages::Event.originator_types.keys.excluding('guest').each do |originator_type|
+ events_definition = Packages::Event.unique_counters_for(event_scope, event_type, originator_type).map do |event_name|
+ {
+ "name" => event_name,
+ "category" => "#{originator_type}_packages",
"aggregation" => "weekly",
"redis_slot" => "package",
"feature_flag" => "collect_package_events_redis"
}
end
+
+ events.concat(events_definition)
end
end
- events.sort_by { |event| event["name"] }
+ events.sort_by { |event| event["name"] }.uniq
end
- def guest_events_list
- event_pairs.map do |event_type, event_scope|
- Packages::Event.allowed_event_name(event_scope, event_type, "guest")
- end.compact.sort
+ def counter_events_list
+ counters = event_pairs.flat_map do |event_type, event_scope|
+ Packages::Event.originator_types.keys.flat_map do |originator_type|
+ Packages::Event.counters_for(event_scope, event_type, originator_type)
+ end
+ end
+
+ counters.compact.sort.uniq
end
end
end
diff --git a/lib/tasks/gitlab/pages.rake b/lib/tasks/gitlab/pages.rake
new file mode 100644
index 00000000000..e15cbb4e32e
--- /dev/null
+++ b/lib/tasks/gitlab/pages.rake
@@ -0,0 +1,35 @@
+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")
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/storage.rake b/lib/tasks/gitlab/storage.rake
index ccc96b7edfb..f7819fd974b 100644
--- a/lib/tasks/gitlab/storage.rake
+++ b/lib/tasks/gitlab/storage.rake
@@ -116,6 +116,21 @@ namespace :gitlab do
helper.projects_list('projects using Hashed Storage', Project.with_storage_feature(:repository))
end
+ desc 'Gitlab | Storage | Prune projects using Hashed Storage. Remove all hashed directories that do not have a project associated'
+ task prune_hashed_projects: [:environment, :gitlab_environment] do
+ if Rails.env.production?
+ abort('This destructive action may only be run in development')
+ end
+
+ helper = Gitlab::HashedStorage::RakeHelper
+ name = 'projects using Hashed Storage'
+ relation = Project.with_storage_feature(:repository)
+ root = Gitlab.config.repositories.storages['default'].legacy_disk_path
+ dry_run = !ENV['FORCE'].present?
+
+ helper.prune(name, relation, dry_run: dry_run, root: root)
+ end
+
desc 'Gitlab | Storage | Summary of project attachments using Legacy Storage'
task legacy_attachments: :environment do
helper = Gitlab::HashedStorage::RakeHelper
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 9b034d1c6c2..79920968603 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -42,10 +42,7 @@ class UploadedFile
@remote_id = remote_id
end
- # TODO this function is meant to replace .from_params when the feature flag
- # upload_middleware_jwt_params_handler is removed
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/233895#roll-out-steps
- def self.from_params_without_field(params, upload_paths)
+ def self.from_params(params, upload_paths)
path = params['path']
remote_id = params['remote_id']
return if path.blank? && remote_id.blank?
@@ -71,33 +68,6 @@ class UploadedFile
)
end
- # Deprecated. Don't use it.
- # .from_params_without_field will replace this one
- # See .from_params_without_field and
- # https://gitlab.com/gitlab-org/gitlab/-/issues/233895#roll-out-steps
- def self.from_params(params, field, upload_paths, path_override = nil)
- path = path_override || params["#{field}.path"]
- remote_id = params["#{field}.remote_id"]
- return if path.blank? && remote_id.blank?
-
- if remote_id.present? # don't use file_path if remote_id is set
- file_path = nil
- elsif path.present?
- file_path = File.realpath(path)
-
- unless self.allowed_path?(file_path, Array(upload_paths).compact)
- raise InvalidPathError, "insecure path used '#{file_path}'"
- end
- end
-
- UploadedFile.new(file_path,
- filename: params["#{field}.name"],
- content_type: params["#{field}.type"] || 'application/octet-stream',
- sha256: params["#{field}.sha256"],
- remote_id: remote_id,
- size: params["#{field}.size"])
- end
-
def self.allowed_path?(file_path, paths)
paths.any? do |path|
File.exist?(path) && file_path.start_with?(File.realpath(path))
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 6b5ffc365e2..82fa7e3e31c 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: 2020-12-03 08:13\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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 "የ%{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 ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 1668530af22..13b37fb9ef3 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: 2020-12-03 08:15\n"
+"PO-Revision-Date: 2021-01-08 23:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -583,12 +583,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -1051,6 +1060,33 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1222,9 +1258,15 @@ 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 ""
@@ -1531,28 +1573,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1564,6 +1603,9 @@ 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 ""
@@ -1591,6 +1633,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1600,6 +1645,9 @@ 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 ""
@@ -1618,13 +1666,16 @@ 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."
+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."
+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"
@@ -1633,10 +1684,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1648,9 +1702,15 @@ 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 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 ""
+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 ""
@@ -1669,13 +1729,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1717,6 +1780,9 @@ 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 ""
@@ -2314,6 +2380,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2323,6 +2392,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2803,9 +2875,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2869,15 +2938,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2905,9 +2968,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2977,10 +3037,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -3046,12 +3106,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -3136,9 +3190,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3199,6 +3250,9 @@ 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 ""
@@ -3337,7 +3391,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3373,6 +3427,9 @@ 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 ""
@@ -3385,6 +3442,9 @@ 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 ""
@@ -3607,9 +3667,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3631,6 +3688,9 @@ 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 ""
@@ -3640,6 +3700,9 @@ 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 ""
@@ -3658,7 +3721,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3673,6 +3736,9 @@ 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 ""
@@ -3751,7 +3817,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3916,13 +3982,13 @@ msgstr[5] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3943,6 +4009,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -4045,9 +4114,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4219,6 +4285,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4237,12 +4309,18 @@ 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 ""
@@ -4255,6 +4333,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4282,6 +4363,9 @@ 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 ""
@@ -4330,9 +4414,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4489,10 +4570,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4513,10 +4594,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4558,7 +4642,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4621,9 +4705,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4636,12 +4717,21 @@ 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 ""
@@ -4651,13 +4741,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4672,15 +4762,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4693,9 +4780,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4720,9 +4804,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4807,22 +4888,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4864,10 +4951,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4921,6 +5017,30 @@ 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 ""
@@ -4951,9 +5071,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -5122,6 +5239,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5215,7 +5350,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5242,10 +5380,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5275,9 +5413,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5326,6 +5461,30 @@ 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 ""
@@ -5347,6 +5506,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5479,15 +5641,33 @@ 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|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 ""
@@ -5509,13 +5689,16 @@ 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 were successfully made."
+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}."
@@ -5527,9 +5710,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5797,9 +5977,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -6058,6 +6244,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -6070,6 +6259,18 @@ 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 ""
@@ -7177,10 +7378,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7456,6 +7657,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7585,6 +7804,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7681,13 +7903,13 @@ msgstr[5] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7696,18 +7918,42 @@ 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 policy:"
+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 ""
@@ -7735,9 +7981,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7747,9 +7990,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7774,6 +8014,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7792,9 +8035,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7873,16 +8113,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7918,12 +8152,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -8080,6 +8308,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8317,15 +8548,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8383,9 +8611,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8449,6 +8674,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8542,6 +8845,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8626,45 +8932,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8914,6 +9193,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8980,6 +9262,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -9028,6 +9316,9 @@ 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 ""
@@ -9235,18 +9526,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9259,6 +9544,9 @@ 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 ""
@@ -9307,9 +9595,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9799,9 +10084,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9811,6 +10093,9 @@ 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 ""
@@ -10012,22 +10297,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -10036,6 +10360,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -10045,18 +10372,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10330,6 +10672,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10414,9 +10759,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10471,9 +10813,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10513,6 +10852,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10540,12 +10882,18 @@ 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 ""
@@ -10579,6 +10927,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10648,10 +10999,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10732,6 +11083,9 @@ 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 ""
@@ -10801,6 +11155,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10816,9 +11173,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10852,6 +11206,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10888,9 +11245,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10933,6 +11287,9 @@ 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 ""
@@ -11074,6 +11431,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -11191,6 +11551,12 @@ 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 ""
@@ -11251,9 +11617,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11359,9 +11722,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11497,9 +11857,18 @@ 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 ""
@@ -11614,22 +11983,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11668,9 +12037,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11710,6 +12076,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11851,6 +12220,9 @@ 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 ""
@@ -11869,6 +12241,12 @@ 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 ""
@@ -11896,9 +12274,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -12049,6 +12424,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -12109,9 +12487,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -12208,9 +12583,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -12220,16 +12592,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12343,6 +12712,9 @@ 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 ""
@@ -12445,6 +12817,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12478,12 +12853,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12535,9 +12904,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12556,6 +12922,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12685,9 +13054,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -13153,6 +13519,12 @@ 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 ""
@@ -13228,9 +13600,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13450,7 +13819,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13678,9 +14047,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -14014,10 +14380,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -14041,9 +14413,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -14071,7 +14440,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -14104,6 +14473,9 @@ 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 ""
@@ -14182,6 +14554,9 @@ 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 ""
@@ -14191,22 +14566,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14434,6 +14833,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14608,6 +15010,9 @@ 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 ""
@@ -14689,6 +15094,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14737,6 +15148,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14797,19 +15211,19 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14833,6 +15247,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14989,13 +15406,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -15010,6 +15427,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15262,6 +15682,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,9 +15772,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15448,13 +15871,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15466,9 +15889,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15538,6 +15958,24 @@ 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 ""
@@ -15595,9 +16033,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15649,6 +16084,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15664,7 +16102,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15703,7 +16141,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15823,6 +16261,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15907,6 +16348,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15931,19 +16375,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16372,6 +16816,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16426,9 +16873,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16468,9 +16921,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16495,6 +16945,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16861,6 +17314,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16948,6 +17404,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17185,6 +17644,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -17206,6 +17668,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17347,6 +17812,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17479,9 +17950,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17542,6 +18010,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17557,9 +18028,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17704,9 +18172,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17722,9 +18196,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18295,9 +18766,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18481,9 +18949,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18622,6 +19087,9 @@ 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 ""
@@ -18634,6 +19102,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18643,6 +19114,9 @@ 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 ""
@@ -18943,6 +19417,12 @@ 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 ""
@@ -19081,7 +19561,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19327,6 +19807,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19345,6 +19828,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19582,6 +20068,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19603,27 +20092,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19639,9 +20206,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19660,6 +20239,15 @@ 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 ""
@@ -19957,6 +20545,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19966,10 +20557,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19987,7 +20575,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -20047,6 +20635,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -20113,10 +20704,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -20218,7 +20815,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -20230,18 +20827,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20371,10 +20962,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20443,6 +21037,9 @@ 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 ""
@@ -20479,6 +21076,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20491,6 +21091,15 @@ 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 ""
@@ -20506,7 +21115,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20611,9 +21220,15 @@ 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 ""
@@ -20629,6 +21244,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20677,6 +21295,18 @@ 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 ""
@@ -20692,6 +21322,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20905,6 +21538,9 @@ 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 ""
@@ -20929,6 +21565,9 @@ 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 ""
@@ -21139,13 +21778,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals from users who make commits to the MR."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -21157,7 +21799,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -21190,6 +21832,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21325,6 +21970,9 @@ 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 ""
@@ -21427,6 +22075,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21475,6 +22126,9 @@ 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 ""
@@ -21757,9 +22411,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21916,12 +22567,18 @@ 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 ""
@@ -21949,7 +22606,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21970,6 +22627,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -22018,9 +22678,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -22057,6 +22714,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -22165,12 +22825,21 @@ 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|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 ""
@@ -22189,9 +22858,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -22204,6 +22870,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -22246,7 +22915,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22687,7 +23356,7 @@ 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"
+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"
@@ -22720,7 +23389,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22987,6 +23656,12 @@ 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 ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -23113,7 +23791,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -23239,15 +23920,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23326,6 +24007,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23362,6 +24046,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23407,6 +24094,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23437,6 +24127,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23653,6 +24346,9 @@ 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 ""
@@ -23665,7 +24361,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23674,9 +24370,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23752,9 +24445,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23797,7 +24487,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23824,9 +24517,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23941,12 +24631,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23968,6 +24652,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23989,6 +24676,9 @@ 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 ""
@@ -24052,6 +24742,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -24148,21 +24841,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -24178,9 +24859,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -24190,13 +24868,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -24274,6 +24955,15 @@ 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 ""
@@ -24325,9 +25015,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24388,10 +25075,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24409,7 +25096,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24532,6 +25219,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24559,6 +25249,9 @@ 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 ""
@@ -24733,16 +25426,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24856,9 +25549,15 @@ 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 ""
@@ -24943,6 +25642,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -25021,6 +25723,12 @@ 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 ""
@@ -25303,9 +26011,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25405,6 +26110,9 @@ 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 ""
@@ -25435,10 +26143,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25636,9 +26341,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25678,6 +26380,9 @@ 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 ""
@@ -25699,6 +26404,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25708,9 +26416,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25747,6 +26452,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -26077,6 +26785,9 @@ 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 ""
@@ -26113,7 +26824,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -26140,6 +26854,9 @@ 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 ""
@@ -26200,7 +26917,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -26239,7 +26959,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26656,13 +27376,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26683,6 +27406,9 @@ 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 ""
@@ -26701,6 +27427,9 @@ 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 ""
@@ -26938,6 +27667,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -27214,6 +27946,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27448,9 +28186,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27460,12 +28213,30 @@ 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 ""
@@ -27478,9 +28249,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27631,7 +28414,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27646,6 +28429,9 @@ 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] ""
@@ -27661,6 +28447,9 @@ 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 ""
@@ -27727,6 +28516,9 @@ 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 ""
@@ -27853,9 +28645,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27874,9 +28663,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -28144,6 +28930,9 @@ 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 ""
@@ -28240,6 +29029,9 @@ 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 ""
@@ -28318,6 +29110,9 @@ 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 ""
@@ -28399,6 +29194,9 @@ 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 ""
@@ -28696,6 +29494,9 @@ 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 ""
@@ -28780,6 +29581,15 @@ 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 ""
@@ -28795,9 +29605,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28870,12 +29677,33 @@ 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 ""
@@ -28891,6 +29719,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28903,12 +29734,21 @@ 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 ""
@@ -28918,7 +29758,7 @@ 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."
+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"
@@ -28927,6 +29767,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29542,12 +30385,24 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29566,6 +30421,39 @@ 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 Gold 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 Gold 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 ""
@@ -29956,6 +30844,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29980,7 +30871,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -30037,7 +30928,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -30052,7 +30943,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -30094,9 +30985,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30607,6 +31495,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -31054,6 +31945,9 @@ 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 ""
@@ -31081,6 +31975,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -31108,6 +32005,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -31126,6 +32029,9 @@ 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 ""
@@ -31138,6 +32044,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -31171,6 +32080,9 @@ 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 ""
@@ -31273,6 +32185,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -31309,6 +32224,9 @@ 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 ""
@@ -31435,7 +32353,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31813,6 +32731,9 @@ 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 ""
@@ -31903,6 +32824,9 @@ 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 ""
@@ -31912,9 +32836,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31936,6 +32857,9 @@ 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 ""
@@ -31972,9 +32896,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -32047,6 +32968,9 @@ 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 ""
@@ -32056,6 +32980,9 @@ 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 ""
@@ -32089,6 +33016,9 @@ 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 ""
@@ -32248,6 +33178,9 @@ 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 ""
@@ -32320,6 +33253,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32395,6 +33331,9 @@ 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 ""
@@ -32416,6 +33355,9 @@ 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 ""
@@ -32473,6 +33415,9 @@ 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 ""
@@ -32575,6 +33520,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32593,9 +33541,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32638,6 +33592,9 @@ 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 ""
@@ -32677,6 +33634,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32833,6 +33793,9 @@ 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] ""
@@ -33055,6 +34018,12 @@ 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 ""
@@ -33241,6 +34210,9 @@ 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] ""
@@ -33919,18 +34891,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index 70354758563..fb43edc3225 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: 2020-12-03 08:12\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 89369f55fb2..e008ae794b0 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: 2020-12-03 08:10\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index d843e637f82..76f2a561710 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: 2020-12-03 08:12\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -867,9 +888,15 @@ 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 ""
@@ -1086,28 +1113,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1119,6 +1143,9 @@ 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 ""
@@ -1146,6 +1173,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1155,6 +1185,9 @@ 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 ""
@@ -1173,13 +1206,16 @@ 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."
+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."
+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"
@@ -1188,10 +1224,13 @@ 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 ready-to-go template for use with Android apps."
+msgid "A ready-to-go template for use with Android apps"
msgstr ""
-msgid "A ready-to-go template for use with iOS Swift apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 ""
@@ -1224,13 +1269,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1272,6 +1320,9 @@ 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 ""
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2744,6 +2780,9 @@ 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 ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 ""
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3739,6 +3790,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3757,12 +3814,18 @@ 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 ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,10 +4065,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4023,10 +4089,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4146,12 +4212,21 @@ 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 ""
@@ -4161,13 +4236,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4182,15 +4257,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4627,6 +4729,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4747,10 +4870,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4780,9 +4903,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 ""
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 ""
@@ -5014,13 +5179,16 @@ 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 were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5575,6 +5749,18 @@ 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 ""
@@ -6682,10 +6868,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,15 +8013,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -7929,6 +8139,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8734,6 +9004,9 @@ 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 ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9244,9 +9514,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9854,9 +10184,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ 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 ""
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 ""
@@ -10691,9 +11042,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13113,9 +13467,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13449,10 +13800,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13859,6 +14243,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14152,6 +14548,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19711,10 +20282,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 ""
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 ""
@@ -20767,6 +21395,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 ""
@@ -21097,9 +21731,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,7 +21926,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,7 +23782,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23139,9 +23812,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25302,6 +25990,9 @@ 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 ""
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,7 +27604,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ 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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 ""
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 ""
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] ""
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index c14bddbee17..b03e7155ebb 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: 2020-12-03 08:15\n"
+"PO-Revision-Date: 2021-01-08 23:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ТърÑете в клоните"
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Отказ"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr "Етикет"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Ñи Ñъздадете личен жетон за доÑтъп"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Задайте потребителÑки шаблон, използвайки ÑинтакÑиÑа на „Cron“"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "ОпиÑание"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "ТърÑене по път"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "ТърÑене на файл"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr "ОÑвежаването започна уÑпешно"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr "ВнаÑÑне на хранилище"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Ðаучете повече в"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "документациÑта отноÑно планирането на Ñхеми"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr "Планове за Ñхема"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr "Коефициент на уÑпех:"
msgid "PipelineCharts|Successful:"
msgstr "УÑпешни:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr "ЗаÑвка за доÑтъп"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr "Планиране на Ñхемите"
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr "Етапът на проблемите показва колко е вр
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr "Без звезда"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ИÑкате ли да видите данните? Помолете админиÑтратор за доÑтъп."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index a59575c4e99..17dcc57321a 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: 2020-12-03 08:09\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 963e5174709..cc31963e35a 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: 2020-12-03 08:13\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index 0654967a4ce..f1e2844a5e7 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: 2020-12-03 08:11\n"
+"PO-Revision-Date: 2021-01-08 22:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -415,12 +415,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -850,6 +859,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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] ""
+msgstr[2] ""
+
+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] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1009,9 +1036,15 @@ 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 ""
@@ -1264,28 +1297,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1297,6 +1327,9 @@ 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 ""
@@ -1324,6 +1357,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1333,6 +1369,9 @@ 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 ""
@@ -1351,13 +1390,16 @@ 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."
+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."
+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"
@@ -1366,10 +1408,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1381,9 +1426,15 @@ 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 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 ""
+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 ""
@@ -1402,13 +1453,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1450,6 +1504,9 @@ 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 ""
@@ -2044,6 +2101,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2053,6 +2113,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2530,9 +2593,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2596,15 +2656,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2632,9 +2686,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2704,10 +2755,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2773,12 +2824,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2863,9 +2908,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2926,6 +2968,9 @@ 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 ""
@@ -3064,7 +3109,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3100,6 +3145,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ 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 ""
@@ -3334,9 +3385,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3358,6 +3406,9 @@ 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 ""
@@ -3367,6 +3418,9 @@ 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 ""
@@ -3385,7 +3439,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3400,6 +3454,9 @@ 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 ""
@@ -3478,7 +3535,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3631,13 +3688,13 @@ msgstr[2] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3658,6 +3715,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3760,9 +3820,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3931,6 +3988,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3949,12 +4012,18 @@ msgstr "Zaduži sebi ovaj zadatak"
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 ""
@@ -3967,6 +4036,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Zaduženi"
@@ -3991,6 +4063,9 @@ 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 ""
@@ -4036,9 +4111,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4195,10 +4267,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4219,10 +4291,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4264,7 +4339,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4327,9 +4402,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4342,12 +4414,21 @@ 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 ""
@@ -4357,13 +4438,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4378,15 +4459,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4399,9 +4477,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4426,9 +4501,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4513,22 +4585,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4567,10 +4645,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4624,6 +4711,30 @@ 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 ""
@@ -4654,9 +4765,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4825,6 +4933,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4918,7 +5044,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4945,10 +5074,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4978,9 +5107,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5029,6 +5155,30 @@ 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 ""
@@ -5050,6 +5200,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5182,15 +5335,33 @@ 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|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 ""
@@ -5212,13 +5383,16 @@ 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 were successfully made."
+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}."
@@ -5230,9 +5404,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5500,9 +5671,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5761,6 +5938,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5773,6 +5953,18 @@ 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 ""
@@ -6880,10 +7072,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7156,6 +7348,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7285,6 +7495,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7375,13 +7588,13 @@ msgstr[2] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7390,18 +7603,42 @@ 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 policy:"
+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 ""
@@ -7429,9 +7666,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7441,9 +7675,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7468,6 +7699,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7486,9 +7720,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7564,16 +7795,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7609,12 +7834,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7771,6 +7990,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8005,15 +8227,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8071,9 +8290,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8137,6 +8353,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Kreirano"
@@ -8230,6 +8524,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8314,45 +8611,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8599,6 +8869,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8665,6 +8938,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8713,6 +8992,9 @@ 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 ""
@@ -8920,18 +9202,12 @@ msgstr "Standardni prvi dan sedmice u kalendarima i izbornicima datuma."
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8944,6 +9220,9 @@ 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 ""
@@ -8992,9 +9271,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9466,9 +9742,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9478,6 +9751,9 @@ 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 ""
@@ -9679,22 +9955,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9703,6 +10018,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9712,18 +10030,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9994,6 +10327,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10078,9 +10414,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10135,9 +10468,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10177,6 +10507,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10204,12 +10537,18 @@ 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 ""
@@ -10243,6 +10582,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10312,10 +10654,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10396,6 +10738,9 @@ 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 ""
@@ -10465,6 +10810,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10480,9 +10828,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10516,6 +10861,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10552,9 +10900,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10597,6 +10942,9 @@ 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 ""
@@ -10738,6 +11086,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10855,6 +11206,12 @@ 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 ""
@@ -10915,9 +11272,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11023,9 +11377,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11161,9 +11512,18 @@ 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 ""
@@ -11278,22 +11638,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11332,9 +11692,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11374,6 +11731,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11515,6 +11875,9 @@ 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 ""
@@ -11533,6 +11896,12 @@ 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 ""
@@ -11560,9 +11929,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11713,6 +12079,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11773,9 +12142,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11869,9 +12235,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11881,16 +12244,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12004,6 +12364,9 @@ 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 ""
@@ -12106,6 +12469,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12139,12 +12505,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12196,9 +12556,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12217,6 +12574,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12346,9 +12706,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12814,6 +13171,12 @@ 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 ""
@@ -12889,9 +13252,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13111,7 +13471,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13339,9 +13699,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13675,10 +14032,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13702,9 +14065,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13732,7 +14092,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13765,6 +14125,9 @@ 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 ""
@@ -13843,6 +14206,9 @@ 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 ""
@@ -13852,22 +14218,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14089,6 +14479,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14263,6 +14656,9 @@ 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 ""
@@ -14338,6 +14734,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14386,6 +14788,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14446,19 +14851,16 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14482,6 +14884,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14638,13 +15043,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14659,6 +15064,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14908,6 +15316,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14992,9 +15406,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15094,13 +15505,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15112,9 +15523,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15184,6 +15592,24 @@ 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 ""
@@ -15241,9 +15667,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15295,6 +15718,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15310,7 +15736,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15349,7 +15775,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15469,6 +15895,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15553,6 +15982,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15577,19 +16009,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16015,6 +16447,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16069,9 +16504,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16111,9 +16552,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16138,6 +16576,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16483,6 +16924,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16570,6 +17014,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16807,6 +17254,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16828,6 +17278,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16969,6 +17422,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17101,9 +17560,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17164,6 +17620,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17179,9 +17638,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17326,9 +17782,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17344,9 +17806,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17911,9 +18370,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18097,9 +18553,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18232,6 +18685,9 @@ 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 ""
@@ -18244,6 +18700,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18253,6 +18712,9 @@ 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 ""
@@ -18550,6 +19012,12 @@ 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 ""
@@ -18688,7 +19156,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18934,6 +19402,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18952,6 +19423,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19189,6 +19663,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19210,27 +19687,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19246,9 +19801,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19267,6 +19834,15 @@ 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 ""
@@ -19561,6 +20137,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19570,10 +20149,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19591,7 +20167,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19651,6 +20227,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19717,10 +20296,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19822,7 +20407,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19834,18 +20419,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Stranice"
@@ -19975,10 +20554,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20047,6 +20629,9 @@ 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 ""
@@ -20083,6 +20668,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20095,6 +20683,15 @@ 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 ""
@@ -20110,7 +20707,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20215,9 +20812,15 @@ 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 ""
@@ -20233,6 +20836,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20281,6 +20887,18 @@ 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 ""
@@ -20296,6 +20914,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20509,6 +21130,9 @@ 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 ""
@@ -20533,6 +21157,9 @@ 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 ""
@@ -20743,13 +21370,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20761,7 +21391,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20794,6 +21424,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20929,6 +21562,9 @@ 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 ""
@@ -21031,6 +21667,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21079,6 +21718,9 @@ 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 ""
@@ -21361,9 +22003,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21520,12 +22159,18 @@ 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 ""
@@ -21553,7 +22198,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21574,6 +22219,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21622,9 +22270,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21661,6 +22306,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21769,12 +22417,21 @@ 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|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 ""
@@ -21793,9 +22450,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21808,6 +22462,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21850,7 +22507,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22291,7 +22948,7 @@ 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"
+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"
@@ -22324,7 +22981,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22591,6 +23248,12 @@ 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 ""
@@ -22609,6 +23272,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22714,7 +23380,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22837,15 +23506,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22924,6 +23593,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22960,6 +23632,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23035,6 +23713,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23242,6 +23923,9 @@ 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 ""
@@ -23254,7 +23938,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23263,9 +23947,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23341,9 +24022,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23386,7 +24064,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23413,9 +24094,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23524,12 +24202,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23551,6 +24223,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23572,6 +24247,9 @@ 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 ""
@@ -23632,6 +24310,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23725,21 +24406,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23755,9 +24424,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23767,13 +24433,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23851,6 +24520,15 @@ 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 ""
@@ -23902,9 +24580,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23965,10 +24640,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23986,7 +24661,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24109,6 +24784,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24136,6 +24814,9 @@ 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 ""
@@ -24277,16 +24958,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24400,9 +25081,15 @@ 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 ""
@@ -24487,6 +25174,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24562,6 +25252,12 @@ 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 ""
@@ -24844,9 +25540,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24946,6 +25639,9 @@ msgstr "Usluga"
msgid "Service Desk"
msgstr "TehniÄka PodrÅ¡ka"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr ""
@@ -24976,10 +25672,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25177,9 +25870,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25219,6 +25909,9 @@ 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 ""
@@ -25240,6 +25933,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25249,9 +25945,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25288,6 +25981,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25612,6 +26308,9 @@ 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 ""
@@ -25648,7 +26347,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25675,6 +26377,9 @@ 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 ""
@@ -25735,7 +26440,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25774,7 +26482,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26191,13 +26899,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26218,6 +26929,9 @@ 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 ""
@@ -26236,6 +26950,9 @@ 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 ""
@@ -26473,6 +27190,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26749,6 +27469,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26977,9 +27703,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26989,12 +27730,30 @@ 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 ""
@@ -27007,9 +27766,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27157,7 +27928,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27172,6 +27943,9 @@ 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] ""
@@ -27184,6 +27958,9 @@ 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 ""
@@ -27250,6 +28027,9 @@ 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 ""
@@ -27373,9 +28153,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27394,9 +28171,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27664,6 +28438,9 @@ 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 ""
@@ -27760,6 +28537,9 @@ 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 ""
@@ -27838,6 +28618,9 @@ 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 ""
@@ -27919,6 +28702,9 @@ 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 ""
@@ -28216,6 +29002,9 @@ 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 ""
@@ -28300,6 +29089,15 @@ 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 ""
@@ -28315,9 +29113,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28390,12 +29185,33 @@ 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 ""
@@ -28411,6 +29227,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28423,12 +29242,21 @@ 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 ""
@@ -28438,7 +29266,7 @@ 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."
+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"
@@ -28447,6 +29275,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29056,12 +29887,21 @@ 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] ""
+msgstr[2] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29080,6 +29920,39 @@ 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 Gold 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 Gold 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 ""
@@ -29470,6 +30343,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29494,7 +30370,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29551,7 +30427,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29566,7 +30442,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29608,9 +30484,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30121,6 +30994,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30562,6 +31438,9 @@ 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 ""
@@ -30589,6 +31468,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30616,6 +31498,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30634,6 +31522,9 @@ 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 ""
@@ -30646,6 +31537,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30679,6 +31573,9 @@ 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 ""
@@ -30781,6 +31678,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30817,6 +31717,9 @@ 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 ""
@@ -30940,7 +31843,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31318,6 +32221,9 @@ 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 ""
@@ -31408,6 +32314,9 @@ 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 ""
@@ -31417,9 +32326,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31441,6 +32347,9 @@ 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 ""
@@ -31477,9 +32386,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31552,6 +32458,9 @@ 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 ""
@@ -31561,6 +32470,9 @@ 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 ""
@@ -31594,6 +32506,9 @@ 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 ""
@@ -31753,6 +32668,9 @@ 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 ""
@@ -31825,6 +32743,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31900,6 +32821,9 @@ 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 ""
@@ -31921,6 +32845,9 @@ 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 ""
@@ -31978,6 +32905,9 @@ 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 ""
@@ -32077,6 +33007,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32095,9 +33028,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32140,6 +33079,9 @@ 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 ""
@@ -32179,6 +33121,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32335,6 +33280,9 @@ 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] ""
@@ -32542,6 +33490,12 @@ 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 ""
@@ -32725,6 +33679,9 @@ 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] ""
@@ -33385,18 +34342,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index d5de0d1a6da..49f233fbd53 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: 2020-12-03 08:15\n"
+"PO-Revision-Date: 2021-01-08 23:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 "Peticions de fusió assignades"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Color de fons"
msgid "Badges"
msgstr "Insígnies"
-msgid "Badges|A new badge was added."
-msgstr "S'ha afegit una insígnia nova."
-
msgid "Badges|Add badge"
msgstr "Afegeix una insígnia"
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr "Enllaç"
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr "Desa els canvis"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr "Nom de la branca"
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr "Tasques"
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Cancel·la"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Trieu una plantilla..."
msgid "Choose a type..."
msgstr "Trieu un tipus..."
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 "Tanca"
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Connecta"
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr "Crea una branca nova"
@@ -8033,6 +8246,84 @@ msgstr "Etiqueta"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Creat"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Branca actual"
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr "Descendent"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "Descripció"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr "Edita l'aplicació"
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ msgstr "Introduïu el títol de la petició de fusió"
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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr "Com ho puc resoldre-ho?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Més informació"
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Filtra"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr "Enrere"
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Peticions de fusió"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 7cf048a0364..3164c7baac1 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: 2020-12-03 08:15\n"
+"PO-Revision-Date: 2021-01-08 23:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -917,6 +926,27 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1080,9 +1110,15 @@ 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 ""
@@ -1353,28 +1389,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1386,6 +1419,9 @@ 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 ""
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1422,6 +1461,9 @@ 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 ""
@@ -1440,13 +1482,16 @@ 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."
+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."
+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"
@@ -1455,10 +1500,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 ""
@@ -1491,13 +1545,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1539,6 +1596,9 @@ 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 ""
@@ -2134,6 +2194,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3017,6 +3062,9 @@ 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 ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 ""
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,7 +3533,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 ""
@@ -3569,7 +3629,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3726,13 +3786,13 @@ msgstr[3] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4027,6 +4087,12 @@ msgstr "Přiřadit štítky"
msgid "Assign milestone"
msgstr "Přiřadit milník"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4045,12 +4111,18 @@ 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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4088,6 +4163,9 @@ 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 ""
@@ -4134,9 +4212,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,10 +4368,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4317,10 +4392,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4440,12 +4515,21 @@ 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 ""
@@ -4455,13 +4539,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4476,15 +4560,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4524,9 +4602,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,10 +4747,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr "Název větve"
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4924,6 +5035,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5044,10 +5176,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5077,9 +5209,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 ""
@@ -5149,6 +5302,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 ""
@@ -5311,13 +5485,16 @@ 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 were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5872,6 +6055,18 @@ 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 ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7874,6 +8096,9 @@ msgstr ""
msgid "Copy branch name"
msgstr "Kopírovat název větve"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8175,9 +8397,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8241,6 +8460,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8418,45 +8718,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ 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 ""
@@ -9097,9 +9379,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9577,9 +9856,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9589,6 +9865,9 @@ 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 ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10289,6 +10622,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ 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 ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 ""
@@ -11027,9 +11387,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11135,9 +11492,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11273,9 +11627,18 @@ 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 ""
@@ -11390,22 +11753,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 ""
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 ""
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,7 +13587,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13452,9 +13815,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13788,10 +14148,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13815,9 +14181,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,7 +14208,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13878,6 +14241,9 @@ 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 ""
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,13 +15164,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15212,13 +15627,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15230,9 +15645,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15428,7 +15858,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16257,6 +16699,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17452,9 +17912,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 ""
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19849,10 +20432,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20107,10 +20690,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20179,6 +20765,9 @@ 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 ""
@@ -20215,6 +20804,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ 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 ""
@@ -20242,7 +20843,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 ""
@@ -20875,13 +21506,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ 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 ""
@@ -21163,6 +21803,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 ""
@@ -21493,9 +22139,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 ""
@@ -21685,7 +22334,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21754,9 +22406,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21793,6 +22442,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21982,7 +22643,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,7 +23117,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22723,6 +23384,12 @@ 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 ""
@@ -22741,6 +23408,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23169,6 +23851,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23478,9 +24163,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,7 +24205,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23690,6 +24366,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23896,9 +24569,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23908,13 +24578,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,10 +24785,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24127,7 +24806,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24277,6 +24959,9 @@ 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 ""
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25099,6 +25796,9 @@ 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 ""
@@ -25129,10 +25829,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25330,9 +26027,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25767,6 +26467,9 @@ 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 ""
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26346,13 +27058,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27315,7 +28090,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27330,6 +28105,9 @@ 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] ""
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 ""
@@ -27533,9 +28317,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28079,6 +28866,9 @@ 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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 ""
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,7 +30594,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29728,7 +30609,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,7 +32013,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 ""
@@ -31582,9 +32496,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ 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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32261,9 +33199,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 45600e213ff..67513c02769 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: 2020-12-03 08:08\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -583,12 +583,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -1051,6 +1060,33 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1222,9 +1258,15 @@ 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 ""
@@ -1531,28 +1573,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1564,6 +1603,9 @@ 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 ""
@@ -1591,6 +1633,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1600,6 +1645,9 @@ 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 ""
@@ -1618,13 +1666,16 @@ 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."
+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."
+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"
@@ -1633,10 +1684,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1648,9 +1702,15 @@ 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 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 ""
+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 ""
@@ -1669,13 +1729,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1717,6 +1780,9 @@ 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 ""
@@ -2314,6 +2380,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2323,6 +2392,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2803,9 +2875,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2869,15 +2938,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2905,9 +2968,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2977,10 +3037,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -3046,12 +3106,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -3136,9 +3190,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3199,6 +3250,9 @@ 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 ""
@@ -3337,7 +3391,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3373,6 +3427,9 @@ 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 ""
@@ -3385,6 +3442,9 @@ 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 ""
@@ -3607,9 +3667,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3631,6 +3688,9 @@ 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 ""
@@ -3640,6 +3700,9 @@ 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 ""
@@ -3658,7 +3721,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3673,6 +3736,9 @@ 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 ""
@@ -3751,7 +3817,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3916,13 +3982,13 @@ msgstr[5] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3943,6 +4009,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -4045,9 +4114,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4219,6 +4285,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4237,12 +4309,18 @@ 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 ""
@@ -4255,6 +4333,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4282,6 +4363,9 @@ 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 ""
@@ -4330,9 +4414,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4489,10 +4570,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4513,10 +4594,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4558,7 +4642,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4621,9 +4705,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4636,12 +4717,21 @@ 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 ""
@@ -4651,13 +4741,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4672,15 +4762,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4693,9 +4780,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4720,9 +4804,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4807,22 +4888,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4864,10 +4951,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4921,6 +5017,30 @@ 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 ""
@@ -4951,9 +5071,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -5122,6 +5239,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5215,7 +5350,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5242,10 +5380,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5275,9 +5413,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5326,6 +5461,30 @@ 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 ""
@@ -5347,6 +5506,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5479,15 +5641,33 @@ 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|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 ""
@@ -5509,13 +5689,16 @@ 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 were successfully made."
+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}."
@@ -5527,9 +5710,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5797,9 +5977,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -6058,6 +6244,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -6070,6 +6259,18 @@ 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 ""
@@ -7177,10 +7378,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7456,6 +7657,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7585,6 +7804,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7681,13 +7903,13 @@ msgstr[5] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7696,18 +7918,42 @@ 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 policy:"
+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 ""
@@ -7735,9 +7981,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7747,9 +7990,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7774,6 +8014,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7792,9 +8035,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7873,16 +8113,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7918,12 +8152,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -8080,6 +8308,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8317,15 +8548,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8383,9 +8611,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8449,6 +8674,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8542,6 +8845,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8626,45 +8932,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8914,6 +9193,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8980,6 +9262,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -9028,6 +9316,9 @@ 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 ""
@@ -9235,18 +9526,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9259,6 +9544,9 @@ 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 ""
@@ -9307,9 +9595,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9799,9 +10084,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9811,6 +10093,9 @@ 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 ""
@@ -10012,22 +10297,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -10036,6 +10360,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -10045,18 +10372,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10330,6 +10672,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10414,9 +10759,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10471,9 +10813,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10513,6 +10852,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10540,12 +10882,18 @@ 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 ""
@@ -10579,6 +10927,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10648,10 +10999,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10732,6 +11083,9 @@ 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 ""
@@ -10801,6 +11155,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10816,9 +11173,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10852,6 +11206,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10888,9 +11245,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10933,6 +11287,9 @@ 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 ""
@@ -11074,6 +11431,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -11191,6 +11551,12 @@ 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 ""
@@ -11251,9 +11617,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11359,9 +11722,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11497,9 +11857,18 @@ 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 ""
@@ -11614,22 +11983,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11668,9 +12037,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11710,6 +12076,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11851,6 +12220,9 @@ 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 ""
@@ -11869,6 +12241,12 @@ 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 ""
@@ -11896,9 +12274,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -12049,6 +12424,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -12109,9 +12487,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -12208,9 +12583,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -12220,16 +12592,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12343,6 +12712,9 @@ 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 ""
@@ -12445,6 +12817,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12478,12 +12853,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12535,9 +12904,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12556,6 +12922,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12685,9 +13054,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -13153,6 +13519,12 @@ 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 ""
@@ -13228,9 +13600,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13450,7 +13819,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13678,9 +14047,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -14014,10 +14380,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -14041,9 +14413,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -14071,7 +14440,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -14104,6 +14473,9 @@ 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 ""
@@ -14182,6 +14554,9 @@ 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 ""
@@ -14191,22 +14566,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14434,6 +14833,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14608,6 +15010,9 @@ 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 ""
@@ -14689,6 +15094,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14737,6 +15148,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14797,19 +15211,19 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14833,6 +15247,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14989,13 +15406,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -15010,6 +15427,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15262,6 +15682,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,9 +15772,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15448,13 +15871,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15466,9 +15889,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15538,6 +15958,24 @@ 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 ""
@@ -15595,9 +16033,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15649,6 +16084,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15664,7 +16102,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15703,7 +16141,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15823,6 +16261,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15907,6 +16348,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15931,19 +16375,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16372,6 +16816,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16426,9 +16873,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16468,9 +16921,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16495,6 +16945,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16861,6 +17314,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16948,6 +17404,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17185,6 +17644,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -17206,6 +17668,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17347,6 +17812,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17479,9 +17950,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17542,6 +18010,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17557,9 +18028,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17704,9 +18172,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17722,9 +18196,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18295,9 +18766,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18481,9 +18949,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18622,6 +19087,9 @@ 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 ""
@@ -18634,6 +19102,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18643,6 +19114,9 @@ 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 ""
@@ -18943,6 +19417,12 @@ 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 ""
@@ -19081,7 +19561,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19327,6 +19807,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19345,6 +19828,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19582,6 +20068,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19603,27 +20092,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19639,9 +20206,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19660,6 +20239,15 @@ 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 ""
@@ -19957,6 +20545,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19966,10 +20557,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19987,7 +20575,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -20047,6 +20635,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -20113,10 +20704,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -20218,7 +20815,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -20230,18 +20827,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20371,10 +20962,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20443,6 +21037,9 @@ 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 ""
@@ -20479,6 +21076,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20491,6 +21091,15 @@ 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 ""
@@ -20506,7 +21115,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20611,9 +21220,15 @@ 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 ""
@@ -20629,6 +21244,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20677,6 +21295,18 @@ 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 ""
@@ -20692,6 +21322,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20905,6 +21538,9 @@ 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 ""
@@ -20929,6 +21565,9 @@ 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 ""
@@ -21139,13 +21778,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals from users who make commits to the MR."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -21157,7 +21799,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -21190,6 +21832,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21325,6 +21970,9 @@ 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 ""
@@ -21427,6 +22075,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21475,6 +22126,9 @@ 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 ""
@@ -21757,9 +22411,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21916,12 +22567,18 @@ 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 ""
@@ -21949,7 +22606,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21970,6 +22627,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -22018,9 +22678,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -22057,6 +22714,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -22165,12 +22825,21 @@ 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|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 ""
@@ -22189,9 +22858,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -22204,6 +22870,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -22246,7 +22915,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22687,7 +23356,7 @@ 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"
+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"
@@ -22720,7 +23389,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22987,6 +23656,12 @@ 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 ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -23113,7 +23791,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -23239,15 +23920,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23326,6 +24007,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23362,6 +24046,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23407,6 +24094,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23437,6 +24127,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23653,6 +24346,9 @@ 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 ""
@@ -23665,7 +24361,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23674,9 +24370,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23752,9 +24445,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23797,7 +24487,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23824,9 +24517,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23941,12 +24631,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23968,6 +24652,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23989,6 +24676,9 @@ 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 ""
@@ -24052,6 +24742,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -24148,21 +24841,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -24178,9 +24859,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -24190,13 +24868,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -24274,6 +24955,15 @@ 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 ""
@@ -24325,9 +25015,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24388,10 +25075,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24409,7 +25096,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24532,6 +25219,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24559,6 +25249,9 @@ 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 ""
@@ -24733,16 +25426,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24856,9 +25549,15 @@ 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 ""
@@ -24943,6 +25642,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -25021,6 +25723,12 @@ 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 ""
@@ -25303,9 +26011,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25405,6 +26110,9 @@ 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 ""
@@ -25435,10 +26143,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25636,9 +26341,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25678,6 +26380,9 @@ 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 ""
@@ -25699,6 +26404,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25708,9 +26416,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25747,6 +26452,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -26077,6 +26785,9 @@ 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 ""
@@ -26113,7 +26824,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -26140,6 +26854,9 @@ 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 ""
@@ -26200,7 +26917,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -26239,7 +26959,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26656,13 +27376,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26683,6 +27406,9 @@ 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 ""
@@ -26701,6 +27427,9 @@ 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 ""
@@ -26938,6 +27667,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -27214,6 +27946,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27448,9 +28186,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27460,12 +28213,30 @@ 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 ""
@@ -27478,9 +28249,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27631,7 +28414,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27646,6 +28429,9 @@ 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] ""
@@ -27661,6 +28447,9 @@ 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 ""
@@ -27727,6 +28516,9 @@ 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 ""
@@ -27853,9 +28645,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27874,9 +28663,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -28144,6 +28930,9 @@ 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 ""
@@ -28240,6 +29029,9 @@ 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 ""
@@ -28318,6 +29110,9 @@ 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 ""
@@ -28399,6 +29194,9 @@ 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 ""
@@ -28696,6 +29494,9 @@ 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 ""
@@ -28780,6 +29581,15 @@ 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 ""
@@ -28795,9 +29605,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28870,12 +29677,33 @@ 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 ""
@@ -28891,6 +29719,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28903,12 +29734,21 @@ 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 ""
@@ -28918,7 +29758,7 @@ 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."
+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"
@@ -28927,6 +29767,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29542,12 +30385,24 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29566,6 +30421,39 @@ 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 Gold 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 Gold 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 ""
@@ -29956,6 +30844,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29980,7 +30871,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -30037,7 +30928,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -30052,7 +30943,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -30094,9 +30985,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30607,6 +31495,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -31054,6 +31945,9 @@ 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 ""
@@ -31081,6 +31975,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -31108,6 +32005,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -31126,6 +32029,9 @@ 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 ""
@@ -31138,6 +32044,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -31171,6 +32080,9 @@ 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 ""
@@ -31273,6 +32185,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -31309,6 +32224,9 @@ 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 ""
@@ -31435,7 +32353,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31813,6 +32731,9 @@ 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 ""
@@ -31903,6 +32824,9 @@ 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 ""
@@ -31912,9 +32836,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31936,6 +32857,9 @@ 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 ""
@@ -31972,9 +32896,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -32047,6 +32968,9 @@ 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 ""
@@ -32056,6 +32980,9 @@ 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 ""
@@ -32089,6 +33016,9 @@ 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 ""
@@ -32248,6 +33178,9 @@ 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 ""
@@ -32320,6 +33253,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32395,6 +33331,9 @@ 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 ""
@@ -32416,6 +33355,9 @@ 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 ""
@@ -32473,6 +33415,9 @@ 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 ""
@@ -32575,6 +33520,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32593,9 +33541,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32638,6 +33592,9 @@ 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 ""
@@ -32677,6 +33634,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32833,6 +33793,9 @@ 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] ""
@@ -33055,6 +34018,12 @@ 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 ""
@@ -33241,6 +34210,9 @@ 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] ""
@@ -33919,18 +34891,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 46a606ec8d9..94db870b536 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: 2020-12-03 08:15\n"
+"PO-Revision-Date: 2021-01-08 23:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 3a57ac52aab..3db3d8b874e 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: 2020-12-03 08:16\n"
+"PO-Revision-Date: 2021-01-08 23:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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 "%{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)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commits"
+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 "%{strong_start}%{human_size}%{strong_end} Dateien"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} zusammengeführt)"
msgid "(%{value}) has already been taken"
msgstr ""
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Keine Änderungen)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(Fortschritt überprüfen)"
@@ -1175,29 +1205,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "Ein 'Runner' ist ein Prozess, welcher ein Job ausführt. Du kannst so viele Runner erstellen wie du benötigst."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Eine .NET Core-Konsolenanwendungsvorlage, anpassbar für jedes .NET Core-Projekt"
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 "Eine GitBook-Seite, welche statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
+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 "Eine Hexo-Seite, die statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
+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 "Eine Hugo-Seite, die statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
+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 "Eine Jekyll-Seite, die statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
+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 "Ein SSL-Zertifikat von Let's Encrypt kann erst nach Domainbestätigung abgerufen werden."
@@ -1208,6 +1235,9 @@ msgstr "Ein Let's Encrypt-Konto wird für diese GitLab-Installation mit deiner E
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "Eine grundlegende Seite und serverlose Funktion, die AWS Lambda, AWS API Gateway und GitLab Pages verwendet"
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
msgid "A complete DevOps platform"
msgstr ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 "Deinen Bericht wird so schnell wie möglich von einer zuständigen Person überprüfen."
@@ -1244,6 +1277,9 @@ msgstr "Eine Genehmigung des Merge-Requests ist erforderlich, wenn ein Sicherhei
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 ""
@@ -1262,13 +1298,16 @@ msgstr "Eine neuer Identitätswechsel-Token wurde erstellt."
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 "Eine einfache HTML-Seite, welche statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
+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."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Eine gebrauchsfertige Vorlage zur Nutzung mit Android-Apps."
+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 "Eine gebrauchsfertige Vorlage zur Nutzung mit iOS Swift-Apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1292,9 +1334,15 @@ msgstr "Ein sicheres Token, das die Anfrage eines externen Speichers identifizie
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 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 ""
+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 "Ein(e) Benutzer(in) mit Schreibzugriff auf den Quellbranch hat diese Option ausgewählt"
@@ -1313,14 +1361,17 @@ msgstr "API Token"
msgid "AWS Access Key"
msgstr "AWS Zugangsschlüssel"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "AWS Zugangsschlüssel. Nur dann erforderlich, wenn Rollen-Instanz-Anmeldeinformationen nicht verwendet werden"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS Geheimer Zugangsschlüssel"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "AWS Zugangsschlüssel. Nur dann erforderlich, wenn Rollen-Instanz-Anmeldeinformationen nicht verwendet werden"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "Abbrechen"
@@ -1361,6 +1412,9 @@ msgstr "Zugriff für dein LDAP-Konto verweigert."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Zugriff abgelehnt! Stelle sicher, dass du diesem Repository Bereitstellungsschlüssel hinzufügen kannst."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Zugriff auf das Ablaufdatum"
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr "'Shared Runners' für neue Projekte aktivieren"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Umgebungsvariablen sind standardmäßig geschützt"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr "Alle Branches"
msgid "All changes are committed"
msgstr "Alle Änderungen sind committed"
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr "Alle E-Mail-Adressen werden verwendet, um deine Commits zu identifizieren."
@@ -2835,6 +2874,9 @@ msgstr "Gruppenbesitzer erlauben, LDAP-bezogene Einstellungen zu verwalten"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Nur die ausgewählten Protokolle für den Git-Zugriff zulassen."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Es ist ein Fehler aufgetreten"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
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 "Beim Aktualisieren der Ticket-Gewichtung ist ein Fehler aufgetreten"
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Beim Speichern des LDAP-Ãœberschreibungsstatus ist ein Fehler aufgetreten. Bitte versuche es erneut."
-
msgid "An error occurred while saving assignees"
msgstr "Beim Speichern der Zuweisungen ist ein Fehler aufgetreten"
@@ -3267,6 +3312,9 @@ msgstr "Beim Abbestellen der Benachrichtigungen ist ein Fehler aufgetreten."
msgid "An error occurred while updating approvers"
msgstr "Beim Ändern der Genehmigungsberechtigten ist ein Fehler aufgetreten"
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3276,6 +3324,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Beim Aktualisieren des Kommentars ist ein Fehler aufgetreten"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,7 +3345,7 @@ msgstr "Ein Fehler ist aufgetreten. Bitte versuche es erneut."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 "Ein Ticket kann ein Fehler, ein To-do oder eine Feature-Anfrage sein, das in einem Projekt diskutiert werden muss. Außerdem sind Tickets durchsuchbar und filterbar."
+msgid "An issue title is required"
+msgstr ""
+
msgid "An unauthenticated user"
msgstr ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,15 +3590,15 @@ msgstr[1] "%{count} Zustimmungen von %{membersCount} nötig"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Genehmigungsberechtigte(r)"
msgid "ApprovalRule|Name"
msgstr "Name"
-msgid "ApprovalRule|No. approvals required"
-msgstr "Zahl erforderlicher Zustimmungen"
-
msgid "ApprovalRule|Rule name"
msgstr "Regelname"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr "Möchtest du diesen %{typeOfComment} wirklich entfernen?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "Möchtest du dieses Board wirklich löschen?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr "Label zuweisen"
msgid "Assign milestone"
msgstr "Meilenstein zuweisen"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Einige Tickets diesem Meilenstein zuordnen."
@@ -3853,12 +3913,18 @@ msgstr ""
msgid "Assigned %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} zugewiesen."
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Zugewiesene Tickets"
msgid "Assigned Merge Requests"
msgstr "Zugewiesene Merge-Requests"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Mir zugewiesen"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Beauftragte(r)"
@@ -3894,6 +3963,9 @@ msgstr ""
msgid "Assigns %{assignee_users_sentence}."
msgstr "Weise %{assignee_users_sentence} zu."
+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 "Mindestens eine Zustimmung der Code-Eigentümer(innen) ist erforderlich, um Dateien zu ändern, auf die die entsprechenden CODEOWNER-Regeln zutreffen."
@@ -3938,9 +4010,6 @@ msgstr "Audit-Ereignisse"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr "Mit Audit Events können Sie wichtige Ereignisse in GitLab nachverfolgen."
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr "(entfernt)"
@@ -4097,12 +4166,12 @@ msgstr "Lösche redundante, ausstehende Pipelines automatisch"
msgid "Auto-close referenced issues on default branch"
msgstr "Referenzierte Tickets im Standard-Branch automatisch schließen"
+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 "Auto-DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr "Auto DevOps kann Anwendungen basierend auf einer vordefinierten Konfiguration für kontinuierliche Integration und Bereitstellung automatisch erstellen, testen und bereitstellen. %{auto_devops_start}Erfahren Sie mehr über Auto DevOps%{auto_devops_end} oder verwenden Sie unsere %{quickstart_start}Kurzanleitung%{quickstart_end}, um sofort loszulegen."
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto-DevOps-Dokumentation"
@@ -4121,10 +4190,13 @@ msgstr "Erfahre mehr in der %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr "Automatische Zertifikatsverwaltung mit Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Hintergrundfarbe"
msgid "Badges"
msgstr "Badges"
-msgid "Badges|A new badge was added."
-msgstr "Ein neuer Badge wurde hinzugefügt."
-
msgid "Badges|Add badge"
msgstr "Badge hinzufügen"
@@ -4244,12 +4313,21 @@ msgstr "Badge-Bild-URL"
msgid "Badges|Badge image preview"
msgstr "Badge-Bild-Vorschau"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "Badge löschen?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "Löschen des Badges fehlgeschlagen, bitte versuchen es erneut."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Gruppen-Badge"
@@ -4259,15 +4337,15 @@ msgstr "Link"
msgid "Badges|Name"
msgstr ""
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "Kein Badge-Bild"
msgid "Badges|No image to preview"
msgstr "Kein Bild zur Vorschau"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Bitte trage eine gültige URL ein"
-
msgid "Badges|Project Badge"
msgstr "Projekt-Badge"
@@ -4280,15 +4358,12 @@ msgstr "Änderungen speichern"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Speichern des Badges fehlgeschlagen, bitte überprüfe die eingegebenen URLs und versuche es erneut."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "Die %{docsLinkStart}Variablen%{docsLinkEnd} die GitLab unterstützt: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Das Badge wurde gelöscht."
-msgid "Badges|The badge was saved."
-msgstr "Das Badge wurde gespeichert."
-
msgid "Badges|This group has no badges"
msgstr "Diese Gruppe hat keine Badges"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Deine Badges"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "z. B. %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Balsamiq-Datei konnte nicht geladen werden."
@@ -4328,9 +4400,6 @@ msgstr "Du musst in Bamboo eine automatische Versionskennzeichnung und einen Rep
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Vorsicht. Änderungen am Projektnamensraum können unbeabsichtigte Nebenwirkungen haben."
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,12 +4543,21 @@ msgstr "Blöcke"
msgid "Blog"
msgstr "Blog"
-msgid "Board scope"
-msgstr "Board-Bereich"
-
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "Der Board-Bereich beeinflusst, welche Themen für jeden angezeigt werden, der dieses Board besucht"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
msgid "Boards"
msgstr "Boards"
@@ -4525,6 +4609,30 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Bereich anzeigen"
+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 ""
@@ -4555,9 +4663,6 @@ msgstr "Branch-Name"
msgid "Branch not loaded - %{branchId}"
msgstr "Branch nicht geladen - %{branchId}"
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Branches durchsuchen"
@@ -4726,6 +4831,24 @@ msgstr "Integriert"
msgid "Bulk request concurrency"
msgstr "Parallelität von Massenanfragen"
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr "CI/CD für externes Repo"
msgid "CI/CD settings"
msgstr "CI/CD-Einstellungen"
-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."
+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"
@@ -4846,12 +4972,12 @@ msgstr "Bereitstellungsstrategie"
msgid "CICD|Jobs"
msgstr "Jobs"
+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 "Die Auto-DevOps-Pipeline wird ausgeführt, wenn keine alternative CI-Konfigurationsdatei gefunden wird."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr "Gruppe aktiviert"
@@ -4879,9 +5005,6 @@ msgstr "Callback-URL"
msgid "Can be manually deployed to"
msgstr "Kann manuell bereitgestellt werden für"
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Kann erforderliche Genehmigungsberechtigte und Genehmigungen pro Merge-Request überschreiben"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Abbrechen"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr "Schließe Vorschau"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Kann nicht automatisch zusammengeführt werden"
@@ -5083,15 +5233,33 @@ msgstr "In dem Branch wählen"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Im Branch wiederherstellen"
+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 "Cherry-Pick"
msgid "ChangeTypeAction|Revert"
msgstr "Wiederherstellen "
+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 "Dies wird einen neuen Commit erzeugen, um die vorhandenen Änderungen rückgängig zu machen."
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr ""
@@ -5113,13 +5281,16 @@ msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr ""
+msgid "Changes saved."
+msgstr ""
+
msgid "Changes suppressed. Click to show."
msgstr "Änderungen unterdrückt. Zum Anzeigen klicken."
msgid "Changes the title to \"%{title_param}\"."
msgstr "Ändert den Titel in \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Vorlage auswählen ..."
msgid "Choose a type..."
msgstr "Typ auswählen..."
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr "Klonen"
msgid "Clone repository"
msgstr "Repository klonen"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ msgstr "Mit KRB5 klonen"
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 "Schließen"
@@ -6781,12 +6970,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "Code-Eigentümer"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr ""
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr "DSGVO"
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Verbinden"
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-msgstr "Ablaufintervall:"
-
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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr "URL kopieren"
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "Befehl kopieren"
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr "Board erstellen"
-
msgid "Create branch"
msgstr "Branch erstellen"
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "Neues Board erstellen"
-
msgid "Create new branch"
msgstr "Neuen Branch erstellen"
@@ -8033,6 +8246,84 @@ msgstr "Tag "
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Erstelle einen persönlichen Zugriffstoken"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Erstellt"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Aktueller Branch"
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
-msgid "CustomCycleAnalytics|Name"
-msgstr "Name"
-
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr "Standardwert für den ersten Wochentag im Kalender und in der Datumsausw
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "Standard: Ordne eine FogBugz-Konto-ID einem vollständigen Namen zu"
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Erstelle ein benutzerdefiniertes Muster mittels Cron-Syntax"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr "Kommentar entfernen"
@@ -9355,9 +9628,6 @@ msgstr "Absteigend"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr "Beschreibe die Anforderung hier"
-
msgid "Description"
msgstr "Beschreibung"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "CSV herunterladen"
@@ -9966,9 +10299,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 and/or belong to one of the following types:"
-msgstr "Jeder Runner kann in einer der folgenden Phasen sein und/oder zu einem der folgenden Typen gehören:"
-
msgid "Each Runner can be in one of the following states:"
msgstr "Jeder Runner kann in einem der folgenden Zustände sein:"
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr "Anwendung bearbeiten"
-msgid "Edit board"
-msgstr "Board bearbeiten"
-
msgid "Edit comment"
msgstr "Kommentar bearbeiten"
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr "Öffentlichen Bereitstellungsschlüssel bearbeiten"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "Phase bearbeiten"
@@ -10092,12 +10422,18 @@ 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 "Indizierungsbeschränkungen für Elasticsearch"
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr "E-Mails"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ msgstr ""
msgid "Enable and configure Prometheus metrics."
msgstr "Aktiviere und konfiguriere Prometheus-Messwerte."
+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 "Aktiviere die Klassifizierungskontrolle mithilfe eines externen Service"
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr "Nutzungsbericht einschalten"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Endet am (UTC)"
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ msgstr "Gib den Titel des Merge-Requests ein"
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 ""
@@ -10626,6 +10971,9 @@ msgstr "Bereitstellen für..."
msgid "Environments|Deployment"
msgstr "Bereitstellung"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 "Aktualisiert"
@@ -10803,9 +11157,6 @@ msgstr "Wie kann ich dieses Problem lösen?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Weitere Informationen"
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr "Fehler beim Abrufen des Netzwerkgraphen."
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr "Fehler beim Abrufen der Referenzen"
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ msgstr "Jeder kann beitragen"
msgid "Everything on your to-do list is marked as done."
msgstr ""
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "Ablaufzeitpunkt"
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ msgstr "Wechsel des/der Besitzers/-in fehlgeschlagen"
msgid "Failed to check related branches."
msgstr "Verwandte Branches konnten nicht überprüft werden."
+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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr "Bereitstellung fehlgeschlagen für"
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 "Prozentsatz"
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Filter"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtern nach %{issuable_type}, die derzeit geschlossen sind."
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr "Nach Name filtern"
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Finde über den Pfad"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "Finde Datei"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr "Fertiggestellt"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr "Erstmals gesehen"
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ msgstr "Erhalte eine kostenlose Instanzprüfung"
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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr "Zurück"
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr "Gruppenavatar"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "Gruppenbeschreibung"
-
msgid "Group description (optional)"
msgstr "Gruppenbeschreibung (optional)"
@@ -13562,11 +13916,17 @@ 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 your group badges."
-msgstr "Deine Gruppen-Badges anpassen."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "Erfahre mehr über Badges."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ msgstr "Keine Gruppen gefunden"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Du kannst die Berechtigungen deiner Gruppenmitglieder und den Zugriff auf jedes Projekt in der Gruppe verwalten."
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr "Bereinigung erfolgreich gestartet"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr "Aus Jira importieren"
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "Import wird durchgeführt"
@@ -14269,6 +14668,9 @@ msgstr "Importiere Repositories von GitHub"
msgid "Import repository"
msgstr "Repository importieren"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "Verbessere Ticketboards mit der GitLab Enterprise Edition."
+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 "Verbessere Merge-Requests und den Kundensupport mit GitLab Enterprise Edition."
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr "Einladen"
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Ticketereignisse"
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,20 +15887,20 @@ 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|This feature requires a Premium plan."
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Transition ID(s)"
-msgstr "Transition-ID(s)"
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
-msgstr "Verwende , oder ; um mehrere Transition-IDs zu trennen"
+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 ""
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Erfahre mehr in den"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "Pipelineplanungsdokumentation"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Verlassen"
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr "Maximale Zugriffsstufe"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Merge-Request-Genehmigungen"
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Merge-Requests"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Merge-Requests dienen dazu, deine Änderungsvorschläge für ein Projekt einzureichen und sie mit anderen zu diskutieren"
@@ -17200,9 +17652,15 @@ 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 ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr "Benutzer(in) spiegeln"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "Gespiegelte Repositories"
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "Mehrere Ticket-Boards"
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Neue Datei"
msgid "New group"
msgstr "Neue Gruppe"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr "Keine Branches gefunden"
msgid "No changes"
msgstr "Keine Änderungen"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr "Nicht verfügbar für private Projekte"
msgid "Not available for protected branches"
msgstr "Für geschützte Branches nicht verfügbar"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Nicht vertraulich"
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Seiten"
@@ -19843,11 +20418,14 @@ msgstr ""
msgid "Pause"
msgstr "Pausieren"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr "Replikation pausieren"
-msgid "Paused Runners don't accept new jobs"
-msgstr "Angehaltene Runner akzeptieren keine neuen Jobs"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "In Arbeit"
@@ -19915,6 +20493,9 @@ msgstr "Berechtigungen, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Persönlicher Zugangs-Token"
+msgid "Personal Access Token prefix"
+msgstr ""
+
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
@@ -19951,6 +20532,9 @@ msgstr "Zeitpläne der Pipeline"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ msgstr "Pipeline-Trigger"
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 ""
@@ -19978,7 +20571,7 @@ msgstr "Erfolgsquote:"
msgid "PipelineCharts|Successful:"
msgstr "Erfolgreich:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ msgstr ""
msgid "Pipelines|Editor"
msgstr ""
+msgid "Pipelines|Get started with CI/CD"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Erste Schritte mit Pipelines"
+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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "Pipelines laden"
@@ -20149,6 +20751,18 @@ msgstr "Derzeit gibt es keine Pipelines."
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."
+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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,15 +21234,18 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Verhindere das Hinzufügen neuer Mitglieder zur Projektmitgliedschaft in dieser Gruppe"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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 "Verhindere das Hinzufügen neuer Mitglieder zur Projektmitgliedschaft in dieser Gruppe"
+
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr "Primär"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "Priorisieren"
@@ -20797,6 +21426,9 @@ 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 "Konto zur Löschung vorgemerkt."
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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"
@@ -21229,9 +21867,6 @@ msgstr "Projektname"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,8 +22062,8 @@ msgstr "Kontaktiere eine(n) Administrator(in), um diese Einstellung zu ändern."
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
-msgstr "Deine Projekt-Badges anpassen."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr ""
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "Erfahre mehr über Badges."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Nur signierte Commits können zu diesem Repository gepusht werden."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr "Branch schützen"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "Zuletzt gesucht"
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr "Runner entfernen"
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr "Priorität entfernen"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Sekundärknoten entfernen"
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr "Ordner umbenennen"
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr "Wieder öffnen"
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Repository"
@@ -23204,9 +23881,6 @@ msgstr "Auswählen"
msgid "Request Access"
msgstr "Anfrage auf Zugriff"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Fordere alle Benutzer(innen) auf, die Nutzungsbedingungen und Datenschutzrichtlinien zu akzeptieren, wenn sie auf GitLab zugreifen."
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr "Antwortmesswerte (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Antwortmesswerte (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Unmarkierte Jobs ausführen"
-msgid "Runner cannot be assigned to other projects"
-msgstr "Runner kann keinem anderen Projekt zugewiesen werden"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "Runner führt Jobs von allen nicht zugewiesenen Projekten aus"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "Runner führt Jobs von allen nicht zugewiesenen Projekten in seiner Gruppe aus"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "Runner führt Jobs von zugewiesenen Projekten aus"
-
msgid "Runner token"
msgstr "Runner-Token"
@@ -23614,9 +24279,6 @@ msgstr "Runner wurde nicht aktualisiert."
msgid "Runner was successfully updated."
msgstr "Runner wurde erfolreich aktualisiert."
-msgid "Runner will not receive any new jobs"
-msgstr "Runner wird keine neuen Jobs annehmen"
-
msgid "Runners"
msgstr "Runners"
@@ -23626,14 +24288,17 @@ 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 placed on separate users, servers, 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 ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "Runner derzeit online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr "Öffentlicher SSH-Schlüssel"
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr "Geplant"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,8 +24516,8 @@ msgstr "Pipelines planen"
msgid "Scope"
msgstr "Gültigkeitsbereich"
-msgid "Scoped issue boards"
-msgstr "Ticketboards mit festgelegtem Umfang"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr ""
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Suche Benutzer(innen)"
@@ -23995,6 +24669,9 @@ msgstr "Merge-Requests, die ich erstellt habe"
msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "Merge-Requests, die mir zugewiesen sind"
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
msgid "SearchAutocomplete|in all GitLab"
msgstr "im ganzen GitLab"
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr "September"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ msgstr ""
msgid "Service Desk"
msgstr "Service-Desk"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr ""
@@ -24823,12 +25515,9 @@ 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 template for issue descriptions."
+msgid "Set a default description template to be used for new issues. %{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "Set a number of approvals required, the approvers and other approval settings."
-msgstr "Lege eine Anzahl der erforderlichen Genehmigungen, die Genehmigungsberechtigten und andere Genehmigungseinstellungen fest."
-
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Lege ein Passwort für dein Konto fest, um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
@@ -25024,9 +25713,6 @@ msgstr "Einstellungen"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr "Alle Mitglieder anzeigen"
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Neuste Version zeigen"
@@ -25457,6 +26149,9 @@ 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 "Bei uns ist etwas schief gelaufen"
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr "Etwas ist beim Laden der Liste %{listType} fehlgeschlagen"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Beim Abrufen der Kommentare ist etwas schiefgelaufen. Bitte versuche es erneut."
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,15 +26740,18 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Beginnt am (UTC)"
+msgid "Starts on"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Gib deine Nachricht an, um sie zu aktivieren"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 "Test"
@@ -26999,8 +27766,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
-msgstr "Vielen Dank! Zeig es mir nicht nochmal"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ msgstr ""
msgid "The current issue"
msgstr "Das aktuelle Ticket"
+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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr "Die maximal zulässige Dateigröße beträgt 200 KB."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ msgstr "Es gibt noch keine geteilten Projekte mit dieser Gruppe"
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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ msgstr "Diese GitLab-Instanz stellt noch keine geteilten Runner bereit. Instanz-
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 ""
@@ -28056,6 +28838,9 @@ msgstr "Dies bedeutet, dass du keinen Code pushen kannst, bevor du kein leeres R
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 ""
@@ -28140,6 +28925,15 @@ 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 "Dieser Runner wird nur Pipelines von geschützen Branches ausführen"
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr "Gesamte Anfragen"
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ msgstr "Baumstrukturansicht"
msgid "Trending"
msgstr "Beliebt"
+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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr "Entfavorisieren"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "Abonnement entfernen"
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "Deine Gruppenbezeichnung, Beschreibung, Avatar und Sichtbarkeit anpassen."
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr "Aktualisiere deinen Tarif, um Gruppen-Webhooks zu aktivieren."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "Upgrade deinen Tarif um die Ticketboards zu verbessern."
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr "Beschreibung"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projekt"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Du möchtest die Daten sehen? Bitte frage eine(n) Administrator(in) nach dem Zugang."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 "Wir haben potenziellen Spam in %{humanized_resource_name} gefunden. Bitte löse den reCAPTCHA um fortzufahren."
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 "Du kannst den Merge-Konflikt lösen, indem du entweder den interaktiven Modus verwendest, indem du die Schaltflächen %{use_ours} oder %{use_theirs} wählst, oder indem du die Dateien direkt bearbeitest. Übernimm diese Änderungen mittels Commit in %{branch_name}"
@@ -31252,9 +32156,6 @@ msgstr "Sie können Ihre Chat-Konten sehen."
msgid "You can set up as many Runners as you need to run your jobs."
msgstr ""
-msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr "Du kannst Jobs so einrichten, dass nur Runner mit bestimmten Tags verwendet werden. Trenne die Tags durch Kommas."
-
msgid "You can specify notification level per group or per project."
msgstr ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "Du verfügst nicht über die erforderlichen Berechtigungen um die Einstellungen der LDAP-Gruppensynchronisierung zu überschreiben."
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Du musst Betreuerzugriff besitzen, um das Entfernen einer Sperre zu erzwingen"
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr "Branch-Name"
msgid "by"
msgstr "von"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 "%{linkStartTag}Lerne mehr über Containerüberprüfung%{linkEndTag}"
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Fehler beim Wiedereinblenden. Bitte versuche es erneut."
+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] "Verwendet von %{packagesString}"
@@ -32371,6 +33314,12 @@ msgstr ""
msgid "has already been taken"
msgstr "ist bereits vergeben"
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
msgid "has been completed."
msgstr ""
@@ -32553,6 +33502,9 @@ 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] "Merge-Request"
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "Tag-Name"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 4d1e794a084..78533691c22 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: 2020-12-03 08:16\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 39d845fc0ff..256bd9f8292 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: 2020-12-03 08:11\n"
+"PO-Revision-Date: 2021-01-08 22:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Serĉu branĉon"
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Nuligi"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ msgstr "Elekti en branĉon"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Malfari en branĉo"
+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 "Precize elekti"
msgid "ChangeTypeAction|Revert"
msgstr "Malfari"
+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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr "Etikedo"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "kreos propran atingoĵetonon"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Difini propran Åablonon, uzante la sintakson de Cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "Priskribo"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ msgstr "Ne eblas ÅanÄi la posedanton"
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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Trovi per dosierindiko"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "Trovi dosieron"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr "La refreÅigo komenciÄis sukcese"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr "Enporti deponejon"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Lernu pli en la"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "dokumentado pri ĉenstablaj planoj"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Nova dosiero"
msgid "New group"
msgstr ""
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr "Ĉenstablaj planoj"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr "Proporcio de sukceso:"
msgid "PipelineCharts|Successful:"
msgstr "Sukcesaj:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr "Peti atingeblon"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr "Planado de la ĉenstabloj"
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ msgstr "Ĉi tiu signifas, ke vi ne povos alpuÅi kodon, antaÅ­ ol vi kreos malpl
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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr "Malsteligi"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 4787a15ef44..49a76901b83 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: 2020-12-03 08:14\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ msgstr "%{address} no es en un rango de direcciones IP válido"
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 "%{author_link} escribió:"
msgid "%{authorsName}'s thread"
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)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commits"
+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 "%{strong_start}%{human_size}%{strong_end} Archivos"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} fusionado)"
msgid "(%{value}) has already been taken"
msgstr ""
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Sin cambios)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(comprobar el progreso)"
@@ -1175,29 +1205,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "Un ejecutor es un proceso que ejecuta un trabajo. Puede configurar tantos ejecutores como usted necesite."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Una plantilla de aplicación de consola .NET Core, personalizable para cualquier proyecto .NET Core"
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 "Un sitio basado en GitBook que utiliza Netlify como herramienta de CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
+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 "Un sitio basado en Hexo que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
+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 "Un sitio basado en Hugo que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
+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 "Un sitio basado en Jekyll que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con las de más excelentes características de GitLab."
+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 "No se puede obtener un certificado SSL de Let's Encrypt hasta que se verifique su dominio."
@@ -1208,6 +1235,9 @@ msgstr "Se configurará una cuenta de Let's Encrypt para esta instalación de Gi
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 "Una plataforma DevOps completa"
@@ -1235,6 +1265,9 @@ 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 maximum of %{count} participants can be added"
+msgstr ""
+
msgid "A member of the abuse team will review your report as soon as possible."
msgstr "Un miembro del equipo revisará su informe tan pronto como sea posible."
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ msgstr "Se ha creado un nuevo token de impersonación."
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 "Un sitio hecho con HTML plano que utiliza Netlify para CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
+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."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Una plantilla lista para utilizar con aplicaciones de Android."
+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 "Una plantilla lista para utilizar con las aplicaciones iOS basadas en Swift."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1292,9 +1334,15 @@ msgstr "Un token seguro que identifica una petición de almacenamiento externo."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "Se ha realizado un inicio de sesión en su cuenta desde la siguiente dirección 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 ""
+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 "Un usuario con acceso de escritura a la rama origen seleccionó esta opción"
@@ -1313,13 +1361,16 @@ msgstr "Token del API"
msgid "AWS Access Key"
msgstr "AWS Access Key"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "AWS Acces Key. Se requiere solo si no se utilizan credenciales de instancia de rol"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS Secret Access Key"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ msgstr "Acceso denegado para su cuenta LDAP."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "¡Acceso denegado! Por favor, verifique que puede agregar las claves de despliegue a este repositorio."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Fecha de expiración del acceso"
@@ -1954,6 +2008,9 @@ msgstr "Aplicar la configuración de integración a todos los proyectos"
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr "Habilitar ejecutores compartidos para los nuevos proyectos"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Las variables de entorno están protegidas por defecto"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "Ir a los ajustes generales"
@@ -2439,9 +2499,6 @@ msgstr "Ninguno"
msgid "AlertManagement|Open"
msgstr "Abrir"
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr "Opsgenie está habilitado"
-
msgid "AlertManagement|Please try again."
msgstr "Por favor, inténtelo de nuevo."
@@ -2505,15 +2562,9 @@ msgstr "Desconocido"
msgid "AlertManagement|Value"
msgstr "Valor"
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr "Ver alertas en Opsgenie"
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr "1. Seleccione el tipo de integración"
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr "AlertSettings|URL del webhook"
@@ -2772,9 +2814,6 @@ msgstr "Todas las ramas"
msgid "All changes are committed"
msgstr "Se ha realizado commit de todos los cambios"
-msgid "All default stages are currently visible"
-msgstr "Todas las fases predeterminadas son visibles actualmente"
-
msgid "All email addresses will be used to identify your commits."
msgstr "Todas las direcciones de correo electrónico se utilizarán para identificar sus commits."
@@ -2835,6 +2874,9 @@ msgstr "Permitir a los propietarios de los grupos administrar configuraciones re
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que sólo los protocolos seleccionados tengan acceso a Git."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Se ha producido un error"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Se produjo un error al activar/desactivar la suscripción de notificaciÃ
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 "Se ha producido un error al actualizar el tamaño de la incidencia"
@@ -3021,6 +3066,9 @@ msgstr "Se ha producido un error al añadir los aprobadores."
msgid "An error occurred while adding formatted title for epic"
msgstr "Se ha producido un error al añadir el título formateado para la tarea épica"
+msgid "An error occurred while authorizing your role"
+msgstr ""
+
msgid "An error occurred while checking group path. Please refresh and try again."
msgstr "Se ha producido un error durante la comprobación de ruta del grupo. Por favor, actualice y vuelva a intentarlo."
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr "Se ha producido un error al obtener los proyectos."
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Se ha producido un error al guardar el estado de LDAP. Por favor, inténtalo de nuevo."
-
msgid "An error occurred while saving assignees"
msgstr "Se ha producido un error al guardar las asignaciones"
@@ -3267,6 +3312,9 @@ msgstr "Se ha producido un error al cancelar la suscripción a las notificacione
msgid "An error occurred while updating approvers"
msgstr "Se ha producido un error al actualizar los aprobadores"
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr "Se ha producido un error al actualizar la configuración."
@@ -3276,6 +3324,9 @@ msgstr "Se ha producido un error al actualizar las etiquetas."
msgid "An error occurred while updating the comment"
msgstr "Se ha producido un error al actualizar el comentario"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,8 +3345,8 @@ msgstr "Se ha producido un error. Por favor inténtelo de nuevo."
msgid "An error ocurred while loading your content. Please try again."
msgstr "Se ha producido un error al cargar su contenido. Por favor, inténtelo de nuevo."
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
-msgstr "Un proyecto de ejemplo para administrar clústeres de Kubernetes integrado con GitLab."
+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 ""
@@ -3309,6 +3360,9 @@ msgstr "Ya existe una incidencia"
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 "Una incidencia puede ser un error, una tarea pendiente o una solicitud de una nueva funcionalidad que debe tratarse en un proyecto. Además, recuerde que las incidencias se pueden buscar y filtrar."
+msgid "An issue title is required"
+msgstr ""
+
msgid "An unauthenticated user"
msgstr "Un usuario no autenticado"
@@ -3387,8 +3441,8 @@ msgstr ""
msgid "Any label"
msgstr "Cualquier etiqueta"
-msgid "Any member with Developer or higher permissions to the project."
-msgstr "Cualquier miembro con permisos de desarrollador o con permisos superiores para el proyecto."
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
msgid "Any milestone"
msgstr "Cualquier hito"
@@ -3536,15 +3590,15 @@ msgstr[1] "%{count} aprobaciones requeridas para %{membersCount}"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Aprobadores"
msgid "ApprovalRule|Name"
msgstr "Nombre"
-msgid "ApprovalRule|No. approvals required"
-msgstr "No se requiere aprobaciones"
-
msgid "ApprovalRule|Rule name"
msgstr "Nombre de la regla"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr "Sección: %section"
@@ -3665,9 +3722,6 @@ msgstr "¿Esta seguro de que desea eliminar esto %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "¿Está seguro de que desea eliminar esta tablero?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "¿Está seguro de que desea borrar este dispositivo? Esta acción no se puede deshacer."
@@ -3835,6 +3889,12 @@ msgstr "Asignar etiquetas"
msgid "Assign milestone"
msgstr "Asignar milestone"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Asignar algunas incidencias a este hito."
@@ -3853,12 +3913,18 @@ msgstr "Asignarse esta incidencia"
msgid "Assigned %{assignee_users_sentence}."
msgstr "Asignado a %{assignee_users_sentence}."
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Incidencias asignadas"
msgid "Assigned Merge Requests"
msgstr "Merge requests asignados"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr "Asignado a %{assigneeName}"
@@ -3871,6 +3937,9 @@ msgstr "Asignado a %{name}"
msgid "Assigned to me"
msgstr "Asignado a mí"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Asignado"
@@ -3894,6 +3963,9 @@ msgstr "Asignados"
msgid "Assigns %{assignee_users_sentence}."
msgstr "Asigna %{assignee_users_sentence}."
+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 "Se requiere al menos la aprobación de un propietario del código para cambiar los archivos que coincidan con las reglas de CODEOWNER."
@@ -3938,9 +4010,6 @@ msgstr "Eventos de auditoría"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr "Audit Events es una forma de realizar un seguimiento de los eventos importantes que ocurrieron en GitLab."
-msgid "Audit Log"
-msgstr "Registro de auditoría"
-
msgid "AuditLogs|(removed)"
msgstr "(eliminado)"
@@ -4097,12 +4166,12 @@ msgstr "Cancelación redundante automática, pipelines pendientes"
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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr ""
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Documentación de Auto DevOps"
@@ -4121,10 +4190,13 @@ msgstr "Más información en %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr "Gestión automática de los certificados utilizando Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Color de fondo"
msgid "Badges"
msgstr "Insignias"
-msgid "Badges|A new badge was added."
-msgstr "Se ha añadido una nueva insignia."
-
msgid "Badges|Add badge"
msgstr "Añadir insignia"
@@ -4244,12 +4313,21 @@ msgstr "URL de imagen de la insignia"
msgid "Badges|Badge image preview"
msgstr "Vista previa de la imagen de la insignia"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "¿Desea eliminar la insignia?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "Se ha producido un error al eliminar la insignia. Inténtelo de nuevo."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Insignia del grupo"
@@ -4259,15 +4337,15 @@ msgstr "Enlace"
msgid "Badges|Name"
msgstr "Nombre"
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "No hay imagen de insignia"
msgid "Badges|No image to preview"
msgstr "No hay imagen para la vista previa"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Por favor, introduzca una URL válida"
-
msgid "Badges|Project Badge"
msgstr "Insignia del proyecto"
@@ -4280,15 +4358,12 @@ msgstr "Guardar los cambios"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Se ha producido un error al guardar la insignia, por favor, compruebe las URLs introducidas e inténtelo de nuevo."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "Las %{docsLinkStart}variables%{docsLinkEnd} que admite GitLab: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Se ha eliminado la insignia."
-msgid "Badges|The badge was saved."
-msgstr "Se ha guardado la insignia."
-
msgid "Badges|This group has no badges"
msgstr "Este grupo no tiene insignias"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Sus insignias"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "por ejemplo, %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "El archivo Balsamiq no se pudo cargar."
@@ -4328,9 +4400,6 @@ msgstr "Debe configurar el etiquetado automático de revisión y un disparador d
msgid "Based on"
msgstr "Basado en"
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Tenga cuidado. Cambiar el espacio de nombres del proyecto puede tener efectos secundarios no deseados."
@@ -4415,22 +4484,28 @@ msgstr "Contactar con ventas"
msgid "BillingPlan|Upgrade"
msgstr "Actualizar"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,12 +4543,21 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
-msgid "Board scope"
-msgstr "Alcance del panel de control"
-
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "El alcance del panel de control afecta qué problemas se muestran para cualquiera persona que visite este panel"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
msgid "Boards"
msgstr "Tableros"
@@ -4525,6 +4609,30 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver alcance"
+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 ""
@@ -4555,9 +4663,6 @@ msgstr "Nombre de la rama"
msgid "Branch not loaded - %{branchId}"
msgstr "Branch no cargada - %{branchId}"
-msgid "Branch prefix"
-msgstr "Prefijo de la rama"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Buscar ramas"
@@ -4726,6 +4831,24 @@ msgstr "Integrado"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,8 +4942,11 @@ msgstr "CI/CD para repositorio externo"
msgid "CI/CD settings"
msgstr "Configuración de CI/CD"
-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 "Añadir una %{kubernetes_cluster_link_start}integraciónde un clúster de Kubernetes %{link_end} con un dominio o cree una variable AUTO_DEVOPS_PLATFORM_TARGET CI."
+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 "Auto DevOps"
@@ -4846,12 +4972,12 @@ msgstr "Estrategia de despliegue"
msgid "CICD|Jobs"
msgstr "Trabajos"
+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 "El pipeline de Auto DevOps se ejecutará si no se encuentra ningún archivo de configuración alternativo de CI."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr "Debe agregar un %{base_domain_link_start}dominio base%{link_end} a su %{kubernetes_cluster_link_start}clúster de Kubernetes%{link_end} para que su estrategia de despliegue funcione."
-
msgid "CICD|group enabled"
msgstr "grupo habilitado"
@@ -4879,9 +5005,6 @@ msgstr "URL de callback"
msgid "Can be manually deployed to"
msgstr "Puede ser desplegado manualmente en"
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Los aprobadores y las aprobaciones requeridas se pueden sobreescribir por cada merge request"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Cancelar"
@@ -4951,6 +5098,9 @@ msgstr "Cancelado el despliegue a"
msgid "Cancelling Preview"
msgstr "Cancelando la vista previa"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "No se puede hacer merge automáticamente"
@@ -5083,15 +5233,33 @@ msgstr "Escoger en la rama"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Revertir en la rama"
+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 "Cherry-pick"
msgid "ChangeTypeAction|Revert"
msgstr "Revertir"
+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 "Esta acción creará un nuevo commit para deshacer los cambios existentes."
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr "Asignado(s) cambiado(s)."
@@ -5113,13 +5281,16 @@ msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr ""
+msgid "Changes saved."
+msgstr ""
+
msgid "Changes suppressed. Click to show."
msgstr "Cambios eliminados. Haga clic para mostrar."
msgid "Changes the title to \"%{title_param}\"."
msgstr "Cambia el título a \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr "Gráficos"
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Elegir una plantilla..."
msgid "Choose a type..."
msgstr "Elegir un tipo..."
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr "Clonar"
msgid "Clone repository"
msgstr "Clonar repositorio"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "Clonar con %{http_label}"
@@ -5674,6 +5851,18 @@ msgstr "Clonar con KRB5"
msgid "Clone with SSH"
msgstr "Clonar con SSH"
+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 "Cerrar"
@@ -6781,12 +6970,12 @@ msgstr "Datos de cobertura de código vacíos"
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr "No es posible recuperar los datos de la cobertura de código"
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "Propietarios del código"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr "Calidad del código"
@@ -7056,6 +7245,24 @@ msgstr ""
msgid "ComplianceDashboard|created by:"
msgstr "Creado por:"
+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 "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "¡Enhorabuena ha habilitado la autenticación de dos factores!"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Conectar"
@@ -7273,13 +7483,13 @@ msgstr[1] "%{count} Etiquetas"
msgid "ContainerRegistry|%{imageName} tags"
msgstr "%{imageName} etiquetas"
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ msgstr "Construir una imagen"
msgid "ContainerRegistry|CLI Commands"
msgstr "Comandos del CLI"
+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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Error de conexión de Docker"
-msgid "ContainerRegistry|Expiration interval:"
-msgstr "Intervalo de caducidad:"
-
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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr "Filtrar por nombre"
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr "Iniciar sesión"
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr "ContainerRegistry|Número de etiquetas a retener:"
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "Publicado %{timeInfo}"
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "Con el registro de contenedores, cada proyecto puede tener su propio espacio para almacenar sus imágenes de Docker. %{docLinkStart}Más Información%{docLinkEnd}"
@@ -7668,6 +7884,9 @@ msgstr "Copiar la URL"
msgid "Copy branch name"
msgstr "Copiar el nombre de rama"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "Copiar el comando"
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr "Crear una cuenta utilizando:"
-msgid "Create an issue. Issues are created for each alert triggered."
-msgstr "Crear una incidencia. Se crearán incidencias para cada alerta activada."
+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 board"
-msgstr "Crear tablero"
-
msgid "Create branch"
msgstr "Crear rama"
@@ -7967,9 +8183,6 @@ msgstr "Crear nuevo"
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "Crear nuevo tablero"
-
msgid "Create new branch"
msgstr "Crear una nueva rama"
@@ -8033,6 +8246,84 @@ msgstr "Etiqueta"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "crear un token de acceso personal"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Creado"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr "Crossplane"
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Rama actual"
@@ -8210,45 +8504,18 @@ msgstr "Agregar una etapa"
msgid "CustomCycleAnalytics|Editing stage"
msgstr "Editar etapa"
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr "Introduzca un nombre para la etapa"
-
-msgid "CustomCycleAnalytics|Name"
-msgstr "Nombre"
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr "Nueva etapa"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr "Por favor, seleccione un evento de inicio primero"
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr "Seleccione un evento de inicio"
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr "Seleccione un evento de detención"
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr "El nombre de la etapa ya existe"
-msgid "CustomCycleAnalytics|Start event"
-msgstr "Iniciar evento"
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr "Se modifico el evento de inicio, se debe seleccionar un evento de salida válido"
-
msgid "CustomCycleAnalytics|Start event label"
msgstr "Etiqueta del evento de inicio"
-msgid "CustomCycleAnalytics|Stop event"
-msgstr "Detener evento"
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr "Etiqueta del evento de detención"
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr "Actualizar etapa"
-
msgid "Customer Portal"
msgstr "Portal de cliente"
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr "Primer día de la semana por defecto en calendarios y selectores de fech
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "Plantilla de incidencia por defecto"
-
msgid "Default project deletion protection"
msgstr "Protección por defecto de eliminación de proyectos"
msgid "Default projects limit"
msgstr "Límite predeterminado de proyectos"
-msgid "Default stages"
-msgstr "Etapas predeterminadas"
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "Por defecto: Asignar un ID de cuenta de FogBugz a un nombre completo"
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Definir un patrón personalizado con la sintaxis de cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr "Eliminar artefactos"
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "Eliminar el tablero"
-
msgid "Delete comment"
msgstr "Eliminar comentario"
@@ -9355,9 +9628,6 @@ msgstr "Descendente"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr "Describa el requisito aquí"
-
msgid "Description"
msgstr "Descripción"
@@ -9367,6 +9637,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "Descripción analizada con %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
msgid "Description template"
msgstr ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr "Descargar %{format}"
msgid "Download %{format}:"
msgstr "Descargar %{format}:"
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "Descargar CSV"
@@ -9966,9 +10299,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 and/or belong to one of the following types:"
-msgstr "Cada runner puede estar en uno de los siguientes estados y/o pertenecer a uno de los siguientes tipos:"
-
msgid "Each Runner can be in one of the following states:"
msgstr "Cada ejecutor puede estar en uno de los siguientes estados:"
@@ -10023,9 +10353,6 @@ msgstr "Editar hook del sistema"
msgid "Edit application"
msgstr "Editar aplicación"
-msgid "Edit board"
-msgstr "Editar tablero"
-
msgid "Edit comment"
msgstr "Editar comentario"
@@ -10065,6 +10392,9 @@ msgstr "Editar iteración"
msgid "Edit public deploy key"
msgstr "Editar clave pública de despliegue"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "Editar etapa"
@@ -10092,12 +10422,18 @@ msgstr "Editado %{timeago}"
msgid "Editing"
msgstr "Editando"
+msgid "Editor Lite instance is required to set up an extension."
+msgstr ""
+
msgid "Elasticsearch AWS IAM credentials"
msgstr "Credenciales IAM de AWS Elasticsearch"
msgid "Elasticsearch HTTP client timeout value in seconds."
msgstr ""
+msgid "Elasticsearch indexing"
+msgstr ""
+
msgid "Elasticsearch indexing restrictions"
msgstr "Restricciones en la indexación de Elasticsearch"
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr "Notificación por correo electrónico"
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,11 +10539,11 @@ msgstr "reiniciando..."
msgid "Emails"
msgstr "Correos electrónicos"
-msgid "Emails sent from Service Desk will have this name"
-msgstr "Los correos electrónicos enviados desde Service Desk tendrán este nombre"
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
-msgid "Emails sent to %{email} will still be supported"
-msgstr "Los correos electrónicos enviados a %{email} continuarán siendo compatibles"
+msgid "Emails sent to %{email} are also supported."
+msgstr ""
msgid "Emails separated by comma"
msgstr "Correos electrónicos separados por comas"
@@ -10284,6 +10623,9 @@ msgstr "Habilitar y configurar Grafana."
msgid "Enable and configure Prometheus metrics."
msgstr "Habilitar y configurar las métricas de Prometheus."
+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 "Habilitar control de clasificación utilizando un servicio externo"
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr "Habilitar la autenticación de dos factores"
msgid "Enable usage ping"
msgstr "Habilitar ping de uso"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr "Habilitar/Deshabilitar su Service Desk. %{link_start} Obtenga más información sobre Service Desk en el siguiente enlace %{link_end}."
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ 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)"
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr "Introduzca al menos tres caracteres para buscar"
-msgid "Enter board name"
-msgstr "Introduzca el nombre del tablero"
-
msgid "Enter domain"
msgstr "Introduzca un dominio"
@@ -10485,6 +10827,9 @@ msgstr "Introduzca el título del merge request"
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 ""
@@ -10626,6 +10971,9 @@ msgstr "Desplegar en..."
msgid "Environments|Deployment"
msgstr "Despliegue"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 "Esta acción ejecutará el trabajo definido por %{name} para el commit %{linkStart}%{commitId}%{linkEnd}, estableciendo el entorno a una versión anterior. Puede dejar el entorno en la última versión de su aplicación volviendo a desplegarlo. ¿Está seguro de que desea continuar?"
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Actualizado"
@@ -10803,9 +11157,6 @@ msgstr "¿Cómo puedo resolver esto?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Más información"
-
msgid "Epics|Remove epic"
msgstr "Eliminar tarea épica"
@@ -10911,9 +11262,6 @@ msgstr "Se ha producido un error al obtener el gráfico de la red."
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr "Se ha producido un error al obtener los proyectos"
-
msgid "Error fetching refs"
msgstr "Se ha producido un error al obtener los refs"
@@ -11049,9 +11397,18 @@ msgstr "Error con Akismet. Por favor, compruebe los registros de error para obte
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 "Activo"
@@ -11166,23 +11523,23 @@ msgstr "Todo el mundo puede colaborar"
msgid "Everything on your to-do list is marked as done."
msgstr "Todo lo que está en su lista de tareas se ha marcado como hecho."
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
+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 "Todo lo que necesita para crear un sitio de GitLab Pages con GitBook."
+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 "Todo lo que necesita para crear un sitio de GitLab Pages utilizando Hexo."
+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 "Todo lo que necesitas para crear un sitio de GitLab Pages con Hugo."
+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 "Todo lo que necesita para crear un sitio de GitLab Pages con Jekyll."
+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 "Todo lo que necesita para crear un sitio de GitLab Pages utilizando HTML plano."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
msgid "Evidence collection"
msgstr "Recopilación de evidencias"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr "Miembros y grupos existentes"
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr "Experiencia"
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "Vencimiento"
@@ -11403,6 +11760,9 @@ msgstr "Se ha producido un error al agregar una reunión de Zoom"
msgid "Failed to apply commands."
msgstr "Se ha producido un error al aplicar los comandos."
+msgid "Failed to assign a reviewer because no user was found."
+msgstr ""
+
msgid "Failed to assign a user because no user was found."
msgstr "Se ha producido un error al asignar un usuario debido no se ha encontrado el usuario."
@@ -11421,6 +11781,12 @@ msgstr "Error al cambiar el propietario"
msgid "Failed to check related branches."
msgstr "Se ha producido un error al verificar las branchs relacionadas."
+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 "No es posible realizar el merge request. Por favor, inténtelo de nuevo."
@@ -11448,9 +11814,6 @@ msgstr "Se ha producido un error al crear los recursos"
msgid "Failed to create wiki"
msgstr "Se ha producido un error al crear el wiki"
-msgid "Failed to delete board. Please try again."
-msgstr "Se ha producido un error al eliminar el panel de control. Por favor, inténtelo de nuevo."
-
msgid "Failed to deploy to"
msgstr "Se ha producido un error al desplegar a"
@@ -11601,6 +11964,9 @@ msgstr "¡Se ha producido un error al actualizar la rama!"
msgid "Failed to update environment!"
msgstr "Se ha producido un error al actualizar el entorno!"
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr "Se ha producido un error al actualizar el estado de la incidencia"
@@ -11661,9 +12027,6 @@ msgstr "No se ha eliminado la Feature Flag."
msgid "Feature flag was successfully removed."
msgstr "Feature flag eliminada correctamente."
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "Feature Flags"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "Se a a eliminar la Feature Flag%{name}. ¿Está seguro de que desea continuar?"
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 "Porcentaje"
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Filtro"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrar por %{issuable_type} que actualmente estén cerrados."
@@ -12026,12 +12389,6 @@ msgstr "Filtrar por nombre del hito"
msgid "Filter by name"
msgstr "Filtrar por nombre"
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr "Filtrar por estado"
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Buscar por ruta"
-msgid "Find existing members by name"
-msgstr "Buscar miembros existentes por su nombre"
-
msgid "Find file"
msgstr "Buscar archivo"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr "Finalizado"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr "Visto por primera vez"
@@ -12233,9 +12590,6 @@ msgstr "Forks"
msgid "Format: %{dateFormat}"
msgstr "Formato: %{dateFormat}"
-msgid "Forward external support email address to"
-msgstr "Reenviar la dirección de correo electrónico de soporte externo a"
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "Se han encontrado errores en su archivo %{gitlab_ci_yml}:"
@@ -12701,6 +13055,12 @@ msgstr "Obtenga una revisión de instancia gratuita"
msgid "Get started"
msgstr "Empezar"
+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 "Comenzar con el control de errores"
@@ -12776,9 +13136,6 @@ msgstr "Incidencia de GitLab"
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,8 +13355,8 @@ msgstr "Configuración global de las notificaciones"
msgid "Go Back"
msgstr "Volver"
-msgid "Go Micro is a framework for micro service development."
-msgstr "Go Micro es un framework para el desarrollo de microservicios."
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
msgid "Go back"
msgstr "Volver"
@@ -13226,9 +13583,6 @@ msgstr "Avatar del grupo"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "Descripción del grupo"
-
msgid "Group description (optional)"
msgstr "Descripción del grupo (opcional)"
@@ -13562,11 +13916,17 @@ 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 "Plantillas de proyecto personalizadas"
-msgid "GroupSettings|Customize your group badges."
-msgstr "Personalice sus insignias de grupo."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr "Por defecto, al pipeline de Auto DevOps para todos los proyectos englobados dentro de este grupo"
@@ -13589,9 +13949,6 @@ msgstr "Si la visibilidad del grupo principal es menor que la visibilidad actual
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "Aprenda más sobre insignias."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr "Más información sobre las plantillas de proyecto a nivel de grupo."
@@ -13619,8 +13976,8 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr "Seleccione un subgrupo como fuente de plantilla de proyecto personalizada para este grupo."
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr "El pipeline Auto DevOps se ejecutará si no se encuentra ningún archivo de configuración de CI/CD alternativo."
+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 "Se ha producido un error al actualizar el pipeline de Auto DevOps: %{error_messages}."
@@ -13652,6 +14009,9 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr "Transferir grupo"
+msgid "GroupSettings|What are badges?"
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "Sólo puede transferir el grupo a un grupo que administre."
@@ -13730,6 +14090,9 @@ msgstr "No se encuentran grupos"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Puede administrar los permisos y el acceso de cada miembro del grupo a cada proyecto del grupo."
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
@@ -13739,22 +14102,46 @@ msgstr "GroupsNew|Crear"
msgid "GroupsNew|Create group"
msgstr "GroupsNew|Crear grupo"
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ 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 does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "Cómo funciona"
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr "Importar desde"
msgid "Import from Jira"
msgstr "Importado desde JIRA"
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "Importación en progreso"
@@ -14269,6 +14668,9 @@ msgstr "Importar repositorios desde GitHub"
msgid "Import repository"
msgstr "Importar repositorio"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr "Importación iniciada por: %{importInitiator}"
@@ -14329,19 +14731,15 @@ msgstr "Se ha producido un error al actualizar los proyectos importados con camb
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr "Mejorar el tablero de incidencias"
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "Mejore los tableros de incidencias con GitLab Enterprise Edition."
+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 "Mejore los merge request y la atención al cliente con GitLab Enterprise Edition."
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr "Incidente"
msgid "Incident Management Limits"
msgstr "Límites de gestión de incidentes"
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,14 +14922,14 @@ msgstr ""
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
msgstr "Incluye objetos LFS. Se puede sobreescribir a nivel de grupo o de proyecto. Puede establecerse a 0 para hacer que este valor sea ilimitado."
-msgid "Includes an MVC structure to help you get started."
-msgstr "Incluye una estructura MVC para ayudarle a comenzar."
+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 "Incluye una estructura MVC, Gemfile, Rakefile, junto con muchos otros, para ayudarlo a comenzar."
+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 "Incluye una estructura MVC, mvnw y pom.xml para ayudarle a comenzar."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
msgid "Incoming email"
msgstr "Correo electrónico entrante"
@@ -14542,6 +14943,9 @@ msgstr "¡Conjunto de opciones incompatibles configuradas!"
msgid "Incompatible project"
msgstr "Proyecto incompatible"
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr "Indentar"
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr "Ref de Git no válido"
-
msgid "Invalid Insights config file detected"
msgstr "Archivo de configuración de Insights no válido detectado"
@@ -14976,15 +15383,15 @@ msgstr ""
msgid "Invite"
msgstr "Invitar"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "Invitar a \"%{trimmed}\" por correo electrónico"
msgid "Invite Members"
msgstr ""
-msgid "Invite another teammate"
-msgstr ""
-
msgid "Invite group"
msgstr "Invitar al grupo"
@@ -14994,9 +15401,6 @@ msgstr "Invitar al miembro"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr "Invitado"
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr "Ejecuciones"
@@ -15177,6 +15596,9 @@ msgstr "Incidencia no encontrada."
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Eventos de incidencia"
@@ -15192,8 +15614,8 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
-msgstr "Plantilla de la incidencia (opcional)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
msgstr "Se ha producido un error al actualizar incidencia"
@@ -15231,7 +15653,7 @@ msgstr "Estado"
msgid "IssueAnalytics|Weight"
msgstr "Peso"
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr "Iteración cambiada a"
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr "Iteración eliminada"
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Los eventos para %{noteable_model_name} están deshabilitados."
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Si es diferente de la URL Web"
@@ -15459,20 +15887,20 @@ msgstr "Gestos de incidencias Jira"
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 "Contraseña o token del API"
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Transition ID(s)"
-msgstr "ID(s) de transición"
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
-msgstr "Utilice , o ; para separar múltiples IDs de transición"
+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 "Utilice una contraseña para la versión servidor y un token API para la versión en la nube"
@@ -15896,6 +16324,9 @@ msgstr "Última comprobación de repositorio ejecutada"
msgid "Last seen"
msgstr "Visto por ùltima vez"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr "Última sincronización correcta"
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "Aprenda GitLab"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "Aprenda como contribuir %{link_start}a las plantillas integradas%{link_end}"
@@ -15992,9 +16429,6 @@ msgstr ""
msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Obtenga más información sobre cómo agregar certificados a su proyecto siguiendo la documentación %{docs_link_start}en las páginas%{docs_link_end}GitLab."
-msgid "Learn more about approvals."
-msgstr "Obtenga más información sobre las aprobaciones."
-
msgid "Learn more about custom project templates"
msgstr "Más información sobre las plantillas de proyecto personalizadas"
@@ -16019,6 +16453,9 @@ msgstr "Más información en la"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "documentación sobre la programación de pipelines"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Abandonar"
@@ -16357,6 +16794,9 @@ msgstr "Se agotó el tiempo de espera al cargar las funciones. Por favor, vuelva
msgid "Loading issues"
msgstr "Cargando incidencias"
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr "Cargando fragmento de código"
@@ -16444,6 +16884,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr "Nivel de acceso máximo"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr "Uso de memoria"
msgid "Merge"
msgstr "Merge"
-msgid "Merge (when the pipeline succeeds)"
-msgstr "Merge (cuando el pipeline finalice correctamente)"
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr "Merge request %{iid} creado por %{authorName}"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Aprobar los merge request"
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Merge requests"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Los merge request son un lugar para proponer los cambios que ha realizado en un proyecto y discutir esos cambios con otros miembros"
@@ -17200,9 +17652,15 @@ 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 ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr "Replicar usuario"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "Repositorios replicados"
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "Múltiples tableros de incidencias"
-
msgid "Multiple model types found: %{model_types}"
msgstr "Se encontraron varios tipos de modelo: %{model_types}"
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Nuevo archivo"
msgid "New group"
msgstr "Nuevo grupo"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr "¡Se ha generado un nuevo token de acceso para la verificación de estado!"
@@ -18557,7 +19021,7 @@ msgstr "No se han encontrado ramas"
msgid "No changes"
msgstr "Sin cambios"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr "No está disponible para proyectos privados"
msgid "Not available for protected branches"
msgstr "No está disponible para ramas protegidas"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "No es confidencial"
@@ -18821,6 +19288,9 @@ msgstr "No está listo todavía. Por favor, inténtalo de nuevo más tarde."
msgid "Not started"
msgstr "No iniciado"
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr "Nota"
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr "¡Oh, no!"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "Más antiguo primero"
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr "La receta del paquete ya existe"
msgid "Package type must be Conan"
msgstr "El tipo de paquete debe ser Conan"
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "El tipo de paquete debe ser Maven"
@@ -19438,10 +20013,7 @@ msgstr "El tipo de paquete debe ser NuGet"
msgid "Package type must be PyPi"
msgstr "El tipo de paquete debe ser PyPi"
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr "Copiar comando yarn"
msgid "PackageRegistry|Copy yarn setup command"
msgstr "Copiar comando de configuración de yarn"
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr "Eliminar la versión del paquete"
@@ -19585,12 +20160,18 @@ msgstr "Comando NuGet"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
-msgstr "Comando Pip"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
+msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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 "Comando Pip"
+
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr ""
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Páginas"
@@ -19843,11 +20418,14 @@ msgstr "Las rutas pueden contener comodines, como por ejemplo */welcome"
msgid "Pause"
msgstr "Pausar"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr "Pausar replicación"
-msgid "Paused Runners don't accept new jobs"
-msgstr "Los runers pausados no aceptan nuevos trabajos"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "Pendiente"
@@ -19915,6 +20493,9 @@ msgstr "Permisos, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Token de acceso personal"
+msgid "Personal Access Token prefix"
+msgstr ""
+
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr "No se permite la creación de proyectos personales. Por favor, póngase en contacto con su administrador con preguntas"
@@ -19951,6 +20532,9 @@ msgstr "Programaciones de los Pipelines"
msgid "Pipeline minutes quota"
msgstr "Cuota de minutos del pipeline"
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ msgstr "Disparadores de los triggers"
msgid "Pipeline: %{status}"
msgstr "Pipeline: %{status}"
+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 ""
@@ -19978,7 +20571,7 @@ msgstr "Ratio de éxito"
msgid "PipelineCharts|Successful:"
msgstr "Exitosos:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ msgstr ""
msgid "Pipelines|Editor"
msgstr ""
+msgid "Pipelines|Get started with CI/CD"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Comenzar a utilizar los pipelines"
+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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "Cargar pipelines"
@@ -20149,6 +20751,18 @@ msgstr "Actualmente no hay pipelines."
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."
+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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 "Por favor, cree una nueva contraseña para su cuenta."
@@ -20401,6 +21021,9 @@ msgstr "Por favor, introduzca un número mayor que %{number} (desde la configura
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 "Por favor, introduzca un número válido"
@@ -20611,14 +21234,17 @@ msgstr "Presione %{key}-C para copiar"
msgid "Prev"
msgstr "Previo"
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Impedir que se añadan nuevos miembros al proyecto dentro de este grupo"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
-msgstr "Impedir la aprobación de merge request por el autor del merge request"
+msgid "Prevent MR approvals by the author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
-msgstr "Impedir la aprobación de merge request por colaboradores del merge request"
+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 "Impedir que se añadan nuevos miembros al proyecto dentro de este grupo"
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr "Principal"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "Priorizar"
@@ -20797,6 +21426,9 @@ msgstr ""
msgid "Profiles|@username"
msgstr "@nombredeusuario"
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Cuenta programada para su eliminación."
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr "Nombre completo"
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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"
@@ -21229,9 +21867,6 @@ msgstr "Nombre del proyecto"
msgid "Project name suffix"
msgstr "Sufijo del nombre del proyecto"
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-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."
@@ -21388,12 +22023,18 @@ msgstr "Todas las discusiones deben ser resueltas"
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 "Permitir a los usuarios solicitar acceso"
+msgid "ProjectSettings|Analytics"
+msgstr ""
+
msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
msgstr ""
@@ -21421,8 +22062,8 @@ msgstr "Póngase en contacto con el administrador para cambiar esta configuraciÃ
msgid "ProjectSettings|Container registry"
msgstr "Registro de contenedores"
-msgid "ProjectSettings|Customize your project badges."
-msgstr "Personalice las insignias de su proyecto."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr "Desactivar notificaciones por correo electrónico"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "Todo merge crea un merge commit"
@@ -21490,9 +22134,6 @@ msgstr "Incidencias"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "Más información sobre insignias."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr "Nota: el registro de contenedores siempre es visible cuando el proyecto
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Solo se pueden enviar commits firmados a este repositorio."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "Paquetes"
@@ -21637,12 +22281,21 @@ msgstr "Ver y editar archivos en este proyecto"
msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
msgstr ""
+msgid "ProjectSettings|View project analytics"
+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 "Cuando surgen conflictos, al usuario se le da la opción de realizar un rebase"
+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 ""
@@ -21661,9 +22314,6 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21718,7 +22371,7 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,8 +22812,8 @@ msgstr ""
msgid "Protected branches"
msgstr "Ramas protegidas"
-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 "Se admiten%{wildcards_link_start}comodines%{wildcards_link_end} como por ejemplo %{code_tag_start}*-estable%{code_tag_end} o %{code_tag_start}producción/*%{code_tag_end}"
+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 "Permitido merge"
@@ -22192,7 +22845,7 @@ msgstr "Proteger una rama"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr "Ramas protegidas (%{protected_branches_count})"
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ msgstr "Rebase"
msgid "Rebase in progress"
msgstr "Rebase en progreso"
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "Recibe alertas desde los servidores de Prometheus configurados manualmente."
@@ -22477,6 +23136,9 @@ msgstr "Actividad reciente del proyecto"
msgid "Recent Searches Service is unavailable"
msgstr "El servicio de búsquedas recientes no está disponible"
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "Búsquedas recientes"
@@ -22581,7 +23243,10 @@ msgstr "Su perfil"
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr "Eliminar ejecutor"
msgid "Remove Zoom meeting"
msgstr "Eliminar la reunión de Zoom"
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-msgstr "Elimine todas las aprobaciones en un merge request cuando se realicen nuevos commits a la rama de origen"
-
msgid "Remove all or specific assignee(s)"
msgstr "Eliminar todos los asignados o los asignados específicos"
msgid "Remove all or specific label(s)"
msgstr "Eliminar todas las etiquetas o las etiquetas específicas"
+msgid "Remove all or specific reviewer(s)"
+msgstr ""
+
msgid "Remove approver"
msgstr ""
@@ -22790,6 +23455,9 @@ msgstr "Eliminar prioridad"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Eliminar nodo secundario"
@@ -22826,6 +23494,9 @@ msgstr "Eliminada %{label_references} %{label_text}."
msgid "Removed %{milestone_reference} milestone."
msgstr "Eliminado %{milestone_reference} hitos."
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "Eliminado %{type} con id %{id}"
@@ -22871,6 +23542,9 @@ msgstr "Eliminar %{label_references} %{label_text}."
msgid "Removes %{milestone_reference} milestone."
msgstr "Elimina el %{milestone_reference} hito."
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr "Elimina todas las etiquetas."
@@ -22901,6 +23575,9 @@ msgstr "Renombrar carpeta"
msgid "Rename/Move"
msgstr "Renombrar/Mover"
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr "Volver a abrir"
@@ -23105,6 +23782,9 @@ 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 "Última actualización"
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Repositorio"
@@ -23204,9 +23881,6 @@ msgstr "Seleccionar"
msgid "Request Access"
msgstr "Solicitar acceso"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,8 +23923,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Requerir a todos los usuarios que acepten los términos del servicio y la política de privacidad cuando accedan a GitLab."
-msgid "Require user password to approve"
-msgstr "Requiere una contraseña de usuario para aprobar"
+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 "Requerir a los usuarios desmostrar la propiedad de los dominios personalizados"
@@ -23276,9 +23953,6 @@ msgstr "Se ha reabierto el requisito %{reference}"
msgid "Requirement %{reference} has been updated"
msgstr "Se ha actualizado el requisito %{reference}"
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "El título del requisito no puede tener más de %{limit} caracteres."
@@ -23385,12 +24059,6 @@ msgstr "Resuelve las direcciones IP una vez y las utiliza para enviar peticiones
msgid "Response"
msgstr "Respuesta"
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr "La respuesta no contiene `service_desk_address`"
@@ -23412,6 +24080,9 @@ msgstr "Métricas de respuesta (NGINX)"
msgid "Response metrics (NGINX)"
msgstr "Respuesta métricas (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "Reiniciar el terminal"
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr "Ver la última aplicación"
msgid "Review requested from %{name}"
msgstr "Revisión solicitada por %{name}"
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,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 cannot be assigned to other projects"
-msgstr "No se puede asignar el ejecutor a otros proyectos"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "El ejecutor ejecuta los trabajos de todos los proyectos desasignados"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "El ejecutor ejecuta los trabajos de todos los proyectos desasignados"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "El ejecutor ejecuta los trabajos de todos los proyectos asignados"
-
msgid "Runner token"
msgstr "Token del ejecutor"
@@ -23614,9 +24279,6 @@ msgstr "No se actualizó el ejecutor."
msgid "Runner was successfully updated."
msgstr "El ejecutor se ha actualizado correctamente."
-msgid "Runner will not receive any new jobs"
-msgstr "El ejecutor no recibirá ningún trabajo nuevo"
-
msgid "Runners"
msgstr "Runners"
@@ -23626,14 +24288,17 @@ 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 placed on separate users, servers, even on your local machine."
-msgstr "Los ejecutores se pueden colocar como usuarios separados, en servidores o incluso en su máquina local."
+msgid "Runners can be:"
+msgstr ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "Ejecutores actualmente en línea: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ msgstr "Ejecutando…"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Ejecuta una serie de tareas de mantenimiento dentro del repositorio actual, como comprimir las revisiones de los archivos y eliminar objetos no disponibles."
+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 ""
@@ -23761,9 +24435,6 @@ msgstr "Clave pública SSH"
msgid "SSL Verification:"
msgstr "Verificación SSL:"
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr "Programado"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,8 +24516,8 @@ msgstr "Programación de Pipelines"
msgid "Scope"
msgstr "Alcance"
-msgid "Scoped issue boards"
-msgstr "Tableros de incidencias con alcance limitado"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr "Alcances"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr "Requisitos de búsqueda"
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Buscar usuarios"
@@ -23995,6 +24669,9 @@ msgstr "Merge requests creados por mí"
msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "Merge requests asignados a mí"
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
msgid "SearchAutocomplete|in all GitLab"
msgstr "en todo GitLab"
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ msgstr "Descartada '%{vulnerabilityName}'"
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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ msgstr "No se puede añadir %{invalidProjects}"
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 ""
@@ -24691,9 +25383,6 @@ msgstr "Separar temas con comas."
msgid "September"
msgstr "Septiembre"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr "y"
@@ -24793,6 +25482,9 @@ msgstr "Servicio"
msgid "Service Desk"
msgstr "Service Desk"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr ""
@@ -24823,11 +25515,8 @@ 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 template for issue descriptions."
-msgstr "Establecer una plantilla predeterminada para las descripciones de las incidencias."
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
-msgstr "Establezca el número de aprobaciones requeridas, los aprobadores y otras opciones de configuración de las aprobaciones."
+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 "Establezca una contraseña en su cuenta para hacer pull o push vía %{protocol}."
@@ -25024,9 +25713,6 @@ msgstr "Configuración"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr "Mostrar toda la actividad"
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr "Mostrar todos los miembros"
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr "Mostrar el explorador de archivos"
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Mostrar la última versión"
@@ -25457,6 +26149,9 @@ msgstr "Alguien editó este %{issueType} al mismo tiempo que usted. La descripci
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "Alguien editó este merge request al mismo tiempo que lo hizo usted. Por favor, actualice la página para ver los cambios."
+msgid "Something went wrong"
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "Algo salió mal por nuestra parte"
@@ -25493,7 +26188,10 @@ msgstr "Se ha producido un error al aplicar la sugerencia. Por favor, inténtelo
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ msgstr "Se ha producido un error al editar su comentario. Por favor, inténtalo
msgid "Something went wrong while fetching %{listType} list"
msgstr "Algo salió mal al obtener la lista de %{listType}. ¡Por favor, inténtelo de nuevo!"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Algo salió mal al buscar comentarios. Inténtalo de nuevo. ¡Por favor, inténtelo de nuevo!"
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr "Se ha producido un error al obtener los proyectos"
msgid "Something went wrong, unable to search projects"
msgstr "Se ha producido un error al buscar los proyectos"
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,15 +26740,18 @@ 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 "State your message to activate"
msgstr "Indique su mensaje para activar"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 "Volver al sitio web"
@@ -26318,6 +27031,9 @@ msgstr "Suscripción creada correctamente."
msgid "Subscription successfully deleted."
msgstr "Suscripción eliminada correctamente."
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "Sistema"
@@ -26820,9 +27542,24 @@ msgstr "Se ha producido un error al generar un informe de Terraform."
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr "Se ha generado un informe de Terraform en sus pipelines."
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ msgstr "La generación del informe provocó un error."
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 ""
@@ -26850,9 +27605,21 @@ 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|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 "Probar"
@@ -26999,8 +27766,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr "¡Gracias por su compra!"
-msgid "Thanks! Don't show me this again"
-msgstr "¡Gracias! No mostrar esto de nuevo"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27014,6 +27781,9 @@ 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] "El %{type} contiene el siguiente error:"
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ msgstr ""
msgid "The current issue"
msgstr "La incidencia actual"
+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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ 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 allowed is 200KB."
-msgstr "El tamaño máximo de archivo permitido es de 200KB."
-
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."
@@ -27504,6 +28274,9 @@ msgstr "Aún no hay proyectos compartidos con este grupo"
msgid "There are no variables yet."
msgstr "Todavía no hay variables."
+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 ""
@@ -27600,6 +28373,9 @@ msgstr "Se ha producido un error al recuperar los datos de la etiqueta para el g
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 "Se ha producido un error al obtener el %{replicableType}"
@@ -27678,6 +28454,9 @@ msgstr "Se ha producido un error al intentar validar su consulta"
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 ""
@@ -27759,6 +28538,9 @@ msgstr "Esta instancia de GitLab aún no proporciona ningún 'runner' compartido
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 ""
@@ -28056,6 +28838,9 @@ msgstr "Esto significa que no puede enviar código hasta que cree un repositorio
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 ""
@@ -28140,6 +28925,15 @@ 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 "Este ejecutor solo se ejecutará en pipelines disparados sobre ramas protegidas"
@@ -28155,9 +28949,6 @@ msgstr "Esta suscripción es para"
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr "Este tiempo de espera tendrá prioridad cuando sea más bajo que el tiempo de espera definido por el proyecto y acepte un lenguaje de entrada de tiempo legible como por ejemplo, \"1 hora\". Los valores sin especificación de tipo representan segundos."
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr "Este usuario no puede ser desbloqueado manualmente desde GitLab"
@@ -28230,12 +29021,33 @@ 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 "Entorno"
+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 "No se han detectado entornos"
@@ -28251,6 +29063,9 @@ msgstr "Políticas"
msgid "ThreatMonitoring|Requests"
msgstr "Peticiones"
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr "Mostrar último"
@@ -28263,12 +29078,21 @@ 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 "Threat Monitoring"
@@ -28278,7 +29102,7 @@ msgstr "Enlace de la página de ayuda de Threat Monitoring"
msgid "ThreatMonitoring|Time"
msgstr "Tiempo"
-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."
+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"
@@ -28287,6 +29111,9 @@ msgstr "Total de paquetes"
msgid "ThreatMonitoring|Total Requests"
msgstr "Total de peticiones"
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr "Ver documentación"
@@ -28894,12 +29721,20 @@ msgstr "Vista de árbol"
msgid "Trending"
msgstr "Tendencia"
+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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "Volver a GitLab"
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr "Saltar periodo de prueba (Continuar con cuenta gratuita)"
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 "Disparador"
@@ -29308,6 +30176,9 @@ msgstr "No programado"
msgid "Unstar"
msgstr "No Destacar"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "Eliminar suscripción"
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr "Hasta"
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,8 +30260,8 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "Actualice el nombre de su grupo, su descripción, su avatar y su visibilidad."
-msgid "Update your project name, topics, description and avatar."
-msgstr "Actualice el nombre de su proyecto, los temas, la descripción y el avatar."
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr "¡No se puede cambiar el nombre del proyecto porque el registro de contenedores contiene etiquetas!"
@@ -29404,7 +30275,7 @@ msgstr "¡Nuevo nivel de visibilidad no permitido!"
msgid "UpdateProject|Project could not be updated!"
msgstr "¡No ha sido posible actualizar el proyecto!"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr "Actualice su plan para activar la herramienta Group Webhooks."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "Actualice su plan para mejorar los tableros de incidencias."
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr "Actualice su plan para mejorar los merge requests."
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr "Usuarios añadidos con éxito."
@@ -30398,6 +31269,9 @@ msgstr "%{scannerName} (versión %{scannerVersion})"
msgid "Vulnerability|Activity"
msgstr ""
+msgid "Vulnerability|Actual Response"
+msgstr ""
+
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
@@ -30425,6 +31299,9 @@ msgstr "Descripción"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "Evidencia"
@@ -30452,6 +31329,12 @@ msgstr "Espacio de nombres"
msgid "Vulnerability|Project"
msgstr "Proyecto"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ msgstr "Estado"
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 "Espera a que el archivo se cargue para copiar su contenido"
@@ -30482,6 +31368,9 @@ msgstr "Esperar por los datos de rendimiento"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "¿Quieres ver los datos? Por favor pide acceso al administrador."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr "Advertencia:"
@@ -30515,6 +31404,9 @@ msgstr ""
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "No ha sido posible conectar al servidor de Prometheus. O el servidor ya no existe o debe actualizar los detalles de configuración."
+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 "Hemos detectado spam potencial en %{humanized_resource_name}. Por favor resuelva el reCAPTCHA para poder continuar."
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,8 +31673,8 @@ msgstr "Cuando:"
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 be an approver?"
-msgstr "¿Quién puede ser un aprobador?"
+msgid "Who can approve?"
+msgstr ""
msgid "Who can see this group?"
msgstr "¿Quién puede ver este grupo?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 "Puede resolver el conflicto del merge request utilizando el modo Interactivo, utilizando los botones %{use_ours} o %{use_theirs}, o editando los archivos directamente. Confirme estos cambios en %{branch_name}"
@@ -31252,9 +32156,6 @@ 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 "Puede configurar trabajos para usar solo ejecutores con etiquetas específicas. Por favor, separe las etiquetas con comas."
-
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."
@@ -31276,6 +32177,9 @@ msgstr "No puede suplantar a un usuario que no puede iniciar sesión"
msgid "You cannot impersonate an internal user"
msgstr "No puede suplantar a un usuario interno"
+msgid "You cannot make this a shared runner."
+msgstr ""
+
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
msgstr "No puede ejecutar este pipeline programado en este momento. Por favor, espere un minuto."
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "No tiene los permisos necesarios para sobreescribir la configuración de la sincronización de grupos de LDAP."
-
msgid "You don't have any U2F devices registered yet."
msgstr "No tiene ningún dispositivo U2F registrado."
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Debe tener permiso como mantenedor para forzar la eliminación de un bloqueo"
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr "Su dispositivo U2F no envió una respuesta JSON válida."
msgid "Your U2F device was registered!"
msgstr "¡Se ha registrado su dispositivo U2F!"
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ msgstr ""
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr "¡El dispositivo se ha configurado correctamente!. Por favor, asígnele un nombre y regístrelo con el servidor de GitLab."
+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 "Su primer proyecto"
@@ -31756,6 +32675,9 @@ msgstr "Se están importando sus incidencias. Al finalizar el proceso, recibirá
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr "Sus incidencias serán importados como tarea de fondo. Al finalizar el proceso, recibirá un correo electrónico de confirmación."
+msgid "Your license does not support on-call rotations"
+msgstr ""
+
msgid "Your license does not support on-call schedules"
msgstr ""
@@ -31813,6 +32735,9 @@ 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 "Su respuesta ha sido registrada."
@@ -31911,6 +32836,9 @@ msgstr "cómo %{role}."
msgid "assign yourself"
msgstr "asignar a ti mismo"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr "en riesgo"
@@ -31929,9 +32857,15 @@ msgstr "nombre de la rama"
msgid "by"
msgstr "por"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 "no se puede modificar si un proyecto personal ya contiene etiquetas de registro de contenedor."
@@ -31974,6 +32908,9 @@ 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 "%{linkStartTag}Aprenda más sobre el analísis de contenedores %{linkEndTag}"
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Todos los proyectos"
@@ -32169,6 +33109,9 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Se ha producido un error al descartar la vulnerabilidad. Por favor, inténtalo de nuevo."
+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] "Utilizado por %{packagesString}"
@@ -32371,6 +33314,12 @@ msgstr "ya ha sido vinculado a otra vulnerabilidad"
msgid "has already been taken"
msgstr "ya está en uso"
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
msgid "has been completed."
msgstr ""
@@ -32553,6 +33502,9 @@ 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] "merge request"
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "nombre de la etiqueta"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 86be48e5144..0d7ec929c2f 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: 2020-12-03 08:10\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 8c311bf6a8e..024018e5e51 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: 2020-12-03 08:09\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 7353b0fbce3..a3c2ce82996 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: 2020-12-03 08:16\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index b729f8dcd42..aef913b4214 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: 2020-12-03 08:11\n"
+"PO-Revision-Date: 2021-01-08 22:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index ef1c591a30d..9e05d1cf3b4 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: 2020-12-03 08:14\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} commit"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} commits"
+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 "%{strong_start}%{human_size}%{strong_end} fichiers"
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,29 +1205,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "Un « exécuteur » est un processus qui exécute une tâche. Vous pouvez configurer autant d’exécuteurs que nécessaire."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Un modèle d’application de console .NET Core, personnalisable pour tout projet .NET Core"
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 "Un site GitBook qui utilise Netlify comme intégration et livraison continues (CI/CD) au lieu de GitLab, mais en gardant toutes les autres fonctionnalités géniales de GitLab."
+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 "Un site Hexo qui utilise Netlify comme intégration et livraison continues (CI/CD) au lieu de GitLab, mais en gardant toutes les autres fonctionnalités géniales de GitLab."
+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 "Un site Hugo qui utilise Netlify comme intégration et livraison continues (CI/CD) au lieu de GitLab, mais en gardant toutes les autres fonctionnalités géniales de GitLab."
+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 "Un site Jekyll qui utilise Netlify comme intégration et livraison continues (CI/CD) au lieu de GitLab, mais en gardant toutes les autres fonctionnalités géniales de GitLab."
+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 ""
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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 "Un site HTML simple qui utilise Netlify comme intégration et livraison continues (CI/CD) au lieu de GitLab, mais en gardant toutes les autres fonctionnalités géniales de GitLab."
+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."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Un modèle prêt à l’emploi à utiliser pour les applications Android."
+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 "Un modèle prêt à l’emploi à utiliser pour les applications iOS en Swift."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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 ""
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 "Une personne avec un accès en écriture à la branche source a sélectionné cette option"
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Accès refusé ! Veuillez vérifier que vous pouvez ajouter des clefs de déploiement à ce dépôt."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Date d’expiration de l’accès"
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr "Toutes les modifications sont validées"
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Une erreur est survenue"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Une erreur s’est produite lors de l’activation ou la désactivation
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 "Une erreur est survenue lors de la mise à jour du poids du ticket"
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Une erreur est survenue lors de l’enregistrement du statut d’outrepassement de l’annuaire LDAP. Veuillez réessayer."
-
msgid "An error occurred while saving assignees"
msgstr "Une erreur s’est produite lors de l’enregistrement des destinataires"
@@ -3267,6 +3312,9 @@ msgstr "Une erreur est survenue lors du désabonnement aux notifications."
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3276,6 +3324,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Une erreur est survenue lors de la mise à jour du commentaire"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,7 +3345,7 @@ msgstr "Une erreur est survenue. Merci de réessayer."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr "Attribuer des étiquettes"
msgid "Assign milestone"
msgstr "Attribuer un jalon"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ msgstr ""
msgid "Assigned %{assignee_users_sentence}."
msgstr ""
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Tickets assignés"
msgid "Assigned Merge Requests"
msgstr "Demandes de fusion assignées"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Assigné à moi"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 "Au moins une approbation d’un propriétaire de code est requise pour modifier les fichiers correspondant aux règles de propriété du code (CODEOWNER)."
@@ -3938,9 +4010,6 @@ msgstr "Événements d’audit"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,12 +4166,12 @@ msgstr "Annuler automatiquement les pipelines redondants en attente"
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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr ""
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "documentation Auto DevOps"
@@ -4121,10 +4190,13 @@ msgstr "Apprenezâ€en davantage en consultant la %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Couleur d’arrièreâ€plan"
msgid "Badges"
msgstr "Badges numériques"
-msgid "Badges|A new badge was added."
-msgstr "Un nouveau badge a été ajouté."
-
msgid "Badges|Add badge"
msgstr "Ajouter un badge"
@@ -4244,12 +4313,21 @@ msgstr "URL de l’image du badge"
msgid "Badges|Badge image preview"
msgstr "Aperçu de l’image du badge"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "Supprimer le badge ?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "La suppression du badge a échoué, veuillez réessayer."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Badge de groupe"
@@ -4259,15 +4337,15 @@ msgstr "Lien"
msgid "Badges|Name"
msgstr ""
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "Pas d’image de badge"
msgid "Badges|No image to preview"
msgstr "Aucune image à prévisualiser"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Veuillez saisir une URL valide"
-
msgid "Badges|Project Badge"
msgstr "Badge de projet"
@@ -4280,15 +4358,12 @@ msgstr "Enregistrer les modifications"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "L’enregistrement du badge a échoué. Veuillez vérifier les URL entrées et réessayer."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "Les %{docsLinkStart}variables%{docsLinkEnd} que GitLab prend en charge : %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Le badge a été supprimé."
-msgid "Badges|The badge was saved."
-msgstr "Le badge a été enregistré."
-
msgid "Badges|This group has no badges"
msgstr "Ce groupe n’a pas de badge"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Vos badges numériques"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "p. ex. %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr "Nom de la branche"
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Rechercher les branches"
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr "Intégration et livraison continues pour dépôt externe"
msgid "CI/CD settings"
msgstr "Paramètres de l’intégration et de la livraison continues"
-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."
+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"
@@ -4846,12 +4972,12 @@ msgstr "Stratégie de déploiement"
msgid "CICD|Jobs"
msgstr "Tâches"
+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 "Le pipeline Auto DevOps sera exécuté si aucun autre fichier de configuration n’est trouvé."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr ""
@@ -4879,9 +5005,6 @@ msgstr "URL de retour"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Annuler"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Ne peut être fusionnée automatiquement"
@@ -5083,15 +5233,33 @@ msgstr "Picorer dans la branche"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Défaire dans la branche"
+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 "Picorer"
msgid "ChangeTypeAction|Revert"
msgstr "Défaire"
+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 "Cela va créer un nouveau commit afin de défaire les modifications existantes."
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Choisir un modèle…"
msgid "Choose a type..."
msgstr "Choisir un type…"
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr "Cloner le dépôt"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 "Fermer"
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Connecter"
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr "Créer une branche"
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr "Créer une nouvelle branche"
@@ -8033,6 +8246,84 @@ msgstr "Étiquette"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Créer un jeton d’accès personnel"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Créé"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Branche actuelle"
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "Par défaut : associer un identifiant de compte FogBugz à un nom complet"
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Définir un schéma personnalisé avec une syntaxe Cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr "Supprimer le commentaire"
@@ -9355,9 +9628,6 @@ msgstr "Décroissant"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "Description"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,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 and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr "Chaque exécuteur peut être dans l’un des états suivants :"
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr "Modifier l’application"
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr "Courriels"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ msgstr ""
msgid "Enable and configure Prometheus metrics."
msgstr "Activer et configurer les métriques Prometheus."
+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 "Activer le contrôle de classification à l’aide d’un service externe"
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr "Activer la collecte des données d’utilisation"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Se termine à (UTC)"
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ msgstr "Entrez l’intitulé de la demande de fusion"
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 ""
@@ -10626,6 +10971,9 @@ msgstr "Déployer vers…"
msgid "Environments|Deployment"
msgstr "Déploiement"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 "Mis à jour"
@@ -10803,9 +11157,6 @@ msgstr "Comment puisâ€je résoudre ceci ?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "En savoir plus"
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr "Erreur lors de la récupération du graphique du réseau."
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr "Erreur lors de la récupération des refs"
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ msgstr "Tout le monde peut contribuer"
msgid "Everything on your to-do list is marked as done."
msgstr ""
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ msgstr "Échec du changement de propriétaire"
msgid "Failed to check related branches."
msgstr "Échec de la vérification des branches liées."
+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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr "Échec du déploiement sur"
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Filtrer"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement fermés."
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Rechercher par chemin d’accès"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "Rechercher un fichier"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr "Terminé"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ msgstr "Obtenez une revue d’instance gratuite"
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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr "Retour"
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr "Avatar de groupe"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "Description du groupe"
-
msgid "Group description (optional)"
msgstr "Description du groupe (optionnel)"
@@ -13562,11 +13916,17 @@ 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 your group badges."
-msgstr "Personnalisez vos badges numériques de groupe."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "En savoir plus sur les badges numériques."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ msgstr "Aucun groupe trouvé"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accéder à chacun de ses projets."
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr "Maintenance démarrée avec succès"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "Importation en cours"
@@ -14269,6 +14668,9 @@ msgstr "Importer des dépôts à partir de GitHub"
msgid "Import repository"
msgstr "Importer un dépôt"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "Améliorez le tableau des tickets avec Gitlab Entreprise Edition."
+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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr "Inviter"
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Événements du ticket"
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Apprenezâ€en plus dans la"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "documentation sur la programmation de pipelines"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Quitter"
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr "Niveau d’accès maximum"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Approbations de la demande de fusion"
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Demandes de fusion"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Les demandes de fusion permettent de proposer les modifications que vous avez apportées à un projet et de discuter de ces modifications avec les autres"
@@ -17200,9 +17652,15 @@ 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 ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr "Utilisateur accédant au miroir"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "Dépôts mis en miroir"
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "Tableaux de tickets multiples"
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Nouveau fichier"
msgid "New group"
msgstr "Nouveau groupe"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr "Aucune branche trouvée"
msgid "No changes"
msgstr "Aucun changement"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr "Non disponible pour les projets privés"
msgid "Not available for protected branches"
msgstr "Non disponible pour les branches protégées"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Pas confidentiel·le"
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Pages"
@@ -19843,11 +20418,14 @@ msgstr ""
msgid "Pause"
msgstr "Pause"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
-msgstr "Les exécuteurs en pause n’acceptent pas de nouvelles tâches"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "En attente"
@@ -19915,6 +20493,9 @@ msgstr "Autorisations, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Jeton d’accès personnel"
+msgid "Personal Access Token prefix"
+msgstr ""
+
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
@@ -19951,6 +20532,9 @@ msgstr "Planifications de pipelines"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ msgstr "Déclencheurs de pipeline"
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 ""
@@ -19978,7 +20571,7 @@ msgstr "Taux de réussite :"
msgid "PipelineCharts|Successful:"
msgstr "Réussites :"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ msgstr ""
msgid "Pipelines|Editor"
msgstr ""
+msgid "Pipelines|Get started with CI/CD"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Premiers pas avec les pipelines"
+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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "Chargement des pipelines"
@@ -20149,6 +20751,18 @@ msgstr "Il n’y a actuellement aucun pipeline."
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."
+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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,15 +21234,18 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Empêcher l’ajout de nouveaux membres au projet au sein de ce groupe"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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 "Empêcher l’ajout de nouveaux membres au projet au sein de ce groupe"
+
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr "Principal"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "Prioriser"
@@ -20797,6 +21426,9 @@ 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 "Compte programmé pour suppression."
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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"
@@ -21229,9 +21867,6 @@ msgstr "Nom du projet"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,8 +22062,8 @@ msgstr "Contactez un administrateur pour modifier ce paramètre."
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
-msgstr "Personnalisez les badges numériques de votre projet."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr ""
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "En savoir plus sur les badges numériques."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Seuls les commits signés peuvent être poussés sur ce dépôt Git."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "Recherches récentes"
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr "Supprimer l’exécuteur"
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr "Supprimer la priorité"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr "Renommer le dossier"
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Dépôt"
@@ -23204,9 +23881,6 @@ msgstr "Sélectionner"
msgid "Request Access"
msgstr "Demander l’accès"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Exiger que tous les utilisateurs acceptent les conditions générales d’utilisation et la politique de confidentialité quand ils accèdent à GitLab."
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr "Métriques de réponse (nginx Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Métriques de réponse (nginx)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Exécuter les tâches non étiquetées"
-msgid "Runner cannot be assigned to other projects"
-msgstr "L’exécuteur ne peut être affecté à d’autres projets"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "L’exécuteur exécute des tâches de tous les projets non attribués"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "L’exécuteur exécute des tâches de tous les projets non attribués de son groupe"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "L’exécuteur exécute des tâches de projets attribués"
-
msgid "Runner token"
msgstr "Jeton de l’exécuteur"
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr "L’exécuteur ne recevra aucune nouvelle tâche"
-
msgid "Runners"
msgstr "Exécuteurs"
@@ -23626,14 +24288,17 @@ 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 placed on separate users, servers, even on your local machine."
-msgstr "Les exécuteurs peuvent fonctionner sur différents serveurs, avec différents comptes d’utilisateur, y compris sur votre machine locale."
+msgid "Runners can be:"
+msgstr ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "Exécuteurs actuellement en ligne : %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr "Clef SSH publique"
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr "Planifié"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,8 +24516,8 @@ msgstr "Planification des pipelines"
msgid "Scope"
msgstr "Portée"
-msgid "Scoped issue boards"
-msgstr "Tableaux de tickets à portée limitée"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr ""
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Rechercher des utilisateurs et utilisatrices"
@@ -23995,6 +24669,9 @@ msgstr "Demandes de fusion que j’ai créées"
msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "Demandes de fusion qui me sont assignées"
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
msgid "SearchAutocomplete|in all GitLab"
msgstr "Dans tout GitLab"
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr "septembre"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ msgstr ""
msgid "Service Desk"
msgstr "Service d’assistance"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr "Paramètres"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Afficher la dernière version"
@@ -25457,6 +26149,9 @@ 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 "Une erreur est survenue de notre côté"
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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}"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Une erreur est survenue lors de la récupération des commentaires. Veuillez réessayer."
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,15 +26740,18 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Démarre à (UTC)"
+msgid "Starts on"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Énoncez votre message à activer"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,8 +27766,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
-msgstr "Merci ! Ne plus afficher ce message"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr "La taille maximale autorisée pour un fichier est de 200 Kio."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ msgstr "Il n’y a pas encore de projets partagés avec ce groupe"
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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ msgstr "Cette instance de GitLab ne fournit aucun exécuteur partagé pour le mo
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 ""
@@ -28056,6 +28838,9 @@ msgstr "Cela signifie que vous ne pouvez pas pousser du code tant que vous n’a
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 ""
@@ -28140,6 +28925,15 @@ 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 "Cet exécuteur ne fonctionnera que sur les pipelines déclenchés sur des branches protégées"
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ msgstr "Vue arborescente"
msgid "Trending"
msgstr "Tendance"
+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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr "Déprogrammer la tâche"
msgid "Unstar"
msgstr "Supprimer des favoris"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "Se désabonner"
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "Modifiez le nom du groupe, sa description, son avatar et sa visibilité."
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr "Mettez à niveau votre forfait pour activer les webhooks de groupe."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "Mettez à niveau votre forfait pour améliorer les tableaux de tickets."
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr "Description"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projet"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 "Nous avons détecté un potentiel courriel indésirable dans %{humanized_resource_name}. Veuillez résoudre le reCAPTCHA pour continuer."
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif, en cliquant sur les boutons « %{use_ours} » ou « %{use_theirs} », soit en modifiant directement les fichiers. Valider ces modifications dans la branche « %{branch_name} »"
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
msgstr ""
-msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr "Vous pouvez configurer des tâches pour n’utiliser des exécuteurs qu’avec des étiquettes spécifiques. Séparez les étiquettes par des virgules."
-
msgid "You can specify notification level per group or per project."
msgstr ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "Vous ne disposez pas des autorisations appropriées pour outrepasser les paramètres de synchronisation du groupe LDAP."
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Seul un responsable peut forcer la suppression d’un verrou"
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr "nom de la branche"
msgid "by"
msgstr "par"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 "%{linkStartTag}En savoir plus à propos de l’analyse des conteneurs %{linkEndTag}"
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Une erreur s’est produite lors de l’annulation du rejet. Veuillez réessayer."
+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] "Utilisé par %{packagesString}"
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] "demande de fusion"
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 7d1a5301247..e47bbec804f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -724,6 +724,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 +915,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 +1039,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"
@@ -1205,9 +1211,6 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr ""
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr ""
@@ -1238,6 +1241,9 @@ 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 ""
@@ -1265,6 +1271,15 @@ 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 ""
@@ -1298,6 +1313,9 @@ 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 ""
@@ -1316,6 +1334,9 @@ msgstr ""
msgid "A ready-to-go template for use with iOS Swift apps"
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 ""
@@ -1325,7 +1346,10 @@ msgstr ""
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
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 string appended to the project path to form the Service Desk email address."
+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"
@@ -1609,6 +1633,9 @@ 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 ""
@@ -2197,6 +2224,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2484,9 +2514,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2550,15 +2577,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2586,9 +2607,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2658,9 +2676,6 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
-msgstr ""
-
msgid "AlertSettings|Proceed with editing"
msgstr ""
@@ -2730,12 +2745,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2754,7 +2763,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"
@@ -2820,9 +2829,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2949,6 +2955,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3000,6 +3009,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 ""
@@ -3024,7 +3036,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3060,6 +3072,9 @@ 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 ""
@@ -3297,9 +3312,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3369,6 +3381,9 @@ 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 ""
@@ -3411,6 +3426,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3525,12 +3543,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3784,15 +3796,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 ""
@@ -3862,7 +3877,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"
@@ -3895,6 +3910,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3913,12 +3934,18 @@ 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 ""
@@ -3931,6 +3958,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3954,6 +3984,9 @@ 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 ""
@@ -4121,9 +4154,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 ""
@@ -4154,10 +4184,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4178,10 +4208,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4244,16 +4277,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"
@@ -4286,9 +4319,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4301,12 +4331,21 @@ 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 ""
@@ -4316,13 +4355,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4337,15 +4376,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4358,9 +4394,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4469,22 +4502,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4525,6 +4564,18 @@ 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 ""
@@ -4537,6 +4588,9 @@ 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 ""
@@ -4858,6 +4912,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 ""
@@ -4867,6 +4924,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 ""
@@ -4909,7 +4969,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4936,10 +4999,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5008,9 +5071,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 ""
@@ -5062,6 +5122,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5158,6 +5221,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5194,18 +5263,39 @@ 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|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 ""
@@ -5224,13 +5314,16 @@ 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 were successfully made."
+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}."
@@ -5305,6 +5398,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 ""
@@ -5746,7 +5842,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."
@@ -6910,6 +7006,9 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr ""
@@ -7329,6 +7428,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7371,9 +7473,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7432,15 +7531,42 @@ 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 ""
@@ -7596,10 +7722,10 @@ 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}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7803,6 +7929,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8153,6 +8282,90 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+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|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 "Created"
msgstr ""
@@ -8258,6 +8471,9 @@ msgstr ""
msgid "Current Project"
msgstr ""
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr ""
@@ -8333,45 +8549,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8617,6 +8806,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8632,6 +8824,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 ""
@@ -8644,6 +8842,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 ""
@@ -8656,6 +8857,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8671,6 +8875,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8686,13 +8893,16 @@ 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 Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8704,9 +8914,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8746,6 +8953,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8755,6 +8968,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8764,9 +8980,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 ""
@@ -8782,6 +9004,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8791,6 +9016,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8803,6 +9031,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -8944,18 +9175,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9451,6 +9676,30 @@ 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 "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9493,6 +9742,9 @@ 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 ""
@@ -9631,7 +9883,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"
@@ -9682,25 +9934,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"
@@ -9727,22 +9979,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}."
@@ -9751,24 +10000,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 ""
@@ -9790,18 +10039,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 ""
@@ -9859,7 +10102,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10065,6 +10308,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10149,12 +10395,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10245,6 +10485,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10281,6 +10524,9 @@ msgstr ""
msgid "Elasticsearch HTTP client timeout value in seconds."
msgstr ""
+msgid "Elasticsearch indexing"
+msgstr ""
+
msgid "Elasticsearch indexing restrictions"
msgstr ""
@@ -10314,6 +10560,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10374,6 +10623,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 ""
@@ -10383,10 +10641,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10440,6 +10698,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10449,6 +10710,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10467,6 +10731,9 @@ 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 ""
@@ -10485,7 +10752,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10524,7 +10791,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"
@@ -10554,9 +10821,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10590,10 +10854,13 @@ 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"
@@ -10671,6 +10938,9 @@ 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 ""
@@ -11394,9 +11664,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 ""
@@ -11418,9 +11685,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11535,6 +11799,9 @@ 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 ""
@@ -11544,6 +11811,9 @@ msgstr ""
msgid "Export variable to pipelines running on protected branches and tags only."
msgstr ""
+msgid "Exported requirements"
+msgstr ""
+
msgid "External Classification Policy Authorization"
msgstr ""
@@ -11604,6 +11874,9 @@ 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 ""
@@ -11664,6 +11937,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 ""
@@ -11969,9 +12245,6 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
@@ -11981,9 +12254,6 @@ msgstr ""
msgid "FeatureFlags|Get started with user lists"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
-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 ""
@@ -12287,9 +12557,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12308,6 +12575,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12371,6 +12641,12 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
@@ -12437,9 +12713,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12482,7 +12755,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"
@@ -12530,6 +12803,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 ""
@@ -12905,6 +13181,9 @@ 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 ""
@@ -12971,9 +13250,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 ""
@@ -12983,9 +13259,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13013,6 +13286,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 ""
@@ -13400,9 +13676,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13418,9 +13691,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 ""
@@ -13472,6 +13742,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13505,6 +13781,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 ""
@@ -13775,7 +14057,7 @@ msgstr ""
msgid "GroupSettings|Custom project templates"
msgstr ""
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13799,9 +14081,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13829,7 +14108,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13862,6 +14141,9 @@ 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 ""
@@ -13904,9 +14186,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 ""
@@ -14211,6 +14490,15 @@ 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 ""
@@ -14349,6 +14637,9 @@ 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 ""
@@ -14385,6 +14676,9 @@ 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 ""
@@ -14575,10 +14869,15 @@ 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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14587,6 +14886,9 @@ 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 ""
@@ -14731,9 +15033,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 ""
@@ -14815,7 +15147,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"
@@ -14857,10 +15189,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}."
@@ -14994,6 +15326,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15024,6 +15359,9 @@ msgstr ""
msgid "Integrations|Enable comments"
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 ""
@@ -15033,6 +15371,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 ""
@@ -15084,6 +15434,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 ""
@@ -15171,6 +15524,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15216,6 +15572,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr ""
@@ -15228,6 +15587,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15426,6 +15788,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15441,6 +15806,9 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
+msgid "Issue title"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -15477,7 +15845,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15573,6 +15941,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 ""
@@ -15915,6 +16286,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16127,7 +16501,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:"
@@ -16205,9 +16579,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16226,9 +16606,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -17032,9 +17409,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 ""
@@ -17104,7 +17478,7 @@ 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}"
+msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
msgid "Members listed as CODEOWNERS of affected files."
@@ -17122,9 +17496,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 ""
@@ -17242,9 +17613,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17305,6 +17673,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17314,13 +17685,13 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
-msgid "Merge request was scheduled to merge after pipeline succeeds"
+msgid "Merge request events"
msgstr ""
-msgid "Merge requests"
+msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
-msgid "Merge requests approvals"
+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"
@@ -17398,9 +17769,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17485,9 +17853,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17871,6 +18236,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18041,6 +18409,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18092,9 +18463,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18263,9 +18631,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18363,6 +18728,9 @@ 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 ""
@@ -18375,6 +18743,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18384,6 +18755,9 @@ 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 ""
@@ -18824,7 +19198,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19070,6 +19444,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19088,6 +19465,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19325,6 +19705,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19358,6 +19741,9 @@ 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 ""
@@ -19376,6 +19762,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19385,12 +19774,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 ""
@@ -19418,6 +19813,18 @@ 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 ""
@@ -19445,9 +19852,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19466,6 +19885,15 @@ 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 ""
@@ -19546,9 +19974,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19684,6 +20109,9 @@ msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19759,6 +20187,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -20173,10 +20604,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20281,15 +20715,24 @@ 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 ""
@@ -20323,9 +20766,6 @@ msgstr ""
msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
-msgid "PipelineCharts|Total duration:"
-msgstr ""
-
msgid "PipelineCharts|Total:"
msgstr ""
@@ -20428,9 +20868,15 @@ 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 ""
@@ -20446,13 +20892,13 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
-msgid "Pipelines|Loading Pipelines"
+msgid "Pipelines|Lint"
msgstr ""
-msgid "Pipelines|More Information"
+msgid "Pipelines|Loading Pipelines"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
+msgid "Pipelines|More Information"
msgstr ""
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
@@ -20467,9 +20913,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 ""
@@ -20491,9 +20934,24 @@ 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 ""
@@ -20509,6 +20967,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20590,6 +21051,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -20962,6 +21426,9 @@ msgstr ""
msgid "Prev"
msgstr ""
+msgid "Prevent MR approvals by author."
+msgstr ""
+
msgid "Prevent MR approvals by the author."
msgstr ""
@@ -20971,12 +21438,6 @@ msgstr ""
msgid "Prevent adding new members to project membership within this group"
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
-msgstr ""
-
-msgid "Prevent approval of merge requests by merge request committers"
-msgstr ""
-
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -20986,7 +21447,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -21598,9 +22059,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21796,7 +22254,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21817,6 +22275,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21865,9 +22326,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21904,6 +22362,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -22015,6 +22476,12 @@ 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 ""
@@ -22054,6 +22521,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -22507,6 +22977,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22537,7 +23010,7 @@ 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"
+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"
@@ -22555,6 +23028,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22570,7 +23046,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22831,12 +23307,21 @@ 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 ""
@@ -22855,6 +23340,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22935,12 +23423,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 ""
@@ -22959,27 +23456,18 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Rejected (closed)"
+msgid "Reindexing Status: %{status}"
msgstr ""
-msgid "Related Deployed Jobs"
+msgid "Rejected (closed)"
msgstr ""
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23075,9 +23563,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23087,6 +23572,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove all or specific reviewer(s)"
+msgstr ""
+
msgid "Remove approver"
msgstr ""
@@ -23165,6 +23653,12 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23201,6 +23695,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23246,6 +23743,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23573,6 +24073,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 ""
@@ -23706,7 +24209,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -23781,6 +24284,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23802,6 +24308,9 @@ 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 ""
@@ -23823,6 +24332,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -23861,12 +24373,18 @@ 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 ""
@@ -23908,6 +24426,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -23953,21 +24474,12 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
+msgid "Runner API"
msgstr ""
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23983,25 +24495,13 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
-msgid "Runners API"
+msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners activated for this project"
-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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -24079,6 +24579,15 @@ 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 ""
@@ -24130,6 +24639,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24190,10 +24702,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24211,6 +24723,9 @@ msgstr ""
msgid "Scope"
msgstr ""
+msgid "Scope board to current iteration"
+msgstr ""
+
msgid "Scopes"
msgstr ""
@@ -24331,6 +24846,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24470,6 +24988,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24820,13 +25341,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"
@@ -24886,7 +25407,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"
@@ -25171,6 +25692,9 @@ 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 ""
@@ -25201,7 +25725,7 @@ 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 template for issue descriptions."
+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}."
@@ -25294,10 +25818,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."
@@ -25312,9 +25836,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25399,9 +25920,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25462,9 +25980,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 ""
@@ -25519,6 +26034,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25904,9 +26422,15 @@ 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 ""
@@ -26267,7 +26791,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26276,9 +26800,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 ""
@@ -26387,9 +26908,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26426,19 +26944,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts: %{startsAt}"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26999,6 +27514,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27020,6 +27541,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 ""
@@ -27044,9 +27568,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 ""
@@ -27300,6 +27830,9 @@ 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 ""
@@ -27612,9 +28145,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 ""
@@ -27669,6 +28199,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 ""
@@ -27954,10 +28487,13 @@ 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 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."
@@ -28005,6 +28541,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 ""
@@ -28017,6 +28556,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 ""
@@ -28176,10 +28718,16 @@ 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 configured in the parent group settings, and will be active in the current project in addition to the project variables."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28209,7 +28757,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."
@@ -28224,6 +28772,18 @@ 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 ""
@@ -28254,13 +28814,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"
@@ -28353,13 +28916,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}"
@@ -28512,6 +29078,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 ""
@@ -28521,6 +29090,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 ""
@@ -28557,7 +29135,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."
@@ -28602,9 +29180,21 @@ 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 ""
@@ -28617,9 +29207,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28641,9 +29228,6 @@ 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 ""
@@ -28704,6 +29288,9 @@ msgstr ""
msgid "ThreatMonitoring|Environment"
msgstr ""
+msgid "ThreatMonitoring|Hide dismissed alerts"
+msgstr ""
+
msgid "ThreatMonitoring|In review"
msgstr ""
@@ -28770,7 +29357,7 @@ 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."
+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"
@@ -29059,6 +29646,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 ""
@@ -29074,6 +29664,9 @@ 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."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29083,6 +29676,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 ""
@@ -29149,12 +29745,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 ""
@@ -29389,6 +29979,11 @@ 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 Gold trial."
msgstr ""
@@ -29416,6 +30011,39 @@ 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 Gold 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 Gold 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 ""
@@ -29428,7 +30056,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."
@@ -29833,7 +30461,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29905,7 +30533,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29929,9 +30557,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
-msgstr ""
-
msgid "Upgrade your plan"
msgstr ""
@@ -29950,6 +30575,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30169,7 +30797,7 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
msgstr ""
msgid "Use your global notification setting"
@@ -30283,7 +30911,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}"
@@ -30454,7 +31082,7 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
msgid "Users were successfully added."
@@ -30517,9 +31145,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 ""
@@ -30926,6 +31551,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30953,6 +31581,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
msgid "Vulnerability|Request"
msgstr ""
@@ -31025,6 +31656,9 @@ 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 ""
@@ -31166,7 +31800,7 @@ 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 member is added to a group"
+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"
@@ -31247,7 +31881,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?"
@@ -31285,6 +31919,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 ""
@@ -31693,9 +32330,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 ""
@@ -31717,6 +32351,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 ""
@@ -31732,15 +32369,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 ""
@@ -31759,16 +32396,16 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+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 see your chat accounts."
+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 set up as many Runners as you need to run your jobs."
+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."
+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."
@@ -31792,6 +32429,9 @@ 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 ""
@@ -31828,9 +32468,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31903,6 +32540,9 @@ 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 ""
@@ -31918,6 +32558,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 ""
@@ -32101,6 +32744,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 ""
@@ -32287,6 +32933,9 @@ 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 ""
@@ -32296,6 +32945,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 ""
@@ -32469,6 +33121,9 @@ 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 ""
@@ -32914,6 +33569,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -32923,6 +33581,12 @@ 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 ""
@@ -33431,6 +34095,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 ""
@@ -33654,6 +34321,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -33762,12 +34432,6 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index e4c08ff3817..d1c90435d50 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: 2020-12-03 08:08\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index ac65e6717b3..f04e733d4d4 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: 2020-12-03 08:16\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -917,6 +926,27 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1080,9 +1110,15 @@ 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 ""
@@ -1353,28 +1389,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1386,6 +1419,9 @@ 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 ""
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1422,6 +1461,9 @@ 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 ""
@@ -1440,13 +1482,16 @@ 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."
+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."
+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"
@@ -1455,10 +1500,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 ""
@@ -1491,13 +1545,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1539,6 +1596,9 @@ 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 ""
@@ -2134,6 +2194,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3017,6 +3062,9 @@ 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 ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 ""
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,7 +3533,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 ""
@@ -3569,7 +3629,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3726,13 +3786,13 @@ msgstr[3] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4027,6 +4087,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4045,12 +4111,18 @@ 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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4088,6 +4163,9 @@ 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 ""
@@ -4134,9 +4212,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,10 +4368,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4317,10 +4392,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4440,12 +4515,21 @@ 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 ""
@@ -4455,13 +4539,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4476,15 +4560,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4524,9 +4602,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,10 +4747,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4924,6 +5035,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5044,10 +5176,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5077,9 +5209,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 ""
@@ -5149,6 +5302,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 ""
@@ -5311,13 +5485,16 @@ 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 were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5872,6 +6055,18 @@ 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 ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7874,6 +8096,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8175,9 +8397,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8241,6 +8460,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8418,45 +8718,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ 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 ""
@@ -9097,9 +9379,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9577,9 +9856,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9589,6 +9865,9 @@ 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 ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10289,6 +10622,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ 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 ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 ""
@@ -11027,9 +11387,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11135,9 +11492,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11273,9 +11627,18 @@ 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 ""
@@ -11390,22 +11753,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 ""
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 ""
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,7 +13587,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13452,9 +13815,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13788,10 +14148,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13815,9 +14181,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,7 +14208,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13878,6 +14241,9 @@ 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 ""
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,13 +15164,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15212,13 +15627,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15230,9 +15645,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15428,7 +15858,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16257,6 +16699,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17452,9 +17912,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 ""
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19849,10 +20432,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20107,10 +20690,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20179,6 +20765,9 @@ 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 ""
@@ -20215,6 +20804,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ 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 ""
@@ -20242,7 +20843,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 ""
@@ -20875,13 +21506,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ 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 ""
@@ -21163,6 +21803,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 ""
@@ -21493,9 +22139,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 ""
@@ -21685,7 +22334,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21754,9 +22406,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21793,6 +22442,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21982,7 +22643,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,7 +23117,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22723,6 +23384,12 @@ 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 ""
@@ -22741,6 +23408,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23169,6 +23851,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23478,9 +24163,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,7 +24205,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23690,6 +24366,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23896,9 +24569,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23908,13 +24578,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,10 +24785,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24127,7 +24806,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24277,6 +24959,9 @@ 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 ""
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25099,6 +25796,9 @@ 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 ""
@@ -25129,10 +25829,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25330,9 +26027,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25767,6 +26467,9 @@ 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 ""
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26346,13 +27058,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27315,7 +28090,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27330,6 +28105,9 @@ 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] ""
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 ""
@@ -27533,9 +28317,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28079,6 +28866,9 @@ 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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 ""
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,7 +30594,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29728,7 +30609,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,7 +32013,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 ""
@@ -31582,9 +32496,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ 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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32261,9 +33199,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index fc969506005..ce58ff867e0 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: 2020-12-03 08:10\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index b48119c16cb..e0adc702017 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: 2020-12-03 08:09\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -415,12 +415,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -850,6 +859,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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] ""
+msgstr[2] ""
+
+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] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1009,9 +1036,15 @@ 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 ""
@@ -1264,28 +1297,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1297,6 +1327,9 @@ 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 ""
@@ -1324,6 +1357,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1333,6 +1369,9 @@ 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 ""
@@ -1351,13 +1390,16 @@ 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."
+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."
+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"
@@ -1366,10 +1408,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1381,9 +1426,15 @@ 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 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 ""
+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 ""
@@ -1402,13 +1453,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1450,6 +1504,9 @@ 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 ""
@@ -2044,6 +2101,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2053,6 +2113,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2530,9 +2593,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2596,15 +2656,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2632,9 +2686,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2704,10 +2755,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2773,12 +2824,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2863,9 +2908,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2926,6 +2968,9 @@ 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 ""
@@ -3064,7 +3109,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3100,6 +3145,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ 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 ""
@@ -3334,9 +3385,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3358,6 +3406,9 @@ 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 ""
@@ -3367,6 +3418,9 @@ 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 ""
@@ -3385,7 +3439,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3400,6 +3454,9 @@ 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 ""
@@ -3478,7 +3535,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3631,13 +3688,13 @@ msgstr[2] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3658,6 +3715,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3760,9 +3820,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3931,6 +3988,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3949,12 +4012,18 @@ 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 ""
@@ -3967,6 +4036,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3991,6 +4063,9 @@ 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 ""
@@ -4036,9 +4111,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4195,10 +4267,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4219,10 +4291,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4264,7 +4339,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4327,9 +4402,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4342,12 +4414,21 @@ 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 ""
@@ -4357,13 +4438,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4378,15 +4459,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4399,9 +4477,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4426,9 +4501,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4513,22 +4585,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4567,10 +4645,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4624,6 +4711,30 @@ 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 ""
@@ -4654,9 +4765,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4825,6 +4933,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4918,7 +5044,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4945,10 +5074,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4978,9 +5107,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5029,6 +5155,30 @@ 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 ""
@@ -5050,6 +5200,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5182,15 +5335,33 @@ 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|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 ""
@@ -5212,13 +5383,16 @@ 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 were successfully made."
+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}."
@@ -5230,9 +5404,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5500,9 +5671,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5761,6 +5938,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5773,6 +5953,18 @@ 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 ""
@@ -6880,10 +7072,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7156,6 +7348,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7285,6 +7495,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7375,13 +7588,13 @@ msgstr[2] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7390,18 +7603,42 @@ 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 policy:"
+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 ""
@@ -7429,9 +7666,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7441,9 +7675,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7468,6 +7699,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7486,9 +7720,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7564,16 +7795,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7609,12 +7834,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7771,6 +7990,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8005,15 +8227,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8071,9 +8290,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8137,6 +8353,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8230,6 +8524,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8314,45 +8611,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8599,6 +8869,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8665,6 +8938,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8713,6 +8992,9 @@ 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 ""
@@ -8920,18 +9202,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8944,6 +9220,9 @@ 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 ""
@@ -8992,9 +9271,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9466,9 +9742,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9478,6 +9751,9 @@ 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 ""
@@ -9679,22 +9955,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9703,6 +10018,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9712,18 +10030,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9994,6 +10327,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10078,9 +10414,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10135,9 +10468,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10177,6 +10507,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10204,12 +10537,18 @@ 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 ""
@@ -10243,6 +10582,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10312,10 +10654,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10396,6 +10738,9 @@ 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 ""
@@ -10465,6 +10810,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10480,9 +10828,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10516,6 +10861,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10552,9 +10900,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10597,6 +10942,9 @@ 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 ""
@@ -10738,6 +11086,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10855,6 +11206,12 @@ 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 ""
@@ -10915,9 +11272,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11023,9 +11377,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11161,9 +11512,18 @@ 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 ""
@@ -11278,22 +11638,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11332,9 +11692,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11374,6 +11731,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11515,6 +11875,9 @@ 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 ""
@@ -11533,6 +11896,12 @@ 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 ""
@@ -11560,9 +11929,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11713,6 +12079,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11773,9 +12142,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11869,9 +12235,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11881,16 +12244,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12004,6 +12364,9 @@ 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 ""
@@ -12106,6 +12469,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12139,12 +12505,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12196,9 +12556,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12217,6 +12574,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12346,9 +12706,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12814,6 +13171,12 @@ 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 ""
@@ -12889,9 +13252,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13111,7 +13471,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13339,9 +13699,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13675,10 +14032,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13702,9 +14065,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13732,7 +14092,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13765,6 +14125,9 @@ 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 ""
@@ -13843,6 +14206,9 @@ 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 ""
@@ -13852,22 +14218,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14089,6 +14479,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14263,6 +14656,9 @@ 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 ""
@@ -14338,6 +14734,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14386,6 +14788,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14446,19 +14851,16 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14482,6 +14884,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14638,13 +15043,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14659,6 +15064,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14908,6 +15316,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14992,9 +15406,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15094,13 +15505,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15112,9 +15523,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15184,6 +15592,24 @@ 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 ""
@@ -15241,9 +15667,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15295,6 +15718,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15310,7 +15736,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15349,7 +15775,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15469,6 +15895,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15553,6 +15982,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15577,19 +16009,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16015,6 +16447,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16069,9 +16504,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16111,9 +16552,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16138,6 +16576,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16483,6 +16924,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16570,6 +17014,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16807,6 +17254,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16828,6 +17278,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16969,6 +17422,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17101,9 +17560,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17164,6 +17620,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17179,9 +17638,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17326,9 +17782,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17344,9 +17806,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17911,9 +18370,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18097,9 +18553,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18232,6 +18685,9 @@ 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 ""
@@ -18244,6 +18700,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18253,6 +18712,9 @@ 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 ""
@@ -18550,6 +19012,12 @@ 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 ""
@@ -18688,7 +19156,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18934,6 +19402,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18952,6 +19423,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19189,6 +19663,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19210,27 +19687,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19246,9 +19801,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19267,6 +19834,15 @@ 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 ""
@@ -19561,6 +20137,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19570,10 +20149,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19591,7 +20167,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19651,6 +20227,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19717,10 +20296,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19822,7 +20407,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19834,18 +20419,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19975,10 +20554,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20047,6 +20629,9 @@ 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 ""
@@ -20083,6 +20668,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20095,6 +20683,15 @@ 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 ""
@@ -20110,7 +20707,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20215,9 +20812,15 @@ 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 ""
@@ -20233,6 +20836,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20281,6 +20887,18 @@ 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 ""
@@ -20296,6 +20914,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20509,6 +21130,9 @@ 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 ""
@@ -20533,6 +21157,9 @@ 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 ""
@@ -20743,13 +21370,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20761,7 +21391,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20794,6 +21424,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20929,6 +21562,9 @@ 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 ""
@@ -21031,6 +21667,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21079,6 +21718,9 @@ 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 ""
@@ -21361,9 +22003,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21520,12 +22159,18 @@ 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 ""
@@ -21553,7 +22198,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21574,6 +22219,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21622,9 +22270,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21661,6 +22306,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21769,12 +22417,21 @@ 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|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 ""
@@ -21793,9 +22450,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21808,6 +22462,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21850,7 +22507,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22291,7 +22948,7 @@ 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"
+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"
@@ -22324,7 +22981,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22591,6 +23248,12 @@ 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 ""
@@ -22609,6 +23272,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22714,7 +23380,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22837,15 +23506,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22924,6 +23593,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22960,6 +23632,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23035,6 +23713,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23242,6 +23923,9 @@ 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 ""
@@ -23254,7 +23938,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23263,9 +23947,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23341,9 +24022,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23386,7 +24064,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23413,9 +24094,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23524,12 +24202,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23551,6 +24223,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23572,6 +24247,9 @@ 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 ""
@@ -23632,6 +24310,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23725,21 +24406,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23755,9 +24424,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23767,13 +24433,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23851,6 +24520,15 @@ 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 ""
@@ -23902,9 +24580,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23965,10 +24640,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23986,7 +24661,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24109,6 +24784,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24136,6 +24814,9 @@ 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 ""
@@ -24277,16 +24958,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24400,9 +25081,15 @@ 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 ""
@@ -24487,6 +25174,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24562,6 +25252,12 @@ 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 ""
@@ -24844,9 +25540,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24946,6 +25639,9 @@ 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 ""
@@ -24976,10 +25672,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25177,9 +25870,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25219,6 +25909,9 @@ 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 ""
@@ -25240,6 +25933,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25249,9 +25945,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25288,6 +25981,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25612,6 +26308,9 @@ 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 ""
@@ -25648,7 +26347,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25675,6 +26377,9 @@ 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 ""
@@ -25735,7 +26440,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25774,7 +26482,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26191,13 +26899,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26218,6 +26929,9 @@ 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 ""
@@ -26236,6 +26950,9 @@ 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 ""
@@ -26473,6 +27190,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26749,6 +27469,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26977,9 +27703,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26989,12 +27730,30 @@ 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 ""
@@ -27007,9 +27766,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27157,7 +27928,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27172,6 +27943,9 @@ 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] ""
@@ -27184,6 +27958,9 @@ 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 ""
@@ -27250,6 +28027,9 @@ 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 ""
@@ -27373,9 +28153,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27394,9 +28171,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27664,6 +28438,9 @@ 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 ""
@@ -27760,6 +28537,9 @@ 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 ""
@@ -27838,6 +28618,9 @@ 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 ""
@@ -27919,6 +28702,9 @@ 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 ""
@@ -28216,6 +29002,9 @@ 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 ""
@@ -28300,6 +29089,15 @@ 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 ""
@@ -28315,9 +29113,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28390,12 +29185,33 @@ 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 ""
@@ -28411,6 +29227,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28423,12 +29242,21 @@ 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 ""
@@ -28438,7 +29266,7 @@ 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."
+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"
@@ -28447,6 +29275,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29056,12 +29887,21 @@ 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] ""
+msgstr[2] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29080,6 +29920,39 @@ 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 Gold 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 Gold 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 ""
@@ -29470,6 +30343,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29494,7 +30370,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29551,7 +30427,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29566,7 +30442,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29608,9 +30484,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30121,6 +30994,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30562,6 +31438,9 @@ 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 ""
@@ -30589,6 +31468,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30616,6 +31498,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30634,6 +31522,9 @@ 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 ""
@@ -30646,6 +31537,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30679,6 +31573,9 @@ 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 ""
@@ -30781,6 +31678,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30817,6 +31717,9 @@ 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 ""
@@ -30940,7 +31843,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31318,6 +32221,9 @@ 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 ""
@@ -31408,6 +32314,9 @@ 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 ""
@@ -31417,9 +32326,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31441,6 +32347,9 @@ 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 ""
@@ -31477,9 +32386,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31552,6 +32458,9 @@ 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 ""
@@ -31561,6 +32470,9 @@ 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 ""
@@ -31594,6 +32506,9 @@ 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 ""
@@ -31753,6 +32668,9 @@ 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 ""
@@ -31825,6 +32743,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31900,6 +32821,9 @@ 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 ""
@@ -31921,6 +32845,9 @@ 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 ""
@@ -31978,6 +32905,9 @@ 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 ""
@@ -32077,6 +33007,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32095,9 +33028,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32140,6 +33079,9 @@ 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 ""
@@ -32179,6 +33121,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32335,6 +33280,9 @@ 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] ""
@@ -32542,6 +33490,12 @@ 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 ""
@@ -32725,6 +33679,9 @@ 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] ""
@@ -33385,18 +34342,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index a004ca72448..58fbc6434c3 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: 2020-12-03 08:16\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index c345a25614c..4787bbc59a6 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: 2020-12-03 08:09\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -867,9 +888,15 @@ 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 ""
@@ -1086,28 +1113,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1119,6 +1143,9 @@ 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 ""
@@ -1146,6 +1173,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1155,6 +1185,9 @@ 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 ""
@@ -1173,13 +1206,16 @@ 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."
+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."
+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"
@@ -1188,10 +1224,13 @@ 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 ready-to-go template for use with Android apps."
+msgid "A ready-to-go template for use with Android apps"
msgstr ""
-msgid "A ready-to-go template for use with iOS Swift apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 ""
@@ -1224,13 +1269,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1272,6 +1320,9 @@ 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 ""
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2744,6 +2780,9 @@ 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 ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 ""
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3739,6 +3790,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3757,12 +3814,18 @@ 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 ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,10 +4065,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4023,10 +4089,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4146,12 +4212,21 @@ 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 ""
@@ -4161,13 +4236,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4182,15 +4257,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4627,6 +4729,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4747,10 +4870,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4780,9 +4903,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 ""
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 ""
@@ -5014,13 +5179,16 @@ 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 were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5575,6 +5749,18 @@ 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 ""
@@ -6682,10 +6868,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,15 +8013,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -7929,6 +8139,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8734,6 +9004,9 @@ 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 ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9244,9 +9514,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9854,9 +10184,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ 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 ""
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 ""
@@ -10691,9 +11042,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13113,9 +13467,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13449,10 +13800,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13859,6 +14243,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14152,6 +14548,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19711,10 +20282,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 ""
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 ""
@@ -20767,6 +21395,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 ""
@@ -21097,9 +21731,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,7 +21926,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,7 +23782,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23139,9 +23812,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25302,6 +25990,9 @@ 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 ""
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,7 +27604,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ 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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 ""
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 ""
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] ""
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index d1eab10eb20..028fef649f3 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: 2020-12-03 08:13\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -867,9 +888,15 @@ 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 ""
@@ -1086,28 +1113,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1119,6 +1143,9 @@ 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 ""
@@ -1146,6 +1173,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1155,6 +1185,9 @@ 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 ""
@@ -1173,13 +1206,16 @@ 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."
+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."
+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"
@@ -1188,10 +1224,13 @@ 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 ready-to-go template for use with Android apps."
+msgid "A ready-to-go template for use with Android apps"
msgstr ""
-msgid "A ready-to-go template for use with iOS Swift apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 ""
@@ -1224,13 +1269,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1272,6 +1320,9 @@ 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 ""
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2744,6 +2780,9 @@ 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 ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 ""
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3739,6 +3790,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3757,12 +3814,18 @@ 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 ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,10 +4065,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4023,10 +4089,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4146,12 +4212,21 @@ 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 ""
@@ -4161,13 +4236,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4182,15 +4257,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4627,6 +4729,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4747,10 +4870,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4780,9 +4903,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 ""
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 ""
@@ -5014,13 +5179,16 @@ 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 were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5575,6 +5749,18 @@ 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 ""
@@ -6682,10 +6868,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,15 +8013,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -7929,6 +8139,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8734,6 +9004,9 @@ 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 ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9244,9 +9514,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9854,9 +10184,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ 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 ""
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 ""
@@ -10691,9 +11042,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13113,9 +13467,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13449,10 +13800,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13859,6 +14243,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14152,6 +14548,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19711,10 +20282,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 ""
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 ""
@@ -20767,6 +21395,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 ""
@@ -21097,9 +21731,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,7 +21926,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,7 +23782,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23139,9 +23812,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25302,6 +25990,9 @@ 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 ""
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,7 +27604,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ 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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 ""
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 ""
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] ""
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index 0cadf3c3d0f..2669092e227 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: 2020-12-03 08:09\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 0a71ad952b9..55039677a52 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: 2020-12-03 08:17\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commit"
+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 "%{strong_start}%{human_size}%{strong_end} File"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} mergiati)"
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 "(verifica progresso)"
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Errore durante l'attivazione/disattivazione della sottoscrizione per l'i
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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr "Si è verificato un errore. Riprova."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ msgstr "Approfondisci: %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr "Nome Branch"
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Cerca branches"
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr "Jobs"
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Cancella"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ msgstr "Preleva nella branch"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Ripristina nella branch"
+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 "Cherry-pick"
msgid "ChangeTypeAction|Revert"
msgstr "Ripristina"
+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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr "Clona repository"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr "Crea un nuova branch"
@@ -8033,6 +8246,84 @@ msgstr "Tag"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Crea token d'accesso personale"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Definisci un patter personalizzato mediante la sintassi cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "Descrizione"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr "E-mail"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr "Rilascio"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 "Aggiornato"
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ msgstr "Impossibile cambiare owner"
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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Trova in percorso"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "Trova file"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr "Housekeeping iniziato con successo"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr "Importa repository"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Leggi di più su"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "documentazione sulla pianificazione delle pipelines"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Nuovo file"
msgid "New group"
msgstr "Nuovo gruppo"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr "Pianificazione multipla Pipeline"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr "Percentuale di successo"
msgid "PipelineCharts|Successful:"
msgstr "Completata:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 "Account pianificato per la rimozione."
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr "Richiedi accesso"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr "Pianificazione pipelines"
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr "Settembre"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr "Impostazioni"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ msgstr "Questo significa che non è possibile effettuare push di codice fino a c
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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vuoi visualizzare i dati? Richiedi l'accesso ad un amministratore, grazie."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 660811136e1..a8e737c7b73 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: 2020-12-03 08:17\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -26,7 +26,7 @@ msgid " (from %{timeoutSource})"
msgstr " (%{timeoutSource} ã‹ã‚‰)"
msgid " Collected %{time}"
-msgstr ""
+msgstr "åŽé›†æ—¥æ™‚: %{time}"
msgid " Please sign in."
msgstr " サインインã—ã¦ãã ã•ã„。"
@@ -58,13 +58,13 @@ msgid " or "
msgstr " ã¾ãŸã¯ "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr " ã¾ãŸã¯ %{emphasisStart} !マージリクエストID %{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
-msgstr ""
+msgstr " ã¾ãŸã¯ %{emphasisStart} #イシューID %{emphasisEnd}"
msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
-msgstr ""
+msgstr " ã¾ãŸã¯ %{emphasisStart} &エピックID %{emphasisEnd}"
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " ã¾ãŸã¯ãƒªãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹å½¢å¼ï¼ˆä¾‹: path/to/project!merge_request_id)"
@@ -73,7 +73,7 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "「%{path}ã€ã¯ã€Œ%{ref}ã€ã«å­˜åœ¨ã—ã¾ã›ã‚“ã§ã—ãŸ"
msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "createInstance() ã«ã¯ \"el\" パラメータãŒå¿…è¦ã§ã™"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -81,7 +81,7 @@ msgstr[0] "%d 件ã®æ‰¿èª"
msgid "%d Other"
msgid_plural "%d Others"
-msgstr[0] ""
+msgstr[0] "ãã®ä»– %d 件"
msgid "%d Package"
msgid_plural "%d Packages"
@@ -89,7 +89,7 @@ msgstr[0] "%d 件ã®ãƒ‘ッケージ"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
-msgstr[0] ""
+msgstr[0] "%d 個ã®ã‚¹ã‚­ãƒ£ãƒ³ã•ã‚ŒãŸURL"
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
@@ -97,11 +97,11 @@ msgstr[0] "%d 件ã®ã‚¹ã‚­ãƒ£ãƒ³ã•ã‚ŒãŸ URL"
msgid "%d approver"
msgid_plural "%d approvers"
-msgstr[0] ""
+msgstr[0] "%d 人ã®æ‰¿èªè€…"
msgid "%d approver (you've approved)"
msgid_plural "%d approvers (you've approved)"
-msgstr[0] ""
+msgstr[0] "%d 人ã®æ‰¿èªè€… (ã‚ãªãŸã‚‚承èªæ¸ˆ)"
msgid "%d changed file"
msgid_plural "%d changed files"
@@ -113,7 +113,7 @@ msgstr[0] "%d 件ã®å­ã‚¨ãƒ”ック"
msgid "%d code quality issue"
msgid_plural "%d code quality issues"
-msgstr[0] "%d 件ã®ã‚³ãƒ¼ãƒ‰å“質ã®èª²é¡Œ"
+msgstr[0] "%d 件ã®ã‚³ãƒ¼ãƒ‰å“質ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%d comment"
msgid_plural "%d comments"
@@ -140,7 +140,7 @@ msgstr "%d個ã®ã‚³ãƒŸãƒƒãƒˆ"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
+msgstr[0] "%d件ã®å®Œäº†ã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%d contribution"
msgid_plural "%d contributions"
@@ -156,7 +156,7 @@ msgstr[0] "%d 件ã®ã‚¨ãƒ©ãƒ¼"
msgid "%d error found:"
msgid_plural "%d errors found:"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -168,7 +168,7 @@ msgstr[0] "%d 件ã®å¤±æ•—"
msgid "%d failed security job"
msgid_plural "%d failed security jobs"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¸ãƒ§ãƒ–ãŒå¤±æ•—ã—ã¾ã—ãŸ"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
@@ -176,7 +176,7 @@ msgstr[0] "%d 件ã®ãƒ†ã‚¹ãƒˆã§ä¿®æ­£ã•ã‚Œã¾ã—ãŸ"
msgid "%d group selected"
msgid_plural "%d groups selected"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžæ¸ˆã¿"
msgid "%d hour"
msgid_plural "%d hours"
@@ -188,15 +188,15 @@ msgstr[0] "%d 個ã®ã‚¢ã‚¯ã‚»ã‚¹ã§ããªã„マージリクエスト"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] "%d個ã®èª²é¡Œ"
+msgstr[0] "%d個ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«%d件ã®èª²é¡Œ"
+msgstr[0] "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«%d件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
-msgstr[0] "%d 件ã®èª²é¡Œã‚’ラベル付ãã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã—ãŸ"
+msgstr[0] "%d 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ラベル付ãã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã—ãŸ"
msgid "%d layer"
msgid_plural "%d layers"
@@ -216,7 +216,7 @@ msgstr[0] "%d メトリクス"
msgid "%d milestone"
msgid_plural "%d milestones"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³"
msgid "%d minute"
msgid_plural "%d minutes"
@@ -228,19 +228,19 @@ msgstr[0] "%d 件以上ã®ã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
+msgstr[0] "%d 件ã®æœªå®Œäº†ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚³ãƒ¡ãƒ³ãƒˆãŒä¿ç•™ä¸­"
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[0] "%d 件ã®å€‹äººãƒ—ロジェクトãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚復元ã§ãã¾ã›ã‚“。"
msgid "%d previously merged commit"
msgid_plural "%d previously merged commits"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ãƒžãƒ¼ã‚¸æ¸ˆã¿ã®ã‚³ãƒŸãƒƒãƒˆ"
msgid "%d project"
msgid_plural "%d projects"
@@ -248,7 +248,7 @@ msgstr[0] "%d件ã®ãƒ—ロジェクト"
msgid "%d project selected"
msgid_plural "%d projects selected"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžæ¸ˆã¿"
msgid "%d request with warnings"
msgid_plural "%d requests with warnings"
@@ -260,7 +260,7 @@ msgstr[0] "%d 秒"
msgid "%d shard selected"
msgid_plural "%d shards selected"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚·ãƒ£ãƒ¼ãƒ‰ã‚’é¸æŠžæ¸ˆã¿"
msgid "%d tag"
msgid_plural "%d tags"
@@ -268,11 +268,11 @@ msgstr[0] "%d ã‚¿ã‚°"
msgid "%d tag per image name"
msgid_plural "%d tags per image name"
-msgstr[0] ""
+msgstr[0] "ç”»åƒåã”ã¨ã«%d 件ã®ã‚¿ã‚°"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒæœªå‰²å½“"
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
@@ -280,15 +280,15 @@ msgstr[0] "%d 件ã®æœªè§£æ±ºã‚¹ãƒ¬ãƒƒãƒ‰"
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
-msgstr[0] ""
+msgstr[0] "%d 件ã®è„†å¼±æ€§"
msgid "%d vulnerability dismissed"
msgid_plural "%d vulnerabilities dismissed"
-msgstr[0] ""
+msgstr[0] "%d 件ã®è„†å¼±æ€§ãŒç„¡è¦–ã•ã‚Œã¾ã—ãŸ"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
+msgstr[0] "%d 件ã®è­¦å‘ŠãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -298,34 +298,43 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 㨠%{openOrClose} %{noteable}"
msgid "%{address} is an invalid IP address range"
-msgstr ""
+msgstr "%{address} ã¯ç„¡åŠ¹ãªIPアドレス範囲ã§ã™"
msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr "インスタンスã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ç™»éŒ²ã‚’カスタマイズ/無効化ã™ã‚‹æ–¹æ³•ã®%{anchorOpen}詳細を表示ã™ã‚‹%{anchorClose}。"
+
+msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
-msgid "%{author_link} wrote:"
+msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
msgstr ""
+msgid "%{author_link} wrote:"
+msgstr "%{author_link} ãŒæ›¸ãã¾ã—ãŸ:"
+
msgid "%{authorsName}'s thread"
msgstr "%{authorsName}ã®ã‚¹ãƒ¬ãƒƒãƒ‰"
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+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}Protected%{code_close} variables are only exposed to protected branches or tags."
-msgstr ""
+msgstr "%{code_open}ä¿è­·%{code_close} 変数ã¯ä¿è­·ãƒ–ランãƒã‚„ä¿è­·ã‚¿ã‚°ã«ã®ã¿å…¬é–‹ã•ã‚Œã¾ã™ã€‚"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} ㌠%{commit_timeago} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸ"
msgid "%{completedCount} completed weight"
-msgstr ""
+msgstr "%{completedCount} ウェイトãŒå®Œäº†ã—ã¾ã—ãŸ"
msgid "%{completedWeight} of %{totalWeight} weight completed"
-msgstr ""
+msgstr "%{completedWeight}/%{totalWeight} ウェイトãŒå®Œäº†ã—ã¾ã—ãŸ"
msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
-msgstr ""
+msgstr "%{containerScanningLinkStart}コンテスキャン%{containerScanningLinkEnd}ã¾ãŸã¯ %{dependencyScanningLinkStart}ä¾å­˜é–¢ä¿‚スキャン%{dependencyScanningLinkEnd}を有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚%{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd}ã¯ã€è‡ªå‹•ä½œæˆã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ä½œæˆè€…ã«ãªã‚Šã¾ã™ã€‚%{moreInfoLinkStart}詳細を表示ã™ã‚‹%{moreInfoLinkEnd}。"
msgid "%{cores} cores"
msgstr "%{cores} コア"
@@ -348,11 +357,11 @@ msgstr "%{count} ファイルãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
msgid "%{count} issue selected"
msgid_plural "%{count} issues selected"
-msgstr[0] ""
+msgstr[0] "%{count} 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’é¸æŠžæ¸ˆã¿"
msgid "%{count} merge request selected"
msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
+msgstr[0] "%{count} 件ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é¸æŠžæ¸ˆã¿"
msgid "%{count} more"
msgstr "他 %{count} 件"
@@ -378,10 +387,10 @@ msgid "%{count} related %{pluralized_subject}: %{links}"
msgstr "%{count} 件ã®é–¢é€£ã—㟠%{pluralized_subject}: %{links}"
msgid "%{count} total weight"
-msgstr ""
+msgstr "åˆè¨ˆã‚¦ã‚§ã‚¤ãƒˆ %{count}"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}%{critical} é‡å¤§%{criticalEnd} %{highStart}%{high} 高%{highEnd} ã¾ãŸã¯ %{otherStart}%{otherMessage}%{otherEnd}"
msgid "%{dashboard_path} could not be found."
msgstr "%{dashboard_path} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -396,13 +405,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 ""
+msgstr "%{doc_link_start}高度ãªæ¤œç´¢%{doc_link_end} ãŒæœ‰åŠ¹ã§ã™ã€‚"
msgid "%{due_date} (Past due)"
-msgstr ""
+msgstr "%{due_date} (期é™åˆ‡ã‚Œ)"
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -432,7 +441,7 @@ msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} +他 %{numberOfOtherMilestones} 件"
msgid "%{global_id} is not a valid ID for %{expected_type}."
-msgstr ""
+msgstr "%{global_id} 㯠%{expected_type} ã§ã¯æœ‰åŠ¹ãªIDã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}グループ%{group_docs_link_end}を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ãƒ—ロジェクトを管ç†ã—ã¦å…±åŒä½œæ¥­ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¯ã€æ‰€å±žã™ã‚‹ãƒ—ロジェクトã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
@@ -444,37 +453,37 @@ msgid "%{group_name} uses group managed accounts. You need to create a new GitLa
msgstr "%{group_name} ã¯ã‚°ãƒ«ãƒ¼ãƒ—管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¾ã™ã€‚ %{group_name} ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã‚‹æ–°ã—ã„GitLabアカウントを作æˆã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name}&%{epic_iid} &middot; %{author} ã«ã‚ˆã‚Š %{epic_created} オープンã•ã‚Œã¾ã—ãŸ"
msgid "%{hook_type} was deleted"
-msgstr ""
+msgstr "%{hook_type} ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
msgid "%{hook_type} was scheduled for deletion"
-msgstr ""
+msgstr "%{hook_type} ã®å‰Šé™¤ãŒã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸ"
msgid "%{host} sign-in from new location"
msgstr "æ–°ã—ã„場所%{host} ã‹ã‚‰ã®ãƒ­ã‚°ã‚¤ãƒ³"
msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
-msgstr ""
+msgstr "%{integrations_link_start}インテグレーション%{link_end} を利用ã—ã¦ã€ã‚µãƒ¼ãƒ‰ãƒ‘ーティアプリケーションを GitLab ワークフローã«çµ±åˆã§ãã¾ã™ã€‚利用å¯èƒ½ãªã‚¤ãƒ³ãƒ†ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒè¦ä»¶ã‚’満ãŸã•ãªã„å ´åˆã¯ã€ %{webhooks_link_start}ウェブフック%{link_end} ã®ä½¿ç”¨ã‚’検討ã—ã¦ãã ã•ã„。"
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType}を削除ã—ã¾ã™ï¼ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "%{issueType} actions"
-msgstr ""
+msgstr "%{issueType} アクション"
msgid "%{issuesCount} issues with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "最大 %{maxIssueCount} 件中ã€%{issuesCount} 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "最大 %{maxIssueCount} 件中〠%{issuesSize} 件"
msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}実際ã®ãƒ¬ã‚¹ãƒãƒ³ã‚¹:%{labelEnd} %{headers}"
msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
-msgstr ""
+msgstr "%{labelStart}アサート:%{labelEnd} %{assertion}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr "%{labelStart}クラス:%{labelEnd} %{class}"
@@ -483,43 +492,43 @@ msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
msgstr "%{labelStart}クラッシュアドレス:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}クラッシュ状態:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
-msgstr ""
+msgstr "%{labelStart}エビデンス:%{labelEnd} %{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}ファイル:%{labelEnd} %{file}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
-msgstr ""
+msgstr "%{labelStart}イメージ:%{labelEnd} %{image}"
msgid "%{labelStart}Method:%{labelEnd} %{method}"
-msgstr ""
+msgstr "%{labelStart}メソッド:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
-msgstr ""
+msgstr "%{labelStart}åå‰ç©ºé–“:%{labelEnd} %{namespace}"
msgid "%{labelStart}Scan Type:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart} スキャンタイプ:%{labelEnd} %{reportType}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
-msgstr ""
+msgstr "%{labelStart}スキャナー:%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}é€ä¿¡ã—ãŸãƒªã‚¯ã‚¨ã‚¹ãƒˆ:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}é‡è¦åº¦:%{labelEnd} %{severity}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}修正ã•ã‚Œã¦ã„ãªã„レスãƒãƒ³ã‚¹:%{labelEnd} %{headers}"
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)ã§ã€Webサイトã§HTTPS(SSL/TLS)を有効ã«ã™ã‚‹ãŸã‚ã«ãƒ‡ã‚¸ã‚¿ãƒ«è¨¼æ˜Žæ›¸ã‚’発行ã§ãã¾ã™ã€‚"
@@ -561,22 +570,22 @@ msgid "%{message} showing first %{warnings_displayed}"
msgstr ""
msgid "%{milestone_name} (Past due)"
-msgstr ""
+msgstr "%{milestone_name} (期é™åˆ‡ã‚Œ)"
msgid "%{milestone} (expired)"
-msgstr ""
+msgstr "%{milestone} (期é™åˆ‡ã‚Œ)"
msgid "%{milliseconds}ms"
msgstr "%{milliseconds} ミリ秒"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr "%{mrText} ã€ã“ã®èª²é¡Œã¯è‡ªå‹•çš„ã«ã‚¯ãƒ­ãƒ¼ã‚ºã—ã¾ã™ã€‚"
+msgstr "%{mrText} ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¯è‡ªå‹•çš„ã«ã‚¯ãƒ­ãƒ¼ã‚ºã—ã¾ã™ã€‚"
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 "%{name_with_link} 㯠%{percent}ã¾ãŸã¯ãれ以下ã®å…±æœ‰ãƒ©ãƒ³ãƒŠãƒ¼ãƒ‘イプライン分ãŒæ®‹ã£ã¦ã„ã¾ã™ã€‚ã“ã‚ŒãŒãªããªã‚‹ã¨ã€ãã®ãƒ—ロジェクトã®æ–°ã—ã„ジョブやパイプラインã¯å®Ÿè¡Œã•ã‚Œãªããªã‚Šã¾ã™ã€‚"
msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name_with_link} ã¯å…±æœ‰ãƒ©ãƒ³ãƒŠãƒ¼ãƒ‘イプラインã®å®Ÿè¡Œæ™‚é–“(分)を使ã„切りã¾ã—ãŸã€‚ãã®ãŸã‚プロジェクトã®æ–°ã—ã„ジョブやパイプラインã¯å®Ÿè¡Œã•ã‚Œã¾ã›ã‚“。"
msgid "%{name} contained %{resultsString}"
msgstr "%{name} ã«ã¯ %{resultsString} ãŒå«ã¾ã‚Œã¦ã„ã¾ã™"
@@ -585,19 +594,19 @@ msgid "%{name} found %{resultsString}"
msgstr "%{name} ã« %{resultsString} ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ"
msgid "%{name} is already being used for another emoji"
-msgstr ""
+msgstr "%{name} ã¯æ—¢ã«åˆ¥ã®çµµæ–‡å­—ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
msgid "%{name} is scheduled for %{action}"
-msgstr ""
+msgstr "%{name} 㯠%{action} ã§ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«æ¸ˆã¿ã§ã™"
msgid "%{name}'s avatar"
msgstr "%{name}ã®ã‚¢ãƒã‚¿ãƒ¼"
msgid "%{name}(%{url}) has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name}(%{url}) 㯠%{percent}ã¾ãŸã¯ãã®é…下ã®å…±æœ‰ãƒ©ãƒ³ãƒŠãƒ¼ãƒ‘イプラインã®å®Ÿè¡Œæ™‚é–“(分)ãŒæ®‹ã£ã¦ã„ã¾ã™ã€‚ã“れを使ã„切るã¨ã€ãã®ãƒ—ロジェクトã®æ–°ã—ã„ジョブやパイプラインã¯å®Ÿè¡Œã•ã‚Œãªããªã‚Šã¾ã™ã€‚"
msgid "%{name}(%{url}) has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name}(%{url}) 㯠共有ランナーパイプラインã®å®Ÿè¡Œæ™‚é–“(分)を使ã„切りã¾ã—ãŸã€‚ãã®ãŸã‚ã€ãã®ãƒ—ロジェクトã®æ–°ã—ã„ジョブやパイプラインã¯å®Ÿè¡Œã•ã‚Œãªããªã‚Šã¾ã™ã€‚"
msgid "%{no_of_days} day"
msgid_plural "%{no_of_days} days"
@@ -616,7 +625,7 @@ msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} オープン, %{closedIssues} 完了"
msgid "%{percentage}%% weight completed"
-msgstr ""
+msgstr "ウェイト㮠%{percentage}%% ãŒå®Œäº†ã—ã¾ã—ãŸ"
msgid "%{percent}%% complete"
msgstr "%{percent}%% 完了"
@@ -625,7 +634,7 @@ msgid "%{percent}%{percentSymbol} complete"
msgstr "%{percent}%{percentSymbol} 完了"
msgid "%{placeholder} is not a valid color scheme"
-msgstr ""
+msgstr "%{placeholder} ã¯æœ‰åŠ¹ãªã‚«ãƒ©ãƒ¼ã‚¹ã‚­ãƒ¼ãƒ ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "%{placeholder} is not a valid theme"
msgstr "%{placeholder} 㯠有効ãªãƒ†ãƒ¼ãƒžã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -634,7 +643,7 @@ msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
msgid "%{ref} cannot be added: %{error}"
-msgstr ""
+msgstr "%{ref} を追加ã™ã‚‹ãã¾ã›ã‚“ã§ã—ãŸ: %{error}"
msgid "%{releases} release"
msgid_plural "%{releases} releases"
@@ -653,21 +662,21 @@ msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
-msgstr ""
+msgstr "%{retryButtonStart}ã‚‚ã†ä¸€åº¦è©¦ã™%{retryButtonEnd} ã¾ãŸã¯ %{newFileButtonStart}æ–°ã—ã„ファイルを添付ã™ã‚‹%{newFileButtonEnd}。"
msgid "%{seconds}s"
-msgstr ""
+msgstr "%{seconds} 秒"
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[0] "ã“ã®ãƒ—ロジェクト㧠%{securityScanner} ã¯ç„¡åŠ¹ã§ã™ã€‚ %{linkStart}詳細情報%{linkEnd}"
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[0] "%{securityScanner} ã®çµæžœã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。パイプラインãŒæœ‰åŠ¹ã«ãªã£ã¦ã‹ã‚‰ã¾ã å®Ÿè¡Œã•ã‚Œã¦ã„ãªã„ãŸã‚ã§ã™ã€‚ %{linkStart}パイプラインを実行%{linkEnd}"
msgid "%{size} %{unit}"
-msgstr ""
+msgstr "%{size} %{unit}"
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -682,13 +691,13 @@ msgid "%{size} bytes"
msgstr "%{size} ãƒã‚¤ãƒˆ"
msgid "%{sourceBranch} into %{targetBranch}"
-msgstr ""
+msgstr "%{sourceBranch} ã‚’ %{targetBranch} ã«"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} ã¯Akismetã«æ­£å¸¸ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚"
msgid "%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}"
-msgstr ""
+msgstr "%{spanStart}行%{spanEnd} %{errorLine}%{errorColumn}"
msgid "%{spanStart}in%{spanEnd} %{errorFn}"
msgstr ""
@@ -700,10 +709,10 @@ msgid "%{state} epics"
msgstr "%{state}エピック"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
-msgstr ""
+msgstr "ソースブランãƒã‚’%{strongStart}削除%{strongEnd}"
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
+msgstr "%{strongStart}注: %{strongEnd} カスタムステージを追加後ã«ã€ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’目的ã®ä½ç½®ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’並ã¹æ›¿ãˆã¦ãã ã•ã„。"
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} コミット"
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} ファイル"
@@ -753,13 +774,13 @@ msgid "%{text} is available"
msgstr "%{text} ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚"
msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
+msgstr "%{timebox_name} ã¯ã€ãƒ—ロジェクトã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã„ãšã‚Œã‹ã«å±žã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "%{timebox_type} does not support burnup charts"
-msgstr ""
+msgstr "%{timebox_type} ã¯ãƒãƒ¼ãƒ³ã‚¢ãƒƒãƒ—ãƒãƒ£ãƒ¼ãƒˆã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“"
msgid "%{timebox_type} must have a start and due date"
-msgstr ""
+msgstr "%{timebox_type} ã«ã¯é–‹å§‹æ—¥ã¨çµ‚了日ãŒå¿…è¦ã§ã™"
msgid "%{title} %{operator} %{threshold}"
msgstr "%{title} %{operator} %{threshold}"
@@ -774,19 +795,19 @@ msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
msgstr ""
msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} 空ã)"
msgid "%{totalWeight} total weight"
-msgstr ""
+msgstr "%{totalWeight} åˆè¨ˆã‚¦ã‚§ã‚¤ãƒˆ"
msgid "%{total_warnings} warning(s) found:"
-msgstr ""
+msgstr "%{total_warnings} 件ã®è­¦å‘ŠãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
msgid "%{total} open issue weight"
-msgstr "%{total} 件ã®èª²é¡Œ"
+msgstr "%{total} 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
-msgstr ""
+msgstr "%{total} 件ã®è­¦å‘ŠãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: 最åˆã® %{warningsDisplayed} を表示"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "GitLab Inc. ã¨ã©ã®ã‚ˆã†ãªæƒ…報を共有ã™ã‚‹ã‹ã«ã¤ã„ã¦ã¯ %{usage_ping_link_start} ã“ã¡ã‚‰%{usage_ping_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -801,49 +822,49 @@ msgid "%{user_name} profile page"
msgstr "%{user_name} プロフィールページ"
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
-msgstr ""
+msgstr "%{username} ãŒã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ %{host} ã® GitLab アカウントをリクエストã—ã¾ã—ãŸã€‚"
msgid "%{username}'s avatar"
msgstr "%{username}ã®ã‚¢ãƒã‚¿ãƒ¼"
msgid "%{value} s"
-msgstr ""
+msgstr "%{value} 秒"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} ã—㦠%{time_spent_value} ãŒçµŒéŽã—ã¾ã—ãŸã€‚"
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
-msgstr ""
+msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} を使ã†ã¨ã€ã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ãƒ—ロジェクトã®ã‚¤ãƒ™ãƒ³ãƒˆã«å¿œã˜ã¦ã‚¦ã‚§ãƒ–アプリケーションã«é€šçŸ¥ã‚’é€ä¿¡ã§ãã¾ã™ã€‚"
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
msgid "&lt; 1 hour"
-msgstr ""
+msgstr "&lt; 1時間"
msgid "'%{data}' at %{location} does not match format: %{format}"
-msgstr ""
+msgstr "%{location} ã«ã‚ã‚‹ '%{data}' ㌠%{format} フォーマットã¨ä¸€è‡´ã—ã¾ã›ã‚“。"
msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
-msgstr ""
+msgstr "%{location} ã«ã‚ã‚‹ '%{data}' ㌠%{pattern} パターンã¨ä¸€è‡´ã—ã¾ã›ã‚“。"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
-msgstr ""
+msgstr "%{location} ã® %{data} ã¯ç„¡åŠ¹ã§ã™ï¼šerror_type =%{type}"
msgid "'%{data}' at %{location} is not of type: %{type}"
-msgstr ""
+msgstr "%{location} ã® %{data} 㯠%{type} åž‹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "'%{data}' at %{location} is not one of: %{enum}"
-msgstr ""
+msgstr "%{location} ã® %{data} 㯠%{enum} ã®ã„ãšã‚Œã‹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "'%{data}' at %{location} is not: %{const}"
-msgstr ""
+msgstr "%{location} ã® %{data} 㯠%{const} ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "'%{level}' is not a valid visibility level"
msgstr "'%{level}' ã¯æœ‰åŠ¹ãªå¯è¦–レベルã§ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "'%{name}' ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ãŒä½œæˆã•ã‚Œã¾ã—ãŸ"
msgid "'%{name}' Value Stream deleted"
msgstr ""
@@ -865,22 +886,28 @@ msgid "(%{mrCount} merged)"
msgstr "(%{mrCount} 個ã®ãƒžãƒ¼ã‚¸æ¸ˆã¿)"
msgid "(%{value}) has already been taken"
+msgstr "(%{value})ã¯æ—¢ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
+
+msgid "(+%{count}&nbsp;rules)"
msgstr ""
msgid "(No changes)"
msgstr "(変更ãªã—)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(進行状æ³ã‚’確èªã™ã‚‹)"
msgid "(deleted)"
-msgstr ""
+msgstr "(削除済ã¿)"
msgid "(line: %{startLine})"
-msgstr ""
+msgstr "(行: %{startLine})"
msgid "(max size 15 MB)"
-msgstr ""
+msgstr "(最大サイズ 15MB)"
msgid "(removed)"
msgstr "(除去ã—ã¾ã—ãŸ)"
@@ -889,7 +916,7 @@ msgid "(revoked)"
msgstr "(失効)"
msgid "* * * * *"
-msgstr ""
+msgstr "* * * * *"
msgid "+ %{amount} more"
msgstr "+ %{amount} 件以上"
@@ -904,7 +931,7 @@ msgid "+ %{numberOfHiddenAssignees} more"
msgstr "+ %{numberOfHiddenAssignees} 以上"
msgid "+ %{numberOfHiddenReviewers} more"
-msgstr ""
+msgstr "+ %{numberOfHiddenReviewers} 件以上"
msgid "+%d more"
msgid_plural "+%d more"
@@ -914,19 +941,19 @@ msgid "+%{approvers} more approvers"
msgstr "%{approvers} 人以上ã®æ‰¿èªè€…"
msgid "+%{more_assignees_count}"
-msgstr ""
+msgstr "+%{more_assignees_count}"
msgid "+%{more_assignees_count} more assignees"
-msgstr ""
+msgstr "+%{more_assignees_count} 人以上ã®æ‹…当者"
msgid "+%{more_reviewers_count}"
-msgstr ""
+msgstr "+%{more_reviewers_count}"
msgid "+%{more_reviewers_count} more reviewers"
-msgstr ""
+msgstr "+%{more_reviewers_count} 人以上ã®ãƒ¬ãƒ“ューア"
msgid "+%{tags} more"
-msgstr ""
+msgstr "+%{tags} 以上"
msgid ", or "
msgstr "ã€ã¾ãŸã¯"
@@ -946,25 +973,25 @@ msgid_plural "- Users"
msgstr[0] "- ユーザー"
msgid "- of - weight completed"
-msgstr ""
+msgstr "-/- ウェイト完了ã—ã¾ã—ãŸ"
msgid "- show less"
msgstr "- 折りãŸãŸã‚€"
msgid "."
-msgstr ""
+msgstr "."
msgid "0 bytes"
-msgstr ""
+msgstr "0 ãƒã‚¤ãƒˆ"
msgid "0 for unlimited"
msgstr "0ã¯ç„¡åˆ¶é™ã®æ„味"
msgid "0 for unlimited, only effective with remote storage enabled."
-msgstr ""
+msgstr "リモートストレージãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹å ´åˆã«ã®ã¿ã€0ã¯ç„¡åˆ¶é™ã«ãªã‚Šã¾ã™ã€‚"
msgid "0t1DgySidms"
-msgstr ""
+msgstr "0t1DgySidms"
msgid "1 Day"
msgid_plural "%d Days"
@@ -972,11 +999,11 @@ msgstr[0] "%d æ—¥"
msgid "1 Issue"
msgid_plural "%d Issues"
-msgstr[0] ""
+msgstr[0] "%d 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "1 closed issue"
msgid_plural "%{issues} closed issues"
-msgstr[0] "%{issues}件ã®ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸèª²é¡Œ"
+msgstr[0] "%{issues}件ã®ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "1 closed merge request"
msgid_plural "%{merge_requests} closed merge requests"
@@ -988,7 +1015,7 @@ msgstr[0] "%d æ—¥"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
-msgstr[0] ""
+msgstr[0] "%d 個ã®ãƒ‡ãƒ—ロイキー"
msgid "1 group"
msgid_plural "%d groups"
@@ -1008,7 +1035,7 @@ msgstr[0] "%d 分"
msgid "1 open issue"
msgid_plural "%{issues} open issues"
-msgstr[0] "%{issues}件ã®èª²é¡Œ"
+msgstr[0] "%{issues}件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "1 open merge request"
msgid_plural "%{merge_requests} open merge requests"
@@ -1051,7 +1078,7 @@ msgid "3 hours"
msgstr "3 時間"
msgid "30 days"
-msgstr ""
+msgstr "30 æ—¥"
msgid "30 minutes"
msgstr "30 分"
@@ -1075,40 +1102,37 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ãŒæ­£ã—ããªã„å ´åˆã€GitLab 管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
msgid "7 days"
-msgstr ""
+msgstr "7 æ—¥"
msgid "8 hours"
msgstr "8 時間"
msgid ":%{startLine} to %{endLine}"
-msgstr ""
+msgstr ":%{startLine} 行目ã‹ã‚‰ %{endLine} 行目"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "「Runnerã€ã¯ã‚¸ãƒ§ãƒ–を実行ã™ã‚‹ãƒ—ロセスã§ã™ã€‚å¿…è¦ãªæ•°ã® Runner ã‚’ä»»æ„ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã§ãã¾ã™ã€‚"
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "ä»»æ„ã®.NET Coreプロジェクト用ã«ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºå¯èƒ½ãªã€.NET Coreコンソールアプリケーションテンプレート"
msgid "A CI/CD pipeline must run and be successful before merge."
-msgstr ""
+msgstr "マージå‰ã«CI/CDパイプラインãŒå®Ÿè¡Œãƒ»æˆåŠŸã—ã¦ã„ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
-msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ GitBook サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
+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 ""
+msgstr "Springã¨Javaã§æ§‹æˆã•ã‚ŒãŸã‚¦ã‚§ãƒ–アプリケーションã®Gitpod"
-msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ Hexo サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
+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 "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ Hugo サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
+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 "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ Jekyll サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
+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 "Let's Encrypt ã®SSL証明書ã¯ã€ã‚ãªãŸã®ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒç¢ºèªã•ã‚Œã‚‹ã¾ã§å–å¾—ã§ãã¾ã›ã‚“。"
@@ -1119,9 +1143,12 @@ msgstr "Let's Encryptアカウントをã“ã®GitLabインストール用ã«æ§‹æˆ
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "AWS Lambdaã€AWS API Gatewayã€ãŠã‚ˆã³GitLab Pagesを使用ã™ã‚‹åŸºæœ¬çš„ãªãƒšãƒ¼ã‚¸ã¨ã‚µãƒ¼ãƒãƒ¼ãƒ¬ã‚¹é–¢æ•°"
-msgid "A complete DevOps platform"
+msgid "A basic template for developing Linux programs using Kotlin Native"
msgstr ""
+msgid "A complete DevOps platform"
+msgstr "完全㪠DevOps ã®ãƒ—ラットフォーム"
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "プロジェクトãŒç©ºã®å ´åˆã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ–ランãƒã‚’é¸æŠžã§ãã¾ã›ã‚“。"
@@ -1138,12 +1165,15 @@ msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "ファイル '%{file_name}' ã¯æ—¢ã« %{branch} ブランãƒã«å­˜åœ¨ã—ã¾ã™"
msgid "A fork is a copy of a project."
-msgstr ""
+msgstr "フォークã¨ã¯ãƒ—ロジェクトã®ã‚³ãƒ”ーã®ã“ã¨ã§ã™ã€‚"
msgid "A group is a collection of several projects"
-msgstr ""
+msgstr "グループã§è¤‡æ•°ã®ãƒ—ロジェクトをã¾ã¨ã‚ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã™ã€‚"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
+msgstr "グループã§ã‚ãªãŸã®çµ„織を表ç¾ã§ãã¾ã™ã€‚グループå˜ä½ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’管ç†ã—ã€è¤‡æ•°ã®ãƒ—ロジェクトã«ã‚ãŸã£ã¦ã‚³ãƒ©ãƒœãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚"
+
+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."
@@ -1153,6 +1183,9 @@ msgid "A merge request approval is required when a security report contains a ne
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"
@@ -1171,28 +1204,34 @@ 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 HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„るプレーン HTML サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
+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 ""
+msgstr "プラットフォームã®å€¤ã¯ã€ã‚¦ã‚§ãƒ–ã€ãƒ¢ãƒã‚¤ãƒ«ã€ã¾ãŸã¯ã‚¢ãƒ—リã§ã™ã€‚"
-msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools."
-msgstr "Salesforce Developerツールを使用ã—ãŸSalesforceアプリケーション開発å‘ã‘ã®ãƒ—ロジェクトテンプレート。"
+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 "アメリカåˆè¡†å›½ä¿å¥ç¦ç¥‰çœãŒç™ºè¡Œã—ãŸHIPAA監査プロトコルã®å„監査照会ã®èª²é¡Œã‚’å«ã‚€ãƒ—ロジェクト"
+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}"
+msgstr "プロジェクトã¨ã¯ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’æ ¼ç´ã—ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã§è¨ˆç”»ã‚’ç«‹ã¦ã€Wikiã§ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’公開ã™ã‚‹å ´æ‰€ã§ã™ã€‚ %{among_other_things_link}"
-msgid "A ready-to-go template for use with Android apps."
-msgstr "Android アプリã§ã™ãã«ä½¿ãˆã‚‹ãƒ†ãƒ³ãƒ—レート。"
+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 ready-to-go template for use with iOS Swift apps."
-msgstr "iOS Swift アプリã§ã™ãã«ä½¿ãˆã‚‹ãƒ†ãƒ³ãƒ—レート。"
+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 "ジョブã®ãƒ­ã‚°ã‹ã‚‰ãƒ†ã‚¹ãƒˆã‚«ãƒãƒ¬ãƒƒã‚¸ã®çµæžœã‚’見ã¤ã‘ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã‚‹æ­£è¦è¡¨ç¾ã€‚無効ã«ã™ã‚‹å ´åˆã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
@@ -1201,11 +1240,17 @@ 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 "次ã®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 user can only participate in a rotation once"
+msgstr ""
+
msgid "A user with write access to the source branch selected this option"
msgstr "ã“ã®ã‚ªãƒ—ションをé¸æŠžã—ãŸã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¸ã®æ›¸ãè¾¼ã¿ã‚’許å¯ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
@@ -1213,10 +1258,10 @@ msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt c
msgstr "アクションãŒå¿…è¦ï¼šGitLab Pagesã®ãƒ‰ãƒ¡ã‚¤ãƒ³ '%{domain}'ã¸ã®Let's Encrypt証明書ã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "API Fuzzing"
-msgstr ""
+msgstr "APIファジング"
msgid "API Help"
-msgstr ""
+msgstr "API ヘルプ"
msgid "API Token"
msgstr "API トークン"
@@ -1224,14 +1269,17 @@ msgstr "API トークン"
msgid "AWS Access Key"
msgstr "AWS アクセスキー"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "AWSアクセスキー。ロールインスタンスã®è³‡æ ¼æƒ…報を使用ã—ãªã„å ´åˆã«ã®ã¿å¿…è¦"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS 秘密アクセスキー"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "AWSã®ç§˜å¯†ã‚¢ã‚¯ã‚»ã‚¹ã‚­ãƒ¼ã€‚ロールインスタンスã®è³‡æ ¼æƒ…報を使用ã—ãªã„å ´åˆã«ã®ã¿å¿…è¦"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "中止"
@@ -1272,6 +1320,9 @@ msgstr "ã‚ãªãŸã® LDAP アカウントã®ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸ
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "アクセスãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸï¼ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ‡ãƒ—ロイキーを追加ã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "アクセス有効期é™"
@@ -1282,10 +1333,10 @@ msgid "Access forbidden. Check your access level."
msgstr "アクセスã¯ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚アクセスレベルを確èªã—ã¦ãã ã•ã„。"
msgid "Access granted"
-msgstr ""
+msgstr "アクセスãŒè¨±å¯ã•ã‚Œã¾ã—ãŸ"
msgid "Access requests"
-msgstr ""
+msgstr "アクセスリクエスト"
msgid "Access to '%{classification_label}' not allowed"
msgstr "'%{classification_label}'ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
@@ -1294,7 +1345,7 @@ msgid "Access to Pages websites are controlled based on the user's membership to
msgstr "Pages ã® Webサイトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯ã€ãƒ—ロジェクトã§ä¸Žãˆã‚‰ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¡ãƒ³ãƒãƒ¼ã‚·ãƒƒãƒ—ã«æˆ»ã¥ã„ã¦ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã•ã‚Œã¾ã™ã€‚ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚ãªãŸã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹å†…ã® Pages Webサイトã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ãŸã‚ã«ã€ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ "
msgid "AccessDropdown|Deploy Keys"
-msgstr ""
+msgstr "デプロイキー"
msgid "AccessDropdown|Groups"
msgstr "グループ"
@@ -1315,7 +1366,7 @@ msgid "AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will
msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿç¾åœ¨ä½¿ç”¨ã—ã¦ã„ã‚‹RSSã¾ãŸã¯ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ã®URLã¯æ©Ÿèƒ½ã—ãªããªã‚Šã¾ã™ã€‚"
msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
-msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿç¾åœ¨ä½¿ç”¨ã—ã¦ã„る課題メールアドレスã¯æ©Ÿèƒ½ã—ãªããªã‚Šã¾ã™ã€‚"
+msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿç¾åœ¨ä½¿ç”¨ã—ã¦ã„るメールアドレスã¯æ©Ÿèƒ½ã—ãªããªã‚Šã¾ã™ã€‚"
msgid "AccessTokens|Created"
msgstr "作æˆæ¸ˆã¿"
@@ -1333,7 +1384,7 @@ msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can acce
msgstr "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’外部ã«æ¼ã‚‰ã•ãªã„ã§ãã ã•ã„。ã“れを知ã£ãŸäººã¯èª°ã§ã‚‚ã‚ãªãŸã«ãªã‚Šã™ã¾ã—ã¦ãƒªãƒã‚¸ãƒˆãƒªã®é™çš„オブジェクトã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚æ¼æ´©ã—ãŸå ´åˆã€ %{reset_link_start} ã“れをリセット %{reset_link_end}ã™ã¹ãã§ã™ã€‚"
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 "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’外部ã«æ¼ã‚‰ã•ãªã„ã§ãã ã•ã„。ã“れを知ã£ãŸäººã¯èª°ã§ã‚‚ã‚ãªãŸã«ãªã‚Šã™ã¾ã—ã¦èª²é¡Œã‚’作æˆã§ãã¾ã™ã€‚æ¼æ´©ã—ãŸå ´åˆã€%{link_reset_it} ã™ã¹ãã§ã™ã€‚"
+msgstr "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’外部ã«æ¼ã‚‰ã•ãªã„ã§ãã ã•ã„。ã“れを知ã£ãŸäººã¯èª°ã§ã‚‚ã‚ãªãŸã«ãªã‚Šã™ã¾ã—ã¦ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã§ãã¾ã™ã€‚æ¼æ´©ã—ãŸå ´åˆã€%{link_reset_it} ã™ã¹ãã§ã™ã€‚"
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 "ã“ã®ãƒˆãƒ¼ã‚¯ãƒ³ã‚’外部ã«æ¼ã‚‰ã•ãªã„ã§ãã ã•ã„。ã“れを知ã£ãŸäººã¯èª°ã§ã‚‚ã‚ãªãŸã®ã‚ˆã†ã«ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを読ã‚ã€ã‚ãªãŸã¨ã—ã¦RSSフィードやカレンダーã®ãƒ•ã‚£ãƒ¼ãƒ‰ã‚’発行ã§ãã¾ã™ã€‚æ¼æ´©ã—ãŸå ´åˆã€%{link_reset_it} ã™ã¹ãã§ã™ã€‚"
@@ -1357,7 +1408,7 @@ msgid "AccessTokens|Your feed token is used to authenticate you when your RSS re
msgstr "RSSリーダーãŒå€‹äººç”¨RSSフィードを読ã¿è¾¼ã‚€ã¨ãã€ã¾ãŸã¯ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚¢ãƒ—リケーションãŒå€‹äººç”¨ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚’読ã¿è¾¼ã‚€ã¨ãã«ã€ãƒ•ã‚£ãƒ¼ãƒ‰ãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦ã‚ãªãŸã‚’èªè¨¼ã—ã¾ã™ã€‚"
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 "ã‚ãªãŸã®å—信メールトークンã¯ã‚ãªãŸãŒãƒ¡ãƒ¼ãƒ«ã§æ–°ã—ã„課題を作æˆã™ã‚‹ã¨ãã‚ãªãŸã‚’èªè¨¼ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚ã¾ãŸã€ã‚ãªãŸã®å€‹äººçš„ãªãƒ—ロジェクト特有ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«å«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
+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 "é™çš„オブジェクトトークンã¯ã€ (アーカイブã€ãƒ–ロブãªã©ã®) リãƒã‚¸ãƒˆãƒªã®é™çš„オブジェクトãŒå¤–部ストレージã‹ã‚‰æä¾›ã•ã‚Œã¦ã„ã‚‹å ´åˆã®èªè¨¼ã«ä½¿ç”¨ã—ã¾ã™ã€‚"
@@ -1366,7 +1417,7 @@ msgid "AccessTokens|reset it"
msgstr "リセット"
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "詳細を表示"
msgid "AccessibilityReport|Message: %{message}"
msgstr "メッセージ: %{message}"
@@ -1375,7 +1426,7 @@ msgid "AccessibilityReport|New"
msgstr " æ–°ã—ã„"
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
-msgstr ""
+msgstr "アクセシビリティã®ã‚¹ã‚­ãƒ£ãƒ³ã§æ¬¡ã®ã‚¿ã‚¤ãƒ—ã®ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %{code}"
msgid "Account"
msgstr "アカウント"
@@ -1390,22 +1441,22 @@ msgid "Account: %{account}"
msgstr "アカウント: %{account}"
msgid "Action to take when receiving an alert. %{docsLink}"
-msgstr ""
+msgstr "アラートをå—信時ã«å–ã‚‹ã¹ãアクション 。%{docsLink}"
msgid "Actions"
-msgstr ""
+msgstr "アクション"
msgid "Activate Service Desk"
msgstr "サービスデスクを有効ã«ã™ã‚‹"
msgid "Activate user activity analysis"
-msgstr ""
+msgstr "ユーザーアクティビティ分æžã‚’有効ã«ã™ã‚‹"
msgid "Active"
msgstr "有効"
msgid "Active %{type} (%{token_length})"
-msgstr ""
+msgstr "有効 %{type} (%{token_length})"
msgid "Active Sessions"
msgstr "アクティブ セッション"
@@ -1417,11 +1468,11 @@ msgid "Add"
msgstr "追加"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "\"%{value}\" を追加"
msgid "Add %d issue"
msgid_plural "Add %d issues"
-msgstr[0] "課題を%d 件ã€è¿½åŠ "
+msgstr[0] "イシューを%d 件ã€è¿½åŠ "
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr "リリース㫠%{linkStart}アセット%{linkEnd} を追加ã—ã¾ã™ã€‚ GitLab ã«ã¯ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚„リリースã®ã‚¨ãƒ“デンスãªã©ã®èª­ã¿å–り専用ã®ã‚¢ã‚»ãƒƒãƒˆãŒè‡ªå‹•çš„ã«å«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -1448,7 +1499,7 @@ msgid "Add LICENSE"
msgstr "ライセンスã®è¿½åŠ "
msgid "Add New Node"
-msgstr ""
+msgstr "æ–°ã—ã„ノードを追加"
msgid "Add README"
msgstr "README を追加"
@@ -1460,7 +1511,7 @@ msgid "Add Zoom meeting"
msgstr "Zoom ミーティングを追加"
msgid "Add a %{type}"
-msgstr ""
+msgstr "%{type} を追加"
msgid "Add a GPG key"
msgstr "GPGキーを追加"
@@ -1472,13 +1523,13 @@ msgid "Add a To Do"
msgstr "Todoを追加"
msgid "Add a To-Do"
-msgstr ""
+msgstr "Todoを追加"
msgid "Add a bullet list"
msgstr "箇æ¡æ›¸ãリストを追加"
msgid "Add a comment to this line"
-msgstr ""
+msgstr "ã“ã®è¡Œã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "ã“ã® %{noteableDisplayName} ã¸ä¸€èˆ¬çš„ãªã‚³ãƒ¡ãƒ³ãƒˆã‚’追加。"
@@ -1490,19 +1541,19 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "ã‚ãªãŸã® Wiki ã«ãƒ—ロジェクトã«é–¢ã™ã‚‹æƒ…報をå«ã‚€ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’追加ã™ã‚‹ã¨ã€GitLab ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®ä»£ã‚ã‚Šã«ãれをã“ã“ã«è¡¨ç¤ºã—ã¾ã™ã€‚"
msgid "Add a line"
-msgstr ""
+msgstr "行を追加"
msgid "Add a link"
msgstr "リンクを追加"
msgid "Add a new issue"
-msgstr "æ–°ã—ã„課題を作æˆã™ã‚‹"
+msgstr "æ–°ã—ã„イシューを作æˆã™ã‚‹"
msgid "Add a numbered list"
msgstr "番å·ä»˜ãリストを追加"
msgid "Add a related issue"
-msgstr ""
+msgstr "関連ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’追加"
msgid "Add a table"
msgstr "テーブルを追加ã™ã‚‹"
@@ -1511,7 +1562,7 @@ msgid "Add a task list"
msgstr "タスクリストを追加"
msgid "Add a to do"
-msgstr ""
+msgstr "Todoを追加"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã«è¡¨ç¤ºã™ã‚‹ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã—ã¾ã™ã€‚ ãŸã ã—ã€%{character_limit} 文字ã®åˆ¶é™ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -1520,7 +1571,7 @@ msgid "Add an SSH key"
msgstr "SSH éµã‚’追加"
msgid "Add an existing issue"
-msgstr ""
+msgstr "既存ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’追加"
msgid "Add an impersonation token"
msgstr ""
@@ -1544,7 +1595,7 @@ msgid "Add comment now"
msgstr "コメントã™ã‚‹"
msgid "Add comment to design"
-msgstr ""
+msgstr "デザインã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
msgid "Add deploy freeze"
msgstr ""
@@ -1559,7 +1610,7 @@ msgid "Add environment"
msgstr "環境ã®è¿½åŠ "
msgid "Add existing confidential %{issuableType}"
-msgstr ""
+msgstr "既存ã®éžå…¬é–‹ %{issuableType} を追加"
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "メールã«ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’追加ã—ã¾ã™ã€‚色設定ã¯ã‚¢ãƒ—リケーションインターフェース内ã§ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚"
@@ -1568,13 +1619,13 @@ msgid "Add image comment"
msgstr "ç”»åƒã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
msgid "Add issues"
-msgstr "課題を追加"
+msgstr "イシューを追加"
msgid "Add italic text"
msgstr "斜体ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’追加"
msgid "Add key"
-msgstr ""
+msgstr "キーを追加"
msgid "Add label(s)"
msgstr "ラベルを追加"
@@ -1589,13 +1640,13 @@ msgid "Add new directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’追加"
msgid "Add or remove previously merged commits"
-msgstr ""
+msgstr "以å‰ã«ãƒžãƒ¼ã‚¸ã—ãŸã‚³ãƒŸãƒƒãƒˆã‚’追加ã¾ãŸã¯å‰Šé™¤"
msgid "Add or subtract spent time"
msgstr "作業時間を追加ã¾ãŸã¯æ¸›ã‚‰ã™"
msgid "Add previously merged commits"
-msgstr ""
+msgstr "以å‰ã«ãƒžãƒ¼ã‚¸ã—ãŸã‚³ãƒŸãƒƒãƒˆã‚’追加"
msgid "Add reaction"
msgstr "リアクションã®è¿½åŠ "
@@ -1604,10 +1655,10 @@ msgid "Add request manually"
msgstr "リクエストを手動ã§è¿½åŠ ã—ã¾ã™"
msgid "Add strikethrough text"
-msgstr ""
+msgstr "å–り消ã—線を追加ã™ã‚‹"
msgid "Add suggestion to batch"
-msgstr ""
+msgstr "æ案をãƒãƒƒãƒã«è¿½åŠ "
msgid "Add system hook"
msgstr "システムフックã®è¿½åŠ "
@@ -1643,10 +1694,10 @@ msgid "Add webhook"
msgstr "Webhook ã®è¿½åŠ "
msgid "Add/remove"
-msgstr ""
+msgstr "追加ã¨å‰Šé™¤"
msgid "AddContextCommits|Add previously merged commits"
-msgstr ""
+msgstr "以å‰ã«ãƒžãƒ¼ã‚¸ã—ãŸã‚³ãƒŸãƒƒãƒˆã‚’追加"
msgid "AddContextCommits|Add/remove"
msgstr ""
@@ -1667,10 +1718,10 @@ msgid "Added %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} を追加ã—ã¾ã—ãŸã€‚"
msgid "Added a to do."
-msgstr ""
+msgstr "Todoã¸è¿½åŠ ã—ã¾ã—ãŸã€‚"
msgid "Added an issue to an epic."
-msgstr "課題をエピックã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
+msgstr "イシューをエピックã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
msgid "Added at"
msgstr "追加日時: "
@@ -1685,7 +1736,7 @@ msgid "Adding new applications is disabled in your GitLab instance. Please conta
msgstr "ã‚ãªãŸã® GitLab インスタンスã§æ–°ã—ã„アプリケーションを追加ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。権é™ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GitLab 管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
msgid "Additional Metadata"
-msgstr ""
+msgstr "追加メタデータ"
msgid "Additional minutes"
msgstr "追加分数"
@@ -1706,10 +1757,10 @@ msgid "Adds a Zoom meeting"
msgstr "Zoom ミーティングを追加"
msgid "Adds a to do."
-msgstr ""
+msgstr "Todoを追加ã—ã¾ã™ã€‚"
msgid "Adds an issue to an epic."
-msgstr "課題をエピックã«è¿½åŠ ã€‚"
+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 ""
@@ -1721,13 +1772,13 @@ msgid "Admin Note"
msgstr "管ç†è€…メモ"
msgid "Admin Notifications"
-msgstr ""
+msgstr "管ç†é€šçŸ¥"
msgid "Admin Overview"
msgstr "管ç†è€…用概è¦"
msgid "Admin Section"
-msgstr ""
+msgstr "管ç†ã‚»ã‚¯ã‚·ãƒ§ãƒ³"
msgid "Admin mode already enabled"
msgstr "管ç†è€…モードã¯æ—¢ã«æœ‰åŠ¹ã§ã™"
@@ -1748,7 +1799,7 @@ msgid "AdminArea|Active users"
msgstr " アクティブãªãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
-msgstr ""
+msgstr "%{billable_users_link_start}請求対象%{billable_users_link_end} 以外ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚‚å«ã‚€ã€ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹å†…ã«ä½œæˆã•ã‚ŒãŸã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã€‚"
msgid "AdminArea|Billable users"
msgstr "請求ã®å¯èƒ½ãªãƒ¦ãƒ¼ã‚¶ãƒ¼"
@@ -1760,16 +1811,16 @@ msgid "AdminArea|Bots"
msgstr "ボット"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "コンãƒãƒ¼ãƒãƒ³ãƒˆ"
msgid "AdminArea|Developer"
msgstr "開発者"
msgid "AdminArea|Features"
-msgstr ""
+msgstr "機能"
msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
+msgstr "グループ: %{number_of_groups}"
msgid "AdminArea|Guest"
msgstr "ゲスト"
@@ -1778,34 +1829,34 @@ msgid "AdminArea|Included Free in license"
msgstr "ライセンスã«ç„¡æ–™ã§å«ã¾ã‚Œã¦ã„ã¾ã™"
msgid "AdminArea|Latest groups"
-msgstr ""
+msgstr "最新ã®ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "AdminArea|Latest projects"
-msgstr ""
+msgstr "最新ã®ãƒ—ロジェクト"
msgid "AdminArea|Latest users"
-msgstr ""
+msgstr "最新ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "AdminArea|Maintainer"
msgstr "メンテナー"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "æ–°è¦ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "æ–°è¦ãƒ—ロジェクト"
msgid "AdminArea|New user"
-msgstr ""
+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 ""
+msgstr "インスタンスã®ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°ãŒä¸Šé™ã«é”ã™ã‚‹ã¨ã€è¿½åŠ ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€ç®¡ç†è€…ã«ã‚ˆã‚‹æ‰¿èªãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚無制é™ã¨ã™ã‚‹ã«ã¯ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã‚’空ã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
msgid "AdminArea|Owner"
msgstr "オーナー"
msgid "AdminArea|Projects: %{number_of_projects}"
-msgstr ""
+msgstr "プロジェクト: %{number_of_projects}"
msgid "AdminArea|Reporter"
msgstr "レãƒãƒ¼ã‚¿ãƒ¼"
@@ -1826,7 +1877,7 @@ msgid "AdminArea|Total users"
msgstr "全ユーザー"
msgid "AdminArea|User cap"
-msgstr ""
+msgstr "ユーザーキャップ"
msgid "AdminArea|Users statistics"
msgstr "ユーザー統計"
@@ -1838,7 +1889,7 @@ msgid "AdminArea|Users without a Group and Project"
msgstr "グループã¨ãƒ—ロジェクトã®ãªã„ユーザー"
msgid "AdminArea|Users: %{number_of_users}"
-msgstr ""
+msgstr "ユーザー: %{number_of_users}"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "å…¨ã¦ã®ã‚¸ãƒ§ãƒ–ã‚’åœæ­¢ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç¾åœ¨å®Ÿè¡Œä¸­ã®ã‚¸ãƒ§ãƒ–ã¯åœæ­¢ã•ã‚Œã¾ã™ã€‚"
@@ -1850,7 +1901,7 @@ 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 "プロジェクト %{projectName} ã¨ãã®ãƒªãƒã‚¸ãƒˆãƒªã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãªã©ã®ã™ã¹ã¦ã®é–¢é€£ãƒªã‚½ãƒ¼ã‚¹ã‚’完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã„ã¾ä¸€åº¦ç¢ºèªã—〠%{strong_start}プロジェクトã®å‰Šé™¤%{strong_end}を押ã—ã¦ãã ã•ã„。削除ã—ãŸã‚ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgstr "プロジェクト %{projectName} ã¨ãã®ãƒªãƒã‚¸ãƒˆãƒªã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãªã©ã®ã™ã¹ã¦ã®é–¢é€£ãƒªã‚½ãƒ¼ã‚¹ã‚’完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã„ã¾ä¸€åº¦ç¢ºèªã—〠%{strong_start}プロジェクトã®å‰Šé™¤%{strong_end}を押ã—ã¦ãã ã•ã„。削除ã—ãŸã‚ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
msgid "AdminProjects|Delete"
msgstr "削除"
@@ -1864,15 +1915,21 @@ msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクトã«çµ±åˆè¨­å®šã‚’é©ç”¨"
msgid "AdminSettings|Auto DevOps domain"
msgstr "Auto DevOps ドメイン"
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+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 を有効ã«ã™ã‚‹"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "環境変数ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ä¿è­·ã•ã‚Œã¦ã„ã¾ã™"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "一般設定ã«ç§»å‹•"
@@ -1880,7 +1937,7 @@ msgid "AdminSettings|Integrations configured here will automatically apply to al
msgstr "ã“ã“ã§è¨­å®šã—ãŸçµ±åˆã¯ã€ã“ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã«è‡ªå‹•çš„ã«é©ç”¨ã•ã‚Œã¾ã™ã€‚"
msgid "AdminSettings|Moved to integrations"
-msgstr ""
+msgstr "インテグレーションã«ç§»å‹•"
msgid "AdminSettings|No required pipeline"
msgstr "必須パイプラインãªã—"
@@ -1895,7 +1952,7 @@ msgid "AdminSettings|Select a template"
msgstr "管ç†è¨­å®š |テンプレートé¸æŠž"
msgid "AdminSettings|Service Templates will soon be deprecated."
-msgstr ""
+msgstr "サービステンプレートã¯é–“ã‚‚ãªãéžæŽ¨å¥¨ã¨ãªã‚Šã¾ã™ã€‚"
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr "Serviceテンプレートã¯ã€çµ±åˆã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã‚’設定ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™"
@@ -1913,7 +1970,7 @@ msgid "AdminSettings|The required pipeline configuration can be selected from th
msgstr "必須パイプライン設定ã¯ã€è¨­å®šæ¸ˆã¿ã®%{link_start}インスタンステンプレートリãƒã‚¸ãƒˆãƒª%{link_end}内㮠%{code_start}gitlab-ci%{code_end} ディレクトリã€ã¾ãŸã¯ GitLab æä¾›ã®è¨­å®šã‹ã‚‰é¸æŠžã§ãã¾ã™ã€‚"
msgid "AdminSettings|Try using the latest version of Integrations instead."
-msgstr ""
+msgstr "代ã‚ã‚Šã«æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚¤ãƒ³ãƒ†ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’使用ã—ã¦ãã ã•ã„。"
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "環境変数ã®æ–°è¦ä½œæˆæ™‚ã«ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ä¿è­·ã•ã‚Œã¾ã™"
@@ -1925,7 +1982,7 @@ msgid "AdminStatistics|Forks"
msgstr "フォーク"
msgid "AdminStatistics|Issues"
-msgstr "課題"
+msgstr "イシュー"
msgid "AdminStatistics|Merge Requests"
msgstr "マージリクエスト"
@@ -1943,19 +2000,19 @@ msgid "AdminStatistics|Snippets"
msgstr "スニペット"
msgid "AdminUsers|(Admin)"
-msgstr ""
+msgstr "(管ç†è€…)"
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "(ブロック)"
msgid "AdminUsers|(Deactivated)"
-msgstr ""
+msgstr "(éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–)"
msgid "AdminUsers|(Internal)"
-msgstr ""
+msgstr "(内部)"
msgid "AdminUsers|(Pending approval)"
-msgstr ""
+msgstr "(承èªå¾…ã¡)"
msgid "AdminUsers|2FA Disabled"
msgstr "2FA 無効"
@@ -1964,22 +2021,22 @@ msgid "AdminUsers|2FA Enabled"
msgstr "2FA 有効"
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "アクセス"
msgid "AdminUsers|Access Git repositories"
-msgstr ""
+msgstr "Git リãƒã‚¸ãƒˆãƒªã«ã‚¢ã‚¯ã‚»ã‚¹"
msgid "AdminUsers|Access the API"
-msgstr ""
+msgstr "API ã«ã‚¢ã‚¯ã‚»ã‚¹"
msgid "AdminUsers|Activate"
-msgstr ""
+msgstr "アクティブ化"
msgid "AdminUsers|Activate user"
-msgstr ""
+msgstr "ユーザーをアクティブã«ã™ã‚‹"
msgid "AdminUsers|Activate user %{username}?"
-msgstr ""
+msgstr "ユーザー %{username} をアクティブã«ã—ã¾ã™ã‹?"
msgid "AdminUsers|Active"
msgstr "アクティブ"
@@ -1988,34 +2045,34 @@ msgid "AdminUsers|Admin"
msgstr "管ç†è€…"
msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr ""
+msgstr "管ç†è€…ã¯ã™ã¹ã¦ã®ã‚°ãƒ«ãƒ¼ãƒ—ã€ãƒ—ロジェクトã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚ã¾ãŸã“ã® GitLab ã®ã™ã¹ã¦ã®æ©Ÿèƒ½ã‚’管ç†ã§ãã¾ã™"
msgid "AdminUsers|Admins"
msgstr "管ç†è€…"
msgid "AdminUsers|Approve"
-msgstr ""
+msgstr "承èªã™ã‚‹"
msgid "AdminUsers|Approve user"
-msgstr ""
+msgstr "ユーザーを承èªã™ã‚‹"
msgid "AdminUsers|Approved users can:"
-msgstr ""
+msgstr "承èªã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™:"
msgid "AdminUsers|Are you sure?"
-msgstr ""
+msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "AdminUsers|Automatically marked as default internal user"
-msgstr ""
+msgstr "自動的ã«ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å†…部ユーザーã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
msgid "AdminUsers|Be added to groups and projects"
-msgstr ""
+msgstr "グループã¨ãƒ—ロジェクトã«è¿½åŠ ã™ã‚‹"
msgid "AdminUsers|Block"
msgstr "ブロック"
msgid "AdminUsers|Block this user"
-msgstr ""
+msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’ブロックã™ã‚‹"
msgid "AdminUsers|Block user"
msgstr "ブロックユーザー"
@@ -2030,7 +2087,7 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "ユーザーã®ãƒ–ロックã«ã¯æ¬¡ã®åŠ¹æžœãŒã‚ã‚Šã¾ã™:"
msgid "AdminUsers|Cannot sign in or access instance information"
-msgstr ""
+msgstr "サインインã¾ãŸã¯ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹æƒ…å ±ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "LDAP ã§ãƒ–ロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’ブロック解除ã§ãã¾ã›ã‚“"
@@ -2295,37 +2352,37 @@ 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 ""
+msgstr "ã™ã¹ã¦ã®ç›£è¦–ツールã‹ã‚‰ã®ã‚¢ãƒ©ãƒ¼ãƒˆã‚’ GitLab 内ã§ç›´æŽ¥è¡¨ç¤ºã—ã¾ã™ã€‚アラートã®èª¿æŸ»ã¨ã‚¤ãƒ³ã‚·ãƒ‡ãƒ³ãƒˆã¸ã®ã‚¨ã‚¹ã‚«ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’åˆç†åŒ–ã—ã¾ã™ã€‚"
msgid "AlertManagement|Edit"
-msgstr ""
+msgstr "編集"
msgid "AlertManagement|Environment"
-msgstr ""
+msgstr "環境"
msgid "AlertManagement|Events"
msgstr "イベント"
msgid "AlertManagement|High"
-msgstr ""
+msgstr "高"
msgid "AlertManagement|Incident"
-msgstr ""
+msgstr "インシデント"
msgid "AlertManagement|Info"
-msgstr ""
+msgstr "情報"
msgid "AlertManagement|Key"
-msgstr ""
+msgstr "キー"
msgid "AlertManagement|Low"
-msgstr ""
+msgstr "低"
msgid "AlertManagement|Medium"
-msgstr ""
+msgstr "中"
msgid "AlertManagement|Metrics"
-msgstr ""
+msgstr "メトリクス"
msgid "AlertManagement|Metrics weren't available in the alerts payload."
msgstr ""
@@ -2334,25 +2391,22 @@ msgid "AlertManagement|More information"
msgstr "詳細情報"
msgid "AlertManagement|No alert data to display."
-msgstr ""
+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 ""
+msgstr "表示ã™ã‚‹ã‚¢ãƒ©ãƒ¼ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "AlertManagement|None"
-msgstr ""
+msgstr "ãªã—"
msgid "AlertManagement|Open"
-msgstr ""
-
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
+msgstr "é–‹ã"
msgid "AlertManagement|Please try again."
-msgstr ""
+msgstr "ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "AlertManagement|Reported %{when}"
msgstr ""
@@ -2361,22 +2415,22 @@ msgid "AlertManagement|Reported %{when} by %{tool}"
msgstr ""
msgid "AlertManagement|Resolved"
-msgstr ""
+msgstr "解決済ã¿"
msgid "AlertManagement|Runbook"
msgstr ""
msgid "AlertManagement|Service"
-msgstr ""
+msgstr "サービス"
msgid "AlertManagement|Severity"
-msgstr ""
+msgstr "é‡è¦åº¦"
msgid "AlertManagement|Start time"
msgstr "開始時間"
msgid "AlertManagement|Status"
-msgstr ""
+msgstr "状態"
msgid "AlertManagement|Surface alerts in GitLab"
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr "ã™ã¹ã¦ã®ãƒ–ランãƒ"
msgid "All changes are committed"
msgstr "ã™ã¹ã¦ã®å¤‰æ›´ãŒã‚³ãƒŸãƒƒãƒˆã•ã‚Œã¦ã„ã¾ã™"
-msgid "All default stages are currently visible"
-msgstr "ç¾åœ¨ã€ã™ã¹ã¦ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚¹ãƒ†ãƒ¼ã‚¸ã‚’表示ã—ã¦ã„ã¾ã™"
-
msgid "All email addresses will be used to identify your commits."
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã‚ãªãŸã®ã‚³ãƒŸãƒƒãƒˆã‚’識別ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
@@ -2700,10 +2736,10 @@ msgid "All groups and projects"
msgstr "全グループã¨ãƒ—ロジェクト"
msgid "All issues for this milestone are closed."
-msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®èª²é¡Œã‚’完了ã—ã¾ã—ãŸã€‚"
+msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’完了ã—ã¾ã—ãŸã€‚"
msgid "All issues for this milestone are closed. You may close this milestone now."
-msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«é–¢ã™ã‚‹èª²é¡Œã¯ã™ã¹ã¦è§£æ±ºã•ã‚Œã¾ã—ãŸã€‚ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’クローズã§ãã¾ã™ã€‚"
+msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«é–¢ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã¯ã™ã¹ã¦è§£æ±ºã•ã‚Œã¾ã—ãŸã€‚ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’クローズã§ãã¾ã™ã€‚"
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr "ã™ã¹ã¦ã®ç«¶åˆãŒè§£æ±ºã•ã‚Œã¾ã—ãŸã€‚マージリクエストをマージã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -2744,6 +2780,9 @@ msgstr "グループオーナー㌠LDAP 関連ã®è¨­å®šã‚’管ç†ã§ãるよã†
msgid "Allow only the selected protocols to be used for Git access."
msgstr "é¸æŠžã—ãŸãƒ—ロトコルã®ã¿ã‚’ Git アクセスã«ä½¿ç”¨ã§ãるよã†ã«ã—ã¾ã™ã€‚"
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2874,7 +2913,7 @@ msgid "An email notification was recently sent from the admin panel. Please wait
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 "GitLab ユーザフィールドãŒç©ºã®å ´åˆã€ã™ã¹ã¦ã®å•é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã®èª¬æ˜Žã« FogBugz ユーザã®ãƒ•ãƒ«ãƒãƒ¼ãƒ  (例ãˆã°ã€By John Smith)を追加ã—ã¾ã™ã€‚ã¾ãŸã€ã“れらã®å•é¡Œã‚„コメントをプロジェクト作æˆè€…ã«é–¢é€£ä»˜ã‘ã‚‹ã‹ã€ã¾ãŸã¯å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
+msgstr "GitLab ユーザフィールドãŒç©ºã®å ´åˆã€ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¨ã‚³ãƒ¡ãƒ³ãƒˆã®èª¬æ˜Žã« FogBugz ユーザã®ãƒ•ãƒ«ãƒãƒ¼ãƒ  (例ãˆã°ã€By John Smith)を追加ã—ã¾ã™ã€‚ã¾ãŸã€ã“れらã®å•é¡Œã‚„コメントをプロジェクト作æˆè€…ã«é–¢é€£ä»˜ã‘ã‚‹ã‹ã€ã¾ãŸã¯å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
msgid "An empty index will be created if one does not already exist"
msgstr ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,8 +2957,11 @@ 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 "課題ã®ã‚¦ã‚¨ã‚¤ãƒˆæ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgstr "イシューã®ã‚¦ã‚§ã‚¤ãƒˆæ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
msgstr ""
@@ -2930,6 +2972,9 @@ 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 ""
@@ -2979,7 +3024,7 @@ msgid "An error occurred while fetching folder content."
msgstr "フォルダã®ä¸­èº«ã®å–å¾—ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching issues."
-msgstr "課題ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgstr "イシューã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching label colors."
msgstr "ラベルã®è‰²ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3072,7 +3117,7 @@ msgid "An error occurred while loading group members."
msgstr "グループメンãƒãƒ¼ã®èª­ã¿è¾¼ã‚€é–“ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ."
msgid "An error occurred while loading issues"
-msgstr "課題ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgstr "イシューã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while loading merge requests."
msgstr "マージリクエストã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3114,7 +3159,7 @@ msgid "An error occurred while making the request."
msgstr "リクエスト作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while moving the issue."
-msgstr "課題ã®ç§»å‹•ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgstr "イシューã®ç§»å‹•ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while parsing recent searches"
msgstr "検索履歴ã®è§£æžä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3126,7 +3171,7 @@ msgid "An error occurred while removing epics."
msgstr "エピックã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while removing issues."
-msgstr "課題ã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgstr "イシューã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while rendering preview broadcast message"
msgstr "プレビュー時ã®ãƒ–ロードキャストメッセージをレンダリングã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3135,7 +3180,7 @@ msgid "An error occurred while rendering the editor"
msgstr ""
msgid "An error occurred while reordering issues."
-msgstr "課題ã®ä¸¦ã¹æ›¿ãˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgstr "イシューã®ä¸¦ã¹æ›¿ãˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while requesting data from the Jira service"
msgstr ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "LDAP ã®ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰çŠ¶æ…‹ã‚’ä¿å­˜ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
-
msgid "An error occurred while saving assignees"
msgstr "担当者ã®ç™»éŒ²ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,8 +3251,8 @@ 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 "GitLab ã¨çµ±åˆã•ã‚ŒãŸ Kubernetes クラスターを管ç†ã™ã‚‹ãŸã‚ã®ã‚µãƒ³ãƒ—ルプロジェクト。"
+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 ""
@@ -3216,7 +3264,10 @@ 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 "課題ã¯ã€ãƒ—ロジェクトã§è­°è«–ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ãƒã‚°ã€todoã€ã¾ãŸã¯æ©Ÿèƒ½ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãã®ä¸Šã€èª²é¡Œã¯æ¤œç´¢ã§ãã€ãƒ•ã‚£ãƒ«ã‚¿ã§ãã¾ã™ã€‚"
+msgstr "イシューã¯ã€ãƒ—ロジェクトã§è­°è«–ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ãƒã‚°ã€todoã€ã¾ãŸã¯æ©Ÿèƒ½ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãã®ä¸Šã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¯æ¤œç´¢ã§ãã€ãƒ•ã‚£ãƒ«ã‚¿ã§ãã¾ã™ã€‚"
+
+msgid "An issue title is required"
+msgstr ""
msgid "An unauthenticated user"
msgstr ""
@@ -3267,7 +3318,7 @@ 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 "別ã®èª²é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ã‚’ã™ã§ã«ä½¿ç”¨ã—ã¦ã„ã¾ã™ã€‚一度ã«ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ã§ãる課題トラッカーサービスã¯1ã¤ã ã‘ã§ã™"
+msgstr "別ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãƒˆãƒ©ãƒƒã‚«ãƒ¼ã‚’ã™ã§ã«ä½¿ç”¨ã—ã¦ã„ã¾ã™ã€‚一度ã«ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ã§ãるイシュートラッカーサービスã¯1ã¤ã ã‘ã§ã™"
msgid "Anti-spam verification"
msgstr "スパム対策ã®æ¤œè¨¼"
@@ -3296,8 +3347,8 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
-msgstr "ã“ã®ãƒ—ロジェクトã®é–‹ç™ºè€…ã¾ãŸã¯ãれ以上ã®æ¨©é™ã‚’æŒã¤ãƒ¡ãƒ³ãƒãƒ¼ã€‚"
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
msgid "Any milestone"
msgstr ""
@@ -3393,7 +3444,7 @@ msgid "Applying"
msgstr ""
msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
-msgstr "テンプレートをé©ç”¨ã™ã‚‹ã¨ã€æ—¢å­˜ã®èª²é¡Œã®èª¬æ˜ŽãŒç½®ãæ›ãˆã‚‰ã‚Œã¾ã™ã€‚ è¡Œã£ãŸå¤‰æ›´ã¯ã™ã¹ã¦å¤±ã‚ã‚Œã¾ã™ã€‚"
+msgstr "テンプレートをé©ç”¨ã™ã‚‹ã¨ã€æ—¢å­˜ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®èª¬æ˜ŽãŒç½®ãæ›ãˆã‚‰ã‚Œã¾ã™ã€‚ è¡Œã£ãŸå¤‰æ›´ã¯ã™ã¹ã¦å¤±ã‚ã‚Œã¾ã™ã€‚"
msgid "Applying command"
msgstr "コマンドをé©ç”¨"
@@ -3441,15 +3492,15 @@ msgstr[0] "%{membersCount} åã®ã†ã¡ %{count} åã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "承èªè€…"
msgid "ApprovalRule|Name"
msgstr "åå‰"
-msgid "ApprovalRule|No. approvals required"
-msgstr "å¿…è¦ãªæ‰¿èªã®æ•°"
-
msgid "ApprovalRule|Rule name"
msgstr "ルールå"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3538,7 +3592,7 @@ 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}"
+msgstr "プロジェクトをアーカイブã«ã™ã‚‹ã¨ã€ãƒ—ロジェクトã¯å®Œå…¨ã«èª­ã¿å–り専用ã«ãªã‚Šã¾ã™ã€‚ ã¾ãŸã€ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã‹ã‚‰è¡¨ç¤ºã•ã‚Œãšã€æ¤œç´¢ã§ã‚‚表示ã•ã‚Œã¾ã›ã‚“。 %{strong_start}ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã¯ã‚³ãƒŸãƒƒãƒˆã§ãã¾ã›ã‚“ã—ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚„コメントã¾ãŸä»–ã®ã‚¨ãƒ³ãƒ†ã‚£ãƒ†ã‚£ã‚’作æˆã§ãã¾ã›ã‚“。 %{strong_end}"
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
@@ -3553,7 +3607,7 @@ msgid "Are you sure you want to cancel editing this comment?"
msgstr "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã®ç·¨é›†ã‚’キャンセルã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to close this blocked issue?"
-msgstr "ã“ã®ãƒ–ロックã•ã‚Œã¦ã„る課題をクローズã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgstr "ã“ã®ãƒ–ロックã•ã‚Œã¦ã„るイシューをクローズã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to delete \"%{name}\" Value Stream?"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr "本当ã«ã“ã® %{typeOfComment} を削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "本当ã«ã“ã®ãƒœãƒ¼ãƒ‰ã‚’削除ã—ã¾ã™ã‹?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "本当ã«ã€ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹? ã“ã®æ“作ã¯å…ƒã«æˆ»ã™ã“ã¨ãŒã§ãã¾ã›ã‚“。"
@@ -3599,7 +3650,7 @@ msgid "Are you sure you want to lose unsaved changes?"
msgstr "変更ãŒä¿å­˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒç ´æ£„ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to lose your issue information?"
-msgstr "本当ã«èª²é¡Œæƒ…報を削除ã—ã¾ã™ã‹?"
+msgstr "本当ã«ã‚¤ã‚·ãƒ¥ãƒ¼æƒ…報を削除ã—ã¾ã™ã‹?"
msgid "Are you sure you want to merge immediately?"
msgstr "本当ã«ã™ãã«ãƒžãƒ¼ã‚¸ã—ã¾ã™ã‹ï¼Ÿ"
@@ -3739,8 +3790,14 @@ msgstr "ラベルを割り当ã¦ã‚‹"
msgid "Assign milestone"
msgstr "マイルストーンを割り当ã¦ã‚‹"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
-msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ã„ãã¤ã‹ã®èª²é¡Œã‚’割り当ã¦ã¾ã™ã€‚"
+msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ã„ãã¤ã‹ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’割り当ã¦ã¾ã™ã€‚"
msgid "Assign to"
msgstr "割り当ã¦å…ˆ"
@@ -3749,20 +3806,26 @@ msgid "Assign to commenting user"
msgstr ""
msgid "Assign yourself to these issues"
-msgstr "ã“れらã®èª²é¡Œã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
+msgstr "ã“れらã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
msgid "Assign yourself to this issue"
-msgstr "ã“ã®èª²é¡Œã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
msgid "Assigned %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} を割り当ã¦ã¾ã—ãŸã€‚"
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
-msgstr "割り当ã¦ã‚‰ã‚ŒãŸèª²é¡Œ"
+msgstr "割り当ã¦ã‚‰ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Assigned Merge Requests"
msgstr "割り当ã¦ã‚‰ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "自分ã«å‰²ã‚Šå½“ã¦ã‚‹"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3786,7 +3852,7 @@ msgid "Assignee lists not available with your current license"
msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯æ‹…当者リストを利用ã§ãã¾ã›ã‚“"
msgid "Assignee lists show all issues assigned to the selected user."
-msgstr "担当者一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®èª²é¡ŒãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
+msgstr "担当者一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "Assignee(s)"
msgstr "担当者"
@@ -3797,6 +3863,9 @@ msgstr ""
msgid "Assigns %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} を割り当ã¦ã¾ã™ã€‚"
+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 "ãã‚Œãžã‚Œã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’変更ã™ã‚‹ã«ã¯ã€CODEOWNERã®ãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã€å°‘ãªãã¨ã‚‚1åã®ã‚³ãƒ¼ãƒ‰æ‰€æœ‰è€…ã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚"
@@ -3840,9 +3909,6 @@ msgstr "監査イベント"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr "監査イベントã¯ã€GitLab ã§ç™ºç”Ÿã—ãŸé‡è¦ãªã‚¤ãƒ™ãƒ³ãƒˆã‚’追跡ã—続ã‘る方法ã§ã™ã€‚"
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3997,14 +4063,14 @@ msgid "Auto-cancel redundant, pending pipelines"
msgstr "冗長・ä¿ç•™ä¸­ã®ãƒ‘イプラインを自動キャンセル"
msgid "Auto-close referenced issues on default branch"
-msgstr "デフォルトã®ãƒ–ランãƒã§å‚ç…§ã•ã‚Œã¦ã„る課題を自動的ã«çµ‚了ã—ã¾ã™ã€‚"
+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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr "Auto DevOps ã¯ã‚らã‹ã˜ã‚定義ã•ã‚ŒãŸç¶™ç¶šçš„インテグレーションã¨ãƒ‡ãƒªãƒãƒªãƒ¼ã®è¨­å®šã«åŸºã¥ã„ã¦ã€ã‚¢ãƒ—リケーションを自動的ã«ãƒ“ルドã€ãƒ†ã‚¹ãƒˆã€ãƒ‡ãƒ—ロイã—ã¾ã™ã€‚ %{auto_devops_start}Auto DevOps ã®è©³ç´°%{auto_devops_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。ã¾ãŸã¯%{quickstart_start} クイックスタートガイド %{quickstart_end} ã§æ­£ã—ã„方法を学ã³ã¾ã—ょã†ã€‚"
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto DevOps ドキュメント"
@@ -4023,10 +4089,13 @@ 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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr "Let's Encryptを用ã„ãŸè‡ªå‹•è¨¼æ˜Žæ›¸ç®¡ç†"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr "背景色"
msgid "Badges"
msgstr "ãƒãƒƒã‚¸"
-msgid "Badges|A new badge was added."
-msgstr "æ–°ã—ã„ãƒãƒƒã‚¸ãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸã€‚"
-
msgid "Badges|Add badge"
msgstr "ãƒãƒƒã‚¸ã‚’追加"
@@ -4146,12 +4212,21 @@ msgstr "ãƒãƒƒã‚¸ç”»åƒã®URL"
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 "グループãƒãƒƒã‚¸"
@@ -4161,15 +4236,15 @@ 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|Please fill in a valid URL"
-msgstr "有効㪠URL を入力ã—ã¦ãã ã•ã„。"
-
msgid "Badges|Project Badge"
msgstr "プロジェクト ãƒãƒƒã‚¸"
@@ -4182,15 +4257,12 @@ msgstr "変更ã®ä¿å­˜"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "ãƒãƒƒã‚¸ã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚入力ã—ãŸURLを確èªã—ã¦ã€ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "GitLabã¯æ¬¡ã® %{docsLinkStart}変数%{docsLinkEnd} をサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "ãƒãƒƒã‚¸ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
-msgid "Badges|The badge was saved."
-msgstr "ãƒãƒƒã‚¸ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸã€‚"
-
msgid "Badges|This group has no badges"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ãƒãƒƒã‚¸ã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "ãƒãƒƒã‚¸"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "例 %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Balsamiq ファイルを読ã¿è¾¼ã¿ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -4230,9 +4299,6 @@ msgstr "Bambooã§è‡ªå‹•ãƒªãƒ“ジョンラベリングã¨ãƒªãƒã‚¸ãƒˆãƒªãƒˆãƒªã‚¬
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®åå‰ç©ºé–“を変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "アップグレード"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4358,7 +4430,7 @@ msgid_plural "Blocked by %d issues"
msgstr[0] ""
msgid "Blocked issue"
-msgstr "ブロックã•ã‚ŒãŸèª²é¡Œ"
+msgstr "ブロックã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Blocking issues"
msgstr ""
@@ -4369,11 +4441,20 @@ msgstr "ブロック"
msgid "Blog"
msgstr "ブログ"
-msgid "Board scope"
-msgstr "ボードスコープ"
-
msgid "Board scope affects which issues are displayed for anyone who visits this board"
-msgstr "ボードã®ç¯„囲ã¯ã€ã“ã®ãƒœãƒ¼ãƒ‰ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãŸä»»æ„ã®äººã«è¡¨ç¤ºã•ã‚Œã‚‹ã€èª²é¡Œã«å½±éŸ¿ã—ã¾ã™"
+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 "ボード"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr "ブランãƒå"
msgid "Branch not loaded - %{branchId}"
msgstr "%{branchId} ブランãƒã¯ãƒ­ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
-msgid "Branch prefix"
-msgstr "ブランãƒãƒ—レフィックス"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ブランãƒã‚’検索"
@@ -4627,6 +4729,24 @@ msgstr "ビルトイン"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4643,10 +4763,10 @@ msgid "Burndown charts are now fixed. This means that removing issues from a mil
msgstr ""
msgid "BurndownChartLabel|Open issue weight"
-msgstr "課題ã®é‡ã¿ã‚’é–‹ã"
+msgstr "イシューã®ã‚¦ã‚§ã‚¤ãƒˆã‚’é–‹ã"
msgid "BurndownChartLabel|Open issues"
-msgstr "未解決ã®èª²é¡Œ"
+msgstr "未解決ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Burnup chart"
msgstr ""
@@ -4720,7 +4840,10 @@ msgstr "外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD"
msgid "CI/CD settings"
msgstr "CI/CD 設定"
-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."
+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"
@@ -4747,12 +4870,12 @@ 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 "ãã®ä»–ã« CI 設定ファイルãŒè¦‹ã¤ã‹ã‚‰ãªã„å ´åˆã€Auto DevOps パイプラインãŒå®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr "ã‚ãªãŸã®ãƒ‡ãƒ—ロイ戦略を動作ã•ã›ã‚‹ã«ã¯ã€%{base_domain_link_start} ベースドメイン %{link_end} ã‚’ %{kubernetes_cluster_link_start} Kubernetesクラスター %{link_end} ã«è¿½åŠ ã—ã¦ãã ã•ã„。"
-
msgid "CICD|group enabled"
msgstr "グループã¯æœ‰åŠ¹ã§ã™"
@@ -4780,9 +4903,6 @@ msgstr "コールãƒãƒƒã‚¯ URL"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr "マージリクエストã”ã¨ã«å¿…è¦ãªæ‰¿èªè€…ã¨æ‰¿èªã‚’上書ãã§ãã¾ã™"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 "キャンセル"
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr "プレビューをキャンセル"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "自動的ã«ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
@@ -4871,7 +5018,7 @@ msgid "Cannot have multiple unresolved alerts"
msgstr ""
msgid "Cannot import because issues are not available in this project."
-msgstr "ã“ã®ãƒ—ロジェクトã«ã¯èª²é¡ŒãŒãªã„ãŸã‚ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。"
+msgstr "ã“ã®ãƒ—ロジェクトã«ã¯ã‚¤ã‚·ãƒ¥ãƒ¼ãŒãªã„ãŸã‚ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。"
msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
@@ -4889,10 +5036,10 @@ msgid "Cannot modify provider during creation"
msgstr "作æˆä¸­ã¯ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‚’修正・変更ã§ãã¾ã›ã‚“"
msgid "Cannot promote issue because it does not belong to a group."
-msgstr "グループã«æ‰€å±žã—ã¦ã„ãªã„ãŸã‚ã€èª²é¡Œã‚’プロモートã§ãã¾ã›ã‚“。"
+msgstr "グループã«æ‰€å±žã—ã¦ã„ãªã„ãŸã‚ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’プロモートã§ãã¾ã›ã‚“。"
msgid "Cannot promote issue due to insufficient permissions."
-msgstr "権é™ãŒä¸å分ãªãŸã‚ã€èª²é¡Œã‚’プロモートã§ãã¾ã›ã‚“。"
+msgstr "権é™ãŒä¸å分ãªãŸã‚ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’プロモートã§ãã¾ã›ã‚“。"
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 "コミット済ã®å¤‰æ›´ã‚’ revert ã™ã‚‹ãŸã‚ã«æ–°ã—ã„コミットを作æˆã—ã¾ã™"
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr "担当者を変更ã—ã¾ã—ãŸã€‚"
@@ -5014,13 +5179,16 @@ 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 "タイトルを \"%{title_param}\" ã«å¤‰æ›´ã—ã¾ã™ã€‚"
-msgid "Changes were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr "ãƒãƒ£ãƒ¼ãƒˆ"
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr "グラフを表示ã§ãã¾ã›ã‚“。データリクエストãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ãŸãŸã‚ã§ã™ã€‚%{documentationLink}"
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5321,7 +5492,7 @@ 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 "表示レベルã€ãƒ—ロジェクト機能(課題ã€ãƒªãƒã‚¸ãƒˆãƒªã€Wikiã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆ) ã®æœ‰åŠ¹/無効や権é™ã®è¨­å®š"
+msgstr "表示レベルã€ãƒ—ロジェクト機能(イシューã€ãƒªãƒã‚¸ãƒˆãƒªã€Wikiã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆ) ã®æœ‰åŠ¹/無効や権é™ã®è¨­å®š"
msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr "クローン"
msgid "Clone repository"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’クローン"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "%{http_label} ã§ã‚¯ãƒ­ãƒ¼ãƒ³"
@@ -5575,6 +5749,18 @@ msgstr "KRB5 ã§ã‚¯ãƒ­ãƒ¼ãƒ³"
msgid "Clone with SSH"
msgstr "SSH ã§ã‚¯ãƒ­ãƒ¼ãƒ³"
+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 "クローズã™ã‚‹"
@@ -5606,7 +5792,7 @@ msgid "Closed epics"
msgstr ""
msgid "Closed issues"
-msgstr "クローズã—ãŸèª²é¡Œ"
+msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Closed this %{quick_action_target}."
msgstr "%{quick_action_target} ã‚’é–‰ã˜ãŸã€‚"
@@ -6682,12 +6868,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "コードオーナー"
-msgid "Code Owners to the merge request changes."
-msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«å¯¾ã™ã‚‹ã‚³ãƒ¼ãƒ‰ã‚ªãƒ¼ãƒŠãƒ¼ã€‚"
-
msgid "Code Quality"
msgstr ""
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7026,7 +7230,7 @@ msgid "Configure existing installation"
msgstr "既存ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’設定ã™ã‚‹"
msgid "Configure limit for issues created per minute by web and API requests."
-msgstr "Web 㨠API リクエストã«ã‚ˆã£ã¦1分ã‚ãŸã‚Šã«ä½œæˆã•ã‚Œã‚‹èª²é¡Œã®åˆ¶é™ã‚’設定ã—ã¾ã™ã€‚"
+msgstr "Webã¨APIリクエストã«ã‚ˆã£ã¦1分ã‚ãŸã‚Šã«ä½œæˆã•ã‚Œã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã®åˆ¶é™ã‚’設定ã—ã¾ã™ã€‚"
msgid "Configure limits for Project/Group Import/Export."
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "ãŠã‚ã§ã¨ã†ã”ã–ã„ã¾ã™ã€‚2è¦ç´ èªè¨¼ãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã—ãŸã€‚"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "接続"
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Docker接続エラー"
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr "有効期é™ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«:"
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr "ログイン"
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr "ä¿æŒã™ã‚‹ã‚¿ã‚°ã®æ•°:"
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "コンテナレジストリã§ã€å„プロジェクトã¯Dockerイメージを格ç´ã™ã‚‹å ´æ‰€ã‚’æŒã¦ã¾ã™ã€‚%{docLinkStart} 詳細ã¯ã“ã¡ã‚‰ %{docLinkEnd}"
@@ -7473,10 +7686,10 @@ msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %
msgstr ""
msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
-msgstr "%{start_date} 以é™ã®ã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ プッシュã«ã¤ã„ã¦ã®è²¢çŒ®åº¦åˆ†æž"
+msgstr "%{start_date} 以é™ã®ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ プッシュã«ã¤ã„ã¦ã®è²¢çŒ®åº¦åˆ†æž"
msgid "ContributionAnalytics|Issues"
-msgstr "課題"
+msgstr "イシュー"
msgid "ContributionAnalytics|Last 3 months"
msgstr "éŽåŽ»3ã‹æœˆ"
@@ -7491,7 +7704,7 @@ msgid "ContributionAnalytics|Merge Requests"
msgstr "マージリクエスト"
msgid "ContributionAnalytics|No issues for the selected time period."
-msgstr "é¸æŠžã•ã‚ŒãŸæœŸé–“内ã«èª²é¡Œã¯ã‚ã‚Šã¾ã›ã‚“"
+msgstr "é¸æŠžã•ã‚ŒãŸæœŸé–“内ã«ã‚¤ã‚·ãƒ¥ãƒ¼ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "ContributionAnalytics|No merge requests for the selected time period."
msgstr "é¸æŠžã•ã‚ŒãŸæœŸé–“内ã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -7565,6 +7778,9 @@ msgstr "URL をコピー"
msgid "Copy branch name"
msgstr "ブランãƒåをコピー"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "コピーコマンド"
@@ -7593,7 +7809,7 @@ msgid "Copy labels and milestone from %{source_issuable_reference}."
msgstr "%{source_issuable_reference} ã‹ã‚‰ãƒ©ãƒ™ãƒ«ã¨ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’コピー。"
msgid "Copy labels and milestone from other issue or merge request in this project"
-msgstr "ã“ã®ãƒ—ロジェクトã®ä»–ã®èª²é¡Œã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‹ã‚‰ãƒ©ãƒ™ãƒ«ã¨ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’コピーã™ã‚‹"
+msgstr "ã“ã®ãƒ—ロジェクトã®ä»–ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‹ã‚‰ãƒ©ãƒ™ãƒ«ã¨ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’コピーã™ã‚‹"
msgid "Copy link"
msgstr "リンクをコピー"
@@ -7783,7 +7999,7 @@ msgid "Create a new file as there are no files yet. Afterwards, you'll be able t
msgstr "ã¾ã ãƒ•ã‚¡ã‚¤ãƒ«ãŒãªã„ãŸã‚ã€æ–°ã—ã„ファイルを作æˆã—ã¾ã™ã€‚ ãã®å¾Œã€ã‚ãªãŸã¯å¤‰æ›´ã‚’コミットã§ãã¾ã™ã€‚"
msgid "Create a new issue"
-msgstr "課題ã®æ–°è¦ä½œæˆ"
+msgstr "イシューã®æ–°è¦ä½œæˆ"
msgid "Create a new repository"
msgstr "æ–°ã—ã„リãƒã‚¸ãƒˆãƒªã‚’作æˆ"
@@ -7797,15 +8013,12 @@ msgstr ""
msgid "Create an account using:"
msgstr "アカウントを作æˆã™ã‚‹ã€‚ãã®æ–¹æ³•:"
-msgid "Create an issue. Issues are created for each alert triggered."
-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 board"
-msgstr "ボードを作æˆ"
-
msgid "Create branch"
msgstr "ブランãƒä½œæˆ"
@@ -7840,13 +8053,13 @@ msgid "Create group label"
msgstr "グループラベルを作æˆ"
msgid "Create issue"
-msgstr "課題ã®ä½œæˆ"
+msgstr "イシューã®ä½œæˆ"
msgid "Create iteration"
msgstr ""
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr "ラベルã‹ã‚‰ãƒªã‚¹ãƒˆã‚’作æˆã€‚ãã®ãƒ©ãƒ™ãƒ«ã®èª²é¡ŒãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
+msgstr "ラベルã‹ã‚‰ãƒªã‚¹ãƒˆã‚’作æˆã€‚ãã®ãƒ©ãƒ™ãƒ«ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "Create merge request"
msgstr "マージリクエストを作æˆ"
@@ -7863,9 +8076,6 @@ msgstr "æ–°è¦ä½œæˆ "
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "æ–°ã—ã„ボードを作æˆ"
-
msgid "Create new branch"
msgstr "æ–°ã—ã„ブランãƒã‚’作æˆ"
@@ -7929,6 +8139,84 @@ msgstr "ã‚¿ã‚°"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "個人用アクセストークンを作æˆ"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "作æˆæ¸ˆã¿"
@@ -7942,10 +8230,10 @@ msgid "Created On"
msgstr "作æˆæ—¥æ™‚"
msgid "Created a branch and a merge request to resolve this issue."
-msgstr "ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã¾ã—ãŸã€‚ã“ã‚Œã§ã“ã®èª²é¡Œã‚’解決ã§ãã¾ã™ã€‚"
+msgstr "ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã¾ã—ãŸã€‚ã“ã‚Œã§ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’解決ã§ãã¾ã™ã€‚"
msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
-msgstr "'%{branch_name}' ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã¾ã—ãŸã€‚ã“ã‚Œã§ã“ã®èª²é¡Œã‚’解決ã§ãã¾ã™ã€‚"
+msgstr "'%{branch_name}' ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã¾ã—ãŸã€‚ã“ã‚Œã§ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’解決ã§ãã¾ã™ã€‚"
msgid "Created by %{job}"
msgstr ""
@@ -7960,10 +8248,10 @@ msgid "Created date"
msgstr ""
msgid "Created issue %{issueLink}"
-msgstr "作æˆã—ãŸèª²é¡Œ %{issueLink}"
+msgstr "作æˆã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼ %{issueLink}"
msgid "Created issue %{issueLink} at %{projectLink}"
-msgstr "%{projectLink} ã«èª²é¡Œ %{issueLink} を作æˆã—ã¾ã—ãŸ"
+msgstr "%{projectLink} ã«ã‚¤ã‚·ãƒ¥ãƒ¼ %{issueLink} を作æˆã—ã¾ã—ãŸ"
msgid "Created merge request %{mergeRequestLink}"
msgstr "作æˆã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ %{mergeRequestLink}"
@@ -7981,10 +8269,10 @@ msgid "Created on:"
msgstr "作æˆæ—¥æ™‚:"
msgid "Creates a branch and a merge request to resolve this issue."
-msgstr "ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã¦ã€ã“ã®èª²é¡Œã‚’解決ã—ã¾ã™ã€‚"
+msgstr "ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã¦ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’解決ã—ã¾ã™ã€‚"
msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
-msgstr "'%{branch_name}' ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã€ã“ã®èª²é¡Œã‚’解決ã—ã¾ã™ã€‚"
+msgstr "'%{branch_name}' ブランãƒã‚’作æˆã—マージリクエストを作æˆã—ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’解決ã—ã¾ã™ã€‚"
msgid "Creating"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr "Crossplane"
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "ç¾åœ¨ã®ãƒ–ランãƒ"
@@ -8106,45 +8397,18 @@ msgstr "ステージを追加"
msgid "CustomCycleAnalytics|Editing stage"
msgstr "ステージã®ç·¨é›†"
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr "ステージã®åå‰ã‚’入力ã—ã¦ãã ã•ã„"
-
-msgid "CustomCycleAnalytics|Name"
-msgstr "åå‰"
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr "新ステージ"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr "開始イベントを先ã«é¸æŠžã—ã¦ãã ã•ã„。"
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr "開始イベントをé¸æŠžã—ã¦ãã ã•ã„。"
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr "åœæ­¢ã‚¤ãƒ™ãƒ³ãƒˆã‚’é¸æŠžã—ã¦ãã ã•ã„。"
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr "ãã®ã‚¹ãƒ†ãƒ¼ã‚¸åã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™"
-msgid "CustomCycleAnalytics|Start event"
-msgstr "開始イベント"
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr "開始イベントãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚有効ãªåœæ­¢ã‚¤ãƒ™ãƒ³ãƒˆã‚’é¸æŠžã—ã¦ãã ã•ã„。"
-
msgid "CustomCycleAnalytics|Start event label"
msgstr "開始イベントã®ãƒ©ãƒ™ãƒ«"
-msgid "CustomCycleAnalytics|Stop event"
-msgstr "åœæ­¢ã‚¤ãƒ™ãƒ³ãƒˆ"
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr "åœæ­¢ã‚¤ãƒ™ãƒ³ãƒˆã®ãƒ©ãƒ™ãƒ«"
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr "ステージã®æ›´æ–°"
-
msgid "Customer Portal"
msgstr ""
@@ -8185,31 +8449,31 @@ msgid "Cycle Time"
msgstr ""
msgid "CycleAnalyticsEvent|Issue closed"
-msgstr "完了ã—ãŸèª²é¡Œ"
+msgstr "完了ã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Issue created"
-msgstr "作æˆã•ã‚ŒãŸèª²é¡Œ"
+msgstr "作æˆã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Issue first added to a board"
-msgstr "ボードã«æœ€åˆã«åŠ ãˆã‚‰ã‚ŒãŸèª²é¡Œ"
+msgstr "ボードã«æœ€åˆã«åŠ ãˆã‚‰ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
-msgstr "マイルストーンã«æœ€åˆã«é–¢é€£ä»˜ã‘られãŸèª²é¡Œ"
+msgstr "マイルストーンã«æœ€åˆã«é–¢é€£ä»˜ã‘られãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
-msgstr "最åˆã«ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«é–¢é€£ã¥ã‘られãŸèª²é¡Œã€ã¾ãŸã¯æœ€åˆã«ãƒœãƒ¼ãƒ‰ã«åŠ ãˆã‚‰ã‚ŒãŸèª²é¡Œ"
+msgstr "最åˆã«ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«é–¢é€£ã¥ã‘られãŸã‚¤ã‚·ãƒ¥ãƒ¼ã€ã¾ãŸã¯æœ€åˆã«ãƒœãƒ¼ãƒ‰ã«åŠ ãˆã‚‰ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
-msgstr "コミットã§æœ€åˆã«è¨€åŠã•ã‚ŒãŸèª²é¡Œ"
+msgstr "コミットã§æœ€åˆã«è¨€åŠã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Issue label was added"
-msgstr "追加ã•ã‚ŒãŸèª²é¡Œãƒ©ãƒ™ãƒ«"
+msgstr "追加ã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼ãƒ©ãƒ™ãƒ«"
msgid "CycleAnalyticsEvent|Issue label was removed"
-msgstr "削除ã•ã‚ŒãŸèª²é¡Œãƒ©ãƒ™ãƒ«"
+msgstr "削除ã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼ãƒ©ãƒ™ãƒ«"
msgid "CycleAnalyticsEvent|Issue last edited"
-msgstr "最後ã«ç·¨é›†ã•ã‚ŒãŸèª²é¡Œ"
+msgstr "最後ã«ç·¨é›†ã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "CycleAnalyticsEvent|Merge request closed"
msgstr "クローズã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -8245,7 +8509,7 @@ msgid "CycleAnalyticsStage|Code"
msgstr "コード"
msgid "CycleAnalyticsStage|Issue"
-msgstr "課題"
+msgstr "イシュー"
msgid "CycleAnalyticsStage|Plan"
msgstr "計画"
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8696,7 +8972,7 @@ msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
-msgstr "課題ã®ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®èª¬æ˜Žãƒ†ãƒ³ãƒ—レート"
+msgstr "イシューã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®èª¬æ˜Žãƒ†ãƒ³ãƒ—レート"
msgid "Default description template for merge requests"
msgstr "マージリクエストã®ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®èª¬æ˜Žãƒ†ãƒ³ãƒ—レート"
@@ -8710,18 +8986,12 @@ msgstr "カレンダーã¨æ—¥ä»˜ã®è¨­å®šã§ä½¿ç”¨ã™ã‚‹ã€é€±ã®æœ€åˆã®æ—¥(ãƒ
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "デフォルトã®èª²é¡Œãƒ†ãƒ³ãƒ—レート"
-
msgid "Default project deletion protection"
msgstr "プロジェクトã®å‰Šé™¤ä¿è­·è¨­å®šï¼ˆãƒ‡ãƒ•ã‚©ãƒ«ãƒˆï¼‰"
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "デフォルト:FogBugz ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆIDをフルãƒãƒ¼ãƒ ã«ãƒžãƒƒãƒ—ã™ã‚‹"
@@ -8734,6 +9004,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Cron 構文ã§ã‚«ã‚¹ã‚¿ãƒ ãªãƒ‘ターンを指定ã™ã‚‹"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8782,9 +9055,6 @@ msgstr "アーãƒãƒ•ã‚¡ã‚¯ãƒˆã‚’削除"
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "ボードã®å‰Šé™¤"
-
msgid "Delete comment"
msgstr "コメントを削除"
@@ -9244,9 +9514,6 @@ msgstr "é™é †"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr "変更ã®ç›®çš„ã¨ãƒ¬ãƒ“ュアーãŒçŸ¥ã£ã¦ãŠãã¹ãã“ã¨ã‚’説明ã—ã¦ä¸‹ã•ã„。"
-msgid "Describe the requirement here"
-msgstr "ã“ã“ã«è¦ä»¶ã‚„è¦æ±‚事項を説明ã—ã¦ãã ã•ã„"
-
msgid "Description"
msgstr "説明"
@@ -9256,11 +9523,14 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "%{link_start} GitLab風ã®ãƒžãƒ¼ã‚¯ãƒ€ã‚¦ãƒ³ %{link_end} ã§ãƒ‘ースã—ãŸèª¬æ˜Ž"
+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 "Description テンプレートを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®èª²é¡ŒãŠã‚ˆã³ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆèª¬æ˜Žã«å¯¾ã™ã‚‹ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆå›ºæœ‰ã®ãƒ†ãƒ³ãƒ—レートを定義ã§ãã¾ã™ã€‚"
+msgstr "説明テンプレートを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŠã‚ˆã³ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®èª¬æ˜Žã«å¯¾ã™ã‚‹ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆå›ºæœ‰ã®ãƒ†ãƒ³ãƒ—レートを定義ã§ãã¾ã™ã€‚"
msgid "Description:"
msgstr "説明:"
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr "%{format} をダウンロード"
msgid "Download %{format}:"
msgstr "%{format} をダウンロード:"
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "CSV をダウンロード"
@@ -9854,9 +10184,6 @@ msgstr "ã“ã®ãƒ—ロセスã®é€”中ã§ã€GitLab å´ã‹ã‚‰ã® URL ã‚’èžã‹ã‚Œã‚‹
msgid "Dynamic Application Security Testing (DAST)"
msgstr "動的アプリケーションセキュリティテスト (DAST)"
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr "å„ Runner ã¯æ¬¡ã®ã„ãšã‚Œã‹ã®çŠ¶æ…‹ã‚’ã¨ã‚Šã¾ã™:"
@@ -9911,9 +10238,6 @@ msgstr "システムフックを編集"
msgid "Edit application"
msgstr "アプリケーションã®ç·¨é›†"
-msgid "Edit board"
-msgstr "ボードを編集"
-
msgid "Edit comment"
msgstr "コメントを編集"
@@ -9945,7 +10269,7 @@ msgid "Edit inline"
msgstr ""
msgid "Edit issues"
-msgstr "課題を編集"
+msgstr "イシューを編集"
msgid "Edit iteration"
msgstr ""
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr "公開デプロイキーã®ç·¨é›†"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "ステージã®ç·¨é›†"
@@ -9980,12 +10307,18 @@ msgstr ""
msgid "Editing"
msgstr "編集中"
+msgid "Editor Lite instance is required to set up an extension."
+msgstr ""
+
msgid "Elasticsearch AWS IAM credentials"
msgstr "Elasticsearch AWS IAMèªè¨¼æƒ…å ±"
msgid "Elasticsearch HTTP client timeout value in seconds."
msgstr ""
+msgid "Elasticsearch indexing"
+msgstr ""
+
msgid "Elasticsearch indexing restrictions"
msgstr "Elasticsearchã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ä½œæˆã®åˆ¶é™"
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10062,7 +10398,7 @@ msgid "EmailError|The thread you are replying to no longer exists, perhaps it wa
msgstr "返信ã•ã‚ŒãŸã‚¹ãƒ¬ãƒƒãƒ‰ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã›ã‚“。ãŠãらããã‚Œã¯å‰Šé™¤ã•ã‚ŒãŸã‚‚ã®ã¨æ€ã‚ã‚Œã¾ã™ã€‚ã“ã‚ŒãŒèª¤ã£ã¦ã„ã‚‹ã¨æ€ã‚れる場åˆã¯ã€ã‚¹ã‚¿ãƒƒãƒ•ãƒ¡ãƒ³ãƒãƒ¼ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
-msgstr "é€ä¿¡ã•ã‚ŒãŸãƒ¡ãƒ¼ãƒ«ã‚’処ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚Webインターフェース上ã‹ã‚‰èª²é¡Œã‚’作æˆã™ã‚‹ã‹ã€ã‚³ãƒ¡ãƒ³ãƒˆã‚’ã—ã¦ãã ã•ã„。"
+msgstr "é€ä¿¡ã•ã‚ŒãŸãƒ¡ãƒ¼ãƒ«ã‚’処ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚Webインターフェース上ã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã™ã‚‹ã‹ã€ã‚³ãƒ¡ãƒ³ãƒˆã‚’ã—ã¦ãã ã•ã„。"
msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
msgstr "メールãŒã©ã“ã¸ã®è¿”ä¿¡ã‹åˆ¤ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ Webインターフェイス上ã‹ã‚‰ã‚³ãƒ¡ãƒ³ãƒˆã‚’作æˆã—ã¦ãã ã•ã„。"
@@ -10088,10 +10424,10 @@ msgstr "リセット中..."
msgid "Emails"
msgstr "メール"
-msgid "Emails sent from Service Desk will have this name"
-msgstr "サービスデスクã‹ã‚‰é€ä¿¡ã—ãŸãƒ¡ãƒ¼ãƒ«ã«ã¯ã“ã®åå‰ãŒä»˜ãã¾ã™"
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ msgstr "Grafana を有効ã«ã—ã¦æ§‹æˆã™ã‚‹ã€‚"
msgid "Enable and configure Prometheus metrics."
msgstr "Prometheus ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’有効ã«ã—ã¦è¨­å®šã™ã‚‹ã€‚"
+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 "外部サービスを使用ã—ã¦ã€åˆ†é¡žåˆ¶å¾¡ã‚’有効ã«ã™ã‚‹ã€‚"
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr "2è¦ç´ èªè¨¼ã‚’有効ã«ã™ã‚‹"
msgid "Enable usage ping"
msgstr "利用状æ³ã®é€ä¿¡ã‚’有効ã«ã™ã‚‹"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr "サービスデスクを有効/無効ã«ã—ã¾ã™ã€‚ %{link_start}サービスデスクã®è©³ç´°ã«ã¤ã„ã¦%{link_end}"
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr "%{stepStart} ステップ1 %{stepEnd}: KubernetesãŒè¨­å®šã•ã‚Œã¦ãŠã‚Šã€ %{linkStart}クラスター%{linkEnd} ã®ãƒ™ãƒ¼ã‚¹ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒã‚ã‚‹ã“ã¨ã‚’確èªã—ã¾ã™ã€‚"
@@ -10292,6 +10631,9 @@ msgstr "レンダリング中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %{err}"
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "終了時刻 (UTC)"
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr "å°‘ãªãã¨ã‚‚3文字以上ã§æ¤œç´¢ã—ã¦ãã ã•ã„"
-msgid "Enter board name"
-msgstr "ボードåを入力"
-
msgid "Enter domain"
msgstr "ドメインを入力"
@@ -10350,7 +10689,7 @@ msgid "Enter new AWS Secret Access Key"
msgstr "æ–°ã—ã„AWSシークレットアクセスキーを入力ã—ã¾ã™"
msgid "Enter number of issues"
-msgstr "課題数を入力ã—ã¦ãã ã•ã„"
+msgstr "イシュー数を入力ã—ã¦ãã ã•ã„"
msgid "Enter one or more user ID separated by commas"
msgstr "ユーザーID入力ã—ã¦ãã ã•ã„。二ã¤ä»¥ä¸Šå…¥åŠ›ã™ã‚‹ã¨ãã¯ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šã§ã™ã€‚"
@@ -10359,10 +10698,10 @@ msgid "Enter the code from the two-factor app on your mobile device. If you've l
msgstr "モãƒã‚¤ãƒ«ç«¯æœ«ã®2è¦ç´ èªè¨¼ã‚¢ãƒ—リã‹ã‚‰ã‚³ãƒ¼ãƒ‰ã‚’入力ã—ã¾ã™ã€‚デãƒã‚¤ã‚¹ã‚’紛失ã—ãŸå ´åˆã¯ã€ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã®ã„ãšã‚Œã‹ã‚’入力ã—ã¦ãã ã•ã„。"
msgid "Enter the issue description"
-msgstr "課題ã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
+msgstr "イシューã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
msgid "Enter the issue title"
-msgstr "課題ã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’入力ã—ã¦ãã ã•ã„"
+msgstr "イシューã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’入力ã—ã¦ãã ã•ã„"
msgid "Enter the merge request description"
msgstr "マージリクエストã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr "デプロイã—ã¾ã™"
msgid "Environments|Deployment"
msgstr "デプロイ"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ã€ã‚³ãƒŸãƒƒãƒˆ %{commit_id}ã«å¯¾ã—㦠%{envir
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 "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ã€ã‚³ãƒŸãƒƒãƒˆ %{linkStart}%{commitId}%{linkEnd} ã«å¯¾ã—㦠%{name} ã§å®šç¾©ã•ã‚ŒãŸã‚¸ãƒ§ãƒ–を実行ã—ã¦ã€ç’°å¢ƒã‚’å‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã—ã¾ã™ã€‚アプリケーションã®æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å†ãƒ‡ãƒ—ロイã™ã‚‹ã“ã¨ã§ revert ã§ãã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ"
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "更新済ã¿"
@@ -10659,7 +11010,7 @@ msgid "Epics Roadmap"
msgstr "エピック ロードマップ"
msgid "Epics and Issues"
-msgstr "エピックã¨èª²é¡Œ"
+msgstr "エピックã¨ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "エピックを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ãƒãƒ¼ãƒˆãƒ•ã‚©ãƒªã‚ªã‚’より効率的ã‹ã¤å°‘ãªã„労力ã§ç®¡ç†ã§ãã¾ã™"
@@ -10691,20 +11042,17 @@ msgstr "ã©ã†ã™ã‚Œã°è§£æ±ºã§ãã¾ã™ã‹ï¼Ÿ"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "詳ã—ã„情報"
-
msgid "Epics|Remove epic"
msgstr "エピックを削除"
msgid "Epics|Remove issue"
-msgstr "課題ã®å‰Šé™¤"
+msgstr "イシューã®å‰Šé™¤"
msgid "Epics|Show more"
msgstr "詳細を見る"
msgid "Epics|Something went wrong while assigning issue to epic."
-msgstr "課題をエピックã«å‰²ã‚Šå½“ã¦ä¸­ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgstr "イシューをエピックã«å‰²ã‚Šå½“ã¦ä¸­ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Epics|Something went wrong while creating child epics."
msgstr "å­ã‚¨ãƒ”ック作æˆä¸­ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -10725,10 +11073,10 @@ msgid "Epics|Something went wrong while ordering item."
msgstr "アイテムを並ã¹ã¦ã„ã‚‹é–“ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Epics|Something went wrong while removing issue from epic."
-msgstr "エピックã‹ã‚‰èª²é¡Œã‚’削除ã—ã¦ã‚‹é–“ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+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 "ã“れらã®æ—¥ä»˜ã¯ã€ã‚ãªãŸã®ã‚¨ãƒ”ックãŒãƒ­ãƒ¼ãƒ‰ãƒžãƒƒãƒ—ã«ã©ã®ã‚ˆã†ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‹ã«å½±éŸ¿ã—ã¾ã™ã€‚マイルストーンã®æ—¥ä»˜ã¯ã€ã‚¨ãƒ”ックã®èª²é¡Œã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ç”±æ¥ã—ã¾ã™ã€‚日付を修正ã™ã‚‹ã“ã¨ã‚‚ã€å®Œå…¨ã«å‰Šé™¤ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
+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 ""
@@ -10737,7 +11085,7 @@ msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle
msgstr "%{bStart}%{parentEpicTitle}%{bEnd} ã‹ã‚‰ %{bStart}%{targetEpicTitle}%{bEnd} 以下ã®å…¨ã¦ã®èª²é¡Œã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
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 "マイルストーンã«åŸºã¥ã„ãŸã‚¨ãƒ”ック㮠%{epicDateType} をスケジューリングã™ã‚‹ã«ã¯ã€ã‚¨ãƒ”ックã®èª²é¡Œã« %{epicDateType} ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’割り当ã¦ã¾ã™ã€‚"
+msgstr "マイルストーンã«åŸºã¥ã„ãŸã‚¨ãƒ”ック㮠%{epicDateType} をスケジューリングã™ã‚‹ã«ã¯ã€ã‚¨ãƒ”ックã®ã‚¤ã‚·ãƒ¥ãƒ¼ã« %{epicDateType} ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’割り当ã¦ã¾ã™ã€‚"
msgid "Epics|Unable to perform this action"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚°ãƒ©ãƒ•ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr "å‚ç…§ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ"
@@ -10869,7 +11214,7 @@ msgid "Error occurred while updating the issue status"
msgstr ""
msgid "Error occurred while updating the issue weight"
-msgstr "課題ã®ã‚¦ã‚¨ã‚¤ãƒˆæ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgstr "イシューã®ã‚¦ã‚§ã‚¤ãƒˆã‚’更新時ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Error occurred. A blocked user cannot be deactivated"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ブロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯éžæœ‰åŠ¹åŒ–ã§ãã¾ã›ã‚“。"
@@ -10937,9 +11282,18 @@ msgstr "Akismet ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚詳細ã«ã¤ã„ã¦ã¯ãƒ­ã‚°ã
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 "アクティブ"
@@ -10995,7 +11349,7 @@ msgid "EventFilterBy|Filter by epic events"
msgstr "エピックイベントã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
msgid "EventFilterBy|Filter by issue events"
-msgstr "課題イベントã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
+msgstr "イシューイベントã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
msgid "EventFilterBy|Filter by merge events"
msgstr "マージイベントã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
@@ -11054,23 +11408,23 @@ msgstr "全員ãŒè²¢çŒ®ã§ãã¾ã™"
msgid "Everything on your to-do list is marked as done."
msgstr "ã‚ãªãŸã®To Doリストã®é …ç›®ã™ã¹ã¦ãŒå®Œäº†ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
+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 "GitBook を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã“ã¨ã™ã¹ã¦ã€‚"
+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 "Hexo を使ã£ã¦GitLab Pagesサイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
+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 "Hugo を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
+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 "Jekyll を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
+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 "プレーンHTML を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
msgid "Evidence collection"
msgstr "証拠集ã‚"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr "既存ã®ãƒ¡ãƒ³ãƒãƒ¼ã¨ã‚°ãƒ«ãƒ¼ãƒ—"
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "有効期é™"
@@ -11181,7 +11535,7 @@ msgid "Expires:"
msgstr "有効期é™:"
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
-msgstr "å•é¡Œã‚’説明ã—ã¦ãã ã•ã„。必è¦ã«å¿œã˜ã¦ã€è©²å½“ã™ã‚‹èª²é¡Œã¾ãŸã¯ã‚³ãƒ¡ãƒ³ãƒˆã¸ã®ãƒªãƒ³ã‚¯ã‚’æä¾›ã—ã¦ãã ã•ã„。"
+msgstr "å•é¡Œã‚’説明ã—ã¦ãã ã•ã„。必è¦ã«å¿œã˜ã¦ã€è©²å½“ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã¾ãŸã¯ã‚³ãƒ¡ãƒ³ãƒˆã¸ã®ãƒªãƒ³ã‚¯ã‚’æä¾›ã—ã¦ãã ã•ã„。"
msgid "Explore"
msgstr "探索"
@@ -11214,7 +11568,7 @@ msgid "Export group"
msgstr ""
msgid "Export issues"
-msgstr "課題をエクスãƒãƒ¼ãƒˆ"
+msgstr "イシューをエクスãƒãƒ¼ãƒˆ"
msgid "Export merge requests"
msgstr ""
@@ -11291,6 +11645,9 @@ msgstr "Zoom ミーティングã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ"
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 "ユーザーã®å‰²ã‚Šå½“ã¦ã«å¤±æ•—ã—ã¾ã—ãŸã€‚見ã¤ã‹ã‚‰ãªã‹ã£ãŸã‹ã‚‰ã§ã™ã€‚"
@@ -11309,6 +11666,12 @@ 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 "マージリクエストã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
@@ -11316,7 +11679,7 @@ msgid "Failed to create To-Do for the design."
msgstr ""
msgid "Failed to create a branch for this issue. Please try again."
-msgstr "ã“ã®èª²é¡Œã®ãŸã‚ã®ãƒ–ランãƒã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®ãŸã‚ã®ãƒ–ランãƒã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Failed to create framework"
msgstr ""
@@ -11336,9 +11699,6 @@ msgstr "リソースã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr "ボードを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—下ã•ã„。"
-
msgid "Failed to deploy to"
msgstr "デプロイã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -11409,16 +11769,16 @@ 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 "å‚ç…§ã•ã‚ŒãŸèª²é¡ŒãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ã“ã®èª²é¡Œã‚’複製ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgstr "å‚ç…§ã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼ãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’é‡è¤‡ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failed to move this issue because label was not found."
-msgstr "ラベルãŒè¦‹ã¤ã‹ã‚‰ãªã‹ã£ãŸã®ã§ã€ã“ã®èª²é¡Œã®ç§»å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgstr "ラベルãŒè¦‹ã¤ã‹ã‚‰ãªã‹ã£ãŸã®ã§ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®ç§»å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Failed to move this issue because only a single label can be provided."
-msgstr "課題ã®ç§»å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚一ã¤ã®ãƒ©ãƒ™ãƒ«ã—ã‹ä»˜ä¸Žã§ããªã„ãŸã‚ã§ã™ã€‚"
+msgstr "イシューã®ç§»å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚一ã¤ã®ãƒ©ãƒ™ãƒ«ã—ã‹ä»˜ä¸Žã§ããªã„ãŸã‚ã§ã™ã€‚"
msgid "Failed to move this issue because target project doesn't exist."
-msgstr "ターゲットã®ãƒ—ロジェクトãŒå­˜åœ¨ã—ãªã„ã®ã§ã€ã“ã®èª²é¡Œã‚’移動ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgstr "ターゲットã®ãƒ—ロジェクトãŒå­˜åœ¨ã—ãªã„ã®ã§ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’移動ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "内部エラーã®ãŸã‚ã€ãƒ©ãƒ™ãƒ«ã‚’昇格ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚管ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
@@ -11439,7 +11799,7 @@ msgid "Failed to remove a Zoom meeting"
msgstr "Zoom ミーティングã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to remove issue from board, please try again."
-msgstr "ボードã®èª²é¡Œã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgstr "ボードã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Failed to remove mirror."
msgstr "ミラーã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -11489,11 +11849,14 @@ msgstr "ブランãƒã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to update environment!"
msgstr "環境ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
-msgstr "課題ã®çŠ¶æ…‹ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgstr "イシューã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to update issues, please try again."
-msgstr "課題ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgstr "イシューã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Failed to update tag!"
msgstr "ã‚¿ã‚°ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -11549,9 +11912,6 @@ msgstr "機能フラグを削除ã—ã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Feature flag was successfully removed."
msgstr "機能フラグを正常ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚"
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "機能フラグ"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr "フィーãƒãƒ£ãƒ¼ãƒ•ãƒ©ã‚°ã¯ã€æ¬¡ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã§ã¯ç•°ãªã‚‹å¤–観ã«ãªã‚Šã¾ã™ã€‚アクションã¯å¿…è¦ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ¯ãƒ¼ã‚¯ãƒ•ãƒ­ãƒ¼ã‚’改善ã™ã‚‹ãŸã‚ã«æ©Ÿèƒ½ãŒå¤‰æ›´ã•ã‚ŒãŸã“ã¨ã«æ°—ã¥ãã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。"
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "機能フラグ%{name} ãŒã€å‰Šé™¤ã•ã‚Œã¾ã™ã€‚本当ã«å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ"
@@ -11655,16 +12012,13 @@ msgstr "機能フラグを有効ã«ã™ã‚‹ã¨ã€ç‰¹å®šã®æ©Ÿèƒ½ã¸ã®å‹•çš„切り
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "機能フラグを使ã„ã¯ã˜ã‚ã‚‹"
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr "フィルター"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "ã‚ãªãŸãŒæœ€è¿‘é–‰ã˜ãŸ %{issuable_type} ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
@@ -11913,12 +12273,6 @@ msgstr "マイルストーンåã§çµžã‚Šè¾¼ã‚€"
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr "パスã§æ¤œç´¢"
-msgid "Find existing members by name"
-msgstr "既存ã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’åå‰ã§æŽ¢ã™"
-
msgid "Find file"
msgstr "ファイルを検索"
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr "完了"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr "最åˆã«è¦‹ãŸ"
@@ -12120,9 +12474,6 @@ msgstr "フォーク"
msgid "Format: %{dateFormat}"
msgstr "フォーマット:%{dateFormat}"
-msgid "Forward external support email address to"
-msgstr "外部サãƒãƒ¼ãƒˆã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’転é€"
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "%{gitlab_ci_yml} ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™"
@@ -12160,7 +12511,7 @@ msgid "From %{providerTitle}"
msgstr "%{providerTitle} ã‹ã‚‰"
msgid "From issue creation until deploy to production"
-msgstr "課題ãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
+msgstr "イシューãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
msgid "From merge request merge until deploy to production"
msgstr "マージリクエストãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
@@ -12588,6 +12939,12 @@ 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 "エラー追跡を開始"
@@ -12658,14 +13015,11 @@ msgid "GitLab Import"
msgstr "GitLab インãƒãƒ¼ãƒˆ"
msgid "GitLab Issue"
-msgstr "GitLab 課題"
+msgstr "GitLabイシュー"
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,8 +13239,8 @@ msgstr "グローãƒãƒ«é€šçŸ¥è¨­å®š"
msgid "Go Back"
msgstr "戻る"
-msgid "Go Micro is a framework for micro service development."
-msgstr "Go Microã¯ã€ãƒžã‚¤ã‚¯ãƒ­ã‚µãƒ¼ãƒ“ス開発ã®ãŸã‚ã®ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯ã§ã™ã€‚"
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
msgid "Go back"
msgstr "å‰ã«æˆ»ã‚‹"
@@ -12937,10 +13291,10 @@ msgid "Go to fork"
msgstr ""
msgid "Go to issue boards"
-msgstr "課題ボードã¸ç§»å‹•"
+msgstr "イシューボードã¸ç§»å‹•"
msgid "Go to issues"
-msgstr "課題ã¸ç§»å‹•"
+msgstr "イシューã¸ç§»å‹•"
msgid "Go to jobs"
msgstr "ジョブã¸"
@@ -12997,7 +13351,7 @@ msgid "Go to your groups"
msgstr "ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ç§»å‹•"
msgid "Go to your issues"
-msgstr "ã‚ãªãŸã®èª²é¡Œã¸ç§»å‹•"
+msgstr "ã‚ãªãŸã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¸ç§»å‹•"
msgid "Go to your merge requests"
msgstr "マージリクエストã¸ç§»å‹•"
@@ -13036,7 +13390,7 @@ msgid "GrafanaIntegration|Active"
msgstr "アクティブ"
msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr "GitLab ã®èª²é¡Œã« Grafana ãƒãƒ£ãƒ¼ãƒˆã‚’埋ã‚è¾¼ã¿ã¾ã™ã€‚"
+msgstr "GitLabã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«Grafanaãƒãƒ£ãƒ¼ãƒˆã‚’埋ã‚è¾¼ã¿ã¾ã™ã€‚"
msgid "GrafanaIntegration|Enter the Grafana API Token."
msgstr "Grafana API トークンを入力。"
@@ -13113,9 +13467,6 @@ msgstr "グループアãƒã‚¿ãƒ¼"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "グループã®èª¬æ˜Ž"
-
msgid "Group description (optional)"
msgstr "グループã®èª¬æ˜Ž(ä»»æ„)"
@@ -13449,11 +13800,17 @@ 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 your group badges."
-msgstr "グループãƒãƒƒã‚¸ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º"
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã«å¯¾ã—ã¦ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã® Auto DevOps パイプライン"
@@ -13476,9 +13833,6 @@ msgstr "親グループã®å¯è¦–性ãŒã‚°ãƒ«ãƒ¼ãƒ—ã®ç¾åœ¨ã®å¯è¦–性より低
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "ãƒãƒƒã‚¸ã®è©³ç´°ã€‚"
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr "グループレベルã®ãƒ—ロジェクトテンプレートã®è©³ç´°."
@@ -13506,8 +13860,8 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚«ã‚¹ã‚¿ãƒ ãƒ—ロジェクトテンプレートソースã¨ã—ã¦ã‚µãƒ–グループをé¸æŠž"
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr "代替㮠CI 設定ファイルãŒè¦‹ã¤ã‹ã‚‰ãªã„å ´åˆã¯ã€Auto DevOps パイプラインãŒå®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
+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 "Auto DevOps パイプラインã®æ›´æ–°ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸï¼š %{error_messages} 。"
@@ -13539,6 +13893,9 @@ 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 "ã‚ãªãŸãŒç®¡ç†ã§ãるグループã«ã®ã¿ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を転é€ã§ãã¾ã™ã€‚"
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr "作æˆ"
msgid "GroupsNew|Create group"
msgstr "グループを作æˆ"
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13747,7 +14131,7 @@ msgid "Helps prevent bots from creating accounts."
msgstr "ボットãŒã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’作æˆã§ããªã„よã†ã«ã—ã¾ã™ã€‚"
msgid "Helps reduce alert volume (e.g. if creating too many issues)"
-msgstr "アラートã®é‡ã‚’減らã™ã®ã«å½¹ç«‹ã¡ã¾ã™(例:作æˆã™ã‚‹èª²é¡ŒãŒå¤šã™ãŽã‚‹å ´åˆ)"
+msgstr "アラートã®é‡ã‚’減らã™ã®ã«å½¹ç«‹ã¡ã¾ã™(例:作æˆã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒå¤šã™ãŽã‚‹å ´åˆ)"
msgid "Helps reduce request volume for protected paths"
msgstr "ä¿è­·ã•ã‚ŒãŸãƒ‘スã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆé‡ã‚’減らã™ã®ã«å½¹ç«‹ã¡ã¾ã™"
@@ -13859,6 +14243,9 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ãƒ‘スã€è»¢é€ã€å‰Šé™¤ã€ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–。"
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "仕組ã¿"
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "インãƒãƒ¼ãƒˆä¸­ã§ã™"
@@ -14111,7 +14507,7 @@ msgid "Import in progress. Refresh page to see newly added issues."
msgstr ""
msgid "Import issues"
-msgstr "課題ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+msgstr "イシューã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import members"
msgstr "メンãƒãƒ¼ã‚’インãƒãƒ¼ãƒˆ"
@@ -14152,6 +14548,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã‚’ GitHub ã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹"
msgid "Import repository"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆ"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr "インãƒãƒ¼ãƒˆé–‹å§‹è€…: %{importInitiator}"
@@ -14159,7 +14558,7 @@ msgid "Import tasks"
msgstr "タスクã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Import tasks from Phabricator into issues"
-msgstr "Phabricator ã‹ã‚‰èª²é¡Œã¸ã‚¿ã‚¹ã‚¯ã‚’インãƒãƒ¼ãƒˆã™ã‚‹"
+msgstr "Phabricatorã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã¸ã‚¿ã‚¹ã‚¯ã‚’インãƒãƒ¼ãƒˆã™ã‚‹"
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr "インãƒãƒ¼ãƒˆãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚インãƒãƒ¼ãƒˆã« %{import_jobs_expiration} 秒以上ã‹ã‹ã‚Šã¾ã—ãŸ"
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "GitLab エンタープライズエディションを使用ã™ã‚‹ã¨ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®æ©Ÿèƒ½ãŒå¼·åŒ–ã•ã‚Œã¾ã™ã€‚"
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr "GitLab エンタープライズエディションã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¨ã‚«ã‚¹ã‚¿ãƒžãƒ¼ã‚µãƒãƒ¼ãƒˆã‚’改善"
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr "インシデント管ç†åˆ¶é™"
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,14 +14801,14 @@ msgstr ""
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
msgstr "LFSオブジェクトをå«ã¿ã¾ã™ã€‚グループã”ã¨ã€ã¾ãŸã¯ãƒ—ロジェクトã”ã¨ã«ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã§ãã¾ã™ã€‚無制é™ã‚’指定ã™ã‚‹å ´åˆã¯0ã«ã—ã¾ã™ã€‚"
-msgid "Includes an MVC structure to help you get started."
-msgstr "MVC構造をå«ã‚ã¦ã€é–‹å§‹ã—ã¾ã™ã€‚"
+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 "MVC構造体ã€Gemfileã€Rakefile等をå«ã‚ã¦é–‹å§‹ã—ã¾ã™ã€‚"
+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 "MVC構造体ã€mvnwã€pom.xmlã‚’å«ã‚ã¦é–‹å§‹ã—ã¾ã™ã€‚"
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
msgid "Incoming email"
msgstr "å—信メール"
@@ -14425,6 +14822,9 @@ msgstr "互æ›æ€§ã®ãªã„オプションãŒã‚»ãƒƒãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®ç´¹ä»‹"
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr "無効㪠Insights 設定ファイルãŒã¿ã¤ã‹ã‚Šã¾ã—ãŸ"
@@ -14858,15 +15261,15 @@ msgstr ""
msgid "Invite"
msgstr "招待"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "メール㧠\"%{trimmed}\" を招待"
msgid "Invite Members"
msgstr ""
-msgid "Invite another teammate"
-msgstr ""
-
msgid "Invite group"
msgstr "グループã«æ‹›å¾…ã™ã‚‹"
@@ -14876,9 +15279,6 @@ msgstr "メンãƒãƒ¼ã‚’招待ã™ã‚‹"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr "呼ã³å‡ºã—"
@@ -15039,28 +15454,31 @@ msgid "IssuableStatus|promoted"
msgstr ""
msgid "Issue"
-msgstr "課題"
+msgstr "イシュー"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
-msgstr "課題 %{issue_reference} をエピック %{epic_reference} ã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
+msgstr "イシュー %{issue_reference} をエピック %{epic_reference} ã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
msgid "Issue Analytics"
-msgstr "課題分æž"
+msgstr "イシュー分æž"
msgid "Issue Boards"
-msgstr "課題ボード"
+msgstr "イシューボード"
msgid "Issue already promoted to epic."
msgstr ""
msgid "Issue cannot be found."
-msgstr "課題を見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"
+msgstr "イシューを見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
-msgstr "課題イベント"
+msgstr "イシューイベント"
msgid "Issue first deployed to production"
msgstr ""
@@ -15074,14 +15492,14 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
-msgstr "課題テンプレート(オプション)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
-msgstr "課題ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgstr "イシューã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Issue was closed by %{name} %{reason}"
-msgstr "課題㯠%{name} ã«ã‚ˆã£ã¦ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚Œã¾ã—㟠%{reason}"
+msgstr "イシュー㯠%{name} ã«ã‚ˆã£ã¦ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚Œã¾ã—㟠%{reason}"
msgid "Issue weight"
msgstr ""
@@ -15096,7 +15514,7 @@ msgid "IssueAnalytics|Due date"
msgstr "期日"
msgid "IssueAnalytics|Failed to load issues. Please try again."
-msgstr "課題ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgstr "イシューã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "IssueAnalytics|Issue"
msgstr ""
@@ -15113,7 +15531,7 @@ msgstr "ステータス"
msgid "IssueAnalytics|Weight"
msgstr "ウェイト"
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15138,58 +15556,58 @@ msgid "IssueBoards|Switch board"
msgstr "ボードを切り替ãˆã‚‹"
msgid "IssueTracker|Bugzilla issue tracker"
-msgstr "Bugzilla課題トラッカー"
+msgstr "Bugzillaイシュートラッカー"
msgid "IssueTracker|Custom issue tracker"
-msgstr "カスタム課題トラッカー"
+msgstr "カスタムイシュートラッカー"
msgid "IssueTracker|EWM work items tracker"
msgstr ""
msgid "IssueTracker|Redmine issue tracker"
-msgstr "Redmine 課題トラッカー"
+msgstr "Redmineイシュートラッカー"
msgid "IssueTracker|YouTrack issue tracker"
-msgstr "YouTrack 課題トラッカー"
+msgstr "YouTrackイシュートラッカー"
msgid "Issues"
-msgstr "課題"
+msgstr "イシュー"
msgid "Issues Rate Limits"
-msgstr " 課題レート制é™"
+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 "課題ã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤ãƒ‡ã‚¢ã§ã™ã€‚ã¾ãŸã€èª²é¡Œã¯æ¤œç´¢ã‚„フィルター処ç†ãŒå¯èƒ½ã§ã™ã€‚"
+msgstr "イシューã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤ãƒ‡ã‚¢ã§ã™ã€‚ã¾ãŸã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¯æ¤œç´¢ã‚„フィルター処ç†ãŒå¯èƒ½ã§ã™ã€‚"
msgid "Issues closed"
-msgstr "クローズã—ãŸèª²é¡Œ"
+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 "コメントã®ã‚る課題ã€å·®åˆ†ã¨ã‚³ãƒ¡ãƒ³ãƒˆã€ãƒ©ãƒ™ãƒ«ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆã€ãã®ä»–ã®ãƒ—ロジェクトエンティティã¨é–¢é€£ã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgstr "コメントã®ã‚るイシューã€å·®åˆ†ã¨ã‚³ãƒ¡ãƒ³ãƒˆã€ãƒ©ãƒ™ãƒ«ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆã€ãã®ä»–ã®ãƒ—ロジェクトエンティティã¨é–¢é€£ã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Issues with no epic assigned"
msgstr ""
msgid "Issues, merge requests, pushes, and comments."
-msgstr "課題ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒ—ッシュã€ã‚³ãƒ¡ãƒ³ãƒˆ"
+msgstr "イシューã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒ—ッシュã€ã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
-msgstr "プロジェクトã®èª²é¡Œã®ä½œæˆã‚’開始ã—ãŸã‚‰ã€ãƒ—ロジェクトã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’追跡ã—ã¦è¡¨ç¤ºã§ãã¾ã™ã€‚"
+msgstr "プロジェクトã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®ä½œæˆã‚’開始ã—ãŸã‚‰ã€ãƒ—ロジェクトã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’追跡ã—ã¦è¡¨ç¤ºã§ãã¾ã™ã€‚"
msgid "IssuesAnalytics|Avg/Month:"
msgstr "月平å‡:"
msgid "IssuesAnalytics|Issues opened"
-msgstr "未解決ã®èª²é¡Œ"
+msgstr "未解決ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "IssuesAnalytics|Issues opened per month"
-msgstr "未解決ã®èª²é¡Œæ•°/月"
+msgstr "未解決ã®ã‚¤ã‚·ãƒ¥ãƒ¼æ•°/月"
msgid "IssuesAnalytics|Last 12 months"
msgstr "éŽåŽ»12ヶ月間"
@@ -15198,7 +15616,7 @@ msgid "IssuesAnalytics|Sorry, your filter produced no results"
msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“。ã‚ãªãŸãŒæŒ‡å®šã—ãŸãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã§ã¯è©²å½“ã™ã‚‹çµæžœãŒã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr "ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ—ロジェクトã«ã¯ã€èª²é¡ŒãŒã‚ã‚Šã¾ã›ã‚“。"
+msgstr "ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ—ロジェクトã«ã¯ã‚¤ã‚·ãƒ¥ãƒ¼ãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr "検索を拡大ã™ã‚‹ã«ã¯ã€ä¸Šè¨˜ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒãƒ¼ã§ãƒ•ã‚£ãƒ«ã‚¿ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™"
@@ -15216,7 +15634,7 @@ 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 "ヘッダー行ã¨å°‘ãªãã¨ã‚‚2ã¤ã®åˆ—ãŒå¿…è¦ã§ã™ã€‚最åˆã®åˆ—ã¯èª²é¡Œã®ã‚¿ã‚¤ãƒˆãƒ«ã€2番目ã®åˆ—ã¯èª²é¡Œã®èª¬æ˜Žã§ã™ã€‚区切り文字ã¯è‡ªå‹•çš„ã«æ¤œå‡ºã•ã‚Œã¾ã™ã€‚"
+msgstr "ヘッダー行ã¨å°‘ãªãã¨ã‚‚2ã¤ã®åˆ—ãŒå¿…è¦ã§ã™ã€‚最åˆã®åˆ—ã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¿ã‚¤ãƒˆãƒ«ã€2番目ã®åˆ—ã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã®èª¬æ˜Žã§ã™ã€‚区切り文字ã¯è‡ªå‹•çš„ã«æ¤œå‡ºã•ã‚Œã¾ã™ã€‚"
msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
msgstr "ä¾å­˜é–¢ä¿‚スキャンジョブã¯æ­£å¸¸ã«å®Ÿè¡Œã•ã‚Œã¾ã—ãŸã€‚ã—ã‹ã—ã‚ãªãŸã®ãƒ—ロジェクトã§ä¾å­˜é–¢ä¿‚ã¯æ¤œå‡ºã•ã‚Œã¦ã„ã¾ã›ã‚“。"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} イベントã¯ç„¡åŠ¹ã§ã™ã€‚"
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Web URLã¨ç•°ãªã‚‹å ´åˆ"
@@ -15330,31 +15754,31 @@ msgid "JiraService|Jira Issues"
msgstr ""
msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
-msgstr "課題ãŒã‚³ãƒŸãƒƒãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ JiraコメントãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
+msgstr "イシューãŒã‚³ãƒŸãƒƒãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ Jiraã®ã‚³ãƒ¡ãƒ³ãƒˆãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
-msgstr "課題ãŒãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ Jira コメントãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
+msgstr "イシューãŒãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ Jiraã®ã‚³ãƒ¡ãƒ³ãƒˆãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
msgid "JiraService|Jira issue tracker"
-msgstr "Jira 課題トラッカー"
+msgstr "Jiraイシュートラッカー"
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 "パスワードã¾ãŸã¯APIトークン"
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Transition ID(s)"
-msgstr "é·ç§»ID"
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
-msgstr "複数ã®é·ç§»IDを記載ã™ã‚‹å ´åˆã€ã‚³ãƒ³ãƒž, ã¾ãŸã¯ã‚»ãƒŸã‚³ãƒ­ãƒ³; を使ã£ã¦åˆ†ã‘ã‚‹"
+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 "サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯ãƒ‘スワードを使用ã—ã¦ãã ã•ã„。クラウドãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯APIトークンを使用ã—ã¦ãã ã•ã„。"
@@ -15666,7 +16090,7 @@ msgid "Label actions dropdown"
msgstr "ラベルアクションドロップダウン"
msgid "Label lists show all issues with the selected label."
-msgstr "ラベル一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ©ãƒ™ãƒ«ãŒä»˜ã„ãŸã™ã¹ã¦ã®èª²é¡ŒãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
+msgstr "ラベル一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ©ãƒ™ãƒ«ãŒä»˜ã„ãŸã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "Label was created"
msgstr "ラベルãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
@@ -15693,10 +16117,10 @@ msgid "Labels can be applied to %{features}. Group labels are available for any
msgstr "ラベルを%{features} ã«é©ç”¨ã§ãã¾ã™ã€‚グループラベルã¯ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr "ラベルを使用ã—ã¦ã€èª²é¡Œã‚„マージリクエストを分類ã§ãã¾ã™ã€‚"
+msgstr "ラベルを使用ã—ã¦ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚„マージリクエストを分類ã§ãã¾ã™ã€‚"
msgid "Labels can be applied to issues and merge requests."
-msgstr "ラベルã¯èª²é¡Œã¨ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«é©ç”¨ã§ãã¾ã™ã€‚"
+msgstr "ラベルã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã¨ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«é©ç”¨ã§ãã¾ã™ã€‚"
msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
@@ -15777,6 +16201,9 @@ msgstr "最後ã®ãƒªãƒã‚¸ãƒˆãƒªãƒã‚§ãƒƒã‚¯ã‚’実行"
msgid "Last seen"
msgstr "最終閲覧"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr "最後ã«æˆåŠŸã—ãŸåŒæœŸ"
@@ -15831,9 +16258,15 @@ msgstr "リード"
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "GitLab ã‚’å­¦ã¶"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "%{link_start} ビルトインã®ãƒ†ãƒ³ãƒ—レートã«è²¢çŒ® %{link_end}ã™ã‚‹æ–¹æ³•ã‚’å­¦ã¶"
@@ -15873,9 +16306,6 @@ msgstr ""
msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "%{docs_link_start}GitLab Pages 文書%{docs_link_end}ã«å¾“ã£ã¦ã€ã“ã®ãƒ—ロジェクトã¸ã®è¨¼æ˜Žæ›¸ã®è¿½åŠ ã«ã¤ã„ã¦å­¦ã¶ã€‚"
-msgid "Learn more about approvals."
-msgstr "承èªã®è©³ç´°"
-
msgid "Learn more about custom project templates"
msgstr "カスタムプロジェクトテンプレートã®è©³ç´°"
@@ -15900,6 +16330,9 @@ msgstr "詳ã—ã見る:"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "詳ã—ãã¯ãƒ‘イプラインスケジュールã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "離れる"
@@ -16169,7 +16602,7 @@ msgid "Linked emails (%{email_count})"
msgstr "リンクã•ã‚ŒãŸãƒ¡ãƒ¼ãƒ« (%{email_count})"
msgid "Linked issues"
-msgstr "リンクã•ã‚ŒãŸèª²é¡Œ"
+msgstr "リンクã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -16229,7 +16662,10 @@ msgid "Loading functions timed out. Please reload the page to try again."
msgstr "Fcuntionã®èª­ã¿è¾¼ã¿ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã€ãƒšãƒ¼ã‚¸ã‚’リロードã—ã¦ãã ã•ã„。"
msgid "Loading issues"
-msgstr "課題ã®ãƒ­ãƒ¼ãƒ‰"
+msgstr "イシューã®ãƒ­ãƒ¼ãƒ‰"
+
+msgid "Loading more issues"
+msgstr ""
msgid "Loading snippet"
msgstr "スニペットã®ãƒ­ãƒ¼ãƒ‰ä¸­"
@@ -16318,6 +16754,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr "マージ済ã¿"
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16349,7 +16788,7 @@ msgid "MRDiff|Show full file"
msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’表示"
msgid "Made this issue confidential."
-msgstr "ã“ã®èª²é¡Œã‚’éžå…¬é–‹ã«è¨­å®šã—ãŸã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’éžå…¬é–‹ã«ã—ã¾ã—ãŸã€‚"
msgid "Maintenance mode"
msgstr ""
@@ -16361,7 +16800,7 @@ msgid "Make everyone on your team more productive regardless of their location.
msgstr "ãƒãƒ¼ãƒ å…¨å“¡ãŒå ´æ‰€ã«é–¢ä¿‚ãªãより生産的ã«æ´»å‹•ã§ãã¾ã™ã€‚GitLab Geo ã¯ã€å¤§ããªã‚µã‚¤ã‚ºã®ãƒªãƒã‚¸ãƒˆãƒªã®å–得やクローンã«ã‹ã‹ã‚‹æ™‚間を削減ã™ã‚‹ãŸã‚ã«ã€èª­ã¿è¾¼ã¿å°‚用ã®ãƒŸãƒ©ãƒ¼ã‚’ GitLab インスタンス上ã«ä½œæˆã—ã¾ã™ã€‚"
msgid "Make issue confidential"
-msgstr "課題をéžå…¬é–‹ã«è¨­å®šã™ã‚‹"
+msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹"
msgid "Make sure you save it - you won't be able to access it again."
msgstr "ã“ã‚Œã¯å¿…ãšä¿å­˜ã—ã¦ãã ã•ã„。二度ã¨ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。"
@@ -16370,7 +16809,7 @@ msgid "Make this epic confidential"
msgstr ""
msgid "Makes this issue confidential."
-msgstr "課題をéžå…¬é–‹ã«è¨­å®šã™ã‚‹ã€‚"
+msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹ã€‚"
msgid "Manage"
msgstr "管ç†"
@@ -16424,7 +16863,7 @@ msgid "Manifest import"
msgstr ""
msgid "ManualOrdering|Couldn't save the order of the issues"
-msgstr "ã“ã®èª²é¡Œã®é †åºã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®é †åºã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Manually link this issue by adding it to the linked issue section of the %{originating_vulnerability}."
msgstr ""
@@ -16451,10 +16890,10 @@ msgid "Mark as resolved"
msgstr "解決済ã«ã™ã‚‹"
msgid "Mark this issue as a duplicate of another issue"
-msgstr "ã“ã®èª²é¡Œã‚’別ã®èª²é¡Œã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’別ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
msgid "Mark this issue as related to another issue"
-msgstr "ã“ã®èª²é¡Œã‚’別ã®èª²é¡Œã«é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’別ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¨é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
msgid "Mark to do as done"
msgstr ""
@@ -16496,10 +16935,10 @@ msgid "Marked this %{noun} as a draft."
msgstr ""
msgid "Marked this issue as a duplicate of %{duplicate_param}."
-msgstr "ã“ã®èª²é¡Œã¯ %{duplicate_param} ã¨é‡è¤‡ã¨ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ %{duplicate_param} ã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
msgid "Marked this issue as related to %{issue_ref}."
-msgstr "ã“ã®èª²é¡Œã‚’ %{issue_ref} ã«é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ %{issue_ref} ã¨é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
msgid "Marked to do as done."
msgstr ""
@@ -16508,10 +16947,10 @@ msgid "Marks this %{noun} as a draft."
msgstr ""
msgid "Marks this issue as a duplicate of %{duplicate_reference}."
-msgstr "ã“ã®èª²é¡Œã‚’ %{duplicate_reference} ã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹ã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ %{duplicate_reference} ã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹ã€‚"
msgid "Marks this issue as related to %{issue_ref}."
-msgstr "ã“ã®èª²é¡Œã‚’ %{issue_ref} ã«é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹ã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ %{issue_ref} ã¨é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹ã€‚"
msgid "Marks to do as done."
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr "ã“ã®ã‚µãƒ¼ãƒ“スã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯Mattermostã«ã‚¹ãƒ©ãƒƒã‚·ãƒ
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr "最大アクセスレベル"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr "メモリ使用é‡"
msgid "Merge"
msgstr "マージ"
-msgid "Merge (when the pipeline succeeds)"
-msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸"
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr "マージリクエスト %{iid} ㌠%{authorName}ã«ã‚ˆã£ã¦ä½œæˆã•ã‚
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "マージリクエスト承èª"
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr "マージリクエスト"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "マージリクエストã¨ã¯ã€ãƒ—ロジェクトã«åŠ ãˆãŸå¤‰æ›´ã‚’æ示ã—ã€ãã®å¤‰æ›´ã«ã¤ã„ã¦ä»–ã®ãƒ¡ãƒ³ãƒãƒ¼ã¨è©±ã—åˆã†ãŸã‚ã®å ´æ‰€ã§ã™"
@@ -17012,7 +17460,7 @@ msgid "MergeRequests|Reply..."
msgstr "返信..."
msgid "MergeRequests|Resolve this thread in a new issue"
-msgstr "æ–°ã—ã„課題ã§ã“ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’解決ã™ã‚‹"
+msgstr "æ–°ã—ã„イシューã§ã“ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’解決ã™ã‚‹"
msgid "MergeRequests|Saving the comment failed"
msgstr "コメントã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -17074,9 +17522,15 @@ msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr "マージ済ã¿"
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 "既存ã®ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã«æ‚ªå½±éŸ¿ã‚’与ãˆã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ãŸã‚ã€ç›´ã¡ã«ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ã¯å‹§ã‚られã¾ã›ã‚“。詳細ã«ã¤ã„ã¦ã¯ã€ %{docsLinkStart}ドキュメント%{docsLinkEnd} ã‚’ãŠèª­ã¿ãã ã•ã„。"
@@ -17488,7 +17939,7 @@ msgid "Milestone lists not available with your current license"
msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯ マイルストーンリストを利用ã§ãã¾ã›ã‚“"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr "マイルストーンリストã«ã¯ã€é¸æŠžã—ãŸãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®èª²é¡Œã‚’表示ã—ã¾ã™ã€‚"
+msgstr "マイルストーンリストã«ã¯ã€é¸æŠžã—ãŸãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示ã—ã¾ã™ã€‚"
msgid "MilestoneCombobox|An error occurred while searching for milestones"
msgstr ""
@@ -17578,7 +18029,7 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
msgstr "ã‚ãªãŸã¯ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ %{milestoneTitle} を永久ã«å‰Šé™¤ã—〠%{issuesWithCount} 㨠%{mergeRequestsWithCount} ã‹ã‚‰å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚一度削除ã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr "ã‚ãªãŸã¯ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ %{milestoneTitle} を永久ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã¯ç¾åœ¨ã€èª²é¡Œã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+msgstr "ã‚ãªãŸã¯ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ %{milestoneTitle} を永久ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã¯ç¾åœ¨ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Milestones|Close Milestone"
msgstr ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr "ミラーã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr "ミラー化ã•ã‚ŒãŸãƒ–ランãƒã«ã¯ã“ã®ãƒ—レフィックスãŒä»˜ãã¾ã™ã€‚ 「ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã®ã¿ã‚’ミラーリングã™ã‚‹ã€ã‚’有効ã«ã—ãŸå ´åˆã€ã“ã®ãƒ—ロジェクトã®ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã«ã‚‚ã“ã®ãƒ—レフィックスãŒãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。ãã†ã§ãªã„ã¨ã€ä½•ã‚‚ミラーリングã§ãã¾ã›ã‚“。"
-
msgid "Mirrored repositories"
msgstr "ミラーã•ã‚ŒãŸãƒªãƒã‚¸ãƒˆãƒª"
@@ -17779,10 +18227,10 @@ msgid "Move"
msgstr "移動"
msgid "Move issue"
-msgstr "課題を移動"
+msgstr "イシューを移動"
msgid "Move issue from one column of the board to another"
-msgstr "ボードã®ã‚るカラムã‹ã‚‰åˆ¥ã®ã‚«ãƒ©ãƒ ã¸èª²é¡Œã‚’移動"
+msgstr "ボードã®ã‚るカラムã‹ã‚‰åˆ¥ã®ã‚«ãƒ©ãƒ ã¸ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’移動"
msgid "Move selection down"
msgstr "é¸æŠžã‚’下ã¸ç§»å‹•"
@@ -17794,25 +18242,25 @@ msgid "Move test case"
msgstr ""
msgid "Move this issue to another project."
-msgstr "課題を別ã®ãƒ—ロジェクトã«ç§»å‹•ã™ã‚‹"
+msgstr "イシューを別ã®ãƒ—ロジェクトã«ç§»å‹•ã™ã‚‹"
msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
-msgstr "権é™ãŒä¸å分ãªãŸã‚ã€èª²é¡Œã‚’移動ã§ãã¾ã›ã‚“。"
+msgstr "権é™ãŒä¸å分ãªãŸã‚ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’移動ã§ãã¾ã›ã‚“。"
msgid "MoveIssue|Cannot move issue to project it originates from!"
-msgstr "発行元ã®ãƒ—ロジェクトã«èª²é¡Œã‚’移動ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgstr "発行元ã®ãƒ—ロジェクトã«ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’移動ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
msgid "Moved issue to %{label} column in the board."
-msgstr "課題ã¯ãƒœãƒ¼ãƒ‰ã® %{label} 列ã«ç§»å‹•ã—ãŸã€‚"
+msgstr "イシューをボード㮠%{label} 列ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
msgid "Moved this issue to %{path_to_project}."
-msgstr "課題㯠%{path_to_project} ã«ç§»å‹•ã—ãŸã€‚"
+msgstr "イシューを %{path_to_project} ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
msgid "Moves issue to %{label} column in the board."
-msgstr "課題をボード㮠%{label} 列ã«ç§»å‹•ã—ã¾ã™ã€‚"
+msgstr "イシューをボード㮠%{label} 列ã«ç§»å‹•ã—ã¾ã™ã€‚"
msgid "Moves this issue to %{path_to_project}."
-msgstr "課題を %{path_to_project} ã«ç§»å‹•ã™ã‚‹ã€‚"
+msgstr "イシューを %{path_to_project} ã«ç§»å‹•ã—ã¾ã™ã€‚"
msgid "MrDeploymentActions|Deploy"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "マルãƒèª²é¡Œãƒœãƒ¼ãƒ‰"
-
msgid "Multiple model types found: %{model_types}"
msgstr "複数ã®ãƒ¢ãƒ‡ãƒ«ã‚¿ã‚¤ãƒ—ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %{model_types}"
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18214,7 +18668,7 @@ msgstr "æ–°ã—ã„ ID"
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] "æ–°è¦èª²é¡Œ"
+msgstr[0] "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "New Jira import"
msgstr "æ–°ã—ã„ Jira インãƒãƒ¼ãƒˆ"
@@ -18288,6 +18742,12 @@ 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 "æ–°ã—ã„ヘルスãƒã‚§ãƒƒã‚¯ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã—ã¾ã—ãŸã€‚"
@@ -18295,10 +18755,10 @@ msgid "New identity"
msgstr "æ–°ã—ã„ ID"
msgid "New issue"
-msgstr "æ–°è¦èª²é¡Œ"
+msgstr "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "New issue title"
-msgstr "æ–°ã—ã„課題ã®ã‚¿ã‚¤ãƒˆãƒ«"
+msgstr "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¿ã‚¤ãƒˆãƒ«"
msgid "New iteration"
msgstr ""
@@ -18426,7 +18886,7 @@ msgstr "ブランãƒãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
msgid "No changes"
msgstr "変更ãªã—"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr "プライベートプロジェクトã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“"
msgid "Not available for protected branches"
msgstr "ä¿è­·ãƒ–ランãƒã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "機密ã§ã¯ãªã„"
@@ -18690,6 +19153,9 @@ msgstr "準備ãŒã¾ã ã§ãã¦ã„ã¾ã›ã‚“。ã‚ã¨ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã
msgid "Not started"
msgstr "開始ã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr "注æ„事項"
@@ -18766,7 +19232,7 @@ msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
msgid "NotificationEvent|Close issue"
-msgstr "課題をクローズ"
+msgstr "イシューをクローズ"
msgid "NotificationEvent|Close merge request"
msgstr "マージリクエストをクローズ"
@@ -18790,7 +19256,7 @@ msgid "NotificationEvent|New epic"
msgstr "æ–°è¦ã‚¨ãƒ“ック"
msgid "NotificationEvent|New issue"
-msgstr "æ–°è¦èª²é¡Œ"
+msgstr "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "NotificationEvent|New merge request"
msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -18805,13 +19271,13 @@ msgid "NotificationEvent|Push to merge request"
msgstr ""
msgid "NotificationEvent|Reassign issue"
-msgstr "課題ã®æ‹…当者を変更"
+msgstr "イシューã®æ‹…当者を変更"
msgid "NotificationEvent|Reassign merge request"
msgstr "マージリクエスト担当者を変更"
msgid "NotificationEvent|Reopen issue"
-msgstr "課題をå†ã‚ªãƒ¼ãƒ—ン"
+msgstr "イシューをå†ã‚ªãƒ¼ãƒ—ン"
msgid "NotificationEvent|Reopen merge request"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr "ãŠã£ã¨!"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "å¤ã„é †"
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19133,7 +19701,7 @@ msgid "Open in file view"
msgstr ""
msgid "Open issues"
-msgstr "課題を開ã"
+msgstr "イシューを開ã"
msgid "Open raw"
msgstr "ãã®ã¾ã¾é–‹ã"
@@ -19157,7 +19725,7 @@ msgid "Opened MRs"
msgstr ""
msgid "Opened issues"
-msgstr "オープン中ã®èª²é¡Œ"
+msgstr "オープン中ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "OpenedNDaysAgo|Opened"
msgstr "オープンã•ã‚ŒãŸã®ã¯"
@@ -19297,6 +19865,9 @@ msgstr "パッケージã®ãƒ¬ã‚·ãƒ”ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™"
msgid "Package type must be Conan"
msgstr "パッケージタイプ㌠Conan ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "パッケージタイプ㌠Maven ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr "Yarn コマンドをコピー"
msgid "PackageRegistry|Copy yarn setup command"
msgstr "Yarn 設定コマンドã®ã‚³ãƒ”ー"
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr "パッケージãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®å‰Šé™¤"
@@ -19453,12 +20024,18 @@ msgstr "NuGet コマンド"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
-msgstr "pip コマンド"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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 "pip コマンド"
+
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr ""
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Pages"
@@ -19691,7 +20262,7 @@ msgid "Paste epic link"
msgstr "エピックリンクã®è²¼ã‚Šä»˜ã‘"
msgid "Paste issue link"
-msgstr "課題リンクã®è²¼ã‚Šä»˜ã‘"
+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 ""
@@ -19711,11 +20282,14 @@ msgstr "パスã«ã¯ã€*/welcomeã®ã‚ˆã†ãªãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰ã‚’å«ã‚ã‚‹ã“
msgid "Pause"
msgstr "åœæ­¢"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr "レプリケーションã®ä¸€æ™‚åœæ­¢"
-msgid "Paused Runners don't accept new jobs"
-msgstr "一時åœæ­¢ã—ãŸãƒ©ãƒ³ãƒŠãƒ¼ã¯æ–°ã—ã„ジョブをå—ã‘入れãªã„"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "ä¿ç•™ä¸­"
@@ -19783,6 +20357,9 @@ msgstr "パーミッションã€LFSã€2FA"
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 "個人的ãªãƒ—ロジェクトã®ä½œæˆã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。質å•ãŒã‚ã‚‹å ´åˆã¯ã‚·ã‚¹ãƒ†ãƒ ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„"
@@ -19819,6 +20396,9 @@ msgstr "パイプラインスケジュール"
msgid "Pipeline minutes quota"
msgstr "パイプラインクォータ(分)"
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ msgstr "パイプラインã®ãƒˆãƒªã‚¬ãƒ¼"
msgid "Pipeline: %{status}"
msgstr "パイプライン: %{status}"
+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 "CI/CD 分æž"
@@ -19846,7 +20435,7 @@ msgstr "æˆåŠŸæ¯”率:"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸ:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "パイプラインを読ã¿è¾¼ã¿ä¸­"
@@ -20017,6 +20615,18 @@ 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 "ã“ã‚Œã¯è¦ªãƒ‘イプライン内ã«ã‚ã‚‹å­ãƒ‘イプラインã§ã™"
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 "æ–°ã—ã„アカウントã®ãƒ‘スワードを作æˆã—ã¦ãã ã•ã„。"
@@ -20269,6 +20885,9 @@ msgstr "%{number} より大ãã„数字を入力ã—ã¦ãã ã•ã„。(プロジã
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 "有効ãªæ•°å€¤ã‚’入力ã—ã¦ãã ã•ã„"
@@ -20360,7 +20979,7 @@ 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 "課題やコメントã¸ã®ã‚¹ãƒ‘ム行為ã€ã¾ãŸä¸é©åˆ‡ãªæŒ™å‹•ã‚’ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¤ã„ã¦ã¯ã€ã“ã¡ã‚‰ã®ãƒ•ã‚©ãƒ¼ãƒ ã‹ã‚‰ç®¡ç†è€…ã«å ±å‘Šã—ã¦ãã ã•ã„。"
+msgstr "イシューやコメントã¸ã®ã‚¹ãƒ‘ム行為ã€ã¾ãŸä¸é©åˆ‡ãªæŒ™å‹•ã‚’ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¤ã„ã¦ã¯ã€ã“ã¡ã‚‰ã®ãƒ•ã‚©ãƒ¼ãƒ ã‹ã‚‰ç®¡ç†è€…ã«å ±å‘Šã—ã¦ãã ã•ã„。"
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "少々ãŠå¾…ã¡ãã ã•ã„。準備ãŒæ•´ã„次第ã“ã®ãƒšãƒ¼ã‚¸ã¯è‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
@@ -20479,14 +21098,17 @@ msgstr "%{key} + C を押ã—ã¦ã‚³ãƒ”ーã™ã‚‹"
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request 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 approval of merge requests by merge request committers"
-msgstr "マージリクエストã®ã‚³ãƒŸãƒƒã‚¿ãƒ¼ã«ã‚ˆã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®æ‰¿èªã‚’ç¦æ­¢ã™ã‚‹"
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
msgid "Prevent environment from auto-stopping"
msgstr "環境ãŒè‡ªå‹•åœæ­¢ã—ãªã„よã†ã«ã™ã‚‹"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr "ユーザーãŒãƒ—ロファイルåを変更ã§ããªã„よã†ã«è¨­å®šã™ã‚‹"
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr "プライマリ"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "優先順ä½ã‚’付ã‘ã‚‹"
@@ -20651,7 +21276,7 @@ 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 "ã‚ãªãŸã¯ %{yourAccount} ã¨ã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒªãƒ³ã‚¯ã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ã‚°ãƒ«ãƒ¼ãƒ—を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ %{deleteAccount} を確èªã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgstr "ã‚ãªãŸã¯ %{yourAccount} ã¨ã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒªãƒ³ã‚¯ã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ã‚°ãƒ«ãƒ¼ãƒ—を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ %{deleteAccount} を確èªã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
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 "ユーザåã‚’ %{currentUsernameBold} ã‹ã‚‰ %{newUsernameBold} ã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚プロファイルã¨ãƒ—ロジェクト㯠%{newUsername} åå‰ç©ºé–“ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã™ã€‚ã—ã‹ã—〠%{currentUsername} åå‰ç©ºé–“ãŒåˆ¥ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚ˆã£ã¦ç™»éŒ²ã•ã‚Œã‚‹ã¨ã€ã“ã®ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã¯æœŸé™åˆ‡ã‚Œã«ãªã‚Šã¾ã™ã€‚ Gitリãƒã‚¸ãƒˆãƒªã®ãƒªãƒ¢ãƒ¼ãƒˆã‚’ã§ãã‚‹ã ã‘æ—©ãæ›´æ–°ã—ã¦ãã ã•ã„。"
@@ -20665,6 +21290,9 @@ msgstr ""
msgid "Profiles|@username"
msgstr "@username"
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "削除予定ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã™ã€‚"
@@ -20767,6 +21395,9 @@ msgstr "フィードトークンを正常ã«ãƒªã‚»ãƒƒãƒˆã§ãã¾ã—ãŸ"
msgid "Profiles|Full name"
msgstr "フルãƒãƒ¼ãƒ "
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 "ã‚ãªãŸã®æ–°ã—ã„ã‚¢ãƒã‚¿ãƒ¼ã®ä½ç½®ã¨ã‚µã‚¤ã‚º"
@@ -21097,9 +21731,6 @@ msgstr "プロジェクトå"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr "ローカルストレージãŒåˆ©ç”¨ã§ããªã„ãŸã‚ã€ãƒ—ロジェクトã®é †åºã¯ä¿å­˜ã•ã‚Œã¾ã›ã‚“。"
@@ -21256,12 +21887,18 @@ 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 "期é™åˆ‡ã‚Œã«ãªã£ãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®å·®åˆ†ãƒ‡ã‚£ã‚¹ã‚«ãƒƒã‚·ãƒ§ãƒ³ã‚’自動的ã«è§£æ±ºã—ã¾ã™ã€‚"
@@ -21289,8 +21926,8 @@ msgstr "ã“ã®è¨­å®šã‚’変更ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。
msgid "ProjectSettings|Container registry"
msgstr "コンテナレジストリ"
-msgid "ProjectSettings|Customize your project badges."
-msgstr "ã‚ãªãŸã®ãƒ—ロジェクトãƒãƒƒã‚¸ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º"
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr "メール通知を無効ã«ã™ã‚‹"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "マージã”ã¨ã«ãƒžãƒ¼ã‚¸ã‚³ãƒŸãƒƒãƒˆãŒä½œæˆã•ã‚Œã¾ã™"
@@ -21353,16 +21993,13 @@ msgid "ProjectSettings|Internal"
msgstr "内部"
msgid "ProjectSettings|Issues"
-msgstr "課題"
+msgstr "イシュー"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "ãƒãƒƒã‚¸ã®è©³ç´°ã€‚"
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
-msgstr "ã“ã®ãƒ—ロジェクトã®è»½é‡ã®èª²é¡Œè¿½è·¡ã‚·ã‚¹ãƒ†ãƒ "
+msgstr "ã“ã®ãƒ—ロジェクトã®è»½é‡ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ "
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files"
msgstr "オーディオã€ãƒ“デオã€ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãªã©ã®å¤§ããªãƒ•ã‚¡ã‚¤ãƒ«ã‚’管ç†ã—ã¾ã™"
@@ -21397,6 +22034,9 @@ msgstr "注:プロジェクトãŒå…¬é–‹ã®å ´åˆã€ã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒª
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã¯ç½²åã•ã‚ŒãŸã‚³ãƒŸãƒƒãƒˆã®ã¿ãƒ—ッシュã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "パッケージ"
@@ -21505,14 +22145,23 @@ 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|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 "ã“ã®æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã¨ã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãŠã‚ˆã³ã‚¹ãƒ‹ãƒšãƒƒãƒˆã«ã¯ã€è³›æˆã¨å対ã®çµµæ–‡å­—リアクションボタンãŒå¸¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
+msgstr "ã“ã®æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã¨ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãŠã‚ˆã³ã‚¹ãƒ‹ãƒšãƒƒãƒˆã«ã¯ã€è³›æˆã¨å対ã®çµµæ–‡å­—リアクションボタンãŒå¸¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
@@ -21529,9 +22178,6 @@ msgstr ".Net Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21586,7 +22235,7 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -21887,7 +22536,7 @@ msgid "Promote confidential issue to a non-confidential epic"
msgstr ""
msgid "Promote issue to an epic"
-msgstr "課題をエピックã«æ˜‡æ ¼"
+msgstr "イシューをエピックã«æ˜‡æ ¼"
msgid "Promote to epic"
msgstr ""
@@ -21908,7 +22557,7 @@ msgid "Promoted confidential issue to a non-confidential epic. Information in th
msgstr ""
msgid "Promoted issue to an epic."
-msgstr "課題をエピックã«æ˜‡æ ¼æ¸ˆã¿"
+msgstr "イシューをエピックã«æ˜‡æ ¼æ¸ˆã¿"
msgid "Promotion is not supported."
msgstr ""
@@ -21938,7 +22587,7 @@ 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 "エピックを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトやマイルストーンをã¾ãŸãŒã‚‹å…±é€šãƒ†ãƒ¼ãƒžã®èª²é¡Œã‚°ãƒ«ãƒ¼ãƒ—を追跡ã§ãã€ãƒ—ロジェクトã®ãƒãƒ¼ãƒˆãƒ•ã‚©ãƒªã‚ªã‚’より効率的ã«ç°¡å˜ã«ç®¡ç†ã§ãã¾ã™ã€‚"
+msgstr "エピックを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトやマイルストーンをã¾ãŸãŒã‚‹å…±é€šãƒ†ãƒ¼ãƒžã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’追跡ã§ãã€ãƒ—ロジェクトã®ãƒãƒ¼ãƒˆãƒ•ã‚©ãƒªã‚ªã‚’より効率的ã«ç°¡å˜ã«ç®¡ç†ã§ãã¾ã™ã€‚"
msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
msgstr ""
@@ -21983,13 +22632,13 @@ msgid "Promotions|Weight"
msgstr ""
msgid "Promotions|Weighting your issue"
-msgstr "課題ã®é‡ã¿ä»˜ã‘"
+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 "多ãã®èª²é¡ŒãŒã‚ã‚‹å ´åˆã€å…¨ä½“を把æ¡ã™ã‚‹ã®ã¯å›°é›£ã§ã™ã€‚ 課題ã«é‡ã¿ã‚’付ã‘ã‚‹ã“ã¨ã§ã€ãã‚Œãžã‚Œã®åŠ´åŠ›ã€ã‚³ã‚¹ãƒˆã€å¿…è¦ãªæ™‚é–“ã€ã¾ãŸã¯ä¾¡å€¤ã‚’よりよã把æ¡ã§ãã€ãれらをよりé©åˆ‡ã«ç®¡ç†ã§ãã¾ã™ã€‚"
+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 "貢献度分æžã‚’使用ã™ã‚‹ã¨ã€çµ„ç¹”ã¨ãã®ãƒ¡ãƒ³ãƒãƒ¼ã®èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒ—ッシュイベントã®æ´»å‹•ã®æ¦‚è¦ã‚’知るã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgstr "貢献度分æžã‚’使用ã™ã‚‹ã¨ã€çµ„ç¹”ã¨ãã®ãƒ¡ãƒ³ãƒãƒ¼ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒ—ッシュイベントã®æ´»å‹•ã®æ¦‚è¦ã‚’知るã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "Prompt users to upload SSH keys"
msgstr "SSH éµã‚’アップロードã™ã‚‹ã‚ˆã†ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ä¿ƒã™"
@@ -22027,8 +22676,8 @@ 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 "%{code_tag_start} *-stable%{code_tag_end}ã¾ãŸã¯%{code_tag_start} production / *%{code_tag_end}ãªã©ã®%{wildcards_link_start} ワイルドカード%{wildcards_link_end}をサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™"
+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 "マージを許å¯"
@@ -22060,8 +22709,8 @@ msgstr "ブランãƒã‚’ä¿è­·"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr "ä¿è­·ãƒ–ランム(%{protected_branches_count})"
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
-msgstr "CODEOWNERSファイルã¨ä¸€è‡´ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«åを変更ã™ã‚‹ãƒ—ッシュã¯æ‹’å¦ã•ã‚Œã¾ã™"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
msgstr "コード所有者ã®æ‰¿èªãŒå¿…è¦ï¼š"
@@ -22277,7 +22926,7 @@ msgid "Queued"
msgstr "キュー済"
msgid "Quick actions can be used in the issues description and comment boxes."
-msgstr "クイックアクションã¯èª²é¡Œã®èª¬æ˜Žã¨ã‚³ãƒ¡ãƒ³ãƒˆæ¬„ã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
+msgstr "クイックアクションã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã®èª¬æ˜Žã¨ã‚³ãƒ¡ãƒ³ãƒˆæ¬„ã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
msgid "Quick range"
msgstr "クイックレンジ"
@@ -22316,7 +22965,7 @@ msgid "Read more about project permissions %{help_link_open}here%{help_link_clos
msgstr ""
msgid "Read more about related issues"
-msgstr "関連ã™ã‚‹èª²é¡Œã«ã¤ã„ã¦ã‚‚ã£ã¨èª­ã‚€"
+msgstr "関連ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã«ã¤ã„ã¦ã‚‚ã£ã¨èª­ã‚€"
msgid "Real-time features"
msgstr "リアルタイム機能"
@@ -22327,6 +22976,12 @@ msgstr "Rebase"
msgid "Rebase in progress"
msgstr "進行中㮠Rebase"
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "手動ã§è¨­å®šã—ãŸPrometheusサーãƒãƒ¼ã‹ã‚‰ã‚¢ãƒ©ãƒ¼ãƒˆã‚’å—ã‘å–る。"
@@ -22345,6 +23000,9 @@ msgstr "最近ã®ãƒ—ロジェクトアクティビティ"
msgid "Recent Searches Service is unavailable"
msgstr "最近ã®æ¤œç´¢ã‚µãƒ¼ãƒ“スã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "最近ã®æ¤œç´¢"
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22458,7 +23119,7 @@ msgid "Related Deployed Jobs"
msgstr "関連ã™ã‚‹ãƒ‡ãƒ—ロイ済ジョブ"
msgid "Related Issues"
-msgstr "関連ã™ã‚‹èª²é¡Œ"
+msgstr "関連ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Related Jobs"
msgstr "関連ã™ã‚‹ã‚¸ãƒ§ãƒ–"
@@ -22569,15 +23230,15 @@ msgstr "Runner を削除"
msgid "Remove Zoom meeting"
msgstr "Zoom ミーティングを削除"
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr "優先度を削除"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "セカンダリノードã®å‰Šé™¤"
@@ -22692,6 +23356,9 @@ msgstr "%{label_references} %{label_text} を削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{milestone_reference} milestone."
msgstr "%{milestone_reference} マイルストーンを削除ã—ã¾ã—ãŸã€‚"
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "Id %{id} 㮠%{type} を削除"
@@ -22699,7 +23366,7 @@ msgid "Removed all labels."
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除済ã¿"
msgid "Removed an issue from an epic."
-msgstr "課題をエピックã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚"
+msgstr "イシューをエピックã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚"
msgid "Removed group can not be restored!"
msgstr "削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã¯ãƒ¬ã‚¹ãƒˆã‚¢ã§ãã¾ã›ã‚“ï¼"
@@ -22737,11 +23404,14 @@ msgstr "%{label_references} %{label_text} を削除ã—ã¾ã™ã€‚"
msgid "Removes %{milestone_reference} milestone."
msgstr "%{milestone_reference} マイルストーンを削除"
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除"
msgid "Removes an issue from an epic."
-msgstr "エピックã‹ã‚‰èª²é¡Œã‚’削除"
+msgstr "エピックã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’削除"
msgid "Removes parent epic %{epic_ref}."
msgstr "親エピック %{epic_ref} を削除ã—ã¾ã™ã€‚"
@@ -22767,6 +23437,9 @@ msgstr "フォルダåを変更"
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "リãƒã‚¸ãƒˆãƒª"
@@ -23067,9 +23740,6 @@ msgstr "é¸æŠž"
msgid "Request Access"
msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,8 +23782,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "GitLab ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã«ã€ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹ã“ã¨ã‚’è¦æ±‚ã—ã¾ã™ã€‚"
-msgid "Require user password to approve"
-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 "ユーザーã«ã‚«ã‚¹ã‚¿ãƒ ãƒ‰ãƒ¡ã‚¤ãƒ³ã®æ‰€æœ‰ã‚’証明ã™ã‚‹ã“ã¨ã‚’è¦æ±‚ã™ã‚‹"
@@ -23139,9 +23812,6 @@ msgstr "è¦ä»¶ã® %{reference} ãŒå†ã‚ªãƒ¼ãƒ—ンã•ã‚Œã¾ã—ãŸ"
msgid "Requirement %{reference} has been updated"
msgstr "è¦ä»¶ã® %{reference} ãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸ"
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23211,7 +23881,7 @@ msgid "Resolve"
msgstr "解決ã™ã‚‹"
msgid "Resolve all threads in new issue"
-msgstr "æ–°ã—ã„課題ã®ã™ã¹ã¦ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’解決ã™ã‚‹"
+msgstr "æ–°ã—ã„イシューã®ã™ã¹ã¦ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’解決ã™ã‚‹"
msgid "Resolve conflicts"
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr "IPアドレスを一度解決ã—ã¦ã€ãれを使ã£ã¦ãƒªã‚¯ã‚¨ã‚¹ãƒˆã
msgid "Response"
msgstr "レスãƒãƒ³ã‚¹"
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr "応答㫠`service_desk_address`ã¯å«ã¾ã‚Œã¦ã„ã¾ã›ã‚“ã§ã—ãŸ"
@@ -23273,6 +23937,9 @@ msgstr "レスãƒãƒ³ã‚¹ãƒ¡ãƒˆãƒªãƒƒã‚¯ (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "レスãƒãƒ³ã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "ターミナルをå†èµ·å‹•"
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr "最新ã®ã‚¢ãƒ—リを表示"
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr "Webターミナルを使用ã—ã¦ãƒ†ã‚¹ãƒˆã‚’実行"
msgid "Run untagged jobs"
msgstr "ã‚¿ã‚°ã®ãªã„ジョブã®å®Ÿè¡Œ"
-msgid "Runner cannot be assigned to other projects"
-msgstr "Runnerã‚’ä»–ã®ãƒ—ロジェクトã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¾ã›ã‚“"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "Runnerã¯æœªå‰²ã‚Šå½“ã¦ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã‹ã‚‰ã‚¸ãƒ§ãƒ–を実行ã—ã¾ã™"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "Runnerã¯ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã®æœªå‰²ã‚Šå½“ã¦ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã‹ã‚‰ã‚¸ãƒ§ãƒ–を実行ã—ã¾ã™"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "Runnerã¯å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸãƒ—ロジェクトã‹ã‚‰ã‚¸ãƒ§ãƒ–を実行ã—ã¾ã™"
-
msgid "Runner token"
msgstr "Runner トークン"
@@ -23473,9 +24134,6 @@ msgstr "Runner ã¯æ›´æ–°ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Runner was successfully updated."
msgstr "Runner ã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
-msgid "Runner will not receive any new jobs"
-msgstr "Runnerã¯æ–°ã—ã„ジョブを処ç†ã—ã¾ã›ã‚“"
-
msgid "Runners"
msgstr "Runner"
@@ -23485,14 +24143,17 @@ 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 placed on separate users, servers, even on your local machine."
-msgstr "Runnerã¯åˆ¥ã€…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã‚µãƒ¼ãƒãƒ¼ã€ã•ã‚‰ã«ã¯ã‚ãªãŸã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒžã‚·ãƒ¼ãƒ³ã«ã‚‚é…ç½®ã§ãã¾ã™ã€‚"
+msgid "Runners can be:"
+msgstr ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "ç¾åœ¨ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã®Runner: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr "SSH 公開éµ"
msgid "SSL Verification:"
msgstr "SSL ã®æ¤œè¨¼:"
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,11 +24350,11 @@ msgstr "スケジュール済"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
-msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’マージã™ã‚‹ã‚ˆã†ã«ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã—ã¾ã—ãŸ"
+msgid "Scheduled to merge this merge request (%{strategy})."
+msgstr ""
msgid "Schedules"
msgstr "スケジュール"
@@ -23704,8 +24371,8 @@ msgstr "パイプラインスケジューリング"
msgid "Scope"
msgstr "スコープ"
-msgid "Scoped issue boards"
-msgstr "スコープ付課題ボード"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr "スコープ"
@@ -23789,7 +24456,7 @@ msgid "Search for a user"
msgstr "ユーザーを検索"
msgid "Search for projects, issues, etc."
-msgstr "プロジェクトや課題ãªã©ã‚’検索ã™ã‚‹ã€‚"
+msgstr "プロジェクトやイシューãªã©ã‚’検索ã™ã‚‹ã€‚"
msgid "Search for this text"
msgstr "ã“ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’検索"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "ユーザーを検索"
@@ -23843,10 +24513,10 @@ msgid "SearchAutocomplete|All GitLab"
msgstr "å…¨ã¦ã® GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr "自身ãŒä½œæˆã—ãŸèª²é¡Œ"
+msgstr "自身ãŒä½œæˆã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr "自身ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸèª²é¡Œ"
+msgstr "自身ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "SearchAutocomplete|Merge requests I've created"
msgstr "自身ãŒä½œæˆã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -23854,6 +24524,9 @@ 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 "å…¨ã¦ã® GitLab 中ã§"
@@ -23896,7 +24569,7 @@ msgstr[0] ""
msgid "SearchResults|issue"
msgid_plural "SearchResults|issues"
-msgstr[0] "課題"
+msgstr[0] "イシュー"
msgid "SearchResults|merge request"
msgid_plural "SearchResults|merge requests"
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
-msgstr "ライセンススキャンを有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ %{linkStart}詳細情報%{linkEnd}ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
-msgstr "セキュリティスキャナーを一ã¤ä»¥ä¸Šæœ‰åŠ¹ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ %{linkStart}詳細情報%{linkEnd}ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+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}More information%{linkEnd}"
+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."
@@ -24082,7 +24755,7 @@ msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
msgid "SecurityReports|Create issue"
-msgstr "課題を作æˆã™ã‚‹"
+msgstr "イシューを作æˆã™ã‚‹"
msgid "SecurityReports|Dismiss Selected"
msgstr ""
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr "トピックã¯ã‚³ãƒ³ãƒžã§åŒºåˆ‡ã‚Šã¾ã™ã€‚"
msgid "September"
msgstr "9月"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 "サービスデスクã¯æœ‰åŠ¹ã§ã™ã€‚ã—ã‹ã—アクティブã§ã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -24670,11 +25358,8 @@ 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 template for issue descriptions."
-msgstr "課題説明ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ†ãƒ³ãƒ—レートを設定ã—ã¾ã™ã€‚"
-
-msgid "Set a number of approvals required, the approvers and other approval 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 "%{protocol} プロコトル経由ã§ãƒ—ルã€ãƒ—ッシュã™ã‚‹ãŸã‚ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードを設定。"
@@ -24871,9 +25556,6 @@ msgstr "設定"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr "ã™ã¹ã¦ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを表示"
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr "å…¨ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’表示"
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr "ファイルブラウザを表示"
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示"
@@ -25036,13 +25724,13 @@ msgid_plural "Showing %{count} projects"
msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
-msgstr "%{total_count} 件中 %{limit} ã®èª²é¡Œã‚’表示. "
+msgstr "%{total_count} 件中 %{limit} ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示. "
msgid "Showing %{pageSize} of %{total} issues"
-msgstr "%{total} 件中 %{pageSize} ã®èª²é¡Œã‚’表示"
+msgstr "%{total} 件中 %{pageSize} ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示"
msgid "Showing all issues"
-msgstr "ã™ã¹ã¦ã®èª²é¡Œã‚’表示"
+msgstr "ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示"
msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
@@ -25153,7 +25841,7 @@ msgid "Signing in using your %{label} account without a pre-existing GitLab acco
msgstr "既存ã®GitLabアカウントを使用ã›ãšã«%{label} アカウントを使用ã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ã“ã¨ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Similar issues"
-msgstr "é¡žä¼¼ã®èª²é¡Œ"
+msgstr "é¡žä¼¼ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
@@ -25288,13 +25976,13 @@ msgid "Some common domains are not allowed. %{read_more_link}."
msgstr "ã„ãã¤ã‹ã®ä¸€èˆ¬çš„ãªãƒ‰ãƒ¡ã‚¤ãƒ³ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。 %{read_more_link}."
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 "一部ã®ãƒ¡ãƒ¼ãƒ«ã‚µãƒ¼ãƒãƒ¼ã¯ã€ãƒ¡ãƒ¼ãƒ«é€ä¿¡è€…åã®ä¸Šæ›¸ãをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。ã“ã®ã‚ªãƒ—ションを有効ã«ã™ã‚‹ã¨ã€ä»£ã‚ã‚Šã«ãƒ¡ãƒ¼ãƒ«æœ¬æ–‡ã«èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ã¾ãŸã¯ã‚³ãƒ¡ãƒ³ãƒˆã®ä½œæˆè€…ã®åå‰ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+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 "誰ã‹ãŒåŒæ™‚ã«èª²é¡Œã‚’編集ã—ã¾ã—ãŸã€‚%{linkStart} 課題 %{linkEnd} を確èªã—ã¦ã€å¤‰æ›´ç‚¹ãŒæ„図ã›ãšå‰Šé™¤ã•ã‚Œãªã„よã†ã«æ°—ã‚’ã¤ã‘ã¦ãã ã•ã„。"
+msgstr "誰ã‹ãŒåŒæ™‚ã«ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’編集ã—ã¾ã—ãŸã€‚%{linkStart} イシュー %{linkEnd} を確èªã—ã¦ã€å¤‰æ›´ç‚¹ãŒæ„図ã›ãšå‰Šé™¤ã•ã‚Œãªã„よã†ã«æ°—ã‚’ã¤ã‘ã¦ãã ã•ã„。"
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 "ã‚ãªãŸã®ç·¨é›†ã¨åŒæ™‚ã«èª°ã‹ãŒã“ã® %{issueType} を編集ã—ãŸãŸã‚ã€èª¬æ˜ŽãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ç·¨é›†ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -25302,6 +25990,9 @@ msgstr "ã‚ãªãŸã®ç·¨é›†ã¨åŒæ™‚ã«èª°ã‹ãŒã“ã® %{issueType} を編集ã—ã
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 "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -25315,7 +26006,7 @@ msgid "Something went wrong on our end. Please try again."
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ã経ã£ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。"
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr "課題ã®å…¬é–‹ç¯„囲ã®å¤‰æ›´ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgstr "イシューã®å…¬é–‹ç¯„囲ã®å¤‰æ›´ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "%{issuableDisplayName} をロック状態ã«ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -25338,7 +26029,10 @@ msgstr "æ案ã—ã¦ã„ã‚‹é–“ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Š
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ msgstr "コメントを編集ã™ã‚‹é–“ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€
msgid "Something went wrong while fetching %{listType} list"
msgstr "%{listType} ã®ãƒªã‚¹ãƒˆå–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "コメントã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
@@ -25411,7 +26108,7 @@ msgid "Something went wrong while merging this merge request. Please try again."
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ãƒžãƒ¼ã‚¸ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Something went wrong while moving issues."
-msgstr "課題を移動ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgstr "イシューを移動ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong while obtaining the Let's Encrypt certificate."
msgstr "Let's Encrypt ã®è¨¼æ˜Žæ›¸ã‚’å–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ—ロジェクトをå–å¾—ã§ãã¾ã›ã‚“。"
msgid "Something went wrong, unable to search projects"
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ—ロジェクトを検索ã§ãã¾ã›ã‚“。"
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,15 +26581,18 @@ msgstr "開始中..."
msgid "Starts %{startsIn}"
msgstr "%{startsIn} を開始ã—ã¾ã™"
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "開始時刻 (UTC)"
+msgid "Starts on"
+msgstr ""
+
msgid "State your message to activate"
msgstr "メッセージを有効ã«ã™ã‚‹"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr "é™çš„アプリケーションセキュリティテスト (SAST)"
@@ -25908,6 +26611,9 @@ 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 "ブランãƒã‚’作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26107,7 +26816,7 @@ msgid "Submit feedback"
msgstr "フィードãƒãƒƒã‚¯ã‚’é€ä¿¡"
msgid "Submit issue"
-msgstr "課題ã®é€ä¿¡"
+msgstr "イシューを作æˆ"
msgid "Submit review"
msgstr "レビューをé€ä¿¡"
@@ -26163,6 +26872,9 @@ msgstr "サブスクリプションã®ä½œæˆã«æˆåŠŸã—ã¾ã—ãŸã€‚"
msgid "Subscription successfully deleted."
msgstr "サブスクリプションã®å‰Šé™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚"
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "システム"
@@ -26608,7 +27326,7 @@ msgid "Template"
msgstr "テンプレート"
msgid "Template to append to all Service Desk issues"
-msgstr "å…¨ã¦ã®ã‚µãƒ¼ãƒ“スデスク課題ã«è¿½åŠ ã™ã‚‹ãƒ†ãƒ³ãƒ—レート"
+msgstr "å…¨ã¦ã®ã‚µãƒ¼ãƒ“スデスクã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«è¿½åŠ ã™ã‚‹ãƒ†ãƒ³ãƒ—レート"
msgid "Templates"
msgstr "テンプレート"
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 "テスト"
@@ -26773,7 +27536,7 @@ msgid "TestHooks|Ensure the project has deployments."
msgstr ""
msgid "TestHooks|Ensure the project has issues."
-msgstr "プロジェクトã«èª²é¡ŒãŒã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+msgstr "プロジェクトã«ã‚¤ã‚·ãƒ¥ãƒ¼ãŒã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
msgid "TestHooks|Ensure the project has merge requests."
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -26841,8 +27604,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
-msgstr "ã‚ã‚ŠãŒã¨ã†ï¼ä»Šå¾Œè¡¨ç¤ºã—ãªã„"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -26856,6 +27619,9 @@ msgstr "\"CODEOWNERSã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦\" 設定ã¯%{banner_link_start}ä¿è
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] "%{type} ã«æ¬¡ã®ã‚¨ãƒ©ãƒ¼ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -26866,14 +27632,17 @@ 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 "課題トラッカーã¯ã€ãƒ—ロジェクトを改善ã—ãŸã‚Šè§£æ±ºã—ãŸã‚Šã™ã‚‹ãŸã‚ã«å¿…è¦ãªæƒ…報を追加ã™ã‚‹å ´æ‰€ã§ã™"
+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 "課題トラッカーã¯ã€ãƒ—ロジェクトを改善ã—ãŸã‚Šè§£æ±ºã—ãŸã‚Šã™ã‚‹ãŸã‚ã«å¿…è¦ãªæƒ…報を追加ã™ã‚‹å ´æ‰€ã§ã™ã€‚ã“ã®ãƒ—ロジェクトã«èª²é¡Œã‚’作æˆã™ã‚‹ãŸã‚ã«ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ç™»éŒ²ã¾ãŸã¯ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"
+msgstr "イシュートラッカーã¯ã€ãƒ—ロジェクトを改善ã—ãŸã‚Šè§£æ±ºã—ãŸã‚Šã™ã‚‹ãŸã‚ã«å¿…è¦ãªæƒ…報を追加ã™ã‚‹å ´æ‰€ã§ã™ã€‚ã“ã®ãƒ—ロジェクトã«ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã™ã‚‹ãŸã‚ã«ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ç™»éŒ²ã¾ãŸã¯ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"
msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
msgstr "Prometheusサーãƒãƒ¼ã¯ã€Œæ‚ªã„リクエストã€ã¨å¿œç­”ã—ã¾ã—ãŸã€‚クエリãŒæ­£ã—ãã‚ãªãŸã®Prometheusã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 %{documentationLink}"
@@ -26930,7 +27699,10 @@ msgid "The contents of this group, its subgroups and projects will be permanentl
msgstr ""
msgid "The current issue"
-msgstr "ç¾åœ¨ã®èª²é¡Œ"
+msgstr "ç¾åœ¨ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
+
+msgid "The current user is not authorized to access the job log."
+msgstr ""
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr "データソースã«ã¯æŽ¥ç¶šã§ãã¦ã„ã¾ã™ãŒã€è¡¨ç¤ºã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã¯ã‚ã‚Šã¾ã›ã‚“。 %{documentationLink}"
@@ -27048,14 +27820,11 @@ 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 "課題ステージã§ã¯ã€èª²é¡ŒãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã‚‹ã‹ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®ãƒªã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã™ã‚‹ã«ã¯èª²é¡Œã‚’最åˆã«ä½œæˆã—ã¦ãã ã•ã„。"
+msgstr "イシューステージã«ã¯ã€ã‚¤ã‚·ãƒ¥ãƒ¼ãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã‚‹ã‹ã€ã‚¤ã‚·ãƒ¥ãƒ¼ãƒœãƒ¼ãƒ‰ã®ãƒªã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã‚’表示ã™ã‚‹ã«ã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’最åˆã«ä½œæˆã—ã¦ãã ã•ã„。"
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ %{size} ã§ã™ã€‚"
-msgid "The maximum file size allowed is 200KB."
-msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ 200KB ã§ã™ã€‚"
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«å¯¾ã™ã‚‹ãƒžãƒ¼ã‚¸ã®ç«¶åˆã¯ GitLab ã§ã¯è§£æ±ºã§ãã¾ã›ã‚“。ローカルã§è§£æ±ºã—ã¦ãã ã•ã„。"
@@ -27300,7 +28066,7 @@ msgid "There are no charts configured for this page"
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã«è¨­å®šã—ã¦ã„ã‚‹ãƒãƒ£ãƒ¼ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "There are no closed issues"
-msgstr "クローズã•ã‚ŒãŸèª²é¡Œã¯ã‚ã‚Šã¾ã›ã‚“"
+msgstr "クローズã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "There are no closed merge requests"
msgstr "クローズã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -27312,10 +28078,10 @@ msgid "There are no custom project templates set up for this GitLab instance. Th
msgstr "ã“ã® GitLab インスタンス用ã«è¨­å®šã•ã‚ŒãŸã‚«ã‚¹ã‚¿ãƒ ãƒ—ロジェクトテンプレートã¯ã‚ã‚Šã¾ã›ã‚“。カスタムプロジェクトテンプレート㯠GitLab ã®ç®¡ç†è€…エリアã§æœ‰åŠ¹ã«ã§ãã¾ã™ã€‚設定ã™ã‚‹ã«ã¯ã€ GitLab インスタンス管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
msgid "There are no issues to show"
-msgstr "表示ã™ã‚‹èª²é¡ŒãŒã‚ã‚Šã¾ã›ã‚“"
+msgstr "表示ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "There are no issues to show."
-msgstr "表示ã™ã‚‹èª²é¡ŒãŒã‚ã‚Šã¾ã›ã‚“."
+msgstr "表示ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒã‚ã‚Šã¾ã›ã‚“."
msgid "There are no labels yet"
msgstr "ã¾ã ãƒ©ãƒ™ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -27324,7 +28090,7 @@ msgid "There are no matching files"
msgstr "一致ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "There are no open issues"
-msgstr "オープン中ã®èª²é¡Œã¯ã‚ã‚Šã¾ã›ã‚“"
+msgstr "オープン中ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "There are no open merge requests"
msgstr "オープン中ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27420,7 +28189,7 @@ msgid "There was an error creating the dashboard, branch named: %{branch} alread
msgstr ""
msgid "There was an error creating the issue"
-msgstr "課題ã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgstr "イシューã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "There was an error deleting the To Do."
msgstr "To Doã®å‰Šé™¤ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27555,7 +28330,7 @@ msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚ reCAPTCHA ã‚’ã‚‚ã†ä¸€åº¦å®Ÿæ–½ã—ã¦ãã ã•ã„。"
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
-msgstr "既存ã®èª²é¡Œã«åŒæ§˜ã®ã‚¿ã‚¤ãƒˆãƒ«ãŒã‚ã‚Šã¾ã™ã€‚別ã®ä¼¼ãŸã‚ˆã†ãªèª²é¡Œã‚’作æˆã™ã‚‹ã‚ˆã‚Šã€ãã“ã«ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹æ–¹ãŒè‰¯ã„ã§ã™ã€‚"
+msgstr "既存ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«åŒæ§˜ã®ã‚¿ã‚¤ãƒˆãƒ«ãŒã‚ã‚Šã¾ã™ã€‚別ã®ä¼¼ãŸã‚ˆã†ãªã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã™ã‚‹ã‚ˆã‚Šã€ãã“ã«ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹æ–¹ãŒè‰¯ã„ã§ã™ã€‚"
msgid "These paths are protected for POST requests."
msgstr ""
@@ -27599,6 +28374,9 @@ msgstr "ã“ã® GitLab インスタンスã¯ã¾ã å…±æœ‰ Runner ã‚’æä¾›ã—ã¦ã
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 ""
@@ -27618,7 +28396,7 @@ 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 ""
+msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ã€%{strongOpen}ç›´ã¡ã«%{strongClose}ã€ãƒªãƒã‚¸ãƒˆãƒªã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å«ã‚ã¦%{codeOpen}%{project}%{codeClose}ã‚’%{strongOpen}æ’ä¹…çš„ã«å‰Šé™¤ã—ã¾ã™%{strongClose}。"
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 ""
@@ -27756,7 +28534,7 @@ msgid "This group, its subgroups and projects will be removed on %{date} since i
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 "ã“ã‚Œã¯ã€ä»¥å‰ã«å‰Šé™¤ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã£ã¦ä½œæˆã•ã‚ŒãŸã™ã¹ã¦ã®å•é¡Œã‚’ä¿æŒã™ã‚‹ãŸã‚ã«ä½œæˆã•ã‚ŒãŸã€ã€Œã‚´ãƒ¼ã‚¹ãƒˆãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã§ã™ã€‚ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å‰Šé™¤ã§ãã¾ã›ã‚“。"
+msgstr "ã“ã‚Œã¯ã€ä»¥å‰ã«å‰Šé™¤ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã£ã¦ä½œæˆã•ã‚ŒãŸã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ä¿æŒã™ã‚‹ãŸã‚ã«ä½œæˆã•ã‚ŒãŸã€ã€Œã‚´ãƒ¼ã‚¹ãƒˆãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã§ã™ã€‚ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å‰Šé™¤ã§ãã¾ã›ã‚“。"
msgid "This is a Premium feature"
msgstr ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 "ã“ã® Runner ã¯ä¿è­·ãƒ–ランãƒä¸Šã§èµ·å‹•ã•ã‚ŒãŸãƒ‘イプラインã§ã®ã¿å®Ÿè¡Œã§ãã¾ã™ã€‚"
@@ -27995,9 +28785,6 @@ msgstr "ã“ã®ã‚µãƒ–スクリプションã¯"
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr "ã“ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã¯ã€ãƒ—ロジェクトã§å®šç¾©ã•ã‚ŒãŸã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã‚ˆã‚Šã‚‚å°ã•ã„å ´åˆã«å„ªå…ˆã•ã‚Œã€ã€Œ1時間ã€ãªã©ã®å…¥åŠ›è¨€èªžã«ã‚ˆã‚‹äººãŒèª­ã¿ã‚„ã™ã„相対時間形å¼ã‚’å—ã‘入れã¾ã™ã€‚値ã®æŒ‡å®šãŒç„¡ã„å ´åˆã¯ç§’を表ã—ã¾ã™ã€‚"
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ GitLab ã‹ã‚‰ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«æ“作ã§ãƒ­ãƒƒã‚¯ã‚’解除ã§ãã¾ã›ã‚“"
@@ -28041,7 +28828,7 @@ msgid "This will remove the fork relationship between this project and other pro
msgstr "ã“ã®æ“作ã¯ã€ã“ã®ãƒ—ロジェクトã¨ãƒ•ã‚©ãƒ¼ã‚¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã®ä»–ã®ãƒ—ロジェクトã®é–“ã®ãƒ•ã‚©ãƒ¼ã‚¯é–¢ä¿‚を削除ã—ã¾ã™ã€‚"
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
-msgstr "ã“ã“ã«ãƒªã‚¹ãƒˆã‚¢ãƒƒãƒ—ã•ã‚Œã¦ã„ã‚‹ã“れらã®ãƒ¡ãƒ¼ãƒ«ã¯è‡ªå‹•çš„ã«èª²é¡Œã«ãªã‚Šã¾ã™ã€‚(メールã®ã‚„ã‚Šå–ã‚Šã¯èª²é¡Œã®ã‚³ãƒ¡ãƒ³ãƒˆã«ãªã‚Šã¾ã™ï¼‰"
+msgstr "ã“ã“ã«ãƒªã‚¹ãƒˆã‚¢ãƒƒãƒ—ã•ã‚Œã¦ã„ã‚‹ã“れらã®ãƒ¡ãƒ¼ãƒ«ã¯è‡ªå‹•çš„ã«ã‚¤ã‚·ãƒ¥ãƒ¼ã«ãªã‚Šã¾ã™ã€‚(メールã®ã‚„ã‚Šå–ã‚Šã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚³ãƒ¡ãƒ³ãƒˆã«ãªã‚Šã¾ã™ï¼‰"
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 "è„…å¨ç›£è¦–"
@@ -28118,8 +28938,8 @@ 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."
-msgstr "ã“ã®ãƒ‡ãƒ¼ã‚¿ã‚’表示ã™ã‚‹ã«ã¯ã€ã“ã®ãƒ—ロジェクトã®ç’°å¢ƒã‚’構æˆã—ã€å°‘ãªãã¨ã‚‚1ã¤ã®è„…å¨ç›£è¦–機能ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+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 ""
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28149,10 +28972,10 @@ msgid "Time based: Yes"
msgstr "時間ベース: ã‚ã‚Š"
msgid "Time before an issue gets scheduled"
-msgstr "課題ãŒè¨ˆç”»ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
+msgstr "イシューãŒè¨ˆç”»ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
msgid "Time before an issue starts implementation"
-msgstr "課題ã®å®Ÿè£…ãŒé–‹å§‹ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
+msgstr "イシューã®å®Ÿè£…ãŒé–‹å§‹ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
msgid "Time before enforced"
msgstr "実施å‰ã®æ™‚é–“"
@@ -28442,7 +29265,7 @@ msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
msgid "To keep this project going, create a new issue"
-msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ãŸã‚ã«ã€æ–°ã—ã„課題を作æˆã—ã¦ãã ã•ã„"
+msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ãŸã‚ã«ã€æ–°ã—ã„イシューを作æˆã—ã¦ãã ã•ã„"
msgid "To keep this project going, create a new merge request"
msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ã«ã¯ã€æ–°ã—ã„マージリクエストを作æˆã—ã¦ãã ã•ã„"
@@ -28463,10 +29286,10 @@ msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size
msgstr ""
msgid "To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
-msgstr "ã“ã®èª²é¡Œã®æ©Ÿå¯†æ€§ã‚’ä¿è­·ã™ã‚‹ãŸã‚ã«ã€%{forkLink} ã¨ãƒ•ã‚©ãƒ¼ã‚¯ã®å¯è¦–性をプライベートã«è¨­å®šã—ã¾ã™ã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®æ©Ÿå¯†æ€§ã‚’ä¿è­·ã™ã‚‹ãŸã‚ã«ã€%{forkLink} ã¨ãƒ•ã‚©ãƒ¼ã‚¯ã®å¯è¦–性をプライベートã«è¨­å®šã—ã¾ã™ã€‚"
msgid "To protect this issue's confidentiality, a private fork of this project was selected."
-msgstr "ã“ã®èª²é¡Œã®æ©Ÿå¯†æ€§ã‚’ä¿è­·ã™ã‚‹ãŸã‚ã«ã€ã“ã®ãƒ—ロジェクトã®ãƒ—ライベートフォークãŒé¸æŠžã•ã‚Œã¾ã—ãŸã€‚"
+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 "手動ã§è¨­å®šã•ã‚ŒãŸPrometheus サービスã‹ã‚‰ã‚¢ãƒ©ãƒ¼ãƒˆã‚’å—ä¿¡ã™ã‚‹ã«ã¯ã€æ¬¡ã®URLã¨èªè¨¼ã‚­ãƒ¼ã‚’ Prometheus webhook ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã«è¿½åŠ ã—ã¦ãã ã•ã„。GitLab ã«ã‚¢ãƒ©ãƒ¼ãƒˆã‚’é€ä¿¡ã™ã‚‹ãŸã‚ã® %{linkEnd} Prometheusã®è¨­å®š %{linkStart} ã®è©³ç´°ã‚’ã”覧ãã ã•ã„。"
@@ -28634,7 +29457,7 @@ msgid "Total days to completion"
msgstr ""
msgid "Total issues"
-msgstr "全課題"
+msgstr "全イシュー"
msgid "Total memory (GB)"
msgstr ""
@@ -28661,7 +29484,7 @@ msgid "Tracing"
msgstr "トレーシング"
msgid "Track groups of issues that share a theme, across projects and milestones"
-msgstr "プロジェクトãŠã‚ˆã³ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³å…¨ä½“ã§ã€ãƒ†ãƒ¼ãƒžã‚’共有ã™ã‚‹èª²é¡Œã®ã‚°ãƒ«ãƒ¼ãƒ—を追跡"
+msgstr "プロジェクトãŠã‚ˆã³ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³å…¨ä½“ã§ã€ãƒ†ãƒ¼ãƒžã‚’共有ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚°ãƒ«ãƒ¼ãƒ—を追跡"
msgid "Track time with quick actions"
msgstr "クイックアクションã§ä½œæ¥­æ™‚間を記録"
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 "トリガー"
@@ -29006,13 +29869,13 @@ msgid "Unable to update this epic at this time."
msgstr "ç¾æ™‚点ã§ã¯ã“ã®ã‚¨ãƒ”ックを更新ã§ãã¾ã›ã‚“。"
msgid "Unable to update this issue at this time."
-msgstr "ç¾æ™‚点ã§ã¯ã“ã®å•é¡Œã‚’æ›´æ–°ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。"
+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}"
+msgstr "ã“ã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–化ã—ãŸãƒ—ロジェクトを解除ã™ã‚‹ã¨ã€ã“ã®ãƒ—ロジェクトã«å¤‰æ›´ã‚’加ãˆã‚‰ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªã¯ã‚³ãƒŸãƒƒãƒˆã§ãるよã†ã«ãªã‚Šã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ã‚³ãƒ¡ãƒ³ãƒˆã€ãã®ä»–ã®ã‚¨ãƒ³ãƒ†ã‚£ãƒ†ã‚£ã‚’作æˆã§ãã¾ã™ã€‚ %{strong_start}ã“ã®ãƒ—ロジェクトをアクティブ化ãŒçµ‚ã‚‹ã¨ã€ã“ã®ãƒ—ロジェクトã¯æ¤œç´¢ã¨ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚%{strong_end}"
msgid "Unassign from commenting user"
msgstr ""
@@ -29146,6 +30009,9 @@ msgstr "ジョブã®ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’解除"
msgid "Unstar"
msgstr "スターを外ã™"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "購読を解除"
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr "ã¾ã§"
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,8 +30093,8 @@ msgstr "ã‚ãªãŸã®ãƒ–ックマークã•ã‚ŒãŸURLã‚’æ›´æ–°ã—ã¦ãã ã•ã„。
msgid "Update your group name, description, avatar, and visibility."
msgstr "グループåã€èª¬æ˜Žã€ã‚¢ãƒã‚¿ãƒ¼ã€ãŠã‚ˆã³å¯è¦–性を更新ã—ã¾ã™ã€‚"
-msgid "Update your project name, topics, description and avatar."
-msgstr "プロジェクトåã€ãƒˆãƒ”ックã€èª¬æ˜Žã€ãã‚Œã«ã‚¢ãƒã‚¿ãƒ¼ã‚’æ›´æ–°ã—ã¦ãã ã•ã„。"
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr "プロジェクトåを変更ã§ãã¾ã›ã‚“。プロジェクトã«ã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚¿ã‚°ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã‹ã‚‰ã§ã™ã€‚"
@@ -29242,7 +30108,7 @@ msgstr "æ–°ã—ã„å¯è¦–性レベルã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“ï¼"
msgid "UpdateProject|Project could not be updated!"
msgstr "プロジェクトを更新ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr "グループ ウェブフックを有効ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランã‚
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "課題ボードã®æ©Ÿèƒ½ã‚’強化ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr "マージリクエストã®æ©Ÿèƒ½ã‚’強化ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
@@ -29684,7 +30547,7 @@ 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 "課題ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ãŸã‚Šã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é€ä¿¡ã—ãŸã‚Šã—ã¦è²¢çŒ®ã™ã‚‹ãŸã‚ã«ã€ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã¾ãŸã¯ä½œæˆã—ã¾ã—ょã†ã€‚"
+msgstr "イシューã«ã‚³ãƒ¡ãƒ³ãƒˆã—ãŸã‚Šã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é€ä¿¡ã—ãŸã‚Šã—ã¦è²¢çŒ®ã™ã‚‹ãŸã‚ã«ã€ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã¾ãŸã¯ä½œæˆã—ã¾ã—ょã†ã€‚"
msgid "UserProfile|Most Recent Activity"
msgstr "最新ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティ"
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr "ユーザーを正常ã«è¿½åŠ ã§ãã¾ã—ãŸã€‚"
@@ -29867,10 +30733,10 @@ msgid "ValueStreamAnalytics|%{days}d"
msgstr "%{days}æ—¥"
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
-msgstr "最åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰èª²é¡Œã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
+msgstr "最åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
-msgstr "課題ã®ä½œæˆã‹ã‚‰èª²é¡Œã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
+msgstr "イシューã®ä½œæˆã‹ã‚‰ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -29933,7 +30799,7 @@ msgid "View alert details."
msgstr ""
msgid "View all issues"
-msgstr "ã™ã¹ã¦ã®èª²é¡Œã‚’表示"
+msgstr "ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示"
msgid "View blame prior to this change"
msgstr "ã“ã®å¤‰æ›´å‰ã® blame を表示"
@@ -29989,10 +30855,10 @@ msgid "View incident issues."
msgstr ""
msgid "View issue"
-msgstr "課題を表示"
+msgstr "イシューを表示"
msgid "View issues"
-msgstr "課題を表示"
+msgstr "イシューを表示"
msgid "View it on GitLab"
msgstr "GitLab ã§è¡¨ç¤º"
@@ -30234,6 +31100,9 @@ msgstr "%{scannerName} (ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %{scannerVersion})"
msgid "Vulnerability|Activity"
msgstr ""
+msgid "Vulnerability|Actual Response"
+msgstr ""
+
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
@@ -30261,6 +31130,9 @@ msgstr "説明"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr "åå‰ç©ºé–“"
msgid "Vulnerability|Project"
msgstr "プロジェクト"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 "ファイルをロードã—ã€ãã®å†…容をコピーã—ã¦ã„ã¾ã™ã€‚ãŠå¾…ã¡ãã ã•ã„。"
@@ -30318,6 +31199,9 @@ msgstr "パフォーマンスデータ待ã¡"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ã“ã®ãƒ‡ãƒ¼ã‚¿ã‚’å‚ç…§ã—ãŸã„ã§ã™ã‹ï¼Ÿã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr "警告:"
@@ -30337,7 +31221,7 @@ msgid "We could not determine the path to remove the epic"
msgstr "エピックを削除ã™ã‚‹ãƒ‘スを特定ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "We could not determine the path to remove the issue"
-msgstr "課題を削除ã™ã‚‹ãŸã‚ã®ãƒ‘スを特定ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgstr "イシューを削除ã™ã‚‹ãŸã‚ã®ãƒ‘スを特定ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "We couldn't find any %{scope} matching %{term}"
msgstr ""
@@ -30351,6 +31235,9 @@ msgstr ""
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "Prometheusサーãƒãƒ¼ã«åˆ°é”ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚サーãƒãƒ¼ãŒå­˜åœ¨ã—ãªã„ã‹ã€è¨­å®šã®è©³ç´°ã‚’æ›´æ–°ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+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 "%{humanized_resource_name} ã«ã‚¹ãƒ‘ムãŒã‚ã‚‹å¯èƒ½æ€§ã‚’検出ã—ã¾ã—ãŸã€‚続行ã™ã‚‹ã«ã¯ reCAPTCHA を実行ã—ã¦ãã ã•ã„。"
@@ -30424,7 +31311,7 @@ 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 "Webhookã¯ã€ä¾‹ãˆã°æ–°ã—ã„コードãŒãƒ—ッシュã•ã‚ŒãŸã‚Šã€æ–°ã—ã„課題ãŒä½œæˆã•ã‚ŒãŸå ´åˆã«ã€URL を呼ã³ã ã™ã“ã¨ãŒã§ãã¾ã™ã€‚プッシュã€èª²é¡Œã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã‚ˆã†ãªã‚¤ãƒ™ãƒ³ãƒˆã‹ã‚‰ã©ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’監視ã™ã‚‹ã‹Webhookを設定ã§ãã¾ã™ã€‚グループウェブフックã¯ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã«é©ç”¨ã•ã‚Œã€ã‚°ãƒ«ãƒ¼ãƒ—全体ã§Webhookを標準化ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgstr "Webhookã¯ã€ä¾‹ãˆã°æ–°ã—ã„コードãŒãƒ—ッシュã•ã‚ŒãŸã‚Šã€æ–°ã—ã„イシューãŒä½œæˆã•ã‚ŒãŸå ´åˆã«ã€URL を呼ã³ã ã™ã“ã¨ãŒã§ãã¾ã™ã€‚プッシュã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã‚ˆã†ãªã‚¤ãƒ™ãƒ³ãƒˆã‹ã‚‰ã©ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’監視ã™ã‚‹ã‹Webhookを設定ã§ãã¾ã™ã€‚グループウェブフックã¯ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã«é©ç”¨ã•ã‚Œã€ã‚°ãƒ«ãƒ¼ãƒ—全体ã§Webhookを標準化ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr "Webhook ã¯è¨­å®šãƒ¡ãƒ‹ãƒ¥ãƒ¼ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
@@ -30436,7 +31323,7 @@ msgid "Webhooks|Confidential Comments"
msgstr "機密コメント"
msgid "Webhooks|Confidential Issues events"
-msgstr "機密課題イベント"
+msgstr "éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ã‚¤ãƒ™ãƒ³ãƒˆ"
msgid "Webhooks|Deployment events"
msgstr "デプロイイベント"
@@ -30448,11 +31335,14 @@ msgid "Webhooks|Feature Flag events"
msgstr ""
msgid "Webhooks|Issues events"
-msgstr "課題イベント"
+msgstr "イシューイベント"
msgid "Webhooks|Job events"
msgstr "ジョブイベント"
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr "マージリクエストイベント"
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,8 +31503,8 @@ 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 be an approver?"
-msgstr "誰ãŒæ‰¿èªè€…ã«ãªã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ"
+msgid "Who can approve?"
+msgstr ""
msgid "Who can see this group?"
msgstr "誰ãŒã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を見れã¾ã™ã‹ï¼Ÿ"
@@ -30665,10 +31558,10 @@ msgid "WikiEmptyIssueMessage|You must be a group member in order to add wiki pag
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 "Wiki ページを追加ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクトメンãƒãƒ¼ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。ã“ã®ãƒ—ロジェクト㮠Wiki を改善ã™ã‚‹æ–¹æ³•ã®æ案ãŒã‚ã‚‹å ´åˆã¯ã€ %{issues_link} ã§å•é¡Œã‚’é–‹ãã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
+msgstr "Wiki ページを追加ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクトメンãƒãƒ¼ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。ã“ã®ãƒ—ロジェクト㮠Wiki を改善ã™ã‚‹æ–¹æ³•ã®æ案ãŒã‚ã‚‹å ´åˆã¯ã€ %{issues_link} ã§ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
msgid "WikiEmptyIssueMessage|issue tracker"
-msgstr "課題トラッカー"
+msgstr "イシュートラッカー"
msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
msgstr ""
@@ -30872,7 +31765,7 @@ msgid "Yes, add it"
msgstr "ã¯ã„ã€è¿½åŠ ã—ã¾ã™"
msgid "Yes, close issue"
-msgstr "ã¯ã„ã€èª²é¡Œã‚’é–‰ã˜ã¾ã™"
+msgstr "ã¯ã„ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’クローズã—ã¾ã™"
msgid "Yes, delete project"
msgstr ""
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ msgstr "既存ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã«ç ´æ£„ã—ãŸã¨ãã«ã‚¢ãƒƒãƒ—ロードã§ãã‚‹
msgid "You can recover this project until %{date}"
msgstr "%{date} ã¾ã§ã“ã®ãƒ—ロジェクトを復元ã§ãã¾ã™"
+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 "対話モードã§ã¯ã€%{use_ours} ボタンã¾ãŸã¯%{use_theirs} ボタンã§ã®é¸æŠžã¨ã€ãã®ä»–ファイルã®ç›´æŽ¥ç·¨é›†ã§ç«¶åˆã‚’解決ã§ãã¾ã™ã€‚ãã‚Œã‹ã‚‰ã“れらã®å¤‰æ›´ã‚’ %{branch_name} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã™ã€‚"
@@ -31087,9 +31986,6 @@ 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 "特定ã®ã‚¿ã‚°ã‚’æŒã¤ Runner ã®ã¿ã‚’使用ã™ã‚‹ã‚ˆã†ã«ã‚¸ãƒ§ãƒ–を設定ã§ãã¾ã™ã€‚ã‚¿ã‚°ã¯ã‚³ãƒ³ãƒžã§åŒºåˆ‡ã£ã¦æŒ‡å®šã—ã¾ã™ã€‚"
-
msgid "You can specify notification level per group or per project."
msgstr "グループã”ã¨ã¾ãŸã¯ãƒ—ロジェクトã”ã¨ã«é€šçŸ¥ãƒ¬ãƒ™ãƒ«ã‚’設定ã§ãã¾ã™ã€‚"
@@ -31111,6 +32007,9 @@ 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 "ç¾æ™‚点ã§ã¯ã“ã®ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã•ã‚ŒãŸãƒ‘イプラインを実行ã§ãã¾ã›ã‚“。少々ãŠå¾…ã¡ãã ã•ã„。"
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "LDAP グループã®åŒæœŸã®è¨­å®šã‚’上書ãã™ã‚‹ãŸã‚ã®é©åˆ‡ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
-
msgid "You don't have any U2F devices registered yet."
msgstr "ã‚ãªãŸã¯ã¾ã 2è¦ç´ èªè¨¼ãƒ‡ãƒã‚¤ã‚¹ã‚’登録ã—ã¦ã„ã¾ã›ã‚“。"
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31247,10 +32149,10 @@ msgid "You have successfully purchased a %{plan} plan subscription for %{seats}.
msgstr ""
msgid "You haven't added any issues to your project yet"
-msgstr "ã‚ãªãŸã¯ã¾ã ãƒ—ロジェクトã«èª²é¡Œã‚’追加ã—ã¦ã„ã¾ã›ã‚“"
+msgstr "ã‚ãªãŸã¯ã¾ã ãƒ—ロジェクトã«ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’追加ã—ã¦ã„ã¾ã›ã‚“"
msgid "You haven't selected any issues yet"
-msgstr "ã‚ãªãŸã¯ã¾ã èª²é¡Œã‚’é¸æŠžã—ã¦ã„ã¾ã›ã‚“。"
+msgstr "ã‚ãªãŸã¯ã¾ã ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’é¸æŠžã—ã¦ã„ã¾ã›ã‚“。"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "ã‚ãªãŸã¯ \"%{membershipable_human_name}\"%{source_type} を残ã—ã¾ã—ãŸã€‚"
@@ -31264,6 +32166,9 @@ 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 "ロックを強制的ã«å‰Šé™¤ã™ã‚‹ã«ã¯ã€Maintainer ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãŒå¿…è¦ã§ã™"
@@ -31423,6 +32328,9 @@ 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 "CSV エクスãƒãƒ¼ãƒˆã‚’開始ã—ã¾ã—ãŸã€‚完了後ã«ã€%{email} ã«ãƒ¡ãƒ¼ãƒ«ã§é€ä¿¡ã—ã¾ã™ã€‚"
@@ -31495,6 +32403,9 @@ msgstr "ã‚ãªãŸã®U2Fデãƒã‚¤ã‚¹ã¯ã€æœ‰åŠ¹ãªJSON応答をé€ä¿¡ã—ã¾ã›ã‚
msgid "Your U2F device was registered!"
msgstr "ã‚ãªãŸã® U2F デãƒã‚¤ã‚¹ãŒç™»éŒ²ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ msgstr ""
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr "ã‚ãªãŸã®ãƒ‡ãƒã‚¤ã‚¹ã¯æ­£å¸¸ã«è¨­å®šã•ã‚Œã¾ã—ãŸã€‚åå‰ã‚’付ã‘ã¦GitLabサーãƒãƒ¼ã«ç™»éŒ²ã—ã¾ã™ã€‚"
+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 ""
@@ -31586,10 +32500,13 @@ 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 "ã‚ãªãŸã®èª²é¡Œã‚’インãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚終了ã™ã‚‹ã¨ã€ç¢ºèªãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚"
+msgstr "ã‚ãªãŸã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’インãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚終了ã™ã‚‹ã¨ã€ç¢ºèªãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚"
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
-msgstr "ã‚ãªãŸã®èª²é¡Œã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰å‡¦ç†ã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚終了ã™ã‚‹ã¨ã€ç¢ºèªãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚"
+msgstr "ã‚ãªãŸã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰å‡¦ç†ã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚終了ã™ã‚‹ã¨ã€ç¢ºèªãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚"
+
+msgid "Your license does not support on-call rotations"
+msgstr ""
msgid "Your license does not support on-call schedules"
msgstr ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31698,7 +32618,7 @@ msgid "added %{created_at_timeago}"
msgstr "%{created_at_timeago} を追加ã—ã¾ã—ãŸ"
msgid "added a Zoom call to this issue"
-msgstr "ã“ã®èª²é¡Œã«ã‚ºãƒ¼ãƒ ã‚³ãƒ¼ãƒ«ã‚’追加ã—ã¾ã—ãŸ"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«Zoomコールを追加ã—ã¾ã—ãŸ"
msgid "ago"
msgstr "å‰"
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr "自分ã«å‰²ã‚Šå½“ã¦"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr "リスクã‚ã‚Š"
@@ -31763,9 +32686,15 @@ msgstr "ブランãƒå"
msgid "by"
msgstr "by"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 "個人用プロジェクトã«ã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚¿ã‚°ãŒã‚ã‚‹å ´åˆã€å¤‰æ›´ã§ãã¾ã›ã‚“。"
@@ -31808,6 +32737,9 @@ 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 "%{linkStartTag}コンテナスキャンã®è©³ç´°%{linkEndTag}"
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
@@ -31893,7 +32828,7 @@ msgid "ciReport|Create a merge request to implement this solution, or download a
msgstr "マージリクエストを作æˆã—ã¦ã“ã®ã‚½ãƒªãƒ¥ãƒ¼ã‚·ãƒ§ãƒ³ã‚’実装ã™ã‚‹ã€ã¾ãŸã¯æ‰‹å‹•ã§ãƒ‘ッãƒã‚’ダウンロードã—ã¦é©ç”¨ã—ã¾ã™ã€‚"
msgid "ciReport|Create issue"
-msgstr "課題を作æˆã™ã‚‹"
+msgstr "イシューを作æˆã™ã‚‹"
msgid "ciReport|DAST"
msgstr "DAST"
@@ -31929,7 +32864,7 @@ msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
-msgstr "課題を作æˆã—ã¦ã€ã“ã®è„†å¼±æ€§ã‚’調査・検証ã—ã¦ãã ã•ã„"
+msgstr "イシューを作æˆã—ã¦ã€ã“ã®è„†å¼±æ€§ã‚’調査ã—ã¾ã™"
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -31950,7 +32885,7 @@ msgid "ciReport|No changes to code quality"
msgstr "コードå“質ã«å¤‰æ›´ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "ciReport|No code quality issues found"
-msgstr "コードå“質ã®èª²é¡Œã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
+msgstr "コードå“質ã®å•é¡Œã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "ciReport|RPS"
msgstr ""
@@ -31989,7 +32924,7 @@ msgid "ciReport|TTFB P95"
msgstr "TTFB P95"
msgid "ciReport|There was an error creating the issue. Please try again."
-msgstr "課題を作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgstr "イシューを作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "ciReport|There was an error creating the merge request. Please try again."
msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -32003,6 +32938,9 @@ 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] "%{packagesString}ã€%{lastPackage} ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -32017,7 +32955,7 @@ msgid "ciReport|is loading, errors when loading results"
msgstr ""
msgid "closed issue"
-msgstr "クローズã—ãŸèª²é¡Œ"
+msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "collect usage information"
msgstr ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32301,16 +33245,16 @@ msgid "is too long (maximum is 1000 entries)"
msgstr "ãŒé•·ã™ãŽã¾ã™ï¼ˆæœ€å¤§1000エントリ)"
msgid "issue"
-msgstr "課題"
+msgstr "イシュー"
msgid "issues at risk"
-msgstr "リスクã®ã‚る課題"
+msgstr "リスクã®ã‚るイシュー"
msgid "issues need attention"
msgstr ""
msgid "issues on track"
-msgstr "順調ãªèª²é¡Œ"
+msgstr "順調ãªã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "it is larger than %{limit}"
msgstr ""
@@ -32381,6 +33325,9 @@ msgstr "ã“ã®ã‚¨ãƒ³ãƒˆãƒªã®æ•°å¼ã¯ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã«æ™‚é–“ãŒã‹ã‹ã‚Šã™
msgid "math|There was an error rendering this math block"
msgstr "ã“ã® math ブロックã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "member%{number}@company.com"
+msgstr ""
+
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "マージリクエスト"
@@ -32903,7 +33850,7 @@ msgid "remove weight"
msgstr "ウェイトを削除"
msgid "removed a Zoom call from this issue"
-msgstr "ã“ã® issue ã‹ã‚‰ã‚ºãƒ¼ãƒ ã‚³ãƒ¼ãƒ«ã‚’削除ã—ã¾ã—ãŸã€‚"
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‹ã‚‰Zoomコールを削除ã—ã¾ã—ãŸã€‚"
msgid "rendered diff"
msgstr "差分を表示"
@@ -33029,23 +33976,14 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "ã‚¿ã‚°å"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
msgid "the following issue(s)"
-msgstr "次ã®èª²é¡Œ"
+msgstr "次ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "this document"
msgstr "ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index ad2eb42c260..11be5548778 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: 2020-12-03 08:14\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index 0af4b0a73d4..77e0bc12602 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: 2020-12-03 08:20\n"
+"PO-Revision-Date: 2021-01-08 23:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 40e0a4e25d9..379a7448e56 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: 2020-12-03 08:17\n"
+"PO-Revision-Date: 2021-01-08 23:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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 "%{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 ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} 커밋"
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} 파ì¼"
@@ -816,7 +837,7 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
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 ""
+msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}ì„ ì‚¬ìš©í•˜ë©´ 그룹 ë˜ëŠ” 프로ì íŠ¸ì˜ ì´ë²¤íŠ¸ì— 대한 ì‘답으로 웹 애플리케ì´ì…˜ì— ì•Œë¦¼ì„ ë³´ë‚¼ 수 있습니다. Webhook보다 %{integrations_link_start}통합%{link_end}ì„ ì‚¬ìš©í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
msgid "&lt; 1 hour"
msgstr ""
@@ -867,9 +888,15 @@ msgstr "(%{mrCount} 병합)"
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 "(진행 ìƒí™© 확ì¸)"
@@ -1086,29 +1113,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "'러너(Runner)'는 ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” 프로세스입니다. 필요한 ë§Œí¼ ëŸ¬ë„ˆë¥¼ ì…‹ì—…í•  수 있습니다."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr ".NET 코어 콘솔 ì‘ìš© 프로그램 템플릿, 모든 .NET 코어 프로ì íŠ¸ì— 맞게 ì‚¬ìš©ìž ì •ì˜ ê°€ëŠ¥"
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 "ì´ GitBook 사ì´íŠ¸ëŠ” GitLab CI/CD 대신 Netlify를 사용하지만, GitLabì˜ ë‹¤ë¥¸ 멋진 ê¸°ëŠ¥ì„ ê³„ì† ì‚¬ìš©í•  수 있습니다."
+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 "ì´ Hexo 사ì´íŠ¸ëŠ” GitLab CI/CD 대신 Netlify를 사용하지만, GitLabì˜ ë‹¤ë¥¸ 멋진 ê¸°ëŠ¥ì„ ê³„ì† ì‚¬ìš©í•  수 있습니다."
+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 "ì´ Hugo 사ì´íŠ¸ëŠ” GitLab CI/CD 대신 Netlify를 사용하지만, GitLabì˜ ë‹¤ë¥¸ 멋진 ê¸°ëŠ¥ì„ ê³„ì† ì‚¬ìš©í•  수 있습니다."
+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 "ì´ Jekyll 사ì´íŠ¸ëŠ” GitLab CI/CD 대신 Netlify를 사용하지만, GitLabì˜ ë‹¤ë¥¸ 멋진 ê¸°ëŠ¥ì„ ê³„ì† ì‚¬ìš©í•  수 있습니다."
+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 "Let's Encrypt SSL ì¸ì¦ì„œëŠ” ë„ë©”ì¸ì´ ì¸ì¦ë˜ê¸° ì „ì—는 사용할 수 없습니다."
@@ -1119,6 +1143,9 @@ msgstr "ì´ë©”ì¼ ì£¼ì†Œë¥¼ ì‚¬ìš©í•˜ì—¬ì´ GitLab ì„¤ì¹˜ì— ëŒ€í•´ Let 's Encry
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "ì´ ê¸°ë³¸ 페ì´ì§€ì™€ 서버리스 ê¸°ëŠ¥ì€ AWS Lambda, AWS API Gateway, 그리고 GitLab를 사용합니다"
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
msgid "A complete DevOps platform"
msgstr "완벽한 DevOps 플랫í¼"
@@ -1146,6 +1173,9 @@ msgstr "ê·¸ë£¹ì€ ì—¬ëŸ¬ 프로ì íŠ¸ë“¤ì˜ 모ìŒìž…니다."
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
msgstr "ê·¸ë£¹ì€ GitLabì˜ ì¡°ì§ì„ 나타냅니다. ê·¸ë£¹ì„ ì‚¬ìš©í•˜ë©´ 사용ìžë¥¼ 관리하고, ì—¬ëŸ¬ê°œì˜ í”„ë¡œì íŠ¸ì—ì„œ ê³µë™ìœ¼ë¡œ ìž‘ì—…í•  수 있습니다."
+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 "사ì´ë²„ í­ë ¥ ë°©ì§€íŒ€ì´ ìµœëŒ€í•œ 빨리 ê·€í•˜ì˜ ë¦¬í¬íŠ¸ë¥¼ 검토할 것 입니다."
@@ -1155,6 +1185,9 @@ 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 "새로운 Auto DevOps 파ì´í”„ë¼ì¸ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. %{pipelines_link_start}파ì´í”„ë¼ì¸ 페ì´ì§€%{pipelines_link_end}ë¡œ ì´ë™í•˜ì—¬ ìžì„¸ížˆ 알아보세요."
@@ -1173,13 +1206,16 @@ 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 "ì´ ì¼ë°˜ HTML 사ì´íŠ¸ëŠ” GitLab CI/CD 대신 Netlify를 사용하지만, GitLabì˜ ë‹¤ë¥¸ 멋진 ê¸°ëŠ¥ì„ ê³„ì† ì‚¬ìš©í•  수 있습니다."
+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."
+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"
@@ -1188,10 +1224,13 @@ 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 ready-to-go template for use with Android apps."
+msgid "A ready-to-go template for use with Android apps"
msgstr ""
-msgid "A ready-to-go template for use with iOS Swift apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 "소스 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ìžˆëŠ” 사용ìžê°€ ì´ ì˜µì…˜ì„ ì„ íƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -1224,13 +1269,16 @@ msgstr "API 토í°"
msgid "AWS Access Key"
msgstr "AWS 엑세스 키"
-msgid "AWS Access Key. Only required if not using role instance credentials"
+msgid "AWS Access Key. Only required if not using role instance credentials"
msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS 비밀 액세스 키"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1272,6 +1320,9 @@ msgstr "LDAP 계정 ì ‘ê·¼ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "ì ‘ê·¼ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤! ì´ ì €ìž¥ì†Œì— ë°°í¬ í‚¤ë¥¼ 추가 í•  수 있는지 확ì¸í•´ 주세요."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "액세스 만료ì¼"
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr "새 프로ì íŠ¸ì— 공유 러너 활성화"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "환경 변수는 기본ì ìœ¼ë¡œ 보호ë©ë‹ˆë‹¤."
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr "모든 브랜치"
msgid "All changes are committed"
msgstr "모든 ë³€ê²½ì‚¬í•­ì´ ì»¤ë°‹ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr "모든 ì´ë©”ì¼ ì£¼ì†ŒëŠ” ì»¤ë°‹ì„ ì‹ë³„하는 ë° ì‚¬ìš©ë©ë‹ˆë‹¤."
@@ -2744,6 +2780,9 @@ 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 ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 "ì´ìŠˆ ì¤‘ìš”ë„ ì—…ë°ì´íŠ¸ 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "LDAP 무시 ìƒíƒœë¥¼ 저장하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오."
-
msgid "An error occurred while saving assignees"
msgstr "담당ìžë¥¼ 저장하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr "오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3739,6 +3790,12 @@ msgstr "ë¼ë²¨ 지정"
msgid "Assign milestone"
msgstr "마ì¼ìŠ¤í†¤ 지정"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "ì´ ë§ˆì¼ë“œìŠ¤í†¤ì— ì´ìŠˆë¥¼ 할당합니다."
@@ -3757,12 +3814,18 @@ 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 "í• ë‹¹ëœ ë¨¸ì§€ 리퀘스트(MR)"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "나ì—게 할당 ë¨"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr "ê°ì‚¬ ì´ë²¤íŠ¸"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,12 +4065,12 @@ 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 "Auto DevOps|Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr ""
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto DevOps 문서"
@@ -4023,10 +4089,13 @@ 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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr "Let's Encrypt를 사용하여 ì¸ì¦ì„œë¥¼ ìžë™ìœ¼ë¡œ 관리"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr "배경 색"
msgid "Badges"
msgstr "배지"
-msgid "Badges|A new badge was added."
-msgstr "새로운 배지가 추가ë˜ì—ˆìŠµë‹ˆë‹¤."
-
msgid "Badges|Add badge"
msgstr "배지 추가"
@@ -4146,12 +4212,21 @@ msgstr "배지 ì´ë¯¸ì§€ URL"
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 "그룹 배지"
@@ -4161,15 +4236,15 @@ 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|Please fill in a valid URL"
-msgstr "유효한 URLì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤."
-
msgid "Badges|Project Badge"
msgstr "프로ì íŠ¸ 배지"
@@ -4182,15 +4257,12 @@ msgstr "변경 사항 저장"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "배지 저장 실패, 입력한 URLì„ í™•ì¸í•˜ì‹œê³  다시 ì‹œë„하십시오."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "GitLabì´ ì§€ì›í•˜ëŠ” %{docsLinkStart}변수%{docsLinkEnd}: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "배지가 ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "Badges|The badge was saved."
-msgstr "배지를 저장했습니다."
-
msgid "Badges|This group has no badges"
msgstr "ê·¸ë£¹ì— ë°°ì§€ê°€ 없습니다."
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "내 배지"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "e.g. %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Balsamiq 파ì¼ì„ 로드하지 못했습니다."
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "업그레ì´ë“œ"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr "블로그"
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr "브랜치 ì´ë¦„"
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "브랜치 검색"
@@ -4627,6 +4729,24 @@ msgstr "내장ëœ"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr "외부 저장소용 CI/CD"
msgid "CI/CD settings"
msgstr "CI/CD 설정"
-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."
+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"
@@ -4747,12 +4870,12 @@ 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 "대체 CI 구성 파ì¼ì´ì—†ëŠ” 경우 Auto DevOps 파ì´í”„ë¼ì¸ì´ 실행ë©ë‹ˆë‹¤."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr ""
@@ -4780,9 +4903,6 @@ msgstr "콜백 URL"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr "승ì¸ìžë¥¼ ë®ì–´ì“¸ 수 있으며, 매 머지 리퀘스트 마다 승ì¸ì´ 필요합니다."
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 "취소"
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "ìžë™ìœ¼ë¡œ 머지할 수 없습니다."
@@ -4984,15 +5131,33 @@ msgstr "브랜치ì—ì„œ Pick"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "브랜치ì—ì„œ Revert"
+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 "Cherry-pick"
msgid "ChangeTypeAction|Revert"
msgstr "Revert"
+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 ""
@@ -5014,13 +5179,16 @@ 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 were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr "Clone"
msgid "Clone repository"
msgstr "저장소 í´ë¡ "
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "%{http_label} clone"
@@ -5575,6 +5749,18 @@ msgstr "KRB5로 clone"
msgid "Clone with SSH"
msgstr "SSH로 clone"
+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 "닫기"
@@ -6682,12 +6868,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "코드 소유ìž"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr "코드 품질"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7020,7 +7224,7 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
-msgstr "ìžë™ git 검사 ë° ì €ìž¥ì†Œ 하우스 í‚¤í•‘ì„ ì„¤ì •í•©ë‹ˆë‹¤."
+msgstr "ìžë™ git 검사 ë° ì €ìž¥ì†Œ 정리를 설정합니다."
msgid "Configure existing installation"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "축하합니다! ì´ì¤‘ ì¸ì¦ì„ 활성화했습니다!"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "ì—°ê²°"
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr "URL 복사"
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,13 +8013,10 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues 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."
+msgid "Create an incident. Incidents are created for each alert triggered."
msgstr ""
-msgid "Create board"
+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"
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "새 보드 만들기"
-
msgid "Create new branch"
msgstr "새 브랜치 ìƒì„±"
@@ -7929,6 +8139,84 @@ msgstr "태그"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ í† í° ë§Œë“¤ê¸°"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "ìƒì„±ë¨"
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "현재 브랜치"
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8161,7 +8425,7 @@ msgid "Customize icon"
msgstr ""
msgid "Customize language and region related settings."
-msgstr ""
+msgstr "언어 ë° ì§€ì—­ 관련 ì„¤ì •ì„ ë³€ê²½í•©ë‹ˆë‹¤."
msgid "Customize name"
msgstr ""
@@ -8176,7 +8440,7 @@ msgid "CustomizeHomepageBanner|Do you want to customize this page?"
msgstr ""
msgid "CustomizeHomepageBanner|Go to preferences"
-msgstr ""
+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 ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8696,7 +8972,7 @@ msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
-msgstr ""
+msgstr "ì´ìŠˆì˜ 기본 설명 템플릿"
msgid "Default description template for merge requests"
msgstr ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "기본: FogBugz 계정 ID를 풀네임으로 매핑"
@@ -8734,6 +9004,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "cron êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì—¬ ì‚¬ìš©ìž ì •ì˜ íŒ¨í„´ ì •ì˜"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "보드 삭제"
-
msgid "Delete comment"
msgstr "댓글 삭제"
@@ -9244,9 +9514,6 @@ msgstr "내림차순"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "설명"
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "CSV 다운로드"
@@ -9854,9 +10184,6 @@ msgstr "ì´ ê³¼ì •ì—ì„œ GitLabì˜ URLì„ ë¬»ëŠ” 메시지가 나타납니다. ì
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr "ê° Runner는 ë‹¤ìŒ ìƒíƒœ 중 í•˜ë‚˜ì¼ ìˆ˜ 있습니다."
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr "애플리케ì´ì…˜ 수정"
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr "댓글 편집"
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr "공개 ë°°í¬ í‚¤ 편집"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr "ì´ë©”ì¼"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ msgstr ""
msgid "Enable and configure Prometheus metrics."
msgstr "Prometheus 매트릭스를 활성화하고 구성합니다."
+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 "외부 서비스로 분류 제어 사용"
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr "2단계 ì¸ì¦ 활성화"
msgid "Enable usage ping"
msgstr "ping 사용 활성화"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "(UTC)ì— ì¢…ë£Œë©ë‹ˆë‹¤"
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ msgstr "머지 리퀘스트(MR) ì œëª©ì„ ìž…ë ¥ 해주세요"
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 ""
@@ -10514,6 +10856,9 @@ msgstr "다ìŒì— ë°°í¬..."
msgid "Environments|Deployment"
msgstr "ë°°í¬"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 "갱신ë¨"
@@ -10691,9 +11042,6 @@ msgstr "ì´ê²ƒì„ 어떻게 í•´ê²°í•  수 있습니까?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "ìžì„¸í•œ ë‚´ìš©"
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr "ë„¤íŠ¸ì›Œí¬ ê·¸ëž˜í”„ ë°˜ì˜ ì¤‘ 오류"
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr "refs ë°˜ì˜ ì¤‘ 오류"
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr "ì— ë°°í¬í•˜ì§€ 못했습니다."
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr "í•„í„°"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr "경로로 찾기"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "íŒŒì¼ ì°¾ê¸°"
@@ -11991,11 +12342,14 @@ msgstr ""
msgid "Finished"
msgstr "완료"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
msgid "First day of the week"
-msgstr "ì£¼ì˜ ì²«ë‚ "
+msgstr "첫번째 ìš”ì¼"
msgid "First name"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr "í¬í¬"
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12334,7 +12685,7 @@ msgid "GeoNodes|Unused slots"
msgstr ""
msgid "GeoNodes|Updated %{timeAgo}"
-msgstr ""
+msgstr "%{timeAgo} ì „ ì—…ë°ì´íŠ¸ ë¨"
msgid "GeoNodes|Used slots"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12856,7 +13210,7 @@ msgid "Gitlab Pages"
msgstr ""
msgid "Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
msgstr ""
@@ -12865,10 +13219,10 @@ msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "Gitpod URL"
msgid "Gitpod|e.g. https://gitpod.example.com"
-msgstr ""
+msgstr "예: https://gitpod.example.com"
msgid "Given access %{time_ago}"
msgstr "%{time_ago} ì „ 엑세스 권한 부여ë¨"
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr "ì´ì „으로"
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -12988,7 +13342,7 @@ msgid "Go to wiki"
msgstr ""
msgid "Go to your To-Do list"
-msgstr ""
+msgstr "ë‚˜ì˜ í•  ì¼ ëª©ë¡ìœ¼ë¡œ ì´ë™"
msgid "Go to your fork"
msgstr ""
@@ -13113,9 +13467,6 @@ msgstr "그룹 아바타"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "그룹 설명"
-
msgid "Group description (optional)"
msgstr "그룹 설명 (ì„ íƒ ì‚¬í•­)"
@@ -13195,7 +13546,7 @@ msgid "Group was exported"
msgstr ""
msgid "Group was successfully updated."
-msgstr ""
+msgstr "ê·¸ë£¹ì´ ì„±ê³µì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Group-level events in %{group_name} (no project-level events)"
msgstr ""
@@ -13449,11 +13800,17 @@ 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 your group badges."
-msgstr "그룹 배지를 ì‚¬ìš©ìž ì •ì˜í•©ë‹ˆë‹¤."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "ë°°ì§€ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr "그룹 수준 프로ì íŠ¸ í…œí”Œë¦¿ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13851,12 +14235,15 @@ msgid "Hour (UTC)"
msgstr ""
msgid "Housekeeping"
-msgstr ""
+msgstr "정리"
msgid "Housekeeping successfully started"
-msgstr "Housekeepingì´ ì„±ê³µì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
+msgstr "정리가 성공ì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr "정리, 내보내기, 경로, 전송, 삭제, 보관"
+
+msgid "How does cleanup work?"
msgstr ""
msgid "How it works"
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "가져오기 진행중"
@@ -14152,6 +14548,9 @@ msgstr "GitHub으로 부터 저장소 가져오기"
msgid "Import repository"
msgstr "저장소 가져 오기"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14210,21 +14609,16 @@ msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
msgid "Imported requirements"
-msgstr ""
+msgstr "가져온 요구 사항"
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "GitLab Enterprise Editionì„ í†µí•´ ì´ìŠˆ 보드를 í–¥ìƒ ì‹œí‚µë‹ˆë‹¤."
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr "초대"
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "ì´ìŠˆ ì´ë²¤íŠ¸"
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ 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 "JiraService | 비밀번호 ë˜ëŠ” API 토í°"
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Transition ID(s)"
-msgstr ""
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr "ë” ìžì„¸ížˆ 알아보기"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "파ì´í”„ë¼ì¸ 스케쥴 문서로부터 ë” ì•Œì•„ë³´ê¸°"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "나가기"
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr "ì´ìŠˆ 불러오는 중"
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr "최대 액세스 수준"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "머지 리퀘스트(MR) 승ì¸"
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr "머지 리퀘스트(MR)"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "머지 리퀘스트(MR)는 프로ì íŠ¸ì˜ 변경 ì‚¬í•­ì„ ì œì•ˆí•˜ê³  변경 ì‚¬í•­ì„ ë‹¤ë¥¸ 사람들과 ë…¼ì˜ í•˜ëŠ” 곳입니다."
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr "머지ë¨"
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr "미러 사용ìž"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "미러ë§ëœ 저장소"
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "여러 ì´ìŠˆ ë³´ë“œ"
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr "브랜치가 존재하지 않습니다."
msgid "No changes"
msgstr "변경 사항 ì—†ìŒ"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr "프ë¼ì´ë¹— 프로ì íŠ¸ì—는 사용할 수 없습니다."
msgid "Not available for protected branches"
msgstr "프로í…íŠ¸ëœ ë¸Œëžœì¹˜ì—는 사용할 수 없습니다."
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "비밀 아님"
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19547,7 +20124,7 @@ msgid "Packages"
msgstr "패키지"
msgid "Packages & Registries"
-msgstr ""
+msgstr "패키지 & 레지스트리"
msgid "Page not found"
msgstr ""
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "페ì´ì§€"
@@ -19711,11 +20282,14 @@ msgstr ""
msgid "Pause"
msgstr "중지"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
-msgstr "ì¼ì‹œì •ì§€ëœ 러너는 새로운 ìž‘ì—…ì„ í—ˆìš©í•˜ì§€ 않습니다."
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "대기중"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr "파ì´í”„ë¼ì¸ 스케쥴"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr "성공 비율 :"
msgid "PipelineCharts|Successful:"
msgstr "성공 :"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "파ì´í”„ë¼ì¸ 로딩중"
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 "새 ê³„ì •ì˜ ë¹„ë°€ë²ˆí˜¸ë¥¼ ìƒì„±í•´ì£¼ì„¸ìš”."
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20393,7 +21012,7 @@ msgid "Preferences"
msgstr "환경 설정"
msgid "Preferences saved."
-msgstr ""
+msgstr "ì„¤ì •ì„ ì €ìž¥í–ˆìŠµë‹ˆë‹¤."
msgid "Preferences|Behavior"
msgstr ""
@@ -20408,7 +21027,7 @@ 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 ""
+msgstr "애플리케ì´ì…˜ì˜ ìƒë‹¨ ë° ë„¤ë¹„ê²Œì´ì…˜ 사ì´ë“œ ë°”ì˜ í…Œë§ˆë¥¼ 변경합니다."
msgid "Preferences|Display time in 24-hour format"
msgstr ""
@@ -20423,10 +21042,10 @@ msgid "Preferences|Instead of all the files changed, show only one file at a tim
msgstr ""
msgid "Preferences|Layout width"
-msgstr ""
+msgstr "ë ˆì´ì•„웃 너비"
msgid "Preferences|Must be a number between %{min} and %{max}"
-msgstr ""
+msgstr "%{min}와 %{max} 사ì´ì˜ 숫ìžì—¬ì•¼ 합니다."
msgid "Preferences|Navigation theme"
msgstr "테마 íƒìƒ‰"
@@ -20444,7 +21063,7 @@ msgid "Preferences|Show whitespace changes in diffs"
msgstr ""
msgid "Preferences|Syntax highlighting theme"
-msgstr ""
+msgstr "문법 하ì´ë¼ì´íŒ… 테마"
msgid "Preferences|Tab width"
msgstr ""
@@ -20453,22 +21072,22 @@ msgid "Preferences|These settings will update how dates and times are displayed
msgstr ""
msgid "Preferences|This feature is experimental and translations are not complete yet"
-msgstr ""
+msgstr "ì´ ê¸°ëŠ¥ì€ ì‹¤í—˜ì ì´ë©°, ë²ˆì—­ì´ ëª¨ë‘ ë나지 않았습니다."
msgid "Preferences|This setting allows you to customize the appearance of the syntax."
-msgstr ""
+msgstr "ì´ ì„¤ì •ì„ ë³€ê²½í•˜ë©´, ë¬¸ë²•ì˜ í…Œë§ˆë¥¼ 변경할 수 있습니다."
msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
msgstr ""
msgid "Preferences|Time display"
-msgstr ""
+msgstr "시간 표시"
msgid "Preferences|Time format"
-msgstr ""
+msgstr "시간 형ì‹"
msgid "Preferences|Time preferences"
-msgstr ""
+msgstr "시간 설정"
msgid "Preferences|Use relative times"
msgstr ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr "주"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "우선 순위"
@@ -20630,22 +21255,22 @@ msgid "Profile Settings"
msgstr "프로필 설정"
msgid "ProfilePreferences|Customize integrations with third party services."
-msgstr ""
+msgstr "ì œ 3ìž ì„œë¹„ìŠ¤ì™€ì˜ í†µí•©ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "ProfilePreferences|Enable Gitpod integration"
-msgstr ""
+msgstr "Gitpod 통합 활성화"
msgid "ProfilePreferences|Enable integrated code intelligence on code views"
-msgstr ""
+msgstr "코드를 ë³¼ ë•Œ 코드 ì¸í…”리전스 활성화"
msgid "ProfilePreferences|Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "ProfilePreferences|Integrations"
-msgstr ""
+msgstr "통합"
msgid "ProfilePreferences|Sourcegraph"
-msgstr ""
+msgstr "Sourcegraph"
msgid "ProfileSession|on"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 "ê³„ì •ì´ ì‚­ì œë  ì˜ˆì •ìž…ë‹ˆë‹¤."
@@ -20702,7 +21330,7 @@ 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 ""
+msgstr "프로ì íŠ¸, 저장소 ë˜ëŠ” ì¡°ì§ ì •ë³´ ì—†ì´ ê³µê°œ í”„ë¡œí•„ì— ë¹„ë°€ 프로ì íŠ¸ì˜ 기여ë„를 표시하려면 ì´ í•­ëª©ì„ ì„ íƒí•©ë‹ˆë‹¤"
msgid "Profiles|City, country"
msgstr "ë„ì‹œ, êµ­ê°€"
@@ -20741,7 +21369,7 @@ msgid "Profiles|Disconnect"
msgstr "연결 해제"
msgid "Profiles|Disconnect %{provider}"
-msgstr ""
+msgstr "%{provider} ì—°ê²° ëŠê¸°"
msgid "Profiles|Do not show on profile"
msgstr "í”„ë¡œí•„ì— í‘œì‹œí•˜ì§€ ì•ŠìŒ"
@@ -20767,6 +21395,9 @@ msgstr "피드 토í°ì´ 성공ì ìœ¼ë¡œ 초기화ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Profiles|Full name"
msgstr "ì´ë¦„"
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 "새 아바타 위치 ë° í¬ê¸° ì¡°ì ˆ"
@@ -20912,7 +21546,7 @@ msgid "Profiles|What's your status?"
msgstr "ìƒíƒœëŠ” 어떤가요?"
msgid "Profiles|Who you represent or work for"
-msgstr ""
+msgstr "ë‚´ê°€ 대표로 있는 ê³³ ë˜ëŠ” ì¼í•˜ëŠ” ê³³"
msgid "Profiles|You can change your avatar here"
msgstr "여기ì—ì„œ 아바타를 변경할 수 있습니다."
@@ -20939,7 +21573,7 @@ msgid "Profiles|You must transfer ownership or delete these groups before you ca
msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì„ ì‚­ì œí•˜ê¸° ì „ì— ì´ ê·¸ë£¹ë“¤ì˜ ì†Œìœ ê¶Œì„ ì´ì „하거나 삭제해야합니다."
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
-msgstr ""
+msgstr "linkedin.com/in/profilenameì˜ í”„ë¡œí•„ ì´ë¦„"
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì€ í˜„ìž¬ ë‹¤ìŒ ê·¸ë£¹ë“¤ì˜ ì†Œìœ ìžìž…니다:"
@@ -21097,9 +21731,6 @@ msgstr "프로ì íŠ¸ ì´ë¦„"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,8 +21926,8 @@ msgstr "ì´ ì„¤ì •ì„ ë³€ê²½í•˜ë ¤ë©´ 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
-msgstr "프로ì íŠ¸ 뱃지 커스텀마ì´ì§•"
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr ""
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "ë±ƒì§€ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "ì´ ì €ìž¥ì†Œì—는 ì„œëª…ëœ ì»¤ë°‹ë§Œ 푸쉬할 수 있습니다."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21431,10 +22071,10 @@ msgid "ProjectSettings|Require"
msgstr ""
msgid "ProjectSettings|Requirements"
-msgstr ""
+msgstr "요구 사항"
msgid "ProjectSettings|Requirements management system for this project"
-msgstr ""
+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 ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "최근 검색"
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr "Runner 제거"
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr "우선 순위 삭제"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr "í´ë” ì´ë¦„ 바꾸기"
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "저장소"
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr "액세스 요청"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,8 +23782,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "GitLabì— ì•¡ì„¸ìŠ¤ í•  ë•Œ 모든 사용ìžê°€ 서비스 약관 ë° ê°œì¸ ì •ë³´ 취급 ë°©ì¹¨ì— ë™ì˜í•˜ë„ë¡í•˜ì‹­ì‹œì˜¤."
-msgid "Require user password to approve"
-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 ""
@@ -23139,14 +23812,11 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
msgid "Requirements"
-msgstr ""
+msgstr "요구 사항"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "í„°ë¯¸ë„ ìž¬ì‹œìž‘"
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23432,7 +24105,7 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr ""
msgid "Run housekeeping"
-msgstr ""
+msgstr "정리 실행"
msgid "Run manual or delayed jobs"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "태그없는 작업 실행"
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr "Runner 토í°"
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr "Runners"
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23567,6 +24228,15 @@ 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"
@@ -23620,9 +24290,6 @@ msgstr "SSH 공개키"
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr "예정ë¨"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr "파ì´í”„ë¼ì¸ 스케줄ë§"
msgid "Scope"
msgstr "스코프"
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23825,6 +24492,9 @@ msgid "Search refs"
msgstr ""
msgid "Search requirements"
+msgstr "요구 사항 검색"
+
+msgid "Search settings"
msgstr ""
msgid "Search users"
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23956,7 +24629,7 @@ msgid "Security"
msgstr "보안"
msgid "Security & Compliance"
-msgstr ""
+msgstr "보안 ë° ì¤€ìˆ˜ 사항"
msgid "Security Configuration"
msgstr ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr "9ì›”"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr "설정"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "최신 버전 보기"
@@ -25302,6 +25990,9 @@ 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 "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "(UTC)ì— ì‹œìž‘"
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26413,7 +27125,7 @@ msgid "Switch branch/tag"
msgstr "스위치 브랜치/태그"
msgid "Switch to GitLab Next"
-msgstr ""
+msgstr "GitLab Next로 전환"
msgid "Switch to the source to copy the file contents"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,8 +27604,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
-msgstr "ê°ì‚¬í•©ë‹ˆë‹¤! 다시 보지 않겠습니다."
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr "ì´ìŠˆ 단계ì—는 ì´ìŠˆë¥¼ 작성하여 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 지정하ë
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr "허용ë˜ëŠ” 최대 íŒŒì¼ í¬ê¸°ëŠ” 200KB입니다."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ msgstr "ì´ GitLab ì¸ìŠ¤í„´ìŠ¤ëŠ” 공유 Runnersê°€ 제공ë˜ì§€ 않습니다.
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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28523,13 +29346,13 @@ msgid "To widen your search, change or remove filters."
msgstr ""
msgid "To-Do"
-msgstr ""
+msgstr "í•  ì¼"
msgid "To-Do List"
-msgstr ""
+msgstr "í•  ì¼ ëª©ë¡"
msgid "To-do item successfully marked as done."
-msgstr ""
+msgstr "í•  ì¼ í•­ëª©ì´ ì„±ê³µì ìœ¼ë¡œ 완료로 표시ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Today"
msgstr "오늘"
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -28988,7 +29851,7 @@ msgid "Unable to save your changes. Please try again."
msgstr ""
msgid "Unable to save your preference"
-msgstr ""
+msgstr "ì„¤ì •ì„ ì €ìž¥í•  수 없습니다."
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr "별표 제거"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "êµ¬ë… ì·¨ì†Œ"
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "그룹 ì´ë¦„ê³¼ 설명, 아바타 ë° ê³µê°œ 여부를 수정하십시오."
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29357,67 +30220,67 @@ 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 ""
+msgstr "%{help_link_start}공유 러너%{help_link_end}ê°€ 비활성화ë˜ì—ˆê¸° 때문ì—, 파ì´í”„ë¼ì¸ ì‚¬ìš©ì— ëŒ€í•œ ì œí•œì´ ì„¤ì •ë˜ì§€ 않았습니다."
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
-msgstr ""
+msgstr "구매한 저장 공간 중 %{percentageLeft} 사용 가능"
msgid "UsageQuota|Artifacts"
-msgstr ""
+msgstr "아티팩트"
msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
-msgstr ""
+msgstr "아티팩트는 빌드와 파ì´í”„ë¼ì¸ ì•„í‹°íŒ©íŠ¸ì˜ í•©ê³„ìž…ë‹ˆë‹¤."
msgid "UsageQuota|Buy additional minutes"
-msgstr ""
+msgstr "추가 시간 구매"
msgid "UsageQuota|Current period usage"
-msgstr ""
+msgstr "ì´ë²ˆ ê²°ì œ 주기 사용량"
msgid "UsageQuota|Increase storage temporarily"
-msgstr ""
+msgstr "ì¼ì‹œì ìœ¼ë¡œ 저장 공간 확장"
msgid "UsageQuota|LFS Objects"
-msgstr ""
+msgstr "LFS ê°ì²´"
msgid "UsageQuota|LFS Storage"
-msgstr ""
+msgstr "LFS 저장소"
msgid "UsageQuota|Packages"
-msgstr ""
+msgstr "패키지"
msgid "UsageQuota|Pipelines"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸"
msgid "UsageQuota|Purchase more storage"
-msgstr ""
+msgstr "추가 저장 공간 구매"
msgid "UsageQuota|Purchased storage available"
-msgstr ""
+msgstr "구매한 저장 공간 사용 가능"
msgid "UsageQuota|Repositories"
-msgstr ""
+msgstr "저장소"
msgid "UsageQuota|Repository"
-msgstr ""
+msgstr "저장소"
msgid "UsageQuota|Snippets"
-msgstr ""
+msgstr "스니펫"
msgid "UsageQuota|Storage"
-msgstr ""
+msgstr "저장 공간"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
-msgstr ""
+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 ""
+msgstr "ì´ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤ì—는 잠긴 프로ì íŠ¸ê°€ í¬í•¨ë˜ì–´ 있습니다."
msgid "UsageQuota|This namespace has no projects which use shared runners"
-msgstr ""
+msgstr "ì´ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤ì—는 공유 러너를 사용하는 프로ì íŠ¸ê°€ 없습니다."
msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
msgstr ""
@@ -29435,28 +30298,28 @@ msgid "UsageQuota|Total excess storage used"
msgstr ""
msgid "UsageQuota|Total namespace storage used"
-msgstr ""
+msgstr "ì´ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤ 저장 공간 사용량"
msgid "UsageQuota|Unlimited"
-msgstr ""
+msgstr "무제한"
msgid "UsageQuota|Uploads"
-msgstr ""
+msgstr "업로드"
msgid "UsageQuota|Usage"
-msgstr ""
+msgstr "사용량"
msgid "UsageQuota|Usage Quotas"
-msgstr ""
+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 ""
+msgstr "ë‚´ 프로ì íŠ¸ì˜ 리소스 사용량"
msgid "UsageQuota|Usage quotas help link"
-msgstr ""
+msgstr "사용량 제한 ë„움 ë§í¬"
msgid "UsageQuota|Usage since"
msgstr ""
@@ -29465,10 +30328,10 @@ msgid "UsageQuota|When you purchase additional storage, we automatically unlock
msgstr ""
msgid "UsageQuota|Wiki"
-msgstr ""
+msgstr "위키"
msgid "UsageQuota|Wikis"
-msgstr ""
+msgstr "위키"
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -29480,7 +30343,7 @@ msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr ""
msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
-msgstr ""
+msgstr "구입한 저장 ê³µê°„ì´ ë¶€ì¡±í•©ë‹ˆë‹¤. 프로ì íŠ¸ê°€ ìž ê¸°ëŠ”ê²ƒì„ ë°©ì§€í•˜ë ¤ë©´, ë” ë§Žì€ ì¶”ê°€ 저장 ê³µê°„ì„ êµ¬ë§¤í•˜ì„¸ìš”."
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30070,7 +30936,7 @@ msgid "Visibility settings have been disabled by the administrator."
msgstr ""
msgid "Visibility, project features, permissions"
-msgstr ""
+msgstr "표시 여부, 프로ì íŠ¸ 기능, 권한"
msgid "Visibility:"
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr "설명"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ì´ ë°ì´í„°ë¥¼ ë³´ê³  싶ì€ê°€ìš”? 관리ìžì—게 액세스 ê¶Œí•œì„ ìš”ì²­í•˜ì„¸ìš”."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 "%{humanized_resource_name}ì—ì„œ 잠재ì ì¸ ìŠ¤íŒ¸ì„ íƒì§€í–ˆìŠµë‹ˆë‹¤. 계ì†í•˜ë ¤ë©´ reCAPTCHA를 진행하세요."
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 "강제로 ìž ê¸ˆì„ ì œê±°í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ ìžˆì–´ì•¼í•©ë‹ˆë‹¤."
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31472,13 +32380,13 @@ msgid "Your Primary Email will be used for avatar detection."
msgstr ""
msgid "Your Projects (default)"
-msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ (기본값)"
+msgstr "ë‚´ 프로ì íŠ¸ (기본값)"
msgid "Your Projects' Activity"
-msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ 활ë™"
+msgstr "ë‚˜ì˜ í”„ë¡œì íŠ¸ 활ë™"
msgid "Your Public Email will be displayed on your public profile."
-msgstr ""
+msgstr "ë‚´ 공개 ì´ë©”ì¼ì´ ë‚´ 공개 í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
msgid "Your SSH key was deleted"
msgstr ""
@@ -31487,7 +32395,7 @@ msgid "Your SSH keys (%{count})"
msgstr ""
msgid "Your To-Do List"
-msgstr ""
+msgstr "ë‚˜ì˜ í•  ì¼ ëª©ë¡"
msgid "Your U2F device did not send a valid JSON response."
msgstr ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr "브랜치 ì´ë¦„"
msgid "by"
msgstr "by"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] "머지 리퀘스트(MR)"
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
@@ -33096,7 +34034,7 @@ msgid "user avatar"
msgstr "ì‚¬ìš©ìž ì•„ë°”íƒ€"
msgid "user preferences"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì„¤ì •"
msgid "username"
msgstr "사용ìžëª…"
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index ac093c7ca3b..56576c7a63f 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: 2020-12-03 08:17\n"
+"PO-Revision-Date: 2021-01-08 23:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index e482d3ed192..ef263bb395c 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: 2020-12-03 08:10\n"
+"PO-Revision-Date: 2021-01-08 22:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 8c619f1b0f4..508d8b48530 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: 2020-12-03 08:18\n"
+"PO-Revision-Date: 2021-01-08 23:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -917,6 +926,27 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1080,9 +1110,15 @@ 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 ""
@@ -1353,28 +1389,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1386,6 +1419,9 @@ 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 ""
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1422,6 +1461,9 @@ 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 ""
@@ -1440,13 +1482,16 @@ 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."
+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."
+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"
@@ -1455,10 +1500,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 ""
@@ -1491,13 +1545,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1539,6 +1596,9 @@ 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 ""
@@ -2134,6 +2194,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3017,6 +3062,9 @@ 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 ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 ""
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,7 +3533,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 ""
@@ -3569,7 +3629,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3726,13 +3786,13 @@ msgstr[3] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4027,6 +4087,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4045,12 +4111,18 @@ 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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4088,6 +4163,9 @@ 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 ""
@@ -4134,9 +4212,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,10 +4368,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4317,10 +4392,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4440,12 +4515,21 @@ 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 ""
@@ -4455,13 +4539,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4476,15 +4560,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4524,9 +4602,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,10 +4747,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4924,6 +5035,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5044,10 +5176,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5077,9 +5209,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 ""
@@ -5149,6 +5302,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 ""
@@ -5311,13 +5485,16 @@ 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 were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5872,6 +6055,18 @@ 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 ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7874,6 +8096,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8175,9 +8397,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8241,6 +8460,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8418,45 +8718,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ 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 ""
@@ -9097,9 +9379,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9577,9 +9856,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9589,6 +9865,9 @@ 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 ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10289,6 +10622,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ 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 ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 ""
@@ -11027,9 +11387,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11135,9 +11492,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11273,9 +11627,18 @@ 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 ""
@@ -11390,22 +11753,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 ""
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 ""
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,7 +13587,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13452,9 +13815,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13788,10 +14148,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13815,9 +14181,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,7 +14208,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13878,6 +14241,9 @@ 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 ""
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,13 +15164,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15212,13 +15627,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15230,9 +15645,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15428,7 +15858,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16257,6 +16699,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17452,9 +17912,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 ""
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19849,10 +20432,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20107,10 +20690,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20179,6 +20765,9 @@ 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 ""
@@ -20215,6 +20804,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ 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 ""
@@ -20242,7 +20843,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 ""
@@ -20875,13 +21506,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ 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 ""
@@ -21163,6 +21803,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 ""
@@ -21493,9 +22139,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 ""
@@ -21685,7 +22334,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21754,9 +22406,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21793,6 +22442,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21982,7 +22643,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,7 +23117,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22723,6 +23384,12 @@ 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 ""
@@ -22741,6 +23408,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23169,6 +23851,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23478,9 +24163,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,7 +24205,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23690,6 +24366,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23896,9 +24569,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23908,13 +24578,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,10 +24785,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24127,7 +24806,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24277,6 +24959,9 @@ 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 ""
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25099,6 +25796,9 @@ 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 ""
@@ -25129,10 +25829,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25330,9 +26027,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25767,6 +26467,9 @@ 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 ""
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26346,13 +27058,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27315,7 +28090,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27330,6 +28105,9 @@ 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] ""
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 ""
@@ -27533,9 +28317,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28079,6 +28866,9 @@ 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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 ""
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,7 +30594,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29728,7 +30609,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,7 +32013,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 ""
@@ -31582,9 +32496,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ 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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32261,9 +33199,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index 1887a269bc4..6510d36520f 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: 2020-12-03 08:18\n"
+"PO-Revision-Date: 2021-01-08 23:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 69bbf0e3c0e..ed1b52c323a 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: 2020-12-03 08:18\n"
+"PO-Revision-Date: 2021-01-08 23:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 7cb7ceaab88..b81c8de9968 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: 2020-12-03 08:12\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ msgstr "%{address} er et ugyldig IP-adresseområde"
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 "%{author_link} skrev:"
msgid "%{authorsName}'s thread"
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)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} commit"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} commiter"
+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 "%{strong_start}%{human_size}%{strong_end} filer"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} innflettet)"
msgid "(%{value}) has already been taken"
msgstr "(%{value}) har allerede blitt tatt"
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Ingen endringer)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(sjekk fremgang)"
@@ -1175,29 +1205,26 @@ msgstr ":%{startLine} til %{endLine}"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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 "En CI/CD-rørledning må kjøre og være vellykket før sammenslåing."
-msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Et Gitbook-nettsted som bruker Netlify for CI/CD i stedet for GitLab, men som fremdeles has alle de andre gode GitLab-funksjonene."
+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 "Et Hexo-nettsted som bruker Netlify for CI/CD i stedet for GitLab, men som fremdeles has alle de andre gode GitLab-funksjonene."
+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 "Et Hugo-nettsted som bruker Netlify for CI/CD i stedet for GitLab, men som fremdeles has alle de andre gode GitLab-funksjonene."
+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 "Et Jekyll-nettsted som bruker Netlify for CI/CD i stedet for GitLab, men som fremdeles has alle de andre gode GitLab-funksjonene."
+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 "Et 'Let's Encrypt'-SSL-sertifikat kan ikke fås før domenet ditt har blitt bekreftet."
@@ -1208,6 +1235,9 @@ msgstr "En Let's Encrypt-konto vil bli konfigurert for denne GitLab-installasjon
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 "En komplett DevOps-plattform"
@@ -1235,6 +1265,9 @@ 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 maximum of %{count} participants can be added"
+msgstr ""
+
msgid "A member of the abuse team will review your report as soon as possible."
msgstr "Et medlem av misbruksteamet vil vurdere rapporten din så snart som mulig."
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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 "Et rent HTML-nettsted som bruker Netlify for CI/CD i stedet for GitLab, men som fremdeles has alle de andre gode GitLab-funksjonene."
+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 "En plattformverdi kan være web, mob, eller app."
-msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "En klar-til-bruk-mal for bruk til Android-apper."
+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 "En klar-til-bruk-mal for bruk til iOS Swift-apper."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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 ""
@@ -1292,9 +1334,15 @@ 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 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 user can only participate in a rotation once"
+msgstr ""
+
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1313,14 +1361,17 @@ msgstr "API-token"
msgid "AWS Access Key"
msgstr "AWS tilgangsnøkkel"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "AWS-tilgangsnøkkel. Bare påkrevd hvis du ikke bruker rolleinstans-legitimasjoner"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS hemmelig tilgangsnøkkel"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "AWS hemmelig tilgangsnøkkel. Bare påkrevd hvis du ikke bruker rolleinstans-legitimasjoner"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "Avbryt"
@@ -1361,6 +1412,9 @@ msgstr "Tilgang nektet for LDAP-kontoen din."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Ingen tilgang! Vennligst verifiser at du kan legge til nøkler i dette kodelageret."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Tilgangsutløpsdato"
@@ -1954,6 +2008,9 @@ msgstr "Benytt integreringsinnstillingene på alle prosjekter"
msgid "AdminSettings|Auto DevOps domain"
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."
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Miljøvariabler er beskyttet som standard"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "GÃ¥ til Generelle innstillinger"
@@ -2439,9 +2499,6 @@ msgstr "Ingen"
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr "Opsgenie er aktivert"
-
msgid "AlertManagement|Please try again."
msgstr "Vennligst prøv igjen."
@@ -2505,15 +2562,9 @@ msgstr "Ukjent"
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr "Vis alarmer i Opsgenie"
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr "Du må oppgi denne URL-en og autorisasjonsnøkkelen for å autorisere en
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,12 +2661,12 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
-msgstr "Opsgenie"
-
msgid "AlertSettings|Proceed with editing"
msgstr ""
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
msgid "AlertSettings|Prometheus API base URL"
msgstr ""
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr "Webhook-URL"
@@ -2772,9 +2814,6 @@ msgstr "Alle grener"
msgid "All changes are committed"
msgstr "Alle endringer er loggført"
-msgid "All default stages are currently visible"
-msgstr "Alle standardtrinn er synlige for øyeblikket"
-
msgid "All email addresses will be used to identify your commits."
msgstr "Alle e-postadressene vil bli brukt til å identifisere dine commiter."
@@ -2835,6 +2874,9 @@ msgstr "Tillat gruppeeiere å behandle LDAP-relaterte innstillinger"
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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "En feil har oppstått"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "En feil oppstod under veksling av varslingsabonnement"
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 "En feil oppstod under oppdatering av saksvektleggingen"
@@ -3021,6 +3066,9 @@ msgstr "En feil oppstod under tillegging av godkjennere"
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 "En feil oppstod under sjekking av gruppefilbanen. Vennligst oppdater og prøv igjen."
@@ -3243,9 +3291,6 @@ msgstr "En feil oppstod under innhenting av diff-filer"
msgid "An error occurred while retrieving projects."
msgstr "Det oppstod en feil under innhenting av prosjekter."
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr "En feil oppstod under lagring av tilordnede"
@@ -3267,6 +3312,9 @@ msgstr "En feil oppstod under avabonnering på varsler."
msgid "An error occurred while updating approvers"
msgstr "En feil oppstod under oppdatering av godkjennere"
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3276,6 +3324,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "En feil oppstod under oppdatering av kommentaren"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,8 +3345,8 @@ msgstr "En feil oppstod. Vennligst prøv igjen."
msgid "An error ocurred while loading your content. Please try again."
msgstr "En feil oppstod under innlasting av innholdet ditt. Vennligst prøv igjen."
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
-msgstr "Et eksempelprosjekt for å administrere Kubernetes-klynger som er integrert med GitLab."
+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 ""
@@ -3309,6 +3360,9 @@ msgstr "En sak finnes allerede"
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 "En sak kan være en feil, et gjøremål, eller en funksjonsforespørsel som behøver å diskuteres i et prosjekt. Dessuten er saker søkbare og filtrerbare."
+msgid "An issue title is required"
+msgstr ""
+
msgid "An unauthenticated user"
msgstr "En uautentisert bruker"
@@ -3387,7 +3441,7 @@ msgstr "Alle filer som er større enn denne grensen, vil ikke bli indeksert, og
msgid "Any label"
msgstr "Ethvert stempel"
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,15 +3590,15 @@ msgstr[1] "%{count} godkjenninger kreves fra %{membersCount}"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Godkjennere"
msgid "ApprovalRule|Name"
msgstr "Navn"
-msgid "ApprovalRule|No. approvals required"
-msgstr "Antall påkrevde godkjenninger"
-
msgid "ApprovalRule|Rule name"
msgstr "Regelnavn"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr "Seksjon: %seksjon"
@@ -3665,9 +3722,6 @@ msgstr "Er du sikker på at du vil slette denne %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "Er du sikker på at du vil slette dette panelet?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Er du sikker på at du vil slette denne enheten? Denne handlingen kan ikke angres på."
@@ -3835,6 +3889,12 @@ msgstr "Tilordne stempler"
msgid "Assign milestone"
msgstr "Tilordne milepæl"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Tildel noen saker til denne milepælen."
@@ -3853,12 +3913,18 @@ msgstr "Tildel deg selv til denne saken"
msgid "Assigned %{assignee_users_sentence}."
msgstr ""
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Tilegnede saker"
msgid "Assigned Merge Requests"
msgstr "Tilordnede fletteforespørsel"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr "Tilordnet til %{assigneeName}"
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Tilordnet meg"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Tilordnet"
@@ -3894,6 +3963,9 @@ msgstr "Tilordnede"
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 "Minst én godkjenning fra en kodeeier kreves for å endre filer som samsvarer med de respektive CODEOWNER-reglene."
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr "Revisjonslogg"
-
msgid "AuditLogs|(removed)"
msgstr "(fjernet)"
@@ -4097,12 +4166,12 @@ 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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr "Auto DevOps kan automatisk bygge, teste og distribuere applikasjoner basert på forhåndsdefinert kontinuerlig integrasjon og leveringsoppsett. %{auto_devops_start}Lær mer om Auto DevOps%{auto_devops_end} eller bruk vår %{quickstart_start}hurtigstartguide%{quickstart_end} for å komme i gang umiddelbart."
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto DevOps dokumentasjon"
@@ -4121,10 +4190,13 @@ msgstr "Lær mer i %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr "Automatisk sertifikatshåndtering med Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Bakgrunnsfarge"
msgid "Badges"
msgstr "Merker"
-msgid "Badges|A new badge was added."
-msgstr "Et nytt merke ble lagt til."
-
msgid "Badges|Add badge"
msgstr "Legg til merke"
@@ -4244,12 +4313,21 @@ msgstr "Merkebilde nettadresse"
msgid "Badges|Badge image preview"
msgstr "Forhåndsvisning av merkebilde"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "Slette badge?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "Sletting av merket mislyktes, vennligst prøv igjen."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Grupper merker"
@@ -4259,15 +4337,15 @@ msgstr "Lenke"
msgid "Badges|Name"
msgstr "Navn"
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "Ingen merkebilde"
msgid "Badges|No image to preview"
msgstr "Ingen bilder å forhåndsvise"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Vennligst fyll inn en gyldig nettadresse"
-
msgid "Badges|Project Badge"
msgstr "Prosjektmerke"
@@ -4280,15 +4358,12 @@ msgstr "Lagre endringer"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Lagring av merket mislyktes, sjekk de angitte nettadressene og prøv igjen."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "%{docsLinkStart}variablene%{docsLinkEnd} GitLab støtter: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Merket ble slettet."
-msgid "Badges|The badge was saved."
-msgstr "Merket ble lagret."
-
msgid "Badges|This group has no badges"
msgstr "Denne gruppen har ingen merker"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Dine merker"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "f.eks. %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Balsamiq-filen kunne ikke lastes inn."
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr "Kontakt salgsavdelingen"
msgid "BillingPlan|Upgrade"
msgstr "Oppgrader"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr "Blokk"
msgid "Blog"
msgstr "Blogg"
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ msgstr "Utvid"
msgid "Boards|View scope"
msgstr "Vis omfang"
+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 ""
@@ -4555,9 +4663,6 @@ msgstr "Grennavn"
msgid "Branch not loaded - %{branchId}"
msgstr "Grenen ble ikke lastet inn - %{branchId}"
-msgid "Branch prefix"
-msgstr "Grenprefiks"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Søk i grener"
@@ -4726,6 +4831,24 @@ msgstr "Innebygget"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr "CI/CD for eksternt kodelager"
msgid "CI/CD settings"
msgstr "CI/CD-innstillinger"
-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."
+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"
@@ -4846,10 +4972,10 @@ msgstr "Distribusjonsstrategi"
msgid "CICD|Jobs"
msgstr "Jobber"
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr "URL-adresse for tilbakeringing"
msgid "Can be manually deployed to"
msgstr "Kan distribueres manuelt til"
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr "Kan ikke benytte det, siden kildegrenen ble slettet."
@@ -4930,6 +5053,30 @@ 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 "Avbryt"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr "Avbryter forhåndsvisningen"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Kan ikke flettes automatisk"
@@ -5083,15 +5233,33 @@ msgstr ""
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Tilbakestill i grenen"
+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|Revert"
msgstr "Tilbakestill"
+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 "Dette vil opprette en ny commit for å kunne tilbakestille de eksisterende endringene."
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr "Endret tilordnet person(er)."
@@ -5113,13 +5281,16 @@ msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr ""
+msgid "Changes saved."
+msgstr ""
+
msgid "Changes suppressed. Click to show."
msgstr "Endringer er klappet sammen. Klikk for å vise."
msgid "Changes the title to \"%{title_param}\"."
msgstr "Endrer tittelen til \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr "Endring av gruppe-URL-en kan ha utilsiktede bivirkninger."
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr "Diagram"
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Velg en mal …"
msgid "Choose a type..."
msgstr "Velg en type …"
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr "Klone"
msgid "Clone repository"
msgstr "Klon lageret"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "Klon med %{http_label}"
@@ -5674,6 +5851,18 @@ msgstr "Klon med KRB5"
msgid "Clone with SSH"
msgstr "Klon med SSH"
+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 "Lukk"
@@ -6781,12 +6970,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "Kodeeiere"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr "Kodekvalitet"
@@ -7056,6 +7245,24 @@ msgstr ""
msgid "ComplianceDashboard|created by:"
msgstr "opprettet av:"
+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 "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Koble til"
@@ -7273,13 +7483,13 @@ msgstr[1] "%{count} etiketter"
msgid "ContainerRegistry|%{imageName} tags"
msgstr "%{imageName} etiketter"
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ msgstr ""
msgid "ContainerRegistry|CLI Commands"
msgstr "CLI-kommandoer"
+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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr "Sammendrag: %{imageId}"
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 "Utløpsretningslinjer hjelper deg med å administrere lagringsplassen som brukes av container-registeret, men utløpsretningslinjene for dette registeret er deaktivert. Kontakt administratoren din for å aktivere. %{docLinkStart}Mer informasjon%{docLinkEnd}"
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr "Filtrer etter navn"
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr "Innlogging"
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr "Antall etiketter å beholde:"
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "Publisert den %{timeInfo}"
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ msgstr "For å utvide søket, endre eller fjerne filtrene ovenfor."
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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr "Jokertegn som %{codeStart}*-master%{codeEnd} eller %{codeStart}release-.*%{codeEnd} er støttet"
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr "Kopier nettadresse"
msgid "Copy branch name"
msgstr "Kopier gren-navn"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "Kopier kommando"
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr "Lag en konto med:"
-msgid "Create an issue. Issues are created for each alert triggered."
+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 "Koble til og lever din %{link_start}personlige GitHub-tilgangssjetong%{link_end}. Du vil måtte velge %{code_open}kodelager%{code_close}-omfanget, så vi kan vise en liste over dine offentlige og private kodelagre som er tilgjengelige for å importere."
-msgid "Create board"
-msgstr ""
-
msgid "Create branch"
msgstr "Opprett gren"
@@ -7967,9 +8183,6 @@ msgstr "Opprett ny"
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "Opprett ny tavle"
-
msgid "Create new branch"
msgstr "Opprett ny gren"
@@ -8033,6 +8246,84 @@ msgstr "Etikett"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Opprettet"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr "Crossplane"
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Nåværende gren"
@@ -8210,45 +8504,18 @@ msgstr "Legg til trinn"
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
-msgid "CustomCycleAnalytics|Name"
-msgstr "Navn"
-
msgid "CustomCycleAnalytics|New stage"
msgstr "Nytt trinn"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr "Velg starthendelse"
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr "Velg stopphendelse"
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr "Trinnavnet finnes allerede"
-msgid "CustomCycleAnalytics|Start event"
-msgstr "Starthendelse"
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr "Stopphendelse"
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr "Oppdater trinn"
-
msgid "Customer Portal"
msgstr "Kundeportal"
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr "Er du sikker på at du vil slette profilen?"
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr "Detaljer om feilen"
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr "Profilnavn"
+msgid "DastProfiles|Request headers"
+msgstr ""
+
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "Standard-sakermal"
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr "Standardtrinn"
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr "Slett artefakter"
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "Slett tavle"
-
msgid "Delete comment"
msgstr "Slett kommentar"
@@ -9355,9 +9628,6 @@ msgstr "Synkende"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr "Beskriv kravet her"
-
msgid "Description"
msgstr "Beskrivelse"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr "Last ned %{format}"
msgid "Download %{format}:"
msgstr "Last ned %{format}:"
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "Last ned CSV"
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr "Rediger applikasjonen"
-msgid "Edit board"
-msgstr "Rediger tavle"
-
msgid "Edit comment"
msgstr "Rediger kommentar"
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "Rediger trinn"
@@ -10092,12 +10422,18 @@ msgstr "Redigert %{timeago}"
msgid "Editing"
msgstr "Redigerer"
+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 ""
@@ -10131,6 +10467,9 @@ msgstr "E-post %{number}"
msgid "Email Notification"
msgstr "E-postvarsling"
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr "tilbakestiller …"
msgid "Emails"
msgstr "E-poster"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ msgstr "Skru på og sett opp Grafana."
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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr "Skru på 2-trinnsautentisering"
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr "Sluttid"
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Slutter den (UTC)"
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr "Skriv inn minst tre tegn for å søke"
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr "Skriv inn domene"
@@ -10485,6 +10827,9 @@ msgstr "Skriv inn fletteforespørselens tittel"
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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ msgstr "Denne handlingen vil kjøre jobben som er definert av %{environment_name
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 "Denne handlingen vil kjøre jobben som er definert av %{name} for innsmettingen %{linkStart}%{commitId}%{linkEnd}, som setter miljøet til en tidligere versjon. Du kan tilbakestille det ved å distribuere den nyeste versjonen av applikasjonen på nytt. Er du sikker på at du vil fortsette?"
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Oppdatert"
@@ -10803,9 +11157,6 @@ msgstr "Hvordan kan jeg løse dette?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Mer informasjon"
-
msgid "Epics|Remove epic"
msgstr "Fjern epos"
@@ -10911,9 +11262,6 @@ msgstr "Feil ved henting av nettverksgrafer."
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr "Feil under innhenting av prosjekter"
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr "Feil: %{error_message}"
+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 "Aktiv"
@@ -11166,22 +11523,22 @@ msgstr "Alle kan bidra"
msgid "Everything on your to-do list is marked as done."
msgstr ""
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr "Eksisterende greinnavn, etikett, eller commit-SHA"
-msgid "Existing members and groups"
-msgstr "Eksisterende medlemmer og grupper"
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr "Forventede dokumenter: %{expected_documents}"
msgid "Experienced"
msgstr "Erfaren"
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "Utløp"
@@ -11403,6 +11760,9 @@ msgstr "Mislyktes i å legge til et Zoom-møte"
msgid "Failed to apply commands."
msgstr "Mislyktes i å benytte kommandoer."
+msgid "Failed to assign a reviewer because no user was found."
+msgstr ""
+
msgid "Failed to assign a user because no user was found."
msgstr ""
@@ -11421,6 +11781,12 @@ msgstr "Klarte ikke å endre eieren"
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 "Klarte ikke å opprette fletteforespørsel. Vennligst prøv igjen."
@@ -11448,9 +11814,6 @@ msgstr "Mislyktes i å opprette ressurser"
msgid "Failed to create wiki"
msgstr "Mislyktes i å opprette wiki"
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr "Mislyktes i å oppdatere gren!"
msgid "Failed to update environment!"
msgstr "Mislyktes i å oppdatere miljø!"
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr "Mislyktes i å oppdatere-sakerstatus"
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] "%d bruker"
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "Funksjonsflagg"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ msgstr "Brukerliste"
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 "Prosentandel"
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Filter"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrer etter %{issuable_type} som for øyeblikket er stengt."
@@ -12026,12 +12389,6 @@ msgstr "Filtrer etter milepælnavn"
msgid "Filter by name"
msgstr "Filtrer etter navn"
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr "Filtrer etter status"
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Finn utifra filbane"
-msgid "Find existing members by name"
-msgstr "Finn eksisterende medlemmer med navn"
-
msgid "Find file"
msgstr "Finn fil"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr "Fullført"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr "Først sett"
@@ -12233,9 +12590,6 @@ msgstr "Utgreininger"
msgid "Format: %{dateFormat}"
msgstr "Format: %{dateFormat}"
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "Fant feil i din %{gitlab_ci_yml}:"
@@ -12701,6 +13055,12 @@ msgstr ""
msgid "Get started"
msgstr "Kom i gang"
+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 ""
@@ -12776,9 +13136,6 @@ msgstr "Gitlab-sak"
msgid "GitLab Pages"
msgstr "GitLab-sider"
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr "GitLab-tjenestedesken er en enkel måte å la folk opprette saksrapporter i din GitLab-forekomst uten å behøve sin egen brukerkonto. Det sørger for en unik e-postadresse for sluttbrukere til å opprette saksrapporter i et prosjekt, og svar kan sendes enten via GitLab-grensesnittet eller via e-post. Sluttbrukere vil bare se tråden via e-post."
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr "Universelle varslingsinnstillinger"
msgid "Go Back"
msgstr "GÃ¥ tilbake"
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr "Gruppeavatar"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "Gruppebeskrivelse"
-
msgid "Group description (optional)"
msgstr "Gruppebeskrivelse (valgfritt)"
@@ -13562,10 +13916,16 @@ msgstr "Endre gruppe-URL"
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 "Tilpassede prosjektmaler"
-msgid "GroupSettings|Customize your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr "Hvis overgruppens synlighet er lavere enn gruppens nåværende synlighet
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr "Prosjekter vil bli slettet permanent etter en %{waiting_period}-dags for
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr "Overfør gruppe"
+msgid "GroupSettings|What are badges?"
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -13730,6 +14090,9 @@ msgstr "Ingen grupper ble funnet"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr "Kontakt en administrator for å aktivere alternativer for å importere gruppen din."
@@ -13739,22 +14102,46 @@ msgstr "Opprett"
msgid "GroupsNew|Create group"
msgstr "Opprett gruppe"
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
msgid "GroupsNew|Import"
msgstr "Importer"
-msgid "GroupsNew|Import a GitLab group export file"
-msgstr ""
-
msgid "GroupsNew|Import group"
msgstr "Importer gruppe"
+msgid "GroupsNew|Import groups from another instance of GitLab"
+msgstr ""
+
msgid "GroupsNew|My Awesome Group"
msgstr "Min fantastiske gruppe"
+msgid "GroupsNew|Navigate to user settings to find your %{link_start}personal access token%{link_end}."
+msgstr ""
+
msgid "GroupsNew|No import options available"
msgstr "Ingen importalternativer er tilgjengelige"
-msgid "GroupsNew|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "Hvordan det virker"
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr "Importer fra"
msgid "Import from Jira"
msgstr "Importer fra Jira"
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "Holder på å importere"
@@ -14269,6 +14668,9 @@ msgstr "Importer kodelagre fra GitHub"
msgid "Import repository"
msgstr "Importer kodelager"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr "Importering startet av: %{importInitiator}"
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr "Inkompatibelt prosjekt"
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr "Rykk inn"
@@ -14790,6 +15194,12 @@ 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|Linked namespaces"
+msgstr ""
+
+msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr "Ugyldig Git-ref"
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,15 +15383,15 @@ msgstr ""
msgid "Invite"
msgstr "Inviter"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "Inviter «%{trimmed}» via e-post"
msgid "Invite Members"
msgstr "Inviter medlemmer"
-msgid "Invite another teammate"
-msgstr "Inviter en annen teamkamerat"
-
msgid "Invite group"
msgstr "Inviter gruppe"
@@ -14994,9 +15401,6 @@ msgstr "Inviter medlem"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr "Invitert"
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr "Saken kunne ikke bli funnet."
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Sakshendelser"
@@ -15192,8 +15614,8 @@ msgstr ""
msgid "Issue published on status page."
msgstr "Sak publisert på statussiden."
-msgid "Issue template (optional)"
-msgstr "Saksrapportmal (valgfritt)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
msgstr "Saksoppdatering mislyktes"
@@ -15231,7 +15653,7 @@ msgstr "Status"
msgid "IssueAnalytics|Weight"
msgstr "Vektlegging"
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr "Skru på Jira-saker"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,21 +15887,21 @@ msgstr "Jira-sakssporer"
msgid "JiraService|Jira project key"
msgstr "Jira-prosjektnøkkel"
+msgid "JiraService|Jira workflow transition IDs"
+msgstr ""
+
msgid "JiraService|Open Jira"
msgstr "Ã…pne Jira"
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr "Denne funksjonen krever en Premium-plan."
-msgid "JiraService|Transition ID(s)"
-msgstr "Overgangs-ID(-er)"
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
-msgstr ""
-
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr "Sist sett"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr "Tips"
msgid "Lead Time"
msgstr "Ledetid"
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "Lær GitLab"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ msgstr "Lær mer om X.509-signerte commiter"
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 approvals."
-msgstr "Lær mer om godkjenninger."
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Lær mer i"
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Forlat"
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr "Laster inn saker"
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr "Laster inn utdrag"
@@ -16444,6 +16884,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr "INNFLETTET"
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr "Maks tilgangsnivå"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr "Minneforbruk"
msgid "Merge"
msgstr "Flett"
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr "Flettekonflikter"
@@ -17038,6 +17490,9 @@ msgstr "Fletteforespørsel %{iid} skapt av %{authorName}"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr "Fletteforespørselen %{mr_link} ble gjennomgått av %{mr_author}"
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Godkjenninger av fletteforespørsel"
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Fletteforespørsel"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ 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"
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr "Speilingsinnstillinger er bare tilgjengelige for GitLab-administratorer.
msgid "Mirror user"
msgstr "Speil bruker"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "Speilede kodelagre"
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ msgstr "%{ifLabelStart}hvis%{ifLabelEnd} %{ruleType} %{isLabelStart}er%{isLabelE
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr "%{ifLabelStart}hvis%{ifLabelEnd} %{ruleType} %{isLabelStart}er%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}og er utgående fra en%{directionLabelEnd} %{rule} %{portsLabelStart}på%{portsLabelEnd} %{ports}"
+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 ""
@@ -18114,6 +18566,9 @@ msgstr "%{strongOpen}alle%{strongClose} podder"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr "%{strongOpen}enhver%{strongClose} port"
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ".yaml"
@@ -18123,6 +18578,9 @@ msgstr ".yaml-modus"
msgid "NetworkPolicies|Actions"
msgstr "Handlinger"
+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 "Alle valgt"
@@ -18419,6 +18877,12 @@ msgstr "Ny fil"
msgid "New group"
msgstr "Ny gruppe"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr "Ingen grener funnet"
msgid "No changes"
msgstr "Ingen endringer"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr "Ikke tilgjengelig for private prosjekter"
msgid "Not available for protected branches"
msgstr "Ikke tilgjengelig for beskyttede grener"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Ikke konfidensiell"
@@ -18821,6 +19288,9 @@ msgstr "Ikke klar enda. Prøv igjen senere."
msgid "Not started"
msgstr "Ikke påbegynt"
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr "Notis"
@@ -19058,6 +19528,9 @@ msgstr "Av"
msgid "Oh no!"
msgstr "Ã… nei!"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "Eldste øverst"
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a new site profile"
msgstr "Opprett en ny nettstedsprofil"
+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 profiles"
msgstr "Behandle profiler"
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ msgstr ""
msgid "OnDemandScans|Run scan"
msgstr "Kjør skanning"
+msgid "OnDemandScans|Save and run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save scan"
+msgstr ""
+
+msgid "OnDemandScans|Scan name"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr "Pakketypen må være Conan"
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "Pakketypen må være Maven"
@@ -19438,11 +20013,8 @@ msgstr "Pakketypen må være NuGet"
msgid "Package type must be PyPi"
msgstr "Pakketypen må være PyPi"
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr "%{name} versjon %{version} ble opprettet den %{datetime}"
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
-msgstr "%{name} versjon %{version} ble oppdatert den %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
+msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
@@ -19459,7 +20031,7 @@ msgstr "Appgruppe: %{group}"
msgid "PackageRegistry|App name: %{name}"
msgstr "Appnavn: %{name}"
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr "Kopier yarn-kommando"
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr "Slett pakkeversjonen"
@@ -19585,12 +20160,18 @@ msgstr "NuGet-kommando"
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 "Pip-kommando"
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
-msgstr "Rørledningen %{link} ble trigget %{datetime} av %{author}"
-
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr ""
@@ -19690,7 +20271,7 @@ msgstr "Sideinnstillinger"
msgid "PagerDutySettings|Active"
msgstr "Aktiv"
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr "Tilbakestill Webhook-URL-en"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr "Webhook-URL"
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr "Webhook-URL-oppdateringen var vellykket"
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Sider"
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr "Pause"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ msgstr "Tillatelser, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Personlige tilgangsnøkkel"
+msgid "Personal Access Token prefix"
+msgstr ""
+
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ msgstr ""
msgid "Pipeline: %{status}"
msgstr "Rørledning: %{status}"
+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 ""
@@ -19978,7 +20571,7 @@ msgstr "Suksessfrekvens:"
msgid "PipelineCharts|Successful:"
msgstr "Vellykket:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ msgstr "Det er ingen rørledninger for øyeblikket."
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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ msgstr "Ta kontakt med administratoren."
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 "Vennligst skriv inn et passord for din nye konto."
@@ -20401,6 +21021,9 @@ 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 "Vennligst skriv inn et gyldig nummer"
@@ -20611,13 +21234,16 @@ msgstr "Trykk %{key}-C for å kopiere"
msgid "Prev"
msgstr "Forrige"
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals from users who make commits to the MR."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr "Forrige uoppklarte diskusjon"
msgid "Primary"
msgstr "Primær"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "Prioriter"
@@ -20797,6 +21426,9 @@ msgstr ""
msgid "Profiles|@username"
msgstr "@brukernavn"
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr "Fullt navn"
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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"
@@ -21229,9 +21867,6 @@ msgstr "Prosjektets navn"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ msgstr "Alle diskusjoner må bli oppklart"
msgid "ProjectSettings|Allow"
msgstr "Tillat"
+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 "Tillat brukere å be om tilgang"
+msgid "ProjectSettings|Analytics"
+msgstr ""
+
msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
msgstr ""
@@ -21421,7 +22062,7 @@ msgstr "Kontakt en administrator for å endre på denne innstillingen."
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr "Oppmuntre til"
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "Alle innflettinger skaper en innflettings-commit"
@@ -21490,9 +22134,6 @@ msgstr "Saker"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr "LFS-objekter fra dette kodelageret er fortsatt tilgjengelig for utgreininger. %{linkStart}Hvordan fjerner jeg dem?%{linkEnd}"
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "Pakker"
@@ -21637,12 +22281,21 @@ msgstr "Vis og rediger filer i dette prosjektet"
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|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 "Når dette er aktivert, viser saker, fletteforespørsler og utdrag alltid tommel-opp- og tommel-ned-emojiknapper."
@@ -21661,9 +22314,6 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,8 +22812,8 @@ msgstr "Beskyttede etiketter"
msgid "Protected branches"
msgstr "Beskyttede grener"
-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 "%{wildcards_link_start}Jokertegn%{wildcards_link_end} slik som %{code_tag_start}*-stable%{code_tag_end} eller %{code_tag_start}production/*%{code_tag_end} er støttet"
+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 "Tillatelse til å innflette"
@@ -22192,7 +22845,7 @@ msgstr "Beskytt en gren"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ msgstr "Nullstill"
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 ""
@@ -22477,6 +23136,9 @@ msgstr "Nylig prosjektaktivitet"
msgid "Recent Searches Service is unavailable"
msgstr "Tjeneste for nylige søk er ikke tilgjengelig"
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "Nylige søk"
@@ -22581,8 +23243,11 @@ msgstr "Profilen din"
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
-msgstr "Reindekserer statusen"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
+msgstr ""
msgid "Rejected (closed)"
msgstr "Avslått (lukket)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr "Fjern Zoom-møte"
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 "Fjern godkjenner"
@@ -22790,6 +23455,9 @@ msgstr "Fjern prioritet"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Fjern sekundærnode"
@@ -22826,6 +23494,9 @@ msgstr "Fjernet %{label_references} %{label_text}."
msgid "Removed %{milestone_reference} milestone."
msgstr "Fjernet %{milestone_reference}-milepæl."
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "Fjernet %{type} med ID %{id}"
@@ -22871,6 +23542,9 @@ msgstr "Fjerner %{label_references} %{label_text}."
msgid "Removes %{milestone_reference} milestone."
msgstr "Fjerner %{milestone_reference}-milepælen."
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr "Fjerner alle stempler."
@@ -22901,6 +23575,9 @@ msgstr "Gi mappen nytt navn"
msgid "Rename/Move"
msgstr "Endre navn/flytt"
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr "Åpne på nytt"
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Kodelager"
@@ -23204,9 +23881,6 @@ msgstr "Velg"
msgid "Request Access"
msgstr "Be om tilgang"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,8 +23923,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
-msgstr "Krev brukerpassord for å godkjenne"
+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 ""
@@ -23276,9 +23953,6 @@ msgstr "Kravet %{reference} har blitt gjenåpnet"
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr "Svar"
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr "Responsstatus"
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr "Responsmåltall (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Responsmåltall (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "Start terminalen på nytt"
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr "Løpere"
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ msgstr "Kjører …"
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 "SAML"
@@ -23761,9 +24435,6 @@ msgstr "Offentlig SSH-nøkkel"
msgid "SSL Verification:"
msgstr "SSL-verifisering:"
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr "Planlagt"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr "Omfang"
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Søk etter brukere"
@@ -23995,6 +24669,9 @@ 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 "på hele GitLab"
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ msgstr "Avfeide '%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Download %{artifactName}"
+msgstr ""
+
msgid "SecurityReports|Download Report"
msgstr "Last ned rapport"
+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 "Enten har du ikke tillatelse til å se dette kontrollpanelet, eller så har kontrollpanelet ikke blitt konfigurert. Kontroller tillatelsesinnstillingene dine med administratoren din, eller sjekk kontrollpanelkonfigurasjonene sine for å fortsette."
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ msgstr "Klarte ikke å legge til %{invalidProjects}"
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 "SÃ¥rbarhetsrapport"
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr "September"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ msgstr "Tjeneste"
msgid "Service Desk"
msgstr "Tjenestedesk"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr ""
@@ -24823,10 +25515,7 @@ 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 "Angi .gitlab-ci.yml for å aktivere eller konfigurere SAST.sikkerhetsskanning ved hjelp av den GitLab-håndterte malen. Du kan [legge til variabel-overstyring](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) for å tilpasse SAST-innstillinger."
-msgid "Set a default template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr "Alternativer"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr "Oppsett"
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr "Vis all aktivitet"
@@ -25096,9 +25788,6 @@ msgstr "Vis alle saker."
msgid "Show all members"
msgstr "Vis alle medlemmer"
-msgid "Show all requirements."
-msgstr "Vis alle krav."
-
msgid "Show all test cases."
msgstr "Vis alle testsaker."
@@ -25135,6 +25824,9 @@ msgstr "Vis filutforsker"
msgid "Show file contents"
msgstr "Vis filens innhold"
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Vis nyeste versjon"
@@ -25457,6 +26149,9 @@ 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 "Noe gikk galt i vår ende"
@@ -25493,7 +26188,10 @@ msgstr "Noe gikk galt under benyttelse av forslaget. Vennligst prøv igjen."
msgid "Something went wrong while archiving a requirement."
msgstr "Noe gikk galt under arkivering av et krav."
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ msgstr "Noe gikk galt under redigering av kommentaren din. Prøv igjen senere."
msgid "Something went wrong while fetching %{listType} list"
msgstr "Noe gikk feil under henting av %{listType} listen"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Noe gikk feil under henting av kommentarer. Vennligst prøv igjen."
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr "Noe gikk galt under gjenåpning av et krav."
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,8 +26323,8 @@ msgstr "Noe gikk galt, kunne ikke innhente prosjekter"
msgid "Something went wrong, unable to search projects"
msgstr "Noe gikk galt, kunne ikke søke i prosjekter"
-msgid "Something went wrong."
-msgstr "Noe gikk galt."
+msgid "Something went wrong. Please try again later"
+msgstr ""
msgid "Something went wrong. Please try again."
msgstr "Noe gikk galt. Vennligst prøv igjen."
@@ -26036,13 +26740,16 @@ msgstr "Starter …"
msgid "Starts %{startsIn}"
msgstr "Starter %{startsIn}"
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Starter (UTC)"
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 "GÃ¥ tilbake til nettstedet"
@@ -26318,6 +27031,9 @@ msgstr "Abonnementet ble vellykket opprettet."
msgid "Subscription successfully deleted."
msgstr "Abonnementet ble vellykket slettet."
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr "Synkroniserer …"
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "System"
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ msgstr "Genereringen av prosjektet forårsaket en feil."
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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 "Test"
@@ -26999,8 +27766,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr "Takk for handelen!"
-msgid "Thanks! Don't show me this again"
-msgstr "Takk! Ikke vis meg dette igjen"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ msgstr "Det avansert søket i GitLab er en kraftig søketjeneste som sparer deg
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 ""
@@ -27091,6 +27864,9 @@ msgstr "Innholdet i denne gruppen, dens undergrupper og prosjekter blir fjernet
msgid "The current issue"
msgstr "Den nåværende saken"
+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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "Den maks tillatte filstørrelsen er %{size}."
-msgid "The maximum file size allowed is 200KB."
-msgstr "Den maksimale filstørrelsen som er tillatt er 200KB."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ msgstr ""
msgid "There are no variables yet."
msgstr "Det er ingen variabler enda."
+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 ""
@@ -27600,6 +28373,9 @@ 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 "En feil oppstod under innhenting av %{replicableType}"
@@ -27678,6 +28454,9 @@ msgstr ""
msgid "There was an error updating the Geo Settings"
msgstr "Det oppstod en feil under oppdatering av Geo-innstillingene"
+msgid "There was an error updating the Maintenance Mode Settings"
+msgstr ""
+
msgid "There was an error updating the dashboard, branch name is invalid."
msgstr ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ msgstr ""
msgid "ThreatMonitoring|Container NetworkPolicies not detected"
msgstr ""
+msgid "ThreatMonitoring|Date and time"
+msgstr ""
+
+msgid "ThreatMonitoring|Dismissed"
+msgstr ""
+
msgid "ThreatMonitoring|Dropped Packets"
msgstr "Droppede pakker"
msgid "ThreatMonitoring|Environment"
msgstr "Miljø"
+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 ""
@@ -28251,6 +29063,9 @@ msgstr "Retningslinjer"
msgid "ThreatMonitoring|Requests"
msgstr "Forespørsler"
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr "Vis siste"
@@ -28263,12 +29078,21 @@ msgstr "Noe gikk galt, kunne ikke innhente statistikker"
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 "TGrafen nedenfor er en oversikt over trafikk som kommer inn til applikasjonen din, som sporet av Web Application Firewall (WAF). Se dokumentene for instruksjoner om hvordan du får tilgang til WAF-loggene for å se hvilken type skadelig trafikk som prøver å få tilgang til appen din. Dokumentkoblingen er også tilgjengelig ved å klikke på «?»-ikonet ved siden av tittelen nedenfor."
+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 "Trusselovervåking"
@@ -28278,7 +29102,7 @@ msgstr ""
msgid "ThreatMonitoring|Time"
msgstr "Tid"
-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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr "Vis dokumentasjon"
@@ -28894,12 +29721,20 @@ msgstr "Tre-visning"
msgid "Trending"
msgstr "Populære"
+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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "GÃ¥ tilbake til GitLab"
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 "Utløser"
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr "Fjern stjerne"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "Avabonner"
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr "Frem til"
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "Oppdater ditt gruppenavn, beskrivelse, avatar og synlighet."
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr "Prosjektet kunne ikke bli oppdatert!"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr "Brukerne ble vellykket lagt til."
@@ -30398,6 +31269,9 @@ msgstr "%{scannerName} (versjon %{scannerVersion})"
msgid "Vulnerability|Activity"
msgstr ""
+msgid "Vulnerability|Actual Response"
+msgstr ""
+
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
msgstr ""
@@ -30425,6 +31299,9 @@ msgstr "Beskrivelse"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "Bevis"
@@ -30452,6 +31329,12 @@ msgstr "Navnefelt"
msgid "Vulnerability|Project"
msgstr "Prosjekt"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ msgstr "Status"
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 ""
@@ -30482,6 +31368,9 @@ msgstr "Venter på ytelsesdata"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Ønsker du å se dataene? Vennligst kontakt en administrator for å få tilgang."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr "Advarsel:"
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr "Jobb-hendelser"
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,8 +31673,8 @@ msgstr "NÃ¥r:"
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 be an approver?"
-msgstr "Hvem kan bli en godkjenner?"
+msgid "Who can approve?"
+msgstr ""
msgid "Who can see this group?"
msgstr "Hvem kan se denne gruppen?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr "Du kan gjenopprette dette prosjektet frem til %{date}"
+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 ""
@@ -31252,9 +32156,6 @@ msgstr "Du kan se dine chatkontoer."
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr "Du har ikke registrert noen U2F-enheter enda."
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Du må ha vedlikeholder-tilgang for å tvangsslette en lås"
@@ -31588,6 +32498,9 @@ msgstr "Ditt %{strong}%{plan_name}%{strong_close} abonnement på %{strong}%{name
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 ""
@@ -31660,6 +32573,9 @@ msgstr "U2F-enheten din sendte ikke et gyldig JSON-svar."
msgid "Your U2F device was registered!"
msgstr "Din U2F-enhet ble registrert!"
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 "Ditt første prosjekt"
@@ -31756,6 +32675,9 @@ msgstr "Sakene dine blir importert. Når det er ferdig, vil du få en bekreftels
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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr "som %{role}."
msgid "assign yourself"
msgstr "tildel deg selv"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr "i faresonen"
@@ -31929,9 +32857,15 @@ msgstr "grennavn"
msgid "by"
msgstr "av"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ msgstr "%{degradedNum} degradert"
msgid "ciReport|%{improvedNum} improved"
msgstr "%{improvedNum} forbedret"
+msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Alle prosjekter"
@@ -32169,6 +33109,9 @@ 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] "Brukes av %{packagesString}"
@@ -32371,6 +33314,12 @@ msgstr ""
msgid "has already been taken"
msgstr "er allerede i bruk"
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
msgid "has been completed."
msgstr ""
@@ -32553,6 +33502,9 @@ msgstr "Matematikken i denne oppføringen tar for lang tid å gjengi og vises ka
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] "fletteforespørsel"
@@ -33207,18 +34159,9 @@ 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 "Vi legger til en GitLab CI-konfigurasjonsfil for å legge til en rørledning i prosjektet. Du kan opprette det manuelt, men vi anbefaler at du starter med en GitLab-mal som fungerer rett ut av boksen."
-msgid "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "etikettnavn"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index eba24446d6b..80519ed1b7e 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: 2020-12-03 08:18\n"
+"PO-Revision-Date: 2021-01-08 23:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "BranchSwitcherPlaceholder|Zoek branches"
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Annuleren"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 45bd4e556c7..4a507651a88 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: 2020-12-03 08:18\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index ce2d14d994a..e24a195408c 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: 2020-12-03 08:19\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -917,6 +926,27 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1080,9 +1110,15 @@ 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 ""
@@ -1353,28 +1389,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1386,6 +1419,9 @@ 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 ""
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1422,6 +1461,9 @@ 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 ""
@@ -1440,13 +1482,16 @@ 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."
+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."
+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"
@@ -1455,10 +1500,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 ""
@@ -1491,13 +1545,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1539,6 +1596,9 @@ 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 ""
@@ -2134,6 +2194,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3017,6 +3062,9 @@ 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 ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 ""
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Wystąpił błąd podczas aktualizacji komentarza"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3476,7 +3533,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 ""
@@ -3569,7 +3629,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3726,13 +3786,13 @@ msgstr[3] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4027,6 +4087,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4045,12 +4111,18 @@ 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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4088,6 +4163,9 @@ 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 ""
@@ -4134,9 +4212,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,10 +4368,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4317,10 +4392,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4440,12 +4515,21 @@ 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 ""
@@ -4455,13 +4539,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4476,15 +4560,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4524,9 +4602,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,10 +4747,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4924,6 +5035,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5044,12 +5176,12 @@ 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 "Proces Automatyczny DevOps zostanie uruchomiony, jeśli nie zostanie znaleziony alternatywny plik konfiguracji CI."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr ""
@@ -5077,9 +5209,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 ""
@@ -5149,6 +5302,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 ""
@@ -5311,13 +5485,16 @@ 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 were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5872,6 +6055,18 @@ 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 ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7874,6 +8096,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8175,9 +8397,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8241,6 +8460,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8418,45 +8718,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ 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 ""
@@ -9097,9 +9379,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9577,9 +9856,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9589,6 +9865,9 @@ 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 ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10289,6 +10622,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ 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 ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 ""
@@ -11027,9 +11387,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11135,9 +11492,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11273,9 +11627,18 @@ 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 ""
@@ -11390,22 +11753,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 ""
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 ""
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,7 +13587,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13452,9 +13815,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13788,10 +14148,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13815,9 +14181,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,7 +14208,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13878,6 +14241,9 @@ 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 ""
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,13 +15164,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15212,13 +15627,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15230,9 +15645,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15428,7 +15858,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16257,6 +16699,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17452,9 +17912,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 ""
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19849,10 +20432,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20107,10 +20690,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20179,6 +20765,9 @@ 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 ""
@@ -20215,6 +20804,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ 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 ""
@@ -20242,7 +20843,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 ""
@@ -20875,13 +21506,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals from users who make commits to the MR."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ 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 ""
@@ -21163,6 +21803,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 ""
@@ -21493,9 +22139,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 ""
@@ -21685,7 +22334,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21754,9 +22406,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21793,6 +22442,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21982,7 +22643,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,7 +23117,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22723,6 +23384,12 @@ 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 ""
@@ -22741,6 +23408,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23169,6 +23851,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23478,9 +24163,6 @@ msgstr "Wybierz"
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,7 +24205,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Wymagaj od wszystkich użytkowników akceptacji Warunków Usługi i Polityki Prywatności, gdy będą chcieli korzystać z GitLab."
-msgid "Require user password to approve"
+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"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23690,6 +24366,9 @@ msgstr "Metryki odpowiedzi (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Metryki odpowiedzi (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Uruchom nieoznaczone zadania"
-msgid "Runner cannot be assigned to other projects"
-msgstr "Runner nie może być przypisany do innych projektów"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "Runner uruchamia zadania ze wszystkich nieprzypisanych projektów"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "Runner uruchamia zadania ze wszystkich nieprzypisanych projektów w swojej grupie"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "Runner uruchamia zadania z przypisanych projektów"
-
msgid "Runner token"
msgstr "Token robotnika"
@@ -23896,9 +24569,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr "Robotnik nie otrzyma żadnych nowych zadań"
-
msgid "Runners"
msgstr "Robotnicy"
@@ -23908,14 +24578,17 @@ 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 placed on separate users, servers, 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 ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "Liczba Robotników online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,10 +24785,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24127,7 +24806,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24277,6 +24959,9 @@ 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 ""
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25099,6 +25796,9 @@ 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 ""
@@ -25129,10 +25829,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25330,9 +26027,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25767,6 +26467,9 @@ 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 ""
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26346,15 +27058,18 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Rozpoczyna siÄ™ o (UTC)"
+msgid "Starts on"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Określ swoją wiadomość, aby aktywować"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27315,7 +28090,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27330,6 +28105,9 @@ 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] ""
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 ""
@@ -27533,9 +28317,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27824,6 +28602,9 @@ msgstr "Nie ma jeszcze projektów udostępnionych w tej grupie"
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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28079,6 +28866,9 @@ 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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 ""
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,7 +30594,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29728,7 +30609,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,7 +32013,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 ""
@@ -31582,9 +32496,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ 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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32261,9 +33199,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index e8c81aab0ec..2b54b342daa 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: 2020-12-03 08:09\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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 "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)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commits"
+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 "%{strong_start}%{human_size}%{strong_end} Arquivos"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} merges realizados)"
msgid "(%{value}) has already been taken"
msgstr ""
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Nenhuma mudança)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(verificar progresso)"
@@ -1175,29 +1205,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "'Runner' é um processo que executa uma tarefa. Você pode configurar quantos Runners você precisar."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Um template de aplicação console .NET Core customizável para qualquer projeto .NET Code"
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 "Um site Gitbook que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do Gitlab."
+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 "Um site Hexo que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do Gitlab."
+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 "Um site Hugo que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do Gitlab."
+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 "Um site Jekyll que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do Gitlab."
+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 "Um certificado SSL Let's Encrypt não pode ser obtido até que seu domínio seja verificado."
@@ -1208,6 +1235,9 @@ msgstr "Uma conta Let's Encrypt será configurada para esta instalação do GitL
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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 "Um membro da equipe de abusos irá rever a sua avaliação assim que possível."
@@ -1244,6 +1277,9 @@ msgstr "Uma aprovação de merge request é necessária quando um relatório de
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 ""
@@ -1262,13 +1298,16 @@ msgstr "Um novo token de representação foi criado."
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 "Um site HTML simples que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do Gitlab."
+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."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Um modelo pronto para uso com aplicativos Android."
+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 ready-to-go template for use with iOS Swift apps."
-msgstr "Um modelo pronto para uso com aplicativos iOS Swift."
+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 ""
@@ -1292,9 +1334,15 @@ msgstr "Um token seguro que identifica uma requisição de armazenamento externo
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 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 ""
+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 "Um usuário com permissão de escrita no branch de origem selecionou esta opção"
@@ -1313,13 +1361,16 @@ msgstr "Token da API"
msgid "AWS Access Key"
msgstr "Chave de acesso AWS"
-msgid "AWS Access Key. Only required if not using role instance credentials"
+msgid "AWS Access Key. Only required if not using role instance credentials"
msgstr ""
msgid "AWS Secret Access Key"
msgstr "Chave de acesso secreta da AWS"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ msgstr "Acesso negado para sua conta LDAP."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Acesso negado! Por favor, verifique se você pode adicionar chaves de deploy neste repositório."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Data de expiração do acesso"
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr "Ativar runners compartilhados para novos projetos"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Variáveis de ambiente são protegidas por padrão"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr "Todos os branches"
msgid "All changes are committed"
msgstr "Houve commit com todas as mudanças"
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr "Todos os endereços de e-mail serão usados para identificar seus commits."
@@ -2835,6 +2874,9 @@ msgstr "Permitir que proprietários de grupos gerenciem configurações relacion
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que apenas os protocolos selecionados sejam usados para acesso ao Git."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Ocorreu um erro"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Erro ao modificar notificação de assinatura"
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 "Ocorreu um erro ao atualizar o peso do issue"
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Ocorreu um erro ao salvar o status de substituição do LDAP. Por favor, tente novamente."
-
msgid "An error occurred while saving assignees"
msgstr "Erro ao salvar assignees"
@@ -3267,6 +3312,9 @@ msgstr "Ocorreu um erro ao desinscrever às notificações."
msgid "An error occurred while updating approvers"
msgstr "Ocorreu um erro ao atualizar os aprovadores"
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3276,6 +3324,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Ocorreu um erro durante a atualização do comentário"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,7 +3345,7 @@ msgstr "Ocorreu um erro. Tente novamente."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 "Um issue pode ser um bug, um afazer ou uma solicitação de recurso que precisa ser discutida em um projeto. Além disso, os issues são pesquisáveis e filtráveis."
+msgid "An issue title is required"
+msgstr ""
+
msgid "An unauthenticated user"
msgstr ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,15 +3590,15 @@ msgstr[1] "%{count} aprovações obrigatórias de %{membersCount}"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Aprovadores"
msgid "ApprovalRule|Name"
msgstr "Nome"
-msgid "ApprovalRule|No. approvals required"
-msgstr "No. de aprovações requeridas"
-
msgid "ApprovalRule|Rule name"
msgstr "Nome da regra"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr "Tem certeza de que deseja excluir este %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "Tem certeza de que deseja excluir este painel?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Tem certeza de que deseja excluir este dispositivo? Esta ação não pode ser desfeita."
@@ -3835,6 +3889,12 @@ msgstr "Atribuir etiquetas"
msgid "Assign milestone"
msgstr "Atribuir marco"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Atribua alguns issues a este marco."
@@ -3853,12 +3913,18 @@ msgstr "Atribuir-se a essa issue"
msgid "Assigned %{assignee_users_sentence}."
msgstr ""
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Problemas Atribuídos"
msgid "Assigned Merge Requests"
msgstr "Merge requests com responsável"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Atribuído a mim"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Responsável"
@@ -3894,6 +3963,9 @@ 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 "Pelo menos uma aprovação de um proprietário do código é necessária para alterar arquivos que coincidem com as respectivas regras CODEOWNER."
@@ -3938,9 +4010,6 @@ msgstr "Eventos de Auditoria"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr "Eventos de auditoria é uma maneira de acompanhar eventos importantes que aconteceram no GitLab."
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,12 +4166,12 @@ msgstr "Cancelar automaticamente os pipelines redundantes pendentes"
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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr ""
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Documentação de auto DevOps"
@@ -4121,10 +4190,13 @@ msgstr "Saiba mais em %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr "Gerenciamento automático de certificado usando Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Cor do plano de fundo"
msgid "Badges"
msgstr "Selos"
-msgid "Badges|A new badge was added."
-msgstr "Novo selo adicionado."
-
msgid "Badges|Add badge"
msgstr "Novo selo"
@@ -4244,12 +4313,21 @@ msgstr "URL da imagem do selo"
msgid "Badges|Badge image preview"
msgstr "Pré-visualização da imagem do selo"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "Apagar selo?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "Erro ao apagar selo, por favor, tente novamente."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Selo de grupo"
@@ -4259,15 +4337,15 @@ msgstr "Link"
msgid "Badges|Name"
msgstr ""
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "Sem imagem"
msgid "Badges|No image to preview"
msgstr "Sem imagem para pré-visualizar"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Por favor, preencha um URL válido"
-
msgid "Badges|Project Badge"
msgstr "Selo de projeto"
@@ -4280,15 +4358,12 @@ msgstr "Salvar alterações"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Erro ao salvar selo, por favor, cheque os URLs digitados e tente novamente."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "As %{docsLinkStart}variáveis%{docsLinkEnd} suportadas pelo GitLab: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "O selo foi apagado."
-msgid "Badges|The badge was saved."
-msgstr "O selo foi salvo."
-
msgid "Badges|This group has no badges"
msgstr "Esse grupo não tem selos"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Seus selos"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "por exemplo, %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "O arquivo Balsamiq não pôde ser carregado."
@@ -4328,9 +4400,6 @@ msgstr "Você precisa configurar etiquetas de revisão automáticas e um gatilho
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Cuidado. Alterar o namespace do projeto pode ter efeitos colaterais indesejados."
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,12 +4543,21 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
-msgid "Board scope"
-msgstr "Escopo do painel"
-
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "O escopo do painel afeta quais issues são exibidas para qualquer um que visite este painel"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
msgid "Boards"
msgstr "Painéis"
@@ -4525,6 +4609,30 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver escopo"
+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 ""
@@ -4555,9 +4663,6 @@ msgstr "Nome da branch"
msgid "Branch not loaded - %{branchId}"
msgstr "Branch não carregado - %{branchId}"
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Procurar por branches"
@@ -4726,6 +4831,24 @@ msgstr "Embutido"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr "CI/CD para um repositório externo"
msgid "CI/CD settings"
msgstr "Configurações de CI/CD"
-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."
+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"
@@ -4846,12 +4972,12 @@ msgstr "Estratégia de deploy"
msgid "CICD|Jobs"
msgstr "Tarefas"
+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 "O pipeline de Auto DevOps será executado se nenhum arquivo de configuração de IC alternativo for encontrado."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr "grupo habilitado"
@@ -4879,9 +5005,6 @@ msgstr "URL de Retorno"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Pode substituir aprovadores e aprovações necessárias por merge request"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Cancelar"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr "Cancelando pré-visualização"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Não pode ser feito o merge automaticamente"
@@ -5083,15 +5233,33 @@ msgstr "Pick para um branch"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Reverter no branch"
+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 "Cherry-pick"
msgid "ChangeTypeAction|Revert"
msgstr "Reverter"
+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 "Isso criará um novo commit para reverter as mudanças existentes."
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr ""
@@ -5113,13 +5281,16 @@ msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr ""
+msgid "Changes saved."
+msgstr ""
+
msgid "Changes suppressed. Click to show."
msgstr "Alterações suprimidas. Clique para mostrar."
msgid "Changes the title to \"%{title_param}\"."
msgstr "Altera o título para \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Escolha um modelo..."
msgid "Choose a type..."
msgstr "Escolha um tipo..."
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr "Clonar"
msgid "Clone repository"
msgstr "Clonar repositório"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "Clonar com %{http_label}"
@@ -5674,6 +5851,18 @@ msgstr "Clonar com KRB5"
msgid "Clone with SSH"
msgstr "Clonar com SSH"
+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 "Fechar"
@@ -6781,12 +6970,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "Proprietários de código"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr ""
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "Parabéns! Você ativou a autenticação de dois fatores!"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Conectar"
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,13 +8120,10 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
-msgstr "Crie um issue. Os Issues são criados para cada alerta acionado."
-
-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."
+msgid "Create an incident. Incidents are created for each alert triggered."
msgstr ""
-msgid "Create board"
+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"
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr "Criar novo branch"
@@ -8033,6 +8246,84 @@ msgstr "Tag"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "criar um token de acesso pessoal"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Feito"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Branch atual"
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr "Primeiro dia da semana padrão em calendários e selecionadores de data.
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "Modelo de issue padrão"
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "Padrão: Mapeie uma ID de conta do FogBugz para um nome completo"
@@ -8839,6 +9112,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Defina um padrão personalizado utilizando a sintaxe do cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr "Excluir comentário"
@@ -9355,9 +9628,6 @@ msgstr "Decrescente"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "Descrição"
@@ -9367,6 +9637,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "Descrição analisada com %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
msgid "Description template"
msgstr ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,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 and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr "Cada runner pode estar em um dos seguintes estados:"
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr "Editar aplicativo"
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr "Editar comentário"
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr "Editar chave de deploy pública"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr "E-mails"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ msgstr ""
msgid "Enable and configure Prometheus metrics."
msgstr "Ativar e configurar métricas do Prometheus."
+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 "Ativar controle de classificação usando um serviço externo"
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr "Ativar autenticação de dois fatores"
msgid "Enable usage ping"
msgstr "Ativar dados de uso"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "Termina em (UTC)"
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr "Insira o domínio"
@@ -10485,6 +10827,9 @@ msgstr "Digite o título do merge request"
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 ""
@@ -10626,6 +10971,9 @@ msgstr "Implantar para..."
msgid "Environments|Deployment"
msgstr "Deploy"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 "Atualizado"
@@ -10803,9 +11157,6 @@ msgstr "Como posso resolver isso?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Mais informações"
-
msgid "Epics|Remove epic"
msgstr "Remover épico"
@@ -10911,9 +11262,6 @@ msgstr "Erro ao recuperar gráfico de rede."
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr "Erro ao obter projetos"
-
msgid "Error fetching refs"
msgstr "Erro ao recuperar refs"
@@ -11049,9 +11397,18 @@ 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 "Ativo"
@@ -11166,23 +11523,23 @@ msgstr "Todos podem contribuir"
msgid "Everything on your to-do list is marked as done."
msgstr "Tudo na sua lista de afazeres está marcado como concluído."
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
+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 "Tudo o que você precisa para criar um site do GitLab Pages usando o GitBook."
+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 "Tudo o que você precisa para criar um site do GitLab Pages usando o Hexo."
+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 "Tudo o que você precisa para criar um site do GitLab Pages usando o Hugo."
+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 "Tudo o que você precisa para criar um site do GitLab Pages usando o Jekyll."
+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 "Tudo o que você precisa para criar um site do GitLab Pages usando HTML simples."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
msgid "Evidence collection"
msgstr ""
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr "Membros e grupos existentes"
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ msgstr ""
msgid "Failed to apply commands."
msgstr "Falha ao aplicar comandos."
+msgid "Failed to assign a reviewer because no user was found."
+msgstr ""
+
msgid "Failed to assign a user because no user was found."
msgstr "Falha ao associar um usuário porque nenhum usuário foi encontrado."
@@ -11421,6 +11781,12 @@ msgstr "Erro ao alterar o proprietário"
msgid "Failed to check related branches."
msgstr "Falha ao procurar por branches relacionadas."
+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 ""
@@ -11448,9 +11814,6 @@ msgstr "Falha ao criar recursos"
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr "Falha ao fazer deploy para"
@@ -11601,6 +11964,9 @@ msgstr "Falha ao atualizar o branch!"
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr "O Feature flag não foi removido."
msgid "Feature flag was successfully removed."
msgstr "A feature flag foi removida com sucesso."
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "Feature flags"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "A feature flag %{name} será removido. Você tem certeza?"
@@ -11768,16 +12128,13 @@ msgstr "Feature flags permitem que você configure o seu código em diferentes v
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "Começar a usar feature flags"
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Filtro"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrar por %{issuable_type} que estão atualmente fechados."
@@ -12026,12 +12389,6 @@ msgstr "Filtrar por nome de marco"
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Localizar por caminho"
-msgid "Find existing members by name"
-msgstr "Encontre membros existentes por nome"
-
msgid "Find file"
msgstr "Localizar arquivo"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr "Finalizado"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr "Forks"
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "Erros encontrados em seu %{gitlab_ci_yml}:"
@@ -12701,6 +13055,12 @@ msgstr "Obter gratuitamente uma instância de revisão"
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 "Comece com o rastreamento de erros"
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,8 +13355,8 @@ msgstr "Configurações de notificação global"
msgid "Go Back"
msgstr "Voltar"
-msgid "Go Micro is a framework for micro service development."
-msgstr "Go Micro é um framework para desenvolvimento de microsserviços."
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
msgid "Go back"
msgstr "Voltar"
@@ -13226,9 +13583,6 @@ msgstr "Avatar do grupo"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "Descrição do grupo"
-
msgid "Group description (optional)"
msgstr "Descrição do grupo (opcional)"
@@ -13562,11 +13916,17 @@ 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 "Modelos de projetos personalizados"
-msgid "GroupSettings|Customize your group badges."
-msgstr "Personalize os selos do seu grupo."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "Saiba mais sobre os selos."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ msgstr "Nenhum grupo encontrado"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para cada projeto no grupo."
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr "Manutenção iniciada com sucesso"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "Como funciona"
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "Importação em andamento"
@@ -14269,6 +14668,9 @@ msgstr "Importar repositórios do GitHub"
msgid "Import repository"
msgstr "Importar repositório"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "Melhore os painéis com GitLab Enterprise Edition."
+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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,14 +14922,14 @@ msgstr ""
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
msgstr "Inclui objetos LFS. Pode ser substituído individualmente por grupo ou por projeto. 0 para ilimitado."
-msgid "Includes an MVC structure to help you get started."
-msgstr "Inclui uma estrutura MVC para ajudar você a começar."
+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 "Inclui uma estrutura MVC, um Gemfile, um Rakefile e muito mais para ajudar você a começar."
+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 "Inclui uma estrutura MVC, mvnw e um pom.xml para ajudar você a começar."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
msgid "Incoming email"
msgstr ""
@@ -14542,6 +14943,9 @@ msgstr "Opções incompatíveis definidas!"
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr "Arquivo de configuração de Insights inválido detectado"
@@ -14976,15 +15383,15 @@ msgstr ""
msgid "Invite"
msgstr "Convidar"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "Convidar \"%{trimmed}\" por e-mail"
msgid "Invite Members"
msgstr ""
-msgid "Invite another teammate"
-msgstr ""
-
msgid "Invite group"
msgstr "Convidar grupo"
@@ -14994,9 +15401,6 @@ msgstr "Convidar membro"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Eventos de issue"
@@ -15192,8 +15614,8 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
-msgstr "Modelo de issue (opcional)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
msgstr ""
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Eventos para %{noteable_model_name} estão desabilitados."
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Se diferente do URL da Web"
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr "Visto pela última vez"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "Aprenda GitLab"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "Aprenda como %{link_start}contribuir para os modelos embutidos%{link_end}"
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr "Saiba mas sobre aprovações."
-
msgid "Learn more about custom project templates"
msgstr "Saiba mais sobre os modelos de projetos personalizados"
@@ -16019,6 +16453,9 @@ msgstr "Saiba mais em"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "documentação de agendamento de pipeline"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Sair"
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr "Nível máximo de acesso"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Aprovações de merge request"
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Merge requests"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "A tela de Merge request é um lugar para propor mudanças em um projeto e discutir essas mudanças com outros"
@@ -17200,9 +17652,15 @@ 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 ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr "Espelhar usuário"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "Repositórios espelhados"
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "Múltiplos painéis"
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Novo arquivo"
msgid "New group"
msgstr "Novo grupo"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr "Nenhuma branch encontrada"
msgid "No changes"
msgstr "Sem alterarções"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr "Não disponível para projetos privados"
msgid "Not available for protected branches"
msgstr "Não disponível para Branches protegidas"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Não confidencial"
@@ -18821,6 +19288,9 @@ msgstr "Ainda não está pronto. Tente mais tarde."
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Páginas"
@@ -19843,11 +20418,14 @@ msgstr ""
msgid "Pause"
msgstr "Pausar"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
-msgstr "Runners pausados não aceitam novas tarefas"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "Pendente"
@@ -19915,6 +20493,9 @@ msgstr "Permissões, LFS, 2FA"
msgid "Personal Access Token"
msgstr "Token de Acesso Pessoal"
+msgid "Personal Access Token prefix"
+msgstr ""
+
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
@@ -19951,6 +20532,9 @@ msgstr "Agendamentos da Pipeline"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ msgstr "Gatilho de pipeline"
msgid "Pipeline: %{status}"
msgstr "Pipeline: %{status}"
+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 ""
@@ -19978,7 +20571,7 @@ msgstr "Taxa de sucesso:"
msgid "PipelineCharts|Successful:"
msgstr "Sucesso:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ msgstr ""
msgid "Pipelines|Editor"
msgstr ""
+msgid "Pipelines|Get started with CI/CD"
+msgstr ""
+
msgid "Pipelines|Get started with Pipelines"
msgstr "Saiba como funcionam as pipelines"
+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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "Carregando Pipelines"
@@ -20149,6 +20751,18 @@ msgstr "Atualmente não há pipelines."
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."
+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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 "Por favor, crie uma senha para sua nova conta."
@@ -20401,6 +21021,9 @@ msgstr "Por favor, insira um número maior que %{number} (das configurações do
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 "Digite um número válido"
@@ -20611,15 +21234,18 @@ msgstr "Pressione %{key}-C para copiar"
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Impede a adição de novos membros ao projeto pertencentes a este grupo"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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 "Impede a adição de novos membros ao projeto pertencentes a este grupo"
+
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr "Primário"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "Priorizar"
@@ -20797,6 +21426,9 @@ msgstr ""
msgid "Profiles|@username"
msgstr "@nomedeusuário"
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Conta agendada para remoção."
@@ -20899,6 +21531,9 @@ 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."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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"
@@ -21229,9 +21867,6 @@ msgstr "Nome do projeto"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ msgstr "Todas as discussões devem ser resolvidas"
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 "Resolver automaticamente discussões de diff do merge request quando elas se tornam desatualizadas"
@@ -21421,8 +22062,8 @@ msgstr "Contate um administrador para alterar essa configuração."
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
-msgstr "Personalize os selos do seu projeto."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr ""
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "Cada merge cria um commit de merge"
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "Saiba mais sobre os selos."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Apenas para commits assinados pode-se fazer push para este repositório."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 "Quando conflitos surgem, o usuários tem a opção de fazer rebase"
+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 ""
@@ -21661,9 +22314,6 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21718,7 +22371,7 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr "Atividade recente do projeto"
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "Pesquisas recentes"
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr "Remover Runner"
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr "Remover prioridade"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "Removido %{type} com id %{id}"
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr "Renomear pasta"
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Repositório"
@@ -23204,9 +23881,6 @@ msgstr "Selecionar"
msgid "Request Access"
msgstr "Solicitar acesso"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,8 +23923,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Exija que todos os usuários aceitem Termos de Serviço e Política de Privacidade quando acessarem o GitLab."
-msgid "Require user password to approve"
-msgstr "Exigir senha do usuário para aprovar"
+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 "Exigir que os usuários comprovem a propriedade de domínios personalizados"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr "Resposta"
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr "A resposta não incluiu `service_desk_address`"
@@ -23412,6 +24080,9 @@ msgstr "Métricas de resposta (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Métricas de resposta (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "Reiniciar terminal"
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Rodar tarefas sem tags"
-msgid "Runner cannot be assigned to other projects"
-msgstr "Runner não pode ser atribuído a outros projetos"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "O runner executa tarefas de todos os projetos não atribuídos"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "O runner executa tarefas de todos os projetos não atribuídos em seu grupo"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "O runner executa tarefas de projetos atribuídos"
-
msgid "Runner token"
msgstr "Token de runner"
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr "O runner não receberá nenhuma tarefa nova"
-
msgid "Runners"
msgstr "Runners"
@@ -23626,14 +24288,17 @@ 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 placed on separate users, servers, even on your local machine."
-msgstr "Executores podem ser alocados em usuários separados, servidores, até mesmo em sua máquina local."
+msgid "Runners can be:"
+msgstr ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "Executores online no momento: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ msgstr "Executando…"
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 ""
@@ -23761,9 +24435,6 @@ msgstr "Chave SSH pública"
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr "Agendado"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,8 +24516,8 @@ msgstr "Agendando pipelines"
msgid "Scope"
msgstr "Escopo"
-msgid "Scoped issue boards"
-msgstr "Painéis de escopo"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr ""
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Procurar usuários"
@@ -23995,6 +24669,9 @@ msgstr "Merge requests que eu criei"
msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "Merge requests atribuídas a mim"
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
msgid "SearchAutocomplete|in all GitLab"
msgstr "em todo o GitLab"
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr "Separe os tópicos com vírgulas."
msgid "September"
msgstr "Setembro"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ msgstr ""
msgid "Service Desk"
msgstr "Balcão de Atendimento"
+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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr "Defina um modelo padrão para descrições de issues."
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr "Configurações"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr "Mostrar todas as atividades"
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Mostrar a versão mais recente"
@@ -25457,6 +26149,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "Alguém editou este merge request ao mesmo tempo que você. Por favor, atualize a página para ver as alterações."
+msgid "Something went wrong"
+msgstr ""
+
msgid "Something went wrong on our end"
msgstr "Algo deu errado do nosso lado"
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr "Algo deu errado ao recuperar a lista de %{listType}"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Algo deu errado ao buscar os comentários. Por favor, tente novamente."
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr "Algo deu errado, não foi possível obter os projetos"
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,15 +26740,18 @@ 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 "State your message to activate"
msgstr "Regitre sua mensagem para ativar"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "Sistema"
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,8 +27766,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
-msgstr "Obrigado! Não me mostre isso novamente"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr "O tamanho máximo do arquivo é de 200KB."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ msgstr "Não há projetos compartilhados com esse grupo ainda"
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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ msgstr "Esta instância do GitLab ainda não fornece nenhum Runner compartilhado
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 ""
@@ -28056,6 +28838,9 @@ msgstr "Isto significa que você não pode entregar código até que crie um rep
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 ""
@@ -28140,6 +28925,15 @@ 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 "Este Runner somente será executado em Pipelines acionados em branches protegidos"
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ msgstr "Visão em árvore"
msgid "Trending"
msgstr "Mais populares"
+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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr "Desprogramar tarefa"
msgid "Unstar"
msgstr "Desmarcar como favorito"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "Cancelar inscrição"
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,8 +30260,8 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "Atualize o nome do seu grupo, descrição, avatar e visibilidade."
-msgid "Update your project name, topics, description and avatar."
-msgstr "Atualize o nome do seu projeto, tópicos, a descrição e o avatar."
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr ""
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr "Aprimore seu plano para ativar os Webhooks de Grupo."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "Faça upgrade de plano para melhorar os painéis."
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr "Descrição"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projeto"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Precisa visualizar os dados? Solicite acesso ao administrador."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 "Detectamos spam potencial no %{humanized_resource_name}. Por favor, resolva o reCAPTCHA para continuar."
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ msgstr "Quando:"
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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 "Você pode resolver o conflito de merge usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}"
@@ -31252,9 +32156,6 @@ msgstr "Você pode ver suas contas de bate-papo."
msgid "You can set up as many Runners as you need to run your jobs."
msgstr ""
-msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr "Você pode configurar tarefas para só usar os runners com tags específicas. Separe tags com vírgulas."
-
msgid "You can specify notification level per group or per project."
msgstr ""
@@ -31276,6 +32177,9 @@ msgstr "Você não pode se passar por um usuário que não pode fazer login"
msgid "You cannot impersonate an internal user"
msgstr "Você não pode se passar por um usuário interno"
+msgid "You cannot make this a shared runner."
+msgstr ""
+
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
msgstr ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "Você não tem as permissões corretas para substituir as configurações de sincronização do grupo LDAP."
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Você deve ter o acesso de mantenedor para apagar um bloqueio"
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr "nome da branch"
msgid "by"
msgstr "por"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 "%{linkStartTag}Saiba mais sobre Verificação de Container %{linkEndTag}"
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Todos os projetos"
@@ -32169,6 +33109,9 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Houve um erro ao reverter o descarte. Por favor, tente novamente."
+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] "Usado por %{packagesString}"
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] "merge request"
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 0e840533474..9abb1a593e7 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: 2020-12-03 08:19\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Envio"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Envios"
+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 "%{strong_start}%{human_size}%{strong_end} Ficheiros"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} mesclado)"
msgid "(%{value}) has already been taken"
msgstr ""
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Sem alterações)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(verificar progresso)"
@@ -1175,29 +1205,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "Um 'Executador' é um processo que executa um trabalho. Podes configurar tantos 'Executadores' quantos precisares."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Um .NET Core de um modelo da aplicação de consola, personalizável para qualquer projeto .NET Core"
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 "Um site GitBook que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
+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 "Um site Hexo que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
+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 "Um site Hugo que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
+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 "Um site Jekyll que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
+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 ""
@@ -1208,6 +1235,9 @@ msgstr "Uma conta Vamos Criptografar será configurada para esta instalação no
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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 "Um membro da equipa de abuso irá, rever a tua denúncia assim que possível."
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ msgstr "Um novo token de representação foi criado."
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 "Um site HTML simples que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
+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."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Um modelo pronto para uso para usar em aplicações Android."
+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 ready-to-go template for use with iOS Swift apps."
-msgstr "Um modelo pronto para uso para usar em aplicações iOS Swift."
+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 ""
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 "Um utilizador com permissão de escrita ao ramo de origem selecionado para esta opção"
@@ -1313,13 +1361,16 @@ msgstr "Token API"
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ msgstr "Acesso negado à tua conta LDAP."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Acesso negado! Por favor, verifica se podes adicionar chaves de implantação para este repositório."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Data de expiração do acesso"
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr "Ativar executadores compartilhados aos novos projetos"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Variáveis de ambiente são protegidas por padrão"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr "Todas as alterações foram enviadas"
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr "Todos os endereços de email serão usados para identificar os teus envios."
@@ -2835,6 +2874,9 @@ msgstr "Permitir que proprietários de grupos gerenciem as definições relacion
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir apenas, que os protocolos selecionados sejam usados para acessar o Git."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Ocorreu um erro"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Ocorreu um erro ao alternar a notificação de assinatura"
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 "Ocorreu um erro ao atualizar o peso do problema"
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Ocorreu um erro ao guardar o estado de sobreposição do LDAP. Por favor, tenta novamente."
-
msgid "An error occurred while saving assignees"
msgstr "Ocorreu um erro ao guardar destinatários"
@@ -3267,6 +3312,9 @@ msgstr "Ocorreu um erro ao cancelar a assinatura das notificações."
msgid "An error occurred while updating approvers"
msgstr "Ocorreu um erro ao atualizar aprovadores"
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3276,6 +3324,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Ocorreu um erro ao atualizar o comentário"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,7 +3345,7 @@ msgstr "Ocorreu um erro. Por favor, tenta novamente."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 "Um problema pode ser uma falha (bug), um \"todo\" ou um pedido de recurso que precisa de ser discutido num projeto. Além disso, os problemas são pesquisáveis e filtráveis."
+msgid "An issue title is required"
+msgstr ""
+
msgid "An unauthenticated user"
msgstr ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,15 +3590,15 @@ msgstr[1] "%{count} aprovações obrigatórias de %{membersCount}"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Nome"
-msgid "ApprovalRule|No. approvals required"
-msgstr "Nº de aprovações obrigatórias"
-
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Tens a certeza de que desejas apagar este dispositivo? Esta ação não pode ser desfeita."
@@ -3835,6 +3889,12 @@ msgstr "Atribuir etiquetas"
msgid "Assign milestone"
msgstr "Atribuir objetivo"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Atribuir alguns problemas para este objetivo."
@@ -3853,12 +3913,18 @@ msgstr "Atribuir-te esta tarefa"
msgid "Assigned %{assignee_users_sentence}."
msgstr ""
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Problemas Atribuídos"
msgid "Assigned Merge Requests"
msgstr "Pedidos de Mesclagem Atribuídos"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Atribuído a mim"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 "Pelo menos uma aprovação de um código proprietário é necessário para alterar ficheiros que coincidem com as respetivas regras de CODEOWNER."
@@ -3938,9 +4010,6 @@ msgstr "Eventos de Auditoria"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,12 +4166,12 @@ msgstr "Cancelar, automaticamente, os pipelines redundantes pendentes"
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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr ""
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Documentação do Auto DevOps"
@@ -4121,10 +4190,13 @@ msgstr "Saber mais no %{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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr "Gestão automática de certificados ao usar Vamos Criptografar"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Cor de fundo"
msgid "Badges"
msgstr "Emblemas"
-msgid "Badges|A new badge was added."
-msgstr "Foi adicionado um novo emblema."
-
msgid "Badges|Add badge"
msgstr "Adicionar emblema"
@@ -4244,12 +4313,21 @@ msgstr "URL da imagem do emblema"
msgid "Badges|Badge image preview"
msgstr "Pré-visualização da imagem do emblema"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "Apagar emblema?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "Erro ao apagar emblema, por favor, tenta novamente."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Emblema do grupo"
@@ -4259,15 +4337,15 @@ msgstr "Link"
msgid "Badges|Name"
msgstr ""
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "Sem imagem de emblema"
msgid "Badges|No image to preview"
msgstr "Sem imagem para pré-visualizar"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Por favor, preenche uma URL válida"
-
msgid "Badges|Project Badge"
msgstr "Emblema do Projeto"
@@ -4280,15 +4358,12 @@ msgstr "Guardar alterações"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Erro ao guardar o emblema, por favor, verifica os URLs introduzidos e tenta novamente."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "As %{docsLinkStart}variáveis%{docsLinkEnd} suportadas pelo GitLab: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "O emblema foi apagado."
-msgid "Badges|The badge was saved."
-msgstr "O emblema foi guardado."
-
msgid "Badges|This group has no badges"
msgstr "Este grupo não tem emblemas"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Os teus emblemas"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "por exemplo, %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "O ficheiro Balsamiq não pôde ser carregado."
@@ -4328,9 +4400,6 @@ msgstr "Deves configurar uma etiqueta de revisão automático e um disparador de
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Tem cuidado. Alterar o espaço de nomes do projeto pode ter efeitos secundários não intencionais."
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr "Blogue"
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver escopo"
+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 ""
@@ -4555,9 +4663,6 @@ msgstr "Nome do ramo"
msgid "Branch not loaded - %{branchId}"
msgstr "Ramo não carregado - %{branchId}"
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Procurar por ramos"
@@ -4726,6 +4831,24 @@ msgstr "Incorporado"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr "CI/CD para um repositório externo"
msgid "CI/CD settings"
msgstr "Definições de CI/CD"
-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."
+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"
@@ -4846,12 +4972,12 @@ msgstr "Estratégia de implantação"
msgid "CICD|Jobs"
msgstr "Trabalhos"
+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 "A pipeline de Auto DevOps será executada, se nenhum ficheiro de configuração de IC alternativo, for encontrado."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr "grupo ativado"
@@ -4879,9 +5005,6 @@ msgstr "URL de Resposta"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Pode substituir aprovadores e aprovações requeridas por pedido de mesclagem"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Cancelar"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Não pode ser mesclado automaticamente"
@@ -5083,15 +5233,33 @@ msgstr "Escolher no ramo"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Reverter no ramo"
+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 "Cherry-pick"
msgid "ChangeTypeAction|Revert"
msgstr "Reverter"
+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 "Isto irá criar um envio para reverter as alterações existentes."
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
msgid "Changed assignee(s)."
msgstr ""
@@ -5113,13 +5281,16 @@ msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr ""
+msgid "Changes saved."
+msgstr ""
+
msgid "Changes suppressed. Click to show."
msgstr "Alterações suprimidas Clica para mostrar."
msgid "Changes the title to \"%{title_param}\"."
msgstr "Altera o título para \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Escolhe um modelo..."
msgid "Choose a type..."
msgstr "Escolhe um tipo..."
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr "Clone"
msgid "Clone repository"
msgstr "Clonar repositório"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "Clonar com %{http_label}"
@@ -5674,6 +5851,18 @@ msgstr "Clonar com KRB5"
msgid "Clone with SSH"
msgstr "Clonar com SSH"
+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 "Fechar"
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr "Filtrar por nome de objetivo"
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "Erros encontrados no teu %{gitlab_ci_yml}:"
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr "Definições globais de notificação"
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ 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 ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ 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 license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Deves ter acesso de responsável para forçar o apagamento de um bloqueio"
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr "nome do ramo"
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index dbc70c40e91..cab7261fb8a 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: 2020-12-03 08:07\n"
+"PO-Revision-Date: 2021-01-08 22:54\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -415,12 +415,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -850,6 +859,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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] ""
+msgstr[2] ""
+
+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] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1009,9 +1036,15 @@ 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 ""
@@ -1264,28 +1297,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1297,6 +1327,9 @@ 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 ""
@@ -1324,6 +1357,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1333,6 +1369,9 @@ 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 ""
@@ -1351,13 +1390,16 @@ 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."
+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."
+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"
@@ -1366,10 +1408,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1381,9 +1426,15 @@ 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 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 ""
+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 ""
@@ -1402,13 +1453,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1450,6 +1504,9 @@ 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 ""
@@ -2044,6 +2101,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2053,6 +2113,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2530,9 +2593,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2596,15 +2656,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2632,9 +2686,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2704,10 +2755,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2773,12 +2824,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2863,9 +2908,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2926,6 +2968,9 @@ 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 ""
@@ -3064,7 +3109,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3100,6 +3145,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ 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 ""
@@ -3334,9 +3385,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3358,6 +3406,9 @@ 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 ""
@@ -3367,6 +3418,9 @@ 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 ""
@@ -3385,7 +3439,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3400,6 +3454,9 @@ 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 ""
@@ -3478,7 +3535,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3631,13 +3688,13 @@ msgstr[2] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3658,6 +3715,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3760,9 +3820,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3931,6 +3988,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3949,12 +4012,18 @@ 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 ""
@@ -3967,6 +4036,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3991,6 +4063,9 @@ 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 ""
@@ -4036,9 +4111,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4195,10 +4267,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4219,10 +4291,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4264,7 +4339,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4327,9 +4402,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4342,12 +4414,21 @@ 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 ""
@@ -4357,13 +4438,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4378,15 +4459,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4399,9 +4477,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4426,9 +4501,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4513,22 +4585,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4567,10 +4645,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4624,6 +4711,30 @@ 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 ""
@@ -4654,9 +4765,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4825,6 +4933,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4918,7 +5044,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4945,10 +5074,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4978,9 +5107,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5029,6 +5155,30 @@ 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 ""
@@ -5050,6 +5200,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5182,15 +5335,33 @@ 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|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 ""
@@ -5212,13 +5383,16 @@ 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 were successfully made."
+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}."
@@ -5230,9 +5404,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5500,9 +5671,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5761,6 +5938,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5773,6 +5953,18 @@ 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 ""
@@ -6880,10 +7072,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7156,6 +7348,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7285,6 +7495,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7375,13 +7588,13 @@ msgstr[2] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7390,18 +7603,42 @@ 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 policy:"
+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 ""
@@ -7429,9 +7666,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7441,9 +7675,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7468,6 +7699,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7486,9 +7720,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7564,16 +7795,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7609,12 +7834,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7771,6 +7990,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8005,15 +8227,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8071,9 +8290,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8137,6 +8353,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8230,6 +8524,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8314,45 +8611,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8599,6 +8869,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8665,6 +8938,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8713,6 +8992,9 @@ 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 ""
@@ -8920,18 +9202,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8944,6 +9220,9 @@ 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 ""
@@ -8992,9 +9271,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9466,9 +9742,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9478,6 +9751,9 @@ 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 ""
@@ -9679,22 +9955,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9703,6 +10018,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9712,18 +10030,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9994,6 +10327,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10078,9 +10414,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10135,9 +10468,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10177,6 +10507,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10204,12 +10537,18 @@ 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 ""
@@ -10243,6 +10582,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10312,10 +10654,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10396,6 +10738,9 @@ 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 ""
@@ -10465,6 +10810,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10480,9 +10828,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10516,6 +10861,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10552,9 +10900,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10597,6 +10942,9 @@ 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 ""
@@ -10738,6 +11086,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10855,6 +11206,12 @@ 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 ""
@@ -10915,9 +11272,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11023,9 +11377,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11161,9 +11512,18 @@ 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 ""
@@ -11278,22 +11638,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11332,9 +11692,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11374,6 +11731,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11515,6 +11875,9 @@ 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 ""
@@ -11533,6 +11896,12 @@ 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 ""
@@ -11560,9 +11929,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11713,6 +12079,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11773,9 +12142,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11869,9 +12235,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11881,16 +12244,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12004,6 +12364,9 @@ 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 ""
@@ -12106,6 +12469,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12139,12 +12505,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12196,9 +12556,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12217,6 +12574,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12346,9 +12706,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12814,6 +13171,12 @@ 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 ""
@@ -12889,9 +13252,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13111,7 +13471,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13339,9 +13699,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13675,10 +14032,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13702,9 +14065,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13732,7 +14092,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13765,6 +14125,9 @@ 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 ""
@@ -13843,6 +14206,9 @@ 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 ""
@@ -13852,22 +14218,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14089,6 +14479,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14263,6 +14656,9 @@ 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 ""
@@ -14338,6 +14734,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14386,6 +14788,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14446,19 +14851,16 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14482,6 +14884,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14638,13 +15043,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14659,6 +15064,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14908,6 +15316,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14992,9 +15406,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15094,13 +15505,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15112,9 +15523,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15184,6 +15592,24 @@ 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 ""
@@ -15241,9 +15667,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15295,6 +15718,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15310,7 +15736,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15349,7 +15775,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15469,6 +15895,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15553,6 +15982,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15577,19 +16009,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16015,6 +16447,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16069,9 +16504,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16111,9 +16552,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16138,6 +16576,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16483,6 +16924,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16570,6 +17014,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16807,6 +17254,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16828,6 +17278,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16969,6 +17422,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17101,9 +17560,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17164,6 +17620,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17179,9 +17638,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17326,9 +17782,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17344,9 +17806,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17911,9 +18370,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18097,9 +18553,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18232,6 +18685,9 @@ 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 ""
@@ -18244,6 +18700,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18253,6 +18712,9 @@ 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 ""
@@ -18550,6 +19012,12 @@ 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 ""
@@ -18688,7 +19156,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18934,6 +19402,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18952,6 +19423,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19189,6 +19663,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19210,27 +19687,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19246,9 +19801,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19267,6 +19834,15 @@ 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 ""
@@ -19561,6 +20137,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19570,10 +20149,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19591,7 +20167,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19651,6 +20227,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19717,10 +20296,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19822,7 +20407,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19834,18 +20419,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19975,10 +20554,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20047,6 +20629,9 @@ 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 ""
@@ -20083,6 +20668,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20095,6 +20683,15 @@ 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 ""
@@ -20110,7 +20707,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20215,9 +20812,15 @@ 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 ""
@@ -20233,6 +20836,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20281,6 +20887,18 @@ 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 ""
@@ -20296,6 +20914,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20509,6 +21130,9 @@ 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 ""
@@ -20533,6 +21157,9 @@ 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 ""
@@ -20743,13 +21370,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20761,7 +21391,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20794,6 +21424,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20929,6 +21562,9 @@ 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 ""
@@ -21031,6 +21667,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21079,6 +21718,9 @@ 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 ""
@@ -21361,9 +22003,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21520,12 +22159,18 @@ 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 ""
@@ -21553,7 +22198,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21574,6 +22219,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21622,9 +22270,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21661,6 +22306,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21769,12 +22417,21 @@ 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|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 ""
@@ -21793,9 +22450,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21808,6 +22462,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21850,7 +22507,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22291,7 +22948,7 @@ 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"
+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"
@@ -22324,7 +22981,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22591,6 +23248,12 @@ 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 ""
@@ -22609,6 +23272,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22714,7 +23380,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22837,15 +23506,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22924,6 +23593,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22960,6 +23632,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23035,6 +23713,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23242,6 +23923,9 @@ 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 ""
@@ -23254,7 +23938,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23263,9 +23947,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23341,9 +24022,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23386,7 +24064,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23413,9 +24094,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23524,12 +24202,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23551,6 +24223,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23572,6 +24247,9 @@ 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 ""
@@ -23632,6 +24310,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23725,21 +24406,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23755,9 +24424,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23767,13 +24433,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23851,6 +24520,15 @@ 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 ""
@@ -23902,9 +24580,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23965,10 +24640,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23986,7 +24661,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24109,6 +24784,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24136,6 +24814,9 @@ 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 ""
@@ -24277,16 +24958,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24400,9 +25081,15 @@ 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 ""
@@ -24487,6 +25174,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24562,6 +25252,12 @@ 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 ""
@@ -24844,9 +25540,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24946,6 +25639,9 @@ 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 ""
@@ -24976,10 +25672,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25177,9 +25870,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25219,6 +25909,9 @@ 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 ""
@@ -25240,6 +25933,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25249,9 +25945,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25288,6 +25981,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25612,6 +26308,9 @@ 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 ""
@@ -25648,7 +26347,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25675,6 +26377,9 @@ 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 ""
@@ -25735,7 +26440,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25774,7 +26482,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26191,13 +26899,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26218,6 +26929,9 @@ 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 ""
@@ -26236,6 +26950,9 @@ 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 ""
@@ -26473,6 +27190,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26749,6 +27469,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26977,9 +27703,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26989,12 +27730,30 @@ 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 ""
@@ -27007,9 +27766,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27157,7 +27928,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27172,6 +27943,9 @@ 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] ""
@@ -27184,6 +27958,9 @@ 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 ""
@@ -27250,6 +28027,9 @@ 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 ""
@@ -27373,9 +28153,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27394,9 +28171,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27664,6 +28438,9 @@ 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 ""
@@ -27760,6 +28537,9 @@ 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 ""
@@ -27838,6 +28618,9 @@ 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 ""
@@ -27919,6 +28702,9 @@ 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 ""
@@ -28216,6 +29002,9 @@ 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 ""
@@ -28300,6 +29089,15 @@ 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 ""
@@ -28315,9 +29113,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28390,12 +29185,33 @@ 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 ""
@@ -28411,6 +29227,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28423,12 +29242,21 @@ 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 ""
@@ -28438,7 +29266,7 @@ 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."
+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"
@@ -28447,6 +29275,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29056,12 +29887,21 @@ 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] ""
+msgstr[2] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29080,6 +29920,39 @@ 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 Gold 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 Gold 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 ""
@@ -29470,6 +30343,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29494,7 +30370,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29551,7 +30427,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29566,7 +30442,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29608,9 +30484,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30121,6 +30994,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30562,6 +31438,9 @@ 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 ""
@@ -30589,6 +31468,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30616,6 +31498,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30634,6 +31522,9 @@ 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 ""
@@ -30646,6 +31537,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30679,6 +31573,9 @@ 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 ""
@@ -30781,6 +31678,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30817,6 +31717,9 @@ 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 ""
@@ -30940,7 +31843,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31318,6 +32221,9 @@ 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 ""
@@ -31408,6 +32314,9 @@ 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 ""
@@ -31417,9 +32326,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31441,6 +32347,9 @@ 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 ""
@@ -31477,9 +32386,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31552,6 +32458,9 @@ 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 ""
@@ -31561,6 +32470,9 @@ 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 ""
@@ -31594,6 +32506,9 @@ 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 ""
@@ -31753,6 +32668,9 @@ 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 ""
@@ -31825,6 +32743,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31900,6 +32821,9 @@ 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 ""
@@ -31921,6 +32845,9 @@ 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 ""
@@ -31978,6 +32905,9 @@ 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 ""
@@ -32077,6 +33007,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32095,9 +33028,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32140,6 +33079,9 @@ 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 ""
@@ -32179,6 +33121,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32335,6 +33280,9 @@ 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] ""
@@ -32542,6 +33490,12 @@ 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 ""
@@ -32725,6 +33679,9 @@ 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] ""
@@ -33385,18 +34342,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 2508cac27f4..43acbd904e3 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,10 +14,10 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-12-03 08:19\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
-msgstr ""
+msgstr " %{project_name}#%{issuable_iid} &middot; %{author} открыл %{issuable_created}"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -64,13 +64,13 @@ msgid " or "
msgstr " или "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr " или %{emphasisStart}!id запроÑа на ÑлиÑние%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
-msgstr ""
+msgstr " или %{emphasisStart}#id обÑуждениÑ%{emphasisEnd}"
msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
-msgstr ""
+msgstr " или %{emphasisStart}&id цели%{emphasisEnd}"
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " или ÑÑылки (например: path/to/project!merge_request_id)"
@@ -79,7 +79,7 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" не ÑущеÑтвует на \"%{ref}\""
msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "Параметр \"el\" необходим Ð´Ð»Ñ createInstance()"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -97,10 +97,10 @@ msgstr[3] ""
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d пакет"
+msgstr[1] "%d пакета"
+msgstr[2] "%d пакетов"
+msgstr[3] "%d пакетов"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
@@ -191,10 +191,10 @@ msgstr "%d коммитов"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d закрытое обÑуждение"
+msgstr[1] "%d закрытых обÑуждениÑ"
+msgstr[2] "%d закрытых обÑуждений"
+msgstr[3] "%d закрытых обÑуждений"
msgid "%d contribution"
msgid_plural "%d contributions"
@@ -219,10 +219,10 @@ msgstr[3] "%d ошибок"
msgid "%d error found:"
msgid_plural "%d errors found:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "найдена %d ошибка:"
+msgstr[1] "найдены %d ошибки:"
+msgstr[2] "найдено %d ошибок:"
+msgstr[3] "найдено %d ошибок:"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -282,17 +282,17 @@ msgstr[3] "%d обÑуждений"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d обÑуждение в Ñтой группе"
+msgstr[1] "%d обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð² Ñтой группе"
+msgstr[2] "%d обÑуждений в Ñтой группе"
+msgstr[3] "%d обÑуждений в Ñтой группе"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d обÑуждение уÑпешно импортировано Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹"
+msgstr[1] "%d обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ ÑƒÑпешно импортированы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹"
+msgstr[2] "%d обÑуждений уÑпешно импортированы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹"
+msgstr[3] "%d обÑуждений уÑпешно импортированы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹"
msgid "%d layer"
msgid_plural "%d layers"
@@ -324,10 +324,10 @@ msgstr[3] "%d метрик"
msgid "%d milestone"
msgid_plural "%d milestones"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Ñтап"
+msgstr[1] "%d Ñтапа"
+msgstr[2] "%d Ñтапов"
+msgstr[3] "%d Ñтапов"
msgid "%d minute"
msgid_plural "%d minutes"
@@ -352,24 +352,24 @@ msgstr[3] "%d открытых обÑуждений"
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d ожидающий комментарий"
+msgstr[1] "%d ожидающих комментариÑ"
+msgstr[2] "%d ожидающих комментариев"
+msgstr[3] "%d ожидающих комментариÑ"
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d личный проект будет удалён без возможноÑти воÑÑтановлениÑ."
+msgstr[1] "%d личных проекта будут удалены без возможноÑти воÑÑтановлениÑ."
+msgstr[2] "%d личных проектов будут удалены без возможноÑти воÑÑтановлениÑ."
+msgstr[3] "%d личных проектов будут удалены без возможноÑти воÑÑтановлениÑ."
msgid "%d previously merged commit"
msgid_plural "%d previously merged commits"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d ранее Ñлитый коммит"
+msgstr[1] "%d ранее Ñлитых коммита"
+msgstr[2] "%d ранее Ñлитых коммитов"
+msgstr[3] "%d ранее Ñлитых коммитов"
msgid "%d project"
msgid_plural "%d projects"
@@ -436,10 +436,10 @@ msgstr[3] "%d нерешённых тем"
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d уÑзвимоÑÑ‚ÑŒ"
+msgstr[1] "%d уÑзвимоÑти"
+msgstr[2] "%d уÑзвимоÑтей"
+msgstr[3] "%d уÑзвимоÑтей"
msgid "%d vulnerability dismissed"
msgid_plural "%d vulnerabilities dismissed"
@@ -450,10 +450,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."
@@ -466,9 +466,15 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{address} is an invalid IP address range"
-msgstr ""
+msgstr "%{address} — недопуÑтимый диапазон IP-адреÑов"
msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr "%{anchorOpen}Узнайте больше%{anchorClose} о том, как наÑтроить/отключить региÑтрацию на Ñвоем ÑкземплÑре."
+
+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:"
@@ -477,6 +483,9 @@ msgstr "%{author_link} напиÑал:"
msgid "%{authorsName}'s thread"
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 ""
@@ -519,17 +528,17 @@ msgstr "затронуто %{count} файлов"
msgid "%{count} issue selected"
msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "выбрано %{count} обÑуждение"
+msgstr[1] "выбраны %{count} обÑуждениÑ"
+msgstr[2] "выбрано %{count} обÑуждений"
+msgstr[3] "выбрано %{count} обÑуждений"
msgid "%{count} merge request selected"
msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "выбран %{count} Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgstr[1] "выбраны %{count} запроÑа на ÑлиÑние"
+msgstr[2] "выбрано %{count} запроÑов на ÑлиÑние"
+msgstr[3] "выбрано %{count} запроÑов на ÑлиÑние"
msgid "%{count} more"
msgstr "ещё %{count}"
@@ -612,16 +621,16 @@ msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} + ещё %{labelCount}"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
-msgstr ""
+msgstr "%{firstMilestoneName} + ещё %{numberOfOtherMilestones}"
msgid "%{global_id} is not a valid ID for %{expected_type}."
-msgstr ""
+msgstr "%{global_id} не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым ID Ð´Ð»Ñ %{expected_type}."
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Группы%{group_docs_link_end} позволÑÑŽÑ‚ управлÑÑ‚ÑŒ неÑколькими проектами и Ñотрудничать Ñ Ð½Ð¸Ð¼Ð¸. Члены группы имеют доÑтуп ко вÑем ее проектам."
msgid "%{group_name} group members"
-msgstr ""
+msgstr "УчаÑтники группы %{group_name}"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} иÑпользует управлÑемые групповые аккаунты. Вам нужно Ñоздать новый аккаунт GitLab, который будет управлÑÑ‚ÑŒÑÑ %{group_name}."
@@ -636,7 +645,7 @@ msgid "%{hook_type} was scheduled for deletion"
msgstr ""
msgid "%{host} sign-in from new location"
-msgstr ""
+msgstr "%{host} вход из нового меÑтоположениÑ"
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 "%{integrations_link_start}Интеграции%{link_end} позволÑÑŽÑ‚ вам Ñделать Ñторонние Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‡Ð°Ñтью вашего рабочего процеÑÑа GitLab. ЕÑли доÑтупные интеграции не ÑоответÑтвуют вашим потребноÑÑ‚Ñм, раÑÑмотрите возможноÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ %{webhooks_link_start}веб-обработчика%{link_end}."
@@ -666,7 +675,7 @@ msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
msgstr ""
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}СоÑтоÑние ÑбоÑ:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}ДоказательÑтва:%{labelEnd} %{evidence}"
@@ -681,7 +690,7 @@ msgid "%{labelStart}Method:%{labelEnd} %{method}"
msgstr "%{labelStart}Метод:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
-msgstr ""
+msgstr "%{labelStart}ПроÑтранÑтво имён:%{labelEnd} %{namespace}"
msgid "%{labelStart}Scan Type:%{labelEnd} %{reportType}"
msgstr ""
@@ -702,7 +711,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) на веб-Ñайтах."
@@ -833,13 +842,13 @@ msgid "%{remaining_approvals} left"
msgstr "%{remaining_approvals} оÑталоÑÑŒ"
msgid "%{reportType} %{status}"
-msgstr ""
+msgstr "%{reportType} %{status}"
msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
-msgstr ""
+msgstr "%{reportType} обнаружено %{totalStart}%{total}%{totalEnd} потенциальных %{vulnMessage}"
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
-msgstr ""
+msgstr "%{reportType} не обнаружено %{totalStart} ни одной %{totalEnd} уÑзвимоÑти."
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -849,10 +858,10 @@ msgstr "%{seconds}Ñ"
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] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{securityScanner} не включен Ð´Ð»Ñ Ñтого проекта. %{linkStart}Подробнее%{linkEnd}"
+msgstr[1] "%{securityScanner} не включены Ð´Ð»Ñ Ñтого проекта. %{linkStart}Подробнее%{linkEnd}"
+msgstr[2] "%{securityScanner} не включены Ð´Ð»Ñ Ñтого проекта. %{linkStart}Подробнее%{linkEnd}"
+msgstr[3] "%{securityScanner} не включены Ð´Ð»Ñ Ñтого проекта. %{linkStart}Подробнее%{linkEnd}"
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}"
@@ -862,7 +871,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "%{size} %{unit}"
-msgstr ""
+msgstr "%{size} %{unit}"
msgid "%{size} GiB"
msgstr "%{size} ГиБ"
@@ -877,7 +886,7 @@ msgid "%{size} bytes"
msgstr "%{size} байт"
msgid "%{sourceBranch} into %{targetBranch}"
-msgstr ""
+msgstr "%{sourceBranch} в %{targetBranch}"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} было уÑпешно отправлено в Akismet."
@@ -895,7 +904,7 @@ msgid "%{state} epics"
msgstr "%{state} цели"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
-msgstr ""
+msgstr "%{strongStart}УдалÑет%{strongEnd} иÑходную ветку"
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr "%{strongStart}Примечание:%{strongEnd} ПоÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑкого Ñтапа вы можете изменить порÑдок Ñтапов, перетаÑÐºÐ¸Ð²Ð°Ñ Ð¸Ñ… в нужное положение."
@@ -917,6 +926,27 @@ msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Коммита"
msgstr[2] "%{strong_start}%{commit_count}%{strong_end} Коммитов"
msgstr[3] "%{strong_start}%{commit_count}%{strong_end} Коммитов"
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} Файлов"
@@ -966,7 +996,7 @@ msgid "%{timebox_name} should belong either to a project or a group."
msgstr "%{timebox_name} должен принадлежать проекту или группе"
msgid "%{timebox_type} does not support burnup charts"
-msgstr ""
+msgstr "%{timebox_type} не поддерживает диаграммы ÑгораниÑ"
msgid "%{timebox_type} must have a start and due date"
msgstr ""
@@ -1050,13 +1080,13 @@ msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
-msgstr ""
+msgstr "'%{level}' не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым уровнем видимоÑти"
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "Поток ценноÑти '%{name}' Ñоздан"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "Поток ценноÑти '%{name}' удалён"
msgid "'%{name}' stage already exists"
msgstr "Этап '%{name}' уже ÑущеÑтвует"
@@ -1080,9 +1110,15 @@ msgstr "(%{mrCount} объединено)"
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 "(прогреÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸)"
@@ -1090,10 +1126,10 @@ msgid "(deleted)"
msgstr "(удалено)"
msgid "(line: %{startLine})"
-msgstr ""
+msgstr "(Ñтрока: %{startLine})"
msgid "(max size 15 MB)"
-msgstr ""
+msgstr "(макÑ. размер 15 Мбайт)"
msgid "(removed)"
msgstr "(удалено)"
@@ -1130,7 +1166,7 @@ msgid "+%{approvers} more approvers"
msgstr "+ещё %{approvers} утверждающих"
msgid "+%{more_assignees_count}"
-msgstr ""
+msgstr "+%{more_assignees_count}"
msgid "+%{more_assignees_count} more assignees"
msgstr ""
@@ -1225,10 +1261,10 @@ msgstr[3] "%d дней"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 ключ развёртываниÑ"
+msgstr[1] "%d ключа развёртываниÑ"
+msgstr[2] "%d ключей развёртываниÑ"
+msgstr[3] "%d ключей развёртываниÑ"
msgid "1 group"
msgid_plural "%d groups"
@@ -1353,29 +1389,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "«Runner» - Ñто процеÑÑ, который выполнÑет Ñозданное вами задание. Ð’Ñ‹ можете наÑтроить Ñтолько таких процеÑÑов, Ñколько вам нужно."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Шаблон конÑольного Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ .NET Core, наÑтраиваемый Ð´Ð»Ñ Ð»ÑŽÐ±Ð¾Ð³Ð¾ проекта .NET Core"
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 "Сайт GitBook, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
+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 "ÐаÑтроенное через Gitpod веб-приложение на Spring и Java"
-msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Сайт Hexo, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
+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 "Сайт Hugo, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
-msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Сайт Jekyll, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
msgstr "SSL Ñертификат Let's Encrypt не может быть получен, пока ваш домен не будет проверен."
@@ -1386,6 +1419,9 @@ msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Let's Encrypt будет наÑтроена
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ñтраница и беÑÑÐµÑ€Ð²ÐµÑ€Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ, иÑпользующие AWS Lambda, AWS API Gateway, и GitLab Pages"
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
msgid "A complete DevOps platform"
msgstr "КомплекÑÐ½Ð°Ñ DevOps-платформа"
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 "УчаÑтник команды по борьбе Ñ Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñми раÑÑмотрит ваш отчет при первой возможноÑти."
@@ -1422,6 +1461,9 @@ 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 "ÐÐ¾Ð²Ð°Ñ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps Ñоздана, обратитеÑÑŒ к %{pipelines_link_start}Ñтранице, поÑвÑщенной Сборочным линиÑм%{pipelines_link_end} за подробноÑÑ‚Ñми"
@@ -1438,16 +1480,19 @@ 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 HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "ПроÑтой HTML-Ñайт, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
+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 "Шаблон проекта Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Salesforce-Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Salesforce Developer Tools."
+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 ""
@@ -1455,11 +1500,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Готовый шаблон Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñми Android."
+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 "Готовый шаблон Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñми iOS Swift."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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 "РегулÑрное выражение, которое будет иÑпользоватьÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка результатов Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами в логах заданиÑ. ОÑтавьте пуÑтым Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 "Пользователь Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸ÐµÐ¼ на запиÑÑŒ в ветку иÑточника выбрал Ñтот вариант"
@@ -1491,14 +1545,17 @@ msgstr "API токен"
msgid "AWS Access Key"
msgstr "Ключ доÑтупа AWS"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "Ключ доÑтупа AWS. ТребуетÑÑ, только еÑли Ð´Ð»Ñ Ð´Ð¾Ñтупа к инÑтанÑу не иÑпользуетÑÑ Ñ€Ð¾Ð»ÑŒ"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "Секретный ключ доÑтупа AWS"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "Секретный ключ доÑтупа AWS. ТребуетÑÑ, только еÑли Ð´Ð»Ñ Ð´Ð¾Ñтупа к инÑтанÑу не иÑпользуетÑÑ Ñ€Ð¾Ð»ÑŒ"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "Отменить"
@@ -1539,6 +1596,9 @@ 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 "Дата Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа"
@@ -1624,7 +1684,7 @@ msgid "AccessTokens|Your feed token is used to authenticate you when your RSS re
msgstr "Когда ваш RSS-reader загружает перÑональную RSS ленту или когда приложение ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð·Ð°Ð³Ñ€ÑƒÐ¶Ð°ÐµÑ‚ перÑональный календарь, ваш токен канала иÑпользуетÑÑ Ð´Ð»Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ и включен в URL-адреÑа ленты."
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 "Ваш токен входÑщей Ñлектронной почты иÑпользуетÑÑ Ð´Ñл аутентификации когда вы Ñоздаете новую задачу при помощи Ñлектронной почты и включен в ваши перÑональные Ñлектронные адреÑа, отноÑÑщиеÑÑ Ðº проекту."
+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 "Ваш токен ÑтатичеÑких объектов иÑпользуетÑÑ Ð´Ð»Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ при обÑлуживании ÑтатичеÑких объектов (например, архивов, бинарных данных, ...) из внешнего хранилища."
@@ -1666,7 +1726,7 @@ msgid "Activate Service Desk"
msgstr "Ðктивировать Ñлужбу поддержки"
msgid "Activate user activity analysis"
-msgstr ""
+msgstr "Ðктивировать анализ дейÑтвий пользователÑ"
msgid "Active"
msgstr "Ðктивный"
@@ -1859,13 +1919,13 @@ msgid "Add new directory"
msgstr "Добавить новый каталог"
msgid "Add or remove previously merged commits"
-msgstr ""
+msgstr "Добавить или удалить коммиты, Ñлитые ранее"
msgid "Add or subtract spent time"
msgstr "Добавить или вычеÑÑ‚ÑŒ потраченное времÑ"
msgid "Add previously merged commits"
-msgstr ""
+msgstr "Добавить ранее Ñлитые коммиты"
msgid "Add reaction"
msgstr "Добавить реакцию"
@@ -1916,7 +1976,7 @@ msgid "Add/remove"
msgstr "Добавить/удалить"
msgid "AddContextCommits|Add previously merged commits"
-msgstr ""
+msgstr "Добавить ранее Ñлитые коммиты"
msgid "AddContextCommits|Add/remove"
msgstr ""
@@ -2039,7 +2099,7 @@ msgid "AdminArea|Features"
msgstr ""
msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
+msgstr "Групп : %{number_of_groups}"
msgid "AdminArea|Guest"
msgstr "Guest"
@@ -2048,7 +2108,7 @@ msgid "AdminArea|Included Free in license"
msgstr "Включены в лицензию беÑплатно"
msgid "AdminArea|Latest groups"
-msgstr ""
+msgstr "ПоÑледние группы"
msgid "AdminArea|Latest projects"
msgstr ""
@@ -2060,10 +2120,10 @@ msgid "AdminArea|Maintainer"
msgstr "Maintainer"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "Ðовый проект"
msgid "AdminArea|New user"
msgstr ""
@@ -2134,6 +2194,9 @@ msgstr "Применить наÑтройки интеграции ко вÑем
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr "ИÑпользовать общие Runner'Ñ‹ в новых проект
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Переменные Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ñ‹ по умолчанию"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "Перейти к общим наÑтройкам"
@@ -2336,7 +2402,7 @@ 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 ""
+msgstr "Внешние пользователи не могут видеть внутренние или приватные проекты, еÑли доÑтуп не предоÑтавлен Ñвно. Внешние пользователи также не могут Ñоздавать проекты, группы или личные Ñниппеты."
msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
msgstr ""
@@ -2529,7 +2595,7 @@ msgid "AlertManagement|Acknowledged"
msgstr "Прочитано"
msgid "AlertManagement|Activity feed"
-msgstr ""
+msgstr "Лента активноÑти"
msgid "AlertManagement|Alert"
msgstr "Оповещение"
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr "Ð’Ñе ветви"
msgid "All changes are committed"
msgstr "Ð’Ñе Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð°Ñ„Ð¸ÐºÑированы"
-msgid "All default stages are currently visible"
-msgstr "Ðа данный момент вÑе Ñтапы по умолчанию видны"
-
msgid "All email addresses will be used to identify your commits."
msgstr "Ð’Ñе адреÑа Ñлектронной почты будут иÑпользоватьÑÑ Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ ваших коммитов."
@@ -3017,6 +3062,9 @@ msgstr "Разрешить владельцам групп управлÑÑ‚ÑŒ н
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Разрешить иÑпользовать только выбранные протоколы Ð´Ð»Ñ Ð´Ð¾Ñтупа к Git."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Произошла ошибка"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 "Произошла ошибка при обновлении приоритета обÑуждениÑ"
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Произошла ошибка при Ñохранении ÑтатуÑа Ð¿ÐµÑ€ÐµÐ¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ LDAP. ПожалуйÑта, попробуйте ещё раз."
-
msgid "An error occurred while saving assignees"
msgstr "Произошла ошибка при Ñохранении ответÑтвенных"
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,7 +3533,7 @@ msgstr "Произошла ошибка. ПожалуйÑта, попробуйÑ
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 "Ðеавторизованный пользователь"
@@ -3569,8 +3629,8 @@ msgstr ""
msgid "Any label"
msgstr "Ð›ÑŽÐ±Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
-msgid "Any member with Developer or higher permissions to the project."
-msgstr "Любой учаÑтник проекта Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¼Ð¸ Developer или выше."
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
msgid "Any milestone"
msgstr ""
@@ -3726,15 +3786,15 @@ msgstr[3] "Ðеобходимо %{count} одобрений из %{membersCount}
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Утверждающие"
msgid "ApprovalRule|Name"
msgstr "ИмÑ"
-msgid "ApprovalRule|No. approvals required"
-msgstr "КоличеÑтво ÑоглаÑований"
-
msgid "ApprovalRule|Rule name"
msgstr "Ðазвание правила"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3841,7 +3904,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}?"
@@ -3855,9 +3918,6 @@ msgstr "Ð’Ñ‹ уверены что дейÑтвительно хотите удÐ
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "Ð’Ñ‹ уверены, что дейÑтвительно хотите удалить Ñту доÑку?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñто уÑтройÑтво? Это дейÑтвие не может быть отменено."
@@ -3962,7 +4022,7 @@ msgid "Are you sure? This will invalidate your registered applications and U2F d
msgstr "Ð’Ñ‹ уверены? Это аннулирует ваши зарегиÑтрированные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ U2F уÑтройÑтва."
msgid "Arrange charts"
-msgstr "УпорÑдочить графики"
+msgstr "УпорÑдочить диаграммы"
msgid "Artifact"
msgstr "Ðртефакт"
@@ -4010,7 +4070,7 @@ msgid "Assign"
msgstr "Ðазначить"
msgid "Assign Iteration"
-msgstr ""
+msgstr "Ðазначить итерацию"
msgid "Assign To"
msgstr "Ðазначить на "
@@ -4027,6 +4087,12 @@ msgstr "Ðазначить метки"
msgid "Assign milestone"
msgstr "Ðазначить Ñтап"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Ðазначить какие-либо задачи Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñтапа."
@@ -4045,24 +4111,33 @@ msgstr "ВзÑÑ‚ÑŒ на ÑÐµÐ±Ñ Ñто обÑуждение"
msgid "Assigned %{assignee_users_sentence}."
msgstr "Ðазначены %{assignee_users_sentence}."
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Ðазначенные обÑуждениÑ"
msgid "Assigned Merge Requests"
msgstr "Ðазначенные запроÑÑ‹ на ÑлиÑние"
-msgid "Assigned to %{assigneeName}"
+msgid "Assigned projects"
msgstr ""
+msgid "Assigned to %{assigneeName}"
+msgstr "Ðазначено %{assigneeName}"
+
msgid "Assigned to %{assignee_name}"
msgstr "Ðазначен %{assignee_name}"
msgid "Assigned to %{name}"
-msgstr ""
+msgstr "Ðазначено %{name}"
msgid "Assigned to me"
msgstr "Ðазначить мне"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "ОтветÑтвенный"
@@ -4088,6 +4163,9 @@ msgstr "ОтветÑтвенные"
msgid "Assigns %{assignee_users_sentence}."
msgstr "Ðазначение %{assignee_users_sentence}."
+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 ""
@@ -4134,9 +4212,6 @@ msgstr "Ðудит Ñобытий"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr "Журнал аудита"
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,12 +4368,12 @@ 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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr "Auto DevOps может автоматичеÑки Ñобирать, теÑтировать и развертывать приложениÑ, оÑновываÑÑÑŒ на предопределенных наÑтройках непрерывной интеграции и развертываниÑ. %{auto_devops_start}Узнайте больше про Auto DevOps%{auto_devops_end} или иÑпользуйте наше %{quickstart_start} краткое руководÑтво пользователÑ%{quickstart_end}, чтобы приÑтупить Ñразу же."
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ð¾ Auto DevOps"
@@ -4317,10 +4392,13 @@ 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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr "ÐвтоматичеÑкое управление Ñертификата
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr "Цвет фона"
msgid "Badges"
msgstr "Значки"
-msgid "Badges|A new badge was added."
-msgstr "Ðовый значок был добавлен."
-
msgid "Badges|Add badge"
msgstr "Добавить значок"
@@ -4440,12 +4515,21 @@ msgstr "URL-Ð°Ð´Ñ€ÐµÑ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ°"
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 "Значок Группы"
@@ -4455,15 +4539,15 @@ 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|Please fill in a valid URL"
-msgstr "ПожалуйÑта, введите дейÑтвительный URL"
-
msgid "Badges|Project Badge"
msgstr "Значок Проекта"
@@ -4476,15 +4560,12 @@ msgstr "Сохранить изменениÑ"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Сохранение значка не удалоÑÑŒ, проверьте введенные URL-адреÑа и повторите попытку."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "%{docsLinkStart}переменные%{docsLinkEnd} GitLab поддерживает: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Значок был удален."
-msgid "Badges|The badge was saved."
-msgstr "Значок был Ñохранен."
-
msgid "Badges|This group has no badges"
msgstr "Эта группа не имеет значков"
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Ваши значки"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "например %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Файл Balsamiq не может быть загружен."
@@ -4524,9 +4602,6 @@ msgstr "Ð’Ñ‹ должны наÑтроить автоматичеÑкое при
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте оÑторожны. Изменение пути проекта может вызвать нежелательные побочные Ñффекты."
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Улучшить"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,12 +4747,21 @@ msgstr "Блокирует"
msgid "Blog"
msgstr "Блог"
-msgid "Board scope"
-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 "ДоÑки"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr "Ð˜Ð¼Ñ Ð²ÐµÑ‚Ð²Ð¸"
msgid "Branch not loaded - %{branchId}"
msgstr "Ветка не загружена - %{branchId}"
-msgid "Branch prefix"
-msgstr "ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð²ÐµÑ‚Ð²Ð¸"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ПоиÑк веток"
@@ -4924,6 +5035,24 @@ msgstr "Ð’Ñтроенный"
msgid "Bulk request concurrency"
msgstr "РаÑпараллеливание маÑÑовых запроÑов"
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4934,10 +5063,10 @@ msgid "BulkImport|must be a group"
msgstr ""
msgid "Burndown chart"
-msgstr "ÐиÑходÑщий график"
+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 "Открыть приоритет задачи"
@@ -5003,7 +5132,7 @@ msgid "CI variables"
msgstr "Переменные CI"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "CI будет запуÑкатьÑÑ Ñ Ð¸Ñпользованием учетных данных, указанных выше."
msgid "CI/CD"
msgstr "CI/CD"
@@ -5017,7 +5146,10 @@ msgstr "CI/CD Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ репозиториÑ"
msgid "CI/CD settings"
msgstr "ÐаÑтройки CI/CD"
-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."
+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"
@@ -5044,12 +5176,12 @@ 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 "Сборка Auto DevOps будет запущена, еÑли не будет найден иной файл конфигурации CI."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr "Ð’Ñ‹ должны добавить %{base_domain_link_start}базовый домен%{link_end} в Ñвой %{kubernetes_cluster_link_start}Kubernetes клаÑтер%{link_end} Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы ваша ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ð¸Ñ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð°Ð»Ð°."
-
msgid "CICD|group enabled"
msgstr "группа включена"
@@ -5077,9 +5209,6 @@ msgstr "URL обратного вызова"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Может переопределÑÑ‚ÑŒ утверждающих и их ÑƒÑ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа на ÑлиÑние"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 "Отмена"
@@ -5149,6 +5302,9 @@ msgstr "Отменено развёртывание в"
msgid "Cancelling Preview"
msgstr "Отмена предварительного проÑмотра"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Ðет возможноÑти объединить автоматичеÑки"
@@ -5201,7 +5357,7 @@ msgid "Cannot show preview. For previews on sketch files, they must have the fil
msgstr ""
msgid "Cannot skip two factor authentication setup"
-msgstr ""
+msgstr "Ðевозможно пропуÑтить наÑтройку двухфакторной аутентификации"
msgid "Capacity threshold"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 "Изменён ответÑтвенный(ые)."
@@ -5311,13 +5485,16 @@ 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 "ИзменÑет название на \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5329,11 +5506,8 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
-msgstr ""
+msgstr "Ðе удалоÑÑŒ отобразить диаграммы, так как Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа данных иÑтекло. %{documentationLink}"
msgid "Chat"
msgstr "Чат"
@@ -5393,7 +5567,7 @@ msgid "Check out, review, and merge locally"
msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
-msgstr ""
+msgstr "Подробнее в %{docs_link_start}документации%{docs_link_end}."
msgid "Check your Docker images for known vulnerabilities."
msgstr "Проверьте ваши образы Docker на наличие извеÑтных уÑзвимоÑтей."
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5654,7 +5834,7 @@ msgid "CiStatusLabel|pending"
msgstr "в ожидании"
msgid "CiStatusLabel|preparing"
-msgstr ""
+msgstr "подготовка"
msgid "CiStatusLabel|skipped"
msgstr "пропущено"
@@ -5860,6 +6040,9 @@ msgstr "Клонировать"
msgid "Clone repository"
msgstr "Клонировать репозиторий"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "Клонировать Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ %{http_label}"
@@ -5872,6 +6055,18 @@ msgstr "Клонировать Ñ KRB5"
msgid "Clone with SSH"
msgstr "Клонировать Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ SSH"
+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 "Закрыть"
@@ -5921,7 +6116,7 @@ msgid "Cluster Health"
msgstr ""
msgid "Cluster cache cleared."
-msgstr ""
+msgstr "КÑш клаÑтера очищен."
msgid "Cluster does not exist"
msgstr ""
@@ -6488,7 +6683,7 @@ msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to crea
msgstr "УбедитеÑÑŒ, что ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{link_to_requirements} Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ñтеров"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
-msgstr ""
+msgstr "УправлÑйте клаÑтером Kubernetes, поÑетив %{provider_link}"
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7197,7 +7392,7 @@ msgid "Company name"
msgstr ""
msgid "Compare"
-msgstr "Сравнить"
+msgstr "Сравнение"
msgid "Compare %{oldCommitId}...%{newCommitId}"
msgstr ""
@@ -7209,13 +7404,13 @@ msgid "Compare Revisions"
msgstr "Сравнить верÑии"
msgid "Compare changes"
-msgstr ""
+msgstr "Сравнить изменениÑ"
msgid "Compare changes with the last commit"
msgstr "Сравнить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ñледним коммитом"
msgid "Compare changes with the merge request target branch"
-msgstr ""
+msgstr "Сравнить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ веткой запроÑа на ÑлиÑние"
msgid "Compare submodule commit revisions"
msgstr ""
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7314,7 +7527,7 @@ msgid "Configure Prometheus"
msgstr ""
msgid "Configure Tracing"
-msgstr ""
+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 ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "ПоздравлÑем! Ð’Ñ‹ включили двухфакторную аутентификацию!"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Подключить"
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr "%{imageName} тегов"
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ msgstr "Собрать образ"
msgid "ContainerRegistry|CLI Commands"
msgstr "Команды CLI"
+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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Ошибка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Docker"
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr "Правила иÑÑ‚ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ‹"
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr "РаÑпиÑание иÑтечениÑ:"
-
msgid "ContainerRegistry|Filter by name"
msgstr "Фильтровать по имени"
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr "Вход"
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr "КоличеÑтво тегов Ð´Ð»Ñ ÑохранениÑ:"
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr "Теги Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸, ÑоответÑтвующими Ñтому регулÑрному выражению, будут %{italicStart}проÑрочены:%{italicEnd}"
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "С рееÑтром контейнеров каждый проект может иметь Ñвое меÑто Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñвоих Docker образов. %{docLinkStart}ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ%{docLinkEnd}"
@@ -7830,7 +8052,7 @@ msgid "Cookie domain"
msgstr ""
msgid "Copied"
-msgstr ""
+msgstr "Скопировано"
msgid "Copied labels and milestone from %{source_issuable_reference}."
msgstr "Скопированы метки и Ñтап из %{source_issuable_reference}."
@@ -7874,6 +8096,9 @@ msgstr "Копировать URL"
msgid "Copy branch name"
msgstr "Копировать Ð¸Ð¼Ñ Ð²ÐµÑ‚ÐºÐ¸"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7917,7 +8142,7 @@ msgid "Copy secret"
msgstr ""
msgid "Copy source branch name"
-msgstr ""
+msgstr "Скопировать Ð¸Ð¼Ñ Ð¸Ñходной ветки"
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
@@ -7992,7 +8217,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 ""
@@ -8071,7 +8296,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}."
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
-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 board"
-msgstr "Создать доÑку"
-
msgid "Create branch"
msgstr "Создать ветку"
@@ -8155,7 +8377,7 @@ msgid "Create issue"
msgstr ""
msgid "Create iteration"
-msgstr ""
+msgstr "Создать итерацию"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "Создать ÑпиÑок из меток. ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ñтой меткой поÑвлÑÑŽÑ‚ÑÑ Ð² Ñтом ÑпиÑке."
@@ -8173,10 +8395,7 @@ msgid "Create new"
msgstr ""
msgid "Create new Value Stream"
-msgstr ""
-
-msgid "Create new board"
-msgstr "Создать новую доÑку"
+msgstr "Создать новый Поток ценноÑти"
msgid "Create new branch"
msgstr "Создать новую ветку"
@@ -8209,7 +8428,7 @@ msgid "Create project label"
msgstr "Создать метку проекта"
msgid "Create release"
-msgstr ""
+msgstr "Создать релиз"
msgid "Create requirement"
msgstr "Создать требование"
@@ -8241,6 +8460,84 @@ msgstr "Тег"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Ñоздать перÑональный токен доÑтупа"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Создан"
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð’ÐµÑ‚ÐºÐ°"
@@ -8418,45 +8718,18 @@ msgstr "Добавить Ñтап"
msgid "CustomCycleAnalytics|Editing stage"
msgstr "Редактиование Ñтапа"
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr "Введите название Ñтапа"
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr "Ðовый Ñтап"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr "Ð˜Ð¼Ñ Ñтапа уже ÑущеÑтвует"
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr "Метка начального ÑобытиÑ"
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr "Метка конечного ÑобытиÑ"
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr "Обновить Ñтап"
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "Шаблон обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию"
-
msgid "Default project deletion protection"
-msgstr ""
+msgstr "Защита от ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° по умолчанию"
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr "Этапы по умолчанию"
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Определить наÑтраиваемый шаблон Ñ ÑинтакÑиÑом cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -9086,10 +9368,10 @@ msgid "Delete Comment"
msgstr "Удалить комментарий"
msgid "Delete Value Stream"
-msgstr ""
+msgstr "Удалить Поток ценноÑти"
msgid "Delete account"
-msgstr ""
+msgstr "Удалить аккаунт"
msgid "Delete artifacts"
msgstr "Удалить артефакты"
@@ -9097,9 +9379,6 @@ msgstr "Удалить артефакты"
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "Удалить доÑку"
-
msgid "Delete comment"
msgstr "Удалить комментарий"
@@ -9167,7 +9446,7 @@ msgid "Deleted"
msgstr "Удалено"
msgid "Deleted Projects"
-msgstr ""
+msgstr "Удалённые проекты"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Удалённый никнейм чата: %{chat_name}!"
@@ -9209,7 +9488,7 @@ msgid "Denylist file"
msgstr ""
msgid "Dependencies"
-msgstr ""
+msgstr "ЗавиÑимоÑти"
msgid "Dependencies help page link"
msgstr ""
@@ -9296,10 +9575,10 @@ msgid "Dependencies|Vulnerable components"
msgstr "УÑзвимые компоненты"
msgid "Dependency List"
-msgstr ""
+msgstr "СпиÑок завиÑимоÑтей"
msgid "Dependency List has no entries"
-msgstr ""
+msgstr "СпиÑок завиÑимоÑтей пуÑÑ‚"
msgid "Dependency Proxy"
msgstr "ПрокÑи завиÑимоÑтей"
@@ -9577,9 +9856,6 @@ msgstr "По убыванию"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr "Опишите требование здеÑÑŒ"
-
msgid "Description"
msgstr "ОпиÑание"
@@ -9589,6 +9865,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "ОпиÑание обработано Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
msgid "Description template"
msgstr ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9989,7 +10325,7 @@ msgid "Disk Usage"
msgstr ""
msgid "Dismiss"
-msgstr ""
+msgstr "Отклонить"
msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
@@ -10005,7 +10341,7 @@ msgid "Dismiss Merge Request promotion"
msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
-msgstr ""
+msgstr "Закрыть окно Ð²Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð² Ðналитику потока ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ†ÐµÐ½Ð½Ð¾Ñти"
msgid "Dismiss selected"
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "Скачать CSV"
@@ -10149,7 +10488,7 @@ msgid "DownloadSource|Download"
msgstr "Скачать"
msgid "Downstream"
-msgstr ""
+msgstr "ÐиÑходÑщаÑ"
msgid "Downvotes"
msgstr "ГолоÑа \"против\""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr "Редактировать доÑку"
-
msgid "Edit comment"
msgstr "Редактировать комментарий"
@@ -10266,7 +10599,7 @@ msgid "Edit fork in Web IDE"
msgstr ""
msgid "Edit group: %{group_name}"
-msgstr ""
+msgstr "Правка группы: %{group_name}"
msgid "Edit identity for %{user_name}"
msgstr "Изменить идентификацию Ð´Ð»Ñ %{user_name}"
@@ -10281,14 +10614,17 @@ msgid "Edit inline"
msgstr ""
msgid "Edit issues"
-msgstr ""
+msgstr "Редактировать обÑуждениÑ"
msgid "Edit iteration"
-msgstr ""
+msgstr "Изменить итерацию"
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "Редактировать Ñтап"
@@ -10305,7 +10641,7 @@ msgid "Edit wiki page"
msgstr "Изменить wiki Ñтраницу"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
-msgstr ""
+msgstr "Редактировать Ñвой поÑледний комментарий в теме (в пуÑтом текÑтовом поле)"
msgid "Edited"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr "ÑброÑ..."
msgid "Emails"
msgstr "ÐдреÑа Ñл. почты"
-msgid "Emails sent from Service Desk will have this name"
-msgstr "ПиÑьма, отправленные Ñлужбой поддержки будут иметь Ñто имÑ"
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ msgstr "Включить и наÑтроить Grafana."
msgid "Enable and configure Prometheus metrics."
msgstr "Включить и наÑтроить метрики Prometheus."
+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 ""
@@ -10551,7 +10899,7 @@ msgid "Enable or disable Seat Link."
msgstr ""
msgid "Enable or disable keyboard shortcuts"
-msgstr ""
+msgstr "Включить или отключить ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr "Включить двухфакторную аутентификацию
msgid "Enable usage ping"
msgstr "Включить Ñбор ÑтатиÑтики иÑпользованиÑ"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr "Включить/отключить Ñлужбу поддержки. %{link_start}Узнайте больше о Ñлужбе поддержки%{link_end}."
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr "%{stepStart}Шаг 1%{stepEnd}. УбедитеÑÑŒ, что Kubernetes наÑтроен и имеет базовый домен Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ %{linkStart}клаÑтера%{linkEnd}."
@@ -10628,6 +10976,9 @@ msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ñ€ÐµÐ½Ð´ÐµÑ€Ð¸Ð½Ð³Ð°: %{
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "ЗаканчиваетÑÑ Ð² (UTC)"
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr "Введите не менее трех Ñимволов Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка"
-msgid "Enter board name"
-msgstr "Введите название доÑки"
-
msgid "Enter domain"
msgstr "Введите домен"
@@ -10701,7 +11049,7 @@ msgid "Enter the issue title"
msgstr "Введите заголовок обÑуждениÑ"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "Введите опиÑание запроÑа на ÑлиÑние"
msgid "Enter the merge request title"
msgstr "Введите заголовок запроÑа на ÑлиÑние"
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr "Развертывание"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 "Это дейÑтвие запуÑтит задание, определённое %{name} Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ð° %{linkStart}%{commitId}%{linkEnd}, Ð¿ÐµÑ€ÐµÐ²ÐµÐ´Ñ Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ðµ в предыдущую верÑию. Ð’Ñ‹ можете обратить Ñтот Ñффект, повторно развернув поÑледнюю верÑию Ñвоего приложениÑ. Ð’Ñ‹ дейÑтвительно хотите продолжить?"
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Обновлено"
@@ -11001,7 +11361,7 @@ msgid "Epics let you manage your portfolio of projects more efficiently and with
msgstr "Цели позволÑÑ‚ вам управлÑÑ‚ÑŒ портфелем проектов более Ñффективно и Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼Ð¸ уÑилиÑми"
msgid "Epics, Issues, and Merge Requests"
-msgstr ""
+msgstr "Цели, ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ ЗапроÑÑ‹ на ÑлиÑние"
msgid "Epics|Add a new epic"
msgstr ""
@@ -11016,7 +11376,7 @@ 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 ""
+msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить %{bStart}%{targetIssueTitle}%{bEnd} из %{bStart}%{parentEpicTitle}%{bEnd}?"
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11027,9 +11387,6 @@ msgstr "Как Ñ Ð¼Ð¾Ð³Ñƒ Ñто иÑправить?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"
-
msgid "Epics|Remove epic"
msgstr "Удалить цель"
@@ -11103,7 +11460,7 @@ msgid "Error creating label."
msgstr "Ошибка при Ñоздании метки."
msgid "Error creating new iteration"
-msgstr ""
+msgstr "Ошибка при Ñоздании новой итерации"
msgid "Error creating repository for snippet with id %{snippet_id}"
msgstr ""
@@ -11135,14 +11492,11 @@ msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñетевого графа."
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr "Ошибка при загрузке проектов"
-
msgid "Error fetching refs"
msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑÑылок"
msgid "Error fetching the dependency list. Please check your network connection and try again."
-msgstr ""
+msgstr "Ошибка при извлечении ÑпиÑка завиÑимоÑтей. ПожалуйÑта, проверьте подключение к Ñети и попробуйте ещё раз."
msgid "Error loading branch data. Please try again."
msgstr "Ошибка загрузки данных ветки. ПожалуйÑта, попробуйте ещё раз."
@@ -11163,7 +11517,7 @@ msgid "Error loading issues"
msgstr ""
msgid "Error loading iterations"
-msgstr ""
+msgstr "Ошибка при загрузке итераций"
msgid "Error loading last commit."
msgstr "Ошибка загрузки поÑледнего коммита."
@@ -11273,9 +11627,18 @@ 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 "Ðктивно"
@@ -11313,10 +11676,10 @@ msgid "Errors:"
msgstr "Ошибки:"
msgid "Estimate"
-msgstr ""
+msgstr "Оценить"
msgid "Estimated"
-msgstr ""
+msgstr "Оценочно"
msgid "EventFilterBy|Filter by all"
msgstr "Фильтр по вÑему"
@@ -11390,23 +11753,23 @@ 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 "Ð’Ñе, что вам нужно, чтобы Ñоздать Ñайт GitLab Pages Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Gatsby."
+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 "Ð’Ñе необходимое Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñайта GitLab Pages Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ GitBook."
+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 "Ð’Ñе необходимое Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñайта GitLab Pages Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Hexo."
+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 "Ð’Ñе необходимое Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñайта GitLab Pages Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Hugo."
+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 "Ð’Ñе необходимое Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñайта GitLab Pages Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Jekyll."
+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 "Ð’ÑÑ‘ необходимое Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñайта GitLab Pages Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ HTML."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
msgid "Evidence collection"
msgstr ""
@@ -11415,13 +11778,13 @@ msgid "Exactly one of %{attributes} is required"
msgstr ""
msgid "Example: %{ip_address}. %{read_more_link}."
-msgstr ""
+msgstr "Пример: %{ip_address}. %{read_more_link}."
msgid "Example: @sub\\.company\\.com$"
msgstr ""
msgid "Example: My Value Stream"
-msgstr ""
+msgstr "Пример: Мой поток ценноÑти"
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11502,7 +11865,7 @@ msgid "Expired:"
msgstr ""
msgid "Expires"
-msgstr ""
+msgstr "ИÑтекает"
msgid "Expires at"
msgstr "ИÑтекает"
@@ -11580,7 +11943,7 @@ msgid "External Wiki"
msgstr "ВнешнÑÑ Wiki"
msgid "External authentication"
-msgstr ""
+msgstr "ВнешнÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
msgid "External authorization denied access to this project"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 "Ðе удалоÑÑŒ назначить пользователÑ, так как пользовать не найден."
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr "Ðе удалоÑÑŒ удалить доÑку. Попробуйте ещё раз."
-
msgid "Failed to deploy to"
msgstr ""
@@ -11688,7 +12057,7 @@ msgid "Failed to get ref."
msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ ÑÑылку"
msgid "Failed to install."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ уÑтановить."
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -11739,7 +12108,7 @@ msgid "Failed to load sidebar lock status"
msgstr ""
msgid "Failed to load stacktrace."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ загрузить траÑÑировку Ñтека."
msgid "Failed to make repository read-only. %{reason}"
msgstr ""
@@ -11811,7 +12180,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 ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr "Ðе удалоÑÑŒ обновить окружение!"
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "Функциональные опции"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12040,7 +12403,7 @@ msgid "FeatureFlags|More information"
msgstr "Подробнее"
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "Ðазвание"
msgid "FeatureFlags|New"
msgstr ""
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr "Фильтр"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr "Фильтр по названию Ñтапа"
msgid "Filter by name"
msgstr "Фильтровать по имени"
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr "ПоиÑк по пути"
-msgid "Find existing members by name"
-msgstr "ПоиÑк учаÑтников"
-
msgid "Find file"
msgstr "Ðайти файл"
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr "Завершено"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12394,7 +12757,7 @@ msgid "For a faster browsing experience, some files are collapsed by default."
msgstr ""
msgid "For help setting up the Service Desk for your instance, please contact an administrator."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ð¸ в наÑтройке Службы поддержки Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра, пожалуйÑта, обратитеÑÑŒ к админиÑтратору."
msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr "ОтветвлениÑ"
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr "ПереÑлать внешний Ð°Ð´Ñ€ÐµÑ Ñлектронной почты поддержки на"
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 "Ðачать Ñ Ð¾Ñ‚ÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº"
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,14 +13587,14 @@ msgstr "Глобальные наÑтройки уведомлений"
msgid "Go Back"
msgstr "ВернутьÑÑ Ð½Ð°Ð·Ð°Ð´"
-msgid "Go Micro is a framework for micro service development."
-msgstr "Go Micro — Ñто фреймворк Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ микроÑервиÑов."
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
msgid "Go back"
msgstr "ВернутьÑÑ"
msgid "Go back (while searching for files)"
-msgstr ""
+msgstr "ВернутьÑÑ (при поиÑке файлов)"
msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
msgstr ""
@@ -13243,7 +13606,7 @@ msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongE
msgstr ""
msgid "Go to Integrations"
-msgstr ""
+msgstr "Перейти к ИнтеграциÑм"
msgid "Go to Webhooks"
msgstr "Перейти к веб-обработчикам"
@@ -13264,22 +13627,22 @@ msgid "Go to file"
msgstr "Перейти к файлу"
msgid "Go to file permalink (while viewing a file)"
-msgstr ""
+msgstr "Перейти к поÑтоÑнной ÑÑылке (при проÑмотре файла)"
msgid "Go to files"
msgstr "Перейти к файлам"
msgid "Go to find file"
-msgstr ""
+msgstr "Перейти к поиÑку файла"
msgid "Go to fork"
msgstr ""
msgid "Go to issue boards"
-msgstr ""
+msgstr "Перейти к доÑкам обÑуждений"
msgid "Go to issues"
-msgstr ""
+msgstr "Перейти к обÑуждениÑм"
msgid "Go to jobs"
msgstr "Перейти к заданиÑм"
@@ -13303,7 +13666,7 @@ msgid "Go to releases"
msgstr "Перейти к релизам"
msgid "Go to repository charts"
-msgstr ""
+msgstr "Перейти к диаграммам репозиториÑ"
msgid "Go to repository graph"
msgstr "Перейти к графу репозиториÑ"
@@ -13327,25 +13690,25 @@ msgid "Go to wiki"
msgstr "Перейти к вики"
msgid "Go to your To-Do list"
-msgstr ""
+msgstr "Перейти к Ñвоему To-Do-ÑпиÑку"
msgid "Go to your fork"
msgstr ""
msgid "Go to your groups"
-msgstr "Перейти к вашим группам"
+msgstr "Перейти к Ñвоим группам"
msgid "Go to your issues"
-msgstr "Перейти к вашим задачам"
+msgstr "Перейти к Ñвоим обÑуждениÑм"
msgid "Go to your merge requests"
-msgstr "Перейти к вашим запроÑам на ÑлиÑние"
+msgstr "Перейти к Ñвоим запроÑам на ÑлиÑние"
msgid "Go to your projects"
-msgstr "Перейдите к вашим проектам"
+msgstr "Перейдити к Ñвоим проектам"
msgid "Go to your snippets"
-msgstr "Перейти к вашим Ñниппетам"
+msgstr "Перейти к Ñвоим Ñниппетам"
msgid "Goal of the changes and what reviewers should be aware of"
msgstr ""
@@ -13375,7 +13738,7 @@ msgid "GrafanaIntegration|Active"
msgstr ""
msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr ""
+msgstr "Ð’Ñтроить графики Grafana в обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ GitLab."
msgid "GrafanaIntegration|Enter the Grafana API Token."
msgstr ""
@@ -13390,7 +13753,7 @@ msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
msgid "Grant access"
-msgstr ""
+msgstr "ПредоÑтавить доÑтуп"
msgid "Graph"
msgstr "Диаграмма"
@@ -13452,9 +13815,6 @@ msgstr "Ðватар группы"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "ОпиÑание группы"
-
msgid "Group description (optional)"
msgstr "ОпиÑание группы (необÑзательно)"
@@ -13555,7 +13915,7 @@ msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
msgid "GroupActivityMetrics|Recent activity (last 90 days)"
-msgstr ""
+msgstr "ÐедавнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚ÑŒ (за поÑледние 90 дней)"
msgid "GroupImport|Failed to import group."
msgstr ""
@@ -13788,11 +14148,17 @@ 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 your group badges."
-msgstr "Изменить значки группы."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr "ИÑпользовать по умолчанию Ñборочные линии Auto DevOps Ð´Ð»Ñ Ð²Ñех проектов в Ñтой группе"
@@ -13815,9 +14181,6 @@ msgstr "ЕÑли видимоÑÑ‚ÑŒ родительÑкой группы ниж
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr "Сконфигурированные здеÑÑŒ интеграции будут автоматичеÑки применены ко вÑем проектам данной группы."
-msgid "GroupSettings|Learn more about badges."
-msgstr "Узнать больше о значках."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,8 +14208,8 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps будет запущена, еÑли не будет найден альтернативный файл конфигурации CI."
+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 ""
@@ -13878,6 +14241,9 @@ 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 "Ð’Ñ‹ можете перенеÑти Ñту группу только в группу, которой вы управлÑете."
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr "Создать группу"
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14092,10 +14485,10 @@ 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 ""
+msgstr "Вот вÑе ваши проекты в вашей группе, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‚Ð¾Ñ‚, который вы только что Ñоздали. Ð”Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° давайте взглÑнем на ваш индивидуальный учебный проект, который поможет вам узнать о GitLab в удобном темпе."
msgid "Here you will find recent merge request activity"
-msgstr "ЗдеÑÑŒ вы найдёте недавнюю активноÑÑ‚ÑŒ, ÑвÑзанную Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñами на ÑлиÑние"
+msgstr "ЗдеÑÑŒ вы найдёте поÑледние дейÑтвиÑ, ÑвÑзанные Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñами на ÑлиÑние"
msgid "Hi %{username}!"
msgstr "Привет, %{username}!"
@@ -14204,6 +14597,9 @@ msgstr "ОчиÑтка уÑпешно запущена"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ОчиÑтка, ÑкÑпорт, путь, перемещение, удаление, архивирование."
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "Как Ñто работает"
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14438,7 +14837,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "Import CSV"
-msgstr ""
+msgstr "Импорт CSV"
msgid "Import Projects from Gitea"
msgstr "Импорт проектов из Gitea"
@@ -14455,6 +14854,12 @@ msgstr "Импортировать из"
msgid "Import from Jira"
msgstr "Импортировать из Jira"
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "ВыполнÑетÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚"
@@ -14471,10 +14876,10 @@ msgid "Import members from another project"
msgstr "Импорт учаÑтников из другого проекта"
msgid "Import multiple repositories by uploading a manifest file."
-msgstr ""
+msgstr "Импортировать неÑколько репозиториев, загрузив файл манифеÑта."
msgid "Import project"
-msgstr ""
+msgstr "Импортировать проект"
msgid "Import project from"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr "Импорт репозиториев из GitHub"
msgid "Import repository"
msgstr "Импорт репозиториÑ"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr "Импорт запущен: %{importInitiator}"
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14585,7 +14991,7 @@ msgid "In %{time_to_now}"
msgstr ""
msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
+msgstr "Чтобы включить Службу поддержки Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра, Ñначала наÑтройте входÑщую Ñлектронную почту."
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
@@ -14594,11 +15000,14 @@ msgid "In progress"
msgstr "Ð’ процеÑÑе"
msgid "Incident"
-msgstr ""
+msgstr "Инцидент"
msgid "Incident Management Limits"
msgstr "Лимиты, ÑвÑзанные Ñ Ð£Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ инцидентами"
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,14 +15164,14 @@ 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 "Включает в ÑÐµÐ±Ñ Ñтруктуру в MVC, чтобы помочь вам начать работу."
+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 "Включает в ÑÐµÐ±Ñ Ñтруктуру MVC, Gem файлы, Rake файлы и многие другие, которые помогут вам начать работу."
+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 "Включает в ÑÐµÐ±Ñ Ñтруктуру MVC, mvnw и pom.xml, которые помогут вам начать работу."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
msgid "Incoming email"
msgstr ""
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr "ПредÑтавлÑем Ðналитику потока ÑозданиÑ
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr "ÐедейÑÑ‚Ð²Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ ÑÑылка Git"
-
msgid "Invalid Insights config file detected"
msgstr "Обнаружен неверный файл конфигурации Insights"
@@ -15204,7 +15619,7 @@ msgid "Investigate vulnerability: %{title}"
msgstr ""
msgid "Invitation"
-msgstr ""
+msgstr "Приглашение"
msgid "Invitation declined"
msgstr ""
@@ -15212,15 +15627,15 @@ msgstr ""
msgid "Invite"
msgstr "Приглашение"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "ПриглаÑить \"%{trimmed}\" по Ñлектронной почте"
msgid "Invite Members"
msgstr ""
-msgid "Invite another teammate"
-msgstr ""
-
msgid "Invite group"
msgstr "ПриглаÑить группу"
@@ -15230,9 +15645,6 @@ msgstr "ПриглаÑить учаÑтников"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15387,7 +15814,7 @@ msgid "IssuableStatus|duplicated"
msgstr ""
msgid "IssuableStatus|moved"
-msgstr ""
+msgstr "перемещено"
msgid "IssuableStatus|promoted"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¾Ð±Ñуждений"
@@ -15428,8 +15858,8 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
-msgstr "Шаблон обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ (необÑзательно)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
msgstr ""
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15513,7 +15943,7 @@ msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and Merge Requests"
-msgstr ""
+msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ ЗапроÑÑ‹ на ÑлиÑние"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr "ОбÑуждениÑми могут быть ошибки, задачи или идеи. Также, по обÑуждениÑм можно выполнÑÑ‚ÑŒ поиÑк и отбор."
@@ -15522,7 +15952,7 @@ msgid "Issues closed"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹"
msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
+msgstr "ОбÑуждениÑ, упомÑнутые в запроÑах на ÑлиÑние и коммитах в ветви по умолчанию, будут автоматичеÑки закрыты"
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñми, запроÑÑ‹ на ÑлиÑние Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñми и комментариÑми, метками, Ñтапами, Ñниппетами и другими объектами проекта"
@@ -15582,28 +16012,31 @@ msgid "It's you"
msgstr "Это вы"
msgid "Iteration"
-msgstr ""
+msgstr "ИтерациÑ"
msgid "Iteration changed to"
+msgstr "Ð˜Ñ‚ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð° на"
+
+msgid "Iteration lists not available with your current license"
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 ""
@@ -15615,7 +16048,7 @@ msgid "Jaeger URL"
msgstr ""
msgid "Jaeger tracing"
-msgstr ""
+msgstr "ТраÑÑировка Jaeger"
msgid "Jan"
msgstr "Янв."
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð´Ð»Ñ %{noteable_model_name} отключены."
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr "СиÑтема отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Jira"
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 "Пароль или API токен"
-msgid "JiraService|This feature requires a Premium plan."
-msgstr ""
-
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15885,7 +16321,7 @@ msgid "July"
msgstr "Июль"
msgid "Jump to next unresolved thread"
-msgstr ""
+msgstr "Перейти к Ñледующей нерешённой теме"
msgid "Jun"
msgstr "Июн."
@@ -15918,16 +16354,16 @@ msgid "Key: %{key}"
msgstr "Ключ: %{key}"
msgid "Keyboard shortcuts"
-msgstr ""
+msgstr "Ð¡Ð¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
msgid "KeyboardKey|Ctrl+"
msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
+msgstr "Глобальные ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
+msgstr "Показать/Ñкрыть панель производительноÑти"
msgid "Keys"
msgstr "Ключи"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr "ПоÑледнее поÑещение"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "Узнайте о GitLab"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "Узнайте, как %{link_start}внеÑти Ñвой вклад во вÑтроенные шаблоны%{link_end}"
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr "Подробнее об ÑоглаÑовании."
-
msgid "Learn more about custom project templates"
msgstr "Узнайте больше о пользовательÑких шаблонах проекта"
@@ -16257,6 +16699,9 @@ msgstr "Узнайте больше в"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "Подробнее в|документации по раÑпиÑаниÑм Ñборочных линий"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Покинуть"
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr "Загрузка Ñниппета"
@@ -16673,7 +17121,7 @@ msgid "Locks the discussion."
msgstr ""
msgid "Login with smartcard"
-msgstr ""
+msgstr "Вход Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñмарт-карты"
msgid "Logo was successfully removed."
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr "СЛИТО"
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr "МакÑимальный уровень доÑтупа"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17015,7 +17472,7 @@ msgid "Maximum import size (MB)"
msgstr ""
msgid "Maximum job timeout"
-msgstr ""
+msgstr "МакÑимальное Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð´Ð°Ð½Ð¸Ñ"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr "МакÑимальный тайм-аут Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐµÑ‚ значение, которое не может быть принÑто"
@@ -17095,6 +17552,12 @@ 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 ""
+
+msgid "Members listed as CODEOWNERS of affected files."
+msgstr ""
+
msgid "Members of %{group} can also merge into this branch: %{branch}"
msgstr ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr "СлиÑние"
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние %{iid}, Ñозданный %{authorName
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Подтверждение запроÑов на ÑлиÑние"
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr "ЗапроÑÑ‹ на ÑлиÑние"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "ЗапроÑÑ‹ на ÑлиÑние- Ñто меÑто, где можно предлагать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð½Ð¾Ñимые в проект, и обÑуждать Ñти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸"
@@ -17384,7 +17844,7 @@ msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "Ðе удалоÑÑŒ объединить коммиты. Это должно быть выполнено вручную."
msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
+msgstr "Перейти к Ñледующей нерешённой теме"
msgid "MergeRequests|Reply..."
msgstr "Ответить..."
@@ -17452,9 +17912,15 @@ 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 ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr "ÐаÑтройки Ð·ÐµÑ€ÐºÐ°Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð¾Ñтупны толÑ
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr "Отзеркаленные репозитории"
@@ -18169,10 +18629,10 @@ msgid "Move issue from one column of the board to another"
msgstr ""
msgid "Move selection down"
-msgstr ""
+msgstr "ПеремеÑтить выбор ниже"
msgid "Move selection up"
-msgstr ""
+msgstr "ПеремеÑтить выбор выше"
msgid "Move test case"
msgstr ""
@@ -18193,7 +18653,7 @@ msgid "Moved this issue to %{path_to_project}."
msgstr ""
msgid "Moves issue to %{label} column in the board."
-msgstr ""
+msgstr "Перемещает обÑуждение на доÑке в колонку %{label}."
msgid "Moves this issue to %{path_to_project}."
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr "Ðайдено неÑколько типов моделей: %{model_types}"
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18661,7 +19127,7 @@ msgid "New confidential issue title"
msgstr ""
msgid "New deploy key"
-msgstr ""
+msgstr "Ðовый ключ развёртываниÑ"
msgid "New directory"
msgstr "Ðовый каталог"
@@ -18681,6 +19147,12 @@ 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 "Ðовый токен доÑтупа Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ работоÑпоÑобноÑти Ñгенерирован!"
@@ -18694,10 +19166,10 @@ msgid "New issue title"
msgstr "Заголовок нового обÑуждениÑ"
msgid "New iteration"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð¸Ñ‚ÐµÑ€Ð°Ñ†Ð¸Ñ"
msgid "New iteration created"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð¸Ñ‚ÐµÑ€Ð°Ñ†Ð¸Ñ Ñоздана"
msgid "New label"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
@@ -18769,10 +19241,10 @@ msgid "Next commit"
msgstr "Следующий коммит"
msgid "Next file in diff"
-msgstr ""
+msgstr "Следующий файл в отличиÑÑ… (diff)"
msgid "Next unresolved discussion"
-msgstr ""
+msgstr "Следующее нерешённое обÑуждение"
msgid "Nickname"
msgstr "Ðикнейм"
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr "Ðет изменений"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18862,7 +19334,7 @@ msgid "No errors to display."
msgstr ""
msgid "No estimate or time spent"
-msgstr ""
+msgstr "Ðет оценочного или потраченного времени"
msgid "No file chosen"
msgstr "Файл не выбран"
@@ -18871,7 +19343,7 @@ msgid "No file hooks found."
msgstr ""
msgid "No file selected"
-msgstr ""
+msgstr "Файл не выбран"
msgid "No files"
msgstr "Ðет файлов"
@@ -18889,10 +19361,10 @@ msgid "No issues found"
msgstr ""
msgid "No iteration"
-msgstr ""
+msgstr "Ðет итераций"
msgid "No iterations to show"
-msgstr ""
+msgstr "Ðет итераций Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ"
msgid "No job log"
msgstr ""
@@ -18988,7 +19460,7 @@ msgid "No source selected"
msgstr ""
msgid "No stack trace for this error"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ ошибки недоÑтуна траÑÑировка Ñтека"
msgid "No starrers matched your search"
msgstr ""
@@ -19054,7 +19526,7 @@ msgid "Not all data has been processed yet, the accuracy of the chart for the se
msgstr "Были обработаны не вÑе данные, точноÑÑ‚ÑŒ графика Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ периода времени ограничена."
msgid "Not applicable to personal namespaced projects, which are deleted immediately on request."
-msgstr ""
+msgstr "Ðе применимо к проектам из личного проÑтранÑтва, удалÑемым непоÑредÑтвенно поÑле запроÑа."
msgid "Not available"
msgstr "ÐедоÑтупно"
@@ -19065,6 +19537,9 @@ msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ñ‹Ñ… проектов"
msgid "Not available for protected branches"
msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ð½Ñ‹Ñ… веток"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Ðе конфиденциально"
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr "Заметка"
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr "О, нет!"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "Сначала Ñтарые"
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19463,7 +20043,7 @@ msgid "One or more of your personal access tokens will expire in %{days_to_expir
msgstr "Срок дейÑÑ‚Ð²Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ или неÑкольких ваших токенов личного доÑтупа иÑтечёт через %{days_to_expire} дней или раньше."
msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
-msgstr ""
+msgstr "Только роли «Reporter» и выше на планах Premium / Silver и выше могут проÑматривать Ðналитику потока ценноÑти."
msgid "Only 1 appearances row can exist"
msgstr ""
@@ -19508,10 +20088,10 @@ msgid "Oops, are you sure?"
msgstr ""
msgid "Open"
-msgstr "Открыть"
+msgstr "Открыто"
msgid "Open Selection"
-msgstr ""
+msgstr "Открыть выбранное"
msgid "Open comment type dropdown"
msgstr ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr "Копировать команду yarn"
msgid "PackageRegistry|Copy yarn setup command"
msgstr "Копировать команду наÑтройки yarn"
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr "Удалить верÑию пакета"
@@ -19849,12 +20432,18 @@ msgstr "Команда NuGet"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
-msgstr "Команда pip"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
+msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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 "Команда pip"
+
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr ""
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Страницы"
@@ -20107,10 +20690,13 @@ msgstr "Путь необÑзательно должен быть абÑолют
msgid "Pause"
msgstr "ПриоÑтановить"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr "ПриоÑтановить репликацию"
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20165,7 +20751,7 @@ msgid "PerformanceBar|SQL queries"
msgstr ""
msgid "PerformanceBar|trace"
-msgstr ""
+msgstr "траÑÑировка"
msgid "Permissions"
msgstr "Права доÑтупа"
@@ -20179,6 +20765,9 @@ msgstr "РазрешениÑ, LFS, 2FA"
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 "Создание личного проекта запрещено. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором по данному вопроÑу"
@@ -20215,6 +20804,9 @@ msgstr "РаÑпиÑÐ°Ð½Ð¸Ñ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ñ‹Ñ… Линий"
msgid "Pipeline minutes quota"
msgstr "Квота иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ CI в минутах"
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ msgstr "Триггеры Ñборки"
msgid "Pipeline: %{status}"
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ:%{status}"
+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 "Ðналитика CI / CD"
@@ -20234,7 +20835,7 @@ msgid "PipelineCharts|Failed:"
msgstr "Ðеудача:"
msgid "PipelineCharts|Overall statistics"
-msgstr "СтатиÑтика"
+msgstr "ÐžÐ±Ñ‰Ð°Ñ ÑтатиÑтика"
msgid "PipelineCharts|Success ratio:"
msgstr "КоÑффициент уÑпеха:"
@@ -20242,7 +20843,7 @@ msgstr "КоÑффициент уÑпеха:"
msgid "PipelineCharts|Successful:"
msgstr "УÑпех:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 "У группы %{namespace_name} оÑталоÑÑŒ %{percentage}%% или менее минут на Shared Runner Pipeline. Как только они закончатÑÑ, новые Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð¸ Ñборочные линии проектов Ñтой группы переÑтанут выполнÑÑ‚ÑŒÑÑ."
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "ЗагружаютÑÑ Ñборочные линии"
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20612,7 +21237,7 @@ 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 ""
+msgstr "ПожалуйÑта, проверьте файл конфигурации, чтобы убедитьÑÑ, что набор диаграмм объÑвлен."
msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 "ПожалуйÑта введите правильное чиÑло"
@@ -20875,15 +21506,18 @@ msgstr ""
msgid "Prev"
msgstr "Пред."
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Запретить добавление новых учаÑтников в проектах Ñтой группы"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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 ""
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20915,10 +21549,10 @@ msgid "Previous Artifacts"
msgstr ""
msgid "Previous commit"
-msgstr ""
+msgstr "Предыдущий коммит"
msgid "Previous file in diff"
-msgstr ""
+msgstr "Предыдущий файл в отличиÑÑ… (diff)"
msgid "Previous unresolved discussion"
msgstr ""
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr "ОÑновной"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ msgstr ""
msgid "Profiles|@username"
msgstr "@username"
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ запланирована к удалению."
@@ -21163,6 +21803,9 @@ msgstr "Токен новоÑтной ленты уÑпешно Ñброшен"
msgid "Profiles|Full name"
msgstr "Полное имÑ"
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 "Положение и размер вашего нового аватара"
@@ -21493,9 +22139,6 @@ msgstr "Ð˜Ð¼Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr "Ð¡ÑƒÑ„Ñ„Ð¸ÐºÑ Ð¸Ð¼ÐµÐ½Ð¸ проекта - Ñто пользовательÑÐºÐ°Ñ Ñтрока, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ добавлена к пути проекта, и будет формировать Ð°Ð´Ñ€ÐµÑ email в Ñлужбе поддержки"
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 "ÐвтоматичеÑки разрешать обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ по запроÑу на ÑлиÑние, когда они ÑтановÑÑ‚ÑÑ Ð½ÐµÐ°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ð¼Ð¸"
@@ -21685,8 +22334,8 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr "РееÑÑ‚Ñ€ контейнеров"
-msgid "ProjectSettings|Customize your project badges."
-msgstr "ÐаÑтройте значки вашего проекта."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr "Отключить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "Каждый ÑлиÑние Ñоздает коммит ÑлиÑниÑ"
@@ -21754,9 +22406,6 @@ msgstr "ОбÑуждениÑ"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "Узнать больше о значках."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr "ПроÑÑ‚Ð°Ñ ÑиÑтема обÑуждений Ð´Ð»Ñ Ñтого проекта"
@@ -21793,6 +22442,9 @@ msgstr "Примечание: рееÑÑ‚Ñ€ контейнеров вÑегда Ð
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "Пакеты"
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21982,7 +22643,7 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22310,7 +22971,7 @@ 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 ""
+msgstr "Диаграммы ÑÐ³Ð¾Ñ€Ð°Ð½Ð¸Ñ Ð·Ð°Ð´Ð°Ñ‡ — Ñто визуальное предÑтавление прогреÑÑа в выполнении Ñтапа. Текущее ÑоÑтоÑние дел можно оценить буквально Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ взглÑда. Без них вам пришлоÑÑŒ бы ÑиÑтематизировать ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾Ð± Ñтапах и вручную Ñтроить графики, чтобы ощутить понимание прогреÑÑа такого же уровнÑ."
msgid "Promotions|Buy EE"
msgstr ""
@@ -22328,7 +22989,7 @@ msgid "Promotions|Contact your Administrator to upgrade your license."
msgstr ""
msgid "Promotions|Dismiss burndown charts promotion"
-msgstr ""
+msgstr "Убрать рекламу диаграмм ÑгораниÑ"
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -22340,7 +23001,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 "Узнать больше"
@@ -22373,7 +23034,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 ""
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,8 +23117,8 @@ msgstr "Защитить ветку"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
-msgstr "Отправки, менÑющие имена файлов, ÑоответÑтвующих файлу CODEOWNERS будут отклонены"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
msgstr "ТребуетÑÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ðµ от владельцев кода:"
@@ -22643,7 +23304,7 @@ 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 ""
+msgstr "Pushover облегчает получение мгновенных уведомлений на Android-уÑтройÑтвах, iPhone, iPad и деÑктопах."
msgid "PushoverService|See project %{project_full_name}"
msgstr "ПоÑмотреть проект %{project_full_name}"
@@ -22723,6 +23384,12 @@ 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 "Получать Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ наÑтроенных вручную Ñерверов Prometheus."
@@ -22741,6 +23408,9 @@ msgstr "Ðедавние дейÑÑ‚Ð²Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
msgid "Recent Searches Service is unavailable"
msgstr "ÐÐ¾Ð²Ð°Ñ Ñлужба поиÑка недоÑтупна"
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22794,7 +23464,7 @@ msgid "Regenerate instance ID"
msgstr ""
msgid "Regenerate key"
-msgstr ""
+msgstr "Создать ключ заново"
msgid "Regenerate recovery codes"
msgstr "Обновить коды воÑÑтановлениÑ"
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr "Удалить Runner"
msgid "Remove Zoom meeting"
msgstr "Удалить вÑтречу в Zoom"
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23026,7 +23699,7 @@ msgid "Remove group"
msgstr ""
msgid "Remove iteration"
-msgstr ""
+msgstr "Удалить итерацию"
msgid "Remove license"
msgstr ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23068,7 +23744,7 @@ msgid "Remove stage"
msgstr "Удалить Ñтап"
msgid "Remove time estimate"
-msgstr ""
+msgstr "Удалить оценку времени"
msgid "Remove user & report"
msgstr ""
@@ -23086,7 +23762,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 ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr "Удалён Ñтап %{milestone_reference}."
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "Удалено %{type} Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ %{id}"
@@ -23116,7 +23795,7 @@ msgid "Removed the due date."
msgstr ""
msgid "Removed time estimate."
-msgstr ""
+msgstr "Удалено оценочное времÑ."
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -23131,7 +23810,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 ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr "УдалÑет %{milestone_reference} Ñтап."
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr "УдалÑет вÑе метки."
@@ -23155,20 +23837,23 @@ msgid "Removes the due date."
msgstr "УдалÑет дату завершениÑ."
msgid "Removes time estimate."
-msgstr ""
+msgstr "УдалÑет оценочное времÑ."
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr "Удаление Ñтой группы также приведет к удалению вÑех дочерних проектов, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð°Ñ€Ñ…Ð¸Ð²Ð½Ñ‹Ðµ, а также их реÑурÑов."
msgid "Rename file"
-msgstr ""
+msgstr "Переименовать файл"
msgid "Rename folder"
-msgstr ""
+msgstr "Переименовать папку"
msgid "Rename/Move"
msgstr "Переименовать/перемеÑтить"
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr "Открыть заново"
@@ -23194,10 +23879,10 @@ msgid "Reopens this %{quick_action_target}."
msgstr ""
msgid "Repair authentication"
-msgstr ""
+msgstr "ВоÑÑтановить аутентификацию"
msgid "Replace"
-msgstr ""
+msgstr "Заменить"
msgid "Replace all label(s)"
msgstr "Заменить вÑе метки"
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Репозиторий"
@@ -23478,9 +24163,6 @@ msgstr ""
msgid "Request Access"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,8 +24205,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
-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 ""
@@ -23550,9 +24235,6 @@ msgstr "Требование %{reference} было открыто повторн
msgid "Requirement %{reference} has been updated"
msgstr "Требование %{reference} было обновлено"
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "Заголовок Ñ‚Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ может Ñодержать больше %{limit} Ñимволов."
@@ -23607,13 +24289,13 @@ msgid "Reset health check access token"
msgstr "СброÑить ключ доÑтупа проверки работоÑпоÑобноÑти"
msgid "Reset key"
-msgstr ""
+msgstr "Ð¡Ð±Ñ€Ð¾Ñ ÐºÐ»ÑŽÑ‡Ð°"
msgid "Reset runners registration token"
msgstr "СброÑить ключ региÑтрации обработчиков заданий"
msgid "Reset template"
-msgstr ""
+msgstr "Ð¡Ð±Ñ€Ð¾Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°"
msgid "Reset to project defaults"
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr "Ответ"
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr "Ответ не включает `service_desk_address`"
@@ -23690,6 +24366,9 @@ msgstr "Метрики откликов (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Метрики откликов (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23739,7 +24421,7 @@ msgid "Retry this job in order to create the necessary resources."
msgstr "Повторите Ñту задание, чтобы Ñоздать необходимые реÑурÑÑ‹."
msgid "Retry update"
-msgstr ""
+msgstr "Повторить попытку обновлениÑ"
msgid "Retry verification"
msgstr ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23807,7 +24492,7 @@ msgid "Reviewing (merge request !%{mergeRequestId})"
msgstr ""
msgid "Revoke"
-msgstr ""
+msgstr "Отозвать"
msgid "Revoked"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr "ЗапуÑкайте теÑÑ‚Ñ‹ Ð´Ð»Ñ Ñвоего кода в реал
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr "Runner токен"
@@ -23896,9 +24569,6 @@ msgstr "Обработчик заданий не был обновлен."
msgid "Runner was successfully updated."
msgstr "Обработчик заданий уÑпешно обновлен."
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr "Runner'Ñ‹"
@@ -23908,13 +24578,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr "Открытый ключ SSH"
msgid "SSL Verification:"
msgstr "Ð’ÐµÑ€Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ SSL:"
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24059,13 +24738,13 @@ msgid "Save %{name} size limits"
msgstr ""
msgid "Save Changes"
-msgstr ""
+msgstr "Сохранить изменениÑ"
msgid "Save Push Rules"
msgstr ""
msgid "Save application"
-msgstr ""
+msgstr "Сохранить приложение"
msgid "Save changes"
msgstr "Сохранить изменениÑ"
@@ -24106,10 +24785,10 @@ msgstr "Запланировано"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24119,7 +24798,7 @@ msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
msgid "Scheduling"
-msgstr ""
+msgstr "Планирование"
msgid "Scheduling Pipelines"
msgstr "Планирование Сборочных Линий"
@@ -24127,7 +24806,7 @@ msgstr "Планирование Сборочных Линий"
msgid "Scope"
msgstr "ОблаÑÑ‚ÑŒ"
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24149,10 +24828,10 @@ msgid "Scroll right"
msgstr "Прокрутить вправо"
msgid "Scroll to bottom"
-msgstr ""
+msgstr "Прокрутить к концу"
msgid "Scroll to top"
-msgstr ""
+msgstr "Прокрутить к началу"
msgid "Scroll up"
msgstr "Прокрутить вверх"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "ПоиÑк пользователей"
@@ -24277,6 +24959,9 @@ 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 "во вÑех GitLab"
@@ -24293,13 +24978,13 @@ msgid "SearchResults|Showing %{count} %{scope} for%{term_element}"
msgstr ""
msgid "SearchResults|Showing %{count} %{scope} for%{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "Показано %{count} %{scope} длÑ%{term_element} в ваших личных Ñниппетах и Ñниппетах проекта"
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 ""
+msgstr "Показано %{from} - %{to} из %{count} %{scope} длÑ%{term_element} в ваших личных Ñниппетах и Ñниппетах проекта"
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr "Отчет о безопаÑноÑти уÑтарел. ЗапуÑтите %{newPipelineLinkStart}новую Ñборочную линию%{newPipelineLinkEnd} в целевой ветке (%{targetBranchName})"
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24797,7 +25497,7 @@ msgid "Select a reason"
msgstr "Выберите причину"
msgid "Select a repository"
-msgstr ""
+msgstr "Выберите репозиторий"
msgid "Select a template repository"
msgstr ""
@@ -24809,7 +25509,7 @@ msgid "Select a timezone"
msgstr "Выбор временной зоны"
msgid "Select all"
-msgstr ""
+msgstr "Выбрать вÑе"
msgid "Select an existing Kubernetes cluster or create a new one"
msgstr "Выбрать ÑущеÑтвующий клаÑтер Kubernetes или Ñоздать новый"
@@ -24977,7 +25677,7 @@ msgid "Send message"
msgstr ""
msgid "Send report"
-msgstr ""
+msgstr "Отправить отчёт"
msgid "Send usage data"
msgstr "ОтправлÑÑ‚ÑŒ данные об иÑпользовании"
@@ -24997,9 +25697,6 @@ msgstr "РазделÑйте теги запÑтыми."
msgid "September"
msgstr "СентÑбрь"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr "и"
@@ -25099,14 +25796,17 @@ msgstr ""
msgid "Service Desk"
msgstr "Служба поддержки"
-msgid "Service Desk is enabled but not yet active"
+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 ""
+msgstr "Служба поддержки не включена"
msgid "Service Desk is not supported"
-msgstr ""
+msgstr "Служба поддержки не поддерживаетÑÑ"
msgid "Service Templates"
msgstr "Шаблоны Служб"
@@ -25129,11 +25829,8 @@ 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 template for issue descriptions."
-msgstr "УÑтановите шаблон по умолчанию Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñаний обÑуждений."
-
-msgid "Set a number of approvals required, the approvers and other approval 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 "УÑтановите пароль в Ñвоем аккаунте, чтобы отправлÑÑ‚ÑŒ или получать код через %{protocol}."
@@ -25154,7 +25851,7 @@ msgid "Set instance-wide template repository"
msgstr ""
msgid "Set iteration"
-msgstr ""
+msgstr "Задать итерацию"
msgid "Set limit to 0 to allow any file size."
msgstr ""
@@ -25199,7 +25896,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 ""
@@ -25214,10 +25911,10 @@ msgid "Set the timeout in seconds to send a secondary node status to the primary
msgstr ""
msgid "Set time estimate"
-msgstr ""
+msgstr "Задать оценку времени"
msgid "Set time estimate to %{time_estimate}."
-msgstr ""
+msgstr "Задать оценку времени в %{time_estimate}."
msgid "Set up CI/CD"
msgstr "ÐаÑтройка CI/CD"
@@ -25310,13 +26007,13 @@ 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}."
msgid "Sets time estimate to %{time_estimate}."
-msgstr ""
+msgstr "Задаёт оценку времени в %{time_estimate}."
msgid "Sets weight to %{weight}."
msgstr "УÑтанавливает приоритет на %{weight}."
@@ -25330,9 +26027,6 @@ msgstr "ÐаÑтройки"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr "Показывать вÑех учаÑтников"
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Показать поÑледнюю верÑию"
@@ -25767,6 +26467,9 @@ 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 "Что-то пошло не так Ñ Ð½Ð°ÑˆÐµÐ¹ Ñтороны"
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr "Что-то пошло не так при архивировании требованиÑ."
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr "Что-то пошло не так при повторном открытии требованиÑ."
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26209,10 +26921,10 @@ msgid "Squash commits"
msgstr "Объединить иÑторию коммитов"
msgid "Stack trace"
-msgstr ""
+msgstr "ТраÑÑировка Ñтека"
msgid "Stacktrace snippet"
-msgstr ""
+msgstr "Сниппет траÑÑировки Ñтека"
msgid "Stage"
msgstr "Этап"
@@ -26305,7 +27017,7 @@ msgid "Start merge train when pipeline succeeds"
msgstr ""
msgid "Start search"
-msgstr ""
+msgstr "Ðачать поиÑк"
msgid "Start the Runner!"
msgstr "ЗапуÑтить GitLab Runner!"
@@ -26346,13 +27058,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr "Будет запущен %{startsIn}"
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "Опубликовать (UTC)"
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "СиÑтема"
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 "ТеÑÑ‚"
@@ -27315,8 +28090,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr "СпаÑибо за покупку!"
-msgid "Thanks! Don't show me this again"
-msgstr "СпаÑибо! Больше не показывать"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27330,6 +28105,9 @@ 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] "%{type} Ñодержит Ñледующую ошибку:"
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 "ИÑточник данных подключен, но нет данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ. %{documentationLink}"
@@ -27533,9 +28317,6 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, коÑ
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr "Лицензионный ключ недейÑтвителен. УдоÑтоверьтеÑÑŒ, что он Ñовпадает Ñ Ñ‚ÐµÐ¼, что вы получили от GitLab Inc."
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальный размер файла - %{size}."
-msgid "The maximum file size allowed is 200KB."
-msgstr "МакÑимально допуÑтимый размер файла ÑоÑтавлÑет 200 Кбайт."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr "Конфликты ÑлиÑÐ½Ð¸Ñ Ð´Ð»Ñ Ñтого запроÑа на ÑлиÑние не могут быть разрешены Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ GitLab. ПожалуйÑта, попробуйте разрешить их локально."
@@ -27651,7 +28429,7 @@ msgid "The repository for this project does not exist."
msgstr "Репозиторий Ð´Ð»Ñ Ñтого проекта не ÑущеÑтвует."
msgid "The repository for this project is empty"
-msgstr "Репозиторий Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ проекта пуÑтой"
+msgstr "Репозиторий данного проекта пуÑÑ‚"
msgid "The repository is being updated..."
msgstr ""
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27942,7 +28726,7 @@ msgid "There was an error fetching the variables."
msgstr "Произошла ошибка при извлечении переменных."
msgid "There was an error fetching value stream analytics stages."
-msgstr ""
+msgstr "Произошла ошибка при получении Ñтапов аналитики потока значений."
msgid "There was an error gathering the chart data"
msgstr "При Ñборе данных диаграммы произошла ошибка"
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28023,13 +28810,13 @@ 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 ""
+msgstr "Произошла ошибка при получении данных аналитики потока ценноÑти."
msgid "There was an error while fetching value stream analytics duration data."
-msgstr ""
+msgstr "Произошла ошибка при получении аналитичеÑких данных о длительноÑти потока ценноÑти."
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -28079,6 +28866,9 @@ msgstr "Этот ÑкземплÑÑ€ GitLab пока не предоÑтавлÑÐ
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-лицензиÑ."
+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 ""
@@ -28215,7 +29005,7 @@ msgid "This field is required."
msgstr ""
msgid "This group"
-msgstr ""
+msgstr "Эта группа"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28419,7 +29212,7 @@ msgid "This project does not belong to a group and can therefore not make use of
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 ""
+msgstr "Ð’ Ñтом проекте не включена %{service_desk_link_start}Служба поддержки%{service_desk_link_end}, поÑтому пользователь, Ñоздавший обÑуждение, переÑтанет получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте о новых дейÑтвиÑÑ…."
msgid "This project does not have a wiki homepage yet"
msgstr ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28491,7 +29290,7 @@ msgid "This user has no identities"
msgstr ""
msgid "This user has previously committed to the %{name} project."
-msgstr ""
+msgstr "Этот пользователь ранее отправлÑл коммиты в проект %{name}."
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 "ÐŸÑ€Ð¸Ð²ÐµÐ´ÐµÐ½Ð½Ð°Ñ Ð½Ð¸Ð¶Ðµ диаграмма — Ñто обзор входÑщего трафика вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² том виде, в котором его отÑлеживает Web Application Firewall (WAF). ОбратитеÑÑŒ к документации, чтобы узнать, как получить доÑтуп к журналам WAF и увидеть, какой тип вредоноÑного трафика пытаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ доÑтуп к приложению. СÑылка на документацию также доÑтупна по щелчку на иконке \"?\" Ñ€Ñдом Ñ Ð½Ð¸Ð¶ÐµÑ€Ð°Ñположенным заголовком."
+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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28641,7 +29476,7 @@ msgid "Time between merge request creation and merge/close"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ñозданием запроÑа ÑлиÑÐ½Ð¸Ñ Ð¸ ÑлиÑнием / закрытием"
msgid "Time estimate"
-msgstr ""
+msgstr "Оценочное времÑ"
msgid "Time from first comment to last commit"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ первого ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð´Ð¾ поÑледнего коммита"
@@ -28686,7 +29521,7 @@ msgid "TimeTracking|%{startTag}Spent: %{endTag}%{timeSpentHumanReadable}"
msgstr "%{startTag}Затрачено: %{endTag}%{timeSpentHumanReadable}"
msgid "TimeTracking|Estimated:"
-msgstr "Запланировано:"
+msgstr "Оценочно:"
msgid "TimeTracking|Over by %{timeRemainingHumanReadable}"
msgstr ""
@@ -28943,7 +29778,7 @@ msgid "To only use CI/CD features for an external repository, choose %{strong_op
msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
-msgstr ""
+msgstr "Чтобы открыть Jaeger и Ñ Ð»Ñ‘Ð³ÐºÐ¾Ñтью проÑматривать траÑÑировку из GitLab, привÑжите Ñтраницу %{link} к Ñвоему Ñерверу"
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29057,10 +29892,10 @@ msgid "Toggle sidebar"
msgstr "Переключить боковую панель"
msgid "Toggle the Performance Bar"
-msgstr ""
+msgstr "Показать/Ñкрыть панель производительноÑти"
msgid "Toggle this dialog"
-msgstr ""
+msgstr "Скрыть/показать Ñто окно"
msgid "Toggle thread"
msgstr ""
@@ -29120,7 +29955,7 @@ msgid "Total days to completion"
msgstr ""
msgid "Total issues"
-msgstr ""
+msgstr "Ð’Ñего обÑуждений"
msgid "Total memory (GB)"
msgstr ""
@@ -29144,7 +29979,7 @@ msgid "TotalRefCountIndicator|1000+"
msgstr ""
msgid "Tracing"
-msgstr ""
+msgstr "ТраÑÑировка"
msgid "Track groups of issues that share a theme, across projects and milestones"
msgstr "Следите за обÑуждениÑми, Ñгруппированными по темам, Ñразу из неÑкольких проектов и Ñтапов"
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 "СобытиÑ"
@@ -29285,7 +30163,7 @@ msgid "Triggers can force a specific branch or tag to get rebuilt with an API ca
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
-msgstr ""
+msgstr "УÑтранÑйте неполадки и Ñледите за ÑоÑтоÑнием Ñвоего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ помощи траÑÑировки"
msgid "Try again"
msgstr "Попробовать Ñнова"
@@ -29330,7 +30208,7 @@ msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user
msgstr ""
msgid "Turn on Service Desk"
-msgstr ""
+msgstr "Включить Ñлужбу поддержки"
msgid "Turn on usage ping"
msgstr ""
@@ -29468,7 +30346,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 "Ðевозможно Ñохранить ваши изменениÑ. ПожалуйÑта, попробуйте ещё раз."
@@ -29549,7 +30427,7 @@ msgid "Unknown encryption strategy: %{encrypted_strategy}!"
msgstr "ÐеизвеÑтный алгоритм шифрованиÑ: %{encrypted_strategy}!"
msgid "Unknown format"
-msgstr ""
+msgstr "ÐеизвеÑтный формат"
msgid "Unknown response text"
msgstr "ÐеизвеÑтный текÑÑ‚ ответа"
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr "Убрать из избранного"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "ОтпиÑатьÑÑ"
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr "До"
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29696,10 +30577,10 @@ msgid "Update it"
msgstr "Обновить Ñто"
msgid "Update iteration"
-msgstr ""
+msgstr "Обновить итерацию"
msgid "Update now"
-msgstr ""
+msgstr "Обновить ÑейчаÑ"
msgid "Update username"
msgstr ""
@@ -29713,8 +30594,8 @@ msgstr "Обновите ваши URL-адреÑа из закладок, поÑ
msgid "Update your group name, description, avatar, and visibility."
msgstr "Обновить наименование вашей группы, её опиÑание, аватар и видимоÑÑ‚ÑŒ."
-msgid "Update your project name, topics, description and avatar."
-msgstr "Обновите название Ñвоего проекта, теги, опиÑание и логотип."
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr "Ðе удаетÑÑ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ñ‚ÑŒ проект, потому что он Ñодержит теги рееÑтра контейнеров!"
@@ -29728,7 +30609,7 @@ msgstr "Ðовый уровень видимоÑти не разрешен!"
msgid "UpdateProject|Project could not be updated!"
msgstr "Проект не может быть обновлен!"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr "Улучшите Ñвой тарифный план, чтобы иÑпо
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29975,7 +30853,7 @@ msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%
msgstr "ИÑпользуйте %{code_start}::%{code_end}, чтобы Ñоздать %{link_start}набор Ñелективных меток%{link_end} (например, %{code_start}priority::1%{code_end})"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
+msgstr "ИÑпользуйте Службу поддержки Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ пользователÑми (например, Ð´Ð»Ñ Ð¾ÑущеÑÑ‚Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ клиентов) через Ñлектронную почту непоÑредÑтвенно в GitLab"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "ИÑпользуйте одноразовый аутентификатор Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ð° вашем мобильном уÑтройÑтве или компьютере, чтобы включить двухфакторную аутентификацию (2FA)."
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr "Пользователи были уÑпешно добавлены."
@@ -30332,34 +31213,34 @@ msgid "Value"
msgstr ""
msgid "Value Stream"
-msgstr ""
+msgstr "Поток ценноÑти"
msgid "Value Stream Analytics"
-msgstr ""
+msgstr "Ðналитика потока ценноÑти"
msgid "Value Stream Analytics can help you determine your team’s velocity"
-msgstr ""
+msgstr "Ðналитика потока ценноÑти поможет вам определить ÑкороÑÑ‚ÑŒ работы вашей команды"
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "Ðналитика потока ценноÑти дает общее предÑтавление о том, Ñколько времени в вашем проекте занимает путь от идеи до выпуÑка."
msgid "Value Stream Name"
-msgstr ""
+msgstr "Ðазвание потока ценноÑти"
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
-msgstr ""
+msgstr "У Ð½Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñтого Ñтапа."
msgid "ValueStreamAnalytics|%{days}d"
-msgstr ""
+msgstr "%{days}дн"
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
-msgstr ""
+msgstr "Медианное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ первого коммита до Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð¾Ð±ÑуждениÑ."
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
-msgstr ""
+msgstr "Медианное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ его закрытиÑ."
msgid "ValueStream|The Default Value Stream cannot be deleted"
-msgstr ""
+msgstr "Поток ценноÑти по умолчанию не может быть удалён"
msgid "Variable"
msgstr ""
@@ -30505,7 +31386,7 @@ msgid "View log"
msgstr ""
msgid "View merge request"
-msgstr ""
+msgstr "ПроÑмотреть Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "View open merge request"
msgstr "ПроÑмотреть открытый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr "ОпиÑание"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr "ПроÑтранÑтво имён"
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хотите увидеть данные? ОбратитеÑÑŒ к админиÑтратору за доÑтупом."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr "Предупреждение:"
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31024,7 +31932,7 @@ msgid "Weekday"
msgstr "День недели"
msgid "Weeks"
-msgstr ""
+msgstr "Ðедели"
msgid "Weight"
msgstr "Приоритет"
@@ -31039,7 +31947,7 @@ msgid "Welcome to GitLab"
msgstr ""
msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr ""
+msgstr "Добро пожаловать в GitLab%{br_tag}%{name}!"
msgid "Welcome to GitLab, %{first_name}!"
msgstr "Добро пожаловать в GitLab, %{first_name}!"
@@ -31100,13 +32008,13 @@ msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{
msgstr ""
msgid "When:"
-msgstr ""
+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 be an approver?"
-msgstr "Кто может быть утверждающим?"
+msgid "Who can approve?"
+msgstr ""
msgid "Who can see this group?"
msgstr ""
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 "Ð’Ñ‹ можете разрешить конфликт ÑлиÑниÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð»Ð¸Ð±Ð¾ интерактивный режим, выбрав кнопки %{use_ours} или %{use_theirs}, либо отредактировав файлы напрÑмую. Примите Ñти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² %{branch_name}"
@@ -31582,9 +32496,6 @@ msgstr "Ð’Ñ‹ можете проÑмотреть ваши аккаунты чаÑ
msgid "You can set up as many Runners as you need to run your jobs."
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 "Вы можете указать уровень уведомлений в каждой группе или в проекте."
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ необходимых прав Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð² из групповой Ñинхронизации LDAP."
-
msgid "You don't have any U2F devices registered yet."
msgstr "У Ð²Ð°Ñ ÐµÑ‰Ñ‘ нет зарегиÑтрированных уÑтройÑтв U2F."
@@ -31682,7 +32593,7 @@ 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 ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к аналитике потока ценноÑти данной группы"
msgid "You have a license that activates at a future date. Please see the License History table below."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr "Ваше уÑтройÑтво U2F зарегиÑтрировано!"
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32009,7 +32935,7 @@ msgid "Your account uses dedicated credentials for the \"%{group_name}\" group a
msgstr "Ваш аккаунт иÑпользует Ñпециальные учетные данные Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹ \"%{group_name}\" и может быть обновлен только через SSO."
msgid "Your applications (%{size})"
-msgstr ""
+msgstr "Ваши Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (%{size})"
msgid "Your authorized applications"
msgstr ""
@@ -32065,6 +32991,9 @@ msgstr ""
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr "Ваше уÑтройÑтво было уÑпешно наÑтроено! Дайте ему Ð¸Ð¼Ñ Ð¸ зарегиÑтрируйте его на Ñервере GitLab."
+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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr "назначить ÑебÑ"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr "под угрозой"
@@ -32261,9 +33199,15 @@ msgstr "Ð¸Ð¼Ñ Ð²ÐµÑ‚Ð²Ð¸"
msgid "by"
msgstr "по"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 "невозможно изменить, еÑли в личном проекте еÑÑ‚ÑŒ метки рееÑтра контейнеров."
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Ð’Ñе проекты"
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32702,7 +33655,7 @@ msgid "group"
msgstr "группа"
msgid "group members"
-msgstr ""
+msgstr "учаÑтники группы"
msgid "groups"
msgstr ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32793,7 +33752,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 "не Ñ Ñлектронной почты, которой вы владеете"
@@ -32897,6 +33856,9 @@ 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] "Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -33286,7 +34248,7 @@ msgid "nounSeries|%{firstItem} and %{lastItem}"
msgstr ""
msgid "nounSeries|%{item}"
-msgstr ""
+msgstr "%{item}"
msgid "nounSeries|%{item}, %{nextItem}"
msgstr ""
@@ -33307,7 +34269,7 @@ msgid "opened %{timeAgoString} by %{user}"
msgstr ""
msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
+msgstr "открыто %{timeAgoString} пользователем %{user} в Jira"
msgid "opened %{timeAgo}"
msgstr ""
@@ -33348,16 +34310,16 @@ msgid "per day"
msgstr "в день"
msgid "personal access token"
-msgstr ""
+msgstr "личный токен доÑтупа"
msgid "personal access tokens"
-msgstr ""
+msgstr "личные токены доÑтупа"
msgid "pipeline"
msgstr "ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
-msgstr ""
+msgstr "pod_name может Ñодержать только латинÑкие буквы в нижнем региÑтре, цифры, знаки '-' и '.', а также должен начинатьÑÑ Ð¸ заканчиватьÑÑ Ð±ÑƒÐºÐ²Ð¾Ð¹ или цифрой."
msgid "pod_name cannot be larger than %{max_length} chars"
msgstr "pod_name не может быть больше, чем %{max_length} Ñимволов"
@@ -33370,10 +34332,10 @@ msgstr[2] "балов"
msgstr[3] "балов"
msgid "private"
-msgstr ""
+msgstr "приватный"
msgid "private key does not match certificate."
-msgstr ""
+msgstr "закрытый ключ не ÑоответÑтвует Ñертификату."
msgid "processing"
msgstr ""
@@ -33398,13 +34360,13 @@ msgid "project bots cannot be added to other groups / projects"
msgstr ""
msgid "project is read-only"
-msgstr ""
+msgstr "проект доÑтупен только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
msgid "project members"
msgstr ""
msgid "project name"
-msgstr ""
+msgstr "название проекта"
msgid "projects"
msgstr "проекты"
@@ -33413,7 +34375,7 @@ msgid "quick actions"
msgstr "быÑтрые дейÑтвиÑ"
msgid "recent activity"
-msgstr ""
+msgstr "недавнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚ÑŒ"
msgid "register"
msgstr ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "название тега"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
@@ -33585,7 +34538,7 @@ msgid "this document"
msgstr "Ñтот документ"
msgid "time summary"
-msgstr ""
+msgstr "Ñводка по времени"
msgid "to automatically add approvers based on file paths and file types."
msgstr ""
@@ -33664,10 +34617,10 @@ msgstr ""
msgid "vulnerability"
msgid_plural "vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "уÑзвимоÑÑ‚ÑŒ"
+msgstr[1] "уÑзвимоÑти"
+msgstr[2] "уÑзвимоÑтей"
+msgstr[3] "уÑзвимоÑтей"
msgid "vulnerability|Add a comment"
msgstr ""
@@ -33715,5 +34668,5 @@ msgid "yaml invalid"
msgstr "неверный YAML"
msgid "your settings"
-msgstr ""
+msgstr "ваши наÑтройки"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 6b3f842ac61..46326486ed6 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: 2020-12-03 08:12\n"
+"PO-Revision-Date: 2021-01-08 22:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 4249a695aab..60a537ec8db 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: 2020-12-03 08:19\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -917,6 +926,27 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1080,9 +1110,15 @@ 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 ""
@@ -1353,28 +1389,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1386,6 +1419,9 @@ 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 ""
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1422,6 +1461,9 @@ 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 ""
@@ -1440,13 +1482,16 @@ 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."
+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."
+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"
@@ -1455,10 +1500,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 ""
@@ -1491,13 +1545,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1539,6 +1596,9 @@ 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 ""
@@ -2134,6 +2194,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3017,6 +3062,9 @@ 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 ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 ""
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,7 +3533,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 ""
@@ -3569,7 +3629,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3726,13 +3786,13 @@ msgstr[3] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4027,6 +4087,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4045,12 +4111,18 @@ 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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4088,6 +4163,9 @@ 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 ""
@@ -4134,9 +4212,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,10 +4368,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4317,10 +4392,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4440,12 +4515,21 @@ 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 ""
@@ -4455,13 +4539,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4476,15 +4560,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4524,9 +4602,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,10 +4747,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4924,6 +5035,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5044,10 +5176,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5077,9 +5209,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 ""
@@ -5149,6 +5302,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 ""
@@ -5311,13 +5485,16 @@ 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 were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5872,6 +6055,18 @@ 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 ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7874,6 +8096,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8175,9 +8397,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8241,6 +8460,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8418,45 +8718,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ 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 ""
@@ -9097,9 +9379,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9577,9 +9856,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9589,6 +9865,9 @@ 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 ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10289,6 +10622,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ 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 ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 ""
@@ -11027,9 +11387,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11135,9 +11492,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11273,9 +11627,18 @@ 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 ""
@@ -11390,22 +11753,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 ""
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 ""
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,7 +13587,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13452,9 +13815,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13788,10 +14148,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13815,9 +14181,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,7 +14208,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13878,6 +14241,9 @@ 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 ""
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,13 +15164,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15212,13 +15627,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15230,9 +15645,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15428,7 +15858,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16257,6 +16699,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17452,9 +17912,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 ""
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19849,10 +20432,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20107,10 +20690,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20179,6 +20765,9 @@ 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 ""
@@ -20215,6 +20804,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ 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 ""
@@ -20242,7 +20843,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 ""
@@ -20875,13 +21506,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ 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 ""
@@ -21163,6 +21803,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 ""
@@ -21493,9 +22139,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 ""
@@ -21685,7 +22334,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21754,9 +22406,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21793,6 +22442,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21982,7 +22643,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,7 +23117,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22723,6 +23384,12 @@ 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 ""
@@ -22741,6 +23408,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23169,6 +23851,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23478,9 +24163,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,7 +24205,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23690,6 +24366,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23896,9 +24569,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23908,13 +24578,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,10 +24785,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24127,7 +24806,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24277,6 +24959,9 @@ 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 ""
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25099,6 +25796,9 @@ 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 ""
@@ -25129,10 +25829,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25330,9 +26027,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25767,6 +26467,9 @@ 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 ""
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26346,13 +27058,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27315,7 +28090,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27330,6 +28105,9 @@ 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] ""
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 ""
@@ -27533,9 +28317,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28079,6 +28866,9 @@ 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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 ""
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,7 +30594,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29728,7 +30609,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,7 +32013,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 ""
@@ -31582,9 +32496,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ 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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32261,9 +33199,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 175328ad42a..7ee3e7426cc 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: 2020-12-03 08:19\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -917,6 +926,27 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1080,9 +1110,15 @@ 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 ""
@@ -1353,28 +1389,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1386,6 +1419,9 @@ 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 ""
@@ -1413,6 +1449,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1422,6 +1461,9 @@ 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 ""
@@ -1440,13 +1482,16 @@ 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."
+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."
+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"
@@ -1455,10 +1500,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 ""
@@ -1491,13 +1545,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1539,6 +1596,9 @@ 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 ""
@@ -2134,6 +2194,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2621,9 +2687,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3017,6 +3062,9 @@ 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 ""
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 ""
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,7 +3533,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3491,6 +3548,9 @@ 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 ""
@@ -3569,7 +3629,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3726,13 +3786,13 @@ msgstr[3] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4027,6 +4087,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4045,12 +4111,18 @@ 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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -4088,6 +4163,9 @@ 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 ""
@@ -4134,9 +4212,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4293,10 +4368,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4317,10 +4392,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4440,12 +4515,21 @@ 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 ""
@@ -4455,13 +4539,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4476,15 +4560,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4524,9 +4602,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,10 +4747,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4924,6 +5035,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -5044,10 +5176,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5077,9 +5209,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 ""
@@ -5149,6 +5302,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5281,15 +5437,33 @@ 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|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 ""
@@ -5311,13 +5485,16 @@ 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 were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5872,6 +6055,18 @@ 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 ""
@@ -6979,10 +7174,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7385,6 +7598,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7874,6 +8096,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8175,9 +8397,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8241,6 +8460,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8334,6 +8631,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8418,45 +8718,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -9049,6 +9328,9 @@ 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 ""
@@ -9097,9 +9379,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9577,9 +9856,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9589,6 +9865,9 @@ 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 ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10190,9 +10529,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10247,9 +10583,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10289,6 +10622,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10316,12 +10652,18 @@ 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 ""
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ 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 ""
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ 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 ""
@@ -11027,9 +11387,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11135,9 +11492,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11273,9 +11627,18 @@ 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 ""
@@ -11390,22 +11753,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11627,6 +11990,9 @@ 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 ""
@@ -11645,6 +12011,12 @@ 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 ""
@@ -11672,9 +12044,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11825,6 +12194,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11994,16 +12360,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 ""
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12252,12 +12621,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12927,6 +13287,12 @@ 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 ""
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,7 +13587,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13452,9 +13815,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13788,10 +14148,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13815,9 +14181,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13845,7 +14208,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13878,6 +14241,9 @@ 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 ""
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14503,6 +14908,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,13 +15164,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14776,6 +15185,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15212,13 +15627,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15230,9 +15645,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15413,6 +15840,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15428,7 +15858,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15467,7 +15897,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15671,6 +16104,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15695,19 +16131,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16134,6 +16570,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16188,9 +16627,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16230,9 +16675,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16257,6 +16699,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16609,6 +17054,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16696,6 +17144,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17452,9 +17912,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 ""
@@ -18819,7 +19291,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -19083,6 +19558,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19320,6 +19798,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19849,10 +20432,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19954,7 +20543,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -20107,10 +20690,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20179,6 +20765,9 @@ 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 ""
@@ -20215,6 +20804,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ 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 ""
@@ -20242,7 +20843,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 ""
@@ -20665,6 +21293,9 @@ 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 ""
@@ -20875,13 +21506,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -21061,6 +21698,9 @@ 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 ""
@@ -21163,6 +21803,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 ""
@@ -21493,9 +22139,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21652,12 +22295,18 @@ 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 ""
@@ -21685,7 +22334,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21754,9 +22406,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21793,6 +22442,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21901,12 +22553,21 @@ 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|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 ""
@@ -21925,9 +22586,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21982,7 +22643,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,7 +23084,7 @@ 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"
+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"
@@ -22456,7 +23117,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22723,6 +23384,12 @@ 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 ""
@@ -22741,6 +23408,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23094,6 +23770,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23139,6 +23818,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23169,6 +23851,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23478,9 +24163,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,7 +24205,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23663,12 +24345,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23690,6 +24366,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23896,9 +24569,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23908,13 +24578,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 ""
@@ -24043,9 +24725,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,10 +24785,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -24127,7 +24806,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24277,6 +24959,9 @@ 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 ""
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ 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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -25099,6 +25796,9 @@ 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 ""
@@ -25129,10 +25829,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25330,9 +26027,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25767,6 +26467,9 @@ 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 ""
@@ -25803,7 +26506,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ 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 ""
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,7 +26641,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26346,13 +27058,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27315,7 +28090,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27330,6 +28105,9 @@ 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] ""
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 ""
@@ -27533,9 +28317,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 ""
@@ -27998,6 +28782,9 @@ 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 ""
@@ -28079,6 +28866,9 @@ 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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 ""
@@ -28475,9 +29277,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 ""
@@ -29632,6 +30510,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,7 +30594,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29728,7 +30609,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30780,6 +31667,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 ""
@@ -30810,6 +31706,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30843,6 +31742,9 @@ 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 ""
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,7 +32013,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 ""
@@ -31582,9 +32496,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31606,6 +32517,9 @@ 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 ""
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 ""
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ 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 ""
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32261,9 +33199,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32306,6 +33250,9 @@ 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 ""
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32501,6 +33451,9 @@ 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] ""
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] ""
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 4fe2aefd997..3f57f5ee2ea 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: 2020-12-03 08:20\n"
+"PO-Revision-Date: 2021-01-08 23:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 13a34ee1d3f..52d2fd272cc 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: 2020-12-03 08:13\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -415,12 +415,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -850,6 +859,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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] ""
+msgstr[2] ""
+
+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] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1009,9 +1036,15 @@ 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 ""
@@ -1264,28 +1297,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1297,6 +1327,9 @@ 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 ""
@@ -1324,6 +1357,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1333,6 +1369,9 @@ 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 ""
@@ -1351,13 +1390,16 @@ 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."
+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."
+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"
@@ -1366,10 +1408,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1381,9 +1426,15 @@ 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 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 ""
+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 ""
@@ -1402,13 +1453,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1450,6 +1504,9 @@ 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 ""
@@ -2044,6 +2101,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2053,6 +2113,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2530,9 +2593,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2596,15 +2656,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2632,9 +2686,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2704,10 +2755,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2773,12 +2824,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2863,9 +2908,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2926,6 +2968,9 @@ 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 ""
@@ -3064,7 +3109,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3100,6 +3145,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ 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 ""
@@ -3334,9 +3385,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3358,6 +3406,9 @@ 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 ""
@@ -3367,6 +3418,9 @@ 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 ""
@@ -3385,7 +3439,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3400,6 +3454,9 @@ 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 ""
@@ -3478,7 +3535,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3631,13 +3688,13 @@ msgstr[2] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3658,6 +3715,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3760,9 +3820,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3931,6 +3988,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3949,12 +4012,18 @@ 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 ""
@@ -3967,6 +4036,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3991,6 +4063,9 @@ 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 ""
@@ -4036,9 +4111,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4195,10 +4267,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4219,10 +4291,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4264,7 +4339,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4327,9 +4402,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4342,12 +4414,21 @@ 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 ""
@@ -4357,13 +4438,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4378,15 +4459,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4399,9 +4477,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4426,9 +4501,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4513,22 +4585,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4567,10 +4645,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4624,6 +4711,30 @@ 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 ""
@@ -4654,9 +4765,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4825,6 +4933,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4918,7 +5044,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4945,10 +5074,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4978,9 +5107,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5029,6 +5155,30 @@ 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 ""
@@ -5050,6 +5200,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5182,15 +5335,33 @@ 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|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 ""
@@ -5212,13 +5383,16 @@ 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 were successfully made."
+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}."
@@ -5230,9 +5404,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5500,9 +5671,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5761,6 +5938,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5773,6 +5953,18 @@ 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 ""
@@ -6880,10 +7072,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7156,6 +7348,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7285,6 +7495,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7375,13 +7588,13 @@ msgstr[2] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7390,18 +7603,42 @@ 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 policy:"
+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 ""
@@ -7429,9 +7666,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7441,9 +7675,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7468,6 +7699,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7486,9 +7720,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7564,16 +7795,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7609,12 +7834,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7771,6 +7990,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8005,15 +8227,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8071,9 +8290,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8137,6 +8353,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8230,6 +8524,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8314,45 +8611,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8599,6 +8869,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8665,6 +8938,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8713,6 +8992,9 @@ 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 ""
@@ -8920,18 +9202,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8944,6 +9220,9 @@ 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 ""
@@ -8992,9 +9271,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9466,9 +9742,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9478,6 +9751,9 @@ 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 ""
@@ -9679,22 +9955,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9703,6 +10018,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9712,18 +10030,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9994,6 +10327,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10078,9 +10414,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10135,9 +10468,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10177,6 +10507,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10204,12 +10537,18 @@ 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 ""
@@ -10243,6 +10582,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10312,10 +10654,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10396,6 +10738,9 @@ 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 ""
@@ -10465,6 +10810,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10480,9 +10828,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10516,6 +10861,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10552,9 +10900,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10597,6 +10942,9 @@ 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 ""
@@ -10738,6 +11086,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10855,6 +11206,12 @@ 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 ""
@@ -10915,9 +11272,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11023,9 +11377,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11161,9 +11512,18 @@ 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 ""
@@ -11278,22 +11638,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11332,9 +11692,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11374,6 +11731,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11515,6 +11875,9 @@ 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 ""
@@ -11533,6 +11896,12 @@ 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 ""
@@ -11560,9 +11929,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11713,6 +12079,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11773,9 +12142,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11869,9 +12235,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11881,16 +12244,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12004,6 +12364,9 @@ 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 ""
@@ -12106,6 +12469,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12139,12 +12505,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12196,9 +12556,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12217,6 +12574,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12346,9 +12706,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12814,6 +13171,12 @@ 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 ""
@@ -12889,9 +13252,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13111,7 +13471,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13339,9 +13699,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13675,10 +14032,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13702,9 +14065,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13732,7 +14092,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13765,6 +14125,9 @@ 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 ""
@@ -13843,6 +14206,9 @@ 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 ""
@@ -13852,22 +14218,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14089,6 +14479,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14263,6 +14656,9 @@ 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 ""
@@ -14338,6 +14734,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14386,6 +14788,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14446,19 +14851,16 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14482,6 +14884,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14638,13 +15043,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14659,6 +15064,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14908,6 +15316,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14992,9 +15406,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15094,13 +15505,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15112,9 +15523,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15184,6 +15592,24 @@ 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 ""
@@ -15241,9 +15667,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15295,6 +15718,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15310,7 +15736,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15349,7 +15775,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15469,6 +15895,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15553,6 +15982,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15577,19 +16009,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16015,6 +16447,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16069,9 +16504,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16111,9 +16552,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16138,6 +16576,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16483,6 +16924,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16570,6 +17014,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16807,6 +17254,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16828,6 +17278,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16969,6 +17422,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17101,9 +17560,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17164,6 +17620,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17179,9 +17638,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17326,9 +17782,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17344,9 +17806,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17911,9 +18370,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18097,9 +18553,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18232,6 +18685,9 @@ 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 ""
@@ -18244,6 +18700,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18253,6 +18712,9 @@ 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 ""
@@ -18550,6 +19012,12 @@ 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 ""
@@ -18688,7 +19156,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18934,6 +19402,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18952,6 +19423,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19189,6 +19663,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19210,27 +19687,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19246,9 +19801,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19267,6 +19834,15 @@ 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 ""
@@ -19561,6 +20137,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19570,10 +20149,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19591,7 +20167,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19651,6 +20227,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19717,10 +20296,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19822,7 +20407,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19834,18 +20419,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19975,10 +20554,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20047,6 +20629,9 @@ 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 ""
@@ -20083,6 +20668,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20095,6 +20683,15 @@ 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 ""
@@ -20110,7 +20707,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20215,9 +20812,15 @@ 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 ""
@@ -20233,6 +20836,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20281,6 +20887,18 @@ 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 ""
@@ -20296,6 +20914,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20509,6 +21130,9 @@ 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 ""
@@ -20533,6 +21157,9 @@ 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 ""
@@ -20743,13 +21370,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20761,7 +21391,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20794,6 +21424,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20929,6 +21562,9 @@ 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 ""
@@ -21031,6 +21667,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21079,6 +21718,9 @@ 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 ""
@@ -21361,9 +22003,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21520,12 +22159,18 @@ 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 ""
@@ -21553,7 +22198,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21574,6 +22219,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21622,9 +22270,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21661,6 +22306,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21769,12 +22417,21 @@ 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|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 ""
@@ -21793,9 +22450,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21808,6 +22462,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21850,7 +22507,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22291,7 +22948,7 @@ 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"
+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"
@@ -22324,7 +22981,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22591,6 +23248,12 @@ 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 ""
@@ -22609,6 +23272,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22714,7 +23380,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22837,15 +23506,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22924,6 +23593,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22960,6 +23632,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23035,6 +23713,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23242,6 +23923,9 @@ 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 ""
@@ -23254,7 +23938,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23263,9 +23947,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23341,9 +24022,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23386,7 +24064,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23413,9 +24094,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23524,12 +24202,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23551,6 +24223,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23572,6 +24247,9 @@ 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 ""
@@ -23632,6 +24310,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23725,21 +24406,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23755,9 +24424,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23767,13 +24433,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23851,6 +24520,15 @@ 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 ""
@@ -23902,9 +24580,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23965,10 +24640,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23986,7 +24661,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24109,6 +24784,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24136,6 +24814,9 @@ 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 ""
@@ -24277,16 +24958,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24400,9 +25081,15 @@ 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 ""
@@ -24487,6 +25174,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24562,6 +25252,12 @@ 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 ""
@@ -24844,9 +25540,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24946,6 +25639,9 @@ 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 ""
@@ -24976,10 +25672,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25177,9 +25870,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25219,6 +25909,9 @@ 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 ""
@@ -25240,6 +25933,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25249,9 +25945,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25288,6 +25981,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25612,6 +26308,9 @@ 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 ""
@@ -25648,7 +26347,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25675,6 +26377,9 @@ 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 ""
@@ -25735,7 +26440,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25774,7 +26482,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26191,13 +26899,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26218,6 +26929,9 @@ 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 ""
@@ -26236,6 +26950,9 @@ 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 ""
@@ -26473,6 +27190,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26749,6 +27469,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26977,9 +27703,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26989,12 +27730,30 @@ 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 ""
@@ -27007,9 +27766,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27157,7 +27928,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27172,6 +27943,9 @@ 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] ""
@@ -27184,6 +27958,9 @@ 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 ""
@@ -27250,6 +28027,9 @@ 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 ""
@@ -27373,9 +28153,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27394,9 +28171,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27664,6 +28438,9 @@ 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 ""
@@ -27760,6 +28537,9 @@ 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 ""
@@ -27838,6 +28618,9 @@ 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 ""
@@ -27919,6 +28702,9 @@ 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 ""
@@ -28216,6 +29002,9 @@ 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 ""
@@ -28300,6 +29089,15 @@ 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 ""
@@ -28315,9 +29113,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28390,12 +29185,33 @@ 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 ""
@@ -28411,6 +29227,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28423,12 +29242,21 @@ 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 ""
@@ -28438,7 +29266,7 @@ 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."
+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"
@@ -28447,6 +29275,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29056,12 +29887,21 @@ 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] ""
+msgstr[2] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29080,6 +29920,39 @@ 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 Gold 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 Gold 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 ""
@@ -29470,6 +30343,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29494,7 +30370,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29551,7 +30427,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29566,7 +30442,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29608,9 +30484,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30121,6 +30994,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30562,6 +31438,9 @@ 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 ""
@@ -30589,6 +31468,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30616,6 +31498,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30634,6 +31522,9 @@ 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 ""
@@ -30646,6 +31537,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30679,6 +31573,9 @@ 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 ""
@@ -30781,6 +31678,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30817,6 +31717,9 @@ 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 ""
@@ -30940,7 +31843,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31318,6 +32221,9 @@ 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 ""
@@ -31408,6 +32314,9 @@ 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 ""
@@ -31417,9 +32326,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31441,6 +32347,9 @@ 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 ""
@@ -31477,9 +32386,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31552,6 +32458,9 @@ 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 ""
@@ -31561,6 +32470,9 @@ 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 ""
@@ -31594,6 +32506,9 @@ 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 ""
@@ -31753,6 +32668,9 @@ 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 ""
@@ -31825,6 +32743,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31900,6 +32821,9 @@ 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 ""
@@ -31921,6 +32845,9 @@ 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 ""
@@ -31978,6 +32905,9 @@ 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 ""
@@ -32077,6 +33007,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32095,9 +33028,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32140,6 +33079,9 @@ 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 ""
@@ -32179,6 +33121,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32335,6 +33280,9 @@ 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] ""
@@ -32542,6 +33490,12 @@ 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 ""
@@ -32725,6 +33679,9 @@ 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] ""
@@ -33385,18 +34342,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 8e4a96d0f3c..76a9042199a 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: 2020-12-03 08:20\n"
+"PO-Revision-Date: 2021-01-08 23:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -415,12 +415,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -850,6 +859,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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] ""
+msgstr[2] ""
+
+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] ""
+msgstr[2] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -1009,9 +1036,15 @@ 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 ""
@@ -1264,28 +1297,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1297,6 +1327,9 @@ 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 ""
@@ -1324,6 +1357,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1333,6 +1369,9 @@ 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 ""
@@ -1351,13 +1390,16 @@ 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."
+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."
+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"
@@ -1366,10 +1408,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1381,9 +1426,15 @@ 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 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 ""
+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 ""
@@ -1402,13 +1453,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1450,6 +1504,9 @@ 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 ""
@@ -2044,6 +2101,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2053,6 +2113,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2530,9 +2593,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2596,15 +2656,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2632,9 +2686,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2704,10 +2755,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2773,12 +2824,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2863,9 +2908,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2926,6 +2968,9 @@ 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 ""
@@ -3064,7 +3109,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3100,6 +3145,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ 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 ""
@@ -3334,9 +3385,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3358,6 +3406,9 @@ 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 ""
@@ -3367,6 +3418,9 @@ 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 ""
@@ -3385,7 +3439,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3400,6 +3454,9 @@ 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 ""
@@ -3478,7 +3535,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3631,13 +3688,13 @@ msgstr[2] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3658,6 +3715,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3760,9 +3820,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3931,6 +3988,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3949,12 +4012,18 @@ 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 ""
@@ -3967,6 +4036,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3991,6 +4063,9 @@ 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 ""
@@ -4036,9 +4111,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4195,10 +4267,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4219,10 +4291,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4264,7 +4339,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4327,9 +4402,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4342,12 +4414,21 @@ 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 ""
@@ -4357,13 +4438,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4378,15 +4459,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4399,9 +4477,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4426,9 +4501,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4513,22 +4585,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4567,10 +4645,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4624,6 +4711,30 @@ 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 ""
@@ -4654,9 +4765,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4825,6 +4933,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4918,7 +5044,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4945,10 +5074,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4978,9 +5107,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5029,6 +5155,30 @@ 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 ""
@@ -5050,6 +5200,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5182,15 +5335,33 @@ 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|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 ""
@@ -5212,13 +5383,16 @@ 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 were successfully made."
+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}."
@@ -5230,9 +5404,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5500,9 +5671,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5761,6 +5938,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5773,6 +5953,18 @@ 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 ""
@@ -6880,10 +7072,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7156,6 +7348,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7285,6 +7495,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7375,13 +7588,13 @@ msgstr[2] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7390,18 +7603,42 @@ 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 policy:"
+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 ""
@@ -7429,9 +7666,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7441,9 +7675,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7468,6 +7699,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7486,9 +7720,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7564,16 +7795,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7609,12 +7834,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7771,6 +7990,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -8005,15 +8227,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -8071,9 +8290,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8137,6 +8353,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8230,6 +8524,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8314,45 +8611,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8599,6 +8869,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8665,6 +8938,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8713,6 +8992,9 @@ 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 ""
@@ -8920,18 +9202,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8944,6 +9220,9 @@ 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 ""
@@ -8992,9 +9271,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9466,9 +9742,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9478,6 +9751,9 @@ 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 ""
@@ -9679,22 +9955,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9703,6 +10018,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9712,18 +10030,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9994,6 +10327,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -10078,9 +10414,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10135,9 +10468,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10177,6 +10507,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10204,12 +10537,18 @@ 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 ""
@@ -10243,6 +10582,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10312,10 +10654,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10396,6 +10738,9 @@ 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 ""
@@ -10465,6 +10810,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10480,9 +10828,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10516,6 +10861,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10552,9 +10900,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10597,6 +10942,9 @@ 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 ""
@@ -10738,6 +11086,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10855,6 +11206,12 @@ 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 ""
@@ -10915,9 +11272,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -11023,9 +11377,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11161,9 +11512,18 @@ 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 ""
@@ -11278,22 +11638,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11332,9 +11692,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11374,6 +11731,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11515,6 +11875,9 @@ 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 ""
@@ -11533,6 +11896,12 @@ 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 ""
@@ -11560,9 +11929,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11713,6 +12079,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11773,9 +12142,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11869,9 +12235,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11881,16 +12244,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12004,6 +12364,9 @@ 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 ""
@@ -12106,6 +12469,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12139,12 +12505,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12196,9 +12556,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12217,6 +12574,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12346,9 +12706,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12814,6 +13171,12 @@ 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 ""
@@ -12889,9 +13252,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13111,7 +13471,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13339,9 +13699,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13675,10 +14032,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13702,9 +14065,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13732,7 +14092,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13765,6 +14125,9 @@ 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 ""
@@ -13843,6 +14206,9 @@ 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 ""
@@ -13852,22 +14218,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14089,6 +14479,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14263,6 +14656,9 @@ 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 ""
@@ -14338,6 +14734,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14386,6 +14788,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14446,19 +14851,16 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14482,6 +14884,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14638,13 +15043,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14659,6 +15064,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14908,6 +15316,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14992,9 +15406,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -15094,13 +15505,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -15112,9 +15523,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15184,6 +15592,24 @@ 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 ""
@@ -15241,9 +15667,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15295,6 +15718,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15310,7 +15736,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15349,7 +15775,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15469,6 +15895,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15553,6 +15982,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15577,19 +16009,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -16015,6 +16447,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -16069,9 +16504,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -16111,9 +16552,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16138,6 +16576,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16483,6 +16924,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16570,6 +17014,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16807,6 +17254,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16828,6 +17278,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16969,6 +17422,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17101,9 +17560,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17164,6 +17620,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17179,9 +17638,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17326,9 +17782,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17344,9 +17806,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17911,9 +18370,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -18097,9 +18553,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18232,6 +18685,9 @@ 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 ""
@@ -18244,6 +18700,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18253,6 +18712,9 @@ 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 ""
@@ -18550,6 +19012,12 @@ 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 ""
@@ -18688,7 +19156,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18934,6 +19402,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18952,6 +19423,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19189,6 +19663,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19210,27 +19687,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19246,9 +19801,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19267,6 +19834,15 @@ 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 ""
@@ -19561,6 +20137,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19570,10 +20149,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19591,7 +20167,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19651,6 +20227,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19717,10 +20296,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+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|Pipeline %{link} triggered %{datetime} by %{author}"
+msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
@@ -19822,7 +20407,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19834,18 +20419,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19975,10 +20554,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -20047,6 +20629,9 @@ 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 ""
@@ -20083,6 +20668,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20095,6 +20683,15 @@ 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 ""
@@ -20110,7 +20707,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20215,9 +20812,15 @@ 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 ""
@@ -20233,6 +20836,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20281,6 +20887,18 @@ 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 ""
@@ -20296,6 +20914,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20509,6 +21130,9 @@ 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 ""
@@ -20533,6 +21157,9 @@ 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 ""
@@ -20743,13 +21370,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20761,7 +21391,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20794,6 +21424,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20929,6 +21562,9 @@ 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 ""
@@ -21031,6 +21667,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21079,6 +21718,9 @@ 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 ""
@@ -21361,9 +22003,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21520,12 +22159,18 @@ 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 ""
@@ -21553,7 +22198,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21574,6 +22219,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21622,9 +22270,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21661,6 +22306,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21769,12 +22417,21 @@ 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|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 ""
@@ -21793,9 +22450,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21808,6 +22462,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21850,7 +22507,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22291,7 +22948,7 @@ 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"
+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"
@@ -22324,7 +22981,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22591,6 +23248,12 @@ 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 ""
@@ -22609,6 +23272,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22714,7 +23380,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22837,15 +23506,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22924,6 +23593,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22960,6 +23632,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -23005,6 +23680,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -23035,6 +23713,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23242,6 +23923,9 @@ 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 ""
@@ -23254,7 +23938,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23263,9 +23947,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23341,9 +24022,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23386,7 +24064,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23413,9 +24094,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23524,12 +24202,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23551,6 +24223,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23572,6 +24247,9 @@ 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 ""
@@ -23632,6 +24310,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23725,21 +24406,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23755,9 +24424,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23767,13 +24433,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23851,6 +24520,15 @@ 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 ""
@@ -23902,9 +24580,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23965,10 +24640,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23986,7 +24661,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -24109,6 +24784,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -24136,6 +24814,9 @@ 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 ""
@@ -24277,16 +24958,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24400,9 +25081,15 @@ 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 ""
@@ -24487,6 +25174,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24562,6 +25252,12 @@ 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 ""
@@ -24844,9 +25540,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24946,6 +25639,9 @@ 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 ""
@@ -24976,10 +25672,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25177,9 +25870,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25219,6 +25909,9 @@ 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 ""
@@ -25240,6 +25933,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25249,9 +25945,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25288,6 +25981,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25612,6 +26308,9 @@ 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 ""
@@ -25648,7 +26347,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25675,6 +26377,9 @@ 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 ""
@@ -25735,7 +26440,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25774,7 +26482,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26191,13 +26899,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26218,6 +26929,9 @@ 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 ""
@@ -26236,6 +26950,9 @@ 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 ""
@@ -26473,6 +27190,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26749,6 +27469,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26977,9 +27703,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26989,12 +27730,30 @@ 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 ""
@@ -27007,9 +27766,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -27157,7 +27928,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27172,6 +27943,9 @@ 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] ""
@@ -27184,6 +27958,9 @@ 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 ""
@@ -27250,6 +28027,9 @@ 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 ""
@@ -27373,9 +28153,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27394,9 +28171,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27664,6 +28438,9 @@ 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 ""
@@ -27760,6 +28537,9 @@ 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 ""
@@ -27838,6 +28618,9 @@ 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 ""
@@ -27919,6 +28702,9 @@ 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 ""
@@ -28216,6 +29002,9 @@ 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 ""
@@ -28300,6 +29089,15 @@ 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 ""
@@ -28315,9 +29113,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28390,12 +29185,33 @@ 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 ""
@@ -28411,6 +29227,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28423,12 +29242,21 @@ 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 ""
@@ -28438,7 +29266,7 @@ 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."
+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"
@@ -28447,6 +29275,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29056,12 +29887,21 @@ 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] ""
+msgstr[2] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29080,6 +29920,39 @@ 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 Gold 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 Gold 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 ""
@@ -29470,6 +30343,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29494,7 +30370,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29551,7 +30427,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29566,7 +30442,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29608,9 +30484,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -30121,6 +30994,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30562,6 +31438,9 @@ 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 ""
@@ -30589,6 +31468,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30616,6 +31498,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30634,6 +31522,9 @@ 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 ""
@@ -30646,6 +31537,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30679,6 +31573,9 @@ 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 ""
@@ -30781,6 +31678,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30817,6 +31717,9 @@ 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 ""
@@ -30940,7 +31843,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31318,6 +32221,9 @@ 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 ""
@@ -31408,6 +32314,9 @@ 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 ""
@@ -31417,9 +32326,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31441,6 +32347,9 @@ 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 ""
@@ -31477,9 +32386,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31552,6 +32458,9 @@ 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 ""
@@ -31561,6 +32470,9 @@ 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 ""
@@ -31594,6 +32506,9 @@ 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 ""
@@ -31753,6 +32668,9 @@ 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 ""
@@ -31825,6 +32743,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31900,6 +32821,9 @@ 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 ""
@@ -31921,6 +32845,9 @@ 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 ""
@@ -31978,6 +32905,9 @@ 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 ""
@@ -32077,6 +33007,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -32095,9 +33028,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -32140,6 +33079,9 @@ 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 ""
@@ -32179,6 +33121,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32335,6 +33280,9 @@ 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] ""
@@ -32542,6 +33490,12 @@ 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 ""
@@ -32725,6 +33679,9 @@ 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] ""
@@ -33385,18 +34342,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 324df6a59ac..af54a79c8f0 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: 2020-12-03 08:20\n"
+"PO-Revision-Date: 2021-01-08 23:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 704d652a81b..a68a0d39f94 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: 2020-12-03 08:12\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 874baf45f33..10ac0aabb5b 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: 2020-12-03 08:17\n"
+"PO-Revision-Date: 2021-01-08 23:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -79,18 +79,18 @@ msgstr ""
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Onay"
+msgstr[1] "%d Onay"
msgid "%d Other"
msgid_plural "%d Others"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d DiÄŸer"
+msgstr[1] "%d DiÄŸer"
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Paket"
+msgstr[1] "%d Paket"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
@@ -157,8 +157,8 @@ msgstr "%d iÅŸlem"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tamamlanmış konu"
+msgstr[1] "%d tamamlanmış konu"
msgid "%d contribution"
msgid_plural "%d contributions"
@@ -267,8 +267,8 @@ msgstr[1] "%d yorum daha"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d açık konu"
+msgstr[1] "%d açık konu"
msgid "%d pending comment"
msgid_plural "%d pending comments"
@@ -359,12 +359,21 @@ msgstr "%{address} geçersiz bir IP adresi aralığıdır"
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 "%{author_link} yazdı:"
msgid "%{authorsName}'s thread"
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)."
msgstr ""
@@ -783,6 +792,21 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Ä°ÅŸlem"
msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Ä°ÅŸlem"
+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 "%{strong_start}%{human_size}%{strong_end} Dosya"
@@ -938,9 +962,15 @@ msgstr "(%{mrCount} birleÅŸtirildi)"
msgid "(%{value}) has already been taken"
msgstr "(%{value}) zaten alınmış"
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(DeÄŸiÅŸiklik yok)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(ilerlemeyi kontrol et)"
@@ -1175,29 +1205,26 @@ msgstr ":%{startLine} satırından %{endLine} satırına"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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 "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab özelliklerine sahip bir Hexo sitesi."
+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 "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab özelliklerine sahip bir Hugo sitesi."
+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 "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab özelliklerine sahip bir Jekyll sitesi."
+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 ""
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ 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 maximum of %{count} participants can be added"
+msgstr ""
+
msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ msgstr "Yeni bir kimliğe bürünme belirteci oluşturuldu."
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 "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab özelliklerine sahip bir düz bir HTML sitesi."
+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 "Bir platform deÄŸeri web, mobil veya uygulama olabilir."
-msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools."
+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"
@@ -1277,11 +1316,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Android uygulamalarıyla kullanım için kullanıma-hazır bir şablon."
+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 ready-to-go template for use with iOS Swift apps."
-msgstr "iOS Swift uygulamalarıyla kullanım için kullanıma-hazır bir şablon."
+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 ""
@@ -1292,9 +1334,15 @@ msgstr "Harici depolama isteğini tanımlayan güvenli bir erişim anahtarı."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
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."
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 "Bu dala yazma yetkisi olan kullanıcı bu seçeneği seçti"
@@ -1313,14 +1361,17 @@ msgstr "API Erişim Anahtarı"
msgid "AWS Access Key"
msgstr "AWS Erişim Anahtarı"
-msgid "AWS Access Key. Only required if not using role instance credentials"
+msgid "AWS Access Key. Only required if not using role instance credentials"
msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS Gizli Erişim Anahtarı"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "AWS Gizli Erişim Anahtarı. Yalnızca rol örneği kimlik bilgileri kullanılmıyorsa gereklidir"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "Ä°ptal"
@@ -1361,6 +1412,9 @@ msgstr "LDAP hesabınız için erişim reddedildi."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Erişim reddedildi! Lütfen bu depoya dağıtım anahtarlarını ekleyebileceğinizi doğrulayın."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "EriÅŸim bitiÅŸ tarihi"
@@ -1954,6 +2008,9 @@ msgstr "Tüm projelere entegrasyon ayarlarını uygula"
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr "Yeni projeler için paylaşılan çalıştırıcıları etkinleştir"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Ortam değişkenleri öntanımlı olarak korunur"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "Genel Ayarlar'a Git"
@@ -2439,9 +2499,6 @@ msgstr "Yok"
msgid "AlertManagement|Open"
msgstr "Aç"
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr "Opsgenie etkinleÅŸtirildi"
-
msgid "AlertManagement|Please try again."
msgstr "Lütfen tekrar deneyin."
@@ -2505,15 +2562,9 @@ msgstr "Bilinmeyen"
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr "Bütün dallar"
msgid "All changes are committed"
msgstr "Tüm değişiklikler işlendi"
-msgid "All default stages are currently visible"
-msgstr "Tüm varsayılan aşamalar şu anda görünür"
-
msgid "All email addresses will be used to identify your commits."
msgstr "Tüm e-posta adresleri işlemlerinizi tanımlamak için kullanılacaktır."
@@ -2835,6 +2874,9 @@ msgstr "Grup sahiplerinin LDAP ile ilgili ayarları yönetmesine izin ver"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Git erişimi için yalnızca seçili protokollerin kullanılmasına izin ver."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "Bir hata oluÅŸtu"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ msgstr "Bildirim aboneliÄŸini deÄŸiÅŸtirirken bir sorun meydana geldi"
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 "Sorun ağırlığı güncellenirken bir hata oluştu"
@@ -3021,6 +3066,9 @@ msgstr ""
msgid "An error occurred while adding formatted title for epic"
msgstr "Epik için biçimlendirilmiş başlık eklenirken bir hata oluştu"
+msgid "An error occurred while authorizing your role"
+msgstr ""
+
msgid "An error occurred while checking group path. Please refresh and try again."
msgstr ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr "Vekiller kaydedilirken bir hata oluÅŸtu"
@@ -3267,6 +3312,9 @@ msgstr "Bildirim aboneliÄŸi iptal edilirken bir hata oluÅŸtu."
msgid "An error occurred while updating approvers"
msgstr "Onaylama sırasında güncelleme yapılırken bir hata oluştu"
+msgid "An error occurred while updating assignees."
+msgstr ""
+
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3276,6 +3324,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Yorum güncellenirken bir hata oluştu"
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
msgid "An error occurred while updating the milestone."
msgstr ""
@@ -3294,7 +3345,7 @@ msgstr "Bir hata oluştu. Lütfen tekrar deneyin."
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ msgstr "Bir sorun zaten var"
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 "Kimliği doğrulanmamış bir kullanıcı"
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr "Herhangi bir etiket"
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,15 +3590,15 @@ msgstr[1] "%{membersCount} tarafından %{count} onay gerekli"
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Onaylayanlar"
msgid "ApprovalRule|Name"
msgstr "Ä°sim"
-msgid "ApprovalRule|No. approvals required"
-msgstr "Onay gerekli deÄŸil"
-
msgid "ApprovalRule|Rule name"
msgstr "Kural adı"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr "Bu %{typeOfComment} silmek istediÄŸinizden emin misiniz?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "Bu panoyu silmek istediÄŸinizden emin misiniz?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Bu cihazı silmek istediğinizden emin misiniz? Bu işlem geri alınamaz."
@@ -3835,6 +3889,12 @@ msgstr "Etiket tanımla"
msgid "Assign milestone"
msgstr "Kilometre taşı ata"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Bu dönüm noktasına bazı sorunları atayın."
@@ -3853,12 +3913,18 @@ msgstr "Kendinizi bu soruna atayın"
msgid "Assigned %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} atandı."
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Atanan sorunlar"
msgid "Assigned Merge Requests"
msgstr "Atanan Karşılaştırma İstekleri"
+msgid "Assigned projects"
+msgstr ""
+
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Bana atanan"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Vekil"
@@ -3894,6 +3963,9 @@ msgstr "Atananlar"
msgid "Assigns %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} atar."
+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 ""
@@ -3938,9 +4010,6 @@ msgstr "Denetim Etkinlikleri"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr "Denetim Günlüğü"
-
msgid "AuditLogs|(removed)"
msgstr "(kaldırıldı)"
@@ -4038,7 +4107,7 @@ msgid "Author: %{author_name}"
msgstr ""
msgid "Authored %{timeago}"
-msgstr "%{timeago} yazıldı"
+msgstr "%{timeago} oluÅŸturuldu"
msgid "Authored %{timeago} by %{author}"
msgstr "%{author} tarafından %{timeago} oluşturuldu"
@@ -4097,12 +4166,12 @@ msgstr "Yedekli, bekleyen iş hatlarını otomatik olarak iptal et"
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 "Otomatik DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr ""
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Otomatik DevOps belgeleri"
@@ -4121,10 +4190,13 @@ msgstr "%{link_to_documentation} adresinden daha fazla bilgi edinin"
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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr "Let's Encrypt kullanarak otomatik sertifika yönetimi"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr "Arkaplan rengi"
msgid "Badges"
msgstr "Rozetler"
-msgid "Badges|A new badge was added."
-msgstr "Yeni bir rozet eklendi."
-
msgid "Badges|Add badge"
msgstr "Rozet ekle"
@@ -4244,12 +4313,21 @@ msgstr "Rozet resim bağlantısı"
msgid "Badges|Badge image preview"
msgstr "Rozet resmi önizlemesi"
+msgid "Badges|Badge saved."
+msgstr ""
+
msgid "Badges|Delete badge?"
msgstr "Rozet silinsin mi?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr "Rozet resmi silinemedi, lütfen daha sonra tekrar deneyin."
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
msgid "Badges|Group Badge"
msgstr "Grup Rozeti"
@@ -4259,15 +4337,15 @@ msgstr "Bağlantı"
msgid "Badges|Name"
msgstr "Ä°sim"
+msgid "Badges|New badge added."
+msgstr ""
+
msgid "Badges|No badge image"
msgstr "Rozet resmi yok"
msgid "Badges|No image to preview"
msgstr "Önizleme için resim yok"
-msgid "Badges|Please fill in a valid URL"
-msgstr "Lütfen geçerli bir URL girin"
-
msgid "Badges|Project Badge"
msgstr "Proje Rozeti"
@@ -4280,15 +4358,12 @@ msgstr "DeÄŸiÅŸiklikleri kaydet"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Rozetin kaydedilmesi başarısız oldu, lütfen girilen URL'leri kontrol edin ve tekrar deneyin."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Rozet silindi."
-msgid "Badges|The badge was saved."
-msgstr "Rozet kaydedildi."
-
msgid "Badges|This group has no badges"
msgstr "Bu grubun rozeti yok"
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Rozetleriniz"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "örn. %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Balsamiq dosyası yüklenemedi."
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Dikkatli olun. Projenin isim alanını değiştirmek, istenmeyen yan etkilere neden olabilir."
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Yükselt"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,12 +4543,21 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
-msgid "Board scope"
-msgstr "Pano kapsamı"
-
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "Pano kapsamı, bu panoyu ziyaret eden kişilere hangi sorunların gösterileceğini belirler"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
msgid "Boards"
msgstr "Panolar"
@@ -4525,6 +4609,30 @@ msgstr "GeniÅŸlet"
msgid "Boards|View scope"
msgstr "Kapsamı görüntüle"
+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 ""
@@ -4555,9 +4663,6 @@ msgstr "Dal adı"
msgid "Branch not loaded - %{branchId}"
msgstr "Dal yüklü değil - %{branchId}"
-msgid "Branch prefix"
-msgstr "Dal öneki"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Dallarda ara"
@@ -4726,6 +4831,24 @@ msgstr "Dahili"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr "CI/CD için harici depo"
msgid "CI/CD settings"
msgstr "CI / CD ayarları"
-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."
+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"
@@ -4846,12 +4972,12 @@ msgstr "Dağıtım stratejisi"
msgid "CICD|Jobs"
msgstr "Ä°ÅŸler"
+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 "Alternatif CI yapılandırma dosyası bulunmazsa, Otomatik DevOps iş hattı çalışır."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr ""
-
msgid "CICD|group enabled"
msgstr "grup etkinleÅŸtirildi"
@@ -4879,9 +5005,6 @@ msgstr "Geridönüş bağlantısı"
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Birleştirme isteği için gereken onaylayıcıları ve onayları geçersiz kılabilir"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 "Ä°ptal"
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Otomatik olarak birleÅŸtirilemez"
@@ -5083,15 +5233,33 @@ msgstr "Dalı seç"
msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Dalı geri al"
+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 "Dikkatli seç"
msgid "ChangeTypeAction|Revert"
msgstr "Geri al"
+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 "Vekil(ler) deÄŸiÅŸtirildi."
@@ -5113,13 +5281,16 @@ msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr "Değişiklikler hala izleniyor. Küme/dizin taşımaları için kullanışlıdır."
+msgid "Changes saved."
+msgstr ""
+
msgid "Changes suppressed. Click to show."
msgstr "Değişiklikler bastırıldı. Göstermek için tıkla."
msgid "Changes the title to \"%{title_param}\"."
msgstr ""
-msgid "Changes were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr "Kanal yönetimi (ör. Şehir Meydanı)"
-msgid "Charts"
-msgstr "Grafikler"
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ msgstr "Bir şablon seç..."
msgid "Choose a type..."
msgstr "Bir tür seç..."
+msgid "Choose any color"
+msgstr ""
+
msgid "Choose any color."
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 ""
@@ -5662,6 +5836,9 @@ msgstr "Klonla"
msgid "Clone repository"
msgstr "Depoyu klonla"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "%{http_label} ile klonla"
@@ -5674,6 +5851,18 @@ msgstr "KRB5 ile klonla"
msgid "Clone with SSH"
msgstr "SSH ile klonla"
+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 "Kapat"
@@ -6781,12 +6970,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "Kod Sahipleri"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr "Kod Kalitesi"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "BaÄŸlan"
@@ -7273,19 +7483,37 @@ msgstr[1] "%{count} Etiket"
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 "%{title} başarıyla silinmek üzere zamanlandı"
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|Build an image"
+msgstr ""
+
+msgid "ContainerRegistry|CLI Commands"
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|Cleanup disabled"
msgstr ""
-msgid "ContainerRegistry|Build an image"
+msgid "ContainerRegistry|Cleanup in progress"
msgstr ""
-msgid "ContainerRegistry|CLI Commands"
+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"
@@ -7294,12 +7522,18 @@ msgstr ""
msgid "ContainerRegistry|Cleanup policy successfully saved."
msgstr ""
-msgid "ContainerRegistry|Cleanup policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr "Sona erme ilkesi devre dışı"
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr "Sona erme ilkesi %{time} süresi içinde çalışacak"
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr "İsme göre filtrele"
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
+msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
msgstr ""
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr "URL'yi kopyala"
msgid "Copy branch name"
msgstr "Dal adını kopyala"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "Komutu kopyala"
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr "Pano oluÅŸtur"
-
msgid "Create branch"
msgstr "Dal oluÅŸtur"
@@ -7967,9 +8183,6 @@ msgstr "Yeni oluÅŸtur"
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "Yeni pano oluÅŸtur"
-
msgid "Create new branch"
msgstr "Yeni dal oluÅŸtur"
@@ -8033,6 +8246,84 @@ msgstr "Etiket"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "kiÅŸisel eriÅŸim belirteci oluÅŸtur"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "OluÅŸturdu:"
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr "AÅŸama ekle"
msgid "CustomCycleAnalytics|Editing stage"
msgstr "Düzenleme aşaması"
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr "Aşama için bir isim girin"
-
-msgid "CustomCycleAnalytics|Name"
-msgstr "Ä°sim"
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr "Yeni aÅŸama"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8771,7 +9050,7 @@ msgid "December"
msgstr "Aralık"
msgid "Decline"
-msgstr ""
+msgstr "Reddet"
msgid "Decline and sign out"
msgstr "Reddet ve çıkış yap"
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "Varsayılan sorun şablonu"
-
msgid "Default project deletion protection"
msgstr "Varsayılan proje silme koruması"
msgid "Default projects limit"
msgstr "Varsayılan proje limiti"
-msgid "Default stages"
-msgstr "Varsayılan aşamalar"
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "Panoyu sil"
-
msgid "Delete comment"
msgstr "Yorumu sil"
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "Açıklama"
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr "%{format} olarak indir"
msgid "Download %{format}:"
msgstr "%{format} indir:"
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "CSV olarak indir"
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr "Uygulamayı düzenle"
-msgid "Edit board"
-msgstr "Panoyu düzenle"
-
msgid "Edit comment"
msgstr "Yorumu düzenle"
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr "Genel dağıtım anahtarını düzenle"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "Aşamayı düzenle"
@@ -10092,12 +10422,18 @@ msgstr "%{timeago} düzenlendi"
msgid "Editing"
msgstr "Düzenleme"
+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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr "E-postalar"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr "İki aşamalı doğrulamayı etkinleştir"
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr "Servis masanızı etkinleştirin/devre dışı bırakın. %{link_start}Servis masası hakkında daha fazla bilgi edinin%{link_end}."
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr "Aramak için en az üç karakter girin"
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ msgstr "Birleştirme isteğinin başlığını girin"
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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr "Dağıtım"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 "Güncellendi"
@@ -10803,9 +11157,6 @@ msgstr "Bunu nasıl çözebilirim?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Daha fazla bilgi"
-
msgid "Epics|Remove epic"
msgstr "EpiÄŸi sil"
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 "Hata: Dağıtım dondurma oluşturulamıyor"
+msgid "Error: Unable to find AWS role for current user"
+msgstr ""
+
msgid "ErrorTracking|Active"
msgstr "Etkin"
@@ -11166,22 +11523,22 @@ msgstr ""
msgid "Everything on your to-do list is marked as done."
msgstr "Yapılacaklar listenizdeki her şey bitti olarak işaretlendi."
-msgid "Everything you need to create a GitLab Pages site using Gatsby."
-msgstr "Gatsby kullanarak GitLab Sayfalar sitesi oluşturmak için ihtiyacınız olan her şey."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr "Mevcut dal adı, etiketi veya işlem SHA"
-msgid "Existing members and groups"
-msgstr "Mevcut üyeler ve gruplar"
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr "Deneyimli"
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "Süre sonu"
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ msgstr "Sahibi değiştirme başarısız"
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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr "Viki oluşturulamadı"
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "Özellik Bayrakları"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "Özellik bayrağı %{name} kaldırılacak. Emin misiniz?"
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "Özellik bayraklarını kullanmaya başlayın"
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr "Süzgeç"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Kapalı olan %{issuable_type} türüne göre filtrele."
@@ -12026,12 +12389,6 @@ msgstr "Dönüm noktası adına göre filtrele"
msgid "Filter by name"
msgstr "İsme göre filtrele"
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr "Duruma göre filtrele"
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr "Yolu bul"
-msgid "Find existing members by name"
-msgstr "Mevcut üyeleri isme göre bul"
-
msgid "Find file"
msgstr "Dosya bul"
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr "İlk Görülme"
@@ -12233,9 +12590,6 @@ msgstr "Çatallar"
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12339,7 +12693,7 @@ msgid "Geo nodes are paused using a command run on the node"
msgstr ""
msgid "GeoNodeStatusEvent|%{timeAgoStr} (%{pendingEvents} events)"
-msgstr ""
+msgstr "%{timeAgoStr} (%{pendingEvents} olay)"
msgid "GeoNodeSyncStatus|Node is failing or broken."
msgstr "Düğüm başarısız veya bozuk."
@@ -12701,11 +13055,17 @@ msgstr "Ücretsiz bir örnek incelemesi alın"
msgid "Get started"
msgstr "Başlayın"
+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 ""
+msgstr "Performans izlemeye başlayın"
msgid "Get started!"
msgstr ""
@@ -12776,9 +13136,6 @@ msgstr "GitLab Sorunu"
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr "Genel bildirim ayarları"
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr "Grup profil resmi"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "Grubun açıklaması"
-
msgid "Group description (optional)"
msgstr "Grup açıklaması (isteğe bağlı)"
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "Rozetler hakkında daha fazla bilgi edin."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ msgstr "Grup bulunamadı"
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 ""
@@ -13739,22 +14102,46 @@ msgstr "OluÅŸtur"
msgid "GroupsNew|Create group"
msgstr "Grup oluÅŸtur"
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
msgid "GroupsNew|Import"
msgstr "İçe aktar"
-msgid "GroupsNew|Import a GitLab group export file"
-msgstr ""
-
msgid "GroupsNew|Import group"
msgstr "Grubu içe aktar"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ 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 does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "İçe aktarma devam ediyor"
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr "Depoyu içe aktar"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "GitLab Kurumsal Sürüm ile sorun panolarını iyileştirin."
+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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,65 +14763,68 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
-msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgid "Incident template (optional)"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr "%{hours} saat, %{minutes} dakika kaldı"
+
msgid "IncidentManagement|%{minutes} minutes remaining"
-msgstr ""
+msgstr "%{minutes} mdakika kaldı"
msgid "IncidentManagement|All"
-msgstr ""
+msgstr "Tümü"
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 ""
+msgstr "Atamalar"
msgid "IncidentManagement|Closed"
-msgstr ""
+msgstr "Kapalı"
msgid "IncidentManagement|Create incident"
-msgstr ""
+msgstr "Olay oluÅŸtur"
msgid "IncidentManagement|Critical - S1"
-msgstr ""
+msgstr "Kritik - S1"
msgid "IncidentManagement|Date created"
-msgstr ""
+msgstr "OluÅŸturulma tarihi"
msgid "IncidentManagement|Display your incidents in a dedicated view"
msgstr ""
msgid "IncidentManagement|High - S2"
-msgstr ""
+msgstr "Yüksek - S2"
msgid "IncidentManagement|Incident"
-msgstr ""
+msgstr "Olay"
msgid "IncidentManagement|Incidents"
-msgstr ""
+msgstr "Olaylar"
msgid "IncidentManagement|Low - S4"
-msgstr ""
+msgstr "Düşük - S4"
msgid "IncidentManagement|Medium - S3"
-msgstr ""
+msgstr "Orta - S3"
msgid "IncidentManagement|No incidents to display."
msgstr ""
msgid "IncidentManagement|Open"
-msgstr ""
+msgstr "Açık"
msgid "IncidentManagement|Published"
-msgstr ""
+msgstr "Yayınlanma"
msgid "IncidentManagement|Published to status page"
msgstr ""
msgid "IncidentManagement|Severity"
-msgstr ""
+msgstr "Önem"
msgid "IncidentManagement|There are no closed incidents"
msgstr ""
@@ -14432,16 +14833,16 @@ msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
msgid "IncidentManagement|Time to SLA"
-msgstr ""
+msgstr "SLA zamanı"
msgid "IncidentManagement|Unassigned"
-msgstr ""
+msgstr "Atanmamış"
msgid "IncidentManagement|Unknown"
-msgstr ""
+msgstr "Bilinmeyen"
msgid "IncidentManagement|Unpublished"
-msgstr ""
+msgstr "Yayınlanmamış"
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
msgstr ""
@@ -14483,13 +14884,13 @@ msgid "IncidentSettings|You may choose to introduce a countdown timer in inciden
msgstr ""
msgid "IncidentSettings|hours"
-msgstr ""
+msgstr "saat"
msgid "IncidentSettings|minutes"
-msgstr ""
+msgstr "dakika"
msgid "Incidents"
-msgstr ""
+msgstr "Olaylar"
msgid "Incident|Alert details"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr "Davet et"
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr "Ãœye davet et"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Sorun etkinlikleri"
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15358,7 +15783,7 @@ msgid "Iteration updated"
msgstr ""
msgid "Iterations"
-msgstr ""
+msgstr "Yinelemeler"
msgid "Iteration|Dates cannot overlap with other existing Iterations"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15640,7 +16068,7 @@ msgid "Join Zoom meeting"
msgstr ""
msgid "Joined %{time_ago}"
-msgstr ""
+msgstr "%{time_ago} katıldı"
msgid "Jul"
msgstr "Tem"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15918,7 +16349,7 @@ msgid "Last used"
msgstr "Son kullanılan"
msgid "Last used %{last_used_at} ago"
-msgstr ""
+msgstr "En son %{last_used_at} önce kullanıldı"
msgid "Last used on:"
msgstr "Son kullanım:"
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr "Onaylar hakkında daha fazla bilgi edinin."
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr "Daha sonra iş hattı zamanlamaları belgelerinden"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "daha fazla bilgi edinin"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Ayrıl"
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr "Sorunlar yükleniyor"
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr "Kod parçacığı yükleniyor"
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr "BÄ°RLEÅžTÄ°RÄ°LDÄ°"
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr "%{iid} birleştirme talebi %{authorName} tarafından oluşturuldu"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Birleştirme isteği onayları"
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr "BirleÅŸtirme istekleri"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ 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 ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "Çoklu sorun panoları"
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ msgstr "Yeni dosya"
msgid "New group"
msgstr "Yeni grup"
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
msgid "New health check access token has been generated!"
msgstr ""
@@ -18557,7 +19021,7 @@ msgstr "Dal bulunamadı"
msgid "No changes"
msgstr "DeÄŸiÅŸiklik yok"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18630,7 +19094,7 @@ msgid "No iteration"
msgstr ""
msgid "No iterations to show"
-msgstr ""
+msgstr "Gösterilecek yineleme yok"
msgid "No job log"
msgstr ""
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Gizli deÄŸil"
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr "Olamaz!"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "Önce en eski"
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19679,7 +20260,7 @@ msgid "Packages"
msgstr "Paketler"
msgid "Packages & Registries"
-msgstr ""
+msgstr "Paketler ve Kayıtlar"
msgid "Page not found"
msgstr ""
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Sayfalar"
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ msgstr ""
msgid "Personal Access Token"
msgstr "Kişisel Erişim Anahtarı"
+msgid "Personal Access Token prefix"
+msgstr ""
+
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
@@ -19951,6 +20532,9 @@ msgstr "İş Hattı Zamanlamaları"
msgid "Pipeline minutes quota"
msgstr "İş hattı dakika kotası"
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ msgstr ""
msgid "Pipeline: %{status}"
msgstr "İş hattı: %{status}"
+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 ""
@@ -19978,7 +20571,7 @@ msgstr "Başarı oranı:"
msgid "PipelineCharts|Successful:"
msgstr "Başarılı:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20033,7 +20626,7 @@ msgid "Pipelines emails"
msgstr "İş hattı e-postaları"
msgid "Pipelines for last month (%{oneMonthAgo} - %{today})"
-msgstr ""
+msgstr "Geçen ayın iş hatları (%{oneMonthAgo} - %{today})"
msgid "Pipelines for last week (%{oneWeekAgo} - %{today})"
msgstr "Geçen haftaki iş hatları (%{oneWeekAgo} - %{today})"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "İş Hatları Yükleniyor"
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 "Lütfen yeni hesabınız için bir şifre oluşturun."
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,14 +21234,17 @@ msgstr ""
msgid "Prev"
msgstr "Önceki"
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
-msgstr "Birleştirme isteği yazarı tarafından birleştirme isteklerini onaylanmasını önle"
+msgid "Prevent MR approvals from users who make commits to the MR."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
-msgstr "Birleştirme isteği işlemcilerinin birleştirme isteklerini onaylanmasını önle"
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr "Önceki çözülmemiş tartışma"
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ msgstr ""
msgid "Profiles|@username"
msgstr "@kullanıcıadı"
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
msgid "Profiles|Account scheduled for removal."
msgstr "Hesabın kaldırılması planlandı."
@@ -20899,6 +21531,9 @@ 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."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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"
@@ -21229,14 +21867,11 @@ msgstr "Proje adı"
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
msgid "Project overview"
-msgstr "Projeye genel bakış"
+msgstr "Projeye Genel Bakış"
msgid "Project path"
msgstr "Proje yolu"
@@ -21388,12 +22023,18 @@ msgstr "Tüm tartışmalar çözülmelidir"
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 "Kullanıcıların erişim istemesine izin ver"
+msgid "ProjectSettings|Analytics"
+msgstr ""
+
msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
msgstr ""
@@ -21421,8 +22062,8 @@ msgstr "Bu ayarı değiştirmek için bir yöneticiye başvurun."
msgid "ProjectSettings|Container registry"
msgstr "Kapsayıcı kaydı"
-msgid "ProjectSettings|Customize your project badges."
-msgstr "Proje rozetlerinizi özelleştirin."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr "E-posta bildirimlerini devre dışı bırak"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr "Sorunlar"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "Rozetler hakkında daha fazla bilgi edinin."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr "Bu proje için hafif sorun izleme sistemi"
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Bu depoya yalnızca imzalanmış işlemler yollanabilir."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "Paketler"
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ msgstr ""
msgid "Protected branches"
msgstr "Korunan dallar"
-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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22265,7 +22918,7 @@ msgid "Pseudonymizer data collection"
msgstr ""
msgid "Public"
-msgstr ""
+msgstr "Genel"
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr "Herkese Açık - Grup ve herhangi bir herkese açık proje, herhangi bir kimlik doğrulama olmadan görüntülenebilir."
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr "Son Proje EtkinliÄŸi"
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "Son aramalar"
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-msgstr "Yeni işlemler kaynak dalına aktarıldığında birleştirme isteğindeki tüm onayları kaldır"
-
msgid "Remove all or specific assignee(s)"
msgstr "Tümünü veya özel vekil(ler)i kaldır"
msgid "Remove all or specific label(s)"
msgstr "Tüm veya belirli etiketleri kaldır"
+msgid "Remove all or specific reviewer(s)"
+msgstr ""
+
msgid "Remove approver"
msgstr ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Depo"
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr "EriÅŸim Talebi"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,8 +23923,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
-msgstr "Onaylamak için kullanıcı şifresi iste"
+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 ""
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,20 +24261,8 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
+msgstr "Çalıştırıcılar %{status}, son iletişim %{runner_contact} önceydi"
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr "Çalıştırıcı güncellenemedi."
msgid "Runner was successfully updated."
msgstr "Çalıştırıcı başarıyla güncellendi."
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ msgstr "Çalışıyor…"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Geçerli depoda, dosya düzeltmelerini sıkıştırma ve erişilemeyen nesneleri kaldırma gibi bir dizi temizlik görevi yürütür."
+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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,8 +24516,8 @@ msgstr "İş Hatları Zamanlanıyor"
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
-msgstr "Kapsamlı sorun panoları"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr ""
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr "Gereksinimleri ara"
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Kullanıcıları ara"
@@ -23995,6 +24669,9 @@ msgstr "OluÅŸturduÄŸum istekleri birleÅŸtir"
msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "Bana atanan istekleri birleÅŸtir"
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
msgid "SearchAutocomplete|in all GitLab"
msgstr "Tüm GitLab'da"
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr "Konuları virgüllerle ayırın."
msgid "September"
msgstr "Eylül"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ msgstr ""
msgid "Service Desk"
msgstr "Servis Masası"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr ""
@@ -24823,11 +25515,8 @@ 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 template for issue descriptions."
-msgstr "Sorun açıklamaları için varsayılan bir şablon belirleyin."
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
-msgstr "Gereken onayları, onaylayıcıları ve diğer onay ayarlarını belirleyin."
+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 ""
@@ -25024,14 +25713,11 @@ msgstr "Ayarlar"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
msgid "Severity"
-msgstr ""
+msgstr "Önem"
msgid "SeverityWidget|Severity"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr "Tüm üyeleri göster"
-msgid "Show all requirements."
-msgstr "Tüm gereksinimleri göster."
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr "Bir şeyler ters gitti, projeler aranamıyor"
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr "Başlatılıyor..."
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr "Abonelik başarıyla oluşturuldu."
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26442,7 +27158,7 @@ msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_star
msgstr ""
msgid "Successfully synced %{synced_timeago}."
-msgstr ""
+msgstr "%{synced_timeago} başarıyla eşitlendi."
msgid "Successfully unblocked"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "Sistem"
@@ -26812,7 +27534,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
-msgstr ""
+msgstr "%{user} %{timeAgo} güncelledi"
msgid "Terraform|A Terraform report failed to generate."
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,10 +27569,28 @@ 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 "%{user} tarafından %{timeAgo} kilitlendi"
+
+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"
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,8 +27766,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
-msgstr "Teşekkürler! Bu mesajı tekrar gösterme"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr "İzin verilen en yüksek dosya boyutu 200KB'dır."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ msgstr "Henüz bu grupla paylaşılan proje yok."
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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ msgstr "Bu, boş bir havuz oluşturmadan veya mevcut olanı içe aktarmadan kodu
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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ msgstr ""
msgid "Trending"
msgstr "Öne Çıkanlar"
+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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr "Yıldızı kaldır"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "Abonelikten çık"
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,8 +30260,8 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr "Grup adınızı, açıklamanızı, profil resminizi ve görünürlüğünüzü güncelleyin."
-msgid "Update your project name, topics, description and avatar."
-msgstr "Proje adınızı, konularınızı, açıklamanızı ve profil resminizi güncelleyin."
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr ""
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr "Proje güncellenemedi!"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "Sorun panolarını geliştirmek için planınızı yükseltin."
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30008,7 +30879,7 @@ msgid "Value"
msgstr "DeÄŸer"
msgid "Value Stream"
-msgstr ""
+msgstr "Değer Akışı"
msgid "Value Stream Analytics"
msgstr "Değer Akışı Analizleri"
@@ -30321,16 +31192,16 @@ msgid "VulnerabilityChart|Severity"
msgstr ""
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "%{user} tarafından %{timeago} %{statusStart}onaylandı%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
-msgstr ""
+msgstr "%{pipelineLink} iş hattında %{timeago} %{statusStart}algılandı%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "%{user} tarafından %{timeago} %{statusStart}reddedildi%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "%{user} tarafından %{timeago} %{statusStart}çözümlendi%{statusEnd}"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr "Açıklama"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Proje"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr "Sohbet hesaplarınızı görebilirsiniz."
msgid "You can set up as many Runners as you need to run your jobs."
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 "Grup başına veya proje başına bildirim düzeyi belirleyebilirsiniz."
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 "Bir kilidi silmeye zorlamak için sorumlu erişiminiz olmalıdır"
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr "kendinizi atayın"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr "dal adı"
msgid "by"
msgstr "tarafından"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Tüm projeler"
@@ -32169,6 +33109,9 @@ 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] "%{packagesString} tarafından kullanıldı"
@@ -32371,6 +33314,12 @@ msgstr ""
msgid "has already been taken"
msgstr "zaten alındı"
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
msgid "has been completed."
msgstr ""
@@ -32553,13 +33502,16 @@ 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] "birleÅŸtirme isteÄŸi"
msgstr[1] "birleÅŸtirme isteÄŸi"
msgid "merged %{timeAgo}"
-msgstr ""
+msgstr "%{timeAgo} birleÅŸtirildi"
msgid "metric_id must be unique across a project"
msgstr ""
@@ -32955,13 +33907,13 @@ msgid "open issue"
msgstr ""
msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
+msgstr "%{email} tarafından %{timeAgoString} %{user} aracılığıyla açıldı"
msgid "opened %{timeAgoString} by %{user}"
msgstr "%{user} tarafından %{timeAgoString} açıldı"
msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
+msgstr "Jira'da %{user} tarafından %{timeAgoString} açıldı"
msgid "opened %{timeAgo}"
msgstr "%{timeAgo} açıldı"
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "etiket adı"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index ef6d3b6de8b..0dc9de8e5b4 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: 2020-12-03 08:14\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -471,12 +471,21 @@ msgstr "%{address} - недійÑний діапазон IP-адреÑ"
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 "%{author_link} напиÑав:"
msgid "%{authorsName}'s thread"
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 ""
@@ -917,6 +926,27 @@ msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Коміти"
msgstr[2] "%{strong_start}%{commit_count}%{strong_end} Комітів"
msgstr[3] "%{strong_start}%{commit_count}%{strong_end} Комітів"
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} Файлів"
@@ -1080,9 +1110,15 @@ msgstr "(%{mrCount} злито)"
msgid "(%{value}) has already been taken"
msgstr "(%{value}) вже зайнÑто"
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Ðемає змін)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(перевірити прогреÑ)"
@@ -1353,29 +1389,26 @@ msgstr ":%{startLine} до %{endLine}"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "'Runner' — це процеÑ, Ñкий виконує завданнÑ. Ви можете Ñтворити потрібну кількіÑÑ‚ÑŒ Runner'ів."
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Шаблон конÑольного заÑтоÑунку .NET Core, Ñкий налаштовуєтьÑÑ Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкого проєкту .NET Core"
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 "Сайт GitBook, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
+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 "Сайт Hexo, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
+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 "Сайт Hugo, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
-msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Сайт Jekyll, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
msgstr "Ðе можливо отримати SSL Ñертифікат Let's Encrypt до того Ñк ваш домен буде перевірено."
@@ -1386,6 +1419,9 @@ msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Let's Encrypt буде налаштоваÐ
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "Базова Ñторінка та Serverless функціÑ, що викориÑтовує AWS Lambda, AWS API Gateway та GitLab Pages"
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
msgid "A complete DevOps platform"
msgstr "Повноцінна DevOps платформа "
@@ -1413,6 +1449,9 @@ msgstr "Група — набір із декількох проєктів"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 "УчаÑник команди по боротьбі з порушеннÑми розглÑне ваш звіт Ñкомога швидше."
@@ -1422,6 +1461,9 @@ 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 "Створено новий конвеєр Auto DevOps, детальну інформацію можна знайти на Ñторінці %{pipelines_link_start}Конвеєри%{pipelines_link_end}"
@@ -1440,14 +1482,17 @@ 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 "Сайт на HTML, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
+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 "Шаблон проєкта Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ заÑтоÑунка Salesforce з викориÑтаннÑм Salesforce Developer Tools."
+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 ""
@@ -1455,11 +1500,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "Готовий шаблон Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð· Android заÑтоÑунками."
+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 "Готовий шаблон Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð· iOS Swift заÑтоÑунками."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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 "РегулÑрний вираз, Ñкий буде викориÑтовуватиÑÑ Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами в журналі завданнÑ. Залиште пуÑтим Ð´Ð»Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ"
@@ -1470,9 +1518,15 @@ 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 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 ""
+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 "КориÑтувач із правом запиÑу в гілку-джерело вибрав цей варіант"
@@ -1491,14 +1545,17 @@ msgstr "API-токен"
msgid "AWS Access Key"
msgstr "Ключ доÑтупу AWS"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "Ключ доÑтупу AWS. Ðеобхідний лише Ñкщо не викориÑтовуютÑÑ Ñ€Ð¾Ð»ÑŒÐ¾Ð²Ñ– параметри доÑтупу до інÑтанÑу"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "Секретний ключ доÑтупу AWS"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "Секретний ключ доÑтупу AWS. Ðеобхідний лише Ñкщо не викориÑтовуютÑÑ Ñ€Ð¾Ð»ÑŒÐ¾Ð²Ñ– параметри доÑтупу до інÑтанÑу"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "Зупинити"
@@ -1539,6 +1596,9 @@ msgstr "ДоÑтуп до вашого облікового запиÑу LDAP з
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "ДоÑтуп заборонено! Будь-лаÑка, перевірте, чи ви можете додавати ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ цього Ñховища."
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "Дата Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу"
@@ -2134,6 +2194,9 @@ msgstr "ЗаÑтоÑувати Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— дÐ
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -2143,6 +2206,9 @@ msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проє
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Змінні Ñередовища Ñ” захищеними за замовчуваннÑм"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "Перейти до загальних налаштувань"
@@ -2621,9 +2687,6 @@ msgstr "Ðемає"
msgid "AlertManagement|Open"
msgstr "Відкриті"
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2687,15 +2750,9 @@ msgstr "Ðевідоме"
msgid "AlertManagement|Value"
msgstr "ЗначеннÑ"
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2723,9 +2780,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2795,10 +2849,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2864,12 +2918,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2954,9 +3002,6 @@ msgstr "Ð’ÑÑ– гілки"
msgid "All changes are committed"
msgstr "Ð’ÑÑ– зміни закомічені"
-msgid "All default stages are currently visible"
-msgstr "Ðаразі відображаютьÑÑ Ð²ÑÑ– Ñтадії за замовчуваннÑм"
-
msgid "All email addresses will be used to identify your commits."
msgstr "Ð’ÑÑ– адреÑи електронної пошти будуть викориÑтовуватиÑÑ Ð´Ð»Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— ваших комітів."
@@ -3017,6 +3062,9 @@ msgstr "Дозволити влаÑникам груп керувати нала
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ вибраних протоколів Ð´Ð»Ñ Ð´Ð¾Ñтупу до Git."
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr "Дозволити влаÑникам керувати захиÑтом гілок за замовчуваннÑм Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— групи"
@@ -3155,7 +3203,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3191,6 +3239,9 @@ 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 "Збій під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ задачі"
@@ -3203,6 +3254,9 @@ 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 ""
@@ -3425,9 +3479,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "Помилка при збереженні ÑтатуÑу Ð¿ÐµÑ€ÐµÐ²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ LDAP. Будь лаÑка, Ñпробуйте ще раз."
-
msgid "An error occurred while saving assignees"
msgstr "Помилка при збереженні виконавців"
@@ -3449,6 +3500,9 @@ 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 ""
@@ -3458,6 +3512,9 @@ 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 ""
@@ -3476,8 +3533,8 @@ 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 "Приклад проєкту Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐºÐ»Ð°Ñтерами Kubernetes, інтегрованими з GitLab."
+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 ""
@@ -3491,6 +3548,9 @@ 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 "Ðеавторизований кориÑтувач"
@@ -3569,8 +3629,8 @@ msgstr ""
msgid "Any label"
msgstr "Будь-Ñка мітка"
-msgid "Any member with Developer or higher permissions to the project."
-msgstr "Будь-Ñкий учаÑник з рівнем доÑтупу Розробник або вище до цього проєкту."
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
msgid "Any milestone"
msgstr "Будь-Ñкий етап"
@@ -3726,15 +3786,15 @@ msgstr[3] "Потрібно %{count} затверджень від %{membersCoun
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr "Затверджуючі оÑоби"
msgid "ApprovalRule|Name"
msgstr "Ім'Ñ"
-msgid "ApprovalRule|No. approvals required"
-msgstr "Ðеобхідна кількіÑÑ‚ÑŒ затверджень"
-
msgid "ApprovalRule|Rule name"
msgstr "Ð†Ð¼â€™Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°"
@@ -3753,6 +3813,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3855,9 +3918,6 @@ msgstr "Ви впевнені що хочете видалити цей %{typeOf
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "Ви дійÑно бажаєте видалити цю дошку?"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Ви впевнені, що хочете видалити цей приÑтрій? Цю дію неможливо ÑкаÑувати."
@@ -4027,6 +4087,12 @@ msgstr "Призначити мітку"
msgid "Assign milestone"
msgstr "Призначити етап"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "Призначити деÑкі задачі до цього етапу."
@@ -4045,12 +4111,18 @@ msgstr "Призначити цю задачу Ñобі"
msgid "Assigned %{assignee_users_sentence}."
msgstr "Призначено %{assignee_users_sentence}."
+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 ""
@@ -4063,6 +4135,9 @@ msgstr ""
msgid "Assigned to me"
msgstr "Призначено мені"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Виконавець"
@@ -4088,6 +4163,9 @@ msgstr "Виконавці"
msgid "Assigns %{assignee_users_sentence}."
msgstr "Призначає %{assignee_users_sentence}."
+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 "Потрібне щонайменше одне Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ влаÑника коду Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ файлів, що задовільнÑÑŽÑ‚ÑŒ відповідним правилам CODEOWNER."
@@ -4134,9 +4212,6 @@ msgstr "Події аудиту"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr "Події аудиту дозволÑÑŽÑ‚ÑŒ відÑтежувати важливі події, що відбуваютьÑÑ Ð² GitLab."
-msgid "Audit Log"
-msgstr "Лог аудиту"
-
msgid "AuditLogs|(removed)"
msgstr "(видалено)"
@@ -4293,12 +4368,12 @@ 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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr "Auto DevOps може автоматично збирати, теÑтувати Ñ– розгортати заÑтоÑунки на оÑнові заздалегідь визначених налаштувань безперервної інтеграції та розгортаннÑ. %{auto_devops_start}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps%{auto_devops_end} або ÑкориÑтайтеÑÑ Ð½Ð°ÑˆÐ¸Ð¼ %{quickstart_start}коротким поÑібником%{quickstart_end} щоб відразу ж приÑтупити до роботи."
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto DevOps документації"
@@ -4317,10 +4392,13 @@ 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 ""
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4362,7 +4440,7 @@ msgstr "Ðвтоматичне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñертифікатами зÐ
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4425,9 +4503,6 @@ msgstr "Колір фону"
msgid "Badges"
msgstr "Значки"
-msgid "Badges|A new badge was added."
-msgstr "Ðовий значок був доданий."
-
msgid "Badges|Add badge"
msgstr "Додати значок"
@@ -4440,12 +4515,21 @@ msgstr "URL-адреÑа Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐºÐ°"
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 "Значок групи"
@@ -4455,15 +4539,15 @@ 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|Please fill in a valid URL"
-msgstr "Будь лаÑка, введіть дійÑну URL-адреÑу"
-
msgid "Badges|Project Badge"
msgstr "Значок проєкту"
@@ -4476,15 +4560,12 @@ msgstr "Зберегти зміни"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐºÐ° не вдалоÑÑ, будь лаÑка перевірте введений URL Ñ– Ñпробуйте знову."
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "%{docsLinkStart}Змінні%{docsLinkEnd}, Ñкі підтримує GitLab: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "Значок був видалений."
-msgid "Badges|The badge was saved."
-msgstr "Значок було збережено."
-
msgid "Badges|This group has no badges"
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° не має значків"
@@ -4497,9 +4578,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "Ваші значки"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "напр. %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ файл Balsamiq."
@@ -4524,9 +4602,6 @@ msgstr "Ви повинні налаштувати автоматичне вÑÑ‚
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте обережні. Зміна проÑтору імен проєкту може мати небажані побічні ефекти."
@@ -4611,22 +4686,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Підвищити"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4666,12 +4747,21 @@ msgstr "Блокує"
msgid "Blog"
msgstr "Блог"
-msgid "Board scope"
-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 "Дошки"
@@ -4723,6 +4813,30 @@ 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 ""
@@ -4753,9 +4867,6 @@ msgstr "Ðазва гілки"
msgid "Branch not loaded - %{branchId}"
msgstr "Гілку не завантажено: %{branchId}"
-msgid "Branch prefix"
-msgstr "ÐŸÑ€ÐµÑ„Ñ–ÐºÑ Ð³Ñ–Ð»ÐºÐ¸"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Пошук гілок"
@@ -4924,6 +5035,24 @@ msgstr "Вбудований"
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -5017,7 +5146,10 @@ msgstr "CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторіÑ"
msgid "CI/CD settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
-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."
+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"
@@ -5044,12 +5176,12 @@ 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 "Конвеєр Auto DevOps буде запущено, Ñкщо не буде знайдено альтернативного файлу конфігуріції CI."
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr "Ви повинні додати %{base_domain_link_start}базовий домен%{link_end} до вашого %{kubernetes_cluster_link_start}Kubernetes клаÑтера%{link_end} щоб ваша ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¾Ð½ÑƒÐ²Ð°Ð»Ð°."
-
msgid "CICD|group enabled"
msgstr "група увімкнена"
@@ -5077,9 +5209,6 @@ msgstr "URL зворотнього виклику"
msgid "Can be manually deployed to"
msgstr "Можна вручну розгорнути на"
-msgid "Can override approvers and approvals required per merge request"
-msgstr "Можна змінювати необхідні Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° затверджуючих оÑіб Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на злиттÑ"
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -5128,6 +5257,30 @@ 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 "СкаÑувати"
@@ -5149,6 +5302,9 @@ msgstr "СкаÑовано Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð°"
msgid "Cancelling Preview"
msgstr "СкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "Ðеможливо злити автоматично"
@@ -5281,15 +5437,33 @@ 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 "Вибрати (cherry-pick)"
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 "Змінено виконавцÑ(ців)."
@@ -5311,13 +5485,16 @@ 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 "Змінює заголовок на \"%{title_param}\"."
-msgid "Changes were successfully made."
+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}."
@@ -5329,9 +5506,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr "Графіки"
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr "Графіки не можуть відображатиÑÑ, оÑкільки вичерпано Ñ‡Ð°Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ даних. %{documentationLink}"
@@ -5599,9 +5773,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5860,6 +6040,9 @@ msgstr "Клонувати"
msgid "Clone repository"
msgstr "Клонувати репозиторій"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "Клонувати з %{http_label}"
@@ -5872,6 +6055,18 @@ msgstr "Клонувати з KRB5"
msgid "Clone with SSH"
msgstr "Клонувати з SSH"
+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 "Закрити"
@@ -6979,12 +7174,12 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "ВлаÑники коду"
-msgid "Code Owners to the merge request changes."
-msgstr ""
-
msgid "Code Quality"
msgstr "ЯкіÑÑ‚ÑŒ коду"
@@ -7256,6 +7451,24 @@ 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 "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7385,6 +7598,9 @@ msgstr "Ваш GitLab Wiki може бути доÑтупний тут: %{wiki_l
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "Вітаємо! Ви увімкнули двофакторну автентифікацію!"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "Підключити"
@@ -7477,13 +7693,13 @@ msgstr[3] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr "%{imageName} тегів"
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7492,18 +7708,42 @@ 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 policy:"
+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 ""
@@ -7531,9 +7771,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Помилка Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Docker"
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7543,9 +7780,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr "Розклад завершеннÑ:"
-
msgid "ContainerRegistry|Filter by name"
msgstr "Фільтр за іменем"
@@ -7570,6 +7804,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr "Увійти"
@@ -7588,9 +7825,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr "КількіÑÑ‚ÑŒ тегів Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ:"
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7667,16 +7901,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7712,12 +7940,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "За допомогою РеєÑтру контейнерів, кожен проєкт може мати влаÑний проÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¾Ð±Ñ€Ð°Ð·Ñ–Ð² Docker. %{docLinkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{docLinkEnd}"
@@ -7874,6 +8096,9 @@ msgstr "Скопіювати URL"
msgid "Copy branch name"
msgstr "Скопіювати Ñ–Ð¼â€™Ñ Ð³Ñ–Ð»ÐºÐ¸"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "Скопіювати команду"
@@ -8109,15 +8334,12 @@ msgstr ""
msgid "Create an account using:"
msgstr "Створити обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою:"
-msgid "Create an issue. Issues are created for each alert triggered."
-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 board"
-msgstr "Створити дошку"
-
msgid "Create branch"
msgstr "Створити гілку"
@@ -8175,9 +8397,6 @@ msgstr "Створити новий"
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr "Створіть нову дошку"
-
msgid "Create new branch"
msgstr "Створити нову гілку"
@@ -8241,6 +8460,84 @@ msgstr "Тег"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Створити токен Ð´Ð»Ñ Ð¾ÑобиÑтого доÑтупу"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "Створено"
@@ -8334,6 +8631,9 @@ msgstr "ЧаÑовий поÑÑ Cron"
msgid "Crossplane"
msgstr "Crossplane"
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "Поточна гілка"
@@ -8418,45 +8718,18 @@ msgstr "Додати Ñтадію"
msgid "CustomCycleAnalytics|Editing stage"
msgstr "Редагувати Ñтадію"
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr "ВвеÑти назву Ñтадії"
-
-msgid "CustomCycleAnalytics|Name"
-msgstr "Ðазва"
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr "Ðова ÑтадіÑ"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr "Будь лаÑка, виберіть відразу початкову подію"
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr "Вибрати початкову подію"
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr "Вибрати завершальну подію"
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr "Ім'Ñ Ñтадії вже Ñ–Ñнує"
-msgid "CustomCycleAnalytics|Start event"
-msgstr "Початкова подіÑ"
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr "Початкову подію змінено, будь лаÑка, виберіть коректну завершальну подію"
-
msgid "CustomCycleAnalytics|Start event label"
msgstr "Мітка початкової події"
-msgid "CustomCycleAnalytics|Stop event"
-msgstr "Завершальна подіÑ"
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr "Мітка завершальної події"
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr "Оновити Ñтадію"
-
msgid "Customer Portal"
msgstr "Портал клієнтів"
@@ -8704,6 +8977,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8770,6 +9046,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8818,6 +9100,9 @@ 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 ""
@@ -9025,18 +9310,12 @@ msgstr "Перший день Ñ‚Ð¸Ð¶Ð½Ñ Ð·Ð° замовчуваннÑм в ка
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr "Шаблон задач за замовчуваннÑм"
-
msgid "Default project deletion protection"
msgstr "ЗахиÑÑ‚ від Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ за замовчуваннÑм"
msgid "Default projects limit"
msgstr "Ліміт проєктів за замовчуваннÑм"
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "По замовчуванню: викориÑтовувати ідентифікатор облікового запиÑу FogBugz Ñк повне ім'Ñ"
@@ -9049,6 +9328,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Визначте влаÑний шаблон за допомогою ÑинтакÑиÑу cron"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -9097,9 +9379,6 @@ msgstr "Видалити артефакти"
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr "Видалити дошку"
-
msgid "Delete comment"
msgstr "Видалити коментар"
@@ -9577,9 +9856,6 @@ msgstr "За ÑпаданнÑм"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr "Опишіть мету зміни та на що рецензент повинен звернути увагу."
-msgid "Describe the requirement here"
-msgstr "Опишіть вимогу тут"
-
msgid "Description"
msgstr "ОпиÑ"
@@ -9589,6 +9865,9 @@ msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "ÐžÐ¿Ð¸Ñ Ð¾Ð±Ñ€Ð¾Ð±Ð»ÐµÐ½Ð¾ за допомогою %{link_start}GitLab Flavored Markdown%{link_end}"
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
msgid "Description template"
msgstr ""
@@ -9790,22 +10069,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9814,6 +10132,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9823,18 +10144,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -10106,6 +10442,9 @@ msgstr "Завантажити %{format}"
msgid "Download %{format}:"
msgstr "Завантажити %{format}:"
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "Завантажити CSV"
@@ -10190,9 +10529,6 @@ msgstr "Під Ñ‡Ð°Ñ Ñ†ÑŒÐ¾Ð³Ð¾ процеÑу вам буде запропон
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr "Кожен Runner може бути в одному із таких Ñтанів:"
@@ -10247,9 +10583,6 @@ msgstr "Редагувати ÑиÑтемний хук"
msgid "Edit application"
msgstr "Редагувати заÑтоÑунок"
-msgid "Edit board"
-msgstr "Редагувати дошку"
-
msgid "Edit comment"
msgstr "Редагувати коментар"
@@ -10289,6 +10622,9 @@ msgstr "Редагувати ітерацію"
msgid "Edit public deploy key"
msgstr "Редагувати публічний ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "Редагувати Ñтадію"
@@ -10316,12 +10652,18 @@ msgstr "Відредаговано %{timeago}"
msgid "Editing"
msgstr "РедагуваннÑ"
+msgid "Editor Lite instance is required to set up an extension."
+msgstr ""
+
msgid "Elasticsearch AWS IAM credentials"
msgstr "Параметри доÑтупу IAM Ð´Ð»Ñ Elasticsearch AWS"
msgid "Elasticsearch HTTP client timeout value in seconds."
msgstr ""
+msgid "Elasticsearch indexing"
+msgstr ""
+
msgid "Elasticsearch indexing restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑÑƒÐ²Ð°Ð½Ð½Ñ Elasticsearch"
@@ -10355,6 +10697,9 @@ msgstr ""
msgid "Email Notification"
msgstr "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10424,10 +10769,10 @@ msgstr "ÑкиданнÑ..."
msgid "Emails"
msgstr "ÐдреÑи електронної пошти"
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10508,6 +10853,9 @@ msgstr "Включити і налаштувати Grafana."
msgid "Enable and configure Prometheus metrics."
msgstr "Включити і налаштувати метрики Prometheus."
+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 "Увімкнути контроль за клаÑифікацією за допомогою зовнішньої Ñлужби"
@@ -10577,6 +10925,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10592,9 +10943,6 @@ msgstr "Увімкнути двофакторну автентифікацію"
msgid "Enable usage ping"
msgstr "Увімкнути збір даних про викориÑтаннÑ"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr "Увімкнути/вимкнути Service Desk. %{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Service Desk%{link_end}."
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10628,6 +10976,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr "ЗавершуєтьÑÑ Ð¾ (за Грінвічем)"
@@ -10664,9 +11015,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr "Введіть щонайменше 3 Ñимволи Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ"
-msgid "Enter board name"
-msgstr "Введіть назву дошки"
-
msgid "Enter domain"
msgstr "Введіть домен"
@@ -10709,6 +11057,9 @@ 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 ""
@@ -10850,6 +11201,9 @@ msgstr "Розгортати до..."
msgid "Environments|Deployment"
msgstr "РозгортаннÑ"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10967,6 +11321,12 @@ msgstr "Ð¦Ñ Ð´Ñ–Ñ Ð·Ð°Ð¿ÑƒÑтить Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ–Ð· іменем %{envi
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 "Ð¦Ñ Ð´Ñ–Ñ Ð·Ð°Ð¿ÑƒÑтить Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ–Ð· іменем %{name} Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ %{linkStart}%{commitId}%{linkEnd} повертаючи Ñередовище до попередньої верÑÑ–Ñ—. Ви зможете повернути його шлÑхом повторного Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð¾Ñтанньої верÑÑ–Ñ— вашого заÑтоÑунку. Ви впевнені, що хочете продовжити?"
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "Оновлено"
@@ -11027,9 +11387,6 @@ msgstr "Як Ñ Ð¼Ð¾Ð¶Ñƒ це вирішити?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr "Детальніше"
-
msgid "Epics|Remove epic"
msgstr "Видалити епік"
@@ -11135,9 +11492,6 @@ msgstr "Помилка при отриманні графа мережі."
msgid "Error fetching payload data."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні даних."
-msgid "Error fetching projects"
-msgstr "Помилка Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð²"
-
msgid "Error fetching refs"
msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ refs"
@@ -11273,9 +11627,18 @@ msgstr "Помилка з Akismet. Будь лаÑка, перевірте жуÑ
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 "Ðктивовано"
@@ -11390,23 +11753,23 @@ 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 "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою Gatsby."
+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 "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою GitBook."
+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 "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою Hexo."
+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 "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою Hugo."
+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 "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою Jekyll."
+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 "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою проÑтого HTML."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
msgid "Evidence collection"
msgstr "Збір даних"
@@ -11444,9 +11807,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr "ІÑнуючі учаÑники та групи"
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11486,6 +11846,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "Термін дії"
@@ -11627,6 +11990,9 @@ msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ Zoom-зуÑтріч"
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 "Ðе вдалоÑÑ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ кориÑтувача, тому що жодного кориÑтувача не було знайдено."
@@ -11645,6 +12011,12 @@ 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 "Ðе вдалоÑÑ Ñтворити запит на злиттÑ. Будь лаÑка, Ñпробуйте знову."
@@ -11672,9 +12044,6 @@ msgstr "Ðе вдалоÑÑ Ñтворити реÑурÑ"
msgid "Failed to create wiki"
msgstr "Ðе вдалоÑÑ Ñтворити вікі"
-msgid "Failed to delete board. Please try again."
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дошку. Будь лаÑка, Ñпробуйте знову."
-
msgid "Failed to deploy to"
msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ð½ÑƒÑ‚Ð¸ до"
@@ -11825,6 +12194,9 @@ msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ гілку!"
msgid "Failed to update environment!"
msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ Ñередовище!"
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11885,9 +12257,6 @@ msgstr "Перемикач функцій не був видалений."
msgid "Feature flag was successfully removed."
msgstr "Перемикач функції уÑпішно видалено."
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11982,9 +12351,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr "Перемикачі функцій"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "Перемикач функції %{name} буде видалено. Ви впевнені?"
@@ -11994,16 +12360,13 @@ msgstr "Перемикачі функцій дозволÑÑŽÑ‚ÑŒ налаштоÐ
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "Розпочати роботу з перемикачами функцій"
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -12117,6 +12480,9 @@ 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 "ВідÑоток"
@@ -12219,6 +12585,9 @@ msgstr ""
msgid "Filter"
msgstr "Фільтр"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Фільтрувати закриті за %{issuable_type}."
@@ -12252,12 +12621,6 @@ msgstr "Фільтрувати за назвою етапу"
msgid "Filter by name"
msgstr "Фільтр по імені"
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr "Фільтрувати за ÑтатуÑом"
@@ -12309,9 +12672,6 @@ msgstr ""
msgid "Find by path"
msgstr "Пошук по шлÑху"
-msgid "Find existing members by name"
-msgstr "Знайти Ñ–Ñнуючих учаÑників за ім'Ñм"
-
msgid "Find file"
msgstr "Знайти файл"
@@ -12330,6 +12690,9 @@ msgstr ""
msgid "Finished"
msgstr "Завершено"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12459,9 +12822,6 @@ msgstr "Форки"
msgid "Format: %{dateFormat}"
msgstr "Формат: %{dateFormat}"
-msgid "Forward external support email address to"
-msgstr "ПеренаправлÑти зовнішну адреÑу Ñлужби підтримки на"
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "Знайдено помилки у вашому %{gitlab_ci_yml}:"
@@ -12927,6 +13287,12 @@ 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 "Розпочати роботу з відÑтеженнÑм помилок"
@@ -13002,9 +13368,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr "Gitlab Pages"
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -13224,8 +13587,8 @@ msgstr "Загальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень"
msgid "Go Back"
msgstr "ПовернутиÑÑ"
-msgid "Go Micro is a framework for micro service development."
-msgstr "Go Micro — це фреймворк Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ мікроÑервіÑів."
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
msgid "Go back"
msgstr "ПовернутиÑÑ"
@@ -13452,9 +13815,6 @@ msgstr "Ðватар групи"
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸"
-
msgid "Group description (optional)"
msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸ (необов'Ñзково)"
@@ -13788,11 +14148,17 @@ 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 your group badges."
-msgstr "Ðалаштувати значки групи."
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr "ВикориÑтовувати за замовчуваннÑм конвеєри Auto DevOps Ð´Ð»Ñ ÑƒÑÑ–Ñ… проєктів цієї групи"
@@ -13815,9 +14181,6 @@ msgstr "Якщо видиміÑÑ‚ÑŒ батьківÑької групи нижч
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про значки."
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr "Докладніше про шаблони проєктів на рівні групи."
@@ -13845,8 +14208,8 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr "Виберіть підгрупу Ñк джерело влаÑних шаблонів проєктів Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr "Конвеєр Auto DevOps буде запущено, Ñкщо не буде знайдено альтернативного файлу конфігуріції CI."
+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 "Проблема при оновленні конвеєра Auto DevOps: %{error_messages}."
@@ -13878,6 +14241,9 @@ 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 "Ви можете перенеÑти цю групу тільки в групу, Ñкою ви керуєте."
@@ -13956,6 +14322,9 @@ 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 ""
@@ -13965,22 +14334,46 @@ msgstr "Створити"
msgid "GroupsNew|Create group"
msgstr "Створити групу"
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
msgid "GroupsNew|Import"
msgstr "Імпорт"
-msgid "GroupsNew|Import a GitLab group export file"
-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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -14204,6 +14597,9 @@ msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно розпочато"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ОчищеннÑ, екÑпорт, шлÑÑ…, перенеÑеннÑ, видаленнÑ, архівуваннÑ."
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "Як це працює"
@@ -14378,6 +14774,9 @@ 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 ""
@@ -14455,6 +14854,12 @@ msgstr "Імпортувати з"
msgid "Import from Jira"
msgstr "Імпортувати з Jira"
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "Імпорт триває"
@@ -14503,6 +14908,9 @@ msgstr "Імпорт репозиторіїв з GitHub"
msgid "Import repository"
msgstr "Імпорт репозиторію"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14563,19 +14971,17 @@ msgstr "Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ… проєктÑ
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr "Покращити дошки задач"
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "Покращити дошки обговорень за допомогою верÑÑ–Ñ— GitLab Enterprise Edition."
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr "Покращити запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° підтримку кориÑтувачів за допомогою GitLab Enterprise Edition."
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14599,6 +15005,9 @@ msgstr "Інцидент"
msgid "Incident Management Limits"
msgstr "Ліміти, пов’Ñзані із УправліннÑм Інцидентами"
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14755,14 +15164,14 @@ msgstr ""
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
msgstr "Включає об'єкти LFS. Може бути перевизначено в групі або проєкті. 0 — необмежено."
-msgid "Includes an MVC structure to help you get started."
-msgstr "Включає Ñтруктуру MVC, щоб допомогти вам розпочати роботу."
+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 "Включає Ñтруктуру MVC, Gemfile, Rakefile, а також багато іншого, щоб допомогти вам розпочати роботу."
+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 "Включає Ñтруктуру MVC, mvnw Ñ– pom.xml, щоб допомогти вам розпочати роботу."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
msgid "Incoming email"
msgstr "Вхідна пошта"
@@ -14776,6 +15185,9 @@ msgstr "Ð’Ñтановлено неÑуміÑні параметри!"
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr "ВідÑтуп"
@@ -15026,6 +15438,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -15110,9 +15528,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr "ÐедійÑне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Git"
-
msgid "Invalid Insights config file detected"
msgstr "Знайдено недійÑний файл конфігурації ÑтатиÑтики (Insights)"
@@ -15212,15 +15627,15 @@ msgstr ""
msgid "Invite"
msgstr "ЗапрошеннÑ"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "ЗапроÑити \"%{trimmed}\" за електронною поштою"
msgid "Invite Members"
msgstr "ЗапроÑити учаÑників"
-msgid "Invite another teammate"
-msgstr ""
-
msgid "Invite group"
msgstr "ЗапроÑити групу"
@@ -15230,9 +15645,6 @@ msgstr "ЗапроÑити учаÑника"
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15302,6 +15714,24 @@ 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 ""
@@ -15359,9 +15789,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr "Виклики"
@@ -15413,6 +15840,9 @@ msgstr "Ðеможливо знайти задачу."
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "Задачі"
@@ -15428,8 +15858,8 @@ msgstr "Потрібен ідентифікатор задачі або запи
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
-msgstr "Шаблон задачі (необов’Ñзково)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
msgstr "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– неуÑпішне"
@@ -15467,7 +15897,7 @@ msgstr "СтатуÑ"
msgid "IssueAnalytics|Weight"
msgstr "Вага"
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15587,6 +16017,9 @@ msgstr "ІтераціÑ"
msgid "Iteration changed to"
msgstr "Ітерацію змінено на"
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr "Ітерацію видалено"
@@ -15671,6 +16104,9 @@ msgstr "Увімкнути задачі Jira"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Події Ð´Ð»Ñ %{noteable_model_name} вимкнені."
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Якщо відрізнÑєтьÑÑ Ð²Ñ–Ð´ Веб URL"
@@ -15695,20 +16131,20 @@ msgstr "РеєÑÑ‚Ñ€ задач Jira"
msgid "JiraService|Jira project key"
msgstr "Ключ проєкту Jira"
+msgid "JiraService|Jira workflow transition IDs"
+msgstr ""
+
msgid "JiraService|Open Jira"
msgstr "Відкрити Jira"
msgid "JiraService|Password or API token"
msgstr "Пароль або API токен"
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Transition ID(s)"
-msgstr "Ідентифікатори переходів (Transition ID(s))"
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
-msgstr "ВикориÑтовуйте \",\" або \";\" Ð´Ð»Ñ Ñ€Ð¾Ð·Ð´Ñ–Ð»ÐµÐ½Ð½Ñ ÐºÑ–Ð»ÑŒÐºÐ¾Ñ… ідентифікаторів переходів (Transition IDs)"
+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 "ВикориÑтовуйте пароль Ð´Ð»Ñ Ñерверної верÑÑ–Ñ— та API токен Ð´Ð»Ñ Ñ…Ð¼Ð°Ñ€Ð½Ð¾Ñ— верÑÑ–Ñ—"
@@ -16134,6 +16570,9 @@ msgstr "ОÑтанній запуÑк перевірки репозиторію"
msgid "Last seen"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–ÑÑ‚ÑŒ"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ ÑƒÑпішна ÑинхронізаціÑ"
@@ -16188,9 +16627,15 @@ msgstr "Керувати"
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "ДізнатиÑÑ Ð¿Ñ€Ð¾ GitLab"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "ДізнайтеÑÑ Ñк %{link_start}зробити внеÑок до вбудованих шаблонів%{link_end}"
@@ -16230,9 +16675,6 @@ msgstr ""
msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñертифікатів до проєкту перейшовши до %{docs_link_start}документації по GitLab Pages%{docs_link_end}."
-msgid "Learn more about approvals."
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про затвердженнÑ."
-
msgid "Learn more about custom project templates"
msgstr "Докладніше про влаÑні шаблони проєктів"
@@ -16257,6 +16699,9 @@ msgstr "ДізнайтеÑÑŒ більше"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "Детальніше в документації по розкладами конвеєрів"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "Вийти"
@@ -16609,6 +17054,9 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¹ перевищило ліміт
msgid "Loading issues"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡"
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñніпета"
@@ -16696,6 +17144,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr "ЗЛИТО"
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16933,6 +17384,9 @@ msgstr "Цей ÑÐµÑ€Ð²Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” кориÑтувачам викон
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16954,6 +17408,9 @@ msgstr ""
msgid "Max access level"
msgstr "МакÑимальний рівень доÑтупу"
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17095,6 +17552,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -17227,9 +17690,6 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð°Ð¼â€™ÑÑ‚Ñ–"
msgid "Merge"
msgstr "ЗлиттÑ"
-msgid "Merge (when the pipeline succeeds)"
-msgstr "Злити (коли конвеєр уÑпішно завершитьÑÑ)"
-
msgid "Merge Conflicts"
msgstr ""
@@ -17290,6 +17750,9 @@ msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{iid} від %{authorName}"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на злиттÑ"
@@ -17305,9 +17768,6 @@ msgstr ""
msgid "Merge requests"
msgstr "Запити на злиттÑ"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ â€” це ÑпоÑіб запропонувати Ñвої зміни до проєкту Ñ– обговорити Ñ—Ñ… із іншими"
@@ -17452,9 +17912,15 @@ msgstr "Файлів не знайдено"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr "Злито"
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17470,9 +17936,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 "БезпоÑереднє Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ рекомендуєтьÑÑ Ñ‚Ð°Ðº Ñк може негативно вплинути на Ñ–Ñнуючий ланцюжок змін. Прочитайте %{docsLinkStart}документацію%{docsLinkEnd} Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації."
@@ -18039,9 +18502,6 @@ msgstr ""
msgid "Mirror user"
msgstr "КориÑтувач Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr "Віддзеркалені гілки матимуть цей префікÑ. Якщо ви увімкнули \"Віддзеркалювати лише захищені гілки\" вам необхідно буде включити цей Ð¿Ñ€ÐµÑ„Ñ–ÐºÑ Ñƒ захищені гілки цього проєкту, інакше нічого не буде віддзеркалено."
-
msgid "Mirrored repositories"
msgstr "Віддзеркалені репозиторії"
@@ -18225,9 +18685,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr "Кілька дошок обговореннÑ"
-
msgid "Multiple model types found: %{model_types}"
msgstr "Знайдено декілька типів моделей: %{model_types}"
@@ -18362,6 +18819,9 @@ 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 ""
@@ -18374,6 +18834,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ".yaml"
@@ -18383,6 +18846,9 @@ 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 ""
@@ -18681,6 +19147,12 @@ 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 "Згенеровано новий токен Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ працездатноÑÑ‚Ñ–!"
@@ -18819,7 +19291,7 @@ msgstr "Гілок не знайдено"
msgid "No changes"
msgstr "Ðемає змін"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -19065,6 +19537,9 @@ msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… проєктів"
msgid "Not available for protected branches"
msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰ÐµÐ½Ð¸Ñ… гілок"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "Ðе конфіденційно"
@@ -19083,6 +19558,9 @@ msgstr "Ще не готово. Спробуйте знову пізніше."
msgid "Not started"
msgstr "Ðе розпочато"
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr "Примітка"
@@ -19320,6 +19798,9 @@ msgstr "Вимк."
msgid "Oh no!"
msgstr "О ні!"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "Спочатку Ñтарі"
@@ -19341,27 +19822,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19377,9 +19936,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19398,6 +19969,15 @@ 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 ""
@@ -19693,6 +20273,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19702,10 +20285,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19723,7 +20303,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19783,6 +20363,9 @@ msgstr "Скопіювати команду yarn"
msgid "PackageRegistry|Copy yarn setup command"
msgstr "Скопіювати команду Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ yarn"
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr "Видалити верÑÑ–ÑŽ пакету"
@@ -19849,12 +20432,18 @@ msgstr "Команда NNGet"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
-msgstr "Команда pip"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
+msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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 "Команда pip"
+
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr ""
@@ -19954,7 +20543,7 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñторінки"
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19966,18 +20555,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr "Сторінки"
@@ -20107,11 +20690,14 @@ msgstr "ШлÑхи можуть міÑтити шаблони, наприклаÐ
msgid "Pause"
msgstr "Призупинити"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr "Призупинити реплікацію"
-msgid "Paused Runners don't accept new jobs"
-msgstr "Призупинені Runner'и не приймають нові завданнÑ"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "В очікуванні"
@@ -20179,6 +20765,9 @@ msgstr "Дозволи, LFS, 2FA"
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 "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿ÐµÑ€Ñональних проєктів не дозволено. Будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñвого адмініÑтратор із питаннÑми"
@@ -20215,6 +20804,9 @@ msgstr "Розклади Конвеєрів"
msgid "Pipeline minutes quota"
msgstr "Квота хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -20227,6 +20819,15 @@ msgstr "Тригери конвеєру"
msgid "Pipeline: %{status}"
msgstr "Конвеєр: %{status}"
+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 "CI / CD аналітика"
@@ -20242,7 +20843,7 @@ msgstr "Коефіцієнт уÑпіху:"
msgid "PipelineCharts|Successful:"
msgstr "УÑпішні:"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20347,9 +20948,15 @@ 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 ""
@@ -20365,6 +20972,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
@@ -20413,6 +21023,18 @@ 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 ""
@@ -20428,6 +21050,9 @@ msgstr "Токен"
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20641,6 +21266,9 @@ 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 "Будь лаÑка, Ñтворіть пароль Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ нового облікового запиÑу."
@@ -20665,6 +21293,9 @@ msgstr "Будь лаÑка, введіть чиÑло більше за %{numbe
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 "Будь лаÑка, введіть дійÑний номер"
@@ -20875,14 +21506,17 @@ msgstr "ÐатиÑніть %{key}-C, щоб Ñкопіювати"
msgid "Prev"
msgstr "Ðазад"
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Заборонити Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… учаÑників до членÑтва в цій групі"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
-msgstr "Ðе допуÑкати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ—Ñ… авторами"
+msgid "Prevent MR approvals by the author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
-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 ""
@@ -20893,7 +21527,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr "Заборонити кориÑтувачам змінювати ім'Ñ Ñвого профілю"
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20926,6 +21560,9 @@ msgstr ""
msgid "Primary"
msgstr "Головний"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "Пріоритизувати"
@@ -21061,6 +21698,9 @@ 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 "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð¸Ð¹ Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
@@ -21163,6 +21803,9 @@ msgstr "Токен доÑтупу до каналів уÑпішно перегÐ
msgid "Profiles|Full name"
msgstr "Повне ім'Ñ"
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -21211,6 +21854,9 @@ 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 "Спозиціонуйте ваш аватар та задайте його розмір"
@@ -21493,9 +22139,6 @@ msgstr "Ðазва проєкту"
msgid "Project name suffix"
msgstr "Ð¡ÑƒÑ„Ñ–ÐºÑ Ð½Ð°Ð·Ð²Ð¸ проєкту"
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr "ПорÑдок проєктів не буде збережено, тому що локальне Ñховище недоÑтупне."
@@ -21652,12 +22295,18 @@ 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 "Ðвтоматично завершувати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² запитах на злиттÑ, коли відмінноÑÑ‚Ñ– Ñтають неактуальними"
@@ -21685,8 +22334,8 @@ msgstr "ЗвернітьÑÑ Ð´Ð¾ адмініÑтратора, щоб змінÐ
msgid "ProjectSettings|Container registry"
msgstr "РеєÑÑ‚Ñ€ контейнерів"
-msgid "ProjectSettings|Customize your project badges."
-msgstr "Ðалаштувати значки проєкту."
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr "Вимкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
@@ -21706,6 +22355,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "Кожне Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñтворить окремий коміт"
@@ -21754,9 +22406,6 @@ msgstr "Задачі"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про значки."
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr "Легка ÑиÑтема відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
@@ -21793,6 +22442,9 @@ msgstr "Примітка: Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проєктів реєÑÑ‚Ñ
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Тільки підпиÑані коміти можуть бути надіÑлані в цей репозиторій."
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "Пакети"
@@ -21901,12 +22553,21 @@ 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|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 "Коли з’ÑвлÑÑŽÑ‚ÑŒÑÑ ÐºÐ¾Ð½Ñ„Ð»Ñ–ÐºÑ‚Ð¸, кориÑтувачу даєтьÑÑ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ виконати rebase"
+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 ""
@@ -21925,9 +22586,6 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21940,6 +22598,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr "Протокол аудину HIPAA"
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21982,7 +22643,7 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22423,8 +23084,8 @@ 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 "ПідтримуютьÑÑ %{wildcards_link_start}шаблони%{wildcards_link_end} на зразок %{code_tag_start}*-stable%{code_tag_end} або %{code_tag_start}production/*%{code_tag_end}"
+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 "Дозволене злиттÑ"
@@ -22456,8 +23117,8 @@ msgstr "ЗахиÑтити гілку"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr "Захищена гілка (%{protected_branches_count})"
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
-msgstr "Ð’Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð´Ñƒ Ñкі змінюють файли, що відповідають файлу CODEOWNERS будуть відхилені"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
msgstr "Вимагати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ влаÑників коду:"
@@ -22723,6 +23384,12 @@ msgstr "Rebase"
msgid "Rebase in progress"
msgstr "ВідбуваєтьÑÑ rebase"
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "Отримувати Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ налаштованого вручну Ñервера Prometheus."
@@ -22741,6 +23408,9 @@ msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ð½Ð° активніÑÑ‚ÑŒ"
msgid "Recent Searches Service is unavailable"
msgstr "Ð¡ÐµÑ€Ð²Ñ–Ñ Ð¾Ñтанніх пошуків недоÑтупний"
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "ОÑтанні пошукові запити"
@@ -22847,7 +23517,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22971,15 +23644,15 @@ msgstr "Видалити Runner"
msgid "Remove Zoom meeting"
msgstr "Видалити Zoom-зуÑтріч"
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -23058,6 +23731,9 @@ msgstr "Видалити пріоритет"
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Видалити вторинний вузол"
@@ -23094,6 +23770,9 @@ msgstr "Видалено %{label_references} %{label_text}."
msgid "Removed %{milestone_reference} milestone."
msgstr "Видалено етап %{milestone_reference}."
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "Видалено %{type} з іденнтифікатором %{id}"
@@ -23139,6 +23818,9 @@ msgstr "ВидалÑÑ” %{label_references} %{label_text}."
msgid "Removes %{milestone_reference} milestone."
msgstr "ВидалÑÑ” етап %{milestone_reference}."
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr "ВидалÑÑ” вÑÑ– мітки."
@@ -23169,6 +23851,9 @@ msgstr "Перейменувати папку"
msgid "Rename/Move"
msgstr "Перейменувати/ПереміÑтити"
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr "Повторне відкриттÑ"
@@ -23379,6 +24064,9 @@ 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 ""
@@ -23391,7 +24079,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23400,9 +24088,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "Репозиторій"
@@ -23478,9 +24163,6 @@ msgstr "Вибрати"
msgid "Request Access"
msgstr "Запит доÑтупу"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23523,8 +24205,11 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Вимагати від уÑÑ–Ñ… кориÑтувачів приймати умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та політику конфіденційноÑÑ‚Ñ–, коли вони отримують доÑтуп до GitLab."
-msgid "Require user password to approve"
-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 "Вимагати від кориÑтувачів Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð°Ð²Ð° влаÑноÑÑ‚Ñ– на влаÑні домени"
@@ -23550,9 +24235,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr "Вимогу %{reference} було оновлено"
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "Заголовок вимоги не може міÑтити більше %{limit} знаків."
@@ -23663,12 +24345,6 @@ msgstr "Визначає IP-адреÑи один раз Ñ– викориÑтов
msgid "Response"
msgstr "Відповідь"
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr "Відповідь не міÑтила \"service_desk_address\""
@@ -23690,6 +24366,9 @@ msgstr "Метрики відповідей (NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "Метрики відповідей (NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "ПерезапуÑтити термінал"
@@ -23711,6 +24390,9 @@ 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 ""
@@ -23772,6 +24454,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23866,21 +24551,9 @@ msgstr "ПротеÑтувати ваш запущений код за допоÐ
msgid "Run untagged jobs"
msgstr "Виконати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
-msgid "Runner cannot be assigned to other projects"
-msgstr "Runner не може бути призначено Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… проєктів"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "Runner запуÑкає Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ñ– вÑÑ–Ñ… непризначених проєктів"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "Runner запуÑкає Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ñ– вÑÑ–Ñ… непризначених проєктів в його групі"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "Runner виконує завданні із призначених проєктів"
-
msgid "Runner token"
msgstr "Токен Runner'а"
@@ -23896,9 +24569,6 @@ msgstr "Runner не було оновлено."
msgid "Runner was successfully updated."
msgstr "Runner оновлено уÑпішно."
-msgid "Runner will not receive any new jobs"
-msgstr "Runner не отримуватиме нових завдань"
-
msgid "Runners"
msgstr "Runner'и"
@@ -23908,14 +24578,17 @@ 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 placed on separate users, servers, even on your local machine."
-msgstr "Runner'и можуть бути вÑтановлені на окремі Ñервери, навіть на ваш локальний комп’ютер."
+msgid "Runners can be:"
+msgstr ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "ДоÑтупні Runner'и: %{active_runners_count}"
@@ -23992,6 +24665,15 @@ 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 "SAML"
@@ -24043,9 +24725,6 @@ msgstr "Відкритий SSH-ключ"
msgid "SSL Verification:"
msgstr "Перевірка SSL:"
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -24106,11 +24785,11 @@ msgstr "Заплановано"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
-msgstr "Заплановано Ð·Ð»Ð¸Ð²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ, коли конвеєр завершитьÑÑ ÑƒÑпішно."
+msgid "Scheduled to merge this merge request (%{strategy})."
+msgstr ""
msgid "Schedules"
msgstr "Розклади"
@@ -24127,8 +24806,8 @@ msgstr "ÐŸÐ»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
msgid "Scope"
msgstr "ОблаÑÑ‚ÑŒ дії"
-msgid "Scoped issue boards"
-msgstr "Дошки задач із обмеженою облаÑÑ‚ÑŽ видимоÑÑ‚Ñ–"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr "ОблаÑÑ‚ÑŒ дії"
@@ -24250,6 +24929,9 @@ msgstr ""
msgid "Search requirements"
msgstr "Пошук Ñеред вимог"
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "Пошук кориÑтувачів"
@@ -24277,6 +24959,9 @@ 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 "по вÑьому GitLab"
@@ -24429,16 +25114,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24552,9 +25237,15 @@ msgstr "Відхилено \"%{vulnerabilityName}\""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "Відхилено \"%{vulnerabilityName}\". Щоб переглÑнути вимкніть перемикач \"Ñховати відхилені\"."
+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 ""
@@ -24639,6 +25330,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24715,6 +25409,12 @@ 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 ""
@@ -24997,9 +25697,6 @@ msgstr "ВідділÑйте теми комами."
msgid "September"
msgstr "вереÑень"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr "Ñ–"
@@ -25099,6 +25796,9 @@ msgstr "СервіÑ"
msgid "Service Desk"
msgstr "Service Desk"
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
msgid "Service Desk is enabled but not yet active"
msgstr "Service Desk увімкнено але він ще не активний"
@@ -25129,11 +25829,8 @@ 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 template for issue descriptions."
-msgstr "Ð’Ñтановити шаблон за замовчуваннÑм Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñу задач."
-
-msgid "Set a number of approvals required, the approvers and other approval 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 "Ð’Ñтановіть пароль Ð´Ð»Ñ Ñвого облікового запиÑу, щоб мати можливіÑÑ‚ÑŒ відправлÑти та отримувати через %{protocol}."
@@ -25330,9 +26027,6 @@ msgstr "ÐалаштуваннÑ"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25372,6 +26066,9 @@ 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 ""
@@ -25393,6 +26090,9 @@ 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 ""
+
msgid "Show all activity"
msgstr "Показати вÑÑŽ активніÑÑ‚ÑŒ"
@@ -25402,9 +26102,6 @@ msgstr ""
msgid "Show all members"
msgstr "Показати вÑÑ–Ñ… учаÑників"
-msgid "Show all requirements."
-msgstr "Показати вÑÑ– вимоги."
-
msgid "Show all test cases."
msgstr ""
@@ -25441,6 +26138,9 @@ msgstr "Показати файловий менеджер"
msgid "Show file contents"
msgstr "Показати вміÑÑ‚ файлу"
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "Показати оÑтанню верÑÑ–ÑŽ"
@@ -25767,6 +26467,9 @@ msgstr "ХтоÑÑŒ відредагував цю %{issueType} одночаÑно
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 "ЩоÑÑŒ пішло не так з нашого боку"
@@ -25803,7 +26506,10 @@ msgstr "Помилка при заÑтоÑуванні пропозиції. БÑ
msgid "Something went wrong while archiving a requirement."
msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ Ð°Ñ€Ñ…Ñ–Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼Ð¾Ð³Ð¸."
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25830,6 +26536,9 @@ msgstr "Проблема при редагуванні вашого комент
msgid "Something went wrong while fetching %{listType} list"
msgstr "Помилка при отриманні ÑпиÑку %{listType}"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Проблема при отриманні коментарів. Будь лаÑка, Ñпробуйте знову."
@@ -25890,7 +26599,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25929,8 +26641,8 @@ msgstr "Помилка, не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ проєкти"
msgid "Something went wrong, unable to search projects"
msgstr "Помилка, не вдалоÑÑ Ð·Ð´Ñ–Ð¹Ð½Ñтити пошук проєктів"
-msgid "Something went wrong."
-msgstr "ЩоÑÑŒ пішло не так."
+msgid "Something went wrong. Please try again later"
+msgstr ""
msgid "Something went wrong. Please try again."
msgstr "ЩоÑÑŒ пішло не так. Будь лаÑка Ñпробуйте ще раз."
@@ -26346,15 +27058,18 @@ msgstr "ЗапуÑк..."
msgid "Starts %{startsIn}"
msgstr "Буде запущено %{startsIn}"
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "ПочинаєтьÑÑ Ð¾ (за Грінвічем)"
+msgid "Starts on"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ—"
-msgid "State: %{last_reindexing_task_state}"
-msgstr ""
-
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -26373,6 +27088,9 @@ 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 ""
@@ -26391,6 +27109,9 @@ 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 ""
@@ -26628,6 +27349,9 @@ msgstr "ПідпиÑку уÑпішно Ñтворено."
msgid "Subscription successfully deleted."
msgstr "ПідпиÑку уÑпішно видалено."
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26904,6 +27628,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr "СиÑтемні"
@@ -27134,9 +27864,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -27146,12 +27891,30 @@ 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 ""
@@ -27164,9 +27927,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 "ТеÑÑ‚"
@@ -27315,8 +28090,8 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr "ДÑкуємо за покупку!"
-msgid "Thanks! Don't show me this again"
-msgstr "ДÑкую! Більше не показувати це повідомленнÑ"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
msgstr ""
@@ -27330,6 +28105,9 @@ msgstr "Параметр \"Вимагати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ CODE
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] "%{type} міÑтить наÑтупну помилку:"
@@ -27343,6 +28121,9 @@ 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 ""
@@ -27409,6 +28190,9 @@ 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 "Джерело даних підключено, але даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ¼Ð°Ñ”. %{documentationLink}"
@@ -27533,9 +28317,6 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð—Ð°Ð´Ð°Ñ‡Ð° показує, Ñкільки чаÑу пот
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr "Ваш ліцензійний ключ недійÑний. ПереконайтеÑÑ, що він збігаєтьÑÑ Ð· тим, що ви отримали від GitLab Inc."
@@ -27554,9 +28335,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальний розмір файлу — %{size}."
-msgid "The maximum file size allowed is 200KB."
-msgstr "МакÑимальний розмір файлу — 200 Кб."
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr "Конфлікти у цьому запитті на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ можуть бути вирішені через GitLab. Будь лаÑка, Ñпробуйте зробити це локально."
@@ -27824,6 +28602,9 @@ 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 ""
@@ -27920,6 +28701,9 @@ 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 "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні %{replicableType}"
@@ -27998,6 +28782,9 @@ 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 "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при оновлені інформаційної панелі, назва гілки недійÑна."
@@ -28079,6 +28866,9 @@ msgstr "Цей інÑÑ‚Ð°Ð½Ñ GitLab ще немає загальних Runner'Ñ
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 ""
@@ -28376,6 +29166,9 @@ 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 ""
@@ -28460,6 +29253,15 @@ 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 "Цей runner буде виконуватиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ на тих конвеєрах, Ñкі Ñпрацьовують на захищених гілках"
@@ -28475,9 +29277,6 @@ msgstr "Це підпиÑка длÑ"
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr "Цей Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°Ñ‚Ð¸Ð¼Ðµ перевагу у разі, Ñкщо він менший за той, Ñкий вÑтановлено на рівні проєкту, також він підтримує \"людÑкий\" формат, наприклад \"1 hour\" (1 година). Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±ÐµÐ· одиниць виміру предÑтавлÑÑŽÑ‚ÑŒ Ñекунди."
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr "Цей кориÑтувач не може бути розблокований вручну в GitLab"
@@ -28550,12 +29349,33 @@ 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 ""
@@ -28571,6 +29391,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr "Показати оÑтанній"
@@ -28583,12 +29406,21 @@ 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 ""
@@ -28598,7 +29430,7 @@ 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."
+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"
@@ -28607,6 +29439,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr "Загальна кількіÑÑ‚ÑŒ запитів"
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -29218,12 +30053,22 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "ПовернутиÑÑ Ð´Ð¾ GitLab"
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -29242,6 +30087,39 @@ 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 Gold 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 Gold 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 "Тригер"
@@ -29632,6 +30510,9 @@ msgstr "СкаÑувати заплановане завданнÑ"
msgid "Unstar"
msgstr "Видалити із обраних"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "ВідпиÑатиÑÑ"
@@ -29656,7 +30537,7 @@ msgstr ""
msgid "Until"
msgstr "До"
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29713,8 +30594,8 @@ msgstr "Оновіть Ñвої закладки, тому що URL-адреÑа
msgid "Update your group name, description, avatar, and visibility."
msgstr "Оновіть Ñ–Ð¼â€™Ñ Ð³Ñ€ÑƒÐ¿Ð¸, опиÑ, аватар та видиміÑÑ‚ÑŒ."
-msgid "Update your project name, topics, description and avatar."
-msgstr "Оновіть ім'Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ, теми, Ð¾Ð¿Ð¸Ñ Ñ‚Ð° аватар."
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr "Ðеможливо перейменувати проєкт, тому що він має теги в реєÑтрі контейнерів!"
@@ -29728,7 +30609,7 @@ msgstr "Ðовий рівень видимоÑÑ‚Ñ– не допуÑкаєтьÑÑ
msgid "UpdateProject|Project could not be updated!"
msgstr "Проект не може бути оновлений!"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29770,9 +30651,6 @@ msgstr "Перейдіть на вищий тарифний план щоб ак
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "Перейдіть на вищий тарифний план щоб покращити дошки задач."
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr "Перейдіть на вищий тарифний план Ð´Ð»Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на злиттÑ."
@@ -30283,6 +31161,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr "КориÑтувачів уÑпішно додано."
@@ -30726,6 +31607,9 @@ 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 ""
@@ -30753,6 +31637,9 @@ msgstr "ОпиÑ"
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr "Дані"
@@ -30780,6 +31667,12 @@ msgstr "ПроÑÑ‚Ñ–Ñ€ імен"
msgid "Vulnerability|Project"
msgstr "Проект"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30798,6 +31691,9 @@ 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 "Зачекайте Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð¹Ð¾Ð³Ð¾ вміÑту"
@@ -30810,6 +31706,9 @@ msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… про продуктивніÑÑ‚ÑŒ"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хочете побачити дані? Будь лаÑка, попроÑить у адмініÑтратора доÑтуп."
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr "Увага:"
@@ -30843,6 +31742,9 @@ msgstr ""
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "Ðе вдалоÑÑ Ð¿Ñ–Ð´ÐºÑŽÑ‡Ð¸Ñ‚Ð¸ÑÑ Ð´Ð¾ Ñервера Prometheus. Ðбо Ñервер більше не Ñ–Ñнує, або необхідно оновити деталі конфігурації."
+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 "Ми виÑвили потенційний Ñпам у %{humanized_resource_name}. Будь лаÑка, введіть цей код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ reCAPTCHA, щоб продовжити."
@@ -30945,6 +31847,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30981,6 +31886,9 @@ 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 ""
@@ -31105,8 +32013,8 @@ 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 be an approver?"
-msgstr "Хто може затверджувати?"
+msgid "Who can approve?"
+msgstr ""
msgid "Who can see this group?"
msgstr "Хто може бачити цю групу?"
@@ -31483,6 +32391,9 @@ 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 ""
@@ -31573,6 +32484,9 @@ 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 "Ви можете розв’Ñзати цей конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° допомогою інтерактивного режиму (викориÑтовуючи кнопки %{use_ours} та %{use_theirs}), або безпоÑередньо редагуючи файли. Закомітити зміни у %{branch_name}"
@@ -31582,9 +32496,6 @@ msgstr "Ви можете переглÑдати Ñвої облікові заÐ
msgid "You can set up as many Runners as you need to run your jobs."
msgstr ""
-msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr "Ви можете налаштувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Runnir'ів з конкретними тегами. РозділÑйте теги комами."
-
msgid "You can specify notification level per group or per project."
msgstr "Ви можете вказати рівень Ñповіщень на рівні групи або проєкту."
@@ -31606,6 +32517,9 @@ 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 "Зараз ви не можете запуÑтити цей запланований конвеєр. Будь лаÑка, почекайте хвилину."
@@ -31642,9 +32556,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” необхідних прав доÑтупу, щоб перевизначити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації LDAP-груп."
-
msgid "You don't have any U2F devices registered yet."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” жодного зареєÑтрованого U2F приÑтрою."
@@ -31717,6 +32628,9 @@ 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 ""
@@ -31726,6 +32640,9 @@ 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 ""
@@ -31759,6 +32676,9 @@ 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 "Ви повинні мати доÑтуп керівника Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÑƒÑового Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ "
@@ -31918,6 +32838,9 @@ 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 ""
@@ -31990,6 +32913,9 @@ msgstr "Ваш приÑтрій U2F не надіÑлав коректну віÐ
msgid "Your U2F device was registered!"
msgstr "Ваш приÑтрій U2F уÑпішно зареєÑтровано!"
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -32065,6 +32991,9 @@ msgstr ""
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr "Ваш приÑтрій уÑпішно налаштовано! Дайте йому ім'Ñ Ñ‚Ð° зареєÑтруйте його на Ñервері GitLab."
+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 "Ваш перший проєкт"
@@ -32086,6 +33015,9 @@ 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 ""
@@ -32143,6 +33075,9 @@ 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 ""
@@ -32243,6 +33178,9 @@ msgstr ""
msgid "assign yourself"
msgstr "призначити Ñамому Ñобі"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr "під загрозою"
@@ -32261,9 +33199,15 @@ msgstr "ім'Ñ Ð³Ñ–Ð»ÐºÐ¸"
msgid "by"
msgstr "від"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 "не може бути змінено Ñкщо в реєÑтрі контейнерів оÑобиÑтого проєкту Ñ” теги."
@@ -32306,6 +33250,9 @@ 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 "%{linkStartTag}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² %{linkEndTag}"
@@ -32345,6 +33292,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Ð’ÑÑ– проєкти"
@@ -32501,6 +33451,9 @@ 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] "ВикориÑтовуєтьÑÑ %{packagesString}"
@@ -32713,6 +33666,12 @@ 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 ""
@@ -32897,6 +33856,9 @@ 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] "запит на злиттÑ"
@@ -33563,18 +34525,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "назва тегу"
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 0b86b4abc33..2e804cedc6e 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: 2020-12-03 08:08\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 97bef873a97..fd400a0e456 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: 2020-12-03 08:12\n"
+"PO-Revision-Date: 2021-01-08 22:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -359,12 +359,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -783,6 +792,21 @@ 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 ""
@@ -938,9 +962,15 @@ 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 ""
@@ -1175,28 +1205,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1208,6 +1235,9 @@ 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 ""
@@ -1235,6 +1265,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1244,6 +1277,9 @@ 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 ""
@@ -1262,13 +1298,16 @@ 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."
+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."
+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"
@@ -1277,10 +1316,13 @@ 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 ready-to-go template for use with Android apps."
+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 ready-to-go template for use with iOS Swift apps."
+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"
@@ -1292,9 +1334,15 @@ 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 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 ""
+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 ""
@@ -1313,13 +1361,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1361,6 +1412,9 @@ 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 ""
@@ -1954,6 +2008,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1963,6 +2020,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2439,9 +2499,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2505,15 +2562,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2541,9 +2592,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2613,10 +2661,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2682,12 +2730,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2772,9 +2814,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2835,6 +2874,9 @@ 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 ""
@@ -2973,7 +3015,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -3009,6 +3051,9 @@ 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 ""
@@ -3021,6 +3066,9 @@ 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 ""
@@ -3243,9 +3291,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3267,6 +3312,9 @@ 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 ""
@@ -3276,6 +3324,9 @@ 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 ""
@@ -3294,7 +3345,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3309,6 +3360,9 @@ 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 ""
@@ -3387,7 +3441,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3536,13 +3590,13 @@ msgstr[1] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3563,6 +3617,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3665,9 +3722,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3835,6 +3889,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3853,12 +3913,18 @@ 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 ""
@@ -3871,6 +3937,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3894,6 +3963,9 @@ 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 ""
@@ -3938,9 +4010,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -4097,10 +4166,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4121,10 +4190,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4166,7 +4238,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4229,9 +4301,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4244,12 +4313,21 @@ 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 ""
@@ -4259,13 +4337,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4280,15 +4358,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4301,9 +4376,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4328,9 +4400,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4415,22 +4484,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4468,10 +4543,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4525,6 +4609,30 @@ 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 ""
@@ -4555,9 +4663,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4726,6 +4831,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4819,7 +4942,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4846,10 +4972,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4879,9 +5005,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4930,6 +5053,30 @@ 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 ""
@@ -4951,6 +5098,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -5083,15 +5233,33 @@ 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|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 ""
@@ -5113,13 +5281,16 @@ 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 were successfully made."
+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}."
@@ -5131,9 +5302,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5401,9 +5569,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5662,6 +5836,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5674,6 +5851,18 @@ 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 ""
@@ -6781,10 +6970,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -7056,6 +7245,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7185,6 +7392,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7273,13 +7483,13 @@ msgstr[1] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7288,18 +7498,42 @@ 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 policy:"
+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 ""
@@ -7327,9 +7561,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7339,9 +7570,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7366,6 +7594,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7384,9 +7615,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7461,16 +7689,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7506,12 +7728,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7668,6 +7884,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7901,15 +8120,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7967,9 +8183,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -8033,6 +8246,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8126,6 +8417,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8210,45 +8504,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8494,6 +8761,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8560,6 +8830,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8608,6 +8884,9 @@ 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 ""
@@ -8815,18 +9094,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8839,6 +9112,9 @@ 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 ""
@@ -8887,9 +9163,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9355,9 +9628,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9367,6 +9637,9 @@ 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 ""
@@ -9568,22 +9841,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9592,6 +9904,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9601,18 +9916,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9882,6 +10212,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9966,9 +10299,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -10023,9 +10353,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -10065,6 +10392,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -10092,12 +10422,18 @@ 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 ""
@@ -10131,6 +10467,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10200,10 +10539,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10284,6 +10623,9 @@ 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 ""
@@ -10353,6 +10695,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10368,9 +10713,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10404,6 +10746,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10440,9 +10785,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10485,6 +10827,9 @@ 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 ""
@@ -10626,6 +10971,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10743,6 +11091,12 @@ 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 ""
@@ -10803,9 +11157,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10911,9 +11262,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -11049,9 +11397,18 @@ 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 ""
@@ -11166,22 +11523,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11220,9 +11577,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11262,6 +11616,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11403,6 +11760,9 @@ 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 ""
@@ -11421,6 +11781,12 @@ 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 ""
@@ -11448,9 +11814,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11601,6 +11964,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11661,9 +12027,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11756,9 +12119,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11768,16 +12128,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11891,6 +12248,9 @@ 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 ""
@@ -11993,6 +12353,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -12026,12 +12389,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -12083,9 +12440,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -12104,6 +12458,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12233,9 +12590,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12701,6 +13055,12 @@ 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 ""
@@ -12776,9 +13136,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12998,7 +13355,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13226,9 +13583,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13562,10 +13916,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13589,9 +13949,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13619,7 +13976,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13652,6 +14009,9 @@ 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 ""
@@ -13730,6 +14090,9 @@ 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 ""
@@ -13739,22 +14102,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13974,6 +14361,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14148,6 +14538,9 @@ 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 ""
@@ -14221,6 +14614,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14269,6 +14668,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14329,19 +14731,15 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-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 GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14365,6 +14763,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14521,13 +14922,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14542,6 +14943,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14790,6 +15194,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14874,9 +15284,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14976,13 +15383,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14994,9 +15401,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -15066,6 +15470,24 @@ 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 ""
@@ -15123,9 +15545,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15177,6 +15596,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15192,7 +15614,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15231,7 +15653,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15351,6 +15773,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15435,6 +15860,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15459,19 +15887,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15896,6 +16324,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15950,9 +16381,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15992,9 +16429,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -16019,6 +16453,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16357,6 +16794,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16444,6 +16884,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16681,6 +17124,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16702,6 +17148,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16843,6 +17292,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16975,9 +17430,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17038,6 +17490,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -17053,9 +17508,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17200,9 +17652,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17218,9 +17676,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17783,9 +18238,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17969,9 +18421,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -18102,6 +18551,9 @@ 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 ""
@@ -18114,6 +18566,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -18123,6 +18578,9 @@ 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 ""
@@ -18419,6 +18877,12 @@ 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 ""
@@ -18557,7 +19021,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18803,6 +19267,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18821,6 +19288,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -19058,6 +19528,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -19079,27 +19552,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -19115,9 +19666,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19136,6 +19699,15 @@ 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 ""
@@ -19429,6 +20001,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19438,10 +20013,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19459,7 +20031,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19519,6 +20091,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19585,10 +20160,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19690,7 +20271,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19702,18 +20283,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19843,10 +20418,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19915,6 +20493,9 @@ 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 ""
@@ -19951,6 +20532,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19963,6 +20547,15 @@ 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 ""
@@ -19978,7 +20571,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -20083,9 +20676,15 @@ 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 ""
@@ -20101,6 +20700,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20149,6 +20751,18 @@ 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 ""
@@ -20164,6 +20778,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20377,6 +20994,9 @@ 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 ""
@@ -20401,6 +21021,9 @@ 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 ""
@@ -20611,13 +21234,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20629,7 +21255,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20662,6 +21288,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20797,6 +21426,9 @@ 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 ""
@@ -20899,6 +21531,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20947,6 +21582,9 @@ 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 ""
@@ -21229,9 +21867,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21388,12 +22023,18 @@ 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 ""
@@ -21421,7 +22062,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21442,6 +22083,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21490,9 +22134,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21529,6 +22170,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21637,12 +22281,21 @@ 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|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 ""
@@ -21661,9 +22314,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21676,6 +22326,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21718,7 +22371,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22159,7 +22812,7 @@ 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"
+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"
@@ -22192,7 +22845,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22459,6 +23112,12 @@ 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 ""
@@ -22477,6 +23136,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22581,7 +23243,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22703,15 +23368,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22790,6 +23455,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22826,6 +23494,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22871,6 +23542,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22901,6 +23575,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -23105,6 +23782,9 @@ 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 ""
@@ -23117,7 +23797,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -23126,9 +23806,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23204,9 +23881,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23249,7 +23923,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23276,9 +23953,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23385,12 +24059,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23412,6 +24080,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23433,6 +24104,9 @@ 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 ""
@@ -23492,6 +24166,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23584,21 +24261,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23614,9 +24279,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23626,13 +24288,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23710,6 +24375,15 @@ 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 ""
@@ -23761,9 +24435,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23824,10 +24495,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23845,7 +24516,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23968,6 +24639,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23995,6 +24669,9 @@ 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 ""
@@ -24125,16 +24802,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24248,9 +24925,15 @@ 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 ""
@@ -24335,6 +25018,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24409,6 +25095,12 @@ 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 ""
@@ -24691,9 +25383,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24793,6 +25482,9 @@ 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 ""
@@ -24823,10 +25515,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -25024,9 +25713,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -25066,6 +25752,9 @@ 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 ""
@@ -25087,6 +25776,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -25096,9 +25788,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -25135,6 +25824,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25457,6 +26149,9 @@ 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 ""
@@ -25493,7 +26188,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25520,6 +26218,9 @@ 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 ""
@@ -25580,7 +26281,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25619,7 +26323,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -26036,13 +26740,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -26063,6 +26770,9 @@ 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 ""
@@ -26081,6 +26791,9 @@ 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 ""
@@ -26318,6 +27031,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26594,6 +27310,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26820,9 +27542,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26832,12 +27569,30 @@ 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 ""
@@ -26850,9 +27605,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26999,7 +27766,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -27014,6 +27781,9 @@ 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] ""
@@ -27025,6 +27795,9 @@ 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 ""
@@ -27091,6 +27864,9 @@ 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 ""
@@ -27213,9 +27989,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27234,9 +28007,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27504,6 +28274,9 @@ 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 ""
@@ -27600,6 +28373,9 @@ 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 ""
@@ -27678,6 +28454,9 @@ 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 ""
@@ -27759,6 +28538,9 @@ 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 ""
@@ -28056,6 +28838,9 @@ 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 ""
@@ -28140,6 +28925,15 @@ 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 ""
@@ -28155,9 +28949,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28230,12 +29021,33 @@ 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 ""
@@ -28251,6 +29063,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28263,12 +29078,21 @@ 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 ""
@@ -28278,7 +29102,7 @@ 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."
+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"
@@ -28287,6 +29111,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28894,12 +29721,20 @@ 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 Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28918,6 +29753,39 @@ 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 Gold 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 Gold 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 ""
@@ -29308,6 +30176,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29332,7 +30203,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29389,7 +30260,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29404,7 +30275,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29446,9 +30317,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29959,6 +30827,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30398,6 +31269,9 @@ 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 ""
@@ -30425,6 +31299,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30452,6 +31329,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30470,6 +31353,9 @@ 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 ""
@@ -30482,6 +31368,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30515,6 +31404,9 @@ 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 ""
@@ -30617,6 +31509,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30653,6 +31548,9 @@ 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 ""
@@ -30775,7 +31673,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -31153,6 +32051,9 @@ 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 ""
@@ -31243,6 +32144,9 @@ 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 ""
@@ -31252,9 +32156,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31276,6 +32177,9 @@ 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 ""
@@ -31312,9 +32216,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31387,6 +32288,9 @@ 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 ""
@@ -31396,6 +32300,9 @@ 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 ""
@@ -31429,6 +32336,9 @@ 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 ""
@@ -31588,6 +32498,9 @@ 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 ""
@@ -31660,6 +32573,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31735,6 +32651,9 @@ 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 ""
@@ -31756,6 +32675,9 @@ 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 ""
@@ -31813,6 +32735,9 @@ 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 ""
@@ -31911,6 +32836,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31929,9 +32857,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31974,6 +32908,9 @@ 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 ""
@@ -32013,6 +32950,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32169,6 +33109,9 @@ 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] ""
@@ -32371,6 +33314,12 @@ 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 ""
@@ -32553,6 +33502,9 @@ 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] ""
@@ -33207,18 +34159,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index dee21e39835..6c5513b091f 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: 2020-12-03 08:08\n"
+"PO-Revision-Date: 2021-01-08 22:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -867,9 +888,15 @@ 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 ""
@@ -1086,28 +1113,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1119,6 +1143,9 @@ 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 ""
@@ -1146,6 +1173,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1155,6 +1185,9 @@ 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 ""
@@ -1173,13 +1206,16 @@ 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."
+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."
+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"
@@ -1188,10 +1224,13 @@ 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 ready-to-go template for use with Android apps."
+msgid "A ready-to-go template for use with Android apps"
msgstr ""
-msgid "A ready-to-go template for use with iOS Swift apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 ""
@@ -1224,13 +1269,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1272,6 +1320,9 @@ 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 ""
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2744,6 +2780,9 @@ 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 ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 ""
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr ""
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3739,6 +3790,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3757,12 +3814,18 @@ 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 ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,10 +4065,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4023,10 +4089,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4146,12 +4212,21 @@ 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 ""
@@ -4161,13 +4236,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4182,15 +4257,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4627,6 +4729,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4747,10 +4870,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4780,9 +4903,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 ""
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 ""
@@ -5014,13 +5179,16 @@ 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 were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5575,6 +5749,18 @@ 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 ""
@@ -6682,10 +6868,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+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 kept. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,15 +8013,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -7929,6 +8139,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8734,6 +9004,9 @@ 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 ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9244,9 +9514,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9854,9 +10184,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ 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 ""
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 ""
@@ -10691,9 +11042,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13113,9 +13467,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13449,10 +13800,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13859,6 +14243,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14152,6 +14548,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19711,10 +20282,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 ""
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 ""
@@ -20767,6 +21395,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 ""
@@ -21097,9 +21731,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,7 +21926,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,7 +23782,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23139,9 +23812,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25302,6 +25990,9 @@ 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 ""
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,7 +27604,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ 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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 ""
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 ""
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] ""
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 59a7512d42d..4e6212b8399 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,10 +14,10 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-12-03 08:11\n"
+"PO-Revision-Date: 2021-01-08 22:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
-msgstr ""
+msgstr " %{project_name}#%{issuable_iid} &middot;由%{author}于%{issuable_created}创建"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -58,13 +58,13 @@ msgid " or "
msgstr " 或 "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr "或%{emphasisStart}!åˆå¹¶è¯·æ±‚id%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
-msgstr ""
+msgstr "或%{emphasisStart}#议题id%{emphasisEnd}"
msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
-msgstr ""
+msgstr "或%{emphasisStart}&å²è¯—id%{emphasisEnd}"
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr "或引用 (例如: path/to/project!merge_request_id)"
@@ -73,19 +73,19 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "“%{ref}â€ä¸Šä¸å­˜åœ¨â€œ%{path}â€"
msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "createInstance()必需“elâ€å‚æ•°"
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
+msgstr[0] "%d个核准"
msgid "%d Other"
msgid_plural "%d Others"
-msgstr[0] ""
+msgstr[0] "其他%d项"
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
+msgstr[0] "%d个软件包"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
@@ -140,7 +140,7 @@ msgstr "%d 次æ交"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
+msgstr[0] "%d个已完æˆçš„议题"
msgid "%d contribution"
msgid_plural "%d contributions"
@@ -156,7 +156,7 @@ msgstr[0] "%d个错误"
msgid "%d error found:"
msgid_plural "%d errors found:"
-msgstr[0] ""
+msgstr[0] "找到%d个错误:"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -168,7 +168,7 @@ msgstr[0] "%d个失败"
msgid "%d failed security job"
msgid_plural "%d failed security jobs"
-msgstr[0] ""
+msgstr[0] "%d个失败的安全扫æ作业"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
@@ -228,11 +228,11 @@ msgstr[0] "%d个更多评论"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
+msgstr[0] "%d个开å¯ä¸­çš„议题"
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
+msgstr[0] "%dæ¡å¾…处ç†çš„评论"
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
@@ -248,7 +248,7 @@ msgstr[0] "%d个项目"
msgid "%d project selected"
msgid_plural "%d projects selected"
-msgstr[0] ""
+msgstr[0] "选择了%d个项目"
msgid "%d request with warnings"
msgid_plural "%d requests with warnings"
@@ -268,7 +268,7 @@ msgstr[0] "%d个标签"
msgid "%d tag per image name"
msgid_plural "%d tags per image name"
-msgstr[0] ""
+msgstr[0] "æ¯ä¸ªé•œåƒå称有%d个标签"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
@@ -288,7 +288,7 @@ msgstr[0] "%d个æ¼æ´žå·²å¿½ç•¥"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
+msgstr[0] "找到%d个警告:"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -298,9 +298,15 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
msgid "%{address} is an invalid IP address range"
-msgstr ""
+msgstr "%{address}为无效的IP地å€èŒƒå›´"
msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr "%{anchorOpen}了解更多%{anchorClose}如何在您的实例上定制或ç¦ç”¨æ³¨å†Œ"
+
+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:"
@@ -309,6 +315,9 @@ msgstr "%{author_link}写é“:"
msgid "%{authorsName}'s thread"
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}å˜é‡åœ¨ä½œä¸šæ—¥å¿—中éšè—(虽然它们必须符åˆæŸäº›æ­£åˆ™è¡¨è¾¾å¼è¦æ±‚)。"
@@ -319,7 +328,7 @@ msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "由%{commit_author_link}编写于%{commit_timeago}"
msgid "%{completedCount} completed weight"
-msgstr ""
+msgstr "%{completedCount}已完æˆæƒé‡"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "总æƒé‡%{totalWeight}中的%{completedWeight}已完æˆ"
@@ -331,7 +340,7 @@ msgid "%{cores} cores"
msgstr "%{cores}个核心"
msgid "%{count} %{scope} for term '%{term}'"
-msgstr ""
+msgstr "%{scope}çš„%{count}项æœç´¢'%{term}'结果"
msgid "%{count} LOC/commit"
msgstr "%{count} è¡Œ/æ¯æ交"
@@ -348,11 +357,11 @@ msgstr "已选择 %{count} 个文件"
msgid "%{count} issue selected"
msgid_plural "%{count} issues selected"
-msgstr[0] ""
+msgstr[0] "已选择%{count}个议题"
msgid "%{count} merge request selected"
msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
+msgstr[0] "已选择%{count}个åˆå¹¶è¯·æ±‚"
msgid "%{count} more"
msgstr "其余%{count}项"
@@ -378,10 +387,10 @@ msgid "%{count} related %{pluralized_subject}: %{links}"
msgstr "%{count}个相关的%{pluralized_subject}: %{links}"
msgid "%{count} total weight"
-msgstr ""
+msgstr "总æƒé‡%{count}"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}%{critical}个严é‡%{criticalEnd},%{highStart}%{high}个高å±%{highEnd}以åŠ%{otherStart}%{otherMessage}%{otherEnd}"
msgid "%{dashboard_path} could not be found."
msgstr "未找到%{dashboard_path}。"
@@ -396,13 +405,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 ""
+msgstr "%{doc_link_start}高级æœç´¢%{doc_link_end} å·²å¯ç”¨ã€‚"
msgid "%{due_date} (Past due)"
-msgstr ""
+msgstr "%{due_date} (已过期)"
msgid "%{duration}ms"
msgstr "%{duration}毫秒"
@@ -432,7 +441,7 @@ msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} + 其余%{numberOfOtherMilestones}项"
msgid "%{global_id} is not a valid ID for %{expected_type}."
-msgstr ""
+msgstr "%{global_id}ä¸æ˜¯ä¸€ä¸ª%{expected_type}的有效ID。"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}群组%{group_docs_link_end} å…许您管ç†ã€å作多个项目。群组的æˆå‘˜å¯ä»¥è®¿é—®ç¾¤ç»„下的所有项目。"
@@ -444,13 +453,13 @@ msgid "%{group_name} uses group managed accounts. You need to create a new GitLa
msgstr "%{group_name}使用由群组托管å¸æˆ·ã€‚您需è¦åˆ›å»ºä¸€ä¸ªæ–°çš„GitLabå¸æˆ·ï¼Œè¯¥å¸æˆ·å°†é€šè¿‡%{group_name}组æ¥ç®¡ç†ã€‚"
msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name}&%{epic_iid} &middot; %{epic_created}ç”±%{author}å¼€å¯"
msgid "%{hook_type} was deleted"
-msgstr ""
+msgstr "%{hook_type}已删除"
msgid "%{hook_type} was scheduled for deletion"
-msgstr ""
+msgstr "%{hook_type}已安排删除"
msgid "%{host} sign-in from new location"
msgstr "%{host} 从新ä½ç½®ç™»å½•"
@@ -462,19 +471,19 @@ msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} 将被删除ï¼æ‚¨ç¡®å®šå—?"
msgid "%{issueType} actions"
-msgstr ""
+msgstr "%{issueType}æ“作"
msgid "%{issuesCount} issues with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{issuesCount}个议题,上é™ä¸º%{maxIssueCount}"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
msgstr "%{issuesSize}个,上é™ä¸º%{maxIssueCount}"
msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}实际å“应:%{labelEnd} %{headers}"
msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
-msgstr ""
+msgstr "%{labelStart}断言:%{labelEnd} %{assertion}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr "%{labelStart}类型: %{labelEnd}%{class}"
@@ -501,19 +510,19 @@ msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}命å空间: %{labelEnd}%{namespace}"
msgid "%{labelStart}Scan Type:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}扫æ类型: %{labelEnd}%{reportType}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}扫æ工具:%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}å‘é€è¯·æ±‚:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr "%{labelStart}严é‡ç¨‹åº¦ :%{labelEnd}%{severity}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}未修改的å“应:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message}ä¸å¯ç”¨"
@@ -546,7 +555,7 @@ msgid "%{listToShow}, and %{awardsListLength} more."
msgstr "%{listToShow},还有 %{awardsListLength} 个。"
msgid "%{location} is missing required keys: %{keys}"
-msgstr ""
+msgstr "%{location}缺少必需的键: %{keys}"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 被GitLab用户 %{lock_user_id} é”定"
@@ -558,16 +567,16 @@ msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} å¯ä»¥åˆå¹¶"
msgid "%{message} showing first %{warnings_displayed}"
-msgstr ""
+msgstr "%{message}显示第一个%{warnings_displayed}"
msgid "%{milestone_name} (Past due)"
-msgstr ""
+msgstr "%{milestone_name} (已过期)"
msgid "%{milestone} (expired)"
-msgstr ""
+msgstr "%{milestone} (已过期)"
msgid "%{milliseconds}ms"
-msgstr ""
+msgstr "%{milliseconds}毫秒"
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText},此议题将自动关闭。"
@@ -644,19 +653,19 @@ msgid "%{remaining_approvals} left"
msgstr "还需%{remaining_approvals}"
msgid "%{reportType} %{status}"
-msgstr ""
+msgstr "%{reportType} %{status}"
msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
-msgstr ""
+msgstr "%{reportType}检测到%{totalStart}%{total}%{totalEnd}个潜在的%{vulnMessage}"
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
-msgstr ""
+msgstr "%{reportType}检测到%{totalStart}æ— %{totalEnd}安全æ¼æ´žã€‚"
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
-msgstr ""
+msgstr "%{retryButtonStart}é‡è¯•%{retryButtonEnd}或%{newFileButtonStart}添加新文件%{newFileButtonEnd}。"
msgid "%{seconds}s"
-msgstr ""
+msgstr "%{seconds}秒"
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}"
@@ -667,7 +676,7 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "%{securityScanner}无结果,因为自å¯ç”¨ä»¥æ¥å°šæœªè¿è¡Œæµæ°´çº¿ã€‚%{linkStart}è¿è¡Œæµæ°´çº¿%{linkEnd}"
msgid "%{size} %{unit}"
-msgstr ""
+msgstr "%{size} %{unit}"
msgid "%{size} GiB"
msgstr "%{size} GiB"
@@ -682,7 +691,7 @@ msgid "%{size} bytes"
msgstr "%{size}字节"
msgid "%{sourceBranch} into %{targetBranch}"
-msgstr ""
+msgstr "%{sourceBranch}到%{targetBranch}"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} æˆåŠŸåœ°æ交给 Akismet。"
@@ -700,13 +709,13 @@ msgid "%{state} epics"
msgstr "%{state}å²è¯—"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
-msgstr ""
+msgstr "%{strongStart}删除%{strongEnd}æºåˆ†æ”¯"
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr "%{strongStart}注æ„:%{strongEnd} 添加自定义阶段åŽï¼Œæ‚¨å¯ä»¥é€šè¿‡å°†å…¶æ‹–动到所需ä½ç½®æ¥å¯¹é˜¶æ®µè¿›è¡Œé‡æ–°æŽ’åºã€‚"
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
-msgstr ""
+msgstr "%{strongStart}æ示:%{strongEnd}您å¯ä»¥%{linkStart}通过以下命令%{linkEnd}å°†åˆå¹¶è¯·æ±‚检出到本地。"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} 次æ交"
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} 文件"
@@ -756,10 +777,10 @@ msgid "%{timebox_name} should belong either to a project or a group."
msgstr "%{timebox_name}应该属于一个项目或一个群组。"
msgid "%{timebox_type} does not support burnup charts"
-msgstr ""
+msgstr "%{timebox_type}ä¸æ”¯æŒç‡ƒçƒ§å›¾"
msgid "%{timebox_type} must have a start and due date"
-msgstr ""
+msgstr "%{timebox_type}必须有开始日期和截止日期"
msgid "%{title} %{operator} %{threshold}"
msgstr "%{title} %{operator} %{threshold}"
@@ -780,13 +801,13 @@ msgid "%{totalWeight} total weight"
msgstr "%{totalWeight}总æƒé‡"
msgid "%{total_warnings} warning(s) found:"
-msgstr ""
+msgstr "找到%{total_warnings}个警告(s): "
msgid "%{total} open issue weight"
msgstr "%{total}å¼€å¯è®®é¢˜æƒé‡"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
-msgstr ""
+msgstr "找到%{total}个警告: æ˜¾ç¤ºå‰ %{warningsDisplayed}"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}分享给GitLab Inc.çš„ä¿¡æ¯ã€‚"
@@ -801,7 +822,7 @@ msgid "%{user_name} profile page"
msgstr "%{user_name}的个人资料"
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
-msgstr ""
+msgstr "%{username}请求在您的实例 %{host}创建一个GitLab å¸æˆ·ï¼š"
msgid "%{username}'s avatar"
msgstr "%{username} 的头åƒ"
@@ -819,25 +840,25 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤ç»„或项目中的事件å‘é€é€šçŸ¥åˆ°web应用程åºã€‚ 如需使用webhook, 我们推è优先使用已有%{integrations_link_start}集æˆ%{link_end}。"
msgid "&lt; 1 hour"
-msgstr ""
+msgstr "&lt; 1å°æ—¶"
msgid "'%{data}' at %{location} does not match format: %{format}"
-msgstr ""
+msgstr "%{location}上的'%{data}'ä¸ç¬¦åˆæ ¼å¼: %{format}"
msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
-msgstr ""
+msgstr "%{location}上的'%{data}'ä¸åŒ¹é…模å¼: %{pattern}"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
-msgstr ""
+msgstr "%{location}上的'%{data}'无效: error_type=%{type}"
msgid "'%{data}' at %{location} is not of type: %{type}"
-msgstr ""
+msgstr "%{location}上的'%{data}'ä¸å±žäºŽ: %{type}"
msgid "'%{data}' at %{location} is not one of: %{enum}"
-msgstr ""
+msgstr "%{location}上的'%{data}'ä¸æ˜¯ä»»ä½•ä¸€ç§: %{enum}"
msgid "'%{data}' at %{location} is not: %{const}"
-msgstr ""
+msgstr "%{location}上的'%{data}'ä¸æ˜¯: %{const}"
msgid "'%{level}' is not a valid visibility level"
msgstr "“%{level}â€ä¸æ˜¯æœ‰æ•ˆçš„å¯è§æ€§çº§åˆ«"
@@ -846,7 +867,7 @@ msgid "'%{name}' Value Stream created"
msgstr "'%{name}'价值æµå·²åˆ›å»º"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "“%{name}â€ä»·å€¼æµå·²åˆ é™¤"
msgid "'%{name}' stage already exists"
msgstr "“%{name}â€é˜¶æ®µå·²ç»å­˜åœ¨"
@@ -867,9 +888,15 @@ msgstr "(%{mrCount} å·²åˆå¹¶)"
msgid "(%{value}) has already been taken"
msgstr "(%{value})已被使用"
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(æ— å˜æ›´å†…容)"
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
msgid "(check progress)"
msgstr "(检查进度)"
@@ -880,7 +907,7 @@ msgid "(line: %{startLine})"
msgstr "(行: %{startLine})"
msgid "(max size 15 MB)"
-msgstr ""
+msgstr "(最大 15 MB)"
msgid "(removed)"
msgstr "(已删除)"
@@ -904,7 +931,7 @@ msgid "+ %{numberOfHiddenAssignees} more"
msgstr "+ 其余 %{numberOfHiddenAssignees} æ¡"
msgid "+ %{numberOfHiddenReviewers} more"
-msgstr ""
+msgstr "+ 还有%{numberOfHiddenReviewers}æ¡"
msgid "+%d more"
msgid_plural "+%d more"
@@ -914,16 +941,16 @@ msgid "+%{approvers} more approvers"
msgstr "+å¦å¤–%{approvers}个核准人"
msgid "+%{more_assignees_count}"
-msgstr ""
+msgstr "+%{more_assignees_count}"
msgid "+%{more_assignees_count} more assignees"
-msgstr ""
+msgstr "+其他%{more_assignees_count}å指派人"
msgid "+%{more_reviewers_count}"
-msgstr ""
+msgstr "+%{more_reviewers_count}"
msgid "+%{more_reviewers_count} more reviewers"
-msgstr ""
+msgstr "+%{more_reviewers_count} ä½è¯„审者"
msgid "+%{tags} more"
msgstr "+其余%{tags}个"
@@ -952,7 +979,7 @@ msgid "- show less"
msgstr "- 显示较少"
msgid "."
-msgstr ""
+msgstr "."
msgid "0 bytes"
msgstr "0 字节"
@@ -964,7 +991,7 @@ msgid "0 for unlimited, only effective with remote storage enabled."
msgstr "0表示无é™åˆ¶ï¼Œä»…在å¯ç”¨è¿œç¨‹å­˜å‚¨æ—¶æœ‰æ•ˆã€‚"
msgid "0t1DgySidms"
-msgstr ""
+msgstr "0t1DgySidms"
msgid "1 Day"
msgid_plural "%d Days"
@@ -972,7 +999,7 @@ msgstr[0] "%d天"
msgid "1 Issue"
msgid_plural "%d Issues"
-msgstr[0] ""
+msgstr[0] "%d个议题"
msgid "1 closed issue"
msgid_plural "%{issues} closed issues"
@@ -988,7 +1015,7 @@ msgstr[0] "%d天"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
-msgstr[0] ""
+msgstr[0] "%d个部署密钥"
msgid "1 group"
msgid_plural "%d groups"
@@ -1084,10 +1111,7 @@ msgid ":%{startLine} to %{endLine}"
msgstr ":%{startLine}到%{endLine}"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
-msgstr ""
-
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "Runner是一个执行任务的进程。您å¯ä»¥æ ¹æ®éœ€è¦é…置任æ„æ•°é‡çš„Runner。"
+msgstr "%{incident_docs_start}修改了%{incident_docs_end}个议题,以指导事件的解决。"
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr ".NET Core控制å°åº”用程åºæ¨¡æ¿ï¼Œå¯é’ˆå¯¹ä»»ä½•.NET Core项目进行自定义"
@@ -1095,20 +1119,20 @@ msgstr ".NET Core控制å°åº”用程åºæ¨¡æ¿ï¼Œå¯é’ˆå¯¹ä»»ä½•.NET Core项目进
msgid "A CI/CD pipeline must run and be successful before merge."
msgstr "åˆå¹¶å‰CI/CDæµæ°´çº¿å¿…é¡»è¿è¡Œä¸”æˆåŠŸã€‚"
-msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "一个GitBook站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
+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 ""
+msgstr "Gitpod通过Springå’ŒJavaé…置的Web应用程åº"
-msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "一个Hexo站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
+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 "一个Hugo站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
+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 "一个Jekyll站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
+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 "验è¯ä½ çš„域å之å‰ï¼Œæˆ‘ä»¬æ— æ³•èŽ·å– Encrype SSL è¯ä¹¦ã€‚"
@@ -1119,6 +1143,9 @@ msgstr "将使用您的电å­é‚®ä»¶åœ°å€ä¸ºæ­¤GitLab安装并é…ç½®Let's Encryp
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "使用AWS Lambda,AWS API网关和GitLab Pages的基本页é¢å’Œæ— æœåŠ¡å™¨åŠŸèƒ½"
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
msgid "A complete DevOps platform"
msgstr "一个完整的DevOpså¹³å°"
@@ -1146,6 +1173,9 @@ msgstr "群组为多个项目的集åˆã€‚"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
msgstr "群组在GitLab中代表您的组织。群组å¯ä»¥ç”¨æ¥ç®¡ç†ç”¨æˆ·å¹¶åœ¨è¿›è¡Œè·¨é¡¹ç›®åˆä½œã€‚"
+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 "GitLab滥用审查团队æˆå‘˜å°†ä¼šå°½å¿«æŸ¥çœ‹æ‚¨çš„报告。"
@@ -1153,6 +1183,9 @@ msgid "A merge request approval is required when a security report contains a ne
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"
@@ -1171,16 +1204,19 @@ 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 HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "一个纯HTML站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
+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 "å¹³å°å€¼å¯ä»¥æ˜¯web, mob或app。"
-msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools."
-msgstr "使用Salesforce Developer工具开å‘Salesforce App的项目样æ¿ã€‚"
+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 "项目包å«ç¾Žå›½å«ç”Ÿä¸Žå…¬å…±æœåŠ¡éƒ¨å‘布的HIPAA审计å议中æ¯ä¸ªå®¡è®¡æŸ¥è¯¢çš„议题"
@@ -1188,11 +1224,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "适用于Android应用的éšæ—¶å¯ç”¨çš„模æ¿ã€‚"
+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 ready-to-go template for use with iOS Swift apps."
-msgstr "适用于iOS Swift应用的éšæ—¶å¯ç”¨çš„模æ¿ã€‚"
+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 "用于在作业日志中查找匹é…测试覆盖率输出的正则表达å¼ã€‚留空则ç¦ç”¨"
@@ -1203,9 +1242,15 @@ msgstr "一个用于识别外部储存的请求安全令牌。"
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
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 user can only participate in a rotation once"
+msgstr ""
+
msgid "A user with write access to the source branch selected this option"
msgstr "具有对æºåˆ†æ”¯çš„写入æƒé™çš„用户选择了此选项"
@@ -1213,7 +1258,7 @@ msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt c
msgstr "需è¦å¤„ç†ï¼š 获å–GitLab Pages域%{domain}çš„Let's Encrypt加密è¯ä¹¦æ—¶å‡ºäº†é”™ã€‚"
msgid "API Fuzzing"
-msgstr ""
+msgstr "API模糊测试"
msgid "API Help"
msgstr "API帮助"
@@ -1224,14 +1269,17 @@ msgstr "API令牌"
msgid "AWS Access Key"
msgstr "AWS访问密钥"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "AWS访问密钥。仅当ä¸ä½¿ç”¨è§’色实例凭æ®æ—¶æ‰éœ€è¦"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS秘密访问密钥"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "AWS秘密访问密钥。仅当ä¸ä½¿ç”¨è§’色实例凭æ®æ—¶æ‰éœ€è¦"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "终止"
@@ -1272,20 +1320,23 @@ msgstr "无法使用您的LDAPå¸æˆ·è¿›è¡Œç™»å½•ã€‚"
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 ""
+msgstr "访问过期"
msgid "Access forbidden. Check your access level."
msgstr "访问被ç¦æ­¢ã€‚检查您的访问æƒé™ã€‚"
msgid "Access granted"
-msgstr ""
+msgstr "已授予访问"
msgid "Access requests"
-msgstr ""
+msgstr "访问请求"
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…许访问%{classification_label}"
@@ -1294,7 +1345,7 @@ msgid "Access to Pages websites are controlled based on the user's membership to
msgstr "Pages网站å¯ä¾æ®ç”¨æˆ·å¯¹é¡¹ç›®çš„æˆå‘˜èº«ä»½è¿›è¡Œè®¿é—®æŽ§åˆ¶ã€‚ 选中此项åŽï¼Œç”¨æˆ·éœ€è¦ç™»å½•æ‰èƒ½è®¿é—®æ‰€æœ‰çš„Pages网站。"
msgid "AccessDropdown|Deploy Keys"
-msgstr ""
+msgstr "部署密钥"
msgid "AccessDropdown|Groups"
msgstr "群组"
@@ -1399,7 +1450,7 @@ msgid "Activate Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
msgid "Activate user activity analysis"
-msgstr ""
+msgstr "å¯ç”¨ç”¨æˆ·æ´»åŠ¨åˆ†æž"
msgid "Active"
msgstr "å¯ç”¨"
@@ -1511,7 +1562,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} 字符"
@@ -1544,7 +1595,7 @@ msgid "Add comment now"
msgstr "ç«‹å³æ·»åŠ è¯„论"
msgid "Add comment to design"
-msgstr ""
+msgstr "添加注释到设计"
msgid "Add deploy freeze"
msgstr "添加部署冻结"
@@ -1559,7 +1610,7 @@ msgid "Add environment"
msgstr "添加环境"
msgid "Add existing confidential %{issuableType}"
-msgstr ""
+msgstr "添加现有的ç§å¯†%{issuableType}"
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "添加页眉和页脚到电å­é‚®ä»¶ã€‚请注æ„,颜色设置仅适用于应用程åºç•Œé¢"
@@ -1574,7 +1625,7 @@ msgid "Add italic text"
msgstr "添加斜体文本"
msgid "Add key"
-msgstr ""
+msgstr "添加密钥"
msgid "Add label(s)"
msgstr "添加标记"
@@ -1667,7 +1718,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 "为å²è¯—添加了一个议题。"
@@ -1688,7 +1739,7 @@ msgid "Additional Metadata"
msgstr "附加元数æ®"
msgid "Additional minutes"
-msgstr "é¢å¤–的分钟数"
+msgstr "更多的分钟数"
msgid "Additional text"
msgstr "附加文本"
@@ -1706,7 +1757,7 @@ msgid "Adds a Zoom meeting"
msgstr "添加一个Zoom会议"
msgid "Adds a to do."
-msgstr ""
+msgstr "添加一个待办事项."
msgid "Adds an issue to an epic."
msgstr "将议题添加到å²è¯—。"
@@ -1742,13 +1793,13 @@ msgid "Admin notes"
msgstr "管ç†å‘˜å¤‡æ³¨"
msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
-msgstr ""
+msgstr "%{billable_users_link_start}了解更多%{billable_users_link_end}收费用户是如何定义的"
msgid "AdminArea|Active users"
msgstr "活跃用户"
msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
-msgstr ""
+msgstr "本实例中创建的所有用户,其中也包括éž%{billable_users_link_start}收费用户%{billable_users_link_end}。"
msgid "AdminArea|Billable users"
msgstr "活跃用户"
@@ -1760,16 +1811,16 @@ msgid "AdminArea|Bots"
msgstr "机器人"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "组件"
msgid "AdminArea|Developer"
msgstr "å¼€å‘人员"
msgid "AdminArea|Features"
-msgstr ""
+msgstr "功能"
msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
+msgstr "群组: %{number_of_groups}"
msgid "AdminArea|Guest"
msgstr "访客"
@@ -1778,34 +1829,34 @@ msgid "AdminArea|Included Free in license"
msgstr "å…费包å«äºŽè®¸å¯è¯ä¸­"
msgid "AdminArea|Latest groups"
-msgstr ""
+msgstr "最新群组"
msgid "AdminArea|Latest projects"
-msgstr ""
+msgstr "最新项目"
msgid "AdminArea|Latest users"
-msgstr ""
+msgstr "最新用户"
msgid "AdminArea|Maintainer"
msgstr "维护者"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "新建群组"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "新建项目"
msgid "AdminArea|New user"
-msgstr ""
+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 ""
+msgstr "一旦实例达到用户上é™ï¼Œä»»ä½•æ·»åŠ æˆ–请求访问的用户都必须由管ç†å‘˜æ‰¹å‡†ã€‚该字段留空视为无é™åˆ¶ã€‚"
msgid "AdminArea|Owner"
msgstr "所有者"
msgid "AdminArea|Projects: %{number_of_projects}"
-msgstr ""
+msgstr "项目: %{number_of_projects}"
msgid "AdminArea|Reporter"
msgstr "报告者"
@@ -1826,7 +1877,7 @@ msgid "AdminArea|Total users"
msgstr "所有用户"
msgid "AdminArea|User cap"
-msgstr ""
+msgstr "用户上é™"
msgid "AdminArea|Users statistics"
msgstr "用户统计"
@@ -1838,7 +1889,7 @@ msgid "AdminArea|Users without a Group and Project"
msgstr "没有群组和项目的用户"
msgid "AdminArea|Users: %{number_of_users}"
-msgstr ""
+msgstr "用户: %{number_of_users}"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "您å³å°†åœæ­¢æ‰€æœ‰ä½œä¸šã€‚这会中断并结æŸæ‰€æœ‰æ­£åœ¨è¿è¡Œçš„作业。"
@@ -1864,6 +1915,9 @@ msgstr "将集æˆè®¾ç½®åº”用于所有项目"
msgid "AdminSettings|Auto DevOps domain"
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;常规。"
@@ -1873,6 +1927,9 @@ msgstr "为新项目å¯ç”¨å…±äº«Runner"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "环境å˜é‡é»˜è®¤å—ä¿æŠ¤"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr "转到常规设置"
@@ -1895,7 +1952,7 @@ msgid "AdminSettings|Select a template"
msgstr "选择模æ¿"
msgid "AdminSettings|Service Templates will soon be deprecated."
-msgstr ""
+msgstr "æœåŠ¡æ¨¡æ¿å°†å¾ˆå¿«è¢«å¼ƒç”¨ã€‚"
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr "Service模æ¿å…许您设置集æˆçš„默认值"
@@ -1913,7 +1970,7 @@ msgid "AdminSettings|The required pipeline configuration can be selected from th
msgstr "强制æµæ°´çº¿é…ç½®å¯ä»Ž%{link_start}实例模æ¿åº“%{link_end}中%{code_start}gitlab-ci%{code_end}目录选择或使用GitLabæ供的é…置。"
msgid "AdminSettings|Try using the latest version of Integrations instead."
-msgstr ""
+msgstr "请使用最新版本的集æˆã€‚"
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "创建一个新的环境å˜é‡æ—¶ï¼Œå®ƒä¼šè¢«é»˜è®¤ä¿æŠ¤ã€‚"
@@ -1943,19 +2000,19 @@ msgid "AdminStatistics|Snippets"
msgstr "代ç ç‰‡æ®µ"
msgid "AdminUsers|(Admin)"
-msgstr ""
+msgstr "管ç†å‘˜"
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "å·²å±è”½"
msgid "AdminUsers|(Deactivated)"
-msgstr ""
+msgstr "已冻结"
msgid "AdminUsers|(Internal)"
-msgstr ""
+msgstr "内部"
msgid "AdminUsers|(Pending approval)"
-msgstr ""
+msgstr "等待批准"
msgid "AdminUsers|2FA Disabled"
msgstr "未å¯ç”¨åŒé‡è®¤è¯"
@@ -1967,19 +2024,19 @@ msgid "AdminUsers|Access"
msgstr "访问类型"
msgid "AdminUsers|Access Git repositories"
-msgstr ""
+msgstr "访问 Git 仓库"
msgid "AdminUsers|Access the API"
-msgstr ""
+msgstr "访问 API"
msgid "AdminUsers|Activate"
-msgstr ""
+msgstr "激活"
msgid "AdminUsers|Activate user"
-msgstr ""
+msgstr "激活用户"
msgid "AdminUsers|Activate user %{username}?"
-msgstr ""
+msgstr "激活用户%{username}å—?"
msgid "AdminUsers|Active"
msgstr "活跃"
@@ -1994,28 +2051,28 @@ msgid "AdminUsers|Admins"
msgstr "管ç†å‘˜"
msgid "AdminUsers|Approve"
-msgstr ""
+msgstr "批准"
msgid "AdminUsers|Approve user"
-msgstr ""
+msgstr "批准用户"
msgid "AdminUsers|Approved users can:"
-msgstr ""
+msgstr "已获批准的用户å¯ä»¥ï¼š"
msgid "AdminUsers|Are you sure?"
-msgstr ""
+msgstr "确定继续å—?"
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自动标记为默认内部用户"
msgid "AdminUsers|Be added to groups and projects"
-msgstr ""
+msgstr "添加到群组和项目"
msgid "AdminUsers|Block"
msgstr "ç¦ç”¨"
msgid "AdminUsers|Block this user"
-msgstr ""
+msgstr "å±è”½æ­¤ç”¨æˆ·"
msgid "AdminUsers|Block user"
msgstr "ç¦ç”¨ç”¨æˆ·"
@@ -2030,7 +2087,7 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "ç¦ç”¨ç”¨æˆ·å…·æœ‰ä»¥ä¸‹æ•ˆæžœï¼š"
msgid "AdminUsers|Cannot sign in or access instance information"
-msgstr ""
+msgstr "无法登录或访问实例信æ¯"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "无法解除已ç¦ç”¨çš„ LDAP 用户"
@@ -2042,7 +2099,7 @@ msgid "AdminUsers|Deactivate user"
msgstr "冻结用户"
msgid "AdminUsers|Deactivate user %{username}?"
-msgstr ""
+msgstr "冻结用户%{username}?"
msgid "AdminUsers|Deactivated"
msgstr "已冻结"
@@ -2069,7 +2126,7 @@ msgid "AdminUsers|External users cannot see internal or private projects unless
msgstr "除éžæ˜Žç¡®æŽˆäºˆè®¿é—®æƒé™ï¼Œå¦åˆ™å¤–部用户无法查看内部或ç§æœ‰é¡¹ç›®ã€‚å¦å¤–,外部用户无法创建项目,群组或个人代ç ç‰‡æ®µã€‚"
msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "欲了解更多信æ¯ï¼Œè¯·å‚阅 %{link_start}用户å¸æˆ·åˆ é™¤æ–‡æ¡£ã€‚%{link_end}"
msgid "AdminUsers|Is using seat"
msgstr "正在使用许å¯å¸­ä½"
@@ -2078,7 +2135,7 @@ msgid "AdminUsers|It's you!"
msgstr "自己ï¼"
msgid "AdminUsers|Log in"
-msgstr ""
+msgstr "登录"
msgid "AdminUsers|New user"
msgstr "新用户"
@@ -2090,7 +2147,7 @@ msgid "AdminUsers|Owned groups will be left"
msgstr "拥有的群组将被ä¿ç•™"
msgid "AdminUsers|Pending approval"
-msgstr ""
+msgstr "等待批准"
msgid "AdminUsers|Personal projects will be left"
msgstr "个人项目将被ä¿ç•™"
@@ -2108,13 +2165,13 @@ msgid "AdminUsers|Regular users have access to their groups and projects"
msgstr "普通用户å¯ä»¥è®¿é—®ä»–们的群组和项目"
msgid "AdminUsers|Reject"
-msgstr ""
+msgstr "æ‹’ç»"
msgid "AdminUsers|Reject request"
-msgstr ""
+msgstr "æ‹’ç»è¯·æ±‚"
msgid "AdminUsers|Rejected users:"
-msgstr ""
+msgstr "已拒ç»çš„用户: "
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr "æ¢å¤ç”¨æˆ·è®¿é—®è´¦æˆ·ï¼ŒåŒ…括网页ã€Gitå’ŒAPI。"
@@ -2147,7 +2204,7 @@ msgid "AdminUsers|The user will not receive any notifications"
msgstr "此用户将ä¸ä¼šæ”¶åˆ°ä»»ä½•é€šçŸ¥"
msgid "AdminUsers|This user has requested access"
-msgstr ""
+msgstr "此用户请求访问"
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "请输入 %{projectName} æ¥ç¡®è®¤"
@@ -2156,13 +2213,13 @@ msgid "AdminUsers|To confirm, type %{username}"
msgstr "请输入 %{username} æ¥ç¡®è®¤"
msgid "AdminUsers|Unblock"
-msgstr ""
+msgstr "å–消ç¦ç”¨"
msgid "AdminUsers|Unblock user"
-msgstr ""
+msgstr "å–消ç¦ç”¨ç”¨æˆ·"
msgid "AdminUsers|Unblock user %{username}?"
-msgstr ""
+msgstr "å–消ç¦ç”¨ç”¨æˆ·%{username}å—?"
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "用户将无法访问git仓库"
@@ -2174,55 +2231,55 @@ msgid "AdminUsers|When the user logs back in, their account will reactivate as a
msgstr "用户é‡æ–°ç™»å½•åŽï¼Œå…¶å¸æˆ·å°†æ¢å¤ä¸ºå®Œå…¨æœ‰æ•ˆçš„å¸æˆ·"
msgid "AdminUsers|Will be deleted"
-msgstr ""
+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 ""
+msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。该用户的议题ã€åˆå¹¶è¯·æ±‚以åŠç›¸å…³çš„群组将被转移到系统的“Ghost用户â€ã€‚为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strongStart}ç¦ç”¨ç”¨æˆ·%{strongEnd} 功能。一旦您 %{strongStart}删除用户%{strongEnd},将无法撤消或æ¢å¤ã€‚"
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 ""
+msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。此æ“作会删除该用户的所有议题ã€åˆå¹¶è¯·æ±‚以åŠç›¸å…³çš„群组。为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strongStart}ç¦ç”¨ç”¨æˆ·%{strongEnd} 功能。一旦您 %{strongStart}删除用户%{strongEnd},将无法撤消或æ¢å¤ã€‚"
msgid "AdminUsers|You can always block their account again if needed."
-msgstr ""
+msgstr "如果需è¦ï¼Œæ‚¨éšæ—¶å¯ä»¥ç¦ç”¨ä»–们的å¸æˆ·ã€‚"
msgid "AdminUsers|You can always deactivate their account again if needed."
-msgstr ""
+msgstr "如果需è¦ï¼Œæ‚¨éšæ—¶å¯ä»¥å†»ç»“他们的å¸æˆ·ã€‚"
msgid "AdminUsers|You can always re-activate their account, their data will remain intact."
-msgstr ""
+msgstr "您å¯ä»¥éšæ—¶é‡æ–°æ¿€æ´»ä»–们的å¸æˆ·ï¼Œä»–们的数æ®å°†ä¿æŒä¸å˜ã€‚"
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
-msgstr ""
+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 ""
+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 ""
+msgstr "新加入的用户必须ç»è¿‡ç³»ç»Ÿç®¡ç†å‘˜å®¡æ ¸ä¸Žæ‰¹å‡†ã€‚了解更多关于%{help_link_start}用户数å°é¡¶%{help_link_end}çš„ä¿¡æ¯ã€‚"
msgid "Admin|View pending user approvals"
-msgstr ""
+msgstr "查看等待中的用户批准"
msgid "Admin|Your instance has reached its user cap"
-msgstr ""
+msgstr "您的实例已达到其用户å°é¡¶å€¼"
msgid "Advanced"
msgstr "高级"
msgid "Advanced Search"
-msgstr ""
+msgstr "高级æœç´¢"
msgid "Advanced Search with Elasticsearch"
-msgstr ""
+msgstr "使用Elasticsearch进行高级æœç´¢"
msgid "Advanced Settings"
msgstr "高级设置"
@@ -2237,16 +2294,16 @@ msgid "After a successful password update, you will be redirected to the login p
msgstr "密ç æ›´æ–°æˆåŠŸåŽï¼Œæ‚¨å°†è¢«é‡å®šå‘到登录页é¢ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ–°å¯†ç é‡æ–°ç™»å½•ã€‚"
msgid "After sign-out path"
-msgstr ""
+msgstr "登出åŽè·¯å¾„"
msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr ""
+msgstr "在那之åŽï¼Œæ‚¨å°†æ— æ³•ä½¿ç”¨åˆå¹¶æ‰¹å‡†æˆ–代ç è´¨é‡åŠå…¶ä»–众多功能。"
msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
-msgstr ""
+msgstr "在那之åŽï¼Œæ‚¨å°†æ— æ³•ä½¿ç”¨åˆå¹¶æ‰¹å‡†æˆ–å²è¯—以åŠå…¶ä»–众多功能。"
msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
-msgstr ""
+msgstr "在那之åŽï¼Œæ‚¨å°†æ— æ³•ä½¿ç”¨åˆå¹¶æ‰¹å‡†æˆ–å²è¯—以åŠä¼—多安全功能。"
msgid "Alert"
msgid_plural "Alerts"
@@ -2256,7 +2313,7 @@ msgid "AlertManagement|Acknowledged"
msgstr "已确认"
msgid "AlertManagement|Activity feed"
-msgstr ""
+msgstr "活动订阅"
msgid "AlertManagement|Alert"
msgstr "警报"
@@ -2289,7 +2346,7 @@ msgid "AlertManagement|Authorize external service"
msgstr "授æƒå¤–部æœåŠ¡"
msgid "AlertManagement|Create incident"
-msgstr ""
+msgstr "创建事件"
msgid "AlertManagement|Critical"
msgstr "严é‡"
@@ -2301,7 +2358,7 @@ msgid "AlertManagement|Edit"
msgstr "编辑"
msgid "AlertManagement|Environment"
-msgstr ""
+msgstr "环境"
msgid "AlertManagement|Events"
msgstr "事件"
@@ -2310,13 +2367,13 @@ msgid "AlertManagement|High"
msgstr "高"
msgid "AlertManagement|Incident"
-msgstr ""
+msgstr "事件"
msgid "AlertManagement|Info"
msgstr "ä¿¡æ¯"
msgid "AlertManagement|Key"
-msgstr ""
+msgstr "é”®"
msgid "AlertManagement|Low"
msgstr "低"
@@ -2348,9 +2405,6 @@ msgstr "æ— "
msgid "AlertManagement|Open"
msgstr "打开"
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr "Opsgenieå·²å¯ç”¨"
-
msgid "AlertManagement|Please try again."
msgstr "请é‡è¯•ã€‚"
@@ -2364,7 +2418,7 @@ msgid "AlertManagement|Resolved"
msgstr "已解决"
msgid "AlertManagement|Runbook"
-msgstr ""
+msgstr "Runbook"
msgid "AlertManagement|Service"
msgstr "æœåŠ¡"
@@ -2412,34 +2466,28 @@ msgid "AlertManagement|Unknown"
msgstr "未知"
msgid "AlertManagement|Value"
-msgstr ""
-
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr "在Opsgenie中查看警报"
+msgstr "值"
msgid "AlertManagement|View incident"
-msgstr ""
-
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr "您已å¯ç”¨Opsgenie集æˆã€‚您的警报将å¯ç›´æŽ¥åœ¨Opsgenie中查看。"
+msgstr "查看事件"
msgid "AlertMappingBuilder|Define fallback"
-msgstr ""
+msgstr "定义回退"
msgid "AlertMappingBuilder|GitLab alert key"
-msgstr ""
+msgstr "GitLab警报键"
msgid "AlertMappingBuilder|Make selection"
-msgstr ""
+msgstr "进行选择"
msgid "AlertMappingBuilder|Payload alert key"
-msgstr ""
+msgstr "负载警报键"
msgid "AlertMappingBuilder|Select key"
-msgstr ""
+msgstr "选择键"
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
-msgstr ""
+msgstr "标题为在 GitLab中警报的必填字段。如果您指定的负载字段ä¸å¯ç”¨ï¼Œè¯·æŒ‡æ˜Žåº”该使用哪个字段。"
msgid "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 "查看外部æœåŠ¡çš„文档以了解将此信æ¯æ供给外部æœåŠ¡çš„ä½ç½®ï¼Œä»¥åŠ%{linkStart}GitLab文档%{linkEnd}æ¥äº†è§£æœ‰å…³é…置端点的更多信æ¯ã€‚"
@@ -2448,22 +2496,19 @@ msgid "AlertService|You must provide this URL and authorization key to authorize
msgstr "您必须æ供此URL和授æƒå¯†é’¥æ‰èƒ½æŽˆæƒå¤–部æœåŠ¡å°†è­¦æŠ¥å‘é€åˆ°GitLab。您å¯ä»¥æ供此URL和多个æœåŠ¡çš„密钥。é…置外部æœåŠ¡åŽï¼Œæ¥è‡ªæ‚¨æœåŠ¡çš„警报将显示在GitLab%{linkStart}警报%{linkEnd}页é¢ä¸Šã€‚"
msgid "AlertSettings|1. Select integration type"
-msgstr ""
-
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
+msgstr "1. 选择集æˆç±»åž‹"
msgid "AlertSettings|2. Name integration"
-msgstr ""
+msgstr "2. 集æˆå称"
msgid "AlertSettings|3. Set up webhook"
-msgstr ""
+msgstr "3. 设置webhook"
msgid "AlertSettings|4. Sample alert payload (optional)"
-msgstr ""
+msgstr "4. 示例警报负载(å¯é€‰)"
msgid "AlertSettings|5. Map fields (optional)"
-msgstr ""
+msgstr "5. 映射字段 (å¯é€‰)"
msgid "AlertSettings|API URL"
msgstr "API网å€"
@@ -2475,7 +2520,7 @@ msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr "å°†URLå’Œauth密钥添加到Prometheusé…置文件中"
msgid "AlertSettings|Add new integrations"
-msgstr ""
+msgstr "添加新的集æˆ"
msgid "AlertSettings|Alert test payload"
msgstr "警报测试数æ®"
@@ -2484,19 +2529,19 @@ msgid "AlertSettings|Authorization key"
msgstr "授æƒå¯†é’¥"
msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
-msgstr ""
+msgstr "授æƒå¯†é’¥å·²æˆåŠŸé‡ç½®ã€‚请立å³ä¿å­˜æ‚¨çš„更改。"
msgid "AlertSettings|Copy"
msgstr "å¤åˆ¶"
msgid "AlertSettings|Delete integration"
-msgstr ""
+msgstr "删除集æˆ"
msgid "AlertSettings|Edit payload"
-msgstr ""
+msgstr "编辑负载"
msgid "AlertSettings|Enter integration name"
-msgstr ""
+msgstr "输入集æˆå称"
msgid "AlertSettings|Enter test alert JSON...."
msgstr "输入测试警告JSON ..."
@@ -2505,46 +2550,46 @@ msgid "AlertSettings|External Prometheus"
msgstr "外部Prometheus"
msgid "AlertSettings|HTTP Endpoint"
-msgstr ""
+msgstr "HTTP 端点"
msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
-msgstr ""
+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 ""
+msgstr "如果您æ供了示例警报负载,就å¯ä»¥ä¸ºç«¯ç‚¹åˆ›å»ºè‡ªå®šä¹‰æ˜ å°„。 下é¢åˆ—出默认的GitLab警报键。请定义哪个负载键应该映射到指定的GitLab键。"
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 ""
+msgstr "在 GitLabçš„å…费版本中,æ¯ç§ç±»åž‹åªèƒ½æ·»åŠ ä¸€ä¸ªé›†æˆã€‚ %{linkStart}å‡çº§æ‚¨çš„订阅%{linkEnd}以添加更多集æˆã€‚"
msgid "AlertSettings|Integration"
-msgstr ""
+msgstr "集æˆ"
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
-msgstr ""
-
-msgid "AlertSettings|Opsgenie"
-msgstr "Opsgenie"
+msgstr "了解更多我们å³å°†æŽ¨å‡ºçš„%{linkStart}集æˆ%{linkEnd}"
msgid "AlertSettings|Proceed with editing"
+msgstr "继续编辑"
+
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
-msgstr ""
+msgstr "Prometheus API基础URL"
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 ""
+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 ""
+msgstr "请æ供一个æ¥è‡ªæ¬²é›†æˆç›‘控工具的示例负载。 该负载å¯ç”¨äºŽæµ‹è¯•é›†æˆ(å¯é€‰)。"
msgid "AlertSettings|Reset Key"
-msgstr ""
+msgstr "é‡ç½®é”®"
msgid "AlertSettings|Reset key"
msgstr "é‡ç½®å¯†é’¥"
msgid "AlertSettings|Reset the mapping"
-msgstr ""
+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 "é‡ç½®æ­¤é¡¹ç›®çš„授æƒå¯†é’¥å°†éœ€è¦æ›´æ–°æ¯ä¸ªè­¦æŠ¥æºä¸­å¯ç”¨çš„授æƒå¯†é’¥ã€‚"
@@ -2553,19 +2598,19 @@ msgid "AlertSettings|Review your external service's documentation to learn where
msgstr "查看外部æœåŠ¡çš„文档以了解将此信æ¯æ供给外部æœåŠ¡çš„ä½ç½®ï¼Œä»¥åŠ%{linkStart}GitLab文档%{linkEnd}æ¥äº†è§£æœ‰å…³é…置端点的更多信æ¯ã€‚"
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
-msgstr ""
+msgstr "已解æžç¤ºä¾‹è´Ÿè½½ã€‚您现在å¯ä»¥æ˜ å°„字段。"
msgid "AlertSettings|Save and test payload"
-msgstr ""
+msgstr "ä¿å­˜å¹¶æµ‹è¯•è´Ÿè½½"
msgid "AlertSettings|Save integration"
-msgstr ""
+msgstr "ä¿å­˜é›†æˆ"
msgid "AlertSettings|Select integration type"
-msgstr ""
+msgstr "选择集æˆç±»åž‹"
msgid "AlertSettings|Submit payload"
-msgstr ""
+msgstr "æ交负载"
msgid "AlertSettings|Test alert payload"
msgstr "测试警报数æ®"
@@ -2577,7 +2622,7 @@ 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 ""
+msgstr "更新警报设置时出错。"
msgid "AlertSettings|There was an error while trying to reset the key. Please refresh the page to try again."
msgstr "å°è¯•é‡ç½®å¯†é’¥æ—¶å‡ºé”™ã€‚请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
@@ -2586,16 +2631,10 @@ msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr "URLä¸èƒ½ä¸ºç©ºï¼Œå¿…须以http或https开头。"
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 ""
+msgstr "使用下é¢çš„URL和授æƒå¯†é’¥æŽˆæƒPrometheuså‘GitLabå‘é€è­¦æŠ¥ã€‚查看Prometheus文档以了解在何处添加这些详细信æ¯ï¼Œä»¥åŠæŸ¥é˜…%{linkStart}GitLab文档%{linkEnd}以了解有关é…置端点的更多信æ¯ã€‚"
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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
+msgstr "使用下é¢çš„URL和授æƒå¯†é’¥æŽˆæƒå¤–部æœåŠ¡å‘GitLabå‘é€è­¦æŠ¥ã€‚查看外部æœåŠ¡æ–‡æ¡£ä»¥äº†è§£åœ¨ä½•å¤„添加这些详细信æ¯ï¼Œä»¥åŠæŸ¥é˜…%{linkStart}GitLab文档%{linkEnd}以了解有关é…置端点的更多信æ¯ã€‚"
msgid "AlertSettings|Webhook URL"
msgstr "Webhook网å€"
@@ -2607,10 +2646,10 @@ msgid "AlertSettings|You must provide this URL and authorization key to authoriz
msgstr "您必须æ供此URL和授æƒå¯†é’¥æ‰èƒ½æŽˆæƒå¤–部æœåŠ¡å°†è­¦æŠ¥å‘é€åˆ°GitLab。您å¯ä»¥æ供此URL和多个æœåŠ¡çš„密钥。é…置外部æœåŠ¡åŽï¼Œæ¥è‡ªæ‚¨æœåŠ¡çš„警报将显示在GitLab%{linkStart}警报%{linkEnd}页é¢ä¸Šã€‚"
msgid "AlertSettings|Your integration was successfully updated."
-msgstr ""
+msgstr "您的集æˆå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
-msgstr ""
+msgstr "{ \"events\": [{ \"application\": \"应用å称\" }] }"
msgid "Alerts"
msgstr "警报"
@@ -2619,46 +2658,46 @@ msgid "Alerts endpoint"
msgstr "警报端点"
msgid "AlertsIntegrations|Alerts will be created through this integration"
-msgstr ""
+msgstr "警报将通过此集æˆåˆ›å»º"
msgid "AlertsIntegrations|Alerts will not be created through this integration"
-msgstr ""
+msgstr "警报将ä¸ä¼šé€šè¿‡æ­¤é›†æˆåˆ›å»º"
msgid "AlertsIntegrations|Current integrations"
-msgstr ""
+msgstr "当å‰é›†æˆ"
msgid "AlertsIntegrations|Integration Name"
-msgstr ""
+msgstr "集æˆå称"
msgid "AlertsIntegrations|Integration payload is invalid. You can still save your changes."
-msgstr ""
+msgstr "集æˆè´Ÿè½½æ— æ•ˆã€‚您ä»ç„¶å¯ä»¥ä¿å­˜æ‚¨çš„更改。"
msgid "AlertsIntegrations|No integrations have been added yet"
-msgstr ""
+msgstr "尚未添加任何集æˆ"
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
-msgstr ""
+msgstr "无法更新当å‰é›†æˆã€‚请é‡è¯•ã€‚"
msgid "AlertsIntegrations|The integration could not be added. Please try again."
-msgstr ""
+msgstr "无法添加集æˆã€‚请é‡è¯•ã€‚"
msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
-msgstr ""
+msgstr "无法删除集æˆã€‚请é‡è¯•ã€‚"
msgid "AlertsIntegrations|The integration has been successfully removed."
-msgstr ""
+msgstr "集æˆå·²æˆåŠŸåˆ é™¤ã€‚"
msgid "AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list."
-msgstr ""
+msgstr "集æˆå·²æˆåŠŸä¿å­˜ã€‚æ¥è‡ªè¿™ä¸ªæ–°é›†æˆçš„警报将会显示在您的警报列表中。"
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
-msgstr ""
+msgstr "无法é‡ç½®é›†æˆä»¤ç‰Œã€‚请é‡è¯•ã€‚"
msgid "AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list."
-msgstr ""
+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 ""
+msgstr "您已选择删除%{integrationName}集æˆã€‚ 确定继续å—?这æ„味ç€æ‚¨å°†ä¸å†ä»Žè­¦æŠ¥åˆ—表中的此端点接收警报,此æ“作无法撤消。"
msgid "Algorithm"
msgstr "算法"
@@ -2681,9 +2720,6 @@ msgstr "所有分支"
msgid "All changes are committed"
msgstr "所有更改å‡å·²æ交"
-msgid "All default stages are currently visible"
-msgstr "当å‰æ‰€æœ‰é»˜è®¤é˜¶æ®µéƒ½æ˜¯å¯è§çš„"
-
msgid "All email addresses will be used to identify your commits."
msgstr "所有电å­é‚®ä»¶åœ°å€éƒ½å¯ç”¨äºŽæ ‡è¯†æ‚¨çš„æ交。"
@@ -2691,7 +2727,7 @@ msgid "All environments"
msgstr "所有环境"
msgid "All epics"
-msgstr ""
+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 "从模æ¿æˆ–导入时为空白项目将å¯ç”¨æ‰€æœ‰åŠŸèƒ½ï¼Œä½†å¯ä»¥åœ¨é¡¹ç›®è®¾ç½®ä¸­å°†å…¶ç¦ç”¨ã€‚"
@@ -2718,7 +2754,7 @@ msgid "All projects"
msgstr "所有项目"
msgid "All projects selected"
-msgstr ""
+msgstr "已选择所有项目"
msgid "All security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
msgstr "所有安全扫æ都已å¯ç”¨ï¼Œå› ä¸ºæ­¤é¡¹ç›®å·²å¼€å¯äº†%{linkStart}Auto DevOps%{linkEnd}"
@@ -2744,6 +2780,9 @@ msgstr "å…许群组所有者管ç†LDAP相关的设置"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "ä»…å…许所选å议用于 Git 访问。"
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr "å…许所有者管ç†åœ¨ç¾¤ç»„级别默认分支ä¿æŠ¤"
@@ -2751,7 +2790,7 @@ msgid "Allow owners to manually add users outside of LDAP"
msgstr "å…许负责人手动添加LDAP之外的用户"
msgid "Allow projects and subgroups to override the group setting"
-msgstr ""
+msgstr "å…许项目和å­ç¾¤ç»„覆盖群组设置"
msgid "Allow projects within this group to use Git LFS"
msgstr "å…许该群组中的项目使用Git LFS"
@@ -2763,7 +2802,7 @@ msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "å…许在Asciidoc文档中渲染PlantUML图。"
msgid "Allow rendering of diagrams in AsciiDoc and Markdown documents using %{link}."
-msgstr ""
+msgstr "å…许使用%{link}渲染AsciiDocå’ŒMarkdown文档中的图表。"
msgid "Allow repository mirroring to be configured by project maintainers"
msgstr "å…许项目维护者é…置仓库镜åƒ"
@@ -2778,7 +2817,7 @@ msgid "Allow requests to the local network from web hooks and services"
msgstr "å…许Webhookå’ŒæœåŠ¡å¯¹æœ¬åœ°ç½‘络的请求"
msgid "Allow subgroups to set up their own two-factor authentication rules"
-msgstr ""
+msgstr "å…许副组设置自己的åŒé‡èº«ä»½éªŒè¯è§„则"
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "åŒæ—¶å…许此秘钥推é€æ–‡ä»¶åˆ°ä»“库å—?(默认åªæ‹¥æœ‰æ‹‰å–æƒé™)"
@@ -2802,7 +2841,7 @@ msgid "Allowed Geo IP"
msgstr "å…许的Geo IP"
msgid "Allowed domains for sign-ups"
-msgstr ""
+msgstr "å…许注册的域"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "å…许使用电å­é‚®ä»¶åŸŸåé™åˆ¶ä»…å¯ç”¨äºŽé¡¶çº§ç¾¤ç»„"
@@ -2811,7 +2850,7 @@ msgid "Allowed to fail"
msgstr "å…许失败"
msgid "Allows projects or subgroups in this group to override the global setting."
-msgstr ""
+msgstr "å…许该组中的项目或å­ç»„覆盖全局设置。"
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "这里å¯ä»¥æ·»åŠ å’Œç®¡ç† Kubernetes 集群。"
@@ -2820,7 +2859,7 @@ msgid "Almost there"
msgstr "å³å°†å®Œæˆ"
msgid "Already blocked"
-msgstr ""
+msgstr "已被阻止"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr "也称为“签å‘者â€æˆ–“ä¾èµ–方信任标识符â€"
@@ -2859,10 +2898,10 @@ msgid "An %{link_start}alert%{link_end} with the same fingerprint is already ope
msgstr "具有相åŒæŒ‡çº¹çš„%{link_start}警报%{link_end}已打开。è¦æ›´æ”¹æ­¤è­¦æŠ¥çš„状æ€ï¼Œè¯·å…ˆè§£å†³é“¾æŽ¥ä¸­çš„警报。"
msgid "An administrator changed the password for your GitLab account on %{link_to}."
-msgstr ""
+msgstr "管ç†å‘˜ä¿®æ”¹äº†æ‚¨åœ¨%{link_to}上的GitLabå¸æˆ·å¯†ç ã€‚"
msgid "An alert has been resolved in %{project_path}."
-msgstr ""
+msgstr "警报已在%{project_path}中解决。"
msgid "An alert has been triggered in %{project_path}."
msgstr "在%{project_path}中触å‘了一个警报。"
@@ -2877,12 +2916,12 @@ msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"
msgstr "空GitLab用户字段将在所有问题和注释的æ述中添加FogBugz用户的全å(例如“By John Smithâ€ï¼‰ã€‚它还将与项目创建者关è”å’Œ/或分é…这些问题和评论。"
msgid "An empty index will be created if one does not already exist"
-msgstr ""
+msgstr "如果ä¸å­˜åœ¨ç´¢å¼•ï¼Œå°†åˆ›å»ºä¸€ä¸ªç©ºç´¢å¼•ã€‚"
msgid "An error has occurred"
msgstr "å‘生错误"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2910,12 +2949,15 @@ msgid "An error occurred previewing the blob"
msgstr "预览 blob 时出错"
msgid "An error occurred when removing the label."
-msgstr ""
+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"
@@ -2930,6 +2972,9 @@ 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 "检查群组路径时出错,请刷新页é¢å¹¶é‡è¯•ã€‚"
@@ -2973,7 +3018,7 @@ msgid "An error occurred while fetching environments."
msgstr "获å–环境时出错。"
msgid "An error occurred while fetching exposed artifacts."
-msgstr "获å–展示产物时å‘生错误。"
+msgstr "获å–已展示产物时å‘生错误。"
msgid "An error occurred while fetching folder content."
msgstr "获å–文件夹内容时å‘生错误."
@@ -3012,7 +3057,7 @@ msgid "An error occurred while fetching the job log."
msgstr "获å–作业日志时å‘生错误。"
msgid "An error occurred while fetching the job logs."
-msgstr ""
+msgstr "æå–作业日志时å‘生错误。"
msgid "An error occurred while fetching the job."
msgstr "获å–作业详情时å‘生错误"
@@ -3036,7 +3081,7 @@ 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 ""
+msgstr "获å–自动完整数æ®æ—¶å‘生错误。请刷新页é¢å¹¶é‡è¯•ã€‚"
msgid "An error occurred while getting files for - %{branchId}"
msgstr "获å–文件 - %{branchId} 时出错"
@@ -3048,7 +3093,7 @@ msgid "An error occurred while initializing path locks"
msgstr "åˆå§‹åŒ–路径é”æ—¶å‘生错误"
msgid "An error occurred while loading a section of this page."
-msgstr ""
+msgstr "加载此页é¢çš„æŸéƒ¨åˆ†æ—¶å‡ºé”™ã€‚"
msgid "An error occurred while loading all the files."
msgstr "加载所有文件时å‘生错误。"
@@ -3105,7 +3150,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 "加载æµæ°´çº¿ä½œä¸šæ—¶å‘生错误。"
@@ -3147,13 +3192,10 @@ msgid "An error occurred while retrieving diff"
msgstr "获å–差异时å‘生错误"
msgid "An error occurred while retrieving diff files"
-msgstr ""
+msgstr "获å–差异文件时å‘生错误"
msgid "An error occurred while retrieving projects."
-msgstr ""
-
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "ä¿å­˜LDAP覆盖状æ€æ—¶å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
+msgstr "获å–项目时å‘生错误。"
msgid "An error occurred while saving assignees"
msgstr "ä¿å­˜è¢«æŒ‡æ´¾äººæ—¶å‡ºçŽ°é”™è¯¯ã€‚"
@@ -3165,7 +3207,7 @@ msgid "An error occurred while triggering the job."
msgstr "触å‘作业时å‘生错误。"
msgid "An error occurred while trying to generate the report. Please try again later."
-msgstr ""
+msgstr "å°è¯•ç”ŸæˆæŠ¥å‘Šæ—¶å‡ºé”™ã€‚请ç¨åŽå†è¯•ã€‚"
msgid "An error occurred while trying to run a new pipeline for this Merge Request."
msgstr "å°è¯•ä¸ºæ­¤åˆå¹¶è¯·æ±‚è¿è¡Œæ–°æµæ°´çº¿æ—¶å‘生错误。"
@@ -3176,18 +3218,24 @@ msgstr "å–消订阅通知时å‘生错误。"
msgid "An error occurred while updating approvers"
msgstr "更新核准人时å‘生错误"
-msgid "An error occurred while updating configuration."
+msgid "An error occurred while updating assignees."
msgstr ""
+msgid "An error occurred while updating configuration."
+msgstr "æ›´æ–°é…置时出错。"
+
msgid "An error occurred while updating labels."
-msgstr ""
+msgstr "更新标签时å‘生错误。"
msgid "An error occurred while updating the comment"
msgstr "更新评论时å‘生错误"
-msgid "An error occurred while updating the milestone."
+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 "验è¯ç¾¤ç»„路径时å‘生错误"
@@ -3195,7 +3243,7 @@ msgid "An error occurred while validating username"
msgstr "验è¯ç”¨æˆ·åæ—¶å‘生错误"
msgid "An error occurred. Please sign in again."
-msgstr ""
+msgstr "出现错误。请é‡æ–°ç™»å½•ã€‚"
msgid "An error occurred. Please try again."
msgstr "å‘生了错误,请å†è¯•ä¸€æ¬¡ã€‚"
@@ -3203,8 +3251,8 @@ 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 "一个与GitLab集æˆçš„Kubernetes集群管ç†çš„示例项目。"
+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 "显示如何在GitLab动æ€å­æµæ°´çº¿ä¸­ä½¿ç”¨Jsonnet的示例"
@@ -3218,6 +3266,9 @@ 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 "未ç»è®¤è¯çš„用户"
@@ -3240,7 +3291,7 @@ msgid "An unknown error occurred while loading this graph."
msgstr "加载此图表时å‘生未知错误。"
msgid "An unknown error occurred."
-msgstr ""
+msgstr "å‘生未知错误。"
msgid "Analytics"
msgstr "分æž"
@@ -3276,7 +3327,7 @@ msgid "Any"
msgstr "任何"
msgid "Any %{header}"
-msgstr ""
+msgstr "ä»»æ„%{header}"
msgid "Any Author"
msgstr "任何作者"
@@ -3296,8 +3347,8 @@ msgstr "任何大于此é™åˆ¶çš„文件将ä¸ä¼šè¢«ç´¢å¼•ï¼Œå› æ­¤å°†æ— æ³•è¢«æœ
msgid "Any label"
msgstr "任何标记"
-msgid "Any member with Developer or higher permissions to the project."
-msgstr "任何具有开å‘者或更高æƒé™çš„项目æˆå‘˜ã€‚"
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
msgid "Any milestone"
msgstr "任何里程碑"
@@ -3333,7 +3384,7 @@ msgid "Application ID"
msgstr "应用程åºID"
msgid "Application limits saved successfully"
-msgstr ""
+msgstr "应用程åºé™åˆ¶ä¿å­˜æˆåŠŸ"
msgid "Application settings saved successfully"
msgstr "应用程åºè®¾ç½®ä¿å­˜æˆåŠŸ"
@@ -3375,10 +3426,10 @@ msgid "Apply suggestion"
msgstr "应用建议"
msgid "Apply suggestion commit message"
-msgstr ""
+msgstr "应用建议æ交消æ¯"
msgid "Apply suggestion on %{fileName}"
-msgstr ""
+msgstr "在%{fileName}上应用建议"
msgid "Apply suggestions"
msgstr "应用建议"
@@ -3439,6 +3490,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{membersCount} éœ€è¦ %{count} 个核准"
msgid "ApprovalRule|Approval rules"
+msgstr "核准规则"
+
+msgid "ApprovalRule|Approvals required"
msgstr ""
msgid "ApprovalRule|Approvers"
@@ -3447,9 +3501,6 @@ msgstr "核准人"
msgid "ApprovalRule|Name"
msgstr "å称"
-msgid "ApprovalRule|No. approvals required"
-msgstr "需è¦æ ¸å‡†çš„æ•°é‡"
-
msgid "ApprovalRule|Rule name"
msgstr "规则å称"
@@ -3468,6 +3519,9 @@ msgstr "至少有一æ¡è§„则ä¸éµå®ˆèŒè´£åˆ†ç¦»ã€‚"
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr "未éµå®ˆèŒè´£åˆ†ç¦»"
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr "分段: %section"
@@ -3505,7 +3559,7 @@ msgid "April"
msgstr "4月"
msgid "Architecture not found for OS"
-msgstr ""
+msgstr "找ä¸åˆ°é€‚用于OS的架构"
msgid "Archive"
msgstr "存档"
@@ -3517,16 +3571,16 @@ msgid "Archive project"
msgstr "归档项目"
msgid "Archive test case"
-msgstr ""
+msgstr "归档测试用例"
msgid "Archived"
msgstr "已存档"
msgid "Archived (%{movedToStart}moved%{movedToEnd})"
-msgstr ""
+msgstr "已归档(%{movedToStart}已移动%{movedToEnd})"
msgid "Archived in this version"
-msgstr ""
+msgstr "已在此版本中归档"
msgid "Archived project! Repository and other project resources are read only"
msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
@@ -3556,7 +3610,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}å—?"
@@ -3568,10 +3622,7 @@ msgid "Are you sure you want to delete this %{typeOfComment}?"
msgstr "确实è¦åˆ é™¤æ­¤%{typeOfComment}å—?"
msgid "Are you sure you want to delete this SSH key?"
-msgstr ""
-
-msgid "Are you sure you want to delete this board?"
-msgstr "确定è¦åˆ é™¤æ­¤çœ‹æ¿å—?"
+msgstr "您确定è¦åˆ é™¤æ­¤SSH密钥å—?"
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "您确定è¦åˆ é™¤æ­¤è®¾å¤‡å—?此æ“作无法撤销。"
@@ -3593,7 +3644,7 @@ 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[0] "您确定è¦å¯¼å…¥%d个仓库å—?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "确定è¦æ”¾å¼ƒæœªä¿å­˜çš„更改å—?"
@@ -3611,7 +3662,7 @@ msgid "Are you sure you want to regenerate the public key? You will have to upda
msgstr "您确定è¦é‡æ–°ç”Ÿæˆå…¬é’¥å—?在镜åƒå†æ¬¡è¿è¡Œä¹‹å‰ï¼Œæ‚¨å¿…须更新远程æœåŠ¡å™¨ä¸Šçš„公钥。"
msgid "Are you sure you want to reindex?"
-msgstr ""
+msgstr "您确定è¦é‡å»ºç´¢å¼•å—?"
msgid "Are you sure you want to remove %{group_name}?"
msgstr "确定移除群组 %{group_name} å—?"
@@ -3626,7 +3677,7 @@ msgid "Are you sure you want to remove this identity?"
msgstr "您确定è¦åˆ é™¤è¿™ä¸ªèº«ä»½æ ‡è¯†å—?"
msgid "Are you sure you want to remove this list?"
-msgstr ""
+msgstr "您确定è¦åˆ é™¤æ­¤åˆ—表å—?"
msgid "Are you sure you want to reset registration token?"
msgstr "确定è¦é‡ç½®æ³¨å†Œä»¤ç‰Œå—?"
@@ -3644,7 +3695,7 @@ msgid "Are you sure you want to revoke this nickname?"
msgstr "您确定è¦å–消此昵称?"
msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
-msgstr ""
+msgstr "您确定è¦æ’¤æ¶ˆæ­¤ä¸ªäººè®¿é—®ä»¤ç‰Œå—?此æ“作无法撤消。"
msgid "Are you sure you want to stop this environment?"
msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
@@ -3665,10 +3716,10 @@ msgid "Are you sure? Removing this GPG key does not affect already signed commit
msgstr "您确认è¦åˆ é™¤GPG密钥么?删除此GPG密钥ä¸ä¼šå½±å“å·²ç»ç­¾åçš„æ交。"
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
-msgstr ""
+msgstr "您确定å—?该设备将从GitLab中注销,所有“记ä½æˆ‘â€çš„令牌å‡è¢«æ’¤é”€ã€‚"
msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
+msgstr "你确定å—?这会使您注册的应用程åºå’ŒU2F / WebAuthn设备无效。"
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr "你确定å—?这将使您的已注册应用和U2F设备失效。"
@@ -3689,7 +3740,7 @@ msgid "Artifacts"
msgstr "产物"
msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
-msgstr ""
+msgstr "éšç€æˆ‘们继续为SAST添加更多的功能,我们éžå¸¸æ¬¢è¿Žæ‚¨é€šè¿‡%{linkStart}此议题%{linkEnd}为SASTé…置功能æä¾›å馈。"
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} 推é€åˆ° %{project_name} 的分支%{branch} ( %{commit_url} ): "
@@ -3739,6 +3790,12 @@ msgstr "指派标记"
msgid "Assign milestone"
msgstr "分é…里程碑"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "为此里程碑分é…一些议题。"
@@ -3757,12 +3814,18 @@ msgstr "将此议题分é…给自己"
msgid "Assigned %{assignee_users_sentence}."
msgstr "已指派%{assignee_users_sentence}。"
+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 "分é…ç»™%{assigneeName}"
@@ -3770,11 +3833,14 @@ msgid "Assigned to %{assignee_name}"
msgstr "分é…ç»™%{assignee_name}"
msgid "Assigned to %{name}"
-msgstr ""
+msgstr "分é…ç»™%{name}"
msgid "Assigned to me"
msgstr "已分派给我"
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "%dä½æŒ‡æ´¾äºº"
@@ -3797,6 +3863,9 @@ msgstr "指派人"
msgid "Assigns %{assignee_users_sentence}."
msgstr "指派 %{assignee_users_sentence}。"
+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 "至少需è¦ä¸€ä¸ªä»£ç æ‰€æœ‰è€…批准,以便更改符åˆç›¸åº”çš„ CODEEWNER 规则的文件。"
@@ -3840,9 +3909,6 @@ msgstr "审计事件"
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr "审计事件用æ¥è·Ÿè¸ªGitLab中å‘生的é‡è¦äº‹ä»¶ã€‚"
-msgid "Audit Log"
-msgstr "审核日志"
-
msgid "AuditLogs|(removed)"
msgstr "(已删除)"
@@ -3883,7 +3949,7 @@ msgid "AuditLogs|Target"
msgstr "目标"
msgid "AuditLogs|This month"
-msgstr ""
+msgstr "本月"
msgid "AuditLogs|User Events"
msgstr "用户事件"
@@ -3901,10 +3967,10 @@ msgid "Authenticate with GitHub"
msgstr "使用GitHub身份验è¯"
msgid "Authenticated API request rate limit"
-msgstr ""
+msgstr "ç»è¿‡èº«ä»½éªŒè¯çš„API请求速率é™åˆ¶"
msgid "Authenticated web request rate limit"
-msgstr ""
+msgstr "ç»è¿‡èº«ä»½éªŒè¯çš„web请求速率é™åˆ¶"
msgid "Authenticating"
msgstr "认è¯"
@@ -3931,7 +3997,7 @@ msgid "Authentication via U2F device failed."
msgstr "通过U2F设备进行身份验è¯å¤±è´¥ã€‚"
msgid "Authentication via WebAuthn device failed."
-msgstr ""
+msgstr "通过WebAuthn设备的身份验è¯å¤±è´¥ã€‚"
msgid "Author"
msgstr "作者"
@@ -3964,7 +4030,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "æŽˆæƒ %{link_to_client} 使用您的å¸æˆ·ï¼Ÿ"
msgid "Authorize %{user} to use your account?"
-msgstr ""
+msgstr "授æƒ%{user}使用您的å¸æˆ·å—?"
msgid "Authorize external services to send alerts to GitLab"
msgstr "授æƒå¤–部æœåŠ¡å‘GitLabå‘é€è­¦æŠ¥"
@@ -3999,12 +4065,12 @@ 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 "Auto DevOps"
-msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
-msgstr "Auto DevOpså¯åŸºäºŽé¢„定义的æŒç»­é›†æˆå’Œäº¤ä»˜é…置自动构建,测试和部署应用程åºã€‚%{auto_devops_start}了解有关Auto DevOps%{auto_devops_end}更多信æ¯ï¼Œæˆ–使用我们的%{quickstart_start}快速入门指å—%{quickstart_end}ç«‹å³å¼€å§‹ã€‚"
-
msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto DevOps文档"
@@ -4021,31 +4087,34 @@ 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 "Auto DevOpsæµæ°´çº¿å·²å¯ç”¨ã€‚如果未找到CIé…置文件,将使用该æµæ°´çº¿ã€‚"
+
+msgid "AutoRemediation| 1 Merge Request"
msgstr ""
msgid "AutoRemediation|%{mrsCount} ready for review"
-msgstr ""
+msgstr "%{mrsCount}å·²å¯å®¡æ ¸"
-msgid "AutoRemediation|Auto-fix solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
-msgstr ""
+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 ""
+msgstr "如果您使用ä¾èµ–å’Œ/或容器扫æ并å¯ç”¨è‡ªåŠ¨ä¿®å¤ï¼Œè‡ªåŠ¨ä¿®å¤å°†è‡ªåŠ¨åˆ›å»ºåˆå¹¶è¯·æ±‚,并修å¤æ¼æ´žã€‚"
msgid "AutoRemediation|Introducing GitLab auto-fix"
-msgstr ""
+msgstr "GitLab自动修å¤åŠŸèƒ½ç®€ä»‹"
msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
-msgstr ""
+msgstr "触å‘严é‡è­¦æŠ¥æ—¶å¯åŠ¨è‡ªåŠ¨å›žæ»šã€‚如果无法自动回滚到最åŽä¸€æ¬¡æˆåŠŸçš„部署,ä»ç„¶å¯ä»¥æ‰‹åŠ¨è¿›è¡Œã€‚"
msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
-msgstr ""
+msgstr "检测到严é‡é—®é¢˜æ—¶ï¼Œè‡ªåŠ¨å›žæ»šåˆ°æœ€è¿‘一次的æˆåŠŸéƒ¨ç½²ã€‚"
msgid "AutoRollback|Enable automatic rollbacks"
-msgstr ""
+msgstr "å¯ç”¨è‡ªåŠ¨å›žæ»š"
msgid "Autocomplete"
msgstr "自动补全"
@@ -4066,9 +4135,9 @@ msgid "Automatic certificate management using Let's Encrypt"
msgstr "使用Let's Encrypt自动管ç†è¯ä¹¦"
msgid "Automatic deployment rollbacks"
-msgstr ""
+msgstr "自动部署回滚"
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4087,7 +4156,7 @@ msgid "Available"
msgstr "å¯ç”¨çš„"
msgid "Available ID"
-msgstr ""
+msgstr "å¯ç”¨çš„ID"
msgid "Available Runners: %{runners}"
msgstr "å¯ç”¨çš„Runner: %{runners}"
@@ -4131,9 +4200,6 @@ msgstr "背景颜色"
msgid "Badges"
msgstr "徽章"
-msgid "Badges|A new badge was added."
-msgstr "新徽章已添加。"
-
msgid "Badges|Add badge"
msgstr "添加徽章"
@@ -4146,12 +4212,21 @@ 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 "群组徽章"
@@ -4161,15 +4236,15 @@ 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|Please fill in a valid URL"
-msgstr "请输入正确的 URL"
-
msgid "Badges|Project Badge"
msgstr "项目徽章"
@@ -4182,15 +4257,12 @@ msgstr "ä¿å­˜æ›´æ”¹"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "ä¿å­˜å¾½ç« å¤±è´¥ï¼Œè¯·æ£€æŸ¥è¾“入的网å€å¹¶é‡è¯•ã€‚"
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "GitLab支æŒçš„%{docsLinkStart}å˜é‡%{docsLinkEnd}: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "徽章已删除。"
-msgid "Badges|The badge was saved."
-msgstr "徽章已ä¿å­˜ã€‚"
-
msgid "Badges|This group has no badges"
msgstr "当å‰ç¾¤ç»„无徽章"
@@ -4198,14 +4270,11 @@ 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 ""
+msgstr "您将删除此徽章。已删除的徽章%{strongStart}将无法æ¢å¤%{strongEnd}。"
msgid "Badges|Your badges"
msgstr "您的徽章"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr "例如 %{exampleUrl}"
-
msgid "Balsamiq file could not be loaded."
msgstr "无法加载 balsamiq 文件。"
@@ -4228,10 +4297,7 @@ msgid "BambooService|You must set up automatic revision labeling and a repositor
msgstr "您必须在Bamboo中设置自动版本标签和仓库触å‘器。"
msgid "Based on"
-msgstr ""
-
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
+msgstr "基于"
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "请注æ„,更改项目的命å空间å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
@@ -4252,10 +4318,10 @@ msgid "Below you will find all the groups that are public."
msgstr "您将在下é¢æ‰¾åˆ°æ‰€æœ‰å…¬å¼€çš„群组。"
msgid "Bi-weekly code coverage"
-msgstr "åŒå‘¨ä»£ç è¦†ç›–范围"
+msgstr "åŒå‘¨ä»£ç è¦†ç›–率"
msgid "Billable Users:"
-msgstr ""
+msgstr "收费用户:"
msgid "Billing"
msgstr "计费"
@@ -4267,7 +4333,7 @@ msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan.
msgstr "@%{user_name}您正在使用%{plan_name}计划。"
msgid "BillingPlans|Congratulations, your free trial is activated."
-msgstr ""
+msgstr "æ­å–œï¼Œæ‚¨çš„试用计划已å¯ç”¨ã€‚"
msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
msgstr "如果您想è¦é™çº§æ‚¨çš„订阅计划,请è”ç³»%{support_link_start}客户支æŒ%{support_link_end}。"
@@ -4312,27 +4378,33 @@ msgid "BillingPlans|per user"
msgstr "æ¯ç”¨æˆ·"
msgid "BillingPlan|Contact sales"
-msgstr ""
+msgstr "è”系销售人员"
msgid "BillingPlan|Upgrade"
msgstr "å‡çº§"
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|No users to display."
+msgid "Billing|Group"
msgstr ""
+msgid "Billing|No users to display."
+msgstr "无用户å¯æ˜¾ç¤ºã€‚"
+
msgid "Billing|Private"
-msgstr ""
+msgstr "ç§æœ‰"
-msgid "Billing|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4348,14 +4420,14 @@ msgid "Blame"
msgstr "Blame"
msgid "Block user"
-msgstr ""
+msgstr "å±è”½ç”¨æˆ·"
msgid "Blocked"
msgstr "å·²ç¦ç”¨"
msgid "Blocked by %d issue"
msgid_plural "Blocked by %d issues"
-msgstr[0] ""
+msgstr[0] "被%d个议题阻塞"
msgid "Blocked issue"
msgstr "å—阻的议题"
@@ -4369,12 +4441,21 @@ msgstr "阻止"
msgid "Blog"
msgstr "åšå®¢"
-msgid "Board scope"
-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 "看æ¿"
@@ -4382,37 +4463,37 @@ msgid "Boards and Board Lists"
msgstr "看æ¿å’Œçœ‹æ¿åˆ—表"
msgid "Boards|An error occurred while creating the issue. Please try again."
-msgstr ""
+msgstr "创建列表时å‘生错误。请å†è¯•ä¸€é。"
msgid "Boards|An error occurred while creating the list. Please try again."
-msgstr ""
+msgstr "创建列表时å‘生错误。请å†è¯•ä¸€é。"
msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
+msgstr "读å–看æ¿è®®é¢˜æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
msgid "Boards|An error occurred while fetching labels. Please reload the page."
-msgstr ""
+msgstr "获å–标记时å‘生错误。请é‡æ–°åŠ è½½é¡µé¢ã€‚"
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
-msgstr ""
+msgstr "读å–看æ¿è®®é¢˜æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
-msgstr ""
+msgstr "获å–看æ¿åˆ—表时å‘生错误。请é‡æ–°åŠ è½½é¡µé¢ã€‚"
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
-msgstr ""
+msgstr "读å–看æ¿æ³³é“时出错。请é‡æ–°åŠ è½½é¡µé¢ã€‚"
msgid "Boards|An error occurred while generating lists. Please reload the page."
-msgstr ""
+msgstr "生æˆåˆ—表时å‘生错误。请é‡æ–°åŠ è½½é¡µé¢ã€‚"
msgid "Boards|An error occurred while moving the issue. Please try again."
-msgstr ""
+msgstr "移动议题时å‘生错误,请å†è¯•ä¸€é"
msgid "Boards|An error occurred while removing the list. Please try again."
-msgstr ""
+msgstr "移除列表时å‘生错误。请é‡è¯•ã€‚"
msgid "Boards|An error occurred while updating the list. Please try again."
-msgstr ""
+msgstr "更新列表时出错。请é‡è¯•ã€‚"
msgid "Boards|Collapse"
msgstr "收起"
@@ -4426,12 +4507,36 @@ msgstr "展开"
msgid "Boards|View scope"
msgstr "查看范围"
-msgid "Board|Load more issues"
+msgid "Board|Are you sure you want to delete this board?"
msgstr ""
-msgid "Both project and dashboard_path are required"
+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 "分支"
@@ -4439,13 +4544,13 @@ msgid "Branch %{branchName} was not found in this project's repository."
msgstr "未在此项目的仓库中找到 %{branchName} 分支。"
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr ""
+msgstr "已创建分支 %{branch_name}。如需设置自动部署,请选择åˆé€‚çš„ GitLab CI Yaml模æ¿å¹¶æ交更改。%{link_to_autodeploy_doc}"
msgid "Branch already exists"
-msgstr ""
+msgstr "分支已ç»å­˜åœ¨"
msgid "Branch changed"
-msgstr ""
+msgstr "分支已更改"
msgid "Branch is already taken"
msgstr "分支已被采用"
@@ -4456,9 +4561,6 @@ msgstr "分支å称"
msgid "Branch not loaded - %{branchId}"
msgstr "分支未载入 - %{branchId}"
-msgid "Branch prefix"
-msgstr "分支å‰ç¼€"
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -4589,7 +4691,7 @@ msgid "Branches|protected"
msgstr "å—ä¿æŠ¤"
msgid "Brief title about the change"
-msgstr ""
+msgstr "关于å˜æ›´çš„简短标题"
msgid "Broadcast Message was successfully created."
msgstr "广播消æ¯å·²æˆåŠŸåˆ›å»ºã€‚"
@@ -4627,20 +4729,38 @@ msgstr "内置"
msgid "Bulk request concurrency"
msgstr "并å‘批é‡è¯·æ±‚"
-msgid "BulkImport|expected an associated Group but has an associated Project"
+msgid "BulkImport|From source group"
msgstr ""
-msgid "BulkImport|expected an associated Project but has an associated Group"
+msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|must be a group"
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
+msgstr "燃尽图现已固定。这æ„味ç€åœ¨é‡Œç¨‹ç¢‘过期åŽåœ¨å…¶ä¸­åˆ é™¤è®®é¢˜ä¸ä¼šå½±å“图表。您å¯ä»¥ä½¿ç”¨ %{strongStart}旧版燃尽图%{strongEnd}按钮查看旧图表。"
msgid "BurndownChartLabel|Open issue weight"
msgstr "未解决议题æƒé‡"
@@ -4652,7 +4772,7 @@ msgid "Burnup chart"
msgstr "燃耗图"
msgid "Burnup chart could not be generated due to too many events"
-msgstr ""
+msgstr "事件太多,无法生æˆç‡ƒè€—图。"
msgid "Business"
msgstr "商业"
@@ -4670,7 +4790,7 @@ msgid "By %{user_name}"
msgstr "ç”± %{user_name}"
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
+msgstr "å•å‡»æ³¨å†Œå³ä»£è¡¨æˆ‘åŒæ„我已ç»é˜…读并接å—%{company_name}%{linkStart}使用æ¡æ¬¾å’Œéšç§æ”¿ç­–%{linkEnd}"
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "默认情况下,GitLab 以 HTML 和纯文本格å¼å‘é€ç”µå­é‚®ä»¶ï¼Œå› æ­¤é‚®ä»¶å®¢æˆ·ç«¯å¯ä»¥é€‰æ‹©ä½¿ç”¨å“ªç§æ ¼å¼ã€‚如果您åªæƒ³ä»¥çº¯æ–‡æœ¬æ ¼å¼å‘é€ç”µå­é‚®ä»¶ï¼Œè¯·ç¦ç”¨æ­¤é€‰é¡¹ã€‚"
@@ -4697,7 +4817,7 @@ msgid "CI Lint"
msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
-msgstr ""
+msgstr "CIé…置已验è¯ï¼ŒåŒ…括所有通过%{codeStart}include%{codeEnd}关键字引入的é…置。%{link}"
msgid "CI settings"
msgstr "CI设置"
@@ -4720,8 +4840,11 @@ msgstr "为外部仓库设置的CI/CD"
msgid "CI/CD settings"
msgstr "CI/CD 设置"
-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 "添加具有域的%{kubernetes_cluster_link_start}Kubernetes集群集æˆ%{link_end}或创建一个å˜é‡å为AUTO_DEVOPS_PLATFORM_TARGETçš„CIå˜é‡ã€‚"
+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 "Auto DevOps"
@@ -4747,12 +4870,12 @@ 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 "在未找到备用CIé…置文件时使用Auto DevOpsæµæ°´çº¿ã€‚"
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
-msgstr "您必须将 %{base_domain_link_start}基本域%{link_end} 添加到 %{kubernetes_cluster_link_start}Kubernetes群集%{link_end} ,æ‰èƒ½ä½¿æ‚¨çš„部署策略正常工作。"
-
msgid "CICD|group enabled"
msgstr "群组已å¯ç”¨"
@@ -4766,7 +4889,7 @@ msgid "CLOSED (MOVED)"
msgstr "已关闭(已移走)"
msgid "CODEOWNERS rule violation"
-msgstr ""
+msgstr "è¿åCODEOWNERS规则"
msgid "CONTRIBUTING"
msgstr "贡献信æ¯"
@@ -4780,9 +4903,6 @@ msgstr "回调 URL"
msgid "Can be manually deployed to"
msgstr "å¯ä»¥æ‰‹åŠ¨éƒ¨ç½²åˆ°"
-msgid "Can override approvers and approvals required per merge request"
-msgstr "å¯ä»¥è¦†ç›–æ¯ä¸ªåˆå¹¶è¯·æ±‚所需的核准人和核准信æ¯"
-
msgid "Can't apply as the source branch was deleted."
msgstr "由于æºåˆ†æ”¯å·²åˆ é™¤ï¼Œå› æ­¤æ— æ³•åº”用。"
@@ -4796,7 +4916,7 @@ msgid "Can't apply this suggestion."
msgstr "无法应用此建议。"
msgid "Can't be empty"
-msgstr ""
+msgstr "ä¸èƒ½ä¸ºç©º"
msgid "Can't create snippet: %{err}"
msgstr "无法创建代ç ç‰‡æ–­: %{err}"
@@ -4826,16 +4946,40 @@ msgid "Canary Deployments is a popular CI strategy, where a small portion of the
msgstr "金ä¸é›€éƒ¨ç½²æ˜¯ä¸€é¡¹æµè¡Œçš„CI策略,其中一å°éƒ¨åˆ†èŠ‚点更新到您的新版本应用。"
msgid "Canary Ingress does not exist in the environment."
-msgstr ""
+msgstr "该环境中ä¸å­˜åœ¨Canary Ingress。"
msgid "Canary weight must be specified and valid range (0..100)."
+msgstr "必须指定Canaryæƒé‡ï¼Œæœ‰æ•ˆèŒƒå›´ï¼ˆ0..100)。"
+
+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 ""
+msgstr "å–消删除索引æ“作"
msgid "Cancel running"
msgstr "å–消è¿è¡Œ"
@@ -4852,6 +4996,9 @@ msgstr "å–消部署到"
msgid "Cancelling Preview"
msgstr "å–消预览"
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr "无法自动åˆå¹¶"
@@ -4862,7 +5009,7 @@ 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 ""
+msgstr "无法å¯ç”¨å…±äº«runner,因为其父群组ä¸å…许"
msgid "Cannot have multiple Jira imports running at the same time"
msgstr "ä¸èƒ½åŒæ—¶è¿è¡Œå¤šä¸ªJira导入"
@@ -4874,10 +5021,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 "无法åˆå¹¶"
@@ -4898,7 +5045,7 @@ msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr "无法通过内部ID引用群组%{timebox_type}ï¼"
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 43åŠä»¥ä¸Šç‰ˆæœ¬çš„文件格å¼ã€‚"
@@ -4970,13 +5117,13 @@ msgid "Change your password or recover your current one"
msgstr "更改您的密ç æˆ–æ¢å¤å½“å‰å¯†ç "
msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
-msgstr ""
+msgstr "审核者已从%{old}更改为%{new}"
msgid "ChangeReviewer|Reviewer changed to %{new}"
-msgstr ""
+msgstr "审核者已更改为 %{new}"
msgid "ChangeReviewer|Unassigned"
-msgstr ""
+msgstr "未分é…"
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "选择分支"
@@ -4984,15 +5131,33 @@ 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|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 "å·²å˜æ›´çš„指派人"
@@ -5006,7 +5171,7 @@ msgid "Changes affect new repositories only. If not specified, Git's default nam
msgstr "更改仅影å“新的仓库。如果未指定,将使用Git的默认å称%{branch_name_default}。"
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 ""
+msgstr "更改仅影å“新的仓库。如果未指定,将使用已é…置的应用范围内的默认或Git的默认å称%{branch_name_default}。"
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 "差异显示方å¼ä¾%{b_open}æº%{b_close}版本åˆå¹¶åˆ°%{b_open}目标%{b_close}版本的形å¼ã€‚"
@@ -5014,13 +5179,16 @@ msgstr "差异显示方å¼ä¾%{b_open}æº%{b_close}版本åˆå¹¶åˆ°%{b_open}ç›®æ 
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 "将标题更改为“%{title_param}â€ã€‚"
-msgid "Changes were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr "更改群组URLå¯èƒ½ä¼šæœ‰æ„想ä¸åˆ°çš„副作用。"
msgid "Channel handle (e.g. town-square)"
msgstr "频é“è´¦å·(例如town-square)"
-msgid "Charts"
-msgstr "图表"
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr "无法显示图表,因为数æ®è¯·æ±‚已超时。 %{documentationLink}"
@@ -5093,7 +5258,7 @@ msgid "Check feature availability on namespace plan"
msgstr "检查命å空间方案的功能å¯ç”¨æ€§"
msgid "Check out, review, and merge locally"
-msgstr ""
+msgstr "在本地检出ã€å®¡æ ¸å’Œåˆå¹¶"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "查看%{docs_link_start}文档%{docs_link_end}。"
@@ -5279,7 +5444,7 @@ msgid "Child epic doesn't exist."
msgstr "å­å²è¯—ä¸å­˜åœ¨ã€‚"
msgid "Chinese language support using"
-msgstr ""
+msgstr "中文支æŒä½¿ç”¨"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "选择分支/标签(例如%{master})或输入æ交(例如%{sha})以查看更改内容或创建åˆå¹¶è¯·æ±‚。"
@@ -5302,9 +5467,15 @@ 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 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}以获å–最近的应用程åºä»£ç "
@@ -5315,7 +5486,7 @@ msgid "Choose labels"
msgstr "选择标记"
msgid "Choose specific groups or storage shards"
-msgstr ""
+msgstr "选择指定群组或存储片"
msgid "Choose the top-level group for your repository imports."
msgstr "选择仓库导入的顶级群组。"
@@ -5324,7 +5495,7 @@ msgid "Choose visibility level, enable/disable project features (issues, reposit
msgstr "选择å¯è§æ€§çº§åˆ«ï¼Œå¯ç”¨/ç¦ç”¨é¡¹ç›®åŠŸèƒ½ï¼ˆè®®é¢˜ï¼Œä»“库,wiki,代ç ç‰‡æ®µï¼‰å¹¶è®¾ç½®æƒé™ã€‚"
msgid "Choose what content you want to see on a group’s overview page."
-msgstr ""
+msgstr "选择您想è¦åœ¨ç¾¤ç»„概览页é¢æŸ¥çœ‹çš„内容。"
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "请选择è¦è¿žæŽ¥å¹¶è¿è¡Œ CI/CD æµæ°´çº¿çš„代ç ä»“库。"
@@ -5429,7 +5600,7 @@ msgid "CiVariables|Protected"
msgstr "å—ä¿æŠ¤"
msgid "CiVariables|Remove variable"
-msgstr ""
+msgstr "删除å˜é‡"
msgid "CiVariables|Remove variable row"
msgstr "删除å˜é‡è¡Œ"
@@ -5486,16 +5657,16 @@ msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ä¸å¯ç”¨: %{reason}"
msgid "Clean up image tags"
-msgstr ""
+msgstr "清ç†é•œåƒæ ‡ç­¾"
msgid "Cleanup policy maximum processing time (seconds)"
-msgstr ""
+msgstr "清ç†ç­–略最大处ç†æ—¶é—´(秒)"
msgid "Clear"
msgstr "清除"
msgid "Clear all repository checks"
-msgstr ""
+msgstr "清除所有仓库检查"
msgid "Clear chart filters"
msgstr "清除图表筛选器"
@@ -5528,10 +5699,10 @@ msgid "Clears weight."
msgstr "清除æƒé‡"
msgid "Click %{link_start}here%{link_end} to view the request."
-msgstr ""
+msgstr "点击%{link_start}此处%{link_end}查看请求。"
msgid "Click %{link_to} to view the request."
-msgstr ""
+msgstr "点击%{link_to}查看请求。"
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
msgstr "点击下é¢çš„按钮转到Kubernetes页é¢å¼€å§‹å®‰è£…过程"
@@ -5552,7 +5723,7 @@ msgid "Client authentication key password"
msgstr "客户端认è¯å¯†é’¥å¯†ç "
msgid "Client request timeout"
-msgstr ""
+msgstr "客户端请求超时"
msgid "Clients"
msgstr "客户端"
@@ -5563,6 +5734,9 @@ msgstr "克隆"
msgid "Clone repository"
msgstr "克隆仓库"
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr "使用 %{http_label} 克隆"
@@ -5575,11 +5749,23 @@ msgstr "通过KRB5克隆"
msgid "Clone with SSH"
msgstr "使用 SSH 克隆"
+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 ""
+msgstr "关闭%{issueType}"
msgid "Close %{tabname}"
msgstr "关闭%{tabname}"
@@ -5603,7 +5789,7 @@ msgid "Closed %{epicTimeagoDate}"
msgstr "关闭于%{epicTimeagoDate}"
msgid "Closed epics"
-msgstr ""
+msgstr "已关闭å²è¯—"
msgid "Closed issues"
msgstr "已关闭议题"
@@ -5612,7 +5798,7 @@ msgid "Closed this %{quick_action_target}."
msgstr "已关闭此%{quick_action_target}."
msgid "Closed: %{closed}"
-msgstr ""
+msgstr "关闭: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "关闭此%{quick_action_target}."
@@ -5639,52 +5825,52 @@ msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr "Stages::ClusterEndpointInserter需è¦é›†ç¾¤ç±»åž‹"
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr ""
+msgstr "加载您的GitLab Agentæ—¶å‘生错误"
msgid "ClusterAgents|Configuration"
-msgstr ""
+msgstr "é…ç½®"
msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
+msgstr "将您的集群连接到GitLab Agent"
msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
-msgstr ""
+msgstr "å°†Kubernetes与GitLab Agent集æˆ"
msgid "ClusterAgents|Integrate with the GitLab Agent"
-msgstr ""
+msgstr "与GitLab Agent集æˆ"
msgid "ClusterAgents|Name"
-msgstr ""
+msgstr "å称"
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
-msgstr ""
+msgstr "GitLab Agent也需è¦%{linkStart}å¯ç”¨ä»£ç†æœåŠ¡å™¨%{linkEnd}"
msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "GitLab Kubernetes Agent通过基础设施å³ä»£ç ï¼ŒGitOps方法æ¥å®žçŽ°Kubernetes集群与GitLab的集æˆã€‚ %{linkStart}了解更多信æ¯ã€‚%{linkEnd}"
msgid "ClusterAgent|This feature is only available for premium plans"
-msgstr ""
+msgstr "此功能仅适用于高级计划"
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
-msgstr ""
+msgstr "用户æƒé™ä¸è¶³ï¼Œæ— æ³•ä¸ºæ­¤é¡¹ç›®åˆ›å»ºä»¤ç‰Œ"
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
-msgstr ""
+msgstr "您的æƒé™ä¸è¶³ï¼Œæ— æ³•ä¸ºæ­¤é¡¹ç›®åˆ›å»ºé›†ç¾¤ä»£ç†"
msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
-msgstr ""
+msgstr "您的æƒé™ä¸è¶³ï¼Œæ— æ³•ä¸ºæ­¤é¡¹ç›®åˆ é™¤é›†ç¾¤ä»£ç†"
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} å·²æˆåŠŸå®‰è£…到Kubernetes集群上"
msgid "ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed."
-msgstr ""
+msgstr "%{boldStart}注æ„:%{boldEnd}需è¦å®‰è£…Ingress。"
msgid "ClusterIntegration|%{externalIp}.nip.io"
-msgstr ""
+msgstr "%{externalIp}.nip.io"
msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}更多信æ¯%{linkEnd}"
msgid "ClusterIntegration|%{title} uninstalled successfully."
msgstr "%{title} å·²æˆåŠŸå¸è½½ã€‚"
@@ -5732,16 +5918,16 @@ msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "所有数æ®å°†è¢«åˆ é™¤ï¼Œæ— æ³•æ¢å¤ã€‚"
msgid "ClusterIntegration|All installed applications and related resources"
-msgstr ""
+msgstr "所有已安装的应用程åºå’Œç›¸å…³èµ„æº"
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "å…许GitLab管ç†æ­¤ç¾¤é›†çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚%{linkStart}更多信æ¯%{linkEnd}"
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
-msgstr ""
+msgstr "å…许GitLab管ç†æ­¤é›†ç¾¤çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚"
msgid "ClusterIntegration|Alternatively, "
-msgstr ""
+msgstr "此外,"
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5759,10 +5945,10 @@ msgid "ClusterIntegration|An error occurred while trying to fetch zone machine t
msgstr "å°è¯•èŽ·å–设备类型时å‘生错误:%{error}"
msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
-msgstr ""
+msgstr "å°è¯•è¿žæŽ¥åˆ° Kubernetes æ—¶å‘生未知错误。"
msgid "ClusterIntegration|Any project namespaces"
-msgstr ""
+msgstr "任何项目命å空间"
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "任何正在è¿è¡Œçš„æµæ°´çº¿å°†è¢«å–消。"
@@ -5777,7 +5963,7 @@ msgid "ClusterIntegration|Authenticate with Amazon Web Services"
msgstr "通过Amazon网络æœåŠ¡éªŒè¯"
msgid "ClusterIntegration|Authentication Error"
-msgstr ""
+msgstr "身份验è¯é”™è¯¯"
msgid "ClusterIntegration|Base domain"
msgstr "基础域"
@@ -5789,7 +5975,7 @@ msgid "ClusterIntegration|CA Certificate"
msgstr "CAè¯ä¹¦"
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 ""
+msgstr "å¯ä»¥å®‰å…¨ç§»é™¤ã€‚在 GitLab 13.2之å‰ï¼ŒGitLab 使用远程TilleræœåŠ¡å™¨æ¥ç®¡ç†åº”用程åºã€‚ç›®å‰GitLabä¸å†ä½¿ç”¨æ­¤æœåŠ¡å™¨ã€‚å¸è½½æ­¤æœåŠ¡å™¨å°†ä¸ä¼šå½±å“您的其他应用程åºã€‚æ­¤åŽè¯¥è¡Œå°†ä¸å†æ˜¾ç¤ºã€‚"
msgid "ClusterIntegration|Cert-Manager"
msgstr "Cert-Manager"
@@ -5801,25 +5987,25 @@ msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "è¯ä¹¦æŽˆæƒåŒ…(PEMæ ¼å¼)"
msgid "ClusterIntegration|Check your CA certificate"
-msgstr ""
+msgstr "检查您的CAè¯ä¹¦"
msgid "ClusterIntegration|Check your cluster status"
-msgstr ""
+msgstr "检查您的群集状æ€"
msgid "ClusterIntegration|Check your token"
-msgstr ""
+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 ""
+msgstr "选择应用于在工作节点å­ç½‘中创建并由EKS管ç†çš„弹性网络接å£çš„%{linkStart}安全组%{linkEnd}。"
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
-msgstr ""
+msgstr "在VPC中选择è¿è¡Œå·¥ä½œèŠ‚点的%{linkStart}å­ç½‘%{linkEnd}。"
msgid "ClusterIntegration|Choose the worker node %{linkStart}instance type%{linkEnd}."
-msgstr ""
+msgstr "选择工作节点的%{linkStart}实例类型%{linkEnd}。"
msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
-msgstr ""
+msgstr "选择è¦åœ¨æ‚¨çš„Kubernetes集群上安装应用程åºã€‚"
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "请选择使用此Kubernetes群集的环境。"
@@ -5828,10 +6014,10 @@ msgid "ClusterIntegration|Clear cluster cache"
msgstr "清除集群缓存"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
-msgstr ""
+msgstr "清除命å空间和æœåŠ¡è´¦æˆ·çš„本地缓存。"
msgid "ClusterIntegration|Cluster Region"
-msgstr ""
+msgstr "集群区域"
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr "集群管ç†é¡¹ç›®(alpha)"
@@ -5846,16 +6032,16 @@ msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancesto
msgstr "层级中最低且匹é…环境范围的集群将会被使用。例如,项目群集将优先于群组群集。%{linkStart}更多信æ¯%{linkEnd}"
msgid "ClusterIntegration|Clusters connected with a certificate"
-msgstr ""
+msgstr "使用è¯ä¹¦è¿žæŽ¥çš„集群"
msgid "ClusterIntegration|Connect cluster with certificate"
-msgstr ""
+msgstr "使用è¯ä¹¦è¿žæŽ¥æ•°æ®ç»„"
msgid "ClusterIntegration|Connect existing cluster"
-msgstr ""
+msgstr "连接现有集群"
msgid "ClusterIntegration|Connection Error"
-msgstr ""
+msgstr "连接错误"
msgid "ClusterIntegration|Copy API URL"
msgstr "å¤åˆ¶API地å€"
@@ -5930,10 +6116,10 @@ msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster
msgstr "移除过程中删除此集群中的所有GitLab资æº"
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 ""
+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 ""
+msgstr "å°†æ¯ä¸ªçŽ¯å¢ƒéƒ¨ç½²åˆ°è‡ªå·±çš„命å空间。å¦åˆ™ï¼Œä¸€ä¸ªé¡¹ç›®ä¸­çš„环境共享项目范围的命å空间。 请注æ„,任何能够触å‘部署命å空间的人都å¯ä»¥é˜…读命å空间的秘密。 如果被修改,现有环境将使用当å‰çš„命å空间,直到群集缓存被清除。 %{linkStart}更多信æ¯%{linkEnd}"
msgid "ClusterIntegration|Did you know?"
msgstr "你是å¦äº†è§£ï¼Ÿ"
@@ -6005,7 +6191,7 @@ msgid "ClusterIntegration|Fluentd is an open source data collector, which lets y
msgstr "Fluentd是一个开æºæ•°æ®æ”¶é›†å™¨ï¼Œå¯ä»¥ç»Ÿä¸€æ•°æ®æ”¶é›†å’Œåˆ©ç”¨ï¼Œä»¥ä¾¿æ›´å¥½åœ°ä½¿ç”¨å’Œäº†è§£æ•°æ®ã€‚它è¦æ±‚至少安装一个以下日志。"
msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
+msgstr "GitLab Agent管ç†çš„集群"
msgid "ClusterIntegration|GitLab Container Network Policies"
msgstr "GitLab容器网络策略"
@@ -6020,10 +6206,10 @@ msgid "ClusterIntegration|GitLab Runner connects to the repository and executes
msgstr "GitLab Runner连接到仓库并执行CI/CD作业,返回结果并将应用程åºéƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒã€‚"
msgid "ClusterIntegration|GitLab failed to authenticate."
-msgstr ""
+msgstr "GitLab认è¯å¤±è´¥ã€‚"
msgid "ClusterIntegration|GitLab failed to connect to the cluster."
-msgstr ""
+msgstr "GitLab无法连接到集群。"
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "GitLab管ç†çš„集群"
@@ -6047,7 +6233,7 @@ msgid "ClusterIntegration|Group cluster"
msgstr "群组级集群"
msgid "ClusterIntegration|HTTP Error"
-msgstr ""
+msgstr "HTTP错误"
msgid "ClusterIntegration|Helm release failed to install"
msgstr "Helm版本安装失败"
@@ -6080,10 +6266,10 @@ msgid "ClusterIntegration|Instance type"
msgstr "实例类型"
msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
+msgstr "å°†Kubernetes与集群è¯ä¹¦é›†æˆ"
msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
+msgstr "与集群è¯ä¹¦é›†æˆ"
msgid "ClusterIntegration|Issuer Email"
msgstr "ç­¾å‘人电å­é‚®ä»¶"
@@ -6152,7 +6338,7 @@ msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr "了解有关实例级Kubernetes集群更多信æ¯"
msgid "ClusterIntegration|Legacy Helm Tiller server"
-msgstr ""
+msgstr "传统Helm TilleræœåŠ¡å™¨"
msgid "ClusterIntegration|Loading IAM Roles"
msgstr "加载IAM角色"
@@ -6185,7 +6371,7 @@ msgid "ClusterIntegration|Machine type"
msgstr "机器类型"
msgid "ClusterIntegration|Make sure your API endpoint is correct"
-msgstr ""
+msgstr "请确ä¿æ‚¨çš„API端点正确"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "请确ä¿æ‚¨çš„å¸æˆ·%{link_to_requirements}å¯ä»¥åˆ›å»º Kubernetes 集群"
@@ -6194,7 +6380,7 @@ msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_
msgstr "通过访问%{provider_link}管ç†Kubernetes群集"
msgid "ClusterIntegration|Namespace per environment"
-msgstr ""
+msgstr "按环境分é…命å空间"
msgid "ClusterIntegration|No IAM Roles found"
msgstr "未找到IAM角色"
@@ -6239,7 +6425,7 @@ 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 ""
+msgstr "节点计算使用Kubernetes Metrics API。请确ä¿æ‚¨çš„集群已安装指标。"
msgid "ClusterIntegration|Number of nodes"
msgstr "节点数é‡"
@@ -6248,7 +6434,7 @@ 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 ""
+msgstr "请输入Kubernetes集群的访问信æ¯ã€‚如需帮助,å¯å‚阅Kubernetes集群的%{linkStart}文档%{linkEnd}"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "请确ä¿æ‚¨çš„ Google å¸æˆ·ç¬¦åˆä»¥ä¸‹è¦æ±‚:"
@@ -6284,7 +6470,7 @@ msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr "å¯ç”¨RBAC的群集"
msgid "ClusterIntegration|Read our %{linkStart}help page%{linkEnd} on Kubernetes cluster integration."
-msgstr ""
+msgstr "请查阅关于Kubernetes集群集æˆçš„%{linkStart}帮助页é¢%{linkEnd}。"
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "请查阅关于Kubernetes集群集æˆçš„%{link_start}帮助页é¢%{link_end}。"
@@ -6383,7 +6569,7 @@ 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 ""
+msgstr "请选择EKS集群的VPC。如需使用新的VPC, 请先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个。"
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "选择一个网络以选择å­ç½‘"
@@ -6416,10 +6602,10 @@ 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 ""
+msgstr "选择将用于创建EC2节点的密钥对å称。如需è¦ä½¿ç”¨æ–°çš„密钥对å称,请先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个。"
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 ""
+msgstr "选择您想è¦åˆ›å»ºæ–°é›†ç¾¤çš„区域。 请确ä¿æ‚¨å¯ä»¥è®¿é—®æ­¤åŒºåŸŸï¼Œä»¥ä¾¿æ‚¨çš„角色能够进行身份验è¯ã€‚ 如果没有选定区域,我们将使用%{codeStart}DEFAULT_REGION%{codeEnd}。了解更多关于%{linkStart}区域%{linkEnd}。"
msgid "ClusterIntegration|Select zone"
msgstr "选择地域"
@@ -6467,13 +6653,13 @@ msgid "ClusterIntegration|Something went wrong while updating Knative domain nam
msgstr "æ›´æ–°Knative域å时出错。"
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 ""
+msgstr "指定域将å…许您使用%{linkStart}Auto DevOps%{linkEnd}中的自动评审应用和自动部署阶段。域å应包å«ä¸ŽåŸŸåŒ¹é…的通é…符DNS。"
msgid "ClusterIntegration|Subnets"
msgstr "å­ç½‘"
msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
-msgstr ""
+msgstr "%{gitlabNamespace}å称空间"
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 "与您的角色关è”çš„Amazon资æºå称(ARN)。如果您没有é…置角色,请首先使用上述å¸æˆ·å’Œå¤–部ID在 %{startAwsLink}Amazon Web Services%{externalLinkIcon}%{endLink} 上创建一个。了解%{startMoreInfoLink}更多信æ¯%{endLink}"
@@ -6488,7 +6674,7 @@ msgid "ClusterIntegration|The associated IP and all deployed services will be de
msgstr "å…³è”çš„IPåŠæ‰€æœ‰å·²éƒ¨ç½²çš„æœåŠ¡å°†è¢«åˆ é™¤ï¼Œæ— æ³•æ¢å¤ã€‚å¸è½½Knative会åŒæ—¶ä»Žé›†ç¾¤ä¸­åˆ é™¤ Istio。此æ“作将ä¸ä¼šå½±å“任何其他应用。"
msgid "ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored. Your other applications will remain unaffected."
-msgstr ""
+msgstr "相关的Tiller pod将被删除且无法还原。您的其他应用程åºå°†ä¸å—å½±å“。"
msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr "å…³è”çš„è´Ÿè½½å‡è¡¡å™¨å’ŒIP将被删除,无法还原。"
@@ -6506,37 +6692,37 @@ msgid "ClusterIntegration|The namespace associated with your project. This will
msgstr "与当å‰é¡¹ç›®ç›¸å…³è”的命å空间。用于部署看æ¿ã€pod日志和Web terminal。"
msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
-msgstr ""
+msgstr "新集群将被创建到的区域。您必须é‡æ–°è®¤è¯ä»¥æ›´æ”¹åŒºåŸŸã€‚"
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "群集身份验è¯æ—¶å‡ºçŽ°é—®é¢˜ã€‚请确ä¿æ‚¨çš„CAè¯ä¹¦å’Œä»¤ç‰Œæœ‰æ•ˆã€‚"
msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
-msgstr ""
+msgstr "连接到您的集群时å‘生HTTP错误。"
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "该å¸æˆ·éœ€å…·å¤‡åœ¨å¦‚下指定的%{link_to_container_project}中创建 Kubernetes集群的æƒé™"
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 ""
+msgstr "如集æˆå·²å¤±åŽ»åŒæ­¥ï¼Œåˆ™æ­¤æ“作为必须。缓存将在所需å称空间和æœåŠ¡å¸æˆ·çš„下一个CI作业期间é‡æ–°ç”Ÿæˆã€‚"
msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
-msgstr ""
+msgstr "这是清除之å‰ç”±GitLab管ç†çš„集群中环境与命å空间的关è”所必需的。"
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "此选项å…许您在å¯ç”¨RBAC的群集上安装应用程åºã€‚"
msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
-msgstr ""
+msgstr "此项目未å¯ç”¨è®¡è´¹ã€‚如需创建群集,请%{linkToBillingStart}å¯ç”¨è®¡è´¹%{linkToBillingEnd}åŽé‡è¯•ã€‚"
msgid "ClusterIntegration|This will permanently delete the following resources:"
-msgstr ""
+msgstr "æ­¤æ“作将永久删除以下资æºï¼š"
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "è¦åœ¨éƒ¨ç½²åŽè®¿é—®æ‚¨çš„应用程åºï¼Œè¯·å°†é€šé…符 DNS æŒ‡å‘ Knative 节点。"
msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
-msgstr ""
+msgstr "è¦åˆ›å»ºä¸€ä¸ªé›†ç¾¤ï¼Œé¦–先在 %{docsLinkStart}Google 云平å°%{docsLinkEnd}创建一个项目。"
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr "è¦åˆ é™¤é›†æˆå’Œèµ„æºï¼Œè¯·è¾“å…¥%{clusterName}以确认:"
@@ -6545,22 +6731,22 @@ msgid "ClusterIntegration|To remove your integration, type %{clusterName} to con
msgstr "è¦åˆ é™¤é›†æˆï¼Œè¯·è¾“å…¥%{clusterName}以确认:"
msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
-msgstr ""
+msgstr "è¦ä½¿ç”¨ä¸€ä¸ªæ–°é¡¹ç›®ï¼Œè¯·å…ˆåœ¨%{docsLinkStart}Google 云平å°%{docsLinkEnd}创建一个。"
msgid "ClusterIntegration|Troubleshooting tips:"
-msgstr ""
+msgstr "故障排除æ示:"
msgid "ClusterIntegration|Unable to Authenticate"
-msgstr ""
+msgstr "无法验è¯"
msgid "ClusterIntegration|Unable to Connect"
-msgstr ""
+msgstr "无法连接"
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "å¸è½½ %{appTitle}"
msgid "ClusterIntegration|Unknown Error"
-msgstr ""
+msgstr "未知错误"
msgid "ClusterIntegration|Update %{appTitle}"
msgstr "æ›´æ–°%{appTitle}"
@@ -6584,7 +6770,7 @@ msgid "ClusterIntegration|We could not verify that one of your projects on GCP h
msgstr "无法验è¯æ‚¨åœ¨ GCP 上的æŸä¸ªé¡¹ç›®æ˜¯å¦å¯ç”¨äº†è®¡è´¹ã€‚请é‡è¯•ã€‚"
msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
-msgstr ""
+msgstr "我们无法获å–任何项目。请确ä¿æ‚¨åœ¨%{docsLinkStart}Google 云平å°%{docsLinkEnd}上拥有项目。"
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 "使用与此项目关è”çš„Kubernetes集群,å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨è¯„审应用,部署应用程åºï¼Œè¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
@@ -6623,7 +6809,7 @@ msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your AP
msgstr "您的 API 无法访问。请确ä¿æ‚¨çš„ API URL 正确。"
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 ""
+msgstr "您的æœåŠ¡è§’色ä¸åŒäºŽè®¤è¯æ—¶ä½¿ç”¨çš„æ供角色。它将å…许Amazon EKSå’ŒKubernetes控制层é¢ä»¥æ‚¨çš„身份管ç†AWS资æºã€‚ è‹¥è¦ä½¿ç”¨æ–°è§’色,首先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个角色。"
msgid "ClusterIntegration|Zone"
msgstr "地域"
@@ -6632,7 +6818,7 @@ msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "访问 Google Kubernetes Engine"
msgid "ClusterIntegration|can be used instead of a custom domain. "
-msgstr ""
+msgstr "å¯ä»¥ç”¨æ¥ä»£æ›¿è‡ªå®šä¹‰åŸŸã€‚"
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr "通过%{linkStart}Cloud Run%{linkEnd}安装"
@@ -6682,12 +6868,12 @@ msgstr "代ç è¦†ç›–率数æ®ä¸ºç©º"
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr "无法获å–代ç è¦†ç›–率数æ®"
+msgid "Code Owner"
+msgstr ""
+
msgid "Code Owners"
msgstr "代ç æ‰€æœ‰è€…"
-msgid "Code Owners to the merge request changes."
-msgstr "åˆå¹¶è¯·æ±‚更改的代ç æ‰€æœ‰è€…。"
-
msgid "Code Quality"
msgstr "代ç è´¨é‡"
@@ -6740,7 +6926,7 @@ msgid "Collapse"
msgstr "收起"
msgid "Collapse all threads"
-msgstr ""
+msgstr "折å æ‰€æœ‰ä¸»é¢˜"
msgid "Collapse approvers"
msgstr "折å æ ¸å‡†äºº"
@@ -6806,10 +6992,10 @@ msgid "Comment/Reply (quoting selected text)"
msgstr "评论/å›žå¤ (引用选定的文本)"
msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
-msgstr ""
+msgstr "ç›®å‰ä¸æ”¯æŒè¯„论替æ¢ç¬¦å·é“¾æŽ¥çš„文件或被符å·é“¾æŽ¥çš„文件替æ¢çš„文件。"
msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
-msgstr ""
+msgstr "ç›®å‰ä¸æ”¯æŒè¯„论符å·é“¾æŽ¥ï¼Œè¿™äº›é“¾æŽ¥æ›¿æ¢æ–‡ä»¶æˆ–被文件替æ¢ã€‚"
msgid "Comments"
msgstr "评论"
@@ -6828,7 +7014,7 @@ msgid "Commit Message"
msgstr "æ交消æ¯"
msgid "Commit changes"
-msgstr ""
+msgstr "æ交更改"
msgid "Commit deleted"
msgstr "æ交已删除"
@@ -6891,7 +7077,7 @@ msgid "Commit…"
msgstr "æ交..."
msgid "Community forum"
-msgstr ""
+msgstr "社区论å›"
msgid "Company name"
msgstr "å…¬å¸å称"
@@ -6900,7 +7086,7 @@ msgid "Compare"
msgstr "比较"
msgid "Compare %{oldCommitId}...%{newCommitId}"
-msgstr ""
+msgstr "比较%{oldCommitId}...%{newCommitId}"
msgid "Compare Git revisions"
msgstr "比较Gitæ交版本"
@@ -6918,7 +7104,7 @@ msgid "Compare changes with the merge request target branch"
msgstr "与åˆå¹¶è¯·æ±‚的目标分支比较å˜æ›´å†…容"
msgid "Compare submodule commit revisions"
-msgstr ""
+msgstr "比较å­æ¨¡å—æ交的版本"
msgid "Compare with previous version"
msgstr "与以å‰çš„版本比较"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7017,7 +7221,7 @@ 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 ""
+msgstr "在%{codeStart}.gitlab%{codeEnd}目录中é…ç½®%{codeStart}gitlab-webide.yml%{codeEnd}文件以开始使用Web终端。 %{helpStart}了解更多。%{helpEnd}"
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "在仓库上é…置自动git检查和仓库整ç†ã€‚"
@@ -7053,7 +7257,7 @@ msgid "Configure the way a user creates a new account."
msgstr "é…置用户创建新å¸æˆ·çš„æ–¹å¼ã€‚"
msgid "Configure which lists are shown for anyone who visits this board"
-msgstr ""
+msgstr "é…置显示给任何访问此看æ¿çš„人的列表"
msgid "Confirm"
msgstr "确认"
@@ -7071,7 +7275,7 @@ msgid "ConfluenceService|Confluence Workspace"
msgstr "Confluence工作区"
msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
-msgstr ""
+msgstr "将Confluence Cloud Workspace连接到GitLab"
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 "å¯ç”¨Confluence工作区将ç¦ç”¨é»˜è®¤çš„GitLab Wiki。您的GitLab Wikiæ•°æ®å°†è¢«ä¿å­˜ï¼Œæ‚¨ä»¥åŽéšæ—¶å¯ä»¥é€šè¿‡å…³é—­æ­¤é›†æˆæ¥é‡æ–°å¯ç”¨å®ƒ"
@@ -7085,6 +7289,9 @@ msgstr "您的GitLab Wikiå¯ä»¥åœ¨æ­¤è®¿é—®ï¼š %{wiki_link}。è¦é‡æ–°å¯ç”¨æ‚¨
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "æ­å–œï¼æ‚¨å·²å¯ç”¨äº†åŒé‡è®¤è¯ï¼"
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr "连接"
@@ -7122,10 +7329,10 @@ msgid "Connection timeout"
msgstr "连接超时"
msgid "Consistency guarantee method"
-msgstr ""
+msgstr "一致性ä¿éšœæ–¹æ³•"
msgid "Contact Sales to upgrade"
-msgstr ""
+msgstr "è”系销售人员进行å‡çº§"
msgid "Contact sales to upgrade"
msgstr "è”系销售人员进行å‡çº§"
@@ -7152,7 +7359,7 @@ msgid "Container repositories"
msgstr "容器仓库"
msgid "Container repositories synchronization concurrency limit"
-msgstr ""
+msgstr "容器镜åƒåº“åŒæ­¥å¹¶å‘é™åˆ¶"
msgid "Container repository"
msgstr "容器仓库"
@@ -7171,31 +7378,55 @@ msgstr[0] "%{count}个标签"
msgid "ContainerRegistry|%{imageName} tags"
msgstr "%{imageName}标签"
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
-msgstr "%{title}å·²æˆåŠŸå®‰æŽ’删除"
-
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
-msgstr "%{toggleStatus} - 匹é…以下模å¼çš„标签将被安排删除"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
+msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+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 "%{title}å·²æˆåŠŸå®‰æŽ’删除"
+
msgid "ContainerRegistry|Build an image"
msgstr "构建镜åƒ"
msgid "ContainerRegistry|CLI Commands"
msgstr "CLI命令"
+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 policy:"
-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}"
@@ -7225,9 +7456,6 @@ msgstr "摘è¦: %{imageId}"
msgid "ContainerRegistry|Docker connection error"
msgstr "Docker连接错误"
-msgid "ContainerRegistry|Expiration interval:"
-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 "过期政策有助于优化容器镜åƒåº“使用的存储空间的管ç†ï¼Œä½†è¯¥é•œåƒåº“的过期政策已被ç¦ç”¨ã€‚ 请è”系您的管ç†å‘˜ä»¥å¯ç”¨ã€‚ %{docLinkStart}更多信æ¯%{docLinkEnd}"
@@ -7237,9 +7465,6 @@ msgstr "过期策略已ç¦ç”¨"
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr "到期策略将在%{time}åŽè¿è¡Œ"
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr "过期计划:"
-
msgid "ContainerRegistry|Filter by name"
msgstr "按å称筛选"
@@ -7256,12 +7481,15 @@ msgid "ContainerRegistry|Invalid tag: missing manifest digest"
msgstr "无效标签:缺少æ述摘è¦"
msgid "ContainerRegistry|Keep tags matching:"
-msgstr ""
+msgstr "ä¿ç•™åŒ¹é…标签:"
msgid "ContainerRegistry|Keep the most recent:"
-msgstr ""
+msgstr "ä¿ç•™æœ€è¿‘的:"
msgid "ContainerRegistry|Keep these tags"
+msgstr "ä¿ç•™è¿™äº›æ ‡ç­¾"
+
+msgid "ContainerRegistry|Last updated %{time}"
msgstr ""
msgid "ContainerRegistry|Login"
@@ -7274,16 +7502,13 @@ msgid "ContainerRegistry|Missing or insufficient permission, delete button disab
msgstr "æ— æƒé™æˆ–æƒé™ä¸è¶³ï¼Œåˆ é™¤æŒ‰é’®å·²ç¦ç”¨"
msgid "ContainerRegistry|Next cleanup scheduled to run on:"
-msgstr ""
+msgstr "下次清ç†è®¡åˆ’è¿è¡ŒäºŽ:"
msgid "ContainerRegistry|Not yet scheduled"
-msgstr ""
+msgstr "尚未安排"
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
-msgstr ""
-
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr "è¦ä¿ç•™çš„标签数é‡ï¼š"
+msgstr "注æ„:任何策略更新都会导致对预定è¿è¡Œæ—¥æœŸå’Œæ—¶é—´çš„更改"
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "å‘布于%{timeInfo}"
@@ -7305,25 +7530,25 @@ msgid_plural "ContainerRegistry|Remove tags"
msgstr[0] "删除标签"
msgid "ContainerRegistry|Remove tags matching:"
-msgstr ""
+msgstr "删除匹é…的标签:"
msgid "ContainerRegistry|Remove tags older than:"
-msgstr ""
+msgstr "删除早于以下时间的标签:"
msgid "ContainerRegistry|Remove these tags"
-msgstr ""
+msgstr "删除这些标签"
msgid "ContainerRegistry|Run cleanup:"
-msgstr ""
+msgstr "è¿è¡Œæ¸…ç†ï¼š"
msgid "ContainerRegistry|Some tags were not deleted"
-msgstr ""
+msgstr "部分标签未被删除"
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
msgstr "获å–清ç†æ”¿ç­–时出了错。"
msgid "ContainerRegistry|Something went wrong while fetching the image details."
-msgstr ""
+msgstr "获å–é•œåƒè¯¦ç»†ä¿¡æ¯æ—¶å‡ºäº†é”™ã€‚"
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
msgstr "获å–仓库列表时出错。"
@@ -7353,25 +7578,19 @@ 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 ""
+msgstr "匹é…这些规则的标签会被%{strongStart}ä¿ç•™%{strongEnd},å³ä½¿å®ƒä»¬ä¸Žä¸‹é¢çš„删除规则相匹é…。 %{secondStrongStart}最新的%{secondStrongEnd}标签总是会被ä¿ç•™ã€‚"
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr "å称匹é…此正则表达å¼çš„标签将%{italicStart}被ä¿ç•™:%{italicEnd}"
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr "å称匹é…此正则表达å¼çš„标签将%{italicStart}过期:%{italicEnd}"
+msgstr "匹é…这些规则的标签将被%{strongStart}移除%{strongEnd},除éžä»¥ä¸Šä»»ä¸€è§„则è¦æ±‚ä¿ç•™å®ƒä»¬ã€‚"
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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 ""
+msgstr "清ç†ç­–略在删除所有标签之å‰è¶…时。 管ç†å‘˜å¯ä»¥%{adminLinkStart}ç«‹å³æ‰§è¡Œæ‰‹åŠ¨æ¸…ç†%{adminLinkEnd}或者等待清ç†ç­–略下次自动è¿è¡Œã€‚%{docLinkStart}更多信æ¯%{docLinkEnd}"
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 "与此镜åƒç›¸å…³çš„最åŽä¸€ä¸ªæ ‡ç­¾æœ€è¿‘已被删除。空镜åƒå’Œæ‰€æœ‰ç›¸å…³æ•°æ®å°†ä½œä¸ºå¸¸è§„垃圾收集过程的一部分自动清除。如有任何疑问,请与管ç†å‘˜è”系。"
@@ -7403,12 +7622,6 @@ 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 "当å‰æ— æ³•è¿žæŽ¥åˆ°é•œåƒåº“,原因å¯èƒ½æ˜¯é¡¹ç›®å称或路径的问题。%{docLinkStart}更多信æ¯%{docLinkEnd}"
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr "支æŒé€šé…符,例如%{codeStart}.*-master%{codeEnd}或%{codeStart}release-.*%{codeEnd}"
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr "支æŒé€šé…符,例如%{codeStart}.*-test%{codeEnd}或%{codeStart}dev-.*%{codeEnd}。如需选择所有标签,请使用%{codeStart}.*%{codeEnd}"
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "在容器镜åƒåº“中,æ¯ä¸ªé¡¹ç›®éƒ½æœ‰è‡ªå·±çš„空间æ¥å­˜å‚¨å®¹å™¨é•œåƒã€‚ %{docLinkStart}更多信æ¯%{docLinkEnd}"
@@ -7506,7 +7719,7 @@ msgid "Contributions per group member"
msgstr "群组æˆå‘˜è´¡çŒ®è¯¦æƒ…"
msgid "Contributor"
-msgstr ""
+msgstr "贡献者"
msgid "Contributors"
msgstr "贡献者"
@@ -7515,7 +7728,7 @@ msgid "Control emails linked to your account"
msgstr "控制与您å¸æˆ·å…³è”的电å­é‚®ä»¶"
msgid "Control the display of third party offers."
-msgstr "控制第三方优惠的显示。"
+msgstr "控制第三方推广的显示。"
msgid "Cookie domain"
msgstr "Cookie域"
@@ -7565,6 +7778,9 @@ msgstr "å¤åˆ¶é“¾æŽ¥"
msgid "Copy branch name"
msgstr "å¤åˆ¶åˆ†æ”¯å称"
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr "å¤åˆ¶å‘½ä»¤"
@@ -7614,10 +7830,10 @@ msgid "Copy the code below to implement tracking in your application:"
msgstr "å¤åˆ¶ä¸‹é¢çš„代ç æ¥å®žçŽ°æ‚¨çš„应用程åºä¸­çš„跟踪:"
msgid "Copy this value"
-msgstr ""
+msgstr "å¤åˆ¶æ­¤å€¼"
msgid "Copy to clipboard"
-msgstr ""
+msgstr "å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Copy token"
msgstr "å¤åˆ¶ä»¤ç‰Œ"
@@ -7632,7 +7848,7 @@ msgid "Could not add admins as members"
msgstr "无法将管ç†å‘˜æ·»åŠ ä¸ºæˆå‘˜"
msgid "Could not archive %{design}. Please try again."
-msgstr ""
+msgstr "无法归档%{design}。请é‡è¯•ã€‚"
msgid "Could not authorize chat nickname. Try again!"
msgstr "无法授æƒèŠå¤©æ˜µç§°ã€‚å†è¯•ä¸€æ¬¡ï¼"
@@ -7641,7 +7857,7 @@ msgid "Could not change HEAD: branch '%{branch}' does not exist"
msgstr "无法更改HEAD:分支“%{branch}â€ä¸å­˜åœ¨"
msgid "Could not commit. An unexpected error occurred."
-msgstr ""
+msgstr "无法æ交。å‘生æ„外错误。"
msgid "Could not connect to FogBugz, check your URL"
msgstr "无法连接到 FogBugz,请检查您的 URL"
@@ -7662,22 +7878,22 @@ msgid "Could not create group"
msgstr "无法创建群组"
msgid "Could not create issue"
-msgstr ""
+msgstr "无法创建议题"
msgid "Could not create project"
msgstr "无法创建项目"
msgid "Could not create wiki page"
-msgstr ""
+msgstr "无法创建 wiki 页é¢"
msgid "Could not delete chat nickname %{chat_name}."
msgstr "无法删除èŠå¤©æ˜µç§° %{chat_name}。"
msgid "Could not delete wiki page"
-msgstr ""
+msgstr "无法删除 wiki 页é¢"
msgid "Could not draw the lines for job relationships"
-msgstr ""
+msgstr "无法绘制代表作业关系的线"
msgid "Could not find design."
msgstr "未找到设计."
@@ -7686,10 +7902,10 @@ msgid "Could not find iteration"
msgstr "未找到迭代"
msgid "Could not load instance counts. Please refresh the page to try again."
-msgstr ""
+msgstr "无法加载实例数。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "Could not load the user chart. Please refresh the page to try again."
-msgstr ""
+msgstr "无法加载用户图表。请刷新页é¢ä»¥é‡è¯•ã€‚"
msgid "Could not remove the trigger."
msgstr "无法删除触å‘器。"
@@ -7719,13 +7935,13 @@ msgid "Could not update the LDAP settings"
msgstr "无法更新LDAP设置"
msgid "Could not update wiki page"
-msgstr ""
+msgstr "无法更新 wiki 页é¢"
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "无法上传您的设计,因为ä¸æ”¯æŒå·²ä¸Šä¼ ä¸€ä¸ªæˆ–多个的文件。"
msgid "Couldn't calculate number of %{issuables}."
-msgstr ""
+msgstr "无法计算%{issuables}的数目。"
msgid "Country"
msgstr "国家/地区"
@@ -7738,7 +7954,7 @@ msgstr "Coverage Fuzzing"
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[0] "该æµæ°´çº¿çš„覆盖率是通过对%d个作业的覆盖率值进行平å‡è®¡ç®—得出的。"
msgid "Create"
msgstr "创建"
@@ -7797,15 +8013,12 @@ msgstr "创建一个预置了必è¦æ–‡ä»¶çš„项目方便您快速å¯åŠ¨ã€‚"
msgid "Create an account using:"
msgstr "使用以下方å¼åˆ›å»ºå¸æˆ·ï¼š"
-msgid "Create an issue. Issues are created for each alert triggered."
-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 "请创建并æ供您的GitHub%{link_start}个人访问令牌%{link_end}。您需è¦é€‰æ‹©%{code_open}repo%{code_close}范围,这样我们æ‰å¯ä»¥å‘您显示å¯å¯¼å…¥çš„公共和ç§æœ‰ä»“库的列表。"
-msgid "Create board"
-msgstr "新建看æ¿"
-
msgid "Create branch"
msgstr "创建分支"
@@ -7831,7 +8044,7 @@ msgid "Create file"
msgstr "创建文件"
msgid "Create from"
-msgstr ""
+msgstr "创建自"
msgid "Create group"
msgstr "创建群组"
@@ -7863,14 +8076,11 @@ msgstr "创建新的"
msgid "Create new Value Stream"
msgstr "创建新价值æµ"
-msgid "Create new board"
-msgstr "新建看æ¿"
-
msgid "Create new branch"
msgstr "创建新分支"
msgid "Create new confidential %{issuableType}"
-msgstr ""
+msgstr "创建新的ç§å¯†%{issuableType}"
msgid "Create new directory"
msgstr "创建新目录"
@@ -7897,7 +8107,7 @@ msgid "Create project label"
msgstr "创建项目标记"
msgid "Create release"
-msgstr ""
+msgstr "创建å‘布"
msgid "Create requirement"
msgstr "创建需求"
@@ -7929,6 +8139,84 @@ msgstr "标签"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "创建个人访问令牌"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr "创建于"
@@ -7975,7 +8263,7 @@ msgid "Created on"
msgstr "创建于"
msgid "Created on %{created_at}"
-msgstr ""
+msgstr "创建于%{created_at}"
msgid "Created on:"
msgstr "创建于:"
@@ -8022,6 +8310,9 @@ msgstr "Cron时区"
msgid "Crossplane"
msgstr "Crossplane"
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr "当å‰åˆ†æ”¯"
@@ -8071,13 +8362,13 @@ msgid "Custom Git clone URL for HTTP(S)"
msgstr "自定义HTTP(S)åè®®Git克隆URL"
msgid "Custom analyzers: language support"
-msgstr ""
+msgstr "自定义分æžå™¨ï¼šè¯­è¨€æ”¯æŒ"
msgid "Custom hostname (for private commit emails)"
msgstr "自定义主机å(用于ç§æœ‰æ交电å­é‚®ä»¶ï¼‰"
msgid "Custom metrics"
-msgstr ""
+msgstr "自定义指标"
msgid "Custom notification events"
msgstr "自定义通知事件"
@@ -8106,45 +8397,18 @@ msgstr "添加新阶段"
msgid "CustomCycleAnalytics|Editing stage"
msgstr "编辑阶段"
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr "输入阶段å称"
-
-msgid "CustomCycleAnalytics|Name"
-msgstr "å称"
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr "新阶段"
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr "请先选择一个开始事件"
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr "选择开始事件"
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr "选择åœæ­¢äº‹ä»¶"
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr "阶段å称已存在"
-msgid "CustomCycleAnalytics|Start event"
-msgstr "开始事件"
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr "开始事件已改å˜ï¼Œè¯·é€‰æ‹©ä¸€ä¸ªæœ‰æ•ˆçš„åœæ­¢äº‹ä»¶"
-
msgid "CustomCycleAnalytics|Start event label"
msgstr "开始事件标记"
-msgid "CustomCycleAnalytics|Stop event"
-msgstr "åœæ­¢äº‹ä»¶"
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr "åœæ­¢äº‹ä»¶æ ‡è®°"
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr "更新阶段"
-
msgid "Customer Portal"
msgstr "客户中心"
@@ -8173,13 +8437,13 @@ msgid "Customize your pipeline configuration."
msgstr "自定义您的æµæ°´çº¿é…置。"
msgid "CustomizeHomepageBanner|Do you want to customize this page?"
-msgstr ""
+msgstr "您需è¦å®šåˆ¶æ­¤é¡µé¢å—?"
msgid "CustomizeHomepageBanner|Go to preferences"
-msgstr ""
+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 ""
+msgstr "此页é¢é»˜è®¤æ˜¾ç¤ºæ‚¨çš„项目列表,但也å¯ä»¥æ”¹ä¸ºæ˜¾ç¤ºé¡¹ç›®çš„动æ€ï¼Œç¾¤ç»„,待办事项,分é…的议题,分é…çš„åˆå¹¶è¯·æ±‚等等。 您å¯ä»¥åœ¨â€œä¸»é¡µå†…容â€ä¸‹æ›´æ”¹æ­¤é€‰é¡¹"
msgid "Cycle Time"
msgstr "周期时间"
@@ -8218,7 +8482,7 @@ msgid "CycleAnalyticsEvent|Merge request created"
msgstr "åˆå¹¶è¯·æ±‚已创建"
msgid "CycleAnalyticsEvent|Merge request first commit time"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚首次æ交时间"
msgid "CycleAnalyticsEvent|Merge request first deployed to production"
msgstr "åˆå¹¶è¯·æ±‚首次部署到生产环境"
@@ -8324,7 +8588,7 @@ msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr "给定的日期范围大于180天"
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 ""
+msgstr "æ¯æ—¥å®Œæˆçš„项目在选定阶段所花费的全部时间。数æ®é™äºŽæœ€åŽ500项。"
msgid "CycleAnalytics|Total days to completion"
msgstr "完æˆæ‰€éœ€æ€»å¤©æ•°"
@@ -8348,7 +8612,7 @@ msgid "DAG visualization requires at least 3 dependent jobs."
msgstr "DAGå¯è§†åŒ–至少需è¦3个ä¾èµ–作业。"
msgid "DAST Profiles"
-msgstr ""
+msgstr "DASTé…ç½®"
msgid "DNS"
msgstr "DNS"
@@ -8381,61 +8645,64 @@ msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available f
msgstr "无法添加%{invalidProjects}。此仪表æ¿å¯ç”¨äºŽå…¬å¼€é¡¹ç›®ï¼Œä»¥åŠé“¶ç‰Œæ–¹æ¡ˆç¾¤ç»„中的ç§æœ‰é¡¹ç›®ã€‚"
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 ""
+msgstr "被动扫æ监控å‘é€åˆ°ç›®æ ‡çš„所有HTTP消æ¯(请求和å“应)。主动扫æ会对目标进行攻击以å‘现潜在æ¼æ´žã€‚"
msgid "DastProfiles|AJAX spider"
-msgstr ""
+msgstr "AJAX爬虫"
msgid "DastProfiles|Active"
+msgstr "主动"
+
+msgid "DastProfiles|Additional request headers (Optional)"
msgstr ""
msgid "DastProfiles|Are you sure you want to delete this profile?"
-msgstr ""
+msgstr "您确定è¦åˆ é™¤æ­¤é…ç½®å—?"
msgid "DastProfiles|Authentication"
-msgstr ""
+msgstr "身份验è¯"
msgid "DastProfiles|Authentication URL"
-msgstr ""
+msgstr "身份验è¯ç½‘å€"
msgid "DastProfiles|Could not create the scanner profile. Please try again."
-msgstr ""
+msgstr "无法创建扫æ工具é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr "无法创建站点é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "无法删除扫æ工具é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "DastProfiles|Could not delete scanner profiles:"
-msgstr ""
+msgstr "无法删除扫æ工具é…置:"
msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "无法删除站点é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "DastProfiles|Could not delete site profiles:"
-msgstr ""
+msgstr "无法删除站点é…置:"
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "无法获å–扫æ工具é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "无法获å–站点é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "DastProfiles|Could not update the scanner profile. Please try again."
-msgstr ""
+msgstr "无法更新扫æ工具é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "无法更新站点é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Debug messages"
-msgstr ""
+msgstr "调试消æ¯"
msgid "DastProfiles|Delete profile"
-msgstr ""
+msgstr "删除é…ç½®"
msgid "DastProfiles|Do you want to discard this scanner profile?"
-msgstr ""
+msgstr "您è¦æ”¾å¼ƒæ­¤æ‰«æ工具é…ç½®å—?"
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr "您è¦æ”¾å¼ƒæ­¤ç«™ç‚¹é…ç½®å—?"
@@ -8444,22 +8711,28 @@ msgid "DastProfiles|Do you want to discard your changes?"
msgstr "您è¦æ”¾å¼ƒæ›´æ”¹å—?"
msgid "DastProfiles|Edit scanner profile"
-msgstr ""
+msgstr "编辑扫æ工具é…ç½®"
msgid "DastProfiles|Edit site profile"
msgstr "编辑站点é…ç½®"
msgid "DastProfiles|Enable Authentication"
-msgstr ""
+msgstr "å¯ç”¨èº«ä»½éªŒè¯"
msgid "DastProfiles|Error Details"
+msgstr "错误详细信æ¯"
+
+msgid "DastProfiles|Excluded URLs"
msgstr ""
-msgid "DastProfiles|Hide debug messages"
+msgid "DastProfiles|Excluded URLs (Optional)"
msgstr ""
+msgid "DastProfiles|Hide debug messages"
+msgstr "éšè—调试消æ¯"
+
msgid "DastProfiles|Include debug messages in the DAST console output."
-msgstr ""
+msgstr "在DAST控制å°è¾“出中包å«è°ƒè¯•æ¶ˆæ¯ã€‚"
msgid "DastProfiles|Manage Profiles"
msgstr "管ç†é…ç½®"
@@ -8468,16 +8741,16 @@ msgid "DastProfiles|Manage profiles"
msgstr "管ç†é…ç½®"
msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
-msgstr ""
+msgstr "æœ€å° = 0 (无超时),最大 = 2880 分钟"
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
-msgstr ""
+msgstr "æœ€å° = 1秒,最大 = 3600秒"
msgid "DastProfiles|New Profile"
-msgstr ""
+msgstr "新建é…ç½®"
msgid "DastProfiles|New scanner profile"
-msgstr ""
+msgstr "新建扫æ工具é…ç½®"
msgid "DastProfiles|New site profile"
msgstr "新建站点é…ç½®"
@@ -8486,26 +8759,29 @@ msgid "DastProfiles|No profiles created yet"
msgstr "尚未创建é…ç½®"
msgid "DastProfiles|Not Validated"
-msgstr ""
+msgstr "未验è¯"
msgid "DastProfiles|Passive"
-msgstr ""
+msgstr "被动"
msgid "DastProfiles|Password"
-msgstr ""
+msgstr "密ç "
msgid "DastProfiles|Password form field"
-msgstr ""
+msgstr "密ç è¡¨å•å­—段"
msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
+msgstr "请输入有效的超时值"
msgid "DastProfiles|Profile name"
msgstr "é…ç½®å称"
-msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgid "DastProfiles|Request headers"
msgstr ""
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr "除了传统的爬虫之外,å¯ä»¥è¿è¡ŒAJAX爬虫æ¥é历目标站点。"
+
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr "将目标站点和扫æ设置的常用设定ä¿å­˜ä¸ºé…置。使用这些é…置进行需求扫æ。"
@@ -8513,109 +8789,109 @@ msgid "DastProfiles|Save profile"
msgstr "ä¿å­˜é…ç½®"
msgid "DastProfiles|Scan mode"
-msgstr ""
+msgstr "扫æ模å¼"
msgid "DastProfiles|Scanner Profile"
-msgstr ""
+msgstr "扫æ工具é…ç½®"
msgid "DastProfiles|Scanner Profiles"
-msgstr ""
+msgstr "扫æ工具é…ç½®"
msgid "DastProfiles|Show debug messages"
-msgstr ""
+msgstr "显示调试消æ¯"
msgid "DastProfiles|Site Profile"
-msgstr ""
+msgstr "站点é…ç½®"
msgid "DastProfiles|Site Profiles"
msgstr "站点é…ç½®"
msgid "DastProfiles|Spider timeout"
-msgstr ""
+msgstr "爬虫超时"
msgid "DastProfiles|Target URL"
msgstr "目标URL"
msgid "DastProfiles|Target timeout"
-msgstr ""
+msgstr "目标超时"
msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
-msgstr ""
+msgstr "爬虫é历站点所å…许的最大分钟数。"
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
-msgstr ""
+msgstr "被测站点å“应请求所å…许的最大秒数。"
msgid "DastProfiles|Turn on AJAX spider"
-msgstr ""
+msgstr "å¯ç”¨AJAX爬虫"
msgid "DastProfiles|Username"
-msgstr ""
+msgstr "用户å"
msgid "DastProfiles|Username form field"
-msgstr ""
+msgstr "用户å表å•å­—段"
msgid "DastProfiles|Validated"
-msgstr ""
+msgstr "已验è¯"
msgid "DastSiteValidation|Copy HTTP header to clipboard"
-msgstr ""
+msgstr "å¤åˆ¶HTTP报头到剪贴æ¿"
msgid "DastSiteValidation|Could not create validation token. Please try again."
-msgstr ""
+msgstr "无法创建验è¯ä»¤ç‰Œã€‚请é‡è¯•ã€‚"
msgid "DastSiteValidation|Download validation text file"
-msgstr ""
+msgstr "下载验è¯æ–‡æœ¬æ–‡ä»¶"
msgid "DastSiteValidation|Header validation"
-msgstr ""
+msgstr "报头验è¯"
msgid "DastSiteValidation|Step 1 - Choose site validation method"
-msgstr ""
+msgstr "步骤 1 - 选择站点验è¯æ–¹æ³•"
msgid "DastSiteValidation|Step 2 - Add following HTTP header to your site"
-msgstr ""
+msgstr "步骤2 - 将以下HTTP标头添加到您的网站"
msgid "DastSiteValidation|Step 2 - Add following text to the target site"
-msgstr ""
+msgstr "步骤 2 - 将以下文本添加到目标站点"
msgid "DastSiteValidation|Step 3 - Confirm header location and validate"
-msgstr ""
+msgstr "步骤 3 - 确认报头ä½ç½®å¹¶éªŒè¯"
msgid "DastSiteValidation|Step 3 - Confirm text file location and validate"
-msgstr ""
+msgstr "步骤 3 - 确认文本文件ä½ç½®å¹¶éªŒè¯"
msgid "DastSiteValidation|Text file validation"
-msgstr ""
+msgstr "文本文件验è¯"
msgid "DastSiteValidation|The validation has failed. Please try again."
-msgstr ""
+msgstr "验è¯å¤±è´¥ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
msgid "DastSiteValidation|The validation is in progress. Please wait..."
-msgstr ""
+msgstr "正在验è¯ã€‚请ç¨å€™..."
msgid "DastSiteValidation|Validate"
-msgstr ""
+msgstr "验è¯"
msgid "DastSiteValidation|Validate target site"
-msgstr ""
+msgstr "验è¯ç›®æ ‡ç½‘ç«™"
msgid "DastSiteValidation|Validated"
-msgstr ""
+msgstr "已验è¯"
msgid "DastSiteValidation|Validating..."
-msgstr ""
+msgstr "正在验è¯..."
msgid "DastSiteValidation|Validation failed"
-msgstr ""
+msgstr "验è¯å¤±è´¥"
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
-msgstr ""
+msgstr "验è¯æˆåŠŸã€‚å¯å¯¹ç›®æ ‡ç«™ç‚¹è¿›è¡Œä¸»åŠ¨æ‰«æ和被动扫æ。"
msgid "Data is still calculating..."
msgstr "æ•°æ®ä»åœ¨è®¡ç®—中……"
msgid "Database update failed"
-msgstr ""
+msgstr "æ•°æ®åº“更新失败"
msgid "Datasource name not found"
msgstr "找ä¸åˆ°æ•°æ®æºå称"
@@ -8627,7 +8903,7 @@ msgid "Date picker"
msgstr "日期选择器"
msgid "Date range"
-msgstr ""
+msgstr "日期范围"
msgid "Date range cannot exceed %{maxDateRange} days."
msgstr "日期范围ä¸èƒ½è¶…过%{maxDateRange}天。"
@@ -8654,7 +8930,7 @@ msgid "Days to merge"
msgstr "åˆå¹¶æ‰€éœ€å¤©æ•°"
msgid "Dear Administrator,"
-msgstr ""
+msgstr "亲爱的管ç†å‘˜ï¼Œ"
msgid "Debug"
msgstr "调试"
@@ -8693,7 +8969,7 @@ msgid "Default classification label"
msgstr "默认分类标记"
msgid "Default deletion delay"
-msgstr ""
+msgstr "默认删除延迟"
msgid "Default description template for issues"
msgstr "议题的默认æ述模æ¿"
@@ -8710,18 +8986,12 @@ msgstr "在日期选择器中显示æ¯å‘¨é»˜è®¤çš„起始日。"
msgid "Default initial branch name"
msgstr "默认åˆå§‹åˆ†æ”¯å称"
-msgid "Default issue template"
-msgstr "默认议题模æ¿"
-
msgid "Default project deletion protection"
msgstr "默认项目删除ä¿æŠ¤"
msgid "Default projects limit"
msgstr "默认项目é™åˆ¶"
-msgid "Default stages"
-msgstr "默认阶段"
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr "默认:将FogBugzå¸æˆ·ID映射为全å"
@@ -8734,6 +9004,9 @@ msgstr "使用%{cronSyntaxStart}cron语法%{cronSyntaxEnd}定义自定义部署å
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 语法定义自定义模å¼"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr "定义独立于Akismet的垃圾邮件自定义规则"
@@ -8747,7 +9020,7 @@ msgid "Delayed Project Deletion (%{adjourned_deletion})"
msgstr "延迟项目删除(%{adjourned_deletion})"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
-msgstr ""
+msgstr "确定è¦ç«‹å³è¿è¡Œ%{jobName}å—?å¦åˆ™è¯¥ä½œä¸šå°†åœ¨è®¡æ—¶å™¨ç»“æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
msgstr "您确定è¦ç«‹å³è¿è¡Œ %{job_name} å—?该作业将在计时结æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
@@ -8765,25 +9038,22 @@ msgid "Delete"
msgstr "删除"
msgid "Delete %{name}"
-msgstr ""
+msgstr "删除%{name}"
msgid "Delete Comment"
msgstr "删除评论"
msgid "Delete Value Stream"
-msgstr ""
+msgstr "删除值æµ"
msgid "Delete account"
-msgstr ""
+msgstr "删除账户"
msgid "Delete artifacts"
msgstr "删除产物"
msgid "Delete badge"
-msgstr ""
-
-msgid "Delete board"
-msgstr "删除看æ¿"
+msgstr "删除徽章"
msgid "Delete comment"
msgstr "删除评论"
@@ -8819,7 +9089,7 @@ msgid "Delete source branch"
msgstr "删除æºåˆ†æ”¯"
msgid "Delete subscription"
-msgstr ""
+msgstr "删除订阅"
msgid "Delete this attachment"
msgstr "删除此附件"
@@ -8852,25 +9122,25 @@ msgid "Deleted"
msgstr "已删除"
msgid "Deleted Projects"
-msgstr ""
+msgstr "已删除的项目"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "已删除èŠå¤©çš„昵称: %{chat_name}!"
msgid "Deleted projects"
-msgstr ""
+msgstr "已删除的项目"
msgid "Deleted projects cannot be restored!"
-msgstr ""
+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 ""
+msgstr "删除项目会将其置于åªè¯»çŠ¶æ€ç›´è‡³%{date}。届时项目将被永久删除。确定è¦åˆ é™¤å—?"
msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
+msgstr "删除项目将删除其存储库和所有相关资æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。"
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "删除等待中。此项目将于%{date}被删除。仓库和其他项目资æºä¸ºåªè¯»ã€‚"
@@ -8882,7 +9152,7 @@ msgid "Denied authorization of chat nickname %{user_name}."
msgstr "æ‹’ç»èŠå¤©æ˜µç§° %{user_name} 的授æƒã€‚"
msgid "Denied domains for sign-ups"
-msgstr ""
+msgstr "æ‹’ç»æ³¨å†Œçš„域å"
msgid "Deny"
msgstr "æ‹’ç»"
@@ -8891,7 +9161,7 @@ msgid "Deny access request"
msgstr "æ‹’ç»è®¿é—®è¯·æ±‚"
msgid "Denylist file"
-msgstr ""
+msgstr "æ‹’ç»æ¸…å•æ–‡ä»¶"
msgid "Dependencies"
msgstr "ä¾èµ–项"
@@ -8905,7 +9175,7 @@ msgstr[0] "%d个其它æ¼æ´žæœªæ˜¾ç¤º"
msgid "Dependencies|%d more"
msgid_plural "Dependencies|%d more"
-msgstr[0] ""
+msgstr[0] "更多%d项"
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
@@ -8915,7 +9185,7 @@ msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "其余%{remainingLicensesCount}项"
msgid "Dependencies|(top level)"
-msgstr ""
+msgstr "(顶层)"
msgid "Dependencies|All"
msgstr "所有"
@@ -8930,7 +9200,7 @@ msgid "Dependencies|Component name"
msgstr "组件å称"
msgid "Dependencies|Dependency path"
-msgstr ""
+msgstr "ä¾èµ–项路径"
msgid "Dependencies|Export as JSON"
msgstr "导出为JSON"
@@ -8939,7 +9209,7 @@ msgid "Dependencies|Job failed to generate the dependency list"
msgstr "作业无法生æˆä¾èµ–项列表"
msgid "Dependencies|Learn more about dependency paths"
-msgstr ""
+msgstr "了解更多关于ä¾èµ–路径的信æ¯"
msgid "Dependencies|License"
msgstr "许å¯è¯"
@@ -8948,7 +9218,7 @@ msgid "Dependencies|Location"
msgstr "ä½ç½®"
msgid "Dependencies|Location and dependency path"
-msgstr ""
+msgstr "ä½ç½®å’Œä¾èµ–项路径"
msgid "Dependencies|Packager"
msgstr "打包程åº"
@@ -8957,10 +9227,10 @@ msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has
msgstr "%{codeStartTag}dependency_scanning%{codeEndTag} 作业失败,无法生æˆåˆ—表。请确ä¿ä½œä¸šæ­£å¸¸è¿è¡Œå¹¶é‡å¯æµæ°´çº¿ã€‚"
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 ""
+msgstr "组件ä¾èµ–路径基于é”定文件。有å¯èƒ½æœ‰å¤šä¸ªè·¯å¾„。在这些情况下,将显示的最长的路径。"
msgid "Dependencies|There may be multiple paths"
-msgstr ""
+msgstr "å¯èƒ½æœ‰å¤šä¸ªè·¯å¾„"
msgid "Dependencies|Toggle vulnerability list"
msgstr "切æ¢æ¼æ´žåˆ—表"
@@ -9001,7 +9271,7 @@ msgstr[0] "ä¾èµ–于%d 个正在åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
-msgstr[0] ""
+msgstr[0] "ä¾èµ–于%{strongStart}%{closedCount}已关闭的%{strongEnd}åˆå¹¶è¯·æ±‚。"
msgid "Deploy"
msgid_plural "Deploys"
@@ -9041,7 +9311,7 @@ msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click
msgstr "此项目ä¸å­˜åœ¨éƒ¨ç½²å†»ç»“。如需添加,请点击%{strongStart}添加部署冻结%{strongEnd}"
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 ""
+msgstr "指定环境ä¸å…许部署的时间。必须更新%{filename}文件,以使部署作业获得%{freeze_period_link_start}冻结期%{freeze_period_link_end}的相关信æ¯ã€‚"
msgid "DeployFreeze|Time zone"
msgstr "时区"
@@ -9197,10 +9467,10 @@ msgid "Deployed to"
msgstr "已部署到"
msgid "Deployed-after"
-msgstr ""
+msgstr "之åŽéƒ¨ç½²"
msgid "Deployed-before"
-msgstr ""
+msgstr "之å‰éƒ¨ç½²"
msgid "Deploying to"
msgstr "正在部署到"
@@ -9230,7 +9500,7 @@ msgid "Deployment|running"
msgstr "è¿è¡Œä¸­"
msgid "Deployment|skipped"
-msgstr ""
+msgstr "已跳过"
msgid "Deployment|success"
msgstr "æˆåŠŸ"
@@ -9244,21 +9514,21 @@ msgstr "é™åº"
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr "æ述更改的目的以åŠè¯„审人员应注æ„的事项。"
-msgid "Describe the requirement here"
-msgstr "在此处进行需求æè¿°"
-
msgid "Description"
msgstr "æè¿°"
msgid "Description (optional)"
-msgstr ""
+msgstr "æè¿° (å¯é€‰)"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "使用%{link_start}GitLab风格Markdown%{link_end}解æžçš„æè¿°"
-msgid "Description template"
+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 "æ述模æ¿å…许您为项目的问题和åˆå¹¶è¯·æ±‚定义æ述字段的特定模æ¿ã€‚"
@@ -9290,19 +9560,19 @@ msgid "DesignManagement|Adding a design with the same filename replaces the file
msgstr "添加具有相åŒæ–‡ä»¶å的设计会替æ¢ä¸ºæ–°ç‰ˆæœ¬çš„文件。"
msgid "DesignManagement|Archive design"
-msgstr ""
+msgstr "归档设计"
msgid "DesignManagement|Archive designs"
-msgstr ""
+msgstr "归档设计"
msgid "DesignManagement|Archive selected"
-msgstr ""
+msgstr "存档已选择项"
msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
-msgstr ""
+msgstr "已存档设计ä»å¯åœ¨ä»¥å‰ç‰ˆæœ¬çš„设计集中使用。"
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
-msgstr ""
+msgstr "您确定è¦å½’档选定的设计å—?"
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr "您确定è¦å–消对此评论的更改å—?"
@@ -9350,7 +9620,7 @@ msgid "DesignManagement|Discard comment"
msgstr "放弃评论"
msgid "DesignManagement|Download design"
-msgstr ""
+msgstr "下载设计"
msgid "DesignManagement|Error uploading a new design. Please try again."
msgstr "上传新设计时出错。请å†è¯•ä¸€æ¬¡."
@@ -9392,10 +9662,10 @@ msgid "DesignManagement|The maximum number of designs allowed to be uploaded is
msgstr "å…许上传的设计最大数é‡ä¸º %{upload_limit}。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "DesignManagement|There was an error moving your designs. Please upload your designs below."
-msgstr ""
+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 ""
+msgstr "如需上传设计,请å¯ç”¨LFS并由管ç†å‘˜å¯ç”¨å“ˆå¸Œå­˜å‚¨ã€‚%{requirements_link_start}更多信æ¯%{requirements_link_end}"
msgid "DesignManagement|Unresolve thread"
msgstr "将主题置为未解决"
@@ -9407,7 +9677,7 @@ msgid "DesignManagement|Upload skipped."
msgstr "上传已跳过。"
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
-msgstr ""
+msgstr "您的设计正在å¤åˆ¶è¿‡ç¨‹ä¸­â€¦ 请刷新以获得更新。"
msgid "DesignManagement|and %{moreCount} more."
msgstr "以åŠå…¶ä½™%{moreCount}项。"
@@ -9431,94 +9701,151 @@ msgid "Detect host keys"
msgstr "检测主机密钥"
msgid "DevOps Report"
-msgstr ""
+msgstr "DevOps报告"
msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
-msgstr ""
+msgstr "已达到最大选择数"
msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
-msgstr ""
+msgstr "ä¸èƒ½åŒæ—¶ä¸ºé¡¹ç›®å’Œç¾¤ç»„é…置选择"
msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
-msgstr ""
+msgstr "已达到最大阶段数"
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
-msgstr ""
+msgstr "已达到最大选择数"
msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
-msgstr ""
+msgstr "已选择%{selectedCount}个群组(最多20个)"
msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
-msgstr ""
+msgstr "已选择%{selectedCount}个群组(最多20个)"
msgid "DevopsAdoption|Add a segment to get started"
-msgstr ""
+msgstr "添加新阶段æ¥å¼€å§‹"
msgid "DevopsAdoption|Add new segment"
+msgstr "添加新阶段"
+
+msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
msgstr ""
+msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
msgstr ""
msgid "DevopsAdoption|Create new segment"
+msgstr "创建新阶段"
+
+msgid "DevopsAdoption|Delete segment"
msgstr ""
msgid "DevopsAdoption|Deploys"
-msgstr ""
+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|Edit segment"
msgstr ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsAdoption|Issues"
+msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Issues"
+msgstr "议题"
+
msgid "DevopsAdoption|MRs"
+msgstr "åˆå¹¶è¯·æ±‚"
+
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
msgstr ""
msgid "DevopsAdoption|My segment"
-msgstr ""
+msgstr "我的阶段"
msgid "DevopsAdoption|Name"
-msgstr ""
+msgstr "å称"
msgid "DevopsAdoption|New segment"
+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 "Runners"
+
+msgid "DevopsAdoption|Save changes"
msgstr ""
msgid "DevopsAdoption|Scanning"
-msgstr ""
+msgstr "扫æ"
msgid "DevopsAdoption|Segment"
+msgstr "阶段"
+
+msgid "DevopsAdoption|Segment data pending until the start of next month"
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
-msgstr ""
+msgstr "获å–群组时å‘生错误。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
+msgstr "获å–阶段时å‘生错误。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "DevopsReport|Adoption"
-msgstr ""
+msgstr "采用率"
msgid "DevopsReport|DevOps"
-msgstr ""
+msgstr "DevOps"
msgid "DevopsReport|DevOps Score"
-msgstr ""
+msgstr "DevOps分数"
msgid "DevopsReport|Score"
-msgstr ""
+msgstr "分数"
msgid "Diff content limits"
msgstr "差异内容é™åˆ¶"
@@ -9527,7 +9854,7 @@ msgid "Diff limits"
msgstr "差异é™åˆ¶"
msgid "Diff view settings"
-msgstr ""
+msgstr "差异视图设置"
msgid "Difference between start date and now"
msgstr "开始日期和现在之间的差异"
@@ -9542,16 +9869,16 @@ msgid "Diffs|No file name available"
msgstr "æ— å¯ç”¨çš„文件å"
msgid "Diffs|Show %{unfoldCount} lines"
-msgstr ""
+msgstr "显示%{unfoldCount}行"
msgid "Diffs|Show all unchanged lines"
-msgstr ""
+msgstr "显示所有未改å˜çš„è¡Œ"
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "获å–差异线时å‘生错误。"
msgid "Direct member"
-msgstr ""
+msgstr "直接æˆå‘˜"
msgid "Direction"
msgstr "æ–¹å‘"
@@ -9572,7 +9899,7 @@ msgid "Disable public access to Pages sites"
msgstr "ç¦æ­¢å…¬å¼€è®¿é—®Pages网站"
msgid "Disable shared runners"
-msgstr ""
+msgstr "ç¦ç”¨å…±äº«Runner"
msgid "Disable two-factor authentication"
msgstr "ç¦ç”¨åŒé‡è®¤è¯"
@@ -9663,7 +9990,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] "忽略%d个选定的æ¼æ´žï¼Œå°†å®ƒä»¬å½’类为"
msgid "Dismiss DevOps Report introduction"
-msgstr ""
+msgstr "关闭DevOps报告介ç»"
msgid "Dismiss Merge Request promotion"
msgstr "关闭åˆå¹¶è¯·æ±‚推广"
@@ -9672,7 +9999,7 @@ msgid "Dismiss Value Stream Analytics introduction box"
msgstr "ä¸å†æ˜¾ç¤ºä»·å€¼æµåˆ†æžä»‹ç»æ¡†"
msgid "Dismiss selected"
-msgstr ""
+msgstr "å–消选择"
msgid "Dismiss trial promotion"
msgstr "关闭试用推è"
@@ -9717,7 +10044,7 @@ msgid "Documentation for popular identity providers"
msgstr "常è§çš„身份验è¯æ供商的相关文档"
msgid "Documentation pages URL"
-msgstr ""
+msgstr "文档页é¢URL"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "文档é‡å»ºç´¢å¼•: %{processed_documents} (%{percentage}%%)"
@@ -9729,7 +10056,7 @@ msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr "如已关è”到一个或多个集群,则域ä¸èƒ½åˆ é™¤ã€‚"
msgid "Domain denylist"
-msgstr ""
+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 "域验è¯æ˜¯å…¬å…± GitLab 站点的基本安全措施。用户需è¦è¯æ˜Žä»–们在å¯ç”¨åŸŸä¹‹å‰æ‹¥æœ‰åŸŸçš„所有æƒ"
@@ -9753,7 +10080,7 @@ msgid "Don't paste the private part of the GPG key. Paste the public part which
msgstr "请勿粘贴GPG密钥中的ç§é’¥éƒ¨åˆ†ï¼Œåªéœ€ç²˜è´´ä»¥ '-----BEGIN PGP PUBLIC KEY BLOCK-----' 为开头的公钥部分。"
msgid "Don't send usage data"
-msgstr ""
+msgstr "ä¸å‘é€ä½¿ç”¨æƒ…况数æ®"
msgid "Don't show again"
msgstr "ä¸å†æ˜¾ç¤º"
@@ -9770,6 +10097,9 @@ msgstr "下载%{format}"
msgid "Download %{format}:"
msgstr "下载%{format}:"
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr "下载CSV"
@@ -9828,13 +10158,13 @@ msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
msgstr "拖放或%{linkStart}上传%{linkEnd}设计以附加"
msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
-msgstr ""
+msgstr "拖放或%{linkStart}上传%{linkEnd}文件以附加"
msgid "Drop your designs to start your upload."
msgstr "拖放您的设计以å¯åŠ¨ä¸Šä¼ ã€‚"
msgid "Drop your files to start your upload."
-msgstr ""
+msgstr "拖放您的文件以å¯åŠ¨ä¸Šä¼ ã€‚"
msgid "Due Date"
msgstr "截止日期"
@@ -9854,9 +10184,6 @@ msgstr "在此过程中,我们会è¦æ±‚您æä¾›æ¥è‡ª GitLab çš„ URL 。请ä½
msgid "Dynamic Application Security Testing (DAST)"
msgstr "动æ€åº”用程åºå®‰å…¨æ€§æµ‹è¯•(DAST)"
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr "æ¯ä¸ªRunnerå¯ä»¥åœ¨ä»¥ä¸‹çŠ¶æ€ä¹‹ä¸€å’Œ/或属于以下类型之一:"
-
msgid "Each Runner can be in one of the following states:"
msgstr "æ¯ä¸ªRunnerå¯ä»¥å¤„于以下状æ€ä¸­çš„其中一ç§ï¼š"
@@ -9911,9 +10238,6 @@ msgstr "编辑系统钩å­"
msgid "Edit application"
msgstr "编辑应用"
-msgid "Edit board"
-msgstr "编辑看æ¿"
-
msgid "Edit comment"
msgstr "编辑评论"
@@ -9936,13 +10260,13 @@ msgid "Edit identity for %{user_name}"
msgstr "编辑 %{user_name} 的身份信æ¯"
msgid "Edit in Web IDE"
-msgstr ""
+msgstr "在Web IDE中编辑"
msgid "Edit in single-file editor"
-msgstr ""
+msgstr "在å•æ–‡ä»¶ç¼–辑器中编辑"
msgid "Edit inline"
-msgstr ""
+msgstr "内è”编辑"
msgid "Edit issues"
msgstr "编辑议题"
@@ -9953,17 +10277,20 @@ msgstr "编辑迭代"
msgid "Edit public deploy key"
msgstr "编辑公共部署密钥"
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr "编辑阶段"
msgid "Edit this file only."
-msgstr ""
+msgstr "仅编辑此文件。"
msgid "Edit this release"
msgstr "编辑此å‘布"
msgid "Edit title and description"
-msgstr ""
+msgstr "编辑标题和æè¿°"
msgid "Edit wiki page"
msgstr "编辑Wiki页é¢"
@@ -9972,7 +10299,7 @@ msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "编辑你在最近主题中的评论(从空白文本区)"
msgid "Edited"
-msgstr ""
+msgstr "已编辑"
msgid "Edited %{timeago}"
msgstr "编辑于%{timeago}"
@@ -9980,10 +10307,16 @@ msgstr "编辑于%{timeago}"
msgid "Editing"
msgstr "编辑中"
+msgid "Editor Lite instance is required to set up an extension."
+msgstr ""
+
msgid "Elasticsearch AWS IAM credentials"
msgstr "Elasticsearch AWS IAM凭æ®"
msgid "Elasticsearch HTTP client timeout value in seconds."
+msgstr "Elasticsearch HTTP客户端超时值,以秒为å•ä½ã€‚"
+
+msgid "Elasticsearch indexing"
msgstr ""
msgid "Elasticsearch indexing restrictions"
@@ -10019,9 +10352,12 @@ msgstr "电å­é‚®ä»¶%{number}"
msgid "Email Notification"
msgstr "电å­é‚®ä»¶é€šçŸ¥"
-msgid "Email cannot be blank"
+msgid "Email address to use for Support Desk"
msgstr ""
+msgid "Email cannot be blank"
+msgstr "电å­é‚®ä»¶ä¸èƒ½ä¸ºç©º"
+
msgid "Email could not be sent"
msgstr "邮件无法å‘é€"
@@ -10050,10 +10386,10 @@ msgid "Email the pipelines status to a list of recipients."
msgstr "å°†æµæ°´çº¿çŠ¶æ€é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™å¤šä¸ªæ”¶ä»¶äººã€‚"
msgid "Email updates (optional)"
-msgstr ""
+msgstr "电å­é‚®ä»¶æ›´æ–°(å¯é€‰)"
msgid "Email: %{email}"
-msgstr ""
+msgstr "电å­é‚®ä»¶: %{email}"
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr "电å­é‚®ä»¶å†…容空白。请确ä¿æ‚¨çš„回å¤ä½äºŽç”µå­é‚®ä»¶çš„顶部,因为我们无法处ç†å†…è”回å¤ã€‚"
@@ -10088,10 +10424,10 @@ msgstr "正在é‡ç½®..."
msgid "Emails"
msgstr "电å­é‚®ä»¶"
-msgid "Emails sent from Service Desk will have this name"
-msgstr "从æœåŠ¡å°å‘é€çš„电å­é‚®ä»¶å°†å…·æœ‰æ­¤å称"
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10128,16 +10464,16 @@ msgid "Enable"
msgstr "å¯ç”¨"
msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
+msgstr "å¯ç”¨%{linkStart}Gitpod%{linkEnd}集æˆï¼Œå¯ç›´æŽ¥åœ¨æµè§ˆå™¨ä»ŽGitLabå¯åŠ¨å¼€å‘环境。"
msgid "Enable Auto DevOps"
msgstr "å¯ç”¨Auto DevOps"
msgid "Enable Gitpod"
-msgstr ""
+msgstr "å¯ç”¨Gitpod"
msgid "Enable Gitpod?"
-msgstr ""
+msgstr "å¯ç”¨Gitpodå—?"
msgid "Enable HTML emails"
msgstr "å¯ç”¨ HTML 电å­é‚®ä»¶"
@@ -10146,7 +10482,7 @@ msgid "Enable Incident Management inbound alert limit"
msgstr "å¯ç”¨äº‹ä»¶ç®¡ç†ä¼ å…¥è­¦æŠ¥é™åˆ¶"
msgid "Enable Kroki"
-msgstr ""
+msgstr "å¯ç”¨Kroki"
msgid "Enable PlantUML"
msgstr "å¯ç”¨PlantUML"
@@ -10172,6 +10508,9 @@ msgstr "å¯ç”¨å¹¶é…ç½®Grafana。"
msgid "Enable and configure Prometheus metrics."
msgstr "å¯ç”¨å¹¶é…ç½®Prometheus指标。"
+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 "使用外部æœåŠ¡å¯ç”¨åˆ†ç±»æŽ§åˆ¶"
@@ -10200,10 +10539,10 @@ msgid "Enable integration"
msgstr "å¯ç”¨é›†æˆ"
msgid "Enable kuromoji custom analyzer: Indexing"
-msgstr ""
+msgstr "å¯ç”¨kuromoji自定义分æžå™¨ï¼šç´¢å¼•"
msgid "Enable kuromoji custom analyzer: Search"
-msgstr ""
+msgstr "å¯ç”¨kuromoji自定义分æžå™¨ï¼šæœç´¢"
msgid "Enable maintenance mode"
msgstr "å¯ç”¨ç»´æŠ¤æ¨¡å¼"
@@ -10233,19 +10572,22 @@ msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currentl
msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚对于reCAPTCHA,我们目å‰ä»…æ”¯æŒ %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgid "Enable shared runners"
-msgstr ""
+msgstr "å¯ç”¨å…±äº«Runner"
msgid "Enable shared runners for all projects and subgroups in this group."
-msgstr ""
+msgstr "为该组中的所有项目和å­ç»„å¯ç”¨å…±äº«Runner。"
msgid "Enable shared runners for this group"
+msgstr "为该组å¯ç”¨å…±äº«Runner"
+
+msgid "Enable shared runners for this project"
msgstr ""
msgid "Enable smartcn custom analyzer: Indexing"
-msgstr ""
+msgstr "å¯ç”¨smartcn自定义分æžå™¨ï¼šç´¢å¼•"
msgid "Enable smartcn custom analyzer: Search"
-msgstr ""
+msgstr "å¯ç”¨smartcn自定义分æžå™¨ï¼šæœç´¢"
msgid "Enable snowplow tracking"
msgstr "å¯ç”¨Snowplow跟踪"
@@ -10256,9 +10598,6 @@ msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "Enable usage ping"
msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr "å¯ç”¨/ç¦ç”¨æœåŠ¡å°ã€‚ %{link_start}了解有关æœåŠ¡å°%{link_end}的更多信æ¯ã€‚"
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr "%{stepStart}第一步%{stepEnd}: ç¡®ä¿æ‚¨å·²è®¾ç½®Kubernetes并为您的%{linkStart}集群%{linkEnd}æ供了基本域。"
@@ -10290,6 +10629,9 @@ msgid "Encountered an error while rendering: %{err}"
msgstr "渲染时出现错误: %{err}"
msgid "End Time"
+msgstr "结æŸæ—¶é—´"
+
+msgid "Ends at %{endsAt}"
msgstr ""
msgid "Ends at (UTC)"
@@ -10320,17 +10662,14 @@ msgid "Enter a number"
msgstr "输入数字"
msgid "Enter an integer number between 0 and 100"
-msgstr ""
+msgstr "输入介于0到100之间的整数"
msgid "Enter an integer number number between 0 and 100"
-msgstr ""
+msgstr "输入一个介于0到100之间的整数"
msgid "Enter at least three characters to search"
msgstr "请至少输入三个字符æ‰å¯æœç´¢"
-msgid "Enter board name"
-msgstr "输入看æ¿å称"
-
msgid "Enter domain"
msgstr "输入域å"
@@ -10373,6 +10712,9 @@ msgstr "输入åˆå¹¶è¯·æ±‚标题"
msgid "Enter the name of your application, and we'll return a unique %{type}."
msgstr "输入您的应用程åºçš„å称,我们会返回唯一的%{type}。"
+msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
+msgstr ""
+
msgid "Enter weights for storages for new repositories."
msgstr "输入新存储库的æƒé‡ã€‚"
@@ -10428,7 +10770,7 @@ msgid "Environments in %{name}"
msgstr "%{name}中的环境"
msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
-msgstr ""
+msgstr "%{severity} • %{title} %{text}。 %{linkStart}查看详细信æ¯%{linkEnd} · %{startedAt} "
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "将项目添加到仪表æ¿"
@@ -10455,7 +10797,7 @@ msgid "EnvironmentsDashboard|The environments dashboard provides a summary of ea
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 ""
+msgstr "此仪表æ¿ä¸ºæ¯ä¸ªé¡¹ç›®æ˜¾ç¤º3个环境,并链接到è¿ç»´ä»ªè¡¨æ¿ã€‚从一个仪表æ¿æ·»åŠ æˆ–删除项目时,GitLab也会从å¦ä¸€ä¸ªä»ªè¡¨æ¿æ·»åŠ æˆ–删除项目。 %{readMoreLink}"
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr "å–消自动终止时å‘生错误,请é‡è¯•"
@@ -10500,7 +10842,7 @@ msgid "Environments|Delete"
msgstr "删除"
msgid "Environments|Delete '%{environmentName}'?"
-msgstr ""
+msgstr "删除'%{environmentName}'å—?"
msgid "Environments|Delete environment"
msgstr "删除环境"
@@ -10514,6 +10856,9 @@ msgstr "部署到..."
msgid "Environments|Deployment"
msgstr "部署"
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr "å¯ç”¨å®¡æ ¸åº”用"
@@ -10614,7 +10959,7 @@ msgid "Environments|Stopping"
msgstr "åœæ­¢ä¸­"
msgid "Environments|Stopping %{environmentName}"
-msgstr ""
+msgstr "终止%{environmentName}"
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "获å–日志时出错。请é‡è¯•ã€‚"
@@ -10631,6 +10976,12 @@ msgstr "æ­¤æ“作将è¿è¡Œç”±%{environment_name}定义的作业,使用æ交%{
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 "æ­¤æ“作将è¿è¡Œç”± %{name} 定义的作业,用于æ交 %{linkStart}%{commitId}%{linkEnd} 将环境置于先å‰ç‰ˆæœ¬ä¸­ã€‚您å¯ä»¥é€šè¿‡é‡æ–°éƒ¨ç½²æœ€æ–°ç‰ˆæœ¬çš„应用程åºæ¥è¿˜åŽŸå®ƒã€‚你确定你è¦ç»§ç»­å—?"
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
msgid "Environments|Updated"
msgstr "更新于"
@@ -10691,9 +11042,6 @@ msgstr "我该如何解决该问题?"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr "留空以继承里程碑日期"
-msgid "Epics|More information"
-msgstr "更多信æ¯"
-
msgid "Epics|Remove epic"
msgstr "删除å²è¯—"
@@ -10740,7 +11088,7 @@ msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, a
msgstr "如需根æ®é‡Œç¨‹ç¢‘æ¥å®‰æŽ’å²è¯—çš„ %{epicDateType} 日期,请为å²è¯—中的任一议题指定带有 %{epicDateType} 日期的里程碑。"
msgid "Epics|Unable to perform this action"
-msgstr ""
+msgstr "无法执行此æ“作"
msgid "Epics|Unable to save epic. Please try again"
msgstr "无法ä¿å­˜å²è¯—。请å†è¯•ä¸€æ¬¡"
@@ -10782,7 +11130,7 @@ msgid "Error deleting project. Check logs for error details."
msgstr "删除项目时出错。请检查错误详细信æ¯ã€‚"
msgid "Error fetching burnup chart data"
-msgstr ""
+msgstr "æå–燃烧图数æ®æ—¶å‡ºé”™"
msgid "Error fetching diverging counts for branches. Please try again."
msgstr "获å–分支分å‰æ•°ç›®æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
@@ -10799,9 +11147,6 @@ msgstr "获å–网络图时出错。"
msgid "Error fetching payload data."
msgstr "获å–有效数æ®æ—¶å‡ºé”™ã€‚"
-msgid "Error fetching projects"
-msgstr "获å–项目时出错"
-
msgid "Error fetching refs"
msgstr "获å–refs时出错。"
@@ -10860,7 +11205,7 @@ msgid "Error occurred when saving assignees"
msgstr "ä¿å­˜è¢«æŒ‡æ´¾äººæ—¶å‡ºçŽ°é”™è¯¯ã€‚"
msgid "Error occurred when saving reviewers"
-msgstr ""
+msgstr "ä¿å­˜å®¡æ ¸è€…时出错"
msgid "Error occurred when toggling the notification subscription"
msgstr "切æ¢é€šçŸ¥è®¢é˜…æ—¶å‘生错误"
@@ -10890,7 +11235,7 @@ msgid "Error occurred. User was not unlocked"
msgstr "å‘生了错误。用户未解除é”定"
msgid "Error parsing CSV file. Please make sure it has"
-msgstr ""
+msgstr "解æžCSV文件时出错。请确认它是å¦åŒ…å«"
msgid "Error rendering markdown preview"
msgstr "渲染Markdown预览时出错"
@@ -10937,9 +11282,18 @@ msgstr "Akismet 错误。请检查日志以获å–更多信æ¯ã€‚"
msgid "Error: %{error_message}"
msgstr "错误: %{error_message}"
+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 "å¯ç”¨"
@@ -10971,7 +11325,7 @@ msgid "Errors"
msgstr "错误"
msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
-msgstr ""
+msgstr "在第%{line_number}行中å‘现错误: %{error_lines}。请检查这些行是å¦åŒ…å«æ‰€éœ€çš„标题。"
msgid "Errors:"
msgstr "错误:"
@@ -11054,23 +11408,23 @@ 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 "使用Gatsby创建GitLab Pages网站所需的一切。"
+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 "使用GitBook创建GitLab Pages站点所需的一切。"
+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 "使用Hexo创建GitLab Pages站点所需的一切。"
+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 "使用Hugo创建GitLab Pages站点所需的一切。"
+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 "使用Jekyll创建GitLab Pages站点所需的一切。"
+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 "使用纯HTML创建GitLab Pages网站所需的一切。"
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
msgid "Evidence collection"
msgstr "凭è¯é›†"
@@ -11079,7 +11433,7 @@ msgid "Exactly one of %{attributes} is required"
msgstr "其中的一个%{attributes}是必需的"
msgid "Example: %{ip_address}. %{read_more_link}."
-msgstr ""
+msgstr "示例: %{ip_address}. %{read_more_link}."
msgid "Example: @sub\\.company\\.com$"
msgstr "示例: @sub\\.company\\.com$"
@@ -11094,7 +11448,7 @@ msgid "Except policy:"
msgstr "除外(Except)æ¡ä»¶ï¼š"
msgid "Excess storage"
-msgstr ""
+msgstr "超é¢å­˜å‚¨"
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™%{limit}次æ交。"
@@ -11103,13 +11457,10 @@ msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™6,000次æ交。"
msgid "Execution time"
-msgstr ""
+msgstr "执行时间"
msgid "Existing branch name, tag, or commit SHA"
-msgstr ""
-
-msgid "Existing members and groups"
-msgstr "当å‰æˆå‘˜å’Œç¾¤ç»„"
+msgstr "已存在分支å称,标记或æ交SHA"
msgid "Existing projects may be moved into a group"
msgstr "现有项目å¯èƒ½ä¼šè¢«ç§»åŠ¨åˆ°ç¾¤ç»„"
@@ -11127,16 +11478,16 @@ msgid "Expand all"
msgstr "展开全部"
msgid "Expand all files"
-msgstr ""
+msgstr "展开所有文件"
msgid "Expand all threads"
-msgstr ""
+msgstr "展开所有主题"
msgid "Expand approvers"
msgstr "展开核准人"
msgid "Expand file"
-msgstr ""
+msgstr "展开文件"
msgid "Expand milestones"
msgstr "展开里程碑"
@@ -11150,6 +11501,9 @@ msgstr "需è¦çš„文档: %{expected_documents}"
msgid "Experienced"
msgstr "有ç»éªŒçš„"
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr "过期时间"
@@ -11208,7 +11562,7 @@ msgid "Export as CSV"
msgstr "导出为 CSV"
msgid "Export commit custody report"
-msgstr ""
+msgstr "导出æ交监管报告"
msgid "Export group"
msgstr "导出群组"
@@ -11217,7 +11571,7 @@ msgid "Export issues"
msgstr "导出议题"
msgid "Export merge requests"
-msgstr ""
+msgstr "导出åˆå¹¶è¯·æ±‚"
msgid "Export project"
msgstr "导出项目"
@@ -11291,6 +11645,9 @@ msgstr "无法添加Zoom会议"
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 "由于未找到用户,因此无法指派用户。"
@@ -11309,23 +11666,29 @@ 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 ""
+msgstr "无法为设计创建待办事项。"
msgid "Failed to create a branch for this issue. Please try again."
msgstr "无法为此问题创建分支。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Failed to create framework"
-msgstr ""
+msgstr "创建框架失败"
msgid "Failed to create import label for jira import."
msgstr "为jira导入创建导入标签失败。"
msgid "Failed to create new project access token: %{token_response_message}"
-msgstr ""
+msgstr "创建新项目访问令牌失败: %{token_response_message}"
msgid "Failed to create repository"
msgstr "创建仓库失败"
@@ -11336,9 +11699,6 @@ msgstr "创建资æºå¤±è´¥"
msgid "Failed to create wiki"
msgstr "创建Wiki失败"
-msgid "Failed to delete board. Please try again."
-msgstr "删除看æ¿å¤±è´¥ã€‚请é‡è¯•ã€‚"
-
msgid "Failed to deploy to"
msgstr "无法部署到"
@@ -11361,10 +11721,10 @@ msgid "Failed to load authors. Please try again."
msgstr "加载作者失败。请é‡è¯•ã€‚"
msgid "Failed to load branches. Please try again."
-msgstr ""
+msgstr "加载分支失败。请é‡è¯•ã€‚"
msgid "Failed to load deploy keys."
-msgstr ""
+msgstr "加载部署密钥失败。"
msgid "Failed to load emoji list."
msgstr "无法加载表情列表。"
@@ -11382,7 +11742,7 @@ msgid "Failed to load groups & users."
msgstr "加载群组和用户失败。"
msgid "Failed to load groups, users and deploy keys."
-msgstr ""
+msgstr "无法加载群组,用户和部署密钥。"
msgid "Failed to load labels. Please try again."
msgstr "加载标记失败。请é‡è¯•ã€‚"
@@ -11391,22 +11751,22 @@ msgid "Failed to load milestones. Please try again."
msgstr "加载里程碑失败。请é‡è¯•ã€‚"
msgid "Failed to load projects"
-msgstr ""
+msgstr "加载项目失败"
msgid "Failed to load related branches"
msgstr "加载相关分支失败"
msgid "Failed to load sidebar confidential toggle"
-msgstr ""
+msgstr "加载侧边æ æœºå¯†å¼€å…³å¤±è´¥"
msgid "Failed to load sidebar lock status"
-msgstr ""
+msgstr "加载侧边æ é”状æ€å¤±è´¥"
msgid "Failed to load stacktrace."
msgstr "加载堆栈跟踪失败。"
msgid "Failed to make repository read-only. %{reason}"
-msgstr ""
+msgstr "无法将存储库设为åªè¯»ã€‚ %{reason}"
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "无法将此议题标记为é‡å¤ï¼Œå› ä¸ºæœªæ‰¾åˆ°å¼•ç”¨çš„议题。"
@@ -11433,7 +11793,7 @@ msgid "Failed to publish issue on status page."
msgstr "在状æ€é¡µä¸Šå‘布议题失败。"
msgid "Failed to remove To-Do for the design."
-msgstr ""
+msgstr "无法删除设计的待办事项。"
msgid "Failed to remove a Zoom meeting"
msgstr "无法删除Zoom会议"
@@ -11457,7 +11817,7 @@ msgid "Failed to reset key. Please try again."
msgstr "é‡ç½®å¯†é’¥å¤±è´¥ã€‚请é‡è¯•ã€‚"
msgid "Failed to retrieve page"
-msgstr ""
+msgstr "获å–页é¢å¤±è´¥"
msgid "Failed to save merge conflicts resolutions. Please try again!"
msgstr "ä¿å­˜åˆå¹¶å†²çªè§£å†³åŠžæ³•å¤±è´¥ã€‚请é‡è¯•ï¼"
@@ -11481,7 +11841,7 @@ msgid "Failed to signing using smartcard authentication"
msgstr "无法使用智能å¡èº«ä»½éªŒè¯è¿›è¡Œç™»å½•"
msgid "Failed to toggle To-Do for the design."
-msgstr ""
+msgstr "无法为开关设计的待办事项。"
msgid "Failed to update branch!"
msgstr "更新分支失败ï¼"
@@ -11489,6 +11849,9 @@ msgstr "更新分支失败ï¼"
msgid "Failed to update environment!"
msgstr "更新环境失败ï¼"
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr "更新议题状æ€å¤±è´¥"
@@ -11499,7 +11862,7 @@ msgid "Failed to update tag!"
msgstr "更新标签失败ï¼"
msgid "Failed to update the Canary Ingress."
-msgstr ""
+msgstr "无法更新Canary Ingress。"
msgid "Failed to update."
msgstr "更新失败。"
@@ -11541,7 +11904,7 @@ msgid "Feature Flags"
msgstr "功能标志"
msgid "Feature flag is not enabled on the environment's project."
-msgstr ""
+msgstr "此环境所属项目上没有å¯ç”¨åŠŸèƒ½æ ‡è®°ã€‚"
msgid "Feature flag was not removed."
msgstr "功能标志未被删除。"
@@ -11549,24 +11912,21 @@ msgstr "功能标志未被删除。"
msgid "Feature flag was successfully removed."
msgstr "功能标志已æˆåŠŸåˆ é™¤ã€‚"
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] "%d个用户"
msgid "FeatureFlags|%{percent} by available ID"
-msgstr ""
+msgstr "按å¯ç”¨ID%{percent}"
msgid "FeatureFlags|%{percent} by session ID"
-msgstr ""
+msgstr "按会è¯ID%{percent}"
msgid "FeatureFlags|%{percent} by user ID"
-msgstr ""
+msgstr "按用户ID%{percent}"
msgid "FeatureFlags|%{percent} randomly"
-msgstr ""
+msgstr "éšæœº%{percent}"
msgid "FeatureFlags|* (All Environments)"
msgstr "*(所有环境)"
@@ -11599,7 +11959,7 @@ msgid "FeatureFlags|Configure feature flags"
msgstr "é…置功能标志"
msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
-msgstr ""
+msgstr "请考虑使用更çµæ´»çš„“百分比上线â€ç­–略。"
msgid "FeatureFlags|Create feature flag"
msgstr "创建功能标志"
@@ -11620,7 +11980,7 @@ msgid "FeatureFlags|Edit User List"
msgstr "编辑用户列表"
msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
-msgstr ""
+msgstr "通过é…置功能标志策略,为特定用户和环境å¯ç”¨åŠŸèƒ½ã€‚"
msgid "FeatureFlags|Environment Spec"
msgstr "环境规格"
@@ -11643,9 +12003,6 @@ msgstr "功能标志无策略"
msgid "FeatureFlags|Feature Flags"
msgstr "功能标志"
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr "下一个里程碑中功能标志将有所å˜åŒ–。您ä¸éœ€åšä»»ä½•è°ƒæ•´ï¼Œä½†å°†ä¼šæ³¨æ„到功能å˜åŒ–对工作æµç¨‹çš„改善。"
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "功能标志 %{name} 将被删除。您确定å—?"
@@ -11653,22 +12010,19 @@ msgid "FeatureFlags|Feature flags allow you to configure your code into differen
msgstr "功能标志å…许通过动æ€åˆ‡æ¢æŸäº›åŠŸèƒ½ä½¿åº”用呈现ä¸åŒç‰¹æ€§ã€‚"
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
-msgstr ""
-
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr "标志å³å°†å˜ä¸ºåªè¯»"
+msgstr "功能标志已达到上é™(%{featureFlagsLimit})。在添加新功能标志之å‰åˆ é™¤ä¸€ä¸ªæˆ–多个现有的功能标记。"
msgid "FeatureFlags|Flag is read-only"
-msgstr ""
+msgstr "标记为åªè¯»"
msgid "FeatureFlags|Get started with feature flags"
msgstr "功能标志入门"
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
-msgstr "GitLab正在转å‘到新的功能标志管ç†æ–¹å¼ï¼Œæ­¤åŠŸèƒ½æ ‡å¿—将在13.4中å˜ä¸ºåªè¯»ã€‚请创建一个新的功能标识。"
+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 ""
+msgstr "GitLab正在转å‘到新的功能标志管ç†æ–¹å¼ï¼Œæ­¤åŠŸèƒ½æ ‡å¿—当å‰ä¸ºåªè¯»å¹¶å°†äºŽ14.0中删除。请创建一个新的功能标识。"
msgid "FeatureFlags|ID"
msgstr "ID"
@@ -11683,7 +12037,7 @@ msgid "FeatureFlags|Include additional user IDs"
msgstr "包括其他用户ID"
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 ""
+msgstr "安装%{docsLinkAnchoredStart}兼容的客户端库%{docsLinkAnchoredEnd} ,并在é…置中指定API URLã€åº”用程åºå称和实例ID。%{docsLinkStart}更多信æ¯%{docsLinkEnd}"
msgid "FeatureFlags|Instance ID"
msgstr "实例ID"
@@ -11695,7 +12049,7 @@ msgid "FeatureFlags|Loading feature flags"
msgstr "加载功能标志"
msgid "FeatureFlags|Loading user lists"
-msgstr ""
+msgstr "正在加载用户列表"
msgid "FeatureFlags|More information"
msgstr "更多信æ¯"
@@ -11716,22 +12070,22 @@ msgid "FeatureFlags|New feature flag"
msgstr "新建功能标志"
msgid "FeatureFlags|New user list"
-msgstr ""
+msgstr "新建用户列表"
msgid "FeatureFlags|No user list selected"
-msgstr ""
+msgstr "未选择用户列表"
msgid "FeatureFlags|Percent of users"
msgstr "用户百分比"
msgid "FeatureFlags|Percent rollout"
-msgstr ""
+msgstr "百分比上线"
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "百分比上线(登录用户)"
msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
-msgstr ""
+msgstr "百分比上线必须是0-100之间的整数"
msgid "FeatureFlags|Protected"
msgstr "å—ä¿æŠ¤"
@@ -11761,10 +12115,10 @@ msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr "获å–功能标志时出错。"
msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
+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 ""
+msgstr "为了防止误æ“作,我们需è¦æ‚¨å†æ¬¡ç¡®è®¤ã€‚请输入%{projectName}继续或关闭此对è¯æ¡†ä»¥å–消。"
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "请ç¨åŽé‡è¯•æˆ–è”系支æŒå›¢é˜Ÿã€‚"
@@ -11776,6 +12130,9 @@ 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"
@@ -11785,7 +12142,7 @@ msgid "FeatureFlag|Select a user list"
msgstr "选择一个用户列表"
msgid "FeatureFlag|Select the environment scope for this feature flag"
-msgstr ""
+msgstr "选择应用此功能标志的环境范围"
msgid "FeatureFlag|There are no configured user lists"
msgstr "没有é…置的用户列表"
@@ -11797,7 +12154,7 @@ msgid "FeatureFlag|User IDs"
msgstr "用户ID"
msgid "FeatureFlag|User List"
-msgstr ""
+msgstr "用户列表"
msgid "Feb"
msgstr "2月"
@@ -11806,7 +12163,7 @@ msgid "February"
msgstr "2月"
msgid "Fetch and check out the branch for this merge request"
-msgstr ""
+msgstr "获å–并查看此åˆå¹¶è¯·æ±‚的分支"
msgid "Fetching incoming email"
msgstr "获å–接收邮件地å€"
@@ -11815,7 +12172,7 @@ msgid "File"
msgstr "文件"
msgid "File %{current} of %{total}"
-msgstr ""
+msgstr "文件%{current},总计%{total}"
msgid "File Hooks"
msgstr "文件钩å­"
@@ -11851,7 +12208,7 @@ msgid "File renamed with no changes."
msgstr "文件已é‡å‘½å,但无更改。"
msgid "File synchronization concurrency limit"
-msgstr ""
+msgstr "文件åŒæ­¥å¹¶å‘é™åˆ¶"
msgid "File templates"
msgstr "文件模æ¿"
@@ -11860,7 +12217,7 @@ msgid "File upload error."
msgstr "文件上传错误。"
msgid "Filename"
-msgstr ""
+msgstr "文件å"
msgid "Files"
msgstr "文件"
@@ -11869,7 +12226,7 @@ msgid "Files breadcrumb"
msgstr "文件导航"
msgid "Files with large changes are collapsed by default."
-msgstr ""
+msgstr "具有较大更改的文件默认情况下是折å çš„。"
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
msgstr "æ交引用%{ref}路径%{path}中的文件,目录和å­æ¨¡å—"
@@ -11880,6 +12237,9 @@ msgstr "填写以下字段,开å¯%{strong_open}对此组å¯ç”¨SAML身份验è¯
msgid "Filter"
msgstr "筛选器"
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "筛选器%{issuable_type}当å‰å…³é—­ã€‚"
@@ -11896,7 +12256,7 @@ msgid "Filter by issues that are currently closed."
msgstr "按当å‰å…³é—­çš„议题筛选。"
msgid "Filter by issues that are currently opened."
-msgstr ""
+msgstr "按当å‰å¼€å¯çš„议题筛选。"
msgid "Filter by label"
msgstr "按标记筛选"
@@ -11913,20 +12273,14 @@ msgstr "按里程碑å称筛选"
msgid "Filter by name"
msgstr "按å称筛选"
-msgid "Filter by requirements that are currently archived."
-msgstr "按当å‰å·²å­˜æ¡£çš„需求筛选。"
-
-msgid "Filter by requirements that are currently opened."
-msgstr "按当å‰å¼€æ”¾çš„需求筛选。"
-
msgid "Filter by status"
msgstr "按状æ€ç­›é€‰"
msgid "Filter by test cases that are currently archived."
-msgstr ""
+msgstr "按当å‰å·²å½’档的测试用例筛选。"
msgid "Filter by test cases that are currently opened."
-msgstr ""
+msgstr "按当å‰å¼€å¯ä¸­çš„测试用例筛选。"
msgid "Filter by two-factor authentication"
msgstr "按åŒé‡è®¤è¯ç­›é€‰"
@@ -11935,7 +12289,7 @@ msgid "Filter by user"
msgstr "按用户筛选"
msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
-msgstr ""
+msgstr "筛选å‚数无效。请确ä¿ç»“æŸæ—¥æœŸåœ¨å¼€å§‹æ—¥æœŸä¹‹åŽã€‚"
msgid "Filter pipelines"
msgstr "筛选æµæ°´çº¿"
@@ -11953,7 +12307,7 @@ msgid "Filter results..."
msgstr "筛选结果..."
msgid "Filter your repositories by name"
-msgstr ""
+msgstr "按å称筛选您的仓库"
msgid "Filter..."
msgstr "筛选..."
@@ -11962,17 +12316,14 @@ msgid "Find File"
msgstr "查找文件"
msgid "Find bugs in your code with API fuzzing."
-msgstr ""
+msgstr "使用API模糊测试在代ç ä¸­æŸ¥æ‰¾é”™è¯¯ã€‚"
msgid "Find bugs in your code with coverage-guided fuzzing."
-msgstr ""
+msgstr "通过覆盖率指导的模糊测试在代ç ä¸­æŸ¥æ‰¾é”™è¯¯ã€‚"
msgid "Find by path"
msgstr "按路径查找"
-msgid "Find existing members by name"
-msgstr "按å称查找现有æˆå‘˜"
-
msgid "Find file"
msgstr "查找文件"
@@ -11991,6 +12342,9 @@ msgstr "完æˆæ‚¨çš„%{group_name}专用å¸æˆ·è®¾ç½®ã€‚"
msgid "Finished"
msgstr "已完æˆ"
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr "首次出现"
@@ -12004,7 +12358,7 @@ msgid "First seen"
msgstr "首次出现"
msgid "Fixed burndown chart"
-msgstr ""
+msgstr "固定燃尽图"
msgid "Fixed date"
msgstr "固定日期"
@@ -12052,19 +12406,19 @@ msgid "Footer message"
msgstr "页脚消æ¯"
msgid "For a faster browsing experience, some files are collapsed by default."
-msgstr ""
+msgstr "为了更快的æµè§ˆä½“验,一些文件默认会被折å ã€‚"
msgid "For help setting up the Service Desk for your instance, please contact an administrator."
-msgstr ""
+msgstr "如需帮助为您的实例设置æœåŠ¡å°ï¼Œè¯·è”系管ç†å‘˜ã€‚"
msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
+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 ""
+msgstr "有关如何计算活跃用户数的更多信æ¯ï¼Œè¯·å‚è§æ–‡æ¡£ %{self_managed_subscriptions_doc_link}。"
msgid "For more information, go to the "
msgstr "如需了解详细信æ¯ï¼Œè¯·å‚阅"
@@ -12120,9 +12474,6 @@ msgstr "派生"
msgid "Format: %{dateFormat}"
msgstr "æ ¼å¼ï¼š%{dateFormat}"
-msgid "Forward external support email address to"
-msgstr "转å‘外部支æŒç”µå­é‚®ä»¶åœ°å€åˆ°"
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "在您的 %{gitlab_ci_yml} 中找到错误:"
@@ -12130,7 +12481,7 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "在.gitlab-ci.yml中å‘现错误:"
msgid "Framework successfully deleted"
-msgstr ""
+msgstr "框架删除æˆåŠŸ"
msgid "Free Trial"
msgstr "å…费试用"
@@ -12205,7 +12556,7 @@ msgid "Generate new token"
msgstr "生æˆæ–°çš„令牌"
msgid "Generic package file size in bytes"
-msgstr ""
+msgstr "通用文件包大å°ï¼ˆå­—节)"
msgid "Geo"
msgstr "Geo"
@@ -12352,10 +12703,10 @@ msgid "GeoNodes|secondary nodes"
msgstr "次è¦èŠ‚点"
msgid "Geo|%{itemTitle} checksum progress"
-msgstr ""
+msgstr "%{itemTitle}校验和进度"
msgid "Geo|%{itemTitle} verification progress"
-msgstr ""
+msgstr "%{itemTitle}验è¯è¿›åº¦"
msgid "Geo|%{label} can't be blank"
msgstr "%{label}ä¸èƒ½ä¸ºç©º"
@@ -12421,10 +12772,10 @@ msgid "Geo|Geo Status"
msgstr "Geo状æ€"
msgid "Geo|Go to the primary site"
-msgstr ""
+msgstr "转到主站点"
msgid "Geo|If you want to make changes, you must visit the primary site."
-msgstr ""
+msgstr "如需进行å˜æ›´ï¼Œå¿…须访问主站点。"
msgid "Geo|In progress"
msgstr "进行中"
@@ -12469,7 +12820,7 @@ msgid "Geo|Please refer to Geo Troubleshooting."
msgstr "请å‚阅 Geo 疑难解答。"
msgid "Geo|Primary node"
-msgstr ""
+msgstr "主节点"
msgid "Geo|Project"
msgstr "项目"
@@ -12514,7 +12865,7 @@ msgid "Geo|Review replication status, and resynchronize and reverify items with
msgstr "查看å¤åˆ¶çŠ¶æ€å¹¶ä¸Žä¸»è¦èŠ‚点é‡æ–°åŒæ­¥å’Œé‡æ–°éªŒè¯é¡¹ç›®ã€‚"
msgid "Geo|Secondary node"
-msgstr ""
+msgstr "次节点"
msgid "Geo|Status"
msgstr "状æ€"
@@ -12556,7 +12907,7 @@ msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
msgstr "URL必须是有效的url(例如:https://gitlab.com)"
msgid "Geo|Undefined"
-msgstr ""
+msgstr "未定义"
msgid "Geo|Unknown state"
msgstr "未知状æ€"
@@ -12568,10 +12919,10 @@ msgid "Geo|Waiting for scheduler"
msgstr "等待调度"
msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
-msgstr ""
+msgstr "当å‰å¤„于一个次è¦ï¼Œ%{b_open}åªè¯»çš„%{b_close}Geo节点。"
msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨æ­¤é¡µé¢ä¸Šè¿›è¡Œæœ‰é™çš„更改或执行有é™çš„æ“作。"
msgid "Geo|misconfigured"
msgstr "é…置错误"
@@ -12588,6 +12939,12 @@ 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 "开始使用错误跟踪"
@@ -12604,7 +12961,7 @@ msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "æ­¤ GitLab æœåŠ¡å™¨ä¸Šæœªå¯ç”¨ Git LFS,请è”系管ç†å‘˜ã€‚"
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 ""
+msgstr "如果%{docs_link_start}为项目å¯ç”¨%{docs_link_end}了LFS,则Git LFS对象将会åŒæ­¥ã€‚ 推é€é•œåƒ%{strong_open}无法%{strong_close}通过SSHåŒæ­¥LFS对象。"
msgid "Git LFS status:"
msgstr "Git LFS状æ€ï¼š"
@@ -12625,7 +12982,7 @@ msgid "Git strategy for pipelines"
msgstr "æµæ°´çº¿çš„Gitç­–ç•¥"
msgid "Git transfer in progress"
-msgstr ""
+msgstr "Git传输正在进行中"
msgid "Git version"
msgstr "Git 版本"
@@ -12637,19 +12994,19 @@ msgid "GitHub import"
msgstr "GitHub导入"
msgid "GitLab"
-msgstr ""
+msgstr "GitLab"
msgid "GitLab / Unsubscribe"
msgstr "å–消订阅"
msgid "GitLab API"
-msgstr ""
+msgstr "GitLab API"
msgid "GitLab Account Request"
-msgstr ""
+msgstr "GitLabå¸æˆ·åˆ›å»ºè¯·æ±‚"
msgid "GitLab Billing Team."
-msgstr ""
+msgstr "GitLab计费团队。"
msgid "GitLab Group Runners can execute code for all the projects in this group."
msgstr "Gitlab群组Runnerå¯ä»¥ç”¨æ¥è¿è¡Œç¾¤ç»„内所有项目的代ç ã€‚"
@@ -12661,13 +13018,10 @@ msgid "GitLab Issue"
msgstr "GitLab议题"
msgid "GitLab Pages"
-msgstr ""
-
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr "GitLabæœåŠ¡å°èƒ½å¤Ÿä»¥ç®€å•çš„æ–¹å¼è®©ç”¨æˆ·åœ¨æ‚¨çš„GitLab实例中创建议题,而无需创建账å·ã€‚它为最终用户æ供了在项目中创建问题的唯一电å­é‚®ä»¶åœ°å€ï¼Œå¹¶ä¸”å¯ä»¥é€šè¿‡GitLabç•Œé¢æˆ–通过电å­é‚®ä»¶è¿›è¡Œç­”å¤ã€‚最终用户将仅通过电å­é‚®ä»¶çœ‹åˆ°è¯¥ä¸»é¢˜ã€‚"
+msgstr "GitLab Pages"
msgid "GitLab Shell"
-msgstr ""
+msgstr "GitLab Shell"
msgid "GitLab Support Bot"
msgstr "GitLab支æŒæœºå™¨äºº"
@@ -12679,10 +13033,10 @@ msgid "GitLab User"
msgstr "GitLab用户"
msgid "GitLab Workhorse"
-msgstr ""
+msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
-msgstr ""
+msgstr "GitLabå¸æˆ·è¯·æ±‚被拒ç»"
msgid "GitLab commit"
msgstr "GitLabæ交"
@@ -12694,10 +13048,10 @@ msgid "GitLab for Slack"
msgstr "GitLab for Slack"
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
-msgstr ""
+msgstr "GitLab是一个完整的DevOpså¹³å°ï¼Œä½œä¸ºå•ä¸ªåº”用程åºå‘ˆçŽ°ï¼Œä»Žæ ¹æœ¬ä¸Šæ”¹å˜äº†å¼€å‘,安全和è¿ç»´å›¢é˜Ÿçš„å作方å¼"
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 ""
+msgstr "GitLab是一个完整的DevOpså¹³å°ï¼Œä½œä¸ºå•ä¸ªåº”用程åºå‘ˆçŽ°ï¼Œä»Žæ ¹æœ¬ä¸Šæ”¹å˜äº†%{br_tag}å¼€å‘,安全和è¿ç»´å›¢é˜Ÿçš„å作方å¼"
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 "GitLab是æœåŠ¡äºŽæ•´ä¸ªè½¯ä»¶å¼€å‘生命周期的å•ä¸€åº”用程åºã€‚从项目规划和æºç ç®¡ç†åˆ°CI/CDã€ç›‘控和安全。"
@@ -12772,7 +13126,7 @@ msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr "强制HTTPS (需è¦æœ‰æ•ˆçš„è¯ä¹¦)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
-msgstr ""
+msgstr "GitLab Pages在此项目中ç¦ç”¨ã€‚您å¯ä»¥åœ¨æ‚¨çš„项目的%{strong_start}设置 &gt; 常规 &gt; å¯è§æ€§%{strong_end}页é¢å¯ç”¨ã€‚"
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "首次部署åŽï¼Œç«™ç‚¹å¯èƒ½éœ€è¦è‡³å¤š30分钟æ‰å¯ç”¨ã€‚"
@@ -12856,19 +13210,19 @@ msgid "Gitlab Pages"
msgstr "GitLab Pages"
msgid "Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
+msgstr "添加用æ¥è¯»å–GitLab项目的Gitpod网å€"
msgid "Gitpod|Enable Gitpod integration"
-msgstr ""
+msgstr "å¯ç”¨Gitpod集æˆ"
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "Gitpod网å€"
msgid "Gitpod|e.g. https://gitpod.example.com"
-msgstr ""
+msgstr "例如:https://gitpod.example.com"
msgid "Given access %{time_ago}"
msgstr "%{time_ago}授æƒè®¿é—®"
@@ -12885,8 +13239,8 @@ msgstr "全局通知设置"
msgid "Go Back"
msgstr "返回"
-msgid "Go Micro is a framework for micro service development."
-msgstr "Go Micro是一个微æœåŠ¡å¼€å‘的框架。"
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
msgid "Go back"
msgstr "返回"
@@ -12895,16 +13249,16 @@ 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 ""
+msgstr "返回%{tagStart}å¼€å¯çš„议题%{tagEnd}并选择è¦æ·»åŠ åˆ°çœ‹æ¿çš„议题。"
msgid "Go full screen"
msgstr "å…¨å±æ¨¡å¼"
msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
-msgstr ""
+msgstr "转至%{strongStart}议题%{strongEnd} &gt; %{strongStart}看æ¿%{strongEnd}æ¥è®¿é—®æ‚¨çš„个性化学习议题看æ¿ã€‚"
msgid "Go to Integrations"
-msgstr ""
+msgstr "转到集æˆ"
msgid "Go to Webhooks"
msgstr "转到Webhooks"
@@ -13009,7 +13363,7 @@ msgid "Go to your snippets"
msgstr "转到您的代ç ç‰‡æ®µ"
msgid "Goal of the changes and what reviewers should be aware of"
-msgstr ""
+msgstr "å˜æ›´çš„目的以åŠè¯„审人员应注æ„的事项。"
msgid "Google Cloud Platform"
msgstr "谷歌云平å°"
@@ -13111,10 +13465,7 @@ msgid "Group avatar"
msgstr "群组头åƒ"
msgid "Group by"
-msgstr ""
-
-msgid "Group description"
-msgstr "群组æè¿°"
+msgstr "分组方å¼"
msgid "Group description (optional)"
msgstr "群组æ述(å¯é€‰ï¼‰"
@@ -13183,7 +13534,7 @@ msgid "Group project URLs are prefixed with the group namespace"
msgstr "群组项目的URL以群组命å空间为å‰ç¼€"
msgid "Group push rule exists, try updating"
-msgstr ""
+msgstr "群组推é€è§„则已存在,请å°è¯•æ›´æ–°"
msgid "Group requires separate account"
msgstr "群组需è¦å•ç‹¬è´¦æˆ·"
@@ -13249,10 +13600,10 @@ msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "无开始日期 - %{dateWord}"
msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
+msgstr "路线图最多å¯ä»¥æ˜¾ç¤º1,000个å²è¯—。这些按您选择的排åºé¡ºåºæ˜¾ç¤ºã€‚"
msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
+msgstr "您的一些å²è¯—å¯èƒ½ä¸å¯è§"
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "è¯»å– å²è¯— 时出错"
@@ -13276,10 +13627,10 @@ msgid "GroupRoadmap|To widen your search, change or remove filters; from %{start
msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢ï¼Œè¯·æ›´æ”¹æˆ–移除筛选器,从 %{startDate} 到 %{endDate}。"
msgid "GroupSAML|Active SAML Group Links (%{count})"
-msgstr ""
+msgstr "å¯ç”¨çš„SAML群组链接(%{count})"
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
-msgstr ""
+msgstr "您确定è¦åˆ é™¤SAML群组链接å—?"
msgid "GroupSAML|Certificate fingerprint"
msgstr "è¯ä¹¦æŒ‡çº¹"
@@ -13291,7 +13642,7 @@ msgid "GroupSAML|Copy SAML Response XML"
msgstr "å¤åˆ¶SAMLå“应XML"
msgid "GroupSAML|Could not create SAML group link: %{errors}."
-msgstr ""
+msgstr "无法创建SAML群组链接:%{errors}"
msgid "GroupSAML|Default membership role"
msgstr "默认æˆå‘˜è§’色"
@@ -13339,10 +13690,10 @@ msgid "GroupSAML|NameID Format"
msgstr "NameIDæ ¼å¼"
msgid "GroupSAML|New SAML group link saved."
-msgstr ""
+msgstr "æ–°çš„SAML群组链接已ä¿å­˜"
msgid "GroupSAML|No active SAML group links"
-msgstr ""
+msgstr "没有å¯ç”¨çš„SAML群组链接"
msgid "GroupSAML|Prohibit outer forks"
msgstr "ç¦æ­¢å¤–部派生"
@@ -13351,16 +13702,16 @@ 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 ""
+msgstr "SAML群组链接"
msgid "GroupSAML|SAML Group Name"
-msgstr ""
+msgstr "SAML群组å称"
msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
-msgstr ""
+msgstr "SAML群组å称: %{saml_group_name}"
msgid "GroupSAML|SAML Response Output"
msgstr "SAMLå“应输出"
@@ -13375,7 +13726,7 @@ msgid "GroupSAML|SAML Single Sign On Settings"
msgstr "SAML å•ç‚¹ç™»å½•è®¾ç½®"
msgid "GroupSAML|SAML group link was successfully removed."
-msgstr ""
+msgstr "SAML群组链接已æˆåŠŸåˆ é™¤ã€‚"
msgid "GroupSAML|SCIM API endpoint URL"
msgstr "SCIM API 端点 URL"
@@ -13390,7 +13741,7 @@ msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token aga
msgstr "SCIM 令牌现在已éšè—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œçš„å€¼ï¼Œæ‚¨éœ€è¦ "
msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
-msgstr ""
+msgstr "将由 SAML 身份æ供商å‘é€çš„群组å称,区分大å°å†™ã€‚"
msgid "GroupSAML|This will be set as the access level of users added to the group."
msgstr "这将被设置为添加到群组的用户的访问级别。"
@@ -13417,7 +13768,7 @@ msgid "GroupSAML|Your SCIM token"
msgstr "您的 SCIM 令牌"
msgid "GroupSAML|as %{access_level}"
-msgstr ""
+msgstr "以%{access_level}身份"
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 "必须匹é…“%{extern_uid}â€å­˜å‚¨çš„NameID,因为它用æ¥æ ‡è¯†ç”¨æˆ·ã€‚如果NameID更改,则用户将无法登录。"
@@ -13449,11 +13800,17 @@ msgstr "更改群组URL"
msgid "GroupSettings|Changing group URL can have unintended side effects."
msgstr "更改群组URLå¯èƒ½ä¼šæœ‰æ„想ä¸åˆ°çš„副作用。"
+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 your group badges."
-msgstr "自定义群组徽章。"
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr "默认为此群组中所有项目的 Auto DevOps æµæ°´çº¿"
@@ -13476,9 +13833,6 @@ msgstr "如果新父群组的å¯è§æ€§ä½ŽäºŽå½“å‰ç¾¤ç»„çš„å¯è§æ€§ï¼Œå­ç¾¤ç»„
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr "在此é…置的集æˆå°†è‡ªåŠ¨é€‚用于此组中的所有项目。"
-msgid "GroupSettings|Learn more about badges."
-msgstr "了解有关徽章的更多信æ¯ã€‚"
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr "了解更多关于群组级项目模æ¿"
@@ -13501,13 +13855,13 @@ msgid "GroupSettings|Prevent sharing a project within %{group} with other groups
msgstr "ç¦æ­¢ä¸Žå…¶ä»–群组共享 %{group} 中的项目"
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
-msgstr ""
+msgstr "项目将于%{waiting_period}天延迟期åŽè¢«æ°¸ä¹…删除。该延迟时间å¯ä»¥åœ¨å®žä¾‹è®¾ç½®ä¸­%{customization_link}。"
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr "选择一个å­ç¾¤ç»„作为此群组的自定义项目模æ¿æºã€‚"
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr "在未找到备用 CI é…置文件时使用 Auto DevOps æµæ°´çº¿ã€‚"
+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 "æ›´æ–° Auto DevOps æµæ°´çº¿æ—¶å‡ºçŽ°é—®é¢˜ï¼š %{error_messages}。"
@@ -13539,6 +13893,9 @@ 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 "您åªèƒ½å°†å½“å‰ç¾¤ç»„转移到您管ç†ä¸‹çš„群组。"
@@ -13617,6 +13974,9 @@ 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 "è”系管ç†å‘˜å¯ç”¨å¯¼å…¥ç¾¤ç»„的选项。"
@@ -13626,23 +13986,47 @@ msgstr "创建"
msgid "GroupsNew|Create group"
msgstr "创建群组"
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
msgid "GroupsNew|Import"
msgstr "导入"
-msgid "GroupsNew|Import a GitLab group export file"
-msgstr ""
-
msgid "GroupsNew|Import group"
msgstr "导入群组"
+msgid "GroupsNew|Import groups from another instance of GitLab"
+msgstr ""
+
msgid "GroupsNew|My Awesome Group"
msgstr "My Awesome Group"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
-msgstr "如需在æœåŠ¡å™¨ä¹‹é—´å¤åˆ¶GitLab群组, 请到原æœåŠ¡å™¨çš„群组设置页é¢, 生æˆå¯¼å‡ºæ–‡ä»¶å¹¶å°†å…¶ä¸Šä¼ åˆ°è¿™é‡Œã€‚"
+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 "您确定è¦é€€å‡ºç¾¤ç»„“%{fullName}â€å—?"
@@ -13708,7 +14092,7 @@ msgid "Health status"
msgstr "å¥åº·çŠ¶æ€"
msgid "Health status cannot be edited because this issue is closed"
-msgstr ""
+msgstr "由于此议题已关闭,因此无法编辑å¥åº·çŠ¶æ€"
msgid "HealthCheck|Access token is"
msgstr "访问令牌为"
@@ -13723,13 +14107,13 @@ msgid "HealthCheck|Unhealthy"
msgstr "éžå¥åº·"
msgid "Hello %{name},"
-msgstr ""
+msgstr "您好 %{name},"
msgid "Hello there"
msgstr "你好"
msgid "Hello, %{username}!"
-msgstr ""
+msgstr "%{username},您好!"
msgid "Help"
msgstr "帮助"
@@ -13769,7 +14153,7 @@ msgid_plural "Hide charts"
msgstr[0] "éšè—图表"
msgid "Hide comments on this file"
-msgstr ""
+msgstr "éšè—对此文件的评论"
msgid "Hide details"
msgstr "éšè—详情"
@@ -13815,16 +14199,16 @@ msgid "Highest role:"
msgstr "顶级角色:"
msgid "HighlightBar|Alert events:"
-msgstr ""
+msgstr "警报事件:"
msgid "HighlightBar|Alert start time:"
-msgstr ""
+msgstr "警报开始时间:"
msgid "HighlightBar|Original alert:"
-msgstr ""
+msgstr "原始警报:"
msgid "HighlightBar|Time to SLA:"
-msgstr ""
+msgstr "è·SLA时间: "
msgid "History"
msgstr "历å²"
@@ -13859,6 +14243,9 @@ msgstr "已开始维护"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "管家,导出,路径,转移,删除,存档。"
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr "工作原ç†"
@@ -13890,7 +14277,7 @@ msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%
msgstr "我已ç»é˜…读并åŒæ„Let's Encryptçš„%{link_start}æœåŠ¡æ¡æ¬¾%{link_end}(PDF)"
msgid "I'd like to receive updates about GitLab via email"
-msgstr ""
+msgstr "我希望通过电å­é‚®ä»¶æŽ¥æ”¶GitLabçš„æ›´æ–°"
msgid "ID"
msgstr "ID"
@@ -13998,10 +14385,10 @@ msgid "If enabled, access to projects will be validated on an external service u
msgstr "如果å¯ç”¨ï¼Œåˆ™ä½¿ç”¨å¤–部æœåŠ¡ä¸Šçš„分类标签æ¥éªŒè¯å¯¹é¡¹ç›®çš„访问æƒé™ã€‚"
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
-msgstr ""
+msgstr "如果YouTube网å€ä¸ºhttps://www.youtube.com/watch?v=0t1DgySidms,则视频ID为%{id}"
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 ""
+msgstr "如果活跃用户数é‡è¶…过了用户é™åˆ¶ï¼Œæ‚¨ä¸‹æ¬¡çš„许å¯è¯å¯¹è´¦æ—¶å°†ä¼šæ”¶å–%{users_over_license_link}个席ä½çš„费用。"
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 "如果之å‰æœªä¸Šä¼ è®¸å¯è¯ï¼Œæˆ–者上一个许å¯è¯å·²è¿‡æœŸï¼Œ 部分GitLab功能将无法使用,直到上传新的有效许å¯è¯ã€‚"
@@ -14016,7 +14403,7 @@ msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commit
msgstr "如使用 GitHub,GitHubçš„æ交(commits)和拉å–请求(pull request) 页é¢å°†æ˜¾ç¤ºæµæ°´çº¿çŠ¶æ€ã€‚ %{more_info_link}"
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 ""
+msgstr "如果将%{codeStart}needs%{codeEnd}加到æµæ°´çº¿çš„作业里é¢ï¼Œæ‚¨å°†å¯ä»¥åœ¨%{linkStart}有å‘无环图 (DAG)%{linkEnd}页é¢çœ‹åˆ°ä½œä¸šä¹‹é—´çš„%{codeStart}needs%{codeEnd}关系。"
msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
msgstr "å¦‚æžœæ‚¨æœ€è¿‘æ²¡æœ‰ç™»å½•ï¼Œè¯·ç«‹å³ %{password_link_start}更改密ç %{password_link_end}。"
@@ -14033,11 +14420,14 @@ msgstr "如果您最近从上述IP地å€ç™»å½•è¿‡ï¼Œåˆ™å¯ä»¥å¿½ç•¥æ­¤ç”µå­é‚®ä
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr "如果您删除此许å¯ï¼ŒGitLab将会退回上一个许å¯ï¼Œå¦‚果有的è¯ã€‚"
-msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+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 "如果您想è¦é‡æ–°å¯ç”¨åŒé‡èº«ä»½éªŒè¯ï¼Œè¯·è®¿é—®%{two_factor_link}"
+
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
-msgstr ""
+msgstr "如果您想è¦é‡æ–°å¯ç”¨åŒé‡èº«ä»½éªŒè¯ï¼Œè¯·è®¿é—®%{settings_link_to}页é¢ã€‚"
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "如果您的HTTP仓库无法公开访问,需在地å€ä¸­æ·»åŠ å‡­æ®ã€‚"
@@ -14052,7 +14442,7 @@ msgid "Image URL"
msgstr "图片网å€"
msgid "Image details"
-msgstr ""
+msgstr "é•œåƒè¯¦ç»†ä¿¡æ¯"
msgid "ImageDiffViewer|2-up"
msgstr "并列(2-up)"
@@ -14080,11 +14470,11 @@ msgstr "导入"
msgid "Import %d compatible repository"
msgid_plural "Import %d compatible repositories"
-msgstr[0] ""
+msgstr[0] "导入%d个兼容的仓库"
msgid "Import %d repository"
msgid_plural "Import %d repositories"
-msgstr[0] ""
+msgstr[0] "导入%d个仓库"
msgid "Import CSV"
msgstr "导入CSV"
@@ -14104,6 +14494,12 @@ msgstr "导入自"
msgid "Import from Jira"
msgstr "从Jira导入"
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr "正在导入"
@@ -14126,7 +14522,7 @@ msgid "Import project"
msgstr "导入项目"
msgid "Import project from"
-msgstr ""
+msgstr "导入项目自"
msgid "Import project members"
msgstr "导入项目æˆå‘˜"
@@ -14152,6 +14548,9 @@ msgstr "从 GitHub 导入仓库"
msgid "Import repository"
msgstr "导入仓库"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr "导入已由%{importInitiator}å¯åŠ¨"
@@ -14174,7 +14573,7 @@ msgid "ImportButtons|Connect repositories from"
msgstr "用以下方å¼è¿žæŽ¥å‚¨å­˜åº“"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
-msgstr ""
+msgstr "超过%{provider}的速率é™åˆ¶ã€‚请ç¨åŽå†è¯•"
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "ç¦æ­¢çš„导入URL: %{message}"
@@ -14183,7 +14582,7 @@ msgid "ImportProjects|Error importing repository %{project_safe_import_url} into
msgstr "将仓库 %{project_safe_import_url} 导入到 %{project_full_path} 时出错:%{message}"
msgid "ImportProjects|Import repositories"
-msgstr ""
+msgstr "导入仓库"
msgid "ImportProjects|Importing the project failed"
msgstr "导入项目失败"
@@ -14192,13 +14591,13 @@ msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr "导入项目失败: %{reason}"
msgid "ImportProjects|Requesting namespaces failed"
-msgstr ""
+msgstr "请求命å空间失败"
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr "获å–您的%{provider}仓库失败"
msgid "ImportProjects|Select the repositories you want to import"
-msgstr ""
+msgstr "选择您想è¦å¯¼å…¥çš„仓库"
msgid "ImportProjects|The remote data could not be imported."
msgstr "无法导入远程数æ®ã€‚"
@@ -14210,31 +14609,26 @@ msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr "导入项目实时更新失败"
msgid "Imported requirements"
-msgstr ""
-
-msgid "Improve Issue Boards"
-msgstr ""
+msgstr "导入的需求"
-msgid "Improve Issue boards"
-msgstr "增强议题看æ¿"
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "使用 GitLab ä¼ä¸šç‰ˆçš„增强议题看æ¿ã€‚"
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr "使用GitLab Enterprise Edition以获得增强的åˆå¹¶è¯·æ±‚功能和官方客户支æŒã€‚"
-msgid "Improve customer support with GitLab Service Desk."
-msgstr "通过GitLabæœåŠ¡å°æ”¹è¿›å®¢æˆ·æ”¯æŒã€‚"
+msgid "Improve customer support with Service Desk"
+msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "使用GitLabä¼ä¸šç‰ˆå…¨å±€æœç´¢å¸¦æ¥çš„增强æœç´¢åŠŸèƒ½"
msgid "In %{time_to_now}"
msgstr "%{time_to_now}åŽ"
msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
+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}我们希望对您有更多了解。"
@@ -14243,22 +14637,25 @@ msgid "In progress"
msgstr "进行中"
msgid "Incident"
-msgstr ""
+msgstr "事件"
msgid "Incident Management Limits"
msgstr "事件管ç†é™åˆ¶"
-msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgid "Incident template (optional)"
msgstr ""
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr "剩余%{hours}å°æ—¶%{minutes} 分钟"
+
msgid "IncidentManagement|%{minutes} minutes remaining"
-msgstr ""
+msgstr "剩余%{minutes}分钟"
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 ""
+msgstr "å‡çº§ä¸ºäº‹ä»¶çš„所有警报将自动显示在列表中。您也å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„按钮创建新事件。"
msgid "IncidentManagement|Assignees"
msgstr "指派人"
@@ -14270,16 +14667,16 @@ msgid "IncidentManagement|Create incident"
msgstr "创建事件"
msgid "IncidentManagement|Critical - S1"
-msgstr ""
+msgstr "严é‡-S1"
msgid "IncidentManagement|Date created"
msgstr "创建日期"
msgid "IncidentManagement|Display your incidents in a dedicated view"
-msgstr ""
+msgstr "在专用视图中显示您的事件"
msgid "IncidentManagement|High - S2"
-msgstr ""
+msgstr "高-S2"
msgid "IncidentManagement|Incident"
msgstr "事件"
@@ -14288,10 +14685,10 @@ msgid "IncidentManagement|Incidents"
msgstr "事件"
msgid "IncidentManagement|Low - S4"
-msgstr ""
+msgstr "低-S4"
msgid "IncidentManagement|Medium - S3"
-msgstr ""
+msgstr "中-S3"
msgid "IncidentManagement|No incidents to display."
msgstr "没有è¦æ˜¾ç¤ºçš„事件。"
@@ -14306,28 +14703,28 @@ msgid "IncidentManagement|Published to status page"
msgstr "å‘布到状æ€é¡µ"
msgid "IncidentManagement|Severity"
-msgstr ""
+msgstr "严é‡æ€§"
msgid "IncidentManagement|There are no closed incidents"
-msgstr ""
+msgstr "没有已关闭的事件"
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr "显示事件时出错。"
msgid "IncidentManagement|Time to SLA"
-msgstr ""
+msgstr "è·SLA时间"
msgid "IncidentManagement|Unassigned"
msgstr "å–消指派"
msgid "IncidentManagement|Unknown"
-msgstr ""
+msgstr "未知"
msgid "IncidentManagement|Unpublished"
msgstr "未å‘布"
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
-msgstr ""
+msgstr "å¯ç”¨â€è·SLA时间â€å€’计时器"
msgid "IncidentSettings|Alert integration"
msgstr "警报集æˆ"
@@ -14336,7 +14733,7 @@ msgid "IncidentSettings|Grafana integration"
msgstr "Grafana集æˆ"
msgid "IncidentSettings|Incident settings"
-msgstr ""
+msgstr "事件设置"
msgid "IncidentSettings|Incidents"
msgstr "事件"
@@ -14348,43 +14745,43 @@ msgid "IncidentSettings|Set up integrations with external tools to help better m
msgstr "设置外部工具集æˆä»¥æ›´å¥½åœ°ç®¡ç†äº‹ä»¶ã€‚"
msgid "IncidentSettings|Time limit"
-msgstr ""
+msgstr "时间é™åˆ¶"
msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
-msgstr ""
+msgstr "时间é™åˆ¶å¿…须是15分钟的å€æ•°"
msgid "IncidentSettings|Time limit must be a valid number"
-msgstr ""
+msgstr "时间é™åˆ¶å¿…须是有效的数字"
msgid "IncidentSettings|Time limit must be greater than 0"
-msgstr ""
+msgstr "时间é™åˆ¶å¿…须大于 0"
msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥é€‰æ‹©åœ¨äº‹ä»¶é—®é¢˜ä¸Šå¼•å…¥å€’计时器,以更好地跟踪æœåŠ¡çº§åˆ«åè®® (SLA)。 事件å‘生åŽè‡ªåŠ¨å¼€å§‹è®¡æ—¶å™¨ï¼Œå¹¶ä¸ºäº‹ä»¶çš„解决设定时间é™åˆ¶ã€‚ å¯ç”¨åŽï¼Œæ‰€æœ‰æ–°äº‹ä»¶ä¸­éƒ½ä¼šå‡ºçŽ°â€œSLA时间â€å€’计时。"
msgid "IncidentSettings|hours"
-msgstr ""
+msgstr "å°æ—¶"
msgid "IncidentSettings|minutes"
-msgstr ""
+msgstr "分钟"
msgid "Incidents"
-msgstr "事故"
+msgstr "事件"
msgid "Incident|Alert details"
-msgstr ""
+msgstr "警报详情"
msgid "Incident|Summary"
-msgstr ""
+msgstr "摘è¦"
msgid "Incident|There was an issue loading alert data. Please try again."
-msgstr ""
+msgstr "加载警报数æ®æ—¶å‡ºçŽ°é—®é¢˜ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Incident|There was an issue loading incident data. Please try again."
-msgstr ""
+msgstr "加载事件数æ®æ—¶å‡ºçŽ°é—®é¢˜ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr "包括所有用户必须接å—çš„æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–。"
@@ -14404,14 +14801,14 @@ msgstr "如果需è¦ï¼Œè¯·åœ¨URL中包å«ç”¨æˆ·å:%{code_open}https://usernam
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
msgstr "åŒ…å« LFS 对象。它å¯ä»¥æŒ‰ç¾¤ç»„或项目覆盖。 0 表示无é™åˆ¶ã€‚"
-msgid "Includes an MVC structure to help you get started."
-msgstr "包å«ä¸€ä¸ª MVC 结构æ¥å¸®åŠ©æ‚¨å¼€å§‹ã€‚"
+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 "包括一个 MVC 结构,Gemfile,Rakefile,以åŠå…¶ä»–许多æ¥å¸®åŠ©æ‚¨å¼€å§‹ã€‚"
+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 "包括一个MVC 结构,mvw å’Œ pom.xml æ¥å¸®åŠ©æ‚¨å¼€å§‹ã€‚"
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
msgid "Incoming email"
msgstr "接收电å­é‚®ä»¶"
@@ -14425,6 +14822,9 @@ msgstr "设置了ä¸å…¼å®¹çš„选项ï¼"
msgid "Incompatible project"
msgstr "ä¸å…¼å®¹çš„项目"
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr "缩进"
@@ -14432,7 +14832,7 @@ msgid "Index all projects"
msgstr "索引所有项目"
msgid "Index deletion is canceled"
-msgstr ""
+msgstr "索引删除已å–消"
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ— æ ‡è®°çš„作业"
@@ -14444,7 +14844,7 @@ msgid "Information about additional Pages templates and how to install them can
msgstr "其他Pages模æ¿çš„ä¿¡æ¯åŠå®‰è£…指å—å¯ä»¥åœ¨%{pages_getting_started_guide}中找到."
msgid "Inherited"
-msgstr ""
+msgstr "已继承"
msgid "Inherited:"
msgstr "继承:"
@@ -14465,7 +14865,7 @@ msgid "Insert a quote"
msgstr "æ’入引用"
msgid "Insert a video"
-msgstr ""
+msgstr "æ’入视频"
msgid "Insert an image"
msgstr "æ’入图片"
@@ -14474,7 +14874,7 @@ msgid "Insert code"
msgstr "æ’入代ç "
msgid "Insert image"
-msgstr ""
+msgstr "æ’入图片"
msgid "Insert inline code"
msgstr "æ’入内è”代ç "
@@ -14483,7 +14883,7 @@ msgid "Insert suggestion"
msgstr "æ’入建议"
msgid "Insert video"
-msgstr ""
+msgstr "æ’入视频"
msgid "Insights"
msgstr "洞察"
@@ -14510,7 +14910,7 @@ msgid "Install on clusters"
msgstr "在群集上安装"
msgid "Installation"
-msgstr ""
+msgstr "安装"
msgid "Installed"
msgstr "已安装"
@@ -14529,94 +14929,94 @@ msgid "Instance administrators group already exists"
msgstr "实例管ç†å‘˜ç»„已存在"
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
-msgstr ""
+msgstr "无法加载议题与åˆå¹¶è¯·æ±‚图表。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "InstanceStatistics|Could not load the pipelines chart. Please refresh the page to try again."
-msgstr ""
+msgstr "无法加载æµæ°´çº¿ç»Ÿè®¡å›¾è¡¨ã€‚请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
-msgstr ""
+msgstr "无法加载项目和群组图表。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "InstanceStatistics|Groups"
-msgstr ""
+msgstr "群组"
msgid "InstanceStatistics|Issues"
-msgstr ""
+msgstr "议题"
msgid "InstanceStatistics|Issues & Merge Requests"
-msgstr ""
+msgstr "议题与åˆå¹¶è¯·æ±‚"
msgid "InstanceStatistics|Items"
-msgstr ""
+msgstr "项目"
msgid "InstanceStatistics|Merge Requests"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚"
msgid "InstanceStatistics|Month"
-msgstr ""
+msgstr "月"
msgid "InstanceStatistics|No data available."
-msgstr ""
+msgstr "æ— å¯ç”¨æ•°æ®ã€‚"
msgid "InstanceStatistics|Pipelines"
-msgstr ""
+msgstr "æµæ°´çº¿"
msgid "InstanceStatistics|Pipelines canceled"
-msgstr ""
+msgstr "å–消的æµæ°´çº¿"
msgid "InstanceStatistics|Pipelines failed"
-msgstr ""
+msgstr "失败的æµæ°´çº¿"
msgid "InstanceStatistics|Pipelines skipped"
-msgstr ""
+msgstr "跳过的æµæ°´çº¿"
msgid "InstanceStatistics|Pipelines succeeded"
-msgstr ""
+msgstr "æˆåŠŸçš„æµæ°´çº¿"
msgid "InstanceStatistics|Pipelines total"
-msgstr ""
+msgstr "æµæ°´çº¿æ€»æ•°"
msgid "InstanceStatistics|Projects"
-msgstr ""
+msgstr "项目"
msgid "InstanceStatistics|There was an error fetching the cancelled pipelines"
-msgstr ""
+msgstr "获å–å–消的æµæ°´çº¿æ—¶å‡ºé”™"
msgid "InstanceStatistics|There was an error fetching the failed pipelines"
-msgstr ""
+msgstr "获å–失败的æµæ°´çº¿æ—¶å‡ºé”™"
msgid "InstanceStatistics|There was an error fetching the issues"
-msgstr ""
+msgstr "获å–议题时出错"
msgid "InstanceStatistics|There was an error fetching the merge requests"
-msgstr ""
+msgstr "获å–åˆå¹¶è¯·æ±‚时出错"
msgid "InstanceStatistics|There was an error fetching the skipped pipelines"
-msgstr ""
+msgstr "获å–跳过的æµæ°´çº¿æ—¶å‡ºé”™"
msgid "InstanceStatistics|There was an error fetching the successful pipelines"
-msgstr ""
+msgstr "获å–æˆåŠŸçš„æµæ°´çº¿æ—¶å‡ºé”™"
msgid "InstanceStatistics|There was an error fetching the total pipelines"
-msgstr ""
+msgstr "获å–æµæ°´çº¿æ€»æ•°æ—¶å‡ºé”™"
msgid "InstanceStatistics|There was an error while loading the groups"
-msgstr ""
+msgstr "加载群组时出错"
msgid "InstanceStatistics|There was an error while loading the projects"
-msgstr ""
+msgstr "加载项目时出错"
msgid "InstanceStatistics|Total groups"
-msgstr ""
+msgstr "群组总数"
msgid "InstanceStatistics|Total projects"
-msgstr ""
+msgstr "项目总数"
msgid "InstanceStatistics|Total projects & groups"
-msgstr ""
+msgstr "项目和群组总数"
msgid "InstanceStatistics|Users"
-msgstr ""
+msgstr "用户"
msgid "Integration"
msgstr "集æˆ"
@@ -14628,16 +15028,16 @@ msgid "Integrations"
msgstr "集æˆ"
msgid "Integrations|%{integration} settings saved and active."
-msgstr ""
+msgstr "%{integration}设置已ä¿å­˜å¹¶å¯ç”¨ã€‚"
msgid "Integrations|%{integration} settings saved, but not active."
-msgstr ""
+msgstr "%{integration}设置已ä¿å­˜ä½†æœªå¯ç”¨ã€‚"
msgid "Integrations|All details"
msgstr "所有详细信æ¯"
msgid "Integrations|All projects inheriting these settings will also be reset."
-msgstr ""
+msgstr "继承这些设置的所有项目也将被é‡ç½®ã€‚"
msgid "Integrations|Comment detail:"
msgstr "评论细节:"
@@ -14646,19 +15046,19 @@ msgid "Integrations|Comment settings:"
msgstr "评论设置:"
msgid "Integrations|Connection failed. Please check your settings."
-msgstr ""
+msgstr "连接失败。请检查您的设置。"
msgid "Integrations|Connection successful."
-msgstr ""
+msgstr "连接æˆåŠŸã€‚"
msgid "Integrations|Create new issue in Jira"
-msgstr ""
+msgstr "在Jira中创建新议题"
msgid "Integrations|Default settings are inherited from the group level."
-msgstr ""
+msgstr "默认设置继承自群组级别。"
msgid "Integrations|Default settings are inherited from the instance level."
-msgstr ""
+msgstr "默认设置继承自实例级别。"
msgid "Integrations|Enable comments"
msgstr "å¯ç”¨è¯„论"
@@ -14670,61 +15070,67 @@ msgid "Integrations|Includes commit title and branch"
msgstr "包括æ交的标题和分支"
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr "当议题在Jira中设定的项目中创建åŽï¼ŒJira中创建的议题会显示于此。"
+
+msgid "Integrations|Linked namespaces"
msgstr ""
-msgid "Integrations|Projects using custom settings will not be affected."
+msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
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 ""
+msgstr "除éžé¡¹ç›®æ‰€æœ‰è€…选择使用父级默认值,使用自定义设置的项目ä¸ä¼šå—到影å“。"
msgid "Integrations|Reset integration?"
-msgstr ""
+msgstr "é‡ç½®é›†æˆå—?"
msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
-msgstr ""
+msgstr "é‡ç½®æ­¤é›†æˆå°†æ¸…除设置并åœç”¨æ­¤é›†æˆã€‚"
msgid "Integrations|Return to GitLab for Jira"
-msgstr ""
+msgstr "返回GitLab for Jira"
msgid "Integrations|Save settings?"
-msgstr ""
+msgstr "ä¿å­˜è®¾ç½®å—?"
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
-msgstr ""
+msgstr "ä¿å­˜å°†æ›´æ–°æ‰€æœ‰ä¸ä½¿ç”¨è‡ªå®šä¹‰è®¾ç½®çš„项目的默认设置。"
msgid "Integrations|Search Jira issues"
-msgstr ""
+msgstr "æœç´¢Jira议题"
msgid "Integrations|Standard"
msgstr "标准"
msgid "Integrations|This integration, and inheriting projects were reset."
-msgstr ""
+msgstr "此集æˆå’Œç»§æ‰¿é¡¹ç›®å·²è¢«é‡ç½®ã€‚"
msgid "Integrations|To keep this project going, create a new issue."
-msgstr ""
+msgstr "为了ä¿æŒè¿™ä¸ªé¡¹ç›®çš„推进,请创建一个新的议题."
msgid "Integrations|Update your projects on Packagist, the main Composer repository"
-msgstr ""
+msgstr "在主è¦çš„Composer仓库Packagist上更新您的项目"
msgid "Integrations|Use custom settings"
msgstr "使用自定义设置"
msgid "Integrations|Use default settings"
-msgstr ""
+msgstr "使用默认设置"
msgid "Integrations|Use the GitLab Slack application"
-msgstr ""
+msgstr "使用GitLab Slack应用"
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 "在æ交或åˆå¹¶è¯·æ±‚中æåŠJira议题时,将创建远程链接和评论(如果å¯ç”¨)。"
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
-msgstr ""
+msgstr "您现在å¯ä»¥å…³é—­æ­¤çª—å£å¹¶è¿”回GitLab for Jira应用。"
msgid "Interactive mode"
-msgstr ""
+msgstr "交互模å¼"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "用户å¯ä»¥é€šè¿‡æŽ¨é€æ交æ¥å¯¹é¡¹ç›®ä½œå‡ºè´¡çŒ®ã€‚"
@@ -14733,10 +15139,10 @@ msgid "Internal"
msgstr "内部"
msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
-msgstr ""
+msgstr "除外部用户外,任何登录用户å‡å¯æŸ¥çœ‹è¯¥ç¾¤ç»„和任何内部项目。"
msgid "Internal - The project can be accessed by any logged in user except external users."
-msgstr ""
+msgstr "除外部用户外,任何登录用户å‡å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Internal URL (optional)"
msgstr "内部URL(å¯é€‰)"
@@ -14745,7 +15151,7 @@ msgid "Internal users"
msgstr "内部用户"
msgid "Internal users cannot be deactivated"
-msgstr ""
+msgstr "ä¸èƒ½åœç”¨å†…部用户"
msgid "Interval Pattern"
msgstr "循环周期"
@@ -14754,10 +15160,7 @@ msgid "Introducing Value Stream Analytics"
msgstr "价值æµåˆ†æžä»‹ç»"
msgid "Introducing Your DevOps Report"
-msgstr ""
-
-msgid "Invalid Git ref"
-msgstr "无效的Git ref"
+msgstr "了解您的DevOps报告"
msgid "Invalid Insights config file detected"
msgstr "检测到无效的 Insights é…置文件"
@@ -14766,7 +15169,7 @@ msgid "Invalid Login or password"
msgstr "登录å或密ç æ— æ•ˆ"
msgid "Invalid OS"
-msgstr ""
+msgstr "无效的æ“作系统"
msgid "Invalid URL"
msgstr "无效的网å€"
@@ -14802,7 +15205,7 @@ msgid "Invalid file."
msgstr "无效的文件。"
msgid "Invalid hash"
-msgstr ""
+msgstr "无效哈希"
msgid "Invalid import params"
msgstr "无效导入å‚æ•°"
@@ -14847,26 +15250,26 @@ msgid "Invalid yaml"
msgstr "无效的yaml"
msgid "Investigate vulnerability: %{title}"
-msgstr ""
+msgstr "调查æ¼æ´ž: %{title}"
msgid "Invitation"
msgstr "邀请"
msgid "Invitation declined"
-msgstr ""
+msgstr "邀请被拒ç»"
msgid "Invite"
msgstr "邀请"
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
msgid "Invite \"%{trimmed}\" by email"
msgstr "通过电å­é‚®ä»¶é‚€è¯·â€œ%{trimmed}â€"
msgid "Invite Members"
msgstr "邀请æˆå‘˜"
-msgid "Invite another teammate"
-msgstr "邀请其他团队æˆå‘˜"
-
msgid "Invite group"
msgstr "邀请群组"
@@ -14874,139 +15277,151 @@ msgid "Invite member"
msgstr "邀请æˆå‘˜"
msgid "Invite team members"
-msgstr ""
-
-msgid "Invite teammates (optional)"
-msgstr "邀请团队æˆå‘˜(å¯é€‰)"
+msgstr "邀请团队æˆå‘˜"
msgid "Invite your team"
-msgstr ""
+msgstr "邀请您的团队"
msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr ""
+msgstr "%{inviter}邀请您作为%{role}加入%{project_or_group_name}%{project_or_group}"
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 ""
+msgstr "%{inviter}邀请您作为%{role}加入%{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group}%{br_tag}"
msgid "InviteEmail|Join now"
-msgstr ""
+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 ""
+msgstr "您被邀请以%{role}身份加入%{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group}%{br_tag}"
msgid "InviteEmail|You are invited!"
-msgstr ""
+msgstr "您已被邀请ï¼"
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr ""
+msgstr "您被邀请以%{role}身份加入%{project_or_group_name}%{project_or_group}"
msgid "InviteMembersBanner|Collaborate with your team"
-msgstr ""
+msgstr "与您的团队å作"
msgid "InviteMembersBanner|Invite your colleagues"
-msgstr ""
+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 ""
+msgstr "ç›®å‰æ‚¨è¿˜æ²¡æœ‰é‚€è¯·ä»»ä½•äººåŠ å…¥è¿™ä¸ªç¾¤ç»„。 您å¯ä»¥é‚€è¯·æ‚¨çš„åŒäº‹åˆ°ç¾¤ç»„ç§ï¼Œä»¥æ–¹ä¾¿è®¨è®ºé—®é¢˜ï¼Œåœ¨åˆå¹¶è¯·æ±‚中进行å作,以åŠåˆ†äº«æ‚¨çš„知识。"
msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
-msgstr ""
+msgstr "%{linkStart}了解更多%{linkEnd}关于角色æƒé™çš„ä¿¡æ¯"
msgid "InviteMembersModal|Access expiration date (optional)"
-msgstr ""
+msgstr "访问到期日期(å¯é€‰)"
msgid "InviteMembersModal|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "InviteMembersModal|Choose a role permission"
-msgstr ""
+msgstr "选择角色æƒé™"
msgid "InviteMembersModal|Close invite team members"
-msgstr ""
+msgstr "关闭邀请团队æˆå‘˜"
msgid "InviteMembersModal|GitLab member or Email address"
-msgstr ""
+msgstr "GitLab用户或电å­é‚®ä»¶åœ°å€"
msgid "InviteMembersModal|Invite"
-msgstr ""
+msgstr "邀请"
msgid "InviteMembersModal|Invite team members"
-msgstr ""
+msgstr "邀请团队æˆå‘˜"
msgid "InviteMembersModal|Members were successfully added"
-msgstr ""
+msgstr "æˆå‘˜å·²æˆåŠŸæ·»åŠ "
msgid "InviteMembersModal|Search for members to invite"
-msgstr ""
+msgstr "æœç´¢æ¬²é‚€è¯·çš„æˆå‘˜"
msgid "InviteMembersModal|Some of the members could not be added"
-msgstr ""
+msgstr "部分æˆå‘˜æ— æ³•æ·»åŠ "
msgid "InviteMembersModal|You're inviting members to the %{name} %{type}"
-msgstr ""
+msgstr "您邀请æˆå‘˜åŠ å…¥%{name}%{type}"
msgid "InviteMembers|Invite team members"
+msgstr "邀请团队æˆå‘˜"
+
+msgid "InviteMember|Add members to this project and start collaborating with your team."
msgstr ""
-msgid "InviteMember|Oops, this feature isn't ready yet"
+msgid "InviteMember|Invite Members (optional)"
msgstr ""
-msgid "InviteMember|See who can invite members for you"
+msgid "InviteMember|Invite another member"
msgstr ""
-msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgid "InviteMember|Invite members"
msgstr ""
-msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgid "InviteMember|Invite your team"
msgstr ""
-msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+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 "我们正在努力å…许所有人邀请新æˆå‘˜ï¼Œä½¿å›¢é˜Ÿæ›´å®¹æ˜“开始使用GitLab"
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr "%{inviter}还在等待您注册GitLab"
+
msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
-msgstr ""
+msgstr "%{inviter}正在等待您注册GitLab"
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 ""
+msgstr "%{inviter}正在等待您以%{role}加人%{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group}。"
msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
-msgstr ""
+msgstr "æ¥è‡ª%{inviter}的注册GitLab邀请正在等待中"
msgid "InviteReminderEmail|Accept invitation"
-msgstr ""
+msgstr "接å—邀请"
msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
-msgstr ""
+msgstr "接å—邀请:%{invite_url}"
msgid "InviteReminderEmail|Decline invitation"
-msgstr ""
+msgstr "æ‹’ç»é‚€è¯·"
msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
-msgstr ""
+msgstr "æ‹’ç»é‚€è¯·: %{decline_url}"
msgid "InviteReminderEmail|Hey there %{wave_emoji}"
-msgstr ""
+msgstr "您好%{wave_emoji}"
msgid "InviteReminderEmail|Hey there!"
-msgstr ""
+msgstr "您好ï¼"
msgid "InviteReminderEmail|In case you missed it..."
-msgstr ""
+msgstr "如果您错过它..."
msgid "InviteReminderEmail|Invitation pending"
-msgstr ""
+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 ""
+msgstr "è·%{inviter}邀请您作为%{role}加%{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group}}已有%{invitation_age}天。您有什么计划å—?"
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 ""
+msgstr "这是一个å‹æƒ…æ醒。%{inviter}邀请您作为%{role}加入%{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group}。"
msgid "Invited"
-msgstr ""
-
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr "邀请的用户将被添加开å‘人员级别的æƒé™ã€‚您以åŽå¯ä»¥éšæ—¶æ›´æ”¹æ­¤è®¾ç½®ã€‚"
+msgstr "已邀请"
msgid "Invocations"
msgstr "调用"
@@ -15045,7 +15460,7 @@ msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}
msgstr "议题%{issue_reference}已被添加到å²è¯—%{epic_reference}。"
msgid "Issue Analytics"
-msgstr ""
+msgstr "议题分æž"
msgid "Issue Boards"
msgstr "议题看æ¿"
@@ -15057,13 +15472,16 @@ msgid "Issue cannot be found."
msgstr "议题无法找到"
msgid "Issue created from vulnerability %{vulnerability_link}"
+msgstr "从æ¼æ´ž %{vulnerability_link}创建的议题"
+
+msgid "Issue details"
msgstr ""
msgid "Issue events"
msgstr "议题事件"
msgid "Issue first deployed to production"
-msgstr ""
+msgstr "议题首次部署到生产环境"
msgid "Issue label"
msgstr "议题标记"
@@ -15074,8 +15492,8 @@ msgstr "需è¦è®®é¢˜æˆ–åˆå¹¶è¯·æ±‚ID"
msgid "Issue published on status page."
msgstr "议题å‘布在状æ€é¡µé¢ä¸Šã€‚"
-msgid "Issue template (optional)"
-msgstr "è®®é¢˜æ¨¡æ¿ (å¯é€‰)"
+msgid "Issue title"
+msgstr ""
msgid "Issue update failed"
msgstr "议题更新失败"
@@ -15113,7 +15531,7 @@ msgstr "状æ€"
msgid "IssueAnalytics|Weight"
msgstr "æƒé‡"
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15144,7 +15562,7 @@ msgid "IssueTracker|Custom issue tracker"
msgstr "自定义议题跟踪器"
msgid "IssueTracker|EWM work items tracker"
-msgstr ""
+msgstr "EWM工作项目跟踪器"
msgid "IssueTracker|Redmine issue tracker"
msgstr "Redmine议题跟踪器"
@@ -15213,7 +15631,7 @@ 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 ""
+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 "它必须有标题行和至少有两列:第一æ æ˜¯è®®é¢˜æ ‡é¢˜ï¼Œç¬¬äºŒæ æ˜¯è®®é¢˜æ述。自动检测分隔符。"
@@ -15233,6 +15651,9 @@ msgstr "迭代"
msgid "Iteration changed to"
msgstr "迭代更改为"
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr "迭代已删除"
@@ -15252,10 +15673,10 @@ msgid "Iteration|cannot be more than 500 years in the future"
msgstr "ä¸èƒ½è¶…过未æ¥çš„500å¹´"
msgid "I’m familiar with the basics of DevOps."
-msgstr ""
+msgstr "我熟悉Devops的基本知识。"
msgid "I’m not familiar with the basics of DevOps."
-msgstr ""
+msgstr "我ä¸ç†Ÿæ‚‰Devops的基本知识。"
msgid "Jaeger URL"
msgstr "Jaeger 地å€"
@@ -15270,7 +15691,7 @@ msgid "January"
msgstr "1月"
msgid "Japanese language support using"
-msgstr ""
+msgstr "日语支æŒä½¿ç”¨"
msgid "Jira Issues"
msgstr "Jira议题"
@@ -15303,7 +15724,7 @@ msgid "JiraService| on branch %{branch_link}"
msgstr "于分支%{branch_link}"
msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
-msgstr ""
+msgstr "%{jira_docs_link_start}å¯ç”¨Jira集æˆ%{jira_docs_link_end}以在GitLab中查看您的Jira议题。"
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}"
@@ -15317,6 +15738,9 @@ msgstr "å¯ç”¨Jira议题"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} 事件已ç¦ç”¨ã€‚"
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "如果与 Web URL ä¸åŒ"
@@ -15341,20 +15765,20 @@ msgstr "Jira 议题跟踪"
msgid "JiraService|Jira project key"
msgstr "Jira project key"
+msgid "JiraService|Jira workflow transition IDs"
+msgstr ""
+
msgid "JiraService|Open Jira"
msgstr "打开Jira"
msgid "JiraService|Password or API token"
msgstr "密ç æˆ– API 令牌"
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Transition ID(s)"
-msgstr "转æ¢ID"
-
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
-msgstr "使用“, â€æˆ–“; â€åˆ†éš”多个转æ¢ID"
+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 "æœåŠ¡å™¨ç‰ˆæœ¬è¯·ä½¿ç”¨å¯†ç , 云版本请使用API令牌"
@@ -15366,7 +15790,7 @@ msgid "JiraService|Username or Email"
msgstr "用户å或电å­é‚®ä»¶"
msgid "JiraService|Using Jira for issue tracking?"
-msgstr ""
+msgstr "使用Jira进行议题跟踪å—?"
msgid "JiraService|View Jira issues in GitLab"
msgstr "在GitLab查看Jira议题"
@@ -15432,25 +15856,25 @@ msgid "Jobs"
msgstr "作业"
msgid "Jobs|Are you sure you want to proceed?"
-msgstr ""
+msgstr "确定è¦ç»§ç»­å—?"
msgid "Jobs|Are you sure you want to retry this job?"
-msgstr ""
+msgstr "您确定è¦é‡è¯•æ­¤ä½œä¸šå—?"
msgid "Jobs|Create CI/CD configuration file"
-msgstr ""
+msgstr "创建CI/CDé…置文件"
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 ""
+msgstr "作业是GitLab CI/CDæµæ°´çº¿çš„基本组æˆéƒ¨åˆ†ã€‚æ¯ä¸ªä½œä¸šéƒ½æœ‰ä¸€ä¸ªç‰¹å®šçš„任务,例如测试代ç ã€‚ è‹¥è¦åœ¨CI/CDæµæ°´çº¿ä¸­è®¾ç½®ä½œä¸šï¼Œè¯·åœ¨æ‚¨çš„项目中添加一个CI/CDé…置文件。"
msgid "Jobs|No jobs to show"
-msgstr ""
+msgstr "没有å¯æ˜¾ç¤ºçš„作业"
msgid "Jobs|Use jobs to automate your tasks"
-msgstr ""
+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 ""
+msgstr "ä½ å³å°†é‡è¯•ä¸€ä¸ªä½œä¸šï¼Œæ­¤ä½œä¸šå› è¯•å›¾éƒ¨ç½²æ—§çš„代ç è€Œå¤±è´¥ã€‚ é‡è¯•æ­¤ä»»åŠ¡å¯èƒ½å¯¼è‡´ç”¨æ—§ç‰ˆæœ¬æºä»£ç è¦†ç›–环境。"
msgid "Job|Browse"
msgstr "æµè§ˆ"
@@ -15522,7 +15946,7 @@ msgid "Join Zoom meeting"
msgstr "加入Zoom会议"
msgid "Joined %{time_ago}"
-msgstr ""
+msgstr "加入于%{time_ago}"
msgid "Jul"
msgstr "7月"
@@ -15549,7 +15973,7 @@ msgid "Keep divergent refs"
msgstr "ä¿ç•™åˆ†å‰çš„refs"
msgid "Keep editing"
-msgstr ""
+msgstr "继续编辑"
msgid "Kerberos access denied"
msgstr "Kerberos访问被拒ç»"
@@ -15567,13 +15991,13 @@ msgid "Keyboard shortcuts"
msgstr "å¿«æ·é”®"
msgid "KeyboardKey|Ctrl+"
-msgstr ""
+msgstr "Ctrl +"
msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
+msgstr "全局快æ·é”®"
msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
+msgstr "开关性能æ "
msgid "Keys"
msgstr "é”®"
@@ -15582,7 +16006,7 @@ msgid "Ki"
msgstr "Ki"
msgid "Kroki"
-msgstr ""
+msgstr "Kroki"
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -15627,7 +16051,7 @@ msgid "LDAP Synchronization"
msgstr "LDAPåŒæ­¥"
msgid "LDAP group settings"
-msgstr ""
+msgstr "LDAP组设置"
msgid "LDAP settings"
msgstr "LDAP 设置"
@@ -15639,7 +16063,7 @@ msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to
msgstr "LDAPåŒæ­¥æ­£åœ¨è¿›è¡Œä¸­ã€‚此过程å¯èƒ½éœ€è¦å‡ åˆ†é’Ÿã€‚请刷新页é¢ä»¥æŸ¥çœ‹æ›´æ”¹ã€‚"
msgid "LDAP synchronizations"
-msgstr ""
+msgstr "LDAPåŒæ­¥"
msgid "LFS"
msgstr "LFS"
@@ -15699,7 +16123,7 @@ msgid "Labels can be applied to issues and merge requests."
msgstr "标记å¯ç”¨äºŽè®®é¢˜å’Œåˆå¹¶è¯·æ±‚。"
msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
-msgstr ""
+msgstr "%{spanStart}将标记%{spanEnd}%{labelTitle}%{spanStart}å‡çº§ä¸ºç¾¤ç»„标记?%{spanEnd}"
msgid "Labels|Promote Label"
msgstr "å‡çº§æ ‡è®°"
@@ -15718,16 +16142,16 @@ msgid_plural "Last %d days"
msgstr[0] "最近 %d 天"
msgid "Last 2 weeks"
-msgstr ""
+msgstr "最近 2 周"
msgid "Last 30 days"
-msgstr ""
+msgstr "最近 30 天"
msgid "Last 60 days"
-msgstr ""
+msgstr "最近 60 天"
msgid "Last 90 days"
-msgstr ""
+msgstr "最近 90 天"
msgid "Last Accessed On"
msgstr "最åŽè®¿é—®äºŽ"
@@ -15777,6 +16201,9 @@ msgstr "上次仓库检查"
msgid "Last seen"
msgstr "最åŽå‡ºçŽ°"
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr "上次æˆåŠŸåŒæ­¥"
@@ -15799,13 +16226,13 @@ msgid "Last used"
msgstr "最åŽä½¿ç”¨"
msgid "Last used %{last_used_at} ago"
-msgstr ""
+msgstr "最åŽä½¿ç”¨ %{last_used_at} 之å‰"
msgid "Last used on:"
msgstr "上次使用于:"
msgid "Last week"
-msgstr ""
+msgstr "上周"
msgid "LastCommit|authored"
msgstr "编辑于"
@@ -15823,7 +16250,7 @@ msgid "Latest pipeline for the most recent commit on this branch"
msgstr "此分支上最近æ交的最新æµæ°´çº¿"
msgid "Launch a ready-to-code development environment for your project."
-msgstr ""
+msgstr "为您的项目å¯åŠ¨ä¸€ä¸ªçŽ°æˆçš„代ç å¼€å‘环境。"
msgid "Lead"
msgstr "最高"
@@ -15831,9 +16258,15 @@ msgstr "最高"
msgid "Lead Time"
msgstr "交付时间"
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr "学习GitLab"
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr "了解如何 %{link_start}贡献到内置的模æ¿%{link_end}"
@@ -15847,7 +16280,7 @@ msgid "Learn more"
msgstr "进一步了解"
msgid "Learn more about %{username}"
-msgstr ""
+msgstr "进一步了解%{username}"
msgid "Learn more about Auto DevOps"
msgstr "了解更多关于Auto DevOps"
@@ -15859,7 +16292,7 @@ msgid "Learn more about License-Check"
msgstr "进一步了解有关许å¯è¯æ£€æŸ¥çš„ä¿¡æ¯"
msgid "Learn more about Needs relationships"
-msgstr ""
+msgstr "了解更多关于Needs关系的信æ¯"
msgid "Learn more about Vulnerability-Check"
msgstr "进一步了解有关æ¼æ´žæ£€æŸ¥(Vulnerability-Check)çš„ä¿¡æ¯"
@@ -15873,9 +16306,6 @@ msgstr "了解更多关于X.509ç­¾åæ交"
msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "通过%{docs_link_start}GitLab Pages上的文档%{docs_link_end}了解更多关于å‘项目添加è¯ä¹¦çš„ä¿¡æ¯ã€‚"
-msgid "Learn more about approvals."
-msgstr "了解有关核准的更多信æ¯ã€‚"
-
msgid "Learn more about custom project templates"
msgstr "了解更多关于自定义项目模æ¿"
@@ -15900,6 +16330,9 @@ msgstr "了解更多"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "æµæ°´çº¿è®¡åˆ’文档"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr "退出"
@@ -15922,7 +16355,7 @@ msgid "Leave zen mode"
msgstr "离开禅模å¼"
msgid "Legacy burndown chart"
-msgstr ""
+msgstr "旧版燃尽图"
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encryptä¸æŽ¥å—example.com的电å­é‚®ä»¶"
@@ -15943,7 +16376,7 @@ msgid "License ID:"
msgstr "许å¯è¯ID:"
msgid "License overview"
-msgstr ""
+msgstr "许å¯è¯æ¦‚览"
msgid "License-Check"
msgstr "许å¯è¯æ£€æŸ¥"
@@ -16024,10 +16457,10 @@ msgid "LicenseCompliance|Remove license?"
msgstr "删除许å¯è¯å—?"
msgid "LicenseCompliance|There are currently no policies in this project."
-msgstr ""
+msgstr "此项目目å‰æ²¡æœ‰ç­–略。"
msgid "LicenseCompliance|There are currently no policies that match in this project."
-msgstr ""
+msgstr "此项目目å‰æ²¡æœ‰åŒ¹é…的策略。"
msgid "LicenseCompliance|This license already exists in this project."
msgstr "此许å¯è¯å·²ç»å­˜åœ¨äºŽè¯¥é¡¹ç›®ä¸­ã€‚"
@@ -16051,7 +16484,7 @@ msgid "Licensed to"
msgstr "授æƒç»™"
msgid "Licensed to:"
-msgstr ""
+msgstr "授æƒç»™:"
msgid "Licenses"
msgstr "许å¯è¯"
@@ -16138,7 +16571,7 @@ 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 ""
+msgstr "é™åˆ¶æ­¤æ¬¡è¦èŠ‚点在åŽå°è¿è¡Œçš„并行æ“作数é‡ã€‚"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
@@ -16160,7 +16593,7 @@ msgid "Link title is required"
msgstr "链接标题为必填项"
msgid "Link to an image"
-msgstr ""
+msgstr "链接到镜åƒ"
msgid "Link to go to GitLab pipeline documentation"
msgstr "链接以转到GitLaæµæ°´çº¿æ–‡æ¡£"
@@ -16190,10 +16623,10 @@ msgid "List available repositories"
msgstr "列出å¯ç”¨ä»“库"
msgid "List of all merge commits"
-msgstr ""
+msgstr "所有åˆå¹¶æ交列表"
msgid "List options"
-msgstr ""
+msgstr "列表选项"
msgid "List settings"
msgstr "列表设置"
@@ -16214,7 +16647,7 @@ msgid "Load more"
msgstr "加载更多"
msgid "Load more users"
-msgstr ""
+msgstr "加载更多用户"
msgid "Loading"
msgstr "加载中"
@@ -16231,6 +16664,9 @@ msgstr "加载功能超时。请刷新页é¢é‡è¯•ã€‚"
msgid "Loading issues"
msgstr "加载议题"
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr "正在加载代ç ç‰‡æ®µ"
@@ -16268,7 +16704,7 @@ msgid "Lock the discussion"
msgstr "é”定讨论"
msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "é”定%{issuableDisplayName}å—?é”定åŽå°†åªæœ‰%{strongStart}项目æˆå‘˜%{strongEnd}å¯ä»¥å‘表评论。"
msgid "Lock to current projects"
msgstr "é”定到当å‰é¡¹ç›®"
@@ -16318,11 +16754,14 @@ msgstr "MD5"
msgid "MERGED"
msgstr "å·²åˆå¹¶"
-msgid "MR widget|Back to the Merge request"
+msgid "MERGED (REVERTED)"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr "返回åˆå¹¶è¯·æ±‚"
+
msgid "MR widget|See your pipeline in action"
-msgstr ""
+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 "请查阅我们的%{beginnerLinkStart}æŒç»­é›†æˆæ–°æ‰‹æŒ‡å—%{beginnerLinkEnd}å’Œ%{exampleLinkStart}GitLab CI/CD实例%{exampleLinkEnd}æ¥äº†è§£æ›´å¤šä¿¡æ¯ã€‚"
@@ -16340,7 +16779,7 @@ msgid "MRApprovals|Approvers"
msgstr "核准人"
msgid "MRApprovals|Commented by"
-msgstr ""
+msgstr "已评论"
msgid "MRDiff|Show changes only"
msgstr "åªæŸ¥çœ‹å˜æ›´å†…容"
@@ -16427,7 +16866,7 @@ 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 ""
+msgstr "手动链接此议题,方法是将其添加到%{originating_vulnerability}的链接议题部分。"
msgid "Map a FogBugz account ID to a GitLab user"
msgstr "å°†FogBugzå¸æˆ·ID映射为GitLab用户"
@@ -16442,10 +16881,10 @@ msgid "Mark as done"
msgstr "标记为已完æˆ"
msgid "Mark as draft"
-msgstr ""
+msgstr "标记为è‰ç¨¿"
msgid "Mark as ready"
-msgstr ""
+msgstr "标记为就绪"
msgid "Mark as resolved"
msgstr "标记为已解决"
@@ -16457,7 +16896,7 @@ msgid "Mark this issue as related to another issue"
msgstr "将此议题标记为与å¦ä¸€ä¸ªè®®é¢˜çš„相关"
msgid "Mark to do as done"
-msgstr ""
+msgstr "将待办事项标记为已完æˆã€‚"
msgid "Markdown"
msgstr "Markdown"
@@ -16472,28 +16911,28 @@ msgid "Markdown is supported"
msgstr "支æŒMarkdown"
msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
-msgstr ""
+msgstr "添加链接(%{modifierKey}K)"
msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
-msgstr ""
+msgstr "添加链接(%{modifier_key}K)"
msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
-msgstr ""
+msgstr "添加粗体文本(%{modifierKey}B)"
msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
-msgstr ""
+msgstr "添加粗体文本(%{modifier_key}B)"
msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
-msgstr ""
+msgstr "添加斜体文本(%{modifierKey}I)"
msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
-msgstr ""
+msgstr "添加斜体文本(%{modifier_key}I)"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr "标记删除于 - %{deletion_time}"
msgid "Marked this %{noun} as a draft."
-msgstr ""
+msgstr "已标记此%{noun}为è‰ç¨¿ã€‚"
msgid "Marked this issue as a duplicate of %{duplicate_param}."
msgstr "标记这个议题为%{duplicate_param}çš„é‡å¤é¡¹ã€‚"
@@ -16502,10 +16941,10 @@ msgid "Marked this issue as related to %{issue_ref}."
msgstr "将此议题标记为%{issue_ref}的相关议题。"
msgid "Marked to do as done."
-msgstr ""
+msgstr "将待办事项标记为已完æˆã€‚"
msgid "Marks this %{noun} as a draft."
-msgstr ""
+msgstr "将标记此%{noun}为è‰ç¨¿ã€‚"
msgid "Marks this issue as a duplicate of %{duplicate_reference}."
msgstr "将此议题标记为 %{duplicate_reference} çš„é‡å¤ã€‚"
@@ -16514,7 +16953,7 @@ msgid "Marks this issue as related to %{issue_ref}."
msgstr "将此议题标记为%{issue_ref}的相关议题。"
msgid "Marks to do as done."
-msgstr ""
+msgstr "将待办事项标记为已完æˆã€‚"
msgid "Mask variable"
msgstr "éšè—å˜é‡"
@@ -16553,6 +16992,9 @@ msgid "MattermostService|This service allows users to perform common operations
msgstr "æ­¤æœåŠ¡å…许用户通过在Mattermost中输入斜æ å‘½ä»¤æ¥å¯¹è¯¥é¡¹ç›®æ‰§è¡Œå¸¸è§æ“作。"
msgid "Max 100,000 events"
+msgstr "最多100,000个事件"
+
+msgid "Max 20 characters"
msgstr ""
msgid "Max Group Export Download requests per minute per user"
@@ -16576,26 +17018,29 @@ msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å…¥è¯·æ±‚æ•°"
msgid "Max access level"
msgstr "最高访问级别"
-msgid "Max role"
+msgid "Max file size is 200 KB."
msgstr ""
+msgid "Max role"
+msgstr "最大角色"
+
msgid "MaxBuilds"
-msgstr ""
+msgstr "MaxBuilds"
msgid "Maximum Conan package file size in bytes"
-msgstr ""
+msgstr "最大Conan文件包大å°ï¼ˆå­—节)"
msgid "Maximum Maven package file size in bytes"
-msgstr ""
+msgstr "最大Maven文件包大å°ï¼ˆå­—节)"
msgid "Maximum NPM package file size in bytes"
-msgstr ""
+msgstr "最大NPM文件包大å°ï¼ˆå­—节)"
msgid "Maximum NuGet package file size in bytes"
-msgstr ""
+msgstr "最大NuGet文件包大å°ï¼ˆå­—节)"
msgid "Maximum PyPI package file size in bytes"
-msgstr ""
+msgstr "最大PyPI文件包大å°ï¼ˆå­—节)"
msgid "Maximum Users:"
msgstr "最大用户数:"
@@ -16703,10 +17148,10 @@ msgid "Member since %{date}"
msgstr "加入于 %{date}"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
-msgstr ""
+msgstr "%{member_name}邀请您使用GitLab"
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
-msgstr ""
+msgstr "邀请加入%{project_or_group}%{project_or_group_name}"
msgid "Members"
msgstr "æˆå‘˜"
@@ -16715,13 +17160,19 @@ msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_ope
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 ""
-msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr "%{group}çš„æˆå‘˜ä¹Ÿå¯ä»¥åˆå¹¶åˆ°æ­¤åˆ†æ”¯: %{branch}"
+
msgid "Members of %{group} can also push to this branch: %{branch}"
-msgstr ""
+msgstr "%{group}çš„æˆå‘˜ä¹Ÿå¯ä»¥æŽ¨é€åˆ°æ­¤åˆ†æ”¯: %{branch}"
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr "%{strong_open}%{project_name}%{strong_close}çš„æˆå‘˜"
@@ -16733,115 +17184,115 @@ msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr "有æƒè®¿é—®%{strong_start}%{group_name}%{strong_end}çš„æˆå‘˜"
msgid "Members|%{time} by %{user}"
-msgstr ""
+msgstr "于%{time}由%{user}"
msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
-msgstr ""
+msgstr "%{userName}当å‰æ˜¯LDAP用户。编辑其æƒé™å°†è¦†ç›–LDAP组åŒæ­¥ä¸­çš„设置。"
msgid "Members|2FA"
-msgstr ""
+msgstr "2FA"
msgid "Members|An error occurred while trying to enable LDAP override, please try again."
-msgstr ""
+msgstr "å°è¯•å¯ç”¨LDAP覆盖时å‘生错误,请é‡è¯•ã€‚"
msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
-msgstr ""
+msgstr "å°è¯•æ¢å¤LDAP组åŒæ­¥è®¾ç½®æ—¶å‘生错误,请é‡è¯•ã€‚"
msgid "Members|An error occurred while updating the member's expiration date, please try again."
-msgstr ""
+msgstr "æ›´æ–°æˆå‘˜åˆ°æœŸæ—¥æœŸæ—¶å‘生错误,请é‡è¯•ã€‚"
msgid "Members|An error occurred while updating the member's role, please try again."
-msgstr ""
+msgstr "æ›´æ–°æˆå‘˜è§’色时出错,请é‡è¯•ã€‚"
msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
-msgstr ""
+msgstr "您确定è¦æ‹’ç»%{usersName}加入\"%{source}\"的请求å—?"
msgid "Members|Are you sure you want to leave \"%{source}\"?"
-msgstr ""
+msgstr "您确定è¦ç¦»å¼€\"%{source}\"å—?"
msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
-msgstr ""
+msgstr "您确定è¦åˆ é™¤\"%{groupName}\"å—?"
msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
-msgstr ""
+msgstr "你确定è¦ä»Žâ€œ%{source}â€ä¸­åˆ é™¤%{usersName}å—"
msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
-msgstr ""
+msgstr "您确定è¦ä»Ž\"%{source}\"中移除这个孤立æˆå‘˜å—?"
msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
-msgstr ""
+msgstr "你确定è¦æ’¤é”€%{inviteEmail}加入\"%{source}\"的邀请å—"
msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
-msgstr ""
+msgstr "你确定想è¦æ’¤å›žä½ å¯¹%{source}访问请求å—"
msgid "Members|Direct"
-msgstr ""
+msgstr "直接"
msgid "Members|Disabled"
-msgstr ""
+msgstr "å·²ç¦ç”¨"
msgid "Members|Edit permissions"
-msgstr ""
+msgstr "编辑æƒé™"
msgid "Members|Enabled"
-msgstr ""
+msgstr "å¯ç”¨"
msgid "Members|Expiration date removed successfully."
-msgstr ""
+msgstr "æˆåŠŸåˆ é™¤è¿‡æœŸæ—¥æœŸã€‚"
msgid "Members|Expiration date updated successfully."
-msgstr ""
+msgstr "æˆåŠŸæ›´æ–°è¿‡æœŸæ—¥æœŸã€‚"
msgid "Members|Expired"
-msgstr ""
+msgstr "已过期"
msgid "Members|Filter members"
-msgstr ""
+msgstr "筛选æˆå‘˜"
msgid "Members|Inherited"
-msgstr ""
+msgstr "继承"
msgid "Members|LDAP override enabled."
-msgstr ""
+msgstr "LDAP覆盖已å¯ç”¨ã€‚"
msgid "Members|Leave \"%{source}\""
-msgstr ""
+msgstr "离开\"%{source}\""
msgid "Members|Membership"
-msgstr ""
+msgstr "æˆå‘˜"
msgid "Members|No expiration set"
-msgstr ""
+msgstr "没有过期设置"
msgid "Members|Remove \"%{groupName}\""
-msgstr ""
+msgstr "删除\"%{groupName}\""
msgid "Members|Remove group"
-msgstr ""
+msgstr "删除群组"
msgid "Members|Revert to LDAP group sync settings"
-msgstr ""
+msgstr "æ¢å¤åˆ°LDAP群组åŒæ­¥è®¾ç½®"
msgid "Members|Reverted to LDAP group sync settings."
-msgstr ""
+msgstr "å·²æ¢å¤åˆ°LDAP群组åŒæ­¥è®¾ç½®."
msgid "Members|Role updated successfully."
-msgstr ""
+msgstr "å·²æˆåŠŸæ›´æ–°è§’色。"
msgid "Members|Search invited"
-msgstr ""
+msgstr "æœç´¢å·²é‚€è¯·"
msgid "Members|in %{time}"
-msgstr ""
+msgstr "于%{time}åŽ"
msgid "Member|Deny access"
-msgstr ""
+msgstr "æ‹’ç»è®¿é—®"
msgid "Member|Remove member"
-msgstr ""
+msgstr "移除æˆå‘˜"
msgid "Member|Revoke invite"
-msgstr ""
+msgstr "撤销邀请"
msgid "Memory Usage"
msgstr "内存使用情况"
@@ -16849,9 +17300,6 @@ msgstr "内存使用情况"
msgid "Merge"
msgstr "åˆå¹¶"
-msgid "Merge (when the pipeline succeeds)"
-msgstr "åˆå¹¶(当æµæ°´çº¿æˆåŠŸæ—¶)"
-
msgid "Merge Conflicts"
msgstr "åˆå¹¶å†²çª"
@@ -16877,13 +17325,13 @@ msgid "Merge Requests in Review"
msgstr "评审中的åˆå¹¶è¯·æ±‚"
msgid "Merge Requests merged"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚å·²åˆå¹¶"
msgid "Merge automatically (%{strategy})"
msgstr "自动åˆå¹¶(%{strategy})"
msgid "Merge commit SHA"
-msgstr ""
+msgstr "åˆå¹¶æ交SHA"
msgid "Merge commit message"
msgstr "åˆå¹¶æ交消æ¯"
@@ -16898,7 +17346,7 @@ msgid "Merge in progress"
msgstr "正在åˆå¹¶"
msgid "Merge locally"
-msgstr ""
+msgstr "本地åˆå¹¶"
msgid "Merge options"
msgstr "åˆå¹¶é€‰é¡¹"
@@ -16912,6 +17360,9 @@ msgstr "åˆå¹¶è¯·æ±‚%{iid} 作者: %{authorName}"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr "åˆå¹¶è¯·æ±‚%{mr_link}已被%{mr_author}审核"
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr "åˆå¹¶è¯·æ±‚批准"
@@ -16927,9 +17378,6 @@ msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶"
msgid "Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
-msgid "Merge requests approvals"
-msgstr "åˆå¹¶è¯·æ±‚批准"
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改并与他人进行讨论"
@@ -16937,7 +17385,7 @@ msgid "Merge requests are read-only in a secondary Geo node"
msgstr "åˆå¹¶è¯·æ±‚在Geo次è¦èŠ‚点中为åªè¯»"
msgid "Merge the branch and fix any conflicts that come up"
-msgstr ""
+msgstr "åˆå¹¶åˆ†æ”¯å¹¶è§£å†³å‡ºçŽ°çš„任何冲çª"
msgid "Merge when pipeline succeeds"
msgstr "当æµæ°´çº¿æˆåŠŸæ—¶åˆå¹¶"
@@ -16967,25 +17415,25 @@ msgid "MergeConflict|origin//their changes"
msgstr "æ¥æº//他们的更改"
msgid "MergeRequestAnalytics|Assignees"
-msgstr ""
+msgstr "指派人"
msgid "MergeRequestAnalytics|Date Merged"
-msgstr ""
+msgstr "åˆå¹¶æ—¥æœŸ"
msgid "MergeRequestAnalytics|Line changes"
-msgstr ""
+msgstr "更改行数"
msgid "MergeRequestAnalytics|Merge Request"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚"
msgid "MergeRequestAnalytics|Milestone"
-msgstr ""
+msgstr "里程碑"
msgid "MergeRequestAnalytics|Pipelines"
-msgstr ""
+msgstr "æµæ°´çº¿"
msgid "MergeRequestAnalytics|Time to merge"
-msgstr ""
+msgstr "åˆå¹¶æ—¶é—´"
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "对%{selectStart}开始于%{selectEnd}到%{end}è¡Œå‘表评论"
@@ -17074,9 +17522,15 @@ 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 "å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
@@ -17087,19 +17541,16 @@ msgid "Merged this merge request."
msgstr "å·²åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚。"
msgid "Merged: %{merged}"
-msgstr ""
+msgstr "å·²åˆå¹¶: %{merged}"
msgid "Merges this merge request immediately."
msgstr "ç«‹å³åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚。"
-msgid "Merges this merge request when the pipeline succeeds."
-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 "ä¸å»ºè®®ç«‹å³åˆå¹¶ï¼Œå› ä¸ºå®ƒå¯èƒ½å¯¹çŽ°æœ‰åˆå¹¶åˆ—车产生ä¸åˆ©å½±å“。请查阅%{docsLinkStart}文档%{docsLinkEnd}以了解更多信æ¯ã€‚"
msgid "Message"
-msgstr ""
+msgstr "消æ¯"
msgid "Messages"
msgstr "消æ¯"
@@ -17123,10 +17574,10 @@ msgid "MetricChart|Selected"
msgstr "选中的"
msgid "MetricChart|There is no data available. Please change your selection."
-msgstr ""
+msgstr "没有å¯ç”¨æ•°æ®ã€‚请更改选择。"
msgid "MetricChart|There is too much data to calculate. Please change your selection."
-msgstr ""
+msgstr "æ•°æ®å¤ªå¤šæ— æ³•è®¡ç®—。请更改您的选择。"
msgid "Metrics"
msgstr "指标"
@@ -17231,10 +17682,10 @@ msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "查看有关部署到环境的CI/CD文档"
msgid "Metrics|Collapse panel"
-msgstr ""
+msgstr "收起é¢æ¿"
msgid "Metrics|Collapse panel (Esc)"
-msgstr ""
+msgstr "收起é¢æ¿(Esc)"
msgid "Metrics|Copy YAML"
msgstr "å¤åˆ¶YAML"
@@ -17279,13 +17730,13 @@ msgid "Metrics|Duplicate dashboard"
msgstr "å¤åˆ¶ä»ªè¡¨æ¿"
msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
-msgstr ""
+msgstr "å¤åˆ¶æ­¤ä»ªè¡¨ç›˜ä»¥æ·»åŠ é¢æ¿æˆ–编辑仪表æ¿YAML。"
msgid "Metrics|Duplicating..."
msgstr "正在å¤åˆ¶..."
msgid "Metrics|Edit dashboard YAML"
-msgstr ""
+msgstr "编辑仪表æ¿YAML"
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
@@ -17325,7 +17776,7 @@ msgid "Metrics|Min"
msgstr "最å°å€¼"
msgid "Metrics|More actions"
-msgstr ""
+msgstr "更多æ“作"
msgid "Metrics|Must be a valid PromQL query."
msgstr "必须是有效的 PromQL 查询。"
@@ -17352,7 +17803,7 @@ msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus查询文档"
msgid "Metrics|Refresh Prometheus data"
-msgstr ""
+msgstr "刷新Prometheusæ•°æ®"
msgid "Metrics|Refresh dashboard"
msgstr "刷新仪表æ¿"
@@ -17433,7 +17884,7 @@ msgid "Metrics|View logs"
msgstr "查看日志"
msgid "Metrics|View runbook - %{label}"
-msgstr ""
+msgstr "查看Runbook - %{label}"
msgid "Metrics|Y-axis label"
msgstr "Y轴标签"
@@ -17491,28 +17942,28 @@ 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 "关闭:"
@@ -17602,7 +18053,7 @@ msgid "Milestones|Milestone %{milestoneTitle} was not found"
msgstr "未找到里程碑 %{milestoneTitle}"
msgid "Milestones|No milestones found"
-msgstr ""
+msgstr "未找到里程碑"
msgid "Milestones|Ongoing Issues (open and assigned)"
msgstr "处ç†ä¸­çš„议题(打开和已分é…)"
@@ -17655,9 +18106,6 @@ msgstr "é•œåƒè®¾ç½®ä»…GitLab管ç†å‘˜å¯ç”¨ã€‚"
msgid "Mirror user"
msgstr "é•œåƒç”¨æˆ·"
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr "é•œåƒåˆ†æ”¯éœ€æœ‰æ­¤å‰ç¼€ã€‚如果å¯ç”¨â€œä»…é•œåƒä¿æŠ¤åˆ†æ”¯â€ï¼Œåˆ™éœ€è¦åœ¨æ­¤é¡¹ç›®ä¿æŠ¤åˆ†æ”¯ä¸­åŒ…å«æ­¤å‰ç¼€ï¼Œå¦åˆ™å°†æ— æ³•é•œåƒã€‚"
-
msgid "Mirrored repositories"
msgstr "é•œåƒçš„仓库"
@@ -17677,13 +18125,13 @@ msgid "Mirroring will only be available if the feature is included in the plan o
msgstr "åªæœ‰åœ¨æ‰€é€‰ç¾¤ç»„或用户的计划中包å«é•œåƒåŠŸèƒ½æ—¶ï¼Œæ‰èƒ½ä½¿ç”¨ã€‚"
msgid "Missing OAuth configuration for GitHub."
-msgstr ""
+msgstr "缺少GitHubçš„OAuthé…置。"
msgid "Missing OS"
-msgstr ""
+msgstr "缺少æ“作系统"
msgid "Missing arch"
-msgstr ""
+msgstr "缺少架构"
msgid "Missing commit signatures endpoint!"
msgstr "缺少æ交签å节点ï¼"
@@ -17695,7 +18143,7 @@ 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 ""
+msgstr "在您的个人资料中添加SSH密钥之å‰ï¼Œæ‚¨ä¸èƒ½é€šè¿‡SSHæ¥æ‹‰å–或推é€ä»“库。"
msgid "ModalButton|Add projects"
msgstr "添加项目"
@@ -17731,7 +18179,7 @@ msgid "Monitoring"
msgstr "监控"
msgid "Month"
-msgstr ""
+msgstr "月"
msgid "Months"
msgstr "月"
@@ -17791,7 +18239,7 @@ msgid "Move selection up"
msgstr "上移所选的项目"
msgid "Move test case"
-msgstr ""
+msgstr "移动测试用例"
msgid "Move this issue to another project."
msgstr "将此议题移至å¦ä¸€ä¸ªé¡¹ç›®ã€‚"
@@ -17830,20 +18278,17 @@ msgid "Multi-project Runners cannot be removed"
msgstr "多项目Runner无法删除"
msgid "Multiple HTTP integrations are not supported for this project"
-msgstr ""
+msgstr "此项目ä¸æ”¯æŒå¤šä¸ªHTTP集æˆ"
msgid "Multiple IP address ranges are supported."
msgstr "支æŒå¤šä¸ªIP地å€èŒƒå›´ã€‚"
msgid "Multiple Prometheus integrations are not supported"
-msgstr ""
+msgstr "ä¸æ”¯æŒå¤šä¸ªPrometheus集æˆ"
msgid "Multiple domains are supported."
msgstr "支æŒå¤šä¸ªåŸŸå。"
-msgid "Multiple issue boards"
-msgstr "多é‡è®®é¢˜çœ‹æ¿"
-
msgid "Multiple model types found: %{model_types}"
msgstr "找到多个模型类型: %{model_types}"
@@ -17887,7 +18332,7 @@ msgid "Namespace"
msgstr "命å空间"
msgid "Namespace ID:"
-msgstr ""
+msgstr "命å空间ID:"
msgid "Namespace is empty"
msgstr "命å空间为空"
@@ -17897,32 +18342,32 @@ 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[0] "%{namespace_name}包å«%{locked_project_count}个é”定的项目"
msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
-msgstr ""
+msgstr "%{namespace_name}ç›®å‰ä¸ºåªè¯»çŠ¶æ€ã€‚您ä¸èƒ½ï¼š%{base_message}"
msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
-msgstr ""
+msgstr "如果你已使用100%%存储容é‡ï¼Œä½ å°†æ— æ³•: %{base_message}"
msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
-msgstr ""
+msgstr "请购买更多的存储空间以解é”超过å…è´¹%{free_size_limit}é™åˆ¶çš„项目。你ä¸èƒ½ %{base_message}"
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 ""
+msgstr "您已ç»ç”¨å°½æ‰€æœ‰æ›´å¤šçš„存储空间,请购买更多空间以解é”超过å…è´¹%{free_size_limit}é™åˆ¶çš„项目。你ä¸èƒ½ %{base_message}"
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr ""
+msgstr "你已使用了%{namespace_name}存储空间的%{usage_in_percent}(总计%{storage_limit},已使用%{used_storage})"
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[0] "您已ç»åœ¨%{locked_project_count}项目达到å…费存储空间é™åˆ¶%{free_size_limit}。如需解é”,请购买更多存储空间。"
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 ""
+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 ""
+msgstr "推é€åˆ°æ‚¨çš„仓库,创建æµæ°´çº¿ï¼Œåˆ›å»ºè®®é¢˜æˆ–添加评论。如需å‡å°‘存储使用,请删除未使用的仓库,产物,wiki,议题和æµæ°´çº¿ã€‚"
msgid "Namespaces"
msgstr "命å空间"
@@ -17955,7 +18400,7 @@ msgid "Need help?"
msgstr "如需帮助:"
msgid "Needs"
-msgstr ""
+msgstr "Needs"
msgid "Needs attention"
msgstr "需è¦å…³æ³¨"
@@ -17967,25 +18412,31 @@ 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 ""
+msgstr "%{ifLabelStart}如果%{ifLabelEnd}%{ruleType}%{isLabelStart}为%{isLabelEnd}%{ruleDirection}%{ruleSelector}%{directionLabelStart}且由%{directionLabelEnd}%{rule}%{portsLabelStart}在%{portsLabelEnd} %{ports}传入。"
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr "%{ifLabelStart}如果%{ifLabelEnd}%{ruleType}%{isLabelStart}为%{isLabelEnd}%{ruleDirection}%{ruleSelector}%{directionLabelStart}且å‘%{directionLabelEnd}%{rule}%{portsLabelStart}在%{portsLabelEnd} %{ports}外å‘。"
+
+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 ""
+msgstr "%{labelStart}然åŽ%{labelEnd}%{action}%{spanStart}网络æµé‡ã€‚%{spanEnd}"
msgid "NetworkPolicies|%{number} selected"
-msgstr ""
+msgstr "已选择%{number}项"
msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
-msgstr ""
+msgstr "%{strongOpen}所有%{strongClose}pod"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr "%{strongOpen}任何%{strongClose}端å£"
+
+msgid "NetworkPolicies|+ Add alert"
msgstr ""
msgid "NetworkPolicies|.yaml"
-msgstr ""
+msgstr ".yaml"
msgid "NetworkPolicies|.yaml mode"
msgstr ".yaml模å¼"
@@ -17993,20 +18444,23 @@ msgstr ".yaml模å¼"
msgid "NetworkPolicies|Actions"
msgstr "动作"
-msgid "NetworkPolicies|All selected"
+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 ""
+msgstr "å…许"
msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
-msgstr ""
+msgstr "å…许从%{ruleSelector}到%{selector}于%{ports}的所有入站æµé‡"
msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
-msgstr ""
+msgstr "å…许从%{selector}到%{ruleSelector}于%{ports}的所有出站æµé‡"
msgid "NetworkPolicies|Are you sure you want to delete this policy? This action cannot be undone."
-msgstr ""
+msgstr "您确定è¦åˆ é™¤æ­¤ç­–ç•¥å—?此æ“作ä¸èƒ½æ’¤æ¶ˆã€‚"
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr "选择是å¦å¼ºåˆ¶æ­¤ç­–略。"
@@ -18018,19 +18472,19 @@ msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr "定义此策略的ä½ç½®ï¼Œæ¡ä»¶å’Œæ“作。"
msgid "NetworkPolicies|Delete policy"
-msgstr ""
+msgstr "删除策略"
msgid "NetworkPolicies|Delete policy: %{policy}"
-msgstr ""
+msgstr "删除策略: %{policy}"
msgid "NetworkPolicies|Deny all traffic"
-msgstr ""
+msgstr "æ‹’ç»æ‰€æœ‰æµé‡"
msgid "NetworkPolicies|Description"
msgstr "æè¿°"
msgid "NetworkPolicies|Edit policy"
-msgstr ""
+msgstr "编辑策略"
msgid "NetworkPolicies|Editor mode"
msgstr "编辑模å¼"
@@ -18042,7 +18496,7 @@ msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr "环境没有部署平å°"
msgid "NetworkPolicies|IP/subnet"
-msgstr ""
+msgstr "IP/å­ç½‘"
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 "如果您正在使用Auto DevOps,并在此处改å˜äº†ç­–略,您的%{monospacedStart}auto-deploy-values.yaml%{monospacedEnd}文件将ä¸ä¼šè¢«æ›´æ–°ã€‚Auto DevOps用户需è¦æŒ‰ç…§%{linkStart}容器网络策略文档%{linkEnd}进行修改。"
@@ -18060,13 +18514,13 @@ msgid "NetworkPolicies|Name"
msgstr "å称"
msgid "NetworkPolicies|Namespace"
-msgstr ""
+msgstr "命å空间"
msgid "NetworkPolicies|Network Policy"
msgstr "网络政策"
msgid "NetworkPolicies|Network traffic"
-msgstr ""
+msgstr "网络æµé‡"
msgid "NetworkPolicies|New policy"
msgstr "新建策略"
@@ -18075,7 +18529,7 @@ msgid "NetworkPolicies|No policies detected"
msgstr "未检测到策略"
msgid "NetworkPolicies|None selected"
-msgstr ""
+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进行网络端点通信。"
@@ -18102,19 +18556,19 @@ msgid "NetworkPolicies|Policy type"
msgstr "策略类型"
msgid "NetworkPolicies|Rule"
-msgstr ""
+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 ""
+msgstr "规则模å¼æ— æ³•ç”¨äºŽæ­¤ç­–略。在æŸäº›æƒ…况下,我们无法将YAML文件解æžå›žåˆ°è§„则编辑器中。"
msgid "NetworkPolicies|Rules"
msgstr "规则"
msgid "NetworkPolicies|Save changes"
-msgstr ""
+msgstr "ä¿å­˜æ›´æ”¹"
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr "出现错误,未能更新策略"
@@ -18126,55 +18580,55 @@ msgid "NetworkPolicies|Status"
msgstr "状æ€"
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
+msgstr "ä¸åŒ¹é…任何规则的æµé‡å°†è¢«é˜»æ­¢ã€‚"
msgid "NetworkPolicies|Unable to parse policy"
-msgstr ""
+msgstr "无法解æžç­–ç•¥"
msgid "NetworkPolicies|YAML editor"
msgstr "YAML编辑"
msgid "NetworkPolicies|all DNS names"
-msgstr ""
+msgstr "所有DNS域å"
msgid "NetworkPolicies|all IP addresses"
-msgstr ""
+msgstr "所有IP地å€"
msgid "NetworkPolicies|any pod"
-msgstr ""
+msgstr "任何pod"
msgid "NetworkPolicies|any port"
-msgstr ""
+msgstr "ä»»æ„端å£"
msgid "NetworkPolicies|domain name"
-msgstr ""
+msgstr "域å"
msgid "NetworkPolicies|entity"
-msgstr ""
+msgstr "实体"
msgid "NetworkPolicies|inbound to"
-msgstr ""
+msgstr "传入到"
msgid "NetworkPolicies|nowhere"
-msgstr ""
+msgstr "æ— ä½ç½®"
msgid "NetworkPolicies|outbound from"
-msgstr ""
+msgstr "外å‘自"
msgid "NetworkPolicies|pod with labels"
-msgstr ""
+msgstr "带有标签的pod"
msgid "NetworkPolicies|pods %{pods}"
-msgstr ""
+msgstr "pods %{pods}"
msgid "NetworkPolicies|pods with labels"
-msgstr ""
+msgstr "带有标签的pod"
msgid "NetworkPolicies|ports %{ports}"
-msgstr ""
+msgstr "ç«¯å£ %{ports}"
msgid "NetworkPolicies|ports/protocols"
-msgstr ""
+msgstr "端å£/åè®®"
msgid "Never"
msgstr "从ä¸"
@@ -18183,7 +18637,7 @@ msgid "New"
msgstr "新增"
msgid "New %{issueType}"
-msgstr ""
+msgstr "新建%{issueType}"
msgid "New Application"
msgstr "新建应用"
@@ -18247,7 +18701,7 @@ msgid "New Snippet"
msgstr "新建代ç ç‰‡æ®µ"
msgid "New Test Case"
-msgstr ""
+msgstr "新测试用例"
msgid "New User"
msgstr "新建用户"
@@ -18288,6 +18742,12 @@ 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 "已生æˆæ–°çš„è¿è¡ŒçŠ¶å†µæ£€æŸ¥è®¿é—®ä»¤ç‰Œï¼"
@@ -18334,7 +18794,7 @@ msgid "New response for issue #%{issue_iid}:"
msgstr "议题#%{issue_iid}的新回å¤ï¼š"
msgid "New runner. Has not connected yet"
-msgstr ""
+msgstr "新Runner。尚未连接"
msgid "New runners registration token has been generated!"
msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
@@ -18352,7 +18812,7 @@ msgid "New tag"
msgstr "新建标签"
msgid "New test case"
-msgstr ""
+msgstr "新测试用例"
msgid "New users set to external"
msgstr "新用户设置为外部"
@@ -18426,7 +18886,7 @@ msgstr "未å‘现分支"
msgid "No changes"
msgstr "æ— å˜æ›´å†…容"
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18529,7 +18989,7 @@ msgid "No matching results for \"%{query}\""
msgstr "没有与“%{query}â€åŒ¹é…的结果"
msgid "No members found"
-msgstr ""
+msgstr "未找到æˆå‘˜"
msgid "No merge requests found"
msgstr "找ä¸åˆ°åˆå¹¶è¯·æ±‚"
@@ -18553,7 +19013,7 @@ msgid "No parent group"
msgstr "父群组ä¸å­˜åœ¨"
msgid "No plan"
-msgstr ""
+msgstr "没有计划"
msgid "No pods available"
msgstr "没有å¯ç”¨çš„pod"
@@ -18583,7 +19043,7 @@ msgid "No required pipeline"
msgstr "没有必需的æµæ°´çº¿"
msgid "No runner executable"
-msgstr ""
+msgstr "æ— runnerå¯æ‰§è¡Œæ–‡ä»¶"
msgid "No runners found"
msgstr "未找到Runner"
@@ -18592,7 +19052,7 @@ msgid "No schedules"
msgstr "无计划"
msgid "No source selected"
-msgstr ""
+msgstr "未选择æº"
msgid "No stack trace for this error"
msgstr "没有此错误的堆栈跟踪"
@@ -18646,22 +19106,22 @@ msgid "None"
msgstr "æ— "
msgid "None of the group milestones have the same project as the release"
-msgstr ""
+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 ""
+msgstr "并éžæ‰€æœ‰æµè§ˆå™¨éƒ½æ”¯æŒU2F设备。因此,我们需è¦æ‚¨é¦–先设置一个åŒé‡èº«ä»½éªŒè¯åº”用。这样å³ä½¿æ‚¨ä½¿ç”¨çš„æµè§ˆå™¨ä¸å—支æŒï¼Œæ‚¨ä¹Ÿå¯ä»¥ç™»å½•ã€‚"
msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
-msgstr ""
+msgstr "并éžæ‰€æœ‰æµè§ˆå™¨éƒ½æ”¯æŒWebAuthn。因此,我们需è¦æ‚¨é¦–先设置一个åŒé‡èº«ä»½éªŒè¯åº”用。这样å³ä½¿æ‚¨ä½¿ç”¨çš„æµè§ˆå™¨ä¸å—支æŒï¼Œæ‚¨ä¹Ÿå¯ä»¥ç™»å½•ã€‚"
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 ""
+msgstr "ä¸é€‚用于个人命å空间项目,这些项目的删除请求会立å³æ‰§è¡Œã€‚"
msgid "Not available"
msgstr "æ•°æ®ä¸è¶³"
@@ -18672,6 +19132,9 @@ msgstr "对ç§æœ‰é¡¹ç›®ä¸å¯ç”¨"
msgid "Not available for protected branches"
msgstr "对å—ä¿æŠ¤çš„分支ä¸å¯ç”¨"
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "éžç§å¯†"
@@ -18682,7 +19145,7 @@ msgid "Not found."
msgstr "未找到。"
msgid "Not permitted to destroy framework"
-msgstr ""
+msgstr "没有æƒé™åˆ é™¤æ¡†æž¶"
msgid "Not ready yet. Try again later."
msgstr "还没有准备好。请ç¨åŽå†è¯•ã€‚"
@@ -18690,6 +19153,9 @@ msgstr "还没有准备好。请ç¨åŽå†è¯•ã€‚"
msgid "Not started"
msgstr "未开始"
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr "备注"
@@ -18697,7 +19163,7 @@ msgid "Note parameters are invalid: %{errors}"
msgstr "说明å‚数无效: %{errors}"
msgid "Note that pushing to GitLab requires write access to this repository."
-msgstr ""
+msgstr "请注æ„,推é€åˆ°GitLab需è¦å¯¹æ­¤ä»“库的写æƒé™ã€‚"
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 "请注æ„,此邀请已å‘é€è‡³%{mail_to_invite_email},但您当å‰ä½¿ç”¨ç”µå­é‚®ä»¶%{mail_to_current_user}以%{link_to_current_user} 登录。"
@@ -18739,7 +19205,7 @@ msgid "Notes|This comment has changed since you started editing, please review t
msgstr "自您开始编辑以æ¥ï¼Œæ­¤è¯„论已更改,请查看 %{open_link}更新过的评论%{close_link} 以确ä¿ä¿¡æ¯ä¸ä¼šä¸¢å¤±"
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 ""
+msgstr "您åªèƒ½åœ¨ä¿¡æ¯æµä¸­çœ‹åˆ°%{boldStart}其他活动%{boldEnd} 。è¦æ·»åŠ è¯„论,请切æ¢åˆ°ä»¥ä¸‹é€‰é¡¹ä¹‹ä¸€ã€‚"
msgid "Nothing found…"
msgstr "未找到任何信æ¯â€¦"
@@ -18763,7 +19229,7 @@ msgid "Notification settings saved"
msgstr "通知设置已ä¿å­˜"
msgid "NotificationEvent|Change reviewer merge request"
-msgstr ""
+msgstr "更改审核者åˆå¹¶è¯·æ±‚"
msgid "NotificationEvent|Close issue"
msgstr "关闭议题"
@@ -18778,13 +19244,13 @@ msgid "NotificationEvent|Fixed pipeline"
msgstr "ä¿®å¤çš„æµæ°´çº¿"
msgid "NotificationEvent|Issue due"
-msgstr ""
+msgstr "到期议题"
msgid "NotificationEvent|Merge merge request"
msgstr "åˆå¹¶è¯·æ±‚被åˆå¹¶"
msgid "NotificationEvent|Moved project"
-msgstr ""
+msgstr "移动项目"
msgid "NotificationEvent|New epic"
msgstr "æ–°å²è¯—"
@@ -18802,7 +19268,7 @@ msgid "NotificationEvent|New release"
msgstr "æ–°å‘布"
msgid "NotificationEvent|Push to merge request"
-msgstr ""
+msgstr "推é€åˆ°åˆå¹¶è¯·æ±‚"
msgid "NotificationEvent|Reassign issue"
msgstr "é‡æ–°æŒ‡æ´¾è®®é¢˜"
@@ -18814,7 +19280,7 @@ msgid "NotificationEvent|Reopen issue"
msgstr "é‡å¯è®®é¢˜"
msgid "NotificationEvent|Reopen merge request"
-msgstr ""
+msgstr "é‡æ–°æ‰“å¼€åˆå¹¶è¯·æ±‚"
msgid "NotificationEvent|Successful pipeline"
msgstr "æµæ°´çº¿æˆåŠŸå®Œæˆ"
@@ -18927,6 +19393,9 @@ msgstr "关闭"
msgid "Oh no!"
msgstr "哦ä¸ï¼"
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr "最早在å‰"
@@ -18937,64 +19406,154 @@ msgid "Omnibus Protected Paths throttle is active, and takes priority over these
msgstr "Omnibusä¿æŠ¤è·¯å¾„阈值已å¯ç”¨ï¼Œä¸”优先级高于这些设置。从12.4èµ·Omnibus阈值已弃用,并将在未æ¥ç‰ˆæœ¬ä¸­ç§»é™¤ã€‚请å‚阅%{relative_url_link_start}è¿ç§»ä¿æŠ¤è·¯å¾„文档%{relative_url_link_end}。"
msgid "On"
-msgstr ""
+msgstr "于"
msgid "On track"
msgstr "进度正常"
msgid "On-call Schedules"
-msgstr ""
+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 "在GitLab中创建待命计划"
+
+msgid "OnCallSchedules|Delete rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Delete schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Edit rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
msgid "OnCallSchedules|Failed to add schedule"
+msgstr "添加计划失败"
+
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
+msgstr "选择时区"
msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
+msgstr "设置所有å‚与者的默认时区"
+
+msgid "OnCallSchedules|Successfully created a new rotation"
msgstr ""
-msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgid "OnCallSchedules|Successfully edited your rotation"
msgstr ""
-msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
+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 a new scanner profile"
-msgstr ""
+msgstr "创建一个新的扫æ工具é…置文件"
msgid "OnDemandScans|Create a 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 profiles"
+msgstr "管ç†é…置文件"
+
+msgid "OnDemandScans|My daily scan"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
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 ""
+msgstr "å°šæ— é…置文件。如需创建新扫æ,需è¦è‡³å°‘有一个完整的扫æ工具é…置文件。"
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
-msgstr ""
+msgstr "å°šæ— é…置文件。如需创建新扫æ,需è¦è‡³å°‘有一个完整的站点é…置文件。"
msgid "OnDemandScans|On-demand Scans"
msgstr "按需扫æ"
@@ -19003,31 +19562,40 @@ msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulne
msgstr "按需扫æ在DevOps周期之外è¿è¡Œï¼Œå¹¶åœ¨æ‚¨çš„项目中å‘现æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}"
msgid "OnDemandScans|Run scan"
+msgstr "è¿è¡Œæ‰«æ"
+
+msgid "OnDemandScans|Save and run scan"
msgstr ""
-msgid "OnDemandScans|Scanner profile"
+msgid "OnDemandScans|Save scan"
msgstr ""
-msgid "OnDemandScans|Select one of the existing profiles"
+msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scanner profile"
+msgstr "扫æ工具é…ç½®"
+
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr "选择一个现有的é…置文件"
+
msgid "OnDemandScans|Site profile"
-msgstr ""
+msgstr "站点é…ç½®"
msgid "OnDemandScans|Use existing scanner profile"
-msgstr ""
+msgstr "使用现有的站点é…ç½®"
msgid "OnDemandScans|Use existing site profile"
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥è¿›è¡Œè¢«åŠ¨æ‰«æ或验è¯æ‚¨é€‰æ‹©çš„站点é…置中的目标网站。%{docsLinkStart}了解更多关于站点验è¯çš„ä¿¡æ¯ã€‚%{docsLinkEnd}"
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
-msgstr ""
+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 ""
+msgstr "一旦项目被永久删除将%{strongStart}无法æ¢å¤%{strongEnd}。永久删除此项目将%{strongStart}ç«‹å³åˆ é™¤%{strongEnd}其仓库和%{strongStart}所有相关的资æº%{strongEnd}包括议题ã€åˆå¹¶è¯·æ±‚等。"
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 "项目永久删除åŽï¼Œå°†æ— æ³•æ¢å¤ã€‚您将丢失该项目的仓库和所有内容:议题,åˆå¹¶è¯·æ±‚等。"
@@ -19036,7 +19604,7 @@ msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_st
msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡SSH进行镜åƒã€‚点击%{link_start}此处%{link_end}了解更多."
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 ""
+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 "导出的文件准备就绪åŽï¼Œæ‚¨å°†æ”¶åˆ°å¸¦æœ‰ä¸‹è½½é“¾æŽ¥çš„通知电å­é‚®ä»¶ï¼Œæˆ–者您å¯ä»¥ä»Žæ­¤é¡µé¢ä¸‹è½½ã€‚"
@@ -19100,7 +19668,7 @@ 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 ""
+msgstr "åªæœ‰åœ¨é‡‘牌许å¯ä¸‹åˆ›å»ºçš„项目å¯ä»¥åœ¨å®‰å…¨ä»ªè¡¨æ¿ä¸­æ˜¾ç¤ºã€‚"
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr "åªæœ‰å…·æœ‰è¿™äº›åŸŸå电å­é‚®ä»¶åœ°å€çš„已验è¯ç”¨æˆ·æ‰èƒ½æ·»åŠ åˆ°ç¾¤ç»„。"
@@ -19121,7 +19689,7 @@ msgid "Open comment type dropdown"
msgstr "打开评论类型下拉列表"
msgid "Open epics"
-msgstr ""
+msgstr "打开å²è¯—"
msgid "Open errors"
msgstr "打开错误"
@@ -19139,13 +19707,13 @@ msgid "Open raw"
msgstr "打开原始文件"
msgid "Open registration is enabled on your instance."
-msgstr ""
+msgstr "您实例上å¯ç”¨äº†å¼€æ”¾æ³¨å†Œã€‚"
msgid "Open sidebar"
msgstr "打开侧边æ "
msgid "Open: %{open}"
-msgstr ""
+msgstr "å¼€å¯: %{open}"
msgid "Opened"
msgstr "已打开"
@@ -19217,7 +19785,7 @@ msgid "Origin"
msgstr "æº"
msgid "Orphaned member"
-msgstr ""
+msgstr "孤儿æˆå‘˜"
msgid "Other Labels"
msgstr "其他标记"
@@ -19235,7 +19803,7 @@ msgid "Other visibility settings have been disabled by the administrator."
msgstr "其他å¯è§æ€§è®¾ç½®å·²è¢«ç®¡ç†å‘˜ç¦ç”¨ã€‚"
msgid "Our documentation includes an example DevOps Score report."
-msgstr ""
+msgstr "我们的文档包å«ä¸€ä¸ªDevOps评分报告的示例。"
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr "ä¸ç¬¦åˆè¯¥é¡¹ç›®æ”¿ç­–,应予以删除"
@@ -19253,7 +19821,7 @@ msgid "Outdent"
msgstr "å‡å°‘缩进"
msgid "Overall Activity"
-msgstr ""
+msgstr "活动总计"
msgid "Overridden"
msgstr "覆盖"
@@ -19265,7 +19833,7 @@ msgid "Overwrite diverged branches"
msgstr "覆盖分å‰åˆ†æ”¯"
msgid "Owned by %{image_tag}"
-msgstr ""
+msgstr "由%{image_tag}拥有"
msgid "Owned by anyone"
msgstr "拥有者为任何人"
@@ -19289,7 +19857,7 @@ msgid "Package deleted successfully"
msgstr "包已æˆåŠŸåˆ é™¤"
msgid "Package file size limits"
-msgstr ""
+msgstr "软件包文件大å°é™åˆ¶"
msgid "Package recipe already exists"
msgstr "软件包构æˆå·²å­˜åœ¨"
@@ -19297,6 +19865,9 @@ msgstr "软件包构æˆå·²å­˜åœ¨"
msgid "Package type must be Conan"
msgstr "包类型必须是Conan"
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "包类型必须是Maven"
@@ -19306,11 +19877,8 @@ msgstr "包类型必须是Nuget"
msgid "Package type must be PyPi"
msgstr "包类型必须是PyPi"
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr "%{name}版 %{version}创建于%{datetime}"
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
-msgstr "%{name}版 %{version}更新于%{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
+msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr "添加Conan远端"
@@ -19319,7 +19887,7 @@ msgid "PackageRegistry|Add NuGet Source"
msgstr "添加Nugetæº"
msgid "PackageRegistry|Add composer registry"
-msgstr ""
+msgstr "添加composer注册表"
msgid "PackageRegistry|App group: %{group}"
msgstr "应用分组: %{group}"
@@ -19327,8 +19895,8 @@ msgstr "应用分组: %{group}"
msgid "PackageRegistry|App name: %{name}"
msgstr "应用å称: %{name}"
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
-msgstr "分支%{branch}上的æ交%{link}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
+msgstr ""
msgid "PackageRegistry|Composer"
msgstr "Composer"
@@ -19376,10 +19944,10 @@ msgid "PackageRegistry|Copy npm setup command"
msgstr "å¤åˆ¶npm设置命令"
msgid "PackageRegistry|Copy registry include"
-msgstr ""
+msgstr "å¤åˆ¶æ³¨å†Œè¡¨åŒ…å«"
msgid "PackageRegistry|Copy require package include"
-msgstr ""
+msgstr "å¤åˆ¶æ‰€éœ€çš„软件包并包å«"
msgid "PackageRegistry|Copy yarn command"
msgstr "å¤åˆ¶yarn命令"
@@ -19387,6 +19955,9 @@ msgstr "å¤åˆ¶yarn命令"
msgid "PackageRegistry|Copy yarn setup command"
msgstr "å¤åˆ¶yarn设置命令"
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr "删除软件包版本"
@@ -19397,7 +19968,7 @@ msgid "PackageRegistry|Filter by name"
msgstr "按å称筛选"
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
-msgstr ""
+msgstr "关于Composer注册表的更多信æ¯ï¼Œ%{linkStart}请è§æ–‡æ¡£ã€‚%{linkEnd}"
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "关于Conan注册表的更多信æ¯ï¼Œ %{linkStart}请è§æ–‡æ¡£%{linkEnd}。"
@@ -19412,7 +19983,7 @@ msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}se
msgstr "关于PyPi注册表的更多信æ¯ï¼Œ%{linkStart}请è§æ–‡æ¡£%{linkEnd}。"
msgid "PackageRegistry|Generic"
-msgstr ""
+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}文件中。"
@@ -19421,7 +19992,7 @@ msgid "PackageRegistry|If you haven't already done so, you will need to add the
msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}pom.xml%{codeEnd}文件中。"
msgid "PackageRegistry|Install package version"
-msgstr ""
+msgstr "安装软件包版本"
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "了解如何使用GitLab%{noPackagesLinkStart}å‘布和共享您的软件包%{noPackagesLinkEnd}。"
@@ -19451,22 +20022,28 @@ msgid "PackageRegistry|NuGet Command"
msgstr "NuGet命令"
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 "Pip命令"
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
-msgstr "æµæ°´çº¿%{link}ç”±%{author}触å‘于%{datetime}"
-
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "å‘布和分享å„ç§å¸¸è§çš„软件包管ç†å·¥å…·æ”¯æŒçš„软件包。 %{docLinkStart}更多信æ¯%{docLinkEnd}"
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr "于%{datetime}å‘布到%{project}软件包注册表"
msgid "PackageRegistry|PyPI"
-msgstr ""
+msgstr "PyPI"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr "æž„æˆ: %{recipe}"
@@ -19514,13 +20091,13 @@ msgid "PackageRegistry|You may also need to setup authentication using an auth t
msgstr "您å¯èƒ½è¿˜éœ€è¦ä½¿ç”¨ä»¤ç‰Œè®¾ç½®èº«ä»½éªŒè¯ã€‚%{linkStart}请å‚阅文档%{linkEnd}以了解更多信æ¯ã€‚"
msgid "PackageRegistry|npm command"
-msgstr ""
+msgstr "npm命令"
msgid "PackageRegistry|published by %{author}"
msgstr "ç”±%{author}å‘布"
msgid "PackageRegistry|yarn command"
-msgstr ""
+msgstr "yarn命令"
msgid "PackageType|Composer"
msgstr "Composer"
@@ -19529,7 +20106,7 @@ msgid "PackageType|Conan"
msgstr "Conan"
msgid "PackageType|Generic"
-msgstr ""
+msgstr "通用"
msgid "PackageType|Maven"
msgstr "Maven"
@@ -19541,7 +20118,7 @@ msgid "PackageType|NuGet"
msgstr "NuGet"
msgid "PackageType|PyPI"
-msgstr ""
+msgstr "PyPI"
msgid "Packages"
msgstr "软件包"
@@ -19553,13 +20130,13 @@ msgid "Page not found"
msgstr "找ä¸åˆ°é¡µé¢"
msgid "Page settings"
-msgstr ""
+msgstr "页é¢è®¾ç½®"
msgid "PagerDutySettings|Active"
msgstr "å¯ç”¨"
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
-msgstr "按照%{docsLink}为æ¯ä¸ªPagerDuty事件创建一个GitLab议题"
+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 "æ›´æ–°Webhook网å€å¤±è´¥"
@@ -19570,18 +20147,12 @@ msgstr "é‡ç½®webhook网å€"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr "é‡ç½®æ­¤é¡¹ç›®çš„webhook网å€å°†éœ€è¦åœ¨PagerDuty中更新此集æˆè®¾ç½®ã€‚"
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr "设置对PagerDutyçš„Webhook将自动为æ¯ä¸ªPagerDuty事件创建一个GitLab议题。"
-
msgid "PagerDutySettings|Webhook URL"
msgstr "Webhook网å€"
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr "Webhook网å€æ›´æ–°æˆåŠŸ"
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr "在PagerDuty中é…ç½®Webhook"
-
msgid "Pages"
msgstr "Pages"
@@ -19667,7 +20238,7 @@ msgid "Password successfully changed"
msgstr "密ç ä¿®æ”¹æˆåŠŸ"
msgid "Password was successfully updated. Please sign in again."
-msgstr ""
+msgstr "密ç æ›´æ–°æˆåŠŸã€‚请é‡æ–°ç™»å½•ã€‚"
msgid "Passwords should be unique and not used for any other sites or services."
msgstr "密ç åº”唯一并未用于任何其他网站或æœåŠ¡ã€‚"
@@ -19694,7 +20265,7 @@ 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 ""
+msgstr "粘贴您的SSH 公钥,通常包å«åœ¨æ–‡ä»¶ '~/.ssh/id_ed25519.pub' 或 '~/.ssh/id_rsa.pub' 中,并以“ssh-ed25519â€æˆ–“ssh-rsaâ€å¼€å¤´ã€‚ä¸è¦ç²˜è´´æ‚¨çš„SSHç§é’¥ï¼Œå› ä¸ºè¿™ä¼šæ³„露您的身份信æ¯ã€‚"
msgid "Patch to apply"
msgstr "è¦åº”用的补ä¸"
@@ -19711,17 +20282,20 @@ msgstr "路径å¯ä»¥åŒ…å«é€šé…符,如*/welcome"
msgid "Pause"
msgstr "æš‚åœ"
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr "æš‚åœå¤åˆ¶"
-msgid "Paused Runners don't accept new jobs"
-msgstr "æš‚åœçš„ Runner ä¸æŽ¥å—新作业"
+msgid "Paused runners don't accept new jobs"
+msgstr ""
msgid "Pending"
msgstr "等待中"
msgid "Pending comments"
-msgstr ""
+msgstr "待处ç†çš„评论"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "æƒé™ä¸è¶³çš„用户将无法收到通知,也无法评论。"
@@ -19730,7 +20304,7 @@ msgid "People without permission will never get a notification."
msgstr "无相关æƒé™çš„用户将ä¸ä¼šæ”¶åˆ°é€šçŸ¥ã€‚"
msgid "Percent rollout must be an integer number between 0 and 100"
-msgstr ""
+msgstr "百分比上线必须是0-100之间的整数"
msgid "Percentage"
msgstr "百分比"
@@ -19783,6 +20357,9 @@ msgstr "æƒé™ï¼ŒLFS,2FA"
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 "ä¸å…许创建个人项目。如有疑问,请è”系您的管ç†å‘˜"
@@ -19819,9 +20396,12 @@ msgstr "æµæ°´çº¿è®¡åˆ’"
msgid "Pipeline minutes quota"
msgstr "æµæ°´çº¿åˆ†é’Ÿæ•°é…é¢"
-msgid "Pipeline ran in fork of project"
+msgid "Pipeline minutes quota:"
msgstr ""
+msgid "Pipeline ran in fork of project"
+msgstr "æµæ°´çº¿è¿è¡Œåœ¨é¡¹ç›®æ´¾ç”Ÿä¸­"
+
msgid "Pipeline subscriptions"
msgstr "æµæ°´çº¿è®¢é˜…"
@@ -19831,6 +20411,15 @@ msgstr "æµæ°´çº¿è§¦å‘器"
msgid "Pipeline: %{status}"
msgstr "æµæ°´çº¿: %{status}"
+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 "CI/CD分æž"
@@ -19846,7 +20435,7 @@ msgstr "æˆåŠŸçŽ‡ï¼š"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸï¼š"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19925,7 +20514,7 @@ 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 ""
+msgstr "通过撤销触å‘器将会影å“任何正在调用它的应用。您确定å—?"
msgid "Pipelines|CI Lint"
msgstr "CI é…置检查(CI Lint)"
@@ -19940,20 +20529,26 @@ msgid "Pipelines|Continuous Integration can help catch bugs by running your test
msgstr "æŒç»­é›†æˆå¯ä»¥é€šè¿‡è‡ªåŠ¨è¿è¡Œæµ‹è¯•æ¥å¸®åŠ©æ£€æµ‹ä»£ç ç¼ºé™·ï¼Œè€ŒæŒç»­éƒ¨ç½²å¯ä»¥å¸®åŠ©æ‚¨å‘生产环境交付代ç ã€‚"
msgid "Pipelines|Copy trigger token"
-msgstr ""
+msgstr "å¤åˆ¶è§¦å‘令牌"
msgid "Pipelines|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "Pipelines|Edit"
-msgstr ""
+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 "群组%{namespace_name}当å‰å‰©ä½™%{percentage}%%或更少的共享Runneræµæ°´çº¿åˆ†é’Ÿæ•°ã€‚一旦用完,其下项目将无法è¿è¡Œæ–°çš„作业或æµæ°´çº¿ã€‚"
@@ -19967,6 +20562,9 @@ msgid "Pipelines|It is recommended the code is reviewed thoroughly before runnin
msgstr "建议在使用父项目的CI资æºè¿è¡Œæ­¤æµæ°´çº¿ä¹‹å‰å¯¹ä»£ç è¿›è¡Œè¯¦å°½çš„审核。"
msgid "Pipelines|Last Used"
+msgstr "最近使用"
+
+msgid "Pipelines|Lint"
msgstr ""
msgid "Pipelines|Loading Pipelines"
@@ -19976,25 +20574,25 @@ msgid "Pipelines|More Information"
msgstr "更多信æ¯"
msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
+msgstr "在这个仓库中找ä¸åˆ°CI文件,请添加一个。"
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
-msgstr ""
+msgstr "尚未创建触å‘器。请使用上é¢çš„表å•æ·»åŠ è§¦å‘器。"
msgid "Pipelines|Owner"
-msgstr ""
+msgstr "所有者"
msgid "Pipelines|Pipeline Editor"
-msgstr ""
+msgstr "æµæ°´çº¿ç¼–辑器"
msgid "Pipelines|Project cache successfully reset."
msgstr "项目缓存é‡ç½®æˆåŠŸã€‚"
msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
+msgstr "仓库没有默认分支,请设置一个。"
msgid "Pipelines|Revoke"
-msgstr ""
+msgstr "撤销"
msgid "Pipelines|Run Pipeline"
msgstr "è¿è¡Œæµæ°´çº¿"
@@ -20003,10 +20601,10 @@ msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr "清ç†runner缓存时å‘生错误。"
msgid "Pipelines|The CI configuration was not loaded, please try again."
-msgstr ""
+msgstr "CIé…置未加载,请é‡è¯•ã€‚"
msgid "Pipelines|The GitLab CI configuration could not be updated."
-msgstr ""
+msgstr "GitLab CIé…置无法更新。"
msgid "Pipelines|There are currently no finished pipelines."
msgstr "ç›®å‰æ²¡æœ‰å·²å®Œæˆçš„æµæ°´çº¿ã€‚"
@@ -20017,6 +20615,18 @@ 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 "æ­¤æµæ°´çº¿ä¸ºå…·æœ‰çˆ¶æµæ°´çº¿çš„å­æµæ°´çº¿"
@@ -20027,19 +20637,22 @@ msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "此项目当å‰æœªé…ç½®è¿è¡Œæµæ°´çº¿ã€‚"
msgid "Pipelines|Token"
-msgstr ""
+msgstr "令牌"
msgid "Pipelines|Trigger user has insufficient permissions to project"
+msgstr "触å‘用户没有足够的项目æƒé™"
+
+msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
msgid "Pipelines|Visualize"
-msgstr ""
+msgstr "å¯è§†åŒ–"
msgid "Pipelines|Write pipeline configuration"
-msgstr ""
+msgstr "编写æµæ°´çº¿é…ç½®"
msgid "Pipelines|invalid"
-msgstr ""
+msgstr "无效"
msgid "Pipelines|parent"
msgstr "父级"
@@ -20234,10 +20847,10 @@ msgid "Please complete your profile with email address"
msgstr "请在您的个人资料中填写电å­é‚®ä»¶åœ°å€"
msgid "Please contact your GitLab administrator if you think this is an error."
-msgstr ""
+msgstr "如果您认为这是一个错误,请è”系您的GitLab 管ç†å‘˜ã€‚"
msgid "Please contact your administrator with any questions."
-msgstr ""
+msgstr "如有任何问题,请è”系您的管ç†å‘˜ã€‚"
msgid "Please contact your administrator."
msgstr "请è”系您的管ç†å‘˜ã€‚"
@@ -20245,6 +20858,9 @@ msgstr "请è”系您的管ç†å‘˜ã€‚"
msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
msgstr "请将他们%{linkStart}转æ¢ä¸ºGit%{linkEnd},然åŽå†æ¬¡æ‰§è¡Œ%{linkToImportFlow}。"
+msgid "Please copy, download, or print your recovery codes before proceeding."
+msgstr ""
+
msgid "Please create a password for your new account."
msgstr "请为您的新å¸æˆ·åˆ›å»ºå¯†ç ã€‚"
@@ -20267,6 +20883,9 @@ msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr "请输入大于%{number}(æ¥è‡ªé¡¹ç›®è®¾ç½®)çš„æ•°å­—"
msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr "请输入一个有效的URLæ ¼å¼ï¼Œä¾‹å¦‚:http://www.example.com/home"
+
+msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
msgstr ""
msgid "Please enter a valid number"
@@ -20279,7 +20898,7 @@ msgid "Please fill in a descriptive name for your group."
msgstr "请为您的群组填写æ述性å称。"
msgid "Please fill out this field."
-msgstr ""
+msgstr "请填写此字段。"
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
msgstr "请按照%{link_start}Let's Encrypt故障排除指å—%{link_end}æ¥é‡æ–°èŽ·å–加密è¯ä¹¦ã€‚"
@@ -20294,7 +20913,7 @@ msgid "Please note that this application is not provided by GitLab and you shoul
msgstr "请注æ„,GitLabä¸æ供此应用程åºï¼Œæ‚¨åº”该在å…许访问之å‰éªŒè¯å…¶çœŸå®žæ€§ã€‚"
msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
+msgstr "请仅在安装æ’件åŽå¯ç”¨æœç´¢ï¼Œå¯ç”¨ç´¢å¼•å¹¶é‡æ–°åˆ›å»ºç´¢å¼•"
msgid "Please provide a name"
msgstr "请æä¾›å称"
@@ -20303,7 +20922,7 @@ msgid "Please provide a valid URL"
msgstr "请æ供有效的网å€"
msgid "Please provide a valid YouTube URL or ID"
-msgstr ""
+msgstr "请æ供一个有效的YouTube URL或ID"
msgid "Please provide a valid email address."
msgstr "请æ供有效的电å­é‚®ä»¶åœ°å€ã€‚"
@@ -20312,7 +20931,7 @@ msgid "Please provide attributes to update"
msgstr "请æä¾›è¦æ›´æ–°çš„属性"
msgid "Please reach out if you have any questions and we'll be happy to assist."
-msgstr ""
+msgstr "如果您有任何疑问,请è”系我们,我们将竭诚为您æœåŠ¡ã€‚"
msgid "Please refer to %{docs_url}"
msgstr "请å‚考%{docs_url}"
@@ -20345,7 +20964,7 @@ 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 ""
+msgstr "请在%{linkStart}此议题中%{linkEnd}分享您对%{featureName}çš„å馈,以帮助我们改善体验。"
msgid "Please solve the reCAPTCHA"
msgstr "请填写验è¯ç ã€‚"
@@ -20405,7 +21024,7 @@ msgid "Preferences|Choose what content you want to see on a project’s overview
msgstr "选择项目概览页é¢ä¸­æ‚¨æƒ³çœ‹åˆ°çš„内容。"
msgid "Preferences|Choose what content you want to see on your homepage."
-msgstr ""
+msgstr "选择您想è¦åœ¨é¦–页上看到的内容。"
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "自定义应用程åºé¡¶éƒ¨å’Œå¯¼èˆªä¾§è¾¹æ çš„外观。"
@@ -20417,7 +21036,7 @@ msgid "Preferences|For example: 30 mins ago."
msgstr "例如:30分钟å‰"
msgid "Preferences|Homepage content"
-msgstr ""
+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 "一次仅显示一个文件,而ä¸æ˜¯æ‰€æœ‰æ›´æ”¹çš„文件。è¦åœ¨æ–‡ä»¶ä¹‹é—´åˆ‡æ¢ï¼Œè¯·ä½¿ç”¨æ–‡ä»¶æµè§ˆå™¨ã€‚"
@@ -20479,14 +21098,17 @@ msgstr "按 %{key}-C å¤åˆ¶"
msgid "Prev"
msgstr "上一个"
-msgid "Prevent adding new members to project membership within this group"
-msgstr "ç¦æ­¢å‘当å‰ç¾¤ç»„中的项目添加新æˆå‘˜"
+msgid "Prevent MR approvals by author."
+msgstr ""
-msgid "Prevent approval of merge requests by merge request 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 approval of merge requests by merge request committers"
-msgstr "阻止åˆå¹¶è¯·æ±‚æ交者核准åˆå¹¶è¯·æ±‚"
+msgid "Prevent adding new members to project membership within this group"
+msgstr "ç¦æ­¢å‘当å‰ç¾¤ç»„中的项目添加新æˆå‘˜"
msgid "Prevent environment from auto-stopping"
msgstr "防止环境自动终止"
@@ -20497,7 +21119,7 @@ msgstr "阻止项目派生到当å‰ç¾¤ç»„以外"
msgid "Prevent users from changing their profile name"
msgstr "ç¦æ­¢ç”¨æˆ·æ›´æ”¹é…置文件å称"
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr "上一次未解决的讨论"
msgid "Primary"
msgstr "主è¦"
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr "优先"
@@ -20630,22 +21255,22 @@ msgid "Profile Settings"
msgstr "个人资料设置"
msgid "ProfilePreferences|Customize integrations with third party services."
-msgstr ""
+msgstr "自定义与第三方æœåŠ¡çš„集æˆã€‚"
msgid "ProfilePreferences|Enable Gitpod integration"
-msgstr ""
+msgstr "å¯ç”¨Gitpod集æˆ"
msgid "ProfilePreferences|Enable integrated code intelligence on code views"
-msgstr ""
+msgstr "å¯ç”¨ä»£ç è§†å›¾çš„集æˆä»£ç æ™ºèƒ½åŠŸèƒ½"
msgid "ProfilePreferences|Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "ProfilePreferences|Integrations"
-msgstr ""
+msgstr "集æˆé…ç½®"
msgid "ProfilePreferences|Sourcegraph"
-msgstr ""
+msgstr "Sourcegraph"
msgid "ProfileSession|on"
msgstr "于"
@@ -20657,14 +21282,17 @@ msgid "Profiles| You are going to change the username %{currentUsernameBold} to
msgstr "您将更改用户å %{currentUsernameBold} 为 %{newUsernameBold}。é…置文件和项目将é‡å®šå‘到 %{newUsername} 命å空间,但是一旦 %{currentUsername} 命å空间被å¦ä¸€ä¸ªç”¨æˆ·æˆ–组注册,此é‡å®šå‘将过期。请尽快更新您的远端Git仓库。"
msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
+msgstr "\"忙碌\"将显示在您的åå­—æ—边。"
msgid "Profiles|%{provider} Active"
-msgstr ""
+msgstr "%{provider}有效"
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 "å¸æˆ·å·²å®‰æŽ’被删除。"
@@ -20690,7 +21318,7 @@ msgid "Profiles|Bio"
msgstr "自我介ç»"
msgid "Profiles|Busy"
-msgstr ""
+msgstr "忙碌中"
msgid "Profiles|Change username"
msgstr "更改用户å"
@@ -20717,7 +21345,7 @@ msgid "Profiles|Commit email"
msgstr "æ交邮件"
msgid "Profiles|Connect %{provider}"
-msgstr ""
+msgstr "连接%{provider}"
msgid "Profiles|Connected Accounts"
msgstr "å…³è”账户"
@@ -20741,7 +21369,7 @@ msgid "Profiles|Disconnect"
msgstr "æ–­å¼€"
msgid "Profiles|Disconnect %{provider}"
-msgstr ""
+msgstr "与%{provider}断开连接"
msgid "Profiles|Do not show on profile"
msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示"
@@ -20767,9 +21395,12 @@ msgstr "ä¿¡æ¯åŠ¨æ€ä»¤ç‰Œå·²æˆåŠŸé‡ç½®"
msgid "Profiles|Full name"
msgstr "å…¨å"
-msgid "Profiles|Give your individual key a title."
+msgid "Profiles|GitLab is unable to verify your identity automatically."
msgstr ""
+msgid "Profiles|Give your individual key a title."
+msgstr "给您的个人密钥创建一个标题."
+
msgid "Profiles|Include private contributions on my profile"
msgstr "在个人资料中包å«éžå…¬å¼€è´¡çŒ®"
@@ -20815,6 +21446,9 @@ 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 "您新头åƒçš„ä½ç½®å’Œå¤§å°"
@@ -20858,7 +21492,7 @@ msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "å…许的最大文件大å°ä¸º200KB。"
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 ""
+msgstr "此输入看起æ¥ä¸åƒæ˜¯ä¸€ä¸ªå…¬å…±çš„SSH密钥,您确定è¦æ·»åŠ å®ƒå—?添加åŽå®ƒå°†å…¬å¼€å¯è§ã€‚"
msgid "Profiles|This email will be displayed on your public profile"
msgstr "此电å­é‚®ä»¶å°†æ˜¾ç¤ºåœ¨æ‚¨çš„公开个人资料中。"
@@ -20933,7 +21567,7 @@ 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 ""
+msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„å¸æˆ·ã€‚"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„å¸æˆ·ã€‚"
@@ -21097,9 +21731,6 @@ msgstr "项目å称"
msgid "Project name suffix"
msgstr "项目å称åŽç¼€"
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr "项目å称åŽç¼€æ˜¯ä¸€ä¸ªç”¨æˆ·å®šä¹‰çš„字符串,该字符串将附加到项目路径,并将æˆä¸ºæœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€çš„一部分。"
-
msgid "Project order will not be saved as local storage is not available."
msgstr "由于本地存储ä¸å¯ç”¨ï¼Œå› æ­¤ä¸ä¼šä¿å­˜é¡¹ç›®é¡ºåºã€‚"
@@ -21128,7 +21759,7 @@ msgid "Project visibility level will be changed to match namespace rules when tr
msgstr "当项目转移到群组åŽï¼Œå…¶å¯è§æ€§çº§åˆ«å°†æ›´æ”¹ä¸ºä¸Žå‘½å空间规则匹é…。"
msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
-msgstr ""
+msgstr "未找到项目或者您没有æƒé™å°†æ­¤é¡¹ç›®æ·»åŠ åˆ°å®‰å…¨ä»ªè¡¨æ¿ã€‚"
msgid "Project: %{name}"
msgstr "项目: %{name}"
@@ -21155,7 +21786,7 @@ msgid "ProjectFileTree|Name"
msgstr "å称"
msgid "ProjectFileTree|Show more"
-msgstr ""
+msgstr "显示更多"
msgid "ProjectLastActivity|Never"
msgstr "从未"
@@ -21215,7 +21846,7 @@ msgid "ProjectService|Event will be triggered when a confidential issue is creat
msgstr "ç§å¯†è®®é¢˜åˆ›å»º/æ›´æ–°/关闭时事件将被触å‘"
msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
-msgstr ""
+msgstr "部署开始或完æˆæ—¶å°†è§¦å‘事件"
msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
msgstr "åˆå¹¶è¯·æ±‚创建/æ›´æ–°/åˆå¹¶æ—¶äº‹ä»¶å°†è¢«è§¦å‘"
@@ -21256,12 +21887,18 @@ 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 "自动解决过期的åˆå¹¶è¯·æ±‚差异相关讨论"
@@ -21289,8 +21926,8 @@ msgstr "è”系管ç†å‘˜æ›´æ”¹æ­¤è®¾ç½®ã€‚"
msgid "ProjectSettings|Container registry"
msgstr "容器镜åƒåº“"
-msgid "ProjectSettings|Customize your project badges."
-msgstr "自定义您的项目徽章。"
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
msgid "ProjectSettings|Disable email notifications"
msgstr "ç¦ç”¨ç”µå­é‚®ä»¶é€šçŸ¥"
@@ -21302,14 +21939,17 @@ msgid "ProjectSettings|Enable 'Delete source branch' option by default"
msgstr "默认å¯ç”¨\"删除æºåˆ†æ”¯\"选项"
msgid "ProjectSettings|Enable merge trains."
-msgstr ""
+msgstr "å¯ç”¨åˆå¹¶åˆ—车。"
msgid "ProjectSettings|Enable merged results pipelines."
-msgstr ""
+msgstr "å¯ç”¨åˆå¹¶ç»“æžœæµæ°´çº¿ã€‚"
msgid "ProjectSettings|Encourage"
msgstr "建议"
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "æ¯æ¬¡åˆå¹¶éƒ½ä¼šåˆ›å»ºåˆå¹¶æ交"
@@ -21347,7 +21987,7 @@ 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 ""
+msgstr "如果在CI/CD é…置文件中å¯ç”¨äº†åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿ï¼Œæµæ°´çº¿å°†éªŒè¯æºå’Œç›®æ ‡åˆ†æ”¯çš„åˆå¹¶ç»“果。"
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -21358,9 +21998,6 @@ msgstr "议题"
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr "LFS对象ä»å¯ç”¨äºŽæ´¾ç”Ÿã€‚%{linkStart}如何删除它们?%{linkEnd}"
-msgid "ProjectSettings|Learn more about badges."
-msgstr "了解有关徽章的更多信æ¯ã€‚"
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr "此项目的轻é‡çº§è®®é¢˜è·Ÿè¸ªç³»ç»Ÿ"
@@ -21397,6 +22034,9 @@ msgstr "注æ„:公开项目中容器镜åƒåº“始终å¯è§"
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç­¾ç½²æ交æ‰å¯ä»¥æŽ¨é€åˆ°æ­¤ä»“库。"
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr "软件包"
@@ -21431,10 +22071,10 @@ msgid "ProjectSettings|Require"
msgstr "å¿…é¡»"
msgid "ProjectSettings|Requirements"
-msgstr ""
+msgstr "需求"
msgid "ProjectSettings|Requirements management system for this project"
-msgstr ""
+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 "在åˆå¹¶è¯·æ±‚中设置此选项的默认行为和å¯ç”¨æ€§ï¼Œæ‰€åšçš„更改也适用于现有的åˆå¹¶è¯·æ±‚。"
@@ -21505,12 +22145,21 @@ msgstr "查看和编辑此项目中的文件"
msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
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|View project analytics"
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 "当出现冲çªæ—¶ï¼Œç”¨æˆ·å¯ä»¥é€‰æ‹©rebase"
+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 "å¯ç”¨åŽï¼Œè®®é¢˜ã€åˆå¹¶è¯·æ±‚和代ç ç‰‡æ®µå°†å§‹ç»ˆæ˜¾ç¤ºç¼©ç•¥å›¾å’Œç¼©ç•¥å›¾å¥–励表情符å·æŒ‰é’®ã€‚"
@@ -21529,14 +22178,11 @@ msgstr ".NET Core"
msgid "ProjectTemplates|Android"
msgstr "Android"
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr "GitLab集群管ç†"
msgid "ProjectTemplates|Gitpod/Spring Petclinic"
-msgstr ""
+msgstr "Gitpod/Spring Petclinic"
msgid "ProjectTemplates|Go Micro"
msgstr "Go Micro"
@@ -21544,6 +22190,9 @@ msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr "HIPAA审计åè®®"
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr "Netlify/GitBook"
@@ -21586,7 +22235,7 @@ msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
msgstr "SalesforceDX"
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -21770,7 +22419,7 @@ msgid "PrometheusAlerts|Operator"
msgstr "æ“作符"
msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
+msgstr "Runbook URL (å¯é€‰)"
msgid "PrometheusAlerts|Select query"
msgstr "选择查询"
@@ -21779,16 +22428,16 @@ msgid "PrometheusAlerts|Threshold"
msgstr "阈值"
msgid "PrometheusAlerts|exceeded"
-msgstr ""
+msgstr "超过"
msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
+msgstr "https://gitlab.com/gitlab-com/runbooks"
msgid "PrometheusAlerts|is equal to"
-msgstr ""
+msgstr "等于"
msgid "PrometheusAlerts|is less than"
-msgstr ""
+msgstr "å°äºŽ"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "找到%{exporters} åŠ %{metrics}"
@@ -21851,7 +22500,7 @@ msgid "PrometheusService|New metric"
msgstr "新建指标"
msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
-msgstr ""
+msgstr "未找到%{docsUrlStart}通用指标%{docsUrlEnd}"
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr "尚未创建自定义指标。使用上é¢çš„按钮创建一个"
@@ -21890,7 +22539,7 @@ msgid "Promote issue to an epic"
msgstr "将议题å‡çº§ä¸ºå²è¯—"
msgid "Promote to epic"
-msgstr ""
+msgstr "æå‡åˆ°å²è¯—"
msgid "Promote to group label"
msgstr "å‡çº§åˆ°ç¾¤ç»„标记"
@@ -21911,7 +22560,7 @@ 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 "燃尽图是里程碑完æˆè¿›åº¦çš„视觉呈现。通过燃尽图,您å¯ä»¥é©¬ä¸Šç›´è§‚了解对应的里程碑的完æˆè¿›åº¦ã€‚没有燃尽图的è¯ï¼Œæ‚¨éœ€è¦è‡ªå·±ä»Žé‡Œç¨‹ç¢‘æœé›†æ•°æ®æ¥åˆ¶ä½œè¡¨è¾¾åŒæ ·å«ä¹‰çš„进度图。"
@@ -21995,7 +22644,7 @@ msgid "Prompt users to upload SSH keys"
msgstr "æ示用户上传SSH密钥"
msgid "Protect"
-msgstr ""
+msgstr "ä¿æŠ¤"
msgid "Protect variable"
msgstr "ä¿æŠ¤å˜é‡"
@@ -22027,8 +22676,8 @@ 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 "%{wildcards_link_start}通é…符%{wildcards_link_end} 例如 %{code_tag_start}*-stable%{code_tag_end}或%{code_tag_start}production/*%{code_tag_end}"
+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 "å…许åˆå¹¶"
@@ -22049,7 +22698,7 @@ msgid "ProtectedBranch|Code owner approval"
msgstr "代ç æ‰€æœ‰è€…批准"
msgid "ProtectedBranch|Does not apply to users allowed to push."
-msgstr ""
+msgstr "ä¸é€‚用于å…许直接推é€çš„用户。"
msgid "ProtectedBranch|Protect"
msgstr "ä¿æŠ¤"
@@ -22060,8 +22709,8 @@ msgstr "ä¿æŠ¤åˆ†æ”¯"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr "å—ä¿æŠ¤åˆ†æ”¯ (%{protected_branches_count})"
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
-msgstr "更改与CODEOWNERS文件中匹é…文件å的推é€å°†è¢«æ‹’ç»"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
msgstr "需è¦ä»£ç æ‰€æœ‰è€…的批准:"
@@ -22157,7 +22806,7 @@ msgid "Publish to status page"
msgstr "å‘布到状æ€é¡µ"
msgid "Published"
-msgstr ""
+msgstr "å·²å‘布"
msgid "Published on status page"
msgstr "å·²å‘布到状æ€é¡µ"
@@ -22178,7 +22827,7 @@ msgid "Purchase more minutes"
msgstr "购买更多时间"
msgid "Purchase more storage"
-msgstr ""
+msgstr "购买更多存储"
msgid "Push"
msgstr "推é€"
@@ -22208,7 +22857,7 @@ msgid "Push project from command line"
msgstr "从命令行推é€é¡¹ç›®"
msgid "Push the result of the merge to GitLab"
-msgstr ""
+msgstr "å°†åˆå¹¶ç»“果推é€åˆ°GitLab"
msgid "Push to create a project"
msgstr "通过推é€åˆ›å»ºé¡¹ç›®"
@@ -22283,19 +22932,19 @@ msgid "Quick range"
msgstr "å¿«æ·èŒƒå›´"
msgid "Quickly and easily edit multiple files in your project."
-msgstr ""
+msgstr "快速轻æ¾åœ°ç¼–辑您项目中的多个文件。"
msgid "README"
msgstr "自述文件"
msgid "Rails"
-msgstr ""
+msgstr "Rails"
msgid "Rake Tasks Help"
msgstr "Rake任务帮助"
msgid "Random"
-msgstr ""
+msgstr "éšæœº"
msgid "Raw blob request rate limit per minute"
msgstr "æ¯åˆ†é’ŸåŽŸå§‹Blob请求速率é™åˆ¶"
@@ -22327,6 +22976,12 @@ msgstr "å˜åŸº"
msgid "Rebase in progress"
msgstr "Rebase正在进行中"
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "从手动é…置的 Prometheus æœåŠ¡å™¨æŽ¥æ”¶è­¦æŠ¥ã€‚"
@@ -22345,6 +23000,9 @@ msgstr "最近的项目动æ€"
msgid "Recent Searches Service is unavailable"
msgstr "最近æœç´¢æœåŠ¡ä¸å¯ç”¨"
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr "最近的æœç´¢"
@@ -22364,7 +23022,7 @@ msgid "Redirect to SAML provider to test configuration"
msgstr "跳转到SAML供应商以测试é…ç½®"
msgid "Redis"
-msgstr ""
+msgstr "Redis"
msgid "Reduce project visibility"
msgstr "é™ä½Žé¡¹ç›®å¯è§æ€§"
@@ -22382,7 +23040,7 @@ msgid "Refresh"
msgstr "刷新"
msgid "Refresh the page and try again."
-msgstr ""
+msgstr "刷新页é¢ç„¶åŽé‡è¯•ã€‚"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
@@ -22422,10 +23080,10 @@ msgid "Register Universal Two-Factor (U2F) Device"
msgstr "注册通用åŒé‡è®¤è¯è®¾å¤‡(U2F)"
msgid "Register WebAuthn Device"
-msgstr ""
+msgstr "注册WebAuthn设备"
msgid "Register device"
-msgstr ""
+msgstr "注册设备"
msgid "Register now"
msgstr "ç«‹å³æ³¨å†Œ"
@@ -22446,10 +23104,13 @@ msgid "Registration|Your profile"
msgstr "您的个人资料"
msgid "Registry setup"
+msgstr "é•œåƒåº“设置"
+
+msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing status"
-msgstr "é‡å»ºç´¢å¼•çŠ¶æ€"
+msgid "Reindexing Status: %{status}"
+msgstr ""
msgid "Rejected (closed)"
msgstr "已拒ç»(关闭)"
@@ -22522,7 +23183,7 @@ msgid "ReleaseAssetLinkType|Runbooks"
msgstr "Runbook"
msgid "Released date"
-msgstr ""
+msgstr "å‘布日期"
msgid "Releases"
msgstr "å‘布"
@@ -22540,7 +23201,7 @@ msgid "Releases|New Release"
msgstr "新版本"
msgid "Release|Something went wrong while creating a new release"
-msgstr ""
+msgstr "创建新å‘布时出现错误"
msgid "Release|Something went wrong while getting the release details"
msgstr "获å–å‘布详细信æ¯æ—¶å‡ºé”™"
@@ -22569,18 +23230,18 @@ msgstr "移除Runner"
msgid "Remove Zoom meeting"
msgstr "删除Zoom会议"
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-msgstr "将新的æ交推é€åˆ°å…¶æºåˆ†æ”¯æ—¶ï¼Œåˆ é™¤åˆå¹¶è¯·æ±‚中的所有核准"
-
msgid "Remove all or specific assignee(s)"
msgstr "删除所有或特定指派人"
msgid "Remove all or specific label(s)"
msgstr "删除所有或特定标记"
-msgid "Remove approver"
+msgid "Remove all or specific reviewer(s)"
msgstr ""
+msgid "Remove approver"
+msgstr "移除核准人"
+
msgid "Remove approvers"
msgstr "删除核准人"
@@ -22633,7 +23294,7 @@ msgid "Remove limit"
msgstr "去除é™åˆ¶"
msgid "Remove list"
-msgstr ""
+msgstr "删除列表"
msgid "Remove member"
msgstr "删除æˆå‘˜"
@@ -22654,6 +23315,9 @@ msgid "Remove priority"
msgstr "删除优先级"
msgid "Remove report"
+msgstr "删除报告"
+
+msgid "Remove reviewer"
msgstr ""
msgid "Remove secondary node"
@@ -22669,10 +23333,10 @@ msgid "Remove time estimate"
msgstr "删除时间估计"
msgid "Remove user & report"
-msgstr ""
+msgstr "删除用户和报告"
msgid "Remove user from group"
-msgstr ""
+msgstr "从群组中删除用户"
msgid "Removed"
msgstr "已删除"
@@ -22692,6 +23356,9 @@ msgstr "已删除%{label_references}%{label_text}。"
msgid "Removed %{milestone_reference} milestone."
msgstr "已删除里程碑%{milestone_reference} 。"
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr "已删除 %{type} 的 id %{id}"
@@ -22737,6 +23404,9 @@ msgstr "删除%{label_references}%{label_text}."
msgid "Removes %{milestone_reference} milestone."
msgstr "删除里程碑%{milestone_reference}。"
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr "删除所有标记。"
@@ -22767,11 +23437,14 @@ msgstr "é‡å‘½å文件夹"
msgid "Rename/Move"
msgstr "é‡å‘½å/移动"
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr "é‡æ–°æ‰“å¼€"
msgid "Reopen %{issueType}"
-msgstr ""
+msgstr "é‡æ–°å¼€å¯%{issueType}"
msgid "Reopen epic"
msgstr "é‡æ–°å¼€å¯å²è¯—"
@@ -22780,7 +23453,7 @@ msgid "Reopen milestone"
msgstr "é‡æ–°æ‰“开里程碑"
msgid "Reopen test case"
-msgstr ""
+msgstr "é‡æ–°æ‰“开测试用例"
msgid "Reopen this %{quick_action_target}"
msgstr "é‡æ–°æ‰“å¼€%{quick_action_target}"
@@ -22810,7 +23483,7 @@ msgid "Replication"
msgstr "å¤åˆ¶"
msgid "Replication details"
-msgstr ""
+msgstr "å¤åˆ¶è¯¦æƒ…"
msgid "Replication enabled"
msgstr "å¤åˆ¶å·²å¯ç”¨"
@@ -22846,7 +23519,7 @@ msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "由%{reportedBy}报告于%{timeAgo}"
msgid "Reported by %{reporter}"
-msgstr ""
+msgstr "由%{reporter}报告"
msgid "Reporting"
msgstr "报告"
@@ -22855,11 +23528,11 @@ msgid "Reports|%{combinedString} and %{resolvedString}"
msgstr "%{combinedString}åŠ%{resolvedString}"
msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
-msgstr ""
+msgstr "在过去的14天中,在%{failed}个测试中有%{recentlyFailed}个失败了一次以上"
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[0] "在过去的14天中,在%{failed}个测试中有%{recentlyFailed}个失败了一次以上"
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"
@@ -22894,7 +23567,7 @@ msgstr "执行时间"
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[0] "过去14天中在%{base_branch}上,失败了%{count} 次"
msgid "Reports|Failure"
msgstr "失败"
@@ -22945,52 +23618,52 @@ msgid "Repositories"
msgstr "仓库"
msgid "Repositories Analytics"
-msgstr ""
+msgstr "仓库分æž"
msgid "RepositoriesAnalytics|Average Coverage by Job"
-msgstr ""
+msgstr "作业的平å‡è¦†ç›–率"
msgid "RepositoriesAnalytics|Coverage"
-msgstr ""
+msgstr "覆盖率"
msgid "RepositoriesAnalytics|Coverage Jobs"
-msgstr ""
+msgstr "覆盖率作业"
msgid "RepositoriesAnalytics|Download historic test coverage data"
-msgstr ""
+msgstr "下载历å²æµ‹è¯•è¦†ç›–率数æ®"
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
-msgstr ""
+msgstr "下载历å²æµ‹è¯•è¦†ç›–率数æ®(.csv)"
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 "历å²æµ‹è¯•è¦†ç›–率数æ®åŽŸå§‹æ ¼å¼(.csv)已就绪,å¯ä¾›è¿›ä¸€æ­¥åˆ†æžã€‚"
+
+msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Last Update"
-msgstr ""
+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 ""
+msgstr "请选择è¦æ˜¾ç¤ºçš„项目。"
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
-msgstr ""
+msgstr "测试代ç è¦†ç›–率"
msgid "RepositoriesAnalytics|There was an error fetching the projects."
-msgstr ""
-
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
+msgstr "获å–项目时出错。"
msgid "Repository"
msgstr "仓库"
@@ -23005,7 +23678,7 @@ msgid "Repository Settings"
msgstr "仓库设置"
msgid "Repository already read-only"
-msgstr ""
+msgstr "存储库已ç»æ˜¯åªè¯»"
msgid "Repository check"
msgstr "仓库检查"
@@ -23020,7 +23693,7 @@ msgid "Repository cleanup has started. You will receive an email once the cleanu
msgstr "仓库清ç†å·²ç»å¼€å§‹ã€‚一旦清ç†å®Œæˆï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç”µå­é‚®ä»¶ã€‚"
msgid "Repository clone URL"
-msgstr ""
+msgstr "仓库克隆地å€"
msgid "Repository files count over the limit"
msgstr "仓库文件数超过é™åˆ¶"
@@ -23056,10 +23729,10 @@ msgid "Repository storage"
msgstr "仓库存储"
msgid "Repository synchronization concurrency limit"
-msgstr ""
+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 ""
+msgstr "仓库: %{counter_repositories} /Wikis: %{counter_wikis} /构建产物: %{counter_build_artifacts} /LFS: %{counter_lfs_objects} /代ç ç‰‡æ®µ: %{counter_snippets} /软件包: %{counter_packages} /上传: %{counter_uploads}"
msgid "RepositorySettingsAccessLevel|Select"
msgstr "选择"
@@ -23067,9 +23740,6 @@ msgstr "选择"
msgid "Request Access"
msgstr "申请æƒé™"
-msgid "Request Headers"
-msgstr "请求报头"
-
msgid "Request details"
msgstr "请求详情"
@@ -23077,13 +23747,13 @@ msgid "Request parameter %{param} is missing."
msgstr "请求å‚æ•°%{param}缺失。"
msgid "Request review from"
-msgstr ""
+msgstr "请求审核æ¥è‡ª"
msgid "Request to link SAML account must be authorized"
msgstr "链接SAMLå¸æˆ·çš„请求必须ç»è¿‡æŽˆæƒ"
msgid "Requested"
-msgstr ""
+msgstr "已请求"
msgid "Requested %{time_ago}"
msgstr "请求的 %{time_ago}"
@@ -23104,16 +23774,19 @@ msgid "Requests to these domain(s)/address(es) on the local network will be allo
msgstr "当ä¸å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„本地请求时,将å…许对本地网络上这些域/地å€çš„请求。å¯æ”¯æŒIP范围,例如1:0:0:0:0:0:0:0/124或127.0.0.0/28。当å‰ä¸æ”¯æŒåŸŸé€šé…符。多个æ¡ç›®éœ€ä½¿ç”¨é€—å·ï¼Œåˆ†å·æˆ–æ¢è¡Œç¬¦åˆ†éš”。å…许åå•æœ€å¤šå¯å®¹çº³1000个æ¡ç›®ã€‚域应使用IDNAç¼–ç ã€‚例如:example.com,192.168.1.1ã€127.0.0.0/28, xn--itlab-j1a.com。"
msgid "Require admin approval for new sign-ups"
-msgstr ""
+msgstr "需è¦ç®¡ç†å‘˜æ‰¹å‡†æ‰èƒ½è¿›è¡Œæ–°æ³¨å†Œ"
msgid "Require all users in this group to setup two-factor authentication"
-msgstr ""
+msgstr "è¦æ±‚此群组中的所有用户都å¯ç”¨åŒé‡è®¤è¯"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "è¦æ±‚所有用户在访问GitLab时接å—æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–。"
-msgid "Require user password to approve"
-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 "è¦æ±‚用户è¯æ˜Žè‡ªå®šä¹‰åŸŸçš„所有æƒ"
@@ -23139,9 +23812,6 @@ msgstr "需求%{reference}å·²é‡æ–°æ‰“å¼€"
msgid "Requirement %{reference} has been updated"
msgstr "需求%{reference}已更新"
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr "需求标题ä¸èƒ½è¶…过%{limit}个字符。"
@@ -23175,7 +23845,7 @@ msgid "Resend it"
msgstr "é‡æ–°å‘é€"
msgid "Reset"
-msgstr ""
+msgstr "é‡ç½®"
msgid "Reset authorization key"
msgstr "é‡ç½®æŽˆæƒå¯†é’¥"
@@ -23184,7 +23854,7 @@ msgid "Reset authorization key?"
msgstr "é‡ç½®æŽˆæƒå¯†é’¥ï¼Ÿ"
msgid "Reset filters"
-msgstr ""
+msgstr "é‡ç½®ç­›é€‰å™¨"
msgid "Reset health check access token"
msgstr "é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥è®¿é—®ä»¤ç‰Œ"
@@ -23214,13 +23884,13 @@ msgid "Resolve all threads in new issue"
msgstr "在新议题中解决所有主题"
msgid "Resolve conflicts"
-msgstr ""
+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 ""
+msgstr "解决这些冲çªæˆ–请具有仓库写入æƒé™çš„用户在本地进行åˆå¹¶ã€‚"
msgid "Resolve thread"
msgstr "解决主题"
@@ -23246,12 +23916,6 @@ msgstr "解æžä¸€æ¬¡IP地å€å¹¶ä½¿ç”¨å®ƒä»¬æ交请求"
msgid "Response"
msgstr "å“应"
-msgid "Response Headers"
-msgstr "å“应报头"
-
-msgid "Response Status"
-msgstr "å“应状æ€"
-
msgid "Response didn't include `service_desk_address`"
msgstr "å“应ä¸åŒ…括`service_desk_address`"
@@ -23273,6 +23937,9 @@ msgstr "å“应指标(NGINX Ingress)"
msgid "Response metrics (NGINX)"
msgstr "å“应指标(NGINX)"
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr "é‡å¯ç»ˆç«¯"
@@ -23294,6 +23961,9 @@ 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 "é™åˆ¶æ³¨å†Œçš„电å­é‚®ä»¶åœ°å€éœ€ä¸Žç»™å®šæ­£åˆ™è¡¨è¾¾å¼åŒ¹é…的。请å‚阅%{supported_syntax_link_start}支æŒçš„语法%{supported_syntax_link_end}获å–更多信æ¯ã€‚"
@@ -23313,7 +23983,7 @@ msgid "Retry"
msgstr "é‡è¯•"
msgid "Retry job"
-msgstr ""
+msgstr "é‡è¯•ä½œä¸š"
msgid "Retry this job"
msgstr "é‡è¯•å½“å‰ä½œä¸š"
@@ -23350,10 +24020,13 @@ msgid "Review App|View latest app"
msgstr "查看最新应用"
msgid "Review requested from %{name}"
+msgstr "æ¥è‡ª%{name}的审核请求"
+
+msgid "Review requests for you"
msgstr ""
msgid "Review the changes locally"
-msgstr ""
+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是“æœåŠ¡æ供商â€æˆ–“ä¾èµ–æ–¹â€ã€‚"
@@ -23369,13 +24042,13 @@ msgstr "å¯ç”¨å®¡é˜…应用"
msgid "Reviewer"
msgid_plural "%d Reviewers"
-msgstr[0] ""
+msgstr[0] "%dä½å®¡æ ¸è€…"
msgid "Reviewer(s)"
-msgstr ""
+msgstr "审核者"
msgid "Reviewers"
-msgstr ""
+msgstr "审核者"
msgid "Reviewing"
msgstr "审阅中"
@@ -23417,10 +24090,10 @@ msgid "Rook"
msgstr "Rook"
msgid "Ruby"
-msgstr ""
+msgstr "Ruby"
msgid "Rule name is already taken."
-msgstr ""
+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 "定义此群组中项目所接å—çš„git推é€è§„则。此群组中所有新创建的项目都将使用这些设置。"
@@ -23435,7 +24108,7 @@ msgid "Run housekeeping"
msgstr "è¿è¡Œä¾‹è¡Œç»´æŠ¤"
msgid "Run manual or delayed jobs"
-msgstr ""
+msgstr "è¿è¡Œæ‰‹åŠ¨æˆ–延迟的作业"
msgid "Run tests against your code live using the Web Terminal"
msgstr "使用Web终端对您的代ç è¿›è¡Œå®žæ—¶æµ‹è¯•"
@@ -23443,20 +24116,8 @@ msgstr "使用Web终端对您的代ç è¿›è¡Œå®žæ—¶æµ‹è¯•"
msgid "Run untagged jobs"
msgstr "è¿è¡Œæœªæ ‡è®°çš„作业"
-msgid "Runner cannot be assigned to other projects"
-msgstr "无法将Runner分é…给其他项目"
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects"
-msgstr "Runnerå°†è¿è¡Œæ‰€æœ‰æœªæŒ‡å®šçš„项目的作业"
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr "Runnerå°†è¿è¡Œç¾¤ç»„中所有未指定项目的作业"
-
-msgid "Runner runs jobs from assigned projects"
-msgstr "Runnerå°†è¿è¡ŒæŒ‡å®šé¡¹ç›®çš„作业"
+msgstr "Runner处于%{status},最åŽä¸€æ¬¡è”系是%{runner_contact}å‰"
msgid "Runner token"
msgstr "Runner 令牌"
@@ -23473,9 +24134,6 @@ msgstr "Runner未更新。"
msgid "Runner was successfully updated."
msgstr "Runnerå·²æˆåŠŸæ›´æ–°ã€‚"
-msgid "Runner will not receive any new jobs"
-msgstr "Runnerä¸ä¼šæŽ¥å—新的作业"
-
msgid "Runners"
msgstr "Runner"
@@ -23485,14 +24143,17 @@ 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 placed on separate users, servers, even on your local machine."
-msgstr "Runnerå¯ä»¥æ”¾åœ¨ä¸åŒçš„用户ã€æœåŠ¡å™¨ï¼Œç”šè‡³æœ¬åœ°æœºå™¨ä¸Šã€‚"
+msgid "Runners can be:"
+msgstr ""
msgid "Runners currently online: %{active_runners_count}"
msgstr "当å‰åœ¨çº¿Runner: %{active_runners_count}"
@@ -23501,61 +24162,61 @@ msgid "Runners page."
msgstr "Runner页é¢."
msgid "Runners|Active"
-msgstr ""
+msgstr "å¯ç”¨"
msgid "Runners|Architecture"
-msgstr ""
+msgstr "架构"
msgid "Runners|Can run untagged jobs"
-msgstr ""
+msgstr "å¯ä»¥è¿è¡Œæœªæ ‡è®°çš„作业"
msgid "Runners|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "Runners|Group"
-msgstr ""
+msgstr "群组"
msgid "Runners|IP Address"
-msgstr ""
+msgstr "IP地å€"
msgid "Runners|Last contact"
-msgstr ""
+msgstr "最åŽè”ç³»"
msgid "Runners|Locked to this project"
-msgstr ""
+msgstr "é”定到此项目"
msgid "Runners|Maximum job timeout"
-msgstr ""
+msgstr "最大作业超时"
msgid "Runners|Name"
-msgstr ""
+msgstr "å称"
msgid "Runners|Platform"
-msgstr ""
+msgstr "å¹³å°"
msgid "Runners|Property Name"
-msgstr ""
+msgstr "属性å称"
msgid "Runners|Protected"
-msgstr ""
+msgstr "å—ä¿æŠ¤"
msgid "Runners|Revision"
-msgstr ""
+msgstr "版本"
msgid "Runners|Shared"
-msgstr ""
+msgstr "共享的"
msgid "Runners|Specific"
-msgstr ""
+msgstr "特定的"
msgid "Runners|Tags"
-msgstr ""
+msgstr "标签"
msgid "Runners|Value"
-msgstr ""
+msgstr "值"
msgid "Runners|Version"
-msgstr ""
+msgstr "版本"
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´çº¿æ—¶é—´é…é¢é™åˆ¶ï¼ˆ%{quotaLimit} )。"
@@ -23569,9 +24230,18 @@ msgstr "è¿è¡Œä¸­..."
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "在当å‰ä»“库中è¿è¡Œä¸€äº›ä¾‹è¡Œç»´æŠ¤ä»»åŠ¡ï¼Œä¾‹å¦‚压缩文件修订和删除无法访问的对象。"
-msgid "SAML"
+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 "SAML"
+
msgid "SAML SSO"
msgstr "SAML SSO(å•ç‚¹ç™»å½•)"
@@ -23609,7 +24279,7 @@ msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan}
msgstr "SSH主机密钥在此系统上ä¸å¯ç”¨ã€‚请使用%{ssh_keyscan}命令或与您的GitLab管ç†å‘˜è”系以获å–更多信æ¯ã€‚"
msgid "SSH key"
-msgstr ""
+msgstr "SSH密钥"
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "SSH密钥用于在您的电脑和GitLab建立安全连接。"
@@ -23620,11 +24290,8 @@ msgstr "SSH公钥"
msgid "SSL Verification:"
msgstr "SSL验è¯ï¼š"
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
-msgstr ""
+msgstr "满足"
msgid "Saturday"
msgstr "星期六"
@@ -23633,13 +24300,13 @@ msgid "Save"
msgstr "ä¿å­˜"
msgid "Save %{name} size limits"
-msgstr ""
+msgstr "ä¿å­˜%{name}大å°é™åˆ¶"
msgid "Save Changes"
msgstr "ä¿å­˜ä¿®æ”¹"
msgid "Save Push Rules"
-msgstr ""
+msgstr "ä¿å­˜æŽ¨é€è§„则"
msgid "Save application"
msgstr "ä¿å­˜åº”用"
@@ -23660,10 +24327,10 @@ 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 ""
+msgstr "ä¿å­˜ç©ºé—´å¹¶åœ¨å®¹å™¨æ³¨å†Œè¡¨ä¸­æŸ¥æ‰¾å›¾åƒã€‚删除ä¸éœ€è¦çš„标签并åªä¿ç•™æ‚¨æƒ³è¦çš„标签。"
msgid "Saved scan settings and target site settings which are reusable."
-msgstr ""
+msgstr "å·²ä¿å­˜æ‰«æ设置和目标站点设置。这些设置å¯è¢«é‡å¤ä½¿ç”¨ã€‚"
msgid "Saving"
msgstr "ä¿å­˜ä¸­"
@@ -23672,23 +24339,23 @@ msgid "Saving project."
msgstr "正在ä¿å­˜é¡¹ç›®ã€‚"
msgid "Scanner"
-msgstr ""
+msgstr "扫æ工具"
msgid "Schedule a new pipeline"
msgstr "新建æµæ°´çº¿è®¡åˆ’"
msgid "Scheduled"
-msgstr "已计划"
+msgstr "按计划"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr "计划删除于 - %{permanent_deletion_time}"
+msgid "Scheduled a rebase of branch %{branch}."
+msgstr ""
+
msgid "Scheduled to merge this merge request (%{strategy})."
msgstr "已计划åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚ (%{strategy})。"
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
-msgstr "计划在æµæ°´çº¿æˆåŠŸæ—¶åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚。"
-
msgid "Schedules"
msgstr "计划"
@@ -23704,8 +24371,8 @@ msgstr "æµæ°´çº¿è®¡åˆ’"
msgid "Scope"
msgstr "范围"
-msgid "Scoped issue boards"
-msgstr "指定范围的议题看æ¿"
+msgid "Scope board to current iteration"
+msgstr ""
msgid "Scopes"
msgstr "范围"
@@ -23714,7 +24381,7 @@ msgid "Scopes can't be blank"
msgstr "范围ä¸èƒ½ä¸ºç©º"
msgid "Scopes: %{scope_list}"
-msgstr ""
+msgstr "范围:%{scope_list}"
msgid "Scroll down"
msgstr "å‘下滚动"
@@ -23741,7 +24408,7 @@ msgid "Search Jira issues"
msgstr "æœç´¢Jira议题"
msgid "Search a group"
-msgstr ""
+msgstr "æœç´¢ç¾¤ç»„"
msgid "Search an environment spec"
msgstr "æœç´¢çŽ¯å¢ƒè§„则"
@@ -23756,7 +24423,7 @@ msgid "Search branches and tags"
msgstr "æœç´¢åˆ†æ”¯å’Œæ ‡ç­¾"
msgid "Search branches, tags, and commits"
-msgstr ""
+msgstr "æœç´¢åˆ†æ”¯ï¼Œæ ‡ç­¾å’Œæ交"
msgid "Search by Git revision"
msgstr "使用Git版本æœç´¢"
@@ -23822,11 +24489,14 @@ msgid "Search projects..."
msgstr "æœç´¢é¡¹ç›®..."
msgid "Search refs"
-msgstr ""
+msgstr "æœç´¢refs"
msgid "Search requirements"
msgstr "æœç´¢éœ€æ±‚"
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr "æœç´¢ç”¨æˆ·"
@@ -23854,6 +24524,9 @@ 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 "在整个 GitLab"
@@ -23892,7 +24565,7 @@ msgstr[0] "æ交"
msgid "SearchResults|epic"
msgid_plural "SearchResults|epics"
-msgstr[0] ""
+msgstr[0] "å²è¯—"
msgid "SearchResults|issue"
msgid_plural "SearchResults|issues"
@@ -23932,19 +24605,19 @@ msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr "座ä½é“¾æŽ¥å·²ç¦ç”¨ï¼Œæ— æ³•é€šè¿‡æ­¤è¡¨å•è¿›è¡Œé…置。"
msgid "SeatUsage|Seat usage"
-msgstr ""
+msgstr "席ä½ä½¿ç”¨æƒ…况"
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
-msgstr ""
+msgstr "席ä½ä½¿ç”¨æƒ…况数æ®ï¼Œæˆªè‡³ %{last_enqueue_time} (æ¯å¤©æ›´æ–°ï¼‰"
msgid "Seats usage data is updated every day at 12:00pm UTC"
-msgstr ""
+msgstr "席ä½ä½¿ç”¨æ•°æ®æ›´æ–°äºŽæ¯æ—¥12:00pm UTC"
msgid "Secondary"
msgstr "次è¦"
msgid "Seconds"
-msgstr ""
+msgstr "秒"
msgid "Secret"
msgstr "密ç "
@@ -23973,41 +24646,41 @@ msgstr "安全报告已过时。请使用目标分支(%{targetBranchName})中的
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr "安全报告已过时。请在目标分支(%{targetBranchName})上è¿è¡Œ%{newPipelineLinkStart}æ–°çš„æµæ°´çº¿%{newPipelineLinkEnd}"
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}Learn more%{linkEnd}."
msgstr ""
msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "当结果中包å«æ‹’ç»çš„许å¯è¯æ—¶æ ¸å‡†ä¸ºå¿…须。%{linkStart}更多信æ¯%{linkEnd}"
-msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+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 ""
+msgstr "å¯ç”¨äºŽæŒ‰éœ€DAST"
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 ""
+msgstr "默认情况下,所有分æžå·¥å…·éƒ½ä¼šè¢«è°ƒç”¨ä»¥æ¶µç›–您项目中的所有语言。 并且åªåœ¨åˆå¹¶è¯·æ±‚中检测到相关语言时è¿è¡Œã€‚"
msgid "SecurityConfiguration|Configure"
msgstr "é…ç½®"
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
-msgstr ""
+msgstr "无法获å–é…置数æ®ã€‚请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "SecurityConfiguration|Create Merge Request"
-msgstr ""
+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 ""
+msgstr "自定义常è§çš„SAST设置以满足您的需求。此处所åšçš„é…置更改会覆盖GitLabæ供的é…置,并且ä¸ä¼šåŒ…å«åœ¨æ›´æ–°ä¸­ã€‚有关更多高级é…置选项的详细信æ¯ï¼Œè¯·å‚è§%{linkStart}GitLab SAST文档%{linkEnd}。"
msgid "SecurityConfiguration|Enable"
-msgstr ""
+msgstr "å¯ç”¨"
msgid "SecurityConfiguration|Enable via Merge Request"
msgstr "通过åˆå¹¶è¯·æ±‚å¯ç”¨"
@@ -24025,16 +24698,16 @@ msgid "SecurityConfiguration|Manage"
msgstr "管ç†"
msgid "SecurityConfiguration|More information"
-msgstr ""
+msgstr "更多信æ¯"
msgid "SecurityConfiguration|Not enabled"
msgstr "未å¯ç”¨"
msgid "SecurityConfiguration|SAST Analyzers"
-msgstr ""
+msgstr "SAST分æžå·¥å…·"
msgid "SecurityConfiguration|SAST Configuration"
-msgstr ""
+msgstr "SASTé…ç½®"
msgid "SecurityConfiguration|Security Control"
msgstr "安全控制"
@@ -24049,7 +24722,7 @@ msgid "SecurityConfiguration|Using custom settings. You won't receive automatic
msgstr "使用自定义设置。您ä¸ä¼šæ”¶åˆ°æ­¤å˜é‡çš„自动更新。 %{anchorStart}还原到默认%{anchorEnd}"
msgid "SecurityConfiguration|View history"
-msgstr ""
+msgstr "查看历å²"
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr "您å¯ä»¥é€šè¿‡å¯ç”¨%{linkStart}Auto DevOps%{linkEnd}æ¥å¿«é€Ÿå¯ç”¨æ‰€æœ‰å®‰å…¨æ‰«æ工具。"
@@ -24064,7 +24737,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 "添加项目"
@@ -24096,14 +24769,20 @@ msgstr "已忽略的'%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "已忽略'%{vulnerabilityName}'。请关闭éšè—忽略开关以查看。"
+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 ""
+msgstr "请确ä¿æ­¤é¡¹ç›®å¯ç”¨%{trackingStart}议题跟踪%{trackingEnd}并且您有%{permissionsStart}æƒé™åˆ›å»ºæ–°è®®é¢˜%{permissionsEnd}。"
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr "获å–æ¼æ´žæ•°é‡æ—¶å‡ºé”™ã€‚请检查您的网络连接,然åŽé‡è¯•ã€‚"
@@ -24112,7 +24791,7 @@ msgid "SecurityReports|Error fetching the vulnerability list. Please check your
msgstr "获å–æ¼æ´žåˆ—表时出错。请检查您的网络连接,然åŽé‡è¯•ã€‚"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
-msgstr ""
+msgstr "无法获å–安全报告信æ¯ã€‚请é‡æ–°åŠ è½½é¡µé¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "SecurityReports|False positive"
msgstr "误报"
@@ -24121,7 +24800,7 @@ msgid "SecurityReports|Fuzzing artifacts"
msgstr "Fuzzing产物"
msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
+msgstr "跳转到%{linkStart}æµæ°´çº¿é€‰é¡¹å¡%{linkEnd}下载安全报告"
msgid "SecurityReports|Hide dismissed"
msgstr "éšè—已忽略项"
@@ -24130,7 +24809,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 "了解更多关于仪表æ¿åˆ›å»ºçš„ä¿¡æ¯"
@@ -24139,7 +24818,7 @@ msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr "监控代ç ä¸­çš„æ¼æ´ž"
msgid "SecurityReports|Monitored projects"
-msgstr ""
+msgstr "监控的项目"
msgid "SecurityReports|More info"
msgstr "更多信æ¯"
@@ -24160,7 +24839,7 @@ msgid "SecurityReports|Project"
msgstr "项目"
msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
-msgstr ""
+msgstr "未找到项目或者您没有æƒé™å°†æ­¤é¡¹ç›®æ·»åŠ åˆ°å®‰å…¨ä»ªè¡¨æ¿ã€‚"
msgid "SecurityReports|Projects added"
msgstr "项目已添加"
@@ -24181,10 +24860,13 @@ 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|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
+msgstr "安全扫æå·²è¿è¡Œã€‚跳转到%{linkStart}æµæ°´çº¿é€‰é¡¹å¡%{linkEnd}下载安全报告"
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr "请使用上é¢çš„项目æœç´¢å­—段æ¥é€‰æ‹©è¦æ·»åŠ çš„项目。"
@@ -24227,7 +24909,7 @@ 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 "忽略æ¼æ´žæ—¶å‡ºé”™ã€‚"
@@ -24248,7 +24930,7 @@ msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
-msgstr ""
+msgstr "无法添加%{invalidProjectsMessage}: %{errorMessage}"
msgid "SecurityReports|Unable to add %{invalidProjects}"
msgstr "无法添加%{invalidProjects}"
@@ -24256,9 +24938,15 @@ msgstr "无法添加%{invalidProjects}"
msgid "SecurityReports|Undo dismiss"
msgstr "å–消忽略"
-msgid "SecurityReports|Vulnerability Report"
+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 "虽然您的æµæ°´çº¿ä¸­æ²¡æœ‰æ¼æ´žï¼Œè¿™ç§çŽ°è±¡å¾ˆç½•è§ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。无论如何,建议您仔细检查设置以确ä¿ä»ªè¡¨æ¿çš„é…置正确。"
@@ -24287,10 +24975,10 @@ msgid "See the affected projects in the GitLab admin panel"
msgstr "查看 GitLab 管ç†é¢æ¿ä¸­çš„å—å½±å“项目"
msgid "See vulnerability %{vulnerability_link} for any Remediation details."
-msgstr ""
+msgstr "有关任何修å¤çš„详细信æ¯ï¼Œè¯·å‚è§æ¼æ´ž%{vulnerability_link}。"
msgid "See vulnerability %{vulnerability_link} for any Solution details."
-msgstr ""
+msgstr "有关任何解决方案的详细信æ¯ï¼Œè¯·å‚è§æ¼æ´ž %{vulnerability_link}。"
msgid "See what's new at GitLab"
msgstr "查看GitLab的新功能"
@@ -24413,13 +25101,13 @@ msgid "Select required regulatory standard"
msgstr "选择所需的法规标准"
msgid "Select reviewer(s)"
-msgstr ""
+msgstr "选择审核者"
msgid "Select shards to replicate"
msgstr "选择è¦å¤åˆ¶çš„分片"
msgid "Select source"
-msgstr ""
+msgstr "选择æº"
msgid "Select source branch"
msgstr "选择æºåˆ†æ”¯"
@@ -24431,7 +25119,7 @@ msgid "Select status"
msgstr "选择状æ€"
msgid "Select strategy activation method"
-msgstr ""
+msgstr "选择策略激活方å¼"
msgid "Select subscription"
msgstr "选择订阅"
@@ -24449,7 +25137,7 @@ msgid "Select timezone"
msgstr "选择时区"
msgid "Select type"
-msgstr ""
+msgstr "选择类型"
msgid "Select user"
msgstr "选择用户"
@@ -24538,9 +25226,6 @@ msgstr "用逗å·åˆ†éš”主题。"
msgid "September"
msgstr "9月"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr "与"
@@ -24640,14 +25325,17 @@ 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 ""
+msgstr "æœåŠ¡å°æœªå¯ç”¨"
msgid "Service Desk is not supported"
-msgstr ""
+msgstr "ä¸æ”¯æŒæœåŠ¡å°"
msgid "Service Templates"
msgstr "æœåŠ¡æ¨¡æ¿"
@@ -24656,7 +25344,7 @@ msgid "Service URL"
msgstr "æœåŠ¡ URL"
msgid "Session ID"
-msgstr ""
+msgstr "ä¼šè¯ ID"
msgid "Session duration (minutes)"
msgstr "会è¯æŒç»­æ—¶é—´(分钟)"
@@ -24665,16 +25353,13 @@ msgid "Set %{epic_ref} as the parent epic."
msgstr "å°†%{epic_ref}设置为父å²è¯—。"
msgid "Set .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
+msgstr "设置.gitlab-ci.yml以å¯ç”¨æˆ–é…ç½®SAST"
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 template for issue descriptions."
-msgstr "设置议题æ述的默认模æ¿ã€‚"
+msgstr "设置.gitlab-ci.yml文件,通过GitLab管ç†çš„模æ¿å¯ç”¨æˆ–é…ç½®SAST安全扫æ。您å¯ä»¥[添加å˜é‡è¦†ç›–](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings)æ¥å®šåˆ¶SAST设置。"
-msgid "Set a number of approvals required, the approvers and other approval 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 "为账å·åˆ›å»ºä¸€ä¸ªç”¨äºŽæŽ¨é€æˆ–拉å–çš„ %{protocol} 密ç ã€‚"
@@ -24698,7 +25383,7 @@ msgid "Set iteration"
msgstr "设置迭代"
msgid "Set limit to 0 to allow any file size."
-msgstr ""
+msgstr "设置é™åˆ¶ä¸º 0 以å…许任何文件大å°ã€‚"
msgid "Set max session time for web terminal."
msgstr "为Web终端设置最长会è¯æ—¶é—´ã€‚"
@@ -24773,13 +25458,13 @@ msgid "Set up a %{type} Runner manually"
msgstr "手动设置%{type} Runner "
msgid "Set up a hardware device as a second factor to sign in."
-msgstr ""
+msgstr "设置一个硬件设备作为登录的第二个因素。"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "æ ¹æ®%{docsLinkStart}文档%{icon}%{docsLinkEnd}设置断言/属性/声明(email,first_name,last_name)和NameID"
msgid "Set up new device"
-msgstr ""
+msgstr "设置新设备"
msgid "Set up new password"
msgstr "设置新密ç "
@@ -24788,13 +25473,13 @@ msgid "Set up pipeline subscriptions for this project."
msgstr "为此项目设置æµæ°´çº¿è®¢é˜…。"
msgid "Set up shared runner availability"
-msgstr ""
+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 ""
+msgstr "设置验è¯é™åˆ¶å’Œé¢‘率。"
msgid "Set weight"
msgstr "设置æƒé‡"
@@ -24803,19 +25488,19 @@ msgid "Set weight to %{weight}."
msgstr "å°†æƒé‡è®¾ç½®ä¸º%{weight}。"
msgid "Set what should be replicated by this secondary node."
-msgstr ""
+msgstr "设置此次è¦èŠ‚点应该å¤åˆ¶çš„内容。"
msgid "SetPasswordToCloneLink|set a password"
msgstr "设置密ç "
msgid "SetStatusModal|\"Busy\" will be shown next to your name"
-msgstr ""
+msgstr "\"忙碌\"将显示在您的åå­—æ—边。"
msgid "SetStatusModal|Add status emoji"
msgstr "添加状æ€è¡¨æƒ…"
msgid "SetStatusModal|Busy"
-msgstr ""
+msgstr "忙碌"
msgid "SetStatusModal|Clear status"
msgstr "清除状æ€"
@@ -24836,7 +25521,7 @@ msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try agai
msgstr "对ä¸èµ·ï¼Œæˆ‘们无法设置您的状æ€ã€‚请ç¨åŽå†è¯•ã€‚"
msgid "SetStatusModal|Status updated"
-msgstr ""
+msgstr "状æ€å·²æ›´æ–°"
msgid "SetStatusModal|What's your status?"
msgstr "您的状æ€æ˜¯ä»€ä¹ˆï¼Ÿ"
@@ -24863,7 +25548,7 @@ msgid "Sets weight to %{weight}."
msgstr "å°†æƒé‡è®¾ç½®ä¸º %{weight}。"
msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
+msgstr "设置为 0 æ„味ç€ä½¿ç”¨ç³»ç»Ÿé»˜è®¤è¶…时值。"
msgid "Settings"
msgstr "设置"
@@ -24871,9 +25556,6 @@ msgstr "设置"
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr "与GitLab的软件包注册表的使用和体验有关的设置。"
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr "设置实例中所有项目的ç¦æ­¢è‡ªæˆ‘批准。仅管ç†å‘˜å¯ä»¥ä¿®æ”¹è¿™äº›è®¾ç½®ã€‚"
-
msgid "Setup"
msgstr "设置"
@@ -24881,13 +25563,13 @@ msgid "Severity"
msgstr "严é‡ç¨‹åº¦"
msgid "SeverityWidget|Severity"
-msgstr ""
+msgstr "严é‡æ€§"
msgid "SeverityWidget|Severity: %{severity}"
-msgstr ""
+msgstr "严é‡æ€§: %{severity}"
msgid "SeverityWidget|There was an error while updating severity."
-msgstr ""
+msgstr "更新严é‡æ€§æ—¶å‡ºé”™ã€‚"
msgid "Shards (%{shards})"
msgstr "分片(%{shards})"
@@ -24908,13 +25590,16 @@ msgid "Shared projects"
msgstr "分享项目"
msgid "Shared runners"
-msgstr ""
+msgstr "共享Runner"
msgid "Shared runners are disabled for the parent group"
+msgstr "上级群组的共享Runner被ç¦ç”¨"
+
+msgid "Shared runners are disabled on group level"
msgstr ""
msgid "Shared runners disabled on group level"
-msgstr ""
+msgstr "在群组级别ç¦ç”¨å…±äº«Runner"
msgid "Shared runners help link"
msgstr "共享Runner帮助链接"
@@ -24934,20 +25619,20 @@ 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 ""
+
msgid "Show all activity"
msgstr "显示所有活动"
msgid "Show all issues."
-msgstr ""
+msgstr "显示所有议题。"
msgid "Show all members"
msgstr "显示所有æˆå‘˜"
-msgid "Show all requirements."
-msgstr "显示所有需求。"
-
msgid "Show all test cases."
-msgstr ""
+msgstr "显示所有测试用例。"
msgid "Show archived projects"
msgstr "显示已归档的项目"
@@ -24962,7 +25647,7 @@ msgid "Show comments"
msgstr "显示评论"
msgid "Show comments on this file"
-msgstr ""
+msgstr "显示对此文件的评论"
msgid "Show comments only"
msgstr "仅显示评论"
@@ -24982,6 +25667,9 @@ msgstr "显示文件æµè§ˆå™¨"
msgid "Show file contents"
msgstr "显示文件内容"
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr "显示最新版本"
@@ -24989,16 +25677,16 @@ msgid "Show list"
msgstr "显示列表"
msgid "Show me advanced features"
-msgstr ""
+msgstr "显示高级功能"
msgid "Show me how to add a pipeline"
msgstr "演示如何添加æµæ°´çº¿"
msgid "Show me the basics"
-msgstr ""
+msgstr "展示基本功能"
msgid "Show one file at a time"
-msgstr ""
+msgstr "一次显示一个文件"
msgid "Show only direct members"
msgstr "åªæ˜¾ç¤ºç›´æŽ¥æˆå‘˜"
@@ -25013,10 +25701,10 @@ msgid "Show parent subgroups"
msgstr "查看上级å­ç¾¤ç»„"
msgid "Show the Closed list"
-msgstr ""
+msgstr "显示已关闭列表"
msgid "Show the Open list"
-msgstr ""
+msgstr "显示已打开列表"
msgid "Show whitespace changes"
msgstr "显示空白å˜æ›´å†…容"
@@ -25026,7 +25714,7 @@ msgid_plural "Showing %d events"
msgstr[0] "显示 %d 个事件"
msgid "Showing %{conflict_start}%{conflicts_text}%{strong_end} between %{ref_start}%{source_branch}%{strong_end} and %{ref_start}%{target_branch}%{strong_end}"
-msgstr ""
+msgstr "显示%{ref_start}%{source_branch}%{strong_end}和%{ref_start}%{target_branch}%{strong_end}之间的%{conflict_start}%{conflicts_text}%{strong_end}"
msgid "Showing %{count} of %{total} projects"
msgstr "显示%{count}个项目,共计%{total} 个"
@@ -25051,10 +25739,10 @@ msgid "Showing last %{size} of log -"
msgstr "显示日志的最åŽ%{size} -"
msgid "Showing latest version"
-msgstr ""
+msgstr "显示最新版本"
msgid "Showing version #%{versionNumber}"
-msgstr ""
+msgstr "显示版本#%{versionNumber}"
msgid "Side-by-side"
msgstr "并排"
@@ -25087,7 +25775,7 @@ msgid "Sign in to \"%{group_name}\""
msgstr "登录到 \"%{group_name}\""
msgid "Sign in to GitLab"
-msgstr ""
+msgstr "登录到GitLab"
msgid "Sign in using smart card"
msgstr "使用智能å¡ç™»å½•"
@@ -25117,19 +25805,19 @@ msgid "Sign-in restrictions"
msgstr "登录é™åˆ¶"
msgid "Sign-in text"
-msgstr ""
+msgstr "登录文本"
msgid "Sign-up restrictions"
msgstr "注册é™åˆ¶"
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "å字太长(最多%{max_length}字符)。"
msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "姓æ°å¤ªé•¿(最多%{max_length}字符)。"
msgid "SignUp|Minimum length is %{minimum_password_length} characters."
-msgstr ""
+msgstr "最å°é•¿åº¦ä¸º%{minimum_password_length}个字符。"
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "用户å太长(最大为%{max_length}字符)。"
@@ -25141,7 +25829,7 @@ msgid "Signed in"
msgstr "已登录"
msgid "Signed in to GitLab as %{user_link}"
-msgstr ""
+msgstr "以%{user_link}身份登录到 GitLab"
msgid "Signed in with %{authentication} authentication"
msgstr "使用%{authentication}进行身份验è¯"
@@ -25156,7 +25844,7 @@ msgid "Similar issues"
msgstr "相似议题"
msgid "Simulate a pipeline created for the default branch"
-msgstr ""
+msgstr "模拟为默认分支创建的æµæ°´çº¿"
msgid "Single or combined queries"
msgstr "å•ä¸ªæˆ–组åˆæŸ¥è¯¢"
@@ -25180,7 +25868,7 @@ msgid "Skipped"
msgstr "跳过"
msgid "Skipped deployment to"
-msgstr ""
+msgstr "跳过部署到"
msgid "Slack application"
msgstr "Slack应用"
@@ -25204,7 +25892,7 @@ msgid "SlackIntegration|Select events below to enable notifications. The %{stron
msgstr "选择以下事件以å¯ç”¨é€šçŸ¥ã€‚ %{strong_open}Slack频é“å称%{strong_close}å’Œ%{strong_open}Slack用户å%{strong_close}字段是å¯é€‰çš„。"
msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
-msgstr ""
+msgstr "æ­¤æœåŠ¡å°†é¡¹ç›®äº‹ä»¶çš„通知å‘é€åˆ°Slack频é“。如需设置此æœåŠ¡ï¼š"
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
msgstr "2. å°†%{strong_open}Token%{strong_close}粘贴到下é¢çš„字段中"
@@ -25255,16 +25943,16 @@ msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "没有è¦æ˜¾ç¤ºçš„代ç ç‰‡æ®µã€‚"
msgid "Snippets|Add another file %{num}/%{total}"
-msgstr ""
+msgstr "添加å¦ä¸€ä¸ªæ–‡ä»¶%{num}/%{total}"
msgid "Snippets|Delete file"
-msgstr ""
+msgstr "删除文件"
msgid "Snippets|Description (optional)"
msgstr "æè¿° (å¯é€‰)"
msgid "Snippets|Files"
-msgstr ""
+msgstr "文件"
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr "给文件命å以å¯ç”¨ä»£ç é«˜äº®ï¼Œä¾‹å¦‚Ruby文件example.rb"
@@ -25279,7 +25967,7 @@ msgid "Solution"
msgstr "解决方案"
msgid "Some changes are not shown"
-msgstr ""
+msgstr "一些å˜åŒ–未显示"
msgid "Some child epics may be hidden due to applied filters"
msgstr "æŸäº›å­å²è¯—å¯èƒ½ç”±äºŽåº”用筛选器而被éšè—"
@@ -25302,6 +25990,9 @@ msgstr "有人与您åŒæ—¶ç¼–辑了%{issueType} 。æ述已被更新,您需è¦
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 "出错了,抱歉。"
@@ -25321,7 +26012,7 @@ msgid "Something went wrong trying to change the locked state of this %{issuable
msgstr "è¯•å›¾æ”¹å˜ %{issuableDisplayName} çš„é”定状æ€æ—¶å‡ºé”™äº†"
msgid "Something went wrong when reordering designs. Please try again"
-msgstr ""
+msgstr "é‡æ–°æŽ’åºè®¾è®¡æ—¶å‡ºäº†ç‚¹é—®é¢˜ã€‚请å†è¯•ä¸€æ¬¡"
msgid "Something went wrong when toggling the button"
msgstr "点击按钮时出错"
@@ -25338,7 +26029,10 @@ msgstr "应用åŒæ„时出了点问题。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Something went wrong while archiving a requirement."
msgstr "归档需求时出了错。"
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ msgstr "编辑评论时出错。请é‡è¯•ã€‚"
msgid "Something went wrong while fetching %{listType} list"
msgstr "åœ¨èŽ·å– %{listType} 列表时出错了"
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
msgid "Something went wrong while fetching comments. Please try again."
msgstr "获å–评论时出错。请ç¨åŽé‡è¯•ã€‚"
@@ -25420,12 +26117,15 @@ msgid "Something went wrong while performing the action."
msgstr "执行æ“作时出错。"
msgid "Something went wrong while promoting the issue to an epic. Please try again."
-msgstr ""
+msgstr "将议题å‡çº§åˆ°å²è¯—时出错。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Something went wrong while reopening a requirement."
msgstr "é‡æ–°æ‰“开需求时出了错。"
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25456,7 +26156,7 @@ msgid "Something went wrong, unable to add projects to dashboard"
msgstr "出错了,无法将项目添加到仪表æ¿"
msgid "Something went wrong, unable to delete project"
-msgstr ""
+msgstr "å‘生错误,无法删除项目"
msgid "Something went wrong, unable to get projects"
msgstr "出现了错误,无法获å–项目"
@@ -25464,8 +26164,8 @@ msgstr "出现了错误,无法获å–项目"
msgid "Something went wrong, unable to search projects"
msgstr "出错了,无法æœç´¢é¡¹ç›®"
-msgid "Something went wrong."
-msgstr "出错了。"
+msgid "Something went wrong. Please try again later"
+msgstr ""
msgid "Something went wrong. Please try again."
msgstr "出现错误。请é‡è¯•ã€‚"
@@ -25504,7 +26204,7 @@ msgid "SortOptions|Access level, descending"
msgstr "访问级别,é™åºæŽ’列"
msgid "SortOptions|Blocking"
-msgstr ""
+msgstr "阻塞议题数"
msgid "SortOptions|Created date"
msgstr "创建日期"
@@ -25615,7 +26315,7 @@ msgid "SortOptions|Recently starred"
msgstr "最近星标"
msgid "SortOptions|Relevant"
-msgstr ""
+msgstr "相关性"
msgid "SortOptions|Size"
msgstr "大å°"
@@ -25654,10 +26354,10 @@ msgid "Source (branch or tag)"
msgstr "æº(分支或标签)"
msgid "Source Branch"
-msgstr ""
+msgstr "æºåˆ†æ”¯"
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
-msgstr ""
+msgstr "æºåˆ†æ”¯: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgid "Source code (%{fileExtension})"
msgstr "æºä»£ç (%{fileExtension})"
@@ -25708,10 +26408,10 @@ msgid "SourcegraphPreferences|This feature is experimental."
msgstr "此功能是实验性的。"
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
-msgstr ""
+msgstr "使用%{linkStart}Sourcegraph.com%{linkEnd}。"
msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
-msgstr ""
+msgstr "使用自定义的%{linkStart}Sourcegraph实例%{linkEnd}。"
msgid "Spam Logs"
msgstr "垃圾信æ¯æ—¥å¿—"
@@ -25735,7 +26435,7 @@ msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 设置时指定以下 URL:"
msgid "Speed up your pipelines with Needs relationships"
-msgstr ""
+msgstr "通过Needs关系加速您的æµæ°´çº¿"
msgid "Squash commit message"
msgstr "压缩æ交消æ¯"
@@ -25801,7 +26501,7 @@ msgid "Start Date"
msgstr "开始时间"
msgid "Start Time"
-msgstr ""
+msgstr "开始时间"
msgid "Start Web Terminal"
msgstr "å¯åŠ¨Web终端"
@@ -25881,15 +26581,18 @@ msgstr "正在å¯åŠ¨..."
msgid "Starts %{startsIn}"
msgstr "开始 %{startsIn}"
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr "开始于(UTC)"
+msgid "Starts on"
+msgstr ""
+
msgid "State your message to activate"
msgstr "输入消æ¯ä»¥å¯ç”¨"
-msgid "State: %{last_reindexing_task_state}"
-msgstr "状æ€: %{last_reindexing_task_state}"
-
msgid "Static Application Security Testing (SAST)"
msgstr "é™æ€åº”用程åºå®‰å…¨æµ‹è¯•(SAST)"
@@ -25903,16 +26606,19 @@ msgid "StaticSiteEditor|3. Assign a person to review and accept the merge reques
msgstr "3. 指派用户审核并接å—åˆå¹¶è¯·æ±‚。"
msgid "StaticSiteEditor|A link to view the merge request will appear once ready."
-msgstr ""
+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 ""
+msgstr "å¤åˆ¶æ›´æ–°"
msgid "StaticSiteEditor|Could not commit the content changes."
msgstr "无法æ交内容更改。"
@@ -25921,11 +26627,14 @@ msgid "StaticSiteEditor|Could not create merge request."
msgstr "无法创建åˆå¹¶è¯·æ±‚。"
msgid "StaticSiteEditor|Creating your merge request"
-msgstr ""
+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 "返回站点"
@@ -25945,7 +26654,7 @@ 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 ""
+msgstr "当创建åˆå¹¶è¯·æ±‚åŽï¼Œæ‚¨å¯ä»¥è®¾ç½®ä¸€ä¸ªæŒ‡æ´¾äººæ¥å®¡æŸ¥å’Œéƒ¨ç½²æ‚¨çš„更改。"
msgid "StaticSiteEditor|Your merge request has been created"
msgstr "您的åˆå¹¶è¯·æ±‚已创建"
@@ -25957,7 +26666,7 @@ msgid "Status"
msgstr "状æ€"
msgid "Status was retried."
-msgstr ""
+msgstr "状æ€å·²é‡è¯•ã€‚"
msgid "Status:"
msgstr "状æ€:"
@@ -26014,16 +26723,16 @@ msgid "Stay updated about the performance and health of your environment by conf
msgstr "通过é…ç½®Prometheusæ¥ç›‘控你的部署,了解环境的性能和å¥åº·åº¦çš„最新状æ€ã€‚"
msgid "Step 1."
-msgstr ""
+msgstr "第 1 步."
msgid "Step 2."
-msgstr ""
+msgstr "第 2 步."
msgid "Step 3."
-msgstr ""
+msgstr "第 3 步."
msgid "Step 4."
-msgstr ""
+msgstr "第 4 步."
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 "但我们ä»ç„¶å»ºè®®ä¿å­˜ä¸€ä»½å¤‡ä»½å­˜æ¡£ã€‚ å¦åˆ™ï¼Œå¦‚果你å†æ¬¡éœ€è¦å®ƒä½†æ˜¯å·²ä¸¢å¤±ï¼Œä½ å°†éœ€è¦è¯·æ±‚GitLab Inc.å†æ¬¡å°†å®ƒå‘é€ç»™ä½ ã€‚"
@@ -26098,10 +26807,10 @@ msgid "Submit as spam"
msgstr "垃圾信æ¯ä¸¾æŠ¥"
msgid "Submit changes"
-msgstr ""
+msgstr "æ交更改"
msgid "Submit changes..."
-msgstr ""
+msgstr "æ交更改..."
msgid "Submit feedback"
msgstr "æ交å馈"
@@ -26119,7 +26828,7 @@ msgid "Submit the current review."
msgstr "æ交当å‰è¯„审。"
msgid "Submit your changes"
-msgstr ""
+msgstr "æ交您的更改"
msgid "Submitted the current review."
msgstr "å·²æ交当å‰è¯„审。"
@@ -26163,11 +26872,14 @@ msgstr "订阅已æˆåŠŸåˆ›å»ºã€‚"
msgid "Subscription successfully deleted."
msgstr "订阅已æˆåŠŸåˆ é™¤ã€‚"
-msgid "SubscriptionTable|An error occurred while loading billable members list"
+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 ""
+msgstr "加载订阅信æ¯æ—¶å‘生错误。"
msgid "SubscriptionTable|Billing"
msgstr "è´¦å•"
@@ -26194,7 +26906,7 @@ msgid "SubscriptionTable|Next invoice"
msgstr "下一张å‘票"
msgid "SubscriptionTable|Renew"
-msgstr ""
+msgstr "续订"
msgid "SubscriptionTable|Seats currently in use"
msgstr "当å‰æ­£åœ¨ä½¿ç”¨çš„用户数é‡"
@@ -26203,10 +26915,10 @@ msgid "SubscriptionTable|Seats in subscription"
msgstr "订阅中的用户数é‡"
msgid "SubscriptionTable|Seats owed"
-msgstr "欠款用户数é‡"
+msgstr "欠费用户数é‡"
msgid "SubscriptionTable|See usage"
-msgstr ""
+msgstr "查看使用情况"
msgid "SubscriptionTable|Subscription end date"
msgstr "订阅结æŸæ—¥æœŸ"
@@ -26257,13 +26969,13 @@ msgid "Succeeded"
msgstr "å·²æˆåŠŸ"
msgid "Successful purchase image"
-msgstr ""
+msgstr "æˆåŠŸè´­ä¹°å›¾ç‰‡"
msgid "Successfully activated"
msgstr "å·²æˆåŠŸæ¿€æ´»"
msgid "Successfully approved"
-msgstr ""
+msgstr "å·²æˆåŠŸæ‰¹å‡†"
msgid "Successfully blocked"
msgstr "æˆåŠŸç¦ç”¨"
@@ -26278,7 +26990,7 @@ msgid "Successfully deleted U2F device."
msgstr "æˆåŠŸåˆ é™¤ U2F 设备。"
msgid "Successfully deleted WebAuthn device."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆ é™¤WebAuthn设备。"
msgid "Successfully removed email."
msgstr "æˆåŠŸåˆ é™¤ç”µå­é‚®ä»¶ã€‚"
@@ -26287,7 +26999,7 @@ msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_star
msgstr "æµæ°´çº¿å·²å®‰æŽ’è¿è¡Œã€‚请查看 %{pipelines_link_start}æµæ°´çº¿é¡µé¢%{pipelines_link_end}ä»¥äº†è§£è¯¦ç»†ä¿¡æ¯ ã€‚"
msgid "Successfully synced %{synced_timeago}."
-msgstr ""
+msgstr "å·²æˆåŠŸåŒæ­¥äºŽ%{synced_timeago}。"
msgid "Successfully unblocked"
msgstr "æˆåŠŸè§£é™¤ç¦ç”¨"
@@ -26419,13 +27131,13 @@ msgid "Switch to the source to copy the file contents"
msgstr "切æ¢åˆ°æºæ¨¡å¼ä»¥å¤åˆ¶æ–‡ä»¶å†…容"
msgid "Symbolic link"
-msgstr ""
+msgstr "符å·é“¾æŽ¥"
msgid "Sync information"
msgstr "åŒæ­¥ä¿¡æ¯"
msgid "Sync now"
-msgstr ""
+msgstr "ç«‹å³åŒæ­¥"
msgid "Synced"
msgstr "å·²åŒæ­¥"
@@ -26434,9 +27146,15 @@ msgid "Synchronization disabled"
msgstr "åŒæ­¥å·²ç¦ç”¨"
msgid "Synchronization settings"
-msgstr ""
+msgstr "åŒæ­¥è®¾ç½®"
msgid "Syncing…"
+msgstr "åŒæ­¥ä¸­..."
+
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
msgstr ""
msgid "System"
@@ -26467,7 +27185,7 @@ msgid "System metrics (Kubernetes)"
msgstr "系统指标(Kubernetes)"
msgid "System output"
-msgstr ""
+msgstr "系统输出"
msgid "Table of Contents"
msgstr "目录"
@@ -26482,7 +27200,7 @@ msgid "Tag name"
msgstr "标签å称"
msgid "Tag name is required"
-msgstr ""
+msgstr "标签å称为必填项"
msgid "Tag this commit."
msgstr "为此æ交打标签。"
@@ -26497,7 +27215,7 @@ 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 ""
+msgstr "标签删除直到超时为止。 任何剩余标签都将包括在下次è¿è¡Œç­–略时。è¦è§£é™¤æ—¶é—´é™åˆ¶ï¼Œè¯·è®¾ç½®ä¸º0。"
msgid "Tags feed"
msgstr "标签动æ€"
@@ -26620,7 +27338,7 @@ msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% u
msgstr "åªèƒ½è®¾ç½®ä¸ºå¤§äºŽ%{percentage}%%使用é‡"
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 "GitLabå…许您申请%{strongStart}å…费的一次性存储增加%{strongEnd}。 您在30天内将å¯ä½¿ç”¨æ— é™çš„存储空间。这将使您有时间å‡å°‘您的存储使用é‡ã€‚ 30天åŽï¼Œæ‚¨çš„原始存储é™åˆ¶%{limit}将生效。如果您的存储使用已达容é‡ä¸Šé™ï¼Œæ‚¨çš„账户将å˜ä¸ºåªè¯»ã€‚如需继续使用 GitLab ,您必须购买é¢å¤–的存储或å‡å°‘存储使用é‡ã€‚"
+msgstr "GitLabå…许您申请%{strongStart}å…费的一次性存储增加%{strongEnd}。 您在30天内将å¯ä½¿ç”¨æ— é™çš„存储空间。这将使您有时间å‡å°‘您的存储使用é‡ã€‚ 30天åŽï¼Œæ‚¨çš„原始存储é™åˆ¶%{limit}将生效。如果您的存储使用已达容é‡ä¸Šé™ï¼Œæ‚¨çš„账户将å˜ä¸ºåªè¯»ã€‚如需继续使用 GitLab ,您必须购买更多的存储或å‡å°‘存储使用é‡ã€‚"
msgid "TemporaryStorage|Increase storage temporarily"
msgstr "临时增加存储"
@@ -26644,7 +27362,7 @@ msgid "Terms of Service and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–"
msgid "Terraform"
-msgstr ""
+msgstr "Terraform"
msgid "Terraform|%{number} Terraform report failed to generate"
msgid_plural "Terraform|%{number} Terraform reports failed to generate"
@@ -26655,7 +27373,7 @@ msgid_plural "Terraform|%{number} Terraform reports were generated in your pipel
msgstr[0] "您的æµæ°´çº¿ç”Ÿæˆäº†%{number}个Terraform报告"
msgid "Terraform|%{user} updated %{timeAgo}"
-msgstr ""
+msgstr "%{user}更新于%{timeAgo}"
msgid "Terraform|A Terraform report failed to generate."
msgstr "Terraform报告生æˆå¤±è´¥ã€‚"
@@ -26663,29 +27381,62 @@ msgstr "Terraform报告生æˆå¤±è´¥ã€‚"
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr "您的æµæ°´çº¿ç”Ÿæˆäº†Terraform报告。"
+msgid "Terraform|Actions"
+msgstr ""
+
msgid "Terraform|An error occurred while loading your Terraform States"
+msgstr "加载您的Terraform状æ€æ—¶å‘生错误"
+
+msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
msgstr ""
-msgid "Terraform|Find out how to use the %{linkStart}GitLab managed Terraform State%{linkEnd}"
+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 "了解如何使用%{linkStart}GitLab 管ç†çš„Terraform状æ€%{linkEnd}"
+
msgid "Terraform|Generating the report caused an error."
msgstr "生æˆæŠ¥å‘Šæ—¶å‘生错误。"
msgid "Terraform|Get started with Terraform"
+msgstr "Terraform入门"
+
+msgid "Terraform|Job status"
msgstr ""
-msgid "Terraform|Locked"
+msgid "Terraform|Lock"
msgstr ""
+msgid "Terraform|Locked"
+msgstr "é”定"
+
msgid "Terraform|Locked by %{user} %{timeAgo}"
+msgstr "ç”±%{user}于%{timeAgo}é”定"
+
+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 "报告资æºæ›´æ”¹: 添加%{addNum}项, 更改%{changeNum}项, 删除%{deleteNum}项"
msgid "Terraform|States"
-msgstr ""
+msgstr "状æ€"
msgid "Terraform|The Terraform report %{name} failed to generate."
msgstr "Terraform报告%{name}生æˆå¤±è´¥ã€‚"
@@ -26693,17 +27444,29 @@ msgstr "Terraform报告%{name}生æˆå¤±è´¥ã€‚"
msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
msgstr "您的æµæ°´çº¿ç”Ÿæˆäº†Terraform报告%{name}。"
+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 ""
+msgstr "测试用例"
msgid "Test cases are not available for this project"
-msgstr ""
+msgstr "测试用例对此项目ä¸é€‚用"
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
@@ -26713,52 +27476,52 @@ msgid_plural "Test coverage: %d hits"
msgstr[0] "测试覆盖率: %d次命中"
msgid "Test settings"
-msgstr ""
+msgstr "测试设置"
msgid "TestCases|Move test case"
-msgstr ""
+msgstr "移动测试用例"
msgid "TestCases|Moving test case"
-msgstr ""
+msgstr "移动测试用例"
msgid "TestCases|New Test Case"
-msgstr ""
+msgstr "新建测试用例"
msgid "TestCases|New test case"
-msgstr ""
+msgstr "新建测试用例"
msgid "TestCases|Search test cases"
-msgstr ""
+msgstr "æœç´¢æµ‹è¯•ç”¨ä¾‹"
msgid "TestCases|Something went wrong while adding test case to Todo."
-msgstr ""
+msgstr "添加测试用例到待办事项时出了错。"
msgid "TestCases|Something went wrong while creating a test case."
-msgstr ""
+msgstr "创建新测试用例时出现错误."
msgid "TestCases|Something went wrong while fetching count of test cases."
-msgstr ""
+msgstr "获å–测试用例数目时出了错。"
msgid "TestCases|Something went wrong while fetching test case."
-msgstr ""
+msgstr "获å–测试用例时出错。"
msgid "TestCases|Something went wrong while fetching test cases list."
-msgstr ""
+msgstr "获å–测试用例列表时出错。"
msgid "TestCases|Something went wrong while marking test case todo as done."
-msgstr ""
+msgstr "将测试案例标记为完æˆæ—¶å‡ºé”™ã€‚"
msgid "TestCases|Something went wrong while moving test case."
-msgstr ""
+msgstr "移动测试用例时出错。"
msgid "TestCases|Something went wrong while updating the test case labels."
-msgstr ""
+msgstr "更新测试用例列表标记时出错。"
msgid "TestCases|Something went wrong while updating the test case."
-msgstr ""
+msgstr "更新测试用例列表时出错。"
msgid "TestCases|Submit test case"
-msgstr ""
+msgstr "æ交测试用例"
msgid "TestHooks|Ensure one of your projects has merge requests."
msgstr "ç¡®ä¿æ‚¨çš„任一项目中有åˆå¹¶è¯·æ±‚。"
@@ -26782,7 +27545,7 @@ msgid "TestHooks|Ensure the project has notes."
msgstr "ç¡®ä¿é¡¹ç›®æœ‰æ³¨é‡Šã€‚"
msgid "TestHooks|Ensure the project has releases."
-msgstr ""
+msgstr "ç¡®ä¿é¡¹ç›®åŒ…å«å‘布。"
msgid "TestHooks|Ensure the wiki is enabled and has pages."
msgstr "ç¡®ä¿wikiå·²å¯ç”¨å¹¶å…·æœ‰é¡µé¢ã€‚"
@@ -26827,7 +27590,7 @@ msgid "Thank you for signing up for your free trial! You will get additional ins
msgstr "感谢您注册å…费试用版ï¼éšåŽæ‚¨å°†æ”¶åˆ°æœ‰å…³å®‰è£…使用指å—的邮件。"
msgid "Thank you for your business."
-msgstr ""
+msgstr "感谢您的购买。"
msgid "Thank you for your feedback!"
msgstr "感谢您的å馈ï¼"
@@ -26841,11 +27604,11 @@ msgstr "感谢您的支æŒè¯·æ±‚ï¼æˆ‘们会通过工å•#%{issue_iid}追踪您çš
msgid "Thanks for your purchase!"
msgstr "感谢购买ï¼"
-msgid "Thanks! Don't show me this again"
-msgstr "ä¸å†æ˜¾ç¤º"
+msgid "That is ok, I do not want to renew"
+msgstr ""
msgid "That's it, well done!"
-msgstr ""
+msgstr "就是这样,åšå¾—好ï¼"
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "群组“%{group_path}â€å…许您使用SSO以登录å¸æˆ·"
@@ -26856,16 +27619,22 @@ msgstr "“需è¦æ¥è‡ªä»£ç æ‰€æœ‰è€…的批准â€è®¾ç½®å·²ç§»è‡³%{banner_link_s
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
msgstr "%{link_start}校准模å¼%{link_end}å…许有é¢å¤–用户,这些é¢å¤–用户在更新订阅时将会产生追溯费用。"
+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] "%{type} 包å«ä»¥ä¸‹é”™è¯¯ï¼š"
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 ""
+msgstr "GitLab中的高级æœç´¢åŠŸèƒ½æ˜¯éžå¸¸å¼ºå¤§çš„æœç´¢æœåŠ¡ã€‚您å¯ä»¥æœç´¢å…¶ä»–团队的代ç ä»¥å¸®åŠ©æ‚¨å®Œå–„自己项目中的代ç ã€‚从而é¿å…创建é‡å¤çš„代ç æˆ–浪费时间。"
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 "CSV导出将在åŽå°åˆ›å»ºã€‚完æˆåŽï¼Œå®ƒå°†ä»¥é™„件形å¼å‘é€åˆ°%{strong_open}%{email}%{strong_close}。"
+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 "Jira用户%{jiraDisplayName}将映射到的GitLab用户"
@@ -26882,13 +27651,13 @@ msgid "The URL defined on the primary node that secondary nodes should use to co
msgstr "在主节点上定义的URL,次è¦èŠ‚点应使用该URL与其è”系。"
msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "在主节点上定义的URL,从节点将用此网å€æ¥è”络主节点。%{linkStart}更多信æ¯%{linkEnd}"
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 "用于连接到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 æ—¶ä»ç„¶éªŒè¯æœåŠ¡å™¨è¯ä¹¦ã€‚"
@@ -26918,7 +27687,7 @@ msgid "The commit does not exist"
msgstr "æ­¤æ交ä¸å­˜åœ¨"
msgid "The comparison view may be inaccurate due to merge conflicts."
-msgstr ""
+msgstr "由于存在åˆå¹¶å†²çªï¼Œå¯¹æ¯”视图å¯èƒ½ä¸å‡†ç¡®ã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
@@ -26932,6 +27701,9 @@ msgstr "该群组,其å­ç»„和项目的内容将于%{deletion_adjourned_period
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 "æ•°æ®æºå·²è¿žæŽ¥ï¼Œä½†æ²¡æœ‰å¯æ˜¾ç¤ºçš„æ•°æ®ã€‚ %{documentationLink}"
@@ -26972,16 +27744,16 @@ msgid "The file name should have a .yml extension"
msgstr "文件å应以.yml扩展"
msgid "The following %{user} can also merge into this branch: %{branch}"
-msgstr ""
+msgstr "以下%{user}也å¯ä»¥åˆå¹¶åˆ°è¯¥åˆ†æ”¯ä¸­: %{branch}"
msgid "The following %{user} can also push to this branch: %{branch}"
-msgstr ""
+msgstr "以下%{user}也å¯ä»¥æŽ¨é€åˆ°è¯¥åˆ†æ”¯ä¸­: %{branch}"
msgid "The following Personal Access Token was revoked by an administrator, %{username}."
-msgstr ""
+msgstr "管ç†å‘˜ %{username}撤消了以下个人访问令牌。"
msgid "The following SSH key was deleted by an administrator, %{username}."
-msgstr ""
+msgstr "以下SSH密钥已由管ç†å‘˜ %{username}删除。"
msgid "The following items will NOT be exported:"
msgstr "以下项目将ä¸ä¼šè¢«å¯¼å‡ºï¼š"
@@ -27000,16 +27772,16 @@ msgid "The form contains the following error:"
msgstr "表å•åŒ…å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The form contains the following errors:"
-msgstr ""
+msgstr "表å•åŒ…å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The form contains the following warning:"
-msgstr ""
+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 ""
+msgstr "除外部用户外,任何登录用户å‡å¯æŸ¥çœ‹è¯¥ç»„和任何内部项目。"
msgid "The group and any public projects can be viewed without any authentication."
msgstr "群组和任何公共项目å¯ä»¥åœ¨æ²¡æœ‰ä»»ä½•èº«ä»½éªŒè¯çš„情况下查看。"
@@ -27051,10 +27823,7 @@ msgid "The issue stage shows the time it takes from creating an issue to assigni
msgstr "议题阶段概述了从创建议题到将议题添加到里程碑或议题看æ¿æ‰€èŠ±è´¹çš„时间。创建第一个议题åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„.。"
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
-msgstr ""
-
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
+msgstr "该问题被æˆåŠŸæå‡ä¸ºå²è¯—。é‡å®šå‘到å²è¯—..."
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr "许å¯è¯å¯†é’¥æ— æ•ˆã€‚请确ä¿å®ƒä¸Žæ‚¨ä»ŽGitLab Inc.收到的一致。"
@@ -27074,9 +27843,6 @@ msgstr "许å¯è¯å·²æˆåŠŸä¸Šä¼ ï¼Œå°†äºŽ%{starts_at}激活。您å¯ä»¥åœ¨ä¸‹é¢
msgid "The maximum file size allowed is %{size}."
msgstr "å…许的最大文件大å°ä¸º %{size}。"
-msgid "The maximum file size allowed is 200KB."
-msgstr "文件大å°é™åˆ¶ä¸º 200KB。"
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr "GitLab无法解决此åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªã€‚请å°è¯•åœ¨æœ¬åœ°è§£å†³å®ƒä»¬ã€‚"
@@ -27096,16 +27862,16 @@ msgid "The number of changes to be fetched from GitLab when cloning a repository
msgstr "克隆仓库时从GitLab获å–çš„å˜æ›´æ•°ç›®ã€‚此设置å¯ä»¥åŠ å¿«æµæ°´çº¿çš„执行速度。ä¿æŒä¸ºç©ºæˆ–设置为0将默认ç¦ç”¨æµ…克隆,并使GitLab CIæ¯æ¬¡éƒ½èŽ·å–所有分支和标签。"
msgid "The number of merge requests merged by month."
-msgstr ""
+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 ""
+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 "解密ç§é’¥æ‰€éœ€çš„密ç çŸ­è¯­ã€‚该项为å¯é€‰é¡¹, 并且内容被加密存储。"
@@ -27129,7 +27895,7 @@ msgid "The private key to use when a client certificate is provided. This value
msgstr "æ供客户端è¯ä¹¦æ—¶ä½¿ç”¨çš„ç§é’¥ã€‚该值被加密存储。"
msgid "The project can be accessed by any logged in user except external users."
-msgstr ""
+msgstr "除外部用户外,任何登录用户å‡å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "The project can be accessed by any user who is logged in."
msgstr "任何登录的用户都å¯ä»¥è®¿é—®è¯¥é¡¹ç›®ã€‚"
@@ -27141,7 +27907,7 @@ msgid "The project can be accessed without any authentication."
msgstr "该项目å…许任何人访问。"
msgid "The project has already been added to your dashboard."
-msgstr ""
+msgstr "此项目已被添加到您的仪表æ¿ã€‚"
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "项目åªèƒ½ç”±é¡¹ç›®æˆå‘˜è®¿é—®ã€‚必须明确地å‘æ¯ä¸ªç”¨æˆ·æŽˆäºˆè®¿é—®æƒé™ã€‚"
@@ -27165,7 +27931,7 @@ 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 ""
+msgstr "å¯ä»¥æ交存储库,并å¯ä»¥åˆ›å»ºé—®é¢˜ï¼Œè¯„论和其他实体。"
msgid "The repository for this project does not exist."
msgstr "此项目的仓库ä¸å­˜åœ¨ã€‚"
@@ -27189,7 +27955,7 @@ 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 ""
+msgstr "åŒä¸€ä¸ªå…±äº«runnerå¯æ‰§è¡Œå¤šä¸ªé¡¹ç›®çš„代ç ï¼Œé™¤éžæ‚¨é…置了自动伸缩,将%{link}设置为1 (GitLab.com 上的设置)。"
msgid "The schedule time must be in the future!"
msgstr "计划è¿è¡Œæ—¶é—´å¿…须在将æ¥ï¼"
@@ -27204,7 +27970,7 @@ msgid "The snippet is visible only to project members."
msgstr "该代ç ç‰‡æ®µä»…对项目æˆå‘˜å¯è§ã€‚"
msgid "The snippet is visible to any logged in user except external users."
-msgstr ""
+msgstr "该代ç ç‰‡æ®µå¯¹é™¤å¤–部用户外的所有登录用户å¯è§ã€‚"
msgid "The specified tab is invalid, please select another"
msgstr "指定标签页无效,请选择å¦ä¸€ä¸ª"
@@ -27216,7 +27982,7 @@ msgid "The status of the table below only applies to the default branch and is b
msgstr "下表的状æ€ä»…适用于默认分支,并且基于%{linkStart}最新的æµæ°´çº¿%{linkEnd}。为默认分支é…置了扫æåŽï¼Œæ‚¨åˆ›å»ºçš„所有åŽç»­åŠŸèƒ½åˆ†æ”¯éƒ½å°†åŒ…å«è¯¥æ‰«æ。"
msgid "The tag name can't be changed for an existing release."
-msgstr ""
+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 "测试阶段概述了 GitLab CI 为相关åˆå¹¶è¯·æ±‚è¿è¡Œæ¯ä¸ªæµæ°´çº¿æ‰€éœ€çš„时间。当第一个æµæ°´çº¿è¿è¡Œå®ŒæˆåŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
@@ -27228,7 +27994,7 @@ msgid "The update action will time out after %{number_of_minutes} minutes. For b
msgstr "æ›´æ–°æ“作将在 %{number_of_minutes} 分钟åŽè¶…时。对于大型仓库,请使用clone/push组åˆã€‚"
msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
-msgstr ""
+msgstr "上传的文件无效。支æŒçš„文件扩展å为%{extensions}。"
msgid "The usage ping is disabled, and cannot be configured through this form."
msgstr "使用情况检测(usage ping)å·²ç¦ç”¨ï¼Œæ— æ³•é€šè¿‡æ­¤è¡¨å•è¿›è¡Œé…置。"
@@ -27243,7 +28009,7 @@ msgid "The user map is a mapping of the FogBugz users that participated on your
msgstr "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å将被导入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹è¡¨æ ¼æ¥ä¿®æ”¹æ˜ å°„关系。"
msgid "The user you are trying to approve is not pending an approval"
-msgstr ""
+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}天一直处于活动状æ€ï¼Œå› æ­¤æ— æ³•å†»ç»“。"
@@ -27255,7 +28021,7 @@ msgid "The value of the provided variable exceeds the %{count} character limit"
msgstr "æä¾›å˜é‡çš„值超过了%{count}字符é™åˆ¶"
msgid "The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax."
-msgstr ""
+msgstr "当CI/CDé…置文件语法有效时,å¯è§†åŒ–视图将出现在此选项å¡ä¸‹ã€‚"
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr "æ¼æ´žå·²ä¸å†è¢«æ£€æµ‹åˆ°ã€‚请在更改其状æ€å‰ç¡®ä¿æ¼æ´žå·²ä¿®å¤æˆ–移除。"
@@ -27267,7 +28033,7 @@ msgid "There are currently no events."
msgstr "当å‰æ²¡æœ‰äº‹ä»¶ã€‚"
msgid "There are merge conflicts"
-msgstr ""
+msgstr "存在åˆå¹¶å†²çª"
msgid "There are no %{replicableTypeName} to show"
msgstr "没有å¯æ˜¾ç¤ºçš„%{replicableTypeName}"
@@ -27291,7 +28057,7 @@ msgid "There are no archived requirements"
msgstr "没有已归档的需求"
msgid "There are no archived test cases"
-msgstr ""
+msgstr "没有存档的测试用例"
msgid "There are no changes"
msgstr "没有å˜åŒ–"
@@ -27333,7 +28099,7 @@ msgid "There are no open requirements"
msgstr "没有开å¯çš„需求"
msgid "There are no open test cases"
-msgstr ""
+msgstr "没有开放的测试用例"
msgid "There are no packages yet"
msgstr "还没有包"
@@ -27344,29 +28110,32 @@ msgstr "当å‰å°šæ— åˆ†äº«ç»™è¯¥ç¾¤ç»„的项目"
msgid "There are no variables yet."
msgstr "还没有å˜é‡ã€‚"
-msgid "There are running deployments on the environment. Please retry later."
+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 limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
msgstr "项目的订阅和被订阅数é‡ä¸Šé™ä¸º%{ci_project_subscriptions_limit}。"
msgid "There is already a To-Do for this design."
-msgstr ""
+msgstr "此设计已ç»æœ‰ä¸€ä¸ªå¾…办事项。"
msgid "There is already a repository with that name on disk"
msgstr "ç£ç›˜ä¸Šå·²å­˜åœ¨å…·æœ‰è¯¥å称的仓库"
msgid "There is no chart data available."
-msgstr ""
+msgstr "没有å¯ç”¨çš„图表数æ®ã€‚"
msgid "There is no data available."
-msgstr ""
+msgstr "没有å¯ç”¨çš„æ•°æ®ã€‚"
msgid "There is no data available. Please change your selection."
msgstr "没有å¯ç”¨æ•°æ®ã€‚请更改选择。"
msgid "There is no table data available."
-msgstr ""
+msgstr "没有å¯ç”¨çš„表数æ®ã€‚"
msgid "There is too much data to calculate. Please change your selection."
msgstr "æ•°æ®å¤ªå¤šæ— æ³•è®¡ç®—。请更改您的选择。"
@@ -27375,7 +28144,7 @@ msgid "There was a problem communicating with your device."
msgstr "与您的设备通信时出现问题。"
msgid "There was a problem fetching branches."
-msgstr ""
+msgstr "获å–分支时出现问题。"
msgid "There was a problem fetching groups."
msgstr "获å–群组时出现问题。"
@@ -27384,7 +28153,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 "获å–项目分支时出错。"
@@ -27440,6 +28209,9 @@ 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 "获å–%{replicableType}时出错"
@@ -27518,6 +28290,9 @@ msgstr "å°è¯•éªŒè¯æ‚¨çš„查询时出错"
msgid "There was an error updating the Geo Settings"
msgstr "更新Geo设置时出错"
+msgid "There was an error updating the Maintenance Mode Settings"
+msgstr ""
+
msgid "There was an error updating the dashboard, branch name is invalid."
msgstr "更新仪表æ¿æ—¶å‡ºé”™ï¼Œåˆ†æ”¯å称无效。"
@@ -27537,13 +28312,13 @@ 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 ""
+msgstr "获å–图表数æ®æ—¶å‡ºé”™ã€‚请刷新页é¢ä»¥é‡è¯•ã€‚"
msgid "There was an error while fetching the table data. Please refresh the page to try again."
-msgstr ""
+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 "获å–值æµåˆ†æžæ•°æ®æ—¶å‡ºé”™ã€‚"
@@ -27558,7 +28333,7 @@ msgid "These existing issues have a similar title. It might be better to comment
msgstr "这些现有的议题具有类似的标题。在那里评论å¯èƒ½æ›´å¥½ï¼Œè€Œä¸æ˜¯åˆ›å»ºå¦ä¸€ä¸ªç±»ä¼¼çš„问题。"
msgid "These paths are protected for POST requests."
-msgstr ""
+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 "这些é…置于父群组的å˜é‡ï¼Œå¯ä»¥å’Œé¡¹ç›®å˜é‡ä¸€èµ·ç”¨äºŽå½“å‰é¡¹ç›®ã€‚"
@@ -27570,13 +28345,13 @@ msgid "Third Party Advisory Link"
msgstr "第三方建议链接"
msgid "Third party offers"
-msgstr "第三方优惠"
+msgstr "第三方推广"
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 "æ­¤%{issuable}已被é”定。åªæœ‰%{strong_open}项目æˆå‘˜%{strong_close}æ‰å¯ä»¥å‘表评论。"
@@ -27599,6 +28374,9 @@ msgstr "æ­¤GitLab实例尚未æ供任何共享Runner。管ç†å‘˜å¯ä»¥åœ¨ç®¡ç†
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。"
+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 "此项目目å‰å·²å­˜æ¡£å¹¶åªè¯»ã€‚如果您想è¦æ¢å¤æ‹‰å–é•œåƒï¼Œè¯·å…ˆå–消归档。"
@@ -27609,13 +28387,13 @@ msgid "This action can lead to data loss. To prevent accidental actions we ask y
msgstr "æ­¤æ“作å¯èƒ½å¯¼è‡´æ•°æ®ä¸¢å¤±ã€‚为防止æ„外,我们会è¦æ±‚您确认您的æ“作。"
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
-msgstr ""
+msgstr "æ­¤æ“作无法撤消,它将永久删除%{key}SSH密钥"
msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
-msgstr ""
+msgstr "æ­¤æ“作无法撤消。您将丢失该项目的存储库和所有内容:问题,åˆå¹¶è¯·æ±‚等。"
msgid "This action has been performed too many times. Try again later."
-msgstr ""
+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},包括其仓库åŠæ‰€æœ‰å†…容:议题,åˆå¹¶è¯·æ±‚等。"
@@ -27636,13 +28414,13 @@ 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 ""
+msgstr "该附件已被截断,以é¿å…超过å…许的最大附件大å°15MB。其中已包å«æ€»è®¡%{count}个议题中的%{written_count}个。请考虑选择较å°èŒƒå›´çš„议题é‡æ–°å¯¼å‡ºã€‚"
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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
-msgstr ""
+msgstr "该附件已被截断,以é¿å…超过å…许的最大附件大å°15MBã€‚å…¶ä¸­å·²åŒ…å« %{merge_requests_count}个议题中的 %{written_count} 个。考虑选择范围更å°çš„问题进行é‡æ–°å¯¼å‡ºã€‚"
msgid "This block is self-referential"
msgstr "该阻塞为自我引用"
@@ -27714,7 +28492,7 @@ msgid "This environment is being re-deployed"
msgstr "正在é‡æ–°éƒ¨ç½²åˆ°æ­¤çŽ¯å¢ƒ"
msgid "This environment's canary ingress has been updated recently. Please retry later."
-msgstr ""
+msgstr "此环境的Canary Ingress最近有更新。请ç¨åŽå†è¯•ã€‚"
msgid "This epic already has the maximum number of child epics."
msgstr "æ­¤å²è¯—çš„å­å²è¯—数目已达最大值。"
@@ -27774,19 +28552,19 @@ msgid "This is a security log of important events involving your account."
msgstr "这是一个涉åŠæ‚¨çš„å¸æˆ·é‡è¦äº‹ä»¶çš„安全日志。"
msgid "This is a self-managed instance of GitLab."
-msgstr ""
+msgstr "这是GitLab的自管ç†å®žä¾‹ã€‚"
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 ""
+msgstr "此数目为您æœåŠ¡å™¨å½“å‰%{billable_users_link_start}收费用户%{link_end}çš„æ•°é‡ï¼Œ 也是更新许å¯è¯æ—¶éœ€è¦è´­ä¹°çš„最低数é‡ã€‚"
msgid "This is your current session"
msgstr "这是您当å‰çš„会è¯"
msgid "This issue is currently blocked by the following issues:"
-msgstr ""
+msgstr "此问题目å‰è¢«ä»¥ä¸‹é—®é¢˜é˜»æ­¢ï¼š"
msgid "This issue is in a child epic of the filtered epic"
msgstr "此议题在筛选å²è¯—çš„å­å²è¯—中"
@@ -27896,6 +28674,9 @@ 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 "æ­¤åˆå¹¶è¯·æ±‚已关闭。è¦åº”用此建议,请直接编辑此文件。"
@@ -27903,7 +28684,7 @@ msgid "This merge request is locked."
msgstr "æ­¤åˆå¹¶è¯·æ±‚å·²é”定。"
msgid "This merge request is still a draft."
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚ä»ç„¶æ˜¯è‰ç¨¿ã€‚"
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr "åˆå¹¶è¯·æ±‚å·²åˆå¹¶ã€‚è¦åº”用此建议,请直接编辑此文件。"
@@ -27951,7 +28732,7 @@ 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 ""
+msgstr "此项目使用%{strong_start}%{manager_name}%{strong_end}管ç†å…¶ä¾èµ–关系"
msgid "This project path either does not exist or you do not have access."
msgstr "此项目路径ä¸å­˜åœ¨æˆ–您没有访问æƒé™ã€‚"
@@ -27980,6 +28761,15 @@ msgstr "此仓库上次检查于%{last_check_timestamp}。检查%{strong_start}æ
msgid "This repository was last checked %{last_check_timestamp}. The check passed."
msgstr "此仓库上次检查于%{last_check_timestamp}。检查通过。"
+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 "æ­¤Runner仅在å—ä¿æŠ¤åˆ†æ”¯ä¸Šè§¦å‘çš„æµæ°´çº¿ä¸Šè¿è¡Œ"
@@ -27995,14 +28785,11 @@ msgstr "此订阅适用于"
msgid "This suggestion already matches its content."
msgstr "此建议已ç»ä¸Žå®ƒçš„内容相åŒã€‚"
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr "当低于项目定义的超时时,此超时将优先,并å¯æŽ¥å—英文语å¥ï¼Œå¦‚“1 hourâ€ã€‚默认å•ä½ä¸ºç§’。"
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr "无法从GitLab手动解ç¦æ­¤ç”¨æˆ·"
msgid "This user does not have a pending request"
-msgstr ""
+msgstr "此用户没有待处ç†è¯·æ±‚"
msgid "This user has no active %{type}."
msgstr "此用户没有有效的%{type}。"
@@ -28011,13 +28798,13 @@ msgid "This user has no identities"
msgstr "该用户无身份标识"
msgid "This user has previously committed to the %{name} project."
-msgstr ""
+msgstr "该用户曾ç»æ交到%{name}项目。"
msgid "This user has the %{access} role in the %{name} project."
-msgstr ""
+msgstr "该用户在%{name}项目中的角色为%{access}。"
msgid "This user is the author of this %{noteable}."
-msgstr ""
+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 "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分支或者推é€æ–°æ交到现有分支。"
@@ -28026,7 +28813,7 @@ 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 ""
+msgstr "这将清除数æ®åº“中所有项目仓库的检查状æ€ã€‚æ­¤æ“作无法撤销。确定继续å—?"
msgid "This will help us personalize your onboarding experience."
msgstr "这将帮助我们个人化您的å¯ç”¨ä½“验。"
@@ -28050,10 +28837,10 @@ msgid "Threat Monitoring"
msgstr "å¨èƒç›‘测"
msgid "ThreatMonitoring|Alerts"
-msgstr ""
+msgstr "警报"
msgid "ThreatMonitoring|All Environments"
-msgstr ""
+msgstr "所有环境"
msgid "ThreatMonitoring|Anomalous Requests"
msgstr "异常请求"
@@ -28070,12 +28857,33 @@ 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 "未检测到环境"
@@ -28091,6 +28899,9 @@ msgstr "ç­–ç•¥"
msgid "ThreatMonitoring|Requests"
msgstr "请求"
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr "显示最åŽ"
@@ -28101,6 +28912,9 @@ 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."
@@ -28109,6 +28923,12 @@ 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 "下图是网络应用程åºé˜²ç«å¢™(WAF)跟踪应用程åºçš„æµé‡æ¦‚览。 请查看文档了解如何访问 WAF 日志,ç†è§£å“ªç§ç±»åž‹çš„æ¶æ„æµé‡è¯•å›¾è®¿é—®æ‚¨çš„应用。 点击下é¢æ ‡é¢˜æ—边的“?â€å›¾æ ‡ä¹Ÿå¯è®¿é—®æ–‡æ¡£é“¾æŽ¥ã€‚"
+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 "å¨èƒç›‘测"
@@ -28118,8 +28938,8 @@ 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."
-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 "总数æ®åŒ…"
@@ -28127,6 +28947,9 @@ msgstr "总数æ®åŒ…"
msgid "ThreatMonitoring|Total Requests"
msgstr "总请求"
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr "查看文档"
@@ -28341,10 +29164,10 @@ msgid "Timeago|right now"
msgstr "ç«‹å³"
msgid "Timeline|Turn timeline view off"
-msgstr ""
+msgstr "关闭时间线视图"
msgid "Timeline|Turn timeline view on"
-msgstr ""
+msgstr "å¼€å¯æ—¶é—´çº¿è§†å›¾"
msgid "Timeout"
msgstr "超时"
@@ -28353,7 +29176,7 @@ msgid "Timeout connecting to the Google API. Please try again."
msgstr "连接Google API超时。请é‡è¯•ã€‚"
msgid "Timezone"
-msgstr ""
+msgstr "时区"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -28370,7 +29193,7 @@ msgid "Tip:"
msgstr "æ示:"
msgid "Tip: add a"
-msgstr ""
+msgstr "æ示:添加一个"
msgid "Title"
msgstr "标题"
@@ -28385,7 +29208,7 @@ msgid "To"
msgstr "至"
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
-msgstr ""
+msgstr "è¦%{link_to_help}到您的域å,请将上述密钥添加到DNSé…置中的TXT记录。"
msgid "To Do"
msgstr "待处ç†"
@@ -28436,7 +29259,7 @@ msgid "To help improve GitLab and its user experience, GitLab will periodically
msgstr "为了帮助改进GitLabåŠæå‡ç”¨æˆ·ä½“验, GitLab将定期收集使用信æ¯ã€‚"
msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
-msgstr ""
+msgstr "为了帮助改进GitLab,我们会定期%{docs_link}。您å¯ä»¥éšæ—¶é€šè¿‡%{settings_link}更改设置。"
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "è¦å¯¼å…¥SVN仓库,请查看 %{svn_link}。"
@@ -28487,7 +29310,7 @@ 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 "为简化计费过程, GitLab将收集用户数,以便利用季度调整程åºï¼ŒæŒ‰æ¯”例计算全年用户增长的费用。"
+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 "è‹¥è¦æŒ‡å®šæ‚¨æ‰€å±žçš„群组的æ¯ä¸ªé¡¹ç›®çš„通知级别,您需è¦è®¿é—®é¡¹ç›®é¡µé¢ï¼Œæ›´æ”¹é€šçŸ¥çº§åˆ«ã€‚"
@@ -28502,16 +29325,16 @@ msgid "To unsubscribe from this issue, please paste the following link into your
msgstr "è‹¥è¦é€€è®¢æ­¤é—®é¢˜ï¼Œè¯·å°†ä»¥ä¸‹é“¾æŽ¥ç²˜è´´åˆ°æ‚¨çš„æµè§ˆå™¨ï¼š"
msgid "To update Snippets with multiple files, you must use the `files` parameter"
-msgstr ""
+msgstr "è¦ä½¿ç”¨å¤šä¸ªæ–‡ä»¶æ›´æ–°ä»£ç ç‰‡æ®µï¼Œæ‚¨å¿…须使用 `files` å‚æ•°"
msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
-msgstr ""
+msgstr "è¦ä½¿ç”¨Gitpod,您必须首先在 %{user_prefs}的“集æˆâ€éƒ¨åˆ†ä¸­å¯ç”¨è¯¥åŠŸèƒ½ã€‚"
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
-msgstr ""
+msgstr "如需查看所有%{scannedResourcesCount}已扫æ网å€ï¼Œ%{linkStart}请下载CSV文件%{linkEnd}"
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
-msgstr ""
+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个月的 å²è¯—."
@@ -28565,7 +29388,7 @@ msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
msgid "Toggle project select"
-msgstr ""
+msgstr "切æ¢é¡¹ç›®é€‰æ‹©"
msgid "Toggle sidebar"
msgstr "切æ¢è¾¹æ "
@@ -28592,7 +29415,7 @@ msgid "Toggles :%{name}: emoji award."
msgstr "åˆ‡æ¢ :%{name}: 表情符å·èµžèµã€‚"
msgid "Token valid until revoked"
-msgstr ""
+msgstr "令牌有效直至被撤销"
msgid "Tomorrow"
msgstr "明日"
@@ -28607,10 +29430,10 @@ msgid "Too many projects enabled. You will need to manage them via the console o
msgstr "å¯ç”¨äº†å¤ªå¤šçš„项目。您需è¦é€šè¿‡æŽ§åˆ¶å°æˆ–APIæ¥ç®¡ç†å®ƒä»¬ã€‚"
msgid "Too many users specified (limit is %{user_limit})"
-msgstr ""
+msgstr "指定的用户太多(é™åˆ¶ä¸º%{user_limit})"
msgid "Too much data"
-msgstr ""
+msgstr "æ•°æ®è¿‡å¤š"
msgid "Topics (optional)"
msgstr "主题(å¯é€‰)"
@@ -28631,7 +29454,7 @@ msgid "Total cores (CPUs)"
msgstr "总核心(CPU)"
msgid "Total days to completion"
-msgstr ""
+msgstr "完æˆæ€»å¤©æ•°"
msgid "Total issues"
msgstr "总议题数"
@@ -28643,7 +29466,7 @@ msgid "Total test time for all commits/merges"
msgstr "所有æ交和åˆå¹¶çš„总测试时间"
msgid "Total users"
-msgstr ""
+msgstr "用户总数"
msgid "Total weight"
msgstr "总æƒé‡"
@@ -28652,7 +29475,7 @@ msgid "Total: %{total}"
msgstr "总计:%{total}"
msgid "TotalMilestonesIndicator|1000+"
-msgstr ""
+msgstr "1000+"
msgid "TotalRefCountIndicator|1000+"
msgstr "1000+"
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
-msgstr ""
+msgstr "创建一个新群组,开始您的GitLab Gold试用。"
msgid "Trials|Go back to GitLab"
msgstr "返回GitLab"
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr "跳过试用(继续使用å…è´¹å¸æˆ·)"
@@ -28745,17 +29575,50 @@ msgid "Trials|You can always resume this process by selecting your avatar and ch
msgstr "您å¯ä»¥é€šè¿‡ç‚¹å‡»æ‚¨çš„头åƒå’Œé€‰æ‹©â€œå¼€å§‹é‡‘牌试用â€æ¥æ¢å¤æ­¤è¿›ç¨‹ã€‚"
msgid "Trials|You can apply your trial to a new group or an existing group."
-msgstr ""
+msgstr "您å¯ä»¥å°†æ‚¨åœ¨ä¸€ä¸ªæ–°ç¾¤ç»„或一个现有群组上é¢è¿›è¡Œè¯•ç”¨ã€‚"
msgid "Trials|You can apply your trial to a new group or your personal account."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ä¸ªäººå¸æˆ·æˆ–者群组上进行试用。"
msgid "Trials|You can apply your trial to a new group, an existing group, or your personal account."
-msgstr ""
+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 Gold 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 Gold 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 "触å‘器"
@@ -28763,7 +29626,7 @@ msgid "Trigger cluster reindexing"
msgstr "触å‘集群é‡å»ºç´¢å¼•"
msgid "Trigger manual job"
-msgstr ""
+msgstr "触å‘手动作业"
msgid "Trigger pipelines for mirror updates"
msgstr "触å‘é•œåƒæ›´æ–°çš„æµæ°´çº¿"
@@ -28823,7 +29686,7 @@ 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 ""
+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 "å°è¯•ä¸Žæ‚¨çš„设备通信。请将其æ’入并立å³æŒ‰ä¸‹ä¸Šçš„按钮。"
@@ -28832,7 +29695,7 @@ msgid "Tuesday"
msgstr "星期二"
msgid "Tuning settings"
-msgstr ""
+msgstr "调整设定"
msgid "Turn Off"
msgstr "关闭"
@@ -28841,16 +29704,16 @@ msgid "Turn On"
msgstr "å¼€å¯"
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
-msgstr ""
+msgstr "å¯ç”¨%{strongStart}使用情况检测(usage ping)%{strongEnd}以激活用户活动分æžï¼Œå³%{docLinkStart}世代表%{docLinkEnd}。"
msgid "Turn on Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
msgid "Turn on usage ping"
-msgstr ""
+msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
msgid "Turn on usage ping to review instance-level analytics."
-msgstr ""
+msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)以查看实例级分æž"
msgid "Twitter"
msgstr "Twitter"
@@ -28871,19 +29734,19 @@ msgid "Two-factor authentication"
msgstr "åŒé‡è®¤è¯"
msgid "Two-factor authentication disabled"
-msgstr ""
+msgstr "åŒé‡è®¤è¯å·²ç¦ç”¨"
msgid "Two-factor authentication has been disabled for this user"
-msgstr ""
+msgstr "此用户已ç¦ç”¨åŒé‡è®¤è¯"
msgid "Two-factor authentication has been disabled for your GitLab account."
-msgstr ""
+msgstr "您的å¸æˆ·å·²ç¦ç”¨åŒé‡éªŒè¯"
msgid "Two-factor authentication has been disabled successfully!"
-msgstr ""
+msgstr "åŒé‡éªŒè¯å·²è¢«æˆåŠŸç¦ç”¨ï¼"
msgid "Two-factor authentication is not enabled for this user"
-msgstr ""
+msgstr "此用户未å¯ç”¨åŒé‡éªŒè¯"
msgid "Type"
msgstr "类型"
@@ -28916,10 +29779,10 @@ msgid "URL or request ID"
msgstr "URL或请求ID"
msgid "USER %{user} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "用户 %{user} 将被删除ï¼ä½ ç¡®å®šå—?"
msgid "USER WILL BE BLOCKED! Are you sure?"
-msgstr ""
+msgstr "用户将被ç¦ç”¨ï¼ä½ ç¡®å®šå—?"
msgid "UTC"
msgstr "国际标准时间"
@@ -28952,7 +29815,7 @@ msgid "Unable to convert Kubernetes logs encoding to UTF-8"
msgstr "无法将Kubernetes日志编ç è½¬æ¢ä¸ºUTF-8"
msgid "Unable to create link to vulnerability"
-msgstr ""
+msgstr "无法创建到æ¼æ´žçš„链接"
msgid "Unable to fetch unscanned projects"
msgstr "无法获å–未扫æ的项目"
@@ -28988,7 +29851,7 @@ msgid "Unable to save your changes. Please try again."
msgstr "无法ä¿å­˜æ‚¨çš„更改。请é‡è¯•ã€‚"
msgid "Unable to save your preference"
-msgstr ""
+msgstr "无法ä¿å­˜æ‚¨çš„首选项"
msgid "Unable to schedule a pipeline to run immediately"
msgstr "无法安排æµæ°´çº¿ç«‹å³è¿è¡Œ"
@@ -29021,7 +29884,7 @@ msgid "Unassigned"
msgstr "未分é…"
msgid "Unauthenticated request rate limit"
-msgstr ""
+msgstr "无身份验è¯çš„API请求速率é™åˆ¶"
msgid "Undo"
msgstr "撤消"
@@ -29033,7 +29896,7 @@ msgid "Undo ignore"
msgstr "撤销忽略"
msgid "Unexpected error"
-msgstr ""
+msgstr "æ„外错误"
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr "很é—憾,您å‘é€ç»™GitLab的电å­é‚®ä»¶æ— æ³•å¤„ç†ã€‚"
@@ -29069,7 +29932,7 @@ 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 ""
+msgstr "除éžä¸ŽGitLabå¦æœ‰ä¹¦é¢å议,å¦åˆ™å•å‡»â€œä¸Šä¼ è®¸å¯â€å³è¡¨ç¤ºæ‚¨åŒæ„使用GitLab软件应éµå®ˆ %{eula_link_start}æœåŠ¡æ¡æ¬¾%{eula_link_end}。"
msgid "Unlimited"
msgstr "æ— é™"
@@ -29081,7 +29944,7 @@ msgid "Unlock the discussion"
msgstr "解é”讨论"
msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "解é”æ­¤%{issuableDisplayName}å—?%{strongStart}所有人%{strongEnd}都将å¯ä»¥å‘表评论。"
msgid "Unlocked"
msgstr "未é”定"
@@ -29093,10 +29956,10 @@ msgid "Unlocks the discussion."
msgstr "解é”讨论。"
msgid "Unmarked this %{noun} as a draft."
-msgstr ""
+msgstr "å·²å–消标记此%{noun}为è‰ç¨¿ã€‚"
msgid "Unmarks this %{noun} as a draft."
-msgstr ""
+msgstr "å–消标记此%{noun}为è‰ç¨¿ã€‚"
msgid "Unreachable"
msgstr "无法访问"
@@ -29146,6 +30009,9 @@ msgstr "å–消作业计划"
msgid "Unstar"
msgstr "å–消星标"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr "å–消订阅"
@@ -29170,7 +30036,7 @@ msgstr "传入了ä¸æ”¯æŒçš„待办事项类型。支æŒçš„待办事项类型为
msgid "Until"
msgstr "直到"
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29216,7 +30082,7 @@ msgid "Update now"
msgstr "ç«‹å³æ›´æ–°"
msgid "Update username"
-msgstr ""
+msgstr "更新用户å"
msgid "Update variable"
msgstr "æ›´æ–°å˜é‡"
@@ -29227,8 +30093,8 @@ msgstr "请更新您的书签 Url, 因为筛选/排åºçš„分支 URL 已更改。
msgid "Update your group name, description, avatar, and visibility."
msgstr "更新您的群组å称ã€è¯´æ˜Žã€å¤´åƒä»¥åŠå¯è§æ€§ã€‚"
-msgid "Update your project name, topics, description and avatar."
-msgstr "更新您的项目å称,主题,æ述和头åƒã€‚"
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr "因为项目容器镜åƒåº“已有标签,无法更新当å‰é¡¹ç›®ï¼"
@@ -29242,8 +30108,8 @@ msgstr "ä¸å…许新的å¯è§æ€§çº§åˆ«ï¼"
msgid "UpdateProject|Project could not be updated!"
msgstr "项目无法更新ï¼"
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
-msgstr "移动%{project_full_path}的仓库时å‘生错误 - %{message}"
+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 "%{type}仓库校验和验è¯å¤±è´¥ï¼šæ—§%{old}æ–°%{new}"
@@ -29273,7 +30139,7 @@ msgid "Upgrade your plan"
msgstr "å‡çº§ä½ çš„计划"
msgid "Upgrade your plan to activate Advanced Search."
-msgstr ""
+msgstr "å‡çº§æ‚¨çš„方案以å¯ç”¨é«˜çº§æœç´¢ã€‚"
msgid "Upgrade your plan to activate Audit Events."
msgstr "å‡çº§æ‚¨çš„订阅计划以激活审计事件。"
@@ -29284,9 +30150,6 @@ msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨ç¾¤ç»„Webhook。"
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr "å‡çº§æ‚¨çš„计划以å¯ç”¨æ­¤Jira集æˆåŠŸèƒ½ã€‚"
-msgid "Upgrade your plan to improve Issue boards."
-msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的议题看æ¿ã€‚"
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的åˆå¹¶è¯·æ±‚。"
@@ -29309,7 +30172,7 @@ msgid "Upload a private key for your certificate"
msgstr "为您的è¯ä¹¦ä¸Šä¼ ä¸€ä¸ªç§é’¥"
msgid "Upload an image"
-msgstr ""
+msgstr "上传图片"
msgid "Upload file"
msgstr "上传文件"
@@ -29348,10 +30211,10 @@ msgid "Usage"
msgstr "使用情况"
msgid "Usage Trends"
-msgstr ""
+msgstr "使用趋势"
msgid "Usage ping is off"
-msgstr ""
+msgstr "使用情况检测(usage ping)已关闭"
msgid "Usage statistics"
msgstr "使用情况统计"
@@ -29360,16 +30223,16 @@ msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled,
msgstr "%{help_link_start}共享Runner%{help_link_end}å·²ç¦ç”¨ï¼Œæ‰€ä»¥æµæ°´çº¿ä½¿ç”¨æ²¡æœ‰è®¾ç½®é™åˆ¶"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
-msgstr ""
+msgstr "%{percentageLeft}购买的存储空间å¯ç”¨"
msgid "UsageQuota|Artifacts"
msgstr "产物"
msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
-msgstr ""
+msgstr "产物是构建产物和æµæ°´çº¿äº§ç‰©çš„总和。"
msgid "UsageQuota|Buy additional minutes"
-msgstr "è´­ä¹°é¢å¤–分钟数"
+msgstr "购买更多分钟数"
msgid "UsageQuota|Current period usage"
msgstr "当å‰å‘¨æœŸä½¿ç”¨é‡"
@@ -29393,7 +30256,7 @@ msgid "UsageQuota|Purchase more storage"
msgstr "购买更多存储空间"
msgid "UsageQuota|Purchased storage available"
-msgstr ""
+msgstr "购买的存储空间å¯ç”¨"
msgid "UsageQuota|Repositories"
msgstr "仓库"
@@ -29408,40 +30271,40 @@ msgid "UsageQuota|Storage"
msgstr "存储"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
-msgstr ""
+msgstr "这是此å称空间中所有项目使用的存储空间总和。"
msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
-msgstr ""
+msgstr "这是超出项目å…è´¹%{actualRepositorySizeLimit}存储é™åˆ¶çš„存储空间。"
msgid "UsageQuota|This namespace contains locked projects"
-msgstr ""
+msgstr "此命å空间包å«å·²é”定的项目"
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "此命å空间没有使用共享Runner的项目"
msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr ""
+msgstr "由于已购买的存储空间已在低ä½ï¼Œè¿™ä¸ªé¡¹ç›®æœ‰è¢«é”定的风险。"
msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr ""
+msgstr "此项目被é”定,因为它已ç»ä½¿ç”¨äº†%{actualRepositorySizeLimit}çš„å…费存储空间,并且没有å¯ç”¨çš„更多购买存储空间。"
msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr ""
+msgstr "此项目被é”定,因为它已ç»ä½¿ç”¨äº†%{actualRepositorySizeLimit}çš„å…费存储空间和所有购买的存储空间。"
msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr ""
+msgstr "此项目已接近å…费的 %{actualRepositorySizeLimit} 上é™ï¼Œæœ‰è¢«é”定的风险。"
msgid "UsageQuota|Total excess storage used"
-msgstr ""
+msgstr "已使用超é‡å­˜å‚¨ç©ºé—´æ€»è®¡"
msgid "UsageQuota|Total namespace storage used"
-msgstr ""
+msgstr "已使用命å空间存储总计"
msgid "UsageQuota|Unlimited"
msgstr "æ— é™"
msgid "UsageQuota|Uploads"
-msgstr ""
+msgstr "上传"
msgid "UsageQuota|Usage"
msgstr "使用é‡"
@@ -29462,7 +30325,7 @@ 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 ""
+msgstr "当您购买更多的存储空间时,我们会自动解é”达到%{actualRepositorySizeLimit}é™åˆ¶æ—¶è¢«é”定的项目。"
msgid "UsageQuota|Wiki"
msgstr "Wiki"
@@ -29471,16 +30334,16 @@ msgid "UsageQuota|Wikis"
msgstr "Wiki"
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
-msgstr ""
+msgstr "您已ç»ç”¨å°½æ‰€æœ‰æ›´å¤šçš„存储空间,请购买更多空间以解é”超过å…è´¹%{actualRepositorySizeLimit}é™åˆ¶çš„项目。"
msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
-msgstr ""
+msgstr "您已ç»åœ¨%{projectsLockedText}达到存储空间é™åˆ¶%{actualRepositorySizeLimit}。如需解é”,请购买更多存储空间。"
msgid "UsageQuota|You used: %{usage} %{limit}"
msgstr "您已使用: %{usage} %{limit}"
msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
-msgstr ""
+msgstr "您购买的存储空间已在低ä½ã€‚为了é¿å…项目被é”定,请购买更多存储空间。"
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ",您命å空间存储上é™æ€»è®¡%{formattedLimit}"
@@ -29537,7 +30400,7 @@ msgid "User %{username} was successfully removed."
msgstr "用户 %{username} å·²æˆåŠŸåˆ é™¤ã€‚"
msgid "User ID"
-msgstr ""
+msgstr "用户ID"
msgid "User OAuth applications"
msgstr "用户的 OAuth 应用程åº"
@@ -29591,10 +30454,10 @@ msgid "User was successfully updated."
msgstr "用户已æˆåŠŸæ›´æ–°ã€‚"
msgid "UserAvailability|%{author} (Busy)"
-msgstr ""
+msgstr "%{author} (忙碌)"
msgid "UserAvailability|(Busy)"
-msgstr ""
+msgstr "(忙碌)"
msgid "UserLists|Add"
msgstr "添加"
@@ -29654,7 +30517,7 @@ msgid "UserList|created %{timeago}"
msgstr "创建于%{timeago}"
msgid "UserProfile|(Busy)"
-msgstr ""
+msgstr "(忙碌)"
msgid "UserProfile|Activity"
msgstr "活动"
@@ -29666,7 +30529,7 @@ msgid "UserProfile|Blocked user"
msgstr "å·²ç¦ç”¨ç”¨æˆ·"
msgid "UserProfile|Bot activity"
-msgstr ""
+msgstr "Bot活动"
msgid "UserProfile|Contributed projects"
msgstr "å‚与贡献的项目"
@@ -29702,7 +30565,7 @@ msgid "UserProfile|Report abuse"
msgstr "举报滥用行为"
msgid "UserProfile|Retry"
-msgstr ""
+msgstr "é‡è¯•"
msgid "UserProfile|Snippets"
msgstr "代ç ç‰‡æ®µ"
@@ -29735,7 +30598,7 @@ msgid "UserProfile|This user is blocked"
msgstr "该用户已被ç¦ç”¨"
msgid "UserProfile|Unconfirmed user"
-msgstr ""
+msgstr "未确认的用户"
msgid "UserProfile|View all"
msgstr "查看全部"
@@ -29774,13 +30637,13 @@ msgid "Username or email"
msgstr "用户å或邮箱"
msgid "Username: %{username}"
-msgstr ""
+msgstr "用户å: %{username}"
msgid "Users"
msgstr "用户"
msgid "Users in License"
-msgstr ""
+msgstr "许å¯è¯ä¸­çš„用户数"
msgid "Users in License:"
msgstr "许å¯è¯ä¸­çš„用户数:"
@@ -29795,13 +30658,16 @@ 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 ""
msgid "Users were successfully added."
msgstr "å·²æˆåŠŸæ·»åŠ ç”¨æˆ·ã€‚"
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
+msgstr "具有访客角色或ä¸å±žäºŽé¡¹ç›®æˆ–组的用户将ä¸å ç”¨æ‚¨è®¸å¯è¯ä¸­çš„座ä½ã€‚"
msgid "UsersSelect|%{name} + %{length} more"
msgstr "%{name} + 其余%{length}ä½"
@@ -29825,7 +30691,7 @@ 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 ""
+msgstr "使用%{codeStart}needs%{codeEnd}关键字会使作业比其所在阶段更早è¿è¡Œã€‚åªè¦å®ƒä»¬çš„%{codeStart}needs%{codeEnd}关系得到满足,作业将尽快执行,从而实现æµæ°´çº¿åŠ é€Ÿã€‚"
msgid "Valid from"
msgstr "有效期自"
@@ -29834,7 +30700,7 @@ msgid "Validate"
msgstr "验è¯"
msgid "Validate your GitLab CI configuration"
-msgstr ""
+msgstr "验è¯æ‚¨çš„GitLab CIé…ç½®"
msgid "Validate your GitLab CI configuration file"
msgstr "验è¯æ‚¨çš„GitLab CIé…置文件"
@@ -29861,7 +30727,7 @@ 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}天"
@@ -29873,7 +30739,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 "å˜é‡"
@@ -29897,7 +30763,7 @@ msgid "Various settings that affect GitLab performance."
msgstr "å½±å“GitLab性能相关设置。"
msgid "Verification concurrency limit"
-msgstr ""
+msgstr "验è¯å¹¶å‘é™åˆ¶"
msgid "Verification information"
msgstr "验è¯ä¿¡æ¯"
@@ -29918,19 +30784,19 @@ msgid "Version"
msgstr "版本"
msgid "Version %{versionNumber}"
-msgstr ""
+msgstr "版本 %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
-msgstr ""
+msgstr "版本 %{versionNumber} (最新)"
msgid "View Documentation"
msgstr "查看文档"
msgid "View alert details at"
-msgstr ""
+msgstr "查看警报详细信æ¯äºŽ"
msgid "View alert details."
-msgstr ""
+msgstr "查看警报详细信æ¯ã€‚"
msgid "View all issues"
msgstr "查看所有议题"
@@ -29965,7 +30831,7 @@ msgstr "查看å²è¯—列表"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
-msgstr[0] "查看%d项展示产物"
+msgstr[0] "查看%d项已展示产物"
msgid "View file @ "
msgstr "æµè§ˆæ–‡ä»¶ @ "
@@ -29974,7 +30840,7 @@ msgid "View file @ %{commitSha}"
msgstr "查看文件@%{commitSha}"
msgid "View file @%{commit_sha}"
-msgstr ""
+msgstr "查看文件@%{commit_sha}"
msgid "View full dashboard"
msgstr "查看完整仪表æ¿"
@@ -30034,7 +30900,7 @@ msgid "View replaced file @ "
msgstr "查看替æ¢æ–‡ä»¶ @ "
msgid "View setting"
-msgstr ""
+msgstr "查看设置"
msgid "View supported languages and frameworks"
msgstr "查看支æŒçš„语言和框架"
@@ -30136,7 +31002,7 @@ msgid "Vulnerabilities over time"
msgstr "æ¼æ´žè¶‹åŠ¿å›¾"
msgid "Vulnerability Report"
-msgstr ""
+msgstr "æ¼æ´žæŠ¥å‘Š"
msgid "Vulnerability remediated. Review before resolving."
msgstr "æ¼æ´žå·²ä¿®è¡¥ã€‚置为解决之å‰è¯·å…ˆè¿›è¡Œå®¡æ ¸ã€‚"
@@ -30157,16 +31023,16 @@ msgid "VulnerabilityChart|Severity"
msgstr "严é‡çº§åˆ«"
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "由%{user}%{statusStart}确认%{statusEnd}于%{timeago}"
msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
-msgstr ""
+msgstr "ç”±æµæ°´çº¿%{pipelineLink}于%{timeago}%{statusStart}检测出%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "由%{user}于%{timeago}%{statusStart}忽略%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "由%{user}于%{timeago}%{statusStart}解决%{statusEnd}"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr "真实æ¼æ´žå¹¶å°†ä¿®å¤"
@@ -30178,10 +31044,10 @@ msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessa
msgstr "无法处ç†%{issueReference}: %{errorMessage}。"
msgid "VulnerabilityManagement|Detected"
-msgstr ""
+msgstr "检测到"
msgid "VulnerabilityManagement|Needs triage"
-msgstr ""
+msgstr "需è¦åˆ†ç±»"
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr "试图删除评论时出错。请ç¨åŽå†è¯•ã€‚"
@@ -30232,13 +31098,16 @@ msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
msgstr "%{scannerName} (版本 %{scannerVersion})"
msgid "Vulnerability|Activity"
+msgstr "活动"
+
+msgid "Vulnerability|Actual Response"
msgstr ""
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
-msgstr ""
+msgstr "实际收到的å“应是检测到此故障时收到的å“应"
msgid "Vulnerability|Additional Info"
-msgstr ""
+msgstr "其它信æ¯"
msgid "Vulnerability|Class"
msgstr "类型"
@@ -30247,18 +31116,21 @@ msgid "Vulnerability|Comments"
msgstr "注释"
msgid "Vulnerability|Crash address"
-msgstr ""
+msgstr "崩溃地å€"
msgid "Vulnerability|Crash state"
-msgstr ""
+msgstr "崩溃状æ€"
msgid "Vulnerability|Crash type"
-msgstr ""
+msgstr "崩溃类型"
msgid "Vulnerability|Description"
msgstr "说明"
msgid "Vulnerability|Detected"
+msgstr "检测到"
+
+msgid "Vulnerability|Download"
msgstr ""
msgid "Vulnerability|Evidence"
@@ -30288,9 +31160,15 @@ msgstr "命å空间"
msgid "Vulnerability|Project"
msgstr "项目"
-msgid "Vulnerability|Request/Response"
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
msgstr ""
+msgid "Vulnerability|Request/Response"
+msgstr "请求/å“应"
+
msgid "Vulnerability|Scanner"
msgstr "扫æ工具"
@@ -30304,6 +31182,9 @@ 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"
@@ -30318,6 +31199,9 @@ msgstr "等待性能数æ®"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "æƒé™ä¸è¶³ã€‚如需查看相关数æ®ï¼Œè¯·å‘管ç†å‘˜ç”³è¯·æƒé™ã€‚"
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr "警告:"
@@ -30325,13 +31209,13 @@ msgid "Warning: Displaying this diagram might cause performance issues on this p
msgstr "警告:显示此图表å¯èƒ½ä¼šå¼•èµ·é¡µé¢çš„性能问题。"
msgid "We are currently unable to fetch data for the pipeline header."
-msgstr ""
+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 ""
+msgstr "我们目å‰æ— æ³•èŽ·å–æ­¤æµæ°´çº¿çš„æ•°æ®ã€‚"
msgid "We could not determine the path to remove the epic"
msgstr "我们无法确定删除å²è¯—的路径"
@@ -30340,17 +31224,20 @@ msgid "We could not determine the path to remove the issue"
msgstr "我们无法确定删除议题的路径"
msgid "We couldn't find any %{scope} matching %{term}"
-msgstr ""
+msgstr "找ä¸åˆ°ä»»ä½•åŒ¹é…%{term}çš„%{scope}"
msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
-msgstr ""
+msgstr "我们在群组%{group}中找ä¸åˆ°ä¸Ž%{scope}相匹é…çš„%{term}"
msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
-msgstr ""
+msgstr "我们在项目%{project}中找ä¸åˆ°ä¸Ž%{scope}相匹é…çš„%{term}"
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
msgstr "无法连接PrometheusæœåŠ¡å™¨ã€‚æœåŠ¡å™¨ä¸å†å­˜åœ¨ï¼Œæˆ–者é…置信æ¯éœ€è¦æ›´æ–°ã€‚"
+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 "我们在%{humanized_resource_name}检测到潜在滥用行为。请输入此reCAPTCHA验è¯ç å¹¶ç»§ç»­ã€‚"
@@ -30373,16 +31260,16 @@ 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 ""
+msgstr "我们å°è¯•äºŽ%{expires_on}自动将%{strong}%{namespace_name}%{strong_close}上您的订阅进行续订,但是出现了问题。因此您的订阅已é™çº§ä¸ºå…费计划。您的数æ®æ˜¯ä»ç„¶æ˜¯å®‰å…¨çš„。我们建议您检查付款方å¼å¹¶ä¸Žæˆ‘们的支æŒå›¢é˜Ÿè”ç³»(%{support_link})。他们将很会å助您完æˆç»­è®¢ã€‚"
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 ""
+msgstr "我们会通知%{inviter} ,您拒ç»äº†æ³¨å†ŒGitLab的邀请。您将ä¸ä¼šç»§ç»­æ”¶åˆ°æ醒。"
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 ""
+msgstr "我们在此通知您,您的GitLab ä¼ä¸šç‰ˆè®¢é˜…%{plan_name}已接近其用户上é™ã€‚您当å‰æœ‰%{active_user_count}个活跃用户,å³å°†è¾¾åˆ°%{maximum_user_count}的用户é™åˆ¶ã€‚"
msgid "We've found no vulnerabilities"
msgstr "未å‘现安全æ¼æ´ž"
@@ -30400,10 +31287,10 @@ msgid "Web terminal"
msgstr "Web终端"
msgid "WebAuthn Devices (%{length})"
-msgstr ""
+msgstr "WebAuthn设备 (%{length})"
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
-msgstr ""
+msgstr "WebAuthnåªæ”¯æŒå¯ç”¨äº†HTTPS的网站。您å¯ä»¥è”系管ç†å‘˜èŽ·å¾—更多信æ¯"
msgid "WebIDE|Merge request"
msgstr "åˆå¹¶è¯·æ±‚"
@@ -30430,100 +31317,106 @@ msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr "Webhook设置已移动。现在å¯ä»¥åœ¨è®¾ç½®èœå•ä¸­æ‰¾åˆ°ã€‚"
msgid "Webhooks|Comments"
-msgstr ""
+msgstr "评论"
msgid "Webhooks|Confidential Comments"
-msgstr ""
+msgstr "ç§å¯†è¯„论"
msgid "Webhooks|Confidential Issues events"
-msgstr ""
+msgstr "ç§å¯†è®®é¢˜äº‹ä»¶"
msgid "Webhooks|Deployment events"
-msgstr ""
+msgstr "部署事件"
msgid "Webhooks|Enable SSL verification"
-msgstr ""
+msgstr "å¯ç”¨SSL验è¯"
msgid "Webhooks|Feature Flag events"
-msgstr ""
+msgstr "功能标志事件"
msgid "Webhooks|Issues events"
-msgstr ""
+msgstr "议题事件"
msgid "Webhooks|Job events"
+msgstr "作业事件"
+
+msgid "Webhooks|Member events"
msgstr ""
msgid "Webhooks|Merge request events"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚事件"
msgid "Webhooks|Pipeline events"
-msgstr ""
+msgstr "æµæ°´çº¿äº‹ä»¶"
msgid "Webhooks|Push events"
-msgstr ""
+msgstr "推é€äº‹ä»¶"
msgid "Webhooks|Releases events"
-msgstr ""
+msgstr "å‘布事件"
msgid "Webhooks|SSL verification"
-msgstr ""
+msgstr "SSL验è¯"
msgid "Webhooks|Secret Token"
-msgstr ""
+msgstr "密钥"
msgid "Webhooks|Tag push events"
-msgstr ""
+msgstr "标签推é€äº‹ä»¶"
msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr ""
+msgstr "当部署开始ã€å®Œæˆã€å¤±è´¥æˆ–å–消时触å‘æ­¤URL"
msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
-msgstr ""
+msgstr "当功能标志开å¯æˆ–关闭时触å‘æ­¤URL"
msgid "Webhooks|This URL is triggered when a release is created/updated"
-msgstr ""
+msgstr "当创建/æ›´æ–°å‘布时触å‘æ­¤URL"
msgid "Webhooks|This URL will be triggered by a push to the repository"
-msgstr ""
+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 ""
+msgstr "åˆå¹¶è¯·æ±‚创建/æ›´æ–°/åˆå¹¶æ—¶å°†è§¦å‘此网å€"
msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
-msgstr ""
+msgstr "当一个新标签被推é€åˆ°ä»“库时将触å‘此网å€"
msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
-msgstr ""
+msgstr "wiki页é¢åˆ›å»º/更新时事件将触å‘此网å€"
msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
-msgstr ""
+msgstr "议题创建/æ›´æ–°/关闭时事件将触å‘此网å€"
msgid "Webhooks|This URL will be triggered when someone adds a comment"
-msgstr ""
+msgstr "当有人添加评论时事件将触å‘此网å€"
msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
-msgstr ""
+msgstr "当有人å‘ç§å¯†è®®é¢˜æ·»åŠ è¯„论时网å€å°†è§¦å‘此网å€"
msgid "Webhooks|This URL will be triggered when the job status changes"
-msgstr ""
+msgstr "当作业状æ€å˜åŒ–时将触å‘此网å€ã€‚"
msgid "Webhooks|This URL will be triggered when the pipeline status changes"
-msgstr ""
+msgstr "当æµæ°´çº¿çŠ¶æ€å˜åŒ–时将触å‘此网å€ã€‚"
msgid "Webhooks|Trigger"
-msgstr ""
+msgstr "触å‘æ¥æº"
msgid "Webhooks|URL"
-msgstr ""
+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 ""
+msgstr "使用此令牌验è¯æ”¶åˆ°çš„有效数æ®ã€‚它将在X-Gitlab-Token HTTP报头中与请求一起å‘é€ã€‚"
msgid "Webhooks|Wiki Page events"
-msgstr ""
+msgstr "Wiki页é¢äº‹ä»¶"
msgid "Wednesday"
msgstr "星期三"
@@ -30547,7 +31440,7 @@ msgid "Welcome to GitLab"
msgstr "欢迎æ¥åˆ°GitLab"
msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr ""
+msgstr "欢迎使用GitLab%{br_tag}%{name}!"
msgid "Welcome to GitLab, %{first_name}!"
msgstr "欢迎使用GitLab,%{first_name}ï¼"
@@ -30556,25 +31449,25 @@ msgid "Welcome to the guided GitLab tour"
msgstr "欢迎æ¥åˆ°GitLab导览"
msgid "What are you searching for?"
-msgstr "您正在æœç´¢ä»€ä¹ˆï¼Ÿ"
+msgstr "您è¦æœç´¢ä»€ä¹ˆï¼Ÿ"
msgid "What describes you best?"
msgstr "如何形容您最åˆé€‚?"
msgid "What is squashing?"
-msgstr ""
+msgstr "什么是压缩?"
msgid "What is your job title? (optional)"
-msgstr ""
+msgstr "您的工作èŒä½æ˜¯ä»€ä¹ˆï¼Ÿ(å¯é€‰)"
msgid "What's new at GitLab"
-msgstr ""
+msgstr "GitLab的新功能"
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 ""
+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 "当部署作业æˆåŠŸæ—¶ï¼Œè·³è¿‡ä»åœ¨ç­‰å¾…的旧部署作业"
@@ -30583,7 +31476,7 @@ msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "当Runner被é”定时,ä¸èƒ½å°†å…¶åˆ†é…给其他项目"
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 ""
+msgstr "å¯ç”¨åŽï¼Œä»»ä½•è®¿é—® %{host} 并创建å¸æˆ·çš„用户都必须ç»è¿‡ç®¡ç†å‘˜çš„明确许å¯æ‰èƒ½ç™»å½•ã€‚此设置仅在å¯ç”¨æ³¨å†ŒåŽæ‰æœ‰æ•ˆã€‚"
msgid "When enabled, any user visiting %{host} will be able to create an account."
msgstr "å¯ç”¨åŽï¼Œä»»ä½•è®¿é—®%{host}用户都å¯ä»¥åˆ›å»ºä¸€ä¸ªå¸æˆ·ã€‚"
@@ -30610,8 +31503,8 @@ 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 be an approver?"
-msgstr "è°å¯ä»¥æ˜¯æ ¸å‡†äººï¼Ÿ"
+msgid "Who can approve?"
+msgstr ""
msgid "Who can see this group?"
msgstr "哪些人å¯ä»¥çœ‹åˆ°è¿™ä¸ªç¾¤ç»„?"
@@ -30632,13 +31525,13 @@ msgid "Wiki"
msgstr "Wiki"
msgid "Wiki page was successfully created."
-msgstr ""
+msgstr "Wiki页é¢å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Wiki page was successfully deleted."
-msgstr ""
+msgstr "Wiki页é¢å·²æˆåŠŸåˆ é™¤ã€‚"
msgid "Wiki page was successfully updated."
-msgstr ""
+msgstr "Wiki页é¢å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "WikiClone|Clone your wiki"
msgstr "克隆您的 wiki"
@@ -30794,7 +31687,7 @@ msgid "Wiki|Pages"
msgstr "页é¢"
msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
-msgstr ""
+msgstr "侧边æ åŠ è½½å¤±è´¥ã€‚您å¯ä»¥é‡æ–°åŠ è½½é¡µé¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "Wiki|Title"
msgstr "标题"
@@ -30818,7 +31711,7 @@ 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 ""
+msgstr "使用测试用例,您å¯ä»¥å®šä¹‰é¡¹ç›®çš„æ¡ä»¶ä»¥å†³å®šè´¨é‡"
msgid "Withdraw Access Request"
msgstr "å–消æƒé™ç”³è¯·"
@@ -30833,10 +31726,10 @@ msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
msgid "Would you like to create a new branch?"
-msgstr ""
+msgstr "您è¦åˆ›å»ºä¸€ä¸ªæ–°åˆ†æ”¯å—?"
msgid "Would you like to try auto-generating a branch name?"
-msgstr ""
+msgstr "您想å°è¯•è‡ªåŠ¨ç”Ÿæˆåˆ†æ”¯å称å—?"
msgid "Write"
msgstr "编辑"
@@ -30860,7 +31753,7 @@ msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
msgstr "æ供了错误的外部UID。请正确é…ç½®Auth0。"
msgid "YYYY-MM-DD"
-msgstr ""
+msgstr "YYYY-MM-DD"
msgid "Yes"
msgstr "是"
@@ -30887,7 +31780,7 @@ msgid "You already have pending todo for this alert"
msgstr "您已有针对此警报的待处ç†çš„待办事项"
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
-msgstr ""
+msgstr "å³å°†æŠŠ%{usersTag}相关人员添加到讨论中。他们都会收到通知。"
msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
msgstr "å³å°†ä»Žæ‚¨çš„实例中删除 %{domain}。此域å将无法å†ç”¨äºŽä»»ä½•Knorigin应用程åºã€‚"
@@ -30911,31 +31804,31 @@ msgid "You are connected to the Prometheus server, but there is currently no dat
msgstr "您已连接到PrometheusæœåŠ¡å™¨ï¼Œä½†å½“å‰æ²¡æœ‰æ•°æ®å¯æ˜¾ç¤ºã€‚"
msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "å³å°†è¦åˆ é™¤%{project_full_name}。已删除的项目无法æ¢å¤ï¼ç¡®å®šç»§ç»­å—?"
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 ""
+msgstr "å³å°†åˆ é™¤%{group_name},此æ“作åŒæ—¶ä¹Ÿå°†åˆ é™¤å…¶æ‰€æœ‰å­ç¾¤ç»„和项目。已删除的群组将无法æ¢å¤ï¼ç¡®å®šç»§ç»­ï¼Ÿ"
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "å³å°†åˆ é™¤ä¸Žæºé¡¹ç›®%{project_full_name}的派生关系。确定继续å—?"
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "您将è¦å°† %{project_full_name} 转移到å¦ä¸€ä¸ªå称空间。您完全确定å—?"
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 ""
+msgstr "å³å°†å…³é—­ç§å¯†æ€§ã€‚这将使得%{strongStart}所有用户%{strongEnd}都å¯ä»¥æŸ¥çœ‹å¹¶ä¸”评论当å‰%{issuableType}。"
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 ""
+msgstr "å³å°†å¼€å¯ç§å¯†æ€§ã€‚这将使得%{strongStart}至少有Reporter以上æƒé™%{strongEnd}的团队æˆå‘˜æ‰èƒ½æŸ¥çœ‹å¹¶ä¸”评论当å‰%{issuableType}。"
msgid "You are not allowed to approve a user"
-msgstr ""
+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 ""
+msgstr "您无æƒæ‹’ç»ç”¨æˆ·"
msgid "You are not allowed to unlink your primary login account"
msgstr "您ä¸èƒ½å–消与主登录å¸æˆ·çš„å…³è”"
@@ -30944,7 +31837,7 @@ msgid "You are not authorized to perform this action"
msgstr "您无æƒæ‰§è¡Œæ­¤æ“作"
msgid "You are not authorized to update this scanner profile"
-msgstr ""
+msgstr "您无æƒæ›´æ–°æ­¤æ‰«æ工具é…置文件"
msgid "You are now impersonating %{username}"
msgstr "您正在使用%{username}的身份"
@@ -30956,7 +31849,7 @@ msgid "You are receiving this message because you are a GitLab administrator for
msgstr "您收到此消æ¯æ˜¯å› ä¸ºæ‚¨æ˜¯ %{url} çš„GitLab管ç†å‘˜ã€‚"
msgid "You are signed into GitLab as %{user_link}"
-msgstr ""
+msgstr "您以%{user_link}登录到GitLab"
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr "您正在å°è¯•ä¸Šä¼ éžå›¾ç‰‡æ–‡ä»¶ã€‚请上传.pngã€.jpgã€.jpegã€.gifã€.bmpã€.tiff或.ico。"
@@ -30974,7 +31867,7 @@ msgid "You can also press Ctrl-Enter"
msgstr "您也å¯ä»¥æŒ‰ Ctrl-Enter"
msgid "You can also press ⌘-Enter"
-msgstr ""
+msgstr "您也å¯ä»¥æŒ‰âŒ˜-Enter"
msgid "You can also star a label to make it a priority label."
msgstr "å¯ä»¥é€šè¿‡ä¸ºæ ‡è®°è®¾ç½®æ˜Ÿæ ‡æ¥æ高其优先级。"
@@ -30988,14 +31881,17 @@ msgstr "您还å¯ä»¥æŒ‰ç…§ä»¥ä¸‹è¯´æ˜Žä»Žè®¡ç®—机中上传现有文件。"
msgid "You can always edit this later"
msgstr "您也å¯ä»¥ç¨åŽç¼–辑此选项。"
-msgid "You can create a new %{link}."
+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}。"
+
msgid "You can create a new Personal Access Token by visiting %{link}"
-msgstr ""
+msgstr "您å¯ä»¥é€šè¿‡è®¿é—®%{link}创建一个新的个人访问令牌"
msgid "You can create a new SSH key by visiting %{link}"
-msgstr ""
+msgstr "您å¯ä»¥é€šè¿‡è®¿é—®%{link}创建一个新的SSH密钥"
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr "您å¯ä»¥åœ¨%{pat_link_start}个人访问令牌%{pat_link_end}设置中创建新的令牌或检查现有的令牌。"
@@ -31019,7 +31915,7 @@ 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 ""
+msgstr "您å¯ä»¥åœ¨%{subscriptions_doc_link}中找到更多关于GitLab订阅的信æ¯ã€‚"
msgid "You can generate an access token scoped to this project for each application to use the GitLab API."
msgstr "您å¯ä»¥ä¸ºæ¯ä¸ªåº”用程åºç”Ÿæˆé€‚用于此项目的访问令牌,以使用GitLab API。"
@@ -31028,16 +31924,16 @@ msgid "You can get started by cloning the repository or start adding files to it
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 ""
+msgstr "您å¯ä»¥ä½¿ç”¨æ ‡ç­¾å¯¹æµ‹è¯•ç”¨ä¾‹è¿›è¡Œåˆ†ç»„。è¦äº†è§£æ­¤åŠŸèƒ½çš„未æ¥å‘展方å‘,请访问 %{linkStart}è´¨é‡ç®¡ç†æ–¹å‘页%{linkEnd}。"
msgid "You can invite a new member to %{project_name} or invite another group."
-msgstr ""
+msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜æˆ–å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。"
msgid "You can invite a new member to %{project_name}."
-msgstr ""
+msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜åŠ å…¥%{project_name}。"
msgid "You can invite another group to %{project_name}."
-msgstr ""
+msgstr "您å¯ä»¥é‚€è¯·å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。"
msgid "You can move around the graph by using the arrow keys."
msgstr "å¯ä»¥ä½¿ç”¨æ–¹å‘键移动图形。"
@@ -31046,7 +31942,7 @@ msgid "You can notify the app / group or a project by sending them an email noti
msgstr "您å¯ä»¥é€šè¿‡ç”µå­é‚®ä»¶æ¥é€šçŸ¥åº”用程åº/群组或项目"
msgid "You can now close this window."
-msgstr ""
+msgstr "您现在å¯ä»¥å…³é—­æ­¤çª—å£ã€‚"
msgid "You can now export your security dashboard to a CSV report."
msgstr "现在你å¯ä»¥å¯¼å‡ºå®‰å…¨ä»ªè¡¨æ¿åˆ°CSV报告。"
@@ -31078,6 +31974,9 @@ msgstr "通过拖放到现有设计的方å¼ï¼Œæ‚¨æ¯æ¬¡åªèƒ½ä¸Šä¼ ä¸€ä¸ªè®¾è®¡
msgid "You can recover this project until %{date}"
msgstr "您å¯ä»¥åœ¨%{date}之å‰æ¢å¤æ­¤é¡¹ç›®"
+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 "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}"
@@ -31087,9 +31986,6 @@ 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 "您å¯ä»¥å°†ä½œä¸šè®¾ç½®ä¸ºä»…使用具有特定标签的Runners。请使用逗å·åˆ†éš”ä¸åŒæ ‡ç­¾ã€‚"
-
msgid "You can specify notification level per group or per project."
msgstr "您å¯ä»¥æŒ‡å®šæ¯ä¸ªç¾¤ç»„或æ¯ä¸ªé¡¹ç›®çš„通知级别。"
@@ -31097,7 +31993,7 @@ msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "您也å¯ä»¥é€šè¿‡%{linkStart}Lint%{linkEnd}测试.gitlab-ci.yml."
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
-msgstr ""
+msgstr "您å¯ä»¥æŸ¥çœ‹æºä»£ç æˆ–%{linkStart}%{cloneIcon}克隆仓库%{linkEnd}"
msgid "You cannot access the raw file. Please wait a minute."
msgstr "您ä¸èƒ½è®¿é—®åŽŸå§‹æ–‡ä»¶ã€‚请ç¨å€™ã€‚"
@@ -31111,6 +32007,9 @@ 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 "您目å‰æ— æ³•è¿è¡Œæ­¤æµæ°´çº¿è®¡åˆ’。请ç¨å€™ã€‚"
@@ -31124,10 +32023,10 @@ 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 ""
+msgstr "您没有为%{strong}%{namespace_name}%{strong_close}的订阅进行续订,因此它已é™çº§ä¸ºå…费计划。"
msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
-msgstr ""
+msgstr "您没有续订您的订阅,因此它已é™çº§ä¸ºGitLab核心计划。"
msgid "You do not have an active license"
msgstr "您没有有效的许å¯è¯"
@@ -31142,19 +32041,16 @@ msgid "You do not have permission to run the Web Terminal. Please contact a proj
msgstr "您无æƒè¿è¡ŒWeb终端。请è”系项目管ç†å‘˜ã€‚"
msgid "You do not have permission to update the environment."
-msgstr ""
+msgstr "您没有更新此环境的æƒé™ã€‚"
msgid "You do not have permissions to run the import."
msgstr "您没有æƒé™è¿›è¡Œå¯¼å…¥ã€‚"
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr "您没有更改LDAP组åŒæ­¥ä¸­è®¾ç½®çš„相应æƒé™ã€‚"
-
msgid "You don't have any U2F devices registered yet."
msgstr "您还没有注册任何U2F设备。"
msgid "You don't have any WebAuthn devices registered yet."
-msgstr ""
+msgstr "您尚未注册任何WebAuthn设备。"
msgid "You don't have any active chat names."
msgstr "您没有任何活动èŠå¤©ã€‚"
@@ -31205,7 +32101,7 @@ 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 ""
+msgstr "您已被é‡å®šå‘到唯一的结果;改为查看 %{a_start}æœç´¢ç»“æžœ%{a_end}。"
msgid "You have been unsubscribed from this thread."
msgstr "您已å–消订阅该主题。"
@@ -31220,19 +32116,25 @@ 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 "您没有足够的æƒé™ä¸ºæ­¤é¡¹ç›®åˆ›å»ºHTTP集æˆ"
+
+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 ""
+msgstr "您没有足够的æƒé™æ¥åˆ›å»ºæ­¤é¡¹ç›®çš„待命计划"
msgid "You have insufficient permissions to remove an on-call schedule from this project"
-msgstr ""
+msgstr "您没有足够的æƒé™ä»Žæ­¤é¡¹ç›®ä¸­åˆ é™¤é€šè¯è®¡åˆ’"
msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr "您没有足够的æƒé™åˆ é™¤æ­¤HTTP集æˆ"
+
+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 ""
+msgstr "您没有足够的æƒé™æ¥æ›´æ–°æ­¤HTTP集æˆ"
msgid "You have no permissions"
msgstr "没有æƒé™"
@@ -31259,11 +32161,14 @@ msgid "You may close the milestone now."
msgstr "你现在å¯ä»¥å…³é—­è¿™ä¸ªé‡Œç¨‹ç¢‘。"
msgid "You must be logged in to search across all of GitLab"
-msgstr ""
+msgstr "您必须登录æ‰èƒ½åœ¨æ•´ä¸ªGitLab中进行æœç´¢"
msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
msgstr "删除å‰æ‚¨å¿…须将%{domain}从所有相关的集群中解除关è”。"
+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 "必须拥有维护者æƒé™æ‰èƒ½å¼ºåˆ¶åˆ é™¤é”"
@@ -31301,7 +32206,7 @@ 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 ""
+msgstr "您需è¦å…ˆæ³¨å†Œä¸€ä¸ªä¸¤å› ç´ èº«ä»½éªŒè¯åº”用程åºï¼Œç„¶åŽæ‰èƒ½è®¾ç½®è®¾å¤‡ã€‚"
msgid "You need to set terms to be enforced"
msgstr "您需è¦å°†æ¡æ¬¾è®¾ä¸ºå¼ºåˆ¶"
@@ -31313,7 +32218,7 @@ msgid "You need to upload a GitLab project export archive (ending in .gz)."
msgstr "您需è¦ä¸Šä¼ GitLab项目导出文件(以.gz结尾)."
msgid "You successfully declined the invitation"
-msgstr ""
+msgstr "您æˆåŠŸæ‹’ç»äº†é‚€è¯·"
msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
msgstr "您å°è¯•æ´¾ç”Ÿ %{link_to_the_project} 但由于以下原因导致失败:"
@@ -31355,10 +32260,10 @@ msgid "You won't be able to create new projects because you have reached your pr
msgstr "您将无法创建新项目,因为您已ç»è¾¾åˆ°äº†é¡¹ç›®æ•°é™åˆ¶ã€‚"
msgid "You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account"
-msgstr ""
+msgstr "在账å·%{set_password_link} å‰æ‚¨å°†æ— æ³•é€šè¿‡%{protocol}拉å–或推é€ä»£ç ã€‚"
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 ""
+msgstr "æ ¹æ®åè®®æ¡æ¬¾ï¼Œæ‚¨å°†éœ€è¦æŒ‰å­£åº¦æˆ–年支付%{true_up_link_start}超出许å¯è¯ç”¨æˆ·%{link_end}的费用。"
msgid "You'll be signed out from your current account automatically."
msgstr "您将自动从当å‰å¸æˆ·é€€å‡ºã€‚"
@@ -31406,13 +32311,13 @@ msgid "You've already enabled two-factor authentication using one time password
msgstr "您已ç»ä½¿ç”¨ä¸€æ¬¡å¯†ç éªŒè¯å™¨å¯ç”¨äº†åŒé‡è®¤è¯ã€‚如果您è¦æ³¨å†Œä¸åŒçš„设备,您必须先ç¦ç”¨åŒé‡è®¤è¯ã€‚"
msgid "You've rejected %{user}"
-msgstr ""
+msgstr "您拒ç»äº† %{user}"
msgid "YouTube"
msgstr "YouTube"
msgid "YouTube URL or ID"
-msgstr ""
+msgstr "YouTube URL或ID"
msgid "Your %{host} account was signed in to from a new location"
msgstr "您在%{host}上的å¸æˆ·å·²ä»Žä¸€ä¸ªæ–°çš„ä½ç½®ç™»å½•"
@@ -31421,19 +32326,22 @@ msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{nam
msgstr "您为%{strong}%{namespace_name}%{strong_close}的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。"
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 "您的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。此åŽï¼Œæ‚¨å°†æ— æ³•åˆ›å»ºè®®é¢˜æˆ–åˆå¹¶è¯·æ±‚,åŒæ—¶ä¹Ÿæ— æ³•è®¿é—®å…¶ä»–众多功能。"
+
+msgid "Your CI configuration file is invalid."
msgstr ""
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
msgstr "CSV导出已ç»å¼€å§‹ã€‚完æˆåŽå°†å‘é€ç”µå­é‚®ä»¶è‡³%{email}。"
msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
-msgstr ""
+msgstr "您从项目%{project_link}导出包å«%{count}çš„CSV文件已作为附件添加到此电å­é‚®ä»¶ä¸­ã€‚"
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
msgstr "您从项目%{project_name}(%{project_url})导出包å«%{written_count}çš„CSV文件已作为附件添加到此电å­é‚®ä»¶ä¸­ã€‚"
msgid "Your CSV import for project"
-msgstr ""
+msgstr "您的项目CSV导入"
msgid "Your Commit Email will be used for web based operations, such as edits and merges."
msgstr "您的æ交电å­é‚®ä»¶å°†ç”¨äºŽåŸºäºŽwebçš„æ“作,例如编辑与åˆå¹¶ã€‚"
@@ -31442,13 +32350,13 @@ msgid "Your Default Notification Email will be used for account notifications if
msgstr "如果没有设置%{openingTag}群组特定的电å­é‚®ä»¶åœ°å€%{closingTag} ,您的默认通知电å­é‚®ä»¶å°†ç”¨äºŽå¸æˆ·é€šçŸ¥ã€‚"
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 ""
+msgstr "您的DevOps报告概述了从功能角度使用GitLabçš„æ–¹å¼ã€‚查看您的组织与其他组织的比较,å‘现您尚未å°è¯•ä½¿ç”¨çš„功能,并通过åšå®¢æ–‡ç« å’Œç™½çš®ä¹¦äº†è§£æœ€ä½³å®žè·µã€‚"
msgid "Your GPG keys (%{count})"
msgstr "您的GPG密钥 (%{count})"
msgid "Your GitLab account request has been approved!"
-msgstr ""
+msgstr "您的GitLabå¸æˆ·åˆ›å»ºè¯·æ±‚已被批准ï¼"
msgid "Your GitLab group"
msgstr "您的GitLab群组"
@@ -31463,7 +32371,7 @@ msgid "Your License"
msgstr "您的许å¯è¯"
msgid "Your Personal Access Token was revoked"
-msgstr ""
+msgstr "您的个人访问令牌已被åŠé”€ã€‚"
msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
msgstr "您的个人访问令牌将在%{days_to_expire}天内过期。"
@@ -31481,7 +32389,7 @@ msgid "Your Public Email will be displayed on your public profile."
msgstr "您的公共电å­é‚®ä»¶å°†åœ¨æ‚¨çš„公开信æ¯ä¸­æ˜¾ç¤ºã€‚"
msgid "Your SSH key was deleted"
-msgstr ""
+msgstr "您的SSH密钥已删除"
msgid "Your SSH keys (%{count})"
msgstr "您的SSH密钥(%{count})"
@@ -31495,11 +32403,14 @@ msgstr "您的 U2F 设备没有å‘é€æœ‰æ•ˆçš„ JSON å“应。"
msgid "Your U2F device was registered!"
msgstr "您的 U2F 设备已注册ï¼"
-msgid "Your WebAuthn device did not send a valid JSON response."
+msgid "Your Version"
msgstr ""
+msgid "Your WebAuthn device did not send a valid JSON response."
+msgstr "您的WebAuthn设备未å‘é€æœ‰æ•ˆçš„JSONå“应。"
+
msgid "Your WebAuthn device was registered!"
-msgstr ""
+msgstr "您的WebAuthn设备已注册ï¼"
msgid "Your access request to the %{source_type} has been withdrawn."
msgstr "您对 %{source_type} 访问请求已被撤消。"
@@ -31523,7 +32434,7 @@ msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (versi
msgstr "您的æµè§ˆå™¨ä¸æ”¯æŒU2F。请使用Google Chromeæ¡Œé¢ç‰ˆï¼ˆ41或更高版本)。"
msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
-msgstr ""
+msgstr "您的æµè§ˆå™¨ä¸æ”¯æŒWebAuthn。请使用支æŒçš„æµè§ˆå™¨ï¼Œå¦‚Chrome(67+)或Firefox(60+)。"
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "åˆå¹¶è¯·æ±‚已开å¯ï¼Œå¯ä»¥æ交å˜æ›´åˆ°%{branch_name}。"
@@ -31562,14 +32473,17 @@ msgid "Your deployment services will be broken, you will need to manually fix th
msgstr "您的部署æœåŠ¡å°†å¤±æ•ˆï¼Œéœ€è¦åœ¨é‡å‘½ååŽæ‰‹åŠ¨ä¿®å¤æœåŠ¡ã€‚"
msgid "Your device is not compatible with GitLab. Please try another device"
-msgstr ""
+msgstr "您的设备与GitLabä¸å…¼å®¹ã€‚请å°è¯•å…¶ä»–设备"
msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
-msgstr ""
+msgstr "您的设备需è¦è®¾ç½®ã€‚将其æ’入(如果需è¦ï¼‰ï¼Œç„¶åŽå•å‡»å·¦ä¾§çš„按钮。"
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr "您的设备已æˆåŠŸè®¾ç½®ï¼è¯·ç»™å®ƒå‘½å并将其注册到GitLabæœåŠ¡å™¨ã€‚"
+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 "您的第一个项目"
@@ -31580,7 +32494,7 @@ msgid "Your instance has %{remaining_user_count} users remaining of the %{total_
msgstr "您的实例中包å«%{remaining_user_count}个用户,而您的订阅中包å«%{total_user_count}个用户。您å¯ä»¥æ·»åŠ è¶…过许å¯è¯ä¸­åŒ…å«çš„用户数,我们将在您的下一份账å•ä¸­åŒ…括超é¢è´¹ç”¨ã€‚"
msgid "Your instance has exceeded your subscription's licensed user count."
-msgstr ""
+msgstr "您的实例已超出您的订阅许å¯ç”¨æˆ·æ•°é‡ã€‚"
msgid "Your instance is approaching its licensed user count"
msgstr "您的实例å³å°†è¾¾åˆ°è®¸å¯ç”¨æˆ·æ•°"
@@ -31591,9 +32505,12 @@ 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 schedules"
+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 "您的许å¯è¯æœ‰æ•ˆæœŸè‡ª"
@@ -31643,9 +32560,12 @@ msgid "Your request for access has been queued for review."
msgstr "您的访问请求已进入审核队列。"
msgid "Your request to join %{host} has been rejected."
-msgstr ""
+msgstr "您在%{host}上注册账户的请求已被拒ç»ã€‚"
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."
@@ -31658,7 +32578,7 @@ msgid "Your search didn't match any commits. Try a different query."
msgstr "您的æœç´¢ä¸ŽæœªåŒ¹é…任何æ交。请å°è¯•å…¶ä»–查询。"
msgid "Your sign-in page is %{url}."
-msgstr ""
+msgstr "您的登录页é¢ä¸º%{url}。"
msgid "Your subscription expired!"
msgstr "您的订阅已过期ï¼"
@@ -31670,7 +32590,7 @@ msgid "Your subscription will expire in %{remaining_days}."
msgstr "您的订阅将在%{remaining_days}åŽè¿‡æœŸ."
msgid "Your username is %{username}."
-msgstr ""
+msgstr "您的用户å是%{username}。"
msgid "Zoom meeting added"
msgstr "已添加Zoom会议"
@@ -31722,7 +32642,7 @@ msgid "among other things"
msgstr "åŠå…¶ä»–功能"
msgid "and"
-msgstr ""
+msgstr "和"
msgid "any-approver for the merge request already exists"
msgstr "åˆå¹¶è¯·æ±‚已有任æ„核准人(any-approver)"
@@ -31745,6 +32665,9 @@ msgstr "作为%{role}。"
msgid "assign yourself"
msgstr "分é…给自己"
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr "存在风险"
@@ -31763,20 +32686,26 @@ msgstr "分支å称"
msgid "by"
msgstr "æ¥è‡ª"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
+msgstr "如果å¯ç”¨å…±äº«Runner,则无法更改"
msgid "cannot be enabled because parent group does not allow it"
-msgstr ""
+msgstr "无法å¯ç”¨ï¼Œå› ä¸ºçˆ¶ç¾¤ç»„ä¸å…许"
msgid "cannot be enabled because parent group has shared Runners disabled"
-msgstr ""
+msgstr "无法å¯ç”¨ï¼Œå› ä¸ºçˆ¶ç¾¤ç»„å·²ç¦ç”¨å…±äº«Runner"
msgid "cannot be enabled unless all domains have TLS certificates"
msgstr "除éžæ‰€æœ‰åŸŸéƒ½å…·æœ‰TLSè¯ä¹¦ï¼Œå¦åˆ™æ— æ³•å¯ç”¨"
@@ -31808,6 +32737,9 @@ msgstr "å·²é™ä½Ž%{degradedNum}"
msgid "ciReport|%{improvedNum} improved"
msgstr "已改进%{improvedNum}"
+msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}了解更多有关容器安全扫æçš„ä¿¡æ¯ %{linkEndTag}"
@@ -31824,7 +32756,7 @@ msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
msgstr "%{linkStartTag}了解更多有关SAST %{linkEndTag}çš„ä¿¡æ¯"
msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解更多关于密ç æ£€æµ‹çš„ä¿¡æ¯%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr "%{linkStartTag}了解有关代ç è´¨é‡æŠ¥å‘Šçš„更多信æ¯%{linkEndTag}"
@@ -31842,9 +32774,12 @@ msgid "ciReport|%{sameNum} same"
msgstr "相åŒ%{sameNum}"
msgid "ciReport|: Loading resulted in an error"
-msgstr ""
+msgstr ": 加载导致错误"
msgid "ciReport|API Fuzzing"
+msgstr "API模糊测试"
+
+msgid "ciReport|API fuzzing"
msgstr ""
msgid "ciReport|All projects"
@@ -32003,6 +32938,9 @@ 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] "已用于 %{packagesString} 和 %{lastPackage}"
@@ -32011,16 +32949,16 @@ msgid "ciReport|View full report"
msgstr "查看完整报告"
msgid "ciReport|is loading"
-msgstr ""
+msgstr "正在加载"
msgid "ciReport|is loading, errors when loading results"
-msgstr ""
+msgstr "正在加载,加载结果时出错"
msgid "closed issue"
msgstr "已关闭议题"
msgid "collect usage information"
-msgstr ""
+msgstr "收集使用信æ¯"
msgid "comment"
msgstr "评论"
@@ -32148,7 +33086,7 @@ msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr "无法忽略关è”çš„å‘现(id=%{finding_id}): %{message}"
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
-msgstr ""
+msgstr "无法将关è”çš„å‘现(id=%{finding_id})æ¢å¤åˆ°ä¸ºæ£€æµ‹åˆ°"
msgid "file"
msgid_plural "files"
@@ -32173,7 +33111,7 @@ msgid "for this project"
msgstr "对于这个项目"
msgid "fork"
-msgstr ""
+msgstr "派生"
msgid "fork this project"
msgstr "派生此项目"
@@ -32183,7 +33121,7 @@ msgstr "æ¥è‡ª"
msgid "from %d job"
msgid_plural "from %d jobs"
-msgstr[0] ""
+msgstr[0] "æ¥è‡ª%d个作业"
msgid "group"
msgstr "群组"
@@ -32200,9 +33138,15 @@ msgstr "å·²ç»é“¾æŽ¥åˆ°å¦ä¸€ä¸ªæ¼æ´ž"
msgid "has already been taken"
msgstr "已被使用"
-msgid "has been completed."
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
msgstr ""
+msgid "has been completed."
+msgstr "已完æˆã€‚"
+
msgid "help"
msgstr "帮助"
@@ -32225,7 +33169,7 @@ msgid "import flow"
msgstr "导入æµç¨‹"
msgid "in"
-msgstr ""
+msgstr "于"
msgid "in group %{link_to_group}"
msgstr "在 %{link_to_group} 群组"
@@ -32253,7 +33197,7 @@ msgid "is blocked by"
msgstr "已被阻止。阻止项为"
msgid "is forbidden by a top-level group"
-msgstr ""
+msgstr "被顶级群组ç¦æ­¢"
msgid "is invalid because there is downstream lock"
msgstr "因下游é”定而无效"
@@ -32271,13 +33215,13 @@ msgid "is not a valid X509 certificate."
msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
msgid "is not allowed since the group is not top-level group."
-msgstr ""
+msgstr "ä¸å…许,因为该群组ä¸æ˜¯é¡¶çº§ç¾¤ç»„。"
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr "ä¸è¢«å…许。请使用其他电å­é‚®ä»¶åœ°å€é‡è¯•ï¼Œæˆ–与您的GitLab管ç†å‘˜è”系。"
msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
+msgstr "ä¸è¢«å…许。我们目å‰ä¸æ”¯æŒé¡¹ç›®çº§è¿­ä»£"
msgid "is not an email you own"
msgstr "ä¸æ˜¯æ‚¨è‡ªå·±çš„电å­é‚®ä»¶"
@@ -32292,7 +33236,7 @@ msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "太长(%{current_value})。最大值为%{max_size}。"
msgid "is too long (maximum is %{count} characters)"
-msgstr ""
+msgstr "过长(最长为 %{count} 个字符)"
msgid "is too long (maximum is 100 entries)"
msgstr "太长(最多100个æ¡ç›®ï¼‰"
@@ -32331,7 +33275,7 @@ msgid "jigsaw is not defined"
msgstr "拼图未定义"
msgid "kuromoji custom analyzer"
-msgstr ""
+msgstr "kuromoji自定义分æžå™¨"
msgid "last commit:"
msgstr "最åŽæ交:"
@@ -32381,6 +33325,9 @@ 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] "åˆå¹¶è¯·æ±‚"
@@ -32395,7 +33342,7 @@ msgid "missing"
msgstr "丢失"
msgid "more information"
-msgstr ""
+msgstr "更多信æ¯"
msgid "most recent deployment"
msgstr "最近的部署"
@@ -32437,13 +33384,13 @@ msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineL
msgstr "当å‰%{prefixToLinkStart}æ— æµæ°´çº¿%{prefixToLinkEnd},å¯é€šè¿‡%{addPipelineLinkStart}添加.gitlab-ci.yml æ–‡%{addPipelineLinkEnd}æ¥åˆ›å»ºä¸€ä¸ªã€‚"
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
-msgstr ""
+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 ""
+msgstr "已添加到åˆå¹¶åˆ—车。当å‰æœ‰%{mergeTrainPosition}个åˆå¹¶è¯·æ±‚等待åˆå¹¶"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
@@ -32458,7 +33405,7 @@ msgid "mrWidget|An error occurred while submitting your approval."
msgstr "æ交批准时å‘生错误。"
msgid "mrWidget|Approval is optional"
-msgstr ""
+msgstr "核准为å¯é€‰"
msgid "mrWidget|Approval password is invalid."
msgstr "批准密ç æ— æ•ˆ"
@@ -32467,7 +33414,7 @@ msgid "mrWidget|Approve"
msgstr "批准"
msgid "mrWidget|Approve additionally"
-msgstr "å¦å¤–核准"
+msgstr "é¢å¤–核准"
msgid "mrWidget|Approved by"
msgstr "核准人:"
@@ -32647,10 +33594,10 @@ 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 ""
+msgstr "æ­¤æ“作将在æµæ°´çº¿%{pipelineLink}æˆåŠŸæ—¶å°†åˆå¹¶è¯·æ±‚加入åˆå¹¶åˆ—车。"
msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
+msgstr "æ­¤æ“作将在æµæ°´çº¿%{pipelineLink}æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶åˆ—车。"
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 "此功能是从目标分支åˆå¹¶åˆ°æºåˆ†æ”¯çš„更改。您无法使用此功能,因为æºåˆ†æ”¯å—到ä¿æŠ¤ã€‚"
@@ -32707,7 +33654,7 @@ msgid "must be a root namespace"
msgstr "必须是根命å空间"
msgid "must be a valid IPv4 or IPv6 address"
-msgstr ""
+msgstr "必须是有效的IPv4或IPv6地å€"
msgid "must be greater than start date"
msgstr "必须大于开始日期"
@@ -32746,13 +33693,13 @@ msgid "no expiration"
msgstr "无过期"
msgid "no name set"
-msgstr ""
+msgstr "未设置å称"
msgid "no one can merge"
msgstr "没有人å¯ä»¥åˆå¹¶"
msgid "no scopes selected"
-msgstr ""
+msgstr "未选择范围"
msgid "none"
msgstr "æ— "
@@ -32782,7 +33729,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}"
@@ -32797,7 +33744,7 @@ msgid "or"
msgstr "或"
msgid "originating vulnerability"
-msgstr ""
+msgstr "åˆå§‹æ¼æ´ž"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
@@ -32873,7 +33820,7 @@ msgid "project members"
msgstr "项目æˆå‘˜"
msgid "project name"
-msgstr ""
+msgstr "项目å称"
msgid "projects"
msgstr "项目"
@@ -32882,7 +33829,7 @@ msgid "quick actions"
msgstr "å¿«æ·æ“作"
msgid "recent activity"
-msgstr ""
+msgstr "最近活动"
msgid "register"
msgstr "注册"
@@ -32928,7 +33875,7 @@ msgid "security Reports|There was an error creating the merge request"
msgstr "创建åˆå¹¶è¯·æ±‚时出错"
msgid "severity|Blocker"
-msgstr ""
+msgstr "阻塞"
msgid "severity|Critical"
msgstr "严é‡"
@@ -32943,13 +33890,13 @@ msgid "severity|Low"
msgstr "低"
msgid "severity|Major"
-msgstr ""
+msgstr "主è¦"
msgid "severity|Medium"
msgstr "中"
msgid "severity|Minor"
-msgstr ""
+msgstr "次è¦"
msgid "severity|None"
msgstr "æ— "
@@ -32976,7 +33923,7 @@ msgid "sign in"
msgstr "登录"
msgid "smartcn custom analyzer"
-msgstr ""
+msgstr "smartcn自定义分æžå™¨"
msgid "sort:"
msgstr "排åºï¼š"
@@ -33029,20 +33976,11 @@ 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 "我们正在添加GitLab CIé…置文件,以将æµæ°´çº¿æ·»åŠ åˆ°é¡¹ç›®ä¸­ã€‚您也å¯ä»¥æ‰‹åŠ¨åˆ›å»ºï¼Œä½†æˆ‘们建议您从一个开箱å³ç”¨çš„GitLab模æ¿å¼€å§‹ã€‚"
-msgid "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr "标签å称"
-msgid "teammate%{number}@company.com"
-msgstr "teammate%{number}@company.com"
-
msgid "the correct format."
-msgstr ""
+msgstr "正确的格å¼ã€‚"
msgid "the following issue(s)"
msgstr "下列议题"
@@ -33051,10 +33989,10 @@ msgid "this document"
msgstr "此文档"
msgid "time summary"
-msgstr ""
+msgstr "时间总计"
msgid "to automatically add approvers based on file paths and file types."
-msgstr ""
+msgstr "æ¥æ ¹æ®æ–‡ä»¶è·¯å¾„和文件类型自动添加审批人。"
msgid "to help your contributors communicate effectively!"
msgstr "帮助您的贡献者进行有效沟通ï¼"
@@ -33072,7 +34010,7 @@ msgid "triggered"
msgstr "已触å‘"
msgid "two-factor authentication settings"
-msgstr ""
+msgstr "åŒé‡è®¤è¯è®¾ç½®"
msgid "unicode domains should use IDNA encoding"
msgstr "unicode域å应使用IDNAç¼–ç "
@@ -33096,7 +34034,7 @@ msgid "user avatar"
msgstr "用户头åƒ"
msgid "user preferences"
-msgstr ""
+msgstr "用户首选项"
msgid "username"
msgstr "用户å"
@@ -33130,7 +34068,7 @@ msgstr "查看æºä»£ç "
msgid "vulnerability"
msgid_plural "vulnerabilities"
-msgstr[0] ""
+msgstr[0] "æ¼æ´ž"
msgid "vulnerability|Add a comment"
msgstr "添加评论"
@@ -33145,7 +34083,7 @@ msgid "vulnerability|Add comment & dismiss"
msgstr "添加评论并忽略"
msgid "vulnerability|Add comment and dismiss"
-msgstr ""
+msgstr "添加评论并忽略"
msgid "vulnerability|Dismiss vulnerability"
msgstr "忽略æ¼æ´ž"
@@ -33178,5 +34116,5 @@ msgid "yaml invalid"
msgstr "yaml无效"
msgid "your settings"
-msgstr ""
+msgstr "您的设置"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index d05ec6c77db..3b33ba6f497 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: 2020-12-03 08:11\n"
+"PO-Revision-Date: 2021-01-08 22:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
msgstr ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
@@ -867,9 +888,15 @@ 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 ""
@@ -1086,28 +1113,25 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-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."
+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."
+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."
+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."
+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."
@@ -1119,6 +1143,9 @@ 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 ""
@@ -1146,6 +1173,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 ""
@@ -1155,6 +1185,9 @@ 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 ""
@@ -1173,13 +1206,16 @@ 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."
+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."
+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"
@@ -1188,10 +1224,13 @@ 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 ready-to-go template for use with Android apps."
+msgid "A ready-to-go template for use with Android apps"
msgstr ""
-msgid "A ready-to-go template for use with iOS Swift apps."
+msgid "A ready-to-go template for use with iOS Swift apps"
+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"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 "一個有存å–原始分支權é™çš„使用者,é¸æ“‡äº†æ­¤é …ç›®"
@@ -1224,13 +1269,16 @@ msgstr ""
msgid "AWS Access Key"
msgstr ""
-msgid "AWS Access Key. Only required if not using role instance credentials"
+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"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
msgstr ""
msgid "Abort"
@@ -1272,6 +1320,9 @@ 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 ""
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr ""
msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr ""
msgid "All changes are committed"
msgstr "所有改變都已經æ交"
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -2744,6 +2780,9 @@ 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 ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 "更新議題權é‡æ™‚發生錯誤"
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
-
msgid "An error occurred while saving assignees"
msgstr "儲存指派人時發生錯誤"
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr ""
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr ""
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -3739,6 +3790,12 @@ msgstr "指派標籤"
msgid "Assign milestone"
msgstr "指派里程碑"
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr "分é…一些議題到這個里程碑。"
@@ -3757,12 +3814,18 @@ 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 ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,10 +4065,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4023,10 +4089,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4146,12 +4212,21 @@ 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 "群組徽章"
@@ -4161,15 +4236,15 @@ 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|Please fill in a valid URL"
-msgstr ""
-
msgid "Badges|Project Badge"
msgstr "專案徽章"
@@ -4182,15 +4257,12 @@ msgstr "儲存變更"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr "儲存徽章失敗,請檢查輸入的連çµä¸¦é‡è©¦ã€‚"
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr "%{docsLinkStart} 變數%{docsLinkEnd} GitLab 支æ´ï¼š%{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
msgid "Badges|The badge was deleted."
msgstr "此徽章已移除"
-msgid "Badges|The badge was saved."
-msgstr "此徽章已儲存。"
-
msgid "Badges|This group has no badges"
msgstr "此群組無徽章。"
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr "您的徽章"
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr "分支å稱"
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -4627,6 +4729,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4747,10 +4870,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4780,9 +4903,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 "å–消"
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 ""
@@ -5014,13 +5179,16 @@ 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 "將標題改為「%{title_param}ã€ã€‚"
-msgid "Changes were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5575,6 +5749,18 @@ 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 ""
@@ -6682,10 +6868,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,13 +8013,10 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues 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."
+msgid "Create an incident. Incidents are created for each alert triggered."
msgstr ""
-msgid "Create board"
+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"
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -7929,6 +8139,84 @@ msgstr "標籤"
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "創建個人訪å•ä»¤ç‰Œ"
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8734,6 +9004,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 語法定義自定義模å¼"
+msgid "Define approval settings."
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr "刪除留言"
@@ -9244,9 +9514,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr "æè¿°"
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9854,9 +10184,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr "編輯留言"
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ 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 ""
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 ""
@@ -10691,9 +11042,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr "é€éŽé‡Œç¨‹ç¢‘å稱篩é¸"
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr "按路徑查找"
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr "查找文件"
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13113,9 +13467,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13449,10 +13800,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13859,6 +14243,9 @@ msgstr "已開始維護"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14152,6 +14548,9 @@ msgstr ""
msgid "Import repository"
msgstr "導入存儲庫"
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr "議題事件"
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr "了解更多"
msgid "Learn more in the|pipeline schedules documentation"
msgstr "æµæ°´ç·šè¨ˆåŠƒæ–‡æª”"
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr "åˆä½µè«‹æ±‚"
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr "å·²åˆä½µ"
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr "éžéš±å¯†"
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19711,10 +20282,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr "æˆåŠŸçŽ‡ï¼š"
msgid "PipelineCharts|Successful:"
msgstr "æˆåŠŸï¼š"
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 ""
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 ""
@@ -20767,6 +21395,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 ""
@@ -21097,9 +21731,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,7 +21926,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr "存儲庫"
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr "申請權é™"
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,7 +23782,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23139,9 +23812,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr "ä¹æœˆ"
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr "顯示所有活動"
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25302,6 +25990,9 @@ 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 ""
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,7 +27604,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr "議題階段概述了從創建議題到將議題添加到è£ç¨‹ç¢‘或議
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ 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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr "å–消星標"
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權é™ä¸è¶³ã€‚如需查看相關數據,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 ""
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 ""
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr "分支å稱"
msgid "by"
msgstr ""
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] ""
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 35de6808d39..787e9b452c2 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: 2020-12-03 08:13\n"
+"PO-Revision-Date: 2021-01-08 22:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -303,12 +303,21 @@ 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 "%{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 ""
@@ -716,6 +725,18 @@ msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} 次æ交"
+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] ""
+
+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] ""
+
+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] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr "%{strong_start}%{human_size}%{strong_end} 檔案"
@@ -867,9 +888,15 @@ msgstr "(%{mrCount} å·²åˆä½µ)"
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 "(檢查進度)"
@@ -1086,29 +1113,26 @@ msgstr ""
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
msgstr ""
-msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "「執行器ã€æ˜¯ä¸€å€‹åŸ·è¡Œä½œæ¥­çš„行程。您å¯ä»¥æ ¹æ“šéœ€è¦é…置任æ„個執行器。"
-
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr ".NET Core 控制å°æ‡‰ç”¨ç¨‹å¼ç¯„本,å¯é‡å°ä»»ä½• .NET Core 專案自訂"
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 "一個 GitBook ç«™å°ï¼Œä½¿ç”¨ Netlify 代替 GitLab çš„ CI/CD,但ä»å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„ GitLab 功能。"
+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 "一個 Hexo ç«™å°ï¼Œä½¿ç”¨ Netlify 代替 GitLab çš„ CI/CD,但ä»å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„ GitLab 功能。"
+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 "一個 Hugo ç«™å°ï¼Œä½¿ç”¨ Netlify 代替 GitLab çš„ CI/CD,但ä»å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„ GitLab 功能。"
+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 "一個 Jekyll ç«™å°ï¼Œä½¿ç”¨ Netlify 代替 GitLab çš„ CI/CD,但ä»å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„ GitLab 功能。"
+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 "在網域驗證之å‰ï¼Œæˆ‘們無法å–å¾— Encrype SSL 憑證。"
@@ -1119,6 +1143,9 @@ msgstr "將會使用您的電å­ä¿¡ç®±ä½å€è¨­å®šæ­¤ GitLab 實體的 Let's Enc
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "使用 AWS Lambdaã€AWS API é–˜é“åŠ GitLab Pages 的基本é é¢å’Œç„¡ä¼ºæœå™¨åŠŸèƒ½"
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
msgid "A complete DevOps platform"
msgstr ""
@@ -1146,6 +1173,9 @@ msgstr ""
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
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 "濫用審查團隊æˆå“¡å°‡æœƒå„˜å¿«æª¢é–±æ‚¨çš„報告。"
@@ -1155,6 +1185,9 @@ 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 "已建立新的自動 DevOps æµæ°´ç·šï¼Œè«‹å‰å¾€ %{pipelines_link_start}æµæ°´ç·šé é¢%{pipelines_link_end} 檢視詳細訊æ¯ã€‚"
@@ -1173,14 +1206,17 @@ 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 "一個純 HTML ç«™å°ï¼Œä½¿ç”¨ Netlify 代替 GitLab çš„ CI/CD,但ä»å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„ GitLab 功能。"
+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 "使用 Salesforce 開發者工具開發 Salesforce 應用程å¼çš„專案範本。"
+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 ""
@@ -1188,11 +1224,14 @@ 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 ready-to-go template for use with Android apps."
-msgstr "é©ç”¨æ–¼ Android 應用程å¼ï¼Œæº–備就緒的範本。"
+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 "é©ç”¨æ–¼ iOS Swift 應用程å¼ï¼Œæº–備就緒的範本。"
+msgid "A ready-to-go template for use with iOS Swift apps"
+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 "用來在作業記錄中尋找測試覆蓋率輸出的正è¦è¡¨ç¤ºå¼ã€‚空白則åœç”¨"
@@ -1203,9 +1242,15 @@ 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 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 ""
+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 "有ä½å…·æœ‰ä¾†æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†æ­¤é¸é …"
@@ -1224,14 +1269,17 @@ msgstr "API 權æ–"
msgid "AWS Access Key"
msgstr "AWS å­˜å–金鑰"
-msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr "AWS å­˜å–金鑰。åªåœ¨ä¸ä½¿ç”¨è§’色實體憑證時需è¦"
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
msgid "AWS Secret Access Key"
msgstr "AWS 密碼存å–金鑰"
-msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr "AWS 密碼存å–金鑰。åªåœ¨ä¸ä½¿ç”¨è§’色實體憑證時需è¦"
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
msgid "Abort"
msgstr "中止"
@@ -1272,6 +1320,9 @@ msgstr "å­˜å–您的 LDAP 帳號時被拒絕。"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "å­˜å–被拒ï¼è«‹æª¢æŸ¥æ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
+msgid "Access denied: %{error}"
+msgstr ""
+
msgid "Access expiration date"
msgstr "å­˜å–éŽæœŸæ™‚é–“"
@@ -1864,6 +1915,9 @@ msgstr ""
msgid "AdminSettings|Auto DevOps domain"
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 ""
@@ -1873,6 +1927,9 @@ msgstr "啟用新專案的共享執行器"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "環境變數é è¨­å—ä¿è­·"
+msgid "AdminSettings|Feed token"
+msgstr ""
+
msgid "AdminSettings|Go to General Settings"
msgstr ""
@@ -2348,9 +2405,6 @@ msgstr ""
msgid "AlertManagement|Open"
msgstr ""
-msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2414,15 +2468,9 @@ msgstr ""
msgid "AlertManagement|Value"
msgstr ""
-msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
-
msgid "AlertManagement|View incident"
msgstr ""
-msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
-
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
@@ -2450,9 +2498,6 @@ msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
-msgid "AlertSettings|2. Add link to your Opsgenie alert list"
-msgstr ""
-
msgid "AlertSettings|2. Name integration"
msgstr ""
@@ -2522,10 +2567,10 @@ msgstr ""
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
msgstr ""
-msgid "AlertSettings|Opsgenie"
+msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Proceed with editing"
+msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
@@ -2591,12 +2636,6 @@ 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|Utilizing this option will link the GitLab Alerts navigation item to your existing Opsgenie instance. By selecting this option, you cannot receive alerts from any other source in GitLab; it will effectively be turning Alerts within GitLab off as a feature."
-msgstr ""
-
-msgid "AlertSettings|We will soon be introducing the ability to create multiple unique HTTP endpoints. When this functionality is live, you will be able to configure an integration with Opsgenie to surface Opsgenie alerts in GitLab. This will replace the current Opsgenie integration which will be deprecated. %{linkStart}More Information%{linkEnd}"
-msgstr ""
-
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -2681,9 +2720,6 @@ msgstr "所有分支"
msgid "All changes are committed"
msgstr "所有變更å‡å·²æ交"
-msgid "All default stages are currently visible"
-msgstr ""
-
msgid "All email addresses will be used to identify your commits."
msgstr "所有電å­éƒµä»¶åœ°å€éƒ½å¯ç”¨æ–¼è­˜åˆ¥æ‚¨çš„æ交。"
@@ -2744,6 +2780,9 @@ msgstr "å…è¨±ç¾¤çµ„æ‰€æœ‰è€…ç®¡ç† LDAP 相關的設定"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "僅å…許é¸å–之用於 Git å­˜å–的通訊å”定。"
+msgid "Allow overrides to approval lists per merge request (MR)"
+msgstr ""
+
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -2882,7 +2921,7 @@ msgstr ""
msgid "An error has occurred"
msgstr "發生錯誤"
-msgid "An error occured while making the changes: %{error}"
+msgid "An error occured while saving changes: %{error}"
msgstr ""
msgid "An error occurred adding a draft to the thread."
@@ -2918,6 +2957,9 @@ 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 "更新議題權é‡æ™‚發生錯誤"
@@ -2930,6 +2972,9 @@ 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 ""
@@ -3152,9 +3197,6 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr "儲存 LDAP 覆蓋狀態時發生錯誤,請é‡è©¦ã€‚"
-
msgid "An error occurred while saving assignees"
msgstr "儲存å—託人時發生錯誤。"
@@ -3176,6 +3218,9 @@ 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 ""
@@ -3185,6 +3230,9 @@ 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 ""
@@ -3203,7 +3251,7 @@ msgstr "發生了錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "An error ocurred while loading your content. Please try again."
msgstr ""
-msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+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"
@@ -3218,6 +3266,9 @@ 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 ""
@@ -3296,7 +3347,7 @@ msgstr ""
msgid "Any label"
msgstr ""
-msgid "Any member with Developer or higher permissions to the project."
+msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
@@ -3441,13 +3492,13 @@ msgstr[0] ""
msgid "ApprovalRule|Approval rules"
msgstr ""
-msgid "ApprovalRule|Approvers"
+msgid "ApprovalRule|Approvals required"
msgstr ""
-msgid "ApprovalRule|Name"
+msgid "ApprovalRule|Approvers"
msgstr ""
-msgid "ApprovalRule|No. approvals required"
+msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Rule name"
@@ -3468,6 +3519,9 @@ msgstr ""
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
+msgid "Approvals are optional."
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
@@ -3570,9 +3624,6 @@ msgstr "確定è¦åˆªé™¤æ­¤%{typeOfComment}嗎?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
-msgid "Are you sure you want to delete this board?"
-msgstr "確定è¦åˆªé™¤æ­¤çœ‹æ¿å—Žï¼Ÿ"
-
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "您確定è¦åˆªé™¤æ­¤è£ç½®å—Žï¼Ÿæ­¤å‹•ä½œç„¡æ³•å¾©åŽŸã€‚"
@@ -3739,6 +3790,12 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -3757,12 +3814,18 @@ 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 ""
@@ -3775,6 +3838,9 @@ msgstr ""
msgid "Assigned to me"
msgstr ""
+msgid "Assigned to you"
+msgstr ""
+
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -3797,6 +3863,9 @@ 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 ""
@@ -3840,9 +3909,6 @@ msgstr ""
msgid "Audit Events is a way to keep track of important events that happened in GitLab."
msgstr ""
-msgid "Audit Log"
-msgstr ""
-
msgid "AuditLogs|(removed)"
msgstr ""
@@ -3999,10 +4065,10 @@ msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
-msgid "AutoDevOps|Auto DevOps"
+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 can automatically build, test, and deploy applications based on predefined continuous integration and delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end} or use our %{quickstart_start}quick start guide%{quickstart_end} to get started right away."
+msgid "AutoDevOps|Auto DevOps"
msgstr ""
msgid "AutoDevOps|Auto DevOps documentation"
@@ -4023,10 +4089,13 @@ 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 solution available"
+msgid "AutoRemediation|Auto-fix"
msgstr ""
msgid "AutoRemediation|Auto-fix solutions"
@@ -4068,7 +4137,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4131,9 +4200,6 @@ msgstr ""
msgid "Badges"
msgstr ""
-msgid "Badges|A new badge was added."
-msgstr ""
-
msgid "Badges|Add badge"
msgstr ""
@@ -4146,12 +4212,21 @@ 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 ""
@@ -4161,13 +4236,13 @@ msgstr ""
msgid "Badges|Name"
msgstr ""
-msgid "Badges|No badge image"
+msgid "Badges|New badge added."
msgstr ""
-msgid "Badges|No image to preview"
+msgid "Badges|No badge image"
msgstr ""
-msgid "Badges|Please fill in a valid URL"
+msgid "Badges|No image to preview"
msgstr ""
msgid "Badges|Project Badge"
@@ -4182,15 +4257,12 @@ msgstr ""
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
msgstr ""
-msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
msgstr ""
msgid "Badges|The badge was deleted."
msgstr ""
-msgid "Badges|The badge was saved."
-msgstr ""
-
msgid "Badges|This group has no badges"
msgstr ""
@@ -4203,9 +4275,6 @@ msgstr ""
msgid "Badges|Your badges"
msgstr ""
-msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
-
msgid "Balsamiq file could not be loaded."
msgstr ""
@@ -4230,9 +4299,6 @@ msgstr ""
msgid "Based on"
msgstr ""
-msgid "Basic Sample Data template with Issues, Merge Requests and Milestones."
-msgstr ""
-
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -4317,22 +4383,28 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
-msgid "Billing|An email address is only visible for users managed through Group Managed Accounts."
+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|Updated live"
+msgid "Billing|Type to search"
msgstr ""
-msgid "Billing|Users occupying seats in %{namespaceName} Group (%{total})"
+msgid "Billing|Users occupying seats in"
msgstr ""
msgid "Bitbucket Server Import"
@@ -4369,10 +4441,19 @@ msgstr ""
msgid "Blog"
msgstr ""
-msgid "Board scope"
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
msgstr ""
-msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
msgstr ""
msgid "Boards"
@@ -4426,6 +4507,30 @@ 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 ""
@@ -4456,9 +4561,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "Branch prefix"
-msgstr ""
-
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -4627,6 +4729,24 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing groups from %{link}"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+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 ""
@@ -4720,7 +4840,10 @@ msgstr ""
msgid "CI/CD settings"
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."
+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"
@@ -4747,10 +4870,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -4780,9 +4903,6 @@ msgstr ""
msgid "Can be manually deployed to"
msgstr ""
-msgid "Can override approvers and approvals required per merge request"
-msgstr ""
-
msgid "Can't apply as the source branch was deleted."
msgstr ""
@@ -4831,6 +4951,30 @@ 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 ""
@@ -4852,6 +4996,9 @@ msgstr ""
msgid "Cancelling Preview"
msgstr ""
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
msgid "Cannot be merged automatically"
msgstr ""
@@ -4984,15 +5131,33 @@ 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|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 ""
@@ -5014,13 +5179,16 @@ 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 were successfully made."
+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}."
@@ -5032,9 +5200,6 @@ msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
-msgid "Charts"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5302,9 +5467,15 @@ 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 between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
@@ -5563,6 +5734,9 @@ msgstr ""
msgid "Clone repository"
msgstr ""
+msgid "Clone this issue"
+msgstr ""
+
msgid "Clone with %{http_label}"
msgstr ""
@@ -5575,6 +5749,18 @@ 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 ""
@@ -6682,10 +6868,10 @@ msgstr ""
msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
-msgid "Code Owners"
+msgid "Code Owner"
msgstr ""
-msgid "Code Owners to the merge request changes."
+msgid "Code Owners"
msgstr ""
msgid "Code Quality"
@@ -6956,6 +7142,24 @@ 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 "ComplianceFramework|GDPR"
msgstr ""
@@ -7085,6 +7289,9 @@ msgstr ""
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -7171,13 +7378,13 @@ msgstr[0] ""
msgid "ContainerRegistry|%{imageName} tags"
msgstr ""
-msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
msgstr ""
-msgid "ContainerRegistry|%{toggleStatus} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
msgid "ContainerRegistry|Build an image"
@@ -7186,18 +7393,42 @@ 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 policy:"
+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 ""
@@ -7225,9 +7456,6 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
-msgid "ContainerRegistry|Expiration interval:"
-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 ""
@@ -7237,9 +7465,6 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Expiration schedule:"
-msgstr ""
-
msgid "ContainerRegistry|Filter by name"
msgstr ""
@@ -7264,6 +7489,9 @@ msgstr ""
msgid "ContainerRegistry|Keep these tags"
msgstr ""
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
msgid "ContainerRegistry|Login"
msgstr ""
@@ -7282,9 +7510,6 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
-msgid "ContainerRegistry|Number of tags to retain:"
-msgstr ""
-
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@@ -7358,16 +7583,10 @@ 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 matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
-msgstr ""
-
-msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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}"
@@ -7403,12 +7622,6 @@ 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|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
-
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -7565,6 +7778,9 @@ msgstr ""
msgid "Copy branch name"
msgstr ""
+msgid "Copy codes"
+msgstr ""
+
msgid "Copy command"
msgstr ""
@@ -7797,15 +8013,12 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue. Issues are created for each alert triggered."
+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 board"
-msgstr ""
-
msgid "Create branch"
msgstr ""
@@ -7863,9 +8076,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
-msgid "Create new board"
-msgstr ""
-
msgid "Create new branch"
msgstr ""
@@ -7929,6 +8139,84 @@ msgstr ""
msgid "CreateTokenToCloneLink|create a personal access token"
msgstr ""
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+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 a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+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|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 "Created"
msgstr ""
@@ -8022,6 +8310,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Current"
+msgstr ""
+
msgid "Current Branch"
msgstr ""
@@ -8106,45 +8397,18 @@ msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
+msgid "CustomCycleAnalytics|End event label"
msgstr ""
msgid "CustomCycleAnalytics|New stage"
msgstr ""
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Stage name already exists"
msgstr ""
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid stop event"
-msgstr ""
-
msgid "CustomCycleAnalytics|Start event label"
msgstr ""
-msgid "CustomCycleAnalytics|Stop event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stop event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -8389,6 +8653,9 @@ msgstr ""
msgid "DastProfiles|Active"
msgstr ""
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -8455,6 +8722,12 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
msgid "DastProfiles|Hide debug messages"
msgstr ""
@@ -8503,6 +8776,9 @@ 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 ""
@@ -8710,18 +8986,12 @@ msgstr ""
msgid "Default initial branch name"
msgstr ""
-msgid "Default issue template"
-msgstr ""
-
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
msgstr ""
-msgid "Default stages"
-msgstr ""
-
msgid "Default: Map a FogBugz account ID to a full name"
msgstr ""
@@ -8734,6 +9004,9 @@ 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 ""
@@ -8782,9 +9055,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
-msgid "Delete board"
-msgstr ""
-
msgid "Delete comment"
msgstr ""
@@ -9244,9 +9514,6 @@ msgstr ""
msgid "Describe the goal of the changes and what reviewers should be aware of."
msgstr ""
-msgid "Describe the requirement here"
-msgstr ""
-
msgid "Description"
msgstr ""
@@ -9256,6 +9523,9 @@ 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 ""
@@ -9457,22 +9727,61 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgstr ""
+
msgid "DevopsAdoption|An error occured while saving the segment. 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 segment"
+msgstr ""
+
msgid "DevopsAdoption|Create new segment"
msgstr ""
+msgid "DevopsAdoption|Delete segment"
+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 ""
-msgid "DevopsAdoption|Feature adoption is based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Edit segment"
+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|Issues"
@@ -9481,6 +9790,9 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
+msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgstr ""
+
msgid "DevopsAdoption|My segment"
msgstr ""
@@ -9490,18 +9802,33 @@ msgstr ""
msgid "DevopsAdoption|New segment"
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|Segment"
msgstr ""
+msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
@@ -9770,6 +10097,9 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
+msgid "Download %{name} artifact"
+msgstr ""
+
msgid "Download CSV"
msgstr ""
@@ -9854,9 +10184,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states and/or belong to one of the following types:"
-msgstr ""
-
msgid "Each Runner can be in one of the following states:"
msgstr ""
@@ -9911,9 +10238,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
-msgid "Edit board"
-msgstr ""
-
msgid "Edit comment"
msgstr ""
@@ -9953,6 +10277,9 @@ msgstr ""
msgid "Edit public deploy key"
msgstr ""
+msgid "Edit sidebar"
+msgstr ""
+
msgid "Edit stage"
msgstr ""
@@ -9980,12 +10307,18 @@ 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 ""
@@ -10019,6 +10352,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email address to use for Support Desk"
+msgstr ""
+
msgid "Email cannot be blank"
msgstr ""
@@ -10088,10 +10424,10 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk will have this name"
+msgid "Emails sent from Service Desk have this name."
msgstr ""
-msgid "Emails sent to %{email} will still be supported"
+msgid "Emails sent to %{email} are also supported."
msgstr ""
msgid "Emails separated by comma"
@@ -10172,6 +10508,9 @@ 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 ""
@@ -10241,6 +10580,9 @@ msgstr ""
msgid "Enable shared runners for this group"
msgstr ""
+msgid "Enable shared runners for this project"
+msgstr ""
+
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -10256,9 +10598,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
-
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
msgstr ""
@@ -10292,6 +10631,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends at %{endsAt}"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -10328,9 +10670,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
-msgid "Enter board name"
-msgstr ""
-
msgid "Enter domain"
msgstr ""
@@ -10373,6 +10712,9 @@ 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 ""
@@ -10514,6 +10856,9 @@ msgstr ""
msgid "Environments|Deployment"
msgstr ""
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -10631,6 +10976,12 @@ 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 ""
@@ -10691,9 +11042,6 @@ msgstr ""
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
-msgid "Epics|More information"
-msgstr ""
-
msgid "Epics|Remove epic"
msgstr ""
@@ -10799,9 +11147,6 @@ msgstr ""
msgid "Error fetching payload data."
msgstr ""
-msgid "Error fetching projects"
-msgstr ""
-
msgid "Error fetching refs"
msgstr ""
@@ -10937,9 +11282,18 @@ 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 ""
@@ -11054,22 +11408,22 @@ 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."
+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."
+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."
+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."
+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."
+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."
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
msgid "Evidence collection"
@@ -11108,9 +11462,6 @@ msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
-msgid "Existing members and groups"
-msgstr ""
-
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -11150,6 +11501,9 @@ msgstr ""
msgid "Experienced"
msgstr ""
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
msgid "Expiration"
msgstr ""
@@ -11291,6 +11645,9 @@ 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 ""
@@ -11309,6 +11666,12 @@ 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 ""
@@ -11336,9 +11699,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
-msgid "Failed to delete board. Please try again."
-msgstr ""
-
msgid "Failed to deploy to"
msgstr ""
@@ -11489,6 +11849,9 @@ msgstr ""
msgid "Failed to update environment!"
msgstr ""
+msgid "Failed to update framework"
+msgstr ""
+
msgid "Failed to update issue status"
msgstr ""
@@ -11549,9 +11912,6 @@ msgstr ""
msgid "Feature flag was successfully removed."
msgstr ""
-msgid "Feature not available"
-msgstr ""
-
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
msgstr[0] ""
@@ -11643,9 +12003,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
-msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
-msgstr ""
-
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr ""
@@ -11655,16 +12012,13 @@ msgstr ""
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
msgstr ""
-msgid "FeatureFlags|Flag becomes read only soon"
-msgstr ""
-
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
+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."
@@ -11778,6 +12132,9 @@ 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 ""
@@ -11880,6 +12237,9 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by"
+msgstr ""
+
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
@@ -11913,12 +12273,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by requirements that are currently archived."
-msgstr ""
-
-msgid "Filter by requirements that are currently opened."
-msgstr ""
-
msgid "Filter by status"
msgstr ""
@@ -11970,9 +12324,6 @@ msgstr ""
msgid "Find by path"
msgstr ""
-msgid "Find existing members by name"
-msgstr ""
-
msgid "Find file"
msgstr ""
@@ -11991,6 +12342,9 @@ msgstr ""
msgid "Finished"
msgstr ""
+msgid "Finished at"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -12120,9 +12474,6 @@ msgstr ""
msgid "Format: %{dateFormat}"
msgstr ""
-msgid "Forward external support email address to"
-msgstr ""
-
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -12588,6 +12939,12 @@ 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 ""
@@ -12663,9 +13020,6 @@ msgstr ""
msgid "GitLab Pages"
msgstr ""
-msgid "GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email."
-msgstr ""
-
msgid "GitLab Shell"
msgstr ""
@@ -12885,7 +13239,7 @@ msgstr ""
msgid "Go Back"
msgstr ""
-msgid "Go Micro is a framework for micro service development."
+msgid "Go Micro is a framework for micro service development"
msgstr ""
msgid "Go back"
@@ -13113,9 +13467,6 @@ msgstr ""
msgid "Group by"
msgstr ""
-msgid "Group description"
-msgstr ""
-
msgid "Group description (optional)"
msgstr ""
@@ -13449,10 +13800,16 @@ 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 your group badges."
+msgid "GroupSettings|Customize this group's badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
@@ -13476,9 +13833,6 @@ msgstr ""
msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
msgstr ""
-msgid "GroupSettings|Learn more about badges."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -13506,7 +13860,7 @@ msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
msgstr ""
-msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+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}."
@@ -13539,6 +13893,9 @@ 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 ""
@@ -13617,6 +13974,9 @@ 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 ""
@@ -13626,22 +13986,46 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import a GitLab group export file"
+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|To copy a GitLab group between installations, navigate to the group settings page for the original installation, generate an export file, and upload it here."
+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?"
@@ -13859,6 +14243,9 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How does cleanup work?"
+msgstr ""
+
msgid "How it works"
msgstr ""
@@ -14033,6 +14420,9 @@ 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 ""
@@ -14104,6 +14494,12 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
msgid "Import in progress"
msgstr ""
@@ -14152,6 +14548,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import requirements"
+msgstr ""
+
msgid "Import started by: %{importInitiator}"
msgstr ""
@@ -14212,19 +14611,14 @@ msgstr ""
msgid "Imported requirements"
msgstr ""
-msgid "Improve Issue Boards"
-msgstr ""
-
-msgid "Improve Issue boards"
-msgstr ""
-
-msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
msgstr ""
-msgid "Improve customer support with GitLab Service Desk."
+msgid "Improve customer support with Service Desk"
msgstr ""
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
@@ -14248,6 +14642,9 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
+msgid "Incident template (optional)"
+msgstr ""
+
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
msgstr ""
@@ -14404,13 +14801,13 @@ 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."
+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."
+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."
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
msgstr ""
msgid "Incoming email"
@@ -14425,6 +14822,9 @@ msgstr ""
msgid "Incompatible project"
msgstr ""
+msgid "Incomplete"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -14672,6 +15072,12 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
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|Projects using custom settings will not be affected."
msgstr ""
@@ -14756,9 +15162,6 @@ msgstr ""
msgid "Introducing Your DevOps Report"
msgstr ""
-msgid "Invalid Git ref"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -14858,13 +15261,13 @@ msgstr ""
msgid "Invite"
msgstr ""
-msgid "Invite \"%{trimmed}\" by email"
+msgid "Invite \"%{email}\" by email"
msgstr ""
-msgid "Invite Members"
+msgid "Invite \"%{trimmed}\" by email"
msgstr ""
-msgid "Invite another teammate"
+msgid "Invite Members"
msgstr ""
msgid "Invite group"
@@ -14876,9 +15279,6 @@ msgstr ""
msgid "Invite team members"
msgstr ""
-msgid "Invite teammates (optional)"
-msgstr ""
-
msgid "Invite your team"
msgstr ""
@@ -14948,6 +15348,24 @@ 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 ""
@@ -15005,9 +15423,6 @@ msgstr ""
msgid "Invited"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
-msgstr ""
-
msgid "Invocations"
msgstr ""
@@ -15059,6 +15474,9 @@ msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
msgstr ""
+msgid "Issue details"
+msgstr ""
+
msgid "Issue events"
msgstr ""
@@ -15074,7 +15492,7 @@ msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue template (optional)"
+msgid "Issue title"
msgstr ""
msgid "Issue update failed"
@@ -15113,7 +15531,7 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status."
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
msgid "IssueBoards|Board"
@@ -15233,6 +15651,9 @@ msgstr ""
msgid "Iteration changed to"
msgstr ""
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
msgid "Iteration removed"
msgstr ""
@@ -15317,6 +15738,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
@@ -15341,19 +15765,19 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Open Jira"
+msgid "JiraService|Jira workflow transition IDs"
msgstr ""
-msgid "JiraService|Password or API token"
+msgid "JiraService|Open Jira"
msgstr ""
-msgid "JiraService|This feature requires a Premium plan."
+msgid "JiraService|Password or API token"
msgstr ""
-msgid "JiraService|Transition ID(s)"
+msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
-msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgid "JiraService|This feature requires a Premium plan."
msgstr ""
msgid "JiraService|Use a password for server version and an API token for cloud version"
@@ -15777,6 +16201,9 @@ msgstr ""
msgid "Last seen"
msgstr ""
+msgid "Last sign-in"
+msgstr ""
+
msgid "Last successful sync"
msgstr ""
@@ -15831,9 +16258,15 @@ msgstr ""
msgid "Lead Time"
msgstr ""
+msgid "Learn CI/CD syntax"
+msgstr ""
+
msgid "Learn GitLab"
msgstr ""
+msgid "Learn GitLab - Gold trial"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -15873,9 +16306,6 @@ 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 approvals."
-msgstr ""
-
msgid "Learn more about custom project templates"
msgstr ""
@@ -15900,6 +16330,9 @@ msgstr ""
msgid "Learn more in the|pipeline schedules documentation"
msgstr ""
+msgid "Learn more."
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16231,6 +16664,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -16318,6 +16754,9 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
+msgid "MERGED (REVERTED)"
+msgstr ""
+
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16555,6 +16994,9 @@ msgstr ""
msgid "Max 100,000 events"
msgstr ""
+msgid "Max 20 characters"
+msgstr ""
+
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -16576,6 +17018,9 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max file size is 200 KB."
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -16717,6 +17162,12 @@ msgstr ""
msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
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 ""
@@ -16849,9 +17300,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -16912,6 +17360,9 @@ msgstr ""
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
+msgid "Merge request (MR) approvals"
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -16927,9 +17378,6 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests approvals"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -17074,9 +17522,15 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
+msgid "MergeRequest|reverted"
+msgstr ""
+
msgid "Merged"
msgstr ""
+msgid "Merged (%{reverted})"
+msgstr ""
+
msgid "Merged MRs"
msgstr ""
@@ -17092,9 +17546,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-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 ""
@@ -17655,9 +18106,6 @@ msgstr ""
msgid "Mirror user"
msgstr ""
-msgid "Mirrored branches will have this prefix. If you enabled 'Only mirror protected branches' you need to include this prefix on protected branches in this project or nothing will be mirrored."
-msgstr ""
-
msgid "Mirrored repositories"
msgstr ""
@@ -17841,9 +18289,6 @@ msgstr ""
msgid "Multiple domains are supported."
msgstr ""
-msgid "Multiple issue boards"
-msgstr ""
-
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -17972,6 +18417,9 @@ 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 ""
@@ -17984,6 +18432,9 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
msgid "NetworkPolicies|.yaml"
msgstr ""
@@ -17993,6 +18444,9 @@ 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 ""
@@ -18288,6 +18742,12 @@ 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 ""
@@ -18426,7 +18886,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{sourceBranch} and %{targetBranch}"
+msgid "No changes between %{source} and %{target}"
msgstr ""
msgid "No child epics match applied filters"
@@ -18672,6 +19132,9 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
+msgid "Not available to run jobs."
+msgstr ""
+
msgid "Not confidential"
msgstr ""
@@ -18690,6 +19153,9 @@ msgstr ""
msgid "Not started"
msgstr ""
+msgid "Not supported"
+msgstr ""
+
msgid "Note"
msgstr ""
@@ -18927,6 +19393,9 @@ msgstr ""
msgid "Oh no!"
msgstr ""
+msgid "Ok, let's go"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -18948,27 +19417,105 @@ 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|Failed to add rotation"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add schedule"
msgstr ""
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+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 ""
@@ -18984,9 +19531,21 @@ msgstr ""
msgid "OnDemandScans|Create a 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 profiles"
msgstr ""
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -19005,6 +19564,15 @@ 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 ""
@@ -19297,6 +19865,9 @@ msgstr ""
msgid "Package type must be Conan"
msgstr ""
+msgid "Package type must be Debian"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -19306,10 +19877,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
-msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
@@ -19327,7 +19895,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
-msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
@@ -19387,6 +19955,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -19453,10 +20024,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Pip Command"
+msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
-msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+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}"
@@ -19558,7 +20135,7 @@ msgstr ""
msgid "PagerDutySettings|Active"
msgstr ""
-msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+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"
@@ -19570,18 +20147,12 @@ msgstr ""
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
msgstr ""
-msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
-
msgid "PagerDutySettings|Webhook URL"
msgstr ""
msgid "PagerDutySettings|Webhook URL update was successful"
msgstr ""
-msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
-
msgid "Pages"
msgstr ""
@@ -19711,10 +20282,13 @@ msgstr ""
msgid "Pause"
msgstr ""
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
msgid "Pause replication"
msgstr ""
-msgid "Paused Runners don't accept new jobs"
+msgid "Paused runners don't accept new jobs"
msgstr ""
msgid "Pending"
@@ -19783,6 +20357,9 @@ 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 ""
@@ -19819,6 +20396,9 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
+msgid "Pipeline minutes quota:"
+msgstr ""
+
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -19831,6 +20411,15 @@ 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 ""
@@ -19846,7 +20435,7 @@ msgstr ""
msgid "PipelineCharts|Successful:"
msgstr ""
-msgid "PipelineCharts|Total duration:"
+msgid "PipelineCharts|There was an error parsing the data for the charts."
msgstr ""
msgid "PipelineCharts|Total:"
@@ -19951,9 +20540,15 @@ 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 ""
@@ -19969,6 +20564,9 @@ msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Lint"
+msgstr ""
+
msgid "Pipelines|Loading Pipelines"
msgstr ""
@@ -20017,6 +20615,18 @@ 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 ""
@@ -20032,6 +20642,9 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -20245,6 +20858,9 @@ 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 ""
@@ -20269,6 +20885,9 @@ 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 ""
@@ -20479,13 +21098,16 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent MR approvals by author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request author"
+msgid "Prevent MR approvals by the author."
msgstr ""
-msgid "Prevent approval of merge requests by merge request committers"
+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"
@@ -20497,7 +21119,7 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
-msgid "Prevent users from modifying merge request approvers list"
+msgid "Prevent users from modifying MR approval rules."
msgstr ""
msgid "Prevent users from performing write operations on GitLab while performing maintenance."
@@ -20530,6 +21152,9 @@ msgstr ""
msgid "Primary"
msgstr ""
+msgid "Print codes"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -20665,6 +21290,9 @@ 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 ""
@@ -20767,6 +21395,9 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|GitLab is unable to verify your identity automatically."
+msgstr ""
+
msgid "Profiles|Give your individual key a title."
msgstr ""
@@ -20815,6 +21446,9 @@ 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 ""
@@ -21097,9 +21731,6 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
-msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
-msgstr ""
-
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -21256,12 +21887,18 @@ 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 ""
@@ -21289,7 +21926,7 @@ msgstr ""
msgid "ProjectSettings|Container registry"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Disable email notifications"
@@ -21310,6 +21947,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
@@ -21358,9 +21998,6 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Learn more about badges."
-msgstr ""
-
msgid "ProjectSettings|Lightweight issue tracking system for this project"
msgstr ""
@@ -21397,6 +22034,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Operations"
+msgstr ""
+
msgid "ProjectSettings|Packages"
msgstr ""
@@ -21505,12 +22145,21 @@ 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|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 ""
@@ -21529,9 +22178,6 @@ msgstr ""
msgid "ProjectTemplates|Android"
msgstr ""
-msgid "ProjectTemplates|Basic"
-msgstr ""
-
msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
@@ -21544,6 +22190,9 @@ msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
msgstr ""
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
msgid "ProjectTemplates|Netlify/GitBook"
msgstr ""
@@ -21586,7 +22235,7 @@ msgstr ""
msgid "ProjectTemplates|SalesforceDX"
msgstr ""
-msgid "ProjectTemplates|Serenity Valley"
+msgid "ProjectTemplates|Sample GitLab Project"
msgstr ""
msgid "ProjectTemplates|Serverless Framework/JS"
@@ -22027,7 +22676,7 @@ 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"
+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"
@@ -22060,7 +22709,7 @@ msgstr ""
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
msgstr ""
-msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "ProtectedBranch|Require approval from code owners:"
@@ -22327,6 +22976,12 @@ 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 ""
@@ -22345,6 +23000,9 @@ msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent jobs served by this runner"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
@@ -22448,7 +23106,10 @@ msgstr ""
msgid "Registry setup"
msgstr ""
-msgid "Reindexing status"
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
msgstr ""
msgid "Rejected (closed)"
@@ -22569,15 +23230,15 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
-msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-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 ""
@@ -22656,6 +23317,9 @@ msgstr ""
msgid "Remove report"
msgstr ""
+msgid "Remove reviewer"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -22692,6 +23356,9 @@ msgstr ""
msgid "Removed %{milestone_reference} milestone."
msgstr ""
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -22737,6 +23404,9 @@ msgstr ""
msgid "Removes %{milestone_reference} milestone."
msgstr ""
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
msgid "Removes all labels."
msgstr ""
@@ -22767,6 +23437,9 @@ msgstr ""
msgid "Rename/Move"
msgstr ""
+msgid "Renew subscription"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -22968,6 +23641,9 @@ 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 ""
@@ -22980,7 +23656,7 @@ msgstr ""
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
-msgid "RepositoriesAnalytics|Projects with Tests"
+msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
@@ -22989,9 +23665,6 @@ msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
-msgid "RepositoriesAnalytics|Total Number of Coverages"
-msgstr ""
-
msgid "Repository"
msgstr ""
@@ -23067,9 +23740,6 @@ msgstr ""
msgid "Request Access"
msgstr ""
-msgid "Request Headers"
-msgstr ""
-
msgid "Request details"
msgstr ""
@@ -23112,7 +23782,10 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Require user password to approve"
+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"
@@ -23139,9 +23812,6 @@ msgstr ""
msgid "Requirement %{reference} has been updated"
msgstr ""
-msgid "Requirement title"
-msgstr ""
-
msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
@@ -23246,12 +23916,6 @@ msgstr ""
msgid "Response"
msgstr ""
-msgid "Response Headers"
-msgstr ""
-
-msgid "Response Status"
-msgstr ""
-
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -23273,6 +23937,9 @@ msgstr ""
msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Response text"
+msgstr ""
+
msgid "Restart Terminal"
msgstr ""
@@ -23294,6 +23961,9 @@ 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 ""
@@ -23352,6 +24022,9 @@ msgstr ""
msgid "Review requested from %{name}"
msgstr ""
+msgid "Review requests for you"
+msgstr ""
+
msgid "Review the changes locally"
msgstr ""
@@ -23443,21 +24116,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
-msgid "Runner cannot be assigned to other projects"
-msgstr ""
-
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
-
-msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
-
-msgid "Runner runs jobs from assigned projects"
-msgstr ""
-
msgid "Runner token"
msgstr ""
@@ -23473,9 +24134,6 @@ msgstr ""
msgid "Runner was successfully updated."
msgstr ""
-msgid "Runner will not receive any new jobs"
-msgstr ""
-
msgid "Runners"
msgstr ""
@@ -23485,13 +24143,16 @@ 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 placed on separate users, servers, even on your local machine."
+msgid "Runners can be:"
msgstr ""
msgid "Runners currently online: %{active_runners_count}"
@@ -23569,6 +24230,15 @@ 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 ""
@@ -23620,9 +24290,6 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
-msgid "Sample Data"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -23683,10 +24350,10 @@ msgstr ""
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
-msgid "Scheduled to merge this merge request (%{strategy})."
+msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
msgid "Schedules"
@@ -23704,7 +24371,7 @@ msgstr ""
msgid "Scope"
msgstr ""
-msgid "Scoped issue boards"
+msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
@@ -23827,6 +24494,9 @@ msgstr ""
msgid "Search requirements"
msgstr ""
+msgid "Search settings"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -23854,6 +24524,9 @@ 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 ""
@@ -23973,16 +24646,16 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
-msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+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}More information%{linkEnd}"
+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."
@@ -24096,9 +24769,15 @@ 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 ""
@@ -24183,6 +24862,9 @@ msgstr ""
msgid "SecurityReports|Security reports help page link"
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 ""
@@ -24256,6 +24938,12 @@ 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 ""
@@ -24538,9 +25226,6 @@ msgstr ""
msgid "September"
msgstr ""
-msgid "Serenity Valley Sample Data template."
-msgstr ""
-
msgid "SeriesFinalConjunction|and"
msgstr ""
@@ -24640,6 +25325,9 @@ 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 ""
@@ -24670,10 +25358,7 @@ 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 template for issue descriptions."
-msgstr ""
-
-msgid "Set a number of approvals required, the approvers and other approval settings."
+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}."
@@ -24871,9 +25556,6 @@ msgstr ""
msgid "Settings related to the use and experience of using GitLab's Package Registry."
msgstr ""
-msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
-msgstr ""
-
msgid "Setup"
msgstr ""
@@ -24913,6 +25595,9 @@ 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 ""
@@ -24934,6 +25619,9 @@ 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 ""
+
msgid "Show all activity"
msgstr ""
@@ -24943,9 +25631,6 @@ msgstr ""
msgid "Show all members"
msgstr ""
-msgid "Show all requirements."
-msgstr ""
-
msgid "Show all test cases."
msgstr ""
@@ -24982,6 +25667,9 @@ msgstr ""
msgid "Show file contents"
msgstr ""
+msgid "Show labels"
+msgstr ""
+
msgid "Show latest version"
msgstr ""
@@ -25302,6 +25990,9 @@ 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 ""
@@ -25338,7 +26029,10 @@ msgstr ""
msgid "Something went wrong while archiving a requirement."
msgstr ""
-msgid "Something went wrong while closing the merge request. Please try again later"
+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."
@@ -25365,6 +26059,9 @@ 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 ""
@@ -25425,7 +26122,10 @@ msgstr ""
msgid "Something went wrong while reopening a requirement."
msgstr ""
-msgid "Something went wrong while reopening the merge request. Please try again later"
+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."
@@ -25464,7 +26164,7 @@ msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
-msgid "Something went wrong."
+msgid "Something went wrong. Please try again later"
msgstr ""
msgid "Something went wrong. Please try again."
@@ -25881,13 +26581,16 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
+msgid "Starts at %{startsAt}"
+msgstr ""
+
msgid "Starts at (UTC)"
msgstr ""
-msgid "State your message to activate"
+msgid "Starts on"
msgstr ""
-msgid "State: %{last_reindexing_task_state}"
+msgid "State your message to activate"
msgstr ""
msgid "Static Application Security Testing (SAST)"
@@ -25908,6 +26611,9 @@ 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 ""
@@ -25926,6 +26632,9 @@ 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 ""
@@ -26163,6 +26872,9 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
@@ -26439,6 +27151,12 @@ msgstr ""
msgid "Syncing…"
msgstr ""
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -26663,9 +27381,24 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+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 ""
@@ -26675,12 +27408,30 @@ 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 ""
@@ -26693,9 +27444,21 @@ msgstr ""
msgid "Terraform|The Terraform 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 ""
@@ -26841,7 +27604,7 @@ msgstr ""
msgid "Thanks for your purchase!"
msgstr ""
-msgid "Thanks! Don't show me this again"
+msgid "That is ok, I do not want to renew"
msgstr ""
msgid "That's it, well done!"
@@ -26856,6 +27619,9 @@ 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] ""
@@ -26866,6 +27632,9 @@ 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 ""
@@ -26932,6 +27701,9 @@ 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 ""
@@ -27053,9 +27825,6 @@ msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
-msgid "The license for Deploy Board is required to use this feature."
-msgstr ""
-
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27074,9 +27843,6 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr ""
-msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -27344,6 +28110,9 @@ 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 ""
@@ -27440,6 +28209,9 @@ 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 ""
@@ -27518,6 +28290,9 @@ 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 ""
@@ -27599,6 +28374,9 @@ 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 ""
@@ -27896,6 +28674,9 @@ 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 ""
@@ -27980,6 +28761,15 @@ 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 ""
@@ -27995,9 +28785,6 @@ msgstr ""
msgid "This suggestion already matches its content."
msgstr ""
-msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
-
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
@@ -28070,12 +28857,33 @@ 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 ""
@@ -28091,6 +28899,9 @@ msgstr ""
msgid "ThreatMonitoring|Requests"
msgstr ""
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
msgid "ThreatMonitoring|Show last"
msgstr ""
@@ -28103,12 +28914,21 @@ 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 ""
@@ -28118,7 +28938,7 @@ 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."
+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"
@@ -28127,6 +28947,9 @@ msgstr ""
msgid "ThreatMonitoring|Total Requests"
msgstr ""
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
msgid "ThreatMonitoring|View documentation"
msgstr ""
@@ -28732,12 +29555,19 @@ 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] ""
+
msgid "Trials|Create a new group to start your GitLab Gold trial."
msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
+msgid "Trials|Skip Trial"
+msgstr ""
+
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
@@ -28756,6 +29586,39 @@ 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 Gold 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 Gold 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 ""
@@ -29146,6 +30009,9 @@ msgstr ""
msgid "Unstar"
msgstr ""
+msgid "Unstarted"
+msgstr ""
+
msgid "Unsubscribe"
msgstr ""
@@ -29170,7 +30036,7 @@ msgstr ""
msgid "Until"
msgstr ""
-msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
msgid "Unverified"
@@ -29227,7 +30093,7 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
-msgid "Update your project name, topics, description and avatar."
+msgid "Update your project name, topics, description, and avatar."
msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
@@ -29242,7 +30108,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
@@ -29284,9 +30150,6 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
-
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -29797,6 +30660,9 @@ 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 ""
+
msgid "Users were successfully added."
msgstr ""
@@ -30234,6 +31100,9 @@ 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 ""
@@ -30261,6 +31130,9 @@ msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Download"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -30288,6 +31160,12 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
msgid "Vulnerability|Request/Response"
msgstr ""
@@ -30306,6 +31184,9 @@ 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 ""
@@ -30318,6 +31199,9 @@ msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
+msgid "Warning"
+msgstr ""
+
msgid "Warning:"
msgstr ""
@@ -30351,6 +31235,9 @@ 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 ""
@@ -30453,6 +31340,9 @@ msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Member events"
+msgstr ""
+
msgid "Webhooks|Merge request events"
msgstr ""
@@ -30489,6 +31379,9 @@ 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 ""
@@ -30610,7 +31503,7 @@ 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 be an approver?"
+msgid "Who can approve?"
msgstr ""
msgid "Who can see this group?"
@@ -30988,6 +31881,9 @@ 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 ""
@@ -31078,6 +31974,9 @@ 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 ""
@@ -31087,9 +31986,6 @@ msgstr ""
msgid "You can set up as many Runners as you need to run your jobs."
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 ""
@@ -31111,6 +32007,9 @@ 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 ""
@@ -31147,9 +32046,6 @@ msgstr ""
msgid "You do not have permissions to run the import."
msgstr ""
-msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
-
msgid "You don't have any U2F devices registered yet."
msgstr ""
@@ -31222,6 +32118,9 @@ 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 ""
@@ -31231,6 +32130,9 @@ 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 ""
@@ -31264,6 +32166,9 @@ 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 ""
@@ -31423,6 +32328,9 @@ 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 ""
@@ -31495,6 +32403,9 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
+msgid "Your Version"
+msgstr ""
+
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -31570,6 +32481,9 @@ 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 ""
@@ -31591,6 +32505,9 @@ 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 ""
@@ -31648,6 +32565,9 @@ 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 ""
@@ -31745,6 +32665,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "at"
+msgstr ""
+
msgid "at risk"
msgstr ""
@@ -31763,9 +32686,15 @@ msgstr ""
msgid "by"
msgstr "來自"
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+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 ""
@@ -31808,6 +32737,9 @@ 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 ""
@@ -31847,6 +32779,9 @@ msgstr ""
msgid "ciReport|API Fuzzing"
msgstr ""
+msgid "ciReport|API fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -32003,6 +32938,9 @@ 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] ""
@@ -32200,6 +33138,12 @@ 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 ""
@@ -32381,6 +33325,9 @@ 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] ""
@@ -33029,18 +33976,9 @@ 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 "syntax is correct."
-msgstr ""
-
-msgid "syntax is incorrect."
-msgstr ""
-
msgid "tag name"
msgstr ""
-msgid "teammate%{number}@company.com"
-msgstr ""
-
msgid "the correct format."
msgstr ""
diff --git a/package.json b/package.json
index 14c3fd8533e..a5ca4851efa 100644
--- a/package.json
+++ b/package.json
@@ -42,12 +42,13 @@
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
- "@gitlab/svgs": "1.177.0",
+ "@gitlab/favicon-overlay": "2.0.0",
+ "@gitlab/svgs": "1.178.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "24.8.1",
+ "@gitlab/ui": "25.11.3",
"@gitlab/visual-review-tools": "1.6.1",
- "@rails/actioncable": "^6.0.3-3",
- "@rails/ujs": "^6.0.3-2",
+ "@rails/actioncable": "^6.0.3-4",
+ "@rails/ujs": "^6.0.3-4",
"@sourcegraph/code-host-integration": "0.0.52",
"@toast-ui/editor": "^2.5.1",
"@toast-ui/vue-editor": "^2.5.1",
@@ -81,12 +82,13 @@
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
"document-register-element": "1.14.3",
- "dompurify": "^2.2.4",
+ "dompurify": "^2.2.6",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^7.0.3",
"emoji-unicode-version": "^0.2.1",
"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",
@@ -108,8 +110,8 @@
"katex": "^0.10.0",
"lodash": "^4.17.20",
"marked": "^0.3.12",
+ "mathjax": "3",
"mermaid": "^8.5.2",
- "mersenne-twister": "1.1.0",
"minimatch": "^3.0.4",
"miragejs": "^0.1.40",
"mock-apollo-client": "^0.5.0",
@@ -131,7 +133,7 @@
"sql.js": "^0.4.0",
"stickyfilljs": "^2.1.0",
"string-hash": "1.1.3",
- "style-loader": "^1.1.3",
+ "style-loader": "^1.3.0",
"swagger-ui-dist": "^3.32.4",
"three": "^0.84.0",
"three-orbit-controls": "^82.1.0",
@@ -145,7 +147,7 @@
"visibilityjs": "^1.2.4",
"vue": "^2.6.12",
"vue-apollo": "^3.0.3",
- "vue-loader": "^15.9.5",
+ "vue-loader": "^15.9.6",
"vue-router": "3.4.9",
"vue-template-compiler": "^2.6.12",
"vue-virtual-scroll-list": "^1.4.4",
@@ -161,9 +163,9 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "5.0.0",
+ "@gitlab/eslint-plugin": "6.0.0",
"@testing-library/dom": "^7.16.2",
- "@vue/test-utils": "1.0.0-beta.30",
+ "@vue/test-utils": "1.1.2",
"acorn": "^6.3.0",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^26.5.2",
@@ -208,7 +210,7 @@
"nodemon": "^2.0.4",
"pixelmatch": "^4.0.2",
"postcss": "^7.0.14",
- "prettier": "1.18.2",
+ "prettier": "2.2.1",
"readdir-enhanced": "^2.2.4",
"stylelint": "^10.1.0",
"stylelint-config-recommended": "^2.2.0",
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 925c9758450..d040bddfc7f 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -9,20 +9,10 @@ ENV CHROME_DEB="google-chrome-stable_${CHROME_VERSION}_amd64.deb"
ENV CHROME_URL="https://s3.amazonaws.com/gitlab-google-chrome-stable/${CHROME_DEB}"
##
-# Add support for stretch-backports
-#
-RUN echo "deb http://ftp.debian.org/debian stretch-backports main" >> /etc/apt/sources.list
-
-##
-# Update APT sources and install some dependencies
+# Update APT sources and install dependencies
#
RUN sed -i "s/httpredir.debian.org/ftp.us.debian.org/" /etc/apt/sources.list
-RUN apt-get update && apt-get install -y wget unzip xvfb lsb-release
-
-##
-# Install some packages from backports
-#
-RUN apt-get -y -t stretch-backports install git git-lfs
+RUN apt-get update && apt-get install -y wget unzip xvfb lsb-release git git-lfs
##
# Install Docker
diff --git a/qa/Gemfile b/qa/Gemfile
index fa8fd40d5bb..da45ba3b955 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -9,7 +9,7 @@ gem 'rspec', '~> 3.7'
gem 'selenium-webdriver', '~> 3.12'
gem 'airborne', '~> 0.3.4'
gem 'rest-client', '~> 2.1.0'
-gem 'nokogiri', '~> 1.10.9'
+gem 'nokogiri', '~> 1.11.1'
gem 'rspec-retry', '~> 0.6.1'
gem 'rspec_junit_formatter', '~> 0.4.1'
gem 'faker', '~> 1.6', '>= 1.6.6'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 3ad9b4fed9e..3b532d90526 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
abstract_type (0.0.7)
- activesupport (6.0.3.3)
+ activesupport (6.0.3.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -63,11 +63,12 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2020.0425)
mini_mime (1.0.2)
- mini_portile2 (2.4.0)
+ mini_portile2 (2.5.0)
minitest (5.14.2)
netrc (0.11.0)
- nokogiri (1.10.9)
- mini_portile2 (~> 2.4.0)
+ nokogiri (1.11.1)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
parallel (1.19.2)
parallel_tests (2.29.0)
parallel
@@ -85,6 +86,7 @@ GEM
byebug (~> 9.1)
pry (~> 0.10)
public_suffix (4.0.1)
+ racc (1.5.2)
rack (2.2.3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
@@ -127,7 +129,7 @@ GEM
rubyzip (>= 1.2.2)
thread_safe (0.3.6)
timecop (0.9.1)
- tzinfo (1.2.7)
+ tzinfo (1.2.9)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
@@ -142,7 +144,7 @@ GEM
procto (~> 0.0.2)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.4.0)
+ zeitwerk (2.4.2)
PLATFORMS
ruby
@@ -155,7 +157,7 @@ DEPENDENCIES
faker (~> 1.6, >= 1.6.6)
gitlab-qa
knapsack (~> 1.17)
- nokogiri (~> 1.10.9)
+ nokogiri (~> 1.11.1)
parallel (~> 1.19)
parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1)
diff --git a/qa/qa.rb b/qa/qa.rb
index b30497d88e1..1d1ac2e2749 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -101,6 +101,11 @@ module QA
autoload :ProjectCluster, 'qa/resource/kubernetes_cluster/project_cluster'
end
+ module Clusters
+ autoload :Agent, 'qa/resource/clusters/agent.rb'
+ autoload :AgentToken, 'qa/resource/clusters/agent_token.rb'
+ end
+
module Events
autoload :Base, 'qa/resource/events/base'
autoload :Project, 'qa/resource/events/project'
diff --git a/qa/qa/fixtures/kubernetes_agent/agentk-config.yaml.erb b/qa/qa/fixtures/kubernetes_agent/agentk-config.yaml.erb
new file mode 100644
index 00000000000..2d29cdecbcc
--- /dev/null
+++ b/qa/qa/fixtures/kubernetes_agent/agentk-config.yaml.erb
@@ -0,0 +1,3 @@
+gitops:
+ manifest_projects:
+ - id: <%= project.full_path %> \ No newline at end of file
diff --git a/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb b/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
new file mode 100644
index 00000000000..a13c92d5c6d
--- /dev/null
+++ b/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
@@ -0,0 +1,95 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: gitlab-agent
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: gitlab-agent
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: gitlab-agent
+ template:
+ metadata:
+ labels:
+ app: gitlab-agent
+ spec:
+ serviceAccountName: gitlab-agent
+ containers:
+ - name: agent
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<%= Runtime::Env.gitlab_agentk_version %>"
+ args:
+ - --token-file=/config/token
+ - --kas-address
+ - "<%= kas_wss_address %>" # Use this for GitLab chart deployments
+ # - "<%= kas_grpc_address %>" # Use this for GDK
+ volumeMounts:
+ - name: token-volume
+ mountPath: /config
+ volumes:
+ - name: token-volume
+ secret:
+ secretName: gitlab-agent-token
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 0
+ maxUnavailable: 1
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: gitlab-agent-write
+rules:
+ - resources:
+ - "*"
+ apiGroups:
+ - "*"
+ verbs:
+ - create
+ - update
+ - delete
+ - patch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: gitlab-agent-write-binding
+roleRef:
+ name: gitlab-agent-write
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+subjects:
+ - name: gitlab-agent
+ kind: ServiceAccount
+ namespace: default
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: gitlab-agent-read
+rules:
+ - resources:
+ - "*"
+ apiGroups:
+ - "*"
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: gitlab-agent-read-binding
+roleRef:
+ name: gitlab-agent-read
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+subjects:
+ - name: gitlab-agent
+ kind: ServiceAccount
+ namespace: default
diff --git a/qa/qa/fixtures/kubernetes_agent/galatic-empire-manifest.yaml b/qa/qa/fixtures/kubernetes_agent/galatic-empire-manifest.yaml
new file mode 100644
index 00000000000..78c42f2b94d
--- /dev/null
+++ b/qa/qa/fixtures/kubernetes_agent/galatic-empire-manifest.yaml
@@ -0,0 +1,15 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: "galatic-empire"
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: "imperial-starfleet"
+ namespace: "galatic-empire"
+data:
+ deathStars: "1"
+ starDestroyers: "5"
+ tieFighters: "25"
diff --git a/qa/qa/fixtures/web_ide/README.md b/qa/qa/fixtures/web_ide/README.md
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/qa/qa/fixtures/web_ide/README.md
diff --git a/qa/qa/fixtures/web_ide/dk.png b/qa/qa/fixtures/web_ide/dk.png
new file mode 100644
index 00000000000..1247f2fecd7
--- /dev/null
+++ b/qa/qa/fixtures/web_ide/dk.png
Binary files differ
diff --git a/qa/qa/fixtures/web_ide/logo_sample.svg b/qa/qa/fixtures/web_ide/logo_sample.svg
new file mode 100644
index 00000000000..883e7e6cf92
--- /dev/null
+++ b/qa/qa/fixtures/web_ide/logo_sample.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="210px" height="210px" viewBox="0 0 210 210" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
+ <!-- Generator: Sketch 3.3.2 (12043) - http://www.bohemiancoding.com/sketch -->
+ <title>Slice 1</title>
+ <desc>Created with Sketch.</desc>
+ <script>alert('FAIL')</script>
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
+ <g id="logo" sketch:type="MSLayerGroup" transform="translate(0.000000, 10.000000)">
+ <g id="Page-1" sketch:type="MSShapeGroup">
+ <g id="Fill-1-+-Group-24">
+ <g id="Group-24">
+ <g id="Group">
+ <path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329" class="tanuki-shape"></path>
+ <path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26" class="tanuki-shape"></path>
+ <path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326" class="tanuki-shape"></path>
+ <path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329" class="tanuki-shape"></path>
+ <path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26" class="tanuki-shape"></path>
+ <path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326" class="tanuki-shape"></path>
+ <path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329" class="tanuki-shape"></path>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/qa/qa/fixtures/web_ide/text_file.txt b/qa/qa/fixtures/web_ide/text_file.txt
new file mode 100644
index 00000000000..4c605535558
--- /dev/null
+++ b/qa/qa/fixtures/web_ide/text_file.txt
@@ -0,0 +1 @@
+Simple text
diff --git a/qa/qa/flow/sign_up.rb b/qa/qa/flow/sign_up.rb
index c790a82d904..b367b7976e8 100644
--- a/qa/qa/flow/sign_up.rb
+++ b/qa/qa/flow/sign_up.rb
@@ -6,36 +6,39 @@ module QA
module_function
def sign_up!(user)
+ Page::Main::Menu.perform(&:sign_out_if_signed_in)
Page::Main::Login.perform(&:switch_to_register_page)
+ Page::Registration::SignUp.perform do |sign_up|
+ sign_up.fill_new_user_first_name_field(user.first_name)
+ sign_up.fill_new_user_last_name_field(user.last_name)
+ 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)
+ sign_up.click_new_user_register_button
+ end
- success = Support::Retrier.retry_until(raise_on_failure: false) do
- Page::Registration::SignUp.perform do |sign_up|
- sign_up.fill_new_user_first_name_field(user.first_name)
- sign_up.fill_new_user_last_name_field(user.last_name)
- 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)
+ Page::Registration::Welcome.perform(&:click_get_started_button_if_available)
- # Because invisible_captcha would prevent submitting this form
- # within 4 seconds, sleep here. This can be removed once we
- # implement invisible_captcha as an application setting instead
- # of a feature flag, so we can turn it off while testing.
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/284113
- sleep 5
+ success = if user.expect_fabrication_success
+ Page::Main::Menu.perform(&:has_personal_area?)
+ else
+ Page::Main::Menu.perform(&:not_signed_in?)
+ end
- sign_up.click_new_user_register_button
- end
+ raise "Failed user registration attempt. Registration was expected to #{user.expect_fabrication_success ? 'succeed' : 'fail'} but #{success ? 'succeeded' : 'failed'}." unless success
+ end
- Page::Registration::Welcome.perform(&:click_get_started_button_if_available)
+ def disable_sign_ups
+ Flow::Login.sign_in_as_admin
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_general_settings)
- if user.expect_fabrication_success
- Page::Main::Menu.perform(&:has_personal_area?)
- else
- Page::Main::Menu.perform(&:not_signed_in?)
+ Page::Admin::Settings::General.perform do |general_settings|
+ general_settings.expand_sign_up_restrictions do |signup_settings|
+ signup_settings.disable_signups
+ signup_settings.save_changes
end
end
-
- raise "Failed to register the user" unless success
end
end
end
diff --git a/qa/qa/page/admin/settings/component/sign_up_restrictions.rb b/qa/qa/page/admin/settings/component/sign_up_restrictions.rb
index 8c5b4bf506b..9526faf4126 100644
--- a/qa/qa/page/admin/settings/component/sign_up_restrictions.rb
+++ b/qa/qa/page/admin/settings/component/sign_up_restrictions.rb
@@ -8,6 +8,7 @@ module QA
class SignUpRestrictions < Page::Base
view 'app/views/admin/application_settings/_signup.html.haml' do
element :require_admin_approval_after_user_signup_checkbox
+ element :signup_enabled_checkbox
element :save_changes_button
end
@@ -15,6 +16,11 @@ module QA
check_element :require_admin_approval_after_user_signup_checkbox
click_element :save_changes_button
end
+
+ def disable_signups
+ uncheck_element :signup_enabled_checkbox
+ click_element :save_changes_button
+ end
end
end
end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 00b48dc7fe9..99f73bbba48 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -135,8 +135,11 @@ module QA
def check_element(name)
retry_until(sleep_interval: 1) do
find_element(name).set(true)
+ checked = find_element(name).checked?
- find_element(name).checked?
+ QA::Runtime::Logger.debug(checked ? "#{name} was checked" : "#{name} was not checked")
+
+ checked
end
end
@@ -185,19 +188,31 @@ module QA
end
def has_element?(name, **kwargs)
- wait_for_requests(skip_finished_loading_check: !!kwargs.delete(:skip_finished_loading_check))
-
disabled = kwargs.delete(:disabled)
+ original_kwargs = kwargs.dup
+ wait = kwargs.delete(:wait) || Capybara.default_max_wait_time
+ text = kwargs.delete(:text)
+ klass = kwargs.delete(:class)
- if disabled.nil?
- wait = kwargs.delete(:wait) || Capybara.default_max_wait_time
- text = kwargs.delete(:text)
- klass = kwargs.delete(:class)
-
- has_css?(element_selector_css(name, kwargs), text: text, wait: wait, class: klass)
- else
- find_element(name, kwargs).disabled? == disabled
+ try_find_element = ->(wait) do
+ if disabled.nil?
+ has_css?(element_selector_css(name, kwargs), text: text, wait: wait, class: klass)
+ else
+ find_element(name, original_kwargs).disabled? == disabled
+ end
end
+
+ # Check for the element before waiting for requests, just in case unrelated requests are in progress.
+ # This is to avoid waiting unnecessarily after the element we're interested in has already appeared.
+ return true if try_find_element.call(wait)
+
+ # If the element didn't appear, wait for requests and then check again
+ wait_for_requests(skip_finished_loading_check: !!kwargs.delete(:skip_finished_loading_check))
+
+ # We only wait one second now because we previously waited the full expected duration,
+ # plus however long it took for requests to complete. One second should be enough
+ # for the UI to update after requests complete.
+ try_find_element.call(1)
end
def has_no_element?(name, **kwargs)
@@ -274,8 +289,11 @@ module QA
sleep 1
end
- def within_element(name, text: nil)
- page.within(element_selector_css(name), text: text) do
+ def within_element(name, **kwargs)
+ wait_for_requests
+ text = kwargs.delete(:text)
+
+ page.within(element_selector_css(name, kwargs), text: text) do
yield
end
end
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index 459c02ec883..b98c429df8c 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -78,6 +78,11 @@ module QA
base.view 'app/assets/javascripts/snippets/components/embed_dropdown.vue' do
element :copy_button
end
+
+ base.view 'app/assets/javascripts/blob/components/blob_header_default_actions.vue' do
+ element :default_actions_container
+ element :copy_contents_button
+ end
end
def has_snippet_title?(snippet_title)
@@ -182,7 +187,10 @@ module QA
def add_comment(comment)
fill_element(:note_field, comment)
click_element(:comment_button)
- wait_until(reload: false) { has_element?(:note_author_content) }
+
+ unless has_element?(:note_author_content)
+ raise ElementNotFound, "Comment did not appear as expected"
+ end
end
def has_comment_author?(author_username)
@@ -207,7 +215,10 @@ module QA
click_element(:edit_comment_button)
fill_element(:edit_note_field, comment)
click_element(:save_comment_button)
- wait_until(reload: false) { has_element?(:note_author_content) }
+
+ unless has_element?(:note_author_content)
+ raise ElementNotFound, "Comment did not appear as expected"
+ end
end
def delete_comment(comment)
@@ -215,7 +226,32 @@ module QA
accept_alert do
click_element(:delete_comment_button)
end
- wait_until(reload: false) { has_no_text?(comment) }
+
+ unless has_no_element?(:note_content, text: comment)
+ raise ElementNotFound, "Comment was not removed as expected"
+ end
+ end
+
+ def click_copy_file_contents(file_number = nil)
+ if file_number
+ within_element_by_index(:default_actions_container, file_number - 1) do
+ click_element(:copy_contents_button)
+ end
+ else
+ within_element(:default_actions_container) do
+ click_element(:copy_contents_button)
+ end
+ end
+ end
+
+ def copy_file_contents_to_comment(file_number = nil)
+ click_copy_file_contents(file_number)
+ send_keys_to_element(:note_field, [:shift, :insert])
+ click_element(:comment_button)
+
+ unless has_element?(:note_author_content)
+ raise ElementNotFound, "Comment did not appear as expected"
+ end
end
end
end
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 2ecb27e05b2..8c70d0874c4 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -12,7 +12,7 @@ module QA
end
view 'app/assets/javascripts/jobs/components/stages_dropdown.vue' do
- element :pipeline_path
+ element :pipeline_path, required: true
end
view 'app/assets/javascripts/jobs/components/sidebar.vue' do
diff --git a/qa/qa/page/project/members.rb b/qa/qa/page/project/members.rb
index 88b05ceb1d1..447049ce22a 100644
--- a/qa/qa/page/project/members.rb
+++ b/qa/qa/page/project/members.rb
@@ -17,6 +17,7 @@ module QA
view 'app/views/projects/project_members/index.html.haml' do
element :invite_group_tab
+ element :groups_list_tab
end
view 'app/views/shared/members/_invite_group.html.haml' do
@@ -48,6 +49,7 @@ 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
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 7f96b896c1d..994b1c02a3d 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -77,7 +77,7 @@ module QA
end
def click_job(job_name)
- click_element(:job_link, text: job_name)
+ click_element(:job_link, Project::Job::Show, text: job_name)
end
def expand_child_pipeline
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index 757084fc5b9..9c4b3a3c1c3 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -26,6 +26,7 @@ module QA
view 'app/views/projects/_export.html.haml' do
element :export_project_link
element :download_export_link
+ element :export_project_content
end
def update_project_path_to(path)
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index fc33c753230..a8b30922bd2 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -57,6 +57,7 @@ module QA
view 'app/assets/javascripts/vue_shared/components/file_row.vue' do
element :file_name_content
+ element :file_row_container
end
view 'app/assets/javascripts/ide/components/new_dropdown/index.vue' do
@@ -77,9 +78,29 @@ module QA
element :ide_commit_message_field
end
+ view 'app/assets/javascripts/vue_shared/components/changed_file_icon.vue' do
+ element :changed_file_icon_content
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue' do
+ element :preview_container
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue' do
+ element :download_button
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue' do
+ element :image_viewer_container
+ end
+
+ view 'app/assets/javascripts/ide/components/new_dropdown/upload.vue' do
+ element :file_upload_field
+ end
+
def has_file?(file_name)
within_element(:file_list) do
- page.has_content? file_name
+ has_text?(file_name)
end
end
@@ -87,6 +108,26 @@ module QA
has_element?(:project_path_content, project_path: project_path)
end
+ def has_file_addition_icon?(file_name)
+ within_element(:file_row_container, file_name: file_name) do
+ has_element?(:changed_file_icon_content, title: 'Added')
+ end
+ end
+
+ def has_download_button?(file_name)
+ click_element(:file_row_container, file_name: file_name)
+ within_element(:preview_container) do
+ has_element?(:download_button)
+ end
+ end
+
+ def has_image_viewer?(file_name)
+ click_element(:file_row_container, file_name: file_name)
+ within_element(:preview_container) do
+ has_element?(:image_viewer_container)
+ end
+ end
+
def go_to_project
click_element(:project_path_content, Page::Project::Show)
end
@@ -212,6 +253,12 @@ module QA
has_element?(:file_list)
end
end
+
+ def upload_file(file_path)
+ within_element(:file_list) do
+ find_element(:file_upload_field, visible: false).send_keys(file_path)
+ end
+ end
end
end
end
diff --git a/qa/qa/resource/clusters/agent.rb b/qa/qa/resource/clusters/agent.rb
new file mode 100644
index 00000000000..cad5a4c6b1d
--- /dev/null
+++ b/qa/qa/resource/clusters/agent.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Clusters
+ class Agent < QA::Resource::Base
+ attribute :id
+ attribute :name
+ attribute :project do
+ QA::Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-cluster-agent'
+ end
+ end
+
+ def initialize
+ @name = "my-agent"
+ end
+
+ def fabricate!
+ puts 'TODO: FABRICATE VIA UI'
+ end
+ # TODO
+ #
+ # The UI for this model is not yet implemented. So far it can only be
+ # created through the GraphQL API
+ # def fabricate
+ #
+ # end
+
+ def api_get_path
+ "gid://gitlab/Clusters::Agent/#{id}"
+ end
+
+ def api_post_path
+ "/graphql"
+ end
+
+ def api_post_body
+ <<~GQL
+ mutation createAgent {
+ createClusterAgent(input: { projectPath: "#{project.full_path}", name: "#{@name}" }) {
+ clusterAgent {
+ id
+ name
+ }
+ errors
+ }
+ }
+ GQL
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/clusters/agent_token.rb b/qa/qa/resource/clusters/agent_token.rb
new file mode 100644
index 00000000000..6a5e861b650
--- /dev/null
+++ b/qa/qa/resource/clusters/agent_token.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Clusters
+ class AgentToken < QA::Resource::Base
+ attribute :id
+ attribute :secret
+ attribute :agent do
+ QA::Resource::Clusters::Agent.fabricate_via_api!
+ end
+
+ def fabricate!
+ puts 'TODO: FABRICATE VIA UI'
+ end
+ # TODO
+ #
+ # The UI for this model is not yet implemented. So far it can only be
+ # created through the GraphQL API
+ # def fabricate
+ #
+ # end
+
+ def api_get_path
+ "gid://gitlab/Clusters::AgentToken/#{id}"
+ end
+
+ def api_post_path
+ "/graphql"
+ end
+
+ def api_post_body
+ <<~GQL
+ mutation createToken {
+ clusterAgentTokenCreate(input: { clusterAgentId: "gid://gitlab/Clusters::Agent/#{agent.id}" }) {
+ secret # This is the value you need to use on the next step
+ token {
+ createdAt
+ id
+ }
+ errors
+ }
+ }
+ GQL
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/protected_branch.rb b/qa/qa/resource/protected_branch.rb
index 51ea9d1c5b9..7eb5442a964 100644
--- a/qa/qa/resource/protected_branch.rb
+++ b/qa/qa/resource/protected_branch.rb
@@ -22,7 +22,7 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.branch = branch_name
- commit.start_branch = 'master'
+ commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
commit.add_files([
{ file_path: "new_file-#{SecureRandom.hex(8)}.md", content: 'new file' }
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 24be4e4f978..1c637db5385 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -407,6 +407,10 @@ module QA
QA::Runtime::Scenario.attributes.include?(:geo_secondary_address)
end
+ def gitlab_agentk_version
+ ENV.fetch('GITLAB_AGENTK_VERSION', 'v13.7.0')
+ end
+
private
def remote_grid_credentials
diff --git a/qa/qa/runtime/feature.rb b/qa/qa/runtime/feature.rb
index a48bc216ac2..dd7f9cf898c 100644
--- a/qa/qa/runtime/feature.rb
+++ b/qa/qa/runtime/feature.rb
@@ -32,7 +32,7 @@ module QA
def enabled?(key, **scopes)
feature = JSON.parse(get_features).find { |flag| flag['name'] == key.to_s }
- feature && feature['state'] == 'on' || feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], scopes)
+ feature && (feature['state'] == 'on' || feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], scopes))
end
private
diff --git a/qa/qa/scenario/test/integration/ssh_tunnel.rb b/qa/qa/scenario/test/integration/ssh_tunnel.rb
new file mode 100644
index 00000000000..926dce1807e
--- /dev/null
+++ b/qa/qa/scenario/test/integration/ssh_tunnel.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class SSHTunnel < Test::Instance::All
+ tags :ssh_tunnel
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb
index 84196556547..ddf97046fb0 100644
--- a/qa/qa/service/kubernetes_cluster.rb
+++ b/qa/qa/service/kubernetes_cluster.rb
@@ -43,6 +43,14 @@ module QA
cluster_name
end
+ def create_secret(secret, secret_name)
+ shell("kubectl create secret generic #{secret_name} --from-literal=token='#{secret}'")
+ end
+
+ def apply_manifest(manifest)
+ shell('kubectl apply -f -', stdin_data: manifest)
+ end
+
private
def fetch_api_url
diff --git a/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb
new file mode 100644
index 00000000000..8c3b8d88a29
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'Gitaly', :orchestrated, :mtls do
+ describe 'Using mTLS' do
+ let(:intial_commit_message) { 'Initial commit' }
+ let(:first_added_commit_message) { 'commit over git' }
+ let(:second_added_commit_message) { 'commit over api' }
+
+ it 'pushes to gitaly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1118' do
+ project = Resource::Project.fabricate! do |project|
+ project.name = "mTLS"
+ project.initialize_with_readme = true
+ end
+
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.new_branch = false
+ push.commit_message = first_added_commit_message
+ push.file_content = 'First commit'
+ end
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = second_added_commit_message
+ commit.add_files([
+ {
+ file_path: "file-#{SecureRandom.hex(8)}",
+ content: 'Second commit'
+ }
+ ])
+ end
+
+ expect(project.commits.map { |commit| commit[:message].chomp })
+ .to include(intial_commit_message)
+ .and include(first_added_commit_message)
+ .and include(second_added_commit_message)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb b/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb
index 548933d2cde..4bd99b4820e 100644
--- a/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb
@@ -28,13 +28,6 @@ module QA
end
end
- after do
- # Delete the .netrc file created during this test so that subsequent tests don't try to use the logins
- Git::Repository.perform do |repository|
- repository.delete_netrc
- end
- end
-
it 'download archives of each user project then check they are different', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/427' do
archive_checksums = {}
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
index b9e1ee53246..5f38907f89f 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
@@ -43,7 +43,9 @@ module QA
end
end
- it 'user transfers a project between groups', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/406' do
+ it 'user transfers a project between groups',
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/406',
+ quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/283925', type: :investigating, only: :production } do
# Retry is needed here as the target group is not avaliable for transfer right away.
QA::Support::Retrier.retry_on_exception(reload_page: page) do
Page::File::Show.perform(&:go_to_general_settings)
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 d58857f6da2..d9b246fc458 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
@@ -98,8 +98,10 @@ module QA
before do
enable_require_admin_approval_after_user_signup_via_ui
- @user = Resource::User.fabricate_via_browser_ui! do |user|
- user.expect_fabrication_success = false
+ Support::Retrier.retry_on_exception do
+ @user = Resource::User.fabricate_via_browser_ui! do |user|
+ user.expect_fabrication_success = false
+ end
end
end
@@ -148,26 +150,34 @@ module QA
end
def set_require_admin_approval_after_user_signup_via_api(enable_or_disable)
- return if Runtime::ApplicationSettings.get_application_settings[:require_admin_approval_after_user_signup] == enable_or_disable
+ return if get_require_admin_approval_after_user_signup_via_api == enable_or_disable
Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: enable_or_disable)
sleep 10 # It takes a moment for the setting to come into effect
end
+ def get_require_admin_approval_after_user_signup_via_api
+ Runtime::ApplicationSettings.get_application_settings[:require_admin_approval_after_user_signup]
+ end
+
def enable_require_admin_approval_after_user_signup_via_ui
- unless Runtime::ApplicationSettings.get_application_settings[:require_admin_approval_after_user_signup]
- Flow::Login.while_signed_in_as_admin do
- Page::Main::Menu.perform(&:go_to_admin_area)
- QA::Page::Admin::Menu.perform(&:go_to_general_settings)
- Page::Admin::Settings::General.perform do |setting|
- setting.expand_sign_up_restrictions do |settings|
- settings.require_admin_approval_after_user_signup
+ unless get_require_admin_approval_after_user_signup_via_api
+ QA::Support::Retrier.retry_until do
+ Flow::Login.while_signed_in_as_admin do
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ QA::Page::Admin::Menu.perform(&:go_to_general_settings)
+ Page::Admin::Settings::General.perform do |setting|
+ setting.expand_sign_up_restrictions do |settings|
+ settings.require_admin_approval_after_user_signup
+ end
end
end
- end
- sleep 10 # It takes a moment for the setting to come into effect
+ sleep 15 # It takes a moment for the setting to come into effect
+
+ get_require_admin_approval_after_user_signup_via_api
+ end
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 ff13b769e3a..a2e01398c94 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,8 +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',
- quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/283925', type: :investigating } do
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/429' do
Flow::Login.sign_in
created_project = Resource::Project.fabricate_via_browser_ui! do |project|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
new file mode 100644
index 00000000000..1670ba56064
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Multiple file snippet' do
+ let(:first_file_content) { 'First file content' }
+ let(:second_file_content) { 'Second file content' }
+ let(:third_file_content) { 'Third file content' }
+
+ let(:personal_snippet) do
+ Resource::Snippet.fabricate_via_api! do |snippet|
+ snippet.title = 'Personal snippet to copy file contents from'
+ snippet.file_name = 'First file name'
+ snippet.file_content = first_file_content
+
+ snippet.add_files do |files|
+ files.append(name: 'Second file name', content: second_file_content)
+ files.append(name: 'Third file name', content: third_file_content)
+ end
+ end
+ end
+
+ let(:project_snippet) do
+ Resource::ProjectSnippet.fabricate_via_api! do |snippet|
+ snippet.title = 'Project snippet to copy file contents from'
+ snippet.file_name = 'First file name'
+ snippet.file_content = first_file_content
+
+ snippet.add_files do |files|
+ files.append(name: 'Second file name', content: second_file_content)
+ files.append(name: 'Third file name', content: third_file_content)
+ end
+ end
+ end
+
+ let(:files) do
+ [
+ {
+ number: 1,
+ content: first_file_content
+ },
+ {
+ number: 2,
+ content: second_file_content
+ },
+ {
+ number: 3,
+ content: third_file_content
+ }
+ ]
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ shared_examples 'copying snippet file contents' do |snippet_type|
+ it "copies file contents of a multi-file #{snippet_type} to a comment and verifies them" do
+ send(snippet_type).visit!
+
+ files.each do |files|
+ Page::Dashboard::Snippet::Show.perform do |snippet|
+ snippet.copy_file_contents_to_comment(files[:number])
+ expect(snippet).to have_comment_content(files[:content])
+ snippet.delete_comment(files[:content])
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'copying snippet file contents', :personal_snippet
+ it_behaves_like 'copying snippet file contents', :project_snippet
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
index 971c5371d44..751424222ba 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
@@ -7,7 +7,7 @@ module QA
Resource::Snippet.fabricate! do |snippet|
snippet.title = 'Shared snippet'
snippet.visibility = 'Public'
- snippet.file_content = 'code.py'
+ snippet.file_name = 'code.py'
snippet.file_content = 'code to be shared'
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
new file mode 100644
index 00000000000..d62f894279f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Upload a file in Web IDE' do
+ let(:file_path) { File.absolute_path(File.join('qa', 'fixtures', 'web_ide', file_name)) }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'upload-file-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ project.visit!
+ Page::Project::Show.perform(&:open_web_ide!)
+ end
+
+ context 'when a file with the same name already exists' do
+ let(:file_name) { 'README.md' }
+
+ it 'throws an error' do
+ Page::Project::WebIDE::Edit.perform do |ide|
+ ide.upload_file(file_path)
+ end
+
+ expect(page).to have_content('The name "README.md" is already taken in this directory.')
+ end
+ end
+
+ context 'when the file is a text file' do
+ let(:file_name) { 'text_file.txt' }
+
+ it 'shows the Edit tab with the text' do
+ Page::Project::WebIDE::Edit.perform do |ide|
+ ide.upload_file(file_path)
+
+ expect(ide).to have_file(file_name)
+ expect(ide).to have_file_addition_icon(file_name)
+ expect(ide).to have_text('Simple text')
+
+ ide.commit_changes
+
+ expect(ide).to have_file(file_name)
+ end
+ end
+ end
+
+ context 'when the file is binary' do
+ let(:file_name) { 'logo_sample.svg' }
+
+ it 'shows a Download button' do
+ Page::Project::WebIDE::Edit.perform do |ide|
+ ide.upload_file(file_path)
+
+ expect(ide).to have_file(file_name)
+ expect(ide).to have_file_addition_icon(file_name)
+ expect(ide).to have_download_button(file_name)
+
+ ide.commit_changes
+
+ expect(ide).to have_file(file_name)
+ end
+ end
+ end
+
+ context 'when the file is an image' do
+ let(:file_name) { 'dk.png' }
+
+ it 'shows an image viewer' do
+ Page::Project::WebIDE::Edit.perform do |ide|
+ ide.upload_file(file_path)
+
+ expect(ide).to have_file(file_name)
+ expect(ide).to have_file_addition_icon(file_name)
+ expect(ide).to have_image_viewer(file_name)
+
+ ide.commit_changes
+
+ expect(ide).to have_file(file_name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
index 5410b5023d9..605248e33f7 100644
--- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
@@ -22,10 +22,22 @@ module QA
end
end
- it 'publishes a maven package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/943' do
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let!(:gitlab_address_with_port) do
uri = URI.parse(Runtime::Scenario.gitlab_address)
- gitlab_address_with_port = "#{uri.scheme}://#{uri.host}:#{uri.port}"
- pom_xml = {
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ let(:pom_xml) do
+ {
file_path: 'pom.xml',
content: <<~XML
<project>
@@ -52,28 +64,33 @@ module QA
</project>
XML
}
- settings_xml = {
+ end
+
+ let(:settings_xml) do
+ {
file_path: 'settings.xml',
content: <<~XML
- <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
- <servers>
- <server>
- <id>#{project.name}</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Private-Token</name>
- <value>#{auth_token}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
- </settings>
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+ <servers>
+ <server>
+ <id>#{project.name}</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value>#{auth_token}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ </settings>
XML
}
+ end
+ it 'publishes a maven package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/943' do
# Use a maven docker container to deploy the package
with_fixtures([pom_xml, settings_xml]) do |dir|
Service::DockerRun::Maven.new(dir).publish!
@@ -99,6 +116,43 @@ module QA
expect(index).not_to have_package(package_name)
end
end
+
+ it 'publishes and downloads a maven package via CI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1115' 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
+ deploy:
+ image: maven:3.6-jdk-11
+ script:
+ - 'mvn deploy -s settings.xml'
+ - "mvn dependency:get -Dartifact=#{group_id}:#{artifact_id}:1.0"
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ },
+ settings_xml,
+ pom_xml
+ ])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
end
end
end
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
new file mode 100644
index 00000000000..17c53b3ddc9
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Release', :smoke, :runner do
+ describe 'Pages' do
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'jekyll-pages-project'
+ project.template_name = :jekyll
+ end
+ end
+
+ let(:pipeline) do
+ Resource::Pipeline.fabricate_via_api! do |pipeline|
+ pipeline.project = project
+ pipeline.variables =
+ { key: :CI_PAGES_DOMAIN, value: 'nip.io', variable_type: :env_var },
+ { key: :CI_PAGES_URL, value: 'http://127.0.0.1.nip.io', variable_type: :env_var }
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Runner.fabricate_via_api! do |runner|
+ runner.project = project
+ runner.executor = :docker
+ end
+
+ pipeline.visit!
+ end
+
+ it 'runs a Pages-specific pipeline', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/296937' do
+ Page::Project::Pipeline::Show.perform do |show|
+ expect(show).to have_job(:pages)
+ show.click_job(:pages)
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show).to have_passed(timeout: 300)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index fca46cc2826..e183d711b30 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -143,12 +143,12 @@ module QA
super
end
- def within_element(name, text: nil)
- log("within element :#{name}")
+ def within_element(name, **kwargs)
+ log("within element :#{name} with args #{kwargs}")
element = super
- log("end within element :#{name}")
+ log("end within element :#{name} with args #{kwargs}")
element
end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 9785d0a9014..16d86ef6ed2 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -27,6 +27,11 @@ RSpec.configure do |config|
QA::Runtime::Logger.debug("\nStarting test: #{example.full_description}\n")
end
+ config.after do
+ # If a .netrc file was created during the test, delete it so that subsequent tests don't try to use the same logins
+ QA::Git::Repository.new.delete_netrc
+ end
+
config.after(:context) do
if !QA::Runtime::Browser.blank_page? && QA::Page::Main::Menu.perform(&:signed_in?)
QA::Page::Main::Menu.perform(&:sign_out)
diff --git a/rubocop/cop/lint/last_keyword_argument.rb b/rubocop/cop/lint/last_keyword_argument.rb
index 430ea66e9a1..9652c1ace8d 100644
--- a/rubocop/cop/lint/last_keyword_argument.rb
+++ b/rubocop/cop/lint/last_keyword_argument.rb
@@ -16,7 +16,7 @@ module RuboCop
KEYWORD_DEPRECATION_STR = 'maybe ** should be added to the call'
def on_send(node)
- arg = node.arguments.last
+ arg = get_last_argument(node)
return unless arg
return unless known_match?(processed_source.file_path, node.first_line, node.method_name.to_s)
@@ -44,13 +44,22 @@ module RuboCop
private
+ def get_last_argument(node)
+ return node.arguments[-2] if node.block_argument?
+
+ node.arguments.last
+ end
+
def known_match?(file_path, line_number, method_name)
file_path_from_root = file_path.sub(File.expand_path('../../..', __dir__), '')
+ file_and_line = "#{file_path_from_root}:#{line_number}"
method_name = 'initialize' if method_name == 'new'
- self.class.keyword_warnings.any? do |warning|
- warning.include?("#{file_path_from_root}:#{line_number}") && warning.include?("called method `#{method_name}'")
+ return unless self.class.keyword_warnings[method_name]
+
+ self.class.keyword_warnings[method_name].any? do |warning|
+ warning.include?(file_and_line)
end
end
@@ -63,7 +72,16 @@ module RuboCop
hash.merge!(YAML.safe_load(File.read(file)))
end
- hash.values.flatten.select { |str| str.include?(KEYWORD_DEPRECATION_STR) }.uniq
+ hash.values.flatten.each_with_object({}) do |str, results|
+ next unless str.include?(KEYWORD_DEPRECATION_STR)
+
+ match_data = str.match(/called method `([^\s]+)'/)
+ next unless match_data
+
+ key = match_data[1]
+ results[key] ||= []
+ results[key] << str
+ end
end
end
end
diff --git a/rubocop/cop/rspec/expect_gitlab_tracking.rb b/rubocop/cop/rspec/expect_gitlab_tracking.rb
index ba658558705..e3f790f851c 100644
--- a/rubocop/cop/rspec/expect_gitlab_tracking.rb
+++ b/rubocop/cop/rspec/expect_gitlab_tracking.rb
@@ -53,8 +53,6 @@ module RuboCop
)
PATTERN
- RESTRICT_ON_SEND = [:expect, :allow].freeze
-
def on_send(node)
return unless expect_gitlab_tracking?(node)
diff --git a/rubocop/cop/rspec/web_mock_enable.rb b/rubocop/cop/rspec/web_mock_enable.rb
new file mode 100644
index 00000000000..bcf7f95dbbd
--- /dev/null
+++ b/rubocop/cop/rspec/web_mock_enable.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module RSpec
+ class WebMockEnable < RuboCop::Cop::Cop
+ # This cop checks for `WebMock.disable_net_connect!` usage in specs and
+ # replaces it with `webmock_enable!`
+ #
+ # @example
+ #
+ # # bad
+ # WebMock.disable_net_connect!
+ # WebMock.disable_net_connect!(allow_localhost: true)
+ #
+ # # good
+ # webmock_enable!
+
+ MESSAGE = 'Use webmock_enable! instead of calling WebMock.disable_net_connect! directly.'
+
+ def_node_matcher :webmock_disable_net_connect?, <<~PATTERN
+ (send (const nil? :WebMock) :disable_net_connect! ...)
+ PATTERN
+
+ def on_send(node)
+ if webmock_disable_net_connect?(node)
+ add_offense(node, location: :expression, message: MESSAGE)
+ end
+ end
+
+ def autocorrect(node)
+ lambda do |corrector|
+ corrector.replace(node, 'webmock_enable!')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index 08e09747ae2..c8a573410d8 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,4 +1,4 @@
# frozen_string_literal: true
# Auto-require all cops under `rubocop/cop/**/*.rb`
-Dir[File.join(__dir__, 'cop', '**', '*.rb')].each(&method(:require))
+Dir[File.join(__dir__, 'cop', '**', '*.rb')].sort.each(&method(:require))
diff --git a/scripts/api/cancel_pipeline b/scripts/api/cancel_pipeline.rb
index 0965877a69a..0965877a69a 100755
--- a/scripts/api/cancel_pipeline
+++ b/scripts/api/cancel_pipeline.rb
diff --git a/scripts/api/download_job_artifact b/scripts/api/download_job_artifact.rb
index 8e2207c6fa7..8e2207c6fa7 100755
--- a/scripts/api/download_job_artifact
+++ b/scripts/api/download_job_artifact.rb
diff --git a/scripts/api/get_job_id b/scripts/api/get_job_id.rb
index c7fe859db91..c7fe859db91 100755
--- a/scripts/api/get_job_id
+++ b/scripts/api/get_job_id.rb
diff --git a/scripts/api/play_job b/scripts/api/play_job
deleted file mode 100755
index 199f7e65633..00000000000
--- a/scripts/api/play_job
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-require 'rubygems'
-require 'gitlab'
-require 'optparse'
-require_relative 'get_job_id'
-
-class PlayJob
- DEFAULT_OPTIONS = {
- project: ENV['CI_PROJECT_ID'],
- pipeline_id: ENV['CI_PIPELINE_ID'],
- api_token: ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
- }.freeze
-
- def initialize(options)
- @project = options.delete(:project)
- @options = options
-
- Gitlab.configure do |config|
- config.endpoint = 'https://gitlab.com/api/v4'
- config.private_token = options.fetch(:api_token)
- end
- end
-
- def execute
- job = JobFinder.new(project, options.slice(:api_token, :pipeline_id, :job_name).merge(scope: 'manual')).execute
-
- Gitlab.job_play(project, job.id)
- end
-
- private
-
- attr_reader :project, :options
-end
-
-if $0 == __FILE__
- options = PlayJob::DEFAULT_OPTIONS.dup
-
- OptionParser.new do |opts|
- opts.on("-p", "--project PROJECT", String, "Project where to find the job (defaults to $CI_PROJECT_ID)") do |value|
- options[:project] = value
- end
-
- opts.on("-j", "--job-name JOB_NAME", String, "A job name that needs to exist in the found pipeline") do |value|
- options[:job_name] = value
- end
-
- opts.on("-t", "--api-token API_TOKEN", String, "A value API token with the `read_api` scope") do |value|
- options[:api_token] = value
- end
-
- opts.on("-h", "--help", "Prints this help") do
- puts opts
- exit
- end
- end.parse!
-
- PlayJob.new(options).execute
-end
diff --git a/scripts/api/play_job.rb b/scripts/api/play_job.rb
new file mode 100755
index 00000000000..408dfdf1ef0
--- /dev/null
+++ b/scripts/api/play_job.rb
@@ -0,0 +1,63 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'rubygems'
+require 'gitlab'
+require 'optparse'
+require_relative 'get_job_id'
+
+class PlayJob
+ DEFAULT_OPTIONS = {
+ project: ENV['CI_PROJECT_ID'],
+ pipeline_id: ENV['CI_PIPELINE_ID'],
+ api_token: ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
+ }.freeze
+
+ def initialize(options)
+ @options = options
+
+ Gitlab.configure do |config|
+ config.endpoint = 'https://gitlab.com/api/v4'
+ config.private_token = options.fetch(:api_token)
+ end
+ end
+
+ def execute
+ job = JobFinder.new(options.slice(:project, :api_token, :pipeline_id, :job_name).merge(scope: 'manual')).execute
+
+ Gitlab.job_play(project, job.id)
+ end
+
+ private
+
+ attr_reader :options
+
+ def project
+ options[:project]
+ end
+end
+
+if $0 == __FILE__
+ options = PlayJob::DEFAULT_OPTIONS.dup
+
+ OptionParser.new do |opts|
+ opts.on("-p", "--project PROJECT", String, "Project where to find the job (defaults to $CI_PROJECT_ID)") do |value|
+ options[:project] = value
+ end
+
+ opts.on("-j", "--job-name JOB_NAME", String, "A job name that needs to exist in the found pipeline") do |value|
+ options[:job_name] = value
+ end
+
+ opts.on("-t", "--api-token API_TOKEN", String, "A value API token with the `read_api` scope") do |value|
+ options[:api_token] = value
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ PlayJob.new(options).execute
+end
diff --git a/scripts/frontend/block_dependencies.js b/scripts/frontend/block_dependencies.js
index c9257c9f72b..a1ff8d5ee36 100644
--- a/scripts/frontend/block_dependencies.js
+++ b/scripts/frontend/block_dependencies.js
@@ -5,13 +5,13 @@ const dependencies = packageJson.dependencies;
const devDependencies = packageJson.devDependencies;
const blockedDependenciesNames = Object.keys(blockedDependencies);
const blockedDependenciesFound = blockedDependenciesNames.filter(
- blockedDependency => dependencies[blockedDependency] || devDependencies[blockedDependency],
+ (blockedDependency) => dependencies[blockedDependency] || devDependencies[blockedDependency],
);
if (blockedDependenciesFound.length) {
console.log('The following package.json dependencies are not allowed:');
- blockedDependenciesFound.forEach(blockedDependency => {
+ blockedDependenciesFound.forEach((blockedDependency) => {
const infoLink = blockedDependencies[blockedDependency];
console.log(`- ${blockedDependency}: See ${infoLink} for more information.`);
diff --git a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
index a2bb9f56d84..34e939e3ceb 100755
--- a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
+++ b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
@@ -27,7 +27,7 @@ const file = fs.readFileSync(paths[0], 'utf-8');
const parsed = pjs.parse(file);
-if (parsed.nodes.every(node => ['comment', 'atrule'].includes(node.type))) {
+if (parsed.nodes.every((node) => ['comment', 'atrule'].includes(node.type))) {
console.log('The file does not introduce any side effects, we are all good.');
process.exit(0);
}
diff --git a/scripts/frontend/extract_gettext_all.js b/scripts/frontend/extract_gettext_all.js
index 725522a3540..c34c9a0233d 100644
--- a/scripts/frontend/extract_gettext_all.js
+++ b/scripts/frontend/extract_gettext_all.js
@@ -45,7 +45,7 @@ function printJson() {
text += `\u0000${message.textPlural}`;
}
- message.references.forEach(reference => {
+ message.references.forEach((reference) => {
const filename = reference.replace(/:\d+$/, '');
if (!Array.isArray(result[filename])) {
diff --git a/scripts/frontend/file_test_coverage.js b/scripts/frontend/file_test_coverage.js
index 7d1eb45d4bc..ec6ec4a1e9d 100755
--- a/scripts/frontend/file_test_coverage.js
+++ b/scripts/frontend/file_test_coverage.js
@@ -17,11 +17,11 @@ const sourceDirectories = ['app/assets/javascripts'];
const testDirectories = ['spec/javascripts', 'spec/frontend'];
if (fs.existsSync('ee')) {
- sourceDirectories.forEach(dir => {
+ sourceDirectories.forEach((dir) => {
sourceDirectories.push(`ee/${dir}`);
});
- testDirectories.forEach(dir => {
+ testDirectories.forEach((dir) => {
testDirectories.push(`ee/${dir}`);
});
}
@@ -29,10 +29,10 @@ if (fs.existsSync('ee')) {
let numSourceFiles = 0;
let numTestFiles = 0;
-const isVerbose = process.argv.some(arg => arg === '-v');
+const isVerbose = process.argv.some((arg) => arg === '-v');
-const countSourceFiles = path =>
- forEachFileIn(path, fileName => {
+const countSourceFiles = (path) =>
+ forEachFileIn(path, (fileName) => {
if (fileName.endsWith('.vue') || fileName.endsWith('.js')) {
if (isVerbose) {
console.log(`source file: ${fileName}`);
@@ -42,8 +42,8 @@ const countSourceFiles = path =>
}
});
-const countTestFiles = path =>
- forEachFileIn(path, fileName => {
+const countTestFiles = (path) =>
+ forEachFileIn(path, (fileName) => {
if (fileName.endsWith('_spec.js')) {
if (isVerbose) {
console.log(`test file: ${fileName}`);
@@ -63,7 +63,7 @@ function forEachFileIn(dirPath, callback) {
return;
}
- files.forEach(fileName => {
+ files.forEach((fileName) => {
const absolutePath = path.join(dirPath, fileName);
const stats = fs.statSync(absolutePath);
if (stats.isFile()) {
diff --git a/scripts/frontend/frontend_script_utils.js b/scripts/frontend/frontend_script_utils.js
index e3d357b4a40..43016dce6a4 100644
--- a/scripts/frontend/frontend_script_utils.js
+++ b/scripts/frontend/frontend_script_utils.js
@@ -9,15 +9,10 @@ const exec = (command, args) => {
return execFileSync(command, args, options);
};
-const execGitCmd = args =>
- exec('git', args)
- .trim()
- .toString()
- .split('\n')
- .filter(Boolean);
+const execGitCmd = (args) => exec('git', args).trim().toString().split('\n').filter(Boolean);
module.exports = {
- getStagedFiles: fileExtensionFilter => {
+ getStagedFiles: (fileExtensionFilter) => {
const gitOptions = ['diff', '--name-only', '--cached', '--diff-filter=ACMRTUB'];
if (fileExtensionFilter) gitOptions.push(...fileExtensionFilter);
return execGitCmd(gitOptions);
diff --git a/scripts/frontend/merge_coverage_frontend.js b/scripts/frontend/merge_coverage_frontend.js
index 99034176b29..0c45a38b9b5 100644
--- a/scripts/frontend/merge_coverage_frontend.js
+++ b/scripts/frontend/merge_coverage_frontend.js
@@ -11,7 +11,7 @@ const reportFiles = sync(`${coverageDir}/*/coverage-final.json`);
// Normalize coverage report generated by jest that has additional "data" key
// https://github.com/facebook/jest/issues/2418#issuecomment-423806659
-const normalizeReport = report => {
+const normalizeReport = (report) => {
const normalizedReport = Object.assign({}, report);
Object.entries(normalizedReport).forEach(([k, v]) => {
if (v.data) normalizedReport[k] = v.data;
@@ -20,12 +20,12 @@ const normalizeReport = report => {
};
reportFiles
- .map(reportFile => require(reportFile))
+ .map((reportFile) => require(reportFile))
.map(normalizeReport)
- .forEach(report => coverageMap.merge(report));
+ .forEach((report) => coverageMap.merge(report));
const context = createContext({ coverageMap: coverageMap, dir: 'coverage-frontend' });
-['json', 'lcov', 'text-summary', 'clover', 'cobertura'].forEach(reporter => {
+['json', 'lcov', 'text-summary', 'clover', 'cobertura'].forEach((reporter) => {
create(reporter, {}).execute(context);
});
diff --git a/scripts/frontend/prettier.js b/scripts/frontend/prettier.js
index 7772f80c233..f721e46f36b 100644
--- a/scripts/frontend/prettier.js
+++ b/scripts/frontend/prettier.js
@@ -7,11 +7,11 @@ const matchExtensions = ['js', 'vue', 'graphql'];
// This will improve glob performance by excluding certain directories.
// The .prettierignore file will also be respected, but after the glob has executed.
-const globIgnore = ['**/node_modules/**', 'vendor/**', 'public/**'];
+const globIgnore = ['**/node_modules/**', 'vendor/**', 'public/**', 'fixtures/**'];
const readFileAsync = (file, options) =>
new Promise((resolve, reject) => {
- fs.readFile(file, options, function(err, data) {
+ fs.readFile(file, options, function (err, data) {
if (err) reject(err);
else resolve(data);
});
@@ -19,7 +19,7 @@ const readFileAsync = (file, options) =>
const writeFileAsync = (file, data, options) =>
new Promise((resolve, reject) => {
- fs.writeFile(file, data, options, function(err) {
+ fs.writeFile(file, data, options, function (err) {
if (err) reject(err);
else resolve();
});
@@ -35,7 +35,7 @@ console.log(
`Loading all ${allFiles ? '' : 'staged '}files ${globDir ? `within ${globDir} ` : ''}...`,
);
-const globPatterns = matchExtensions.map(ext => `${globDir}**/*.${ext}`);
+const globPatterns = matchExtensions.map((ext) => `${globDir}**/*.${ext}`);
const matchedFiles = allFiles
? glob.sync(`{${globPatterns.join(',')}}`, { ignore: globIgnore })
: getStagedFiles(globPatterns);
@@ -62,7 +62,7 @@ Please format each file listed below or run "${fixCommand}"
`;
const checkFileWithOptions = (filePath, options) =>
- readFileAsync(filePath, 'utf8').then(input => {
+ readFileAsync(filePath, 'utf8').then((input) => {
if (shouldSave) {
const output = prettier.format(input, options);
if (input === output) {
@@ -92,7 +92,7 @@ const checkFileWithOptions = (filePath, options) =>
}
});
-const checkFileWithPrettierConfig = filePath =>
+const checkFileWithPrettierConfig = (filePath) =>
prettier
.getFileInfo(filePath, { ignorePath: '.prettierignore' })
.then(({ ignored, inferredParser }) => {
@@ -100,7 +100,7 @@ const checkFileWithPrettierConfig = filePath =>
ignoredCount += 1;
return;
}
- return prettier.resolveConfig(filePath).then(fileOptions => {
+ return prettier.resolveConfig(filePath).then((fileOptions) => {
const options = { ...fileOptions, parser: inferredParser };
return checkFileWithOptions(filePath, options);
});
@@ -115,7 +115,7 @@ Promise.all(matchedFiles.map(checkFileWithPrettierConfig))
if (didWarn) process.exit(1);
})
- .catch(e => {
+ .catch((e) => {
console.log(`\nAn error occurred while processing files with prettier: ${e.message}\n`);
process.exit(1);
});
diff --git a/scripts/frontend/stylelint/stylelint-duplicate-selectors.js b/scripts/frontend/stylelint/stylelint-duplicate-selectors.js
index 4b46ee21a7a..89242158157 100644
--- a/scripts/frontend/stylelint/stylelint-duplicate-selectors.js
+++ b/scripts/frontend/stylelint/stylelint-duplicate-selectors.js
@@ -8,12 +8,12 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
},
});
-module.exports = stylelint.createPlugin(ruleName, function(enabled) {
+module.exports = stylelint.createPlugin(ruleName, function (enabled) {
if (!enabled) {
return;
}
- return function(root, result) {
+ return function (root, result) {
const selectorGroups = {};
utils.createPropertiesHashmap(root, result, ruleName, messages, selectorGroups, true);
};
diff --git a/scripts/frontend/stylelint/stylelint-utility-classes.js b/scripts/frontend/stylelint/stylelint-utility-classes.js
index 8a1cfdbf302..1b266fc31c9 100644
--- a/scripts/frontend/stylelint/stylelint-utility-classes.js
+++ b/scripts/frontend/stylelint/stylelint-utility-classes.js
@@ -10,12 +10,12 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
},
});
-module.exports = stylelint.createPlugin(ruleName, function(enabled) {
+module.exports = stylelint.createPlugin(ruleName, function (enabled) {
if (!enabled) {
return;
}
- return function(root, result) {
+ return function (root, result) {
utils.createPropertiesHashmap(root, result, ruleName, messages, utilityClasses, false);
};
});
diff --git a/scripts/frontend/stylelint/stylelint-utility-map.js b/scripts/frontend/stylelint/stylelint-utility-map.js
index 941198e82a4..bf8ee362740 100644
--- a/scripts/frontend/stylelint/stylelint-utility-map.js
+++ b/scripts/frontend/stylelint/stylelint-utility-map.js
@@ -32,7 +32,7 @@ sass.render(
// This suppresses a postcss warning
from: undefined,
})
- .then(result => {
+ .then((result) => {
const selectorGroups = {};
utils.createPropertiesHashmap(result.root, result, null, null, selectorGroups, true);
@@ -42,7 +42,7 @@ sass.render(
prettierOptions,
);
- fs.writeFile(hashMapPath, prettyHashmap, function(err) {
+ fs.writeFile(hashMapPath, prettyHashmap, function (err) {
if (err) {
return console.log(err);
}
diff --git a/scripts/frontend/stylelint/stylelint-utils.js b/scripts/frontend/stylelint/stylelint-utils.js
index 2d931c1c4c2..e7452b0cdb2 100644
--- a/scripts/frontend/stylelint/stylelint-utils.js
+++ b/scripts/frontend/stylelint/stylelint-utils.js
@@ -9,7 +9,7 @@ module.exports.createPropertiesHashmap = (
selectorGroups,
addSelectors,
) => {
- ruleRoot.walkRules(rule => {
+ ruleRoot.walkRules((rule) => {
const selector = rule.selector.replace(/(?:\r\n|\r|\n)/g, ' ');
if (
@@ -25,7 +25,7 @@ module.exports.createPropertiesHashmap = (
)
) {
let cssArray = [];
- rule.nodes.forEach(function(property) {
+ rule.nodes.forEach(function (property) {
const { prop, value } = property;
if (property && value) {
const propval = `${prop}${value}${property.important ? '!important' : ''}`;
diff --git a/scripts/frontend/webpack_dev_server.js b/scripts/frontend/webpack_dev_server.js
index 8026a8d47e2..fbb80c9617d 100755
--- a/scripts/frontend/webpack_dev_server.js
+++ b/scripts/frontend/webpack_dev_server.js
@@ -51,7 +51,7 @@ else {
// print useful messages for nodemon events
nodemon
- .on('start', function() {
+ .on('start', function () {
console.log(`Starting webpack webserver on http://${DEV_SERVER_HOST}:${DEV_SERVER_PORT}`);
if (STATIC_MODE) {
console.log('You are starting webpack in compile-once mode');
@@ -59,10 +59,10 @@ nodemon
console.log('If you change them often, you might want to unset DEV_SERVER_STATIC');
}
})
- .on('quit', function() {
+ .on('quit', function () {
console.log('Shutting down webpack process');
process.exit();
})
- .on('restart', function(files) {
+ .on('restart', function (files) {
console.log('Restarting webpack process due to: ', files);
});
diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build
index 00927646046..62d3dbda911 100755
--- a/scripts/gitaly-test-build
+++ b/scripts/gitaly-test-build
@@ -12,7 +12,7 @@ class GitalyTestBuild
include GitalyTest
def run
- abort 'gitaly build failed' unless system(env, 'make', chdir: tmp_tests_gitaly_dir)
+ abort 'gitaly build failed' unless build_gitaly
ensure_gitlab_shell_secret!
check_gitaly_config!
diff --git a/scripts/gitaly-test-spawn b/scripts/gitaly-test-spawn
index c2ff9cd08aa..caa41a9a0c3 100755
--- a/scripts/gitaly-test-spawn
+++ b/scripts/gitaly-test-spawn
@@ -8,6 +8,7 @@ class GitalyTestSpawn
include GitalyTest
def run
+ install_gitaly_gems if ENV['CI']
check_gitaly_config!
# # Uncomment line below to see all gitaly logs merged into CI trace
diff --git a/scripts/gitaly_test.rb b/scripts/gitaly_test.rb
index 559ad8f4345..c7b3f72d590 100644
--- a/scripts/gitaly_test.rb
+++ b/scripts/gitaly_test.rb
@@ -41,7 +41,7 @@ module GitalyTest
'HOME' => File.expand_path('tmp/tests'),
'GEM_PATH' => Gem.path.join(':'),
'BUNDLE_APP_CONFIG' => File.join(File.dirname(gemfile), '.bundle/config'),
- 'BUNDLE_FLAGS' => "--jobs=4 --retry=3 --quiet",
+ 'BUNDLE_FLAGS' => "--jobs=4 --retry=3",
'BUNDLE_INSTALL_FLAGS' => nil,
'BUNDLE_GEMFILE' => gemfile,
'RUBYOPT' => nil,
@@ -78,6 +78,14 @@ module GitalyTest
end
end
+ def install_gitaly_gems
+ system(env, "make #{tmp_tests_gitaly_dir}/.ruby-bundle", chdir: tmp_tests_gitaly_dir) # rubocop:disable GitlabSecurity/SystemCommandInjection
+ end
+
+ def build_gitaly
+ system(env, 'make', chdir: tmp_tests_gitaly_dir) # rubocop:disable GitlabSecurity/SystemCommandInjection
+ end
+
def start_gitaly
start(:gitaly)
end
diff --git a/scripts/perf/gc/collect_gc_stats.rb b/scripts/perf/gc/collect_gc_stats.rb
new file mode 100755
index 00000000000..050ad66a926
--- /dev/null
+++ b/scripts/perf/gc/collect_gc_stats.rb
@@ -0,0 +1,97 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+####
+# Loads GitLab application classes with a variety of GC settings and prints
+# GC stats and timing data to standard out as CSV.
+#
+# The degree of parallelism can be increased by setting the PAR environment
+# variable (default: 2).
+
+require 'benchmark'
+
+SETTINGS = {
+ 'DEFAULTS' => [''],
+ # Default: 10_000
+ 'RUBY_GC_HEAP_INIT_SLOTS' => %w[100000 1000000 5000000],
+ # Default: 1.8
+ 'RUBY_GC_HEAP_GROWTH_FACTOR' => %w[1.2 1 0.8],
+ # Default: 0 (disabled)
+ 'RUBY_GC_HEAP_GROWTH_MAX_SLOTS' => %w[10000 100000 1000000],
+ # Default: 2.0
+ 'RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR' => %w[2.5 1.5 1],
+ # Default: 4096 (= 2^12)
+ 'RUBY_GC_HEAP_FREE_SLOTS' => %w[16384 2048 0],
+ # Default: 0.20 (20%)
+ 'RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO' => %w[0.1 0.01 0.001],
+ # Default: 0.40 (40%)
+ 'RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO' => %w[0.2 0.01 0.001],
+ # Default: 0.65 (65%)
+ 'RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO' => %w[0.2 0.02 0.002],
+ # Default: 16MB
+ 'RUBY_GC_MALLOC_LIMIT' => %w[8388608 4194304 1048576],
+ # Default: 32MB
+ 'RUBY_GC_MALLOC_LIMIT_MAX' => %w[16777216 8388608 1048576],
+ # Default: 1.4
+ 'RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR' => %w[1.6 1 0.8],
+ # Default: 16MB
+ 'RUBY_GC_OLDMALLOC_LIMIT' => %w[8388608 4194304 1048576],
+ # Default: 128MB
+ 'RUBY_GC_OLDMALLOC_LIMIT_MAX' => %w[33554432 16777216 1048576],
+ # Default: 1.2
+ 'RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR' => %w[1.4 1 0.8]
+}.freeze
+
+USED_GCSTAT_KEYS = [
+ :minor_gc_count,
+ :major_gc_count,
+ :heap_live_slots,
+ :heap_free_slots,
+ :total_allocated_pages,
+ :total_freed_pages,
+ :malloc_increase_bytes,
+ :malloc_increase_bytes_limit,
+ :oldmalloc_increase_bytes,
+ :oldmalloc_increase_bytes_limit
+].freeze
+
+CSV_USED_GCSTAT_KEYS = USED_GCSTAT_KEYS.join(',')
+CSV_HEADER = "setting,value,#{CSV_USED_GCSTAT_KEYS},RSS,gc_time_s,cpu_utime_s,cpu_stime_s,real_time_s\n"
+
+SCRIPT_PATH = __dir__
+RAILS_ROOT = "#{SCRIPT_PATH}/../../../"
+
+def collect_stats(setting, value)
+ warn "Testing #{setting} = #{value} ..."
+ env = {
+ setting => value,
+ 'RAILS_ROOT' => RAILS_ROOT,
+ 'SETTING_CSV' => "#{setting},#{value}",
+ 'GC_STAT_KEYS' => CSV_USED_GCSTAT_KEYS
+ }
+ system(env, 'ruby', "#{SCRIPT_PATH}/print_gc_stats.rb")
+end
+
+par = ENV['PAR']&.to_i || 2
+batch_size = (SETTINGS.size.to_f / par).ceil
+batches = SETTINGS.each_slice(batch_size)
+
+warn "Requested parallelism: #{par} (batches: #{batches.size}, batch size: #{batch_size})"
+
+puts CSV_HEADER
+
+elapsed = Benchmark.realtime do
+ threads = batches.each_with_index.map do |settings_batch, n|
+ Thread.new do
+ settings_batch.each do |setting, values|
+ values.each do |v|
+ collect_stats(setting, v)
+ end
+ end
+ end
+ end
+
+ threads.each(&:join)
+end
+
+warn "All done in #{elapsed} sec"
diff --git a/scripts/perf/gc/print_gc_stats.rb b/scripts/perf/gc/print_gc_stats.rb
new file mode 100755
index 00000000000..4aeb2f1ef07
--- /dev/null
+++ b/scripts/perf/gc/print_gc_stats.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+# Promotes survivors from eden to old gen and runs a compaction.
+#
+# aka "Nakayoshi GC"
+#
+# https://github.com/puma/puma/blob/de632261ac45d7dd85230c83f6af6dd720f1cbd9/lib/puma/util.rb#L26-L35
+def nakayoshi_gc
+ 4.times { GC.start(full_mark: false) }
+ GC.compact
+end
+
+# GC::Profiler is used elsewhere in the code base, so we provide a way for it
+# to be used exclusively by this script, or otherwise results will be tainted.
+module GC::Profiler
+ class << self
+ attr_accessor :use_exclusive
+
+ %i[enable disable clear].each do |method|
+ alias_method "#{method}_orig", "#{method}"
+
+ define_method(method) do
+ if use_exclusive
+ warn "GC::Profiler: ignoring call to #{method}"
+ return
+ end
+
+ send("#{method}_orig") # rubocop: disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+end
+
+GC::Profiler.enable
+GC::Profiler.use_exclusive = true
+
+require 'benchmark'
+
+RAILS_ROOT = ENV['RAILS_ROOT']
+
+tms = Benchmark.measure do
+ require RAILS_ROOT + 'config/boot'
+ require RAILS_ROOT + 'config/environment'
+end
+
+GC::Profiler.use_exclusive = false
+
+nakayoshi_gc
+
+gc_stats = GC.stat
+warn gc_stats.inspect
+
+gc_total_time = GC::Profiler.total_time
+
+GC::Profiler.report($stderr)
+GC::Profiler.disable
+
+gc_stat_keys = ENV['GC_STAT_KEYS'].to_s.split(',').map(&:to_sym)
+
+values = []
+values << ENV['SETTING_CSV']
+values += gc_stat_keys.map { |k| gc_stats[k] }
+values << ::Gitlab::Metrics::System.memory_usage_rss
+values << gc_total_time
+values << tms.utime + tms.cutime
+values << tms.stime + tms.cstime
+values << tms.real
+
+puts values.join(',')
diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb
index e40c6cd7276..bef5b7ad5ee 100755
--- a/scripts/review_apps/automated_cleanup.rb
+++ b/scripts/review_apps/automated_cleanup.rb
@@ -115,6 +115,10 @@ class AutomatedCleanup
delete_helm_releases(releases_to_delete)
end
+ def perform_stale_pvc_cleanup!(days:)
+ kubernetes.cleanup_by_created_at(resource_type: 'pvc', created_before: threshold_time(days: days), wait: false)
+ end
+
private
def fetch_environment(environment)
@@ -155,7 +159,7 @@ class AutomatedCleanup
releases_names = releases.map(&:name)
helm.delete(release_name: releases_names)
- kubernetes.cleanup(release_name: releases_names, wait: false)
+ kubernetes.cleanup_by_release(release_name: releases_names, wait: false)
rescue Tooling::Helm3Client::CommandFailedError => ex
raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
@@ -198,4 +202,8 @@ timed('Helm releases cleanup') do
automated_cleanup.perform_helm_releases_cleanup!(days: 7)
end
+timed('Stale PVC cleanup') do
+ automated_cleanup.perform_stale_pvc_cleanup!(days: 30)
+end
+
exit(0)
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 5b724c9251b..85d7dcec476 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -7,14 +7,14 @@ function retrieve_tests_metadata() {
local test_metadata_job_id
# Ruby
- test_metadata_job_id=$(scripts/api/get_job_id --project "${project_path}" -q "status=success" -q "ref=master" -q "username=gitlab-bot" -Q "scope=success" --job-name "update-tests-metadata")
+ test_metadata_job_id=$(scripts/api/get_job_id.rb --project "${project_path}" -q "status=success" -q "ref=master" -q "username=gitlab-bot" -Q "scope=success" --job-name "update-tests-metadata")
if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then
- scripts/api/download_job_artifact --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
+ scripts/api/download_job_artifact.rb --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
fi
if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
- scripts/api/download_job_artifact --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ scripts/api/download_job_artifact.rb --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
fi
}
@@ -42,10 +42,10 @@ function retrieve_tests_mapping() {
local project_path="gitlab-org/gitlab"
local test_metadata_with_mapping_job_id
- test_metadata_with_mapping_job_id=$(scripts/api/get_job_id --project "${project_path}" -q "status=success" -q "ref=master" -q "username=gitlab-bot" -Q "scope=success" --job-name "update-tests-metadata" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz")
+ test_metadata_with_mapping_job_id=$(scripts/api/get_job_id.rb --project "${project_path}" -q "status=success" -q "ref=master" -q "username=gitlab-bot" -Q "scope=success" --job-name "update-tests-metadata" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz")
if [[ ! -f "${RSPEC_PACKED_TESTS_MAPPING_PATH}" ]]; then
- (scripts/api/download_job_artifact --project "${project_path}" --job-id "${test_metadata_with_mapping_job_id}" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz" && gzip -d "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz") || echo "{}" > "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
+ (scripts/api/download_job_artifact.rb --project "${project_path}" --job-id "${test_metadata_with_mapping_job_id}" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz" && gzip -d "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz") || echo "{}" > "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
fi
scripts/unpack-test-mapping "${RSPEC_PACKED_TESTS_MAPPING_PATH}" "${RSPEC_TESTS_MAPPING_PATH}"
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 6747efa73d7..c598afc4582 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -89,12 +89,12 @@ function echosuccess() {
function fail_pipeline_early() {
local dont_interrupt_me_job_id
- dont_interrupt_me_job_id=$(scripts/api/get_job_id --job-query "scope=success" --job-name "dont-interrupt-me")
+ dont_interrupt_me_job_id=$(scripts/api/get_job_id.rb --job-query "scope=success" --job-name "dont-interrupt-me")
if [[ -n "${dont_interrupt_me_job_id}" ]]; then
echoinfo "This pipeline cannot be interrupted due to \`dont-interrupt-me\` job ${dont_interrupt_me_job_id}"
else
echoinfo "Failing pipeline early for fast feedback due to test failures in rspec fail-fast."
- scripts/api/cancel_pipeline
+ scripts/api/cancel_pipeline.rb
fi
}
diff --git a/scripts/validate_migration_schema b/scripts/validate_migration_schema
new file mode 100755
index 00000000000..95a9ae9f93f
--- /dev/null
+++ b/scripts/validate_migration_schema
@@ -0,0 +1,119 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+require 'open3'
+
+class MigrationSchemaValidator
+ FILENAME = 'db/structure.sql'
+
+ MIGRATION_DIRS = %w[db/migrate db/post_migrate].freeze
+
+ SCHEMA_VERSION_DIR = 'db/schema_migrations'
+
+ VERSION_DIGITS = 14
+
+ def validate!
+ if committed_migrations.empty?
+ puts "\e[32m No migrations found, skipping schema validation\e[0m"
+ return
+ end
+
+ validate_schema_on_rollback!
+ validate_schema_on_migrate!
+ validate_schema_version_files!
+ end
+
+ private
+
+ def validate_schema_on_rollback!
+ committed_migrations.each do |filename|
+ version = find_migration_version(filename)
+
+ run("bin/rails db:migrate:down VERSION=#{version}")
+ end
+
+ git_command = "git diff #{diff_target} -- #{FILENAME}"
+ base_message = "rollback of added migrations does not revert #{FILENAME} to previous state"
+
+ validate_clean_output!(git_command, base_message)
+ end
+
+ def validate_schema_on_migrate!
+ run('bin/rails db:migrate')
+
+ git_command = "git diff -- #{FILENAME}"
+ base_message = "the committed #{FILENAME} does not match the one generated by running added migrations"
+
+ validate_clean_output!(git_command, base_message)
+ end
+
+ def validate_schema_version_files!
+ git_command = "git add -A -n #{SCHEMA_VERSION_DIR}"
+ base_message = "the committed files in #{SCHEMA_VERSION_DIR} do not match those expected by the added migrations"
+
+ validate_clean_output!(git_command, base_message)
+ end
+
+ def committed_migrations
+ @committed_migrations ||= begin
+ git_command = "git diff --name-only --diff-filter=A #{diff_target} -- #{MIGRATION_DIRS.join(' ')}"
+
+ run(git_command).split("\n")
+ end
+ end
+
+ def diff_target
+ @diff_target ||= pipeline_for_merged_results? ? target_branch : merge_base
+ end
+
+ def merge_base
+ run("git merge-base #{target_branch} #{source_ref}")
+ end
+
+ def target_branch
+ ENV['CI_MERGE_REQUEST_TARGET_BRANCH_NAME'] || ENV['TARGET'] || 'master'
+ end
+
+ def source_ref
+ ENV['CI_COMMIT_SHA'] || 'HEAD'
+ end
+
+ def pipeline_for_merged_results?
+ ENV.key?('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA')
+ end
+
+ def find_migration_version(filename)
+ file_basename = File.basename(filename)
+ version_match = /\A(?<version>\d{#{VERSION_DIGITS}})_/.match(file_basename)
+
+ die "#{filename} has an invalid migration version" if version_match.nil?
+
+ version_match[:version]
+ end
+
+ def validate_clean_output!(command, base_message)
+ command_output = run(command)
+
+ return if command_output.empty?
+
+ die "#{base_message}:\n#{command_output}"
+ end
+
+ def die(message, error_code: 1)
+ puts "\e[31mError: #{message}\e[0m"
+ exit error_code
+ end
+
+ def run(cmd)
+ puts "\e[32m$ #{cmd}\e[37m"
+ stdout_str, stderr_str, status = Open3.capture3(cmd)
+ puts "#{stdout_str}#{stderr_str}\e[0m"
+
+ die "command failed: #{stderr_str}" unless status.success?
+
+ stdout_str.chomp
+ end
+end
+
+MigrationSchemaValidator.new.validate!
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index 1c66e19df50..8bf25ea3b5f 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -41,8 +41,8 @@ tests = [
{
explanation: 'Tooling should map to respective spec',
- source: 'tooling/lib/tooling/test_file_finder.rb',
- expected: ['spec/tooling/lib/tooling/test_file_finder_spec.rb']
+ source: 'tooling/lib/tooling/helm3_client.rb',
+ expected: ['spec/tooling/lib/tooling/helm3_client_spec.rb']
},
{
diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb
index 0be30fff0c2..913921b9630 100644
--- a/spec/controllers/admin/dev_ops_report_controller_spec.rb
+++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -3,6 +3,12 @@
require 'spec_helper'
RSpec.describe Admin::DevOpsReportController do
+ describe 'show_adoption?' do
+ it 'is always false' do
+ expect(controller.show_adoption?).to be false
+ end
+ end
+
describe 'GET #show' do
context 'as admin' do
let(:user) { create(:admin) }
diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb
index b5f411c9121..d81b067ffb6 100644
--- a/spec/controllers/admin/projects_controller_spec.rb
+++ b/spec/controllers/admin/projects_controller_spec.rb
@@ -77,4 +77,34 @@ RSpec.describe Admin::ProjectsController do
expect(response.body).to match(project.name)
end
end
+
+ describe 'PUT /projects/transfer/:id' do
+ let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:new_namespace) { create(:namespace) }
+
+ it 'updates namespace' do
+ put :transfer, params: { namespace_id: project.namespace.path, new_namespace_id: new_namespace.id, id: project.path }
+
+ project.reload
+
+ expect(project.namespace).to eq(new_namespace)
+ expect(response).to have_gitlab_http_status(:redirect)
+ expect(response).to redirect_to(admin_project_path(project))
+ end
+
+ context 'when project transfer fails' do
+ it 'flashes error' do
+ old_namespace = project.namespace
+
+ put :transfer, params: { namespace_id: old_namespace.path, new_namespace_id: nil, id: project.path }
+
+ project.reload
+
+ expect(project.namespace).to eq(old_namespace)
+ expect(response).to have_gitlab_http_status(:redirect)
+ expect(response).to redirect_to(admin_project_path(project))
+ expect(flash[:alert]).to eq s_('TransferProject|Please select a new namespace for your project.')
+ end
+ end
+ end
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 9342513d224..4a729008e67 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -720,6 +720,49 @@ RSpec.describe ApplicationController do
end
end
+ describe '#stream_csv_headers' do
+ controller(described_class) do
+ def index
+ respond_to do |format|
+ format.csv do
+ stream_csv_headers('test.csv')
+
+ self.response_body = fixture_file_upload('spec/fixtures/csv_comma.csv')
+ end
+ end
+ end
+ end
+
+ subject { get :index, format: :csv }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'sets no-cache headers', :aggregate_failures do
+ subject
+
+ expect(response.headers['Cache-Control']).to eq 'no-cache, no-store'
+ expect(response.headers['Pragma']).to eq 'no-cache'
+ expect(response.headers['Expires']).to eq 'Fri, 01 Jan 1990 00:00:00 GMT'
+ end
+
+ it 'sets stream headers', :aggregate_failures do
+ subject
+
+ expect(response.headers['Content-Length']).to be nil
+ expect(response.headers['X-Accel-Buffering']).to eq 'no'
+ expect(response.headers['Last-Modified']).to eq '0'
+ end
+
+ it 'sets the csv specific headers', :aggregate_failures do
+ subject
+
+ expect(response.headers['Content-Type']).to eq 'text/csv; charset=utf-8; header=present'
+ expect(response.headers['Content-Disposition']).to eq "attachment; filename=\"test.csv\""
+ end
+ end
+
context 'Gitlab::Session' do
controller(described_class) do
prepend_before_action do
diff --git a/spec/controllers/concerns/redis_tracking_spec.rb b/spec/controllers/concerns/redis_tracking_spec.rb
index 831f5ad7bb1..ef59adf8c1d 100644
--- a/spec/controllers/concerns/redis_tracking_spec.rb
+++ b/spec/controllers/concerns/redis_tracking_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe RedisTracking do
def expect_tracking
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
- .with(instance_of(String), 'g_compliance_approval_rules')
+ .with('g_compliance_approval_rules', values: instance_of(String))
end
def expect_no_tracking
diff --git a/spec/controllers/concerns/spammable_actions_spec.rb b/spec/controllers/concerns/spammable_actions_spec.rb
new file mode 100644
index 00000000000..3b5b4d11a9b
--- /dev/null
+++ b/spec/controllers/concerns/spammable_actions_spec.rb
@@ -0,0 +1,198 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+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
+ def update
+ should_redirect = params[:should_redirect] == 'true'
+
+ recaptcha_check_with_fallback(should_redirect) { render json: :ok }
+ end
+
+ private
+
+ def spammable_path
+ '/fake_spammable_path'
+ end
+ 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
+ end
+
+ describe '#recaptcha_check_with_fallback' do
+ shared_examples 'yields to block' do
+ it do
+ subject
+
+ expect(json_response).to eq({ json: 'ok' })
+ end
+ end
+
+ let(:format) { :html }
+
+ subject { post :update, format: format, params: params }
+
+ let(:spammable) { double(:spammable) }
+ let(:should_redirect) { nil }
+ let(:params) do
+ {
+ should_redirect: should_redirect
+ }
+ end
+
+ before do
+ routes.draw { get 'update' => 'anonymous#update' }
+ allow(controller).to receive(:spammable) { spammable }
+ end
+
+ context 'when should_redirect is true and spammable is valid' do
+ let(:should_redirect) { true }
+
+ before do
+ allow(spammable).to receive(:valid?) { true }
+ end
+
+ it 'redirects to spammable_path' do
+ expect(subject).to redirect_to('/fake_spammable_path')
+ end
+ end
+
+ context 'when should_redirect is false or spammable is not valid' do
+ before 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
+ before do
+ expect(controller).to receive(:render_recaptcha?) { true }
+ end
+
+ context 'when format is :html' do
+ it 'renders :verify' do
+ expect(controller).to receive(:render).with(:verify)
+
+ subject
+ end
+ end
+
+ context 'when format is :json' do
+ let(:format) { :json }
+ let(:recaptcha_html) { '<recaptcha-html/>' }
+
+ it 'renders json with recaptcha_html' do
+ expect(controller).to receive(:render_to_string).with(
+ {
+ partial: 'shared/recaptcha_form',
+ formats: :html,
+ locals: {
+ spammable: spammable,
+ script: false,
+ has_submit: false
+ }
+ }
+ ) { recaptcha_html }
+
+ subject
+
+ expect(json_response).to eq({ 'recaptcha_html' => recaptcha_html })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb
index 2719b7c8a24..dcec8012f03 100644
--- a/spec/controllers/dashboard/projects_controller_spec.rb
+++ b/spec/controllers/dashboard/projects_controller_spec.rb
@@ -13,8 +13,8 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
end
context 'user logged in' do
- let_it_be(:project) { create(:project) }
- let_it_be(:project2) { create(:project) }
+ let_it_be(:project) { create(:project, name: 'Project 1') }
+ let_it_be(:project2) { create(:project, name: 'Project Two') }
let(:projects) { [project, project2] }
before_all do
@@ -36,10 +36,7 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
end
end
- it 'orders the projects by last activity by default' do
- project.update!(last_repository_updated_at: 3.days.ago, last_activity_at: 3.days.ago)
- project2.update!(last_repository_updated_at: 10.days.ago, last_activity_at: 10.days.ago)
-
+ it 'orders the projects by name by default' do
get :index
expect(assigns(:projects)).to eq(projects)
diff --git a/spec/controllers/dashboard/snippets_controller_spec.rb b/spec/controllers/dashboard/snippets_controller_spec.rb
index d981f738e70..016a9f53129 100644
--- a/spec/controllers/dashboard/snippets_controller_spec.rb
+++ b/spec/controllers/dashboard/snippets_controller_spec.rb
@@ -28,5 +28,24 @@ RSpec.describe Dashboard::SnippetsController do
end
it_behaves_like 'snippets sort order'
+
+ context 'when views are rendered' do
+ render_views
+
+ it 'avoids N+1 database queries' do
+ # Warming call to load everything non snippet related
+ get(:index)
+
+ project = create(:project, namespace: user.namespace)
+ create(:project_snippet, project: project, author: user)
+
+ control_count = ActiveRecord::QueryRecorder.new { get(:index) }.count
+
+ project = create(:project, namespace: user.namespace)
+ create(:project_snippet, project: project, author: user)
+
+ expect { get(:index) }.not_to exceed_query_limit(control_count)
+ end
+ end
end
end
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
index 4ec890a528f..cfbd129388d 100644
--- a/spec/controllers/explore/projects_controller_spec.rb
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe Explore::ProjectsController do
end
shared_examples "blocks high page numbers" do
- let(:page_limit) { 200 }
+ let(:page_limit) { described_class::PAGE_LIMIT }
context "page number is too high" do
[:index, :trending, :starred].each do |endpoint|
diff --git a/spec/controllers/groups/labels_controller_spec.rb b/spec/controllers/groups/labels_controller_spec.rb
index 33041f1af9f..b2320615778 100644
--- a/spec/controllers/groups/labels_controller_spec.rb
+++ b/spec/controllers/groups/labels_controller_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe Groups::LabelsController do
before do
group.add_owner(user)
- # by default FFs are enabled in specs so we turn it off
- stub_feature_flags(show_inherited_labels: false)
sign_in(user)
end
@@ -34,41 +32,12 @@ RSpec.describe Groups::LabelsController do
subgroup.add_owner(user)
end
- RSpec.shared_examples 'returns ancestor group labels' do
- it 'returns ancestor group labels' do
- get :index, params: params, format: :json
+ it 'returns ancestor group labels' do
+ params = { group_id: subgroup, only_group_labels: true }
+ get :index, params: params, format: :json
- label_ids = json_response.map {|label| label['title']}
- expect(label_ids).to match_array([group_label_1.title, subgroup_label_1.title])
- end
- end
-
- context 'when include_ancestor_groups true' do
- let(:params) { { group_id: subgroup, include_ancestor_groups: true, only_group_labels: true } }
-
- it_behaves_like 'returns ancestor group labels'
- end
-
- context 'when include_ancestor_groups false' do
- let(:params) { { group_id: subgroup, only_group_labels: true } }
-
- it 'does not return ancestor group labels', :aggregate_failures do
- get :index, params: params, format: :json
-
- label_ids = json_response.map {|label| label['title']}
- expect(label_ids).to match_array([subgroup_label_1.title])
- expect(label_ids).not_to include([group_label_1.title])
- end
- end
-
- context 'when show_inherited_labels enabled' do
- let(:params) { { group_id: subgroup } }
-
- before do
- stub_feature_flags(show_inherited_labels: true)
- end
-
- it_behaves_like 'returns ancestor group labels'
+ label_ids = json_response.map {|label| label['title']}
+ expect(label_ids).to match_array([group_label_1.title, subgroup_label_1.title])
end
end
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index 436daed0af6..d1c138617bb 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -63,9 +63,16 @@ RSpec.describe Import::BulkImportsController do
)
end
+ let(:client_params) do
+ {
+ top_level_only: true,
+ min_access_level: Gitlab::Access::MAINTAINER
+ }
+ end
+
before do
allow(controller).to receive(:client).and_return(client)
- allow(client).to receive(:get).with('groups', top_level_only: true).and_return(client_response)
+ allow(client).to receive(:get).with('groups', client_params).and_return(client_response)
end
it 'returns serialized group data' do
@@ -73,6 +80,17 @@ RSpec.describe Import::BulkImportsController do
expect(json_response).to eq({ importable_data: client_response.parsed_response }.as_json)
end
+
+ context 'when filtering' do
+ it 'returns filtered result' do
+ filter = 'test'
+ search_params = client_params.merge(search: filter)
+
+ expect(client).to receive(:get).with('groups', search_params).and_return(client_response)
+
+ get :status, format: :json, params: { filter: filter }
+ end
+ end
end
context 'when host url is local or not http' do
@@ -131,6 +149,22 @@ RSpec.describe Import::BulkImportsController do
end
end
+ describe 'GET realtime_changes' do
+ let_it_be(:bulk_import) { create(:bulk_import, :created, user: user) }
+
+ it 'returns bulk imports created by current user' do
+ get :realtime_changes
+
+ expect(json_response).to eq([{ 'id' => bulk_import.id, 'status_name' => bulk_import.status_name.to_s }])
+ end
+
+ it 'sets a Poll-Interval header' do
+ get :realtime_changes
+
+ expect(response.headers['Poll-Interval']).to eq(Import::BulkImportsController::POLLING_INTERVAL.to_s)
+ end
+ end
+
describe 'POST create' do
let(:instance_url) { "http://fake-intance" }
let(:pat) { "fake-pat" }
diff --git a/spec/controllers/jwks_controller_spec.rb b/spec/controllers/jwks_controller_spec.rb
deleted file mode 100644
index 013ec01eba2..00000000000
--- a/spec/controllers/jwks_controller_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JwksController do
- describe 'GET #index' do
- let(:ci_jwt_signing_key) { OpenSSL::PKey::RSA.generate(1024) }
- let(:ci_jwk) { ci_jwt_signing_key.to_jwk }
- let(:oidc_jwk) { OpenSSL::PKey::RSA.new(Rails.application.secrets.openid_connect_signing_key).to_jwk }
-
- before do
- stub_application_setting(ci_jwt_signing_key: ci_jwt_signing_key.to_s)
- end
-
- it 'returns signing keys used to sign CI_JOB_JWT' do
- get :index
-
- expect(response).to have_gitlab_http_status(:ok)
-
- ids = json_response['keys'].map { |jwk| jwk['kid'] }
- expect(ids).to contain_exactly(ci_jwk['kid'], oidc_jwk['kid'])
- end
-
- it 'does not leak private key data' do
- get :index
-
- aggregate_failures do
- json_response['keys'].each do |jwk|
- expect(jwk.keys).to contain_exactly('kty', 'kid', 'e', 'n', 'use', 'alg')
- expect(jwk['use']).to eq('sig')
- expect(jwk['alg']).to eq('RS256')
- end
- end
- end
- end
-end
diff --git a/spec/controllers/metrics_controller_spec.rb b/spec/controllers/metrics_controller_spec.rb
index f350d7378dc..9fa90dde997 100644
--- a/spec/controllers/metrics_controller_spec.rb
+++ b/spec/controllers/metrics_controller_spec.rb
@@ -28,8 +28,38 @@ RSpec.describe MetricsController, :request_store do
end
end
+ shared_examples_for 'protected metrics endpoint' do |examples|
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like examples
+ end
+
+ context 'accessed from ip in whitelisted range' do
+ before do
+ allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(ip_in_whitelisted_range)
+ end
+
+ it_behaves_like examples
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
+ it 'returns the expected error response' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
describe '#index' do
- shared_examples_for 'endpoint providing metrics' do
+ shared_examples_for 'providing metrics' do
it 'returns prometheus metrics' do
get :index
@@ -51,32 +81,35 @@ RSpec.describe MetricsController, :request_store do
end
end
- context 'accessed from whitelisted ip' do
- before do
- allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(whitelisted_ip)
- end
-
- it_behaves_like 'endpoint providing metrics'
- end
+ include_examples 'protected metrics endpoint', 'providing metrics'
+ end
- context 'accessed from ip in whitelisted range' do
- before do
- allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(ip_in_whitelisted_range)
+ describe '#system' do
+ shared_examples_for 'providing system stats' do
+ let(:summary) do
+ {
+ version: 'ruby-3.0-patch1',
+ memory_rss: 1024
+ }
end
- it_behaves_like 'endpoint providing metrics'
- end
+ it 'renders system stats JSON' do
+ expect(Prometheus::PidProvider).to receive(:worker_id).and_return('worker-0')
+ expect(Gitlab::Metrics::System).to receive(:summary).and_return(summary)
- context 'accessed from not whitelisted ip' do
- before do
- allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(not_whitelisted_ip)
- end
-
- it 'returns the expected error response' do
- get :index
+ get :system
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_json['version']).to eq('ruby-3.0-patch1')
+ expect(response_json['worker_id']).to eq('worker-0')
+ expect(response_json['memory_rss']).to eq(1024)
end
end
+
+ include_examples 'protected metrics endpoint', 'providing system stats'
+ end
+
+ def response_json
+ Gitlab::Json.parse(response.body)
end
end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index a56425c2a22..16be7394174 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -7,6 +7,82 @@ RSpec.describe Projects::BlobController do
let(:project) { create(:project, :public, :repository) }
+ describe "GET new" do
+ context 'with no jobs' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:file_name) { '.gitlab-ci.yml' }
+
+ def request
+ get(:new, params: { namespace_id: project.namespace, project_id: project, id: 'master', file_name: file_name } )
+ end
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+
+ stub_experiment(ci_syntax_templates: experiment_active)
+ stub_experiment_for_subject(ci_syntax_templates: in_experiment_group)
+ end
+
+ context 'when the experiment is not active' do
+ let(:experiment_active) { false }
+ let(:in_experiment_group) { false }
+
+ it 'does not record the experiment user' do
+ expect(Experiment).not_to receive(:add_user)
+
+ request
+ end
+ end
+
+ context 'when the experiment is active and the user is in the control group' do
+ let(:experiment_active) { true }
+ let(:in_experiment_group) { false }
+
+ it 'records the experiment user in the control group' do
+ expect(Experiment).to receive(:add_user)
+ .with(:ci_syntax_templates, :control, user, namespace_id: project.namespace_id)
+
+ request
+ end
+ end
+
+ context 'when the experiment is active and the user is in the experimental group' do
+ let(:experiment_active) { true }
+ let(:in_experiment_group) { true }
+
+ it 'records the experiment user in the experimental group' do
+ expect(Experiment).to receive(:add_user)
+ .with(:ci_syntax_templates, :experimental, user, namespace_id: project.namespace_id)
+
+ request
+ end
+
+ context 'when requesting a non default config file type' do
+ let(:file_name) { '.non_default_ci_config' }
+ let(:project) { create(:project, :public, :repository, ci_config_path: file_name) }
+
+ it 'records the experiment user in the experimental group' do
+ expect(Experiment).to receive(:add_user)
+ .with(:ci_syntax_templates, :experimental, user, namespace_id: project.namespace_id)
+
+ request
+ end
+ end
+
+ context 'when requesting a different file type' do
+ let(:file_name) { '.gitignore' }
+
+ it 'does not record the experiment user' do
+ expect(Experiment).not_to receive(:add_user)
+
+ request
+ end
+ end
+ end
+ end
+ end
+
describe "GET show" do
def request
get(:show, params: { namespace_id: project.namespace, project_id: project, id: id })
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index d1142cbd129..83ad36b217f 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::EnvironmentsController do
include MetricsDashboardHelpers
+ include KubernetesHelpers
let_it_be(:project) { create(:project) }
let_it_be(:maintainer) { create(:user, name: 'main-dos').tap { |u| project.add_maintainer(u) } }
@@ -34,6 +35,9 @@ RSpec.describe Projects::EnvironmentsController do
context 'when requesting JSON response for folders' do
before do
+ allow_any_instance_of(Environment).to receive(:has_terminals?).and_return(true)
+ allow_any_instance_of(Environment).to receive(:rollout_status).and_return(kube_deployment_rollout_status)
+
create(:environment, project: project,
name: 'staging/review-1',
state: :available)
@@ -91,9 +95,11 @@ RSpec.describe Projects::EnvironmentsController do
it 'responds with a payload describing available environments' do
expect(environments.count).to eq 2
expect(environments.first['name']).to eq 'production'
+ expect(environments.first['latest']['rollout_status']).to be_present
expect(environments.second['name']).to eq 'staging'
expect(environments.second['size']).to eq 2
expect(environments.second['latest']['name']).to eq 'staging/review-2'
+ expect(environments.second['latest']['rollout_status']).to be_present
end
it 'contains values describing environment scopes sizes' do
diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb
index d5fc80bd5a7..f69cc0ddfd8 100644
--- a/spec/controllers/projects/feature_flags_controller_spec.rb
+++ b/spec/controllers/projects/feature_flags_controller_spec.rb
@@ -845,413 +845,64 @@ RSpec.describe Projects::FeatureFlagsController do
put(:update, params: params, format: :json, as: :json)
end
- before do
- stub_feature_flags(
- feature_flags_legacy_read_only: false,
- feature_flags_legacy_read_only_override: false
- )
- end
-
- subject { put(:update, params: params, format: :json) }
-
- let!(:feature_flag) do
- create(:operations_feature_flag,
- :legacy_flag,
- name: 'ci_live_trace',
- active: true,
- project: project)
- end
-
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- name: 'ci_new_live_trace'
- }
- }
- end
-
- it 'returns 200' do
- is_expected.to have_gitlab_http_status(:ok)
- end
-
- it 'updates the name of the feature flag name' do
- subject
-
- expect(json_response['name']).to eq('ci_new_live_trace')
- end
-
- it 'matches json schema' do
- is_expected.to match_response_schema('feature_flag')
- end
-
- context 'when updates active' do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- active: false
- }
- }
- end
-
- it 'updates active from true to false' do
- expect { subject }
- .to change { feature_flag.reload.active }.from(true).to(false)
- end
-
- it "does not change default scope's active" do
- expect { subject }
- .not_to change { feature_flag.default_scope.reload.active }.from(true)
- end
-
- it 'updates active from false to true when an inactive feature flag has an active scope' do
- feature_flag = create(:operations_feature_flag, project: project, name: 'my_flag', active: false)
- create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production', active: true)
-
- put_request(feature_flag, { active: true })
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('feature_flag')
- expect(json_response['active']).to eq(true)
- expect(feature_flag.reload.active).to eq(true)
- expect(feature_flag.default_scope.reload.active).to eq(false)
- end
- end
-
- context 'when user is reporter' do
- let(:user) { reporter }
-
- it 'returns 404' do
- is_expected.to have_gitlab_http_status(:not_found)
- end
- end
-
- context "when creates an additional scope for production environment" do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- scopes_attributes: [{ environment_scope: 'production', active: false }]
- }
- }
- end
-
- it 'creates a production scope' do
- expect { subject }.to change { feature_flag.reload.scopes.count }.by(1)
-
- expect(json_response['scopes'].last['environment_scope']).to eq('production')
- expect(json_response['scopes'].last['active']).to be_falsy
- end
- end
-
- context "when creates a default scope" do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- scopes_attributes: [{ environment_scope: '*', active: false }]
- }
- }
- end
-
- it 'returns 400' do
- is_expected.to have_gitlab_http_status(:bad_request)
- end
- end
-
- context "when updates a default scope's active value" do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- scopes_attributes: [
- {
- id: feature_flag.default_scope.id,
- environment_scope: '*',
- active: false
- }
- ]
- }
- }
- end
-
- it "updates successfully" do
- subject
-
- expect(json_response['scopes'].first['environment_scope']).to eq('*')
- expect(json_response['scopes'].first['active']).to be_falsy
- end
- end
-
- context "when changes default scope's spec" do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- scopes_attributes: [
- {
- id: feature_flag.default_scope.id,
- environment_scope: 'review/*'
- }
- ]
- }
- }
- end
-
- it 'returns 400' do
- is_expected.to have_gitlab_http_status(:bad_request)
- end
- end
+ context 'with a legacy feature flag' do
+ subject { put(:update, params: params, format: :json) }
- context "when destroys the default scope" do
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- iid: feature_flag.iid,
- operations_feature_flag: {
- scopes_attributes: [
- {
- id: feature_flag.default_scope.id,
- _destroy: 1
- }
- ]
- }
- }
- end
-
- it 'raises an error' do
- expect { subject }.to raise_error(ActiveRecord::ReadOnlyRecord)
+ let!(:feature_flag) do
+ create(:operations_feature_flag,
+ :legacy_flag,
+ name: 'ci_live_trace',
+ active: true,
+ project: project)
end
- end
- context "when destroys a production scope" do
- let!(:production_scope) { create_scope(feature_flag, 'production', true) }
let(:params) do
{
namespace_id: project.namespace,
project_id: project,
iid: feature_flag.iid,
operations_feature_flag: {
- scopes_attributes: [
- {
- id: production_scope.id,
- _destroy: 1
- }
- ]
+ name: 'ci_new_live_trace'
}
}
end
- it 'destroys successfully' do
- subject
-
- scopes = json_response['scopes']
- expect(scopes.any? { |scope| scope['environment_scope'] == 'production' })
- .to be_falsy
- end
- end
-
- describe "updating the strategy" do
- it 'creates a default strategy' do
- scope = create_scope(feature_flag, 'production', true, [])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: [{ name: 'default', parameters: {} }]
- }])
+ context 'when user is reporter' do
+ let(:user) { reporter }
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
+ it 'returns 404' do
+ is_expected.to have_gitlab_http_status(:not_found)
end
- expect(scope_json['strategies']).to eq([{
- "name" => "default",
- "parameters" => {}
- }])
end
- it 'creates a gradualRolloutUserId strategy' do
- scope = create_scope(feature_flag, 'production', true, [])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: [{ name: 'gradualRolloutUserId',
- parameters: { groupId: 'default', percentage: "70" } }]
- }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
- end
- expect(scope_json['strategies']).to eq([{
- "name" => "gradualRolloutUserId",
- "parameters" => {
- "groupId" => "default",
- "percentage" => "70"
- }
- }])
- end
-
- it 'creates a userWithId strategy' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'default', parameters: {} }])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: [{ name: 'userWithId', parameters: { userIds: 'sam,fred' } }]
- }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
- end
- expect(scope_json['strategies']).to eq([{
- "name" => "userWithId",
- "parameters" => { "userIds" => "sam,fred" }
- }])
- end
-
- it 'updates an existing strategy' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'default', parameters: {} }])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: [{ name: 'gradualRolloutUserId',
- parameters: { groupId: 'default', percentage: "50" } }]
- }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
- end
- expect(scope_json['strategies']).to eq([{
- "name" => "gradualRolloutUserId",
- "parameters" => {
- "groupId" => "default",
- "percentage" => "50"
+ context "when changing default scope's spec" do
+ let(:params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ iid: feature_flag.iid,
+ operations_feature_flag: {
+ scopes_attributes: [
+ {
+ id: feature_flag.default_scope.id,
+ environment_scope: 'review/*'
+ }
+ ]
+ }
}
- }])
- end
-
- it 'clears an existing strategy' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'default', parameters: {} }])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: []
- }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
- end
- expect(scope_json['strategies']).to eq([])
- end
-
- it 'accepts multiple strategies' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'default', parameters: {} }])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: [
- { name: 'gradualRolloutUserId', parameters: { groupId: 'mygroup', percentage: '55' } },
- { name: 'userWithId', parameters: { userIds: 'joe' } }
- ]
- }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
- end
- expect(scope_json['strategies'].length).to eq(2)
- expect(scope_json['strategies']).to include({
- "name" => "gradualRolloutUserId",
- "parameters" => { "groupId" => "mygroup", "percentage" => "55" }
- })
- expect(scope_json['strategies']).to include({
- "name" => "userWithId",
- "parameters" => { "userIds" => "joe" }
- })
- end
-
- it 'does not modify strategies when there is no strategies key in the params' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'default', parameters: {} }])
-
- put_request(feature_flag, scopes_attributes: [{ id: scope.id }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
end
- expect(scope_json['strategies']).to eq([{
- "name" => "default",
- "parameters" => {}
- }])
- end
-
- it 'leaves an existing strategy when there are no strategies in the params' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'gradualRolloutUserId',
- parameters: { groupId: 'default', percentage: '10' } }])
- put_request(feature_flag, scopes_attributes: [{ id: scope.id }])
-
- expect(response).to have_gitlab_http_status(:ok)
- scope_json = json_response['scopes'].find do |s|
- s['environment_scope'] == 'production'
+ it 'returns 400' do
+ is_expected.to have_gitlab_http_status(:bad_request)
end
- expect(scope_json['strategies']).to eq([{
- "name" => "gradualRolloutUserId",
- "parameters" => { "groupId" => "default", "percentage" => "10" }
- }])
end
- it 'does not accept extra parameters in the strategy params' do
- scope = create_scope(feature_flag, 'production', true, [{ name: 'default', parameters: {} }])
-
- put_request(feature_flag, scopes_attributes: [{
- id: scope.id,
- strategies: [{ name: 'userWithId', parameters: { userIds: 'joe', groupId: 'default' } }]
- }])
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to eq(["Scopes strategies parameters are invalid"])
- end
- end
-
- context 'when legacy feature flags are set to be read only' do
- it 'does not update the flag' do
- stub_feature_flags(feature_flags_legacy_read_only: true)
-
+ it 'does not update a legacy feature flag' do
put_request(feature_flag, name: 'ci_new_live_trace')
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(["Legacy feature flags are read-only"])
end
-
- it 'updates the flag if the legacy read-only override is enabled for a particular project' do
- stub_feature_flags(
- feature_flags_legacy_read_only: true,
- feature_flags_legacy_read_only_override: project
- )
-
- put_request(feature_flag, name: 'ci_new_live_trace')
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('ci_new_live_trace')
- end
end
context 'with a version 2 feature flag' do
@@ -1517,15 +1168,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['strategies'].first['scopes']).to eq([])
end
-
- it 'updates the flag when legacy feature flags are set to be read only' do
- stub_feature_flags(feature_flags_legacy_read_only: true)
-
- put_request(new_version_flag, name: 'some-other-name')
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(new_version_flag.reload.name).to eq('some-other-name')
- end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 12c8c84dd77..d3bdf1baaae 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -227,6 +227,22 @@ RSpec.describe Projects::IssuesController do
end
end
+ describe "GET #show" do
+ before do
+ sign_in(user)
+ project.add_developer(user)
+ end
+
+ it "returns issue_email_participants" do
+ participants = create_list(:issue_email_participant, 2, issue: issue)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['issue_email_participants']).to contain_exactly({ "email" => participants[0].email }, { "email" => participants[1].email })
+ end
+ end
+
describe 'GET #new' do
it 'redirects to signin if not logged in' do
get :new, params: { namespace_id: project.namespace, project_id: project }
@@ -1003,7 +1019,7 @@ RSpec.describe Projects::IssuesController do
def update_verified_issue
update_issue(
issue_params: { title: spammy_title },
- additional_params: { spam_log_id: spam_logs.last.id, recaptcha_verification: true })
+ additional_params: { spam_log_id: spam_logs.last.id, 'g-recaptcha-response': true })
end
it 'returns 200 status' do
@@ -1021,7 +1037,7 @@ RSpec.describe Projects::IssuesController do
it 'does not mark spam log as recaptcha_verified when it does not belong to current_user' do
spam_log = create(:spam_log)
- expect { update_issue(issue_params: { spam_log_id: spam_log.id, recaptcha_verification: true }) }
+ expect { update_issue(issue_params: { spam_log_id: spam_log.id, 'g-recaptcha-response': true }) }
.not_to change { SpamLog.last.recaptcha_verified }
end
end
@@ -1298,7 +1314,7 @@ 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, recaptcha_verification: true } )
+ post_new_issue({}, { spam_log_id: last_spam_log.id, 'g-recaptcha-response': true } )
end
before do
@@ -1316,7 +1332,7 @@ RSpec.describe Projects::IssuesController do
it 'does not mark spam log as recaptcha_verified when it does not belong to current_user' do
spam_log = create(:spam_log)
- expect { post_new_issue({}, { spam_log_id: spam_log.id, recaptcha_verification: true } ) }
+ expect { post_new_issue({}, { spam_log_id: spam_log.id, 'g-recaptcha-response': true } ) }
.not_to change { last_spam_log.recaptcha_verified }
end
end
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index eb5e62f3d44..430808e1c63 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -675,16 +675,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:forbidden)
end
-
- context 'with restrict_access_to_build_debug_mode feature disabled' do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- end
-
- it 'returns response forbidden' do
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
end
end
end
@@ -1139,18 +1129,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:ok)
end
-
- context 'with restrict_access_to_build_debug_mode feature disabled' do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- end
-
- it 'returns response ok' do
- response = subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
end
context 'without proper permissions for debug logging on a project' do
@@ -1164,18 +1142,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:forbidden)
end
-
- context 'with restrict_access_to_build_debug_mode feature disabled' do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- end
-
- it 'returns response ok' do
- response = subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
end
end
end
diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb
index 8a3c55033cb..f452c22a5ca 100644
--- a/spec/controllers/projects/labels_controller_spec.rb
+++ b/spec/controllers/projects/labels_controller_spec.rb
@@ -84,46 +84,12 @@ RSpec.describe Projects::LabelsController do
create(:label_priority, project: project, label: subgroup_label_2, priority: 1)
end
- RSpec.shared_examples 'returns ancestor group labels' do
- it 'returns ancestor group labels', :aggregate_failures do
- get :index, params: params
+ it 'returns ancestor group labels', :aggregate_failures do
+ params = { namespace_id: project.namespace.to_param, project_id: project }
+ get :index, params: params
- expect(assigns(:labels)).to match_array([subgroup_label_1] + group_labels + project_labels)
- expect(assigns(:prioritized_labels)).to match_array([subgroup_label_2] + group_priority_labels + project_priority_labels)
- end
- end
-
- context 'when show_inherited_labels disabled' do
- before do
- stub_feature_flags(show_inherited_labels: false)
- end
-
- context 'when include_ancestor_groups false' do
- let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
-
- it 'does not return ancestor group labels', :aggregate_failures do
- get :index, params: params
-
- expect(assigns(:labels)).to match_array([subgroup_label_1] + project_labels)
- expect(assigns(:prioritized_labels)).to match_array([subgroup_label_2] + project_priority_labels)
- end
- end
-
- context 'when include_ancestor_groups true' do
- let(:params) { { namespace_id: project.namespace.to_param, project_id: project, include_ancestor_groups: true } }
-
- it_behaves_like 'returns ancestor group labels'
- end
- end
-
- context 'when show_inherited_labels enabled' do
- let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
-
- before do
- stub_feature_flags(show_inherited_labels: true)
- end
-
- it_behaves_like 'returns ancestor group labels'
+ expect(assigns(:labels)).to match_array([subgroup_label_1] + group_labels + project_labels)
+ expect(assigns(:prioritized_labels)).to match_array([subgroup_label_2] + group_priority_labels + project_priority_labels)
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 f4f0a9f8108..f54a07de853 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -193,6 +193,29 @@ RSpec.describe Projects::MergeRequests::DiffsController do
end
end
+ context "with the :default_merge_ref_for_diffs flag on" do
+ let(:diffable_merge_ref) { true }
+
+ subject do
+ go(diff_head: true,
+ diff_id: merge_request.merge_request_diff.id,
+ start_sha: merge_request.merge_request_diff.start_commit_sha)
+ end
+
+ it "correctly generates the right diff between versions" do
+ MergeRequests::MergeToRefService.new(project, merge_request.author).execute(merge_request)
+
+ expect_next_instance_of(CompareService) do |service|
+ expect(service).to receive(:execute).with(
+ project,
+ merge_request.merge_request_diff.head_commit_sha,
+ straight: true)
+ end
+
+ subject
+ end
+ end
+
context 'with diff_head param passed' do
before do
allow(merge_request).to receive(:diffable_merge_ref?)
@@ -378,6 +401,57 @@ RSpec.describe Projects::MergeRequests::DiffsController do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it 'tracks mr_diffs event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_mr_diffs_action)
+ .with(merge_request: merge_request)
+
+ subject
+ end
+
+ context 'when DNT is enabled' do
+ before do
+ request.headers['DNT'] = '1'
+ end
+
+ it 'does not track any mr_diffs event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_mr_diffs_action)
+
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_mr_diffs_single_file_action)
+
+ subject
+ end
+ end
+
+ context 'when user has view_diffs_file_by_file set to false' do
+ before do
+ user.update!(view_diffs_file_by_file: false)
+ end
+
+ it 'does not track single_file_diffs events' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_mr_diffs_single_file_action)
+
+ subject
+ end
+ end
+
+ context 'when user has view_diffs_file_by_file set to true' do
+ before do
+ user.update!(view_diffs_file_by_file: true)
+ end
+
+ it 'tracks single_file_diffs events' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_mr_diffs_single_file_action)
+ .with(merge_request: merge_request, user: user)
+
+ subject
+ end
+ end
end
def collection_arguments(pagination_data = {})
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index e1405660ccb..be4a1504fc9 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -272,6 +272,72 @@ 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 74311fa89f3..971eb782fa4 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -14,32 +14,137 @@ RSpec.describe Projects::ProjectMembersController do
expect(response).to have_gitlab_http_status(:ok)
end
- context 'when project belongs to group' do
- let(:user_in_group) { create(:user) }
- let(:project_in_group) { create(:project, :public, group: group) }
+ context 'project members' do
+ context 'when project belongs to group' do
+ let(:user_in_group) { create(:user) }
+ let(:project_in_group) { create(:project, :public, group: group) }
+
+ before do
+ group.add_owner(user_in_group)
+ project_in_group.add_maintainer(user)
+ sign_in(user)
+ end
+
+ it 'lists inherited project members by default' do
+ get :index, params: { namespace_id: project_in_group.namespace, project_id: project_in_group }
+
+ expect(assigns(:project_members).map(&:user_id)).to contain_exactly(user.id, user_in_group.id)
+ end
+
+ it 'lists direct project members only' do
+ get :index, params: { namespace_id: project_in_group.namespace, project_id: project_in_group, with_inherited_permissions: 'exclude' }
+
+ expect(assigns(:project_members).map(&:user_id)).to contain_exactly(user.id)
+ end
+
+ it 'lists inherited project members only' do
+ get :index, params: { namespace_id: project_in_group.namespace, project_id: project_in_group, with_inherited_permissions: 'only' }
+
+ expect(assigns(:project_members).map(&:user_id)).to contain_exactly(user_in_group.id)
+ end
+ end
+
+ context 'when invited members are present' do
+ let!(:invited_member) { create(:project_member, :invited, project: project) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ it 'excludes the invited members from project members list' do
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(assigns(:project_members).map(&:invite_email)).not_to contain_exactly(invited_member.invite_email)
+ end
+ end
+ end
+
+ context 'group links' do
+ let!(:project_group_link) { create(:project_group_link, project: project, group: group) }
+
+ it 'lists group links' do
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(assigns(:group_links).map(&:id)).to contain_exactly(project_group_link.id)
+ end
+
+ context 'when `search_groups` param is present' do
+ let(:group_2) { create(:group, :public, name: 'group_2') }
+ let!(:project_group_link_2) { create(:project_group_link, project: project, group: group_2) }
+
+ it 'lists group links that match search' do
+ get :index, params: { namespace_id: project.namespace, project_id: project, search_groups: 'group_2' }
+
+ expect(assigns(:group_links).map(&:id)).to contain_exactly(project_group_link_2.id)
+ end
+ end
+ end
+
+ context 'invited members' do
+ let!(:invited_member) { create(:project_member, :invited, project: project) }
before do
- group.add_owner(user_in_group)
- project_in_group.add_maintainer(user)
+ project.add_maintainer(user)
sign_in(user)
end
- it 'lists inherited project members by default' do
- get :index, params: { namespace_id: project_in_group.namespace, project_id: project_in_group }
+ context 'when user has `admin_project_member` permissions' do
+ before do
+ allow(controller.helpers).to receive(:can_manage_project_members?).with(project).and_return(true)
+ end
+
+ it 'lists invited members' do
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(assigns(:invited_members).map(&:invite_email)).to contain_exactly(invited_member.invite_email)
+ end
+ end
+
+ context 'when user does not have `admin_project_member` permissions' do
+ before do
+ allow(controller.helpers).to receive(:can_manage_project_members?).with(project).and_return(false)
+ end
+
+ it 'does not list invited members' do
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(assigns(:invited_members)).to be_nil
+ end
+ end
+ end
+
+ context 'access requests' do
+ let(:access_requester_user) { create(:user) }
- expect(assigns(:project_members).map(&:user_id)).to contain_exactly(user.id, user_in_group.id)
+ before do
+ project.request_access(access_requester_user)
+ project.add_maintainer(user)
+ sign_in(user)
end
- it 'lists direct project members only' do
- get :index, params: { namespace_id: project_in_group.namespace, project_id: project_in_group, with_inherited_permissions: 'exclude' }
+ context 'when user has `admin_project_member` permissions' do
+ before do
+ allow(controller.helpers).to receive(:can_manage_project_members?).with(project).and_return(true)
+ end
+
+ it 'lists access requests' do
+ get :index, params: { namespace_id: project.namespace, project_id: project }
- expect(assigns(:project_members).map(&:user_id)).to contain_exactly(user.id)
+ expect(assigns(:requesters).map(&:user_id)).to contain_exactly(access_requester_user.id)
+ end
end
- it 'lists inherited project members only' do
- get :index, params: { namespace_id: project_in_group.namespace, project_id: project_in_group, with_inherited_permissions: 'only' }
+ context 'when user does not have `admin_project_member` permissions' do
+ before do
+ allow(controller.helpers).to receive(:can_manage_project_members?).with(project).and_return(false)
+ end
+
+ it 'does not list access requests' do
+ get :index, params: { namespace_id: project.namespace, project_id: project }
- expect(assigns(:project_members).map(&:user_id)).to contain_exactly(user_in_group.id)
+ expect(assigns(:requesters)).to be_nil
+ end
end
end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index bd7ef3db8b6..a611ac16cd9 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -211,28 +211,13 @@ RSpec.describe ProjectsController do
end
end
- context 'when the storage is not available', :broken_storage do
- let_it_be(:project) { create(:project, :broken_storage) }
-
- before do
- project.add_developer(user)
- sign_in(user)
- end
-
- it 'renders a 503' do
- get :show, params: { namespace_id: project.namespace, id: project }
-
- expect(response).to have_gitlab_http_status(:service_unavailable)
- end
- end
-
context "project with empty repo" do
let_it_be(:empty_project) { create(:project_empty_repo, :public) }
before do
sign_in(user)
- allow(controller).to receive(:record_experiment_user).with(:invite_members_empty_project_version_a)
+ allow(controller).to receive(:record_experiment_user)
end
User.project_views.keys.each do |project_view|
@@ -498,14 +483,14 @@ RSpec.describe ProjectsController do
describe '#housekeeping' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
- let(:housekeeping) { Projects::HousekeepingService.new(project) }
+ let(:housekeeping) { Repositories::HousekeepingService.new(project) }
context 'when authenticated as owner' do
before do
group.add_owner(user)
sign_in(user)
- allow(Projects::HousekeepingService).to receive(:new).with(project, :gc).and_return(housekeeping)
+ allow(Repositories::HousekeepingService).to receive(:new).with(project, :gc).and_return(housekeeping)
end
it 'forces a full garbage collection' do
@@ -616,7 +601,7 @@ RSpec.describe ProjectsController do
expect { update_project path: 'renamed_path' }
.not_to change { project.reload.path }
- expect(controller).to set_flash.now[:alert].to(s_('UpdateProject|Cannot rename project because it contains container registry tags!'))
+ expect(controller).to set_flash[:alert].to(s_('UpdateProject|Cannot rename project because it contains container registry tags!'))
expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -748,7 +733,7 @@ RSpec.describe ProjectsController do
describe '#transfer', :enable_admin_mode do
render_views
- let_it_be(:project, reload: true) { create(:project, :repository) }
+ let_it_be(:project, reload: true) { create(:project) }
let_it_be(:admin) { create(:admin) }
let_it_be(:new_namespace) { create(:namespace) }
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 2fb17e56f37..737ec4f95c5 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe RegistrationsController do
include TermsHelper
before do
- stub_feature_flags(invisible_captcha: false)
stub_application_setting(require_admin_approval_after_user_signup: false)
end
@@ -193,15 +192,10 @@ RSpec.describe RegistrationsController do
context 'when invisible captcha is enabled' do
before do
- stub_feature_flags(invisible_captcha: true)
- InvisibleCaptcha.timestamp_enabled = true
+ stub_application_setting(invisible_captcha_enabled: true)
InvisibleCaptcha.timestamp_threshold = treshold
end
- after do
- InvisibleCaptcha.timestamp_enabled = false
- end
-
let(:treshold) { 4 }
let(:session_params) { { invisible_captcha_timestamp: form_rendered_time.iso8601 } }
let(:form_rendered_time) { Time.current }
diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb
index 551abf9241d..34052496871 100644
--- a/spec/controllers/repositories/git_http_controller_spec.rb
+++ b/spec/controllers/repositories/git_http_controller_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Repositories::GitHttpController do
}.from(0).to(1)
end
- it 'records a namespace onboarding progress action' do
+ it 'records an onboarding progress action' do
expect_next_instance_of(OnboardingProgressService) do |service|
expect(service).to receive(:execute).with(action: :git_read)
end
diff --git a/spec/controllers/runner_setup_controller_spec.rb b/spec/controllers/runner_setup_controller_spec.rb
deleted file mode 100644
index 0b237500907..00000000000
--- a/spec/controllers/runner_setup_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe RunnerSetupController do
- let(:user) { create(:user) }
-
- before do
- sign_in(user)
- end
-
- describe 'GET #platforms' do
- it 'renders the platforms' do
- get :platforms
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to have_key("windows")
- expect(json_response).to have_key("kubernetes")
- end
- end
-end
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
deleted file mode 100644
index 916befe3f62..00000000000
--- a/spec/controllers/users_controller_spec.rb
+++ /dev/null
@@ -1,925 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe UsersController do
- # This user should have the same e-mail address associated with the GPG key prepared for tests
- let(:user) { create(:user, email: GpgHelpers::User1.emails[0]) }
- let(:private_user) { create(:user, private_profile: true) }
- let(:public_user) { create(:user) }
-
- describe 'GET #show' do
- context 'with rendered views' do
- render_views
-
- describe 'when logged in' do
- before do
- sign_in(user)
- end
-
- it 'renders the show template' do
- get :show, params: { username: user.username }
-
- expect(response).to be_successful
- expect(response).to render_template('show')
- end
- end
-
- describe 'when logged out' do
- it 'renders the show template' do
- get :show, params: { username: user.username }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('show')
- end
- end
- end
-
- context 'when public visibility level is restricted' do
- before do
- stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
- end
-
- context 'when logged out' do
- it 'redirects to login page' do
- get :show, params: { username: user.username }
- expect(response).to redirect_to new_user_session_path
- end
- end
-
- context 'when logged in' do
- before do
- sign_in(user)
- end
-
- it 'renders show' do
- get :show, params: { username: user.username }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('show')
- end
- end
- end
-
- context 'when a user by that username does not exist' do
- context 'when logged out' do
- it 'redirects to login page' do
- get :show, params: { username: 'nonexistent' }
- expect(response).to redirect_to new_user_session_path
- end
- end
-
- context 'when logged in' do
- before do
- sign_in(user)
- end
-
- it 'renders 404' do
- get :show, params: { username: 'nonexistent' }
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'json with events' do
- let(:project) { create(:project) }
-
- before do
- project.add_developer(user)
- Gitlab::DataBuilder::Push.build_sample(project, user)
-
- sign_in(user)
- end
-
- it 'loads events' do
- get :show, params: { username: user }, format: :json
-
- expect(assigns(:events)).not_to be_empty
- end
-
- it 'hides events if the user cannot read cross project' do
- allow(Ability).to receive(:allowed?).and_call_original
- expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
-
- get :show, params: { username: user }, format: :json
-
- expect(assigns(:events)).to be_empty
- end
-
- it 'hides events if the user has a private profile' do
- Gitlab::DataBuilder::Push.build_sample(project, private_user)
-
- get :show, params: { username: private_user.username }, format: :json
-
- expect(assigns(:events)).to be_empty
- end
- end
- end
-
- describe 'GET #activity' do
- context 'with rendered views' do
- render_views
-
- describe 'when logged in' do
- before do
- sign_in(user)
- end
-
- it 'renders the show template' do
- get :show, params: { username: user.username }
-
- expect(response).to be_successful
- expect(response).to render_template('show')
- end
- end
-
- describe 'when logged out' do
- it 'renders the show template' do
- get :activity, params: { username: user.username }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('show')
- end
- end
- end
-
- context 'when public visibility level is restricted' do
- before do
- stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
- end
-
- context 'when logged out' do
- it 'redirects to login page' do
- get :activity, params: { username: user.username }
- expect(response).to redirect_to new_user_session_path
- end
- end
-
- context 'when logged in' do
- before do
- sign_in(user)
- end
-
- it 'renders show' do
- get :activity, params: { username: user.username }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('show')
- end
- end
- end
-
- context 'when a user by that username does not exist' do
- context 'when logged out' do
- it 'redirects to login page' do
- get :activity, params: { username: 'nonexistent' }
- expect(response).to redirect_to new_user_session_path
- end
- end
-
- context 'when logged in' do
- before do
- sign_in(user)
- end
-
- it 'renders 404' do
- get :activity, params: { username: 'nonexistent' }
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'json with events' do
- let(:project) { create(:project) }
-
- before do
- project.add_developer(user)
- Gitlab::DataBuilder::Push.build_sample(project, user)
-
- sign_in(user)
- end
-
- it 'loads events' do
- get :activity, params: { username: user }, format: :json
-
- expect(assigns(:events)).not_to be_empty
- end
-
- it 'hides events if the user cannot read cross project' do
- allow(Ability).to receive(:allowed?).and_call_original
- expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
-
- get :activity, params: { username: user }, format: :json
-
- expect(assigns(:events)).to be_empty
- end
-
- it 'hides events if the user has a private profile' do
- Gitlab::DataBuilder::Push.build_sample(project, private_user)
-
- get :activity, params: { username: private_user.username }, format: :json
-
- expect(assigns(:events)).to be_empty
- end
- end
- end
-
- describe "#ssh_keys" do
- describe "non existent user" do
- it "does not generally work" do
- get :ssh_keys, params: { username: 'not-existent' }
-
- expect(response).not_to be_successful
- end
- end
-
- describe "user with no keys" do
- it "does generally work" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all keys separated with a new line" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response.body).to eq("")
- end
-
- it "responds with text/plain content type" do
- get :ssh_keys, params: { username: user.username }
- expect(response.content_type).to eq("text/plain")
- end
- end
-
- describe "user with keys" do
- let!(:key) { create(:key, user: user) }
- let!(:another_key) { create(:another_key, user: user) }
- let!(:deploy_key) { create(:deploy_key, user: user) }
-
- describe "while signed in" do
- before do
- sign_in(user)
- end
-
- it "does generally work" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all non deploy keys separated with a new line" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
- expect(response.body).to eq(user.all_ssh_keys.join("\n"))
-
- expect(response.body).to include(key.key.sub(' dummy@gitlab.com', ''))
- expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', ''))
-
- expect(response.body).not_to include(deploy_key.key)
- end
-
- it "does not render the comment of the key" do
- get :ssh_keys, params: { username: user.username }
- expect(response.body).not_to match(/dummy@gitlab.com/)
- end
-
- it "responds with text/plain content type" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response.content_type).to eq("text/plain")
- end
- end
-
- describe 'when logged out' do
- before do
- sign_out(user)
- end
-
- it "still does generally work" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all non deploy keys separated with a new line" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
- expect(response.body).to eq(user.all_ssh_keys.join("\n"))
-
- expect(response.body).to include(key.key.sub(' dummy@gitlab.com', ''))
- expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', ''))
-
- expect(response.body).not_to include(deploy_key.key)
- end
-
- it "does not render the comment of the key" do
- get :ssh_keys, params: { username: user.username }
- expect(response.body).not_to match(/dummy@gitlab.com/)
- end
-
- it "responds with text/plain content type" do
- get :ssh_keys, params: { username: user.username }
-
- expect(response.content_type).to eq("text/plain")
- end
- end
- end
- end
-
- describe "#gpg_keys" do
- describe "non existent user" do
- it "does not generally work" do
- get :gpg_keys, params: { username: 'not-existent' }
-
- expect(response).not_to be_successful
- end
- end
-
- describe "user with no keys" do
- it "does generally work" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all keys separated with a new line" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.body).to eq("")
- end
-
- it "responds with text/plain content type" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.content_type).to eq("text/plain")
- end
- end
-
- describe "user with keys" do
- let!(:gpg_key) { create(:gpg_key, user: user) }
- let!(:another_gpg_key) { create(:another_gpg_key, user: user) }
-
- describe "while signed in" do
- before do
- sign_in(user)
- end
-
- it "does generally work" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all verified keys separated with a new line" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
- expect(response.body).to eq(user.gpg_keys.select(&:verified?).map(&:key).join("\n"))
-
- expect(response.body).to include(gpg_key.key)
- expect(response.body).to include(another_gpg_key.key)
- end
-
- it "responds with text/plain content type" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.content_type).to eq("text/plain")
- end
- end
-
- describe 'when logged out' do
- before do
- sign_out(user)
- end
-
- it "still does generally work" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all verified keys separated with a new line" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
- expect(response.body).to eq(user.gpg_keys.map(&:key).join("\n"))
-
- expect(response.body).to include(gpg_key.key)
- expect(response.body).to include(another_gpg_key.key)
- end
-
- it "responds with text/plain content type" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.content_type).to eq("text/plain")
- end
- end
-
- describe 'when revoked' do
- before do
- sign_in(user)
- another_gpg_key.revoke
- end
-
- it "doesn't render revoked keys" do
- get :gpg_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
-
- expect(response.body).to include(gpg_key.key)
- expect(response.body).not_to include(another_gpg_key.key)
- end
-
- it "doesn't render revoked keys for non-authorized users" do
- sign_out(user)
- get :gpg_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
-
- expect(response.body).to include(gpg_key.key)
- expect(response.body).not_to include(another_gpg_key.key)
- end
- end
- end
- end
-
- describe 'GET #calendar' do
- context 'for user' do
- let(:project) { create(:project) }
-
- before do
- sign_in(user)
- project.add_developer(user)
- end
-
- context 'with public profile' do
- it 'renders calendar' do
- push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user)
- EventCreateService.new.push(project, public_user, push_data)
-
- get :calendar, params: { username: public_user.username }, format: :json
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'with private profile' do
- it 'does not render calendar' do
- push_data = Gitlab::DataBuilder::Push.build_sample(project, private_user)
- EventCreateService.new.push(project, private_user, push_data)
-
- get :calendar, params: { username: private_user.username }, format: :json
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'forked project' do
- let(:project) { create(:project) }
- let(:forked_project) { Projects::ForkService.new(project, user).execute }
-
- before do
- sign_in(user)
- project.add_developer(user)
-
- push_data = Gitlab::DataBuilder::Push.build_sample(project, user)
-
- fork_push_data = Gitlab::DataBuilder::Push
- .build_sample(forked_project, user)
-
- EventCreateService.new.push(project, user, push_data)
- EventCreateService.new.push(forked_project, user, fork_push_data)
- end
-
- it 'includes forked projects' do
- get :calendar, params: { username: user.username }
- expect(assigns(:contributions_calendar).projects.count).to eq(2)
- end
- end
- end
-
- describe 'GET #calendar_activities' do
- let!(:project) { create(:project) }
- let(:user) { create(:user) }
-
- before do
- allow_next_instance_of(User) do |instance|
- allow(instance).to receive(:contributed_projects_ids).and_return([project.id])
- end
-
- sign_in(user)
- project.add_developer(user)
- end
-
- it 'assigns @calendar_date' do
- get :calendar_activities, params: { username: user.username, date: '2014-07-31' }
- expect(assigns(:calendar_date)).to eq(Date.parse('2014-07-31'))
- end
-
- context 'for user' do
- context 'with public profile' do
- let(:issue) { create(:issue, project: project, author: user) }
- let(:note) { create(:note, noteable: issue, author: user, project: project) }
-
- render_views
-
- before do
- create_push_event
- create_note_event
- end
-
- it 'renders calendar_activities' do
- get :calendar_activities, params: { username: public_user.username }
-
- expect(assigns[:events]).not_to be_empty
- end
-
- it 'avoids N+1 queries', :request_store do
- get :calendar_activities, params: { username: public_user.username }
-
- control = ActiveRecord::QueryRecorder.new { get :calendar_activities, params: { username: public_user.username } }
-
- create_push_event
- create_note_event
-
- expect { get :calendar_activities, params: { username: public_user.username } }.not_to exceed_query_limit(control)
- end
- end
-
- context 'with private profile' do
- it 'does not render calendar_activities' do
- push_data = Gitlab::DataBuilder::Push.build_sample(project, private_user)
- EventCreateService.new.push(project, private_user, push_data)
-
- get :calendar_activities, params: { username: private_user.username }
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'external authorization' do
- subject { get :calendar_activities, params: { username: user.username } }
-
- it_behaves_like 'disabled when using an external authorization service'
- end
-
- def create_push_event
- push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user)
- EventCreateService.new.push(project, public_user, push_data)
- end
-
- def create_note_event
- EventCreateService.new.leave_note(note, public_user)
- end
- end
- end
-
- describe 'GET #contributed' do
- let(:project) { create(:project, :public) }
-
- subject do
- get :contributed, params: { username: author.username }, format: format
- end
-
- before do
- sign_in(user)
-
- project.add_developer(public_user)
- project.add_developer(private_user)
- create(:push_event, project: project, author: author)
-
- subject
- end
-
- shared_examples_for 'renders contributed projects' do
- it 'renders contributed projects' do
- expect(assigns[:contributed_projects]).not_to be_empty
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- %i(html json).each do |format|
- context "format: #{format}" do
- let(:format) { format }
-
- context 'with public profile' do
- let(:author) { public_user }
-
- it_behaves_like 'renders contributed projects'
- end
-
- context 'with private profile' do
- let(:author) { private_user }
-
- it 'returns 404' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- context 'with a user that has the ability to read private profiles', :enable_admin_mode do
- let(:user) { create(:admin) }
-
- it_behaves_like 'renders contributed projects'
- end
- end
- end
- end
- end
-
- describe 'GET #starred' do
- let(:project) { create(:project, :public) }
-
- subject do
- get :starred, params: { username: author.username }, format: format
- end
-
- before do
- author.toggle_star(project)
-
- sign_in(user)
- subject
- end
-
- shared_examples_for 'renders starred projects' do
- it 'renders starred projects' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(assigns[:starred_projects]).not_to be_empty
- end
- end
-
- %i(html json).each do |format|
- context "format: #{format}" do
- let(:format) { format }
-
- context 'with public profile' do
- let(:author) { public_user }
-
- it_behaves_like 'renders starred projects'
- end
-
- context 'with private profile' do
- let(:author) { private_user }
-
- it 'returns 404' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- context 'with a user that has the ability to read private profiles', :enable_admin_mode do
- let(:user) { create(:admin) }
-
- it_behaves_like 'renders starred projects'
- end
- end
- end
- end
- end
-
- describe 'GET #snippets' do
- before do
- sign_in(user)
- end
-
- context 'format html' do
- it 'renders snippets page' do
- get :snippets, params: { username: user.username }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('show')
- end
- end
-
- context 'format json' do
- it 'response with snippets json data' do
- get :snippets, params: { username: user.username }, format: :json
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to have_key('html')
- end
- end
-
- context 'external authorization' do
- subject { get :snippets, params: { username: user.username } }
-
- it_behaves_like 'disabled when using an external authorization service'
- end
- end
-
- describe 'GET #exists' do
- before do
- sign_in(user)
- end
-
- context 'when user exists' do
- it 'returns JSON indicating the user exists' do
- get :exists, params: { username: user.username }
-
- expected_json = { exists: true }.to_json
- expect(response.body).to eq(expected_json)
- end
-
- context 'when the casing is different' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- it 'returns JSON indicating the user exists' do
- get :exists, params: { username: user.username.downcase }
-
- expected_json = { exists: true }.to_json
- expect(response.body).to eq(expected_json)
- end
- end
- end
-
- context 'when the user does not exist' do
- it 'returns JSON indicating the user does not exist' do
- get :exists, params: { username: 'foo' }
-
- expected_json = { exists: false }.to_json
- expect(response.body).to eq(expected_json)
- end
-
- context 'when a user changed their username' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
-
- it 'returns JSON indicating a user by that username does not exist' do
- get :exists, params: { username: 'old-username' }
-
- expected_json = { exists: false }.to_json
- expect(response.body).to eq(expected_json)
- end
- end
- end
- end
-
- describe 'GET #suggests' do
- context 'when user exists' do
- it 'returns JSON indicating the user exists and a suggestion' do
- get :suggests, params: { username: user.username }
-
- expected_json = { exists: true, suggests: ["#{user.username}1"] }.to_json
- expect(response.body).to eq(expected_json)
- end
-
- context 'when the casing is different' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- it 'returns JSON indicating the user exists and a suggestion' do
- get :suggests, params: { username: user.username.downcase }
-
- expected_json = { exists: true, suggests: ["#{user.username.downcase}1"] }.to_json
- expect(response.body).to eq(expected_json)
- end
- end
- end
-
- context 'when the user does not exist' do
- it 'returns JSON indicating the user does not exist' do
- get :suggests, params: { username: 'foo' }
-
- expected_json = { exists: false, suggests: [] }.to_json
- expect(response.body).to eq(expected_json)
- end
-
- context 'when a user changed their username' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
-
- it 'returns JSON indicating a user by that username does not exist' do
- get :suggests, params: { username: 'old-username' }
-
- expected_json = { exists: false, suggests: [] }.to_json
- expect(response.body).to eq(expected_json)
- end
- end
- end
- end
-
- describe '#ensure_canonical_path' do
- before do
- sign_in(user)
- end
-
- context 'for a GET request' do
- context 'when requesting users at the root path' do
- context 'when requesting the canonical path' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- context 'with exactly matching casing' do
- it 'responds with success' do
- get :show, params: { username: user.username }
-
- expect(response).to be_successful
- end
- end
-
- context 'with different casing' do
- it 'redirects to the correct casing' do
- get :show, params: { username: user.username.downcase }
-
- expect(response).to redirect_to(user)
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
-
- it 'redirects to the canonical path' do
- get :show, params: { username: redirect_route.path }
-
- expect(response).to redirect_to(user)
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
-
- context 'when the old path is a substring of the scheme or host' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
-
- it 'does not modify the requested host' do
- get :show, params: { username: redirect_route.path }
-
- expect(response).to redirect_to(user)
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
-
- context 'when the old path is substring of users' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
-
- it 'redirects to the canonical path' do
- get :show, params: { username: redirect_route.path }
-
- expect(response).to redirect_to(user)
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
- end
- end
-
- context 'when requesting users under the /users path' do
- context 'when requesting the canonical path' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- context 'with exactly matching casing' do
- it 'responds with success' do
- get :projects, params: { username: user.username }
-
- expect(response).to be_successful
- end
- end
-
- context 'with different casing' do
- it 'redirects to the correct casing' do
- get :projects, params: { username: user.username.downcase }
-
- expect(response).to redirect_to(user_projects_path(user))
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
-
- it 'redirects to the canonical path' do
- get :projects, params: { username: redirect_route.path }
-
- expect(response).to redirect_to(user_projects_path(user))
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
-
- context 'when the old path is a substring of the scheme or host' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
-
- it 'does not modify the requested host' do
- get :projects, params: { username: redirect_route.path }
-
- expect(response).to redirect_to(user_projects_path(user))
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
-
- context 'when the old path is substring of users' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
-
- # I.e. /users/ser should not become /ufoos/ser
- it 'does not modify the /users part of the path' do
- get :projects, params: { username: redirect_route.path }
-
- expect(response).to redirect_to(user_projects_path(user))
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
- end
- end
- end
- end
-
- context 'token authentication' do
- it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
- before do
- default_params.merge!(username: user.username)
- end
- end
- end
-
- def user_moved_message(redirect_route, user)
- "User '#{redirect_route.path}' was moved to '#{user.full_path}'. Please update any links and bookmarks that may still have the old path."
- end
-end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index a15b9624c9d..3087beb1326 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'Database schema' do
approver_groups: %w[target_id],
approvers: %w[target_id user_id],
audit_events: %w[author_id entity_id target_id],
- audit_events_part_5fc467ac26: %w[author_id entity_id target_id],
+ audit_events_archived: %w[author_id entity_id target_id],
award_emoji: %w[awardable_id user_id],
aws_roles: %w[role_external_id],
boards: %w[milestone_id iteration_id],
diff --git a/spec/factories/alerts_service_data.rb b/spec/factories/alerts_service_data.rb
deleted file mode 100644
index 2dd1d0a714e..00000000000
--- a/spec/factories/alerts_service_data.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :alerts_service_data do
- service { association(:alerts_service) }
- token { SecureRandom.hex }
- end
-end
diff --git a/spec/factories/boards.rb b/spec/factories/boards.rb
index cef7ec37f07..9ea8f3ad06f 100644
--- a/spec/factories/boards.rb
+++ b/spec/factories/boards.rb
@@ -31,4 +31,8 @@ FactoryBot.define do
board.lists.create!(list_type: :closed)
end
end
+
+ factory :group_board, parent: :board do
+ group
+ end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index c3d6e9d7569..24abad66530 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -486,6 +486,14 @@ FactoryBot.define do
end
end
+ trait :non_public_artifacts do
+ options do
+ {
+ artifacts: { public: false }
+ }
+ end
+ end
+
trait :non_playable do
status { 'created' }
self.when { 'manual' }
diff --git a/spec/factories/ci_platform_metrics.rb b/spec/factories/ci_platform_metrics.rb
index 478f9715021..6a517376d65 100644
--- a/spec/factories/ci_platform_metrics.rb
+++ b/spec/factories/ci_platform_metrics.rb
@@ -4,6 +4,6 @@ FactoryBot.define do
factory :ci_platform_metric do
recorded_at { Time.zone.now }
platform_target { generate(:title) }
- count { SecureRandom.random_number(100) }
+ count { SecureRandom.random_number(100) + 1 }
end
end
diff --git a/spec/factories/namespace_onboarding_actions.rb b/spec/factories/namespace_onboarding_actions.rb
deleted file mode 100644
index aca62013b57..00000000000
--- a/spec/factories/namespace_onboarding_actions.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :namespace_onboarding_action do
- namespace
- action { :subscription_created }
- end
-end
diff --git a/spec/factories/namespace_package_settings.rb b/spec/factories/namespace_package_settings.rb
new file mode 100644
index 00000000000..875933ce84f
--- /dev/null
+++ b/spec/factories/namespace_package_settings.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :namespace_package_setting, class: 'Namespace::PackageSetting' do
+ namespace
+
+ maven_duplicates_allowed { true }
+ maven_duplicate_exception_regex { 'SNAPSHOT' }
+
+ trait :group do
+ namespace { association(:group) }
+ end
+ end
+end
diff --git a/spec/factories/onboarding_progresses.rb b/spec/factories/onboarding_progresses.rb
new file mode 100644
index 00000000000..e39bad91b19
--- /dev/null
+++ b/spec/factories/onboarding_progresses.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :onboarding_progress do
+ namespace
+ end
+end
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index 5543be4aa82..31f1aabe5dd 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -26,9 +26,31 @@ FactoryBot.define do
sequence(:version) { |n| "1.0-#{n}" }
package_type { :debian }
+ transient do
+ without_package_files { false }
+ file_metadatum_trait { :keep }
+ end
+
+ after :create do |package, evaluator|
+ unless evaluator.without_package_files
+ create :debian_package_file, :source, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :dsc, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :deb, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :deb2, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :udeb, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :buildinfo, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :changes, evaluator.file_metadatum_trait, package: package
+ end
+ end
+
factory :debian_incoming do
name { 'incoming' }
version { nil }
+
+ transient do
+ without_package_files { false }
+ file_metadatum_trait { :unknown }
+ end
end
end
diff --git a/spec/factories/packages/debian/distribution.rb b/spec/factories/packages/debian/distribution.rb
new file mode 100644
index 00000000000..2015f2923b8
--- /dev/null
+++ b/spec/factories/packages/debian/distribution.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_project_distribution, class: 'Packages::Debian::ProjectDistribution' do
+ container { association(:project) }
+
+ sequence(:codename) { |n| "project-dist-#{n}" }
+
+ factory :debian_group_distribution, class: 'Packages::Debian::GroupDistribution' do
+ container { association(:group) }
+
+ sequence(:codename) { |n| "group-dist-#{n}" }
+ end
+
+ trait(:with_file) do
+ after(:build) do |distribution, evaluator|
+ distribution.file = fixture_file_upload('spec/fixtures/packages/debian/README.md')
+ end
+ end
+
+ trait(:object_storage) do
+ file_store { Packages::PackageFileUploader::Store::REMOTE }
+ end
+ end
+end
diff --git a/spec/factories/packages/debian/file_metadatum.rb b/spec/factories/packages/debian/file_metadatum.rb
new file mode 100644
index 00000000000..088d0140afe
--- /dev/null
+++ b/spec/factories/packages/debian/file_metadatum.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_file_metadatum, class: 'Packages::Debian::FileMetadatum' do
+ package_file { association(:debian_package_file, without_loaded_metadatum: true) }
+ file_type { 'deb' }
+ component { 'main' }
+ architecture { 'amd64' }
+ fields { { 'a': 'b' } }
+
+ trait(:unknown) do
+ file_type { 'unknown' }
+ component { nil }
+ architecture { nil }
+ fields { nil }
+ end
+
+ trait(:source) do
+ file_type { 'source' }
+ component { 'main' }
+ architecture { nil }
+ fields { nil }
+ end
+
+ trait(:dsc) do
+ file_type { 'dsc' }
+ component { 'main' }
+ architecture { nil }
+ fields { { 'a': 'b' } }
+ end
+
+ trait(:deb) do
+ file_type { 'deb' }
+ component { 'main' }
+ architecture { 'amd64' }
+ fields { { 'a': 'b' } }
+ end
+
+ trait(:udeb) do
+ file_type { 'udeb' }
+ component { 'main' }
+ architecture { 'amd64' }
+ fields { { 'a': 'b' } }
+ end
+
+ trait(:buildinfo) do
+ file_type { 'buildinfo' }
+ component { 'main' }
+ architecture { nil }
+ fields { { 'Architecture': 'amd64 source' } }
+ end
+
+ trait(:changes) do
+ file_type { 'changes' }
+ component { nil }
+ architecture { nil }
+ fields { { 'Architecture': 'source amd64' } }
+ end
+ end
+end
diff --git a/spec/factories/packages/debian/group_architecture.rb b/spec/factories/packages/debian/group_architecture.rb
new file mode 100644
index 00000000000..2582faae4ed
--- /dev/null
+++ b/spec/factories/packages/debian/group_architecture.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_group_architecture, class: 'Packages::Debian::GroupArchitecture' do
+ distribution { association(:debian_group_distribution) }
+
+ sequence(:name) { |n| "group-arch-#{n}" }
+ end
+end
diff --git a/spec/factories/packages/debian/project_architecture.rb b/spec/factories/packages/debian/project_architecture.rb
new file mode 100644
index 00000000000..d6985da4128
--- /dev/null
+++ b/spec/factories/packages/debian/project_architecture.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_project_architecture, class: 'Packages::Debian::ProjectArchitecture' do
+ distribution { association(:debian_project_distribution) }
+
+ sequence(:name) { |n| "project-arch-#{n}" }
+ end
+end
diff --git a/spec/factories/packages/package_file.rb b/spec/factories/packages/package_file.rb
index bee1b2076df..c328c01ec95 100644
--- a/spec/factories/packages/package_file.rb
+++ b/spec/factories/packages/package_file.rb
@@ -92,6 +92,97 @@ FactoryBot.define do
end
end
+ factory :debian_package_file do
+ package { association(:debian_package, without_package_files: true) }
+ file_name { 'libsample0_1.2.3~alpha2_amd64.deb' }
+ file_fixture { "spec/fixtures/packages/debian/#{file_name}" }
+ file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
+ file_md5 { '12345abcde' }
+ size { 400.kilobytes }
+
+ transient do
+ without_loaded_metadatum { false }
+ file_metadatum_trait { :deb }
+ end
+
+ after :create do |package_file, evaluator|
+ unless evaluator.without_loaded_metadatum
+ create :debian_file_metadatum, evaluator.file_metadatum_trait, package_file: package_file
+ end
+ end
+
+ trait(:unknown) do
+ package { association(:debian_incoming, without_package_files: true) }
+
+ transient do
+ file_metadatum_trait { :unknown }
+ end
+ end
+
+ trait(:invalid) do
+ file_name { 'README.md' }
+ end
+
+ trait(:source) do
+ file_name { 'sample_1.2.3~alpha2.tar.xz' }
+
+ transient do
+ file_metadatum_trait { :source }
+ end
+ end
+
+ trait(:dsc) do
+ file_name { 'sample_1.2.3~alpha2.dsc' }
+
+ transient do
+ file_metadatum_trait { :dsc }
+ end
+ end
+
+ trait(:deb) do
+ file_name { 'libsample0_1.2.3~alpha2_amd64.deb' }
+
+ transient do
+ file_metadatum_trait { :deb }
+ end
+ end
+
+ trait(:deb2) do
+ file_name { 'sample-dev_1.2.3~binary_amd64.deb' }
+
+ transient do
+ file_metadatum_trait { :deb }
+ end
+ end
+
+ trait(:udeb) do
+ file_name { 'sample-udeb_1.2.3~alpha2_amd64.udeb' }
+
+ transient do
+ file_metadatum_trait { :udeb }
+ end
+ end
+
+ trait(:buildinfo) do
+ file_name { 'sample_1.2.3~alpha2_amd64.buildinfo' }
+
+ transient do
+ file_metadatum_trait { :buildinfo }
+ end
+ end
+
+ trait(:changes) do
+ file_name { 'sample_1.2.3~alpha2_amd64.changes' }
+
+ transient do
+ file_metadatum_trait { :changes }
+ end
+ end
+
+ trait(:keep) do
+ end
+ end
+
trait(:jar) do
file_fixture { 'spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.jar' }
file_name { 'my-app-1.0-20180724.124855-1.jar' }
diff --git a/spec/factories/project_group_links.rb b/spec/factories/project_group_links.rb
index 5e3e83f18c1..b1b0f04d84c 100644
--- a/spec/factories/project_group_links.rb
+++ b/spec/factories/project_group_links.rb
@@ -3,7 +3,7 @@
FactoryBot.define do
factory :project_group_link do
project
- group
+ group { association(:group) }
expires_at { nil }
group_access { Gitlab::Access::DEVELOPER }
diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb
index 0c2ffac4112..3e83ab7118c 100644
--- a/spec/factories/project_members.rb
+++ b/spec/factories/project_members.rb
@@ -15,7 +15,9 @@ FactoryBot.define do
trait(:invited) do
user_id { nil }
invite_token { 'xxx' }
- invite_email { 'email@email.com' }
+ sequence :invite_email do |n|
+ "email#{n}@email.com"
+ end
end
trait :blocked do
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 29a25e71095..f5e496080c4 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -39,11 +39,13 @@ FactoryBot.define do
group_runners_enabled { nil }
merge_pipelines_enabled { nil }
merge_trains_enabled { nil }
+ ci_keep_latest_artifact { nil }
import_status { nil }
import_jid { nil }
import_correlation_id { nil }
import_last_error { nil }
forward_deployment_enabled { nil }
+ restrict_user_defined_variables { nil }
end
before(:create) do |project, evaluator|
@@ -82,6 +84,8 @@ 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.restrict_user_defined_variables = evaluator.restrict_user_defined_variables unless evaluator.restrict_user_defined_variables.nil?
if evaluator.import_status
import_state = project.import_state || project.build_import_state
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 44b157014a5..18d3b2d99b7 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -38,24 +38,6 @@ FactoryBot.define do
end
end
- factory :alerts_service do
- active
- project
- type { 'AlertsService' }
-
- trait :active do
- active { true }
- end
-
- trait :inactive do
- active { false }
- end
-
- before(:create) do |service|
- service.data = build(:alerts_service_data, service: service)
- end
- end
-
factory :drone_ci_service do
project
active { true }
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index f933461a07a..0ed4176109a 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -32,8 +32,8 @@ FactoryBot.define do
create(:service, project: projects[2], type: 'CustomIssueTrackerService', active: true)
create(:project_error_tracking_setting, project: projects[0])
create(:project_error_tracking_setting, project: projects[1], enabled: false)
- create(:alerts_service, project: projects[0])
- create(:alerts_service, :inactive, project: projects[1])
+ create(:service, project: projects[0], type: 'AlertsService', active: true)
+ create(:service, project: projects[1], type: 'AlertsService', active: false)
alert_bot_issues = create_list(:incident, 2, project: projects[0], author: User.alert_bot)
create_list(:incident, 2, project: projects[1], author: User.alert_bot)
issues = create_list(:issue, 4, project: projects[0])
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 1afd5bdb2ca..38ade20de28 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'factories' do
- include DatabaseHelpers
+ include Database::DatabaseHelpers
shared_examples 'factory' do |factory|
describe "#{factory.name} factory" do
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 0e350a5e12e..a8e18385bd2 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -175,6 +175,7 @@ RSpec.describe 'Admin Groups' do
describe 'add admin himself to a group' do
before do
+ stub_feature_flags(invite_members_group_modal: false)
group.add_user(:user, Gitlab::Access::OWNER)
end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index e16cde3fa1c..4f135b81bdf 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe "Admin Runners" do
create(:ci_build, pipeline: pipeline, runner_id: runner.id)
visit admin_runners_path
- expect(page).to have_text "Set up a shared Runner manually"
+ expect(page).to have_text "Set up a shared runner manually"
expect(page).to have_text "Runners currently online: 1"
end
@@ -227,7 +227,7 @@ RSpec.describe "Admin Runners" do
end
it 'has all necessary texts including no runner message' do
- expect(page).to have_text "Set up a shared Runner manually"
+ expect(page).to have_text "Set up a shared runner manually"
expect(page).to have_text "Runners currently online: 0"
expect(page).to have_text 'No runners found'
end
@@ -389,7 +389,7 @@ RSpec.describe "Admin Runners" do
let(:page_token) { find('#registration_token').text }
before do
- click_button 'Reset runners registration token'
+ click_button 'Reset registration token'
end
it 'changes registration token' do
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 06d31b544ea..0c66775c323 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -17,10 +17,7 @@ RSpec.describe 'Admin updates settings' do
end
context 'General page' do
- let(:gitpod_feature_enabled) { true }
-
before do
- stub_feature_flags(gitpod: gitpod_feature_enabled)
visit general_admin_application_settings_path
end
@@ -224,28 +221,16 @@ RSpec.describe 'Admin updates settings' do
end
context 'Configure Gitpod' do
- context 'with feature disabled' do
- let(:gitpod_feature_enabled) { false }
-
- it 'do not show settings' do
- expect(page).not_to have_selector('#js-gitpod-settings')
+ it 'changes gitpod settings' do
+ page.within('#js-gitpod-settings') do
+ check 'Enable Gitpod integration'
+ fill_in 'Gitpod URL', with: 'https://gitpod.test/'
+ click_button 'Save changes'
end
- end
-
- context 'with feature enabled' do
- let(:gitpod_feature_enabled) { true }
- it 'changes gitpod settings' do
- page.within('#js-gitpod-settings') do
- check 'Enable Gitpod integration'
- fill_in 'Gitpod URL', with: 'https://gitpod.test/'
- click_button 'Save changes'
- end
-
- expect(page).to have_content 'Application settings saved successfully'
- expect(current_settings.gitpod_url).to eq('https://gitpod.test/')
- expect(current_settings.gitpod_enabled).to be(true)
- end
+ expect(page).to have_content 'Application settings saved successfully'
+ expect(current_settings.gitpod_url).to eq('https://gitpod.test/')
+ expect(current_settings.gitpod_enabled).to be(true)
end
end
end
diff --git a/spec/features/alert_management/user_filters_alerts_by_status_spec.rb b/spec/features/alert_management/user_filters_alerts_by_status_spec.rb
index ee516418cd6..bebbbcbf5f7 100644
--- a/spec/features/alert_management/user_filters_alerts_by_status_spec.rb
+++ b/spec/features/alert_management/user_filters_alerts_by_status_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User filters Alert Management table by status', :js do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user) }
- let_it_be(:alerts_service) { create(:alerts_service, project: project) }
let_it_be(:alert1, reload: true) { create(:alert_management_alert, :triggered, project: project) }
let_it_be(:alert2, reload: true) { create(:alert_management_alert, :acknowledged, project: project) }
let_it_be(:alert3, reload: true) { create(:alert_management_alert, :acknowledged, project: project) }
diff --git a/spec/features/alert_management/user_searches_alerts_spec.rb b/spec/features/alert_management/user_searches_alerts_spec.rb
index 568321de025..3bb1b260f36 100644
--- a/spec/features/alert_management/user_searches_alerts_spec.rb
+++ b/spec/features/alert_management/user_searches_alerts_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User searches Alert Management alerts', :js do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user) }
- let_it_be(:alerts_service) { create(:alerts_service, project: project) }
let_it_be(:alert) { create(:alert_management_alert, project: project, status: 'triggered') }
before_all do
diff --git a/spec/features/alert_management/user_updates_alert_status_spec.rb b/spec/features/alert_management/user_updates_alert_status_spec.rb
index 8974796662c..2d7be3a0022 100644
--- a/spec/features/alert_management/user_updates_alert_status_spec.rb
+++ b/spec/features/alert_management/user_updates_alert_status_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User updates Alert Management status', :js do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user) }
- let_it_be(:alerts_service) { create(:alerts_service, project: project) }
let_it_be(:alert) { create(:alert_management_alert, project: project, status: 'triggered') }
before_all do
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index 0e76b5478a1..26b376be660 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -110,6 +110,12 @@ RSpec.describe 'Dashboard Merge Requests' do
visit merge_requests_dashboard_path(assignee_username: current_user.username)
end
+ it 'includes assigned and reviewers in badge' do
+ expect(find('.merge-requests-count')).to have_content('3')
+ expect(find('.js-assigned-mr-count')).to have_content('2')
+ expect(find('.js-reviewer-mr-count')).to have_content('1')
+ end
+
it 'shows assigned merge requests' do
expect(page).to have_content(assigned_merge_request.title)
expect(page).to have_content(assigned_merge_request_from_fork.title)
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index f870adbbdb6..8705c22c41a 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -259,7 +259,7 @@ RSpec.describe 'Dashboard Projects' do
# 4. ProjectsHelper#load_pipeline_status
# 5. RendersMemberAccess#preload_max_member_access_for_collection
# 6. User#max_member_access_for_project_ids
- # 7. CommitWithPipeline#last_pipeline
+ # 7. Ci::CommitWithPipeline#last_pipeline
expect { visit dashboard_projects_path }.not_to exceed_query_limit(control_count + 7)
end
diff --git a/spec/features/groups/board_spec.rb b/spec/features/groups/board_spec.rb
index b25aa26d906..aab3f5e68d5 100644
--- a/spec/features/groups/board_spec.rb
+++ b/spec/features/groups/board_spec.rb
@@ -20,14 +20,19 @@ RSpec.describe 'Group Boards' do
page.within(find('.board', match: :first)) do
issue_title = 'New Issue'
find(:css, '.issue-count-badge-add-button').click
+
+ wait_for_requests
+
expect(find('.board-new-issue-form')).to be_visible
fill_in 'issue_title', with: issue_title
- find('.dropdown-menu-toggle').click
- wait_for_requests
+ page.within("[data-testid='project-select-dropdown']") do
+ find('button.gl-dropdown-toggle').click
+
+ find('.gl-new-dropdown-item button').click
+ end
- click_link(project.name)
click_button 'Submit issue'
expect(page).to have_content(issue_title)
diff --git a/spec/features/groups/import_export/connect_instance_spec.rb b/spec/features/groups/import_export/connect_instance_spec.rb
index c0f967fd0b9..2e1bf27ba8b 100644
--- a/spec/features/groups/import_export/connect_instance_spec.rb
+++ b/spec/features/groups/import_export/connect_instance_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Import/Export - Connect to another instance', :js do
pat = 'demo-pat'
stub_path = 'stub-group'
- stub_request(:get, "%{url}/api/v4/groups?page=1&per_page=30&top_level_only=true" % { url: source_url }).to_return(
+ 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(
body: [{
id: 2595438,
web_url: 'https://gitlab.com/groups/auto-breakfast',
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
index 31a2c868cac..e9bbe9de3c9 100644
--- a/spec/features/groups/members/manage_groups_spec.rb
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
let_it_be(:group_to_add) { create(:group) }
before do
+ stub_feature_flags(invite_members_group_modal: false)
group.add_owner(user)
visit group_group_members_path(group)
end
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index e6da05c4873..c27d0afba6f 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -11,9 +11,37 @@ RSpec.describe 'Groups > Members > Manage members' do
let(:group) { create(:group) }
before do
+ stub_feature_flags(invite_members_group_modal: false)
sign_in(user1)
end
+ shared_examples 'includes the correct Invite Members link' do |should_include, should_not_include|
+ it 'includes either the form or the modal trigger' do
+ group.add_owner(user1)
+
+ visit group_group_members_path(group)
+
+ expect(page).to have_selector(should_include)
+ expect(page).not_to have_selector(should_not_include)
+ end
+ end
+
+ context 'when Invite Members modal is enabled' do
+ before do
+ stub_feature_flags(invite_members_group_modal: true)
+ end
+
+ it_behaves_like 'includes the correct Invite Members link', '.js-invite-members-trigger', '.invite-users-form'
+ end
+
+ context 'when Invite Members modal is disabled' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it_behaves_like 'includes the correct Invite Members link', '.invite-users-form', '.js-invite-members-trigger'
+ end
+
it 'update user to owner level', :js do
group.add_owner(user1)
group.add_developer(user2)
diff --git a/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb
index de9b32e00aa..38deee547a3 100644
--- a/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb
+++ b/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
let(:new_member) { create(:user, name: 'Mary Jane') }
before do
+ stub_feature_flags(invite_members_group_modal: false)
group.add_owner(user1)
sign_in(user1)
end
diff --git a/spec/features/groups/members/master_manages_access_requests_spec.rb b/spec/features/groups/members/master_manages_access_requests_spec.rb
index 71c9b280ebe..2a17e7d2a5c 100644
--- a/spec/features/groups/members/master_manages_access_requests_spec.rb
+++ b/spec/features/groups/members/master_manages_access_requests_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Maintainer manages access requests' do
it_behaves_like 'Maintainer manages access requests' do
- let(:has_tabs) { true }
let(:entity) { create(:group, :public) }
let(:members_page_path) { group_group_members_path(entity) }
end
diff --git a/spec/features/groups/members/sort_members_spec.rb b/spec/features/groups/members/sort_members_spec.rb
index 68a748aa76a..03758e0d401 100644
--- a/spec/features/groups/members/sort_members_spec.rb
+++ b/spec/features/groups/members/sort_members_spec.rb
@@ -16,174 +16,92 @@ RSpec.describe 'Groups > Members > Sort members', :js do
sign_in(owner)
end
- context 'when `group_members_filtered_search` feature flag is enabled' do
- 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
-
- it 'sorts by account by default' do
- visit_members_list(sort: nil)
-
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
-
- expect_sort_by('Account', :asc)
- end
-
- it 'sorts by max role ascending' do
- visit_members_list(sort: :access_level_asc)
-
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
-
- expect_sort_by('Max role', :asc)
- end
-
- it 'sorts by max role descending' do
- visit_members_list(sort: :access_level_desc)
-
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
-
- expect_sort_by('Max role', :desc)
- end
-
- it 'sorts by access granted ascending' do
- visit_members_list(sort: :last_joined)
-
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
-
- expect_sort_by('Access granted', :asc)
- end
-
- it 'sorts by access granted descending' do
- visit_members_list(sort: :oldest_joined)
-
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
-
- expect_sort_by('Access granted', :desc)
- end
-
- it 'sorts by account ascending' do
- visit_members_list(sort: :name_asc)
-
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
-
- expect_sort_by('Account', :asc)
+ 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
- it 'sorts by account descending' do
- visit_members_list(sort: :name_desc)
+ it 'sorts by account by default' do
+ visit_members_list(sort: nil)
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
- expect_sort_by('Account', :desc)
- end
+ expect_sort_by('Account', :asc)
+ end
- it 'sorts by last sign-in ascending', :clean_gitlab_redis_shared_state do
- visit_members_list(sort: :recent_sign_in)
+ it 'sorts by max role ascending' do
+ visit_members_list(sort: :access_level_asc)
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
- expect_sort_by('Last sign-in', :asc)
- end
+ expect_sort_by('Max role', :asc)
+ end
- it 'sorts by last sign-in descending', :clean_gitlab_redis_shared_state do
- visit_members_list(sort: :oldest_sign_in)
+ it 'sorts by max role descending' do
+ visit_members_list(sort: :access_level_desc)
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
- expect_sort_by('Last sign-in', :desc)
- end
+ expect_sort_by('Max role', :desc)
end
- context 'when `group_members_filtered_search` feature flag is disabled' do
- dropdown_toggle_selector = '[data-testid="user-sort-dropdown"] [data-testid="dropdown-toggle"]'
+ it 'sorts by access granted ascending' do
+ visit_members_list(sort: :last_joined)
- before do
- stub_feature_flags(group_members_filtered_search: false)
- end
-
- it 'sorts alphabetically by default' do
- visit_members_list(sort: nil)
-
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Name, ascending')
- end
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
- it 'sorts by access level ascending' do
- visit_members_list(sort: :access_level_asc)
+ expect_sort_by('Access granted', :asc)
+ end
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Access level, ascending')
- end
+ it 'sorts by access granted descending' do
+ visit_members_list(sort: :oldest_joined)
- it 'sorts by access level descending' do
- visit_members_list(sort: :access_level_desc)
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Access level, descending')
- end
+ expect_sort_by('Access granted', :desc)
+ end
- it 'sorts by last joined' do
- visit_members_list(sort: :last_joined)
+ it 'sorts by account ascending' do
+ visit_members_list(sort: :name_asc)
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Last joined')
- end
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
- it 'sorts by oldest joined' do
- visit_members_list(sort: :oldest_joined)
+ expect_sort_by('Account', :asc)
+ end
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Oldest joined')
- end
+ it 'sorts by account descending' do
+ visit_members_list(sort: :name_desc)
- it 'sorts by name ascending' do
- visit_members_list(sort: :name_asc)
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Name, ascending')
- end
+ expect_sort_by('Account', :desc)
+ end
- it 'sorts by name descending' do
- visit_members_list(sort: :name_desc)
+ it 'sorts by last sign-in ascending', :clean_gitlab_redis_shared_state do
+ visit_members_list(sort: :recent_sign_in)
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Name, descending')
- end
+ expect(first_row.text).to include(owner.name)
+ expect(second_row.text).to include(developer.name)
- it 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
- visit_members_list(sort: :recent_sign_in)
+ expect_sort_by('Last sign-in', :asc)
+ end
- expect(first_row.text).to include(owner.name)
- expect(second_row.text).to include(developer.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Recent sign in')
- end
+ it 'sorts by last sign-in descending', :clean_gitlab_redis_shared_state do
+ visit_members_list(sort: :oldest_sign_in)
- it 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
- visit_members_list(sort: :oldest_sign_in)
+ expect(first_row.text).to include(developer.name)
+ expect(second_row.text).to include(owner.name)
- expect(first_row.text).to include(developer.name)
- expect(second_row.text).to include(owner.name)
- expect(page).to have_css(dropdown_toggle_selector, text: 'Oldest sign in')
- end
+ expect_sort_by('Last sign-in', :desc)
end
def visit_members_list(sort:)
diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb
index 9c2f9512b9d..b059cd8da29 100644
--- a/spec/features/groups/settings/ci_cd_spec.rb
+++ b/spec/features/groups/settings/ci_cd_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Group CI/CD settings' do
let(:page_token) { find('#registration_token').text }
before do
- click_button 'Reset runners registration token'
+ click_button 'Reset registration token'
end
it 'changes registration token' do
diff --git a/spec/features/groups/settings/packages_and_registries_spec.rb b/spec/features/groups/settings/packages_and_registries_spec.rb
new file mode 100644
index 00000000000..b8ffd73335d
--- /dev/null
+++ b/spec/features/groups/settings/packages_and_registries_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Group Packages & Registries settings' do
+ include WaitForRequests
+
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ context 'when the feature flag is off' do
+ before do
+ stub_feature_flags(packages_and_registries_group_settings: false)
+ end
+
+ it 'the menu item is not visible' do
+ visit group_path(group)
+
+ settings_menu = find_settings_menu
+
+ expect(settings_menu).not_to have_content 'Packages & Registries'
+ end
+ end
+
+ context 'when the feature flag is on' do
+ it 'the menu item is visible' do
+ visit group_path(group)
+
+ settings_menu = find_settings_menu
+ expect(settings_menu).to have_content 'Packages & Registries'
+ end
+
+ it 'has a page title set' do
+ visit_settings_page
+
+ expect(page).to have_title _('Packages & Registries')
+ end
+
+ it 'sidebar menu is open' do
+ visit_settings_page
+
+ sidebar = find('.nav-sidebar')
+ expect(sidebar).to have_link _('Packages & Registries')
+ end
+ end
+
+ def find_settings_menu
+ find('ul[data-testid="group-settings-menu"]')
+ end
+
+ def visit_settings_page
+ visit group_settings_packages_and_registries_path(group)
+ end
+end
diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb
index 3ec7717b649..96f8cf0062c 100644
--- a/spec/features/incidents/incident_details_spec.rb
+++ b/spec/features/incidents/incident_details_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe 'Incident details', :js do
expect(page).to have_selector('.right-sidebar[data-issuable-type="issue"]')
expect(sidebar).to have_selector('.incident-severity')
- expect(sidebar).not_to have_selector('.milestone')
+ expect(sidebar).to have_selector('.milestone')
end
end
end
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 07bf821a590..9b2a11c4b0e 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -294,6 +294,15 @@ RSpec.describe 'GFM autocomplete', :js do
user_item = find('.atwho-view li', text: user.username)
expect(user_item).to have_content(user.username)
end
+
+ it 'does not limit quick actions autocomplete list to 5' do
+ note = find('#note-body')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('/')
+ end
+
+ expect(page).to have_selector('.atwho-view li', minimum: 6, visible: true)
+ end
end
context 'assignees' do
@@ -426,36 +435,16 @@ RSpec.describe 'GFM autocomplete', :js do
visit project_issue_path(project, issue)
note = find('#note-body')
- start_comment_with_emoji(note)
+ start_comment_with_emoji(note, '.atwho-view li')
start_and_cancel_discussion
note.fill_in(with: '')
- start_comment_with_emoji(note)
+ start_comment_with_emoji(note, '.atwho-view li')
note.native.send_keys(:enter)
expect(note.value).to eql('Hello :100: ')
end
-
- def start_comment_with_emoji(note)
- note.native.send_keys('Hello :10')
-
- wait_for_requests
-
- find('.atwho-view li', text: '100')
- end
-
- def start_and_cancel_discussion
- click_button('Reply...')
-
- fill_in('note_note', with: 'Whoops!')
-
- page.accept_alert 'Are you sure you want to cancel creating this comment?' do
- click_button('Cancel')
- end
-
- wait_for_requests
- end
end
shared_examples 'autocomplete suggestions' do
@@ -599,6 +588,33 @@ RSpec.describe 'GFM autocomplete', :js do
expect(page).not_to have_selector('.tribute-container', visible: true)
end
+ it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do
+ note = find('#note-body')
+
+ # Number.
+ page.within '.timeline-content-form' do
+ note.native.send_keys('7:')
+ end
+
+ expect(page).not_to have_selector('.tribute-container', visible: true)
+
+ # ASCII letter.
+ page.within '.timeline-content-form' do
+ note.set('')
+ note.native.send_keys('w:')
+ end
+
+ expect(page).not_to have_selector('.tribute-container', visible: true)
+
+ # Non-ASCII letter.
+ page.within '.timeline-content-form' do
+ note.set('')
+ note.native.send_keys('Ð:')
+ end
+
+ expect(page).not_to have_selector('.tribute-container', visible: true)
+ end
+
it 'selects the first item for assignee dropdowns' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('@')
@@ -624,6 +640,16 @@ RSpec.describe 'GFM autocomplete', :js do
expect(find('.tribute-container ul', 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')
+ end
+
+ wait_for_requests
+
+ expect(find('.tribute-container ul', visible: true)).to have_selector('.highlight:first-of-type')
+ end
+
context 'when autocompleting for groups' do
it 'shows the group when searching for the name of the group' do
page.within '.timeline-content-form' do
@@ -687,20 +713,34 @@ RSpec.describe 'GFM autocomplete', :js do
expect_to_wrap(false, user_item, note, user.username)
end
- it 'triggers autocomplete after selecting a quick action' do
+ it 'does not wrap for emoji values' do
note = find('#note-body')
page.within '.timeline-content-form' do
- note.native.send_keys('/as')
+ note.native.send_keys(":cartwheel_")
end
- find('.atwho-view li', text: '/assign')
- note.native.send_keys(:tab)
- note.native.send_keys(:right)
+ emoji_item = first('.tribute-container li', text: 'cartwheel_tone1', visible: true)
- wait_for_requests
+ expect_to_wrap(false, emoji_item, note, 'cartwheel_tone1')
+ end
- user_item = find('.tribute-container ul', text: user.username, visible: true)
- expect(user_item).to have_content(user.username)
+ it 'does not open autocomplete if there is no space before' do
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys("hello:#{user.username[0..2]}")
+ end
+
+ expect(page).not_to have_selector('.tribute-container')
+ end
+
+ it 'autocompletes for quick actions' do
+ note = find('#note-body')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('/as')
+ wait_for_requests
+ note.native.send_keys(:tab)
+ end
+
+ expect(note.value).to have_text('/assign')
end
end
@@ -719,15 +759,14 @@ RSpec.describe 'GFM autocomplete', :js do
note = find('#note-body')
page.within '.timeline-content-form' do
- note.native.send_keys('/as')
+ note.native.send_keys('/assign ')
+ # The `/assign` ajax response might replace the one by `@` below causing a failed test
+ # so we need to wait for the `/assign` ajax request to finish first
+ wait_for_requests
+ note.native.send_keys('@')
+ wait_for_requests
end
- find('.atwho-view li', text: '/assign')
- note.native.send_keys(:tab)
- note.native.send_keys(:right)
-
- wait_for_requests
-
expect(find('.tribute-container ul', visible: true)).not_to have_content(user.username)
expect(find('.tribute-container ul', visible: true)).to have_content(unassigned_user.username)
end
@@ -739,12 +778,14 @@ RSpec.describe 'GFM autocomplete', :js do
page.within '.timeline-content-form' do
note.native.send_keys('/assign @user2')
note.native.send_keys(:enter)
- note.native.send_keys('/assign @')
- note.native.send_keys(:right)
+ note.native.send_keys('/assign ')
+ # The `/assign` ajax response might replace the one by `@` below causing a failed test
+ # so we need to wait for the `/assign` ajax request to finish first
+ wait_for_requests
+ note.native.send_keys('@')
+ wait_for_requests
end
- wait_for_requests
-
expect(find('.tribute-container ul', visible: true)).not_to have_content(user.username)
expect(find('.tribute-container ul', visible: true)).to have_content(unassigned_user.username)
end
@@ -824,6 +865,26 @@ RSpec.describe 'GFM autocomplete', :js do
end
end
+ context 'when other notes are destroyed' do
+ let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+
+ # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
+ it 'keeps autocomplete key listeners' do
+ visit project_issue_path(project, issue)
+ note = find('#note-body')
+
+ start_comment_with_emoji(note, '.tribute-container li')
+
+ start_and_cancel_discussion
+
+ note.fill_in(with: '')
+ start_comment_with_emoji(note, '.tribute-container li')
+ note.native.send_keys(:enter)
+
+ expect(note.value).to eql('Hello :100: ')
+ end
+ end
+
shared_examples 'autocomplete suggestions' do
it 'suggests objects correctly' do
page.within '.timeline-content-form' do
@@ -913,4 +974,24 @@ RSpec.describe 'GFM autocomplete', :js do
note.native.send_keys(text)
end
end
+
+ def start_comment_with_emoji(note, selector)
+ note.native.send_keys('Hello :10')
+
+ wait_for_requests
+
+ find(selector, text: '100')
+ end
+
+ def start_and_cancel_discussion
+ click_button('Reply...')
+
+ fill_in('note_note', with: 'Whoops!')
+
+ page.accept_alert 'Are you sure you want to cancel creating this comment?' do
+ click_button('Cancel')
+ end
+
+ wait_for_requests
+ end
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index 94a1de06488..59fba5f65e0 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -13,256 +13,280 @@ RSpec.describe 'Issue Sidebar' do
let!(:xss_label) { create(:label, project: project, title: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
before do
- sign_in(user)
+ stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
end
- context 'when concerning the assignee', :js do
- let(:user2) { create(:user) }
- let(:issue2) { create(:issue, project: project, author: user2) }
-
- include_examples 'issuable invite members experiments' do
- let(:issuable_path) { project_issue_path(project, issue2) }
+ context 'when signed in' do
+ before do
+ sign_in(user)
end
- context 'when user is a developer' do
- before do
- project.add_developer(user)
- visit_issue(project, issue2)
-
- find('.block.assignee .edit-link').click
+ context 'when concerning the assignee', :js do
+ let(:user2) { create(:user) }
+ let(:issue2) { create(:issue, project: project, author: user2) }
- wait_for_requests
+ include_examples 'issuable invite members experiments' do
+ let(:issuable_path) { project_issue_path(project, issue2) }
end
- it 'shows author in assignee dropdown' do
- page.within '.dropdown-menu-user' do
- expect(page).to have_content(user2.name)
- end
- end
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ visit_issue(project, issue2)
- it 'shows author when filtering assignee dropdown' do
- page.within '.dropdown-menu-user' do
- find('.dropdown-input-field').set(user2.name)
+ find('.block.assignee .edit-link').click
wait_for_requests
+ end
- expect(page).to have_content(user2.name)
+ it 'shows author in assignee dropdown' do
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_content(user2.name)
+ end
end
- end
- it 'assigns yourself' do
- find('.block.assignee .dropdown-menu-toggle').click
+ it 'shows author when filtering assignee dropdown' do
+ page.within '.dropdown-menu-user' do
+ find('.dropdown-input-field').set(user2.name)
- click_button 'assign yourself'
+ wait_for_requests
- wait_for_requests
+ expect(page).to have_content(user2.name)
+ end
+ end
- find('.block.assignee .edit-link').click
+ it 'assigns yourself' do
+ find('.block.assignee .dropdown-menu-toggle').click
- page.within '.dropdown-menu-user' do
- expect(page.find('.dropdown-header')).to be_visible
- expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
- end
- end
+ click_button 'assign yourself'
- it 'keeps your filtered term after filtering and dismissing the dropdown' do
- find('.dropdown-input-field').set(user2.name)
+ wait_for_requests
- wait_for_requests
+ find('.block.assignee .edit-link').click
- page.within '.dropdown-menu-user' do
- expect(page).not_to have_content 'Unassigned'
- click_link user2.name
+ page.within '.dropdown-menu-user' do
+ expect(page.find('.dropdown-header')).to be_visible
+ expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
+ end
end
- find('.js-right-sidebar').click
- find('.block.assignee .edit-link').click
-
- expect(page.all('.dropdown-menu-user li').length).to eq(1)
- expect(find('.dropdown-input-field').value).to eq(user2.name)
- end
- end
+ it 'keeps your filtered term after filtering and dismissing the dropdown' do
+ find('.dropdown-input-field').set(user2.name)
- it 'shows label text as "Apply" when assignees are changed' do
- project.add_developer(user)
- visit_issue(project, issue2)
+ wait_for_requests
- find('.block.assignee .edit-link').click
- wait_for_requests
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_content 'Unassigned'
+ click_link user2.name
+ end
- click_on 'Unassigned'
+ find('.js-right-sidebar').click
+ find('.block.assignee .edit-link').click
- expect(page).to have_link('Apply')
- end
- end
+ expect(page.all('.dropdown-menu-user li').length).to eq(1)
+ expect(find('.dropdown-input-field').value).to eq(user2.name)
+ end
+ end
- context 'as a allowed user' do
- before do
- project.add_developer(user)
- visit_issue(project, issue)
- end
+ it 'shows label text as "Apply" when assignees are changed' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
- context 'sidebar', :js do
- it 'changes size when the screen size is smaller' do
- sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
- # Resize the window
- resize_screen_sm
- # Make sure the sidebar is collapsed
- find(sidebar_selector)
- expect(page).to have_css(sidebar_selector)
- # Once is collapsed let's open the sidebard and reload
- open_issue_sidebar
- refresh
- find(sidebar_selector)
- expect(page).to have_css(sidebar_selector)
- # Restore the window size as it was including the sidebar
- restore_window_size
- open_issue_sidebar
- end
+ find('.block.assignee .edit-link').click
+ wait_for_requests
- it 'escapes XSS when viewing issue labels' do
- page.within('.block.labels') do
- click_on 'Edit'
+ click_on 'Unassigned'
- expect(page).to have_content '<script>alert("xss");</script>'
- end
+ expect(page).to have_link('Apply')
end
end
- context 'editing issue labels', :js do
+ context 'as a allowed user' do
before do
- issue.update(labels: [label])
- page.within('.block.labels') do
- click_on 'Edit'
- end
+ project.add_developer(user)
+ visit_issue(project, issue)
end
- it 'shows the current set of labels' do
- page.within('.issuable-show-labels') do
- expect(page).to have_content label.title
+ context 'sidebar', :js do
+ it 'changes size when the screen size is smaller' do
+ sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
+ # Resize the window
+ resize_screen_sm
+ # Make sure the sidebar is collapsed
+ find(sidebar_selector)
+ expect(page).to have_css(sidebar_selector)
+ # Once is collapsed let's open the sidebard and reload
+ open_issue_sidebar
+ refresh
+ find(sidebar_selector)
+ expect(page).to have_css(sidebar_selector)
+ # Restore the window size as it was including the sidebar
+ restore_window_size
+ open_issue_sidebar
end
- end
- it 'shows option to create a project label' do
- page.within('.block.labels') do
- expect(page).to have_content 'Create project'
+ it 'escapes XSS when viewing issue labels' do
+ page.within('.block.labels') do
+ click_on 'Edit'
+
+ expect(page).to have_content '<script>alert("xss");</script>'
+ end
end
end
- context 'creating a project label', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/27992' do
+ context 'editing issue labels', :js do
before do
+ issue.update(labels: [label])
page.within('.block.labels') do
- click_link 'Create project'
+ click_on 'Edit'
end
end
- it 'shows dropdown switches to "create label" section' do
- page.within('.block.labels') do
- expect(page).to have_content 'Create project label'
+ it 'shows the current set of labels' do
+ page.within('.issuable-show-labels') do
+ expect(page).to have_content label.title
end
end
- it 'adds new label' do
+ it 'shows option to create a project label' do
page.within('.block.labels') do
- fill_in 'new_label_name', with: 'wontfix'
- page.find('.suggest-colors a', match: :first).click
- page.find('button', text: 'Create').click
+ expect(page).to have_content 'Create project'
+ end
+ end
- page.within('.dropdown-page-one') do
- expect(page).to have_content 'wontfix'
+ context 'creating a project label', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/27992' do
+ before do
+ page.within('.block.labels') do
+ click_link 'Create project'
end
end
- end
- it 'shows error message if label title is taken' do
- page.within('.block.labels') do
- fill_in 'new_label_name', with: label.title
- page.find('.suggest-colors a', match: :first).click
- page.find('button', text: 'Create').click
+ it 'shows dropdown switches to "create label" section' do
+ page.within('.block.labels') do
+ expect(page).to have_content 'Create project label'
+ end
+ end
+
+ it 'adds new label' do
+ page.within('.block.labels') do
+ fill_in 'new_label_name', with: 'wontfix'
+ page.find('.suggest-colors a', match: :first).click
+ page.find('button', text: 'Create').click
+
+ page.within('.dropdown-page-one') do
+ expect(page).to have_content 'wontfix'
+ end
+ end
+ end
- page.within('.dropdown-page-two') do
- expect(page).to have_content 'Title has already been taken'
+ it 'shows error message if label title is taken' do
+ page.within('.block.labels') do
+ fill_in 'new_label_name', with: label.title
+ page.find('.suggest-colors a', match: :first).click
+ page.find('button', text: 'Create').click
+
+ page.within('.dropdown-page-two') do
+ expect(page).to have_content 'Title has already been taken'
+ end
end
end
end
end
- end
- context 'interacting with collapsed sidebar', :js do
- collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
- expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded'
- confidentiality_sidebar_block = '.block.confidentiality'
- lock_sidebar_block = '.block.lock'
- collapsed_sidebar_block_icon = '.sidebar-collapsed-icon'
+ context 'interacting with collapsed sidebar', :js do
+ collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
+ expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded'
+ confidentiality_sidebar_block = '.block.confidentiality'
+ lock_sidebar_block = '.block.lock'
+ collapsed_sidebar_block_icon = '.sidebar-collapsed-icon'
- before do
- resize_screen_sm
- end
+ before do
+ resize_screen_sm
+ end
- it 'confidentiality block expands then collapses sidebar' do
- expect(page).to have_css(collapsed_sidebar_selector)
+ it 'confidentiality block expands then collapses sidebar' do
+ expect(page).to have_css(collapsed_sidebar_selector)
- page.within(confidentiality_sidebar_block) do
- find(collapsed_sidebar_block_icon).click
+ page.within(confidentiality_sidebar_block) do
+ find(collapsed_sidebar_block_icon).click
+ end
+
+ expect(page).to have_css(expanded_sidebar_selector)
+
+ page.within(confidentiality_sidebar_block) do
+ page.find('button', text: 'Cancel').click
+ end
+
+ expect(page).to have_css(collapsed_sidebar_selector)
end
- expect(page).to have_css(expanded_sidebar_selector)
+ it 'lock block expands then collapses sidebar' do
+ expect(page).to have_css(collapsed_sidebar_selector)
+
+ page.within(lock_sidebar_block) do
+ find(collapsed_sidebar_block_icon).click
+ end
+
+ expect(page).to have_css(expanded_sidebar_selector)
+
+ page.within(lock_sidebar_block) do
+ page.find('button', text: 'Cancel').click
+ end
- page.within(confidentiality_sidebar_block) do
- page.find('button', text: 'Cancel').click
+ expect(page).to have_css(collapsed_sidebar_selector)
end
+ end
+ end
- expect(page).to have_css(collapsed_sidebar_selector)
+ context 'as a guest' do
+ before do
+ project.add_guest(user)
+ visit_issue(project, issue)
end
- it 'lock block expands then collapses sidebar' do
- expect(page).to have_css(collapsed_sidebar_selector)
+ it 'does not have a option to edit labels' do
+ expect(page).not_to have_selector('.block.labels .js-sidebar-dropdown-toggle')
+ end
- page.within(lock_sidebar_block) do
- find(collapsed_sidebar_block_icon).click
+ context 'sidebar', :js do
+ it 'finds issue copy forwarding email' do
+ expect(find('[data-qa-selector="copy-forward-email"]').text).to eq "Issue email: #{issue.creatable_note_email_address(user)}"
end
+ end
- expect(page).to have_css(expanded_sidebar_selector)
+ context 'interacting with collapsed sidebar', :js do
+ collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
+ expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded'
+ lock_sidebar_block = '.block.lock'
+ lock_button = '.block.lock .btn-close'
+ collapsed_sidebar_block_icon = '.sidebar-collapsed-icon'
- page.within(lock_sidebar_block) do
- page.find('button', text: 'Cancel').click
+ before do
+ resize_screen_sm
end
- expect(page).to have_css(collapsed_sidebar_selector)
- end
- end
- end
+ it 'expands then does not show the lock dialog form' do
+ expect(page).to have_css(collapsed_sidebar_selector)
- context 'as a guest' do
- before do
- project.add_guest(user)
- visit_issue(project, issue)
- end
+ page.within(lock_sidebar_block) do
+ find(collapsed_sidebar_block_icon).click
+ end
- it 'does not have a option to edit labels' do
- expect(page).not_to have_selector('.block.labels .js-sidebar-dropdown-toggle')
+ expect(page).to have_css(expanded_sidebar_selector)
+ expect(page).not_to have_selector(lock_button)
+ end
+ end
end
+ end
- context 'interacting with collapsed sidebar', :js do
- collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
- expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded'
- lock_sidebar_block = '.block.lock'
- lock_button = '.block.lock .btn-close'
- collapsed_sidebar_block_icon = '.sidebar-collapsed-icon'
-
+ context 'when not signed in' do
+ context 'sidebar', :js do
before do
- resize_screen_sm
+ visit_issue(project, issue)
end
- it 'expands then does not show the lock dialog form' do
- expect(page).to have_css(collapsed_sidebar_selector)
-
- page.within(lock_sidebar_block) do
- find(collapsed_sidebar_block_icon).click
- end
-
- expect(page).to have_css(expanded_sidebar_selector)
- expect(page).not_to have_selector(lock_button)
+ it 'does not find issue email' do
+ expect(page).not_to have_selector('[data-qa-selector="copy-forward-email"]')
end
end
end
diff --git a/spec/features/issues/issue_state_spec.rb b/spec/features/issues/issue_state_spec.rb
index 0ef6eb56dff..d5a115433aa 100644
--- a/spec/features/issues/issue_state_spec.rb
+++ b/spec/features/issues/issue_state_spec.rb
@@ -13,10 +13,13 @@ RSpec.describe 'issue state', :js do
shared_examples 'issue closed' do |selector|
it 'can close an issue' do
+ wait_for_requests
+
expect(find('.status-box')).to have_content 'Open'
within selector do
click_button 'Close issue'
+ wait_for_requests
end
expect(find('.status-box')).to have_content 'Closed'
@@ -25,17 +28,20 @@ RSpec.describe 'issue state', :js do
shared_examples 'issue reopened' do |selector|
it 'can reopen an issue' do
+ wait_for_requests
+
expect(find('.status-box')).to have_content 'Closed'
within selector do
click_button 'Reopen issue'
+ wait_for_requests
end
expect(find('.status-box')).to have_content 'Open'
end
end
- describe 'when open' do
+ 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) }
@@ -57,7 +63,7 @@ RSpec.describe 'issue state', :js do
end
end
- describe 'when closed' do
+ 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') }
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 005d45d9c92..24a261f592b 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe "User comments on issue", :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(tribute_autocomplete: false)
project.add_guest(user)
sign_in(user)
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 668b4265948..98f9ed6c6a2 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -223,8 +223,8 @@ RSpec.describe "User creates issue" do
expect(page).not_to have_selector('.epic-dropdown-container')
end
- it 'hides the milestone select' do
- expect(page).not_to have_selector('.qa-issuable-milestone-dropdown')
+ it 'shows the milestone select' do
+ expect(page).to have_selector('.qa-issuable-milestone-dropdown')
end
it 'hides the weight input' do
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 6376f9ab5fd..2b94c072c8b 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
@@ -55,7 +55,7 @@ RSpec.describe 'User closes/reopens a merge request', :js do
end
end
- describe 'when closed' do
+ 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') }
diff --git a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
index 782a7e3bfb6..ac0c66524f0 100644
--- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
+++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
@@ -69,7 +69,8 @@ RSpec.describe 'Batch diffs', :js do
end
context 'which is in at least page 2 of the batched pages of diffs' do
- it 'scrolls to the correct discussion' do
+ it 'scrolls to the correct discussion',
+ quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/293814' } do
page.within('.diff-file.file-holder:last-of-type') do
click_link('just now')
end
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index cb7c952dfe4..b86586d53e2 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -228,6 +228,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
page.find('.discussion-next-btn').click
end
+ expect(page).to have_button('Resolve thread', visible: true)
expect(page.evaluate_script("window.pageYOffset")).to be > 0
end
diff --git a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb
index d9950f5504b..56517a97716 100644
--- a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb
+++ b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb
@@ -17,15 +17,16 @@ RSpec.describe 'Merge request > User scrolls to note on load', :js do
it 'scrolls note into view' do
visit "#{project_merge_request_path(project, merge_request)}#{fragment_id}"
- wait_for_requests
+ wait_for_all_requests
+
+ expect(page).to have_selector("#{fragment_id}")
- page_height = page.current_window.size[1]
page_scroll_y = page.evaluate_script("window.scrollY")
- fragment_position_top = page.evaluate_script("Math.round($('#{fragment_id}').offset().top)")
+ fragment_position_top = page.evaluate_script("Math.round(document.querySelector('#{fragment_id}').getBoundingClientRect().top + window.pageYOffset)")
expect(find(fragment_id).visible?).to eq true
expect(fragment_position_top).to be >= page_scroll_y
- expect(fragment_position_top).to be < (page_scroll_y + page_height)
+ expect(page.evaluate_script("window.pageYOffset")).to be > 0
end
it 'renders un-collapsed notes with diff' do
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 6647a4e9291..d9743f6f330 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
@@ -62,7 +62,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 2)
- expect(first('.js-pipeline-url-link')).to have_content("##{detached_merge_request_pipeline.id}")
+ expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -97,16 +97,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 4)
- expect(all('.js-pipeline-url-link')[0])
+ expect(all('[data-testid="pipeline-url-link"]')[0])
.to have_content("##{detached_merge_request_pipeline_2.id}")
- expect(all('.js-pipeline-url-link')[1])
+ expect(all('[data-testid="pipeline-url-link"]')[1])
.to have_content("##{detached_merge_request_pipeline.id}")
- expect(all('.js-pipeline-url-link')[2])
+ expect(all('[data-testid="pipeline-url-link"]')[2])
.to have_content("##{push_pipeline_2.id}")
- expect(all('.js-pipeline-url-link')[3])
+ expect(all('[data-testid="pipeline-url-link"]')[3])
.to have_content("##{push_pipeline.id}")
end
end
@@ -197,7 +197,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees a branch pipeline in pipeline tab' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 1)
- expect(first('.js-pipeline-url-link')).to have_content("##{push_pipeline.id}")
+ expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{push_pipeline.id}")
end
end
@@ -246,7 +246,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 2)
- expect(first('.js-pipeline-url-link')).to have_content("##{detached_merge_request_pipeline.id}")
+ expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -287,16 +287,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 4)
- expect(all('.js-pipeline-url-link')[0])
+ expect(all('[data-testid="pipeline-url-link"]')[0])
.to have_content("##{detached_merge_request_pipeline_2.id}")
- expect(all('.js-pipeline-url-link')[1])
+ expect(all('[data-testid="pipeline-url-link"]')[1])
.to have_content("##{detached_merge_request_pipeline.id}")
- expect(all('.js-pipeline-url-link')[2])
+ expect(all('[data-testid="pipeline-url-link"]')[2])
.to have_content("##{push_pipeline_2.id}")
- expect(all('.js-pipeline-url-link')[3])
+ expect(all('[data-testid="pipeline-url-link"]')[3])
.to have_content("##{push_pipeline.id}")
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 0e8012f161f..c2b2ada47be 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -605,11 +605,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
within(".js-report-section-container") do
click_button 'addTest'
-
- expect(page).to have_content('6.66')
- expect(page).to have_content(sample_java_failed_message.gsub(/\s+/, ' ').strip)
end
end
+
+ within("#modal-mrwidget-reports") do
+ expect(page).to have_content('addTest')
+ expect(page).to have_content('6.66')
+ expect(page).to have_content(sample_java_failed_message.gsub(/\s+/, ' ').strip)
+ end
end
end
end
@@ -650,11 +653,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
within(".js-report-section-container") do
click_button 'Test#sum when a is 1 and b is 3 returns summary'
-
- expect(page).to have_content('2.22')
- expect(page).to have_content(sample_rspec_failed_message.gsub(/\s+/, ' ').strip)
end
end
+
+ within("#modal-mrwidget-reports") do
+ expect(page).to have_content('Test#sum when a is 1 and b is 3 returns summary')
+ expect(page).to have_content('2.22')
+ expect(page).to have_content(sample_rspec_failed_message.gsub(/\s+/, ' ').strip)
+ end
end
end
end
@@ -694,10 +700,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
within(".js-report-section-container") do
click_button 'addTest'
-
- expect(page).to have_content('5.55')
end
end
+
+ within("#modal-mrwidget-reports") do
+ expect(page).to have_content('addTest')
+ expect(page).to have_content('5.55')
+ end
end
end
end
@@ -738,10 +747,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
within(".js-report-section-container") do
click_button 'addTest'
-
- expect(page).to have_content('8.88')
end
end
+
+ within("#modal-mrwidget-reports") do
+ expect(page).to have_content('addTest')
+ expect(page).to have_content('8.88')
+ end
end
end
end
@@ -782,10 +794,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
within(".js-report-section-container") do
click_button 'Test#sum when a is 4 and b is 4 returns summary'
-
- expect(page).to have_content('4.44')
end
end
+
+ within("#modal-mrwidget-reports") do
+ expect(page).to have_content('Test#sum when a is 4 and b is 4 returns summary')
+ expect(page).to have_content('4.44')
+ end
end
end
end
@@ -825,10 +840,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
within(".js-report-section-container") do
click_button 'addTest'
-
- expect(page).to have_content('5.55')
end
end
+
+ within("#modal-mrwidget-reports") do
+ expect(page).to have_content('addTest')
+ expect(page).to have_content('5.55')
+ end
end
end
end
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 107fc002ebd..77d2cb77ae3 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -184,7 +184,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
page.within(first('.commit')) do
page.within('.pipeline-tags') do
- expect(page.find('.js-pipeline-url-link')[:href]).to include(expected_project.full_path)
+ expect(page.find('[data-testid="pipeline-url-link"]')[:href]).to include(expected_project.full_path)
expect(page).to have_content('detached')
end
page.within('.pipeline-triggerer') do
@@ -238,11 +238,15 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
threads = []
threads << Thread.new do
- @merge_request = MergeRequests::CreateService.new(project, user, merge_request_params).execute
+ Sidekiq::Worker.skipping_transaction_check do
+ @merge_request = MergeRequests::CreateService.new(project, user, merge_request_params).execute
+ end
end
threads << Thread.new do
- @pipeline = Ci::CreatePipelineService.new(project, user, build_push_data).execute(:push)
+ Sidekiq::Worker.skipping_transaction_check do
+ @pipeline = Ci::CreatePipelineService.new(project, user, build_push_data).execute(:push)
+ end
end
threads.each { |thr| thr.join }
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 8930c55a28c..8999c4d6656 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -191,7 +191,7 @@ RSpec.describe 'Merge request > User sees versions', :js do
find('.btn-default').click
click_link 'version 1'
end
- expect(page).to have_content '0 files'
+ expect(page).to have_content 'No changes between version 1 and version 1'
end
end
@@ -217,7 +217,7 @@ RSpec.describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'version 1'
end
- expect(page).to have_content '0 files'
+ expect(page).to have_content 'No changes between version 1 and version 1'
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 1e1888cd826..a2ec34335ec 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
@@ -87,6 +87,7 @@ RSpec.describe 'User comments on a diff', :js do
expect(page).not_to have_content('Applied')
click_button('Apply suggestion')
+ click_button('Apply')
wait_for_requests
expect(page).to have_content('Applied')
@@ -338,6 +339,7 @@ RSpec.describe 'User comments on a diff', :js do
expect(page).not_to have_content('Applied')
click_button('Apply suggestion')
+ click_button('Apply')
wait_for_requests
expect(page).to have_content('Applied')
@@ -349,6 +351,7 @@ RSpec.describe 'User comments on a diff', :js do
expect(page).not_to have_content('Unresolve thread')
click_button('Apply suggestion')
+ click_button('Apply')
wait_for_requests
expect(page).to have_content('Unresolve thread')
diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb
index 04a2e046f42..b48659353ec 100644
--- a/spec/features/merge_request/user_uses_quick_actions_spec.rb
+++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb
@@ -41,5 +41,6 @@ RSpec.describe 'Merge request > User uses quick actions', :js do
end
it_behaves_like 'merge quick action'
+ it_behaves_like 'rebase quick action'
end
end
diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb
index 466c7ba215e..ccffe25f45e 100644
--- a/spec/features/projects/ci/lint_spec.rb
+++ b/spec/features/projects/ci/lint_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'CI Lint', :js do
end
it 'parses Yaml and displays the jobs' do
- expect(page).to have_content('Status: syntax is correct')
+ expect(page).to have_content('Status: Syntax is correct')
within "table" do
aggregate_failures do
@@ -51,7 +51,7 @@ RSpec.describe 'CI Lint', :js do
let(:yaml_content) { 'value: cannot have :' }
it 'displays information about an error' do
- expect(page).to have_content('Status: syntax is incorrect')
+ expect(page).to have_content('Status: Syntax is incorrect')
expect(page).to have_selector(content_selector, text: yaml_content)
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 ca4e070703b..f3c364dab97 100644
--- a/spec/features/projects/commit/user_reverts_commit_spec.rb
+++ b/spec/features/projects/commit/user_reverts_commit_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
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(:user) { create(:user) }
before do
sign_in(user)
@@ -14,49 +14,37 @@ RSpec.describe 'User reverts a commit', :js do
visit(project_commit_path(project, sample_commit.id))
end
- def click_revert
+ def revert_commit(create_merge_request: false)
find('.header-action-buttons .dropdown').click
- find('a[href="#modal-revert-commit"]').click
- end
+ find('[data-testid="revert-commit-link"]').click
- context 'without creating a new merge request' do
- before do
- click_revert
- page.within('#modal-revert-commit') do
- uncheck('create_merge_request')
- click_button('Revert')
- end
+ page.within('[data-testid="modal-commit"]') do
+ uncheck('create_merge_request') unless create_merge_request
+ click_button('Revert')
end
+ 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)
- find('.header-action-buttons .dropdown').click
- find('a[href="#modal-revert-commit"]').click
-
- 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 commit automatically.')
end
end
context 'with creating a new merge request' do
- before do
- click_revert
- end
-
it 'reverts a commit' do
- page.within('#modal-revert-commit') do
- click_button('Revert')
- end
+ 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")
diff --git a/spec/features/projects/environments_pod_logs_spec.rb b/spec/features/projects/environments_pod_logs_spec.rb
index c491cd62d85..eaef3e6ca28 100644
--- a/spec/features/projects/environments_pod_logs_spec.rb
+++ b/spec/features/projects/environments_pod_logs_spec.rb
@@ -17,6 +17,8 @@ RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do
stub_kubeclient_pods(environment.deployment_namespace)
stub_kubeclient_logs(pod_name, environment.deployment_namespace, container: 'container-0')
+ stub_kubeclient_deployments(environment.deployment_namespace)
+ stub_kubeclient_ingresses(environment.deployment_namespace)
stub_kubeclient_nodes_and_nodes_metrics(cluster.platform.api_url)
sign_in(project.owner)
diff --git a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb
index 750f4dc5ef4..f5941d0ff15 100644
--- a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb
+++ b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb
@@ -25,7 +25,6 @@ RSpec.describe 'User sees feature flag list', :js do
create_flag(project, 'mr_train', true).tap do |feature_flag|
create_scope(feature_flag, 'production', false)
end
- stub_feature_flags(feature_flags_legacy_read_only_override: false)
end
it 'user sees the first flag' do
@@ -79,41 +78,6 @@ RSpec.describe 'User sees feature flag list', :js do
expect_status_toggle_button_to_be_disabled
end
end
-
- context 'when legacy feature flags are not read-only' do
- before do
- stub_feature_flags(feature_flags_legacy_read_only: false)
- end
-
- it 'user updates the status toggle' do
- visit(project_feature_flags_path(project))
-
- within_feature_flag_row(1) do
- status_toggle_button.click
-
- expect_status_toggle_button_to_be_checked
- end
- end
- end
-
- context 'when legacy feature flags are read-only but the override is active for a project' do
- before do
- stub_feature_flags(
- feature_flags_legacy_read_only: true,
- feature_flags_legacy_read_only_override: project
- )
- end
-
- it 'user updates the status toggle' do
- visit(project_feature_flags_path(project))
-
- within_feature_flag_row(1) do
- status_toggle_button.click
-
- expect_status_toggle_button_to_be_checked
- end
- end
- end
end
context 'with new version flags' do
diff --git a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb
index bc2d63e1953..a435e565ff1 100644
--- a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb
+++ b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb
@@ -14,8 +14,7 @@ RSpec.describe 'User updates feature flag', :js do
before do
stub_feature_flags(
- feature_flag_permissions: false,
- feature_flags_legacy_read_only_override: false
+ feature_flag_permissions: false
)
sign_in(user)
end
@@ -79,117 +78,11 @@ RSpec.describe 'User updates feature flag', :js do
let!(:scope) { create_scope(feature_flag, 'review/*', true) }
- context 'when legacy flags are editable' do
- before do
- stub_feature_flags(feature_flags_legacy_read_only: false)
-
- visit(edit_project_feature_flag_path(project, feature_flag))
- end
-
- it 'user sees persisted default scope' do
- within_scope_row(1) do
- within_environment_spec do
- expect(page).to have_content('* (All Environments)')
- end
-
- within_status do
- expect(find('.project-feature-toggle')['aria-label'])
- .to eq('Toggle Status: ON')
- end
- end
- end
-
- context 'when user updates the status of a scope' do
- before do
- within_scope_row(2) do
- within_status { find('.project-feature-toggle').click }
- end
-
- click_button 'Save changes'
- expect(page).to have_current_path(project_feature_flags_path(project))
- end
-
- it 'shows the updated feature flag' do
- within_feature_flag_row(1) do
- expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
- expect_status_toggle_button_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('.badge:nth-child(1)')).to have_content('*')
- expect(page.find('.badge:nth-child(1)')['class']).to include('badge-info')
- expect(page.find('.badge:nth-child(2)')).to have_content('review/*')
- expect(page.find('.badge:nth-child(2)')['class']).to include('badge-muted')
- end
- end
- end
- end
-
- context 'when user adds a new scope' do
- before do
- within_scope_row(3) do
- within_environment_spec do
- find('.js-env-search > input').set('production')
- find('.js-create-button').click
- end
- end
-
- click_button 'Save changes'
- expect(page).to have_current_path(project_feature_flags_path(project))
- end
-
- it 'shows the newly created scope' do
- within_feature_flag_row(1) do
- within_feature_flag_scopes do
- expect(page.find('.badge:nth-child(3)')).to have_content('production')
- expect(page.find('.badge:nth-child(3)')['class']).to include('badge-muted')
- end
- end
- end
- end
-
- context 'when user deletes a scope' do
- before do
- within_scope_row(2) do
- within_delete { find('.js-delete-scope').click }
- end
-
- click_button 'Save changes'
- expect(page).to have_current_path(project_feature_flags_path(project))
- end
-
- it 'shows the updated feature flag' do
- within_feature_flag_row(1) do
- within_feature_flag_scopes do
- expect(page).to have_css('.badge:nth-child(1)')
- expect(page).not_to have_css('.badge:nth-child(2)')
- end
- end
- end
- end
- end
-
- context 'when legacy flags are read-only' do
- it 'the user cannot edit the flag' do
- visit(edit_project_feature_flag_path(project, feature_flag))
-
- expect(page).to have_text 'This feature flag is read-only, and it will be removed in 14.0.'
- expect(page).to have_css('button.js-ff-submit.disabled')
- end
- end
-
- context 'when legacy flags are read-only, but the override is active for one project' do
- it 'the user can edit the flag' do
- stub_feature_flags(feature_flags_legacy_read_only_override: project)
-
- visit(edit_project_feature_flag_path(project, feature_flag))
- status_toggle_button.click
- click_button 'Save changes'
+ it 'the user cannot edit the flag' do
+ visit(edit_project_feature_flag_path(project, feature_flag))
- expect(page).to have_current_path(project_feature_flags_path(project))
- within_feature_flag_row(1) do
- expect_status_toggle_button_not_to_be_checked
- end
- end
+ expect(page).to have_text 'This feature flag is read-only, and it will be removed in 14.0.'
+ expect(page).to have_css('button.js-ff-submit.disabled')
end
end
end
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index a99df8a79d8..17258f7042f 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Projects > Files > User wants to add a Dockerfile file' do
+RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297400' do
before do
project = create(:project, :repository)
sign_in project.owner
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
new file mode 100644
index 00000000000..6308acb41f5
--- /dev/null
+++ b/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do
+ before do
+ project = create(:project, :repository)
+ sign_in project.owner
+ stub_experiment(ci_syntax_templates: experiment_active)
+ stub_experiment_for_subject(ci_syntax_templates: in_experiment_group)
+
+ visit project_new_blob_path(project, 'master', file_name: '.gitlab-ci.yml')
+ end
+
+ context 'when experiment is not active' do
+ let(:experiment_active) { false }
+ let(:in_experiment_group) { false }
+
+ it 'does not show the "Learn CI/CD syntax" template dropdown' do
+ expect(page).not_to have_css('.gitlab-ci-syntax-yml-selector')
+ end
+ end
+
+ context 'when experiment is active and the user is in the control group' do
+ let(:experiment_active) { true }
+ let(:in_experiment_group) { false }
+
+ it 'does not show the "Learn CI/CD syntax" template dropdown' do
+ expect(page).not_to have_css('.gitlab-ci-syntax-yml-selector')
+ end
+ end
+
+ context 'when experiment is active and the user is in the experimental group' 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
+ expect(page).to have_css('.gitlab-ci-syntax-yml-selector')
+
+ find('.js-gitlab-ci-syntax-yml-selector').click
+
+ wait_for_requests
+
+ within '.gitlab-ci-syntax-yml-selector' do
+ find('.dropdown-input-field').set('Artifacts example')
+ find('.dropdown-content .is-focused', text: 'Artifacts example').click
+ end
+
+ 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.')
+ end
+ end
+end
diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
index b5d5527bbfe..bfa7be5bb5c 100644
--- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
+++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'User uploads new design', :js do
let(:feature_enabled) { false }
it 'shows the message about requirements' do
- expect(page).to have_content("To upload designs, you'll need to enable LFS and have admin enable hashed storage.")
+ expect(page).to have_content("To upload designs, you'll need to enable LFS and have an admin enable hashed storage.")
end
end
diff --git a/spec/features/projects/issues/email_participants_spec.rb b/spec/features/projects/issues/email_participants_spec.rb
new file mode 100644
index 00000000000..3ffe0a5ced8
--- /dev/null
+++ b/spec/features/projects/issues/email_participants_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'viewing an issue', :js do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:note) { create(:note_on_issue, project: project, noteable: issue) }
+ let_it_be(:participants) { create_list(:issue_email_participant, 4, issue: issue) }
+
+ before do
+ sign_in(user)
+ visit project_issue_path(project, issue)
+ end
+
+ shared_examples 'email participants warning' do |selector|
+ it 'shows the correct message' do
+ expect(find(selector)).to have_content(", and 1 more will be notified of your comment")
+ end
+ end
+
+ context 'for a new note' do
+ it_behaves_like 'email participants warning', '.new-note'
+ end
+
+ context 'for a reply form' do
+ before do
+ find('.js-reply-button').click
+ end
+
+ it_behaves_like 'email participants warning', '.note-edit-form'
+ end
+end
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index b1e8127c54c..e87880d74b1 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -179,34 +179,6 @@ RSpec.describe 'Project Jobs Permissions' do
expect(status_code).to eq(expected_status_code)
end
end
-
- context 'when restrict_access_to_build_debug_mode feature not enabled' do
- where(:public_builds, :user_project_role, :ci_debug_trace, :expected_status_code) do
- true | 'developer' | true | 200
- true | 'guest' | true | 200
- true | 'developer' | false | 200
- true | 'guest' | false | 200
- false | 'developer' | true | 200
- false | 'guest' | true | 403
- false | 'developer' | false | 200
- false | 'guest' | false | 403
- end
-
- with_them do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- ci_instance_variable.update!(value: ci_debug_trace)
- project.update!(public_builds: public_builds)
- project.add_role(user, user_project_role)
- end
-
- it 'renders trace to authorized users' do
- visit trace_project_job_path(project, job)
-
- expect(status_code).to eq(expected_status_code)
- end
- end
- end
end
describe 'raw page' do
@@ -237,35 +209,6 @@ RSpec.describe 'Project Jobs Permissions' do
expect(page).to have_content(expected_msg)
end
end
-
- context 'when restrict_access_to_build_debug_mode feature not enabled' do
- where(:public_builds, :user_project_role, :ci_debug_trace, :expected_status_code, :expected_msg) do
- true | 'developer' | true | 200 | nil
- true | 'guest' | true | 200 | nil
- true | 'developer' | false | 200 | nil
- true | 'guest' | false | 200 | nil
- false | 'developer' | true | 200 | nil
- false | 'guest' | true | 403 | 'The current user is not authorized to access the job log'
- false | 'developer' | false | 200 | nil
- false | 'guest' | false | 403 | 'The current user is not authorized to access the job log'
- end
-
- with_them do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- ci_instance_variable.update!(value: ci_debug_trace)
- project.update!(public_builds: public_builds)
- project.add_role(user, user_project_role)
- end
-
- it 'renders raw trace to authorized users' do
- visit raw_project_job_path(project, job)
-
- expect(status_code).to eq(expected_status_code)
- expect(page).to have_content(expected_msg)
- end
- end
- end
end
end
end
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index c768b0e281c..5abebf2320e 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'User browses jobs' do
it 'shows the "CI Lint" button' do
page.within('.nav-controls') do
- ci_lint_tool_link = page.find_link('CI lint')
+ ci_lint_tool_link = page.find_link('CI Lint')
expect(ci_lint_tool_link[:href]).to end_with(project_ci_lint_path(project))
end
diff --git a/spec/features/projects/members/group_members_spec.rb b/spec/features/projects/members/group_members_spec.rb
index 3060d2c6a43..aa15f04bf24 100644
--- a/spec/features/projects/members/group_members_spec.rb
+++ b/spec/features/projects/members/group_members_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Projects members' do
+RSpec.describe 'Projects members', :js do
let(:user) { create(:user) }
let(:developer) { create(:user) }
let(:group) { create(:group, :public) }
@@ -66,62 +66,61 @@ RSpec.describe 'Projects members' do
end
end
- context 'with a group and a project invitee' do
+ 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 project invitee, the project developer, and the group owner' do
+ it 'shows the group owner' do
page.within first('.content-list') do
- expect(page).to have_content('test1@abc.com')
- expect(page).not_to have_content('test2@abc.com')
-
- # Project developer
- expect(page).to have_content(developer.name)
-
# Group owner
expect(page).to have_content(user.name)
expect(page).to have_content(group.name)
end
end
- end
- context 'with a group requester' do
- before do
- group.request_access(group_requester)
- visit project_project_members_path(project)
+ it 'shows the project developer' do
+ page.within first('.content-list') do
+ # Project developer
+ expect(page).to have_content(developer.name)
+ end
end
- it 'does not appear in the project members page' do
+ 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
- context 'with a group and a project requesters' do
+ context 'with a group requester' do
before do
+ stub_feature_flags(invite_members_group_modal: false)
group.request_access(group_requester)
- project.request_access(project_requester)
visit project_project_members_path(project)
end
- it 'shows the project requester, the project developer, and the group owner' do
+ 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).to have_content(project_requester.name)
expect(page).not_to have_content(group_requester.name)
end
-
- page.within all('.content-list').last do
- # Project developer
- expect(page).to have_content(developer.name)
-
- # Group owner
- expect(page).to have_content(user.name)
- expect(page).to have_content(group.name)
- 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 d59f8eb4b1d..686d86b1783 100644
--- a/spec/features/projects/members/groups_with_access_list_spec.rb
+++ b/spec/features/projects/members/groups_with_access_list_spec.rb
@@ -16,6 +16,7 @@ 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
@@ -29,6 +30,8 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
visit project_project_members_path(project)
+ click_groups_tab
+
expect(first('.group_member')).to have_content('Guest')
end
@@ -71,23 +74,31 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
expect(page).not_to have_selector('.group_member')
end
- context 'search in existing members (yes, this filters the groups list as well)' do
+ context 'search in existing members' do
it 'finds no results' do
page.within '.user-search-form' do
- fill_in 'search', with: 'testing 123'
+ 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
it 'finds results' do
page.within '.user-search-form' do
- fill_in 'search', with: group.name
+ 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)
end
end
+
+ def click_groups_tab
+ click_link 'Groups'
+ end
end
diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb
index 30e32ad1366..bb56ae348fb 100644
--- a/spec/features/projects/members/invite_group_spec.rb
+++ b/spec/features/projects/members/invite_group_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
it 'the project can be shared with another group' do
visit project_project_members_path(project)
- expect(page).not_to have_css('.project-members-groups')
+ expect(page).not_to have_link 'Groups'
click_on 'invite-group-tab'
@@ -47,7 +47,9 @@ RSpec.describe 'Project > Members > Invite group', :js do
page.find('body').click
find('.btn-success').click
- page.within('.project-members-groups') do
+ click_link 'Groups'
+
+ page.within('[data-testid="project-member-groups"]') do
expect(page).to have_content(group_to_share_with.name)
end
end
@@ -132,7 +134,9 @@ RSpec.describe 'Project > Members > Invite group', :js do
end
it 'the group link shows the expiration time with a warning class' do
- page.within('.project-members-groups') do
+ 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)
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 36ff461aac2..62115f2dce6 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe 'Project members list' do
let(:project) { create(:project, namespace: group) }
before do
+ stub_feature_flags(invite_members_group_modal: false)
sign_in(user1)
group.add_owner(user1)
end
@@ -82,7 +83,9 @@ RSpec.describe 'Project members list' do
add_user('test@example.com', 'Reporter')
- page.within(second_row) do
+ 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')
diff --git a/spec/features/projects/members/master_manages_access_requests_spec.rb b/spec/features/projects/members/master_manages_access_requests_spec.rb
index 2fdc75dca91..4c3eaa93352 100644
--- a/spec/features/projects/members/master_manages_access_requests_spec.rb
+++ b/spec/features/projects/members/master_manages_access_requests_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe 'Projects > Members > Maintainer manages access requests' do
it_behaves_like 'Maintainer manages access requests' do
- let(:has_tabs) { false }
let(:entity) { create(:project, :public) }
let(:members_page_path) { project_project_members_path(entity) }
end
diff --git a/spec/features/projects/members/tabs_spec.rb b/spec/features/projects/members/tabs_spec.rb
new file mode 100644
index 00000000000..bdcf02c82a4
--- /dev/null
+++ b/spec/features/projects/members/tabs_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects > Members > Tabs' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project_members) { create_list(:project_member, 2, project: project) }
+ let_it_be(:access_requests) { create_list(:project_member, 2, :access_request, project: project) }
+ let_it_be(:invites) { create_list(:project_member, 2, :invited, project: project) }
+ let_it_be(:project_group_links) { create_list(:project_group_link, 2, project: project) }
+
+ shared_examples 'active "Members" tab' do
+ it 'displays "Members" tab' do
+ expect(page).to have_selector('.nav-link.active', text: 'Members')
+ 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
+
+ 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}")
+ end
+ end
+
+ context 'displays "Members" tab by default' do
+ it_behaves_like 'active "Members" tab'
+ end
+
+ context 'when searching "Groups"', :js do
+ before do
+ click_link 'Groups'
+
+ page.within '[data-testid="group-link-search-form"]' do
+ fill_in 'search_groups', with: 'group'
+ find('button[type="submit"]').click
+ end
+ end
+
+ 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
diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb
index 0a5f7cc7edd..2acdf983cf2 100644
--- a/spec/features/projects/releases/user_creates_release_spec.rb
+++ b/spec/features/projects/releases/user_creates_release_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'User creates release', :js do
expect(page.find('.ref-selector button')).to have_content(project.default_branch)
end
- context 'when the "Save release" button is clicked' do
+ context 'when the "Save release" button is clicked', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297507' do
let(:tag_name) { 'v1.0' }
let(:release_title) { 'A most magnificent release' }
let(:release_notes) { 'Best. Release. **Ever.** :rocket:' }
diff --git a/spec/features/projects/services/user_activates_alerts_spec.rb b/spec/features/projects/services/user_activates_alerts_spec.rb
deleted file mode 100644
index 8b0acdf3618..00000000000
--- a/spec/features/projects/services/user_activates_alerts_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User activates Alerts', :js do
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- let(:service_name) { 'alerts' }
- let(:service_title) { 'Alerts endpoint' }
-
- before do
- sign_in(user)
- project.add_maintainer(user)
- end
-
- context 'when service is deactivated' do
- it 'user cannot activate service' do
- visit_project_services
-
- expect(page).to have_link(service_title)
- click_link(service_title)
-
- expect(page).to have_callout_message
- expect(page).not_to have_active_service
- expect(page).to have_toggle_active_disabled
- end
- end
-
- context 'when service is activated' do
- let_it_be(:activated_alerts_service) do
- create(:alerts_service, :active, project: project)
- end
-
- before do
- visit_alerts_service
- end
-
- it 'user cannot change settings' do
- expect(page).to have_callout_message
- expect(page).to have_active_service
- expect(page).to have_toggle_active_disabled
- expect(page).to have_button_reset_key_disabled
- end
- end
-
- private
-
- def visit_project_services
- visit(project_settings_integrations_path(project))
- end
-
- def visit_alerts_service
- visit(edit_project_service_path(project, service_name))
- end
-
- def have_callout_message
- within('.gl-alert') do
- have_content('You can now manage alert endpoint configuration in the Alerts section on the Operations settings page.')
- end
- end
-
- def have_active_service
- have_selector('.js-service-active-status[data-value="true"]')
- end
-
- def have_toggle_active_disabled
- have_selector('#activated .project-feature-toggle.is-disabled')
- end
-
- def have_button_reset_key_disabled
- have_button('Reset key', disabled: true)
- end
-end
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index ffc0ecc4966..c087237fd7c 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -183,7 +183,7 @@ RSpec.describe "Projects > Settings > Pipelines settings" do
let(:page_token) { find('#registration_token').text }
before do
- click_button 'Reset runners registration token'
+ click_button 'Reset registration token'
end
it 'changes registration token' do
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 3836b95a28a..726b8fb6840 100644
--- a/spec/features/projects/settings/user_manages_project_members_spec.rb
+++ b/spec/features/projects/settings/user_manages_project_members_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe 'Projects > Settings > User manages project members' do
end
end
- it 'shows all members of project shared group' do
+ it 'shows all members of project shared group', :js do
group.add_owner(user)
group.add_developer(user_dmitriy)
@@ -67,7 +67,9 @@ RSpec.describe 'Projects > Settings > User manages project members' do
visit(project_project_members_path(project))
- page.within('.project-members-groups') do
+ 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')
end
diff --git a/spec/features/projects/snippets/user_deletes_snippet_spec.rb b/spec/features/projects/snippets/user_deletes_snippet_spec.rb
index 6d526e60512..ca49e6a36b7 100644
--- a/spec/features/projects/snippets/user_deletes_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_deletes_snippet_spec.rb
@@ -21,6 +21,8 @@ RSpec.describe 'Projects > Snippets > User deletes a snippet', :js do
click_button('Delete snippet')
wait_for_requests
- expect(page).not_to have_content(snippet.title)
+ # This assertion also confirms we did not end up on an error page
+ expect(page).to have_selector('#new_snippet_link')
+ expect(project.snippets.length).to eq(0)
end
end
diff --git a/spec/features/promotion_spec.rb b/spec/features/promotion_spec.rb
index 9344f9b56b8..8692930376f 100644
--- a/spec/features/promotion_spec.rb
+++ b/spec/features/promotion_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'Promotions', :js do
it 'appears in project edit page' do
visit edit_project_path(project)
- expect(find('#promote_service_desk')).to have_content 'Improve customer support with GitLab Service Desk.'
+ expect(find('#promote_service_desk')).to have_content 'Improve customer support with Service Desk'
end
it 'does not show when cookie is set' do
diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb
index 25447db3c8d..376f990f054 100644
--- a/spec/features/protected_tags_spec.rb
+++ b/spec/features/protected_tags_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'Protected Tags', :js do
click_on "Protect"
within(".protected-tags-list") do
- expect(page).to have_content("Protected tag (2)")
+ expect(page).to have_content("Protected tags (2)")
expect(page).to have_content("2 matching tags")
end
end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 5cddad81927..cc024ab8f35 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'Runners' do
it 'user can see a button to install runners on kubernetes clusters' do
visit project_runners_path(project)
- expect(page).to have_link('Install Runner on Kubernetes', href: project_clusters_path(project))
+ expect(page).to have_link('Install GitLab Runner on Kubernetes', href: project_clusters_path(project))
end
end
@@ -69,7 +69,7 @@ RSpec.describe 'Runners' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- click_on 'Remove Runner'
+ click_on 'Remove runner'
end
expect(page).not_to have_content(specific_runner.display_name)
@@ -226,10 +226,10 @@ RSpec.describe 'Runners' do
it 'group runners are not available' do
visit project_runners_path(project)
- expect(page).to have_content 'This group does not provide any group Runners yet'
+ expect(page).to have_content 'This group does not have any group runners yet.'
- expect(page).to have_content 'Group maintainers can register group runners in the Group CI/CD settings'
- expect(page).not_to have_content 'Ask your group maintainer to set up a group Runner'
+ expect(page).to have_content 'Group maintainers can register group runners in the group\'s CI/CD settings.'
+ expect(page).not_to have_content 'Ask your group maintainer to set up a group runner'
end
end
end
@@ -241,7 +241,7 @@ RSpec.describe 'Runners' do
it 'group runners are not available' do
visit project_runners_path(project)
- expect(page).to have_content 'This project does not belong to a group and can therefore not make use of group Runners.'
+ expect(page).to have_content 'This project does not belong to a group and cannot make use of group runners.'
end
end
@@ -252,10 +252,10 @@ RSpec.describe 'Runners' do
it 'group runners are not available' do
visit project_runners_path(project)
- expect(page).to have_content 'This group does not provide any group Runners yet.'
+ expect(page).to have_content 'This group does not have any group runners yet.'
- expect(page).not_to have_content 'Group maintainers can register group runners in the Group CI/CD settings'
- expect(page).to have_content 'Ask your group maintainer to set up a group Runner.'
+ expect(page).not_to have_content 'Group maintainers can register group runners in the group\'s CI/CD settings.'
+ expect(page).to have_content 'Ask your group maintainer to set up a group runner.'
end
end
@@ -267,21 +267,21 @@ RSpec.describe 'Runners' do
it 'group runners are available' do
visit project_runners_path(project)
- expect(page).to have_content 'Available group Runners: 1'
+ expect(page).to have_content 'Available group runners: 1'
expect(page).to have_content 'group-runner'
end
it 'group runners may be disabled for a project' do
visit project_runners_path(project)
- click_on 'Disable group Runners'
+ click_on 'Disable group runners'
- expect(page).to have_content 'Enable group Runners'
+ expect(page).to have_content 'Enable group runners'
expect(project.reload.group_runners_enabled).to be false
- click_on 'Enable group Runners'
+ click_on 'Enable group runners'
- expect(page).to have_content 'Disable group Runners'
+ expect(page).to have_content 'Disable group runners'
expect(project.reload.group_runners_enabled).to be true
end
end
@@ -305,7 +305,7 @@ RSpec.describe 'Runners' do
it 'user can see a link to install runners on kubernetes clusters' do
visit group_settings_ci_cd_path(group)
- expect(page).to have_link('Install Runner on Kubernetes', href: group_clusters_path(group))
+ expect(page).to have_link('Install GitLab Runner on Kubernetes', href: group_clusters_path(group))
end
end
@@ -316,7 +316,7 @@ RSpec.describe 'Runners' do
visit group_settings_ci_cd_path(group)
expect(page).not_to have_content 'No runners found'
- expect(page).to have_content 'Available Runners: 1'
+ expect(page).to have_content 'Available runners: 1'
expect(page).to have_content 'group-runner'
end
@@ -396,7 +396,7 @@ RSpec.describe 'Runners' do
visit group_settings_ci_cd_path(group)
expect(page).not_to have_content 'No runners found'
- expect(page).to have_content 'Available Runners: 1'
+ expect(page).to have_content 'Available runners: 1'
expect(page).to have_content 'project-runner'
end
diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
index 5ac4a5c1840..5430329d47d 100644
--- a/spec/features/security/dashboard_access_spec.rb
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe "Dashboard access" do
it { expect(new_group_path).to be_denied_for :visitor }
end
- describe "GET /profile/groups" do
+ describe "GET /dashboard/groups" do
subject { dashboard_groups_path }
it { is_expected.to be_allowed_for :admin }
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 3aa8278866c..301efd2d99b 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe "Profile access" do
include AccessMatchers
- describe "GET /profile/keys" do
+ describe "GET /-/profile/keys" do
subject { profile_keys_path }
it { is_expected.to be_allowed_for :admin }
@@ -13,7 +13,7 @@ RSpec.describe "Profile access" do
it { is_expected.to be_denied_for :visitor }
end
- describe "GET /profile" do
+ describe "GET /-/profile" do
subject { profile_path }
it { is_expected.to be_allowed_for :admin }
@@ -21,7 +21,7 @@ RSpec.describe "Profile access" do
it { is_expected.to be_denied_for :visitor }
end
- describe "GET /profile/account" do
+ describe "GET /-/profile/account" do
subject { profile_account_path }
it { is_expected.to be_allowed_for :admin }
@@ -29,7 +29,7 @@ RSpec.describe "Profile access" do
it { is_expected.to be_denied_for :visitor }
end
- describe "GET /profile/preferences" do
+ describe "GET /-/profile/preferences" do
subject { profile_preferences_path }
it { is_expected.to be_allowed_for :admin }
@@ -37,7 +37,7 @@ RSpec.describe "Profile access" do
it { is_expected.to be_denied_for :visitor }
end
- describe "GET /profile/audit_log" do
+ describe "GET /-/profile/audit_log" do
subject { audit_log_profile_path }
it { is_expected.to be_allowed_for :admin }
@@ -45,7 +45,7 @@ RSpec.describe "Profile access" do
it { is_expected.to be_denied_for :visitor }
end
- describe "GET /profile/notifications" do
+ describe "GET /-/profile/notifications" do
subject { profile_notifications_path }
it { is_expected.to be_allowed_for :admin }
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index e4a8d836413..5a537c1d4df 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -742,65 +742,30 @@ RSpec.describe 'Login' do
end
context 'when the user did not enable 2FA' do
- context 'when `vue_2fa_recovery_codes` feature flag is disabled' do
- before do
- stub_feature_flags(vue_2fa_recovery_codes: false)
- end
-
- it 'asks to set 2FA before asking to accept the terms' do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
-
- visit new_user_session_path
-
- fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
-
- click_button 'Sign in'
-
- expect_to_be_on_terms_page
- click_button 'Accept terms'
-
- expect(current_path).to eq(profile_two_factor_auth_path)
-
- fill_in 'pin_code', with: user.reload.current_otp
-
- click_button 'Register with two-factor app'
-
- expect(page).to have_content('Congratulations! You have enabled Two-factor Authentication!')
-
- click_link 'Proceed'
-
- expect(current_path).to eq(profile_account_path)
- end
- end
-
- context 'when `vue_2fa_recovery_codes` feature flag is enabled' do
- it 'asks to set 2FA before asking to accept the terms', :js do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
+ it 'asks to set 2FA before asking to accept the terms', :js do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
- visit new_user_session_path
+ visit new_user_session_path
- fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_login', with: user.email
+ fill_in 'user_password', with: '12345678'
- click_button 'Sign in'
+ click_button 'Sign in'
- expect_to_be_on_terms_page
- click_button 'Accept terms'
+ expect_to_be_on_terms_page
+ click_button 'Accept terms'
- expect(current_path).to eq(profile_two_factor_auth_path)
+ expect(current_path).to eq(profile_two_factor_auth_path)
- fill_in 'pin_code', with: user.reload.current_otp
+ fill_in 'pin_code', with: user.reload.current_otp
- click_button 'Register with two-factor app'
- click_button 'Copy codes'
- click_link 'Proceed'
+ click_button 'Register with two-factor app'
+ click_button 'Copy codes'
+ click_link 'Proceed'
- expect(current_path).to eq(profile_account_path)
- expect(page).to have_content('Congratulations! You have enabled Two-factor Authentication!')
- end
+ expect(current_path).to eq(profile_account_path)
+ expect(page).to have_content('Congratulations! You have enabled Two-factor Authentication!')
end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index bfdd1e1bdb7..5f70517224e 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -294,17 +294,13 @@ RSpec.describe 'Signup' do
context 'when reCAPTCHA and invisible captcha are enabled' do
before do
- InvisibleCaptcha.timestamp_enabled = true
+ stub_application_setting(invisible_captcha_enabled: true)
stub_application_setting(recaptcha_enabled: true)
allow_next_instance_of(RegistrationsController) do |instance|
allow(instance).to receive(:verify_recaptcha).and_return(true)
end
end
- after do
- InvisibleCaptcha.timestamp_enabled = false
- end
-
context 'when reCAPTCHA detects malicious behaviour' do
before do
allow_next_instance_of(RegistrationsController) do |instance|
diff --git a/spec/finders/alert_management/alerts_finder_spec.rb b/spec/finders/alert_management/alerts_finder_spec.rb
index 87a5da38dd1..3a88db5d854 100644
--- a/spec/finders/alert_management/alerts_finder_spec.rb
+++ b/spec/finders/alert_management/alerts_finder_spec.rb
@@ -42,6 +42,12 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do
it { is_expected.to contain_exactly(resolved_alert, ignored_alert) }
end
+
+ context 'skips domain if iid is given' do
+ let(:params) { { iid: resolved_alert.iid, domain: 'threat_monitoring' } }
+
+ it { is_expected.to contain_exactly(resolved_alert) }
+ end
end
context 'empty params' do
diff --git a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
index 28a732fda82..2a6e44673e3 100644
--- a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
+++ b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
@@ -64,13 +64,13 @@ RSpec.describe Ci::DailyBuildGroupReportResultsFinder do
end
end
- context 'when ref_path is not present' do
+ context 'when ref_path query parameter is not present' do
let(:ref_path) { nil }
- context 'when coverages exist for the default branch' do
+ context 'when records with cover data from the default branch exist' do
let(:default_branch) { true }
- it 'returns coverage for the default branch' do
+ it 'returns records with default_branch:true, irrespective of ref_path' do
rspec_coverage_4 = create_daily_coverage('rspec', 66.0, '2020-03-10')
expect(coverages).to contain_exactly(rspec_coverage_4)
diff --git a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
index 64b3c46e122..65f6dc0ba74 100644
--- a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
+++ b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
@@ -225,24 +225,6 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
branch_pipeline_2,
branch_pipeline])
end
-
- context 'when ci_pipelines_for_merge_request_finder_new_cte feature flag is disabled' do
- before do
- stub_feature_flags(ci_pipelines_for_merge_request_finder_new_cte: false)
- end
-
- it 'returns only related merge request pipelines' do
- expect(subject.all)
- .to eq([detached_merge_request_pipeline,
- branch_pipeline_2,
- branch_pipeline])
-
- expect(described_class.new(merge_request_2, nil).all)
- .to eq([detached_merge_request_pipeline_2,
- branch_pipeline_2,
- branch_pipeline])
- end
- end
end
context 'when detached merge request pipeline is run on head ref of the merge request' do
diff --git a/spec/finders/cluster_ancestors_finder_spec.rb b/spec/finders/cluster_ancestors_finder_spec.rb
index ea1dbea4cfe..a54809801b5 100644
--- a/spec/finders/cluster_ancestors_finder_spec.rb
+++ b/spec/finders/cluster_ancestors_finder_spec.rb
@@ -83,8 +83,16 @@ RSpec.describe ClusterAncestorsFinder, '#execute' do
let(:clusterable) { Clusters::Instance.new }
let(:user) { create(:admin) }
- it 'returns the list of instance clusters' do
- is_expected.to eq([instance_cluster])
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns the list of instance clusters' do
+ is_expected.to eq([instance_cluster])
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
end
end
end
diff --git a/spec/finders/concerns/packages/finder_helper_spec.rb b/spec/finders/concerns/packages/finder_helper_spec.rb
new file mode 100644
index 00000000000..73f77647573
--- /dev/null
+++ b/spec/finders/concerns/packages/finder_helper_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Packages::FinderHelper do
+ describe '#packages_visible_to_user' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project1) { create(:project, namespace: group) }
+ let_it_be(:package1) { create(:package, project: project1) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+ let_it_be_with_reload(:project2) { create(:project, namespace: subgroup) }
+ let_it_be(:package2) { create(:package, project: project2) }
+
+ let(:finder_class) do
+ Class.new do
+ include ::Packages::FinderHelper
+
+ def initialize(user)
+ @current_user = user
+ end
+
+ def execute(group)
+ packages_visible_to_user(@current_user, within_group: group)
+ end
+ end
+ end
+
+ let(:finder) { finder_class.new(user) }
+
+ subject { finder.execute(group) }
+
+ shared_examples 'returning both packages' do
+ it { is_expected.to contain_exactly(package1, package2) }
+ end
+
+ shared_examples 'returning package1' do
+ it { is_expected.to eq [package1]}
+ end
+
+ shared_examples 'returning no packages' do
+ it { is_expected.to be_empty }
+ end
+
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages'
+ end
+
+ with_them do
+ before do
+ unless user_role == :anonymous
+ group.send("add_#{user_role}", user)
+ subgroup.send("add_#{user_role}", user)
+ project1.send("add_#{user_role}", user)
+ project2.send("add_#{user_role}", user)
+ end
+
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like params[:shared_example_name]
+ end
+ end
+
+ describe '#projects_visible_to_user' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project1) { create(:project, namespace: group) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+ let_it_be_with_reload(:project2) { create(:project, namespace: subgroup) }
+
+ let(:finder_class) do
+ Class.new do
+ include ::Packages::FinderHelper
+
+ def initialize(user)
+ @current_user = user
+ end
+
+ def execute(group)
+ projects_visible_to_user(@current_user, within_group: group)
+ end
+ end
+ end
+
+ let(:finder) { finder_class.new(user) }
+
+ subject { finder.execute(group) }
+
+ shared_examples 'returning both projects' do
+ it { is_expected.to contain_exactly(project1, project2) }
+ end
+
+ shared_examples 'returning project1' do
+ it { is_expected.to eq [project1]}
+ end
+
+ shared_examples 'returning no project' do
+ it { is_expected.to be_empty }
+ end
+
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project'
+ end
+
+ with_them do
+ before do
+ unless user_role == :anonymous
+ group.send("add_#{user_role}", user)
+ subgroup.send("add_#{user_role}", user)
+ project1.send("add_#{user_role}", user)
+ project2.send("add_#{user_role}", user)
+ end
+
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like params[:shared_example_name]
+ end
+ end
+end
diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb
index c66fdb19260..3fc4393df5d 100644
--- a/spec/finders/group_projects_finder_spec.rb
+++ b/spec/finders/group_projects_finder_spec.rb
@@ -142,20 +142,40 @@ RSpec.describe GroupProjectsFinder do
describe 'with an admin current user' do
let(:current_user) { create(:admin) }
- context "only shared" do
- let(:options) { { only_shared: true } }
+ context 'when admin mode is enabled', :enable_admin_mode do
+ context "only shared" do
+ let(:options) { { only_shared: true } }
- it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1]) }
- end
+ it { is_expected.to contain_exactly(shared_project_3, shared_project_2, shared_project_1) }
+ end
- context "only owned" do
- let(:options) { { only_owned: true } }
+ context "only owned" do
+ let(:options) { { only_owned: true } }
+
+ it { is_expected.to contain_exactly(private_project, public_project) }
+ end
- it { is_expected.to eq([private_project, public_project]) }
+ context "all" do
+ it { is_expected.to contain_exactly(shared_project_3, shared_project_2, shared_project_1, private_project, public_project) }
+ end
end
- context "all" do
- it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1, private_project, public_project]) }
+ context 'when admin mode is disabled' do
+ context "only shared" do
+ let(:options) { { only_shared: true } }
+
+ it { is_expected.to contain_exactly(shared_project_3, shared_project_1) }
+ end
+
+ context "only owned" do
+ let(:options) { { only_owned: true } }
+
+ it { is_expected.to contain_exactly(public_project) }
+ end
+
+ context "all" do
+ it { is_expected.to contain_exactly(shared_project_3, shared_project_1, public_project) }
+ end
end
end
diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb
index c9e9328794e..d69720ae98e 100644
--- a/spec/finders/groups_finder_spec.rb
+++ b/spec/finders/groups_finder_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe GroupsFinder do
+ include AdminModeHelper
+
describe '#execute' do
let(:user) { create(:user) }
@@ -23,11 +25,16 @@ RSpec.describe GroupsFinder do
:external | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
:external | {} | %i(public_group user_public_group user_internal_group user_private_group)
- :admin | { all_available: true } | %i(public_group internal_group private_group user_public_group
- user_internal_group user_private_group)
- :admin | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
- :admin | {} | %i(public_group internal_group private_group user_public_group user_internal_group
- user_private_group)
+ :admin_without_admin_mode | { all_available: true } | %i(public_group internal_group user_public_group
+ user_internal_group user_private_group)
+ :admin_without_admin_mode | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
+ :admin_without_admin_mode | {} | %i(public_group internal_group user_public_group user_internal_group user_private_group)
+
+ :admin_with_admin_mode | { all_available: true } | %i(public_group internal_group private_group user_public_group
+ user_internal_group user_private_group)
+ :admin_with_admin_mode | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
+ :admin_with_admin_mode | {} | %i(public_group internal_group private_group user_public_group user_internal_group
+ user_private_group)
end
with_them do
@@ -52,8 +59,12 @@ RSpec.describe GroupsFinder do
create(:user)
when :external
create(:user, external: true)
- when :admin
+ when :admin_without_admin_mode
create(:user, :admin)
+ when :admin_with_admin_mode
+ admin = create(:user, :admin)
+ enable_admin_mode!(admin)
+ admin
end
@groups.values_at(:user_private_group, :user_internal_group, :user_public_group).each do |group|
group.add_developer(user)
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 0def3412aa7..33b8a5954ae 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -13,7 +13,27 @@ RSpec.describe IssuesFinder do
let(:scope) { 'all' }
it 'returns all issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5)
+ end
+
+ context 'user does not have read permissions' do
+ let(:search_user) { user2 }
+
+ context 'when filtering by project id' do
+ let(:params) { { project_id: project1.id } }
+
+ it 'returns no issues' do
+ expect(issues).to be_empty
+ end
+ end
+
+ context 'when filtering by group id' do
+ let(:params) { { group_id: group.id } }
+
+ it 'returns no issues' do
+ expect(issues).to be_empty
+ end
+ end
end
context 'assignee filtering' do
@@ -21,7 +41,7 @@ RSpec.describe IssuesFinder do
it_behaves_like 'assignee ID filter' do
let(:params) { { assignee_id: user.id } }
- let(:expected_issuables) { [issue1, issue2] }
+ let(:expected_issuables) { [issue1, issue2, issue5] }
end
it_behaves_like 'assignee NOT ID filter' do
@@ -59,7 +79,25 @@ RSpec.describe IssuesFinder do
end
it_behaves_like 'any assignee filter' do
- let(:expected_issuables) { [issue1, issue2, issue3] }
+ let(:expected_issuables) { [issue1, issue2, issue3, issue5] }
+ end
+ end
+
+ context 'filtering by release' do
+ context 'when the release tag is none' do
+ let(:params) { { release_tag: 'none' } }
+
+ it 'returns issues without releases' do
+ expect(issues).to contain_exactly(issue2, issue3, issue4, issue5)
+ end
+ end
+
+ context 'when the release tag exists' do
+ let(:params) { { project_id: project1.id, release_tag: release.tag } }
+
+ it 'returns the issues associated with that release' do
+ expect(issues).to contain_exactly(issue1)
+ end
end
end
@@ -68,7 +106,7 @@ RSpec.describe IssuesFinder do
let(:params) { { projects: [project1.id] } }
it 'returns the issue belonging to the projects' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
end
end
@@ -76,7 +114,7 @@ RSpec.describe IssuesFinder do
let(:params) { { projects: Project.id_in(project1.id) } }
it 'returns the issue belonging to the projects' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
end
end
end
@@ -86,7 +124,7 @@ RSpec.describe IssuesFinder do
context 'when include_subgroup param not set' do
it 'returns all group issues' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
end
context 'when projects outside the group are passed' do
@@ -101,7 +139,7 @@ RSpec.describe IssuesFinder do
let(:params) { { group_id: group.id, projects: [project1.id] } }
it 'returns the issue within the group and projects' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
end
end
@@ -109,7 +147,15 @@ RSpec.describe IssuesFinder do
let(:params) { { group_id: group.id, projects: Project.id_in(project1.id) } }
it 'returns the issue within the group and projects' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
+ end
+ end
+
+ context 'when release_tag is passed as a parameter' do
+ let(:params) { { group_id: group.id, release_tag: 'dne-release-tag' } }
+
+ it 'ignores the release_tag parameter' do
+ expect(issues).to contain_exactly(issue1, issue5)
end
end
end
@@ -120,7 +166,7 @@ RSpec.describe IssuesFinder do
end
it 'returns all group and subgroup issues' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue1, issue4, issue5)
end
context 'when mixed projects are passed' do
@@ -145,7 +191,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { author_id: user2.id } } }
it 'returns issues not created by that user' do
- expect(issues).to contain_exactly(issue1, issue2, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue4, issue5)
end
end
@@ -175,7 +221,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { milestone_title: milestone.title } } }
it 'returns issues not assigned to that milestone' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue2, issue3, issue4, issue5)
end
end
@@ -199,7 +245,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { milestone_title: group_milestone.title } } }
it 'returns issues not assigned to that group milestone' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue1, issue4, issue5)
end
end
end
@@ -208,13 +254,13 @@ RSpec.describe IssuesFinder do
let(:params) { { milestone_title: 'None' } }
it 'returns issues with no milestone' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue2, issue3, issue4, issue5)
end
it 'returns issues with no milestone (deprecated)' do
params[:milestone_title] = Milestone::None.title
- expect(issues).to contain_exactly(issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue2, issue3, issue4, issue5)
end
end
@@ -343,7 +389,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { label_name: label.title } } }
it 'returns issues that do not have that label' do
- expect(issues).to contain_exactly(issue1, issue3, issue4)
+ expect(issues).to contain_exactly(issue1, issue3, issue4, issue5)
end
# IssuableFinder first filters using the outer params (the ones not inside the `not` key.)
@@ -383,7 +429,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
it 'returns issues that do not have any of the labels provided' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue1, issue4, issue5)
end
end
end
@@ -405,7 +451,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
it 'returns issues that do not have ANY ONE of the labels provided' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue1, issue4, issue5)
end
end
end
@@ -414,7 +460,7 @@ RSpec.describe IssuesFinder do
let(:params) { { label_name: described_class::Params::FILTER_NONE } }
it 'returns issues with no labels' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue1, issue4, issue5)
end
end
@@ -483,14 +529,14 @@ RSpec.describe IssuesFinder do
end
context 'filtering by issues iids' do
- let(:params) { { iids: issue3.iid } }
+ let(:params) { { iids: [issue3.iid] } }
- it 'returns issues with iids match' do
- expect(issues).to contain_exactly(issue3)
+ it 'returns issues where iids match' do
+ expect(issues).to contain_exactly(issue3, issue5)
end
context 'using NOT' do
- let(:params) { { not: { iids: issue3.iid } } }
+ let(:params) { { not: { iids: [issue3.iid] } } }
it 'returns issues with no iids match' do
expect(issues).to contain_exactly(issue1, issue2, issue4)
@@ -503,7 +549,7 @@ RSpec.describe IssuesFinder do
let(:params) { { state: 'opened' } }
it 'returns only opened issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5)
end
end
@@ -519,7 +565,7 @@ RSpec.describe IssuesFinder do
let(:params) { { state: 'all' } }
it 'returns all issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4, issue5)
end
end
@@ -527,7 +573,7 @@ RSpec.describe IssuesFinder do
let(:params) { { state: 'invalid_state' } }
it 'returns all issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4, issue5)
end
end
end
@@ -619,7 +665,7 @@ RSpec.describe IssuesFinder do
let(:params) { { my_reaction_emoji: 'None' } }
it 'returns issues that the user did not react to' do
- expect(issues).to contain_exactly(issue2, issue4)
+ expect(issues).to contain_exactly(issue2, issue4, issue5)
end
end
@@ -642,7 +688,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { my_reaction_emoji: 'thumbsup' } } }
it 'returns issues that the user did not thumbsup to' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue2, issue3, issue4, issue5)
end
end
end
@@ -676,7 +722,7 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { my_reaction_emoji: 'thumbsdown' } } }
it 'returns issues that the user thumbsdown to' do
- expect(issues).to contain_exactly(issue1, issue2, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue4, issue5)
end
end
end
@@ -687,7 +733,7 @@ RSpec.describe IssuesFinder do
context 'no filtering' do
it 'returns all issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, confidential_issue)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5, confidential_issue)
end
end
@@ -703,7 +749,7 @@ RSpec.describe IssuesFinder do
let(:params) { { confidential: false } }
it 'returns only confdential issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5)
end
end
end
@@ -715,7 +761,7 @@ RSpec.describe IssuesFinder do
let(:params) { { issue_types: [] } }
it 'returns all issues' do
- expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4)
+ expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4, issue5)
end
end
@@ -731,7 +777,7 @@ RSpec.describe IssuesFinder do
let(:params) { { issue_types: ['issue'] } }
it 'returns all issues with type issue' do
- expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5)
end
end
@@ -739,7 +785,7 @@ RSpec.describe IssuesFinder do
let(:params) { { issue_types: %w(issue incident) } }
it 'returns all issues' do
- expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4)
+ expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4, issue5)
end
end
@@ -790,14 +836,14 @@ RSpec.describe IssuesFinder do
let(:scope) { 'assigned_to_me' }
it 'returns issue assigned to the user' do
- expect(issues).to contain_exactly(issue1, issue2)
+ expect(issues).to contain_exactly(issue1, issue2, issue5)
end
context 'filtering by project' do
let(:params) { { project_id: project1.id } }
it 'returns issues assigned to the user in that project' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
end
end
end
@@ -839,7 +885,7 @@ RSpec.describe IssuesFinder do
let(:params) { base_params.merge(due_date: Issue::NoDueDate.name) }
it 'returns issues with no due date' do
- expect(issues).to contain_exactly(issue1)
+ expect(issues).to contain_exactly(issue1, issue5)
end
end
@@ -872,16 +918,26 @@ RSpec.describe IssuesFinder do
describe '#row_count', :request_store do
let_it_be(:admin) { create(:admin) }
- it 'returns the number of rows for the default state' do
- finder = described_class.new(admin)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns the number of rows for the default state' do
+ finder = described_class.new(admin)
+
+ expect(finder.row_count).to eq(5)
+ end
+
+ it 'returns the number of rows for a given state' do
+ finder = described_class.new(admin, state: 'closed')
- expect(finder.row_count).to eq(4)
+ expect(finder.row_count).to be_zero
+ end
end
- it 'returns the number of rows for a given state' do
- finder = described_class.new(admin, state: 'closed')
+ context 'when admin mode is disabled' do
+ it 'returns no rows' do
+ finder = described_class.new(admin)
- expect(finder.row_count).to be_zero
+ expect(finder.row_count).to be_zero
+ end
end
it 'returns -1 if the query times out' do
@@ -950,8 +1006,17 @@ RSpec.describe IssuesFinder do
subject { described_class.new(admin_user, params).with_confidentiality_access_check }
- it 'returns all issues' do
- expect(subject).to include(public_issue, confidential_issue)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns all issues' do
+ expect(subject).to include(public_issue, confidential_issue)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns only public issues' do
+ expect(subject).to include(public_issue)
+ expect(subject).not_to include(confidential_issue)
+ end
end
end
end
@@ -1023,14 +1088,27 @@ RSpec.describe IssuesFinder do
subject { described_class.new(admin_user, params).with_confidentiality_access_check }
- it 'returns all issues' do
- expect(subject).to include(public_issue, confidential_issue)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns all issues' do
+ expect(subject).to include(public_issue, confidential_issue)
+ end
+
+ it 'does not filter by confidentiality' do
+ expect(Issue).not_to receive(:where).with(a_string_matching('confidential'), anything)
+
+ subject
+ end
end
- it 'does not filter by confidentiality' do
- expect(Issue).not_to receive(:where).with(a_string_matching('confidential'), anything)
+ context 'when admin mode is disabled' do
+ it 'returns only public issues' do
+ expect(subject).to include(public_issue)
+ expect(subject).not_to include(confidential_issue)
+ end
- subject
+ it 'filters by confidentiality' do
+ expect(subject.to_sql).to match("issues.confidential")
+ end
end
end
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 7b59b581b1c..6fdfe780463 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -76,13 +76,40 @@ RSpec.describe MergeRequestsFinder do
expect(merge_requests).to contain_exactly(merge_request3, merge_request4)
end
- it 'filters by commit sha' do
- merge_requests = described_class.new(
- user,
- commit_sha: merge_request5.merge_request_diff.last_commit_sha
- ).execute
+ context 'filters by commit sha' do
+ subject(:merge_requests) { described_class.new(user, commit_sha: commit_sha).execute }
+
+ context 'when commit belongs to the merge request' do
+ let(:commit_sha) { merge_request5.merge_request_diff.last_commit_sha }
+
+ it 'filters by commit sha' do
+ is_expected.to contain_exactly(merge_request5)
+ end
+ end
+
+ context 'when commit is a squash commit' do
+ before do
+ merge_request4.update!(squash_commit_sha: commit_sha)
+ end
+
+ let(:commit_sha) { '1234abcd' }
+
+ it 'filters by commit sha' do
+ is_expected.to contain_exactly(merge_request4)
+ end
+ end
+
+ context 'when commit is a merge commit' do
+ before do
+ merge_request4.update!(merge_commit_sha: commit_sha)
+ end
+
+ let(:commit_sha) { '1234dcba' }
- expect(merge_requests).to contain_exactly(merge_request5)
+ it 'filters by commit sha' do
+ is_expected.to contain_exactly(merge_request4)
+ end
+ end
end
context 'filters by merged_at date' do
@@ -697,10 +724,18 @@ RSpec.describe MergeRequestsFinder do
context 'with admin user' do
let(:user) { create(:user, :admin) }
- it 'returns all merge requests' do
- expect(merge_requests).to eq(
- [mr_internal_private_repo_access, mr_private_repo_access, mr_internal, mr_private, mr_public]
- )
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns all merge requests' do
+ expect(merge_requests).to contain_exactly(
+ mr_internal_private_repo_access, mr_private_repo_access, mr_internal, mr_private, mr_public
+ )
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns public and internal merge requests' do
+ expect(merge_requests).to contain_exactly(mr_internal, mr_public)
+ end
end
end
diff --git a/spec/finders/packages/debian/distributions_finder_spec.rb b/spec/finders/packages/debian/distributions_finder_spec.rb
new file mode 100644
index 00000000000..f141b13e394
--- /dev/null
+++ b/spec/finders/packages/debian/distributions_finder_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::DistributionsFinder do
+ it_behaves_like 'Debian Distributions Finder', :debian_project_distribution, true
+ it_behaves_like 'Debian Distributions Finder', :debian_group_distribution, false
+
+ context 'with nil container' do
+ let(:service) { described_class.new(nil) }
+
+ subject { service.execute.to_a }
+
+ it 'raises error' do
+ expect { subject }.to raise_error ArgumentError, "Unexpected container type of 'NilClass'"
+ end
+ end
+
+ context 'with unexpected container type' do
+ let(:service) { described_class.new(:invalid) }
+
+ subject { service.execute.to_a }
+
+ it 'raises error' do
+ expect { subject }.to raise_error ArgumentError, "Unexpected container type of 'Symbol'"
+ end
+ end
+end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 0db69de65a5..8dd53b9c3f9 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -127,12 +127,6 @@ RSpec.describe Packages::GroupPackagesFinder do
it { is_expected.to match_array([package1, package2]) }
end
- context 'does not include packages without version number' do
- let_it_be(:package_without_version) { create(:maven_package, project: project, version: nil) }
-
- it { is_expected.not_to include(package_without_version) }
- end
-
context 'with package_name' do
let_it_be(:named_package) { create(:maven_package, project: project, name: 'maven') }
let(:params) { { package_name: package_name } }
@@ -151,6 +145,8 @@ RSpec.describe Packages::GroupPackagesFinder do
end
end
end
+
+ it_behaves_like 'concerning versionless param'
end
context 'group has package of all types' do
diff --git a/spec/finders/packages/maven/package_finder_spec.rb b/spec/finders/packages/maven/package_finder_spec.rb
index 239e8c10f52..b955c331f28 100644
--- a/spec/finders/packages/maven/package_finder_spec.rb
+++ b/spec/finders/packages/maven/package_finder_spec.rb
@@ -1,57 +1,81 @@
# frozen_string_literal: true
+
require 'spec_helper'
RSpec.describe ::Packages::Maven::PackageFinder do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project) { create(:project, namespace: group) }
- let(:package) { create(:maven_package, project: project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+ let_it_be(:package) { create(:maven_package, project: project) }
+
+ let(:param_path) { nil }
+ let(:param_project) { nil }
+ let(:param_group) { nil }
+ let(:finder) { described_class.new(param_path, user, project: param_project, group: param_group) }
before do
group.add_developer(user)
end
describe '#execute!' do
- context 'within the project' do
- it 'returns a package' do
- finder = described_class.new(package.maven_metadatum.path, user, project: project)
-
- expect(finder.execute!).to eq(package)
- end
+ subject { finder.execute! }
- it 'raises an error' do
- finder = described_class.new('com/example/my-app/1.0-SNAPSHOT', user, project: project)
+ shared_examples 'handling valid and invalid paths' do
+ context 'with a valid path' do
+ let(:param_path) { package.maven_metadatum.path }
- expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
+ it { is_expected.to eq(package) }
end
- end
- context 'across all projects' do
- it 'returns a package' do
- finder = described_class.new(package.maven_metadatum.path, user)
+ context 'with an invalid path' do
+ let(:param_path) { 'com/example/my-app/1.0-SNAPSHOT' }
- expect(finder.execute!).to eq(package)
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
end
+ end
- it 'raises an error' do
- finder = described_class.new('com/example/my-app/1.0-SNAPSHOT', user)
+ context 'within the project' do
+ let(:param_project) { project }
- expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
- end
+ it_behaves_like 'handling valid and invalid paths'
end
context 'within a group' do
- it 'returns a package' do
- finder = described_class.new(package.maven_metadatum.path, user, group: group)
+ let(:param_group) { group }
- expect(finder.execute!).to eq(package)
- end
+ it_behaves_like 'handling valid and invalid paths'
+ end
+ context 'across all projects' do
it 'raises an error' do
- finder = described_class.new('com/example/my-app/1.0-SNAPSHOT', user, group: group)
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'versionless maven-metadata.xml package' do
+ let_it_be(:sub_group1) { create(:group, parent: group) }
+ let_it_be(:sub_group2) { create(:group, parent: group) }
+ let_it_be(:project1) { create(:project, group: sub_group1) }
+ let_it_be(:project2) { create(:project, group: sub_group2) }
+ let_it_be(:project3) { create(:project, group: sub_group1) }
+ let_it_be(:package_name) { 'foo' }
+ let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
+ let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
+ let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
- expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
+ let(:param_group) { group }
+ let(:param_path) { package_name }
+
+ before do
+ sub_group1.add_developer(user)
+ sub_group2.add_developer(user)
+ # the package with the most recently published file should be returned
+ create(:package_file, :xml, package: package2)
end
+
+ it { is_expected.to eq(package2) }
end
end
end
diff --git a/spec/finders/packages/nuget/package_finder_spec.rb b/spec/finders/packages/nuget/package_finder_spec.rb
index 9295d0c7a2f..10b5f6c8ec2 100644
--- a/spec/finders/packages/nuget/package_finder_spec.rb
+++ b/spec/finders/packages/nuget/package_finder_spec.rb
@@ -2,74 +2,117 @@
require 'spec_helper'
RSpec.describe Packages::Nuget::PackageFinder do
- let_it_be(:package1) { create(:nuget_package) }
- let_it_be(:project) { package1.project }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project) { create(:project, namespace: subgroup) }
+ let_it_be(:package1) { create(:nuget_package, project: project) }
let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0', project: project) }
let_it_be(:package3) { create(:nuget_package, name: 'Another.Dummy.Package', project: project) }
+ let_it_be(:other_package_1) { create(:nuget_package, name: package1.name, version: package1.version) }
+ let_it_be(:other_package_2) { create(:nuget_package, name: package1.name, version: package2.version) }
let(:package_name) { package1.name }
let(:package_version) { nil }
let(:limit) { 50 }
describe '#execute!' do
- subject { described_class.new(project, package_name: package_name, package_version: package_version, limit: limit).execute }
+ subject { described_class.new(user, target, package_name: package_name, package_version: package_version, limit: limit).execute }
- it { is_expected.to match_array([package1, package2]) }
+ shared_examples 'handling all the conditions' do
+ it { is_expected.to match_array([package1, package2]) }
- context 'with lower case package name' do
- let(:package_name) { package1.name.downcase }
+ context 'with lower case package name' do
+ let(:package_name) { package1.name.downcase }
- it { is_expected.to match_array([package1, package2]) }
- end
+ it { is_expected.to match_array([package1, package2]) }
+ end
- context 'with unknown package name' do
- let(:package_name) { 'foobar' }
+ context 'with unknown package name' do
+ let(:package_name) { 'foobar' }
- it { is_expected.to be_empty }
- end
+ it { is_expected.to be_empty }
+ end
- context 'with valid version' do
- let(:package_version) { '2.0.0' }
+ context 'with valid version' do
+ let(:package_version) { '2.0.0' }
- it { is_expected.to match_array([package2]) }
- end
+ it { is_expected.to match_array([package2]) }
+ end
- context 'with unknown version' do
- let(:package_version) { 'foobar' }
+ context 'with unknown version' do
+ let(:package_version) { 'foobar' }
- it { is_expected.to be_empty }
- end
+ it { is_expected.to be_empty }
+ end
+
+ context 'with limit hit' do
+ let_it_be(:package4) { create(:nuget_package, name: package1.name, project: project) }
+ let_it_be(:package5) { create(:nuget_package, name: package1.name, project: project) }
+ let_it_be(:package6) { create(:nuget_package, name: package1.name, project: project) }
+ let(:limit) { 2 }
+
+ it { is_expected.to match_array([package5, package6]) }
+ end
+
+ context 'with downcase package name' do
+ let(:package_name) { package1.name.downcase }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
- context 'with limit hit' do
- let_it_be(:package4) { create(:nuget_package, name: package1.name, project: project) }
- let_it_be(:package5) { create(:nuget_package, name: package1.name, project: project) }
- let_it_be(:package6) { create(:nuget_package, name: package1.name, project: project) }
- let(:limit) { 2 }
+ context 'with prefix wildcard' do
+ let(:package_name) { "%#{package1.name[3..-1]}" }
- it { is_expected.to match_array([package5, package6]) }
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'with suffix wildcard' do
+ let(:package_name) { "#{package1.name[0..-3]}%" }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'with surrounding wildcards' do
+ let(:package_name) { "%#{package1.name[3..-3]}%" }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
end
- context 'with downcase package name' do
- let(:package_name) { package1.name.downcase }
+ context 'with a project' do
+ let(:target) { project }
- it { is_expected.to match_array([package1, package2]) }
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'handling all the conditions'
end
- context 'with prefix wildcard' do
- let(:package_name) { "%#{package1.name[3..-1]}" }
+ context 'with a subgroup' do
+ let(:target) { subgroup }
- it { is_expected.to match_array([package1, package2]) }
+ before do
+ subgroup.add_developer(user)
+ end
+
+ it_behaves_like 'handling all the conditions'
end
- context 'with suffix wildcard' do
- let(:package_name) { "#{package1.name[0..-3]}%" }
+ context 'with a group' do
+ let(:target) { group }
- it { is_expected.to match_array([package1, package2]) }
+ before do
+ group.add_developer(user)
+ end
+
+ it_behaves_like 'handling all the conditions'
end
- context 'with surrounding wildcards' do
- let(:package_name) { "%#{package1.name[3..-3]}%" }
+ context 'with nil' do
+ let(:target) { nil }
- it { is_expected.to match_array([package1, package2]) }
+ it { is_expected.to be_empty }
end
end
end
diff --git a/spec/finders/packages/packages_finder_spec.rb b/spec/finders/packages/packages_finder_spec.rb
index 925b003bb8e..77a171db144 100644
--- a/spec/finders/packages/packages_finder_spec.rb
+++ b/spec/finders/packages/packages_finder_spec.rb
@@ -81,10 +81,6 @@ RSpec.describe ::Packages::PackagesFinder do
it { is_expected.to match_array([conan_package, maven_package]) }
end
- context 'does not include packages without version number' do
- let_it_be(:package_without_version) { create(:maven_package, project: project, version: nil) }
-
- it { is_expected.not_to include(package_without_version) }
- end
+ it_behaves_like 'concerning versionless param'
end
end
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 57977fb69b4..4d9ff30daba 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do
+RSpec.describe ProjectsFinder do
include AdminModeHelper
describe '#execute' do
@@ -353,7 +353,7 @@ RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do
end
before do
- stub_feature_flags(project_finder_similarity_sort: true)
+ stub_feature_flags(project_finder_similarity_sort: current_user)
end
it { is_expected.to eq([internal_project2, internal_project4, internal_project3]) }
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index 6fc1cbcee0a..9c9a04a4df5 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -106,12 +106,18 @@ RSpec.describe SnippetsFinder do
expect(snippets).to contain_exactly(public_personal_snippet)
end
- it 'returns all snippets for an admin' do
+ it 'returns all snippets for an admin in admin mode', :enable_admin_mode do
snippets = described_class.new(admin, author: user).execute
expect(snippets).to contain_exactly(private_personal_snippet, internal_personal_snippet, public_personal_snippet)
end
+ it 'returns all public and internal snippets for an admin without admin mode' do
+ snippets = described_class.new(admin, author: user).execute
+
+ expect(snippets).to contain_exactly(internal_personal_snippet, public_personal_snippet)
+ end
+
context 'when author is not valid' do
it 'returns quickly' do
finder = described_class.new(admin, author: non_existing_record_id)
@@ -180,12 +186,18 @@ RSpec.describe SnippetsFinder do
expect(snippets).to contain_exactly(private_project_snippet)
end
- it 'returns all snippets for an admin' do
+ it 'returns all snippets for an admin in admin mode', :enable_admin_mode do
snippets = described_class.new(admin, project: project).execute
expect(snippets).to contain_exactly(private_project_snippet, internal_project_snippet, public_project_snippet)
end
+ it 'returns public and internal snippets for an admin without admin mode' do
+ snippets = described_class.new(admin, project: project).execute
+
+ expect(snippets).to contain_exactly(internal_project_snippet, public_project_snippet)
+ end
+
context 'filter by author' do
let!(:other_user) { create(:user) }
let!(:other_private_project_snippet) { create(:project_snippet, :private, project: project, author: other_user) }
@@ -218,7 +230,7 @@ RSpec.describe SnippetsFinder do
end
context 'filter by snippet type' do
- context 'when filtering by only_personal snippet' do
+ context 'when filtering by only_personal snippet', :enable_admin_mode do
it 'returns only personal snippet' do
snippets = described_class.new(admin, only_personal: true).execute
@@ -228,7 +240,7 @@ RSpec.describe SnippetsFinder do
end
end
- context 'when filtering by only_project snippet' do
+ context 'when filtering by only_project snippet', :enable_admin_mode do
it 'returns only project snippet' do
snippets = described_class.new(admin, only_project: true).execute
@@ -239,7 +251,7 @@ RSpec.describe SnippetsFinder do
end
end
- context 'filtering by ids' do
+ context 'filtering by ids', :enable_admin_mode do
it 'returns only personal snippet' do
snippets = described_class.new(
admin, ids: [private_personal_snippet.id,
@@ -265,13 +277,21 @@ RSpec.describe SnippetsFinder do
)
end
- it 'returns all personal snippets for admins' do
+ it 'returns all personal snippets for admins when in admin mode', :enable_admin_mode do
snippets = described_class.new(admin, explore: true).execute
expect(snippets).to contain_exactly(
private_personal_snippet, internal_personal_snippet, public_personal_snippet
)
end
+
+ it 'also returns internal personal snippets for admins without admin mode' do
+ snippets = described_class.new(admin, explore: true).execute
+
+ expect(snippets).to contain_exactly(
+ internal_personal_snippet, public_personal_snippet
+ )
+ end
end
context 'when the user cannot read cross project' do
@@ -302,7 +322,7 @@ RSpec.describe SnippetsFinder do
end
end
- context 'no sort param is provided' do
+ context 'no sort param is provided', :enable_admin_mode do
it 'returns snippets sorted by id' do
snippets = described_class.new(admin).execute
@@ -310,7 +330,7 @@ RSpec.describe SnippetsFinder do
end
end
- context 'sort param is provided' do
+ context 'sort param is provided', :enable_admin_mode do
it 'returns snippets sorted by sort param' do
snippets = described_class.new(admin, sort: 'updated_desc').execute
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index 0fdd6ab402d..2da864b9a46 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe TemplateFinder do
:gitlab_ci_ymls | described_class
:licenses | ::LicenseTemplateFinder
:metrics_dashboard_ymls | described_class
+ :gitlab_ci_syntax_ymls | described_class
end
with_them do
@@ -30,6 +31,7 @@ RSpec.describe TemplateFinder do
:gitignores | 'Actionscript'
:gitlab_ci_ymls | 'Android'
:metrics_dashboard_ymls | 'Default'
+ :gitlab_ci_syntax_ymls | 'Artifacts example'
end
with_them do
diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb
index a04f5452fcd..d9cc71106d5 100644
--- a/spec/finders/users_finder_spec.rb
+++ b/spec/finders/users_finder_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe UsersFinder do
it 'returns all users' do
users = described_class.new(user).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user)
end
it 'filters by username' do
@@ -48,13 +48,13 @@ RSpec.describe UsersFinder do
it 'filters by active users' do
users = described_class.new(user, active: true).execute
- expect(users).to contain_exactly(user, normal_user, omniauth_user)
+ expect(users).to contain_exactly(user, normal_user, omniauth_user, admin_user)
end
it 'returns no external users' do
users = described_class.new(user, external: true).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user)
end
it 'filters by created_at' do
@@ -71,7 +71,7 @@ RSpec.describe UsersFinder do
it 'filters by non internal users' do
users = described_class.new(user, non_internal: true).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, admin_user)
end
it 'does not filter by custom attributes' do
@@ -80,17 +80,22 @@ RSpec.describe UsersFinder do
custom_attributes: { foo: 'bar' }
).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user)
end
it 'orders returned results' do
users = described_class.new(user, sort: 'id_asc').execute
- expect(users).to eq([normal_user, blocked_user, omniauth_user, internal_user, user])
+ expect(users).to eq([normal_user, admin_user, blocked_user, omniauth_user, internal_user, user])
+ end
+
+ it 'does not filter by admins' do
+ users = described_class.new(user, admins: true).execute
+ expect(users).to contain_exactly(user, normal_user, admin_user, blocked_user, omniauth_user, internal_user)
end
end
- context 'with an admin user' do
+ context 'with an admin user', :enable_admin_mode do
let(:admin) { create(:admin) }
it 'filters by external users' do
@@ -102,7 +107,13 @@ RSpec.describe UsersFinder do
it 'returns all users' do
users = described_class.new(admin).execute
- expect(users).to contain_exactly(admin, normal_user, blocked_user, external_user, omniauth_user, internal_user)
+ expect(users).to contain_exactly(admin, normal_user, blocked_user, external_user, omniauth_user, internal_user, admin_user)
+ end
+
+ it 'returns only admins' do
+ users = described_class.new(admin, admins: true).execute
+
+ expect(users).to contain_exactly(admin, admin_user)
end
it 'filters by custom attributes' do
diff --git a/spec/fixtures/api/schemas/entities/discussion.json b/spec/fixtures/api/schemas/entities/discussion.json
index 2afabcc9195..1a5b8150ed2 100644
--- a/spec/fixtures/api/schemas/entities/discussion.json
+++ b/spec/fixtures/api/schemas/entities/discussion.json
@@ -48,6 +48,7 @@
"resolved": { "type": "boolean" },
"resolvable": { "type": "boolean" },
"resolved_by": { "type": ["string", "null"] },
+ "resolved_at": { "type": ["date", "null"] },
"note": { "type": "string" },
"note_html": { "type": "string" },
"current_user": { "type": "object" },
diff --git a/spec/fixtures/api/schemas/entities/member.json b/spec/fixtures/api/schemas/entities/member.json
new file mode 100644
index 00000000000..e8b40745803
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/member.json
@@ -0,0 +1,66 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "created_at",
+ "expires_at",
+ "access_level",
+ "requested_at",
+ "source",
+ "valid_roles",
+ "can_update",
+ "can_remove"
+ ],
+ "properties": {
+ "id": { "type": "integer" },
+ "created_at": { "type": "date-time" },
+ "expires_at": { "type": ["date-time", "null"] },
+ "requested_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" }
+ },
+ "additionalProperties": false
+ },
+ "source": {
+ "type": "object",
+ "required": ["id", "full_name", "web_url"],
+ "properties": {
+ "id": { "type": "integer" },
+ "full_name": { "type": "string" },
+ "web_url": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "valid_roles": { "type": "object" },
+ "created_by": {
+ "type": "object",
+ "required": ["name", "web_url"],
+ "properties": {
+ "name": { "type": "string" },
+ "web_url": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "user": {
+ "allOf": [
+ { "$ref": "member_user.json" }
+ ]
+ },
+ "invite": {
+ "type": "object",
+ "required": ["email", "avatar_url", "can_resend"],
+ "properties": {
+ "email": { "type": "string" },
+ "avatar_url": { "type": "string" },
+ "can_resend": { "type": "boolean" }
+ },
+ "additionalProperties": false
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/member_user.json b/spec/fixtures/api/schemas/entities/member_user.json
new file mode 100644
index 00000000000..983cdb7b9d9
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/member_user.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "required": ["id", "name", "username", "avatar_url", "web_url", "blocked", "two_factor_enabled"],
+ "properties": {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "username": { "type": "string" },
+ "avatar_url": { "type": ["string", "null"] },
+ "web_url": { "type": "string" },
+ "blocked": { "type": "boolean" },
+ "two_factor_enabled": { "type": "boolean" },
+ "status": {
+ "type": "object",
+ "required": ["emoji"],
+ "properties": {
+ "emoji": { "type": "string" }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/environment.json b/spec/fixtures/api/schemas/environment.json
index b8c4253056e..4f54a77e6b2 100644
--- a/spec/fixtures/api/schemas/environment.json
+++ b/spec/fixtures/api/schemas/environment.json
@@ -37,6 +37,12 @@
"has_opened_alert": { "type": "boolean" },
"cluster_type": { "type": "types/nullable_string.json" },
"terminal_path": { "type": "types/nullable_string.json" },
+ "rollout_status": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "rollout_status.json" }
+ ]
+ },
"last_deployment": {
"oneOf": [
{ "type": "null" },
diff --git a/spec/fixtures/api/schemas/graphql/namespace/package_settings.json b/spec/fixtures/api/schemas/graphql/namespace/package_settings.json
new file mode 100644
index 00000000000..c1286ee0944
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/namespace/package_settings.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "required": ["mavenDuplicatesAllowed", "mavenDuplicateExceptionRegex"],
+ "properties": {
+ "mavenDuplicatesAllowed": {
+ "type": "boolean"
+ },
+ "mavenDuplicateExceptionRegex": {
+ "type": "string"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_composer_details.json b/spec/fixtures/api/schemas/graphql/packages/package_composer_details.json
new file mode 100644
index 00000000000..bcf64a6e567
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/packages/package_composer_details.json
@@ -0,0 +1,12 @@
+{
+ "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_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
new file mode 100644
index 00000000000..4f90285183c
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -0,0 +1,36 @@
+{
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "createdAt": {
+ "type": "string"
+ },
+ "updatedAt": {
+ "type": "string"
+ },
+ "version": {
+ "type": ["string", "null"]
+ },
+ "package_type": {
+ "type": ["string"],
+ "enum": ["MAVEN", "NPM", "CONAN", "NUGET", "PYPI", "COMPOSER", "GENERIC", "GOLANG", "DEBIAN"]
+ },
+ "tags": {
+ "type": "object"
+ },
+ "project": {
+ "type": "object"
+ },
+ "pipelines": {
+ "type": "object"
+ },
+ "versions": {
+ "type": "object"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/group_member.json b/spec/fixtures/api/schemas/group_member.json
deleted file mode 100644
index 3425108e46e..00000000000
--- a/spec/fixtures/api/schemas/group_member.json
+++ /dev/null
@@ -1,89 +0,0 @@
-{
- "type": "object",
- "required": [
- "id",
- "created_at",
- "expires_at",
- "access_level",
- "requested_at",
- "source",
- "valid_roles",
- "can_update",
- "can_remove"
- ],
- "properties": {
- "id": { "type": "integer" },
- "created_at": { "type": "date-time" },
- "expires_at": { "type": ["date-time", "null"] },
- "requested_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" }
- }
- },
- "source": {
- "type": "object",
- "required": ["id", "name", "web_url"],
- "properties": {
- "id": { "type": "integer" },
- "name": { "type": "string" },
- "web_url": { "type": "string" }
- }
- },
- "valid_roles": { "type": "object" },
- "created_by": {
- "type": "object",
- "required": ["name", "web_url"],
- "properties": {
- "name": { "type": "string" },
- "web_url": { "type": "string" }
- }
- },
- "user": {
- "type": "object",
- "required": [
- "id",
- "name",
- "username",
- "avatar_url",
- "web_url",
- "blocked",
- "two_factor_enabled"
- ],
- "properties": {
- "id": { "type": "integer" },
- "name": { "type": "string" },
- "username": { "type": "string" },
- "avatar_url": { "type": ["string", "null"] },
- "web_url": { "type": "string" },
- "blocked": { "type": "boolean" },
- "two_factor_enabled": { "type": "boolean" },
- "status": {
- "type": "object",
- "required": [
- "emoji",
- "message_html"
- ],
- "properties": {
- "emoji": { "type": "string" },
- "message_html": { "type": "string" }
- }
- }
- }
- },
- "invite": {
- "type": "object",
- "required": ["email", "avatar_url", "can_resend"],
- "properties": {
- "email": { "type": "string" },
- "avatar_url": { "type": "string" },
- "can_resend": { "type": "boolean" }
- }
- }
- }
-}
diff --git a/spec/fixtures/api/schemas/group_members.json b/spec/fixtures/api/schemas/group_members.json
deleted file mode 100644
index 6268c7ef4d8..00000000000
--- a/spec/fixtures/api/schemas/group_members.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "type": "array",
- "items": {
- "$ref": "group_member.json"
- }
-}
diff --git a/spec/fixtures/api/schemas/members.json b/spec/fixtures/api/schemas/members.json
new file mode 100644
index 00000000000..0b0b56da9f8
--- /dev/null
+++ b/spec/fixtures/api/schemas/members.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "entities/member.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/notes.json b/spec/fixtures/api/schemas/public_api/v4/notes.json
index 683dcb19836..c4510207882 100644
--- a/spec/fixtures/api/schemas/public_api/v4/notes.json
+++ b/spec/fixtures/api/schemas/public_api/v4/notes.json
@@ -31,6 +31,7 @@
"resolved": { "type": "boolean" },
"resolvable": { "type": "boolean" },
"resolved_by": { "type": ["string", "null"] },
+ "resolved_at": { "type": ["date", "null"] },
"confidential": { "type": ["boolean", "null"] }
},
"required": [
diff --git a/spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_move.json b/spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_move.json
new file mode 100644
index 00000000000..f51e7e8edc5
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_move.json
@@ -0,0 +1,20 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "created_at",
+ "state",
+ "source_storage_name",
+ "destination_storage_name",
+ "snippet"
+ ],
+ "properties" : {
+ "id": { "type": "integer" },
+ "created_at": { "type": "date" },
+ "state": { "type": "string" },
+ "source_storage_name": { "type": "string" },
+ "destination_storage_name": { "type": "string" },
+ "snippet": { "type": "object" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_moves.json b/spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_moves.json
new file mode 100644
index 00000000000..292bb335539
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/snippet_repository_storage_moves.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "./snippet_repository_storage_move.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/rollout_status.json b/spec/fixtures/api/schemas/rollout_status.json
new file mode 100644
index 00000000000..334bed4ab65
--- /dev/null
+++ b/spec/fixtures/api/schemas/rollout_status.json
@@ -0,0 +1,52 @@
+{
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "status"
+ ],
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "completion": {
+ "type": "integer"
+ },
+ "is_completed": {
+ "type": "boolean"
+ },
+ "has_legacy_app_label": {
+ "type": "boolean"
+ },
+ "instances": {
+ "type": "array",
+ "items": {
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "status",
+ "pod_name",
+ "tooltip",
+ "track",
+ "stable"
+ ],
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "pod_name": {
+ "type": "string"
+ },
+ "tooltip": {
+ "type": "string"
+ },
+ "track": {
+ "type": "string"
+ },
+ "stable": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/emails/valid_note_on_issuable.eml b/spec/fixtures/emails/valid_note_on_issuable.eml
new file mode 100644
index 00000000000..29308c9d969
--- /dev/null
+++ b/spec/fixtures/emails/valid_note_on_issuable.eml
@@ -0,0 +1,24 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq-project_id-auth_token-issue-issue_iid@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-issue-issue_iid@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: New Issue comment by email
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+This should create a new comment on the issue.
+
+- Jake out
+
+> This quoted content will be included in the comment.
diff --git a/spec/fixtures/whats_new/blank.yml b/spec/fixtures/whats_new/blank.yml
new file mode 100644
index 00000000000..4628cae2ecc
--- /dev/null
+++ b/spec/fixtures/whats_new/blank.yml
@@ -0,0 +1,9 @@
+- title:
+ body:
+ stage:
+ self-managed:
+ gitlab-com:
+ url:
+ image_url:
+ published_at:
+ release:
diff --git a/spec/fixtures/whats_new/invalid.yml b/spec/fixtures/whats_new/invalid.yml
new file mode 100644
index 00000000000..0e588efaf8f
--- /dev/null
+++ b/spec/fixtures/whats_new/invalid.yml
@@ -0,0 +1,20 @@
+- title: Create and view requirements in GitLab
+ body: The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level. As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
+ stage: Plan
+ self-managed: true
+ gitlab-com: true
+ packages: [ALL]
+ url: https://docs.gitlab.com/ee/user/project/requirements/index.html
+ image_url: https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png
+ published_at: 2020-04-22
+ release: 12.10
+- title: Retrieve CI/CD secrets from HashiCorp Vault
+ body: In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault. Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp's JWT authentication method rather than manually having to provide secrets as a variable in GitLab.
+ stage: Release
+ self-managed: true
+ gitlab-com: true
+ packages: [Starter]
+ 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
+ release: 12.10
diff --git a/spec/fixtures/whats_new/valid.yml b/spec/fixtures/whats_new/valid.yml
new file mode 100644
index 00000000000..cbe9d666357
--- /dev/null
+++ b/spec/fixtures/whats_new/valid.yml
@@ -0,0 +1,20 @@
+- title: Create and view requirements in GitLab
+ body: The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level. As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
+ stage: Plan
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: https://docs.gitlab.com/ee/user/project/requirements/index.html
+ image_url: https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png
+ published_at: 2020-04-22
+ release: 12.10
+- title: Retrieve CI/CD secrets from HashiCorp Vault
+ body: In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault. Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp's JWT authentication method rather than manually having to provide secrets as a variable in GitLab.
+ stage: Release
+ self-managed: true
+ gitlab-com: true
+ packages: [Starter]
+ 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
+ release: 12.10
diff --git a/spec/frontend/__helpers__/README.md b/spec/frontend/__helpers__/README.md
new file mode 100644
index 00000000000..7b6c488f820
--- /dev/null
+++ b/spec/frontend/__helpers__/README.md
@@ -0,0 +1,5 @@
+This folder contains helpers to be used in specs (and the specs for the helpers itself).
+There is a convenient alias of `helpers/`, so files in this folder (e.g. `wait_for_promises`) can be imported
+with `helpers/wait_for_promises`.
+
+If you are writing a spec for `~/helpers` application code, please place it in [helpers](../helpers).
diff --git a/spec/frontend/__helpers__/backoff_helper.js b/spec/frontend/__helpers__/backoff_helper.js
new file mode 100644
index 00000000000..a971fcb0945
--- /dev/null
+++ b/spec/frontend/__helpers__/backoff_helper.js
@@ -0,0 +1,33 @@
+/**
+ * A mock version of a commonUtils `backOff` to test multiple
+ * retries.
+ *
+ * Usage:
+ *
+ * ```
+ * import * as commonUtils from '~/lib/utils/common_utils';
+ * import { backoffMockImplementation } from '../../helpers/backoff_helper';
+ *
+ * beforeEach(() => {
+ * // ...
+ * jest.spyOn(commonUtils, 'backOff').mockImplementation(backoffMockImplementation);
+ * });
+ * ```
+ *
+ * @param {Function} callback
+ */
+export const backoffMockImplementation = (callback) => {
+ const q = new Promise((resolve, reject) => {
+ const stop = (arg) => (arg instanceof Error ? reject(arg) : resolve(arg));
+ const next = () => callback(next, stop);
+ // Define a timeout based on a mock timer
+ setTimeout(() => {
+ callback(next, stop);
+ });
+ });
+ // Run all resolved promises in chain
+ jest.runOnlyPendingTimers();
+ return q;
+};
+
+export default { backoffMockImplementation };
diff --git a/spec/frontend/helpers/class_spec_helper.js b/spec/frontend/__helpers__/class_spec_helper.js
index b26f087f0c5..b26f087f0c5 100644
--- a/spec/frontend/helpers/class_spec_helper.js
+++ b/spec/frontend/__helpers__/class_spec_helper.js
diff --git a/spec/frontend/helpers/class_spec_helper_spec.js b/spec/frontend/__helpers__/class_spec_helper_spec.js
index 533d5687bde..533d5687bde 100644
--- a/spec/frontend/helpers/class_spec_helper_spec.js
+++ b/spec/frontend/__helpers__/class_spec_helper_spec.js
diff --git a/spec/frontend/__helpers__/datetime_helpers.js b/spec/frontend/__helpers__/datetime_helpers.js
new file mode 100644
index 00000000000..25dbd1d477d
--- /dev/null
+++ b/spec/frontend/__helpers__/datetime_helpers.js
@@ -0,0 +1,6 @@
+import dateFormat from 'dateformat';
+
+/**
+ * Returns a date object corresponding to the given date string.
+ */
+export const dateFromString = (dateString) => new Date(dateFormat(dateString));
diff --git a/spec/frontend/__helpers__/dom_events_helper.js b/spec/frontend/__helpers__/dom_events_helper.js
new file mode 100644
index 00000000000..865ea97903f
--- /dev/null
+++ b/spec/frontend/__helpers__/dom_events_helper.js
@@ -0,0 +1,8 @@
+export const triggerDOMEvent = (type) => {
+ window.document.dispatchEvent(
+ new Event(type, {
+ bubbles: true,
+ cancelable: true,
+ }),
+ );
+};
diff --git a/spec/frontend/helpers/dom_shims/README.md b/spec/frontend/__helpers__/dom_shims/README.md
index 1105e4b0c4c..1105e4b0c4c 100644
--- a/spec/frontend/helpers/dom_shims/README.md
+++ b/spec/frontend/__helpers__/dom_shims/README.md
diff --git a/spec/frontend/helpers/dom_shims/create_object_url.js b/spec/frontend/__helpers__/dom_shims/create_object_url.js
index 94d060cab08..94d060cab08 100644
--- a/spec/frontend/helpers/dom_shims/create_object_url.js
+++ b/spec/frontend/__helpers__/dom_shims/create_object_url.js
diff --git a/spec/frontend/helpers/dom_shims/element_scroll_by.js b/spec/frontend/__helpers__/dom_shims/element_scroll_by.js
index 7d91279e4aa..7d91279e4aa 100644
--- a/spec/frontend/helpers/dom_shims/element_scroll_by.js
+++ b/spec/frontend/__helpers__/dom_shims/element_scroll_by.js
diff --git a/spec/frontend/helpers/dom_shims/element_scroll_into_view.js b/spec/frontend/__helpers__/dom_shims/element_scroll_into_view.js
index a7262d04db0..a7262d04db0 100644
--- a/spec/frontend/helpers/dom_shims/element_scroll_into_view.js
+++ b/spec/frontend/__helpers__/dom_shims/element_scroll_into_view.js
diff --git a/spec/frontend/helpers/dom_shims/element_scroll_to.js b/spec/frontend/__helpers__/dom_shims/element_scroll_to.js
index 68f8a115865..68f8a115865 100644
--- a/spec/frontend/helpers/dom_shims/element_scroll_to.js
+++ b/spec/frontend/__helpers__/dom_shims/element_scroll_to.js
diff --git a/spec/frontend/helpers/dom_shims/form_element.js b/spec/frontend/__helpers__/dom_shims/form_element.js
index 46ef0374848..46ef0374848 100644
--- a/spec/frontend/helpers/dom_shims/form_element.js
+++ b/spec/frontend/__helpers__/dom_shims/form_element.js
diff --git a/spec/frontend/helpers/dom_shims/get_client_rects.js b/spec/frontend/__helpers__/dom_shims/get_client_rects.js
index 7ba60dd7936..7ba60dd7936 100644
--- a/spec/frontend/helpers/dom_shims/get_client_rects.js
+++ b/spec/frontend/__helpers__/dom_shims/get_client_rects.js
diff --git a/spec/frontend/helpers/dom_shims/get_client_rects_spec.js b/spec/frontend/__helpers__/dom_shims/get_client_rects_spec.js
index e7b8f1e235b..e7b8f1e235b 100644
--- a/spec/frontend/helpers/dom_shims/get_client_rects_spec.js
+++ b/spec/frontend/__helpers__/dom_shims/get_client_rects_spec.js
diff --git a/spec/frontend/helpers/dom_shims/image_element_properties.js b/spec/frontend/__helpers__/dom_shims/image_element_properties.js
index d94c157e44d..d94c157e44d 100644
--- a/spec/frontend/helpers/dom_shims/image_element_properties.js
+++ b/spec/frontend/__helpers__/dom_shims/image_element_properties.js
diff --git a/spec/frontend/helpers/dom_shims/index.js b/spec/frontend/__helpers__/dom_shims/index.js
index 9b70cb86b8b..9b70cb86b8b 100644
--- a/spec/frontend/helpers/dom_shims/index.js
+++ b/spec/frontend/__helpers__/dom_shims/index.js
diff --git a/spec/frontend/helpers/dom_shims/inner_text.js b/spec/frontend/__helpers__/dom_shims/inner_text.js
index 2b8201eed31..2b8201eed31 100644
--- a/spec/frontend/helpers/dom_shims/inner_text.js
+++ b/spec/frontend/__helpers__/dom_shims/inner_text.js
diff --git a/spec/frontend/helpers/dom_shims/range.js b/spec/frontend/__helpers__/dom_shims/range.js
index 4ffdf3280ad..4ffdf3280ad 100644
--- a/spec/frontend/helpers/dom_shims/range.js
+++ b/spec/frontend/__helpers__/dom_shims/range.js
diff --git a/spec/frontend/helpers/dom_shims/scroll_by.js b/spec/frontend/__helpers__/dom_shims/scroll_by.js
index 90387e51765..90387e51765 100644
--- a/spec/frontend/helpers/dom_shims/scroll_by.js
+++ b/spec/frontend/__helpers__/dom_shims/scroll_by.js
diff --git a/spec/frontend/__helpers__/dom_shims/size_properties.js b/spec/frontend/__helpers__/dom_shims/size_properties.js
new file mode 100644
index 00000000000..fbb919868b1
--- /dev/null
+++ b/spec/frontend/__helpers__/dom_shims/size_properties.js
@@ -0,0 +1,19 @@
+const convertFromStyle = (style) => {
+ if (style.match(/[0-9](px|rem)/g)) {
+ return Number(style.replace(/[^0-9]/g, ''));
+ }
+
+ return 0;
+};
+
+Object.defineProperty(global.HTMLElement.prototype, 'offsetWidth', {
+ get() {
+ return convertFromStyle(this.style.width || '0px');
+ },
+});
+
+Object.defineProperty(global.HTMLElement.prototype, 'offsetHeight', {
+ get() {
+ return convertFromStyle(this.style.height || '0px');
+ },
+});
diff --git a/spec/frontend/helpers/dom_shims/window_scroll_to.js b/spec/frontend/__helpers__/dom_shims/window_scroll_to.js
index 20ae1910bf3..20ae1910bf3 100644
--- a/spec/frontend/helpers/dom_shims/window_scroll_to.js
+++ b/spec/frontend/__helpers__/dom_shims/window_scroll_to.js
diff --git a/spec/frontend/__helpers__/emoji.js b/spec/frontend/__helpers__/emoji.js
new file mode 100644
index 00000000000..ea6613b53c9
--- /dev/null
+++ b/spec/frontend/__helpers__/emoji.js
@@ -0,0 +1,88 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
+
+export const emojiFixtureMap = {
+ atom: {
+ moji: 'âš›',
+ description: 'atom symbol',
+ unicodeVersion: '4.1',
+ aliases: ['atom_symbol'],
+ },
+ bomb: {
+ moji: '💣',
+ unicodeVersion: '6.0',
+ description: 'bomb',
+ },
+ construction_worker_tone5: {
+ moji: '👷ðŸ¿',
+ unicodeVersion: '8.0',
+ description: 'construction worker tone 5',
+ },
+ five: {
+ moji: '5ï¸âƒ£',
+ unicodeVersion: '3.0',
+ description: 'keycap digit five',
+ },
+ grey_question: {
+ moji: 'â”',
+ 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',
+ description: 'black heart',
+ },
+ heart: {
+ moji: 'â¤',
+ unicodeVersion: '1.1',
+ description: 'heavy black heart',
+ },
+ custard: {
+ moji: 'ðŸ®',
+ unicodeVersion: '6.0',
+ description: 'custard',
+ },
+ star: {
+ moji: 'â­',
+ unicodeVersion: '5.1',
+ description: 'white medium star',
+ },
+};
+
+Object.keys(emojiFixtureMap).forEach((k) => {
+ emojiFixtureMap[k].name = k;
+ if (!emojiFixtureMap[k].aliases) {
+ emojiFixtureMap[k].aliases = [];
+ }
+});
+
+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 }];
+ }),
+ );
+
+ const mock = new MockAdapter(axios);
+ mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(emojiData));
+
+ 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/experimentation_helper.js b/spec/frontend/__helpers__/experimentation_helper.js
index c08c25155e8..c08c25155e8 100644
--- a/spec/frontend/helpers/experimentation_helper.js
+++ b/spec/frontend/__helpers__/experimentation_helper.js
diff --git a/spec/frontend/__helpers__/fake_date.js b/spec/frontend/__helpers__/fake_date.js
new file mode 100644
index 00000000000..5391ae04797
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date.js
@@ -0,0 +1,49 @@
+// 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_spec.js b/spec/frontend/__helpers__/fake_date_spec.js
index b3ed13e238a..b3ed13e238a 100644
--- a/spec/frontend/helpers/fake_date_spec.js
+++ b/spec/frontend/__helpers__/fake_date_spec.js
diff --git a/spec/frontend/__helpers__/fake_request_animation_frame.js b/spec/frontend/__helpers__/fake_request_animation_frame.js
new file mode 100644
index 00000000000..ca9d82b6c3a
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_request_animation_frame.js
@@ -0,0 +1,12 @@
+export const useFakeRequestAnimationFrame = () => {
+ let orig;
+
+ beforeEach(() => {
+ orig = global.requestAnimationFrame;
+ global.requestAnimationFrame = (cb) => cb();
+ });
+
+ afterEach(() => {
+ global.requestAnimationFrame = orig;
+ });
+};
diff --git a/spec/frontend/helpers/filtered_search_spec_helper.js b/spec/frontend/__helpers__/filtered_search_spec_helper.js
index ecf10694a16..ecf10694a16 100644
--- a/spec/frontend/helpers/filtered_search_spec_helper.js
+++ b/spec/frontend/__helpers__/filtered_search_spec_helper.js
diff --git a/spec/frontend/__helpers__/fixtures.js b/spec/frontend/__helpers__/fixtures.js
new file mode 100644
index 00000000000..4b86724df93
--- /dev/null
+++ b/spec/frontend/__helpers__/fixtures.js
@@ -0,0 +1,38 @@
+import fs from 'fs';
+import path from 'path';
+
+import { ErrorWithStack } from 'jest-util';
+
+export function getFixture(relativePath) {
+ const basePath = relativePath.startsWith('static/')
+ ? global.staticFixturesBasePath
+ : global.fixturesBasePath;
+ const absolutePath = path.join(basePath, relativePath);
+ if (!fs.existsSync(absolutePath)) {
+ throw new ErrorWithStack(
+ `Fixture file ${relativePath} does not exist.
+
+Did you run bin/rake frontend:fixtures?`,
+ getFixture,
+ );
+ }
+
+ return fs.readFileSync(absolutePath, 'utf8');
+}
+
+export const getJSONFixture = (relativePath) => JSON.parse(getFixture(relativePath));
+
+export const resetHTMLFixture = () => {
+ document.head.innerHTML = '';
+ document.body.innerHTML = '';
+};
+
+export const setHTMLFixture = (htmlContent, resetHook = afterEach) => {
+ document.body.innerHTML = htmlContent;
+ resetHook(resetHTMLFixture);
+};
+
+export const loadHTMLFixture = (relativePath, resetHook = afterEach) => {
+ const fileContent = getFixture(relativePath);
+ setHTMLFixture(fileContent, resetHook);
+};
diff --git a/spec/frontend/helpers/init_vue_mr_page_helper.js b/spec/frontend/__helpers__/init_vue_mr_page_helper.js
index b9aed63d0f6..b9aed63d0f6 100644
--- a/spec/frontend/helpers/init_vue_mr_page_helper.js
+++ b/spec/frontend/__helpers__/init_vue_mr_page_helper.js
diff --git a/spec/frontend/__helpers__/jest_helpers.js b/spec/frontend/__helpers__/jest_helpers.js
new file mode 100644
index 00000000000..273d2c91966
--- /dev/null
+++ b/spec/frontend/__helpers__/jest_helpers.js
@@ -0,0 +1,22 @@
+/*
+@module
+
+This method provides convenience functions to help migrating from Karma/Jasmine to Jest.
+
+Try not to use these in new tests - this module is provided primarily for convenience of migrating tests.
+ */
+
+/**
+ * Creates a plain JS object pre-populated with Jest spy functions. Useful for making simple mocks classes.
+ *
+ * @see https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3EcreateSpyObj%3C/code%3E
+ * @param {string} baseName Human-readable name of the object. This is used for reporting purposes.
+ * @param methods {string[]} List of method names that will be added to the spy object.
+ */
+export function createSpyObj(baseName, methods) {
+ const obj = {};
+ methods.forEach((method) => {
+ obj[method] = jest.fn().mockName(`${baseName}#${method}`);
+ });
+ return obj;
+}
diff --git a/spec/frontend/helpers/jquery.js b/spec/frontend/__helpers__/jquery.js
index 4af5f904394..4af5f904394 100644
--- a/spec/frontend/helpers/jquery.js
+++ b/spec/frontend/__helpers__/jquery.js
diff --git a/spec/frontend/helpers/keep_alive_component_helper.js b/spec/frontend/__helpers__/keep_alive_component_helper.js
index 54f40bf9093..54f40bf9093 100644
--- a/spec/frontend/helpers/keep_alive_component_helper.js
+++ b/spec/frontend/__helpers__/keep_alive_component_helper.js
diff --git a/spec/frontend/helpers/keep_alive_component_helper_spec.js b/spec/frontend/__helpers__/keep_alive_component_helper_spec.js
index dcccc14f396..dcccc14f396 100644
--- a/spec/frontend/helpers/keep_alive_component_helper_spec.js
+++ b/spec/frontend/__helpers__/keep_alive_component_helper_spec.js
diff --git a/spec/frontend/__helpers__/local_storage_helper.js b/spec/frontend/__helpers__/local_storage_helper.js
new file mode 100644
index 00000000000..21749fd8070
--- /dev/null
+++ b/spec/frontend/__helpers__/local_storage_helper.js
@@ -0,0 +1,49 @@
+/**
+ * Manage the instance of a custom `window.localStorage`
+ *
+ * This only encapsulates the setup / teardown logic so that it can easily be
+ * reused with different implementations (i.e. a spy or a [fake][1])
+ *
+ * [1]: https://stackoverflow.com/a/41434763/1708147
+ *
+ * @param {() => any} fn Function that returns the object to use for localStorage
+ */
+const useLocalStorage = (fn) => {
+ const origLocalStorage = window.localStorage;
+ let currentLocalStorage = origLocalStorage;
+
+ Object.defineProperty(window, 'localStorage', {
+ get: () => currentLocalStorage,
+ });
+
+ beforeEach(() => {
+ currentLocalStorage = fn();
+ });
+
+ afterEach(() => {
+ currentLocalStorage = origLocalStorage;
+ });
+};
+
+/**
+ * Create an object with the localStorage interface but `jest.fn()` implementations.
+ */
+export const createLocalStorageSpy = () => {
+ let storage = {};
+
+ return {
+ clear: jest.fn(() => {
+ storage = {};
+ }),
+ getItem: jest.fn((key) => (key in storage ? storage[key] : null)),
+ setItem: jest.fn((key, value) => {
+ storage[key] = value;
+ }),
+ removeItem: jest.fn((key) => delete storage[key]),
+ };
+};
+
+/**
+ * Before each test, overwrite `window.localStorage` with a spy implementation.
+ */
+export const useLocalStorageSpy = () => useLocalStorage(createLocalStorageSpy);
diff --git a/spec/frontend/helpers/local_storage_helper_spec.js b/spec/frontend/__helpers__/local_storage_helper_spec.js
index 5d9961e7631..5d9961e7631 100644
--- a/spec/frontend/helpers/local_storage_helper_spec.js
+++ b/spec/frontend/__helpers__/local_storage_helper_spec.js
diff --git a/spec/frontend/__helpers__/locale_helper.js b/spec/frontend/__helpers__/locale_helper.js
new file mode 100644
index 00000000000..bb4a2eccf4e
--- /dev/null
+++ b/spec/frontend/__helpers__/locale_helper.js
@@ -0,0 +1,9 @@
+export const setLanguage = (languageCode) => {
+ const htmlElement = document.querySelector('html');
+
+ if (languageCode) {
+ htmlElement.setAttribute('lang', languageCode);
+ } else {
+ htmlElement.removeAttribute('lang');
+ }
+};
diff --git a/spec/frontend/helpers/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js
index 914cce1d662..914cce1d662 100644
--- a/spec/frontend/helpers/mock_apollo_helper.js
+++ b/spec/frontend/__helpers__/mock_apollo_helper.js
diff --git a/spec/frontend/helpers/mock_dom_observer.js b/spec/frontend/__helpers__/mock_dom_observer.js
index 1b93b81535d..1b93b81535d 100644
--- a/spec/frontend/helpers/mock_dom_observer.js
+++ b/spec/frontend/__helpers__/mock_dom_observer.js
diff --git a/spec/frontend/__helpers__/mock_window_location_helper.js b/spec/frontend/__helpers__/mock_window_location_helper.js
new file mode 100644
index 00000000000..08a28fbbbd6
--- /dev/null
+++ b/spec/frontend/__helpers__/mock_window_location_helper.js
@@ -0,0 +1,43 @@
+/**
+ * Manage the instance of a custom `window.location`
+ *
+ * This only encapsulates the setup / teardown logic so that it can easily be
+ * reused with different implementations (i.e. a spy or a [fake][1])
+ *
+ * [1]: https://stackoverflow.com/a/41434763/1708147
+ *
+ * @param {() => any} fn Function that returns the object to use for window.location
+ */
+const useMockLocation = (fn) => {
+ const origWindowLocation = window.location;
+ let currentWindowLocation;
+
+ Object.defineProperty(window, 'location', {
+ get: () => currentWindowLocation,
+ });
+
+ beforeEach(() => {
+ currentWindowLocation = fn();
+ });
+
+ afterEach(() => {
+ currentWindowLocation = origWindowLocation;
+ });
+};
+
+/**
+ * Create an object with the location interface but `jest.fn()` implementations.
+ */
+export const createWindowLocationSpy = () => {
+ return {
+ assign: jest.fn(),
+ reload: jest.fn(),
+ replace: jest.fn(),
+ toString: jest.fn(),
+ };
+};
+
+/**
+ * Before each test, overwrite `window.location` with a spy implementation.
+ */
+export const useMockLocationHelper = () => useMockLocation(createWindowLocationSpy);
diff --git a/spec/frontend/__helpers__/set_timeout_promise_helper.js b/spec/frontend/__helpers__/set_timeout_promise_helper.js
new file mode 100644
index 00000000000..afd18d92d15
--- /dev/null
+++ b/spec/frontend/__helpers__/set_timeout_promise_helper.js
@@ -0,0 +1,4 @@
+export default (time = 0) =>
+ new Promise((resolve) => {
+ setTimeout(resolve, time);
+ });
diff --git a/spec/frontend/helpers/set_window_location_helper.js b/spec/frontend/__helpers__/set_window_location_helper.js
index a94e73762c9..a94e73762c9 100644
--- a/spec/frontend/helpers/set_window_location_helper.js
+++ b/spec/frontend/__helpers__/set_window_location_helper.js
diff --git a/spec/frontend/__helpers__/set_window_location_helper_spec.js b/spec/frontend/__helpers__/set_window_location_helper_spec.js
new file mode 100644
index 00000000000..98f26854822
--- /dev/null
+++ b/spec/frontend/__helpers__/set_window_location_helper_spec.js
@@ -0,0 +1,40 @@
+import setWindowLocation from './set_window_location_helper';
+
+describe('setWindowLocation', () => {
+ const originalLocation = window.location;
+
+ afterEach(() => {
+ window.location = originalLocation;
+ });
+
+ it.each`
+ url | property | value
+ ${'https://gitlab.com#foo'} | ${'hash'} | ${'#foo'}
+ ${'http://gitlab.com'} | ${'host'} | ${'gitlab.com'}
+ ${'http://gitlab.org'} | ${'hostname'} | ${'gitlab.org'}
+ ${'http://gitlab.org/foo#bar'} | ${'href'} | ${'http://gitlab.org/foo#bar'}
+ ${'http://gitlab.com'} | ${'origin'} | ${'http://gitlab.com'}
+ ${'http://gitlab.com/foo/bar/baz'} | ${'pathname'} | ${'/foo/bar/baz'}
+ ${'https://gitlab.com'} | ${'protocol'} | ${'https:'}
+ ${'http://gitlab.com#foo'} | ${'protocol'} | ${'http:'}
+ ${'http://gitlab.com:8080'} | ${'port'} | ${'8080'}
+ ${'http://gitlab.com?foo=bar&bar=foo'} | ${'search'} | ${'?foo=bar&bar=foo'}
+ `(
+ 'sets "window.location.$property" to be "$value" when called with: "$url"',
+ ({ url, property, value }) => {
+ expect(window.location).toBe(originalLocation);
+
+ setWindowLocation(url);
+
+ expect(window.location[property]).toBe(value);
+ },
+ );
+
+ it.each([null, 1, undefined, false, '', 'gitlab.com'])(
+ 'throws an error when called with an invalid url: "%s"',
+ (invalidUrl) => {
+ expect(() => setWindowLocation(invalidUrl)).toThrow(/Invalid URL/);
+ expect(window.location).toBe(originalLocation);
+ },
+ );
+});
diff --git a/spec/frontend/__helpers__/stub_children.js b/spec/frontend/__helpers__/stub_children.js
new file mode 100644
index 00000000000..0711563699f
--- /dev/null
+++ b/spec/frontend/__helpers__/stub_children.js
@@ -0,0 +1,3 @@
+export default function stubChildren(Component) {
+ return Object.fromEntries(Object.keys(Component.components).map((c) => [c, true]));
+}
diff --git a/spec/frontend/helpers/stub_component.js b/spec/frontend/__helpers__/stub_component.js
index 45550450517..45550450517 100644
--- a/spec/frontend/helpers/stub_component.js
+++ b/spec/frontend/__helpers__/stub_component.js
diff --git a/spec/frontend/__helpers__/stub_transition.js b/spec/frontend/__helpers__/stub_transition.js
new file mode 100644
index 00000000000..9cddb432a63
--- /dev/null
+++ b/spec/frontend/__helpers__/stub_transition.js
@@ -0,0 +1,8 @@
+export function stubTransition() {
+ return {
+ render() {
+ // eslint-disable-next-line no-underscore-dangle
+ return this.$options._renderChildren;
+ },
+ };
+}
diff --git a/spec/frontend/helpers/test_constants.js b/spec/frontend/__helpers__/test_constants.js
index 69b78f556aa..69b78f556aa 100644
--- a/spec/frontend/helpers/test_constants.js
+++ b/spec/frontend/__helpers__/test_constants.js
diff --git a/spec/frontend/__helpers__/text_helper.js b/spec/frontend/__helpers__/text_helper.js
new file mode 100644
index 00000000000..164f18faadc
--- /dev/null
+++ b/spec/frontend/__helpers__/text_helper.js
@@ -0,0 +1,18 @@
+/**
+ * Replaces line break with an empty space
+ * @param {*} data
+ */
+export const removeBreakLine = (data) => data.replace(/\r?\n|\r/g, ' ');
+
+/**
+ * Removes line breaks, spaces and trims the given text
+ * @param {String} str
+ * @returns {String}
+ */
+export const trimText = (str) =>
+ str
+ .replace(/\r?\n|\r/g, '')
+ .replace(/\s\s+/g, ' ')
+ .trim();
+
+export const removeWhitespace = (str) => str.replace(/\s\s+/g, ' ');
diff --git a/spec/frontend/__helpers__/timeout.js b/spec/frontend/__helpers__/timeout.js
new file mode 100644
index 00000000000..8688625a95e
--- /dev/null
+++ b/spec/frontend/__helpers__/timeout.js
@@ -0,0 +1,59 @@
+const NS_PER_SEC = 1e9;
+const NS_PER_MS = 1e6;
+const IS_DEBUGGING = process.execArgv.join(' ').includes('--inspect-brk');
+
+let testTimeoutNS;
+
+export const setTestTimeout = (newTimeoutMS) => {
+ const newTimeoutNS = newTimeoutMS * NS_PER_MS;
+ // never accept a smaller timeout than the default
+ if (newTimeoutNS < testTimeoutNS) {
+ return;
+ }
+
+ testTimeoutNS = newTimeoutNS;
+ jest.setTimeout(newTimeoutMS);
+};
+
+// Allows slow tests to set their own timeout.
+// Useful for tests with jQuery, which is very slow in big DOMs.
+let temporaryTimeoutNS = null;
+export const setTestTimeoutOnce = (newTimeoutMS) => {
+ const newTimeoutNS = newTimeoutMS * NS_PER_MS;
+ // never accept a smaller timeout than the default
+ if (newTimeoutNS < testTimeoutNS) {
+ return;
+ }
+
+ temporaryTimeoutNS = newTimeoutNS;
+};
+
+export const initializeTestTimeout = (defaultTimeoutMS) => {
+ setTestTimeout(defaultTimeoutMS);
+
+ let testStartTime;
+
+ // https://github.com/facebook/jest/issues/6947
+ beforeEach(() => {
+ testStartTime = process.hrtime();
+ });
+
+ afterEach(() => {
+ let timeoutNS = testTimeoutNS;
+ if (Number.isFinite(temporaryTimeoutNS)) {
+ timeoutNS = temporaryTimeoutNS;
+ temporaryTimeoutNS = null;
+ }
+
+ const [seconds, remainingNs] = process.hrtime(testStartTime);
+ const elapsedNS = seconds * NS_PER_SEC + remainingNs;
+
+ // Disable the timeout error when debugging. It is meaningless because
+ // debugging always takes longer than the test timeout.
+ if (elapsedNS > timeoutNS && !IS_DEBUGGING) {
+ throw new Error(
+ `Test took too long (${elapsedNS / NS_PER_MS}ms > ${timeoutNS / NS_PER_MS}ms)!`,
+ );
+ }
+ });
+};
diff --git a/spec/frontend/__helpers__/tracking_helper.js b/spec/frontend/__helpers__/tracking_helper.js
new file mode 100644
index 00000000000..08ba5a6628e
--- /dev/null
+++ b/spec/frontend/__helpers__/tracking_helper.js
@@ -0,0 +1,25 @@
+import Tracking from '~/tracking';
+
+export default Tracking;
+
+let document;
+let handlers;
+
+export function mockTracking(category = '_category_', documentOverride, spyMethod) {
+ document = documentOverride || window.document;
+ window.snowplow = () => {};
+ handlers = Tracking.bindDocument(category, document);
+ return spyMethod ? spyMethod(Tracking, 'event') : null;
+}
+
+export function unmockTracking() {
+ window.snowplow = undefined;
+ handlers.forEach((event) => document.removeEventListener(event.name, event.func));
+}
+
+export function triggerEvent(selectorOrEl, eventName = 'click') {
+ const event = new Event(eventName, { bubbles: true });
+ const el = typeof selectorOrEl === 'string' ? document.querySelector(selectorOrEl) : selectorOrEl;
+
+ el.dispatchEvent(event);
+}
diff --git a/spec/frontend/__helpers__/user_mock_data_helper.js b/spec/frontend/__helpers__/user_mock_data_helper.js
new file mode 100644
index 00000000000..db747283d9e
--- /dev/null
+++ b/spec/frontend/__helpers__/user_mock_data_helper.js
@@ -0,0 +1,29 @@
+let id = 1;
+
+// Code taken from: https://gist.github.com/6174/6062387
+const getRandomString = () =>
+ Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
+
+const getRandomUrl = () => `https://${getRandomString()}.com/${getRandomString()}`;
+
+export default {
+ createNumberRandomUsers(numberUsers) {
+ const users = [];
+ for (let i = 0; i < numberUsers; i += 1) {
+ users.push({
+ avatar_url: getRandomUrl(),
+ id: id + 1,
+ name: getRandomString(),
+ username: getRandomString(),
+ user_path: getRandomUrl(),
+ });
+
+ id += 1;
+ }
+ return users;
+ },
+
+ createRandomUser() {
+ return this.createNumberRandomUsers(1)[0];
+ },
+};
diff --git a/spec/frontend/__helpers__/vue_mock_directive.js b/spec/frontend/__helpers__/vue_mock_directive.js
new file mode 100644
index 00000000000..e952f258c4d
--- /dev/null
+++ b/spec/frontend/__helpers__/vue_mock_directive.js
@@ -0,0 +1,25 @@
+export const getKey = (name) => `$_gl_jest_${name}`;
+
+export const getBinding = (el, name) => el[getKey(name)];
+
+const writeBindingToElement = (el, { name, value, arg, modifiers }) => {
+ el[getKey(name)] = {
+ value,
+ arg,
+ modifiers,
+ };
+};
+
+export const createMockDirective = () => ({
+ bind(el, binding) {
+ writeBindingToElement(el, binding);
+ },
+
+ update(el, binding) {
+ writeBindingToElement(el, binding);
+ },
+
+ unbind(el, { name }) {
+ delete el[getKey(name)];
+ },
+});
diff --git a/spec/frontend/helpers/vue_mount_component_helper.js b/spec/frontend/__helpers__/vue_mount_component_helper.js
index 615ff69a01c..615ff69a01c 100644
--- a/spec/frontend/helpers/vue_mount_component_helper.js
+++ b/spec/frontend/__helpers__/vue_mount_component_helper.js
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper.js b/spec/frontend/__helpers__/vue_test_utils_helper.js
new file mode 100644
index 00000000000..ffccfb249c2
--- /dev/null
+++ b/spec/frontend/__helpers__/vue_test_utils_helper.js
@@ -0,0 +1,53 @@
+import { isArray } from 'lodash';
+
+const vNodeContainsText = (vnode, text) =>
+ (vnode.text && vnode.text.includes(text)) ||
+ (vnode.children && vnode.children.filter((child) => vNodeContainsText(child, text)).length);
+
+/**
+ * Determines whether a `shallowMount` Wrapper contains text
+ * within one of it's slots. This will also work on Wrappers
+ * acquired with `find()`, but only if it's parent Wrapper
+ * was shallowMounted.
+ * NOTE: Prefer checking the rendered output of a component
+ * wherever possible using something like `text()` instead.
+ * @param {Wrapper} shallowWrapper - Vue test utils wrapper (shallowMounted)
+ * @param {String} slotName
+ * @param {String} text
+ */
+export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) =>
+ Boolean(
+ shallowWrapper.vm.$slots[slotName].filter((vnode) => vNodeContainsText(vnode, text)).length,
+ );
+
+/**
+ * Returns a promise that waits for a mutation to be fired before resolving
+ * NOTE: There's no reject action here so it will hang if it waits for a mutation that won't happen.
+ * @param {Object} store - The Vue store that contains the mutations
+ * @param {String} expectedMutationType - The Mutation to wait for
+ */
+export const waitForMutation = (store, expectedMutationType) =>
+ new Promise((resolve) => {
+ const unsubscribe = store.subscribe((mutation) => {
+ if (mutation.type === expectedMutationType) {
+ unsubscribe();
+ resolve();
+ }
+ });
+ });
+
+export const extendedWrapper = (wrapper) => {
+ if (isArray(wrapper) || !wrapper?.find) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ '[vue-test-utils-helper]: you are trying to extend an object that is not a VueWrapper.',
+ );
+ return wrapper;
+ }
+
+ return Object.defineProperty(wrapper, 'findByTestId', {
+ value(id) {
+ return this.find(`[data-testid="${id}"]`);
+ },
+ });
+};
diff --git a/spec/frontend/helpers/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
index 31c4ccd5dbb..31c4ccd5dbb 100644
--- a/spec/frontend/helpers/vue_test_utils_helper_spec.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
diff --git a/spec/frontend/__helpers__/vuex_action_helper.js b/spec/frontend/__helpers__/vuex_action_helper.js
new file mode 100644
index 00000000000..e482a8fbc71
--- /dev/null
+++ b/spec/frontend/__helpers__/vuex_action_helper.js
@@ -0,0 +1,128 @@
+const noop = () => {};
+
+/**
+ * Helper for testing action with expected mutations inspired in
+ * https://vuex.vuejs.org/en/testing.html
+ *
+ * @param {(Function|Object)} action to be tested, or object of named parameters
+ * @param {Object} payload will be provided to the action
+ * @param {Object} state will be provided to the action
+ * @param {Array} [expectedMutations=[]] mutations expected to be committed
+ * @param {Array} [expectedActions=[]] actions expected to be dispatched
+ * @param {Function} [done=noop] to be executed after the tests
+ * @return {Promise}
+ *
+ * @example
+ * testAction(
+ * actions.actionName, // action
+ * { }, // mocked payload
+ * state, //state
+ * // expected mutations
+ * [
+ * { type: types.MUTATION}
+ * { type: types.MUTATION_1, payload: expect.any(Number)}
+ * ],
+ * // expected actions
+ * [
+ * { type: 'actionName', payload: {param: 'foobar'}},
+ * { type: 'actionName1'}
+ * ]
+ * done,
+ * );
+ *
+ * @example
+ * testAction(
+ * actions.actionName, // action
+ * { }, // mocked payload
+ * state, //state
+ * [ { type: types.MUTATION} ], // expected mutations
+ * [], // expected actions
+ * ).then(done)
+ * .catch(done.fail);
+ *
+ * @example
+ * await testAction({
+ * action: actions.actionName,
+ * payload: { deleteListId: 1 },
+ * state: { lists: [1, 2, 3] },
+ * expectedMutations: [ { type: types.MUTATION} ],
+ * expectedActions: [],
+ * })
+ */
+export default (
+ actionArg,
+ payloadArg,
+ stateArg,
+ expectedMutationsArg = [],
+ expectedActionsArg = [],
+ doneArg = noop,
+) => {
+ let action = actionArg;
+ let payload = payloadArg;
+ let state = stateArg;
+ let expectedMutations = expectedMutationsArg;
+ let expectedActions = expectedActionsArg;
+ let done = doneArg;
+
+ if (typeof actionArg !== 'function') {
+ ({
+ action,
+ payload,
+ state,
+ expectedMutations = [],
+ expectedActions = [],
+ done = noop,
+ } = actionArg);
+ }
+
+ const mutations = [];
+ const actions = [];
+
+ // mock commit
+ const commit = (type, mutationPayload) => {
+ const mutation = { type };
+
+ if (typeof mutationPayload !== 'undefined') {
+ mutation.payload = mutationPayload;
+ }
+
+ mutations.push(mutation);
+ };
+
+ // mock dispatch
+ const dispatch = (type, actionPayload) => {
+ const dispatchedAction = { type };
+
+ if (typeof actionPayload !== 'undefined') {
+ dispatchedAction.payload = actionPayload;
+ }
+
+ actions.push(dispatchedAction);
+ };
+
+ const validateResults = () => {
+ expect({
+ mutations,
+ actions,
+ }).toEqual({
+ mutations: expectedMutations,
+ actions: expectedActions,
+ });
+ done();
+ };
+
+ const result = action(
+ { commit, state, dispatch, rootState: state, rootGetters: state, getters: state },
+ payload,
+ );
+
+ return (result || new Promise((resolve) => setImmediate(resolve)))
+ .catch((error) => {
+ validateResults();
+ throw error;
+ })
+ .then((data) => {
+ validateResults();
+ return data;
+ });
+};
diff --git a/spec/frontend/__helpers__/vuex_action_helper_spec.js b/spec/frontend/__helpers__/vuex_action_helper_spec.js
new file mode 100644
index 00000000000..b4f5a291774
--- /dev/null
+++ b/spec/frontend/__helpers__/vuex_action_helper_spec.js
@@ -0,0 +1,174 @@
+import MockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'helpers/test_constants';
+import axios from '~/lib/utils/axios_utils';
+import testActionFn from './vuex_action_helper';
+
+const testActionFnWithOptionsArg = (...args) => {
+ const [action, payload, state, expectedMutations, expectedActions, done] = args;
+ return testActionFn({ action, payload, state, expectedMutations, expectedActions, done });
+};
+
+describe.each([testActionFn, testActionFnWithOptionsArg])(
+ 'VueX test helper (testAction)',
+ (testAction) => {
+ let originalExpect;
+ let assertion;
+ let mock;
+ const noop = () => {};
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ /**
+ * In order to test the helper properly, we need to overwrite the Jest
+ * `expect` helper. We test that the testAction helper properly passes the
+ * dispatched actions/committed mutations to the Jest helper.
+ */
+ originalExpect = expect;
+ assertion = null;
+ global.expect = (actual) => ({
+ toEqual: () => {
+ originalExpect(actual).toEqual(assertion);
+ },
+ });
+ });
+
+ afterEach(() => {
+ mock.restore();
+ global.expect = originalExpect;
+ });
+
+ it('properly passes state and payload to action', () => {
+ const exampleState = { FOO: 12, BAR: 3 };
+ const examplePayload = { BAZ: 73, BIZ: 55 };
+
+ const action = ({ state }, payload) => {
+ originalExpect(state).toEqual(exampleState);
+ originalExpect(payload).toEqual(examplePayload);
+ };
+
+ assertion = { mutations: [], actions: [] };
+
+ testAction(action, examplePayload, exampleState);
+ });
+
+ describe('given a sync action', () => {
+ it('mocks committing mutations', () => {
+ const action = ({ commit }) => {
+ commit('MUTATION');
+ };
+
+ assertion = { mutations: [{ type: 'MUTATION' }], actions: [] };
+
+ testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
+ });
+
+ it('mocks dispatching actions', () => {
+ const action = ({ dispatch }) => {
+ dispatch('ACTION');
+ };
+
+ assertion = { actions: [{ type: 'ACTION' }], mutations: [] };
+
+ testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
+ });
+
+ it('works with done callback once finished', (done) => {
+ assertion = { mutations: [], actions: [] };
+
+ testAction(noop, null, {}, assertion.mutations, assertion.actions, done);
+ });
+
+ it('returns a promise', (done) => {
+ assertion = { mutations: [], actions: [] };
+
+ testAction(noop, null, {}, assertion.mutations, assertion.actions)
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('given an async action (returning a promise)', () => {
+ let lastError;
+ const data = { FOO: 'BAR' };
+
+ const asyncAction = ({ commit, dispatch }) => {
+ dispatch('ACTION');
+
+ return axios
+ .get(TEST_HOST)
+ .catch((error) => {
+ commit('ERROR');
+ lastError = error;
+ throw error;
+ })
+ .then(() => {
+ commit('SUCCESS');
+ return data;
+ });
+ };
+
+ beforeEach(() => {
+ lastError = null;
+ });
+
+ it('works with done callback once finished', (done) => {
+ mock.onGet(TEST_HOST).replyOnce(200, 42);
+
+ assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
+
+ testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
+ });
+
+ it('returns original data of successful promise while checking actions/mutations', (done) => {
+ mock.onGet(TEST_HOST).replyOnce(200, 42);
+
+ assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
+
+ testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
+ .then((res) => {
+ originalExpect(res).toEqual(data);
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('returns original error of rejected promise while checking actions/mutations', (done) => {
+ mock.onGet(TEST_HOST).replyOnce(500, '');
+
+ assertion = { mutations: [{ type: 'ERROR' }], actions: [{ type: 'ACTION' }] };
+
+ testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
+ .then(done.fail)
+ .catch((error) => {
+ originalExpect(error).toBe(lastError);
+ done();
+ });
+ });
+ });
+
+ it('works with async actions not returning promises', (done) => {
+ const data = { FOO: 'BAR' };
+
+ const asyncAction = ({ commit, dispatch }) => {
+ dispatch('ACTION');
+
+ axios
+ .get(TEST_HOST)
+ .then(() => {
+ commit('SUCCESS');
+ return data;
+ })
+ .catch((error) => {
+ commit('ERROR');
+ throw error;
+ });
+ };
+
+ mock.onGet(TEST_HOST).replyOnce(200, 42);
+
+ assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
+
+ testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
+ });
+ },
+);
diff --git a/spec/frontend/__helpers__/wait_for_promises.js b/spec/frontend/__helpers__/wait_for_promises.js
new file mode 100644
index 00000000000..2fd1cc6ba0d
--- /dev/null
+++ b/spec/frontend/__helpers__/wait_for_promises.js
@@ -0,0 +1 @@
+export default () => new Promise((resolve) => requestAnimationFrame(resolve));
diff --git a/spec/frontend/helpers/wait_for_text.js b/spec/frontend/__helpers__/wait_for_text.js
index 6bed8a90a98..6bed8a90a98 100644
--- a/spec/frontend/helpers/wait_for_text.js
+++ b/spec/frontend/__helpers__/wait_for_text.js
diff --git a/spec/frontend/__helpers__/wait_using_real_timer.js b/spec/frontend/__helpers__/wait_using_real_timer.js
new file mode 100644
index 00000000000..110d5f46c08
--- /dev/null
+++ b/spec/frontend/__helpers__/wait_using_real_timer.js
@@ -0,0 +1,7 @@
+/* useful for timing promises when jest fakeTimers are not reliable enough */
+export default (timeout) =>
+ new Promise((resolve) => {
+ jest.useRealTimers();
+ setTimeout(resolve, timeout);
+ jest.useFakeTimers();
+ });
diff --git a/spec/frontend/helpers/web_worker_mock.js b/spec/frontend/__helpers__/web_worker_mock.js
index 2b4a391e1d2..2b4a391e1d2 100644
--- a/spec/frontend/helpers/web_worker_mock.js
+++ b/spec/frontend/__helpers__/web_worker_mock.js
diff --git a/spec/frontend/__mocks__/@gitlab/ui.js b/spec/frontend/__mocks__/@gitlab/ui.js
index 94e3f624c25..7cdecefab05 100644
--- a/spec/frontend/__mocks__/@gitlab/ui.js
+++ b/spec/frontend/__mocks__/@gitlab/ui.js
@@ -2,7 +2,7 @@ export * from '@gitlab/ui';
/**
* The @gitlab/ui tooltip directive requires awkward and distracting set up in tests
- * for components that use it (e.g., `attachToDocument: true` and `sync: true` passed
+ * for components that use it (e.g., `attachTo: document.body` and `sync: true` passed
* to the `mount` helper from `vue-test-utils`).
*
* This mock decouples those tests from the implementation, removing the need to set
@@ -38,7 +38,7 @@ 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'].map((prop) => [prop, {}])),
},
render(h) {
return h(
@@ -47,7 +47,7 @@ jest.mock('@gitlab/ui/dist/components/base/popover/popover.js', () => ({
class: 'gl-popover',
...this.$attrs,
},
- Object.keys(this.$slots).map(s => this.$slots[s]),
+ Object.keys(this.$slots).map((s) => this.$slots[s]),
);
},
}));
diff --git a/spec/frontend/__mocks__/lodash/debounce.js b/spec/frontend/__mocks__/lodash/debounce.js
index e8b61c80147..d4fe2ce5406 100644
--- a/spec/frontend/__mocks__/lodash/debounce.js
+++ b/spec/frontend/__mocks__/lodash/debounce.js
@@ -8,7 +8,7 @@
// [2]: https://gitlab.com/gitlab-org/gitlab/-/issues/213378
// Further reference: https://github.com/facebook/jest/issues/3465
-export default fn => {
+export default (fn) => {
const debouncedFn = jest.fn().mockImplementation(fn);
debouncedFn.cancel = jest.fn();
debouncedFn.flush = jest.fn().mockImplementation(() => {
diff --git a/spec/frontend/__mocks__/lodash/defer.js b/spec/frontend/__mocks__/lodash/defer.js
new file mode 100644
index 00000000000..9325cb28ba6
--- /dev/null
+++ b/spec/frontend/__mocks__/lodash/defer.js
@@ -0,0 +1,5 @@
+/**
+ * Instead of messing around with timers, we execute deferred functions
+ * immediately in our specs
+ */
+export default (fn, ...args) => fn(...args);
diff --git a/spec/frontend/__mocks__/lodash/throttle.js b/spec/frontend/__mocks__/lodash/throttle.js
index aef391afd0c..e8a82654c78 100644
--- a/spec/frontend/__mocks__/lodash/throttle.js
+++ b/spec/frontend/__mocks__/lodash/throttle.js
@@ -1,4 +1,4 @@
// Similar to `lodash/debounce`, `lodash/throttle` also causes flaky specs.
// See `./debounce.js` for more details.
-export default fn => fn;
+export default (fn) => fn;
diff --git a/spec/frontend/activities_spec.js b/spec/frontend/activities_spec.js
index d14be3a1f26..00519148b30 100644
--- a/spec/frontend/activities_spec.js
+++ b/spec/frontend/activities_spec.js
@@ -44,23 +44,19 @@ describe('Activities', () => {
});
for (let i = 0; i < filters.length; i += 1) {
- (i => {
+ ((i) => {
describe(`when selecting ${getEventName(i)}`, () => {
beforeEach(() => {
$(getSelector(i)).click();
});
for (let x = 0; x < filters.length; x += 1) {
- (x => {
+ ((x) => {
const shouldHighlight = i === x;
const testName = shouldHighlight ? 'should highlight' : 'should not highlight';
it(`${testName} ${getEventName(x)}`, () => {
- expect(
- $(getSelector(x))
- .parent()
- .hasClass('active'),
- ).toEqual(shouldHighlight);
+ expect($(getSelector(x)).parent().hasClass('active')).toEqual(shouldHighlight);
});
})(x);
}
diff --git a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
index 8948a9926bb..1eb9ccc9c6c 100644
--- a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
+++ b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
@@ -4,6 +4,7 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = `
<gl-modal-stub
body-class="add-review-item pt-0"
cancel-variant="light"
+ dismisslabel="Close"
modalclass=""
modalid="add-review-item"
ok-disabled="true"
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 24948dd6073..3bb3cb68f56 100644
--- a/spec/frontend/add_context_commits_modal/store/actions_spec.js
+++ b/spec/frontend/add_context_commits_modal/store/actions_spec.js
@@ -1,5 +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,
@@ -15,7 +16,6 @@ import {
resetModalState,
} from '~/add_context_commits_modal/store/actions';
import * as types from '~/add_context_commits_modal/store/mutation_types';
-import testAction from '../../helpers/vuex_action_helper';
describe('AddContextCommitsModalStoreActions', () => {
const contextCommitEndpoint =
@@ -42,7 +42,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setBaseConfig', () => {
- it('commits SET_BASE_CONFIG', done => {
+ it('commits SET_BASE_CONFIG', (done) => {
const options = { contextCommitsPath, mergeRequestIid, projectId };
testAction(
setBaseConfig,
@@ -65,7 +65,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setTabIndex', () => {
- it('commits SET_TABINDEX', done => {
+ it('commits SET_TABINDEX', (done) => {
testAction(
setTabIndex,
{ tabIndex: 1 },
@@ -78,7 +78,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setCommits', () => {
- it('commits SET_COMMITS', done => {
+ it('commits SET_COMMITS', (done) => {
testAction(
setCommits,
{ commits: [], silentAddition: false },
@@ -89,7 +89,7 @@ describe('AddContextCommitsModalStoreActions', () => {
);
});
- it('commits SET_COMMITS_SILENT', done => {
+ it('commits SET_COMMITS_SILENT', (done) => {
testAction(
setCommits,
{ commits: [], silentAddition: true },
@@ -102,7 +102,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('createContextCommits', () => {
- it('calls API to create context commits', done => {
+ it('calls API to create context commits', (done) => {
mock.onPost(contextCommitEndpoint).reply(200, {});
testAction(createContextCommits, { commits: [] }, {}, [], [], done);
@@ -126,7 +126,7 @@ describe('AddContextCommitsModalStoreActions', () => {
)
.reply(200, [dummyCommit]);
});
- it('commits FETCH_CONTEXT_COMMITS', done => {
+ it('commits FETCH_CONTEXT_COMMITS', (done) => {
const contextCommit = { ...dummyCommit, isSelected: true };
testAction(
fetchContextCommits,
@@ -150,7 +150,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setContextCommits', () => {
- it('commits SET_CONTEXT_COMMITS', done => {
+ it('commits SET_CONTEXT_COMMITS', (done) => {
testAction(
setContextCommits,
{ data: [] },
@@ -168,7 +168,7 @@ describe('AddContextCommitsModalStoreActions', () => {
.onDelete('/api/v4/projects/gitlab-org%2Fgitlab/merge_requests/1/context_commits')
.reply(204);
});
- it('calls API to remove context commits', done => {
+ it('calls API to remove context commits', (done) => {
testAction(
removeContextCommits,
{ forceReload: false },
@@ -181,7 +181,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setSelectedCommits', () => {
- it('commits SET_SELECTED_COMMITS', done => {
+ it('commits SET_SELECTED_COMMITS', (done) => {
testAction(
setSelectedCommits,
[dummyCommit],
@@ -194,7 +194,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setSearchText', () => {
- it('commits SET_SEARCH_TEXT', done => {
+ it('commits SET_SEARCH_TEXT', (done) => {
const searchText = 'Dummy Text';
testAction(
setSearchText,
@@ -208,7 +208,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setToRemoveCommits', () => {
- it('commits SET_TO_REMOVE_COMMITS', done => {
+ it('commits SET_TO_REMOVE_COMMITS', (done) => {
const commitId = 'abcde';
testAction(
@@ -223,7 +223,7 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('resetModalState', () => {
- it('commits RESET_MODAL_STATE', done => {
+ it('commits RESET_MODAL_STATE', (done) => {
const commitId = 'abcde';
testAction(
diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js
index dda0c2b857c..a4dcfa1a480 100644
--- a/spec/frontend/admin/statistics_panel/components/app_spec.js
+++ b/spec/frontend/admin/statistics_panel/components/app_spec.js
@@ -34,7 +34,7 @@ describe('Admin statistics app', () => {
wrapper.destroy();
});
- const findStats = idx => wrapper.findAll('.js-stats').at(idx);
+ const findStats = (idx) => wrapper.findAll('.js-stats').at(idx);
describe('template', () => {
describe('when app is loading', () => {
diff --git a/spec/frontend/admin/statistics_panel/store/actions_spec.js b/spec/frontend/admin/statistics_panel/store/actions_spec.js
index 9b18b1aebda..ecbc823be12 100644
--- a/spec/frontend/admin/statistics_panel/store/actions_spec.js
+++ b/spec/frontend/admin/statistics_panel/store/actions_spec.js
@@ -22,7 +22,7 @@ describe('Admin statistics panel actions', () => {
mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(200, mockStatistics);
});
- it('dispatches success with received data', done =>
+ it('dispatches success with received data', (done) =>
testAction(
actions.fetchStatistics,
null,
@@ -46,7 +46,7 @@ describe('Admin statistics panel actions', () => {
mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(500);
});
- it('dispatches error', done =>
+ it('dispatches error', (done) =>
testAction(
actions.fetchStatistics,
null,
@@ -67,7 +67,7 @@ describe('Admin statistics panel actions', () => {
});
describe('requestStatistic', () => {
- it('should commit the request mutation', done =>
+ it('should commit the request mutation', (done) =>
testAction(
actions.requestStatistics,
null,
@@ -79,7 +79,7 @@ describe('Admin statistics panel actions', () => {
});
describe('receiveStatisticsSuccess', () => {
- it('should commit received data', done =>
+ it('should commit received data', (done) =>
testAction(
actions.receiveStatisticsSuccess,
mockStatistics,
@@ -96,7 +96,7 @@ describe('Admin statistics panel actions', () => {
});
describe('receiveStatisticsError', () => {
- it('should commit error', done => {
+ it('should commit error', (done) => {
testAction(
actions.receiveStatisticsError,
500,
diff --git a/spec/frontend/admin/users/components/user_avatar_spec.js b/spec/frontend/admin/users/components/user_avatar_spec.js
new file mode 100644
index 00000000000..ba4e83690d0
--- /dev/null
+++ b/spec/frontend/admin/users/components/user_avatar_spec.js
@@ -0,0 +1,63 @@
+import { GlAvatarLink, GlAvatarLabeled, GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+
+import AdminUserAvatar from '~/admin/users/components/user_avatar.vue';
+import { users, paths } from '../mock_data';
+
+describe('AdminUserAvatar component', () => {
+ let wrapper;
+ const user = users[0];
+ const adminUserPath = paths.adminUser;
+
+ const findAvatar = () => wrapper.find(GlAvatarLabeled);
+ const findAvatarLink = () => wrapper.find(GlAvatarLink);
+ const findAllBadges = () => wrapper.findAll(GlBadge);
+
+ const initComponent = (props = {}) => {
+ wrapper = mount(AdminUserAvatar, {
+ propsData: {
+ user,
+ adminUserPath,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when initialized', () => {
+ beforeEach(() => {
+ initComponent();
+ });
+
+ it("links to the user's admin path", () => {
+ expect(findAvatarLink().attributes()).toMatchObject({
+ href: adminUserPath.replace('id', user.username),
+ '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 email", () => {
+ expect(findAvatar().props('subLabel')).toBe(user.email);
+ });
+
+ it("renders the user's avatar image", () => {
+ expect(findAvatar().attributes('src')).toBe(user.avatarUrl);
+ });
+
+ 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);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index ba36e1e32ef..b79d2d4d39d 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -2,6 +2,7 @@ import { GlTable } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import AdminUsersTable from '~/admin/users/components/users_table.vue';
+import AdminUserAvatar from '~/admin/users/components/user_avatar.vue';
import { users, paths } from '../mock_data';
describe('AdminUsersTable component', () => {
@@ -44,8 +45,12 @@ describe('AdminUsersTable component', () => {
${'projectsCount'} | ${'Projects'}
${'createdAt'} | ${'Created on'}
${'lastActivityOn'} | ${'Last activity'}
- `('renders users.$key for $label', ({ key, label }) => {
- expect(getCellByLabel(0, label).text()).toBe(`${user[key]}`);
+ `('renders users.$key in column $label', ({ key, label }) => {
+ expect(getCellByLabel(0, label).text()).toContain(`${user[key]}`);
+ });
+
+ it('renders an AdminUserAvatar component', () => {
+ expect(getCellByLabel(0, 'Name').find(AdminUserAvatar).exists()).toBe(true);
});
});
diff --git a/spec/frontend/admin/users/mock_data.js b/spec/frontend/admin/users/mock_data.js
index 62fa9469638..860994a9152 100644
--- a/spec/frontend/admin/users/mock_data.js
+++ b/spec/frontend/admin/users/mock_data.js
@@ -8,7 +8,10 @@ export const users = [
lastActivityOn: '2020-12-09',
avatarUrl:
'https://secure.gravatar.com/avatar/054f062d8b1a42b123f17e13a173cda8?s=80\\u0026d=identicon',
- badges: [],
+ badges: [
+ { text: 'Admin', variant: 'success' },
+ { text: "It's you!", variant: null },
+ ],
projectsCount: 0,
actions: [],
},
diff --git a/spec/frontend/alert_handler_spec.js b/spec/frontend/alert_handler_spec.js
index 0cee28112a8..e4cd38a7799 100644
--- a/spec/frontend/alert_handler_spec.js
+++ b/spec/frontend/alert_handler_spec.js
@@ -7,7 +7,7 @@ describe('Alert Handler', () => {
const DISMISS_CLASS = 'gl-alert-dismiss';
const DISMISS_LABEL = 'Dismiss';
- const generateHtml = parentClass =>
+ const generateHtml = (parentClass) =>
`<div class="${parentClass}">
<button aria-label="${DISMISS_LABEL}">Dismiss</button>
</div>`;
diff --git a/spec/frontend/alert_management/components/alert_details_spec.js b/spec/frontend/alert_management/components/alert_details_spec.js
index e2d913398f9..976e50625a6 100644
--- a/spec/frontend/alert_management/components/alert_details_spec.js
+++ b/spec/frontend/alert_management/components/alert_details_spec.js
@@ -3,6 +3,7 @@ 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 {
@@ -201,6 +202,11 @@ describe('AlertDetails', () => {
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 } } } });
@@ -215,7 +221,7 @@ describe('AlertDetails', () => {
});
});
- it('shows error alert when incident creation fails ', () => {
+ it('shows error alert when incident creation fails ', async () => {
const errorMsg = 'Something went wrong';
mountComponent({
mountMethod: mount,
@@ -225,9 +231,8 @@ describe('AlertDetails', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
findCreateIncidentBtn().trigger('click');
- setImmediate(() => {
- expect(findIncidentCreationAlert().text()).toBe(errorMsg);
- });
+ await waitForPromises();
+ expect(findIncidentCreationAlert().text()).toBe(errorMsg);
});
});
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 ddb102339cc..509c67743c1 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
@@ -31,17 +31,5 @@ describe('AlertManagementEmptyState', () => {
it('shows empty state', () => {
expect(EmptyState().exists()).toBe(true);
});
-
- it('show OpsGenie integration state when OpsGenie mcv is true', () => {
- mountComponent({
- provide: {
- alertManagementEnabled: false,
- userCanEnableAlertManagement: false,
- opsgenieMvcEnabled: true,
- opsgenieMvcTargetUrl: 'https://opsgenie-url.com',
- },
- });
- expect(EmptyState().props('title')).toBe('Opsgenie is enabled');
- });
});
});
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 f7a629142f9..0cc3d565e10 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -85,11 +85,7 @@ describe('AlertManagementTable', () => {
});
expect(findAlertsTable().exists()).toBe(true);
expect(findLoader().exists()).toBe(true);
- expect(
- findAlerts()
- .at(0)
- .classes(),
- ).not.toContain('gl-hover-bg-blue-50');
+ expect(findAlerts().at(0).classes()).not.toContain('gl-hover-bg-blue-50');
});
it('error state', () => {
@@ -101,11 +97,7 @@ describe('AlertManagementTable', () => {
expect(findAlertsTable().text()).toContain('No alerts to display');
expect(findLoader().exists()).toBe(false);
expect(findAlert().props().variant).toBe('danger');
- expect(
- findAlerts()
- .at(0)
- .classes(),
- ).not.toContain('gl-hover-bg-blue-50');
+ expect(findAlerts().at(0).classes()).not.toContain('gl-hover-bg-blue-50');
});
it('empty state', () => {
@@ -125,11 +117,7 @@ describe('AlertManagementTable', () => {
expect(findAlertsTable().text()).toContain('No alerts to display');
expect(findLoader().exists()).toBe(false);
expect(findAlert().props().variant).toBe('info');
- expect(
- findAlerts()
- .at(0)
- .classes(),
- ).not.toContain('gl-hover-bg-blue-50');
+ expect(findAlerts().at(0).classes()).not.toContain('gl-hover-bg-blue-50');
});
it('has data state', () => {
@@ -140,11 +128,7 @@ describe('AlertManagementTable', () => {
expect(findLoader().exists()).toBe(false);
expect(findAlertsTable().exists()).toBe(true);
expect(findAlerts()).toHaveLength(mockAlerts.length);
- expect(
- findAlerts()
- .at(0)
- .classes(),
- ).toContain('gl-hover-bg-blue-50');
+ expect(findAlerts().at(0).classes()).toContain('gl-hover-bg-blue-50');
});
it('displays the alert ID and title formatted correctly', () => {
@@ -170,11 +154,7 @@ describe('AlertManagementTable', () => {
data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
- expect(
- findStatusDropdown()
- .find('.dropdown-title')
- .exists(),
- ).toBe(false);
+ expect(findStatusDropdown().find('.dropdown-title').exists()).toBe(false);
});
it('shows correct severity icons', async () => {
@@ -186,11 +166,7 @@ describe('AlertManagementTable', () => {
await wrapper.vm.$nextTick();
expect(wrapper.find(GlTable).exists()).toBe(true);
- expect(
- findAlertsTable()
- .find(GlIcon)
- .classes('icon-critical'),
- ).toBe(true);
+ expect(findAlertsTable().find(GlIcon).classes('icon-critical')).toBe(true);
});
it('renders severity text', () => {
@@ -199,11 +175,7 @@ describe('AlertManagementTable', () => {
loading: false,
});
- expect(
- findSeverityFields()
- .at(0)
- .text(),
- ).toBe('Critical');
+ expect(findSeverityFields().at(0).text()).toBe('Critical');
});
it('renders Unassigned when no assignee(s) present', () => {
@@ -212,11 +184,7 @@ describe('AlertManagementTable', () => {
loading: false,
});
- expect(
- findAssignees()
- .at(0)
- .text(),
- ).toBe('Unassigned');
+ expect(findAssignees().at(0).text()).toBe('Unassigned');
});
it('renders user avatar when assignee present', () => {
@@ -225,9 +193,7 @@ describe('AlertManagementTable', () => {
loading: false,
});
- const avatar = findAssignees()
- .at(1)
- .find(GlAvatar);
+ const avatar = findAssignees().at(1).find(GlAvatar);
const { src, label } = avatar.attributes();
const { name, avatarUrl } = mockAlerts[1].assignees.nodes[0];
@@ -244,9 +210,7 @@ describe('AlertManagementTable', () => {
expect(visitUrl).not.toHaveBeenCalled();
- findAlerts()
- .at(0)
- .trigger('click');
+ findAlerts().at(0).trigger('click');
expect(visitUrl).toHaveBeenCalledWith('/1527542/details', false);
});
@@ -258,11 +222,9 @@ describe('AlertManagementTable', () => {
expect(visitUrl).not.toHaveBeenCalled();
- findAlerts()
- .at(0)
- .trigger('click', {
- metaKey: true,
- });
+ findAlerts().at(0).trigger('click', {
+ metaKey: true,
+ });
expect(visitUrl).toHaveBeenCalledWith('/1527542/details', true);
});
@@ -276,24 +238,12 @@ describe('AlertManagementTable', () => {
});
it('shows "None" when no link exists', () => {
- expect(
- findIssueFields()
- .at(0)
- .text(),
- ).toBe('None');
+ expect(findIssueFields().at(0).text()).toBe('None');
});
it('renders a link when one exists', () => {
- expect(
- findIssueFields()
- .at(1)
- .text(),
- ).toBe('#1');
- expect(
- findIssueFields()
- .at(1)
- .attributes('href'),
- ).toBe('/gitlab-org/gitlab/-/issues/1');
+ expect(findIssueFields().at(1).text()).toBe('#1');
+ expect(findIssueFields().at(1).attributes('href')).toBe('/gitlab-org/gitlab/-/issues/1');
});
});
@@ -350,11 +300,7 @@ describe('AlertManagementTable', () => {
loading: false,
});
- expect(
- findAlerts()
- .at(0)
- .classes(),
- ).toContain('new-alert');
+ expect(findAlerts().at(0).classes()).toContain('new-alert');
});
it('should not highlight the row when alert is not new', () => {
@@ -363,11 +309,7 @@ describe('AlertManagementTable', () => {
loading: false,
});
- expect(
- findAlerts()
- .at(0)
- .classes(),
- ).not.toContain('new-alert');
+ expect(findAlerts().at(0).classes()).not.toContain('new-alert');
});
});
});
diff --git a/spec/frontend/alert_management/components/alert_status_spec.js b/spec/frontend/alert_management/components/alert_status_spec.js
index f5916b8b265..6f2ddb86020 100644
--- a/spec/frontend/alert_management/components/alert_status_spec.js
+++ b/spec/frontend/alert_management/components/alert_status_spec.js
@@ -3,7 +3,7 @@ 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 '~/alert_management/graphql/mutations/update_alert_status.mutation.graphql';
+import updateAlertStatusMutation from '~/graphql_shared/mutations/update_alert_status.mutation.graphql';
import Tracking from '~/tracking';
import mockAlerts from '../mocks/alerts.json';
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
index 6430273ec59..00c479071fe 100644
--- 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
@@ -165,21 +165,9 @@ describe('Alert Details Sidebar Assignees', () => {
},
});
- 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');
+ 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_status_spec.js b/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
index bef4a341985..0b60a36cf54 100644
--- a/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
+++ b/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
@@ -2,7 +2,7 @@ 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 '~/alert_management/graphql/mutations/update_alert_status.mutation.graphql';
+import updateAlertStatusMutation from '~/graphql_shared/mutations/update_alert_status.mutation.graphql';
import Tracking from '~/tracking';
import mockAlerts from '../../mocks/alerts.json';
diff --git a/spec/frontend/alert_management/mocks/alerts_provide_config.json b/spec/frontend/alert_management/mocks/alerts_provide_config.json
index af543e641bc..3313ff8128c 100644
--- a/spec/frontend/alert_management/mocks/alerts_provide_config.json
+++ b/spec/frontend/alert_management/mocks/alerts_provide_config.json
@@ -7,7 +7,5 @@
"populatingAlertsHelpUrl": "/link",
"emptyAlertSvgPath": "/link",
"alertManagementEnabled": false,
- "userCanEnableAlertManagement": false,
- "opsgenieMvcTargetUrl": "/link",
- "opsgenieMvcEnabled": false
+ "userCanEnableAlertManagement": false
} \ No newline at end of file
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
index ed78a593944..346059ed7be 100644
--- a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
+++ b/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
@@ -22,29 +23,21 @@ describe('AlertsServiceForm', () => {
let wrapper;
let mockAxios;
- const createComponent = (props = defaultProps, { methods } = {}) => {
+ const createComponent = (props = defaultProps) => {
wrapper = shallowMount(AlertsServiceForm, {
propsData: {
...defaultProps,
...props,
},
- methods,
});
};
const findUrl = () => wrapper.find('#url');
const findAuthorizationKey = () => wrapper.find('#authorization-key');
const findDescription = () => wrapper.find('[data-testid="description"');
- const findActiveStatusIcon = val =>
- document.querySelector(`.js-service-active-status[data-value=${val.toString()}]`);
beforeEach(() => {
mockAxios = new MockAdapter(axios);
- setFixtures(`
- <div>
- <span class="js-service-active-status" data-value="true"><svg class="s16 cgreen" data-testid="check-icon"><use xlink:href="icons.svg#check" /></svg></span>
- <span class="js-service-active-status" data-value="false"><svg class="s16 clgray" data-testid="power-icon"><use xlink:href="icons.svg#power" /></svg></span>
- </div>`);
});
afterEach(() => {
@@ -75,25 +68,16 @@ describe('AlertsServiceForm', () => {
});
describe('reset key', () => {
- it('triggers resetKey method', () => {
- const resetKey = jest.fn();
- const methods = { resetKey };
- createComponent(defaultProps, { methods });
-
- wrapper.find(GlModal).vm.$emit('ok');
-
- expect(resetKey).toHaveBeenCalled();
- });
-
- it('updates the authorization key on success', () => {
+ it('updates the authorization key on success', async () => {
const formPath = 'some/path';
- mockAxios.onPut(formPath, { service: { token: '' } }).replyOnce(200, { token: 'newToken' });
+ mockAxios.onPut(formPath).replyOnce(200, { token: 'newToken' });
createComponent({ formPath });
- return wrapper.vm.resetKey().then(() => {
- expect(findAuthorizationKey().attributes('value')).toBe('newToken');
- });
+ wrapper.find(GlModal).vm.$emit('ok');
+ await axios.waitForAll();
+
+ expect(findAuthorizationKey().attributes('value')).toBe('newToken');
});
it('shows flash message on error', () => {
@@ -112,16 +96,6 @@ describe('AlertsServiceForm', () => {
});
describe('activate toggle', () => {
- it('triggers toggleActivated method', () => {
- const toggleActivated = jest.fn();
- const methods = { toggleActivated };
- createComponent(defaultProps, { methods });
-
- wrapper.find(ToggleButton).vm.$emit('change', true);
-
- expect(toggleActivated).toHaveBeenCalled();
- });
-
describe('successfully completes', () => {
describe.each`
initialActivated | value
@@ -143,11 +117,6 @@ describe('AlertsServiceForm', () => {
it(`updates toggle button value to ${value}`, () => {
expect(wrapper.find(ToggleButton).props('value')).toBe(value);
});
-
- it('updates visible status icons', () => {
- expect(findActiveStatusIcon(!value)).toHaveClass('d-none');
- expect(findActiveStatusIcon(value)).not.toHaveClass('d-none');
- });
},
);
});
@@ -175,7 +144,7 @@ describe('AlertsServiceForm', () => {
it('cannot be toggled', () => {
wrapper.find(ToggleButton).vm.$emit('change');
- return wrapper.vm.$nextTick().then(() => {
+ 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
index a1ced8910b3..ef68a6a2c32 100644
--- a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap
+++ b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap
@@ -4,11 +4,10 @@ exports[`AlertsSettingsFormNew with default values renders the initial template
"<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 custom-select\\" id=\\"__BVID__8\\">
+ <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>
- <option value=\\"OPSGENIE\\">Opsgenie</option>
</select>
<!---->
<!---->
@@ -16,82 +15,84 @@ exports[`AlertsSettingsFormNew with default values renders the initial template
<!---->
</div>
</div>
- <div class=\\"gl-mt-3 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\\">
- <!---->
- <!---->
- <!---->
+ <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>
- <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>
+ <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>
<!---->
- </label>
- <!---->
- <div class=\\"gl-my-4\\"><span class=\\"gl-font-weight-bold\\">
+ <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 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>
- <div class=\\"gl-my-4\\"><span class=\\"gl-font-weight-bold\\">
+ <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\\">
+ <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\\">
<!---->
- <!----> <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\\">
+ <!----> <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 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 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\\">
<!---->
- </div>
- </div>
- <!---->
- <!---->
+ <!----> <span class=\\"gl-button-text\\">Cancel</span></button></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
index 12536c27dfe..5d48ff02e35 100644
--- a/spec/frontend/alerts_settings/alert_mapping_builder_spec.js
+++ b/spec/frontend/alerts_settings/alert_mapping_builder_spec.js
@@ -28,11 +28,7 @@ describe('AlertMappingBuilder', () => {
});
const findColumnInRow = (row, column) =>
- wrapper
- .findAll('.gl-display-table-row')
- .at(row)
- .findAll('.gl-display-table-cell ')
- .at(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);
@@ -67,7 +63,7 @@ describe('AlertMappingBuilder', () => {
const dropdownItems = dropdown.findAll(GlDropdownItem);
const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
const numberOfMappingOptions = nodes.filter(({ type }) =>
- type.some(t => compatibleTypes.includes(t)),
+ type.some((t) => compatibleTypes.includes(t)),
);
expect(dropdown.exists()).toBe(true);
@@ -86,7 +82,7 @@ describe('AlertMappingBuilder', () => {
const dropdownItems = dropdown.findAll(GlDropdownItem);
const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
const numberOfMappingOptions = nodes.filter(({ type }) =>
- type.some(t => compatibleTypes.includes(t)),
+ type.some((t) => compatibleTypes.includes(t)),
);
expect(searchBox.exists()).toBe(Boolean(numberOfFallbacks));
diff --git a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
index 3a7392f64f7..5a3874d055b 100644
--- a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
+++ b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
@@ -72,11 +72,7 @@ describe('AlertIntegrationsList', () => {
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');
+ expect(findTableComponentRows().at(0).classes()).toContain('gl-bg-blue-50');
});
describe('integration status', () => {
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_spec.js
index 428c6f93444..21cdec6f94c 100644
--- a/spec/frontend/alerts_settings/alerts_settings_form_spec.js
+++ b/spec/frontend/alerts_settings/alerts_settings_form_spec.js
@@ -28,7 +28,6 @@ describe('AlertsSettingsFormNew', () => {
propsData: {
loading: false,
canAddIntegration: true,
- canManageOpsgenie: true,
...props,
},
provide: {
@@ -86,11 +85,7 @@ describe('AlertsSettingsFormNew', () => {
await wrapper.vm.$nextTick();
- expect(
- findFormFields()
- .at(0)
- .isVisible(),
- ).toBe(true);
+ expect(findFormFields().at(0).isVisible()).toBe(true);
});
it('disables the dropdown and shows help text when multi integrations are not supported', async () => {
@@ -104,11 +99,7 @@ describe('AlertsSettingsFormNew', () => {
const options = findSelect().findAll('option');
await options.at(2).setSelected();
- expect(
- findFormFields()
- .at(0)
- .attributes('disabled'),
- ).toBe('disabled');
+ expect(findFormFields().at(0).attributes('disabled')).toBe('disabled');
});
});
@@ -119,9 +110,7 @@ describe('AlertsSettingsFormNew', () => {
const options = findSelect().findAll('option');
await options.at(1).setSelected();
- await findFormFields()
- .at(0)
- .setValue('Test integration');
+ await findFormFields().at(0).setValue('Test integration');
await findFormToggle().trigger('click');
await wrapper.vm.$nextTick();
@@ -145,12 +134,8 @@ describe('AlertsSettingsFormNew', () => {
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 findFormFields().at(0).setValue('Test integration');
+ await findFormFields().at(1).setValue('https://test.com');
await findFormToggle().trigger('click');
await wrapper.vm.$nextTick();
@@ -179,9 +164,7 @@ describe('AlertsSettingsFormNew', () => {
},
});
- await findFormFields()
- .at(0)
- .setValue('Test integration post');
+ await findFormFields().at(0).setValue('Test integration post');
await findFormToggle().trigger('click');
await wrapper.vm.$nextTick();
@@ -210,12 +193,8 @@ describe('AlertsSettingsFormNew', () => {
},
});
- await findFormFields()
- .at(0)
- .setValue('Test integration');
- await findFormFields()
- .at(1)
- .setValue('https://test-post.com');
+ await findFormFields().at(0).setValue('Test integration');
+ await findFormFields().at(1).setValue('https://test-post.com');
await findFormToggle().trigger('click');
await wrapper.vm.$nextTick();
@@ -300,11 +279,7 @@ describe('AlertsSettingsFormNew', () => {
resetSamplePayloadConfirmed,
});
await wrapper.vm.$nextTick();
- expect(
- findTestPayloadSection()
- .find(GlFormTextarea)
- .attributes('disabled'),
- ).toBe(disabled);
+ expect(findTestPayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(disabled);
});
});
diff --git a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
index fe187d9e8f9..4d0732ca76c 100644
--- a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
@@ -1,10 +1,10 @@
import VueApollo from 'vue-apollo';
import { mount, createLocalVue } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
-import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
+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';
@@ -376,17 +376,4 @@ describe('AlertsSettingsWrapper', () => {
});
});
});
-
- // TODO: Will be removed in 13.7 as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/273657
- describe('Opsgenie integration', () => {
- it.each([true, false])('it shows/hides the alert when opsgenie is %s', active => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- provide: { opsgenie: { active } },
- loading: false,
- });
-
- expect(wrapper.find(GlAlert).exists()).toBe(active);
- });
- });
});
diff --git a/spec/frontend/alerts_settings/util.js b/spec/frontend/alerts_settings/util.js
index f9f9b69791e..5c07f22f1c9 100644
--- a/spec/frontend/alerts_settings/util.js
+++ b/spec/frontend/alerts_settings/util.js
@@ -19,12 +19,6 @@ export const defaultAlertSettingsConfig = {
url: PROMETHEUS_URL,
active: ACTIVE,
},
- opsgenie: {
- opsgenieMvcIsAvailable: true,
- formPath: INVALID_URL,
- active: ACTIVE,
- opsgenieMvcTargetUrl: GENERIC_URL,
- },
projectPath: '',
multiIntegrations: true,
};
diff --git a/spec/frontend/analytics/instance_statistics/components/app_spec.js b/spec/frontend/analytics/instance_statistics/components/app_spec.js
index 8ac663b3046..cc676e86e99 100644
--- a/spec/frontend/analytics/instance_statistics/components/app_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/app_spec.js
@@ -25,11 +25,11 @@ describe('InstanceStatisticsApp', () => {
expect(wrapper.find(InstanceCounts).exists()).toBe(true);
});
- ['Pipelines', 'Issues & Merge Requests'].forEach(instance => {
+ ['Pipelines', 'Issues & Merge Requests'].forEach((instance) => {
it(`displays the ${instance} chart`, () => {
const chartTitles = wrapper
.findAll(InstanceStatisticsCountChart)
- .wrappers.map(chartComponent => chartComponent.props('chartTitle'));
+ .wrappers.map((chartComponent) => chartComponent.props('chartTitle'));
expect(chartTitles).toContain(instance);
});
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 275a84988f8..a69f3388cbb 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
@@ -2,7 +2,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlLineChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
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 d9f42430aa8..bf94e476ea3 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
@@ -2,7 +2,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlLineChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
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 6ed9d203f3d..b9fa30643df 100644
--- a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
@@ -2,7 +2,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
diff --git a/spec/frontend/api/api_utils_spec.js b/spec/frontend/api/api_utils_spec.js
new file mode 100644
index 00000000000..3fec26f0149
--- /dev/null
+++ b/spec/frontend/api/api_utils_spec.js
@@ -0,0 +1,35 @@
+import * as apiUtils from '~/api/api_utils';
+
+describe('~/api/api_utils.js', () => {
+ describe('buildApiUrl', () => {
+ beforeEach(() => {
+ window.gon = {
+ api_version: 'v7',
+ };
+ });
+
+ it('returns a URL with the correct API version', () => {
+ expect(apiUtils.buildApiUrl('/api/:version/users/:id/status')).toEqual(
+ '/api/v7/users/:id/status',
+ );
+ });
+
+ it('only replaces the first instance of :version in the URL', () => {
+ expect(apiUtils.buildApiUrl('/api/:version/projects/:id/packages/:version')).toEqual(
+ '/api/v7/projects/:id/packages/:version',
+ );
+ });
+
+ describe('when gon includes a relative_url_root property', () => {
+ beforeEach(() => {
+ window.gon.relative_url_root = '/relative/root';
+ });
+
+ it('returns a URL with the correct relative root URL and API version', () => {
+ expect(apiUtils.buildApiUrl('/api/:version/users/:id/status')).toEqual(
+ '/relative/root/api/v7/users/:id/status',
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index 37630c15b89..76d67195499 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -34,7 +34,7 @@ describe('Api', () => {
expect(builtUrl).toEqual(expectedOutput);
});
- [null, '', '/'].forEach(root => {
+ [null, '', '/'].forEach((root) => {
it(`works when relative_url_root is ${root}`, () => {
window.gon.relative_url_root = root;
const input = '/api/:version/foo/bar';
@@ -137,14 +137,14 @@ describe('Api', () => {
});
describe('group', () => {
- it('fetches a group', done => {
+ it('fetches a group', (done) => {
const groupId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}`;
mock.onGet(expectedUrl).reply(httpStatus.OK, {
name: 'test',
});
- Api.group(groupId, response => {
+ Api.group(groupId, (response) => {
expect(response.name).toBe('test');
done();
});
@@ -152,7 +152,7 @@ describe('Api', () => {
});
describe('groupMembers', () => {
- it('fetches group members', done => {
+ it('fetches group members', (done) => {
const groupId = '54321';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/members`;
const expectedData = [{ id: 7 }];
@@ -167,8 +167,52 @@ describe('Api', () => {
});
});
+ describe('addGroupMembersByUserId', () => {
+ it('adds an existing User as a new Group Member by User ID', () => {
+ const groupId = 1;
+ const expectedUserId = 2;
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/1/members`;
+ const params = {
+ user_id: expectedUserId,
+ access_level: 10,
+ expires_at: undefined,
+ };
+
+ mock.onPost(expectedUrl).reply(200, {
+ id: expectedUserId,
+ state: 'active',
+ });
+
+ return Api.addGroupMembersByUserId(groupId, params).then(({ data }) => {
+ expect(data.id).toBe(expectedUserId);
+ expect(data.state).toBe('active');
+ });
+ });
+ });
+
+ describe('inviteGroupMembersByEmail', () => {
+ it('invites a new email address to create a new User and become a Group Member', () => {
+ const groupId = 1;
+ const email = 'email@example.com';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/1/invitations`;
+ const params = {
+ email,
+ access_level: 10,
+ expires_at: undefined,
+ };
+
+ mock.onPost(expectedUrl).reply(200, {
+ status: 'success',
+ });
+
+ return Api.inviteGroupMembersByEmail(groupId, params).then(({ data }) => {
+ expect(data.status).toBe('success');
+ });
+ });
+ });
+
describe('groupMilestones', () => {
- it('fetches group milestones', done => {
+ it('fetches group milestones', (done) => {
const groupId = '16';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/milestones`;
const expectedData = [
@@ -198,7 +242,7 @@ describe('Api', () => {
});
describe('groups', () => {
- it('fetches groups', done => {
+ it('fetches groups', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups.json`;
@@ -208,7 +252,7 @@ describe('Api', () => {
},
]);
- Api.groups(query, options, response => {
+ Api.groups(query, options, (response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
@@ -217,7 +261,7 @@ describe('Api', () => {
});
describe('namespaces', () => {
- it('fetches namespaces', done => {
+ it('fetches namespaces', (done) => {
const query = 'dummy query';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/namespaces.json`;
mock.onGet(expectedUrl).reply(httpStatus.OK, [
@@ -226,7 +270,7 @@ describe('Api', () => {
},
]);
- Api.namespaces(query, response => {
+ Api.namespaces(query, (response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
@@ -235,7 +279,7 @@ describe('Api', () => {
});
describe('projects', () => {
- it('fetches projects with membership when logged in', done => {
+ it('fetches projects with membership when logged in', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
@@ -246,14 +290,14 @@ describe('Api', () => {
},
]);
- Api.projects(query, options, response => {
+ Api.projects(query, options, (response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
});
});
- it('fetches projects without membership when not logged in', done => {
+ it('fetches projects without membership when not logged in', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
@@ -263,7 +307,7 @@ describe('Api', () => {
},
]);
- Api.projects(query, options, response => {
+ Api.projects(query, options, (response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
@@ -272,7 +316,7 @@ describe('Api', () => {
});
describe('updateProject', () => {
- it('update a project with the given payload', done => {
+ it('update a project with the given payload', (done) => {
const projectPath = 'foo';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}`;
mock.onPut(expectedUrl).reply(httpStatus.OK, { foo: 'bar' });
@@ -287,7 +331,7 @@ describe('Api', () => {
});
describe('projectUsers', () => {
- it('fetches all users of a particular project', done => {
+ it('fetches all users of a particular project', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const projectPath = 'gitlab-org%2Fgitlab-ce';
@@ -299,7 +343,7 @@ describe('Api', () => {
]);
Api.projectUsers('gitlab-org/gitlab-ce', query, options)
- .then(response => {
+ .then((response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
})
@@ -312,7 +356,7 @@ describe('Api', () => {
const projectPath = 'abc';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests`;
- it('fetches all merge requests for a project', done => {
+ it('fetches all merge requests for a project', (done) => {
const mockData = [{ source_branch: 'foo' }, { source_branch: 'bar' }];
mock.onGet(expectedUrl).reply(httpStatus.OK, mockData);
Api.projectMergeRequests(projectPath)
@@ -325,7 +369,7 @@ describe('Api', () => {
.catch(done.fail);
});
- it('fetches merge requests filtered with passed params', done => {
+ it('fetches merge requests filtered with passed params', (done) => {
const params = {
source_branch: 'bar',
};
@@ -343,7 +387,7 @@ describe('Api', () => {
});
describe('projectMergeRequest', () => {
- it('fetches a merge request', done => {
+ it('fetches a merge request', (done) => {
const projectPath = 'abc';
const mergeRequestId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}`;
@@ -361,7 +405,7 @@ describe('Api', () => {
});
describe('projectMergeRequestChanges', () => {
- it('fetches the changes of a merge request', done => {
+ it('fetches the changes of a merge request', (done) => {
const projectPath = 'abc';
const mergeRequestId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/changes`;
@@ -379,7 +423,7 @@ describe('Api', () => {
});
describe('projectMergeRequestVersions', () => {
- it('fetches the versions of a merge request', done => {
+ it('fetches the versions of a merge request', (done) => {
const projectPath = 'abc';
const mergeRequestId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/versions`;
@@ -400,7 +444,7 @@ describe('Api', () => {
});
describe('projectRunners', () => {
- it('fetches the runners of a project', done => {
+ it('fetches the runners of a project', (done) => {
const projectPath = 7;
const params = { scope: 'active' };
const mockData = [{ id: 4 }];
@@ -417,7 +461,7 @@ describe('Api', () => {
});
describe('projectMilestones', () => {
- it('fetches project milestones', done => {
+ it('fetches project milestones', (done) => {
const projectId = 1;
const options = { state: 'active' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/1/milestones`;
@@ -458,8 +502,52 @@ describe('Api', () => {
});
});
+ describe('addProjectMembersByUserId', () => {
+ it('adds an existing User as a new Project Member by User ID', () => {
+ const projectId = 1;
+ const expectedUserId = 2;
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/1/members`;
+ const params = {
+ user_id: expectedUserId,
+ access_level: 10,
+ expires_at: undefined,
+ };
+
+ mock.onPost(expectedUrl).reply(200, {
+ id: expectedUserId,
+ state: 'active',
+ });
+
+ return Api.addProjectMembersByUserId(projectId, params).then(({ data }) => {
+ expect(data.id).toBe(expectedUserId);
+ expect(data.state).toBe('active');
+ });
+ });
+ });
+
+ describe('inviteProjectMembersByEmail', () => {
+ it('invites a new email address to create a new User and become a Project Member', () => {
+ const projectId = 1;
+ const expectedEmail = 'email@example.com';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/1/invitations`;
+ const params = {
+ email: expectedEmail,
+ access_level: 10,
+ expires_at: undefined,
+ };
+
+ mock.onPost(expectedUrl).reply(200, {
+ status: 'success',
+ });
+
+ return Api.inviteProjectMembersByEmail(projectId, params).then(({ data }) => {
+ expect(data.status).toBe('success');
+ });
+ });
+ });
+
describe('newLabel', () => {
- it('creates a new label', done => {
+ it('creates a new label', (done) => {
const namespace = 'some namespace';
const project = 'some project';
const labelData = { some: 'data' };
@@ -467,7 +555,7 @@ describe('Api', () => {
const expectedData = {
label: labelData,
};
- mock.onPost(expectedUrl).reply(config => {
+ mock.onPost(expectedUrl).reply((config) => {
expect(config.data).toBe(JSON.stringify(expectedData));
return [
@@ -478,20 +566,20 @@ describe('Api', () => {
];
});
- Api.newLabel(namespace, project, labelData, response => {
+ Api.newLabel(namespace, project, labelData, (response) => {
expect(response.name).toBe('test');
done();
});
});
- it('creates a group label', done => {
+ it('creates a group label', (done) => {
const namespace = 'group/subgroup';
const labelData = { some: 'data' };
const expectedUrl = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespace);
const expectedData = {
label: labelData,
};
- mock.onPost(expectedUrl).reply(config => {
+ mock.onPost(expectedUrl).reply((config) => {
expect(config.data).toBe(JSON.stringify(expectedData));
return [
@@ -502,7 +590,7 @@ describe('Api', () => {
];
});
- Api.newLabel(namespace, undefined, labelData, response => {
+ Api.newLabel(namespace, undefined, labelData, (response) => {
expect(response.name).toBe('test');
done();
});
@@ -510,7 +598,7 @@ describe('Api', () => {
});
describe('groupProjects', () => {
- it('fetches group projects', done => {
+ it('fetches group projects', (done) => {
const groupId = '123456';
const query = 'dummy query';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
@@ -520,7 +608,7 @@ describe('Api', () => {
},
]);
- Api.groupProjects(groupId, query, {}, response => {
+ Api.groupProjects(groupId, query, {}, (response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
@@ -561,7 +649,7 @@ describe('Api', () => {
templateKey,
)}`;
- it('fetches an issue template', done => {
+ it('fetches an issue template', (done) => {
mock.onGet(expectedUrl).reply(httpStatus.OK, 'test');
Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
@@ -587,7 +675,7 @@ describe('Api', () => {
const templateType = 'template type';
const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}`;
- it('fetches all templates by type', done => {
+ it('fetches all templates by type', (done) => {
const expectedData = [
{ key: 'Template1', name: 'Template 1', content: 'This is template 1!' },
];
@@ -615,12 +703,12 @@ describe('Api', () => {
});
describe('projectTemplates', () => {
- it('fetches a list of templates', done => {
+ it('fetches a list of templates', (done) => {
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses`;
mock.onGet(expectedUrl).reply(httpStatus.OK, 'test');
- Api.projectTemplates('gitlab-org/gitlab-ce', 'licenses', {}, response => {
+ Api.projectTemplates('gitlab-org/gitlab-ce', 'licenses', {}, (response) => {
expect(response).toBe('test');
done();
});
@@ -628,13 +716,13 @@ describe('Api', () => {
});
describe('projectTemplate', () => {
- it('fetches a single template', done => {
+ it('fetches a single template', (done) => {
const data = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses/test%20license`;
mock.onGet(expectedUrl).reply(httpStatus.OK, 'test');
- Api.projectTemplate('gitlab-org/gitlab-ce', 'licenses', 'test license', data, response => {
+ Api.projectTemplate('gitlab-org/gitlab-ce', 'licenses', 'test license', data, (response) => {
expect(response).toBe('test');
done();
});
@@ -642,7 +730,7 @@ describe('Api', () => {
});
describe('users', () => {
- it('fetches users', done => {
+ it('fetches users', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users.json`;
@@ -663,7 +751,7 @@ describe('Api', () => {
});
describe('user', () => {
- it('fetches single user', done => {
+ it('fetches single user', (done) => {
const userId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}`;
mock.onGet(expectedUrl).reply(httpStatus.OK, {
@@ -680,7 +768,7 @@ describe('Api', () => {
});
describe('user counts', () => {
- it('fetches single user counts', done => {
+ it('fetches single user counts', (done) => {
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/user_counts`;
mock.onGet(expectedUrl).reply(httpStatus.OK, {
merge_requests: 4,
@@ -696,7 +784,7 @@ describe('Api', () => {
});
describe('user status', () => {
- it('fetches single user status', done => {
+ it('fetches single user status', (done) => {
const userId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}/status`;
mock.onGet(expectedUrl).reply(httpStatus.OK, {
@@ -713,7 +801,7 @@ describe('Api', () => {
});
describe('user projects', () => {
- it('fetches all projects that belong to a particular user', done => {
+ it('fetches all projects that belong to a particular user', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const userId = '123456';
@@ -724,7 +812,7 @@ describe('Api', () => {
},
]);
- Api.userProjects(userId, query, options, response => {
+ Api.userProjects(userId, query, options, (response) => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
@@ -733,7 +821,7 @@ describe('Api', () => {
});
describe('commitPipelines', () => {
- it('fetches pipelines for a given commit', done => {
+ it('fetches pipelines for a given commit', (done) => {
const projectId = 'example/foobar';
const commitSha = 'abc123def';
const expectedUrl = `${dummyUrlRoot}/${projectId}/commit/${commitSha}/pipelines`;
@@ -756,7 +844,7 @@ describe('Api', () => {
describe('pipelineJobs', () => {
it.each([undefined, {}, { foo: true }])(
'fetches the jobs for a given pipeline given %p params',
- async params => {
+ async (params) => {
const projectId = 123;
const pipelineId = 456;
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/pipelines/${pipelineId}/jobs`;
@@ -774,7 +862,7 @@ describe('Api', () => {
});
describe('createBranch', () => {
- it('creates new branch', done => {
+ it('creates new branch', (done) => {
const ref = 'master';
const branch = 'new-branch-name';
const dummyProjectPath = 'gitlab-org/gitlab-ce';
@@ -799,7 +887,7 @@ describe('Api', () => {
});
describe('projectForks', () => {
- it('gets forked projects', done => {
+ it('gets forked projects', (done) => {
const dummyProjectPath = 'gitlab-org/gitlab-ce';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent(
dummyProjectPath,
@@ -822,7 +910,7 @@ describe('Api', () => {
});
describe('createContextCommits', () => {
- it('creates a new context commit', done => {
+ it('creates a new context commit', (done) => {
const projectPath = 'abc';
const mergeRequestId = '123456';
const commitsData = ['abcdefg'];
@@ -851,7 +939,7 @@ describe('Api', () => {
});
describe('allContextCommits', () => {
- it('gets all context commits', done => {
+ it('gets all context commits', (done) => {
const projectPath = 'abc';
const mergeRequestId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/context_commits`;
@@ -872,7 +960,7 @@ describe('Api', () => {
});
describe('removeContextCommits', () => {
- it('removes context commits', done => {
+ it('removes context commits', (done) => {
const projectPath = 'abc';
const mergeRequestId = '123456';
const commitsData = ['abcdefg'];
@@ -1120,7 +1208,7 @@ describe('Api', () => {
});
describe('updateIssue', () => {
- it('update an issue with the given payload', done => {
+ it('update an issue with the given payload', (done) => {
const projectId = 8;
const issue = 1;
const expectedArray = [1, 2, 3];
@@ -1137,7 +1225,7 @@ describe('Api', () => {
});
describe('updateMergeRequest', () => {
- it('update an issue with the given payload', done => {
+ it('update an issue with the given payload', (done) => {
const projectId = 8;
const mergeRequest = 1;
const expectedArray = [1, 2, 3];
@@ -1154,7 +1242,7 @@ describe('Api', () => {
});
describe('tags', () => {
- it('fetches all tags of a particular project', done => {
+ it('fetches all tags of a particular project', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const projectId = 8;
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
new file mode 100644
index 00000000000..9d05e6d99f6
--- /dev/null
+++ b/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Keep latest artifact checkbox sets correct setting value in checkbox with query result 1`] = `
+<div>
+ <!---->
+
+ <gl-form-checkbox-stub
+ checked="true"
+ >
+ <b
+ class="gl-mr-3"
+ >
+ Keep artifacts from most recent successful jobs
+ </b>
+
+ <gl-link-stub
+ href="/help/ci/pipelines/job_artifacts"
+ >
+ More information
+ </gl-link-stub>
+ </gl-form-checkbox-stub>
+
+ <p>
+
+ The latest artifacts created by jobs in the most recent successful pipeline will be stored.
+
+ </p>
+</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
new file mode 100644
index 00000000000..d7f07526b58
--- /dev/null
+++ b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
@@ -0,0 +1,88 @@
+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';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+const keepLatestArtifactMock = {
+ data: {
+ project: {
+ ciCdSettings: { keepLatestArtifact: true },
+ },
+ },
+};
+
+const keepLatestArtifactMockResponse = {
+ data: { ciCdSettingsUpdate: { errors: [], __typename: 'CiCdSettingsUpdatePayload' } },
+};
+
+describe('Keep latest artifact checkbox', () => {
+ let wrapper;
+ let apolloProvider;
+ let requestHandlers;
+
+ const fullPath = 'gitlab-org/gitlab';
+ const helpPagePath = '/help/ci/pipelines/job_artifacts';
+
+ const findCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findHelpLink = () => wrapper.find(GlLink);
+
+ const createComponent = (handlers) => {
+ requestHandlers = {
+ keepLatestArtifactQueryHandler: jest.fn().mockResolvedValue(keepLatestArtifactMock),
+ keepLatestArtifactMutationHandler: jest
+ .fn()
+ .mockResolvedValue(keepLatestArtifactMockResponse),
+ ...handlers,
+ };
+
+ apolloProvider = createMockApollo([
+ [GetKeepLatestArtifactProjectSetting, requestHandlers.keepLatestArtifactQueryHandler],
+ [UpdateKeepLatestArtifactProjectSetting, requestHandlers.keepLatestArtifactMutationHandler],
+ ]);
+
+ wrapper = shallowMount(KeepLatestArtifactCheckbox, {
+ provide: {
+ fullPath,
+ helpPagePath,
+ },
+ 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);
+ });
+
+ it('sets correct setting value in checkbox with query result', async () => {
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('calls mutation on artifact setting change with correct payload', () => {
+ findCheckbox().vm.$emit('change', false);
+
+ expect(requestHandlers.keepLatestArtifactMutationHandler).toHaveBeenCalledWith({
+ fullPath,
+ keepLatestArtifact: false,
+ });
+ });
+});
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 025e605b920..98c8ed4b95d 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
@@ -34,8 +34,8 @@ describe('RecoveryCodes', () => {
const findAlert = () => wrapper.find(GlAlert);
const findRecoveryCodes = () => wrapper.findByTestId('recovery-codes');
const findCopyButton = () => wrapper.find(ClipboardButton);
- const findButtonByText = text =>
- wrapper.findAll(GlButton).wrappers.find(buttonWrapper => buttonWrapper.text() === text);
+ const findButtonByText = (text) =>
+ wrapper.findAll(GlButton).wrappers.find((buttonWrapper) => buttonWrapper.text() === text);
const findDownloadButton = () => findButtonByText('Download codes');
const findPrintButton = () => findButtonByText('Print codes');
const findProceedButton = () => findButtonByText('Proceed');
@@ -59,7 +59,7 @@ describe('RecoveryCodes', () => {
it('renders codes', () => {
const recoveryCodes = findRecoveryCodes().text();
- codes.forEach(code => {
+ codes.forEach((code) => {
expect(recoveryCodes).toContain(code);
});
});
diff --git a/spec/frontend/authentication/u2f/authenticate_spec.js b/spec/frontend/authentication/u2f/authenticate_spec.js
index 7a87b420195..bf50ee88035 100644
--- a/spec/frontend/authentication/u2f/authenticate_spec.js
+++ b/spec/frontend/authentication/u2f/authenticate_spec.js
@@ -38,7 +38,7 @@ describe('U2FAuthenticate', () => {
window.u2f = oldu2f;
});
- it('falls back to normal 2fa', done => {
+ it('falls back to normal 2fa', (done) => {
component
.start()
.then(() => {
@@ -50,15 +50,12 @@ describe('U2FAuthenticate', () => {
});
describe('with u2f available', () => {
- beforeEach(done => {
+ beforeEach((done) => {
// bypass automatic form submission within renderAuthenticated
jest.spyOn(component, 'renderAuthenticated').mockReturnValue(true);
u2fDevice = new MockU2FDevice();
- component
- .start()
- .then(done)
- .catch(done.fail);
+ component.start().then(done).catch(done.fail);
});
it('allows authenticating via a U2F device', () => {
diff --git a/spec/frontend/authentication/u2f/register_spec.js b/spec/frontend/authentication/u2f/register_spec.js
index e89ef773be6..9cbadbc2fef 100644
--- a/spec/frontend/authentication/u2f/register_spec.js
+++ b/spec/frontend/authentication/u2f/register_spec.js
@@ -10,15 +10,12 @@ describe('U2FRegister', () => {
preloadFixtures('u2f/register.html');
- beforeEach(done => {
+ beforeEach((done) => {
loadFixtures('u2f/register.html');
u2fDevice = new MockU2FDevice();
container = $('#js-register-token-2fa');
component = new U2FRegister(container, {});
- component
- .start()
- .then(done)
- .catch(done.fail);
+ component.start().then(done).catch(done.fail);
});
it('allows registering a U2F device', () => {
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index c6a9c911ccf..e9482ffbd3d 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -57,15 +57,13 @@ describe('AwardsHandler', () => {
preloadFixtures('snippets/show.html');
const openAndWaitForEmojiMenu = (sel = '.js-add-award') => {
- $(sel)
- .eq(0)
- .click();
+ $(sel).eq(0).click();
jest.runOnlyPendingTimers();
const $menu = $('.emoji-menu');
- return new Promise(resolve => {
+ return new Promise((resolve) => {
$menu.one('build-emoji-menu-finish', () => {
resolve();
});
@@ -337,9 +335,7 @@ describe('AwardsHandler', () => {
it('should remove already selected emoji', async () => {
await openEmojiMenuAndAddEmoji();
- $('.js-add-award')
- .eq(0)
- .click();
+ $('.js-add-award').eq(0).click();
const $block = $('.js-awards-block');
const $emoji = $('.emoji-menu').find(
`.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`,
@@ -360,7 +356,7 @@ describe('AwardsHandler', () => {
await openAndWaitForEmojiMenu();
const emojiMenu = document.querySelector('.emoji-menu');
- Array.prototype.forEach.call(emojiMenu.querySelectorAll('.emoji-menu-title'), title => {
+ Array.prototype.forEach.call(emojiMenu.querySelectorAll('.emoji-menu-title'), (title) => {
expect(title.textContent.trim().toLowerCase()).not.toBe('frequently used');
});
});
@@ -373,7 +369,7 @@ describe('AwardsHandler', () => {
const emojiMenu = document.querySelector('.emoji-menu');
const hasFrequentlyUsedHeading = Array.prototype.some.call(
emojiMenu.querySelectorAll('.emoji-menu-title'),
- title => title.textContent.trim().toLowerCase() === 'frequently used',
+ (title) => title.textContent.trim().toLowerCase() === 'frequently used',
);
expect(hasFrequentlyUsedHeading).toBe(true);
diff --git a/spec/frontend/badges/components/badge_form_spec.js b/spec/frontend/badges/components/badge_form_spec.js
index 1edc9adbfb2..34c65d51115 100644
--- a/spec/frontend/badges/components/badge_form_spec.js
+++ b/spec/frontend/badges/components/badge_form_spec.js
@@ -50,7 +50,7 @@ describe('BadgeForm component', () => {
});
});
- const sharedSubmitTests = submitAction => {
+ const sharedSubmitTests = (submitAction) => {
const nameSelector = '#badge-name';
const imageUrlSelector = '#badge-image-url';
const findImageUrlElement = () => vm.$el.querySelector(imageUrlSelector);
@@ -65,7 +65,7 @@ describe('BadgeForm component', () => {
const submitButton = vm.$el.querySelector('button[type="submit"]');
submitButton.click();
};
- const expectInvalidInput = inputElementSelector => {
+ const expectInvalidInput = (inputElementSelector) => {
const inputElement = vm.$el.querySelector(inputElementSelector);
expect(inputElement.checkValidity()).toBe(false);
@@ -74,7 +74,7 @@ describe('BadgeForm component', () => {
expect(feedbackElement).toBeVisible();
};
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(vm, submitAction).mockReturnValue(Promise.resolve());
store.replaceState({
...store.state,
diff --git a/spec/frontend/badges/components/badge_list_row_spec.js b/spec/frontend/badges/components/badge_list_row_spec.js
index 31f0d850857..c559c979cb3 100644
--- a/spec/frontend/badges/components/badge_list_row_spec.js
+++ b/spec/frontend/badges/components/badge_list_row_spec.js
@@ -73,7 +73,7 @@ describe('BadgeListRow component', () => {
expect(vm.editBadge).toHaveBeenCalled();
});
- it('calls updateBadgeInModal and shows modal when clicking then delete button', done => {
+ it('calls updateBadgeInModal and shows modal when clicking then delete button', (done) => {
jest.spyOn(vm, 'updateBadgeInModal').mockImplementation(() => {});
const deleteButton = vm.$el.querySelector('.table-button-footer button:last-of-type');
@@ -88,12 +88,10 @@ describe('BadgeListRow component', () => {
});
describe('for a group badge', () => {
- beforeEach(done => {
+ beforeEach((done) => {
badge.kind = GROUP_BADGE;
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ Vue.nextTick().then(done).catch(done.fail);
});
it('renders the badge kind', () => {
diff --git a/spec/frontend/badges/components/badge_list_spec.js b/spec/frontend/badges/components/badge_list_spec.js
index 5ffc046eb97..da59e13e1e9 100644
--- a/spec/frontend/badges/components/badge_list_spec.js
+++ b/spec/frontend/badges/components/badge_list_spec.js
@@ -48,7 +48,7 @@ describe('BadgeList component', () => {
expect(rows).toHaveLength(numberOfDummyBadges);
});
- it('renders a message if no badges exist', done => {
+ it('renders a message if no badges exist', (done) => {
store.state.badges = [];
Vue.nextTick()
@@ -59,7 +59,7 @@ describe('BadgeList component', () => {
.catch(done.fail);
});
- it('shows a loading icon when loading', done => {
+ it('shows a loading icon when loading', (done) => {
store.state.isLoading = true;
Vue.nextTick()
@@ -73,15 +73,13 @@ describe('BadgeList component', () => {
});
describe('for group badges', () => {
- beforeEach(done => {
+ beforeEach((done) => {
store.state.kind = GROUP_BADGE;
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ Vue.nextTick().then(done).catch(done.fail);
});
- it('renders a message if no badges exist', done => {
+ it('renders a message if no badges exist', (done) => {
store.state.badges = [];
Vue.nextTick()
diff --git a/spec/frontend/badges/components/badge_spec.js b/spec/frontend/badges/components/badge_spec.js
index 43004004fb2..990bc094d59 100644
--- a/spec/frontend/badges/components/badge_spec.js
+++ b/spec/frontend/badges/components/badge_spec.js
@@ -23,7 +23,7 @@ describe('Badge component', () => {
const createComponent = (props, el = null) => {
vm = mountComponent(Component, props, el);
const { badgeImage } = findElements();
- return new Promise(resolve => {
+ return new Promise((resolve) => {
badgeImage.addEventListener('load', resolve);
// Manually dispatch load event as it is not triggered
badgeImage.dispatchEvent(new Event('load'));
@@ -36,7 +36,7 @@ describe('Badge component', () => {
describe('watchers', () => {
describe('imageUrl', () => {
- it('sets isLoading and resets numRetries and hasError', done => {
+ it('sets isLoading and resets numRetries and hasError', (done) => {
const props = { ...dummyProps };
createComponent(props)
.then(() => {
@@ -60,7 +60,7 @@ describe('Badge component', () => {
});
describe('methods', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent({ ...dummyProps })
.then(done)
.catch(done.fail);
@@ -98,7 +98,7 @@ describe('Badge component', () => {
});
describe('behavior', () => {
- beforeEach(done => {
+ beforeEach((done) => {
setFixtures('<div id="dummy-element"></div>');
createComponent({ ...dummyProps }, '#dummy-element')
.then(done)
@@ -116,7 +116,7 @@ describe('Badge component', () => {
expect(vm.$el.querySelector('.btn-group')).toBeHidden();
});
- it('shows a loading icon when loading', done => {
+ it('shows a loading icon when loading', (done) => {
vm.isLoading = true;
Vue.nextTick()
@@ -132,7 +132,7 @@ describe('Badge component', () => {
.catch(done.fail);
});
- it('shows an error and reload button if loading failed', done => {
+ it('shows an error and reload button if loading failed', (done) => {
vm.hasError = true;
Vue.nextTick()
diff --git a/spec/frontend/badges/store/actions_spec.js b/spec/frontend/badges/store/actions_spec.js
index 921c21cb55e..52ae29affac 100644
--- a/spec/frontend/badges/store/actions_spec.js
+++ b/spec/frontend/badges/store/actions_spec.js
@@ -9,7 +9,10 @@ import { createDummyBadge, createDummyBadgeResponse } from '../dummy_badge';
describe('Badges store actions', () => {
const dummyEndpointUrl = `${TEST_HOST}/badges/endpoint`;
- const dummyBadges = [{ ...createDummyBadge(), id: 5 }, { ...createDummyBadge(), id: 6 }];
+ const dummyBadges = [
+ { ...createDummyBadge(), id: 5 },
+ { ...createDummyBadge(), id: 6 },
+ ];
let axiosMock;
let badgeId;
@@ -30,7 +33,7 @@ describe('Badges store actions', () => {
});
describe('requestNewBadge', () => {
- it('commits REQUEST_NEW_BADGE', done => {
+ it('commits REQUEST_NEW_BADGE', (done) => {
testAction(
actions.requestNewBadge,
null,
@@ -43,7 +46,7 @@ describe('Badges store actions', () => {
});
describe('receiveNewBadge', () => {
- it('commits RECEIVE_NEW_BADGE', done => {
+ it('commits RECEIVE_NEW_BADGE', (done) => {
const newBadge = createDummyBadge();
testAction(
actions.receiveNewBadge,
@@ -57,7 +60,7 @@ describe('Badges store actions', () => {
});
describe('receiveNewBadgeError', () => {
- it('commits RECEIVE_NEW_BADGE_ERROR', done => {
+ it('commits RECEIVE_NEW_BADGE_ERROR', (done) => {
testAction(
actions.receiveNewBadgeError,
null,
@@ -84,10 +87,10 @@ describe('Badges store actions', () => {
};
});
- it('dispatches requestNewBadge and receiveNewBadge for successful response', done => {
+ it('dispatches requestNewBadge and receiveNewBadge for successful response', (done) => {
const dummyResponse = createDummyBadgeResponse();
- endpointMock.replyOnce(req => {
+ endpointMock.replyOnce((req) => {
expect(req.data).toBe(
JSON.stringify({
name: 'TestBadge',
@@ -111,8 +114,8 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('dispatches requestNewBadge and receiveNewBadgeError for error response', done => {
- endpointMock.replyOnce(req => {
+ it('dispatches requestNewBadge and receiveNewBadgeError for error response', (done) => {
+ endpointMock.replyOnce((req) => {
expect(req.data).toBe(
JSON.stringify({
name: 'TestBadge',
@@ -138,7 +141,7 @@ describe('Badges store actions', () => {
});
describe('requestDeleteBadge', () => {
- it('commits REQUEST_DELETE_BADGE', done => {
+ it('commits REQUEST_DELETE_BADGE', (done) => {
testAction(
actions.requestDeleteBadge,
badgeId,
@@ -151,7 +154,7 @@ describe('Badges store actions', () => {
});
describe('receiveDeleteBadge', () => {
- it('commits RECEIVE_DELETE_BADGE', done => {
+ it('commits RECEIVE_DELETE_BADGE', (done) => {
testAction(
actions.receiveDeleteBadge,
badgeId,
@@ -164,7 +167,7 @@ describe('Badges store actions', () => {
});
describe('receiveDeleteBadgeError', () => {
- it('commits RECEIVE_DELETE_BADGE_ERROR', done => {
+ it('commits RECEIVE_DELETE_BADGE_ERROR', (done) => {
testAction(
actions.receiveDeleteBadgeError,
badgeId,
@@ -185,7 +188,7 @@ describe('Badges store actions', () => {
dispatch = jest.fn();
});
- it('dispatches requestDeleteBadge and receiveDeleteBadge for successful response', done => {
+ it('dispatches requestDeleteBadge and receiveDeleteBadge for successful response', (done) => {
endpointMock.replyOnce(() => {
expect(dispatch.mock.calls).toEqual([['requestDeleteBadge', badgeId]]);
dispatch.mockClear();
@@ -201,7 +204,7 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('dispatches requestDeleteBadge and receiveDeleteBadgeError for error response', done => {
+ it('dispatches requestDeleteBadge and receiveDeleteBadgeError for error response', (done) => {
endpointMock.replyOnce(() => {
expect(dispatch.mock.calls).toEqual([['requestDeleteBadge', badgeId]]);
dispatch.mockClear();
@@ -220,7 +223,7 @@ describe('Badges store actions', () => {
});
describe('editBadge', () => {
- it('commits START_EDITING', done => {
+ it('commits START_EDITING', (done) => {
const dummyBadge = createDummyBadge();
testAction(
actions.editBadge,
@@ -234,7 +237,7 @@ describe('Badges store actions', () => {
});
describe('requestLoadBadges', () => {
- it('commits REQUEST_LOAD_BADGES', done => {
+ it('commits REQUEST_LOAD_BADGES', (done) => {
const dummyData = 'this is not real data';
testAction(
actions.requestLoadBadges,
@@ -248,7 +251,7 @@ describe('Badges store actions', () => {
});
describe('receiveLoadBadges', () => {
- it('commits RECEIVE_LOAD_BADGES', done => {
+ it('commits RECEIVE_LOAD_BADGES', (done) => {
const badges = dummyBadges;
testAction(
actions.receiveLoadBadges,
@@ -262,7 +265,7 @@ describe('Badges store actions', () => {
});
describe('receiveLoadBadgesError', () => {
- it('commits RECEIVE_LOAD_BADGES_ERROR', done => {
+ it('commits RECEIVE_LOAD_BADGES_ERROR', (done) => {
testAction(
actions.receiveLoadBadgesError,
null,
@@ -283,7 +286,7 @@ describe('Badges store actions', () => {
dispatch = jest.fn();
});
- it('dispatches requestLoadBadges and receiveLoadBadges for successful response', done => {
+ it('dispatches requestLoadBadges and receiveLoadBadges for successful response', (done) => {
const dummyData = 'this is just some data';
const dummyReponse = [
createDummyBadgeResponse(),
@@ -307,7 +310,7 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('dispatches requestLoadBadges and receiveLoadBadgesError for error response', done => {
+ it('dispatches requestLoadBadges and receiveLoadBadgesError for error response', (done) => {
const dummyData = 'this is just some data';
endpointMock.replyOnce(() => {
expect(dispatch.mock.calls).toEqual([['requestLoadBadges', dummyData]]);
@@ -327,7 +330,7 @@ describe('Badges store actions', () => {
});
describe('requestRenderedBadge', () => {
- it('commits REQUEST_RENDERED_BADGE', done => {
+ it('commits REQUEST_RENDERED_BADGE', (done) => {
testAction(
actions.requestRenderedBadge,
null,
@@ -340,7 +343,7 @@ describe('Badges store actions', () => {
});
describe('receiveRenderedBadge', () => {
- it('commits RECEIVE_RENDERED_BADGE', done => {
+ it('commits RECEIVE_RENDERED_BADGE', (done) => {
const dummyBadge = createDummyBadge();
testAction(
actions.receiveRenderedBadge,
@@ -354,7 +357,7 @@ describe('Badges store actions', () => {
});
describe('receiveRenderedBadgeError', () => {
- it('commits RECEIVE_RENDERED_BADGE_ERROR', done => {
+ it('commits RECEIVE_RENDERED_BADGE_ERROR', (done) => {
testAction(
actions.receiveRenderedBadgeError,
null,
@@ -385,7 +388,7 @@ describe('Badges store actions', () => {
dispatch = jest.fn();
});
- it('returns immediately if imageUrl is empty', done => {
+ it('returns immediately if imageUrl is empty', (done) => {
jest.spyOn(axios, 'get').mockImplementation(() => {});
badgeInForm.imageUrl = '';
@@ -398,7 +401,7 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('returns immediately if linkUrl is empty', done => {
+ it('returns immediately if linkUrl is empty', (done) => {
jest.spyOn(axios, 'get').mockImplementation(() => {});
badgeInForm.linkUrl = '';
@@ -411,7 +414,7 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('escapes user input', done => {
+ it('escapes user input', (done) => {
jest
.spyOn(axios, 'get')
.mockImplementation(() => Promise.resolve({ data: createDummyBadgeResponse() }));
@@ -434,7 +437,7 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('dispatches requestRenderedBadge and receiveRenderedBadge for successful response', done => {
+ it('dispatches requestRenderedBadge and receiveRenderedBadge for successful response', (done) => {
const dummyReponse = createDummyBadgeResponse();
endpointMock.replyOnce(() => {
expect(dispatch.mock.calls).toEqual([['requestRenderedBadge']]);
@@ -453,7 +456,7 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('dispatches requestRenderedBadge and receiveRenderedBadgeError for error response', done => {
+ it('dispatches requestRenderedBadge and receiveRenderedBadgeError for error response', (done) => {
endpointMock.replyOnce(() => {
expect(dispatch.mock.calls).toEqual([['requestRenderedBadge']]);
dispatch.mockClear();
@@ -472,7 +475,7 @@ describe('Badges store actions', () => {
});
describe('requestUpdatedBadge', () => {
- it('commits REQUEST_UPDATED_BADGE', done => {
+ it('commits REQUEST_UPDATED_BADGE', (done) => {
testAction(
actions.requestUpdatedBadge,
null,
@@ -485,7 +488,7 @@ describe('Badges store actions', () => {
});
describe('receiveUpdatedBadge', () => {
- it('commits RECEIVE_UPDATED_BADGE', done => {
+ it('commits RECEIVE_UPDATED_BADGE', (done) => {
const updatedBadge = createDummyBadge();
testAction(
actions.receiveUpdatedBadge,
@@ -499,7 +502,7 @@ describe('Badges store actions', () => {
});
describe('receiveUpdatedBadgeError', () => {
- it('commits RECEIVE_UPDATED_BADGE_ERROR', done => {
+ it('commits RECEIVE_UPDATED_BADGE_ERROR', (done) => {
testAction(
actions.receiveUpdatedBadgeError,
null,
@@ -526,10 +529,10 @@ describe('Badges store actions', () => {
dispatch = jest.fn();
});
- it('dispatches requestUpdatedBadge and receiveUpdatedBadge for successful response', done => {
+ it('dispatches requestUpdatedBadge and receiveUpdatedBadge for successful response', (done) => {
const dummyResponse = createDummyBadgeResponse();
- endpointMock.replyOnce(req => {
+ endpointMock.replyOnce((req) => {
expect(req.data).toBe(
JSON.stringify({
name: 'TestBadge',
@@ -553,8 +556,8 @@ describe('Badges store actions', () => {
.catch(done.fail);
});
- it('dispatches requestUpdatedBadge and receiveUpdatedBadgeError for error response', done => {
- endpointMock.replyOnce(req => {
+ it('dispatches requestUpdatedBadge and receiveUpdatedBadgeError for error response', (done) => {
+ endpointMock.replyOnce((req) => {
expect(req.data).toBe(
JSON.stringify({
name: 'TestBadge',
@@ -580,7 +583,7 @@ describe('Badges store actions', () => {
});
describe('stopEditing', () => {
- it('commits STOP_EDITING', done => {
+ it('commits STOP_EDITING', (done) => {
testAction(
actions.stopEditing,
null,
@@ -593,7 +596,7 @@ describe('Badges store actions', () => {
});
describe('updateBadgeInForm', () => {
- it('commits UPDATE_BADGE_IN_FORM', done => {
+ it('commits UPDATE_BADGE_IN_FORM', (done) => {
const dummyBadge = createDummyBadge();
testAction(
actions.updateBadgeInForm,
@@ -606,7 +609,7 @@ describe('Badges store actions', () => {
});
describe('updateBadgeInModal', () => {
- it('commits UPDATE_BADGE_IN_MODAL', done => {
+ it('commits UPDATE_BADGE_IN_MODAL', (done) => {
const dummyBadge = createDummyBadge();
testAction(
actions.updateBadgeInModal,
diff --git a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
index 6e0b61db9fa..dcb68b1804f 100644
--- a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
+++ b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
@@ -44,18 +44,8 @@ describe('Batch comments diff file drafts component', () => {
expect(vm.findAll('.js-diff-notes-index').length).toEqual(2);
- expect(
- vm
- .findAll('.js-diff-notes-index')
- .at(0)
- .text(),
- ).toEqual('1');
-
- expect(
- vm
- .findAll('.js-diff-notes-index')
- .at(1)
- .text(),
- ).toEqual('2');
+ expect(vm.findAll('.js-diff-notes-index').at(0).text()).toEqual('1');
+
+ expect(vm.findAll('.js-diff-notes-index').at(1).text()).toEqual('2');
});
});
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
index 99980c98f8b..ae7134b63c8 100644
--- a/spec/frontend/batch_comments/components/draft_note_spec.js
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -65,7 +65,7 @@ describe('Batch comments draft note component', () => {
);
});
- it('sets as loading when draft is publishing', done => {
+ it('sets as loading when draft is publishing', (done) => {
createComponent();
wrapper.vm.$store.state.batchComments.currentlyPublishingDrafts.push(1);
@@ -80,7 +80,7 @@ describe('Batch comments draft note component', () => {
});
describe('update', () => {
- it('dispatches updateDraft', done => {
+ it('dispatches updateDraft', (done) => {
createComponent();
const note = wrapper.find(NoteableNote);
@@ -121,7 +121,7 @@ describe('Batch comments draft note component', () => {
});
describe('quick actions', () => {
- it('renders referenced commands', done => {
+ it('renders referenced commands', (done) => {
createComponent();
wrapper.setProps({
draft: {
diff --git a/spec/frontend/batch_comments/components/drafts_count_spec.js b/spec/frontend/batch_comments/components/drafts_count_spec.js
index 83d2f9eb639..5f74de9c014 100644
--- a/spec/frontend/batch_comments/components/drafts_count_spec.js
+++ b/spec/frontend/batch_comments/components/drafts_count_spec.js
@@ -27,7 +27,7 @@ describe('Batch comments drafts count component', () => {
expect(vm.$el.textContent).toContain('1');
});
- it('renders screen reader text', done => {
+ it('renders screen reader text', (done) => {
const el = vm.$el.querySelector('.sr-only');
expect(el.textContent).toContain('draft');
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 8ddad3dacfe..173b2710a30 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -85,7 +85,7 @@ describe('Batch comments draft preview item component', () => {
describe('for thread', () => {
beforeEach(() => {
- createComponent(false, { discussion_id: '1', resolve_discussion: true }, store => {
+ createComponent(false, { discussion_id: '1', resolve_discussion: true }, (store) => {
store.state.notes.discussions.push({
id: '1',
notes: [
diff --git a/spec/frontend/batch_comments/components/publish_button_spec.js b/spec/frontend/batch_comments/components/publish_button_spec.js
index 4032713150c..eca424814b4 100644
--- a/spec/frontend/batch_comments/components/publish_button_spec.js
+++ b/spec/frontend/batch_comments/components/publish_button_spec.js
@@ -29,7 +29,7 @@ describe('Batch comments publish button component', () => {
expect(vm.$store.dispatch).toHaveBeenCalledWith('batchComments/publishReview', undefined);
});
- it('sets loading when isPublishing is true', done => {
+ it('sets loading when isPublishing is true', (done) => {
vm.$store.state.batchComments.isPublishing = true;
vm.$nextTick(() => {
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 e66f36aa3a2..3ad131de24e 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 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import * as actions from '~/batch_comments/stores/modules/batch_comments/actions';
import axios from '~/lib/utils/axios_utils';
@@ -28,7 +28,7 @@ describe('Batch comments store actions', () => {
});
describe('addDraftToDiscussion', () => {
- it('commits ADD_NEW_DRAFT if no errors returned', done => {
+ it('commits ADD_NEW_DRAFT if no errors returned', (done) => {
res = { id: 1 };
mock.onAny().reply(200, res);
@@ -42,7 +42,7 @@ describe('Batch comments store actions', () => {
);
});
- it('does not commit ADD_NEW_DRAFT if errors returned', done => {
+ it('does not commit ADD_NEW_DRAFT if errors returned', (done) => {
mock.onAny().reply(500);
testAction(
@@ -57,7 +57,7 @@ describe('Batch comments store actions', () => {
});
describe('createNewDraft', () => {
- it('commits ADD_NEW_DRAFT if no errors returned', done => {
+ it('commits ADD_NEW_DRAFT if no errors returned', (done) => {
res = { id: 1 };
mock.onAny().reply(200, res);
@@ -71,7 +71,7 @@ describe('Batch comments store actions', () => {
);
});
- it('does not commit ADD_NEW_DRAFT if errors returned', done => {
+ it('does not commit ADD_NEW_DRAFT if errors returned', (done) => {
mock.onAny().reply(500);
testAction(actions.createNewDraft, { endpoint: TEST_HOST, data: 'test' }, null, [], [], done);
@@ -89,7 +89,7 @@ describe('Batch comments store actions', () => {
};
});
- it('commits DELETE_DRAFT if no errors returned', done => {
+ it('commits DELETE_DRAFT if no errors returned', (done) => {
const commit = jest.fn();
const context = {
getters,
@@ -107,7 +107,7 @@ describe('Batch comments store actions', () => {
.catch(done.fail);
});
- it('does not commit DELETE_DRAFT if errors returned', done => {
+ it('does not commit DELETE_DRAFT if errors returned', (done) => {
const commit = jest.fn();
const context = {
getters,
@@ -136,7 +136,7 @@ describe('Batch comments store actions', () => {
};
});
- it('commits SET_BATCH_COMMENTS_DRAFTS with returned data', done => {
+ it('commits SET_BATCH_COMMENTS_DRAFTS with returned data', (done) => {
const commit = jest.fn();
const context = {
getters,
@@ -170,7 +170,7 @@ describe('Batch comments store actions', () => {
rootGetters = { discussionsStructuredByLineCode: 'discussions' };
});
- it('dispatches actions & commits', done => {
+ it('dispatches actions & commits', (done) => {
mock.onAny().reply(200);
actions
@@ -185,7 +185,7 @@ describe('Batch comments store actions', () => {
.catch(done.fail);
});
- it('dispatches error commits', done => {
+ it('dispatches error commits', (done) => {
mock.onAny().reply(500);
actions
@@ -210,7 +210,7 @@ describe('Batch comments store actions', () => {
};
});
- it('commits RECEIVE_DRAFT_UPDATE_SUCCESS with returned data', done => {
+ it('commits RECEIVE_DRAFT_UPDATE_SUCCESS with returned data', (done) => {
const commit = jest.fn();
const context = {
getters,
@@ -228,7 +228,7 @@ describe('Batch comments store actions', () => {
.catch(done.fail);
});
- it('calls passed callback', done => {
+ it('calls passed callback', (done) => {
const commit = jest.fn();
const context = {
getters,
@@ -249,7 +249,7 @@ describe('Batch comments store actions', () => {
});
describe('expandAllDiscussions', () => {
- it('dispatches expandDiscussion for all drafts', done => {
+ it('dispatches expandDiscussion for all drafts', (done) => {
const state = {
drafts: [
{
diff --git a/spec/frontend/behaviors/autosize_spec.js b/spec/frontend/behaviors/autosize_spec.js
index 3444c7b4075..352bd8a0ed0 100644
--- a/spec/frontend/behaviors/autosize_spec.js
+++ b/spec/frontend/behaviors/autosize_spec.js
@@ -6,7 +6,7 @@ function load() {
jest.mock('~/helpers/startup_css_helper', () => {
return {
- waitForCSSLoaded: jest.fn().mockImplementation(cb => cb.apply()),
+ waitForCSSLoaded: jest.fn().mockImplementation((cb) => cb.apply()),
};
});
diff --git a/spec/frontend/behaviors/bind_in_out_spec.js b/spec/frontend/behaviors/bind_in_out_spec.js
index 92a68ddd387..49425a9377e 100644
--- a/spec/frontend/behaviors/bind_in_out_spec.js
+++ b/spec/frontend/behaviors/bind_in_out_spec.js
@@ -1,5 +1,5 @@
+import ClassSpecHelper from 'helpers/class_spec_helper';
import BindInOut from '~/behaviors/bind_in_out';
-import ClassSpecHelper from '../helpers/class_spec_helper';
describe('BindInOut', () => {
let testContext;
diff --git a/spec/frontend/behaviors/copy_as_gfm_spec.js b/spec/frontend/behaviors/copy_as_gfm_spec.js
index 46d4451c941..16ea4ba8624 100644
--- a/spec/frontend/behaviors/copy_as_gfm_spec.js
+++ b/spec/frontend/behaviors/copy_as_gfm_spec.js
@@ -57,7 +57,7 @@ describe('CopyAsGFM', () => {
const fragment = document.createDocumentFragment();
const node = document.createElement('div');
node.innerHTML = html;
- Array.from(node.childNodes).forEach(item => fragment.appendChild(item));
+ Array.from(node.childNodes).forEach((item) => fragment.appendChild(item));
return fragment;
},
}),
@@ -80,7 +80,7 @@ describe('CopyAsGFM', () => {
return clipboardData;
};
- beforeAll(done => {
+ beforeAll((done) => {
initCopyAsGFM();
// Fake call to nodeToGfm so the import of lazy bundle happened
@@ -94,7 +94,7 @@ describe('CopyAsGFM', () => {
beforeEach(() => jest.spyOn(clipboardData, 'setData'));
describe('list handling', () => {
- it('uses correct gfm for unordered lists', done => {
+ it('uses correct gfm for unordered lists', (done) => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'UL');
window.getSelection = jest.fn(() => selection);
@@ -108,7 +108,7 @@ describe('CopyAsGFM', () => {
});
});
- it('uses correct gfm for ordered lists', done => {
+ it('uses correct gfm for ordered lists', (done) => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'OL');
window.getSelection = jest.fn(() => selection);
@@ -127,7 +127,7 @@ describe('CopyAsGFM', () => {
describe('CopyAsGFM.quoted', () => {
const sampleGFM = '* List 1\n* List 2\n\n`Some code`';
- it('adds quote char `> ` to each line', done => {
+ it('adds quote char `> ` to each line', (done) => {
const expectedQuotedGFM = '> * List 1\n> * List 2\n> \n> `Some code`';
expect(CopyAsGFM.quoted(sampleGFM)).toEqual(expectedQuotedGFM);
done();
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index 46b4e5d3d5c..6e476d84501 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import waitForPromises from 'jest/helpers/wait_for_promises';
+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';
diff --git a/spec/frontend/behaviors/load_startup_css_spec.js b/spec/frontend/behaviors/load_startup_css_spec.js
index 81222ac5aaa..59f49585645 100644
--- a/spec/frontend/behaviors/load_startup_css_spec.js
+++ b/spec/frontend/behaviors/load_startup_css_spec.js
@@ -7,7 +7,7 @@ describe('behaviors/load_startup_css', () => {
const setupListeners = () => {
document
.querySelectorAll('link')
- .forEach(x => x.addEventListener('load', () => loadListener(x)));
+ .forEach((x) => x.addEventListener('load', () => loadListener(x)));
};
beforeEach(() => {
diff --git a/spec/frontend/behaviors/markdown/paste_markdown_table_spec.js b/spec/frontend/behaviors/markdown/paste_markdown_table_spec.js
index eab805382bd..7044618fd9e 100644
--- a/spec/frontend/behaviors/markdown/paste_markdown_table_spec.js
+++ b/spec/frontend/behaviors/markdown/paste_markdown_table_spec.js
@@ -8,7 +8,7 @@ describe('PasteMarkdownTable', () => {
Object.defineProperty(event, 'dataTransfer', {
value: {
- getData: jest.fn().mockImplementation(type => {
+ getData: jest.fn().mockImplementation((type) => {
if (type === 'text/html') {
return '<table><tr><td>First</td><td>Second</td></tr></table>';
}
@@ -48,7 +48,7 @@ describe('PasteMarkdownTable', () => {
it('returns false when the number of rows are not consistent', () => {
data.types = ['text/html', 'text/plain'];
- data.getData = jest.fn().mockImplementation(mimeType => {
+ data.getData = jest.fn().mockImplementation((mimeType) => {
if (mimeType === 'text/html') {
return '<table><tr><td>def test<td></tr></table>';
}
@@ -60,7 +60,7 @@ describe('PasteMarkdownTable', () => {
it('returns false when the table copy comes from a diff', () => {
data.types = ['text/html', 'text/plain'];
- data.getData = jest.fn().mockImplementation(mimeType => {
+ data.getData = jest.fn().mockImplementation((mimeType) => {
if (mimeType === 'text/html') {
return '<table class="diff-wrap-lines"><tr><td>First</td><td>Second</td></tr></table>';
}
@@ -74,7 +74,7 @@ describe('PasteMarkdownTable', () => {
describe('convertToTableMarkdown', () => {
it('returns a Markdown table', () => {
data.types = ['text/html', 'text/plain'];
- data.getData = jest.fn().mockImplementation(type => {
+ data.getData = jest.fn().mockImplementation((type) => {
if (type === 'text/html') {
return '<table><tr><td>First</td><td>Last</td><tr><td>John</td><td>Doe</td><tr><td>Jane</td><td>Doe</td></table>';
} else if (type === 'text/plain') {
@@ -99,7 +99,7 @@ describe('PasteMarkdownTable', () => {
it('returns a Markdown table with rows normalized', () => {
data.types = ['text/html', 'text/plain'];
- data.getData = jest.fn().mockImplementation(type => {
+ data.getData = jest.fn().mockImplementation((type) => {
if (type === 'text/html') {
return '<table><tr><td>First</td><td>Last</td><tr><td>John</td><td>Doe</td><tr><td>Jane</td><td>/td></table>';
} else if (type === 'text/plain') {
diff --git a/spec/frontend/behaviors/quick_submit_spec.js b/spec/frontend/behaviors/quick_submit_spec.js
index 2dc2bb198e8..d3d65892aff 100644
--- a/spec/frontend/behaviors/quick_submit_spec.js
+++ b/spec/frontend/behaviors/quick_submit_spec.js
@@ -17,7 +17,7 @@ describe('Quick Submit behavior', () => {
submit: jest.fn(),
};
- $('form').submit(e => {
+ $('form').submit((e) => {
// Prevent a form submit from moving us off the testing page
e.preventDefault();
// Explicitly call the spie to know this function get's not called
diff --git a/spec/frontend/behaviors/requires_input_spec.js b/spec/frontend/behaviors/requires_input_spec.js
index 617fe49b059..0f27f89d6dc 100644
--- a/spec/frontend/behaviors/requires_input_spec.js
+++ b/spec/frontend/behaviors/requires_input_spec.js
@@ -32,30 +32,18 @@ describe('requiresInput', () => {
it('enables submit when all required fields receive input', () => {
$('.js-requires-input').requiresInput();
- $('#required1')
- .val('input1')
- .change();
+ $('#required1').val('input1').change();
expect(submitButton).toBeDisabled();
- $('#optional1')
- .val('input1')
- .change();
+ $('#optional1').val('input1').change();
expect(submitButton).toBeDisabled();
- $('#required2')
- .val('input2')
- .change();
- $('#required3')
- .val('input3')
- .change();
- $('#required4')
- .val('input4')
- .change();
- $('#required5')
- .val('1')
- .change();
+ $('#required2').val('input2').change();
+ $('#required3').val('input3').change();
+ $('#required4').val('input4').change();
+ $('#required5').val('1').change();
expect($('.submit')).not.toBeDisabled();
});
diff --git a/spec/frontend/behaviors/secret_values_spec.js b/spec/frontend/behaviors/secret_values_spec.js
index 5aaab093c0c..06155017dd1 100644
--- a/spec/frontend/behaviors/secret_values_spec.js
+++ b/spec/frontend/behaviors/secret_values_spec.js
@@ -18,7 +18,7 @@ function generateValueMarkup(
function generateFixtureMarkup(secrets, isRevealed, valueClass, placeholderClass) {
return `
<div class="js-secret-container">
- ${secrets.map(secret => generateValueMarkup(secret, valueClass, placeholderClass)).join('')}
+ ${secrets.map((secret) => generateValueMarkup(secret, valueClass, placeholderClass)).join('')}
<button
class="js-secret-value-reveal-button"
data-secret-reveal-status="${isRevealed}"
@@ -122,12 +122,12 @@ describe('setupSecretValues', () => {
const placeholders = wrapper.querySelectorAll('.js-secret-value-placeholder');
expect(values.length).toEqual(3);
- values.forEach(value => {
+ values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(3);
- placeholders.forEach(placeholder => {
+ placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
@@ -141,24 +141,24 @@ describe('setupSecretValues', () => {
revealButton.click();
expect(values.length).toEqual(3);
- values.forEach(value => {
+ values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(false);
});
expect(placeholders.length).toEqual(3);
- placeholders.forEach(placeholder => {
+ placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(true);
});
revealButton.click();
expect(values.length).toEqual(3);
- values.forEach(value => {
+ values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(3);
- placeholders.forEach(placeholder => {
+ placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
@@ -181,24 +181,24 @@ describe('setupSecretValues', () => {
revealButton.click();
expect(values.length).toEqual(4);
- values.forEach(value => {
+ values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(false);
});
expect(placeholders.length).toEqual(4);
- placeholders.forEach(placeholder => {
+ placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(true);
});
revealButton.click();
expect(values.length).toEqual(4);
- values.forEach(value => {
+ values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(4);
- placeholders.forEach(placeholder => {
+ placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
diff --git a/spec/frontend/behaviors/shortcuts/keybindings_spec.js b/spec/frontend/behaviors/shortcuts/keybindings_spec.js
index 23fea79f828..d05b3fbdce2 100644
--- a/spec/frontend/behaviors/shortcuts/keybindings_spec.js
+++ b/spec/frontend/behaviors/shortcuts/keybindings_spec.js
@@ -9,7 +9,7 @@ describe('~/behaviors/shortcuts/keybindings.js', () => {
useLocalStorageSpy();
});
- const setupCustomizations = async customizationsAsString => {
+ const setupCustomizations = async (customizationsAsString) => {
localStorage.clear();
if (customizationsAsString) {
diff --git a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
index 77dcc28dd48..94ba1615c89 100644
--- a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -15,7 +15,7 @@ describe('ShortcutsIssuable', () => {
preloadFixtures(snippetShowFixtureName, mrShowFixtureName);
- beforeAll(done => {
+ beforeAll((done) => {
initCopyAsGFM();
// Fake call to nodeToGfm so the import of lazy bundle happened
@@ -81,7 +81,7 @@ describe('ShortcutsIssuable', () => {
stubSelection('<p>Selected text.</p>');
});
- it('leaves existing input intact', done => {
+ it('leaves existing input intact', (done) => {
$(FORM_SELECTOR).val('This text was already here.');
expect($(FORM_SELECTOR).val()).toBe('This text was already here.');
@@ -96,7 +96,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `input`', done => {
+ it('triggers `input`', (done) => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -110,7 +110,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `focus`', done => {
+ it('triggers `focus`', (done) => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -122,7 +122,7 @@ describe('ShortcutsIssuable', () => {
});
describe('with a one-line selection', () => {
- it('quotes the selection', done => {
+ it('quotes the selection', (done) => {
stubSelection('<p>This text has been selected.</p>');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -134,7 +134,7 @@ describe('ShortcutsIssuable', () => {
});
describe('with a multi-line selection', () => {
- it('quotes the selected lines as a group', done => {
+ it('quotes the selected lines as a group', (done) => {
stubSelection(
'<p>Selected line one.</p>\n<p>Selected line two.</p>\n<p>Selected line three.</p>',
);
@@ -154,7 +154,7 @@ describe('ShortcutsIssuable', () => {
stubSelection('<p>Selected text.</p>', true);
});
- it('does not add anything to the input', done => {
+ it('does not add anything to the input', (done) => {
ShortcutsIssuable.replyWithSelectedText(true);
setImmediate(() => {
@@ -163,7 +163,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `focus`', done => {
+ it('triggers `focus`', (done) => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -179,7 +179,7 @@ describe('ShortcutsIssuable', () => {
stubSelection('<div class="md">Selected text.</div><p>Invalid selected text.</p>', true);
});
- it('only adds the valid part to the input', done => {
+ it('only adds the valid part to the input', (done) => {
ShortcutsIssuable.replyWithSelectedText(true);
setImmediate(() => {
@@ -188,7 +188,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `focus`', done => {
+ it('triggers `focus`', (done) => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -198,7 +198,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `input`', done => {
+ it('triggers `input`', (done) => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -233,7 +233,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('adds the quoted selection to the input', done => {
+ it('adds the quoted selection to the input', (done) => {
ShortcutsIssuable.replyWithSelectedText(true);
setImmediate(() => {
@@ -242,7 +242,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `focus`', done => {
+ it('triggers `focus`', (done) => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -252,7 +252,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `input`', done => {
+ it('triggers `input`', (done) => {
let triggered = false;
$(FORM_SELECTOR).on('input', () => {
triggered = true;
@@ -287,7 +287,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('does not add anything to the input', done => {
+ it('does not add anything to the input', (done) => {
ShortcutsIssuable.replyWithSelectedText(true);
setImmediate(() => {
@@ -296,7 +296,7 @@ describe('ShortcutsIssuable', () => {
});
});
- it('triggers `focus`', done => {
+ it('triggers `focus`', (done) => {
const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -308,7 +308,7 @@ describe('ShortcutsIssuable', () => {
});
describe('with a valid selection with no text content', () => {
- it('returns the proper markdown', done => {
+ it('returns the proper markdown', (done) => {
stubSelection('<img src="https://gitlab.com/logo.png" alt="logo" />');
ShortcutsIssuable.replyWithSelectedText(true);
@@ -334,7 +334,7 @@ describe('ShortcutsIssuable', () => {
'.sidebar-source-branch button',
);
- [sidebarCollapsedBtn, sidebarExpandedBtn].forEach(btn => jest.spyOn(btn, 'click'));
+ [sidebarCollapsedBtn, sidebarExpandedBtn].forEach((btn) => jest.spyOn(btn, 'click'));
});
afterEach(() => {
diff --git a/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js b/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js
index 3b64e4910e2..09c49617bc5 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 ClassSpecHelper from '../../helpers/class_spec_helper';
jest.mock('sql.js');
@@ -49,7 +49,7 @@ describe('BalsamiqViewer', () => {
);
});
- it('should call `renderFile` on request success', done => {
+ it('should call `renderFile` on request success', (done) => {
jest.spyOn(axios, 'get').mockReturnValue(requestSuccess);
jest.spyOn(bv, 'renderFile').mockImplementation(() => {});
@@ -61,7 +61,7 @@ describe('BalsamiqViewer', () => {
.catch(done.fail);
});
- it('should not call `renderFile` on request failure', done => {
+ it('should not call `renderFile` on request failure', (done) => {
jest.spyOn(axios, 'get').mockReturnValue(Promise.reject());
jest.spyOn(bv, 'renderFile').mockImplementation(() => {});
@@ -95,8 +95,8 @@ describe('BalsamiqViewer', () => {
balsamiqViewer.viewer = viewer;
balsamiqViewer.getPreviews.mockReturnValue(previews);
- balsamiqViewer.renderPreview.mockImplementation(preview => preview);
- viewer.appendChild.mockImplementation(containerElement => {
+ balsamiqViewer.renderPreview.mockImplementation((preview) => preview);
+ viewer.appendChild.mockImplementation((containerElement) => {
container = containerElement;
});
@@ -177,7 +177,9 @@ describe('BalsamiqViewer', () => {
database,
};
- jest.spyOn(BalsamiqViewer, 'parsePreview').mockImplementation(preview => preview.toString());
+ jest
+ .spyOn(BalsamiqViewer, 'parsePreview')
+ .mockImplementation((preview) => preview.toString());
database.exec.mockReturnValue(thumbnails);
getPreviews = BalsamiqViewer.prototype.getPreviews.call(balsamiqViewer);
diff --git a/spec/frontend/blob/components/blob_content_error_spec.js b/spec/frontend/blob/components/blob_content_error_spec.js
index 0c6d269ad05..95686be8294 100644
--- a/spec/frontend/blob/components/blob_content_error_spec.js
+++ b/spec/frontend/blob/components/blob_content_error_spec.js
@@ -32,7 +32,7 @@ describe('Blob Content Error component', () => {
viewerError: error.id,
});
expect(wrapper.text()).toContain(reason);
- options.forEach(option => {
+ options.forEach((option) => {
expect(wrapper.text()).toContain(option);
});
});
@@ -52,7 +52,7 @@ describe('Blob Content Error component', () => {
},
});
expect(wrapper.text()).toContain(reason);
- options.forEach(option => {
+ options.forEach((option) => {
expect(wrapper.text()).toContain(option);
});
});
diff --git a/spec/frontend/blob/components/blob_edit_content_spec.js b/spec/frontend/blob/components/blob_edit_content_spec.js
index dbed086a552..7de8d9236ed 100644
--- a/spec/frontend/blob/components/blob_edit_content_spec.js
+++ b/spec/frontend/blob/components/blob_edit_content_spec.js
@@ -40,7 +40,7 @@ describe('Blob Header Editing', () => {
wrapper.destroy();
});
- const triggerChangeContent = val => {
+ const triggerChangeContent = (val) => {
getValue.mockReturnValue(val);
const [cb] = onDidChangeModelContent.mock.calls[0];
diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js
index 4355f46db7e..22e8e6d986c 100644
--- a/spec/frontend/blob/components/blob_edit_header_spec.js
+++ b/spec/frontend/blob/components/blob_edit_header_spec.js
@@ -15,7 +15,7 @@ describe('Blob Header Editing', () => {
});
};
const findDeleteButton = () =>
- wrapper.findAll(GlButton).wrappers.find(x => x.text() === 'Delete file');
+ wrapper.findAll(GlButton).wrappers.find((x) => x.text() === 'Delete file');
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/blob/components/blob_header_filepath_spec.js b/spec/frontend/blob/components/blob_header_filepath_spec.js
index 067a4ae61a0..7b8b5050486 100644
--- a/spec/frontend/blob/components/blob_header_filepath_spec.js
+++ b/spec/frontend/blob/components/blob_header_filepath_spec.js
@@ -32,12 +32,7 @@ describe('Blob Header Filepath', () => {
it('renders regular name', () => {
createComponent();
- expect(
- wrapper
- .find('.js-blob-header-filepath')
- .text()
- .trim(),
- ).toBe(MockBlob.path);
+ expect(wrapper.find('.js-blob-header-filepath').text().trim()).toBe(MockBlob.path);
});
it('does not fail if the name is empty', () => {
@@ -71,12 +66,7 @@ describe('Blob Header Filepath', () => {
);
expect(wrapper.text()).toContain(slotContent);
- expect(
- wrapper
- .text()
- .trim()
- .substring(0, slotContent.length),
- ).toBe(slotContent);
+ expect(wrapper.text().trim().substring(0, slotContent.length)).toBe(slotContent);
});
});
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
index 3e84347bee4..b3f80183f6b 100644
--- a/spec/frontend/blob/components/blob_header_spec.js
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -75,7 +75,7 @@ describe('Blob Header Default Actions', () => {
expect(wrapper.find(DefaultActions).exists()).toBe(false);
});
- Object.keys(slots).forEach(slot => {
+ Object.keys(slots).forEach((slot) => {
it('renders the slots', () => {
const slotContent = slots[slot];
createComponent(
diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
index e8011558765..d4562019302 100644
--- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js
+++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
@@ -2,6 +2,7 @@ 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 pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue';
import modalProps from './pipeline_tour_success_mock_data';
@@ -10,13 +11,21 @@ describe('PipelineTourSuccessModal', () => {
let cookieSpy;
let trackingSpy;
+ const GlEmoji = { template: '<img/>' };
const createComponent = () => {
wrapper = shallowMount(pipelineTourSuccess, {
propsData: modalProps,
stubs: {
- GlModal,
+ GlModal: stubComponent(GlModal, {
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <slot></slot>
+ <slot name="modal-footer"></slot>
+ </div>`,
+ }),
GlSprintf,
- 'gl-emoji': '<img/>',
+ GlEmoji,
},
});
};
@@ -67,7 +76,7 @@ describe('PipelineTourSuccessModal', () => {
it('has expected structure', () => {
const modal = wrapper.find(GlModal);
const sprintf = modal.find(GlSprintf);
- const emoji = modal.find('img');
+ const emoji = modal.find(GlEmoji);
expect(wrapper.text()).toContain("That's it, well done!");
expect(sprintf.exists()).toBe(true);
diff --git a/spec/frontend/blob/sketch/index_spec.js b/spec/frontend/blob/sketch/index_spec.js
index cd12d5e17a8..a24e7de9037 100644
--- a/spec/frontend/blob/sketch/index_spec.js
+++ b/spec/frontend/blob/sketch/index_spec.js
@@ -11,7 +11,7 @@ describe('Sketch viewer', () => {
});
describe('with error message', () => {
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(SketchLoader.prototype, 'getZipFile').mockImplementation(
() =>
new Promise((resolve, reject) => {
@@ -37,7 +37,7 @@ describe('Sketch viewer', () => {
});
describe('success', () => {
- beforeEach(done => {
+ beforeEach((done) => {
const loadAsyncMock = {
files: {
'previews/preview.png': {
@@ -48,7 +48,7 @@ describe('Sketch viewer', () => {
loadAsyncMock.files['previews/preview.png'].async.mockImplementation(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve('foo');
done();
}),
diff --git a/spec/frontend/blob/utils_spec.js b/spec/frontend/blob/utils_spec.js
index ab9e325e963..fa83690c104 100644
--- a/spec/frontend/blob/utils_spec.js
+++ b/spec/frontend/blob/utils_spec.js
@@ -26,7 +26,7 @@ describe('Blob utilities', () => {
it.each([[{}], [{ blobPath, blobContent, blobGlobalId }]])(
'creates the instance with the passed parameters %s',
- extraParams => {
+ (extraParams) => {
const params = {
el: editorEl,
...extraParams,
diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js
index a4b4044f5f9..4a5eb31602d 100644
--- a/spec/frontend/blob/viewer/index_spec.js
+++ b/spec/frontend/blob/viewer/index_spec.js
@@ -37,7 +37,7 @@ describe('Blob viewer', () => {
window.location.hash = '';
});
- it('loads source file after switching views', done => {
+ it('loads source file after switching views', (done) => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setImmediate(() => {
@@ -51,7 +51,7 @@ describe('Blob viewer', () => {
});
});
- it('loads source file when line number is in hash', done => {
+ it('loads source file when line number is in hash', (done) => {
window.location.hash = '#L1';
new BlobViewer();
@@ -117,7 +117,7 @@ describe('Blob viewer', () => {
expect(copyButton.blur).not.toHaveBeenCalled();
});
- it('enables after switching to simple view', done => {
+ it('enables after switching to simple view', (done) => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setImmediate(() => {
@@ -127,7 +127,7 @@ describe('Blob viewer', () => {
});
});
- it('updates tooltip after switching to simple view', done => {
+ it('updates tooltip after switching to simple view', (done) => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setImmediate(() => {
@@ -171,7 +171,7 @@ describe('Blob viewer', () => {
${['simple', 'rich']}
`('when view switches to $views', ({ views }) => {
beforeEach(async () => {
- views.forEach(view => blob.switchToViewer(view));
+ views.forEach((view) => blob.switchToViewer(view));
await axios.waitForAll();
});
diff --git a/spec/frontend/blob_edit/edit_blob_spec.js b/spec/frontend/blob_edit/edit_blob_spec.js
index 9637ea09a3a..7927c14d2ac 100644
--- a/spec/frontend/blob_edit/edit_blob_spec.js
+++ b/spec/frontend/blob_edit/edit_blob_spec.js
@@ -1,12 +1,12 @@
import waitForPromises from 'helpers/wait_for_promises';
import EditBlob from '~/blob_edit/edit_blob';
import EditorLite from '~/editor/editor_lite';
-import { EditorMarkdownExtension } from '~/editor/editor_markdown_ext';
-import { FileTemplateExtension } from '~/editor/editor_file_template_ext';
+import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext';
+import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
jest.mock('~/editor/editor_lite');
-jest.mock('~/editor/editor_markdown_ext');
-jest.mock('~/editor/editor_file_template_ext');
+jest.mock('~/editor/extensions/editor_markdown_ext');
+jest.mock('~/editor/extensions/editor_file_template_ext');
describe('Blob Editing', () => {
const useMock = jest.fn();
@@ -31,7 +31,7 @@ describe('Blob Editing', () => {
FileTemplateExtension.mockClear();
});
- const editorInst = isMarkdown => {
+ const editorInst = (isMarkdown) => {
return new EditBlob({
isMarkdown,
});
diff --git a/spec/frontend/boards/board_list_deprecated_spec.js b/spec/frontend/boards/board_list_deprecated_spec.js
new file mode 100644
index 00000000000..393d7f954b1
--- /dev/null
+++ b/spec/frontend/boards/board_list_deprecated_spec.js
@@ -0,0 +1,275 @@
+/* global List */
+/* global ListIssue */
+
+import Vue from 'vue';
+import MockAdapter from 'axios-mock-adapter';
+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 '~/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');
+
+ document.body.appendChild(el);
+ const mock = new MockAdapter(axios);
+ mock.onAny().reply(boardsMockInterceptor);
+ boardsStore.create();
+
+ const BoardListComp = Vue.extend(BoardList);
+ const list = new List({ ...listObj, ...listProps });
+ const issue = new ListIssue({
+ title: 'Testing',
+ id: 1,
+ iid: 1,
+ confidential: false,
+ labels: [],
+ assignees: [],
+ ...listIssueProps,
+ });
+ if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesSize')) {
+ list.issuesSize = 1;
+ }
+ list.issues.push(issue);
+
+ const component = new BoardListComp({
+ el,
+ store,
+ propsData: {
+ disabled: false,
+ list,
+ issues: list.issues,
+ ...componentProps,
+ },
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+
+ return { component, mock };
+};
+
+describe('Board list component', () => {
+ let mock;
+ let component;
+ let getIssues;
+ function generateIssues(compWrapper) {
+ for (let i = 1; i < 20; i += 1) {
+ const issue = { ...compWrapper.list.issues[0] };
+ issue.id += i;
+ compWrapper.list.issues.push(issue);
+ }
+ }
+
+ describe('When Expanded', () => {
+ beforeEach((done) => {
+ getIssues = jest.spyOn(List.prototype, 'getIssues').mockReturnValue(new Promise(() => {}));
+ ({ mock, component } = createComponent({ done }));
+ });
+
+ afterEach(() => {
+ mock.restore();
+ component.$destroy();
+ });
+
+ it('loads first page of issues', () => {
+ return waitForPromises().then(() => {
+ expect(getIssues).toHaveBeenCalled();
+ });
+ });
+
+ it('renders component', () => {
+ expect(component.$el.classList.contains('board-list-component')).toBe(true);
+ });
+
+ it('renders loading icon', () => {
+ component.list.loading = true;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-list-loading')).not.toBeNull();
+ });
+ });
+
+ it('renders issues', () => {
+ expect(component.$el.querySelectorAll('.board-card').length).toBe(1);
+ });
+
+ it('sets data attribute with issue id', () => {
+ expect(component.$el.querySelector('.board-card').getAttribute('data-issue-id')).toBe('1');
+ });
+
+ it('shows new issue form', () => {
+ component.toggleForm();
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull();
+
+ expect(component.$el.querySelector('.is-smaller')).not.toBeNull();
+ });
+ });
+
+ it('shows new issue form after eventhub event', () => {
+ eventHub.$emit(`toggle-issue-form-${component.list.id}`);
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull();
+
+ expect(component.$el.querySelector('.is-smaller')).not.toBeNull();
+ });
+ });
+
+ it('does not show new issue form for closed list', () => {
+ component.list.type = 'closed';
+ component.toggleForm();
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-new-issue-form')).toBeNull();
+ });
+ });
+
+ it('shows count list item', () => {
+ component.showCount = true;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-list-count')).not.toBeNull();
+
+ expect(component.$el.querySelector('.board-list-count').textContent.trim()).toBe(
+ 'Showing all issues',
+ );
+ });
+ });
+
+ it('sets data attribute with invalid id', () => {
+ component.showCount = true;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-list-count').getAttribute('data-issue-id')).toBe(
+ '-1',
+ );
+ });
+ });
+
+ it('shows how many more issues to load', () => {
+ component.showCount = true;
+ component.list.issuesSize = 20;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-list-count').textContent.trim()).toBe(
+ 'Showing 1 of 20 issues',
+ );
+ });
+ });
+
+ it('loads more issues after scrolling', () => {
+ jest.spyOn(component.list, 'nextPage').mockImplementation(() => {});
+ generateIssues(component);
+ component.$refs.list.dispatchEvent(new Event('scroll'));
+
+ return waitForPromises().then(() => {
+ expect(component.list.nextPage).toHaveBeenCalled();
+ });
+ });
+
+ it('does not load issues if already loading', () => {
+ component.list.nextPage = jest
+ .spyOn(component.list, 'nextPage')
+ .mockReturnValue(new Promise(() => {}));
+
+ component.onScroll();
+ component.onScroll();
+
+ return waitForPromises().then(() => {
+ expect(component.list.nextPage).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it('shows loading more spinner', () => {
+ component.showCount = true;
+ component.list.loadingMore = true;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.board-list-count .gl-spinner')).not.toBeNull();
+ });
+ });
+ });
+
+ describe('When Collapsed', () => {
+ beforeEach((done) => {
+ getIssues = jest.spyOn(List.prototype, 'getIssues').mockReturnValue(new Promise(() => {}));
+ ({ mock, component } = createComponent({
+ done,
+ listProps: { type: 'closed', collapsed: true, issuesSize: 50 },
+ }));
+ generateIssues(component);
+ component.scrollHeight = jest.spyOn(component, 'scrollHeight').mockReturnValue(0);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ component.$destroy();
+ });
+
+ it('does not load all issues', () => {
+ return waitForPromises().then(() => {
+ // Initial getIssues from list constructor
+ expect(getIssues).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe('max issue count warning', () => {
+ beforeEach((done) => {
+ ({ mock, component } = createComponent({
+ done,
+ listProps: { type: 'closed', collapsed: true, issuesSize: 50 },
+ }));
+ });
+
+ afterEach(() => {
+ mock.restore();
+ component.$destroy();
+ });
+
+ describe('when issue count exceeds max issue count', () => {
+ it('sets background to bg-danger-100', () => {
+ component.list.issuesSize = 4;
+ component.list.maxIssueCount = 3;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.bg-danger-100')).not.toBeNull();
+ });
+ });
+ });
+
+ describe('when list issue count does NOT exceed list max issue count', () => {
+ it('does not sets background to bg-danger-100', () => {
+ component.list.issuesSize = 2;
+ component.list.maxIssueCount = 3;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.bg-danger-100')).toBeNull();
+ });
+ });
+ });
+
+ describe('when list max issue count is 0', () => {
+ it('does not sets background to bg-danger-100', () => {
+ component.list.maxIssueCount = 0;
+
+ return Vue.nextTick().then(() => {
+ expect(component.$el.querySelector('.bg-danger-100')).toBeNull();
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js
index 80d7a72151d..f82b1f7ed5c 100644
--- a/spec/frontend/boards/board_list_helper.js
+++ b/spec/frontend/boards/board_list_helper.js
@@ -5,7 +5,7 @@ import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
import Sortable from 'sortablejs';
import axios from '~/lib/utils/axios_utils';
-import BoardList from '~/boards/components/board_list.vue';
+import BoardList from '~/boards/components/board_list_deprecated.vue';
import '~/boards/models/issue';
import '~/boards/models/list';
diff --git a/spec/frontend/boards/board_list_new_spec.js b/spec/frontend/boards/board_list_new_spec.js
deleted file mode 100644
index 96b03ed927e..00000000000
--- a/spec/frontend/boards/board_list_new_spec.js
+++ /dev/null
@@ -1,268 +0,0 @@
-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_new.vue';
-import BoardCard from '~/boards/components/board_card.vue';
-import '~/boards/models/list';
-import { mockList, mockIssuesByListId, issues, mockIssues } from './mock_data';
-import defaultState from '~/boards/stores/state';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-const actions = {
- fetchIssuesForList: jest.fn(),
-};
-
-const createStore = (state = defaultState) => {
- return new Vuex.Store({
- state,
- actions,
- });
-};
-
-const createComponent = ({
- listIssueProps = {},
- componentProps = {},
- listProps = {},
- state = {},
-} = {}) => {
- const store = createStore({
- issuesByListId: mockIssuesByListId,
- issues,
- pageInfoByListId: {
- 'gid://gitlab/List/1': { hasNextPage: true },
- 'gid://gitlab/List/2': {},
- },
- listsFlags: {
- 'gid://gitlab/List/1': {},
- 'gid://gitlab/List/2': {},
- },
- ...state,
- });
-
- const list = {
- ...mockList,
- ...listProps,
- };
- const issue = {
- title: 'Testing',
- id: 1,
- iid: 1,
- confidential: false,
- labels: [],
- assignees: [],
- ...listIssueProps,
- };
- if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesCount')) {
- list.issuesCount = 1;
- }
-
- const component = mount(BoardList, {
- localVue,
- propsData: {
- disabled: false,
- list,
- issues: [issue],
- canAdminList: true,
- ...componentProps,
- },
- store,
- provide: {
- groupId: null,
- rootPath: '/',
- weightFeatureAvailable: false,
- boardWeight: null,
- },
- });
-
- return component;
-};
-
-describe('Board list component', () => {
- let wrapper;
- const findByTestId = testId => wrapper.find(`[data-testid="${testId}"]`);
- useFakeRequestAnimationFrame();
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('When Expanded', () => {
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- it('renders component', () => {
- expect(wrapper.find('.board-list-component').exists()).toBe(true);
- });
-
- it('renders loading icon', () => {
- wrapper = createComponent({
- state: { listsFlags: { 'gid://gitlab/List/1': { isLoading: true } } },
- });
-
- expect(findByTestId('board_list_loading').exists()).toBe(true);
- });
-
- it('renders issues', () => {
- expect(wrapper.findAll(BoardCard).length).toBe(1);
- });
-
- it('sets data attribute with issue id', () => {
- expect(wrapper.find('.board-card').attributes('data-issue-id')).toBe('1');
- });
-
- it('shows new issue form', async () => {
- wrapper.vm.toggleForm();
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
- });
-
- it('shows new issue form after eventhub event', async () => {
- eventHub.$emit(`toggle-issue-form-${wrapper.vm.list.id}`);
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
- });
-
- it('does not show new issue form for closed list', () => {
- wrapper.setProps({ list: { type: 'closed' } });
- wrapper.vm.toggleForm();
-
- expect(wrapper.find('.board-new-issue-form').exists()).toBe(false);
- });
-
- it('shows count list item', async () => {
- wrapper.vm.showCount = true;
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-list-count').exists()).toBe(true);
-
- expect(wrapper.find('.board-list-count').text()).toBe('Showing all issues');
- });
-
- it('sets data attribute with invalid id', async () => {
- wrapper.vm.showCount = true;
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-list-count').attributes('data-issue-id')).toBe('-1');
- });
-
- it('shows how many more issues to load', async () => {
- wrapper.vm.showCount = true;
- wrapper.setProps({ list: { issuesCount: 20 } });
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-list-count').text()).toBe('Showing 1 of 20 issues');
- });
- });
-
- describe('load more issues', () => {
- beforeEach(() => {
- wrapper = createComponent({
- listProps: { issuesCount: 25 },
- });
- });
-
- it('loads more issues after scrolling', () => {
- wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
-
- expect(actions.fetchIssuesForList).toHaveBeenCalled();
- });
-
- it('does not load issues if already loading', () => {
- wrapper = createComponent({
- state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
- });
- wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
-
- expect(actions.fetchIssuesForList).not.toHaveBeenCalled();
- });
-
- it('shows loading more spinner', async () => {
- wrapper = createComponent({
- state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
- });
- wrapper.vm.showCount = true;
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-list-count .gl-spinner').exists()).toBe(true);
- });
- });
-
- describe('max issue count warning', () => {
- beforeEach(() => {
- wrapper = createComponent({
- listProps: { issuesCount: 50 },
- });
- });
-
- describe('when issue count exceeds max issue count', () => {
- it('sets background to bg-danger-100', async () => {
- wrapper.setProps({ list: { issuesCount: 4, maxIssueCount: 3 } });
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.bg-danger-100').exists()).toBe(true);
- });
- });
-
- describe('when list issue count does NOT exceed list max issue count', () => {
- it('does not sets background to bg-danger-100', () => {
- wrapper.setProps({ list: { issuesCount: 2, maxIssueCount: 3 } });
-
- expect(wrapper.find('.bg-danger-100').exists()).toBe(false);
- });
- });
-
- describe('when list max issue count is 0', () => {
- it('does not sets background to bg-danger-100', () => {
- wrapper.setProps({ list: { maxIssueCount: 0 } });
-
- expect(wrapper.find('.bg-danger-100').exists()).toBe(false);
- });
- });
- });
-
- describe('drag & drop issue', () => {
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- describe('handleDragOnStart', () => {
- it('adds a class `is-dragging` to document body', () => {
- expect(document.body.classList.contains('is-dragging')).toBe(false);
-
- findByTestId('tree-root-wrapper').vm.$emit('start');
-
- expect(document.body.classList.contains('is-dragging')).toBe(true);
- });
- });
-
- describe('handleDragOnEnd', () => {
- it('removes class `is-dragging` from document body', () => {
- jest.spyOn(wrapper.vm, 'moveIssue').mockImplementation(() => {});
- document.body.classList.add('is-dragging');
-
- findByTestId('tree-root-wrapper').vm.$emit('end', {
- oldIndex: 1,
- newIndex: 0,
- item: {
- dataset: {
- issueId: mockIssues[0].id,
- issueIid: mockIssues[0].iid,
- issuePath: mockIssues[0].referencePath,
- },
- },
- to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
- from: { dataset: { listId: 'gid://gitlab/List/2' } },
- });
-
- expect(document.body.classList.contains('is-dragging')).toBe(false);
- });
- });
- });
-});
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 0fe3c88f518..1b62f25044e 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -1,29 +1,51 @@
-/* global List */
-/* global ListIssue */
-
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_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 waitForPromises from '../helpers/wait_for_promises';
import BoardList from '~/boards/components/board_list.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';
-
-const createComponent = ({ done, listIssueProps = {}, componentProps = {}, listProps = {} }) => {
- const el = document.createElement('div');
-
- document.body.appendChild(el);
- const mock = new MockAdapter(axios);
- mock.onAny().reply(boardsMockInterceptor);
- boardsStore.create();
-
- const BoardListComp = Vue.extend(BoardList);
- const list = new List({ ...listObj, ...listProps });
- const issue = new ListIssue({
+import BoardCard from '~/boards/components/board_card.vue';
+import { mockList, mockIssuesByListId, issues, mockIssues } from './mock_data';
+import defaultState from '~/boards/stores/state';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+const actions = {
+ fetchIssuesForList: jest.fn(),
+};
+
+const createStore = (state = defaultState) => {
+ return new Vuex.Store({
+ state,
+ actions,
+ });
+};
+
+const createComponent = ({
+ listIssueProps = {},
+ componentProps = {},
+ listProps = {},
+ state = {},
+} = {}) => {
+ const store = createStore({
+ issuesByListId: mockIssuesByListId,
+ issues,
+ pageInfoByListId: {
+ 'gid://gitlab/List/1': { hasNextPage: true },
+ 'gid://gitlab/List/2': {},
+ },
+ listsFlags: {
+ 'gid://gitlab/List/1': {},
+ 'gid://gitlab/List/2': {},
+ },
+ ...state,
+ });
+
+ const list = {
+ ...mockList,
+ ...listProps,
+ };
+ const issue = {
title: 'Testing',
id: 1,
iid: 1,
@@ -31,244 +53,214 @@ const createComponent = ({ done, listIssueProps = {}, componentProps = {}, listP
labels: [],
assignees: [],
...listIssueProps,
- });
- if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesSize')) {
- list.issuesSize = 1;
+ };
+ if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesCount')) {
+ list.issuesCount = 1;
}
- list.issues.push(issue);
- const component = new BoardListComp({
- el,
- store,
+ const component = mount(BoardList, {
+ localVue,
propsData: {
disabled: false,
list,
- issues: list.issues,
+ issues: [issue],
+ canAdminList: true,
...componentProps,
},
+ store,
provide: {
groupId: null,
rootPath: '/',
+ weightFeatureAvailable: false,
+ boardWeight: null,
},
- }).$mount();
-
- Vue.nextTick(() => {
- done();
});
- return { component, mock };
+ return component;
};
describe('Board list component', () => {
- let mock;
- let component;
- let getIssues;
- function generateIssues(compWrapper) {
- for (let i = 1; i < 20; i += 1) {
- const issue = { ...compWrapper.list.issues[0] };
- issue.id += i;
- compWrapper.list.issues.push(issue);
- }
- }
+ let wrapper;
+ const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
+ useFakeRequestAnimationFrame();
- describe('When Expanded', () => {
- beforeEach(done => {
- getIssues = jest.spyOn(List.prototype, 'getIssues').mockReturnValue(new Promise(() => {}));
- ({ mock, component } = createComponent({ done }));
- });
-
- afterEach(() => {
- mock.restore();
- component.$destroy();
- });
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
- it('loads first page of issues', () => {
- return waitForPromises().then(() => {
- expect(getIssues).toHaveBeenCalled();
- });
+ describe('When Expanded', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
});
it('renders component', () => {
- expect(component.$el.classList.contains('board-list-component')).toBe(true);
+ expect(wrapper.find('.board-list-component').exists()).toBe(true);
});
it('renders loading icon', () => {
- component.list.loading = true;
-
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-list-loading')).not.toBeNull();
+ wrapper = createComponent({
+ state: { listsFlags: { 'gid://gitlab/List/1': { isLoading: true } } },
});
+
+ expect(findByTestId('board_list_loading').exists()).toBe(true);
});
it('renders issues', () => {
- expect(component.$el.querySelectorAll('.board-card').length).toBe(1);
+ expect(wrapper.findAll(BoardCard).length).toBe(1);
});
it('sets data attribute with issue id', () => {
- expect(component.$el.querySelector('.board-card').getAttribute('data-issue-id')).toBe('1');
+ expect(wrapper.find('.board-card').attributes('data-issue-id')).toBe('1');
});
- it('shows new issue form', () => {
- component.toggleForm();
-
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull();
+ it('shows new issue form', async () => {
+ wrapper.vm.toggleForm();
- expect(component.$el.querySelector('.is-smaller')).not.toBeNull();
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
});
- it('shows new issue form after eventhub event', () => {
- eventHub.$emit(`toggle-issue-form-${component.list.id}`);
-
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull();
+ it('shows new issue form after eventhub event', async () => {
+ eventHub.$emit(`toggle-issue-form-${wrapper.vm.list.id}`);
- expect(component.$el.querySelector('.is-smaller')).not.toBeNull();
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-new-issue-form').exists()).toBe(true);
});
it('does not show new issue form for closed list', () => {
- component.list.type = 'closed';
- component.toggleForm();
+ wrapper.setProps({ list: { type: 'closed' } });
+ wrapper.vm.toggleForm();
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-new-issue-form')).toBeNull();
- });
+ expect(wrapper.find('.board-new-issue-form').exists()).toBe(false);
});
- it('shows count list item', () => {
- component.showCount = true;
+ it('shows count list item', async () => {
+ wrapper.vm.showCount = true;
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-list-count')).not.toBeNull();
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-list-count').exists()).toBe(true);
- expect(component.$el.querySelector('.board-list-count').textContent.trim()).toBe(
- 'Showing all issues',
- );
- });
+ expect(wrapper.find('.board-list-count').text()).toBe('Showing all issues');
});
- it('sets data attribute with invalid id', () => {
- component.showCount = true;
+ it('sets data attribute with invalid id', async () => {
+ wrapper.vm.showCount = true;
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-list-count').getAttribute('data-issue-id')).toBe(
- '-1',
- );
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-list-count').attributes('data-issue-id')).toBe('-1');
});
- it('shows how many more issues to load', () => {
- component.showCount = true;
- component.list.issuesSize = 20;
+ it('shows how many more issues to load', async () => {
+ wrapper.vm.showCount = true;
+ wrapper.setProps({ list: { issuesCount: 20 } });
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-list-count').textContent.trim()).toBe(
- 'Showing 1 of 20 issues',
- );
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-list-count').text()).toBe('Showing 1 of 20 issues');
});
+ });
- it('loads more issues after scrolling', () => {
- jest.spyOn(component.list, 'nextPage').mockImplementation(() => {});
- generateIssues(component);
- component.$refs.list.dispatchEvent(new Event('scroll'));
-
- return waitForPromises().then(() => {
- expect(component.list.nextPage).toHaveBeenCalled();
+ describe('load more issues', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ listProps: { issuesCount: 25 },
});
});
- it('does not load issues if already loading', () => {
- component.list.nextPage = jest
- .spyOn(component.list, 'nextPage')
- .mockReturnValue(new Promise(() => {}));
-
- component.onScroll();
- component.onScroll();
+ it('loads more issues after scrolling', () => {
+ wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
- return waitForPromises().then(() => {
- expect(component.list.nextPage).toHaveBeenCalledTimes(1);
- });
+ expect(actions.fetchIssuesForList).toHaveBeenCalled();
});
- it('shows loading more spinner', () => {
- component.showCount = true;
- component.list.loadingMore = true;
-
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.board-list-count .gl-spinner')).not.toBeNull();
+ it('does not load issues if already loading', () => {
+ wrapper = createComponent({
+ state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
});
- });
- });
+ wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
- describe('When Collapsed', () => {
- beforeEach(done => {
- getIssues = jest.spyOn(List.prototype, 'getIssues').mockReturnValue(new Promise(() => {}));
- ({ mock, component } = createComponent({
- done,
- listProps: { type: 'closed', collapsed: true, issuesSize: 50 },
- }));
- generateIssues(component);
- component.scrollHeight = jest.spyOn(component, 'scrollHeight').mockReturnValue(0);
+ expect(actions.fetchIssuesForList).not.toHaveBeenCalled();
});
- afterEach(() => {
- mock.restore();
- component.$destroy();
- });
-
- it('does not load all issues', () => {
- return waitForPromises().then(() => {
- // Initial getIssues from list constructor
- expect(getIssues).toHaveBeenCalledTimes(1);
+ it('shows loading more spinner', async () => {
+ wrapper = createComponent({
+ state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
});
+ wrapper.vm.showCount = true;
+
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-list-count .gl-spinner').exists()).toBe(true);
});
});
describe('max issue count warning', () => {
- beforeEach(done => {
- ({ mock, component } = createComponent({
- done,
- listProps: { type: 'closed', collapsed: true, issuesSize: 50 },
- }));
- });
-
- afterEach(() => {
- mock.restore();
- component.$destroy();
+ beforeEach(() => {
+ wrapper = createComponent({
+ listProps: { issuesCount: 50 },
+ });
});
describe('when issue count exceeds max issue count', () => {
- it('sets background to bg-danger-100', () => {
- component.list.issuesSize = 4;
- component.list.maxIssueCount = 3;
+ it('sets background to bg-danger-100', async () => {
+ wrapper.setProps({ list: { issuesCount: 4, maxIssueCount: 3 } });
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.bg-danger-100')).not.toBeNull();
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.bg-danger-100').exists()).toBe(true);
});
});
describe('when list issue count does NOT exceed list max issue count', () => {
it('does not sets background to bg-danger-100', () => {
- component.list.issuesSize = 2;
- component.list.maxIssueCount = 3;
+ wrapper.setProps({ list: { issuesCount: 2, maxIssueCount: 3 } });
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.bg-danger-100')).toBeNull();
- });
+ expect(wrapper.find('.bg-danger-100').exists()).toBe(false);
});
});
describe('when list max issue count is 0', () => {
it('does not sets background to bg-danger-100', () => {
- component.list.maxIssueCount = 0;
+ wrapper.setProps({ list: { maxIssueCount: 0 } });
+
+ expect(wrapper.find('.bg-danger-100').exists()).toBe(false);
+ });
+ });
+ });
- return Vue.nextTick().then(() => {
- expect(component.$el.querySelector('.bg-danger-100')).toBeNull();
+ describe('drag & drop issue', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ describe('handleDragOnStart', () => {
+ it('adds a class `is-dragging` to document body', () => {
+ expect(document.body.classList.contains('is-dragging')).toBe(false);
+
+ findByTestId('tree-root-wrapper').vm.$emit('start');
+
+ expect(document.body.classList.contains('is-dragging')).toBe(true);
+ });
+ });
+
+ describe('handleDragOnEnd', () => {
+ it('removes class `is-dragging` from document body', () => {
+ jest.spyOn(wrapper.vm, 'moveIssue').mockImplementation(() => {});
+ document.body.classList.add('is-dragging');
+
+ findByTestId('tree-root-wrapper').vm.$emit('end', {
+ oldIndex: 1,
+ newIndex: 0,
+ item: {
+ dataset: {
+ issueId: mockIssues[0].id,
+ issueIid: mockIssues[0].iid,
+ issuePath: mockIssues[0].referencePath,
+ },
+ },
+ to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
+ from: { dataset: { listId: 'gid://gitlab/List/2' } },
});
+
+ expect(document.body.classList.contains('is-dragging')).toBe(false);
});
});
});
diff --git a/spec/frontend/boards/board_new_issue_deprecated_spec.js b/spec/frontend/boards/board_new_issue_deprecated_spec.js
new file mode 100644
index 00000000000..8236b468189
--- /dev/null
+++ b/spec/frontend/boards/board_new_issue_deprecated_spec.js
@@ -0,0 +1,203 @@
+/* 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 boardNewIssue from '~/boards/components/board_new_issue_deprecated.vue';
+import boardsStore from '~/boards/stores/boards_store';
+
+import '~/boards/models/list';
+import { listObj, boardsMockInterceptor } from './mock_data';
+
+describe('Issue boards new issue form', () => {
+ let wrapper;
+ let vm;
+ let list;
+ let mock;
+ let newIssueMock;
+ const promiseReturn = {
+ data: {
+ iid: 100,
+ },
+ };
+
+ const submitIssue = () => {
+ const dummySubmitEvent = {
+ preventDefault() {},
+ };
+ wrapper.vm.$refs.submitButton = wrapper.find({ ref: 'submitButton' });
+ return wrapper.vm.submit(dummySubmitEvent);
+ };
+
+ beforeEach(() => {
+ const BoardNewIssueComp = Vue.extend(boardNewIssue);
+
+ mock = new MockAdapter(axios);
+ mock.onAny().reply(boardsMockInterceptor);
+
+ boardsStore.create();
+
+ list = new List(listObj);
+
+ newIssueMock = Promise.resolve(promiseReturn);
+ jest.spyOn(list, 'newIssue').mockImplementation(() => newIssueMock);
+
+ wrapper = mount(BoardNewIssueComp, {
+ propsData: {
+ disabled: false,
+ list,
+ },
+ provide: {
+ groupId: null,
+ },
+ });
+
+ vm = wrapper.vm;
+
+ return Vue.nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mock.restore();
+ });
+
+ it('calls submit if submit button is clicked', () => {
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ vm.title = 'Testing Title';
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(wrapper.vm.submit).toHaveBeenCalled();
+ });
+ });
+
+ it('disables submit button if title is empty', () => {
+ expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(true);
+ });
+
+ it('enables submit button if title is not empty', () => {
+ wrapper.setData({ title: 'Testing Title' });
+
+ return Vue.nextTick().then(() => {
+ expect(wrapper.find({ ref: 'input' }).element.value).toBe('Testing Title');
+ expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(false);
+ });
+ });
+
+ it('clears title after clicking cancel', () => {
+ wrapper.find({ ref: 'cancelButton' }).trigger('click');
+
+ return Vue.nextTick().then(() => {
+ expect(vm.title).toBe('');
+ });
+ });
+
+ it('does not create new issue if title is empty', () => {
+ return submitIssue().then(() => {
+ expect(list.newIssue).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('submit success', () => {
+ it('creates new issue', () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(list.newIssue).toHaveBeenCalled();
+ });
+ });
+
+ it('enables button after submit', () => {
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(wrapper.vm.$refs.submitButton.props().disabled).toBe(false);
+ });
+ });
+
+ it('clears title after submit', () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(vm.title).toBe('');
+ });
+ });
+
+ it('sets detail issue after submit', () => {
+ expect(boardsStore.detail.issue.title).toBe(undefined);
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(boardsStore.detail.issue.title).toBe('submit issue');
+ });
+ });
+
+ it('sets detail list after submit', () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(boardsStore.detail.list.id).toBe(list.id);
+ });
+ });
+
+ it('sets detail weight after submit', () => {
+ boardsStore.weightFeatureAvailable = true;
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(boardsStore.detail.list.weight).toBe(list.weight);
+ });
+ });
+
+ it('does not set detail weight after submit', () => {
+ boardsStore.weightFeatureAvailable = false;
+ wrapper.setData({ title: 'submit issue' });
+
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(boardsStore.detail.list.weight).toBe(list.weight);
+ });
+ });
+ });
+
+ describe('submit error', () => {
+ beforeEach(() => {
+ newIssueMock = Promise.reject(new Error('My hovercraft is full of eels!'));
+ vm.title = 'error';
+ });
+
+ it('removes issue', () => {
+ const lengthBefore = list.issues.length;
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(list.issues.length).toBe(lengthBefore);
+ });
+ });
+
+ it('shows error', () => {
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(vm.error).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/board_new_issue_spec.js b/spec/frontend/boards/board_new_issue_spec.js
deleted file mode 100644
index 3eebfeca965..00000000000
--- a/spec/frontend/boards/board_new_issue_spec.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/* 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 boardNewIssue from '~/boards/components/board_new_issue.vue';
-import boardsStore from '~/boards/stores/boards_store';
-
-import '~/boards/models/list';
-import { listObj, boardsMockInterceptor } from './mock_data';
-
-describe('Issue boards new issue form', () => {
- let wrapper;
- let vm;
- let list;
- let mock;
- let newIssueMock;
- const promiseReturn = {
- data: {
- iid: 100,
- },
- };
-
- const submitIssue = () => {
- const dummySubmitEvent = {
- preventDefault() {},
- };
- wrapper.vm.$refs.submitButton = wrapper.find({ ref: 'submitButton' });
- return wrapper.vm.submit(dummySubmitEvent);
- };
-
- beforeEach(() => {
- const BoardNewIssueComp = Vue.extend(boardNewIssue);
-
- mock = new MockAdapter(axios);
- mock.onAny().reply(boardsMockInterceptor);
-
- boardsStore.create();
-
- list = new List(listObj);
-
- newIssueMock = Promise.resolve(promiseReturn);
- jest.spyOn(list, 'newIssue').mockImplementation(() => newIssueMock);
-
- wrapper = mount(BoardNewIssueComp, {
- propsData: {
- disabled: false,
- list,
- },
- provide: {
- groupId: null,
- },
- });
-
- vm = wrapper.vm;
-
- return Vue.nextTick();
- });
-
- afterEach(() => {
- wrapper.destroy();
- mock.restore();
- });
-
- it('calls submit if submit button is clicked', () => {
- jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- vm.title = 'Testing Title';
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(wrapper.vm.submit).toHaveBeenCalled();
- });
- });
-
- it('disables submit button if title is empty', () => {
- expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(true);
- });
-
- it('enables submit button if title is not empty', () => {
- wrapper.setData({ title: 'Testing Title' });
-
- return Vue.nextTick().then(() => {
- expect(wrapper.find({ ref: 'input' }).element.value).toBe('Testing Title');
- expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(false);
- });
- });
-
- it('clears title after clicking cancel', () => {
- wrapper.find({ ref: 'cancelButton' }).trigger('click');
-
- return Vue.nextTick().then(() => {
- expect(vm.title).toBe('');
- });
- });
-
- it('does not create new issue if title is empty', () => {
- return submitIssue().then(() => {
- expect(list.newIssue).not.toHaveBeenCalled();
- });
- });
-
- describe('submit success', () => {
- it('creates new issue', () => {
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(list.newIssue).toHaveBeenCalled();
- });
- });
-
- it('enables button after submit', () => {
- jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(wrapper.vm.$refs.submitButton.props().disabled).toBe(false);
- });
- });
-
- it('clears title after submit', () => {
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(vm.title).toBe('');
- });
- });
-
- it('sets detail issue after submit', () => {
- expect(boardsStore.detail.issue.title).toBe(undefined);
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(boardsStore.detail.issue.title).toBe('submit issue');
- });
- });
-
- it('sets detail list after submit', () => {
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(boardsStore.detail.list.id).toBe(list.id);
- });
- });
-
- it('sets detail weight after submit', () => {
- boardsStore.weightFeatureAvailable = true;
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(boardsStore.detail.list.weight).toBe(list.weight);
- });
- });
-
- it('does not set detail weight after submit', () => {
- boardsStore.weightFeatureAvailable = false;
- wrapper.setData({ title: 'submit issue' });
-
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(boardsStore.detail.list.weight).toBe(list.weight);
- });
- });
- });
-
- describe('submit error', () => {
- beforeEach(() => {
- newIssueMock = Promise.reject(new Error('My hovercraft is full of eels!'));
- vm.title = 'error';
- });
-
- it('removes issue', () => {
- const lengthBefore = list.issues.length;
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(list.issues.length).toBe(lengthBefore);
- });
- });
-
- it('shows error', () => {
- return Vue.nextTick()
- .then(submitIssue)
- .then(() => {
- expect(vm.error).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/boards/boards_store_spec.js b/spec/frontend/boards/boards_store_spec.js
index c89f6d22ef2..f1d249ff069 100644
--- a/spec/frontend/boards/boards_store_spec.js
+++ b/spec/frontend/boards/boards_store_spec.js
@@ -77,7 +77,7 @@ describe('boardsStore', () => {
beforeEach(() => {
requestSpy = jest.fn();
- axiosMock.onPost(endpoints.listsEndpoint).replyOnce(config => requestSpy(config));
+ axiosMock.onPost(endpoints.listsEndpoint).replyOnce((config) => requestSpy(config));
});
it('makes a request to create a list', () => {
@@ -114,7 +114,7 @@ describe('boardsStore', () => {
beforeEach(() => {
requestSpy = jest.fn();
- axiosMock.onPut(`${endpoints.listsEndpoint}/${id}`).replyOnce(config => requestSpy(config));
+ axiosMock.onPut(`${endpoints.listsEndpoint}/${id}`).replyOnce((config) => requestSpy(config));
});
it('makes a request to update a list position', () => {
@@ -148,7 +148,7 @@ describe('boardsStore', () => {
requestSpy = jest.fn();
axiosMock
.onDelete(`${endpoints.listsEndpoint}/${id}`)
- .replyOnce(config => requestSpy(config));
+ .replyOnce((config) => requestSpy(config));
});
it('makes a request to delete a list', () => {
@@ -269,7 +269,7 @@ describe('boardsStore', () => {
requestSpy = jest.fn();
axiosMock
.onPut(`${urlRoot}/-/boards/${boardId}/issues/${id}`)
- .replyOnce(config => requestSpy(config));
+ .replyOnce((config) => requestSpy(config));
});
it('makes a request to move an issue between lists', () => {
@@ -308,7 +308,7 @@ describe('boardsStore', () => {
beforeEach(() => {
requestSpy = jest.fn();
- axiosMock.onPost(url).replyOnce(config => requestSpy(config));
+ axiosMock.onPost(url).replyOnce((config) => requestSpy(config));
});
it('makes a request to create a new issue', () => {
@@ -378,7 +378,7 @@ describe('boardsStore', () => {
beforeEach(() => {
requestSpy = jest.fn();
- axiosMock.onPost(endpoints.bulkUpdatePath).replyOnce(config => requestSpy(config));
+ axiosMock.onPost(endpoints.bulkUpdatePath).replyOnce((config) => requestSpy(config));
});
it('makes a request to create a list', () => {
@@ -456,24 +456,6 @@ describe('boardsStore', () => {
});
});
- describe('deleteBoard', () => {
- const id = 'capsized';
- const url = `${endpoints.boardsEndpoint}/${id}.json`;
-
- it('makes a request to delete a boards', () => {
- axiosMock.onDelete(url).replyOnce(200, dummyResponse);
- const expectedResponse = expect.objectContaining({ data: dummyResponse });
-
- return expect(boardsStore.deleteBoard({ id })).resolves.toEqual(expectedResponse);
- });
-
- it('fails for error response', () => {
- axiosMock.onDelete(url).replyOnce(500);
-
- return expect(boardsStore.deleteBoard({ id })).rejects.toThrow();
- });
- });
-
describe('when created', () => {
beforeEach(() => {
setupDefaultResponses();
@@ -603,7 +585,7 @@ describe('boardsStore', () => {
expect(boardsStore.state.lists.length).toBe(1);
- boardsStore.removeList(listObj.id, 'label');
+ boardsStore.removeList(listObj.id);
expect(boardsStore.state.lists.length).toBe(0);
});
diff --git a/spec/frontend/boards/components/board_assignee_dropdown_spec.js b/spec/frontend/boards/components/board_assignee_dropdown_spec.js
index bbdcc707f09..e52c14f9783 100644
--- a/spec/frontend/boards/components/board_assignee_dropdown_spec.js
+++ b/spec/frontend/boards/components/board_assignee_dropdown_spec.js
@@ -6,7 +6,7 @@ import {
GlSearchBoxByType,
GlLoadingIcon,
} from '@gitlab/ui';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
@@ -93,8 +93,8 @@ describe('BoardCardAssigneeDropdown', () => {
await wrapper.vm.$nextTick();
};
- const findByText = text => {
- return wrapper.findAll(GlDropdownItem).wrappers.find(node => node.text().indexOf(text) === 0);
+ const findByText = (text) => {
+ return wrapper.findAll(GlDropdownItem).wrappers.find((node) => node.text().indexOf(text) === 0);
};
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
@@ -102,7 +102,7 @@ describe('BoardCardAssigneeDropdown', () => {
beforeEach(() => {
store.state.activeId = '1';
store.state.issues = {
- '1': {
+ 1: {
iid,
assignees: [{ username: activeIssueName, name: activeIssueName, id: activeIssueName }],
},
@@ -145,12 +145,7 @@ describe('BoardCardAssigneeDropdown', () => {
it('renders gl-avatar-labeled in gl-avatar-link', () => {
const item = findByText('hello');
- expect(
- item
- .find(GlAvatarLink)
- .find(GlAvatarLabeled)
- .exists(),
- ).toBe(true);
+ expect(item.find(GlAvatarLink).find(GlAvatarLabeled).exists()).toBe(true);
});
});
diff --git a/spec/frontend/boards/components/board_card_layout_spec.js b/spec/frontend/boards/components/board_card_layout_spec.js
index 80f649a1a96..d8633871e8d 100644
--- a/spec/frontend/boards/components/board_card_layout_spec.js
+++ b/spec/frontend/boards/components/board_card_layout_spec.js
@@ -1,7 +1,8 @@
/* global List */
/* global ListLabel */
-import { shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
@@ -10,20 +11,35 @@ import axios from '~/lib/utils/axios_utils';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/list';
-import store from '~/boards/stores';
+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 { ISSUABLE } from '~/boards/constants';
+
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 => {
+ const mountComponent = ({ propsData = {}, provide = {} } = {}) => {
wrapper = shallowMount(BoardCardLayout, {
+ localVue,
stubs: {
issueCardInner,
},
@@ -38,6 +54,8 @@ describe('Board card layout', () => {
provide: {
groupId: null,
rootPath: '/',
+ scopedLabelsAvailable: false,
+ ...provide,
},
});
};
@@ -74,6 +92,7 @@ describe('Board card layout', () => {
describe('mouse events', () => {
it('sets showDetail to true on mousedown', async () => {
+ createStore();
mountComponent();
wrapper.trigger('mousedown');
@@ -83,6 +102,7 @@ describe('Board card layout', () => {
});
it('sets showDetail to false on mousemove', async () => {
+ createStore();
mountComponent();
wrapper.trigger('mousedown');
await wrapper.vm.$nextTick();
@@ -91,5 +111,49 @@ describe('Board card layout', () => {
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_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 5e23c781eae..1084009caad 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -29,7 +29,7 @@ describe('BoardCard', () => {
const findUserAvatarLink = () => wrapper.find(userAvatarLink);
// this particular mount component needs to be used after the root beforeEach because it depends on list being initialized
- const mountComponent = propsData => {
+ const mountComponent = (propsData) => {
wrapper = mount(BoardCard, {
stubs: {
issueCardInner,
@@ -45,6 +45,7 @@ describe('BoardCard', () => {
provide: {
groupId: null,
rootPath: '/',
+ scopedLabelsAvailable: false,
},
});
};
@@ -133,9 +134,7 @@ describe('BoardCard', () => {
it('does not set detail issue if link is clicked', () => {
mountComponent();
- findIssueCardInner()
- .find('a')
- .trigger('mouseup');
+ findIssueCardInner().find('a').trigger('mouseup');
expect(boardsStore.detail.issue).toEqual({});
});
diff --git a/spec/frontend/boards/components/board_column_deprecated_spec.js b/spec/frontend/boards/components/board_column_deprecated_spec.js
new file mode 100644
index 00000000000..a703caca4eb
--- /dev/null
+++ b/spec/frontend/boards/components/board_column_deprecated_spec.js
@@ -0,0 +1,94 @@
+import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+
+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 axios from '~/lib/utils/axios_utils';
+
+describe('Board Column Component', () => {
+ let wrapper;
+ let axiosMock;
+
+ beforeEach(() => {
+ window.gon = {};
+ axiosMock = new AxiosMockAdapter(axios);
+ axiosMock.onGet(`${TEST_HOST}/lists/1/issues`).reply(200, { issues: [] });
+ });
+
+ afterEach(() => {
+ axiosMock.restore();
+
+ wrapper.destroy();
+
+ localStorage.clear();
+ });
+
+ const createComponent = ({
+ listType = ListType.backlog,
+ collapsed = false,
+ withLocalStorage = true,
+ } = {}) => {
+ const boardId = '1';
+
+ const listMock = {
+ ...listObj,
+ list_type: listType,
+ collapsed,
+ };
+
+ if (listType === ListType.assignee) {
+ delete listMock.label;
+ listMock.user = {};
+ }
+
+ // Making List reactive
+ const list = Vue.observable(new List(listMock));
+
+ if (withLocalStorage) {
+ localStorage.setItem(
+ `boards.${boardId}.${list.type}.${list.id}.expanded`,
+ (!collapsed).toString(),
+ );
+ }
+
+ wrapper = shallowMount(Board, {
+ propsData: {
+ boardId,
+ disabled: false,
+ list,
+ },
+ provide: {
+ boardId,
+ },
+ });
+ };
+
+ const isExpandable = () => wrapper.classes('is-expandable');
+ const isCollapsed = () => wrapper.classes('is-collapsed');
+
+ describe('Given different list types', () => {
+ it('is expandable when List Type is `backlog`', () => {
+ createComponent({ listType: ListType.backlog });
+
+ expect(isExpandable()).toBe(true);
+ });
+ });
+
+ describe('expanded / collapsed column', () => {
+ it('has class is-collapsed when list is collapsed', () => {
+ createComponent({ collapsed: false });
+
+ expect(wrapper.vm.list.isExpanded).toBe(true);
+ });
+
+ it('does not have class is-collapsed when list is expanded', () => {
+ createComponent({ collapsed: true });
+
+ expect(isCollapsed()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_column_new_spec.js b/spec/frontend/boards/components/board_column_new_spec.js
deleted file mode 100644
index 81c0e60f931..00000000000
--- a/spec/frontend/boards/components/board_column_new_spec.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import { listObj } from 'jest/boards/mock_data';
-import BoardColumn from '~/boards/components/board_column_new.vue';
-import { ListType } from '~/boards/constants';
-import { createStore } from '~/boards/stores';
-
-describe('Board Column Component', () => {
- let wrapper;
- let store;
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const createComponent = ({ listType = ListType.backlog, collapsed = false } = {}) => {
- const boardId = '1';
-
- const listMock = {
- ...listObj,
- listType,
- collapsed,
- };
-
- if (listType === ListType.assignee) {
- delete listMock.label;
- listMock.assignee = {};
- }
-
- store = createStore();
-
- wrapper = shallowMount(BoardColumn, {
- store,
- propsData: {
- disabled: false,
- list: listMock,
- },
- provide: {
- boardId,
- },
- });
- };
-
- const isExpandable = () => wrapper.classes('is-expandable');
- const isCollapsed = () => wrapper.classes('is-collapsed');
-
- describe('Given different list types', () => {
- it('is expandable when List Type is `backlog`', () => {
- createComponent({ listType: ListType.backlog });
-
- expect(isExpandable()).toBe(true);
- });
- });
-
- describe('expanded / collapsed column', () => {
- it('has class is-collapsed when list is collapsed', () => {
- createComponent({ collapsed: false });
-
- expect(isCollapsed()).toBe(false);
- });
-
- it('does not have class is-collapsed when list is expanded', () => {
- createComponent({ collapsed: true });
-
- expect(isCollapsed()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js
index ba11225676b..1dcdad2b492 100644
--- a/spec/frontend/boards/components/board_column_spec.js
+++ b/spec/frontend/boards/components/board_column_spec.js
@@ -1,65 +1,40 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
-import AxiosMockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'helpers/test_constants';
import { listObj } from 'jest/boards/mock_data';
-import Board from '~/boards/components/board_column.vue';
-import List from '~/boards/models/list';
+import BoardColumn from '~/boards/components/board_column.vue';
import { ListType } from '~/boards/constants';
-import axios from '~/lib/utils/axios_utils';
+import { createStore } from '~/boards/stores';
describe('Board Column Component', () => {
let wrapper;
- let axiosMock;
-
- beforeEach(() => {
- window.gon = {};
- axiosMock = new AxiosMockAdapter(axios);
- axiosMock.onGet(`${TEST_HOST}/lists/1/issues`).reply(200, { issues: [] });
- });
+ let store;
afterEach(() => {
- axiosMock.restore();
-
wrapper.destroy();
-
- localStorage.clear();
+ wrapper = null;
});
- const createComponent = ({
- listType = ListType.backlog,
- collapsed = false,
- withLocalStorage = true,
- } = {}) => {
+ const createComponent = ({ listType = ListType.backlog, collapsed = false } = {}) => {
const boardId = '1';
const listMock = {
...listObj,
- list_type: listType,
+ listType,
collapsed,
};
if (listType === ListType.assignee) {
delete listMock.label;
- listMock.user = {};
+ listMock.assignee = {};
}
- // Making List reactive
- const list = Vue.observable(new List(listMock));
+ store = createStore();
- if (withLocalStorage) {
- localStorage.setItem(
- `boards.${boardId}.${list.type}.${list.id}.expanded`,
- (!collapsed).toString(),
- );
- }
-
- wrapper = shallowMount(Board, {
+ wrapper = shallowMount(BoardColumn, {
+ store,
propsData: {
- boardId,
disabled: false,
- list,
+ list: listMock,
},
provide: {
boardId,
@@ -82,7 +57,7 @@ describe('Board Column Component', () => {
it('has class is-collapsed when list is collapsed', () => {
createComponent({ collapsed: false });
- expect(wrapper.vm.list.isExpanded).toBe(true);
+ expect(isCollapsed()).toBe(false);
});
it('does not have class is-collapsed when list is expanded', () => {
diff --git a/spec/frontend/boards/components/board_configuration_options_spec.js b/spec/frontend/boards/components/board_configuration_options_spec.js
index e9a1cb6a4e8..d9614c254e2 100644
--- a/spec/frontend/boards/components/board_configuration_options_spec.js
+++ b/spec/frontend/boards/components/board_configuration_options_spec.js
@@ -3,38 +3,30 @@ import BoardConfigurationOptions from '~/boards/components/board_configuration_o
describe('BoardConfigurationOptions', () => {
let wrapper;
- const board = { hide_backlog_list: false, hide_closed_list: false };
const defaultProps = {
- currentBoard: board,
- board,
- isNewForm: false,
+ hideBacklogList: false,
+ hideClosedList: false,
};
- const createComponent = () => {
+ const createComponent = (props = {}) => {
wrapper = shallowMount(BoardConfigurationOptions, {
- propsData: { ...defaultProps },
+ propsData: { ...defaultProps, ...props },
});
};
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
});
- const backlogListCheckbox = el => el.find('[data-testid="backlog-list-checkbox"]');
- const closedListCheckbox = el => el.find('[data-testid="closed-list-checkbox"]');
+ const backlogListCheckbox = () => wrapper.find('[data-testid="backlog-list-checkbox"]');
+ const closedListCheckbox = () => wrapper.find('[data-testid="closed-list-checkbox"]');
const checkboxAssert = (backlogCheckbox, closedCheckbox) => {
- expect(backlogListCheckbox(wrapper).attributes('checked')).toEqual(
+ expect(backlogListCheckbox().attributes('checked')).toEqual(
backlogCheckbox ? undefined : 'true',
);
- expect(closedListCheckbox(wrapper).attributes('checked')).toEqual(
- closedCheckbox ? undefined : 'true',
- );
+ expect(closedListCheckbox().attributes('checked')).toEqual(closedCheckbox ? undefined : 'true');
};
it.each`
@@ -45,15 +37,28 @@ describe('BoardConfigurationOptions', () => {
${false} | ${false}
`(
'renders two checkbox when one is $backlogCheckboxValue and other is $closedCheckboxValue',
- async ({ backlogCheckboxValue, closedCheckboxValue }) => {
- await wrapper.setData({
+ ({ backlogCheckboxValue, closedCheckboxValue }) => {
+ createComponent({
hideBacklogList: backlogCheckboxValue,
hideClosedList: closedCheckboxValue,
});
-
- return wrapper.vm.$nextTick().then(() => {
- checkboxAssert(backlogCheckboxValue, closedCheckboxValue);
- });
+ checkboxAssert(backlogCheckboxValue, closedCheckboxValue);
},
);
+
+ it('emits a correct value on backlog checkbox change', () => {
+ createComponent();
+
+ backlogListCheckbox().vm.$emit('change');
+
+ expect(wrapper.emitted('update:hideBacklogList')).toEqual([[true]]);
+ });
+
+ it('emits a correct value on closed checkbox change', () => {
+ createComponent();
+
+ closedListCheckbox().vm.$emit('change');
+
+ expect(wrapper.emitted('update:hideClosedList')).toEqual([[true]]);
+ });
});
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index 291013c561e..98be02d7dbf 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -4,7 +4,7 @@ import { GlAlert } from '@gitlab/ui';
import Draggable from 'vuedraggable';
import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
import getters from 'ee_else_ce/boards/stores/getters';
-import BoardColumn from '~/boards/components/board_column.vue';
+import BoardColumnDeprecated from '~/boards/components/board_column_deprecated.vue';
import { mockLists, mockListsWithModel } from '../mock_data';
import BoardContent from '~/boards/components/board_content.vue';
@@ -17,6 +17,7 @@ const actions = {
describe('BoardContent', () => {
let wrapper;
+ window.gon = {};
const defaultState = {
isShowingEpicsSwimlanes: false,
@@ -56,10 +57,12 @@ describe('BoardContent', () => {
wrapper.destroy();
});
- it('renders a BoardColumn component per list', () => {
+ it('renders a BoardColumnDeprecated component per list', () => {
createComponent();
- expect(wrapper.findAll(BoardColumn)).toHaveLength(mockLists.length);
+ expect(wrapper.findAllComponents(BoardColumnDeprecated)).toHaveLength(
+ mockListsWithModel.length,
+ );
});
it('does not display EpicsSwimlanes component', () => {
@@ -70,6 +73,13 @@ describe('BoardContent', () => {
});
describe('graphqlBoardLists feature flag enabled', () => {
+ beforeEach(() => {
+ createComponent({ graphqlBoardListsEnabled: true });
+ gon.features = {
+ graphqlBoardLists: true,
+ };
+ });
+
describe('can admin list', () => {
beforeEach(() => {
createComponent({ graphqlBoardListsEnabled: true, props: { canAdminList: true } });
@@ -85,7 +95,7 @@ describe('BoardContent', () => {
createComponent({ graphqlBoardListsEnabled: true, props: { canAdminList: false } });
});
- it('renders draggable component', () => {
+ it('does not render draggable component', () => {
expect(wrapper.find(Draggable).exists()).toBe(false);
});
});
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index 3b15cbb6b7e..c34987a55de 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -1,20 +1,22 @@
import { shallowMount } from '@vue/test-utils';
-import AxiosMockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import { GlModal } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
+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 BoardConfigurationOptions from '~/boards/components/board_configuration_options.vue';
-import createBoardMutation from '~/boards/graphql/board.mutation.graphql';
+import updateBoardMutation from '~/boards/graphql/board_update.mutation.graphql';
+import createBoardMutation from '~/boards/graphql/board_create.mutation.graphql';
+import destroyBoardMutation from '~/boards/graphql/board_destroy.mutation.graphql';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'),
+ stripFinalUrlSegment: jest.requireActual('~/lib/utils/url_utility').stripFinalUrlSegment,
}));
+jest.mock('~/flash');
const currentBoard = {
id: 1,
@@ -28,18 +30,6 @@ const currentBoard = {
hide_closed_list: false,
};
-const boardDefaults = {
- id: false,
- name: '',
- labels: [],
- milestone_id: undefined,
- assignee: {},
- assignee_id: undefined,
- weight: null,
- hide_backlog_list: false,
- hide_closed_list: false,
-};
-
const defaultProps = {
canAdminBoard: false,
labelsPath: `${TEST_HOST}/labels/path`,
@@ -47,22 +37,15 @@ const defaultProps = {
currentBoard,
};
-const endpoints = {
- boardsEndpoint: 'test-endpoint',
-};
-
-const mutate = jest.fn().mockResolvedValue({});
-
describe('BoardForm', () => {
let wrapper;
- let axiosMock;
+ let mutate;
const findModal = () => wrapper.find(GlModal);
const findModalActionPrimary = () => findModal().props('actionPrimary');
const findForm = () => wrapper.find('[data-testid="board-form"]');
const findFormWrapper = () => wrapper.find('[data-testid="board-form-wrapper"]');
const findDeleteConfirmation = () => wrapper.find('[data-testid="delete-confirmation-message"]');
- const findConfigurationOptions = () => wrapper.find(BoardConfigurationOptions);
const findInput = () => wrapper.find('#board-new-name');
const createComponent = (props, data) => {
@@ -74,26 +57,26 @@ describe('BoardForm', () => {
};
},
provide: {
- endpoints,
+ rootPath: 'root',
},
mocks: {
$apollo: {
mutate,
},
},
- attachToDocument: true,
+ attachTo: document.body,
});
};
beforeEach(() => {
- axiosMock = new AxiosMockAdapter(axios);
+ delete window.location;
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
- axiosMock.restore();
boardsStore.state.currentPage = null;
+ mutate = null;
});
describe('when user can not admin the board', () => {
@@ -145,7 +128,7 @@ describe('BoardForm', () => {
});
it('clears the form', () => {
- expect(findConfigurationOptions().props('board')).toEqual(boardDefaults);
+ expect(findInput().element.value).toBe('');
});
it('shows a correct title about creating a board', () => {
@@ -164,16 +147,21 @@ describe('BoardForm', () => {
it('renders form wrapper', () => {
expect(findFormWrapper().exists()).toBe(true);
});
-
- it('passes a true isNewForm prop to BoardConfigurationOptions component', () => {
- expect(findConfigurationOptions().props('isNewForm')).toBe(true);
- });
});
describe('when submitting a create event', () => {
+ const fillForm = () => {
+ findInput().value = 'Test name';
+ findInput().trigger('input');
+ findInput().trigger('keyup.enter', { metaKey: true });
+ };
+
beforeEach(() => {
- const url = `${endpoints.boardsEndpoint}.json`;
- axiosMock.onPost(url).reply(200, { id: '2', board_path: 'new path' });
+ mutate = jest.fn().mockResolvedValue({
+ data: {
+ createBoard: { board: { id: 'gid://gitlab/Board/123', webPath: 'test-path' } },
+ },
+ });
});
it('does not call API if board name is empty', async () => {
@@ -185,28 +173,37 @@ describe('BoardForm', () => {
expect(mutate).not.toHaveBeenCalled();
});
- it('calls REST and GraphQL API and redirects to correct page', async () => {
+ it('calls a correct GraphQL mutation and redirects to correct page from existing board', async () => {
createComponent({ canAdminBoard: true });
-
- findInput().value = 'Test name';
- findInput().trigger('input');
- findInput().trigger('keyup.enter', { metaKey: true });
+ fillForm();
await waitForPromises();
- expect(axiosMock.history.post[0].data).toBe(
- JSON.stringify({ board: { ...boardDefaults, name: 'test', label_ids: [''] } }),
- );
-
expect(mutate).toHaveBeenCalledWith({
mutation: createBoardMutation,
variables: {
- id: 'gid://gitlab/Board/2',
+ input: expect.objectContaining({
+ name: 'test',
+ }),
},
});
await waitForPromises();
- expect(visitUrl).toHaveBeenCalledWith('new path');
+ expect(visitUrl).toHaveBeenCalledWith('test-path');
+ });
+
+ it('shows an error flash if GraphQL mutation fails', async () => {
+ mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
+ createComponent({ canAdminBoard: true });
+ fillForm();
+
+ await waitForPromises();
+
+ expect(mutate).toHaveBeenCalled();
+
+ await waitForPromises();
+ expect(visitUrl).not.toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalled();
});
});
});
@@ -222,7 +219,7 @@ describe('BoardForm', () => {
});
it('clears the form', () => {
- expect(findConfigurationOptions().props('board')).toEqual(currentBoard);
+ expect(findInput().element.value).toEqual(currentBoard.name);
});
it('shows a correct title about creating a board', () => {
@@ -241,36 +238,121 @@ describe('BoardForm', () => {
it('renders form wrapper', () => {
expect(findFormWrapper().exists()).toBe(true);
});
+ });
- it('passes a false isNewForm prop to BoardConfigurationOptions component', () => {
- expect(findConfigurationOptions().props('isNewForm')).toBe(false);
+ it('calls GraphQL mutation with correct parameters when issues are not grouped', async () => {
+ mutate = jest.fn().mockResolvedValue({
+ data: {
+ updateBoard: { board: { id: 'gid://gitlab/Board/321', webPath: 'test-path' } },
+ },
});
- });
+ window.location = new URL('https://test/boards/1');
+ createComponent({ canAdminBoard: true });
- describe('when submitting an update event', () => {
- beforeEach(() => {
- const url = endpoints.boardsEndpoint;
- axiosMock.onPut(url).reply(200, { board_path: 'new path' });
+ findInput().trigger('keyup.enter', { metaKey: true });
+
+ await waitForPromises();
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: updateBoardMutation,
+ variables: {
+ input: expect.objectContaining({
+ id: `gid://gitlab/Board/${currentBoard.id}`,
+ }),
+ },
});
- it('calls REST and GraphQL API with correct parameters', async () => {
- createComponent({ canAdminBoard: true });
+ await waitForPromises();
+ expect(visitUrl).toHaveBeenCalledWith('test-path');
+ });
- findInput().trigger('keyup.enter', { metaKey: true });
+ it('calls GraphQL mutation with correct parameters when issues are grouped by epic', async () => {
+ mutate = jest.fn().mockResolvedValue({
+ data: {
+ updateBoard: { board: { id: 'gid://gitlab/Board/321', webPath: 'test-path' } },
+ },
+ });
+ window.location = new URL('https://test/boards/1?group_by=epic');
+ createComponent({ canAdminBoard: true });
- await waitForPromises();
+ findInput().trigger('keyup.enter', { metaKey: true });
- expect(axiosMock.history.put[0].data).toBe(
- JSON.stringify({ board: { ...currentBoard, label_ids: [''] } }),
- );
+ await waitForPromises();
- expect(mutate).toHaveBeenCalledWith({
- mutation: createBoardMutation,
- variables: {
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: updateBoardMutation,
+ variables: {
+ input: expect.objectContaining({
id: `gid://gitlab/Board/${currentBoard.id}`,
- },
- });
+ }),
+ },
});
+
+ await waitForPromises();
+ expect(visitUrl).toHaveBeenCalledWith('test-path?group_by=epic');
+ });
+
+ it('shows an error flash if GraphQL mutation fails', async () => {
+ mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
+ createComponent({ canAdminBoard: true });
+ findInput().trigger('keyup.enter', { metaKey: true });
+
+ await waitForPromises();
+
+ expect(mutate).toHaveBeenCalled();
+
+ await waitForPromises();
+ expect(visitUrl).not.toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalled();
+ });
+ });
+
+ describe('when deleting a board', () => {
+ beforeEach(() => {
+ boardsStore.state.currentPage = 'delete';
+ });
+
+ it('passes correct primary action text and variant', () => {
+ createComponent({ canAdminBoard: true });
+ expect(findModalActionPrimary().text).toBe('Delete');
+ expect(findModalActionPrimary().attributes[0].variant).toBe('danger');
+ });
+
+ it('renders delete confirmation message', () => {
+ createComponent({ canAdminBoard: true });
+ 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 });
+ findModal().vm.$emit('primary');
+
+ await waitForPromises();
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: destroyBoardMutation,
+ variables: {
+ id: 'gid://gitlab/Board/1',
+ },
+ });
+
+ await waitForPromises();
+ expect(visitUrl).toHaveBeenCalledWith('root');
+ });
+
+ it('shows an error flash if GraphQL mutation fails', async () => {
+ mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
+ createComponent({ canAdminBoard: true });
+ findModal().vm.$emit('primary');
+
+ await waitForPromises();
+
+ expect(mutate).toHaveBeenCalled();
+
+ await waitForPromises();
+ expect(visitUrl).not.toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/boards/components/board_list_header_deprecated_spec.js b/spec/frontend/boards/components/board_list_header_deprecated_spec.js
new file mode 100644
index 00000000000..6207724e6a9
--- /dev/null
+++ b/spec/frontend/boards/components/board_list_header_deprecated_spec.js
@@ -0,0 +1,165 @@
+import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+
+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 axios from '~/lib/utils/axios_utils';
+
+describe('Board List Header Component', () => {
+ let wrapper;
+ let axiosMock;
+
+ beforeEach(() => {
+ window.gon = {};
+ axiosMock = new AxiosMockAdapter(axios);
+ axiosMock.onGet(`${TEST_HOST}/lists/1/issues`).reply(200, { issues: [] });
+ });
+
+ afterEach(() => {
+ axiosMock.restore();
+
+ wrapper.destroy();
+
+ localStorage.clear();
+ });
+
+ const createComponent = ({
+ listType = ListType.backlog,
+ collapsed = false,
+ withLocalStorage = true,
+ } = {}) => {
+ const boardId = '1';
+
+ const listMock = {
+ ...listObj,
+ list_type: listType,
+ collapsed,
+ };
+
+ if (listType === ListType.assignee) {
+ delete listMock.label;
+ listMock.user = {};
+ }
+
+ // Making List reactive
+ const list = Vue.observable(new List(listMock));
+
+ if (withLocalStorage) {
+ localStorage.setItem(
+ `boards.${boardId}.${list.type}.${list.id}.expanded`,
+ (!collapsed).toString(),
+ );
+ }
+
+ wrapper = shallowMount(BoardListHeader, {
+ propsData: {
+ disabled: false,
+ list,
+ },
+ provide: {
+ boardId,
+ },
+ });
+ };
+
+ const isCollapsed = () => !wrapper.props().list.isExpanded;
+ const isExpanded = () => wrapper.vm.list.isExpanded;
+
+ const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' });
+ const findCaret = () => wrapper.find('.board-title-caret');
+
+ describe('Add issue button', () => {
+ const hasNoAddButton = [ListType.closed];
+ const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee];
+
+ it.each(hasNoAddButton)('does not render when List Type is `%s`', (listType) => {
+ createComponent({ listType });
+
+ expect(findAddIssueButton().exists()).toBe(false);
+ });
+
+ it.each(hasAddButton)('does render when List Type is `%s`', (listType) => {
+ createComponent({ listType });
+
+ expect(findAddIssueButton().exists()).toBe(true);
+ });
+
+ it('has a test for each list type', () => {
+ Object.values(ListType).forEach((value) => {
+ expect([...hasAddButton, ...hasNoAddButton]).toContain(value);
+ });
+ });
+
+ it('does render when logged out', () => {
+ createComponent();
+
+ expect(findAddIssueButton().exists()).toBe(true);
+ });
+ });
+
+ describe('expanding / collapsing the column', () => {
+ it('does not collapse when clicking the header', () => {
+ createComponent();
+
+ expect(isCollapsed()).toBe(false);
+ wrapper.find('[data-testid="board-list-header"]').trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(isCollapsed()).toBe(false);
+ });
+ });
+
+ it('collapses expanded Column when clicking the collapse icon', () => {
+ createComponent();
+
+ expect(isExpanded()).toBe(true);
+ findCaret().vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(isCollapsed()).toBe(true);
+ });
+ });
+
+ it('expands collapsed Column when clicking the expand icon', () => {
+ createComponent({ collapsed: true });
+
+ expect(isCollapsed()).toBe(true);
+ findCaret().vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(isCollapsed()).toBe(false);
+ });
+ });
+
+ it("when logged in it calls list update and doesn't set localStorage", () => {
+ jest.spyOn(List.prototype, 'update');
+ window.gon.current_user_id = 1;
+
+ createComponent({ withLocalStorage: false });
+
+ findCaret().vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.list.update).toHaveBeenCalledTimes(1);
+ expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null);
+ });
+ });
+
+ it("when logged out it doesn't call list update and sets localStorage", () => {
+ jest.spyOn(List.prototype, 'update');
+
+ createComponent();
+
+ findCaret().vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.list.update).not.toHaveBeenCalled();
+ expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded()));
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_list_header_new_spec.js b/spec/frontend/boards/components/board_list_header_new_spec.js
deleted file mode 100644
index 7428dfae83f..00000000000
--- a/spec/frontend/boards/components/board_list_header_new_spec.js
+++ /dev/null
@@ -1,187 +0,0 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-
-import { mockLabelList } from 'jest/boards/mock_data';
-import BoardListHeader from '~/boards/components/board_list_header_new.vue';
-import { ListType } from '~/boards/constants';
-
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
-
-describe('Board List Header Component', () => {
- let wrapper;
- let store;
-
- const updateListSpy = jest.fn();
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
-
- localStorage.clear();
- });
-
- const createComponent = ({
- listType = ListType.backlog,
- collapsed = false,
- withLocalStorage = true,
- currentUserId = null,
- } = {}) => {
- const boardId = '1';
-
- const listMock = {
- ...mockLabelList,
- listType,
- collapsed,
- };
-
- if (listType === ListType.assignee) {
- delete listMock.label;
- listMock.assignee = {};
- }
-
- if (withLocalStorage) {
- localStorage.setItem(
- `boards.${boardId}.${listMock.listType}.${listMock.id}.expanded`,
- (!collapsed).toString(),
- );
- }
-
- store = new Vuex.Store({
- state: {},
- actions: { updateList: updateListSpy },
- getters: {},
- });
-
- wrapper = shallowMount(BoardListHeader, {
- store,
- localVue,
- propsData: {
- disabled: false,
- list: listMock,
- },
- provide: {
- boardId,
- weightFeatureAvailable: false,
- currentUserId,
- },
- });
- };
-
- const isCollapsed = () => wrapper.vm.list.collapsed;
- const isExpanded = () => !isCollapsed;
-
- const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' });
- const findTitle = () => wrapper.find('.board-title');
- const findCaret = () => wrapper.find('.board-title-caret');
-
- describe('Add issue button', () => {
- const hasNoAddButton = [ListType.closed];
- const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee];
-
- it.each(hasNoAddButton)('does not render when List Type is `%s`', listType => {
- createComponent({ listType });
-
- expect(findAddIssueButton().exists()).toBe(false);
- });
-
- it.each(hasAddButton)('does render when List Type is `%s`', listType => {
- createComponent({ listType });
-
- expect(findAddIssueButton().exists()).toBe(true);
- });
-
- it('has a test for each list type', () => {
- createComponent();
-
- Object.values(ListType).forEach(value => {
- expect([...hasAddButton, ...hasNoAddButton]).toContain(value);
- });
- });
-
- it('does render when logged out', () => {
- createComponent();
-
- expect(findAddIssueButton().exists()).toBe(true);
- });
- });
-
- describe('expanding / collapsing the column', () => {
- it('does not collapse when clicking the header', async () => {
- createComponent();
-
- expect(isCollapsed()).toBe(false);
-
- wrapper.find('[data-testid="board-list-header"]').trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(isCollapsed()).toBe(false);
- });
-
- it('collapses expanded Column when clicking the collapse icon', async () => {
- createComponent();
-
- expect(isCollapsed()).toBe(false);
-
- findCaret().vm.$emit('click');
-
- await wrapper.vm.$nextTick();
-
- expect(isCollapsed()).toBe(true);
- });
-
- it('expands collapsed Column when clicking the expand icon', async () => {
- createComponent({ collapsed: true });
-
- expect(isCollapsed()).toBe(true);
-
- findCaret().vm.$emit('click');
-
- await wrapper.vm.$nextTick();
-
- expect(isCollapsed()).toBe(false);
- });
-
- it("when logged in it calls list update and doesn't set localStorage", async () => {
- createComponent({ withLocalStorage: false, currentUserId: 1 });
-
- findCaret().vm.$emit('click');
- await wrapper.vm.$nextTick();
-
- expect(updateListSpy).toHaveBeenCalledTimes(1);
- expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null);
- });
-
- it("when logged out it doesn't call list update and sets localStorage", async () => {
- createComponent();
-
- findCaret().vm.$emit('click');
- await wrapper.vm.$nextTick();
-
- expect(updateListSpy).not.toHaveBeenCalled();
- expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded()));
- });
- });
-
- describe('user can drag', () => {
- const cannotDragList = [ListType.backlog, ListType.closed];
- const canDragList = [ListType.label, ListType.milestone, ListType.assignee];
-
- it.each(cannotDragList)(
- 'does not have user-can-drag-class so user cannot drag list',
- listType => {
- createComponent({ listType });
-
- expect(findTitle().classes()).not.toContain('user-can-drag');
- },
- );
-
- it.each(canDragList)('has user-can-drag-class so user can drag list', listType => {
- createComponent({ listType });
-
- expect(findTitle().classes()).toContain('user-can-drag');
- });
- });
-});
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 656a503bb86..357d05ced02 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -1,28 +1,23 @@
-import Vue from 'vue';
-import { shallowMount } from '@vue/test-utils';
-import AxiosMockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { TEST_HOST } from 'helpers/test_constants';
-import { listObj } from 'jest/boards/mock_data';
+import { mockLabelList } from 'jest/boards/mock_data';
import BoardListHeader from '~/boards/components/board_list_header.vue';
-import List from '~/boards/models/list';
import { ListType } from '~/boards/constants';
-import axios from '~/lib/utils/axios_utils';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
describe('Board List Header Component', () => {
let wrapper;
- let axiosMock;
+ let store;
- beforeEach(() => {
- window.gon = {};
- axiosMock = new AxiosMockAdapter(axios);
- axiosMock.onGet(`${TEST_HOST}/lists/1/issues`).reply(200, { issues: [] });
- });
+ const updateListSpy = jest.fn();
afterEach(() => {
- axiosMock.restore();
-
wrapper.destroy();
+ wrapper = null;
localStorage.clear();
});
@@ -31,65 +26,76 @@ describe('Board List Header Component', () => {
listType = ListType.backlog,
collapsed = false,
withLocalStorage = true,
+ currentUserId = null,
} = {}) => {
const boardId = '1';
const listMock = {
- ...listObj,
- list_type: listType,
+ ...mockLabelList,
+ listType,
collapsed,
};
if (listType === ListType.assignee) {
delete listMock.label;
- listMock.user = {};
+ listMock.assignee = {};
}
- // Making List reactive
- const list = Vue.observable(new List(listMock));
-
if (withLocalStorage) {
localStorage.setItem(
- `boards.${boardId}.${list.type}.${list.id}.expanded`,
+ `boards.${boardId}.${listMock.listType}.${listMock.id}.expanded`,
(!collapsed).toString(),
);
}
+ store = new Vuex.Store({
+ state: {},
+ actions: { updateList: updateListSpy },
+ getters: {},
+ });
+
wrapper = shallowMount(BoardListHeader, {
+ store,
+ localVue,
propsData: {
disabled: false,
- list,
+ list: listMock,
},
provide: {
boardId,
+ weightFeatureAvailable: false,
+ currentUserId,
},
});
};
- const isCollapsed = () => !wrapper.props().list.isExpanded;
- const isExpanded = () => wrapper.vm.list.isExpanded;
+ const isCollapsed = () => wrapper.vm.list.collapsed;
+ const isExpanded = () => !isCollapsed;
const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' });
+ const findTitle = () => wrapper.find('.board-title');
const findCaret = () => wrapper.find('.board-title-caret');
describe('Add issue button', () => {
const hasNoAddButton = [ListType.closed];
const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee];
- it.each(hasNoAddButton)('does not render when List Type is `%s`', listType => {
+ it.each(hasNoAddButton)('does not render when List Type is `%s`', (listType) => {
createComponent({ listType });
expect(findAddIssueButton().exists()).toBe(false);
});
- it.each(hasAddButton)('does render when List Type is `%s`', listType => {
+ it.each(hasAddButton)('does render when List Type is `%s`', (listType) => {
createComponent({ listType });
expect(findAddIssueButton().exists()).toBe(true);
});
it('has a test for each list type', () => {
- Object.values(ListType).forEach(value => {
+ createComponent();
+
+ Object.values(ListType).forEach((value) => {
expect([...hasAddButton, ...hasNoAddButton]).toContain(value);
});
});
@@ -102,64 +108,80 @@ describe('Board List Header Component', () => {
});
describe('expanding / collapsing the column', () => {
- it('does not collapse when clicking the header', () => {
+ it('does not collapse when clicking the header', async () => {
createComponent();
expect(isCollapsed()).toBe(false);
+
wrapper.find('[data-testid="board-list-header"]').trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(isCollapsed()).toBe(false);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(isCollapsed()).toBe(false);
});
- it('collapses expanded Column when clicking the collapse icon', () => {
+ it('collapses expanded Column when clicking the collapse icon', async () => {
createComponent();
- expect(isExpanded()).toBe(true);
+ expect(isCollapsed()).toBe(false);
+
findCaret().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(isCollapsed()).toBe(true);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(isCollapsed()).toBe(true);
});
- it('expands collapsed Column when clicking the expand icon', () => {
+ it('expands collapsed Column when clicking the expand icon', async () => {
createComponent({ collapsed: true });
expect(isCollapsed()).toBe(true);
+
findCaret().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(isCollapsed()).toBe(false);
- });
- });
+ await wrapper.vm.$nextTick();
- it("when logged in it calls list update and doesn't set localStorage", () => {
- jest.spyOn(List.prototype, 'update');
- window.gon.current_user_id = 1;
+ expect(isCollapsed()).toBe(false);
+ });
- createComponent({ withLocalStorage: false });
+ it("when logged in it calls list update and doesn't set localStorage", async () => {
+ createComponent({ withLocalStorage: false, currentUserId: 1 });
findCaret().vm.$emit('click');
+ await wrapper.vm.$nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.list.update).toHaveBeenCalledTimes(1);
- expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null);
- });
+ expect(updateListSpy).toHaveBeenCalledTimes(1);
+ expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null);
});
- it("when logged out it doesn't call list update and sets localStorage", () => {
- jest.spyOn(List.prototype, 'update');
-
+ it("when logged out it doesn't call list update and sets localStorage", async () => {
createComponent();
findCaret().vm.$emit('click');
+ await wrapper.vm.$nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.list.update).not.toHaveBeenCalled();
- expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded()));
- });
+ expect(updateListSpy).not.toHaveBeenCalled();
+ expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded()));
+ });
+ });
+
+ describe('user can drag', () => {
+ const cannotDragList = [ListType.backlog, ListType.closed];
+ const canDragList = [ListType.label, ListType.milestone, ListType.assignee];
+
+ it.each(cannotDragList)(
+ 'does not have user-can-drag-class so user cannot drag list',
+ (listType) => {
+ createComponent({ listType });
+
+ expect(findTitle().classes()).not.toContain('user-can-drag');
+ },
+ );
+
+ it.each(canDragList)('has user-can-drag-class so user can drag list', (listType) => {
+ createComponent({ listType });
+
+ expect(findTitle().classes()).toContain('user-can-drag');
});
});
});
diff --git a/spec/frontend/boards/components/board_new_issue_new_spec.js b/spec/frontend/boards/components/board_new_issue_new_spec.js
deleted file mode 100644
index ee1c4f31cf0..00000000000
--- a/spec/frontend/boards/components/board_new_issue_new_spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import BoardNewIssue from '~/boards/components/board_new_issue_new.vue';
-
-import '~/boards/models/list';
-import { mockList } from '../mock_data';
-
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
-
-describe('Issue boards new issue form', () => {
- let wrapper;
- let vm;
-
- const addListNewIssuesSpy = jest.fn();
-
- const findSubmitButton = () => wrapper.find({ ref: 'submitButton' });
- const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
- const findSubmitForm = () => wrapper.find({ ref: 'submitForm' });
-
- const submitIssue = () => {
- const dummySubmitEvent = {
- preventDefault() {},
- };
-
- return findSubmitForm().trigger('submit', dummySubmitEvent);
- };
-
- beforeEach(() => {
- const store = new Vuex.Store({
- state: {},
- actions: { addListNewIssue: addListNewIssuesSpy },
- getters: {},
- });
-
- wrapper = shallowMount(BoardNewIssue, {
- propsData: {
- disabled: false,
- list: mockList,
- },
- store,
- localVue,
- provide: {
- groupId: null,
- weightFeatureAvailable: false,
- boardWeight: null,
- },
- });
-
- vm = wrapper.vm;
-
- return vm.$nextTick();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('calls submit if submit button is clicked', async () => {
- jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'Testing Title' });
-
- await vm.$nextTick();
- await submitIssue();
- expect(wrapper.vm.submit).toHaveBeenCalled();
- });
-
- it('disables submit button if title is empty', () => {
- expect(findSubmitButton().props().disabled).toBe(true);
- });
-
- it('enables submit button if title is not empty', async () => {
- wrapper.setData({ title: 'Testing Title' });
-
- await vm.$nextTick();
- expect(wrapper.find({ ref: 'input' }).element.value).toBe('Testing Title');
- expect(findSubmitButton().props().disabled).toBe(false);
- });
-
- it('clears title after clicking cancel', async () => {
- findCancelButton().trigger('click');
-
- await vm.$nextTick();
- expect(vm.title).toBe('');
- });
-
- describe('submit success', () => {
- it('creates new issue', async () => {
- wrapper.setData({ title: 'submit issue' });
-
- await vm.$nextTick();
- await submitIssue();
- expect(addListNewIssuesSpy).toHaveBeenCalled();
- });
-
- it('enables button after submit', async () => {
- jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'submit issue' });
-
- await vm.$nextTick();
- await submitIssue();
- expect(findSubmitButton().props().disabled).toBe(false);
- });
-
- it('clears title after submit', async () => {
- wrapper.setData({ title: 'submit issue' });
-
- await vm.$nextTick();
- await submitIssue();
- await vm.$nextTick();
- expect(vm.title).toBe('');
- });
- });
-});
diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js
new file mode 100644
index 00000000000..5a01221a5be
--- /dev/null
+++ b/spec/frontend/boards/components/board_new_issue_spec.js
@@ -0,0 +1,115 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import BoardNewIssue from '~/boards/components/board_new_issue.vue';
+
+import '~/boards/models/list';
+import { mockList, mockGroupProjects } from '../mock_data';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
+
+describe('Issue boards new issue form', () => {
+ let wrapper;
+ let vm;
+
+ const addListNewIssuesSpy = jest.fn();
+
+ const findSubmitButton = () => wrapper.find({ ref: 'submitButton' });
+ const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
+ const findSubmitForm = () => wrapper.find({ ref: 'submitForm' });
+
+ const submitIssue = () => {
+ const dummySubmitEvent = {
+ preventDefault() {},
+ };
+
+ return findSubmitForm().trigger('submit', dummySubmitEvent);
+ };
+
+ beforeEach(() => {
+ const store = new Vuex.Store({
+ state: { selectedProject: mockGroupProjects[0] },
+ actions: { addListNewIssue: addListNewIssuesSpy },
+ getters: {},
+ });
+
+ wrapper = shallowMount(BoardNewIssue, {
+ propsData: {
+ disabled: false,
+ list: mockList,
+ },
+ store,
+ localVue,
+ provide: {
+ groupId: null,
+ weightFeatureAvailable: false,
+ boardWeight: null,
+ },
+ });
+
+ vm = wrapper.vm;
+
+ return vm.$nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('calls submit if submit button is clicked', async () => {
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'Testing Title' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ expect(wrapper.vm.submit).toHaveBeenCalled();
+ });
+
+ it('disables submit button if title is empty', () => {
+ expect(findSubmitButton().props().disabled).toBe(true);
+ });
+
+ it('enables submit button if title is not empty', async () => {
+ wrapper.setData({ title: 'Testing Title' });
+
+ await vm.$nextTick();
+ expect(wrapper.find({ ref: 'input' }).element.value).toBe('Testing Title');
+ expect(findSubmitButton().props().disabled).toBe(false);
+ });
+
+ it('clears title after clicking cancel', async () => {
+ findCancelButton().trigger('click');
+
+ await vm.$nextTick();
+ expect(vm.title).toBe('');
+ });
+
+ describe('submit success', () => {
+ it('creates new issue', async () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ expect(addListNewIssuesSpy).toHaveBeenCalled();
+ });
+
+ it('enables button after submit', async () => {
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'submit issue' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ expect(findSubmitButton().props().disabled).toBe(false);
+ });
+
+ it('clears title after submit', async () => {
+ wrapper.setData({ title: 'submit issue' });
+
+ await vm.$nextTick();
+ await submitIssue();
+ await vm.$nextTick();
+ expect(vm.title).toBe('');
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js
index db3c8c22950..81575bf486a 100644
--- a/spec/frontend/boards/components/boards_selector_spec.js
+++ b/spec/frontend/boards/components/boards_selector_spec.js
@@ -26,7 +26,7 @@ describe('BoardsSelector', () => {
const boards = boardGenerator(20);
const recentBoards = boardGenerator(5);
- const fillSearchBox = filterTerm => {
+ const fillSearchBox = (filterTerm) => {
const searchBox = wrapper.find({ ref: 'searchBox' });
const searchBoxInput = searchBox.find('input');
searchBoxInput.setValue(filterTerm);
@@ -59,7 +59,7 @@ describe('BoardsSelector', () => {
data: {
group: {
boards: {
- edges: boards.map(board => ({ node: board })),
+ edges: boards.map((board) => ({ node: board })),
},
},
},
@@ -94,7 +94,7 @@ describe('BoardsSelector', () => {
weights: [],
},
mocks: { $apollo },
- attachToDocument: true,
+ attachTo: document.body,
});
wrapper.vm.$apollo.addSmartQuery = jest.fn((_, options) => {
@@ -152,7 +152,7 @@ describe('BoardsSelector', () => {
it('shows only matching boards when filtering', () => {
const filterTerm = 'board1';
- const expectedCount = boards.filter(board => board.name.includes(filterTerm)).length;
+ const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
fillSearchBox(filterTerm);
diff --git a/spec/frontend/boards/components/issue_count_spec.js b/spec/frontend/boards/components/issue_count_spec.js
index d1ff0bdbf88..f1870e9cc9e 100644
--- a/spec/frontend/boards/components/issue_count_spec.js
+++ b/spec/frontend/boards/components/issue_count_spec.js
@@ -6,7 +6,7 @@ describe('IssueCount', () => {
let maxIssueCount;
let issuesSize;
- const createComponent = props => {
+ const createComponent = (props) => {
vm = shallowMount(IssueCount, { propsData: props });
};
diff --git a/spec/frontend/boards/components/issue_due_date_spec.js b/spec/frontend/boards/components/issue_due_date_spec.js
index 880859287e1..73340c1b96b 100644
--- a/spec/frontend/boards/components/issue_due_date_spec.js
+++ b/spec/frontend/boards/components/issue_due_date_spec.js
@@ -10,7 +10,7 @@ const createComponent = (dueDate = new Date(), closed = false) =>
},
});
-const findTime = wrapper => wrapper.find('time');
+const findTime = (wrapper) => wrapper.find('time');
describe('Issue Due Date component', () => {
let wrapper;
diff --git a/spec/frontend/boards/components/issue_time_estimate_deprecated_spec.js b/spec/frontend/boards/components/issue_time_estimate_deprecated_spec.js
new file mode 100644
index 00000000000..fafebaf3a4e
--- /dev/null
+++ b/spec/frontend/boards/components/issue_time_estimate_deprecated_spec.js
@@ -0,0 +1,64 @@
+import { shallowMount } from '@vue/test-utils';
+import IssueTimeEstimate from '~/boards/components/issue_time_estimate_deprecated.vue';
+import boardsStore from '~/boards/stores/boards_store';
+
+describe('Issue Time Estimate component', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ boardsStore.create();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when limitToHours is false', () => {
+ beforeEach(() => {
+ boardsStore.timeTracking.limitToHours = false;
+ wrapper = shallowMount(IssueTimeEstimate, {
+ propsData: {
+ estimate: 374460,
+ },
+ });
+ });
+
+ it('renders the correct time estimate', () => {
+ expect(wrapper.find('time').text().trim()).toEqual('2w 3d 1m');
+ });
+
+ it('renders expanded time estimate in tooltip', () => {
+ expect(wrapper.find('.js-issue-time-estimate').text()).toContain('2 weeks 3 days 1 minute');
+ });
+
+ it('prevents tooltip xss', (done) => {
+ const alertSpy = jest.spyOn(window, 'alert');
+ wrapper.setProps({ estimate: 'Foo <script>alert("XSS")</script>' });
+ wrapper.vm.$nextTick(() => {
+ expect(alertSpy).not.toHaveBeenCalled();
+ expect(wrapper.find('time').text().trim()).toEqual('0m');
+ expect(wrapper.find('.js-issue-time-estimate').text()).toContain('0m');
+ done();
+ });
+ });
+ });
+
+ describe('when limitToHours is true', () => {
+ beforeEach(() => {
+ boardsStore.timeTracking.limitToHours = true;
+ wrapper = shallowMount(IssueTimeEstimate, {
+ propsData: {
+ estimate: 374460,
+ },
+ });
+ });
+
+ it('renders the correct time estimate', () => {
+ expect(wrapper.find('time').text().trim()).toEqual('104h 1m');
+ });
+
+ it('renders expanded time estimate in tooltip', () => {
+ expect(wrapper.find('.js-issue-time-estimate').text()).toContain('104 hours 1 minute');
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/issue_time_estimate_spec.js b/spec/frontend/boards/components/issue_time_estimate_spec.js
index 162a6df828b..9ac8fae3fcc 100644
--- a/spec/frontend/boards/components/issue_time_estimate_spec.js
+++ b/spec/frontend/boards/components/issue_time_estimate_spec.js
@@ -1,75 +1,65 @@
+import { config as vueConfig } from 'vue';
import { shallowMount } from '@vue/test-utils';
import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue';
-import boardsStore from '~/boards/stores/boards_store';
describe('Issue Time Estimate component', () => {
let wrapper;
- beforeEach(() => {
- boardsStore.create();
- });
-
afterEach(() => {
wrapper.destroy();
});
describe('when limitToHours is false', () => {
beforeEach(() => {
- boardsStore.timeTracking.limitToHours = false;
wrapper = shallowMount(IssueTimeEstimate, {
propsData: {
estimate: 374460,
},
+ provide: {
+ timeTrackingLimitToHours: false,
+ },
});
});
it('renders the correct time estimate', () => {
- expect(
- wrapper
- .find('time')
- .text()
- .trim(),
- ).toEqual('2w 3d 1m');
+ expect(wrapper.find('time').text().trim()).toEqual('2w 3d 1m');
});
it('renders expanded time estimate in tooltip', () => {
expect(wrapper.find('.js-issue-time-estimate').text()).toContain('2 weeks 3 days 1 minute');
});
- it('prevents tooltip xss', done => {
+ it('prevents tooltip xss', async () => {
const alertSpy = jest.spyOn(window, 'alert');
- wrapper.setProps({ estimate: 'Foo <script>alert("XSS")</script>' });
- wrapper.vm.$nextTick(() => {
- expect(alertSpy).not.toHaveBeenCalled();
- expect(
- wrapper
- .find('time')
- .text()
- .trim(),
- ).toEqual('0m');
- expect(wrapper.find('.js-issue-time-estimate').text()).toContain('0m');
- done();
- });
+
+ try {
+ // This will raise props validating warning by Vue, silencing it
+ vueConfig.silent = true;
+ await wrapper.setProps({ estimate: 'Foo <script>alert("XSS")</script>' });
+ } finally {
+ vueConfig.silent = false;
+ }
+
+ expect(alertSpy).not.toHaveBeenCalled();
+ expect(wrapper.find('time').text().trim()).toEqual('0m');
+ expect(wrapper.find('.js-issue-time-estimate').text()).toContain('0m');
});
});
describe('when limitToHours is true', () => {
beforeEach(() => {
- boardsStore.timeTracking.limitToHours = true;
wrapper = shallowMount(IssueTimeEstimate, {
propsData: {
estimate: 374460,
},
+ provide: {
+ timeTrackingLimitToHours: true,
+ },
});
});
it('renders the correct time estimate', () => {
- expect(
- wrapper
- .find('time')
- .text()
- .trim(),
- ).toEqual('104h 1m');
+ expect(wrapper.find('time').text().trim()).toEqual('104h 1m');
});
it('renders expanded time estimate in tooltip', () => {
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 d7df2ff1563..de414bb929e 100644
--- a/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
@@ -33,6 +33,14 @@ describe('boards sidebar remove issue', () => {
expect(findTitle().text()).toBe(title);
});
+ it('renders provided title slot', () => {
+ const title = 'Sidebar item title on slot';
+ const slots = { title: `<strong>${title}</strong>` };
+ createComponent({ slots });
+
+ expect(wrapper.text()).toContain(title);
+ });
+
it('hides edit button, loader and expanded content by default', () => {
createComponent();
@@ -74,9 +82,19 @@ describe('boards sidebar remove issue', () => {
return wrapper.vm.$nextTick().then(() => {
expect(findCollapsed().isVisible()).toBe(false);
expect(findExpanded().isVisible()).toBe(true);
- expect(findExpanded().text()).toBe('Select item');
});
});
+
+ it('hides the header while editing if `toggleHeader` is true', async () => {
+ createComponent({ canUpdate: true, props: { toggleHeader: true } });
+ findEditButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findEditButton().isVisible()).toBe(false);
+ expect(findTitle().isVisible()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(true);
+ });
});
describe('collapsing an item by offclicking', () => {
@@ -96,12 +114,13 @@ describe('boards sidebar remove issue', () => {
expect(findExpanded().isVisible()).toBe(false);
});
- it('emits close event', async () => {
+ it('emits events', async () => {
document.body.click();
await wrapper.vm.$nextTick();
- expect(wrapper.emitted().close.length).toBe(1);
+ expect(wrapper.emitted().close).toHaveLength(1);
+ expect(wrapper.emitted()['off-click']).toHaveLength(1);
});
});
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
new file mode 100644
index 00000000000..86895c648a4
--- /dev/null
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js
@@ -0,0 +1,182 @@
+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 BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import createFlash from '~/flash';
+import { createStore } from '~/boards/stores';
+
+const TEST_TITLE = 'New issue title';
+const TEST_ISSUE_A = {
+ id: 'gid://gitlab/Issue/1',
+ iid: 8,
+ title: 'Issue 1',
+ referencePath: 'h/b#1',
+};
+const TEST_ISSUE_B = {
+ id: 'gid://gitlab/Issue/2',
+ iid: 9,
+ title: 'Issue 2',
+ referencePath: 'h/b#2',
+};
+
+jest.mock('~/flash');
+
+describe('~/boards/components/sidebar/board_sidebar_issue_title.vue', () => {
+ let wrapper;
+ let store;
+
+ afterEach(() => {
+ localStorage.clear();
+ wrapper.destroy();
+ store = null;
+ wrapper = null;
+ });
+
+ const createWrapper = (issue = TEST_ISSUE_A) => {
+ store = createStore();
+ store.state.issues = { [issue.id]: { ...issue } };
+ store.dispatch('setActiveId', { id: issue.id });
+
+ wrapper = shallowMount(BoardSidebarIssueTitle, {
+ store,
+ provide: {
+ canUpdate: true,
+ },
+ stubs: {
+ 'board-editable-item': BoardEditableItem,
+ },
+ });
+ };
+
+ const findForm = () => wrapper.find(GlForm);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findFormInput = () => wrapper.find(GlFormInput);
+ const findEditableItem = () => wrapper.find(BoardEditableItem);
+ const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
+ const findTitle = () => wrapper.find('[data-testid="issue-title"]');
+ const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
+
+ it('renders title and reference', () => {
+ createWrapper();
+
+ expect(findTitle().text()).toContain(TEST_ISSUE_A.title);
+ expect(findCollapsed().text()).toContain(TEST_ISSUE_A.referencePath);
+ });
+
+ it('does not render alert', () => {
+ createWrapper();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ describe('when new title is submitted', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {
+ store.state.issues[TEST_ISSUE_A.id].title = TEST_TITLE;
+ });
+ findFormInput().vm.$emit('input', TEST_TITLE);
+ findForm().vm.$emit('submit', { preventDefault: () => {} });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders new title', () => {
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findTitle().text()).toContain(TEST_TITLE);
+ });
+
+ it('commits change to the server', () => {
+ expect(wrapper.vm.setActiveIssueTitle).toHaveBeenCalledWith({
+ title: TEST_TITLE,
+ projectPath: 'h/b',
+ });
+ });
+ });
+
+ describe('when submitting and invalid title', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {});
+ findFormInput().vm.$emit('input', '');
+ findForm().vm.$emit('submit', { preventDefault: () => {} });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('commits change to the server', () => {
+ expect(wrapper.vm.setActiveIssueTitle).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when abandoning the form without saving', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ wrapper.vm.$refs.sidebarItem.expand();
+ findFormInput().vm.$emit('input', TEST_TITLE);
+ findEditableItem().vm.$emit('off-click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('does not collapses sidebar and shows alert', () => {
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findAlert().exists()).toBe(true);
+ expect(localStorage.getItem(`${TEST_ISSUE_A.id}/issue-title-pending-changes`)).toBe(
+ TEST_TITLE,
+ );
+ });
+ });
+
+ describe('when accessing the form with pending changes', () => {
+ beforeAll(() => {
+ localStorage.setItem(`${TEST_ISSUE_A.id}/issue-title-pending-changes`, TEST_TITLE);
+
+ createWrapper();
+ });
+
+ it('sets title, expands item and shows alert', async () => {
+ expect(wrapper.vm.title).toBe(TEST_TITLE);
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+
+ describe('when cancel button is clicked', () => {
+ beforeEach(async () => {
+ createWrapper(TEST_ISSUE_B);
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {
+ store.state.issues[TEST_ISSUE_B.id].title = TEST_TITLE;
+ });
+ findFormInput().vm.$emit('input', TEST_TITLE);
+ findCancelButton().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and render former title', () => {
+ expect(wrapper.vm.setActiveIssueTitle).not.toHaveBeenCalled();
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findTitle().text()).toBe(TEST_ISSUE_B.title);
+ });
+ });
+
+ describe('when the mutation fails', () => {
+ beforeEach(async () => {
+ createWrapper(TEST_ISSUE_B);
+
+ jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {
+ throw new Error(['failed mutation']);
+ });
+ findFormInput().vm.$emit('input', 'Invalid title');
+ findForm().vm.$emit('submit', { preventDefault: () => {} });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders former issue title', () => {
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findTitle().text()).toContain(TEST_ISSUE_B.title);
+ expect(createFlash).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
index da000d21f6a..2342caa9dfd 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
@@ -10,8 +10,8 @@ import createFlash from '~/flash';
jest.mock('~/flash');
-const TEST_LABELS_PAYLOAD = TEST_LABELS.map(label => ({ ...label, set: true }));
-const TEST_LABELS_TITLES = TEST_LABELS.map(label => label.title);
+const TEST_LABELS_PAYLOAD = TEST_LABELS.map((label) => ({ ...label, set: true }));
+const TEST_LABELS_TITLES = TEST_LABELS.map((label) => label.title);
describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
let wrapper;
@@ -37,14 +37,15 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
labelsFilterBasePath: TEST_HOST,
},
stubs: {
- 'board-editable-item': BoardEditableItem,
- 'labels-select': '<div></div>',
+ BoardEditableItem,
+ LabelsSelect: true,
},
});
};
const findLabelsSelect = () => wrapper.find({ ref: 'labelsSelect' });
- const findLabelsTitles = () => wrapper.findAll(GlLabel).wrappers.map(item => item.props('title'));
+ const findLabelsTitles = () =>
+ wrapper.findAll(GlLabel).wrappers.map((item) => item.props('title'));
const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
it('renders "None" when no labels are selected', () => {
@@ -76,7 +77,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
it('commits change to the server', () => {
expect(wrapper.vm.setActiveIssueLabels).toHaveBeenCalledWith({
- addLabelIds: TEST_LABELS.map(label => label.id),
+ addLabelIds: TEST_LABELS.map((label) => label.id),
projectPath: 'gitlab-org/test-subgroup/gitlab-test',
removeLabelIds: [],
});
@@ -84,7 +85,10 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
});
describe('when labels are updated over existing labels', () => {
- const testLabelsPayload = [{ id: 5, set: true }, { id: 7, set: true }];
+ const testLabelsPayload = [
+ { id: 5, set: true },
+ { id: 7, set: true },
+ ];
const expectedLabels = [{ id: 5 }, { id: 7 }];
beforeEach(async () => {
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 ee54c662167..b1df0f2d771 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
@@ -83,7 +83,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
});
describe('Board sidebar subscription component `behavior`', () => {
- const mockSetActiveIssueSubscribed = subscribedState => {
+ const mockSetActiveIssueSubscribed = (subscribedState) => {
jest.spyOn(wrapper.vm, 'setActiveIssueSubscribed').mockImplementation(async () => {
store.commit(types.UPDATE_ISSUE_BY_ID, {
issueId: mockActiveIssue.id,
diff --git a/spec/frontend/boards/components/sidebar/remove_issue_spec.js b/spec/frontend/boards/components/sidebar/remove_issue_spec.js
index a33e4046724..1b7a78e6e58 100644
--- a/spec/frontend/boards/components/sidebar/remove_issue_spec.js
+++ b/spec/frontend/boards/components/sidebar/remove_issue_spec.js
@@ -8,7 +8,7 @@ describe('boards sidebar remove issue', () => {
const findButton = () => wrapper.find(GlButton);
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(RemoveIssue, {
propsData: {
issue: {},
diff --git a/spec/frontend/boards/issue_card_deprecated_spec.js b/spec/frontend/boards/issue_card_deprecated_spec.js
new file mode 100644
index 00000000000..fd7b0edb97e
--- /dev/null
+++ b/spec/frontend/boards/issue_card_deprecated_spec.js
@@ -0,0 +1,332 @@
+/* global ListAssignee, ListLabel, ListIssue */
+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';
+
+describe('Issue card component', () => {
+ const user = new ListAssignee({
+ id: 1,
+ name: 'testing 123',
+ username: 'test',
+ avatar: 'test_image',
+ });
+
+ const label1 = new ListLabel({
+ id: 3,
+ title: 'testing 123',
+ color: '#000CFF',
+ text_color: 'white',
+ description: 'test',
+ });
+
+ let wrapper;
+ let issue;
+ let list;
+
+ beforeEach(() => {
+ list = { ...listObj, type: 'label' };
+ issue = new ListIssue({
+ title: 'Testing',
+ id: 1,
+ iid: 1,
+ confidential: false,
+ labels: [list.label],
+ assignees: [],
+ reference_path: '#1',
+ real_path: '/test/1',
+ weight: 1,
+ });
+ wrapper = mount(IssueCardInner, {
+ propsData: {
+ list,
+ issue,
+ },
+ store,
+ stubs: {
+ GlLabel: true,
+ },
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
+ });
+ });
+
+ it('renders issue title', () => {
+ expect(wrapper.find('.board-card-title').text()).toContain(issue.title);
+ });
+
+ it('includes issue base in link', () => {
+ expect(wrapper.find('.board-card-title a').attributes('href')).toContain('/test');
+ });
+
+ it('includes issue title on link', () => {
+ expect(wrapper.find('.board-card-title a').attributes('title')).toBe(issue.title);
+ });
+
+ it('does not render confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(false);
+ });
+
+ it('does not render blocked icon', () => {
+ expect(wrapper.find('.issue-blocked-icon').exists()).toBe(false);
+ });
+
+ it('renders confidential icon', (done) => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ confidential: true,
+ },
+ });
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ done();
+ });
+ });
+
+ it('renders issue ID with #', () => {
+ expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.id}`);
+ });
+
+ describe('assignee', () => {
+ it('does not render assignee', () => {
+ expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(false);
+ });
+
+ describe('exists', () => {
+ beforeEach((done) => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees: [user],
+ updateData(newData) {
+ Object.assign(this, newData);
+ },
+ },
+ });
+
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('renders assignee', () => {
+ expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(true);
+ });
+
+ it('sets title', () => {
+ expect(wrapper.find('.js-assignee-tooltip').text()).toContain(`${user.name}`);
+ });
+
+ it('sets users path', () => {
+ expect(wrapper.find('.board-card-assignee a').attributes('href')).toBe('/test');
+ });
+
+ it('renders avatar', () => {
+ expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
+ });
+
+ it('renders the avatar using avatar_url property', (done) => {
+ wrapper.props('issue').updateData({
+ ...wrapper.props('issue'),
+ assignees: [
+ {
+ id: '1',
+ name: 'test',
+ state: 'active',
+ username: 'test_name',
+ avatar_url: 'test_image_from_avatar_url',
+ },
+ ],
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
+ 'test_image_from_avatar_url?width=24',
+ );
+ done();
+ });
+ });
+ });
+
+ describe('assignee default avatar', () => {
+ beforeEach((done) => {
+ global.gon.default_avatar_url = 'default_avatar';
+
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees: [
+ new ListAssignee({
+ id: 1,
+ name: 'testing 123',
+ username: 'test',
+ }),
+ ],
+ },
+ });
+
+ wrapper.vm.$nextTick(done);
+ });
+
+ afterEach(() => {
+ global.gon.default_avatar_url = null;
+ });
+
+ it('displays defaults avatar if users avatar is null', () => {
+ expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
+ expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
+ 'default_avatar?width=24',
+ );
+ });
+ });
+ });
+
+ describe('multiple assignees', () => {
+ beforeEach((done) => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees: [
+ new ListAssignee({
+ id: 2,
+ name: 'user2',
+ username: 'user2',
+ avatar: 'test_image',
+ }),
+ new ListAssignee({
+ id: 3,
+ name: 'user3',
+ username: 'user3',
+ avatar: 'test_image',
+ }),
+ new ListAssignee({
+ id: 4,
+ name: 'user4',
+ username: 'user4',
+ avatar: 'test_image',
+ }),
+ ],
+ },
+ });
+
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('renders all three assignees', () => {
+ expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(3);
+ });
+
+ describe('more than three assignees', () => {
+ beforeEach((done) => {
+ const { assignees } = wrapper.props('issue');
+ assignees.push(
+ new ListAssignee({
+ id: 5,
+ name: 'user5',
+ username: 'user5',
+ avatar: 'test_image',
+ }),
+ );
+
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees,
+ },
+ });
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('renders more avatar counter', () => {
+ expect(wrapper.find('.board-card-assignee .avatar-counter').text().trim()).toEqual('+2');
+ });
+
+ it('renders two assignees', () => {
+ expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(2);
+ });
+
+ it('renders 99+ avatar counter', (done) => {
+ const assignees = [
+ ...wrapper.props('issue').assignees,
+ ...range(5, 103).map(
+ (i) =>
+ new ListAssignee({
+ id: i,
+ name: 'name',
+ username: 'username',
+ avatar: 'test_image',
+ }),
+ ),
+ ];
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees,
+ },
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.find('.board-card-assignee .avatar-counter').text().trim()).toEqual('99+');
+ done();
+ });
+ });
+ });
+ });
+
+ describe('labels', () => {
+ beforeEach((done) => {
+ issue.addLabel(label1);
+ wrapper.setProps({ issue: { ...issue } });
+
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('does not render list label but renders all other labels', () => {
+ expect(wrapper.findAll(GlLabel).length).toBe(1);
+ const label = wrapper.find(GlLabel);
+ expect(label.props('title')).toEqual(label1.title);
+ expect(label.props('description')).toEqual(label1.description);
+ expect(label.props('backgroundColor')).toEqual(label1.color);
+ });
+
+ it('does not render label if label does not have an ID', (done) => {
+ issue.addLabel(
+ new ListLabel({
+ title: 'closed',
+ }),
+ );
+ wrapper.setProps({ issue: { ...issue } });
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.findAll(GlLabel).length).toBe(1);
+ expect(wrapper.text()).not.toContain('closed');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('blocked', () => {
+ beforeEach((done) => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ blocked: true,
+ },
+ });
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('renders blocked icon if issue is blocked', () => {
+ expect(wrapper.find('.issue-blocked-icon').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/boards/issue_card_inner_spec.js b/spec/frontend/boards/issue_card_inner_spec.js
new file mode 100644
index 00000000000..f9ad78494af
--- /dev/null
+++ b/spec/frontend/boards/issue_card_inner_spec.js
@@ -0,0 +1,372 @@
+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 { updateHistory } from '~/lib/utils/url_utility';
+
+jest.mock('~/lib/utils/url_utility');
+jest.mock('~/boards/eventhub');
+
+describe('Issue card component', () => {
+ const user = {
+ id: 1,
+ name: 'testing 123',
+ username: 'test',
+ avatarUrl: 'test_image',
+ };
+
+ const label1 = {
+ id: 3,
+ title: 'testing 123',
+ color: '#000CFF',
+ textColor: 'white',
+ description: 'test',
+ };
+
+ let wrapper;
+ let issue;
+ let list;
+
+ const createWrapper = (props = {}, store = defaultStore) => {
+ wrapper = mount(IssueCardInner, {
+ store,
+ propsData: {
+ list,
+ issue,
+ ...props,
+ },
+ stubs: {
+ GlLabel: true,
+ },
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ scopedLabelsAvailable: false,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ list = mockLabelList;
+ issue = {
+ title: 'Testing',
+ id: 1,
+ iid: 1,
+ confidential: false,
+ labels: [list.label],
+ assignees: [],
+ referencePath: '#1',
+ webUrl: '/test/1',
+ weight: 1,
+ };
+
+ createWrapper({ issue, list });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ jest.clearAllMocks();
+ });
+
+ it('renders issue title', () => {
+ expect(wrapper.find('.board-card-title').text()).toContain(issue.title);
+ });
+
+ it('includes issue base in link', () => {
+ expect(wrapper.find('.board-card-title a').attributes('href')).toContain('/test');
+ });
+
+ it('includes issue title on link', () => {
+ expect(wrapper.find('.board-card-title a').attributes('title')).toBe(issue.title);
+ });
+
+ it('does not render confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(false);
+ });
+
+ it('does not render blocked icon', () => {
+ expect(wrapper.find('.issue-blocked-icon').exists()).toBe(false);
+ });
+
+ it('renders issue ID with #', () => {
+ expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.id}`);
+ });
+
+ it('does not render assignee', () => {
+ expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(false);
+ });
+
+ describe('confidential issue', () => {
+ beforeEach(() => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ confidential: true,
+ },
+ });
+ });
+
+ it('renders confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ });
+ });
+
+ describe('with assignee', () => {
+ describe('with avatar', () => {
+ beforeEach(() => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees: [user],
+ updateData(newData) {
+ Object.assign(this, newData);
+ },
+ },
+ });
+ });
+
+ it('renders assignee', () => {
+ expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(true);
+ });
+
+ it('sets title', () => {
+ expect(wrapper.find('.js-assignee-tooltip').text()).toContain(`${user.name}`);
+ });
+
+ it('sets users path', () => {
+ expect(wrapper.find('.board-card-assignee a').attributes('href')).toBe('/test');
+ });
+
+ it('renders avatar', () => {
+ expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
+ });
+
+ it('renders the avatar using avatarUrl property', async () => {
+ wrapper.props('issue').updateData({
+ ...wrapper.props('issue'),
+ assignees: [
+ {
+ id: '1',
+ name: 'test',
+ state: 'active',
+ username: 'test_name',
+ avatarUrl: 'test_image_from_avatar_url',
+ },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
+ 'test_image_from_avatar_url?width=24',
+ );
+ });
+ });
+
+ describe('with default avatar', () => {
+ beforeEach(() => {
+ global.gon.default_avatar_url = 'default_avatar';
+
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees: [
+ {
+ id: 1,
+ name: 'testing 123',
+ username: 'test',
+ },
+ ],
+ },
+ });
+ });
+
+ afterEach(() => {
+ global.gon.default_avatar_url = null;
+ });
+
+ it('displays defaults avatar if users avatar is null', () => {
+ expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
+ expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
+ 'default_avatar?width=24',
+ );
+ });
+ });
+ });
+
+ describe('multiple assignees', () => {
+ beforeEach(() => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees: [
+ {
+ id: 2,
+ name: 'user2',
+ username: 'user2',
+ avatarUrl: 'test_image',
+ },
+ {
+ id: 3,
+ name: 'user3',
+ username: 'user3',
+ avatarUrl: 'test_image',
+ },
+ {
+ id: 4,
+ name: 'user4',
+ username: 'user4',
+ avatarUrl: 'test_image',
+ },
+ ],
+ },
+ });
+ });
+
+ it('renders all three assignees', () => {
+ expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(3);
+ });
+
+ describe('more than three assignees', () => {
+ beforeEach(() => {
+ const { assignees } = wrapper.props('issue');
+ assignees.push({
+ id: 5,
+ name: 'user5',
+ username: 'user5',
+ avatarUrl: 'test_image',
+ });
+
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees,
+ },
+ });
+ });
+
+ it('renders more avatar counter', () => {
+ expect(wrapper.find('.board-card-assignee .avatar-counter').text().trim()).toEqual('+2');
+ });
+
+ it('renders two assignees', () => {
+ expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(2);
+ });
+
+ it('renders 99+ avatar counter', async () => {
+ const assignees = [
+ ...wrapper.props('issue').assignees,
+ ...range(5, 103).map((i) => ({
+ id: i,
+ name: 'name',
+ username: 'username',
+ avatarUrl: 'test_image',
+ })),
+ ];
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ assignees,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('.board-card-assignee .avatar-counter').text().trim()).toEqual('99+');
+ });
+ });
+ });
+
+ describe('labels', () => {
+ beforeEach(() => {
+ wrapper.setProps({ issue: { ...issue, labels: [list.label, label1] } });
+ });
+
+ it('does not render list label but renders all other labels', () => {
+ expect(wrapper.findAll(GlLabel).length).toBe(1);
+ const label = wrapper.find(GlLabel);
+ expect(label.props('title')).toEqual(label1.title);
+ expect(label.props('description')).toEqual(label1.description);
+ expect(label.props('backgroundColor')).toEqual(label1.color);
+ });
+
+ it('does not render label if label does not have an ID', async () => {
+ wrapper.setProps({ issue: { ...issue, labels: [label1, { title: 'closed' }] } });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.findAll(GlLabel).length).toBe(1);
+ expect(wrapper.text()).not.toContain('closed');
+ });
+ });
+
+ describe('blocked', () => {
+ beforeEach(() => {
+ wrapper.setProps({
+ issue: {
+ ...wrapper.props('issue'),
+ blocked: true,
+ },
+ });
+ });
+
+ it('renders blocked icon if issue is blocked', () => {
+ expect(wrapper.find('.issue-blocked-icon').exists()).toBe(true);
+ });
+ });
+
+ describe('filterByLabel method', () => {
+ beforeEach(() => {
+ delete window.location;
+
+ wrapper.setProps({
+ updateFilters: true,
+ });
+ });
+
+ describe('when selected label is not in the filter', () => {
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'performSearch').mockImplementation(() => {});
+ window.location = { search: '' };
+ wrapper.vm.filterByLabel(label1);
+ });
+
+ it('calls updateHistory', () => {
+ expect(updateHistory).toHaveBeenCalledTimes(1);
+ });
+
+ it('dispatches performSearch vuex action', () => {
+ expect(wrapper.vm.performSearch).toHaveBeenCalledTimes(1);
+ });
+
+ it('emits updateTokens event', () => {
+ expect(eventHub.$emit).toHaveBeenCalledTimes(1);
+ expect(eventHub.$emit).toHaveBeenCalledWith('updateTokens');
+ });
+ });
+
+ describe('when selected label is already in the filter', () => {
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'performSearch').mockImplementation(() => {});
+ window.location = { search: '?label_name[]=testing%20123' };
+ wrapper.vm.filterByLabel(label1);
+ });
+
+ it('does not call updateHistory', () => {
+ expect(updateHistory).not.toHaveBeenCalled();
+ });
+
+ it('does not dispatch performSearch vuex action', () => {
+ expect(wrapper.vm.performSearch).not.toHaveBeenCalled();
+ });
+
+ it('does not emit updateTokens event', () => {
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/issue_card_spec.js b/spec/frontend/boards/issue_card_spec.js
deleted file mode 100644
index 7e22e9647f0..00000000000
--- a/spec/frontend/boards/issue_card_spec.js
+++ /dev/null
@@ -1,342 +0,0 @@
-/* global ListAssignee, ListLabel, ListIssue */
-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.vue';
-import { listObj } from './mock_data';
-import store from '~/boards/stores';
-
-describe('Issue card component', () => {
- const user = new ListAssignee({
- id: 1,
- name: 'testing 123',
- username: 'test',
- avatar: 'test_image',
- });
-
- const label1 = new ListLabel({
- id: 3,
- title: 'testing 123',
- color: '#000CFF',
- text_color: 'white',
- description: 'test',
- });
-
- let wrapper;
- let issue;
- let list;
-
- beforeEach(() => {
- list = { ...listObj, type: 'label' };
- issue = new ListIssue({
- title: 'Testing',
- id: 1,
- iid: 1,
- confidential: false,
- labels: [list.label],
- assignees: [],
- reference_path: '#1',
- real_path: '/test/1',
- weight: 1,
- });
- wrapper = mount(IssueCardInner, {
- propsData: {
- list,
- issue,
- },
- store,
- stubs: {
- GlLabel: true,
- },
- provide: {
- groupId: null,
- rootPath: '/',
- },
- });
- });
-
- it('renders issue title', () => {
- expect(wrapper.find('.board-card-title').text()).toContain(issue.title);
- });
-
- it('includes issue base in link', () => {
- expect(wrapper.find('.board-card-title a').attributes('href')).toContain('/test');
- });
-
- it('includes issue title on link', () => {
- expect(wrapper.find('.board-card-title a').attributes('title')).toBe(issue.title);
- });
-
- it('does not render confidential icon', () => {
- expect(wrapper.find('.confidential-icon').exists()).toBe(false);
- });
-
- it('does not render blocked icon', () => {
- expect(wrapper.find('.issue-blocked-icon').exists()).toBe(false);
- });
-
- it('renders confidential icon', done => {
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- confidential: true,
- },
- });
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.confidential-icon').exists()).toBe(true);
- done();
- });
- });
-
- it('renders issue ID with #', () => {
- expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.id}`);
- });
-
- describe('assignee', () => {
- it('does not render assignee', () => {
- expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(false);
- });
-
- describe('exists', () => {
- beforeEach(done => {
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- assignees: [user],
- updateData(newData) {
- Object.assign(this, newData);
- },
- },
- });
-
- wrapper.vm.$nextTick(done);
- });
-
- it('renders assignee', () => {
- expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(true);
- });
-
- it('sets title', () => {
- expect(wrapper.find('.js-assignee-tooltip').text()).toContain(`${user.name}`);
- });
-
- it('sets users path', () => {
- expect(wrapper.find('.board-card-assignee a').attributes('href')).toBe('/test');
- });
-
- it('renders avatar', () => {
- expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
- });
-
- it('renders the avatar using avatar_url property', done => {
- wrapper.props('issue').updateData({
- ...wrapper.props('issue'),
- assignees: [
- {
- id: '1',
- name: 'test',
- state: 'active',
- username: 'test_name',
- avatar_url: 'test_image_from_avatar_url',
- },
- ],
- });
-
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
- 'test_image_from_avatar_url?width=24',
- );
- done();
- });
- });
- });
-
- describe('assignee default avatar', () => {
- beforeEach(done => {
- global.gon.default_avatar_url = 'default_avatar';
-
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- assignees: [
- new ListAssignee({
- id: 1,
- name: 'testing 123',
- username: 'test',
- }),
- ],
- },
- });
-
- wrapper.vm.$nextTick(done);
- });
-
- afterEach(() => {
- global.gon.default_avatar_url = null;
- });
-
- it('displays defaults avatar if users avatar is null', () => {
- expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
- expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
- 'default_avatar?width=24',
- );
- });
- });
- });
-
- describe('multiple assignees', () => {
- beforeEach(done => {
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- assignees: [
- new ListAssignee({
- id: 2,
- name: 'user2',
- username: 'user2',
- avatar: 'test_image',
- }),
- new ListAssignee({
- id: 3,
- name: 'user3',
- username: 'user3',
- avatar: 'test_image',
- }),
- new ListAssignee({
- id: 4,
- name: 'user4',
- username: 'user4',
- avatar: 'test_image',
- }),
- ],
- },
- });
-
- wrapper.vm.$nextTick(done);
- });
-
- it('renders all three assignees', () => {
- expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(3);
- });
-
- describe('more than three assignees', () => {
- beforeEach(done => {
- const { assignees } = wrapper.props('issue');
- assignees.push(
- new ListAssignee({
- id: 5,
- name: 'user5',
- username: 'user5',
- avatar: 'test_image',
- }),
- );
-
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- assignees,
- },
- });
- wrapper.vm.$nextTick(done);
- });
-
- it('renders more avatar counter', () => {
- expect(
- wrapper
- .find('.board-card-assignee .avatar-counter')
- .text()
- .trim(),
- ).toEqual('+2');
- });
-
- it('renders two assignees', () => {
- expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(2);
- });
-
- it('renders 99+ avatar counter', done => {
- const assignees = [
- ...wrapper.props('issue').assignees,
- ...range(5, 103).map(
- i =>
- new ListAssignee({
- id: i,
- name: 'name',
- username: 'username',
- avatar: 'test_image',
- }),
- ),
- ];
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- assignees,
- },
- });
-
- wrapper.vm.$nextTick(() => {
- expect(
- wrapper
- .find('.board-card-assignee .avatar-counter')
- .text()
- .trim(),
- ).toEqual('99+');
- done();
- });
- });
- });
- });
-
- describe('labels', () => {
- beforeEach(done => {
- issue.addLabel(label1);
- wrapper.setProps({ issue: { ...issue } });
-
- wrapper.vm.$nextTick(done);
- });
-
- it('does not render list label but renders all other labels', () => {
- expect(wrapper.findAll(GlLabel).length).toBe(1);
- const label = wrapper.find(GlLabel);
- expect(label.props('title')).toEqual(label1.title);
- expect(label.props('description')).toEqual(label1.description);
- expect(label.props('backgroundColor')).toEqual(label1.color);
- });
-
- it('does not render label if label does not have an ID', done => {
- issue.addLabel(
- new ListLabel({
- title: 'closed',
- }),
- );
- wrapper.setProps({ issue: { ...issue } });
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.findAll(GlLabel).length).toBe(1);
- expect(wrapper.text()).not.toContain('closed');
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('blocked', () => {
- beforeEach(done => {
- wrapper.setProps({
- issue: {
- ...wrapper.props('issue'),
- blocked: true,
- },
- });
- wrapper.vm.$nextTick(done);
- });
-
- it('renders blocked icon if issue is blocked', () => {
- expect(wrapper.find('.issue-blocked-icon').exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/boards/list_spec.js b/spec/frontend/boards/list_spec.js
index b731bb6e474..db01f62c9a6 100644
--- a/spec/frontend/boards/list_spec.js
+++ b/spec/frontend/boards/list_spec.js
@@ -37,7 +37,7 @@ describe('List model', () => {
describe('list type', () => {
const notExpandableList = ['blank'];
- const table = Object.keys(ListType).map(k => {
+ const table = Object.keys(ListType).map((k) => {
const value = ListType[k];
return [value, !notExpandableList.includes(value)];
});
@@ -186,7 +186,7 @@ describe('List model', () => {
list.issues = [];
});
- it('adds new issue to top of list', done => {
+ it('adds new issue to top of list', (done) => {
const user = new ListAssignee({
id: 1,
name: 'testing 123',
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index ea6c52c6830..d5cfb9b7d07 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -263,7 +263,7 @@ export const BoardsMockData = {
},
};
-export const boardsMockInterceptor = config => {
+export const boardsMockInterceptor = (config) => {
const body = BoardsMockData[config.method.toUpperCase()][config.url];
return [200, body];
};
@@ -285,7 +285,7 @@ export const setMockEndpoints = (opts = {}) => {
export const mockList = {
id: 'gid://gitlab/List/1',
title: 'Backlog',
- position: null,
+ position: -Infinity,
listType: 'backlog',
collapsed: false,
label: null,
@@ -318,7 +318,7 @@ export const mockLists = [mockList, mockLabelList];
export const mockListsById = keyBy(mockLists, 'id');
-export const mockListsWithModel = mockLists.map(listMock =>
+export const mockListsWithModel = mockLists.map((listMock) =>
Vue.observable(new List({ ...listMock, doNotFetchIssues: true })),
);
@@ -350,3 +350,33 @@ export const issues = {
[mockIssue3.id]: mockIssue3,
[mockIssue4.id]: mockIssue4,
};
+
+export const mockRawGroupProjects = [
+ {
+ id: 0,
+ name: 'Example Project',
+ name_with_namespace: 'Awesome Group / Example Project',
+ path_with_namespace: 'awesome-group/example-project',
+ },
+ {
+ id: 1,
+ name: 'Foobar Project',
+ name_with_namespace: 'Awesome Group / Foobar Project',
+ path_with_namespace: 'awesome-group/foobar-project',
+ },
+];
+
+export const mockGroupProjects = [
+ {
+ id: 0,
+ name: 'Example Project',
+ nameWithNamespace: 'Awesome Group / Example Project',
+ fullPath: 'awesome-group/example-project',
+ },
+ {
+ id: 1,
+ name: 'Foobar Project',
+ nameWithNamespace: 'Awesome Group / Foobar Project',
+ fullPath: 'awesome-group/foobar-project',
+ },
+];
diff --git a/spec/frontend/boards/project_select_deprecated_spec.js b/spec/frontend/boards/project_select_deprecated_spec.js
new file mode 100644
index 00000000000..e4f8f96bd33
--- /dev/null
+++ b/spec/frontend/boards/project_select_deprecated_spec.js
@@ -0,0 +1,261 @@
+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 { 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 { listObj, mockRawGroupProjects } from './mock_data';
+
+jest.mock('~/boards/eventhub');
+jest.mock('~/flash');
+
+const dummyGon = {
+ api_version: 'v4',
+ relative_url_root: '/gitlab',
+};
+
+const mockGroupId = 1;
+const mockProjectsList1 = mockRawGroupProjects.slice(0, 1);
+const mockProjectsList2 = mockRawGroupProjects.slice(1);
+const mockDefaultFetchOptions = {
+ with_issues_enabled: true,
+ with_shared: false,
+ include_subgroups: true,
+ order_by: 'similarity',
+};
+
+const itemsPerPage = 20;
+
+describe('ProjectSelect component', () => {
+ let wrapper;
+ let axiosMock;
+
+ const findLabel = () => wrapper.find("[data-testid='header-label']");
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findGlDropdownLoadingIcon = () =>
+ findGlDropdown().find('button:first-child').find(GlLoadingIcon);
+ const findGlSearchBoxByType = () => wrapper.find(GlSearchBoxByType);
+ const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findFirstGlDropdownItem = () => findGlDropdownItems().at(0);
+ const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']");
+ const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']");
+
+ const mockGetRequest = (data = [], statusCode = httpStatus.OK) => {
+ axiosMock
+ .onGet(`/gitlab/api/v4/groups/${mockGroupId}/projects.json`)
+ .replyOnce(statusCode, data);
+ };
+
+ const searchForProject = async (keyword, waitForAll = true) => {
+ findGlSearchBoxByType().vm.$emit('input', keyword);
+
+ if (waitForAll) {
+ await axios.waitForAll();
+ }
+ };
+
+ const createWrapper = async ({ list = listObj } = {}, waitForAll = true) => {
+ wrapper = mount(ProjectSelect, {
+ propsData: {
+ list,
+ },
+ provide: {
+ groupId: 1,
+ },
+ });
+
+ if (waitForAll) {
+ await axios.waitForAll();
+ }
+ };
+
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ window.gon = dummyGon;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ axiosMock.restore();
+ jest.clearAllMocks();
+ });
+
+ it('displays a header title', async () => {
+ createWrapper({});
+
+ expect(findLabel().text()).toBe('Projects');
+ });
+
+ it('renders a default dropdown text', async () => {
+ createWrapper({});
+
+ expect(findGlDropdown().exists()).toBe(true);
+ expect(findGlDropdown().text()).toContain('Select a project');
+ });
+
+ describe('when mounted', () => {
+ it('displays a loading icon while projects are being fetched', async () => {
+ mockGetRequest([]);
+
+ createWrapper({}, false);
+
+ expect(findGlDropdownLoadingIcon().exists()).toBe(true);
+
+ await axios.waitForAll();
+
+ expect(axiosMock.history.get[0].params).toMatchObject({ search: '' });
+ expect(axiosMock.history.get[0].url).toBe(
+ `/gitlab/api/v4/groups/${mockGroupId}/projects.json`,
+ );
+
+ expect(findGlDropdownLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('when dropdown menu is open', () => {
+ describe('by default', () => {
+ beforeEach(async () => {
+ mockGetRequest(mockProjectsList1);
+
+ await createWrapper();
+ });
+
+ it('shows GlSearchBoxByType with default attributes', () => {
+ expect(findGlSearchBoxByType().exists()).toBe(true);
+ expect(findGlSearchBoxByType().vm.$attrs).toMatchObject({
+ placeholder: 'Search projects',
+ debounce: '250',
+ });
+ });
+
+ it("displays the fetched project's name", () => {
+ expect(findFirstGlDropdownItem().exists()).toBe(true);
+ expect(findFirstGlDropdownItem().text()).toContain(mockProjectsList1[0].name);
+ });
+
+ it("doesn't render loading icon in the menu", () => {
+ expect(findInMenuLoadingIcon().isVisible()).toBe(false);
+ });
+
+ it('renders empty search result message', async () => {
+ await createWrapper();
+
+ expect(findEmptySearchMessage().exists()).toBe(true);
+ });
+ });
+
+ describe('when a project is selected', () => {
+ beforeEach(async () => {
+ mockGetRequest(mockProjectsList1);
+
+ await createWrapper();
+
+ await findFirstGlDropdownItem().find('button').trigger('click');
+ });
+
+ it('emits setSelectedProject with correct project metadata', () => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('setSelectedProject', {
+ id: mockProjectsList1[0].id,
+ path: mockProjectsList1[0].path_with_namespace,
+ name: mockProjectsList1[0].name,
+ namespacedName: mockProjectsList1[0].name_with_namespace,
+ });
+ });
+
+ it('renders the name of the selected project', () => {
+ expect(findGlDropdown().find('.gl-new-dropdown-button-text').text()).toBe(
+ mockProjectsList1[0].name,
+ );
+ });
+ });
+
+ describe('when user searches for a project', () => {
+ beforeEach(async () => {
+ mockGetRequest(mockProjectsList1);
+
+ await createWrapper();
+ });
+
+ it('calls API with correct parameters with default fetch options', async () => {
+ await searchForProject('foobar');
+
+ const expectedApiParams = {
+ search: 'foobar',
+ per_page: itemsPerPage,
+ ...mockDefaultFetchOptions,
+ };
+
+ expect(axiosMock.history.get[1].params).toMatchObject(expectedApiParams);
+ expect(axiosMock.history.get[1].url).toBe(
+ `/gitlab/api/v4/groups/${mockGroupId}/projects.json`,
+ );
+ });
+
+ describe("when list type is defined and isn't backlog", () => {
+ it('calls API with an additional fetch option (min_access_level)', async () => {
+ axiosMock.reset();
+
+ await createWrapper({ list: { ...listObj, type: ListType.label } });
+
+ await searchForProject('foobar');
+
+ const expectedApiParams = {
+ search: 'foobar',
+ per_page: itemsPerPage,
+ ...mockDefaultFetchOptions,
+ min_access_level: featureAccessLevel.EVERYONE,
+ };
+
+ expect(axiosMock.history.get[1].params).toMatchObject(expectedApiParams);
+ expect(axiosMock.history.get[1].url).toBe(
+ `/gitlab/api/v4/groups/${mockGroupId}/projects.json`,
+ );
+ });
+ });
+
+ it('displays and hides gl-loading-icon while and after fetching data', async () => {
+ await searchForProject('some keyword', false);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findInMenuLoadingIcon().isVisible()).toBe(true);
+
+ await axios.waitForAll();
+
+ expect(findInMenuLoadingIcon().isVisible()).toBe(false);
+ });
+
+ it('flashes an error message when fetching fails', async () => {
+ mockGetRequest([], httpStatus.INTERNAL_SERVER_ERROR);
+
+ await searchForProject('foobar');
+
+ expect(flash).toHaveBeenCalledTimes(1);
+ expect(flash).toHaveBeenCalledWith('Something went wrong while fetching projects');
+ });
+
+ describe('with non-empty search result', () => {
+ beforeEach(async () => {
+ mockGetRequest(mockProjectsList2);
+
+ await searchForProject('foobar');
+ });
+
+ it('displays the retrieved list of projects', async () => {
+ expect(findFirstGlDropdownItem().text()).toContain(mockProjectsList2[0].name);
+ });
+
+ it('does not render empty search result message', async () => {
+ expect(findEmptySearchMessage().exists()).toBe(false);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js
new file mode 100644
index 00000000000..14ddab3542b
--- /dev/null
+++ b/spec/frontend/boards/project_select_spec.js
@@ -0,0 +1,154 @@
+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 ProjectSelect from '~/boards/components/project_select.vue';
+
+import { mockList, mockGroupProjects } from './mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+const actions = {
+ fetchGroupProjects: jest.fn(),
+ setSelectedProject: jest.fn(),
+};
+
+const createStore = (state = defaultState) => {
+ return new Vuex.Store({
+ state,
+ actions,
+ });
+};
+
+const mockProjectsList1 = mockGroupProjects.slice(0, 1);
+
+describe('ProjectSelect component', () => {
+ let wrapper;
+
+ const findLabel = () => wrapper.find("[data-testid='header-label']");
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findGlDropdownLoadingIcon = () =>
+ findGlDropdown().find('button:first-child').find(GlLoadingIcon);
+ const findGlSearchBoxByType = () => wrapper.find(GlSearchBoxByType);
+ const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findFirstGlDropdownItem = () => findGlDropdownItems().at(0);
+ const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']");
+ const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']");
+
+ const createWrapper = (state = {}) => {
+ const store = createStore({
+ groupProjects: [],
+ groupProjectsFlags: {
+ isLoading: false,
+ pageInfo: {
+ hasNextPage: false,
+ },
+ },
+ ...state,
+ });
+
+ wrapper = mount(ProjectSelect, {
+ localVue,
+ propsData: {
+ list: mockList,
+ },
+ store,
+ provide: {
+ groupId: 1,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('displays a header title', () => {
+ createWrapper();
+
+ expect(findLabel().text()).toBe('Projects');
+ });
+
+ it('renders a default dropdown text', () => {
+ createWrapper();
+
+ expect(findGlDropdown().exists()).toBe(true);
+ expect(findGlDropdown().text()).toContain('Select a project');
+ });
+
+ describe('when mounted', () => {
+ it('displays a loading icon while projects are being fetched', async () => {
+ createWrapper();
+
+ expect(findGlDropdownLoadingIcon().exists()).toBe(true);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlDropdownLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('when dropdown menu is open', () => {
+ describe('by default', () => {
+ beforeEach(() => {
+ createWrapper({ groupProjects: mockGroupProjects });
+ });
+
+ it('shows GlSearchBoxByType with default attributes', () => {
+ expect(findGlSearchBoxByType().exists()).toBe(true);
+ expect(findGlSearchBoxByType().vm.$attrs).toMatchObject({
+ placeholder: 'Search projects',
+ debounce: '250',
+ });
+ });
+
+ it("displays the fetched project's name", () => {
+ expect(findFirstGlDropdownItem().exists()).toBe(true);
+ expect(findFirstGlDropdownItem().text()).toContain(mockProjectsList1[0].name);
+ });
+
+ it("doesn't render loading icon in the menu", () => {
+ expect(findInMenuLoadingIcon().isVisible()).toBe(false);
+ });
+
+ it('does not render empty search result message', () => {
+ expect(findEmptySearchMessage().exists()).toBe(false);
+ });
+ });
+
+ describe('when no projects are being returned', () => {
+ it('renders empty search result message', () => {
+ createWrapper();
+
+ expect(findEmptySearchMessage().exists()).toBe(true);
+ });
+ });
+
+ describe('when a project is selected', () => {
+ beforeEach(() => {
+ createWrapper({ groupProjects: mockProjectsList1 });
+
+ findFirstGlDropdownItem().find('button').trigger('click');
+ });
+
+ it('renders the name of the selected project', () => {
+ expect(findGlDropdown().find('.gl-new-dropdown-button-text').text()).toBe(
+ mockProjectsList1[0].name,
+ );
+ });
+ });
+
+ describe('when projects are loading', () => {
+ beforeEach(() => {
+ createWrapper({ groupProjectsFlags: { isLoading: true } });
+ });
+
+ it('displays and hides gl-loading-icon while and after fetching data', () => {
+ expect(findInMenuLoadingIcon().isVisible()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 0cae6456887..e4209cd5e55 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -9,19 +9,26 @@ import {
mockMilestone,
labels,
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 } from '~/boards/boards_util';
+import {
+ fullBoardId,
+ formatListIssues,
+ formatBoardLists,
+ formatIssueInput,
+} from '~/boards/boards_util';
import createFlash from '~/flash';
jest.mock('~/flash');
-const expectNotImplemented = action => {
+const expectNotImplemented = (action) => {
it('is not implemented', () => {
expect(action).toThrow(new Error('Not implemented!'));
});
@@ -29,7 +36,7 @@ const expectNotImplemented = action => {
// We need this helper to make sure projectPath is including
// subgroups when the movIssue action is called.
-const getProjectPath = path => path.split('#')[0];
+const getProjectPath = (path) => path.split('#')[0];
beforeEach(() => {
window.gon = { features: {} };
@@ -53,7 +60,7 @@ describe('setInitialBoardData', () => {
});
describe('setFilters', () => {
- it('should commit mutation SET_FILTERS', done => {
+ it('should commit mutation SET_FILTERS', (done) => {
const state = {
filters: {},
};
@@ -72,11 +79,11 @@ describe('setFilters', () => {
});
describe('performSearch', () => {
- it('should dispatch setFilters action', done => {
+ it('should dispatch setFilters action', (done) => {
testAction(actions.performSearch, {}, {}, [], [{ type: 'setFilters', payload: {} }], done);
});
- it('should dispatch setFilters, fetchLists and resetIssues action when graphqlBoardLists FF is on', done => {
+ it('should dispatch setFilters, fetchLists and resetIssues action when graphqlBoardLists FF is on', (done) => {
window.gon = { features: { graphqlBoardLists: true } };
testAction(
actions.performSearch,
@@ -90,7 +97,7 @@ describe('performSearch', () => {
});
describe('setActiveId', () => {
- it('should commit mutation SET_ACTIVE_ID', done => {
+ it('should commit mutation SET_ACTIVE_ID', (done) => {
const state = {
activeId: inactiveId,
};
@@ -108,10 +115,8 @@ describe('setActiveId', () => {
describe('fetchLists', () => {
const state = {
- endpoints: {
- fullPath: 'gitlab-org',
- boardId: 1,
- },
+ fullPath: 'gitlab-org',
+ boardId: '1',
filterParams: {},
boardType: 'group',
};
@@ -131,7 +136,7 @@ describe('fetchLists', () => {
const formattedLists = formatBoardLists(queryResponse.data.group.board.lists);
- it('should commit mutations RECEIVE_BOARD_LISTS_SUCCESS on success', done => {
+ it('should commit mutations RECEIVE_BOARD_LISTS_SUCCESS on success', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
@@ -149,7 +154,7 @@ describe('fetchLists', () => {
);
});
- it('dispatch createList action when backlog list does not exist and is not hidden', done => {
+ it('dispatch createList action when backlog list does not exist and is not hidden', (done) => {
queryResponse = {
data: {
group: {
@@ -181,7 +186,7 @@ describe('fetchLists', () => {
});
describe('createList', () => {
- it('should dispatch addList action when creating backlog list', done => {
+ it('should dispatch addList action when creating backlog list', (done) => {
const backlogList = {
id: 'gid://gitlab/List/1',
listType: 'backlog',
@@ -201,7 +206,8 @@ describe('createList', () => {
);
const state = {
- endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ fullPath: 'gitlab-org',
+ boardId: '1',
boardType: 'group',
disabled: false,
boardLists: [{ type: 'closed' }],
@@ -217,7 +223,7 @@ describe('createList', () => {
);
});
- 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', (done) => {
jest.spyOn(gqlClient, 'mutate').mockReturnValue(
Promise.resolve({
data: {
@@ -230,7 +236,8 @@ describe('createList', () => {
);
const state = {
- endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ fullPath: 'gitlab-org',
+ boardId: '1',
boardType: 'group',
disabled: false,
boardLists: [{ type: 'closed' }],
@@ -248,14 +255,15 @@ describe('createList', () => {
});
describe('moveList', () => {
- it('should commit MOVE_LIST mutation and dispatch updateList action', done => {
+ it('should commit MOVE_LIST mutation and dispatch updateList action', (done) => {
const initialBoardListsState = {
'gid://gitlab/List/1': mockLists[0],
'gid://gitlab/List/2': mockLists[1],
};
const state = {
- endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ fullPath: 'gitlab-org',
+ boardId: '1',
boardType: 'group',
disabled: false,
boardLists: initialBoardListsState,
@@ -297,7 +305,8 @@ describe('moveList', () => {
};
const state = {
- endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ fullPath: 'gitlab-org',
+ boardId: '1',
boardType: 'group',
disabled: false,
boardLists: initialBoardListsState,
@@ -319,7 +328,7 @@ describe('moveList', () => {
});
describe('updateList', () => {
- it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => {
+ it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
updateBoardList: {
@@ -330,7 +339,8 @@ describe('updateList', () => {
});
const state = {
- endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ fullPath: 'gitlab-org',
+ boardId: '1',
boardType: 'group',
disabled: false,
boardLists: [{ type: 'closed' }],
@@ -429,15 +439,13 @@ describe('fetchIssuesForList', () => {
const listId = mockLists[0].id;
const state = {
- endpoints: {
- fullPath: 'gitlab-org',
- boardId: 1,
- },
+ fullPath: 'gitlab-org',
+ boardId: '1',
filterParams: {},
boardType: 'group',
};
- const mockIssuesNodes = mockIssues.map(issue => ({ node: issue }));
+ const mockIssuesNodes = mockIssues.map((issue) => ({ node: issue }));
const pageInfo = {
endCursor: '',
@@ -470,7 +478,7 @@ describe('fetchIssuesForList', () => {
[listId]: pageInfo,
};
- it('should commit mutations REQUEST_ISSUES_FOR_LIST and RECEIVE_ISSUES_FOR_LIST_SUCCESS on success', done => {
+ it('should commit mutations REQUEST_ISSUES_FOR_LIST and RECEIVE_ISSUES_FOR_LIST_SUCCESS on success', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
@@ -492,7 +500,7 @@ describe('fetchIssuesForList', () => {
);
});
- it('should commit mutations REQUEST_ISSUES_FOR_LIST and RECEIVE_ISSUES_FOR_LIST_FAILURE on failure', done => {
+ it('should commit mutations REQUEST_ISSUES_FOR_LIST and RECEIVE_ISSUES_FOR_LIST_FAILURE on failure', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject());
testAction(
@@ -525,12 +533,13 @@ describe('moveIssue', () => {
};
const issues = {
- '436': mockIssue,
- '437': mockIssue2,
+ 436: mockIssue,
+ 437: mockIssue2,
};
const state = {
- endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ fullPath: 'gitlab-org',
+ boardId: '1',
boardType: 'group',
disabled: false,
boardLists: mockLists,
@@ -538,7 +547,7 @@ describe('moveIssue', () => {
issues,
};
- it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_SUCCESS mutation when successful', done => {
+ it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_SUCCESS mutation when successful', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueMoveList: {
@@ -582,7 +591,7 @@ describe('moveIssue', () => {
mutation: issueMoveListMutation,
variables: {
projectPath: getProjectPath(mockIssue.referencePath),
- boardId: fullBoardId(state.endpoints.boardId),
+ boardId: fullBoardId(state.boardId),
iid: mockIssue.iid,
fromListId: 1,
toListId: 2,
@@ -613,7 +622,7 @@ describe('moveIssue', () => {
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
});
- it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_FAILURE mutation when unsuccessful', done => {
+ it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_FAILURE mutation when unsuccessful', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueMoveList: {
@@ -684,7 +693,7 @@ describe('setAssignees', () => {
});
});
- it('calls the correct mutation with the correct values', done => {
+ it('calls the correct mutation with the correct values', (done) => {
testAction(
actions.setAssignees,
{},
@@ -724,8 +733,27 @@ describe('setAssignees', () => {
describe('createNewIssue', () => {
const state = {
boardType: 'group',
- endpoints: {
- fullPath: 'gitlab-org/gitlab',
+ fullPath: 'gitlab-org/gitlab',
+ boardConfig: {
+ labelIds: [],
+ assigneeId: null,
+ milestoneId: -1,
+ },
+ };
+
+ const stateWithBoardConfig = {
+ boardConfig: {
+ labels: [
+ {
+ id: 5,
+ title: 'Test',
+ color: '#ff0000',
+ description: 'testing;',
+ textColor: 'white',
+ },
+ ],
+ assigneeId: 2,
+ milestoneId: 3,
},
};
@@ -743,11 +771,59 @@ describe('createNewIssue', () => {
expect(result).toEqual(mockIssue);
});
- it('should commit CREATE_ISSUE_FAILURE mutation when API returns an error', done => {
+ it('should add board scope to the issue being created', async () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
createIssue: {
- issue: {},
+ issue: mockIssue,
+ errors: [],
+ },
+ },
+ });
+
+ await actions.createNewIssue({ state: stateWithBoardConfig }, mockIssue);
+ expect(gqlClient.mutate).toHaveBeenCalledWith({
+ mutation: issueCreateMutation,
+ variables: {
+ input: formatIssueInput(mockIssue, stateWithBoardConfig.boardConfig),
+ },
+ });
+ });
+
+ it('should add board scope by merging attributes to the issue being created', async () => {
+ const issue = {
+ ...mockIssue,
+ assigneeIds: ['gid://gitlab/User/1'],
+ labelIds: ['gid://gitlab/GroupLabel/4'],
+ };
+
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ createIssue: {
+ issue,
+ errors: [],
+ },
+ },
+ });
+
+ const payload = formatIssueInput(issue, stateWithBoardConfig.boardConfig);
+
+ await actions.createNewIssue({ state: stateWithBoardConfig }, issue);
+ expect(gqlClient.mutate).toHaveBeenCalledWith({
+ mutation: issueCreateMutation,
+ variables: {
+ input: formatIssueInput(issue, stateWithBoardConfig.boardConfig),
+ },
+ });
+ expect(payload.labelIds).toEqual(['gid://gitlab/GroupLabel/4', 'gid://gitlab/GroupLabel/5']);
+ expect(payload.assigneeIds).toEqual(['gid://gitlab/User/1', 'gid://gitlab/User/2']);
+ });
+
+ it('should commit CREATE_ISSUE_FAILURE mutation when API returns an error', (done) => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ createIssue: {
+ issue: mockIssue,
errors: [{ foo: 'bar' }],
},
},
@@ -767,7 +843,7 @@ describe('createNewIssue', () => {
});
describe('addListIssue', () => {
- it('should commit ADD_ISSUE_TO_LIST mutation', done => {
+ it('should commit ADD_ISSUE_TO_LIST mutation', (done) => {
const payload = {
list: mockLists[0],
issue: mockIssue,
@@ -788,14 +864,14 @@ describe('addListIssue', () => {
describe('setActiveIssueLabels', () => {
const state = { issues: { [mockIssue.id]: mockIssue } };
const getters = { activeIssue: mockIssue };
- const testLabelIds = labels.map(label => label.id);
+ const testLabelIds = labels.map((label) => label.id);
const input = {
addLabelIds: testLabelIds,
removeLabelIds: [],
projectPath: 'h/b',
};
- it('should assign labels on success', done => {
+ it('should assign labels on success', (done) => {
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { updateIssue: { issue: { labels: { nodes: labels } } } } });
@@ -839,7 +915,7 @@ describe('setActiveIssueDueDate', () => {
projectPath: 'h/b',
};
- it('should commit due date after setting the issue', done => {
+ it('should commit due date after setting the issue', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
updateIssue: {
@@ -890,7 +966,7 @@ describe('setActiveIssueSubscribed', () => {
projectPath: 'gitlab-org/gitlab-test',
};
- it('should commit subscribed status', done => {
+ it('should commit subscribed status', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueSetSubscription: {
@@ -944,7 +1020,7 @@ describe('setActiveIssueMilestone', () => {
projectPath: 'h/b',
};
- it('should commit milestone after setting the issue', done => {
+ it('should commit milestone after setting the issue', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
updateIssue: {
@@ -986,6 +1062,145 @@ describe('setActiveIssueMilestone', () => {
});
});
+describe('setActiveIssueTitle', () => {
+ const state = { issues: { [mockIssue.id]: mockIssue } };
+ const getters = { activeIssue: mockIssue };
+ const testTitle = 'Test Title';
+ const input = {
+ title: testTitle,
+ projectPath: 'h/b',
+ };
+
+ it('should commit title after setting the issue', (done) => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ updateIssue: {
+ issue: {
+ title: testTitle,
+ },
+ errors: [],
+ },
+ },
+ });
+
+ const payload = {
+ issueId: getters.activeIssue.id,
+ prop: 'title',
+ value: testTitle,
+ };
+
+ testAction(
+ actions.setActiveIssueTitle,
+ input,
+ { ...state, ...getters },
+ [
+ {
+ type: types.UPDATE_ISSUE_BY_ID,
+ payload,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('throws error if fails', async () => {
+ jest
+ .spyOn(gqlClient, 'mutate')
+ .mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
+
+ await expect(actions.setActiveIssueTitle({ getters }, input)).rejects.toThrow(Error);
+ });
+});
+
+describe('fetchGroupProjects', () => {
+ const state = {
+ fullPath: 'gitlab-org',
+ };
+
+ const pageInfo = {
+ endCursor: '',
+ hasNextPage: false,
+ };
+
+ const queryResponse = {
+ data: {
+ group: {
+ projects: {
+ nodes: mockGroupProjects,
+ pageInfo: {
+ endCursor: '',
+ hasNextPage: false,
+ },
+ },
+ },
+ },
+ };
+
+ it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_SUCCESS on success', (done) => {
+ jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
+
+ testAction(
+ actions.fetchGroupProjects,
+ {},
+ state,
+ [
+ {
+ type: types.REQUEST_GROUP_PROJECTS,
+ payload: false,
+ },
+ {
+ type: types.RECEIVE_GROUP_PROJECTS_SUCCESS,
+ payload: { projects: mockGroupProjects, pageInfo, fetchNext: false },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('should commit mutations REQUEST_GROUP_PROJECTS and RECEIVE_GROUP_PROJECTS_FAILURE on failure', (done) => {
+ jest.spyOn(gqlClient, 'query').mockRejectedValue();
+
+ testAction(
+ actions.fetchGroupProjects,
+ {},
+ state,
+ [
+ {
+ type: types.REQUEST_GROUP_PROJECTS,
+ payload: false,
+ },
+ {
+ type: types.RECEIVE_GROUP_PROJECTS_FAILURE,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+});
+
+describe('setSelectedProject', () => {
+ it('should commit mutation SET_SELECTED_PROJECT', (done) => {
+ const project = mockGroupProjects[0];
+
+ testAction(
+ actions.setSelectedProject,
+ project,
+ {},
+ [
+ {
+ type: types.SET_SELECTED_PROJECT,
+ payload: project,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+});
+
describe('fetchBacklog', () => {
expectNotImplemented(actions.fetchBacklog);
});
diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js
index 6ceb8867d1f..44b41b5667d 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -39,7 +39,7 @@ describe('Boards - Getters', () => {
});
describe('getIssueById', () => {
- const state = { issues: { '1': 'issue' } };
+ const state = { issues: { 1: 'issue' } };
it.each`
id | expected
@@ -56,7 +56,7 @@ describe('Boards - Getters', () => {
${'1'} | ${'issue'}
${''} | ${{}}
`('returns $expected when $id is passed to state', ({ id, expected }) => {
- const state = { issues: { '1': 'issue' }, activeId: id };
+ const state = { issues: { 1: 'issue' }, activeId: id };
expect(getters.activeIssue(state)).toEqual(expected);
});
@@ -84,7 +84,7 @@ describe('Boards - Getters', () => {
issues,
};
it('returns issues for a given listId', () => {
- const getIssueById = issueId => [mockIssue, mockIssue2].find(({ id }) => id === issueId);
+ const getIssueById = (issueId) => [mockIssue, mockIssue2].find(({ id }) => id === issueId);
expect(getters.getIssuesByList(boardsState, { getIssueById })('gid://gitlab/List/2')).toEqual(
mockIssues,
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index d93119ede3d..c5fe0e22c3c 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -1,9 +1,9 @@
import mutations from '~/boards/stores/mutations';
import * as types from '~/boards/stores/mutation_types';
import defaultState from '~/boards/stores/state';
-import { mockLists, rawIssue, mockIssue, mockIssue2 } from '../mock_data';
+import { mockLists, rawIssue, mockIssue, mockIssue2, mockGroupProjects } from '../mock_data';
-const expectNotImplemented = action => {
+const expectNotImplemented = (action) => {
it('is not implemented', () => {
expect(action).toThrow(new Error('Not implemented!'));
});
@@ -23,14 +23,8 @@ describe('Board Store Mutations', () => {
describe('SET_INITIAL_BOARD_DATA', () => {
it('Should set initial Boards data to state', () => {
- const endpoints = {
- boardsEndpoint: '/boards/',
- recentBoardsEndpoint: '/boards/',
- listsEndpoint: '/boards/lists',
- bulkUpdatePath: '/boards/bulkUpdate',
- boardId: 1,
- fullPath: 'gitlab-org',
- };
+ const boardId = 1;
+ const fullPath = 'gitlab-org';
const boardType = 'group';
const disabled = false;
const boardConfig = {
@@ -38,13 +32,15 @@ describe('Board Store Mutations', () => {
};
mutations[types.SET_INITIAL_BOARD_DATA](state, {
- ...endpoints,
+ boardId,
+ fullPath,
boardType,
disabled,
boardConfig,
});
- expect(state.endpoints).toEqual(endpoints);
+ expect(state.boardId).toEqual(boardId);
+ expect(state.fullPath).toEqual(fullPath);
expect(state.boardType).toEqual(boardType);
expect(state.disabled).toEqual(disabled);
expect(state.boardConfig).toEqual(boardConfig);
@@ -240,7 +236,7 @@ describe('Board Store Mutations', () => {
'gid://gitlab/List/1': [mockIssue.id],
};
const issues = {
- '1': mockIssue,
+ 1: mockIssue,
};
state = {
@@ -349,8 +345,8 @@ describe('Board Store Mutations', () => {
};
const issues = {
- '1': mockIssue,
- '2': mockIssue2,
+ 1: mockIssue,
+ 2: mockIssue2,
};
state = {
@@ -378,7 +374,7 @@ describe('Board Store Mutations', () => {
describe('MOVE_ISSUE_SUCCESS', () => {
it('updates issue in issues state', () => {
const issues = {
- '436': { id: rawIssue.id },
+ 436: { id: rawIssue.id },
};
state = {
@@ -390,7 +386,7 @@ describe('Board Store Mutations', () => {
issue: rawIssue,
});
- expect(state.issues).toEqual({ '436': { ...mockIssue, id: 436 } });
+ expect(state.issues).toEqual({ 436: { ...mockIssue, id: 436 } });
});
});
@@ -450,7 +446,7 @@ describe('Board Store Mutations', () => {
'gid://gitlab/List/1': [mockIssue.id],
};
const issues = {
- '1': mockIssue,
+ 1: mockIssue,
};
state = {
@@ -476,8 +472,8 @@ describe('Board Store Mutations', () => {
'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
};
const issues = {
- '1': mockIssue,
- '2': mockIssue2,
+ 1: mockIssue,
+ 2: mockIssue2,
};
state = {
@@ -500,8 +496,8 @@ describe('Board Store Mutations', () => {
'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
};
const issues = {
- '1': mockIssue,
- '2': mockIssue2,
+ 1: mockIssue,
+ 2: mockIssue2,
};
state = {
@@ -533,4 +529,64 @@ describe('Board Store Mutations', () => {
describe('TOGGLE_EMPTY_STATE', () => {
expectNotImplemented(mutations.TOGGLE_EMPTY_STATE);
});
+
+ describe('REQUEST_GROUP_PROJECTS', () => {
+ it('Should set isLoading in groupProjectsFlags to true in state when fetchNext is false', () => {
+ mutations[types.REQUEST_GROUP_PROJECTS](state, false);
+
+ expect(state.groupProjectsFlags.isLoading).toBe(true);
+ });
+
+ it('Should set isLoading in groupProjectsFlags to true in state when fetchNext is true', () => {
+ mutations[types.REQUEST_GROUP_PROJECTS](state, true);
+
+ expect(state.groupProjectsFlags.isLoadingMore).toBe(true);
+ });
+ });
+
+ describe('RECEIVE_GROUP_PROJECTS_SUCCESS', () => {
+ it('Should set groupProjects and pageInfo to state and isLoading in groupProjectsFlags to false', () => {
+ mutations[types.RECEIVE_GROUP_PROJECTS_SUCCESS](state, {
+ projects: mockGroupProjects,
+ pageInfo: { hasNextPage: false },
+ });
+
+ expect(state.groupProjects).toEqual(mockGroupProjects);
+ expect(state.groupProjectsFlags.isLoading).toBe(false);
+ expect(state.groupProjectsFlags.pageInfo).toEqual({ hasNextPage: false });
+ });
+
+ it('Should merge projects in groupProjects in state when fetchNext is true', () => {
+ state = {
+ ...state,
+ groupProjects: [mockGroupProjects[0]],
+ };
+
+ mutations[types.RECEIVE_GROUP_PROJECTS_SUCCESS](state, {
+ projects: [mockGroupProjects[1]],
+ fetchNext: true,
+ });
+
+ expect(state.groupProjects).toEqual(mockGroupProjects);
+ });
+ });
+
+ describe('RECEIVE_GROUP_PROJECTS_FAILURE', () => {
+ it('Should set error in state and isLoading in groupProjectsFlags to false', () => {
+ mutations[types.RECEIVE_GROUP_PROJECTS_FAILURE](state);
+
+ expect(state.error).toEqual(
+ 'An error occurred while fetching group projects. Please try again.',
+ );
+ expect(state.groupProjectsFlags.isLoading).toBe(false);
+ });
+ });
+
+ describe('SET_SELECTED_PROJECT', () => {
+ it('Should set selectedProject to state', () => {
+ mutations[types.SET_SELECTED_PROJECT](state, mockGroupProjects[0]);
+
+ expect(state.selectedProject).toEqual(mockGroupProjects[0]);
+ });
+ });
});
diff --git a/spec/frontend/branches/branches_delete_modal_spec.js b/spec/frontend/branches/branches_delete_modal_spec.js
index 21608feafc8..8b10cca7a11 100644
--- a/spec/frontend/branches/branches_delete_modal_spec.js
+++ b/spec/frontend/branches/branches_delete_modal_spec.js
@@ -15,7 +15,7 @@ describe('branches delete modal', () => {
</div>
`);
$deleteButton = $('.js-delete-branch');
- submitSpy = jest.fn(event => event.preventDefault());
+ submitSpy = jest.fn((event) => event.preventDefault());
$('#modal-delete-branch form').on('submit', submitSpy);
// eslint-disable-next-line no-new
new DeleteModal();
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 e07afb5d736..30aa634fc81 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
@@ -16,17 +16,14 @@ describe('TriggersList', () => {
};
const findTable = () => wrapper.find(GlTable);
- const findHeaderAt = i => wrapper.findAll('thead th').at(i);
+ const findHeaderAt = (i) => wrapper.findAll('thead th').at(i);
const findRows = () => wrapper.findAll('tbody tr');
- const findRowAt = i => findRows().at(i);
- const findCell = (i, col) =>
- findRowAt(i)
- .findAll('td')
- .at(col);
- const findClipboardBtn = i => findCell(i, 0).find(ClipboardButton);
- const findInvalidBadge = i => findCell(i, 0).find(GlBadge);
- const findEditBtn = i => findRowAt(i).find('[data-testid="edit-btn"]');
- const findRevokeBtn = i => findRowAt(i).find('[data-testid="trigger_revoke_button"]');
+ const findRowAt = (i) => findRows().at(i);
+ const findCell = (i, col) => findRowAt(i).findAll('td').at(col);
+ const findClipboardBtn = (i) => findCell(i, 0).find(ClipboardButton);
+ const findInvalidBadge = (i) => findCell(i, 0).find(GlBadge);
+ const findEditBtn = (i) => findRowAt(i).find('[data-testid="edit-btn"]');
+ const findRevokeBtn = (i) => findRowAt(i).find('[data-testid="trigger_revoke_button"]');
beforeEach(() => {
createComponent();
@@ -67,11 +64,7 @@ describe('TriggersList', () => {
it('displays a time ago label when last used', () => {
expect(findCell(0, 3).text()).toBe('Never');
- expect(
- findCell(1, 3)
- .find(TimeAgoTooltip)
- .props('time'),
- ).toBe(triggers[1].lastUsed);
+ expect(findCell(1, 3).find(TimeAgoTooltip).props('time')).toBe(triggers[1].lastUsed);
});
it('displays actions in a rows', () => {
diff --git a/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js b/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
index 4a2e56c570d..ad1bdec1735 100644
--- a/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
@@ -31,10 +31,7 @@ describe('VariableList', () => {
it('should add another row when editing the last rows key input', () => {
const $row = $wrapper.find('.js-row');
- $row
- .find('.js-ci-variable-input-key')
- .val('foo')
- .trigger('input');
+ $row.find('.js-ci-variable-input-key').val('foo').trigger('input');
expect($wrapper.find('.js-row').length).toBe(2);
@@ -46,10 +43,7 @@ describe('VariableList', () => {
it('should add another row when editing the last rows value textarea', () => {
const $row = $wrapper.find('.js-row');
- $row
- .find('.js-ci-variable-input-value')
- .val('foo')
- .trigger('input');
+ $row.find('.js-ci-variable-input-value').val('foo').trigger('input');
expect($wrapper.find('.js-row').length).toBe(2);
@@ -61,18 +55,11 @@ describe('VariableList', () => {
it('should remove empty row after blurring', () => {
const $row = $wrapper.find('.js-row');
- $row
- .find('.js-ci-variable-input-key')
- .val('foo')
- .trigger('input');
+ $row.find('.js-ci-variable-input-key').val('foo').trigger('input');
expect($wrapper.find('.js-row').length).toBe(2);
- $row
- .find('.js-ci-variable-input-key')
- .val('')
- .trigger('input')
- .trigger('blur');
+ $row.find('.js-ci-variable-input-key').val('').trigger('input').trigger('blur');
expect($wrapper.find('.js-row').length).toBe(1);
});
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 7bcd558c60f..faa88394447 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
@@ -10,7 +10,7 @@ describe('Ci environments dropdown', () => {
let wrapper;
let store;
- const createComponent = term => {
+ const createComponent = (term) => {
store = new Vuex.Store({
getters: {
joinedEnvironments: () => ['dev', 'prod', 'staging'],
@@ -27,8 +27,8 @@ describe('Ci environments dropdown', () => {
};
const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
- const findDropdownItemByIndex = index => wrapper.findAll(GlDropdownItem).at(index);
- const findActiveIconByIndex = index => findDropdownItemByIndex(index).find(GlIcon);
+ const findDropdownItemByIndex = (index) => wrapper.findAll(GlDropdownItem).at(index);
+ const findActiveIconByIndex = (index) => findDropdownItemByIndex(index).find(GlIcon);
afterEach(() => {
wrapper.destroy();
@@ -78,7 +78,7 @@ describe('Ci environments dropdown', () => {
});
it('should not display create button', () => {
- const environments = findAllDropdownItems().filter(env => env.text().startsWith('Create'));
+ const environments = findAllDropdownItems().filter((env) => env.text().startsWith('Create'));
expect(environments).toHaveLength(0);
expect(findAllDropdownItems()).toHaveLength(1);
});
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 5c2d096418d..b2e51029a06 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
@@ -17,7 +17,7 @@ describe('Ci variable modal', () => {
const createComponent = (method, options = {}) => {
store = createStore();
wrapper = method(CiVariableModal, {
- attachToDocument: true,
+ attachTo: document.body,
stubs: {
GlModal: ModalStub,
},
@@ -31,11 +31,11 @@ describe('Ci variable modal', () => {
const findAddorUpdateButton = () =>
findModal()
.findAll(GlButton)
- .wrappers.find(button => button.props('variant') === 'success');
+ .wrappers.find((button) => button.props('variant') === 'success');
const deleteVariableButton = () =>
findModal()
.findAll(GlButton)
- .wrappers.find(button => button.props('variant') === 'danger');
+ .wrappers.find((button) => button.props('variant') === 'danger');
afterEach(() => {
wrapper.destroy();
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 7dcd82eac5e..12449fc7615 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
@@ -11,7 +11,7 @@ describe('Ci variable table', () => {
let store;
let isGroup;
- const createComponent = groupState => {
+ const createComponent = (groupState) => {
store = createStore();
store.state.isGroup = groupState;
jest.spyOn(store, 'dispatch').mockImplementation();
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 36aeffe7798..fbc34528d4d 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
@@ -17,7 +17,7 @@ describe('Ci variable table', () => {
store.state.isGroup = true;
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = mount(CiVariableTable, {
- attachToDocument: true,
+ attachTo: document.body,
localVue,
store,
});
diff --git a/spec/frontend/ci_variable_list/store/actions_spec.js b/spec/frontend/ci_variable_list/store/actions_spec.js
index 4b89e467df0..075e5829305 100644
--- a/spec/frontend/ci_variable_list/store/actions_spec.js
+++ b/spec/frontend/ci_variable_list/store/actions_spec.js
@@ -86,7 +86,7 @@ describe('CI variable list store actions', () => {
});
describe('deleteVariable', () => {
- it('dispatch correct actions on successful deleted variable', done => {
+ it('dispatch correct actions on successful deleted variable', (done) => {
mock.onPatch(state.endpoint).reply(200);
testAction(
@@ -105,7 +105,7 @@ describe('CI variable list store actions', () => {
);
});
- it('should show flash error and set error in state on delete failure', done => {
+ it('should show flash error and set error in state on delete failure', (done) => {
mock.onPatch(state.endpoint).reply(500, '');
testAction(
@@ -129,7 +129,7 @@ describe('CI variable list store actions', () => {
});
describe('updateVariable', () => {
- it('dispatch correct actions on successful updated variable', done => {
+ it('dispatch correct actions on successful updated variable', (done) => {
mock.onPatch(state.endpoint).reply(200);
testAction(
@@ -148,7 +148,7 @@ describe('CI variable list store actions', () => {
);
});
- it('should show flash error and set error in state on update failure', done => {
+ it('should show flash error and set error in state on update failure', (done) => {
mock.onPatch(state.endpoint).reply(500, '');
testAction(
@@ -172,7 +172,7 @@ describe('CI variable list store actions', () => {
});
describe('addVariable', () => {
- it('dispatch correct actions on successful added variable', done => {
+ it('dispatch correct actions on successful added variable', (done) => {
mock.onPatch(state.endpoint).reply(200);
testAction(
@@ -191,7 +191,7 @@ describe('CI variable list store actions', () => {
);
});
- it('should show flash error and set error in state on add failure', done => {
+ it('should show flash error and set error in state on add failure', (done) => {
mock.onPatch(state.endpoint).reply(500, '');
testAction(
@@ -215,7 +215,7 @@ describe('CI variable list store actions', () => {
});
describe('fetchVariables', () => {
- it('dispatch correct actions on fetchVariables', done => {
+ it('dispatch correct actions on fetchVariables', (done) => {
mock.onGet(state.endpoint).reply(200, { variables: mockData.mockVariables });
testAction(
@@ -236,7 +236,7 @@ describe('CI variable list store actions', () => {
);
});
- it('should show flash error and set error in state on fetch variables failure', done => {
+ it('should show flash error and set error in state on fetch variables failure', (done) => {
mock.onGet(state.endpoint).reply(500);
testAction(actions.fetchVariables, {}, state, [], [{ type: 'requestVariables' }], () => {
@@ -247,7 +247,7 @@ describe('CI variable list store actions', () => {
});
describe('fetchEnvironments', () => {
- it('dispatch correct actions on fetchEnvironments', done => {
+ it('dispatch correct actions on fetchEnvironments', (done) => {
Api.environments = jest.fn().mockResolvedValue({ data: mockData.mockEnvironments });
testAction(
@@ -268,7 +268,7 @@ describe('CI variable list store actions', () => {
);
});
- it('should show flash error and set error in state on fetch environments failure', done => {
+ it('should show flash error and set error in state on fetch environments failure', (done) => {
Api.environments = jest.fn().mockRejectedValue();
testAction(
diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js
index d3277cdb7cc..cd0eda2ab49 100644
--- a/spec/frontend/clusters/clusters_bundle_spec.js
+++ b/spec/frontend/clusters/clusters_bundle_spec.js
@@ -279,7 +279,7 @@ describe('Clusters', () => {
});
describe('uninstallApplication', () => {
- it.each(APPLICATIONS)('tries to uninstall %s', applicationId => {
+ it.each(APPLICATIONS)('tries to uninstall %s', (applicationId) => {
jest.spyOn(cluster.service, 'uninstallApplication').mockResolvedValueOnce();
cluster.store.state.applications[applicationId].status = INSTALLED;
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 6f28573c808..ee4ec4636ea 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
@@ -41,109 +41,119 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
role="menu"
tabindex="-1"
>
- <!---->
-
- <li
- class="gl-new-dropdown-item"
- role="presentation"
+ <div
+ class="gl-new-dropdown-inner"
>
- <button
- class="dropdown-item"
- role="menuitem"
- type="button"
+ <!---->
+
+ <div
+ class="gl-new-dropdown-contents"
>
- <svg
- aria-hidden="true"
- class="gl-icon s16 gl-new-dropdown-item-check-icon"
- data-testid="mobile-issue-close-icon"
- >
- <use
- href="#mobile-issue-close"
- />
- </svg>
-
- <!---->
-
- <!---->
-
- <div
- class="gl-new-dropdown-item-text-wrapper"
+ <li
+ class="gl-new-dropdown-item"
+ role="presentation"
>
- <p
- class="gl-new-dropdown-item-text-primary"
+ <button
+ class="dropdown-item"
+ role="menuitem"
+ type="button"
>
- <strong>
- Remove integration and resources
- </strong>
+ <svg
+ aria-hidden="true"
+ class="gl-icon s16 gl-new-dropdown-item-check-icon"
+ data-testid="mobile-issue-close-icon"
+ >
+ <use
+ href="#mobile-issue-close"
+ />
+ </svg>
+
+ <!---->
+
+ <!---->
- <div>
- Deletes all GitLab resources attached to this cluster during removal
+ <div
+ class="gl-new-dropdown-item-text-wrapper"
+ >
+ <p
+ class="gl-new-dropdown-item-text-primary"
+ >
+ <strong>
+ Remove integration and resources
+ </strong>
+
+ <div>
+ Deletes all GitLab resources attached to this cluster during removal
+ </div>
+ </p>
+
+ <!---->
</div>
- </p>
-
- <!---->
- </div>
+
+ <!---->
+ </button>
+ </li>
- <!---->
- </button>
- </li>
-
- <li
- class="gl-new-dropdown-divider"
- role="presentation"
- >
- <hr
- aria-orientation="horizontal"
- class="dropdown-divider"
- role="separator"
- />
- </li>
- <li
- class="gl-new-dropdown-item"
- role="presentation"
- >
- <button
- class="dropdown-item"
- role="menuitem"
- type="button"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden"
- data-testid="mobile-issue-close-icon"
+ <li
+ class="gl-new-dropdown-divider"
+ role="presentation"
>
- <use
- href="#mobile-issue-close"
+ <hr
+ aria-orientation="horizontal"
+ class="dropdown-divider"
+ role="separator"
/>
- </svg>
-
- <!---->
-
- <!---->
-
- <div
- class="gl-new-dropdown-item-text-wrapper"
+ </li>
+ <li
+ class="gl-new-dropdown-item"
+ role="presentation"
>
- <p
- class="gl-new-dropdown-item-text-primary"
+ <button
+ class="dropdown-item"
+ role="menuitem"
+ type="button"
>
- <strong>
- Remove integration
- </strong>
+ <svg
+ aria-hidden="true"
+ class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden"
+ data-testid="mobile-issue-close-icon"
+ >
+ <use
+ href="#mobile-issue-close"
+ />
+ </svg>
+
+ <!---->
+
+ <!---->
- <div>
- Removes cluster from project but keeps associated resources
+ <div
+ class="gl-new-dropdown-item-text-wrapper"
+ >
+ <p
+ class="gl-new-dropdown-item-text-primary"
+ >
+ <strong>
+ Remove integration
+ </strong>
+
+ <div>
+ Removes cluster from project but keeps associated resources
+ </div>
+ </p>
+
+ <!---->
</div>
- </p>
-
- <!---->
- </div>
+
+ <!---->
+ </button>
+ </li>
<!---->
- </button>
- </li>
-
- <!---->
+ </div>
+
+ <!---->
+ </div>
</ul>
</div>
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index 0a964426c95..49a299cfb3c 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -15,7 +15,7 @@ describe('Application Row', () => {
wrapper.destroy();
});
- const mountComponent = data => {
+ const mountComponent = (data) => {
wrapper = shallowMount(ApplicationRow, {
stubs: { GlSprintf },
propsData: {
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index 5438f3053a8..cf89246c1a5 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -16,7 +16,7 @@ describe('Applications', () => {
gon.features = gon.features || {};
});
- const createApp = ({ applications, type, props } = {}, isShallow) => {
+ const createApp = ({ applications, type, propsData } = {}, isShallow) => {
const mountMethod = isShallow ? shallowMount : mount;
wrapper = mountMethod(Applications, {
@@ -24,13 +24,13 @@ describe('Applications', () => {
propsData: {
type,
applications: { ...APPLICATIONS_MOCK_STATE, ...applications },
- ...props,
+ ...propsData,
},
});
};
- const createShallowApp = options => createApp(options, true);
- const findByTestId = id => wrapper.find(`[data-testid="${id}"]`);
+ const createShallowApp = (options) => createApp(options, true);
+ const findByTestId = (id) => wrapper.find(`[data-testid="${id}"]`);
afterEach(() => {
wrapper.destroy();
});
@@ -544,7 +544,7 @@ describe('Applications', () => {
describe('Cilium application', () => {
it('shows the correct description', () => {
- createApp({ props: { ciliumHelpPath: 'cilium-help-path' } });
+ createApp({ 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 25db8785edc..cd996ae915b 100644
--- a/spec/frontend/clusters/components/fluentd_output_settings_spec.js
+++ b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
@@ -37,11 +37,11 @@ describe('FluentdOutputSettings', () => {
const findSaveButton = () => wrapper.find({ ref: 'saveBtn' });
const findCancelButton = () => wrapper.find({ ref: 'cancelBtn' });
const findProtocolDropdown = () => wrapper.find(GlDropdown);
- const findCheckbox = name =>
- wrapper.findAll(GlFormCheckbox).wrappers.find(x => x.text() === name);
+ const findCheckbox = (name) =>
+ wrapper.findAll(GlFormCheckbox).wrappers.find((x) => x.text() === name);
const findHost = () => wrapper.find('#fluentd-host');
const findPort = () => wrapper.find('#fluentd-port');
- const changeCheckbox = checkbox => {
+ const changeCheckbox = (checkbox) => {
const currentValue = checkbox.attributes('checked')?.toString() === 'true';
checkbox.vm.$emit('input', !currentValue);
};
@@ -49,9 +49,9 @@ describe('FluentdOutputSettings', () => {
element.value = val;
element.dispatchEvent(new Event('input'));
};
- const changePort = val => changeInput(findPort(), val);
- const changeHost = val => changeInput(findHost(), val);
- const changeProtocol = idx => findProtocolDropdown().vm.$children[idx].$emit('click');
+ const changePort = (val) => changeInput(findPort(), val);
+ const changeHost = (val) => changeInput(findHost(), val);
+ const changeProtocol = (idx) => findProtocolDropdown().vm.$children[idx].$emit('click');
const toApplicationSettings = ({ wafLogEnabled, ciliumLogEnabled, ...settings }) => ({
...settings,
waf_log_enabled: wafLogEnabled,
diff --git a/spec/frontend/clusters/components/uninstall_application_button_spec.js b/spec/frontend/clusters/components/uninstall_application_button_spec.js
index 387e2188572..c106292965e 100644
--- a/spec/frontend/clusters/components/uninstall_application_button_spec.js
+++ b/spec/frontend/clusters/components/uninstall_application_button_spec.js
@@ -24,7 +24,7 @@ describe('UninstallApplicationButton', () => {
${UPDATING} | ${false} | ${true} | ${'Uninstall'}
${UNINSTALLING} | ${true} | ${true} | ${'Uninstalling'}
`('when app status is $status', ({ loading, disabled, status, text }) => {
- beforeAll(() => {
+ beforeEach(() => {
createComponent({ status });
});
diff --git a/spec/frontend/clusters/services/application_state_machine_spec.js b/spec/frontend/clusters/services/application_state_machine_spec.js
index 7eee54949fa..a3850a64f3b 100644
--- a/spec/frontend/clusters/services/application_state_machine_spec.js
+++ b/spec/frontend/clusters/services/application_state_machine_spec.js
@@ -25,7 +25,7 @@ const {
const NO_EFFECTS = 'no effects';
describe('applicationStateMachine', () => {
- const noEffectsToEmptyObject = effects => (typeof effects === 'string' ? {} : effects);
+ const noEffectsToEmptyObject = (effects) => (typeof effects === 'string' ? {} : effects);
describe(`current state is ${NO_STATUS}`, () => {
it.each`
@@ -42,7 +42,7 @@ describe('applicationStateMachine', () => {
${UNINSTALLING} | ${UNINSTALLING} | ${NO_EFFECTS}
${INSTALLED} | ${UNINSTALL_ERRORED} | ${{ uninstallFailed: true }}
${UNINSTALLED} | ${UNINSTALLED} | ${NO_EFFECTS}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: NO_STATUS,
@@ -59,7 +59,7 @@ describe('applicationStateMachine', () => {
it.each`
expectedState | event | effects
${INSTALLABLE} | ${INSTALLABLE} | ${NO_EFFECTS}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: NOT_INSTALLABLE,
@@ -79,7 +79,7 @@ describe('applicationStateMachine', () => {
${INSTALLED} | ${INSTALLED} | ${{ installFailed: false }}
${NOT_INSTALLABLE} | ${NOT_INSTALLABLE} | ${NO_EFFECTS}
${UNINSTALLED} | ${UNINSTALLED} | ${{ installFailed: false }}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: INSTALLABLE,
@@ -97,7 +97,7 @@ describe('applicationStateMachine', () => {
expectedState | event | effects
${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: INSTALLING,
@@ -118,7 +118,7 @@ describe('applicationStateMachine', () => {
${NOT_INSTALLABLE} | ${NOT_INSTALLABLE} | ${NO_EFFECTS}
${UNINSTALLED} | ${UNINSTALLED} | ${NO_EFFECTS}
${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: INSTALLED,
@@ -136,7 +136,7 @@ describe('applicationStateMachine', () => {
expectedState | event | effects
${INSTALLED} | ${UPDATED} | ${{ updateSuccessful: true }}
${INSTALLED} | ${UPDATE_ERRORED} | ${{ updateFailed: true }}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: UPDATING,
@@ -154,7 +154,7 @@ describe('applicationStateMachine', () => {
expectedState | event | effects
${INSTALLABLE} | ${INSTALLABLE} | ${{ uninstallSuccessful: true }}
${INSTALLED} | ${UNINSTALL_ERRORED} | ${{ uninstallFailed: true }}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: UNINSTALLING,
@@ -172,7 +172,7 @@ describe('applicationStateMachine', () => {
expectedState | event | effects
${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
- `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ `(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
status: UNINSTALLED,
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
index 381a4717127..df10d9af273 100644
--- a/spec/frontend/clusters/stores/clusters_store_spec.js
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -237,19 +237,22 @@ describe('Clusters Store', () => {
});
});
- describe.each(APPLICATION_INSTALLED_STATUSES)('given the current app status is %s', status => {
- it('marks application as installed', () => {
- const mockResponseData =
- CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
- const runnerAppIndex = 2;
+ describe.each(APPLICATION_INSTALLED_STATUSES)(
+ 'given the current app status is %s',
+ (status) => {
+ it('marks application as installed', () => {
+ const mockResponseData =
+ CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
+ const runnerAppIndex = 2;
- mockResponseData.applications[runnerAppIndex].status = status;
+ mockResponseData.applications[runnerAppIndex].status = status;
- store.updateStateFromServer(mockResponseData);
+ store.updateStateFromServer(mockResponseData);
- expect(store.state.applications[RUNNER].installed).toBe(true);
- });
- });
+ expect(store.state.applications[RUNNER].installed).toBe(true);
+ });
+ },
+ );
it('sets default hostname for jupyter when ingress has a ip address', () => {
const mockResponseData =
diff --git a/spec/frontend/clusters_list/components/ancestor_notice_spec.js b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
index 436f1e97b04..79f917d4601 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 } from '@gitlab/ui';
+import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
import AncestorNotice from '~/clusters_list/components/ancestor_notice.vue';
import ClusterStore from '~/clusters_list/store';
@@ -9,7 +9,7 @@ describe('ClustersAncestorNotice', () => {
const createWrapper = () => {
store = ClusterStore({ ancestorHelperPath: '/some/ancestor/path' });
- wrapper = shallowMount(AncestorNotice, { store, stubs: { GlSprintf } });
+ wrapper = shallowMount(AncestorNotice, { store, stubs: { GlSprintf, GlAlert } });
return wrapper.vm.$nextTick();
};
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 4d157b3a8ab..fa566c2dc57 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
@@ -5,7 +5,7 @@ import NodeErrorHelpText from '~/clusters_list/components/node_error_help_text.v
describe('NodeErrorHelpText', () => {
let wrapper;
- const createWrapper = propsData => {
+ const createWrapper = (propsData) => {
wrapper = shallowMount(NodeErrorHelpText, { propsData, stubs: { GlPopover } });
return wrapper.vm.$nextTick();
};
diff --git a/spec/frontend/clusters_list/store/actions_spec.js b/spec/frontend/clusters_list/store/actions_spec.js
index 3d4e07d00eb..6214cb50e13 100644
--- a/spec/frontend/clusters_list/store/actions_spec.js
+++ b/spec/frontend/clusters_list/store/actions_spec.js
@@ -24,7 +24,7 @@ describe('Clusters store actions', () => {
captureException.mockRestore();
});
- it('should report sentry error', done => {
+ it('should report sentry error', (done) => {
const sentryError = new Error('New Sentry Error');
const tag = 'sentryErrorTag';
@@ -62,7 +62,7 @@ describe('Clusters store actions', () => {
afterEach(() => mock.restore());
- it('should commit SET_CLUSTERS_DATA with received response', done => {
+ it('should commit SET_CLUSTERS_DATA with received response', (done) => {
mock.onGet().reply(200, apiData, headers);
testAction(
@@ -79,7 +79,7 @@ describe('Clusters store actions', () => {
);
});
- it('should show flash on API error', done => {
+ it('should show flash on API error', (done) => {
mock.onGet().reply(400, 'Not Found');
testAction(
@@ -126,7 +126,7 @@ describe('Clusters store actions', () => {
pollStop.mockRestore();
});
- it('should stop polling after MAX Requests', done => {
+ it('should stop polling after MAX Requests', (done) => {
testAction(
actions.fetchClusters,
{ endpoint: apiData.endpoint },
@@ -173,7 +173,7 @@ describe('Clusters store actions', () => {
);
});
- it('should stop polling and report to Sentry when data is invalid', done => {
+ it('should stop polling and report to Sentry when data is invalid', (done) => {
const badApiResponse = { clusters: {} };
mock.onGet().reply(200, badApiResponse, pollHeaders);
diff --git a/spec/frontend/code_navigation/store/actions_spec.js b/spec/frontend/code_navigation/store/actions_spec.js
index fbd93b10a14..39cf4acd5ce 100644
--- a/spec/frontend/code_navigation/store/actions_spec.js
+++ b/spec/frontend/code_navigation/store/actions_spec.js
@@ -8,7 +8,7 @@ jest.mock('~/code_navigation/utils');
describe('Code navigation actions', () => {
describe('setInitialData', () => {
- it('commits SET_INITIAL_DATA', done => {
+ it('commits SET_INITIAL_DATA', (done) => {
testAction(
actions.setInitialData,
{ projectPath: 'test' },
@@ -57,7 +57,7 @@ describe('Code navigation actions', () => {
]);
});
- it('commits REQUEST_DATA_SUCCESS with normalized data', done => {
+ it('commits REQUEST_DATA_SUCCESS with normalized data', (done) => {
testAction(
actions.fetchData,
null,
@@ -84,7 +84,7 @@ describe('Code navigation actions', () => {
);
});
- it('calls addInteractionClass with data', done => {
+ it('calls addInteractionClass with data', (done) => {
testAction(
actions.fetchData,
null,
@@ -125,7 +125,7 @@ describe('Code navigation actions', () => {
mock.onGet(codeNavigationPath).replyOnce(500);
});
- it('dispatches requestDataError', done => {
+ it('dispatches requestDataError', (done) => {
testAction(
actions.fetchData,
null,
@@ -175,15 +175,15 @@ describe('Code navigation actions', () => {
target = document.querySelector('.js-test');
});
- it('returns early when no data exists', done => {
+ it('returns early when no data exists', (done) => {
testAction(actions.showDefinition, { target }, {}, [], [], done);
});
- it('commits SET_CURRENT_DEFINITION when target is not code navitation element', done => {
+ it('commits SET_CURRENT_DEFINITION when target is not code navitation element', (done) => {
testAction(actions.showDefinition, { target }, { data: {} }, [], [], done);
});
- it('commits SET_CURRENT_DEFINITION with LSIF data', done => {
+ it('commits SET_CURRENT_DEFINITION with LSIF data', (done) => {
target.classList.add('js-code-navigation');
target.setAttribute('data-line-index', '0');
target.setAttribute('data-char-index', '0');
diff --git a/spec/frontend/collapsed_sidebar_todo_spec.js b/spec/frontend/collapsed_sidebar_todo_spec.js
index 86f4c450c05..cc89a3c68f0 100644
--- a/spec/frontend/collapsed_sidebar_todo_spec.js
+++ b/spec/frontend/collapsed_sidebar_todo_spec.js
@@ -2,9 +2,9 @@
import { clone } from 'lodash';
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 Sidebar from '~/right_sidebar';
-import waitForPromises from './helpers/wait_for_promises';
describe('Issuable right sidebar collapsed todo toggle', () => {
const fixtureName = 'issues/open-issue.html';
@@ -62,7 +62,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
).toBe('Add a to do');
});
- it('toggle todo state', done => {
+ it('toggle todo state', (done) => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setImmediate(() => {
@@ -80,7 +80,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
});
});
- it('toggle todo state of expanded todo toggle', done => {
+ it('toggle todo state of expanded todo toggle', (done) => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setImmediate(() => {
@@ -92,7 +92,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
});
});
- it('toggles todo button tooltip', done => {
+ it('toggles todo button tooltip', (done) => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setImmediate(() => {
@@ -106,7 +106,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
});
});
- it('marks todo as done', done => {
+ it('marks todo as done', (done) => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
waitForPromises()
@@ -131,7 +131,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
.catch(done.fail);
});
- it('updates aria-label to Mark as done', done => {
+ it('updates aria-label to Mark as done', (done) => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setImmediate(() => {
@@ -145,7 +145,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
});
});
- it('updates aria-label to add todo', done => {
+ it('updates aria-label to add todo', (done) => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
waitForPromises()
diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js
index 625024ee61f..6e4368b5de8 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 { 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 CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
-import { getJSONFixture } from '../helpers/fixtures';
jest.mock('~/lib/utils/poll');
jest.mock('visibilityjs');
@@ -105,7 +105,7 @@ describe('Commit pipeline status component', () => {
describe('when polling', () => {
let pollConfig;
beforeEach(() => {
- Poll.mockImplementation(config => {
+ Poll.mockImplementation((config) => {
pollConfig = config;
return { makeRequest: jest.fn(), restart: jest.fn(), stop: jest.fn() };
});
diff --git a/spec/frontend/commit/pipelines/pipelines_spec.js b/spec/frontend/commit/pipelines/pipelines_spec.js
index a196b66daa0..15b1f224699 100644
--- a/spec/frontend/commit/pipelines/pipelines_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_spec.js
@@ -31,7 +31,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
const { pipelines } = getJSONFixture(jsonFixtureName);
PipelinesTable = Vue.extend(pipelinesTable);
- pipeline = pipelines.find(p => p.user !== null && p.commit !== null);
+ pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
});
afterEach(() => {
@@ -47,7 +47,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
vm = mountComponent(PipelinesTable, props);
});
- it('should render the empty state', done => {
+ it('should render the empty state', (done) => {
setImmediate(() => {
expect(vm.$el.querySelector('.empty-state')).toBeDefined();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
@@ -63,7 +63,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
vm = mountComponent(PipelinesTable, props);
});
- it('should render a table with the received pipelines', done => {
+ it('should render a table with the received pipelines', (done) => {
setImmediate(() => {
expect(vm.$el.querySelectorAll('.ci-table .commit').length).toEqual(1);
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
@@ -74,7 +74,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
describe('with pagination', () => {
- it('should make an API request when using pagination', done => {
+ it('should make an API request when using pagination', (done) => {
setImmediate(() => {
jest.spyOn(vm, 'updateContent').mockImplementation(() => {});
@@ -102,11 +102,11 @@ describe('Pipelines table in Commits and Merge requests', () => {
mock.onGet('endpoint.json').reply(200, [pipeline]);
});
- it('should receive update-pipelines-count event', done => {
+ it('should receive update-pipelines-count event', (done) => {
const element = document.createElement('div');
document.body.appendChild(element);
- element.addEventListener('update-pipelines-count', event => {
+ element.addEventListener('update-pipelines-count', (event) => {
expect(event.detail.pipelines).toEqual([pipeline]);
done();
});
@@ -126,7 +126,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
describe('when latest pipeline has detached flag', () => {
- it('renders the run pipeline button', done => {
+ it('renders the run pipeline button', (done) => {
pipelineCopy.flags.detached_merge_request_pipeline = true;
pipelineCopy.flags.merge_request_pipeline = true;
@@ -143,7 +143,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
describe('when latest pipeline does not have detached flag', () => {
- it('does not render the run pipeline button', done => {
+ it('does not render the run pipeline button', (done) => {
pipelineCopy.flags.detached_merge_request_pipeline = false;
pipelineCopy.flags.merge_request_pipeline = false;
@@ -163,7 +163,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
const findModal = () =>
document.querySelector('#create-pipeline-for-fork-merge-request-modal');
- beforeEach(done => {
+ beforeEach((done) => {
pipelineCopy.flags.detached_merge_request_pipeline = true;
mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
@@ -182,7 +182,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
});
- it('on desktop, shows a loading button', done => {
+ it('on desktop, shows a loading button', (done) => {
findRunPipelineBtn().click();
vm.$nextTick(() => {
@@ -200,7 +200,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
});
- it('on mobile, shows a loading button', done => {
+ it('on mobile, shows a loading button', (done) => {
findRunPipelineBtnMobile().click();
vm.$nextTick(() => {
@@ -223,7 +223,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
const findModal = () =>
document.querySelector('#create-pipeline-for-fork-merge-request-modal');
- beforeEach(done => {
+ beforeEach((done) => {
pipelineCopy.flags.detached_merge_request_pipeline = true;
mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
@@ -244,7 +244,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
});
- it('on desktop, shows a security warning modal', done => {
+ it('on desktop, shows a security warning modal', (done) => {
findRunPipelineBtn().click();
vm.$nextTick(() => {
@@ -253,7 +253,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
});
- it('on mobile, shows a security warning modal', done => {
+ it('on mobile, shows a security warning modal', (done) => {
findRunPipelineBtnMobile().click();
vm.$nextTick(() => {
@@ -271,7 +271,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
vm = mountComponent(PipelinesTable, props);
});
- it('should render error state', done => {
+ it('should render error state', (done) => {
setImmediate(() => {
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBeDefined();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
diff --git a/spec/frontend/commits_spec.js b/spec/frontend/commits_spec.js
index 42bd37570b1..e1b947ddd0d 100644
--- a/spec/frontend/commits_spec.js
+++ b/spec/frontend/commits_spec.js
@@ -70,7 +70,7 @@ describe('Commits List', () => {
mock.restore();
});
- it('should save the last search string', done => {
+ it('should save the last search string', (done) => {
commitsList.searchField.val('GitLab');
commitsList
.filterResults()
@@ -83,7 +83,7 @@ describe('Commits List', () => {
.catch(done.fail);
});
- it('should not make ajax call if the input does not change', done => {
+ it('should not make ajax call if the input does not change', (done) => {
commitsList
.filterResults()
.then(() => {
diff --git a/spec/frontend/commons/nav/user_merge_requests_spec.js b/spec/frontend/commons/nav/user_merge_requests_spec.js
index 4da6d53557a..c441668f7c7 100644
--- a/spec/frontend/commons/nav/user_merge_requests_spec.js
+++ b/spec/frontend/commons/nav/user_merge_requests_spec.js
@@ -3,12 +3,12 @@ import {
closeUserCountsBroadcast,
refreshUserMergeRequestCounts,
} from '~/commons/nav/user_merge_requests';
-import Api from '~/api';
+import * as UserApi from '~/api/user_api';
jest.mock('~/api');
const TEST_COUNT = 1000;
-const MR_COUNT_CLASS = 'merge-requests-count';
+const MR_COUNT_CLASS = 'js-merge-requests-count';
describe('User Merge Requests', () => {
let channelMock;
@@ -24,18 +24,21 @@ describe('User Merge Requests', () => {
newBroadcastChannelMock = jest.fn().mockImplementation(() => channelMock);
global.BroadcastChannel = newBroadcastChannelMock;
- setFixtures(`<div class="${MR_COUNT_CLASS}">0</div>`);
+ setFixtures(
+ `<div><div class="${MR_COUNT_CLASS}">0</div><div class="js-assigned-mr-count"></div><div class="js-reviewer-mr-count"></div></div>`,
+ );
});
const findMRCountText = () => document.body.querySelector(`.${MR_COUNT_CLASS}`).textContent;
describe('refreshUserMergeRequestCounts', () => {
beforeEach(() => {
- Api.userCounts.mockReturnValue(
- Promise.resolve({
- data: { merge_requests: TEST_COUNT },
- }),
- );
+ jest.spyOn(UserApi, 'getUserCounts').mockResolvedValue({
+ data: {
+ assigned_merge_requests: TEST_COUNT,
+ review_requested_merge_requests: TEST_COUNT,
+ },
+ });
});
describe('with open broadcast channel', () => {
@@ -46,15 +49,15 @@ describe('User Merge Requests', () => {
});
it('updates the top count of merge requests', () => {
- expect(findMRCountText()).toEqual(TEST_COUNT.toLocaleString());
+ expect(findMRCountText()).toEqual(Number(TEST_COUNT + TEST_COUNT).toLocaleString());
});
it('calls the API', () => {
- expect(Api.userCounts).toHaveBeenCalled();
+ expect(UserApi.getUserCounts).toHaveBeenCalled();
});
it('posts count to BroadcastChannel', () => {
- expect(channelMock.postMessage).toHaveBeenCalledWith(TEST_COUNT);
+ expect(channelMock.postMessage).toHaveBeenCalledWith(TEST_COUNT + TEST_COUNT);
});
});
diff --git a/spec/frontend/confirm_modal_spec.js b/spec/frontend/confirm_modal_spec.js
index 70076532a94..8a12ff3a01f 100644
--- a/spec/frontend/confirm_modal_spec.js
+++ b/spec/frontend/confirm_modal_spec.js
@@ -29,7 +29,7 @@ describe('ConfirmModal', () => {
beforeEach(() => {
const buttonContainer = document.createElement('div');
- buttons.forEach(x => {
+ buttons.forEach((x) => {
const button = document.createElement('button');
button.setAttribute('class', 'js-confirm-modal-button');
button.setAttribute('data-path', x.path);
@@ -50,7 +50,7 @@ describe('ConfirmModal', () => {
const findModal = () => document.querySelector('.gl-modal');
const findModalOkButton = (modal, variant) =>
modal.querySelector(`.modal-footer .btn-${variant}`);
- const findModalCancelButton = modal => modal.querySelector('.modal-footer .btn-secondary');
+ const findModalCancelButton = (modal) => modal.querySelector('.modal-footer .btn-secondary');
const modalIsHidden = () => findModal() === null;
const serializeModal = (modal, buttonIndex) => {
@@ -63,7 +63,7 @@ describe('ConfirmModal', () => {
title: modal.querySelector('.modal-title').innerHTML,
message: modal.querySelector('.modal-body div').innerHTML,
okVariant: [...findModalOkButton(modal, modalAttributes.okVariant).classList]
- .find(x => x.match('btn-'))
+ .find((x) => x.match('btn-'))
.replace('btn-', ''),
okTitle: findModalOkButton(modal, modalAttributes.okVariant).innerHTML,
},
@@ -78,9 +78,7 @@ describe('ConfirmModal', () => {
describe('when button clicked', () => {
beforeEach(() => {
initConfirmModal();
- findJsHooks()
- .item(0)
- .click();
+ findJsHooks().item(0).click();
});
it('does not replace JsHook with GlModal', () => {
@@ -116,9 +114,7 @@ describe('ConfirmModal', () => {
`(`when multiple buttons exist`, ({ index }) => {
beforeEach(() => {
initConfirmModal();
- findJsHooks()
- .item(index)
- .click();
+ findJsHooks().item(index).click();
});
it('correct props are passed to gl-modal', () => {
diff --git a/spec/frontend/contributors/store/actions_spec.js b/spec/frontend/contributors/store/actions_spec.js
index ad490ea4b67..7d2f93c4940 100644
--- a/spec/frontend/contributors/store/actions_spec.js
+++ b/spec/frontend/contributors/store/actions_spec.js
@@ -17,7 +17,7 @@ describe('Contributors store actions', () => {
mock = new MockAdapter(axios);
});
- it('should commit SET_CHART_DATA with received response', done => {
+ it('should commit SET_CHART_DATA with received response', (done) => {
mock.onGet().reply(200, chartData);
testAction(
@@ -37,7 +37,7 @@ describe('Contributors store actions', () => {
);
});
- it('should show flash on API error', done => {
+ it('should show flash on API error', (done) => {
mock.onGet().reply(400, 'Not Found');
testAction(
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 17abf409717..90c0e2d7827 100644
--- a/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
+++ b/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
@@ -8,9 +8,9 @@ import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_searc
describe('ClusterFormDropdown', () => {
let wrapper;
- const firstItem = { name: 'item 1', value: 1 };
- const secondItem = { name: 'item 2', value: 2 };
- const items = [firstItem, secondItem, { name: 'item 3', value: 3 }];
+ const firstItem = { name: 'item 1', value: '1' };
+ const secondItem = { name: 'item 2', value: '2' };
+ const items = [firstItem, secondItem, { name: 'item 3', value: '3' }];
beforeEach(() => {
wrapper = shallowMount(ClusterFormDropdown);
@@ -44,10 +44,7 @@ describe('ClusterFormDropdown', () => {
wrapper.setProps({ items });
return wrapper.vm.$nextTick().then(() => {
- wrapper
- .findAll('.js-dropdown-item')
- .at(1)
- .trigger('click');
+ wrapper.findAll('.js-dropdown-item').at(1).trigger('click');
return wrapper.vm.$nextTick();
});
});
@@ -58,24 +55,18 @@ describe('ClusterFormDropdown', () => {
});
describe('when multiple items are selected', () => {
- const value = [1];
+ const value = ['1'];
beforeEach(() => {
wrapper.setProps({ items, multiple: true, value });
return wrapper.vm
.$nextTick()
.then(() => {
- wrapper
- .findAll('.js-dropdown-item')
- .at(0)
- .trigger('click');
+ wrapper.findAll('.js-dropdown-item').at(0).trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
- wrapper
- .findAll('.js-dropdown-item')
- .at(1)
- .trigger('click');
+ wrapper.findAll('.js-dropdown-item').at(1).trigger('click');
return wrapper.vm.$nextTick();
});
});
@@ -102,10 +93,7 @@ describe('ClusterFormDropdown', () => {
wrapper.setProps({ items, multiple: true, value: null });
return wrapper.vm.$nextTick().then(() => {
- wrapper
- .findAll('.js-dropdown-item')
- .at(0)
- .trigger('click');
+ wrapper.findAll('.js-dropdown-item').at(0).trigger('click');
expect(wrapper.emitted('input')[0]).toEqual([[firstItem.value]]);
});
@@ -116,7 +104,7 @@ describe('ClusterFormDropdown', () => {
it('displays selected item custom label', () => {
const labelProperty = 'customLabel';
const label = 'Name';
- const currentValue = 1;
+ const currentValue = '1';
const customLabelItems = [{ [labelProperty]: label, value: currentValue }];
wrapper.setProps({ labelProperty, items: customLabelItems, value: currentValue });
@@ -128,12 +116,9 @@ describe('ClusterFormDropdown', () => {
});
describe('when loading', () => {
- it('dropdown button isLoading', () => {
- wrapper.setProps({ loading: true });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DropdownButton).props('isLoading')).toBe(true);
- });
+ it('dropdown button isLoading', async () => {
+ await wrapper.setProps({ loading: true });
+ expect(wrapper.find(DropdownButton).props('isLoading')).toBe(true);
});
});
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 f9984091df0..a4835f8c1c1 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
@@ -128,7 +128,7 @@ describe('EksClusterConfigurationForm', () => {
});
};
- const createValidStateStore = initialState => {
+ const createValidStateStore = (initialState) => {
createStore({
initialState: {
clusterName: 'cluster name',
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 03c22c570a8..2853d18e2cb 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
@@ -101,7 +101,10 @@ describe('awsServicesFacade', () => {
let vpcsOutput;
beforeEach(() => {
- vpcs = [{ VpcId: 'vpc-1', Tags: [] }, { VpcId: 'vpc-2', Tags: [] }];
+ vpcs = [
+ { VpcId: 'vpc-1', Tags: [] },
+ { VpcId: 'vpc-2', Tags: [] },
+ ];
vpcsOutput = vpcs.map(({ VpcId: vpcId }) => ({ name: vpcId, value: vpcId }));
mockDescribeVpcsPromise.mockResolvedValueOnce({ Vpcs: vpcs });
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 f14a555f357..35348d3a03b 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -94,7 +94,7 @@ describe('EKS Cluster Store Actions', () => {
${'setNodeCount'} | ${SET_NODE_COUNT} | ${{ nodeCount }} | ${'node count'}
${'setGitlabManagedCluster'} | ${SET_GITLAB_MANAGED_CLUSTER} | ${gitlabManagedCluster} | ${'gitlab managed cluster'}
${'setNamespacePerEnvironment'} | ${SET_NAMESPACE_PER_ENVIRONMENT} | ${namespacePerEnvironment} | ${'namespace per environment'}
- `(`$action commits $mutation with $payloadDescription payload`, data => {
+ `(`$action commits $mutation with $payloadDescription payload`, (data) => {
const { action, mutation, payload } = data;
testAction(actions[action], payload, state, [{ type: mutation, payload }]);
diff --git a/spec/frontend/create_cluster/eks_cluster/store/getters_spec.js b/spec/frontend/create_cluster/eks_cluster/store/getters_spec.js
index 7c26aeb9b93..46c37961dd3 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/getters_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/getters_spec.js
@@ -6,7 +6,7 @@ describe('EKS Cluster Store Getters', () => {
expect(subnetValid({ selectedSubnet: [1, 2] })).toBe(true);
});
- it.each([[[], [1]]])('returns false if there are 1 or less selected subnets', subnets => {
+ it.each([[[], [1]]])('returns false if there are 1 or less selected subnets', (subnets) => {
expect(subnetValid({ selectedSubnet: subnets })).toBe(false);
});
});
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 8bb014d4758..633cea595d1 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
@@ -66,7 +66,7 @@ describe('Create EKS cluster store mutations', () => {
${SET_INSTANCE_TYPE} | ${'selectedInstanceType'} | ${{ instanceType }} | ${instanceType} | ${'selected instance type payload'}
${SET_NODE_COUNT} | ${'nodeCount'} | ${{ nodeCount }} | ${nodeCount} | ${'node count payload'}
${SET_GITLAB_MANAGED_CLUSTER} | ${'gitlabManagedCluster'} | ${{ gitlabManagedCluster }} | ${gitlabManagedCluster} | ${'gitlab managed cluster'}
- `(`$mutation sets $mutatedProperty to $expectedValueDescription`, data => {
+ `(`$mutation sets $mutatedProperty to $expectedValueDescription`, (data) => {
const { mutation, mutatedProperty, payload, expectedValue } = data;
mutations[mutation](state, payload);
diff --git a/spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js b/spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js
new file mode 100644
index 00000000000..9e4d6996340
--- /dev/null
+++ b/spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js
@@ -0,0 +1,47 @@
+import gapiLoader from '~/create_cluster/gke_cluster/gapi_loader';
+
+describe('gapiLoader', () => {
+ // A mock for document.head.appendChild to intercept the script tag injection.
+ let mockDOMHeadAppendChild;
+
+ beforeEach(() => {
+ mockDOMHeadAppendChild = jest.spyOn(document.head, 'appendChild');
+ });
+
+ afterEach(() => {
+ mockDOMHeadAppendChild.mockRestore();
+ delete window.gapi;
+ delete window.gapiPromise;
+ delete window.onGapiLoad;
+ });
+
+ it('returns a promise', () => {
+ expect(gapiLoader()).toBeInstanceOf(Promise);
+ });
+
+ it('returns the same promise when already loading', () => {
+ const first = gapiLoader();
+ const second = gapiLoader();
+ expect(first).toBe(second);
+ });
+
+ it('resolves the promise when the script loads correctly', async () => {
+ mockDOMHeadAppendChild.mockImplementationOnce((script) => {
+ script.removeAttribute('src');
+ script.appendChild(
+ document.createTextNode(`window.gapi = 'hello gapi'; window.onGapiLoad()`),
+ );
+ document.head.appendChild(script);
+ });
+ await expect(gapiLoader()).resolves.toBe('hello gapi');
+ expect(mockDOMHeadAppendChild).toHaveBeenCalled();
+ });
+
+ it('rejects the promise when the script fails loading', async () => {
+ mockDOMHeadAppendChild.mockImplementationOnce((script) => {
+ script.onerror(new Error('hello error'));
+ });
+ await expect(gapiLoader()).rejects.toThrow('hello error');
+ expect(mockDOMHeadAppendChild).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/create_cluster/gke_cluster/helpers.js b/spec/frontend/create_cluster/gke_cluster/helpers.js
index 52b43b82698..026e99fa8f4 100644
--- a/spec/frontend/create_cluster/gke_cluster/helpers.js
+++ b/spec/frontend/create_cluster/gke_cluster/helpers.js
@@ -8,7 +8,7 @@ const cloudbilling = {
projects: {
getBillingInfo: jest.fn(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
result: { billingEnabled: true },
});
@@ -21,7 +21,7 @@ const cloudresourcemanager = {
projects: {
list: jest.fn(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
result: { ...gapiProjectsResponseMock },
});
@@ -34,7 +34,7 @@ const compute = {
zones: {
list: jest.fn(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
result: { ...gapiZonesResponseMock },
});
@@ -44,7 +44,7 @@ const compute = {
machineTypes: {
list: jest.fn(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
result: { ...gapiMachineTypesResponseMock },
});
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 c1ac3841136..8852baafec7 100644
--- a/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
@@ -14,7 +14,7 @@ import {
describe('GCP Cluster Dropdown Store Actions', () => {
describe('setProject', () => {
- it('should set project', done => {
+ it('should set project', (done) => {
testAction(
actions.setProject,
selectedProjectMock,
@@ -27,7 +27,7 @@ describe('GCP Cluster Dropdown Store Actions', () => {
});
describe('setZone', () => {
- it('should set zone', done => {
+ it('should set zone', (done) => {
testAction(
actions.setZone,
selectedZoneMock,
@@ -40,7 +40,7 @@ describe('GCP Cluster Dropdown Store Actions', () => {
});
describe('setMachineType', () => {
- it('should set machine type', done => {
+ it('should set machine type', (done) => {
testAction(
actions.setMachineType,
selectedMachineTypeMock,
@@ -53,7 +53,7 @@ describe('GCP Cluster Dropdown Store Actions', () => {
});
describe('setIsValidatingProjectBilling', () => {
- it('should set machine type', done => {
+ it('should set machine type', (done) => {
testAction(
actions.setIsValidatingProjectBilling,
true,
@@ -71,10 +71,12 @@ describe('GCP Cluster Dropdown Store Actions', () => {
beforeAll(() => {
originalGapi = window.gapi;
window.gapi = gapi;
+ window.gapiPromise = Promise.resolve(gapi);
});
afterAll(() => {
window.gapi = originalGapi;
+ delete window.gapiPromise;
});
describe('fetchProjects', () => {
@@ -92,7 +94,7 @@ describe('GCP Cluster Dropdown Store Actions', () => {
});
describe('validateProjectBilling', () => {
- it('checks project billing status from Google API', done => {
+ it('checks project billing status from Google API', (done) => {
testAction(
actions.validateProjectBilling,
true,
diff --git a/spec/frontend/create_cluster/gke_cluster_namespace/gke_cluster_namespace_spec.js b/spec/frontend/create_cluster/gke_cluster_namespace/gke_cluster_namespace_spec.js
index b1c25d8fff7..c22167a078c 100644
--- a/spec/frontend/create_cluster/gke_cluster_namespace/gke_cluster_namespace_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster_namespace/gke_cluster_namespace_spec.js
@@ -2,8 +2,8 @@ import initGkeNamespace from '~/create_cluster/gke_cluster_namespace';
describe('GKE cluster namespace', () => {
const changeEvent = new Event('change');
- const isHidden = el => el.classList.contains('hidden');
- const hasDisabledInput = el => el.querySelector('input').disabled;
+ const isHidden = (el) => el.classList.contains('hidden');
+ const hasDisabledInput = (el) => el.querySelector('input').disabled;
let glManagedCheckbox;
let selfManaged;
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 5edd237133d..4b700e31675 100644
--- a/spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js
+++ b/spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js
@@ -27,7 +27,7 @@ describe('Cluster dropdown store mutations', () => {
${RECEIVE_ITEMS_SUCCESS} | ${'items'} | ${{ items }} | ${items} | ${'items payload'}
${RECEIVE_ITEMS_ERROR} | ${'isLoadingItems'} | ${{ error }} | ${false} | ${false}
${RECEIVE_ITEMS_ERROR} | ${'error'} | ${{ error }} | ${error} | ${'received error object'}
- `(`$mutation sets $mutatedProperty to $expectedValueDescription`, data => {
+ `(`$mutation sets $mutatedProperty to $expectedValueDescription`, (data) => {
const { mutation, mutatedProperty, payload, expectedValue } = data;
mutations[mutation](state, payload);
diff --git a/spec/frontend/create_item_dropdown_spec.js b/spec/frontend/create_item_dropdown_spec.js
index a814952faab..7314eb5eee8 100644
--- a/spec/frontend/create_item_dropdown_spec.js
+++ b/spec/frontend/create_item_dropdown_spec.js
@@ -27,20 +27,14 @@ describe('CreateItemDropdown', () => {
function createItemAndClearInput(text) {
// Filter for the new item
- $wrapperEl
- .find('.dropdown-input-field')
- .val(text)
- .trigger('input');
+ $wrapperEl.find('.dropdown-input-field').val(text).trigger('input');
// Create the new item
const $createButton = $wrapperEl.find('.js-dropdown-create-new-item');
$createButton.click();
// Clear out the filter
- $wrapperEl
- .find('.dropdown-input-field')
- .val('')
- .trigger('input');
+ $wrapperEl.find('.dropdown-input-field').val('').trigger('input');
}
beforeEach(() => {
@@ -91,10 +85,7 @@ describe('CreateItemDropdown', () => {
$('.js-dropdown-menu-toggle').click();
// Filter for the new item
- $wrapperEl
- .find('.dropdown-input-field')
- .val(NEW_ITEM_TEXT)
- .trigger('input');
+ $wrapperEl.find('.dropdown-input-field').val(NEW_ITEM_TEXT).trigger('input');
});
it('create new item button should include the filter text', () => {
@@ -171,7 +162,7 @@ describe('CreateItemDropdown', () => {
getData: (term, callback) => {
callback(DROPDOWN_ITEM_DATA);
},
- createNewItemFromValue: newValue => ({
+ createNewItemFromValue: (newValue) => ({
title: `${newValue}-title`,
id: `${newValue}-id`,
text: `${newValue}-text`,
diff --git a/spec/frontend/create_merge_request_dropdown_spec.js b/spec/frontend/create_merge_request_dropdown_spec.js
index bdf03853597..698725b769d 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 { TEST_HOST } from './helpers/test_constants';
describe('CreateMergeRequestDropdown', () => {
let axiosMock;
@@ -36,7 +36,7 @@ describe('CreateMergeRequestDropdown', () => {
});
describe('getRef', () => {
- it('escapes branch names correctly', done => {
+ it('escapes branch names correctly', (done) => {
const endpoint = `${dropdown.refsPath}contains%23hash`;
jest.spyOn(axios, 'get');
axiosMock.onGet(endpoint).replyOnce({});
diff --git a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
index 79c37293fe5..c41adf523f8 100644
--- a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
+++ b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
@@ -1,22 +1,20 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
-import waitForPromises from 'helpers/wait_for_promises';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import axios from '~/lib/utils/axios_utils';
const { CancelToken } = axios;
describe('custom metrics form fields component', () => {
- let component;
+ let wrapper;
let mockAxios;
- const getNamedInput = name => component.element.querySelector(`input[name="${name}"]`);
+ const getNamedInput = (name) => wrapper.element.querySelector(`input[name="${name}"]`);
const validateQueryPath = `${TEST_HOST}/mock/path`;
- const validQueryResponse = { data: { success: true, query: { valid: true, error: '' } } };
+ const validQueryResponse = { success: true, query: { valid: true, error: '' } };
const csrfToken = 'mockToken';
const formOperation = 'post';
- const debouncedValidateQueryMock = jest.fn();
const makeFormData = (data = {}) => ({
formData: {
title: '',
@@ -28,43 +26,42 @@ describe('custom metrics form fields component', () => {
...data,
},
});
- const mountComponent = (props, methods = {}) => {
- component = mount(CustomMetricsFormFields, {
+ const mountComponent = (props) => {
+ wrapper = mount(CustomMetricsFormFields, {
propsData: {
formOperation,
validateQueryPath,
...props,
},
csrfToken,
- methods,
});
};
beforeEach(() => {
mockAxios = new MockAdapter(axios);
- mockAxios.onPost(validateQueryPath).reply(validQueryResponse);
});
afterEach(() => {
- component.destroy();
+ wrapper.destroy();
mockAxios.restore();
});
- it('checks form validity', done => {
+ it('checks form validity', async () => {
+ mockAxios.onPost(validateQueryPath).reply(200, validQueryResponse);
mountComponent({
metricPersisted: true,
...makeFormData({
- title: 'title',
+ title: 'title-old',
yLabel: 'yLabel',
unit: 'unit',
group: 'group',
}),
});
- component.vm.$nextTick(() => {
- expect(component.vm.formIsValid).toBe(false);
- done();
- });
+ wrapper.find(`input[name="prometheus_metric[query]"]`).setValue('query');
+ await axios.waitForAll();
+
+ expect(wrapper.emitted('formValidation')).toStrictEqual([[true]]);
});
describe('hidden inputs', () => {
@@ -110,9 +107,6 @@ describe('custom metrics form fields component', () => {
describe('query input', () => {
const queryInputName = 'prometheus_metric[query]';
- beforeEach(() => {
- mockAxios.onPost(validateQueryPath).reply(validQueryResponse);
- });
it('is empty by default', () => {
mountComponent();
@@ -135,147 +129,65 @@ describe('custom metrics form fields component', () => {
jest.runAllTimers();
});
- it('checks validity on user input', () => {
+ it('checks validity on user input', async () => {
const query = 'changedQuery';
- mountComponent(
- {},
- {
- debouncedValidateQuery: debouncedValidateQueryMock,
- },
- );
- const queryInput = component.find(`input[name="${queryInputName}"]`);
+ mountComponent();
+
+ expect(mockAxios.history.post).toHaveLength(0);
+ const queryInput = wrapper.find(`input[name="${queryInputName}"]`);
queryInput.setValue(query);
- queryInput.trigger('input');
- expect(debouncedValidateQueryMock).toHaveBeenCalledWith(query);
+ await axios.waitForAll();
+ expect(mockAxios.history.post).toHaveLength(1);
});
describe('when query validation is in flight', () => {
beforeEach(() => {
- mountComponent(
- { metricPersisted: true, ...makeFormData({ query: 'validQuery' }) },
- {
- requestValidation: jest.fn().mockImplementation(
- () =>
- new Promise(resolve =>
- setTimeout(() => {
- resolve(validQueryResponse);
- }, 4000),
- ),
- ),
- },
- );
+ mountComponent({ metricPersisted: true, ...makeFormData({ query: 'validQuery' }) });
+ mockAxios.onPost(validateQueryPath).reply(200, validQueryResponse);
});
- afterEach(() => {
- jest.clearAllTimers();
- });
-
- it('expect queryValidateInFlight is in flight', done => {
- const queryInput = component.find(`input[name="${queryInputName}"]`);
+ it('expect loading message to display', async () => {
+ const queryInput = wrapper.find(`input[name="${queryInputName}"]`);
queryInput.setValue('query');
- queryInput.trigger('input');
-
- component.vm.$nextTick(() => {
- expect(component.vm.queryValidateInFlight).toBe(true);
- jest.runOnlyPendingTimers();
- waitForPromises()
- .then(() => {
- component.vm.$nextTick(() => {
- expect(component.vm.queryValidateInFlight).toBe(false);
- expect(component.vm.queryIsValid).toBe(true);
- done();
- });
- })
- .catch(done.fail);
- });
- });
- it('expect loading message to display', done => {
- const queryInput = component.find(`input[name="${queryInputName}"]`);
- queryInput.setValue('query');
- queryInput.trigger('input');
- component.vm.$nextTick(() => {
- expect(component.text()).toContain('Validating query');
- jest.runOnlyPendingTimers();
- done();
- });
+ expect(wrapper.text()).toContain('Validating query');
});
- it('expect loading message to disappear', done => {
- const queryInput = component.find(`input[name="${queryInputName}"]`);
+ it('expect loading message to disappear', async () => {
+ const queryInput = wrapper.find(`input[name="${queryInputName}"]`);
queryInput.setValue('query');
- queryInput.trigger('input');
- component.vm.$nextTick(() => {
- jest.runOnlyPendingTimers();
- waitForPromises()
- .then(() => {
- component.vm.$nextTick(() => {
- expect(component.vm.queryValidateInFlight).toBe(false);
- expect(component.vm.queryIsValid).toBe(true);
- expect(component.vm.errorMessage).toBe('');
- done();
- });
- })
- .catch(done.fail);
- });
+
+ await axios.waitForAll();
+ expect(wrapper.text()).not.toContain('Validating query');
});
});
describe('when query is invalid', () => {
const errorMessage = 'mockErrorMessage';
- const invalidQueryResponse = {
- data: { success: true, query: { valid: false, error: errorMessage } },
- };
+ const invalidQueryResponse = { success: true, query: { valid: false, error: errorMessage } };
beforeEach(() => {
- mountComponent(
- { metricPersisted: true, ...makeFormData({ query: 'invalidQuery' }) },
- {
- requestValidation: jest
- .fn()
- .mockImplementation(() => Promise.resolve(invalidQueryResponse)),
- },
- );
+ mockAxios.onPost(validateQueryPath).reply(200, invalidQueryResponse);
+ mountComponent({ metricPersisted: true, ...makeFormData({ query: 'invalidQuery' }) });
+ return axios.waitForAll();
});
- it('sets queryIsValid to false', done => {
- component.vm.$nextTick(() => {
- expect(component.vm.queryValidateInFlight).toBe(false);
- expect(component.vm.queryIsValid).toBe(false);
- done();
- });
- });
-
- it('shows invalid query message', done => {
- component.vm.$nextTick(() => {
- expect(component.text()).toContain(errorMessage);
- done();
- });
+ it('shows invalid query message', async () => {
+ expect(wrapper.text()).toContain(errorMessage);
});
});
describe('when query is valid', () => {
beforeEach(() => {
- mountComponent(
- { metricPersisted: true, ...makeFormData({ query: 'validQuery' }) },
- {
- requestValidation: jest
- .fn()
- .mockImplementation(() => Promise.resolve(validQueryResponse)),
- },
- );
+ mockAxios.onPost(validateQueryPath).reply(200, validQueryResponse);
+ mountComponent({ metricPersisted: true, ...makeFormData({ query: 'validQuery' }) });
});
- it('sets queryIsValid to true when query is valid', done => {
- component.vm.$nextTick(() => {
- expect(component.vm.queryIsValid).toBe(true);
- done();
- });
- });
+ it('shows valid query message', async () => {
+ await axios.waitForAll();
- it('shows valid query message', () => {
- expect(component.text()).toContain('PromQL query is valid');
+ expect(wrapper.text()).toContain('PromQL query is valid');
});
});
});
diff --git a/spec/frontend/cycle_analytics/limit_warning_component_spec.js b/spec/frontend/cycle_analytics/limit_warning_component_spec.js
index e712dea67cb..edde3725dd6 100644
--- a/spec/frontend/cycle_analytics/limit_warning_component_spec.js
+++ b/spec/frontend/cycle_analytics/limit_warning_component_spec.js
@@ -5,7 +5,7 @@ import LimitWarningComponent from '~/cycle_analytics/components/limit_warning_co
Vue.use(Translate);
-const createComponent = props =>
+const createComponent = (props) =>
shallowMount(LimitWarningComponent, {
propsData: {
...props,
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 9f28ddfd230..650825d1cb7 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
@@ -19,7 +19,7 @@ describe('Deploy freeze modal', () => {
timezoneData: timezoneDataFixture,
});
wrapper = shallowMount(DeployFreezeModal, {
- attachToDocument: true,
+ attachTo: document.body,
stubs: {
GlModal,
},
@@ -29,10 +29,7 @@ describe('Deploy freeze modal', () => {
});
const findModal = () => wrapper.find(GlModal);
- const addDeployFreezeButton = () =>
- findModal()
- .findAll(GlButton)
- .at(1);
+ const addDeployFreezeButton = () => findModal().findAll(GlButton).at(1);
const setInput = (freezeStartCron, freezeEndCron, selectedTimezone) => {
store.state.freezeStartCron = freezeStartCron;
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 8480705b5e3..3b8e8f8485e 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
@@ -18,7 +18,7 @@ describe('Deploy freeze table', () => {
});
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = mount(DeployFreezeTable, {
- attachToDocument: true,
+ attachTo: document.body,
localVue,
store,
});
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index 2aa977dfa5a..1b03cc03d02 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -30,7 +30,7 @@ describe('Deploy freeze timezone dropdown', () => {
};
const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
- const findDropdownItemByIndex = index => wrapper.findAll(GlDropdownItem).at(index);
+ const findDropdownItemByIndex = (index) => wrapper.findAll(GlDropdownItem).at(index);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/deploy_keys/components/app_spec.js b/spec/frontend/deploy_keys/components/app_spec.js
index 291502c9ed7..479320f92f2 100644
--- a/spec/frontend/deploy_keys/components/app_spec.js
+++ b/spec/frontend/deploy_keys/components/app_spec.js
@@ -35,7 +35,7 @@ describe('Deploy keys app component', () => {
});
const findLoadingIcon = () => wrapper.find('.gl-spinner');
- const findKeyPanels = () => wrapper.findAll('.deploy-keys .nav-links li');
+ const findKeyPanels = () => wrapper.findAll('.deploy-keys .gl-tabs-nav li');
it('renders loading icon while waiting for request', () => {
mock.onGet(TEST_ENDPOINT).reply(() => new Promise());
@@ -54,22 +54,14 @@ describe('Deploy keys app component', () => {
});
it.each`
- selector | label | count
- ${'.js-deployKeys-tab-enabled_keys'} | ${'Enabled deploy keys'} | ${1}
- ${'.js-deployKeys-tab-available_project_keys'} | ${'Privately accessible deploy keys'} | ${0}
- ${'.js-deployKeys-tab-public_keys'} | ${'Publicly accessible deploy keys'} | ${1}
- `('$selector title is $label with keys count equal to $count', ({ selector, label, count }) => {
+ selector
+ ${'.js-deployKeys-tab-enabled_keys'}
+ ${'.js-deployKeys-tab-available_project_keys'}
+ ${'.js-deployKeys-tab-public_keys'}
+ `('$selector title exists', ({ selector }) => {
return mountComponent().then(() => {
const element = wrapper.find(selector);
expect(element.exists()).toBe(true);
- expect(element.text().trim()).toContain(label);
-
- expect(
- element
- .find('.badge')
- .text()
- .trim(),
- ).toBe(count.toString());
});
});
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index d990c64c241..fcb4e31dec8 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -9,13 +9,9 @@ describe('Deploy keys key', () => {
const data = getJSONFixture('deploy_keys/keys.json');
- const findTextAndTrim = selector =>
- wrapper
- .find(selector)
- .text()
- .trim();
+ const findTextAndTrim = (selector) => wrapper.find(selector).text().trim();
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = mount(key, {
propsData: {
store,
@@ -103,10 +99,7 @@ describe('Deploy keys key', () => {
it('expands all project labels after click', () => {
createComponent({ deployKey });
const { length } = deployKey.deploy_keys_projects;
- wrapper
- .findAll('.deploy-project-label')
- .at(1)
- .trigger('click');
+ wrapper.findAll('.deploy-project-label').at(1).trigger('click');
return wrapper.vm.$nextTick().then(() => {
const labels = wrapper.findAll('.deploy-project-label');
diff --git a/spec/frontend/deploy_keys/components/keys_panel_spec.js b/spec/frontend/deploy_keys/components/keys_panel_spec.js
index 53c8ba073bc..34b592017e9 100644
--- a/spec/frontend/deploy_keys/components/keys_panel_spec.js
+++ b/spec/frontend/deploy_keys/components/keys_panel_spec.js
@@ -8,7 +8,7 @@ describe('Deploy keys panel', () => {
const findTableRowHeader = () => wrapper.find('.table-row-header');
- const mountComponent = props => {
+ const mountComponent = (props) => {
const store = new DeployKeysStore();
store.keys = data;
wrapper = mount(deployKeysPanel, {
@@ -48,12 +48,9 @@ describe('Deploy keys panel', () => {
expect(wrapper.find('.settings-message').exists()).toBe(true);
- expect(
- wrapper
- .find('.settings-message')
- .text()
- .trim(),
- ).toBe('No deploy keys found. Create one with the form above.');
+ expect(wrapper.find('.settings-message').text().trim()).toBe(
+ 'No deploy keys found. Create one with the form above.',
+ );
});
it('renders no table header if keys are empty', () => {
diff --git a/spec/frontend/deprecated_jquery_dropdown_spec.js b/spec/frontend/deprecated_jquery_dropdown_spec.js
index e6323859899..6070532a1bf 100644
--- a/spec/frontend/deprecated_jquery_dropdown_spec.js
+++ b/spec/frontend/deprecated_jquery_dropdown_spec.js
@@ -56,8 +56,8 @@ describe('deprecatedJQueryDropdown', () => {
search: {
fields: ['name'],
},
- text: project => project.name_with_namespace || project.name,
- id: project => project.id,
+ text: (project) => project.name_with_namespace || project.name,
+ id: (project) => project.id,
...extraOpts,
};
test.dropdownButtonElement = $('#js-project-dropdown', test.dropdownContainerElement);
@@ -230,10 +230,7 @@ describe('deprecatedJQueryDropdown', () => {
it('should still have input value on close and restore', () => {
const $searchInput = $(SEARCH_INPUT_SELECTOR);
initDropDown.call(this, false, true);
- $searchInput
- .trigger('focus')
- .val('g')
- .trigger('input');
+ $searchInput.trigger('focus').val('g').trigger('input');
expect($searchInput.val()).toEqual('g');
test.dropdownButtonElement.trigger('hidden.bs.dropdown');
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 9fbd9b2c2a3..77fc70e08d1 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
@@ -108,7 +108,7 @@ describe('Design discussions component', () => {
it('renders correct amount of discussion notes', () => {
expect(findDesignNotes()).toHaveLength(2);
- expect(findDesignNotes().wrappers.every(w => w.isVisible())).toBe(true);
+ expect(findDesignNotes().wrappers.every((w) => w.isVisible())).toBe(true);
});
it('renders reply placeholder', () => {
@@ -150,16 +150,8 @@ describe('Design discussions component', () => {
});
it('shows only the first note', () => {
- expect(
- findDesignNotes()
- .at(0)
- .isVisible(),
- ).toBe(true);
- expect(
- findDesignNotes()
- .at(1)
- .isVisible(),
- ).toBe(false);
+ expect(findDesignNotes().at(0).isVisible()).toBe(true);
+ expect(findDesignNotes().at(1).isVisible()).toBe(false);
});
it('renders resolved message', () => {
@@ -193,11 +185,7 @@ describe('Design discussions component', () => {
});
it('renders the second note', () => {
- expect(
- findDesignNotes()
- .at(1)
- .isVisible(),
- ).toBe(true);
+ expect(findDesignNotes().at(1).isVisible()).toBe(true);
});
it('renders a reply placeholder', () => {
@@ -263,7 +251,7 @@ describe('Design discussions component', () => {
describe('when any note from a discussion is active', () => {
it.each([notes[0], notes[0].discussion.notes.nodes[1]])(
'applies correct class to all notes in the active discussion',
- note => {
+ (note) => {
createComponent(
{ discussion: mockDiscussion },
{
@@ -277,7 +265,7 @@ describe('Design discussions component', () => {
expect(
wrapper
.findAll(DesignNote)
- .wrappers.every(designNote => designNote.classes('gl-bg-blue-50')),
+ .wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')),
).toBe(true);
},
);
diff --git a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
index 1a80fc4e761..a338a5ef200 100644
--- a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
@@ -36,7 +36,7 @@ describe('Design reply form component', () => {
it('textarea has focus after component mount', () => {
// We need to attach to document, so that `document.activeElement` is properly set in jsdom
- createComponent({}, { attachToDocument: true });
+ createComponent({}, { attachTo: document.body });
expect(findTextarea().element).toEqual(document.activeElement);
});
diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index f4fd4c70dfc..a026cc39c84 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -13,7 +13,7 @@ describe('Design overlay component', () => {
const findAllNotes = () => wrapper.findAll('.js-image-badge');
const findCommentBadge = () => wrapper.find('.comment-indicator');
- const findBadgeAtIndex = noteIndex => findAllNotes().at(noteIndex);
+ const findBadgeAtIndex = (noteIndex) => findAllNotes().at(noteIndex);
const findFirstBadge = () => findBadgeAtIndex(0);
const findSecondBadge = () => findBadgeAtIndex(1);
@@ -108,7 +108,7 @@ describe('Design overlay component', () => {
describe('when no discussion is active', () => {
it('should not apply inactive class to any pins', () => {
expect(
- findAllNotes(0).wrappers.every(designNote => designNote.classes('gl-bg-blue-50')),
+ findAllNotes(0).wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')),
).toBe(false);
});
});
@@ -116,7 +116,7 @@ describe('Design overlay component', () => {
describe('when a discussion is active', () => {
it.each([notes[0].discussion.notes.nodes[1], notes[0].discussion.notes.nodes[0]])(
'should not apply inactive class to the pin for the active discussion',
- note => {
+ (note) => {
wrapper.setData({
activeDiscussion: {
id: note.id,
diff --git a/spec/frontend/design_management/components/design_presentation_spec.js b/spec/frontend/design_management/components/design_presentation_spec.js
index d633d00f2ed..31fd154dc4b 100644
--- a/spec/frontend/design_management/components/design_presentation_spec.js
+++ b/spec/frontend/design_management/components/design_presentation_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import DesignPresentation from '~/design_management/components/design_presentation.vue';
import DesignOverlay from '~/design_management/components/design_overlay.vue';
@@ -100,12 +101,12 @@ describe('Design management design presentation component', () => {
clientY: endCoords.clientY,
});
- return wrapper.vm.$nextTick();
+ return nextTick();
})
.then(() => {
if (mouseup) {
addCommentOverlay.trigger(event.mouseup);
- return wrapper.vm.$nextTick();
+ return nextTick();
}
return undefined;
@@ -125,7 +126,7 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.element).toMatchSnapshot();
});
});
@@ -133,7 +134,7 @@ describe('Design management design presentation component', () => {
it('renders empty state when no image provided', () => {
createComponent();
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.element).toMatchSnapshot();
});
});
@@ -149,7 +150,7 @@ describe('Design management design presentation component', () => {
wrapper.vm.openCommentForm({ x: 1, y: 1 });
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.emitted('openCommentForm')).toEqual([
[{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }],
]);
@@ -166,7 +167,7 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.vm.currentCommentForm).toBeNull();
expect(wrapper.element).toMatchSnapshot();
});
@@ -182,7 +183,7 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.vm.currentCommentForm).toBeNull();
expect(wrapper.element).toMatchSnapshot();
});
@@ -206,7 +207,7 @@ describe('Design management design presentation component', () => {
},
);
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.vm.currentCommentForm).toEqual({
x: 1,
y: 1,
@@ -379,7 +380,7 @@ describe('Design management design presentation component', () => {
});
describe('onImageResize', () => {
- it('sets zoom focal point on initial load', () => {
+ beforeEach(() => {
createComponent(
{
image: 'test.jpg',
@@ -388,22 +389,21 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
- wrapper.setMethods({
- shiftZoomFocalPoint: jest.fn(),
- scaleZoomFocalPoint: jest.fn(),
- scrollToFocalPoint: jest.fn(),
- });
-
+ jest.spyOn(wrapper.vm, 'shiftZoomFocalPoint');
+ jest.spyOn(wrapper.vm, 'scaleZoomFocalPoint');
+ jest.spyOn(wrapper.vm, 'scrollToFocalPoint');
wrapper.vm.onImageResize({ width: 10, height: 10 });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.shiftZoomFocalPoint).toHaveBeenCalled();
- expect(wrapper.vm.initialLoad).toBe(false);
- });
+ return nextTick();
+ });
+
+ it('sets zoom focal point on initial load', () => {
+ expect(wrapper.vm.shiftZoomFocalPoint).toHaveBeenCalled();
+ expect(wrapper.vm.initialLoad).toBe(false);
});
it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', () => {
wrapper.vm.onImageResize({ width: 10, height: 10 });
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled();
expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled();
});
@@ -506,7 +506,7 @@ describe('Design management design presentation component', () => {
.$nextTick()
.then(() => {
addCommentOverlay.trigger('mouseup');
- return wrapper.vm.$nextTick();
+ return nextTick();
})
.then(() => {
expect(wrapper.emitted('openCommentForm')).toBeDefined();
diff --git a/spec/frontend/design_management/components/design_scaler_spec.js b/spec/frontend/design_management/components/design_scaler_spec.js
index 290ec3a18e3..40f53e8d0bf 100644
--- a/spec/frontend/design_management/components/design_scaler_spec.js
+++ b/spec/frontend/design_management/components/design_scaler_spec.js
@@ -10,7 +10,7 @@ describe('Design management design scaler component', () => {
const getResetScaleButton = () => getButtons().at(1);
const getIncreaseScaleButton = () => getButtons().at(2);
- const setScale = scale => wrapper.vm.setScale(scale);
+ const setScale = (scale) => wrapper.vm.setScale(scale);
const createComponent = () => {
wrapper = shallowMount(DesignScaler);
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 de276bd300b..36a2ffd19c3 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
@@ -10,7 +10,10 @@ exports[`Design management list item component when item appears in view after i
exports[`Design management list item component with notes renders item with multiple comments 1`] = `
<router-link-stub
+ ariacurrentvalue="page"
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ event="click"
+ tag="a"
to="[object Object]"
>
<div
@@ -81,7 +84,10 @@ exports[`Design management list item component with notes renders item with mult
exports[`Design management list item component with notes renders item with single comment 1`] = `
<router-link-stub
+ ariacurrentvalue="page"
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ event="click"
+ tag="a"
to="[object Object]"
>
<div
diff --git a/spec/frontend/design_management/components/toolbar/index_spec.js b/spec/frontend/design_management/components/toolbar/index_spec.js
index 2914365b0df..6ac088a2c53 100644
--- a/spec/frontend/design_management/components/toolbar/index_spec.js
+++ b/spec/frontend/design_management/components/toolbar/index_spec.js
@@ -116,6 +116,8 @@ describe('Design management toolbar component', () => {
});
it('renders download button with correct link', () => {
+ createComponent();
+
expect(wrapper.find(GlButton).attributes('href')).toBe(
'/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d',
);
diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
index 8c6b446794f..63afc3f000d 100644
--- a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
+++ b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
@@ -4,6 +4,7 @@ exports[`Design management design version dropdown component renders design vers
<gl-dropdown-stub
category="primary"
headertext=""
+ hideheaderborder="true"
issueiid=""
projectpath=""
size="small"
@@ -44,6 +45,7 @@ exports[`Design management design version dropdown component renders design vers
<gl-dropdown-stub
category="primary"
headertext=""
+ hideheaderborder="true"
issueiid=""
projectpath=""
size="small"
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 4ef787ac754..d841aabf2f3 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
@@ -6,7 +6,7 @@ import mockAllVersions from './mock_data/all_versions';
const LATEST_VERSION_ID = 3;
const PREVIOUS_VERSION_ID = 2;
-const designRouteFactory = versionId => ({
+const designRouteFactory = (versionId) => ({
path: `/designs?version=${versionId}`,
query: {
version: `${versionId}`,
@@ -42,7 +42,7 @@ describe('Design management design version dropdown component', () => {
wrapper.destroy();
});
- const findVersionLink = index => wrapper.findAll(GlDropdownItem).at(index);
+ const findVersionLink = (index) => wrapper.findAll(GlDropdownItem).at(index);
it('renders design version dropdown button', () => {
createComponent();
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 147169dd9aa..7d28d6f6d11 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -1,14 +1,15 @@
+import { nextTick } from 'vue';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo, { ApolloMutation } from 'vue-apollo';
import VueDraggable from 'vuedraggable';
import VueRouter from 'vue-router';
import { GlEmptyState } from '@gitlab/ui';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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 uploadDesignQuery from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
+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 DeleteButton from '~/design_management/components/delete_button.vue';
@@ -113,7 +114,7 @@ describe('Design management index page', () => {
async function moveDesigns(localWrapper) {
await jest.runOnlyPendingTimers();
- await localWrapper.vm.$nextTick();
+ await nextTick();
localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
localWrapper.find(VueDraggable).vm.$emit('change', {
@@ -159,7 +160,7 @@ describe('Design management index page', () => {
localVue,
router,
stubs: { DesignDestroyer, ApolloMutation, VueDraggable, ...stubs },
- attachToDocument: true,
+ attachTo: document.body,
provide: {
projectPath: 'project-path',
issueIid: '1',
@@ -200,14 +201,13 @@ describe('Design management index page', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('renders error', () => {
+ it('renders error', async () => {
createComponent();
wrapper.setData({ error: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
+ await nextTick();
+ expect(wrapper.element).toMatchSnapshot();
});
it('renders a toolbar with buttons when there are designs', () => {
@@ -254,10 +254,10 @@ describe('Design management index page', () => {
createComponent({ designCollection: { designs: [], copyState: 'READY' } });
});
- it('renders design dropzone', () =>
- wrapper.vm.$nextTick().then(() => {
- expect(findDropzone().exists()).toBe(true);
- }));
+ it('renders design dropzone', async () => {
+ await nextTick();
+ expect(findDropzone().exists()).toBe(true);
+ });
it('has correct classes applied to design dropzone', () => {
expect(dropzoneClasses()).not.toContain('design-list-item');
@@ -268,10 +268,10 @@ describe('Design management index page', () => {
expect(findDropzoneWrapper().classes()).toEqual(['col-12']);
});
- it('does not render a toolbar with buttons', () =>
- wrapper.vm.$nextTick().then(() => {
- expect(findToolbar().exists()).toBe(false);
- }));
+ it('does not render a toolbar with buttons', async () => {
+ await nextTick();
+ expect(findToolbar().exists()).toBe(false);
+ });
});
describe('handling design collection copy state', () => {
@@ -290,7 +290,7 @@ describe('Design management index page', () => {
});
describe('uploading designs', () => {
- it('calls mutation on upload', () => {
+ it('calls mutation on upload', async () => {
createComponent({ stubs: { GlEmptyState } });
const mutationVariables = {
@@ -298,7 +298,7 @@ describe('Design management index page', () => {
context: {
hasUpload: true,
},
- mutation: uploadDesignQuery,
+ mutation: uploadDesignMutation,
variables: {
files: [{ name: 'test' }],
projectPath: 'project-path',
@@ -348,21 +348,16 @@ describe('Design management index page', () => {
},
};
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findDropzone().vm.$emit('change', [{ name: 'test' }]);
- expect(mutate).toHaveBeenCalledWith(mutationVariables);
- expect(wrapper.vm.filesToBeSaved).toEqual([{ name: 'test' }]);
- expect(wrapper.vm.isSaving).toBeTruthy();
- })
- .then(() => {
- expect(dropzoneClasses()).toContain('design-list-item');
- expect(dropzoneClasses()).toContain('design-list-item-new');
- });
+ await nextTick();
+ findDropzone().vm.$emit('change', [{ name: 'test' }]);
+ expect(mutate).toHaveBeenCalledWith(mutationVariables);
+ expect(wrapper.vm.filesToBeSaved).toEqual([{ name: 'test' }]);
+ expect(wrapper.vm.isSaving).toBeTruthy();
+ expect(dropzoneClasses()).toContain('design-list-item');
+ expect(dropzoneClasses()).toContain('design-list-item-new');
});
- it('sets isSaving', () => {
+ it('sets isSaving', async () => {
createComponent();
const uploadDesign = wrapper.vm.onUploadDesign([
@@ -373,35 +368,31 @@ describe('Design management index page', () => {
expect(wrapper.vm.isSaving).toBe(true);
- return uploadDesign.then(() => {
- expect(wrapper.vm.isSaving).toBe(false);
- });
+ await uploadDesign;
+ expect(wrapper.vm.isSaving).toBe(false);
});
- it('updates state appropriately after upload complete', () => {
+ it('updates state appropriately after upload complete', async () => {
createComponent({ stubs: { GlEmptyState } });
wrapper.setData({ filesToBeSaved: [{ name: 'test' }] });
wrapper.vm.onUploadDesignDone(designUploadMutationCreatedResponse);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.filesToBeSaved).toEqual([]);
- expect(wrapper.vm.isSaving).toBeFalsy();
- expect(wrapper.vm.isLatestVersion).toBe(true);
- });
+ await nextTick();
+
+ expect(wrapper.vm.filesToBeSaved).toEqual([]);
+ expect(wrapper.vm.isSaving).toBeFalsy();
+ expect(wrapper.vm.isLatestVersion).toBe(true);
});
- it('updates state appropriately after upload error', () => {
+ it('updates state appropriately after upload error', async () => {
createComponent({ stubs: { GlEmptyState } });
wrapper.setData({ filesToBeSaved: [{ name: 'test' }] });
wrapper.vm.onUploadDesignError();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.filesToBeSaved).toEqual([]);
- expect(wrapper.vm.isSaving).toBeFalsy();
- expect(createFlash).toHaveBeenCalled();
-
- createFlash.mockReset();
- });
+ await nextTick();
+ expect(wrapper.vm.filesToBeSaved).toEqual([]);
+ expect(wrapper.vm.isSaving).toBeFalsy();
+ expect(createFlash).toHaveBeenCalled();
});
it('does not call mutation if createDesign is false', () => {
@@ -415,10 +406,6 @@ describe('Design management index page', () => {
describe('upload count limit', () => {
const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
- afterEach(() => {
- createFlash.mockReset();
- });
-
it('does not warn when the max files are uploaded', () => {
createComponent();
@@ -436,7 +423,7 @@ describe('Design management index page', () => {
});
});
- it('flashes warning if designs are skipped', () => {
+ it('flashes warning if designs are skipped', async () => {
createComponent({
mockMutate: () =>
Promise.resolve({
@@ -450,25 +437,22 @@ describe('Design management index page', () => {
},
]);
- return uploadDesign.then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
- message: 'Upload skipped. test.jpg did not change.',
- types: 'warning',
- });
+ await uploadDesign;
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Upload skipped. test.jpg did not change.',
+ types: 'warning',
});
});
describe('dragging onto an existing design', () => {
+ let mockMutate;
beforeEach(() => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
+ mockMutate = jest.fn().mockResolvedValue();
+ createComponent({ designs: mockDesigns, allVersions: [mockVersion], mockMutate });
});
- it('calls onUploadDesign with valid upload', () => {
- wrapper.setMethods({
- onUploadDesign: jest.fn(),
- });
-
+ it('uploads designs with valid upload', () => {
const mockUploadPayload = [
{
name: mockDesigns[0].filename,
@@ -478,8 +462,13 @@ describe('Design management index page', () => {
const designDropzone = findFirstDropzoneWithDesign();
designDropzone.vm.$emit('change', mockUploadPayload);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith(mockUploadPayload);
+ const [{ mutation, variables }] = mockMutate.mock.calls[0];
+ expect(mutation).toBe(uploadDesignMutation);
+ expect(variables).toStrictEqual({
+ files: mockUploadPayload,
+ iid: '1',
+ projectPath: 'project-path',
+ });
});
it.each`
@@ -544,57 +533,39 @@ describe('Design management index page', () => {
expect(findToolbar().isVisible()).toBe(true);
});
- it('adds two designs to selected designs when their checkboxes are checked', () => {
- findDesignCheckboxes()
- .at(0)
- .trigger('click');
-
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findDesignCheckboxes()
- .at(1)
- .trigger('click');
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findDeleteButton().exists()).toBe(true);
- expect(findSelectAllButton().text()).toBe('Deselect all');
- findDeleteButton().vm.$emit('deleteSelectedDesigns');
- const [{ variables }] = mutate.mock.calls[0];
- expect(variables.filenames).toStrictEqual([
- mockDesigns[0].filename,
- mockDesigns[1].filename,
- ]);
- });
+ it('adds two designs to selected designs when their checkboxes are checked', async () => {
+ findDesignCheckboxes().at(0).trigger('click');
+
+ await nextTick();
+ findDesignCheckboxes().at(1).trigger('click');
+
+ await nextTick();
+ expect(findDeleteButton().exists()).toBe(true);
+ expect(findSelectAllButton().text()).toBe('Deselect all');
+ findDeleteButton().vm.$emit('deleteSelectedDesigns');
+ const [{ variables }] = mutate.mock.calls[0];
+ expect(variables.filenames).toStrictEqual([mockDesigns[0].filename, mockDesigns[1].filename]);
});
- it('adds all designs to selected designs when Select All button is clicked', () => {
+ it('adds all designs to selected designs when Select All button is clicked', async () => {
findSelectAllButton().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findDeleteButton().props().hasSelectedDesigns).toBe(true);
- expect(findSelectAllButton().text()).toBe('Deselect all');
- expect(wrapper.vm.selectedDesigns).toEqual(mockDesigns.map(design => design.filename));
- });
+ await nextTick();
+ expect(findDeleteButton().props().hasSelectedDesigns).toBe(true);
+ expect(findSelectAllButton().text()).toBe('Deselect all');
+ expect(wrapper.vm.selectedDesigns).toEqual(mockDesigns.map((design) => design.filename));
});
- it('removes all designs from selected designs when at least one design was selected', () => {
- findDesignCheckboxes()
- .at(0)
- .trigger('click');
-
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findSelectAllButton().vm.$emit('click');
- })
- .then(() => {
- expect(findDeleteButton().props().hasSelectedDesigns).toBe(false);
- expect(findSelectAllButton().text()).toBe('Select all');
- expect(wrapper.vm.selectedDesigns).toEqual([]);
- });
+ it('removes all designs from selected designs when at least one design was selected', async () => {
+ findDesignCheckboxes().at(0).trigger('click');
+ await nextTick();
+
+ findSelectAllButton().vm.$emit('click');
+ await nextTick();
+
+ expect(findDeleteButton().props().hasSelectedDesigns).toBe(false);
+ expect(findSelectAllButton().text()).toBe('Select all');
+ expect(wrapper.vm.selectedDesigns).toEqual([]);
});
});
@@ -632,12 +603,10 @@ describe('Design management index page', () => {
describe('pasting a design', () => {
let event;
+ let mockMutate;
beforeEach(() => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
-
- wrapper.setMethods({
- onUploadDesign: jest.fn(),
- });
+ mockMutate = jest.fn().mockResolvedValue({});
+ createComponent({ designs: mockDesigns, allVersions: [mockVersion], mockMutate });
event = new Event('paste');
event.clipboardData = {
@@ -646,36 +615,56 @@ describe('Design management index page', () => {
};
});
- it('does not call paste event if designs wrapper is not hovered', () => {
+ it('does not upload designs if designs wrapper is not hovered', () => {
document.dispatchEvent(event);
- expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
+ expect(mockMutate).not.toHaveBeenCalled();
});
describe('when designs wrapper is hovered', () => {
+ let realDateNow;
+ const today = () => new Date('2020-12-25');
+ beforeAll(() => {
+ realDateNow = Date.now;
+ global.Date.now = today;
+ });
+
+ afterAll(() => {
+ global.Date.now = realDateNow;
+ });
+
beforeEach(() => {
findDesignsWrapper().trigger('mouseenter');
});
- it('calls onUploadDesign with valid paste', () => {
+ it('uploads design with valid paste', () => {
document.dispatchEvent(event);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([
- new File([{ name: 'image.png' }], 'test.png'),
- ]);
+ const [{ mutation, variables }] = mockMutate.mock.calls[0];
+ expect(mutation).toBe(uploadDesignMutation);
+ expect(variables).toStrictEqual({
+ files: expect.any(Array),
+ iid: '1',
+ projectPath: 'project-path',
+ });
+ expect(variables.files).toEqual(event.clipboardData.files.map((f) => new File([f], '')));
});
it('renames a design if it has an image.png filename', () => {
+ event.clipboardData.getData = () => 'image.png';
document.dispatchEvent(event);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([
- new File([{ name: 'image.png' }], `design_${Date.now()}.png`),
- ]);
+ const [{ mutation, variables }] = mockMutate.mock.calls[0];
+ expect(mutation).toBe(uploadDesignMutation);
+ expect(variables).toStrictEqual({
+ files: expect.any(Array),
+ iid: '1',
+ projectPath: 'project-path',
+ });
+ expect(variables.files[0].name).toEqual(`design_${Date.now()}.png`);
});
- it('does not call onUploadDesign with invalid paste', () => {
+ it('does not call upload with invalid paste', () => {
event.clipboardData = {
items: [{ type: 'text/plain' }, { type: 'text' }],
files: [],
@@ -683,28 +672,27 @@ describe('Design management index page', () => {
document.dispatchEvent(event);
- expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
+ expect(mockMutate).not.toHaveBeenCalled();
});
it('removes onPaste listener after mouseleave event', async () => {
findDesignsWrapper().trigger('mouseleave');
document.dispatchEvent(event);
- expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
+ expect(mockMutate).not.toHaveBeenCalled();
});
});
});
describe('when navigating', () => {
- it('should trigger a scrollIntoView method if designs route is detected', () => {
+ it('should trigger a scrollIntoView method if designs route is detected', async () => {
router.replace({
path: '/designs',
});
createComponent({ loading: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(scrollIntoViewMock).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(scrollIntoViewMock).toHaveBeenCalled();
});
});
@@ -713,14 +701,10 @@ describe('Design management index page', () => {
createComponentWithApollo({});
await jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDesigns()).toHaveLength(3);
- expect(
- findDesigns()
- .at(0)
- .props('id'),
- ).toBe('1');
+ expect(findDesigns().at(0).props('id')).toBe('1');
});
it('calls a mutation with correct parameters and reorders designs', async () => {
@@ -730,13 +714,9 @@ describe('Design management index page', () => {
expect(moveDesignHandler).toHaveBeenCalled();
- await wrapper.vm.$nextTick();
+ await nextTick();
- expect(
- findDesigns()
- .at(0)
- .props('id'),
- ).toBe('2');
+ expect(findDesigns().at(0).props('id')).toBe('2');
});
it('prevents reordering when reorderDesigns mutation is in progress', async () => {
@@ -747,8 +727,8 @@ describe('Design management index page', () => {
expect(draggableAttributes().disabled).toBe(true);
await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
- await wrapper.vm.$nextTick(); // kick off the DOM update
- await wrapper.vm.$nextTick(); // kick off the DOM update for finally block
+ await nextTick(); // kick off the DOM update
+ await nextTick(); // kick off the DOM update for finally block
expect(draggableAttributes().disabled).toBe(false);
});
@@ -760,7 +740,7 @@ describe('Design management index page', () => {
await moveDesigns(wrapper);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
@@ -772,9 +752,9 @@ describe('Design management index page', () => {
await moveDesigns(wrapper);
- await wrapper.vm.$nextTick(); // kick off the DOM update
+ await 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
+ await nextTick(); // kick off the DOM update for flash
expect(createFlash).toHaveBeenCalledWith({
message: 'Something went wrong when reordering designs. Please try again',
diff --git a/spec/frontend/design_management/router_spec.js b/spec/frontend/design_management/router_spec.js
index fac4f7d368d..0b4e68eea78 100644
--- a/spec/frontend/design_management/router_spec.js
+++ b/spec/frontend/design_management/router_spec.js
@@ -40,7 +40,7 @@ describe('Design management router', () => {
window.location.hash = '';
});
- describe.each([['/'], [{ name: DESIGNS_ROUTE_NAME }]])('root route', routeArg => {
+ describe.each([['/'], [{ name: DESIGNS_ROUTE_NAME }]])('root route', (routeArg) => {
it('pushes home component', () => {
const wrapper = factory(routeArg);
@@ -50,7 +50,7 @@ describe('Design management router', () => {
describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])(
'designs detail route',
- routeArg => {
+ (routeArg) => {
it('pushes designs detail component', () => {
const wrapper = factory(routeArg);
diff --git a/spec/frontend/design_management/utils/error_messages_spec.js b/spec/frontend/design_management/utils/error_messages_spec.js
index f5072c3b6b7..b80dcd9abde 100644
--- a/spec/frontend/design_management/utils/error_messages_spec.js
+++ b/spec/frontend/design_management/utils/error_messages_spec.js
@@ -3,7 +3,7 @@ import {
designUploadSkippedWarning,
} from '~/design_management/utils/error_messages';
-const mockFilenames = n =>
+const mockFilenames = (n) =>
Array(n)
.fill(0)
.map((_, i) => ({ filename: `${i + 1}.jpg` }));
@@ -14,7 +14,7 @@ describe('Error message', () => {
const pluralMsg = 'Could not archive designs. Please try again.';
describe('when [singular=true]', () => {
- it.each([[undefined], [true]])('uses singular grammar', singularOption => {
+ it.each([[undefined], [true]])('uses singular grammar', (singularOption) => {
expect(designDeletionError({ singular: singularOption })).toEqual(singularMsg);
});
});
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 416564b72c3..7fbeb33dd93 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -1,5 +1,6 @@
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
@@ -26,6 +27,8 @@ const TEST_ENDPOINT = `${TEST_HOST}/diff/endpoint`;
const COMMIT_URL = `${TEST_HOST}/COMMIT/OLD`;
const UPDATED_COMMIT_URL = `${TEST_HOST}/COMMIT/NEW`;
+Vue.use(Vuex);
+
function getCollapsedFilesWarning(wrapper) {
return wrapper.find(CollapsedFilesWarning);
}
@@ -37,7 +40,6 @@ describe('diffs/components/app', () => {
let mock;
function createComponent(props = {}, extendStore = () => {}, provisions = {}) {
- const localVue = createLocalVue();
const provide = {
...provisions,
glFeatures: {
@@ -45,16 +47,13 @@ describe('diffs/components/app', () => {
},
};
- localVue.use(Vuex);
-
store = createDiffsStore();
store.state.diffs.isLoading = false;
store.state.diffs.isTreeLoaded = true;
extendStore(store);
- wrapper = shallowMount(localVue.extend(App), {
- localVue,
+ wrapper = shallowMount(App, {
propsData: {
endpoint: TEST_ENDPOINT,
endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
@@ -70,11 +69,6 @@ describe('diffs/components/app', () => {
},
provide,
store,
- methods: {
- isLatestVersion() {
- return true;
- },
- },
});
}
@@ -102,13 +96,13 @@ describe('diffs/components/app', () => {
});
describe('fetch diff methods', () => {
- beforeEach(done => {
+ beforeEach(() => {
const fetchResolver = () => {
store.state.diffs.retrievingBatches = false;
store.state.notes.discussions = 'test';
return Promise.resolve({ real_size: 100 });
};
- jest.spyOn(window, 'requestIdleCallback').mockImplementation(fn => fn());
+ jest.spyOn(window, 'requestIdleCallback').mockImplementation((fn) => fn());
createComponent();
jest.spyOn(wrapper.vm, 'fetchDiffFilesMeta').mockImplementation(fetchResolver);
jest.spyOn(wrapper.vm, 'fetchDiffFilesBatch').mockImplementation(fetchResolver);
@@ -119,68 +113,55 @@ describe('diffs/components/app', () => {
jest.spyOn(wrapper.vm, 'unwatchRetrievingBatches').mockImplementation(() => {});
store.state.diffs.retrievingBatches = true;
store.state.diffs.diffFiles = [];
- wrapper.vm.$nextTick(done);
+ return nextTick();
});
- it('calls batch methods if diffsBatchLoad is enabled, and not latest version', done => {
+ it('calls batch methods if diffsBatchLoad is enabled, and not latest version', async () => {
expect(wrapper.vm.diffFilesLength).toEqual(0);
- wrapper.vm.isLatestVersion = () => false;
wrapper.vm.fetchData(false);
- setImmediate(() => {
- expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
- expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
- expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
- expect(wrapper.vm.diffFilesLength).toEqual(100);
- expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
- done();
- });
+ await nextTick();
+
+ expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
+ expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
+ expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
+ expect(wrapper.vm.diffFilesLength).toBe(100);
+ expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
});
- it('calls batch methods if diffsBatchLoad is enabled, and latest version', done => {
+ it('calls batch methods if diffsBatchLoad is enabled, and latest version', async () => {
expect(wrapper.vm.diffFilesLength).toEqual(0);
wrapper.vm.fetchData(false);
- setImmediate(() => {
- expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
- expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
- expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
- expect(wrapper.vm.diffFilesLength).toEqual(100);
- expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
- done();
- });
- });
- });
-
- it('adds container-limiting classes when showFileTree is false with inline diffs', () => {
- createComponent({}, ({ state }) => {
- state.diffs.showTreeList = false;
- state.diffs.isParallelView = false;
- });
-
- expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(true);
- });
+ await nextTick();
- it('does not add container-limiting classes when showFileTree is false with inline diffs', () => {
- createComponent({}, ({ state }) => {
- state.diffs.showTreeList = true;
- state.diffs.isParallelView = false;
+ expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
+ expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
+ expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
+ expect(wrapper.vm.diffFilesLength).toBe(100);
+ expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
});
-
- expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(false);
});
- it('does not add container-limiting classes when isFluidLayout', () => {
- createComponent({ isFluidLayout: true }, ({ state }) => {
- state.diffs.isParallelView = false;
- });
-
- expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(false);
- });
+ it.each`
+ props | state | expected
+ ${{ isFluidLayout: true }} | ${{ isParallelView: false }} | ${false}
+ ${{}} | ${{ isParallelView: false }} | ${true}
+ ${{}} | ${{ showTreeList: true, diffFiles: [{}], isParallelView: false }} | ${false}
+ ${{}} | ${{ showTreeList: false, diffFiles: [{}], isParallelView: false }} | ${true}
+ ${{}} | ${{ showTreeList: false, diffFiles: [], isParallelView: false }} | ${true}
+ `(
+ 'uses container-limiting classes ($expected) with state ($state) and props ($props)',
+ ({ props, state, expected }) => {
+ createComponent(props, ({ state: origState }) => Object.assign(origState.diffs, state));
+
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(expected);
+ },
+ );
it('displays loading icon on loading', () => {
createComponent({}, ({ state }) => {
@@ -216,28 +197,25 @@ describe('diffs/components/app', () => {
window.location.hash = 'ABC_123';
});
- it('sets highlighted row if hash exists in location object', done => {
+ it('sets highlighted row if hash exists in location object', async () => {
createComponent({
shouldShow: true,
});
// Component uses $nextTick so we wait until that has finished
- setImmediate(() => {
- expect(store.state.diffs.highlightedRow).toBe('ABC_123');
+ await nextTick();
- done();
- });
+ expect(store.state.diffs.highlightedRow).toBe('ABC_123');
});
- it('marks current diff file based on currently highlighted row', () => {
+ it('marks current diff file based on currently highlighted row', async () => {
createComponent({
shouldShow: true,
});
// Component uses $nextTick so we wait until that has finished
- return wrapper.vm.$nextTick().then(() => {
- expect(store.state.diffs.currentDiffFileId).toBe('ABC');
- });
+ await nextTick();
+ expect(store.state.diffs.currentDiffFileId).toBe('ABC');
});
});
@@ -261,23 +239,23 @@ describe('diffs/components/app', () => {
});
it('sets width of tree list', () => {
- createComponent();
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ file_hash: '111', file_path: '111.js' }];
+ });
expect(wrapper.find('.js-diff-tree-list').element.style.width).toEqual('320px');
});
});
- it('marks current diff file based on currently highlighted row', done => {
+ it('marks current diff file based on currently highlighted row', async () => {
createComponent({
shouldShow: true,
});
- // Component uses $nextTick so we wait until that has finished
- setImmediate(() => {
- expect(store.state.diffs.currentDiffFileId).toBe('ABC');
+ // Component uses nextTick so we wait until that has finished
+ await nextTick();
- done();
- });
+ expect(store.state.diffs.currentDiffFileId).toBe('ABC');
});
describe('empty state', () => {
@@ -297,79 +275,43 @@ describe('diffs/components/app', () => {
expect(wrapper.find(NoChanges).exists()).toBe(false);
expect(wrapper.findAll(DiffFile).length).toBe(1);
});
-
- it('does not render empty state when versions match', () => {
- createComponent({}, ({ state }) => {
- state.diffs.startVersion = mergeRequestDiff;
- state.diffs.mergeRequestDiff = mergeRequestDiff;
- });
-
- expect(wrapper.find(NoChanges).exists()).toBe(false);
- });
});
describe('keyboard shortcut navigation', () => {
let spies = [];
- let jumpSpy;
let moveSpy;
+ let jumpSpy;
- function setup(componentProps, featureFlags) {
- createComponent(
- componentProps,
- ({ state }) => {
- state.diffs.commit = { id: 'SHA123' };
- },
- { glFeatures: { mrCommitNeighborNav: true, ...featureFlags } },
- );
+ function setup(componentProps) {
+ createComponent(componentProps, ({ state }) => {
+ state.diffs.commit = { id: 'SHA123' };
+ });
moveSpy = jest.spyOn(wrapper.vm, 'moveToNeighboringCommit').mockImplementation(() => {});
- jumpSpy = jest.fn();
+ jumpSpy = jest.spyOn(wrapper.vm, 'jumpToFile').mockImplementation(() => {});
spies = [jumpSpy, moveSpy];
- wrapper.setMethods({
- jumpToFile: jumpSpy,
- });
}
describe('visible app', () => {
it.each`
- key | name | spy | args | featureFlags
- ${'['} | ${'jumpToFile'} | ${0} | ${[-1]} | ${{}}
- ${'k'} | ${'jumpToFile'} | ${0} | ${[-1]} | ${{}}
- ${']'} | ${'jumpToFile'} | ${0} | ${[+1]} | ${{}}
- ${'j'} | ${'jumpToFile'} | ${0} | ${[+1]} | ${{}}
- ${'x'} | ${'moveToNeighboringCommit'} | ${1} | ${[{ direction: 'previous' }]} | ${{ mrCommitNeighborNav: true }}
- ${'c'} | ${'moveToNeighboringCommit'} | ${1} | ${[{ direction: 'next' }]} | ${{ mrCommitNeighborNav: true }}
+ key | name | spy | args
+ ${'['} | ${'jumpToFile'} | ${0} | ${[-1]}
+ ${'k'} | ${'jumpToFile'} | ${0} | ${[-1]}
+ ${']'} | ${'jumpToFile'} | ${0} | ${[+1]}
+ ${'j'} | ${'jumpToFile'} | ${0} | ${[+1]}
+ ${'x'} | ${'moveToNeighboringCommit'} | ${1} | ${[{ direction: 'previous' }]}
+ ${'c'} | ${'moveToNeighboringCommit'} | ${1} | ${[{ direction: 'next' }]}
`(
'calls `$name()` with correct parameters whenever the "$key" key is pressed',
- ({ key, spy, args, featureFlags }) => {
- setup({ shouldShow: true }, featureFlags);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(spies[spy]).not.toHaveBeenCalled();
-
- Mousetrap.trigger(key);
-
- expect(spies[spy]).toHaveBeenCalledWith(...args);
- });
- },
- );
-
- it.each`
- key | name | spy | featureFlags
- ${'x'} | ${'moveToNeighboringCommit'} | ${1} | ${{ mrCommitNeighborNav: false }}
- ${'c'} | ${'moveToNeighboringCommit'} | ${1} | ${{ mrCommitNeighborNav: false }}
- `(
- 'does not call `$name()` even when the correct key is pressed if the feature flag is disabled',
- ({ key, spy, featureFlags }) => {
- setup({ shouldShow: true }, featureFlags);
+ async ({ key, spy, args }) => {
+ setup({ shouldShow: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(spies[spy]).not.toHaveBeenCalled();
+ await nextTick();
+ expect(spies[spy]).not.toHaveBeenCalled();
- Mousetrap.trigger(key);
+ Mousetrap.trigger(key);
- expect(spies[spy]).not.toHaveBeenCalled();
- });
+ expect(spies[spy]).toHaveBeenCalledWith(...args);
},
);
@@ -379,25 +321,23 @@ describe('diffs/components/app', () => {
${'r'} | ${'moveToNeighboringCommit'} | ${1} | ${['x', 'c']}
`(
`does not call \`$name()\` when a key that is not one of \`$allowed\` is pressed`,
- ({ key, spy }) => {
- setup({ shouldShow: true }, { mrCommitNeighborNav: true });
+ async ({ key, spy }) => {
+ setup({ shouldShow: true });
- return wrapper.vm.$nextTick().then(() => {
- Mousetrap.trigger(key);
+ await nextTick();
+ Mousetrap.trigger(key);
- expect(spies[spy]).not.toHaveBeenCalled();
- });
+ expect(spies[spy]).not.toHaveBeenCalled();
},
);
});
describe('hidden app', () => {
- beforeEach(() => {
- setup({ shouldShow: false }, { mrCommitNeighborNav: true });
+ beforeEach(async () => {
+ setup({ shouldShow: false });
- return wrapper.vm.$nextTick().then(() => {
- Mousetrap.reset();
- });
+ await nextTick();
+ Mousetrap.reset();
});
it.each`
@@ -420,8 +360,6 @@ describe('diffs/components/app', () => {
let spy;
beforeEach(() => {
- spy = jest.fn();
-
createComponent({}, () => {
store.state.diffs.diffFiles = [
{ file_hash: '111', file_path: '111.js' },
@@ -429,66 +367,49 @@ describe('diffs/components/app', () => {
{ file_hash: '333', file_path: '333.js' },
];
});
-
- wrapper.setMethods({
- scrollToFile: spy,
- });
+ spy = jest.spyOn(store, 'dispatch');
});
afterEach(() => {
wrapper.destroy();
});
- it('jumps to next and previous files in the list', done => {
- wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.vm.jumpToFile(+1);
+ it('jumps to next and previous files in the list', async () => {
+ await nextTick();
+
+ wrapper.vm.jumpToFile(+1);
- expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
- store.state.diffs.currentDiffFileId = '222';
- wrapper.vm.jumpToFile(+1);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '222.js']);
+ store.state.diffs.currentDiffFileId = '222';
+ wrapper.vm.jumpToFile(+1);
- expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['333.js']);
- store.state.diffs.currentDiffFileId = '333';
- wrapper.vm.jumpToFile(-1);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '333.js']);
+ store.state.diffs.currentDiffFileId = '333';
+ wrapper.vm.jumpToFile(-1);
- expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
- })
- .then(done)
- .catch(done.fail);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '222.js']);
});
- it('does not jump to previous file from the first one', done => {
- wrapper.vm
- .$nextTick()
- .then(() => {
- store.state.diffs.currentDiffFileId = '333';
+ it('does not jump to previous file from the first one', async () => {
+ await nextTick();
+ store.state.diffs.currentDiffFileId = '333';
- expect(wrapper.vm.currentDiffIndex).toEqual(2);
+ expect(wrapper.vm.currentDiffIndex).toBe(2);
- wrapper.vm.jumpToFile(+1);
+ wrapper.vm.jumpToFile(+1);
- expect(wrapper.vm.currentDiffIndex).toEqual(2);
- expect(spy).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(wrapper.vm.currentDiffIndex).toBe(2);
+ expect(spy).not.toHaveBeenCalled();
});
- it('does not jump to next file from the last one', done => {
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.vm.currentDiffIndex).toEqual(0);
+ it('does not jump to next file from the last one', async () => {
+ await nextTick();
+ expect(wrapper.vm.currentDiffIndex).toBe(0);
- wrapper.vm.jumpToFile(-1);
+ wrapper.vm.jumpToFile(-1);
- expect(wrapper.vm.currentDiffIndex).toEqual(0);
- expect(spy).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ expect(wrapper.vm.currentDiffIndex).toBe(0);
+ expect(spy).not.toHaveBeenCalled();
});
});
@@ -514,7 +435,7 @@ describe('diffs/components/app', () => {
window.location = location;
});
- it('when the commit changes and the app is not loading it should update the history, refetch the diff data, and update the view', () => {
+ it('when the commit changes and the app is not loading it should update the history, refetch the diff data, and update the view', async () => {
createComponent({}, ({ state }) => {
state.diffs.commit = { ...state.diffs.commit, id: 'OLD' };
});
@@ -522,14 +443,13 @@ describe('diffs/components/app', () => {
store.state.diffs.commit = { id: 'NEW' };
- return wrapper.vm.$nextTick().then(() => {
- expect(urlUtils.updateHistory).toHaveBeenCalledWith({
- title: document.title,
- url: UPDATED_COMMIT_URL,
- });
- expect(wrapper.vm.refetchDiffData).toHaveBeenCalled();
- expect(wrapper.vm.adjustView).toHaveBeenCalled();
+ await nextTick();
+ expect(urlUtils.updateHistory).toHaveBeenCalledWith({
+ title: document.title,
+ url: UPDATED_COMMIT_URL,
});
+ expect(wrapper.vm.refetchDiffData).toHaveBeenCalled();
+ expect(wrapper.vm.adjustView).toHaveBeenCalled();
});
it.each`
@@ -538,7 +458,7 @@ describe('diffs/components/app', () => {
${false} | ${'NEW'} | ${'NEW'}
`(
'given `{ "isLoading": $isLoading, "oldSha": "$oldSha", "newSha": "$newSha" }`, nothing should happen',
- ({ isLoading, oldSha, newSha }) => {
+ async ({ isLoading, oldSha, newSha }) => {
createComponent({}, ({ state }) => {
state.diffs.isLoading = isLoading;
state.diffs.commit = { ...state.diffs.commit, id: oldSha };
@@ -547,11 +467,10 @@ describe('diffs/components/app', () => {
store.state.diffs.commit = { id: newSha };
- return wrapper.vm.$nextTick().then(() => {
- expect(urlUtils.updateHistory).not.toHaveBeenCalled();
- expect(wrapper.vm.refetchDiffData).not.toHaveBeenCalled();
- expect(wrapper.vm.adjustView).not.toHaveBeenCalled();
- });
+ await nextTick();
+ expect(urlUtils.updateHistory).not.toHaveBeenCalled();
+ expect(wrapper.vm.refetchDiffData).not.toHaveBeenCalled();
+ expect(wrapper.vm.adjustView).not.toHaveBeenCalled();
},
);
});
@@ -559,6 +478,7 @@ describe('diffs/components/app', () => {
describe('diffs', () => {
it('should render compare versions component', () => {
createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ file_hash: '111', file_path: '111.js' }];
state.diffs.mergeRequestDiffs = diffsMockData;
state.diffs.targetBranchName = 'target-branch';
state.diffs.mergeRequestDiff = mergeRequestDiff;
@@ -567,7 +487,8 @@ describe('diffs/components/app', () => {
expect(wrapper.find(CompareVersions).exists()).toBe(true);
expect(wrapper.find(CompareVersions).props()).toEqual(
expect.objectContaining({
- mergeRequestDiffs: diffsMockData,
+ isLimitedContainer: false,
+ diffFilesCountText: null,
}),
);
});
@@ -635,20 +556,22 @@ describe('diffs/components/app', () => {
expect(wrapper.find(DiffFile).exists()).toBe(true);
});
- it('should render tree list', () => {
+ it("doesn't render tree list when no changes exist", () => {
createComponent();
- expect(wrapper.find(TreeList).exists()).toBe(true);
+ expect(wrapper.find(TreeList).exists()).toBe(false);
});
- });
- describe('setTreeDisplay', () => {
- let setShowTreeList;
+ it('should render tree list', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ file_hash: '111', file_path: '111.js' }];
+ });
- beforeEach(() => {
- setShowTreeList = jest.fn();
+ expect(wrapper.find(TreeList).exists()).toBe(true);
});
+ });
+ describe('setTreeDisplay', () => {
afterEach(() => {
localStorage.removeItem('mr_tree_show');
});
@@ -657,14 +580,13 @@ describe('diffs/components/app', () => {
createComponent({}, ({ state }) => {
state.diffs.diffFiles.push({ sha: '123' });
});
-
- wrapper.setMethods({
- setShowTreeList,
- });
-
+ jest.spyOn(store, 'dispatch');
wrapper.vm.setTreeDisplay();
- expect(setShowTreeList).toHaveBeenCalledWith({ showTreeList: false, saving: false });
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowTreeList', {
+ showTreeList: false,
+ saving: false,
+ });
});
it('calls setShowTreeList with true when more than 1 file is in diffs array', () => {
@@ -672,14 +594,14 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ sha: '123' });
state.diffs.diffFiles.push({ sha: '124' });
});
-
- wrapper.setMethods({
- setShowTreeList,
- });
+ jest.spyOn(store, 'dispatch');
wrapper.vm.setTreeDisplay();
- expect(setShowTreeList).toHaveBeenCalledWith({ showTreeList: true, saving: false });
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowTreeList', {
+ showTreeList: true,
+ saving: false,
+ });
});
it.each`
@@ -692,14 +614,14 @@ describe('diffs/components/app', () => {
createComponent({}, ({ state }) => {
state.diffs.diffFiles.push({ sha: '123' });
});
-
- wrapper.setMethods({
- setShowTreeList,
- });
+ jest.spyOn(store, 'dispatch');
wrapper.vm.setTreeDisplay();
- expect(setShowTreeList).toHaveBeenCalledWith({ showTreeList, saving: false });
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowTreeList', {
+ showTreeList,
+ saving: false,
+ });
});
});
@@ -710,7 +632,7 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ file_hash: '312' });
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findAll(DiffFile).length).toBe(1);
});
@@ -724,7 +646,7 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ file_hash: '123' }, { file_hash: '312' });
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(paginator().attributes('prevpage')).toBe(undefined);
expect(paginator().attributes('nextpage')).toBe('2');
@@ -736,7 +658,7 @@ describe('diffs/components/app', () => {
state.diffs.currentDiffFileId = '312';
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(paginator().attributes('prevpage')).toBe('1');
expect(paginator().attributes('nextpage')).toBe(undefined);
@@ -748,7 +670,7 @@ describe('diffs/components/app', () => {
state.diffs.currentDiffFileId = '123';
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(fileByFileNav().exists()).toBe(false);
});
@@ -765,13 +687,13 @@ describe('diffs/components/app', () => {
state.diffs.currentDiffFileId = currentDiffFileId;
});
- await wrapper.vm.$nextTick();
+ await nextTick();
jest.spyOn(wrapper.vm, 'navigateToDiffFileIndex');
paginator().vm.$emit('input', targetFile);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.vm.navigateToDiffFileIndex).toHaveBeenCalledWith(targetFile - 1);
},
@@ -787,10 +709,10 @@ describe('diffs/components/app', () => {
'triggers the action with the new fileByFile setting - $setting - when the event with that setting is received',
async ({ setting }) => {
createComponent();
- await wrapper.vm.$nextTick();
+ await nextTick();
eventHub.$emit(EVT_VIEW_FILE_BY_FILE, { setting });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(store.state.diffs.viewDiffsFileByFile).toBe(setting);
},
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index 8a7eb6aaca6..f588f65dafd 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -37,18 +37,12 @@ describe('diffs/components/commit_item', () => {
const getPrevCommitNavElement = () =>
getCommitNavButtonsElement().find('.btn-group > *:first-child');
- const mountComponent = (propsData, featureFlags = {}) => {
+ const mountComponent = (propsData) => {
wrapper = mount(Component, {
propsData: {
commit,
...propsData,
},
- provide: {
- glFeatures: {
- mrCommitNeighborNav: true,
- ...featureFlags,
- },
- },
stubs: {
CommitPipelineStatus: true,
},
@@ -224,12 +218,6 @@ describe('diffs/components/commit_item', () => {
expect(getCommitNavButtonsElement().exists()).toEqual(true);
});
- it('does not render the commit navigation buttons if the `mrCommitNeighborNav` feature flag is disabled', () => {
- mountComponent({ commit: mrCommit }, { mrCommitNeighborNav: false });
-
- expect(getCommitNavButtonsElement().exists()).toEqual(false);
- });
-
describe('prev commit', () => {
const { location } = window;
diff --git a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js
index 92e4a2d9c62..d99933a1ee9 100644
--- a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js
+++ b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js
@@ -31,7 +31,7 @@ describe('CompareDropdownLayout', () => {
const findListItems = () => wrapper.findAll('li');
const findListItemsData = () =>
- findListItems().wrappers.map(listItem => ({
+ findListItems().wrappers.map((listItem) => ({
href: listItem.find('a').attributes('href'),
text: trimText(listItem.text()),
createdAt: listItem.findAll(TimeAgo).wrappers[0]?.props('time'),
diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js
index 09e9669c474..949cc855200 100644
--- a/spec/frontend/diffs/components/compare_versions_spec.js
+++ b/spec/frontend/diffs/components/compare_versions_spec.js
@@ -11,32 +11,34 @@ localVue.use(Vuex);
describe('CompareVersions', () => {
let wrapper;
+ let store;
const targetBranchName = 'tmp-wine-dev';
- const createWrapper = props => {
- const store = createStore();
- const mergeRequestDiff = diffsMockData[0];
-
- store.state.diffs.addedLines = 10;
- store.state.diffs.removedLines = 20;
- store.state.diffs.diffFiles.push('test');
- store.state.diffs.targetBranchName = targetBranchName;
- store.state.diffs.mergeRequestDiff = mergeRequestDiff;
- store.state.diffs.mergeRequestDiffs = diffsMockData;
-
+ const createWrapper = (props) => {
wrapper = mount(CompareVersionsComponent, {
localVue,
store,
propsData: {
mergeRequestDiffs: diffsMockData,
- diffFilesCountText: null,
+ diffFilesCountText: '1',
...props,
},
});
};
+ const findLimitedContainer = () => wrapper.find('.container-limited.limit-container-width');
+ const findCompareSourceDropdown = () => wrapper.find('.mr-version-dropdown');
+ const findCompareTargetDropdown = () => wrapper.find('.mr-version-compare-dropdown');
beforeEach(() => {
- createWrapper();
+ store = createStore();
+ const mergeRequestDiff = diffsMockData[0];
+
+ store.state.diffs.addedLines = 10;
+ store.state.diffs.removedLines = 20;
+ store.state.diffs.diffFiles.push('test');
+ store.state.diffs.targetBranchName = targetBranchName;
+ store.state.diffs.mergeRequestDiff = mergeRequestDiff;
+ store.state.diffs.mergeRequestDiffs = diffsMockData;
});
afterEach(() => {
@@ -45,6 +47,10 @@ describe('CompareVersions', () => {
});
describe('template', () => {
+ beforeEach(() => {
+ createWrapper();
+ });
+
it('should render Tree List toggle button with correct attribute values', () => {
const treeListBtn = wrapper.find('.js-toggle-tree-list');
@@ -54,8 +60,8 @@ describe('CompareVersions', () => {
});
it('should render comparison dropdowns with correct values', () => {
- const sourceDropdown = wrapper.find('.mr-version-dropdown');
- const targetDropdown = wrapper.find('.mr-version-compare-dropdown');
+ const sourceDropdown = findCompareSourceDropdown();
+ const targetDropdown = findCompareTargetDropdown();
expect(sourceDropdown.exists()).toBe(true);
expect(targetDropdown.exists()).toBe(true);
@@ -63,16 +69,6 @@ describe('CompareVersions', () => {
expect(targetDropdown.find('button').html()).toContain(targetBranchName);
});
- it('should not render comparison dropdowns if no mergeRequestDiffs are specified', () => {
- createWrapper({ mergeRequestDiffs: [] });
-
- const sourceDropdown = wrapper.find('.mr-version-dropdown');
- const targetDropdown = wrapper.find('.mr-version-compare-dropdown');
-
- expect(sourceDropdown.exists()).toBe(false);
- expect(targetDropdown.exists()).toBe(false);
- });
-
it('should render view types buttons with correct values', () => {
const inlineBtn = wrapper.find('#inline-diff-btn');
const parallelBtn = wrapper.find('#parallel-diff-btn');
@@ -88,22 +84,34 @@ describe('CompareVersions', () => {
it('adds container-limiting classes when showFileTree is false with inline diffs', () => {
createWrapper({ isLimitedContainer: true });
- const limitedContainer = wrapper.find('.container-limited.limit-container-width');
-
- expect(limitedContainer.exists()).toBe(true);
+ expect(findLimitedContainer().exists()).toBe(true);
});
it('does not add container-limiting classes when showFileTree is false with inline diffs', () => {
createWrapper({ isLimitedContainer: false });
- const limitedContainer = wrapper.find('.container-limited.limit-container-width');
+ expect(findLimitedContainer().exists()).toBe(false);
+ });
+ });
- expect(limitedContainer.exists()).toBe(false);
+ describe('noChangedFiles', () => {
+ beforeEach(() => {
+ store.state.diffs.diffFiles = [];
+ });
+
+ it('should not render Tree List toggle button when there are no changes', () => {
+ createWrapper();
+
+ const treeListBtn = wrapper.find('.js-toggle-tree-list');
+
+ expect(treeListBtn.exists()).toBe(false);
});
});
describe('setInlineDiffViewType', () => {
it('should persist the view type in the url', () => {
+ createWrapper();
+
const viewTypeBtn = wrapper.find('#inline-diff-btn');
viewTypeBtn.trigger('click');
@@ -113,6 +121,7 @@ describe('CompareVersions', () => {
describe('setParallelDiffViewType', () => {
it('should persist the view type in the url', () => {
+ createWrapper();
const viewTypeBtn = wrapper.find('#parallel-diff-btn');
viewTypeBtn.trigger('click');
@@ -121,11 +130,14 @@ describe('CompareVersions', () => {
});
describe('commit', () => {
- beforeEach(done => {
- wrapper.vm.$store.state.diffs.commit = getDiffWithCommit().commit;
- wrapper.mergeRequestDiffs = [];
+ beforeEach(() => {
+ store.state.diffs.commit = getDiffWithCommit().commit;
+ createWrapper();
+ });
- wrapper.vm.$nextTick(done);
+ it('does not render compare dropdowns', () => {
+ expect(findCompareSourceDropdown().exists()).toBe(false);
+ expect(findCompareTargetDropdown().exists()).toBe(false);
});
it('renders latest version button', () => {
@@ -137,4 +149,16 @@ describe('CompareVersions', () => {
expect(wrapper.text()).toContain(wrapper.vm.commit.short_id);
});
});
+
+ describe('with no versions', () => {
+ beforeEach(() => {
+ store.state.diffs.mergeRequestDiffs = [];
+ createWrapper();
+ });
+
+ it('does not render compare dropdowns', () => {
+ expect(findCompareSourceDropdown().exists()).toBe(false);
+ expect(findCompareTargetDropdown().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 43d295ff1b3..c1cf4793c88 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -102,7 +102,7 @@ describe('DiffContent', () => {
describe('with text based files', () => {
afterEach(() => {
- [isParallelViewGetterMock, isInlineViewGetterMock].forEach(m => m.mockRestore());
+ [isParallelViewGetterMock, isInlineViewGetterMock].forEach((m) => m.mockRestore());
});
const textDiffFile = { ...defaultProps.diffFile, viewer: { name: diffViewerModes.text } };
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index 96b76183cee..5c390054247 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -15,7 +15,7 @@ describe('DiffDiscussions', () => {
let wrapper;
const getDiscussionsMockData = () => [{ ...discussionsMockData }];
- const createComponent = props => {
+ const createComponent = (props) => {
store = createStore();
wrapper = mount(localVue.extend(DiffDiscussions), {
store,
@@ -91,12 +91,7 @@ describe('DiffDiscussions', () => {
const noteableDiscussion = wrapper.find(NoteableDiscussion);
expect(noteableDiscussion.find('.badge-pill').exists()).toBe(true);
- expect(
- noteableDiscussion
- .find('.badge-pill')
- .text()
- .trim(),
- ).toBe('1');
+ expect(noteableDiscussion.find('.badge-pill').text().trim()).toBe('1');
});
});
});
diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
index a3b4b5c3abb..62e85b31f76 100644
--- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js
+++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
@@ -1,6 +1,5 @@
-import Vue from 'vue';
import { cloneDeep } from 'lodash';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import { getByText } from '@testing-library/dom';
import { createStore } from '~/mr_notes/stores';
import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
@@ -14,7 +13,7 @@ const lineSources = {
[INLINE_DIFF_VIEW_TYPE]: 'highlighted_diff_lines',
};
const lineHandlers = {
- [INLINE_DIFF_VIEW_TYPE]: line => line,
+ [INLINE_DIFF_VIEW_TYPE]: (line) => line,
};
function makeLoadMoreLinesPayload({
@@ -59,7 +58,6 @@ describe('DiffExpansionCell', () => {
let mockFile;
let mockLine;
let store;
- let vm;
beforeEach(() => {
mockFile = cloneDeep(diffFileMockData);
@@ -70,7 +68,6 @@ describe('DiffExpansionCell', () => {
});
const createComponent = (options = {}) => {
- const cmp = Vue.extend(DiffExpansionCell);
const defaults = {
fileHash: mockFile.file_hash,
contextLinesPath: 'contextLinesPath',
@@ -78,46 +75,46 @@ describe('DiffExpansionCell', () => {
isTop: false,
isBottom: false,
};
- const props = { ...defaults, ...options };
+ const propsData = { ...defaults, ...options };
- vm = createComponentWithStore(cmp, store, props).$mount();
+ return mount(DiffExpansionCell, { store, propsData });
};
- const findExpandUp = () => vm.$el.querySelector(EXPAND_UP_CLASS);
- const findExpandDown = () => vm.$el.querySelector(EXPAND_DOWN_CLASS);
- const findExpandAll = () => getByText(vm.$el, 'Show all unchanged lines');
+ const findExpandUp = (wrapper) => wrapper.find(EXPAND_UP_CLASS);
+ const findExpandDown = (wrapper) => wrapper.find(EXPAND_DOWN_CLASS);
+ const findExpandAll = ({ element }) => getByText(element, 'Show all unchanged lines');
describe('top row', () => {
it('should have "expand up" and "show all" option', () => {
- createComponent({
+ const wrapper = createComponent({
isTop: true,
});
- expect(findExpandUp()).not.toBe(null);
- expect(findExpandDown()).toBe(null);
- expect(findExpandAll()).not.toBe(null);
+ expect(findExpandUp(wrapper).exists()).toBe(true);
+ expect(findExpandDown(wrapper).exists()).toBe(false);
+ expect(findExpandAll(wrapper)).not.toBe(null);
});
});
describe('middle row', () => {
it('should have "expand down", "show all", "expand up" option', () => {
- createComponent();
+ const wrapper = createComponent();
- expect(findExpandUp()).not.toBe(null);
- expect(findExpandDown()).not.toBe(null);
- expect(findExpandAll()).not.toBe(null);
+ expect(findExpandUp(wrapper).exists()).toBe(true);
+ expect(findExpandDown(wrapper).exists()).toBe(true);
+ expect(findExpandAll(wrapper)).not.toBe(null);
});
});
describe('bottom row', () => {
it('should have "expand down" and "show all" option', () => {
- createComponent({
+ const wrapper = createComponent({
isBottom: true,
});
- expect(findExpandUp()).toBe(null);
- expect(findExpandDown()).not.toBe(null);
- expect(findExpandAll()).not.toBe(null);
+ expect(findExpandUp(wrapper).exists()).toBe(false);
+ expect(findExpandDown(wrapper).exists()).toBe(true);
+ expect(findExpandAll(wrapper)).not.toBe(null);
});
});
@@ -144,9 +141,9 @@ describe('DiffExpansionCell', () => {
newLineNumber,
});
- createComponent();
+ const wrapper = createComponent();
- findExpandAll().click();
+ findExpandAll(wrapper).click();
expect(store.dispatch).toHaveBeenCalledWith(
'diffs/loadMoreLines',
@@ -167,9 +164,9 @@ describe('DiffExpansionCell', () => {
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
- createComponent();
+ const wrapper = createComponent();
- findExpandUp().click();
+ findExpandUp(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith(
'diffs/loadMoreLines',
@@ -195,9 +192,9 @@ describe('DiffExpansionCell', () => {
mockLine.meta_data.old_pos = 200;
mockLine.meta_data.new_pos = 200;
- createComponent();
+ const wrapper = createComponent();
- findExpandDown().click();
+ findExpandDown(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('diffs/loadMoreLines', {
endpoint: 'contextLinesPath',
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index 1b41456f2f5..e9a63e861ed 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -62,7 +62,7 @@ describe('DiffFileHeader component', () => {
diffHasDiscussionsResultMock,
diffHasExpandedDiscussionsResultMock,
...Object.values(mockStoreConfig.modules.diffs.actions),
- ].forEach(mock => mock.mockReset());
+ ].forEach((mock) => mock.mockReset());
wrapper.destroy();
});
@@ -80,7 +80,7 @@ describe('DiffFileHeader component', () => {
const findCollapseIcon = () => wrapper.find({ ref: 'collapseIcon' });
const findEditButton = () => wrapper.find({ ref: 'editButton' });
- const createComponent = props => {
+ const createComponent = (props) => {
mockStoreConfig = cloneDeep(defaultMockStoreConfig);
const store = new Vuex.Store(mockStoreConfig);
@@ -219,7 +219,7 @@ describe('DiffFileHeader component', () => {
});
describe('for any file', () => {
- const otherModes = Object.keys(diffViewerModes).filter(m => m !== 'mode_changed');
+ const otherModes = Object.keys(diffViewerModes).filter((m) => m !== 'mode_changed');
it('for mode_changed file mode displays mode changes', () => {
createComponent({
@@ -236,20 +236,23 @@ describe('DiffFileHeader component', () => {
expect(findModeChangedLine().text()).toMatch(/old-mode.+new-mode/);
});
- it.each(otherModes.map(m => [m]))('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],
+ it.each(otherModes.map((m) => [m]))(
+ '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],
+ },
},
- },
- });
- expect(findModeChangedLine().exists()).toBeFalsy();
- });
+ });
+ expect(findModeChangedLine().exists()).toBeFalsy();
+ },
+ );
it('displays the LFS label for files stored in LFS', () => {
createComponent({
diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js
index 71e0ffd176f..c715d779986 100644
--- a/spec/frontend/diffs/components/diff_file_spec.js
+++ b/spec/frontend/diffs/components/diff_file_spec.js
@@ -1,6 +1,9 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+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';
@@ -96,13 +99,13 @@ function createComponent({ file, first = false, last = false }) {
};
}
-const findDiffHeader = wrapper => wrapper.find(DiffFileHeaderComponent);
-const findDiffContentArea = wrapper => wrapper.find('[data-testid="content-area"]');
-const findLoader = wrapper => wrapper.find('[data-testid="loader-icon"]');
-const findToggleButton = wrapper => wrapper.find('[data-testid="expand-button"]');
+const findDiffHeader = (wrapper) => wrapper.find(DiffFileHeaderComponent);
+const findDiffContentArea = (wrapper) => wrapper.find('[data-testid="content-area"]');
+const findLoader = (wrapper) => wrapper.find('[data-testid="loader-icon"]');
+const findToggleButton = (wrapper) => wrapper.find('[data-testid="expand-button"]');
-const toggleFile = wrapper => findDiffHeader(wrapper).vm.$emit('toggleFile');
-const isDisplayNone = element => element.style.display === 'none';
+const toggleFile = (wrapper) => findDiffHeader(wrapper).vm.$emit('toggleFile');
+const isDisplayNone = (element) => element.style.display === 'none';
const getReadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataReadable));
const getUnreadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataUnreadable));
@@ -118,14 +121,17 @@ const changeViewerType = (store, newType, index = 0) =>
describe('DiffFile', () => {
let wrapper;
let store;
+ let axiosMock;
beforeEach(() => {
+ axiosMock = new MockAdapter(axios);
({ wrapper, store } = createComponent({ file: getReadableFile() }));
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ axiosMock.restore();
});
describe('bus events', () => {
@@ -157,7 +163,7 @@ describe('DiffFile', () => {
await wrapper.vm.$nextTick();
expect(eventHub.$emit).toHaveBeenCalledTimes(events.length);
- events.forEach(event => {
+ events.forEach((event) => {
expect(eventHub.$emit).toHaveBeenCalledWith(event);
});
},
@@ -174,7 +180,7 @@ describe('DiffFile', () => {
}));
jest.spyOn(wrapper.vm, 'loadCollapsedDiff').mockResolvedValue(getReadableFile());
- jest.spyOn(window, 'requestIdleCallback').mockImplementation(fn => fn());
+ jest.spyOn(window, 'requestIdleCallback').mockImplementation((fn) => fn());
makeFileAutomaticallyCollapsed(store);
@@ -247,7 +253,7 @@ describe('DiffFile', () => {
it('should not have any content at all', async () => {
await wrapper.vm.$nextTick();
- Array.from(findDiffContentArea(wrapper).element.children).forEach(child => {
+ Array.from(findDiffContentArea(wrapper).element.children).forEach((child) => {
expect(isDisplayNone(child)).toBe(true);
});
});
@@ -353,8 +359,10 @@ describe('DiffFile', () => {
describe('loading', () => {
it('should have loading icon while loading a collapsed diffs', async () => {
+ const { load_collapsed_diff_url } = store.state.diffs.diffFiles[0];
+ axiosMock.onGet(load_collapsed_diff_url).reply(httpStatus.OK, getReadableFile());
makeFileAutomaticallyCollapsed(store);
- wrapper.vm.isLoadingCollapsedDiff = true;
+ wrapper.vm.requestDiff();
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/diffs/components/diff_gutter_avatars_spec.js b/spec/frontend/diffs/components/diff_gutter_avatars_spec.js
index 61e110b345a..5884a9ebd3a 100644
--- a/spec/frontend/diffs/components/diff_gutter_avatars_spec.js
+++ b/spec/frontend/diffs/components/diff_gutter_avatars_spec.js
@@ -66,9 +66,7 @@ describe('DiffGutterAvatars', () => {
});
it('should emit toggleDiscussions event on avatars click', () => {
- findUserAvatars()
- .at(0)
- .trigger('click');
+ findUserAvatars().at(0).trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
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 75ec5c202af..faa68159c58 100644
--- a/spec/frontend/diffs/components/diff_line_note_form_spec.js
+++ b/spec/frontend/diffs/components/diff_line_note_form_spec.js
@@ -11,14 +11,16 @@ describe('DiffLineNoteForm', () => {
let diffLines;
const getDiffFileMock = () => ({ ...diffFileMockData });
- beforeEach(() => {
+ const createComponent = (args = {}) => {
diffFile = getDiffFileMock();
diffLines = diffFile.highlighted_diff_lines;
const store = createStore();
store.state.notes.userData.id = 1;
store.state.notes.noteableData = noteableDataMock;
- wrapper = shallowMount(DiffLineNoteForm, {
+ store.replaceState({ ...store.state, ...args.state });
+
+ return shallowMount(DiffLineNoteForm, {
store,
propsData: {
diffFileHash: diffFile.file_hash,
@@ -27,9 +29,13 @@ describe('DiffLineNoteForm', () => {
noteTargetLine: diffLines[0],
},
});
- });
+ };
describe('methods', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
describe('handleCancelCommentForm', () => {
it('should ask for confirmation when shouldConfirm and isDirty passed as truthy', () => {
jest.spyOn(window, 'confirm').mockReturnValue(false);
@@ -51,7 +57,7 @@ describe('DiffLineNoteForm', () => {
expect(window.confirm).not.toHaveBeenCalled();
});
- it('should call cancelCommentForm with lineCode', done => {
+ it('should call cancelCommentForm with lineCode', (done) => {
jest.spyOn(window, 'confirm').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'cancelCommentForm').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'resetAutoSave').mockImplementation(() => {});
@@ -72,7 +78,7 @@ describe('DiffLineNoteForm', () => {
});
describe('saveNoteForm', () => {
- it('should call saveNote action with proper params', done => {
+ it('should call saveNote action with proper params', (done) => {
const saveDiffDiscussionSpy = jest
.spyOn(wrapper.vm, 'saveDiffDiscussion')
.mockReturnValue(Promise.resolve());
@@ -114,14 +120,39 @@ describe('DiffLineNoteForm', () => {
describe('mounted', () => {
it('should init autosave', () => {
const key = 'autosave/Note/Issue/98//DiffNote//1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1';
+ wrapper = createComponent();
expect(wrapper.vm.autosave).toBeDefined();
expect(wrapper.vm.autosave.key).toEqual(key);
});
+
+ it('should set selectedCommentPosition', () => {
+ wrapper = createComponent();
+ let startLineCode = wrapper.vm.commentLineStart.line_code;
+ let lineCode = wrapper.vm.line.line_code;
+
+ expect(startLineCode).toEqual(lineCode);
+ wrapper.destroy();
+
+ const state = {
+ notes: {
+ selectedCommentPosition: {
+ start: {
+ line_code: 'test',
+ },
+ },
+ },
+ };
+ wrapper = createComponent({ state });
+ startLineCode = wrapper.vm.commentLineStart.line_code;
+ lineCode = state.notes.selectedCommentPosition.start.line_code;
+ expect(startLineCode).toEqual(lineCode);
+ });
});
describe('template', () => {
it('should have note form', () => {
+ wrapper = createComponent();
expect(wrapper.find(NoteForm).exists()).toBe(true);
});
});
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
index 0ec075c8ad8..c06d8e78316 100644
--- a/spec/frontend/diffs/components/diff_row_spec.js
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -1,7 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { getByTestId, fireEvent } from '@testing-library/dom';
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';
describe('DiffRow', () => {
const testLines = [
@@ -42,16 +45,16 @@ describe('DiffRow', () => {
fileHash: 'abc',
filePath: 'abc',
line: {},
+ index: 0,
...props,
};
- return shallowMount(DiffRow, { propsData, localVue, store });
- };
- it('isHighlighted returns true if isCommented is true', () => {
- const props = { isCommented: true };
- const wrapper = createWrapper({ props });
- expect(wrapper.vm.isHighlighted).toBe(true);
- });
+ const provide = {
+ glFeatures: { dragCommentSelection: true },
+ };
+
+ return shallowMount(DiffRow, { propsData, localVue, store, provide });
+ };
it('isHighlighted returns true given line.left', () => {
const props = {
@@ -124,4 +127,88 @@ describe('DiffRow', () => {
const lineNumber = testLines[0].right.new_line;
expect(wrapper.find(`[data-linenumber="${lineNumber}"]`).exists()).toBe(true);
});
+
+ describe('drag operations', () => {
+ let line;
+
+ beforeEach(() => {
+ line = { ...testLines[0] };
+ });
+
+ it.each`
+ side
+ ${'left'}
+ ${'right'}
+ `('emits `enterdragging` onDragEnter $side side', ({ side }) => {
+ const expectation = { ...line[side], index: 0 };
+ const wrapper = createWrapper({ props: { line } });
+ fireEvent.dragEnter(getByTestId(wrapper.element, `${side}-side`));
+
+ expect(wrapper.emitted().enterdragging).toBeTruthy();
+ expect(wrapper.emitted().enterdragging[0]).toEqual([expectation]);
+ });
+
+ it.each`
+ side
+ ${'left'}
+ ${'right'}
+ `('emits `stopdragging` onDrop $side side', ({ side }) => {
+ const wrapper = createWrapper({ props: { line } });
+ fireEvent.dragEnd(getByTestId(wrapper.element, `${side}-side`));
+
+ expect(wrapper.emitted().stopdragging).toBeTruthy();
+ });
+ });
+
+ describe('sets coverage title and class', () => {
+ const thisLine = diffFileMockData.parallel_diff_lines[2];
+ const rightLine = diffFileMockData.parallel_diff_lines[2].right;
+
+ const mockDiffContent = {
+ diffFile: diffFileMockData,
+ shouldRenderDraftRow: jest.fn(),
+ hasParallelDraftLeft: jest.fn(),
+ hasParallelDraftRight: jest.fn(),
+ draftForLine: jest.fn(),
+ };
+
+ const applyMap = mapParallel(mockDiffContent);
+ const props = {
+ line: applyMap(thisLine),
+ fileHash: diffFileMockData.file_hash,
+ filePath: diffFileMockData.file_path,
+ contextLinesPath: 'contextLinesPath',
+ isHighlighted: false,
+ };
+ const name = diffFileMockData.file_path;
+ const line = rightLine.new_line;
+
+ it('for lines with coverage', () => {
+ const coverageFiles = { files: { [name]: { [line]: 5 } } };
+ const wrapper = createWrapper({ props, state: { coverageFiles } });
+ const coverage = wrapper.find('.line-coverage.right-side');
+
+ expect(coverage.attributes('title')).toContain('Test coverage: 5 hits');
+ expect(coverage.classes('coverage')).toBeTruthy();
+ });
+
+ it('for lines without coverage', () => {
+ const coverageFiles = { files: { [name]: { [line]: 0 } } };
+ const wrapper = createWrapper({ props, state: { coverageFiles } });
+ const coverage = wrapper.find('.line-coverage.right-side');
+
+ expect(coverage.attributes('title')).toContain('No test coverage');
+ expect(coverage.classes('no-coverage')).toBeTruthy();
+ });
+
+ it('for unknown lines', () => {
+ const coverageFiles = {};
+ const wrapper = createWrapper({ props, state: { coverageFiles } });
+ const coverage = wrapper.find('.line-coverage.right-side');
+
+ expect(coverage.attributes('title')).toBeFalsy();
+ expect(coverage.classes('coverage')).toBeFalsy();
+ expect(coverage.classes('no-coverage')).toBeFalsy();
+ });
+ });
});
diff --git a/spec/frontend/diffs/components/diff_row_utils_spec.js b/spec/frontend/diffs/components/diff_row_utils_spec.js
index c001857fa49..d70d6b609ac 100644
--- a/spec/frontend/diffs/components/diff_row_utils_spec.js
+++ b/spec/frontend/diffs/components/diff_row_utils_spec.js
@@ -126,14 +126,14 @@ describe('lineCode', () => {
describe('classNameMapCell', () => {
it.each`
- line | hll | loggedIn | hovered | expectation
- ${undefined} | ${true} | ${true} | ${true} | ${[]}
- ${{ type: 'new' }} | ${false} | ${false} | ${false} | ${['new', { hll: false, 'is-over': false }]}
- ${{ type: 'new' }} | ${true} | ${true} | ${false} | ${['new', { hll: true, 'is-over': false }]}
- ${{ type: 'new' }} | ${true} | ${false} | ${true} | ${['new', { hll: true, 'is-over': false }]}
- ${{ type: 'new' }} | ${true} | ${true} | ${true} | ${['new', { hll: true, 'is-over': true }]}
- `('should return $expectation', ({ line, hll, loggedIn, hovered, expectation }) => {
- const classes = utils.classNameMapCell(line, hll, loggedIn, hovered);
+ line | hll | isLoggedIn | isHover | expectation
+ ${undefined} | ${true} | ${true} | ${true} | ${[]}
+ ${{ type: 'new' }} | ${false} | ${false} | ${false} | ${['new', { hll: false, 'is-over': false, new_line: true, old_line: false }]}
+ ${{ type: 'new' }} | ${true} | ${true} | ${false} | ${['new', { hll: true, 'is-over': false, new_line: true, old_line: false }]}
+ ${{ type: 'new' }} | ${true} | ${false} | ${true} | ${['new', { hll: true, 'is-over': false, new_line: true, old_line: false }]}
+ ${{ type: 'new' }} | ${true} | ${true} | ${true} | ${['new', { hll: true, 'is-over': true, new_line: true, old_line: false }]}
+ `('should return $expectation', ({ line, hll, isLoggedIn, isHover, expectation }) => {
+ const classes = utils.classNameMapCell({ line, hll, isLoggedIn, isHover });
expect(classes).toEqual(expectation);
});
});
diff --git a/spec/frontend/diffs/components/diff_stats_spec.js b/spec/frontend/diffs/components/diff_stats_spec.js
index 4dcbb3ec332..0aaec027c0a 100644
--- a/spec/frontend/diffs/components/diff_stats_spec.js
+++ b/spec/frontend/diffs/components/diff_stats_spec.js
@@ -39,7 +39,7 @@ describe('diff_stats', () => {
});
describe('line changes', () => {
- const findFileLine = name => wrapper.find(name);
+ const findFileLine = (name) => wrapper.find(name);
it('shows the amount of lines added', () => {
expect(findFileLine('.js-file-addition-line').text()).toBe(TEST_ADDED_LINES.toString());
@@ -51,10 +51,10 @@ describe('diff_stats', () => {
});
describe('files changes', () => {
- const findIcon = name =>
+ const findIcon = (name) =>
wrapper
.findAll(GlIcon)
- .filter(c => c.attributes('name') === name)
+ .filter((c) => c.attributes('name') === name)
.at(0).element.parentNode;
it('shows amount of file changed with plural "files" when 0 files has changed', () => {
diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js
index 4d90112d8f6..3d36ebf14a3 100644
--- a/spec/frontend/diffs/components/diff_view_spec.js
+++ b/spec/frontend/diffs/components/diff_view_spec.js
@@ -1,19 +1,19 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import DiffView from '~/diffs/components/diff_view.vue';
-// import DraftNote from '~/batch_comments/components/draft_note.vue';
-// import DiffRow from '~/diffs/components/diff_row.vue';
-// import DiffCommentCell from '~/diffs/components/diff_comment_cell.vue';
-// import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
describe('DiffView', () => {
const DiffExpansionCell = { template: `<div/>` };
const DiffRow = { template: `<div/>` };
const DiffCommentCell = { template: `<div/>` };
const DraftNote = { template: `<div/>` };
- const createWrapper = props => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ const showCommentForm = jest.fn();
+ const setSelectedCommentPosition = jest.fn();
+ const getDiffRow = (wrapper) => wrapper.findComponent(DiffRow).vm;
+
+ const createWrapper = (props) => {
+ Vue.use(Vuex);
const batchComments = {
getters: {
@@ -26,8 +26,13 @@ describe('DiffView', () => {
},
namespaced: true,
};
- const diffs = { getters: { commitId: () => 'abc123' }, namespaced: true };
+ const diffs = {
+ actions: { showCommentForm },
+ getters: { commitId: () => 'abc123' },
+ namespaced: true,
+ };
const notes = {
+ actions: { setSelectedCommentPosition },
state: { selectedCommentPosition: null, selectedCommentPositionHover: null },
};
@@ -41,7 +46,7 @@ describe('DiffView', () => {
...props,
};
const stubs = { DiffExpansionCell, DiffRow, DiffCommentCell, DraftNote };
- return shallowMount(DiffView, { propsData, store, localVue, stubs });
+ return shallowMount(DiffView, { propsData, store, stubs });
};
it('renders a match line', () => {
@@ -64,12 +69,7 @@ describe('DiffView', () => {
inline: type === 'inline',
});
expect(wrapper.findAll(DiffCommentCell).length).toBe(total);
- expect(
- wrapper
- .find(container)
- .find(DiffCommentCell)
- .exists(),
- ).toBe(true);
+ expect(wrapper.find(container).find(DiffCommentCell).exists()).toBe(true);
},
);
@@ -79,4 +79,55 @@ describe('DiffView', () => {
});
expect(wrapper.find(DraftNote).exists()).toBe(true);
});
+
+ describe('drag operations', () => {
+ it('sets `dragStart` onStartDragging', () => {
+ const wrapper = createWrapper({ diffLines: [{}] });
+
+ wrapper.findComponent(DiffRow).vm.$emit('startdragging', { test: true });
+ expect(wrapper.vm.dragStart).toEqual({ test: true });
+ });
+
+ it('does not call `setSelectedCommentPosition` on different chunks onDragOver', () => {
+ const wrapper = createWrapper({ diffLines: [{}] });
+ const diffRow = getDiffRow(wrapper);
+
+ diffRow.$emit('startdragging', { chunk: 0 });
+ diffRow.$emit('enterdragging', { chunk: 1 });
+
+ expect(setSelectedCommentPosition).not.toHaveBeenCalled();
+ });
+
+ it.each`
+ start | end | expectation
+ ${1} | ${2} | ${{ start: { index: 1 }, end: { index: 2 } }}
+ ${2} | ${1} | ${{ start: { index: 1 }, end: { index: 2 } }}
+ ${1} | ${1} | ${{ start: { index: 1 }, end: { index: 1 } }}
+ `(
+ 'calls `setSelectedCommentPosition` with correct `updatedLineRange`',
+ ({ start, end, expectation }) => {
+ const wrapper = createWrapper({ diffLines: [{}] });
+ const diffRow = getDiffRow(wrapper);
+
+ diffRow.$emit('startdragging', { chunk: 1, index: start });
+ diffRow.$emit('enterdragging', { chunk: 1, index: end });
+
+ const arg = setSelectedCommentPosition.mock.calls[0][1];
+
+ expect(arg).toMatchObject(expectation);
+ },
+ );
+
+ it('sets `dragStart` to null onStopDragging', () => {
+ const wrapper = createWrapper({ diffLines: [{}] });
+ const diffRow = getDiffRow(wrapper);
+
+ diffRow.$emit('startdragging', { test: true });
+ expect(wrapper.vm.dragStart).toEqual({ test: true });
+
+ diffRow.$emit('stopdragging');
+ expect(wrapper.vm.dragStart).toBeNull();
+ expect(showCommentForm).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/diffs/components/file_row_stats_spec.js b/spec/frontend/diffs/components/file_row_stats_spec.js
index 34d85ba10b0..3f5a63c19e5 100644
--- a/spec/frontend/diffs/components/file_row_stats_spec.js
+++ b/spec/frontend/diffs/components/file_row_stats_spec.js
@@ -1,33 +1,21 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import FileRowStats from '~/diffs/components/file_row_stats.vue';
describe('Diff file row stats', () => {
- let Component;
- let vm;
-
- beforeAll(() => {
- Component = Vue.extend(FileRowStats);
- });
-
- beforeEach(() => {
- vm = mountComponent(Component, {
+ const wrapper = mount(FileRowStats, {
+ propsData: {
file: {
addedLines: 20,
removedLines: 10,
},
- });
- });
-
- afterEach(() => {
- vm.$destroy();
+ },
});
it('renders added lines count', () => {
- expect(vm.$el.querySelector('.cgreen').textContent).toContain('+20');
+ expect(wrapper.find('.cgreen').text()).toContain('+20');
});
it('renders removed lines count', () => {
- expect(vm.$el.querySelector('.cred').textContent).toContain('-10');
+ expect(wrapper.find('.cred').text()).toContain('-10');
});
});
diff --git a/spec/frontend/diffs/components/hidden_files_warning_spec.js b/spec/frontend/diffs/components/hidden_files_warning_spec.js
index 6fb4e4645f8..3f1f23a40f5 100644
--- a/spec/frontend/diffs/components/hidden_files_warning_spec.js
+++ b/spec/frontend/diffs/components/hidden_files_warning_spec.js
@@ -26,13 +26,15 @@ describe('HiddenFilesWarning', () => {
});
it('has a correct plain diff URL', () => {
- const plainDiffLink = wrapper.findAll('a').wrappers.filter(x => x.text() === 'Plain diff')[0];
+ const plainDiffLink = wrapper.findAll('a').wrappers.filter((x) => x.text() === 'Plain diff')[0];
expect(plainDiffLink.attributes('href')).toBe(propsData.plainDiffPath);
});
it('has a correct email patch URL', () => {
- const emailPatchLink = wrapper.findAll('a').wrappers.filter(x => x.text() === 'Email patch')[0];
+ const emailPatchLink = wrapper
+ .findAll('a')
+ .wrappers.filter((x) => x.text() === 'Email patch')[0];
expect(emailPatchLink.attributes('href')).toBe(propsData.emailPatchPath);
});
diff --git a/spec/frontend/diffs/components/image_diff_overlay_spec.js b/spec/frontend/diffs/components/image_diff_overlay_spec.js
index 087715111b4..93c9b922fdd 100644
--- a/spec/frontend/diffs/components/image_diff_overlay_spec.js
+++ b/spec/frontend/diffs/components/image_diff_overlay_spec.js
@@ -21,6 +21,11 @@ describe('Diffs image diff overlay component', () => {
wrapper = shallowMount(ImageDiffOverlay, {
store,
+ parentComponent: {
+ data() {
+ return dimensions;
+ },
+ },
propsData: {
discussions: [...imageDiffDiscussions],
fileHash: 'ABC',
@@ -28,9 +33,6 @@ describe('Diffs image diff overlay component', () => {
renderedHeight: 200,
...props,
},
- methods: {
- getImageDimensions: jest.fn().mockReturnValue(dimensions),
- },
});
}
@@ -49,18 +51,8 @@ describe('Diffs image diff overlay component', () => {
createComponent();
const imageBadges = getAllImageBadges();
- expect(
- imageBadges
- .at(0)
- .text()
- .trim(),
- ).toBe('1');
- expect(
- imageBadges
- .at(1)
- .text()
- .trim(),
- ).toBe('2');
+ expect(imageBadges.at(0).text().trim()).toBe('1');
+ expect(imageBadges.at(1).text().trim()).toBe('2');
});
it('renders icon when showCommentIcon is true', () => {
@@ -124,7 +116,7 @@ describe('Diffs image diff overlay component', () => {
describe('comment form', () => {
const getCommentIndicator = () => wrapper.find('.comment-indicator');
beforeEach(() => {
- createComponent({ canComment: true }, store => {
+ createComponent({ canComment: true }, (store) => {
store.state.diffs.commentForms.push({
fileHash: 'ABC',
x: 20,
diff --git a/spec/frontend/diffs/components/no_changes_spec.js b/spec/frontend/diffs/components/no_changes_spec.js
index 78805a1cddc..df9af51f9cf 100644
--- a/spec/frontend/diffs/components/no_changes_spec.js
+++ b/spec/frontend/diffs/components/no_changes_spec.js
@@ -1,20 +1,22 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+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 diffsMockData from '../mock_data/merge_request_diffs';
-describe('Diff no changes empty state', () => {
- let vm;
+const localVue = createLocalVue();
+localVue.use(Vuex);
- function createComponent(extendStore = () => {}) {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+const TEST_TARGET_BRANCH = 'foo';
+const TEST_SOURCE_BRANCH = 'dev/update';
- const store = createStore();
- extendStore(store);
+describe('Diff no changes empty state', () => {
+ let wrapper;
+ let store;
- vm = shallowMount(NoChanges, {
+ function createComponent(mountFn = shallowMount) {
+ wrapper = mountFn(NoChanges, {
localVue,
store,
propsData: {
@@ -23,26 +25,61 @@ describe('Diff no changes empty state', () => {
});
}
+ beforeEach(() => {
+ store = createStore();
+ store.state.diffs.mergeRequestDiff = {};
+ store.state.notes.noteableData = {
+ target_branch: TEST_TARGET_BRANCH,
+ source_branch: TEST_SOURCE_BRANCH,
+ };
+ store.state.diffs.mergeRequestDiffs = diffsMockData;
+ });
+
afterEach(() => {
- vm.destroy();
+ wrapper.destroy();
+ wrapper = null;
});
+ const findMessage = () => wrapper.find('[data-testid="no-changes-message"]');
+
it('prevents XSS', () => {
- createComponent(store => {
- // eslint-disable-next-line no-param-reassign
- store.state.notes.noteableData = {
- source_branch: '<script>alert("test");</script>',
- target_branch: '<script>alert("test");</script>',
- };
- });
+ store.state.notes.noteableData = {
+ source_branch: '<script>alert("test");</script>',
+ target_branch: '<script>alert("test");</script>',
+ };
- expect(vm.find('script').exists()).toBe(false);
+ createComponent();
+
+ expect(wrapper.find('script').exists()).toBe(false);
});
describe('Renders', () => {
it('Show create commit button', () => {
createComponent();
- expect(vm.find(GlButton).exists()).toBe(true);
+
+ expect(wrapper.find(GlButton).exists()).toBe(true);
});
+
+ it.each`
+ expectedText | sourceIndex | targetIndex
+ ${`No changes between ${TEST_SOURCE_BRANCH} and ${TEST_TARGET_BRANCH}`} | ${null} | ${null}
+ ${`No changes between ${TEST_SOURCE_BRANCH} and version 1`} | ${diffsMockData[0].version_index} | ${1}
+ ${`No changes between version 3 and version 2`} | ${3} | ${2}
+ ${`No changes between version 3 and ${TEST_TARGET_BRANCH}`} | ${3} | ${-1}
+ `(
+ 'renders text "$expectedText" (sourceIndex=$sourceIndex and targetIndex=$targetIndex)',
+ ({ expectedText, targetIndex, sourceIndex }) => {
+ if (targetIndex !== null) {
+ store.state.diffs.startVersion = { version_index: targetIndex };
+ }
+ if (sourceIndex !== null) {
+ store.state.diffs.mergeRequestDiff.version_index = sourceIndex;
+ }
+
+ createComponent(mount);
+
+ expect(findMessage().text()).toBe(expectedText);
+ },
+ );
});
});
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 57eff177261..445553706b7 100644
--- a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
@@ -40,7 +40,7 @@ describe('ParallelDiffTableRow', () => {
vm = wrapper.vm;
});
- it('does not highlight non empty line content when line does not match highlighted row', done => {
+ it('does not highlight non empty line content when line does not match highlighted row', (done) => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.line_content.right-side').classList).not.toContain('hll');
@@ -49,7 +49,7 @@ describe('ParallelDiffTableRow', () => {
.catch(done.fail);
});
- it('highlights nonempty line content when line is the highlighted row', done => {
+ it('highlights nonempty line content when line is the highlighted row', (done) => {
vm.$nextTick()
.then(() => {
vm.$store.state.diffs.highlightedRow = rightLine.line_code;
@@ -86,7 +86,7 @@ describe('ParallelDiffTableRow', () => {
}).$mount();
});
- it('does not highlight either line when line does not match highlighted row', done => {
+ it('does not highlight either line when line does not match highlighted row', (done) => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.line_content.right-side').classList).not.toContain('hll');
@@ -96,7 +96,7 @@ describe('ParallelDiffTableRow', () => {
.catch(done.fail);
});
- it('adds hll class to lineContent when line is the highlighted row', done => {
+ it('adds hll class to lineContent when line is the highlighted row', (done) => {
vm.$nextTick()
.then(() => {
vm.$store.state.diffs.highlightedRow = rightLine.line_code;
@@ -112,7 +112,7 @@ describe('ParallelDiffTableRow', () => {
});
describe('sets coverage title and class', () => {
- it('for lines with coverage', done => {
+ it('for lines with coverage', (done) => {
vm.$nextTick()
.then(() => {
const name = diffFileMockData.file_path;
@@ -132,7 +132,7 @@ describe('ParallelDiffTableRow', () => {
.catch(done.fail);
});
- it('for lines without coverage', done => {
+ it('for lines without coverage', (done) => {
vm.$nextTick()
.then(() => {
const name = diffFileMockData.file_path;
@@ -152,7 +152,7 @@ describe('ParallelDiffTableRow', () => {
.catch(done.fail);
});
- it('for unknown lines', done => {
+ it('for unknown lines', (done) => {
vm.$nextTick()
.then(() => {
vm.$store.state.diffs.coverageFiles = {};
diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js
index eb9f9b4db73..fcb627c570a 100644
--- a/spec/frontend/diffs/components/settings_dropdown_spec.js
+++ b/spec/frontend/diffs/components/settings_dropdown_spec.js
@@ -73,7 +73,7 @@ describe('Diff settings dropdown component', () => {
});
it('sets list button as selected when renderTreeList is false', () => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
renderTreeList: false,
});
@@ -84,7 +84,7 @@ describe('Diff settings dropdown component', () => {
});
it('sets tree button as selected when renderTreeList is true', () => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
renderTreeList: true,
});
@@ -97,7 +97,7 @@ describe('Diff settings dropdown component', () => {
describe('compare changes', () => {
it('sets inline button as selected', () => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
diffViewType: INLINE_DIFF_VIEW_TYPE,
});
@@ -108,7 +108,7 @@ describe('Diff settings dropdown component', () => {
});
it('sets parallel button as selected', () => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
diffViewType: PARALLEL_DIFF_VIEW_TYPE,
});
@@ -137,7 +137,7 @@ describe('Diff settings dropdown component', () => {
describe('whitespace toggle', () => {
it('does not set as checked when showWhitespace is false', () => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
showWhitespace: false,
});
@@ -147,7 +147,7 @@ describe('Diff settings dropdown component', () => {
});
it('sets as checked when showWhitespace is true', () => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
showWhitespace: true,
});
@@ -183,7 +183,7 @@ describe('Diff settings dropdown component', () => {
`(
'sets the checkbox to { checked: $checked } if the fileByFile setting is $fileByFile',
async ({ fileByFile, checked }) => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
viewDiffsFileByFile: fileByFile,
});
@@ -202,7 +202,7 @@ describe('Diff settings dropdown component', () => {
`(
'when the file by file setting starts as $start, toggling the checkbox should emit an event set to $emit',
async ({ start, emit }) => {
- createComponent(store => {
+ createComponent((store) => {
Object.assign(store.state.diffs, {
viewDiffsFileByFile: start,
});
diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js
index c89403e4869..4666321e0c2 100644
--- a/spec/frontend/diffs/components/tree_list_spec.js
+++ b/spec/frontend/diffs/components/tree_list_spec.js
@@ -88,16 +88,8 @@ describe('Diffs tree list component', () => {
it('renders tree', () => {
expect(getFileRows()).toHaveLength(2);
- expect(
- getFileRows()
- .at(0)
- .html(),
- ).toContain('index.js');
- expect(
- getFileRows()
- .at(1)
- .html(),
- ).toContain('app');
+ expect(getFileRows().at(0).html()).toContain('index.js');
+ expect(getFileRows().at(1).html()).toContain('app');
});
it('hides file stats', () => {
@@ -111,9 +103,7 @@ describe('Diffs tree list component', () => {
it('calls toggleTreeOpen when clicking folder', () => {
jest.spyOn(wrapper.vm.$store, 'dispatch').mockReturnValue(undefined);
- getFileRows()
- .at(1)
- .trigger('click');
+ getFileRows().at(1).trigger('click');
expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('diffs/toggleTreeOpen', 'app');
});
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index fef7676e795..056ac23fcf7 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -2,7 +2,8 @@ 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 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
import {
DIFF_VIEW_COOKIE_NAME,
INLINE_DIFF_VIEW_TYPE,
@@ -49,11 +50,11 @@ import {
setCurrentDiffFileIdFromNote,
navigateToDiffFileIndex,
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 testAction from '../../helpers/vuex_action_helper';
import * as utils from '~/diffs/store/utils';
import * as commonUtils from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -77,22 +78,22 @@ describe('DiffsStoreActions', () => {
jest.spyOn(commonUtils, 'scrollToElement').mockImplementation(() => null);
jest.spyOn(utils, 'convertExpandLines').mockImplementation(() => null);
jest.spyOn(utils, 'idleCallback').mockImplementation(() => null);
- ['requestAnimationFrame', 'requestIdleCallback'].forEach(method => {
- global[method] = cb => {
+ ['requestAnimationFrame', 'requestIdleCallback'].forEach((method) => {
+ global[method] = (cb) => {
cb();
};
});
});
afterEach(() => {
- ['requestAnimationFrame', 'requestIdleCallback'].forEach(method => {
+ ['requestAnimationFrame', 'requestIdleCallback'].forEach((method) => {
global[method] = originalMethods[method];
});
createFlash.mockClear();
});
describe('setBaseConfig', () => {
- it('should set given endpoint and project path', done => {
+ it('should set given endpoint and project path', (done) => {
const endpoint = '/diffs/set/endpoint';
const endpointMetadata = '/diffs/set/endpoint/metadata';
const endpointBatch = '/diffs/set/endpoint/batch';
@@ -152,7 +153,7 @@ describe('DiffsStoreActions', () => {
mock.restore();
});
- it('should fetch batch diff files', done => {
+ it('should fetch batch diff files', (done) => {
const endpointBatch = '/fetch/diffs_batch';
const res1 = { diff_files: [{ file_hash: 'test' }], pagination: { next_page: 2 } };
const res2 = { diff_files: [{ file_hash: 'test2' }], pagination: {} };
@@ -240,7 +241,7 @@ describe('DiffsStoreActions', () => {
mock.onGet(endpointMetadata).reply(200, diffMetadata);
});
- it('should fetch diff meta information', done => {
+ it('should fetch diff meta information', (done) => {
testAction(
fetchDiffFilesMeta,
{},
@@ -270,8 +271,8 @@ describe('DiffsStoreActions', () => {
afterEach(() => mock.restore());
- it('should commit SET_COVERAGE_DATA with received response', done => {
- const data = { files: { 'app.js': { '1': 0, '2': 1 } } };
+ it('should commit SET_COVERAGE_DATA with received response', (done) => {
+ const data = { files: { 'app.js': { 1: 0, 2: 1 } } };
mock.onGet(endpointCoverage).reply(200, { data });
@@ -285,7 +286,7 @@ describe('DiffsStoreActions', () => {
);
});
- it('should show flash on API error', done => {
+ it('should show flash on API error', (done) => {
mock.onGet(endpointCoverage).reply(400);
testAction(fetchCoverageFiles, {}, { endpointCoverage }, [], [], () => {
@@ -310,7 +311,7 @@ describe('DiffsStoreActions', () => {
window.location.hash = '';
});
- it('should merge discussions into diffs', done => {
+ it('should merge discussions into diffs', (done) => {
window.location.hash = 'ABC_123';
const state = {
@@ -404,7 +405,7 @@ describe('DiffsStoreActions', () => {
);
});
- it('dispatches setCurrentDiffFileIdFromNote with note ID', done => {
+ it('dispatches setCurrentDiffFileIdFromNote with note ID', (done) => {
window.location.hash = 'note_123';
testAction(
@@ -419,7 +420,7 @@ describe('DiffsStoreActions', () => {
});
describe('removeDiscussionsFromDiff', () => {
- it('should remove discussions from diffs', done => {
+ it('should remove discussions from diffs', (done) => {
const state = {
diffFiles: [
{
@@ -511,7 +512,7 @@ describe('DiffsStoreActions', () => {
});
describe('setInlineDiffViewType', () => {
- it('should set diff view type to inline and also set the cookie properly', done => {
+ it('should set diff view type to inline and also set the cookie properly', (done) => {
testAction(
setInlineDiffViewType,
null,
@@ -529,7 +530,7 @@ describe('DiffsStoreActions', () => {
});
describe('setParallelDiffViewType', () => {
- it('should set diff view type to parallel and also set the cookie properly', done => {
+ it('should set diff view type to parallel and also set the cookie properly', (done) => {
testAction(
setParallelDiffViewType,
null,
@@ -547,7 +548,7 @@ describe('DiffsStoreActions', () => {
});
describe('showCommentForm', () => {
- it('should call mutation to show comment form', done => {
+ it('should call mutation to show comment form', (done) => {
const payload = { lineCode: 'lineCode', fileHash: 'hash' };
testAction(
@@ -562,7 +563,7 @@ describe('DiffsStoreActions', () => {
});
describe('cancelCommentForm', () => {
- it('should call mutation to cancel comment form', done => {
+ it('should call mutation to cancel comment form', (done) => {
const payload = { lineCode: 'lineCode', fileHash: 'hash' };
testAction(
@@ -577,7 +578,7 @@ describe('DiffsStoreActions', () => {
});
describe('loadMoreLines', () => {
- it('should call mutation to show comment form', done => {
+ it('should call mutation to show comment form', (done) => {
const endpoint = '/diffs/load/more/lines';
const params = { since: 6, to: 26 };
const lineNumbers = { oldLineNumber: 3, newLineNumber: 5 };
@@ -610,7 +611,7 @@ describe('DiffsStoreActions', () => {
describe('loadCollapsedDiff', () => {
const state = { showWhitespace: true };
- it('should fetch data and call mutation with response and the give parameter', done => {
+ it('should fetch data and call mutation with response and the give parameter', (done) => {
const file = { hash: 123, load_collapsed_diff_url: '/load/collapsed/diff/url' };
const data = { hash: 123, parallelDiffLines: [{ lineCode: 1 }] };
const mock = new MockAdapter(axios);
@@ -810,7 +811,7 @@ describe('DiffsStoreActions', () => {
});
describe('saveDiffDiscussion', () => {
- it('dispatches actions', done => {
+ it('dispatches actions', (done) => {
const commitId = 'something';
const formData = {
diffFile: { ...mockDiffFile },
@@ -822,7 +823,7 @@ describe('DiffsStoreActions', () => {
id: commitId,
},
};
- const dispatch = jest.fn(name => {
+ const dispatch = jest.fn((name) => {
switch (name) {
case 'saveNote':
return Promise.resolve({
@@ -854,7 +855,7 @@ describe('DiffsStoreActions', () => {
});
describe('toggleTreeOpen', () => {
- it('commits TOGGLE_FOLDER_OPEN', done => {
+ it('commits TOGGLE_FOLDER_OPEN', (done) => {
testAction(
toggleTreeOpen,
'path',
@@ -903,7 +904,7 @@ describe('DiffsStoreActions', () => {
});
describe('setShowTreeList', () => {
- it('commits toggle', done => {
+ it('commits toggle', (done) => {
testAction(
setShowTreeList,
{ showTreeList: true },
@@ -991,7 +992,7 @@ describe('DiffsStoreActions', () => {
});
describe('setRenderTreeList', () => {
- it('commits SET_RENDER_TREE_LIST', done => {
+ it('commits SET_RENDER_TREE_LIST', (done) => {
testAction(
setRenderTreeList,
true,
@@ -1014,7 +1015,7 @@ describe('DiffsStoreActions', () => {
jest.spyOn(eventHub, '$emit').mockImplementation();
});
- it('commits SET_SHOW_WHITESPACE', done => {
+ it('commits SET_SHOW_WHITESPACE', (done) => {
testAction(
setShowWhitespace,
{ showWhitespace: true },
@@ -1057,13 +1058,13 @@ describe('DiffsStoreActions', () => {
});
describe('setRenderIt', () => {
- it('commits RENDER_FILE', done => {
+ it('commits RENDER_FILE', (done) => {
testAction(setRenderIt, 'file', {}, [{ type: types.RENDER_FILE, payload: 'file' }], [], done);
});
});
describe('receiveFullDiffError', () => {
- it('updates state with the file that did not load', done => {
+ it('updates state with the file that did not load', (done) => {
testAction(
receiveFullDiffError,
'file',
@@ -1091,7 +1092,7 @@ describe('DiffsStoreActions', () => {
mock.onGet(`${TEST_HOST}/context`).replyOnce(200, ['test']);
});
- it('commits the success and dispatches an action to expand the new lines', done => {
+ it('commits the success and dispatches an action to expand the new lines', (done) => {
const file = {
context_lines_path: `${TEST_HOST}/context`,
file_path: 'test',
@@ -1113,7 +1114,7 @@ describe('DiffsStoreActions', () => {
mock.onGet(`${TEST_HOST}/context`).replyOnce(500);
});
- it('dispatches receiveFullDiffError', done => {
+ it('dispatches receiveFullDiffError', (done) => {
testAction(
fetchFullDiff,
{ context_lines_path: `${TEST_HOST}/context`, file_path: 'test', file_hash: 'test' },
@@ -1135,7 +1136,7 @@ describe('DiffsStoreActions', () => {
};
});
- it('dispatches fetchFullDiff when file is not expanded', done => {
+ it('dispatches fetchFullDiff when file is not expanded', (done) => {
testAction(
toggleFullDiff,
'test',
@@ -1211,7 +1212,7 @@ describe('DiffsStoreActions', () => {
});
describe('setFileUserCollapsed', () => {
- it('commits SET_FILE_COLLAPSED', done => {
+ it('commits SET_FILE_COLLAPSED', (done) => {
testAction(
setFileCollapsedByUser,
{ filePath: 'test', collapsed: true },
@@ -1230,12 +1231,12 @@ describe('DiffsStoreActions', () => {
describe('setExpandedDiffLines', () => {
beforeEach(() => {
- utils.idleCallback.mockImplementation(cb => {
+ utils.idleCallback.mockImplementation((cb) => {
cb({ timeRemaining: () => 50 });
});
});
- it('commits SET_CURRENT_VIEW_DIFF_FILE_LINES when lines less than MAX_RENDERING_DIFF_LINES', done => {
+ it('commits SET_CURRENT_VIEW_DIFF_FILE_LINES when lines less than MAX_RENDERING_DIFF_LINES', (done) => {
utils.convertExpandLines.mockImplementation(() => ['test']);
testAction(
@@ -1253,7 +1254,7 @@ describe('DiffsStoreActions', () => {
);
});
- it('commits ADD_CURRENT_VIEW_DIFF_FILE_LINES when lines more than MAX_RENDERING_DIFF_LINES', done => {
+ it('commits ADD_CURRENT_VIEW_DIFF_FILE_LINES when lines more than MAX_RENDERING_DIFF_LINES', (done) => {
const lines = new Array(501).fill().map((_, i) => `line-${i}`);
utils.convertExpandLines.mockReturnValue(lines);
@@ -1280,7 +1281,7 @@ describe('DiffsStoreActions', () => {
});
describe('setSuggestPopoverDismissed', () => {
- it('commits SET_SHOW_SUGGEST_POPOVER', done => {
+ it('commits SET_SHOW_SUGGEST_POPOVER', (done) => {
const state = { dismissEndpoint: `${TEST_HOST}/-/user_callouts` };
const mock = new MockAdapter(axios);
mock.onPost(state.dismissEndpoint).reply(200, {});
@@ -1409,7 +1410,7 @@ describe('DiffsStoreActions', () => {
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
getDiscussion: () => ({ diff_file: { file_hash: '123' } }),
- notesById: { '1': { discussion_id: '2' } },
+ notesById: { 1: { discussion_id: '2' } },
};
setCurrentDiffFileIdFromNote({ commit, state, rootGetters }, '1');
@@ -1422,7 +1423,7 @@ describe('DiffsStoreActions', () => {
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
getDiscussion: () => ({ id: '1' }),
- notesById: { '1': { discussion_id: '2' } },
+ notesById: { 1: { discussion_id: '2' } },
};
setCurrentDiffFileIdFromNote({ commit, state, rootGetters }, '1');
@@ -1435,7 +1436,7 @@ describe('DiffsStoreActions', () => {
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
getDiscussion: () => ({ diff_file: { file_hash: '124' } }),
- notesById: { '1': { discussion_id: '2' } },
+ notesById: { 1: { discussion_id: '2' } },
};
setCurrentDiffFileIdFromNote({ commit, state, rootGetters }, '1');
@@ -1445,7 +1446,7 @@ describe('DiffsStoreActions', () => {
});
describe('navigateToDiffFileIndex', () => {
- it('commits VIEW_DIFF_FILE', done => {
+ it('commits VIEW_DIFF_FILE', (done) => {
testAction(
navigateToDiffFileIndex,
0,
@@ -1472,4 +1473,46 @@ describe('DiffsStoreActions', () => {
);
});
});
+
+ describe('reviewFile', () => {
+ const file = {
+ id: '123',
+ file_identifier_hash: 'abc',
+ load_collapsed_diff_url: 'gitlab-org/gitlab-test/-/merge_requests/1/diffs',
+ };
+ it.each`
+ reviews | diffFile | reviewed
+ ${{ abc: ['123'] }} | ${file} | ${true}
+ ${{}} | ${file} | ${false}
+ `(
+ 'sets reviews ($reviews) to localStorage and state for file $file if it is marked reviewed=$reviewed',
+ ({ reviews, diffFile, reviewed }) => {
+ const commitSpy = jest.fn();
+ const getterSpy = jest.fn().mockReturnValue([]);
+
+ reviewFile(
+ {
+ commit: commitSpy,
+ getters: {
+ fileReviews: getterSpy,
+ },
+ state: {
+ mrReviews: { abc: ['123'] },
+ },
+ },
+ {
+ file: diffFile,
+ reviewed,
+ },
+ );
+
+ expect(localStorage.setItem).toHaveBeenCalledTimes(1);
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ 'gitlab-org/gitlab-test/-/merge_requests/1-file-reviews',
+ JSON.stringify(reviews),
+ );
+ expect(commitSpy).toHaveBeenCalledWith(types.SET_MR_FILE_REVIEWS, reviews);
+ },
+ );
+ });
});
diff --git a/spec/frontend/diffs/store/getters_spec.js b/spec/frontend/diffs/store/getters_spec.js
index 7e936c561fc..4d7f861ac22 100644
--- a/spec/frontend/diffs/store/getters_spec.js
+++ b/spec/frontend/diffs/store/getters_spec.js
@@ -251,9 +251,12 @@ describe('Diffs Module Getters', () => {
discussionMock.diff_file.file_hash = diffFileMock.file_hash;
expect(
- getters.getDiffFileDiscussions(localState, {}, {}, { discussions: [discussionMock] })(
- diffFileMock,
- ).length,
+ getters.getDiffFileDiscussions(
+ localState,
+ {},
+ {},
+ { discussions: [discussionMock] },
+ )(diffFileMock).length,
).toEqual(1);
});
@@ -345,7 +348,7 @@ describe('Diffs Module Getters', () => {
describe('fileLineCoverage', () => {
beforeEach(() => {
- Object.assign(localState.coverageFiles, { files: { 'app.js': { '1': 0, '2': 5 } } });
+ Object.assign(localState.coverageFiles, { files: { 'app.js': { 1: 0, 2: 5 } } });
});
it('returns empty object when no coverage data is available', () => {
@@ -372,4 +375,26 @@ describe('Diffs Module Getters', () => {
});
});
});
+
+ describe('fileReviews', () => {
+ const file1 = { id: '123', file_identifier_hash: 'abc' };
+ const file2 = { id: '098', file_identifier_hash: 'abc' };
+
+ 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'] }} | ${[]} | ${[]}
+ `(
+ 'returns $fileReviews based on the diff files in state and the existing reviews $reviews',
+ ({ reviews, files, fileReviews }) => {
+ localState.diffFiles = files;
+ localState.mrReviews = reviews;
+
+ expect(getters.fileReviews(localState)).toStrictEqual(fileReviews);
+ },
+ );
+ });
});
diff --git a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
index 0343ef75732..f7954515422 100644
--- a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
+++ b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
@@ -49,7 +49,7 @@ describe('Compare diff version dropdowns', () => {
let expectedHeadVersion;
const originalLocation = window.location;
- const setupTest = includeDiffHeadParam => {
+ const setupTest = (includeDiffHeadParam) => {
const diffHeadParam = includeDiffHeadParam ? '?diff_head=true' : '';
Object.defineProperty(window, 'location', {
@@ -81,7 +81,7 @@ describe('Compare diff version dropdowns', () => {
};
};
- const assertVersions = targetVersions => {
+ const assertVersions = (targetVersions) => {
// base and head should be the last two versions in that order
const targetBaseVersion = targetVersions[targetVersions.length - 2];
const targetHeadVersion = targetVersions[targetVersions.length - 1];
@@ -136,6 +136,7 @@ describe('Compare diff version dropdowns', () => {
...firstDiff,
href: firstDiff.version_path,
commitsText: `${firstDiff.commits_count} commits,`,
+ isLatestVersion: true,
versionName: 'latest version',
selected: true,
};
@@ -144,6 +145,9 @@ describe('Compare diff version dropdowns', () => {
selectedSourceIndex: expectedShape.version_index,
});
expect(sourceVersions[0]).toEqual(expectedShape);
- expect(sourceVersions[1].selected).toBe(false);
+ expect(sourceVersions[1]).toMatchObject({
+ selected: false,
+ isLatestVersion: false,
+ });
});
});
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index 13e7cad835d..2c342d8e2a5 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -105,7 +105,7 @@ describe('DiffsStoreMutations', () => {
describe('SET_COVERAGE_DATA', () => {
it('should set coverage data properly', () => {
const state = { coverageFiles: {} };
- const coverage = { 'app.js': { '1': 0, '2': 1 } };
+ const coverage = { 'app.js': { 1: 0, 2: 1 } };
mutations[types.SET_COVERAGE_DATA](state, coverage);
@@ -906,4 +906,19 @@ describe('DiffsStoreMutations', () => {
expect(state.viewDiffsFileByFile).toBe(value);
});
});
+
+ describe('SET_MR_FILE_REVIEWS', () => {
+ it.each`
+ newReviews | oldReviews
+ ${{ abc: ['123'] }} | ${{}}
+ ${{ abc: [] }} | ${{ abc: ['123'] }}
+ ${{}} | ${{ abc: ['123'] }}
+ `('sets mrReviews to $newReviews', ({ newReviews, oldReviews }) => {
+ const state = { mrReviews: oldReviews };
+
+ mutations[types.SET_MR_FILE_REVIEWS](state, newReviews);
+
+ expect(state.mrReviews).toStrictEqual(newReviews);
+ });
+ });
});
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 7ee97224707..a19e5e91677 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -481,7 +481,7 @@ describe('DiffsStoreUtils', () => {
});
it('adds the `.brokenSymlink` property to each diff file', () => {
- preparedDiff.diff_files.forEach(file => {
+ preparedDiff.diff_files.forEach((file) => {
expect(file).toEqual(expect.objectContaining({ brokenSymlink: false }));
});
});
@@ -492,9 +492,9 @@ describe('DiffsStoreUtils', () => {
...splitInlineDiff.diff_files,
...splitParallelDiff.diff_files,
...completedDiff.diff_files,
- ].flatMap(file => [...file[INLINE_DIFF_LINES_KEY]]);
+ ].flatMap((file) => [...file[INLINE_DIFF_LINES_KEY]]);
- lines.forEach(line => {
+ lines.forEach((line) => {
expect(line.commentsDisabled).toBe(false);
});
});
@@ -560,7 +560,7 @@ describe('DiffsStoreUtils', () => {
});
it('adds the `.brokenSymlink` property to each meta diff file', () => {
- preparedDiffFiles.forEach(file => {
+ preparedDiffFiles.forEach((file) => {
expect(file).toMatchObject({ brokenSymlink: false });
});
});
@@ -1119,22 +1119,87 @@ describe('DiffsStoreUtils', () => {
});
});
+ describe('isConflictMarker', () => {
+ it.each`
+ type | expected
+ ${'conflict_marker_our'} | ${true}
+ ${'conflict_marker_their'} | ${true}
+ ${'conflict_their'} | ${false}
+ ${'conflict_our'} | ${false}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isConflictMarker({ type })).toBe(expected);
+ });
+ });
+
+ describe('isConflictOur', () => {
+ it.each`
+ type | expected
+ ${'conflict_marker_our'} | ${false}
+ ${'conflict_marker_their'} | ${false}
+ ${'conflict_their'} | ${false}
+ ${'conflict_our'} | ${true}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isConflictOur({ type })).toBe(expected);
+ });
+ });
+
+ describe('isConflictTheir', () => {
+ it.each`
+ type | expected
+ ${'conflict_marker_our'} | ${false}
+ ${'conflict_marker_their'} | ${false}
+ ${'conflict_their'} | ${true}
+ ${'conflict_our'} | ${false}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isConflictTheir({ type })).toBe(expected);
+ });
+ });
+
describe('parallelizeDiffLines', () => {
it('converts inline diff lines to parallel diff lines', () => {
const file = getDiffFileMock();
- expect(utils.parallelizeDiffLines(file[INLINE_DIFF_LINES_KEY])).toEqual(
+ expect(utils.parallelizeDiffLines(file[INLINE_DIFF_LINES_KEY])).toMatchObject(
file.parallel_diff_lines,
);
});
+ it('converts conflicted diffs line', () => {
+ const lines = [
+ { type: 'new' },
+ { type: 'conflict_marker_our' },
+ { type: 'conflict_our' },
+ { type: 'conflict_marker' },
+ { type: 'conflict_their' },
+ { type: 'conflict_marker_their' },
+ ];
+
+ expect(utils.parallelizeDiffLines(lines)).toEqual([
+ {
+ left: null,
+ right: {
+ chunk: 0,
+ type: 'new',
+ },
+ },
+ {
+ left: { chunk: 0, type: 'conflict_marker_our' },
+ right: { chunk: 0, type: 'conflict_marker_their' },
+ },
+ {
+ left: { chunk: 0, type: 'conflict_our' },
+ right: { chunk: 0, type: 'conflict_their' },
+ },
+ ]);
+ });
+
it('converts inline diff lines', () => {
const file = getDiffFileMock();
const files = utils.parallelizeDiffLines(file.highlighted_diff_lines, true);
- expect(files[5].left).toEqual(file.parallel_diff_lines[5].left);
+ expect(files[5].left).toMatchObject(file.parallel_diff_lines[5].left);
expect(files[5].right).toBeNull();
- expect(files[6].left).toEqual(file.parallel_diff_lines[5].right);
+ expect(files[6].left).toMatchObject(file.parallel_diff_lines[5].right);
expect(files[6].right).toBeNull();
});
});
diff --git a/spec/frontend/diffs/utils/diff_file_spec.js b/spec/frontend/diffs/utils/diff_file_spec.js
index 2e6247b8c07..2de8db28e71 100644
--- a/spec/frontend/diffs/utils/diff_file_spec.js
+++ b/spec/frontend/diffs/utils/diff_file_spec.js
@@ -1,6 +1,8 @@
import { prepareRawDiffFile } from '~/diffs/utils/diff_file';
function getDiffFiles() {
+ const loadFull = 'namespace/project/-/merge_requests/12345/diff_for_path?file_identifier=abc';
+
return [
{
blob: {
@@ -8,6 +10,7 @@ function getDiffFiles() {
},
file_hash: 'ABC', // This file is just a normal file
file_identifier_hash: 'ABC1',
+ load_collapsed_diff_url: loadFull,
},
{
blob: {
@@ -15,6 +18,7 @@ function getDiffFiles() {
},
file_hash: 'DEF', // This file replaces a symlink
file_identifier_hash: 'DEF1',
+ load_collapsed_diff_url: loadFull,
a_mode: '0',
b_mode: '0755',
},
@@ -24,6 +28,7 @@ function getDiffFiles() {
},
file_hash: 'DEF', // This symlink is replaced by a file
file_identifier_hash: 'DEF2',
+ load_collapsed_diff_url: loadFull,
a_mode: '120000',
b_mode: '0',
},
@@ -33,6 +38,7 @@ function getDiffFiles() {
},
file_hash: 'GHI', // This symlink replaces a file
file_identifier_hash: 'GHI1',
+ load_collapsed_diff_url: loadFull,
a_mode: '0',
b_mode: '120000',
},
@@ -42,6 +48,7 @@ function getDiffFiles() {
},
file_hash: 'GHI', // This file is replaced by a symlink
file_identifier_hash: 'GHI2',
+ load_collapsed_diff_url: loadFull,
a_mode: '0755',
b_mode: '0',
},
@@ -86,11 +93,11 @@ describe('diff_file utilities', () => {
it.each`
fileIndex | id
- ${0} | ${'8dcd585e-a421-4dab-a04e-6f88c81b7b4c'}
- ${1} | ${'3f178b78-392b-44a4-bd7d-5d6192208a97'}
- ${2} | ${'3d9e1354-cddf-4a11-8234-f0413521b2e5'}
- ${3} | ${'460f005b-d29d-43c1-9a08-099a7c7f08de'}
- ${4} | ${'d8c89733-6ce1-4455-ae3d-f8aad6ee99f9'}
+ ${0} | ${'68296a4f-f1c7-445a-bd0e-6e3b02c4eec0'}
+ ${1} | ${'051c9bb8-cdba-4eb7-b8d1-508906e6d8ba'}
+ ${2} | ${'ed3d53d5-5da0-412d-a3c6-7213f84e88d3'}
+ ${3} | ${'39d998dc-bc69-4b19-a6af-41e4369c2bd5'}
+ ${4} | ${'7072d115-ce39-423c-8346-9fcad58cd68e'}
`('sets the file id properly { id: $id } on normal diff files', ({ fileIndex, id }) => {
const preppedFile = prepareRawDiffFile({
file: files[fileIndex],
@@ -122,5 +129,18 @@ describe('diff_file utilities', () => {
expect(preppedFile).not.toHaveProp('id');
});
+
+ it('does not set the id property if the file is missing a `load_collapsed_diff_url` property', () => {
+ const fileMissingContentSha = { ...files[0] };
+
+ delete fileMissingContentSha.load_collapsed_diff_url;
+
+ const preppedFile = prepareRawDiffFile({
+ file: fileMissingContentSha,
+ allFiles: files,
+ });
+
+ expect(preppedFile).not.toHaveProp('id');
+ });
});
});
diff --git a/spec/frontend/diffs/utils/file_reviews_spec.js b/spec/frontend/diffs/utils/file_reviews_spec.js
new file mode 100644
index 00000000000..819426ee75f
--- /dev/null
+++ b/spec/frontend/diffs/utils/file_reviews_spec.js
@@ -0,0 +1,146 @@
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+
+import {
+ getReviewsForMergeRequest,
+ setReviewsForMergeRequest,
+ isFileReviewed,
+ markFileReview,
+ reviewable,
+} from '~/diffs/utils/file_reviews';
+
+function getDefaultReviews() {
+ return {
+ abc: ['123', '098'],
+ };
+}
+
+describe('File Review(s) utilities', () => {
+ const mrPath = 'my/fake/mr/42';
+ const storageKey = `${mrPath}-file-reviews`;
+ const file = { id: '123', file_identifier_hash: 'abc' };
+ const storedValue = JSON.stringify(getDefaultReviews());
+ let reviews;
+
+ useLocalStorageSpy();
+
+ beforeEach(() => {
+ reviews = getDefaultReviews();
+ localStorage.clear();
+ });
+
+ describe('getReviewsForMergeRequest', () => {
+ it('fetches the appropriate stored reviews from localStorage', () => {
+ getReviewsForMergeRequest(mrPath);
+
+ expect(localStorage.getItem).toHaveBeenCalledTimes(1);
+ expect(localStorage.getItem).toHaveBeenCalledWith(storageKey);
+ });
+
+ it('returns an empty object if there have never been stored reviews for this MR', () => {
+ expect(getReviewsForMergeRequest(mrPath)).toStrictEqual({});
+ });
+
+ it.each`
+ data
+ ${'+++'}
+ ${'{ lookinGood: "yeah!", missingClosingBrace: "yeah :(" '}
+ `(
+ "returns an empty object if the stored reviews are corrupted/aren't parseable as JSON (like: $data)",
+ ({ data }) => {
+ localStorage.getItem.mockReturnValueOnce(data);
+
+ expect(getReviewsForMergeRequest(mrPath)).toStrictEqual({});
+ },
+ );
+
+ it('fetches the reviews for the MR if they exist', () => {
+ localStorage.setItem(storageKey, storedValue);
+
+ expect(getReviewsForMergeRequest(mrPath)).toStrictEqual(reviews);
+ });
+ });
+
+ describe('setReviewsForMergeRequest', () => {
+ it('sets the new value to localStorage', () => {
+ setReviewsForMergeRequest(mrPath, reviews);
+
+ expect(localStorage.setItem).toHaveBeenCalledTimes(1);
+ expect(localStorage.setItem).toHaveBeenCalledWith(storageKey, storedValue);
+ });
+
+ it('returns the new value for chainability', () => {
+ expect(setReviewsForMergeRequest(mrPath, reviews)).toStrictEqual(reviews);
+ });
+ });
+
+ 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
+ ${true} | ${file} | ${'has an `.id` and a `.file_identifier_hash`'}
+ ${false} | ${{ file_identifier_hash: 'abc' }} | ${'does not have an `.id`'}
+ ${false} | ${{ ...file, id: undefined }} | ${'has an undefined `.id`'}
+ ${false} | ${{ ...file, id: null }} | ${'has a null `.id`'}
+ ${false} | ${{ ...file, id: 0 }} | ${'has an `.id` set to 0'}
+ ${false} | ${{ ...file, id: false }} | ${'has an `.id` set to false'}
+ ${false} | ${{ id: '123' }} | ${'does not have a `.file_identifier_hash`'}
+ ${false} | ${{ ...file, file_identifier_hash: undefined }} | ${'has an undefined `.file_identifier_hash`'}
+ ${false} | ${{ ...file, file_identifier_hash: null }} | ${'has a null `.file_identifier_hash`'}
+ ${false} | ${{ ...file, file_identifier_hash: 0 }} | ${'has a `.file_identifier_hash` set to 0'}
+ ${false} | ${{ ...file, file_identifier_hash: false }} | ${'has a `.file_identifier_hash` set to false'}
+ `('returns `$response` when the file $description`', ({ response, diffFile }) => {
+ expect(reviewable(diffFile)).toBe(response);
+ });
+ });
+
+ describe('markFileReview', () => {
+ it("adds a review when there's nothing that already exists", () => {
+ expect(markFileReview(null, file)).toStrictEqual({ abc: ['123'] });
+ });
+
+ it("overwrites an existing review if it's for the same file (identifier hash)", () => {
+ expect(markFileReview(reviews, file)).toStrictEqual(getDefaultReviews());
+ });
+
+ it('removes a review from the list when `reviewed` is `false`', () => {
+ expect(markFileReview(reviews, file, false)).toStrictEqual({ abc: ['098'] });
+ });
+
+ it('adds a new review if the file ID is new', () => {
+ const updatedFile = { ...file, id: '098' };
+ const allReviews = markFileReview({ abc: ['123'] }, updatedFile);
+
+ expect(allReviews).toStrictEqual(getDefaultReviews());
+ expect(allReviews.abc).toStrictEqual(['123', '098']);
+ });
+
+ it.each`
+ description | diffFile
+ ${'missing an `.id`'} | ${{ file_identifier_hash: 'abc' }}
+ ${'missing a `.file_identifier_hash`'} | ${{ id: '123' }}
+ `("doesn't modify the reviews if the file is $description", ({ diffFile }) => {
+ expect(markFileReview(reviews, diffFile)).toStrictEqual(getDefaultReviews());
+ });
+
+ it('removes the file key if there are no more reviews for it', () => {
+ let updated = markFileReview(reviews, file, false);
+
+ updated = markFileReview(updated, { ...file, id: '098' }, false);
+
+ expect(updated).toStrictEqual({});
+ });
+ });
+});
diff --git a/spec/frontend/diffs/utils/merge_request_spec.js b/spec/frontend/diffs/utils/merge_request_spec.js
new file mode 100644
index 00000000000..8c7b1e1f2a5
--- /dev/null
+++ b/spec/frontend/diffs/utils/merge_request_spec.js
@@ -0,0 +1,31 @@
+import { getDerivedMergeRequestInformation } from '~/diffs/utils/merge_request';
+import { diffMetadata } from '../mock_data/diff_metadata';
+
+describe('Merge Request utilities', () => {
+ const derivedMrInfo = {
+ mrPath: '/gitlab-org/gitlab-test/-/merge_requests/4',
+ userOrGroup: 'gitlab-org',
+ project: 'gitlab-test',
+ id: '4',
+ };
+ const unparseableEndpoint = {
+ mrPath: undefined,
+ userOrGroup: undefined,
+ project: undefined,
+ id: undefined,
+ };
+
+ describe('getDerivedMergeRequestInformation', () => {
+ const endpoint = `${diffMetadata.latest_version_path}.json?searchParam=irrelevant`;
+
+ it.each`
+ argument | response
+ ${{ endpoint }} | ${derivedMrInfo}
+ ${{}} | ${unparseableEndpoint}
+ ${{ endpoint: undefined }} | ${unparseableEndpoint}
+ ${{ endpoint: null }} | ${unparseableEndpoint}
+ `('generates the correct derived results based on $argument', ({ argument, response }) => {
+ expect(getDerivedMergeRequestInformation(argument)).toStrictEqual(response);
+ });
+ });
+});
diff --git a/spec/frontend/diffs/utils/uuids_spec.js b/spec/frontend/diffs/utils/uuids_spec.js
index 79d3ebadd4f..8d0a01e8cbd 100644
--- a/spec/frontend/diffs/utils/uuids_spec.js
+++ b/spec/frontend/diffs/utils/uuids_spec.js
@@ -32,7 +32,7 @@ describe('UUIDs Util', () => {
const ids = uuids({ count: 11 });
expect(ids.length).toEqual(11);
- expect(ids.every(id => UUIDV4.test(id))).toEqual(true);
+ expect(ids.every((id) => UUIDV4.test(id))).toEqual(true);
});
it.each`
diff --git a/spec/frontend/dirty_submit/dirty_submit_collection_spec.js b/spec/frontend/dirty_submit/dirty_submit_collection_spec.js
index 170d581be23..465391633e6 100644
--- a/spec/frontend/dirty_submit/dirty_submit_collection_spec.js
+++ b/spec/frontend/dirty_submit/dirty_submit_collection_spec.js
@@ -1,15 +1,15 @@
import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
import { setInputValue, createForm } from './helper';
-jest.mock('lodash/throttle', () => jest.fn(fn => fn));
+jest.mock('lodash/throttle', () => jest.fn((fn) => fn));
describe('DirtySubmitCollection', () => {
const testElementsCollection = [createForm(), createForm()];
- const forms = testElementsCollection.map(testElements => testElements.form);
+ const forms = testElementsCollection.map((testElements) => testElements.form);
new DirtySubmitCollection(forms); // eslint-disable-line no-new
- it.each(testElementsCollection)('disables submits until there are changes', testElements => {
+ it.each(testElementsCollection)('disables submits until there are changes', (testElements) => {
const { input, submit } = testElements;
const originalValue = input.value;
diff --git a/spec/frontend/dirty_submit/dirty_submit_form_spec.js b/spec/frontend/dirty_submit/dirty_submit_form_spec.js
index d7f690df1f3..cfcf1be609e 100644
--- a/spec/frontend/dirty_submit/dirty_submit_form_spec.js
+++ b/spec/frontend/dirty_submit/dirty_submit_form_spec.js
@@ -2,7 +2,7 @@ import { range as rge, throttle } from 'lodash';
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
import { getInputValue, setInputValue, createForm } from './helper';
-jest.mock('lodash/throttle', () => jest.fn(fn => fn));
+jest.mock('lodash/throttle', () => jest.fn((fn) => fn));
const lodash = jest.requireActual('lodash');
function expectToToggleDisableOnDirtyUpdate(submit, input) {
@@ -66,7 +66,7 @@ describe('DirtySubmitForm', () => {
const { form, input } = createForm();
const updateDirtyInputSpy = jest.spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
- rge(10).forEach(i => {
+ rge(10).forEach((i) => {
setInputValue(input, `change ${i}`, false);
});
@@ -78,13 +78,13 @@ describe('DirtySubmitForm', () => {
it('does not throttle updates when rapid changes are made to different form elements', () => {
const form = document.createElement('form');
const range = rge(10);
- range.forEach(i => {
+ range.forEach((i) => {
form.innerHTML += `<input type="text" name="input-${i}" class="js-input-${i}"/>`;
});
const updateDirtyInputSpy = jest.spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
- range.forEach(i => {
+ range.forEach((i) => {
const input = form.querySelector(`.js-input-${i}`);
setInputValue(input, `change`, false);
});
diff --git a/spec/frontend/droplab/drop_down_spec.js b/spec/frontend/droplab/drop_down_spec.js
index d33d6bb70f1..c1fbda6f211 100644
--- a/spec/frontend/droplab/drop_down_spec.js
+++ b/spec/frontend/droplab/drop_down_spec.js
@@ -151,7 +151,7 @@ describe('DropLab DropDown', () => {
};
testContext.dummyListItem = document.createElement('li');
- jest.spyOn(testContext.event.target, 'closest').mockImplementation(selector => {
+ jest.spyOn(testContext.event.target, 'closest').mockImplementation((selector) => {
if (selector === 'li') {
return testContext.dummyListItem;
}
@@ -402,7 +402,7 @@ describe('DropLab DropDown', () => {
beforeEach(() => {
testContext.renderableList = {};
testContext.list = {
- querySelector: q => {
+ querySelector: (q) => {
if (q === '.filter-dropdown-loading') {
return false;
}
@@ -414,7 +414,7 @@ describe('DropLab DropDown', () => {
testContext.data = [0, 1];
testContext.customEvent = {};
- jest.spyOn(testContext.dropdown, 'renderChildren').mockImplementation(data => data);
+ jest.spyOn(testContext.dropdown, 'renderChildren').mockImplementation((data) => data);
jest.spyOn(testContext.list, 'dispatchEvent').mockImplementation(() => {});
jest.spyOn(testContext.data, 'map');
jest.spyOn(window, 'CustomEvent').mockReturnValue(testContext.customEvent);
@@ -465,7 +465,7 @@ describe('DropLab DropDown', () => {
testContext.dropdown = { renderChildren: () => {}, list: testContext.list };
testContext.data = [0, 1];
- jest.spyOn(testContext.dropdown, 'renderChildren').mockImplementation(data => data);
+ jest.spyOn(testContext.dropdown, 'renderChildren').mockImplementation((data) => data);
jest.spyOn(testContext.list, 'querySelector').mockImplementation(() => {});
jest.spyOn(testContext.data, 'map');
diff --git a/spec/frontend/droplab/plugins/ajax_filter_spec.js b/spec/frontend/droplab/plugins/ajax_filter_spec.js
index 5ec0400cbc5..d91884a60e5 100644
--- a/spec/frontend/droplab/plugins/ajax_filter_spec.js
+++ b/spec/frontend/droplab/plugins/ajax_filter_spec.js
@@ -28,7 +28,7 @@ describe('AjaxFilter', () => {
let ajaxSpy;
beforeEach(() => {
- jest.spyOn(AjaxCache, 'retrieve').mockImplementation(url => ajaxSpy(url));
+ jest.spyOn(AjaxCache, 'retrieve').mockImplementation((url) => ajaxSpy(url));
jest.spyOn(AjaxFilter, '_loadData').mockImplementation(() => {});
dummyConfig.onLoadingFinished = jest.fn();
@@ -38,8 +38,8 @@ describe('AjaxFilter', () => {
dummyList.list.appendChild(dynamicList);
});
- it('calls onLoadingFinished after loading data', done => {
- ajaxSpy = url => {
+ it('calls onLoadingFinished after loading data', (done) => {
+ ajaxSpy = (url) => {
expect(url).toBe('dummy endpoint?dummy search key=');
return Promise.resolve(dummyData);
};
@@ -52,16 +52,16 @@ describe('AjaxFilter', () => {
.catch(done.fail);
});
- it('does not call onLoadingFinished if Ajax call fails', done => {
+ it('does not call onLoadingFinished if Ajax call fails', (done) => {
const dummyError = new Error('My dummy is sick! :-(');
- ajaxSpy = url => {
+ ajaxSpy = (url) => {
expect(url).toBe('dummy endpoint?dummy search key=');
return Promise.reject(dummyError);
};
AjaxFilter.trigger()
.then(done.fail)
- .catch(error => {
+ .catch((error) => {
expect(error).toBe(dummyError);
expect(dummyConfig.onLoadingFinished.mock.calls.length).toBe(0);
})
diff --git a/spec/frontend/editor/editor_ci_schema_ext_spec.js b/spec/frontend/editor/editor_ci_schema_ext_spec.js
new file mode 100644
index 00000000000..9dd88aad7e6
--- /dev/null
+++ b/spec/frontend/editor/editor_ci_schema_ext_spec.js
@@ -0,0 +1,107 @@
+import { languages } from 'monaco-editor';
+import { TEST_HOST } from 'helpers/test_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';
+
+ let editor;
+ let instance;
+ let editorEl;
+ let originalGitlabUrl;
+
+ const createMockEditor = ({ blobPath = defaultBlobPath } = {}) => {
+ setFixtures('<div id="editor"></div>');
+ editorEl = document.getElementById('editor');
+ editor = new EditorLite();
+ instance = editor.createInstance({
+ el: editorEl,
+ blobPath,
+ blobContent: '',
+ });
+ instance.use(new CiSchemaExtension());
+ };
+
+ beforeAll(() => {
+ originalGitlabUrl = gon.gitlab_url;
+ gon.gitlab_url = TEST_HOST;
+ });
+
+ afterAll(() => {
+ gon.gitlab_url = originalGitlabUrl;
+ });
+
+ beforeEach(() => {
+ createMockEditor();
+ });
+
+ afterEach(() => {
+ instance.dispose();
+ editorEl.remove();
+ });
+
+ describe('registerCiSchema', () => {
+ beforeEach(() => {
+ jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
+ });
+
+ describe('register validations options with monaco for yaml language', () => {
+ const mockProjectNamespace = 'namespace1';
+ const mockProjectPath = 'project1';
+
+ const getConfiguredYmlSchema = () => {
+ return languages.yaml.yamlDefaults.setDiagnosticsOptions.mock.calls[0][0].schemas[0];
+ };
+
+ it('with expected basic validation configuration', () => {
+ instance.registerCiSchema({
+ projectNamespace: mockProjectNamespace,
+ projectPath: mockProjectPath,
+ });
+
+ const expectedOptions = {
+ validate: true,
+ enableSchemaRequest: true,
+ hover: true,
+ completion: true,
+ };
+
+ expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledTimes(1);
+ expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect.objectContaining(expectedOptions),
+ );
+ });
+
+ it('with an schema uri that contains project and ref', () => {
+ const mockRef = 'AABBCCDD';
+
+ instance.registerCiSchema({
+ projectNamespace: mockProjectNamespace,
+ projectPath: mockProjectPath,
+ ref: mockRef,
+ });
+
+ expect(getConfiguredYmlSchema()).toEqual({
+ uri: `${TEST_HOST}/${mockProjectNamespace}/${mockProjectPath}/-/schema/${mockRef}/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`,
+ fileMatch: [defaultBlobPath],
+ });
+ });
+
+ it('with an alternative file name match', () => {
+ createMockEditor({ blobPath: 'dir1/dir2/another-ci-filename.yml' });
+
+ instance.registerCiSchema({
+ projectNamespace: mockProjectNamespace,
+ projectPath: mockProjectPath,
+ });
+
+ expect(getConfiguredYmlSchema()).toEqual({
+ uri: `${TEST_HOST}/${mockProjectNamespace}/${mockProjectPath}/-/schema/master/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`,
+ fileMatch: ['another-ci-filename.yml'],
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/editor/editor_lite_extension_base_spec.js b/spec/frontend/editor/editor_lite_extension_base_spec.js
index ff53640b096..5490e9dc7b5 100644
--- a/spec/frontend/editor/editor_lite_extension_base_spec.js
+++ b/spec/frontend/editor/editor_lite_extension_base_spec.js
@@ -1,5 +1,5 @@
import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from '~/editor/constants';
-import { EditorLiteExtension } from '~/editor/editor_lite_extension_base';
+import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base';
describe('The basis for an Editor Lite extension', () => {
let ext;
@@ -16,7 +16,7 @@ describe('The basis for an Editor Lite extension', () => {
if (instance) {
if (options) {
- Object.entries(options).forEach(prop => {
+ Object.entries(options).forEach((prop) => {
expect(instance[prop]).toBeUndefined();
});
// Both instance and options are passed
diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js
index 3a7680f6d17..c3099997287 100644
--- a/spec/frontend/editor/editor_lite_spec.js
+++ b/spec/frontend/editor/editor_lite_spec.js
@@ -2,7 +2,7 @@
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
import waitForPromises from 'helpers/wait_for_promises';
import Editor from '~/editor/editor_lite';
-import { EditorLiteExtension } from '~/editor/editor_lite_extension_base';
+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';
@@ -324,13 +324,13 @@ describe('Base editor', () => {
${'multiple simple objects'} | ${[FooObjExt, BarObjExt]} | ${['foo', 'bar']} | ${[fooRes, barRes]}
${'combination of ES6 classes and objects'} | ${[AlphaExt, BarObjExt]} | ${['alpha', 'bar']} | ${[alphaRes, barRes]}
`('is extensible with $type', ({ extensions, methods, expectations } = {}) => {
- methods.forEach(method => {
+ methods.forEach((method) => {
expect(instance[method]).toBeUndefined();
});
instance.use(extensions);
- methods.forEach(method => {
+ methods.forEach((method) => {
expect(instance[method]).toBeDefined();
});
@@ -359,7 +359,7 @@ describe('Base editor', () => {
it.each([WithStaticMethod, WithStaticMethodExtended])(
'properly resolves data for an extension with private data',
- ExtClass => {
+ (ExtClass) => {
const base = 1;
expect(instance.base).toBeUndefined();
expect(instance.boo).toBeUndefined();
@@ -408,7 +408,7 @@ describe('Base editor', () => {
};
beforeEach(() => {
- editorExtensionSpy = jest.spyOn(Editor, 'pushToImportsArray').mockImplementation(arr => {
+ editorExtensionSpy = jest.spyOn(Editor, 'pushToImportsArray').mockImplementation((arr) => {
arr.push(
Promise.resolve({
default: {},
@@ -524,7 +524,7 @@ describe('Base editor', () => {
});
it('sets default syntax highlighting theme', () => {
- const expectedTheme = themes.find(t => t.name === DEFAULT_THEME);
+ const expectedTheme = themes.find((t) => t.name === DEFAULT_THEME);
editor = new Editor();
@@ -533,7 +533,7 @@ describe('Base editor', () => {
});
it('sets correct theme if it is set in users preferences', () => {
- const expectedTheme = themes.find(t => t.name !== DEFAULT_THEME);
+ const expectedTheme = themes.find((t) => t.name !== DEFAULT_THEME);
expect(expectedTheme.name).not.toBe(DEFAULT_THEME);
diff --git a/spec/frontend/editor/editor_markdown_ext_spec.js b/spec/frontend/editor/editor_markdown_ext_spec.js
index b432d4d66ad..3f64dcfd7a0 100644
--- a/spec/frontend/editor/editor_markdown_ext_spec.js
+++ b/spec/frontend/editor/editor_markdown_ext_spec.js
@@ -1,6 +1,6 @@
import { Range, Position } from 'monaco-editor';
import EditorLite from '~/editor/editor_lite';
-import { EditorMarkdownExtension } from '~/editor/editor_markdown_ext';
+import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext';
describe('Markdown Extension for Editor Lite', () => {
let editor;
@@ -114,7 +114,7 @@ describe('Markdown Extension for Editor Lite', () => {
});
describe('moveCursor', () => {
- const setPosition = endCol => {
+ const setPosition = (endCol) => {
const currentPos = new Position(2, endCol);
instance.setPosition(currentPos);
};
diff --git a/spec/frontend/emoji/emoji_spec.js b/spec/frontend/emoji/emoji_spec.js
index f528313ef02..feec445bc8d 100644
--- a/spec/frontend/emoji/emoji_spec.js
+++ b/spec/frontend/emoji/emoji_spec.js
@@ -369,11 +369,11 @@ describe('gl_emoji', () => {
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);
+ 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);
+ const subject = (query) => search(query);
describeEmojiFields('with $field', ({ accessor }) => {
it(`should match by lower case: ${accessor(atom)}`, () => {
@@ -403,7 +403,7 @@ describe('gl_emoji', () => {
});
describe('with fuzzy match', () => {
- const subject = query => search(query, { match: 'fuzzy' });
+ const subject = (query) => search(query, { match: 'fuzzy' });
describeEmojiFields('with $field', ({ accessor }) => {
it(`should match by lower case: ${accessor(atom)}`, () => {
@@ -421,7 +421,7 @@ describe('gl_emoji', () => {
});
describe('with contains match', () => {
- const subject = query => search(query, { match: 'contains' });
+ const subject = (query) => search(query, { match: 'contains' });
describeEmojiFields('with $field', ({ accessor }) => {
it(`should match by lower case: ${accessor(atom)}`, () => {
@@ -443,7 +443,7 @@ describe('gl_emoji', () => {
});
describe('with fallback', () => {
- const subject = query => search(query, { fallback: true });
+ const subject = (query) => search(query, { fallback: true });
it.each`
query
@@ -454,7 +454,7 @@ describe('gl_emoji', () => {
});
describe('with name and alias fields', () => {
- const subject = query => search(query, { fields: ['name', 'alias'] });
+ const subject = (query) => search(query, { fields: ['name', 'alias'] });
it(`should match by name: ${atom.name}`, () => {
expect(subject(atom.name)).toContain(atom.name);
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index 733bf4378eb..c055702d832 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -3,7 +3,7 @@
const path = require('path');
const { ErrorWithStack } = require('jest-util');
const JSDOMEnvironment = require('jest-environment-jsdom');
-const { TEST_HOST } = require('./helpers/test_constants');
+const { TEST_HOST } = require('./__helpers__/test_constants');
const ROOT_PATH = path.resolve(__dirname, '../..');
@@ -37,7 +37,7 @@ class CustomEnvironment extends JSDOMEnvironment {
this.rejectedPromises = [];
- this.global.promiseRejectionHandler = error => {
+ this.global.promiseRejectionHandler = (error) => {
this.rejectedPromises.push(error);
};
diff --git a/spec/frontend/environments/canary_ingress_spec.js b/spec/frontend/environments/canary_ingress_spec.js
new file mode 100644
index 00000000000..3dd67de1369
--- /dev/null
+++ b/spec/frontend/environments/canary_ingress_spec.js
@@ -0,0 +1,102 @@
+import { mount } from '@vue/test-utils';
+import { GlDropdownItem } from '@gitlab/ui';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { CANARY_UPDATE_MODAL } from '~/environments/constants';
+import CanaryIngress from '~/environments/components/canary_ingress.vue';
+
+describe('/environments/components/canary_ingress.vue', () => {
+ let wrapper;
+
+ const setWeightTo = (weightWrapper, x) =>
+ weightWrapper
+ .findAll(GlDropdownItem)
+ .at(x / 5)
+ .vm.$emit('click');
+
+ const createComponent = () => {
+ wrapper = mount(CanaryIngress, {
+ propsData: {
+ canaryIngress: {
+ canary_weight: 60,
+ },
+ },
+ directives: {
+ GlModal: createMockDirective(),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+
+ wrapper = null;
+ });
+
+ describe('stable weight', () => {
+ let stableWeightDropdown;
+
+ beforeEach(() => {
+ stableWeightDropdown = wrapper.find('[data-testid="stable-weight"]');
+ });
+
+ it('displays the current stable weight', () => {
+ expect(stableWeightDropdown.props('text')).toBe('40');
+ });
+
+ it('emits a change with the new canary weight', () => {
+ setWeightTo(stableWeightDropdown, 15);
+
+ expect(wrapper.emitted('change')).toContainEqual([85]);
+ });
+
+ it('lists options from 0 to 100 in increments of 5', () => {
+ const options = stableWeightDropdown.findAll(GlDropdownItem);
+ expect(options).toHaveLength(21);
+ options.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ });
+
+ it('is set to open the change modal', () => {
+ stableWeightDropdown
+ .findAll(GlDropdownItem)
+ .wrappers.forEach((w) =>
+ expect(getBinding(w.element, 'gl-modal')).toMatchObject({ value: CANARY_UPDATE_MODAL }),
+ );
+ });
+ });
+
+ describe('canary weight', () => {
+ let canaryWeightDropdown;
+
+ beforeEach(() => {
+ canaryWeightDropdown = wrapper.find('[data-testid="canary-weight"]');
+ });
+
+ it('displays the current canary weight', () => {
+ expect(canaryWeightDropdown.props('text')).toBe('60');
+ });
+
+ it('emits a change with the new canary weight', () => {
+ setWeightTo(canaryWeightDropdown, 15);
+
+ expect(wrapper.emitted('change')).toContainEqual([15]);
+ });
+
+ it('lists options from 0 to 100 in increments of 5', () => {
+ canaryWeightDropdown
+ .findAll(GlDropdownItem)
+ .wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ });
+
+ it('is set to open the change modal', () => {
+ const options = canaryWeightDropdown.findAll(GlDropdownItem);
+ expect(options).toHaveLength(21);
+ options.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ });
+ });
+});
diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js
new file mode 100644
index 00000000000..d0b97cf2eda
--- /dev/null
+++ b/spec/frontend/environments/canary_update_modal_spec.js
@@ -0,0 +1,126 @@
+import { mount } from '@vue/test-utils';
+import { GlAlert, GlModal } from '@gitlab/ui';
+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';
+
+describe('/environments/components/canary_update_modal.vue', () => {
+ let wrapper;
+ let modal;
+ let mutate;
+
+ const findAlert = () => wrapper.find(GlAlert);
+
+ const createComponent = () => {
+ mutate = jest.fn().mockResolvedValue();
+ wrapper = mount(CanaryUpdateModal, {
+ propsData: {
+ environment: {
+ name: 'staging',
+ global_id: 'gid://environments/staging',
+ },
+ weight: 60,
+ visible: true,
+ },
+ mocks: {
+ $apollo: { mutate },
+ },
+ });
+ modal = wrapper.find(GlModal);
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+
+ wrapper = null;
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should bind the modal props', () => {
+ expect(modal.props()).toMatchObject({
+ modalId: 'confirm-canary-change',
+ actionPrimary: {
+ text: 'Change ratio',
+ attributes: [{ variant: 'info' }],
+ },
+ actionCancel: { text: 'Cancel' },
+ });
+ });
+
+ it('should display the new weights', () => {
+ expect(modal.text()).toContain('Stable: 40');
+ expect(modal.text()).toContain('Canary: 60');
+ });
+
+ it('should display the affected environment', () => {
+ expect(modal.text()).toContain(
+ 'You are changing the ratio of the canary rollout for staging compared to the stable deployment to:',
+ );
+ });
+
+ it('should update the weight on primary action', () => {
+ modal.vm.$emit('primary');
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: updateCanaryIngress,
+ variables: {
+ input: {
+ id: 'gid://environments/staging',
+ weight: 60,
+ },
+ },
+ });
+ });
+
+ it('should do nothing on cancel', () => {
+ modal.vm.$emit('secondary');
+ expect(mutate).not.toHaveBeenCalled();
+ });
+
+ it('should not display an error if there was not one', async () => {
+ mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: [] } } });
+ modal.vm.$emit('primary');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('should display an error if there was one', async () => {
+ mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
+ modal.vm.$emit('primary');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().text()).toBe('error');
+ });
+
+ it('should display a generic error if there was a top-level one', async () => {
+ mutate.mockRejectedValue();
+ modal.vm.$emit('primary');
+
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().text()).toBe('Something went wrong. Please try again later');
+ });
+
+ it('hides teh alert on dismiss', async () => {
+ mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
+ modal.vm.$emit('primary');
+
+ await wrapper.vm.$nextTick();
+
+ const alert = findAlert();
+ alert.vm.$emit('dismiss');
+
+ await wrapper.vm.$nextTick();
+
+ expect(alert.exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
new file mode 100644
index 00000000000..dbef03f99d8
--- /dev/null
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -0,0 +1,139 @@
+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 { deployBoardMockData, environment } from './mock_data';
+
+const logsPath = `gitlab-org/gitlab-test/-/logs?environment_name=${environment.name}`;
+
+describe('Deploy Board', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) =>
+ mount(Vue.extend(DeployBoard), {
+ provide: { glFeatures: { canaryIngressWeightControl: true } },
+ propsData: {
+ deployBoardData: deployBoardMockData,
+ isLoading: false,
+ isEmpty: false,
+ logsPath,
+ ...props,
+ },
+ });
+
+ describe('with valid data', () => {
+ beforeEach((done) => {
+ wrapper = createComponent();
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('should render percentage with completion value provided', () => {
+ expect(wrapper.vm.$refs.percentage.innerText).toEqual(`${deployBoardMockData.completion}%`);
+ });
+
+ it('should render total instance count', () => {
+ const renderedTotal = wrapper.find('.deploy-board-instances-text');
+ const actualTotal = deployBoardMockData.instances.length;
+ const output = `${actualTotal > 1 ? 'Instances' : 'Instance'} (${actualTotal})`;
+
+ expect(renderedTotal.text()).toEqual(output);
+ });
+
+ it('should render all instances', () => {
+ const instances = wrapper.findAll('.deploy-board-instances-container a');
+
+ expect(instances).toHaveLength(deployBoardMockData.instances.length);
+ expect(
+ instances.at(1).classes(`deployment-instance-${deployBoardMockData.instances[2].status}`),
+ ).toBe(true);
+ });
+
+ it('should render an abort and a rollback button with the provided url', () => {
+ const buttons = wrapper.findAll('.deploy-board-actions a');
+
+ expect(buttons.at(0).attributes('href')).toEqual(deployBoardMockData.rollback_url);
+ expect(buttons.at(1).attributes('href')).toEqual(deployBoardMockData.abort_url);
+ });
+
+ it('sets up a tooltip for the legend', () => {
+ const iconSpan = wrapper.find('[data-testid="legend-tooltip-target"]');
+ const tooltip = wrapper.find(GlTooltip);
+ const icon = iconSpan.find(GlIcon);
+
+ expect(tooltip.props('target')()).toBe(iconSpan.element);
+ expect(icon.props('name')).toBe('question');
+ });
+
+ it('renders the canary weight selector', () => {
+ const canary = wrapper.find(CanaryIngress);
+ expect(canary.exists()).toBe(true);
+ expect(canary.props('canaryIngress')).toEqual({ canary_weight: 50 });
+ });
+ });
+
+ describe('with empty state', () => {
+ beforeEach((done) => {
+ wrapper = createComponent({
+ deployBoardData: {},
+ isLoading: false,
+ isEmpty: true,
+ logsPath,
+ });
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('should render the empty state', () => {
+ expect(wrapper.find('.deploy-board-empty-state-svg svg')).toBeDefined();
+ expect(
+ wrapper.find('.deploy-board-empty-state-text .deploy-board-empty-state-title').text(),
+ ).toContain('Kubernetes deployment not found');
+ });
+ });
+
+ describe('with loading state', () => {
+ beforeEach((done) => {
+ wrapper = createComponent({
+ deployBoardData: {},
+ isLoading: true,
+ isEmpty: false,
+ logsPath,
+ });
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('should render loading spinner', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+
+ describe('has legend component', () => {
+ let statuses = [];
+ beforeEach((done) => {
+ wrapper = createComponent({
+ isLoading: false,
+ isEmpty: false,
+ logsPath: environment.log_path,
+ deployBoardData: deployBoardMockData,
+ });
+ ({ statuses } = wrapper.vm);
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('with all the possible statuses', () => {
+ const deployBoardLegend = wrapper.find('.deploy-board-legend');
+
+ expect(deployBoardLegend).toBeDefined();
+ expect(deployBoardLegend.findAll('a')).toHaveLength(Object.keys(statuses).length);
+ });
+
+ Object.keys(statuses).forEach((item) => {
+ it(`with ${item} text next to deployment instance icon`, () => {
+ expect(wrapper.find(`.deployment-instance-${item}`)).toBeDefined();
+ expect(wrapper.find(`.deployment-instance-${item} + .legend-text`).text()).toBe(
+ statuses[item].text,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index cc5153d6eba..875a01c07ea 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -38,9 +38,9 @@ describe('EnvironmentActions Component', () => {
return createComponent({ actions: [scheduledJobAction, expiredJobAction] }, opts);
}
- const findDropdownItem = action => {
+ const findDropdownItem = (action) => {
const buttons = wrapper.findAll(GlDropdownItem);
- return buttons.filter(button => button.text().startsWith(action.name)).at(0);
+ return buttons.filter((button) => button.text().startsWith(action.name)).at(0);
};
afterEach(() => {
diff --git a/spec/frontend/environments/environment_monitoring_spec.js b/spec/frontend/environments/environment_monitoring_spec.js
index a73f49f1047..bbd49c04fb6 100644
--- a/spec/frontend/environments/environment_monitoring_spec.js
+++ b/spec/frontend/environments/environment_monitoring_spec.js
@@ -16,7 +16,8 @@ describe('Monitoring Component', () => {
};
const findButtons = () => wrapper.findAll(GlButton);
- const findButtonsByIcon = icon => findButtons().filter(button => button.props('icon') === icon);
+ const findButtonsByIcon = (icon) =>
+ findButtons().filter((button) => button.props('icon') === icon);
beforeEach(() => {
createWrapper();
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index b8ef40e2568..daef35bcf99 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -1,10 +1,11 @@
import { mount } from '@vue/test-utils';
import EnvironmentTable from '~/environments/components/environments_table.vue';
-import { folder } from './mock_data';
+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 = {
- canaryDeploymentFeatureId: 'canary_deployment',
- showCanaryDeploymentCallout: true,
userCalloutsPath: '/callouts',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
helpCanaryDeploymentsPath: 'help/canary-deployments',
@@ -37,10 +38,127 @@ describe('Environment table', () => {
wrapper.destroy();
});
- it('Should render a table', () => {
+ it('Should render a table', async () => {
+ const mockItem = {
+ name: 'review',
+ folderName: 'review',
+ size: 3,
+ isFolder: true,
+ environment_path: 'url',
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
expect(wrapper.classes()).toContain('ci-table');
});
+ it('should render deploy board container when data is provided', async () => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ logs_path: 'url',
+ id: 1,
+ hasDeployBoard: true,
+ deployBoardData: deployBoardMockData,
+ isDeployBoardVisible: true,
+ isLoadingDeployBoard: false,
+ isEmptyDeployBoard: false,
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canCreateDeployment: false,
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ expect(wrapper.find('.js-deploy-board-row').exists()).toBe(true);
+ expect(wrapper.find('.deploy-board-icon').exists()).toBe(true);
+ });
+
+ it('should toggle deploy board visibility when arrow is clicked', (done) => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ id: 1,
+ hasDeployBoard: true,
+ deployBoardData: {
+ instances: [{ status: 'ready', tooltip: 'foo' }],
+ abort_url: 'url',
+ rollback_url: 'url',
+ completion: 100,
+ is_completed: true,
+ canary_ingress: { canary_weight: 60 },
+ },
+ isDeployBoardVisible: false,
+ };
+
+ eventHub.$on('toggleDeployBoard', (env) => {
+ expect(env.id).toEqual(mockItem.id);
+ done();
+ });
+
+ factory({
+ propsData: {
+ environments: [mockItem],
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ wrapper.find('.deploy-board-icon').trigger('click');
+ });
+
+ it('should set the enviornment to change and weight when a change canary weight event is recevied', async () => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ logs_path: 'url',
+ id: 1,
+ hasDeployBoard: true,
+ deployBoardData: deployBoardMockData,
+ isDeployBoardVisible: true,
+ isLoadingDeployBoard: false,
+ isEmptyDeployBoard: false,
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canCreateDeployment: false,
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40);
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({
+ weight: 40,
+ environment: mockItem,
+ });
+ });
+
describe('sortEnvironments', () => {
it('should sort environments by last updated', () => {
const mockItems = [
@@ -266,7 +384,7 @@ describe('Environment table', () => {
},
});
- expect(wrapper.vm.sortedEnvironments.map(env => env.name)).toEqual([
+ expect(wrapper.vm.sortedEnvironments.map((env) => env.name)).toEqual([
review.name,
staging.name,
production.name,
diff --git a/spec/frontend/environments/environment_terminal_button_spec.js b/spec/frontend/environments/environment_terminal_button_spec.js
index 274186fbbd6..2475785a927 100644
--- a/spec/frontend/environments/environment_terminal_button_spec.js
+++ b/spec/frontend/environments/environment_terminal_button_spec.js
@@ -5,7 +5,7 @@ describe('Stop Component', () => {
let wrapper;
const terminalPath = '/path';
- const mountWithProps = props => {
+ const mountWithProps = (props) => {
wrapper = shallowMount(TerminalComponent, {
propsData: props,
});
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index bb114e31063..d6614e2fd2b 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -5,6 +5,7 @@ import EnableReviewAppModal from '~/environments/components/enable_review_app_mo
import Container from '~/environments/components/container.vue';
import EmptyState from '~/environments/components/empty_state.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';
@@ -18,8 +19,6 @@ describe('Environment', () => {
canReadEnvironment: true,
newEnvironmentPath: 'environments/new',
helpPagePath: 'help',
- canaryDeploymentFeatureId: 'canary_deployment',
- showCanaryDeploymentCallout: true,
userCalloutsPath: '/callouts',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
helpCanaryDeploymentsPath: 'help/canary-deployments',
@@ -114,6 +113,35 @@ describe('Environment', () => {
expect(wrapper.vm.updateContent).toHaveBeenCalledTimes(0);
});
});
+
+ describe('deploy boards', () => {
+ beforeEach(() => {
+ const deployEnvironment = {
+ ...environment,
+ rollout_status: {
+ status: 'found',
+ },
+ };
+
+ mockRequest(200, {
+ environments: [deployEnvironment],
+ stopped_count: 1,
+ available_count: 0,
+ });
+
+ return createWrapper();
+ });
+
+ it('should render deploy boards', () => {
+ expect(wrapper.find(DeployBoard).exists()).toBe(true);
+ });
+
+ it('should render arrow to open deploy boards', () => {
+ expect(
+ wrapper.find('.deploy-board-icon [data-testid="chevron-down-icon"]').exists(),
+ ).toBe(true);
+ });
+ });
});
});
diff --git a/spec/frontend/environments/environments_folder_view_spec.js b/spec/frontend/environments/environments_folder_view_spec.js
new file mode 100644
index 00000000000..e4661d27872
--- /dev/null
+++ b/spec/frontend/environments/environments_folder_view_spec.js
@@ -0,0 +1,59 @@
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import EnvironmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
+import axios from '~/lib/utils/axios_utils';
+import { environmentsList } from './mock_data';
+
+describe('Environments Folder View', () => {
+ let mock;
+ let wrapper;
+
+ const mockData = {
+ endpoint: 'environments.json',
+ folderName: 'review',
+ canReadEnvironment: true,
+ cssContainerClass: 'container',
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('successful request', () => {
+ beforeEach(() => {
+ mock.onGet(mockData.endpoint).reply(
+ 200,
+ {
+ environments: environmentsList,
+ stopped_count: 1,
+ available_count: 0,
+ },
+ {
+ 'X-nExt-pAge': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '20',
+ 'X-Total-Pages': '10',
+ },
+ );
+
+ wrapper = mount(EnvironmentsFolderViewComponent, { propsData: mockData });
+ return axios.waitForAll();
+ });
+
+ describe('deploy boards', () => {
+ it('should render arrow to open deploy boards', () => {
+ expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/environments_store_spec.js b/spec/frontend/environments/environments_store_spec.js
index 8abdbcbbe54..4a07281353f 100644
--- a/spec/frontend/environments/environments_store_spec.js
+++ b/spec/frontend/environments/environments_store_spec.js
@@ -1,5 +1,5 @@
import Store from '~/environments/stores/environments_store';
-import { environmentsList, serverData } from './mock_data';
+import { environmentsList, serverData, deployBoardMockData } from './mock_data';
describe('Store', () => {
let store;
@@ -160,4 +160,58 @@ describe('Store', () => {
expect(store.getOpenFolders()[0]).toEqual(store.state.environments[1]);
});
});
+
+ it('should store a non folder environment with deploy board if rollout_status key is provided', () => {
+ const environment = {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ rollout_status: deployBoardMockData,
+ },
+ };
+
+ store.storeEnvironments([environment]);
+
+ expect(store.state.environments[0].hasDeployBoard).toEqual(true);
+ expect(store.state.environments[0].isDeployBoardVisible).toEqual(true);
+ expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
+ });
+
+ describe('deploy boards', () => {
+ beforeEach(() => {
+ const environment = {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ },
+ rollout_status: deployBoardMockData,
+ };
+
+ store.storeEnvironments([environment]);
+ });
+
+ it('should toggle deploy board property for given environment id', () => {
+ store.toggleDeployBoard(1);
+
+ expect(store.state.environments[0].isDeployBoardVisible).toEqual(false);
+ });
+
+ it('should keep deploy board data when updating environments', () => {
+ expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
+
+ const environment = {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ },
+ rollout_status: deployBoardMockData,
+ };
+ store.storeEnvironments([environment]);
+
+ expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
+ });
+ });
});
diff --git a/spec/frontend/environments/folder/environments_folder_view_spec.js b/spec/frontend/environments/folder/environments_folder_view_spec.js
index f55cb851dde..3943e89c6cf 100644
--- a/spec/frontend/environments/folder/environments_folder_view_spec.js
+++ b/spec/frontend/environments/folder/environments_folder_view_spec.js
@@ -16,14 +16,12 @@ describe('Environments Folder View', () => {
folderName: 'review',
canReadEnvironment: true,
cssContainerClass: 'container',
- canaryDeploymentFeatureId: 'canary_deployment',
- showCanaryDeploymentCallout: true,
userCalloutsPath: '/callouts',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
helpCanaryDeploymentsPath: 'help/canary-deployments',
};
- const mockEnvironments = environmentList => {
+ const mockEnvironments = (environmentList) => {
mock.onGet(mockData.endpoint).reply(
200,
{
diff --git a/spec/frontend/environments/mock_data.js b/spec/frontend/environments/mock_data.js
index e7b99c8688c..4ad005f55c3 100644
--- a/spec/frontend/environments/mock_data.js
+++ b/spec/frontend/environments/mock_data.js
@@ -26,6 +26,45 @@ const buildProps = {
updated_at: '2017-02-01T19:42:18.400Z',
};
+const deployBoardMockData = {
+ instances: [
+ { status: 'finished', tooltip: 'tanuki-2334 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2335 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2336 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2337 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2338 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2339 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2340 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2334 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2335 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2336 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2337 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2338 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2339 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2340 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2341 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2342 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2343 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'failed', tooltip: 'tanuki-2344 Failed', pod_name: 'production-tanuki-1' },
+ { status: 'ready', tooltip: 'tanuki-2345 Ready', pod_name: 'production-tanuki-1' },
+ { status: 'ready', tooltip: 'tanuki-2346 Ready', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2348 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2349 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2350 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2353 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2354 Waiting', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2355 Waiting', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2356 Waiting', pod_name: 'production-tanuki-1' },
+ ],
+ abort_url: 'url',
+ rollback_url: 'url',
+ completion: 100,
+ status: 'found',
+ canary_ingress: {
+ canary_weight: 50,
+ },
+};
+
const environment = {
name: 'production',
size: 1,
@@ -262,4 +301,4 @@ const tableData = {
},
};
-export { environment, environmentsList, folder, serverData, tableData };
+export { environment, environmentsList, folder, serverData, tableData, deployBoardMockData };
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index ef3eeb8c7e4..0b9e0008ed7 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -38,8 +38,8 @@ describe('ErrorDetails', () => {
let mocks;
const externalUrl = 'https://sentry.io/organizations/test-sentry-nk/issues/1/?project=1';
- const findInput = name => {
- const inputs = wrapper.findAll(GlFormInput).filter(c => c.attributes('name') === name);
+ const findInput = (name) => {
+ const inputs = wrapper.findAll(GlFormInput).filter((c) => c.attributes('name') === name);
return inputs.length ? inputs.at(0) : inputs;
};
@@ -245,7 +245,7 @@ describe('ErrorDetails', () => {
it.each(Object.keys(severityLevel))(
'should set correct severity level variant for %s badge',
- level => {
+ (level) => {
wrapper.setData({
error: {
tags: { level: severityLevel[level] },
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 b22805f5227..05b3d2f1dec 100644
--- a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
@@ -41,16 +41,8 @@ describe('Error Tracking Actions', () => {
expect(findButtons().exists()).toBe(true);
return wrapper.vm.$nextTick().then(() => {
- expect(
- findButtons()
- .at(0)
- .attributes('title'),
- ).toBe('Ignore');
- expect(
- findButtons()
- .at(1)
- .attributes('title'),
- ).toBe('Resolve');
+ expect(findButtons().at(0).attributes('title')).toBe('Ignore');
+ expect(findButtons().at(1).attributes('title')).toBe('Resolve');
});
});
});
@@ -64,11 +56,7 @@ describe('Error Tracking Actions', () => {
expect(findButtons().exists()).toBe(true);
return wrapper.vm.$nextTick().then(() => {
- expect(
- findButtons()
- .at(0)
- .attributes('title'),
- ).toBe('Undo Ignore');
+ expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore');
});
});
});
@@ -82,11 +70,7 @@ describe('Error Tracking Actions', () => {
expect(findButtons().exists()).toBe(true);
return wrapper.vm.$nextTick().then(() => {
- expect(
- findButtons()
- .at(1)
- .attributes('title'),
- ).toBe('Unresolve');
+ expect(findButtons().at(1).attributes('title')).toBe('Unresolve');
});
});
});
diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
index a77bf39cb54..da12237b1d9 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -19,18 +19,9 @@ describe('ErrorTrackingList', () => {
const findErrorListTable = () => wrapper.find('table');
const findErrorListRows = () => wrapper.findAll('tbody tr');
const dropdownsArray = () => wrapper.findAll(GlDropdown);
- const findRecentSearchesDropdown = () =>
- dropdownsArray()
- .at(0)
- .find(GlDropdown);
- const findStatusFilterDropdown = () =>
- dropdownsArray()
- .at(1)
- .find(GlDropdown);
- const findSortDropdown = () =>
- dropdownsArray()
- .at(2)
- .find(GlDropdown);
+ const findRecentSearchesDropdown = () => dropdownsArray().at(0).find(GlDropdown);
+ const findStatusFilterDropdown = () => dropdownsArray().at(1).find(GlDropdown);
+ const findSortDropdown = () => dropdownsArray().at(2).find(GlDropdown);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findPagination = () => wrapper.find(GlPagination);
const findErrorActions = () => wrapper.find(ErrorTrackingActions);
@@ -156,7 +147,7 @@ describe('ErrorTrackingList', () => {
});
it('each error in the list should have an action button set', () => {
- findErrorListRows().wrappers.forEach(row => {
+ findErrorListRows().wrappers.forEach((row) => {
expect(row.find(ErrorTrackingActions).exists()).toBe(true);
});
});
@@ -243,7 +234,6 @@ describe('ErrorTrackingList', () => {
stubs: {
GlTable: false,
GlLink: false,
- GlDeprecatedButton: false,
},
});
});
@@ -274,7 +264,6 @@ describe('ErrorTrackingList', () => {
stubs: {
GlTable: false,
GlLink: false,
- GlDeprecatedButton: false,
},
});
});
@@ -454,7 +443,6 @@ describe('ErrorTrackingList', () => {
stubs: {
GlTable: false,
GlLink: false,
- GlDeprecatedButton: false,
},
});
});
diff --git a/spec/frontend/error_tracking/store/actions_spec.js b/spec/frontend/error_tracking/store/actions_spec.js
index 43037473a61..34ad600af05 100644
--- a/spec/frontend/error_tracking/store/actions_spec.js
+++ b/spec/frontend/error_tracking/store/actions_spec.js
@@ -28,7 +28,7 @@ describe('Sentry common store actions', () => {
const params = { endpoint, redirectUrl, status };
describe('updateStatus', () => {
- it('should handle successful status update', done => {
+ it('should handle successful status update', (done) => {
mock.onPut().reply(200, {});
testAction(
actions.updateStatus,
@@ -48,7 +48,7 @@ describe('Sentry common store actions', () => {
);
});
- it('should handle unsuccessful status update', done => {
+ it('should handle unsuccessful status update', (done) => {
mock.onPut().reply(400, {});
testAction(actions.updateStatus, params, {}, [], [], () => {
expect(visitUrl).not.toHaveBeenCalled();
diff --git a/spec/frontend/error_tracking/store/details/actions_spec.js b/spec/frontend/error_tracking/store/details/actions_spec.js
index 58e77c46e02..152ecde6985 100644
--- a/spec/frontend/error_tracking/store/details/actions_spec.js
+++ b/spec/frontend/error_tracking/store/details/actions_spec.js
@@ -28,7 +28,7 @@ describe('Sentry error details store actions', () => {
describe('startPollingStacktrace', () => {
const endpoint = '123/stacktrace';
- it('should commit SET_ERROR with received response', done => {
+ it('should commit SET_ERROR with received response', (done) => {
const payload = { error: [1, 2, 3] };
mockedAdapter.onGet().reply(200, payload);
testAction(
@@ -46,7 +46,7 @@ describe('Sentry error details store actions', () => {
);
});
- it('should show flash on API error', done => {
+ it('should show flash on API error', (done) => {
mockedAdapter.onGet().reply(400);
testAction(
@@ -62,7 +62,7 @@ describe('Sentry error details store actions', () => {
);
});
- it('should not restart polling when receiving an empty 204 response', done => {
+ it('should not restart polling when receiving an empty 204 response', (done) => {
mockedRestart = jest.spyOn(Poll.prototype, 'restart');
mockedAdapter.onGet().reply(204);
diff --git a/spec/frontend/error_tracking/store/list/actions_spec.js b/spec/frontend/error_tracking/store/list/actions_spec.js
index 7326472e1dd..a93608fe70d 100644
--- a/spec/frontend/error_tracking/store/list/actions_spec.js
+++ b/spec/frontend/error_tracking/store/list/actions_spec.js
@@ -20,7 +20,7 @@ describe('error tracking actions', () => {
});
describe('startPolling', () => {
- it('should start polling for data', done => {
+ it('should start polling for data', (done) => {
const payload = { errors: [{ id: 1 }, { id: 2 }] };
mock.onGet().reply(httpStatusCodes.OK, payload);
@@ -41,14 +41,17 @@ describe('error tracking actions', () => {
);
});
- it('should show flash on API error', done => {
+ it('should show flash on API error', (done) => {
mock.onGet().reply(httpStatusCodes.BAD_REQUEST);
testAction(
actions.startPolling,
{},
{},
- [{ type: types.SET_LOADING, payload: true }, { type: types.SET_LOADING, payload: false }],
+ [
+ { type: types.SET_LOADING, payload: true },
+ { type: types.SET_LOADING, payload: false },
+ ],
[],
() => {
expect(createFlash).toHaveBeenCalledTimes(1);
@@ -64,7 +67,10 @@ describe('error tracking actions', () => {
actions.restartPolling,
{},
{},
- [{ type: types.SET_ERRORS, payload: [] }, { type: types.SET_LOADING, payload: true }],
+ [
+ { type: types.SET_ERRORS, payload: [] },
+ { type: types.SET_LOADING, payload: true },
+ ],
[],
);
});
@@ -110,7 +116,10 @@ describe('error tracking actions', () => {
actions.sortByField,
field,
{},
- [{ type: types.SET_CURSOR, payload: null }, { type: types.SET_SORT_FIELD, payload: field }],
+ [
+ { type: types.SET_CURSOR, payload: null },
+ { type: types.SET_SORT_FIELD, payload: field },
+ ],
[{ type: 'stopPolling' }, { type: 'startPolling' }],
);
});
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 f4a765a3d73..e2a8b57f555 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
@@ -35,12 +35,7 @@ describe('error tracking settings form', () => {
it('is rendered', () => {
expect(wrapper.findAll(GlFormInput).length).toBe(2);
expect(wrapper.find(GlFormInput).attributes('id')).toBe('error-tracking-api-host');
- expect(
- wrapper
- .findAll(GlFormInput)
- .at(1)
- .attributes('id'),
- ).toBe('error-tracking-token');
+ expect(wrapper.findAll(GlFormInput).at(1).attributes('id')).toBe('error-tracking-token');
expect(wrapper.findAll(GlButton).exists()).toBe(true);
});
@@ -56,12 +51,9 @@ describe('error tracking settings form', () => {
);
expect(pageText).not.toContain('Connection has failed. Re-check Auth Token and try again');
- expect(
- wrapper
- .findAll(GlFormInput)
- .at(0)
- .attributes('placeholder'),
- ).toContain('https://mysentryserver.com');
+ expect(wrapper.findAll(GlFormInput).at(0).attributes('placeholder')).toContain(
+ 'https://mysentryserver.com',
+ );
});
});
diff --git a/spec/frontend/error_tracking_settings/store/actions_spec.js b/spec/frontend/error_tracking_settings/store/actions_spec.js
index b076e6ecd31..216bf8011e8 100644
--- a/spec/frontend/error_tracking_settings/store/actions_spec.js
+++ b/spec/frontend/error_tracking_settings/store/actions_spec.js
@@ -27,7 +27,7 @@ describe('error tracking settings actions', () => {
refreshCurrentPage.mockClear();
});
- it('should request and transform the project list', done => {
+ it('should request and transform the project list', (done) => {
mock.onGet(TEST_HOST).reply(() => [200, { projects: projectList }]);
testAction(
actions.fetchProjects,
@@ -48,7 +48,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should handle a server error', done => {
+ it('should handle a server error', (done) => {
mock.onGet(`${TEST_HOST}.json`).reply(() => [400]);
testAction(
actions.fetchProjects,
@@ -68,7 +68,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should request projects correctly', done => {
+ it('should request projects correctly', (done) => {
testAction(
actions.requestProjects,
null,
@@ -79,7 +79,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should receive projects correctly', done => {
+ it('should receive projects correctly', (done) => {
const testPayload = [];
testAction(
actions.receiveProjectsSuccess,
@@ -95,7 +95,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should handle errors when receiving projects', done => {
+ it('should handle errors when receiving projects', (done) => {
const testPayload = [];
testAction(
actions.receiveProjectsError,
@@ -126,7 +126,7 @@ describe('error tracking settings actions', () => {
mock.restore();
});
- it('should save the page', done => {
+ it('should save the page', (done) => {
mock.onPatch(TEST_HOST).reply(200);
testAction(actions.updateSettings, null, state, [], [{ type: 'requestSettings' }], () => {
expect(mock.history.patch.length).toBe(1);
@@ -135,7 +135,7 @@ describe('error tracking settings actions', () => {
});
});
- it('should handle a server error', done => {
+ it('should handle a server error', (done) => {
mock.onPatch(TEST_HOST).reply(400);
testAction(
actions.updateSettings,
@@ -156,7 +156,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should request to save the page', done => {
+ it('should request to save the page', (done) => {
testAction(
actions.requestSettings,
null,
@@ -167,7 +167,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should handle errors when requesting to save the page', done => {
+ it('should handle errors when requesting to save the page', (done) => {
testAction(
actions.receiveSettingsError,
{},
@@ -181,7 +181,7 @@ describe('error tracking settings actions', () => {
describe('generic actions to update the store', () => {
const testData = 'test';
- it('should reset the `connect success` flag when updating the api host', done => {
+ it('should reset the `connect success` flag when updating the api host', (done) => {
testAction(
actions.updateApiHost,
testData,
@@ -192,7 +192,7 @@ describe('error tracking settings actions', () => {
);
});
- it('should reset the `connect success` flag when updating the token', done => {
+ it('should reset the `connect success` flag when updating the token', (done) => {
testAction(
actions.updateToken,
testData,
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 06b9385b112..21b894ccbef 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
@@ -36,7 +36,7 @@ describe('Configure Feature Flags Modal', () => {
const findPrimaryAction = () => findGlModal().props('actionPrimary');
const findProjectNameInput = () => wrapper.find('#project_name_verification');
const findDangerGlAlert = () =>
- wrapper.findAll(GlAlert).filter(c => c.props('variant') === 'danger');
+ wrapper.findAll(GlAlert).filter((c) => c.props('variant') === 'danger');
describe('idle', () => {
afterEach(() => wrapper.destroy());
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 f8e25925774..a754c682356 100644
--- a/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
+++ b/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
@@ -42,7 +42,7 @@ describe('Edit feature flag form', () => {
});
};
- beforeEach(done => {
+ beforeEach((done) => {
mock = new MockAdapter(axios);
mock.onGet(`${TEST_HOST}/feature_flags.json`).replyOnce(200, {
id: 21,
diff --git a/spec/frontend/feature_flags/components/environments_dropdown_spec.js b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
index 917f5f5ccd3..042fccaa369 100644
--- a/spec/frontend/feature_flags/components/environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon, GlDeprecatedButton, GlSearchBoxByType } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlSearchBoxByType } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import EnvironmentsDropdown from '~/feature_flags/components/environments_dropdown.vue';
@@ -11,7 +11,7 @@ describe('Feature flags > Environments dropdown ', () => {
let wrapper;
let mock;
const results = ['production', 'staging'];
- const factory = props => {
+ const factory = (props) => {
wrapper = shallowMount(EnvironmentsDropdown, {
propsData: {
...props,
@@ -99,8 +99,8 @@ describe('Feature flags > Environments dropdown ', () => {
it('emits event when a suggestion is clicked', async () => {
const button = wrapper
- .findAll(GlDeprecatedButton)
- .filter(b => b.text() === 'production')
+ .findAll(GlButton)
+ .filter((b) => b.text() === 'production')
.at(0);
button.vm.$emit('click');
await wrapper.vm.$nextTick();
@@ -110,7 +110,7 @@ describe('Feature flags > Environments dropdown ', () => {
describe('on click clear button', () => {
beforeEach(async () => {
- wrapper.find(GlDeprecatedButton).vm.$emit('click');
+ wrapper.find(GlButton).vm.$emit('click');
await wrapper.vm.$nextTick();
});
@@ -136,10 +136,7 @@ describe('Feature flags > Environments dropdown ', () => {
});
it('emits create event', async () => {
- wrapper
- .findAll(GlDeprecatedButton)
- .at(0)
- .vm.$emit('click');
+ wrapper.findAll(GlButton).at(0).vm.$emit('click');
await wrapper.vm.$nextTick();
expect(wrapper.emitted('createClicked')).toEqual([['production']]);
});
diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js
index 3c1234fea94..8242d667d2e 100644
--- a/spec/frontend/feature_flags/components/feature_flags_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_spec.js
@@ -85,7 +85,7 @@ describe('Feature flags', () => {
describe('when limit exceeded', () => {
const provideData = { ...mockData, featureFlagsLimitExceeded: true };
- beforeEach(done => {
+ beforeEach((done) => {
mock
.onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
.reply(200, getRequestData, {});
@@ -101,11 +101,9 @@ describe('Feature flags', () => {
it('shows a feature flags limit reached alert', () => {
expect(limitAlert().exists()).toBe(true);
- expect(
- limitAlert()
- .find(GlSprintf)
- .attributes('message'),
- ).toContain('Feature flags limit reached');
+ expect(limitAlert().find(GlSprintf).attributes('message')).toContain(
+ 'Feature flags limit reached',
+ );
});
describe('when the alert is dismissed', () => {
@@ -134,7 +132,7 @@ describe('Feature flags', () => {
newUserListPath: null,
};
- beforeEach(done => {
+ beforeEach((done) => {
mock
.onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
.reply(200, getRequestData, {});
@@ -219,7 +217,7 @@ describe('Feature flags', () => {
});
describe('with paginated feature flags', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mock
.onGet(mockState.endpoint, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
.replyOnce(200, getRequestData, {
@@ -299,7 +297,7 @@ describe('Feature flags', () => {
});
describe('in user lists tab', () => {
- beforeEach(done => {
+ beforeEach((done) => {
factory();
setImmediate(done);
});
@@ -319,7 +317,7 @@ describe('Feature flags', () => {
});
describe('unsuccessful request', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mock
.onGet(mockState.endpoint, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
.replyOnce(500, {});
@@ -352,7 +350,7 @@ describe('Feature flags', () => {
});
describe('rotate instance id', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mock
.onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
.reply(200, getRequestData, {});
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 a488662470e..8881cfae88d 100644
--- a/spec/frontend/feature_flags/components/feature_flags_table_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_table_spec.js
@@ -120,13 +120,11 @@ describe('Feature flag table', () => {
describe('when active and with an update toggle', () => {
let toggle;
- let spy;
beforeEach(() => {
props.featureFlags[0].update_path = props.featureFlags[0].destroy_path;
createWrapper(props);
toggle = wrapper.find(GlToggle);
- spy = mockTracking('_category_', toggle.element, jest.spyOn);
});
it('should have a toggle', () => {
@@ -142,14 +140,6 @@ describe('Feature flag table', () => {
expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]);
});
});
-
- it('should track a click', () => {
- toggle.trigger('click');
-
- expect(spy).toHaveBeenCalledWith('_category_', 'click_button', {
- label: 'feature_flag_toggle',
- });
- });
});
describe('with an active scope and a percentage rollout strategy', () => {
@@ -180,6 +170,8 @@ describe('Feature flag table', () => {
});
describe('with a new version flag', () => {
+ let toggle;
+ let spy;
let badges;
beforeEach(() => {
@@ -194,6 +186,7 @@ describe('Feature flag table', () => {
description: 'flag description',
destroy_path: 'destroy/path',
edit_path: 'edit/path',
+ update_path: 'update/path',
version: NEW_VERSION_FLAG,
scopes: [],
strategies: [
@@ -226,6 +219,8 @@ describe('Feature flag table', () => {
provide: { csrfToken: 'fakeToken', glFeatures: { featureFlagsNewVersion: true } },
});
+ toggle = wrapper.find(GlToggle);
+ spy = mockTracking('_category_', toggle.element, jest.spyOn);
badges = wrapper.findAll('[data-testid="strategy-badge"]');
});
@@ -254,6 +249,14 @@ describe('Feature flag table', () => {
it('shows the name of a user list for user list', () => {
expect(badges.at(3).text()).toContain('User List - test list');
});
+
+ it('tracks a click', () => {
+ toggle.trigger('click');
+
+ expect(spy).toHaveBeenCalledWith('_category_', 'click_button', {
+ label: 'feature_flag_toggle',
+ });
+ });
});
it('renders a feature flag without an iid', () => {
diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js
index 2c2a726d26f..3a057aedde9 100644
--- a/spec/frontend/feature_flags/components/form_spec.js
+++ b/spec/frontend/feature_flags/components/form_spec.js
@@ -118,7 +118,7 @@ describe('feature flag form', () => {
});
});
- it('should be disabled if the feature flag is not active', done => {
+ 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);
@@ -191,7 +191,7 @@ describe('feature flag form', () => {
expect(wrapper.vm.formScopes[0].active).toBe(false);
});
- it('should be disabled if the feature flag is not active', done => {
+ it('should be disabled if the feature flag is not active', (done) => {
wrapper.setProps({ active: false });
wrapper.vm.$nextTick(() => {
@@ -301,7 +301,7 @@ describe('feature flag form', () => {
});
describe('on submit', () => {
- const selectFirstRolloutStrategyOption = dropdownIndex => {
+ const selectFirstRolloutStrategyOption = (dropdownIndex) => {
wrapper
.findAll('select.js-rollout-strategy')
.at(dropdownIndex)
@@ -347,10 +347,7 @@ describe('feature flag form', () => {
return wrapper.vm.$nextTick();
})
.then(() => {
- wrapper
- .find('.js-add-new-scope')
- .find(ToggleButton)
- .vm.$emit('change', true);
+ wrapper.find('.js-add-new-scope').find(ToggleButton).vm.$emit('change', true);
})
.then(() => {
wrapper.find(ToggleButton).vm.$emit('change', true);
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 12dc98fbde8..ad58ceaf5f8 100644
--- a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
@@ -94,7 +94,7 @@ describe('New Environments Dropdown', () => {
});
it('should not display a create label', () => {
- items = items.filter(i => i.text().startsWith('Create'));
+ items = items.filter((i) => i.text().startsWith('Create'));
expect(items).toHaveLength(0);
});
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 b34fe7779e3..1c85eadc678 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
@@ -66,7 +66,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
it('should search when the filter changes', async () => {
let r;
Api.searchFeatureFlagUserLists.mockReturnValue(
- new Promise(resolve => {
+ new Promise((resolve) => {
r = resolve;
}),
);
diff --git a/spec/frontend/feature_flags/components/strategy_parameters_spec.js b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
index a024384e623..82811c05195 100644
--- a/spec/frontend/feature_flags/components/strategy_parameters_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
@@ -51,7 +51,7 @@ describe('~/feature_flags/components/strategy_parameters.vue', () => {
});
it('should show the correct component', () => {
- expect(wrapper.contains(component)).toBe(true);
+ expect(wrapper.find(component).exists()).toBe(true);
});
it('should emit changes from the lower component', () => {
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 d6ced3be168..974f63ba934 100644
--- a/spec/frontend/feature_flags/components/user_lists_table_spec.js
+++ b/spec/frontend/feature_flags/components/user_lists_table_spec.js
@@ -42,7 +42,7 @@ describe('User Lists Table', () => {
it('should display a user list entry per user list', () => {
const lists = wrapper.findAll('[data-testid="ffUserList"]');
expect(lists).toHaveLength(5);
- lists.wrappers.forEach(list => {
+ lists.wrappers.forEach((list) => {
expect(list.find('[data-testid="ffUserListName"]').exists()).toBe(true);
expect(list.find('[data-testid="ffUserListIds"]').exists()).toBe(true);
expect(list.find('[data-testid="ffUserListTimestamp"]').exists()).toBe(true);
diff --git a/spec/frontend/feature_flags/store/edit/actions_spec.js b/spec/frontend/feature_flags/store/edit/actions_spec.js
index 9d764799d09..20cec5daac0 100644
--- a/spec/frontend/feature_flags/store/edit/actions_spec.js
+++ b/spec/frontend/feature_flags/store/edit/actions_spec.js
@@ -44,7 +44,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('success', () => {
- it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagSuccess ', done => {
+ it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagSuccess ', (done) => {
const featureFlag = {
name: 'feature_flag',
description: 'feature flag',
@@ -80,7 +80,7 @@ describe('Feature flags Edit Module actions', () => {
done,
);
});
- it('handles new version flags as well', done => {
+ it('handles new version flags as well', (done) => {
const featureFlag = {
name: 'name',
description: 'description',
@@ -117,7 +117,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('error', () => {
- it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagError ', done => {
+ it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagError ', (done) => {
mock.onPut(`${TEST_HOST}/endpoint.json`).replyOnce(500, { message: [] });
testAction(
@@ -145,7 +145,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('requestUpdateFeatureFlag', () => {
- it('should commit REQUEST_UPDATE_FEATURE_FLAG mutation', done => {
+ it('should commit REQUEST_UPDATE_FEATURE_FLAG mutation', (done) => {
testAction(
requestUpdateFeatureFlag,
null,
@@ -158,7 +158,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('receiveUpdateFeatureFlagSuccess', () => {
- it('should commit RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS mutation', done => {
+ it('should commit RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS mutation', (done) => {
testAction(
receiveUpdateFeatureFlagSuccess,
null,
@@ -175,7 +175,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('receiveUpdateFeatureFlagError', () => {
- it('should commit RECEIVE_UPDATE_FEATURE_FLAG_ERROR mutation', done => {
+ it('should commit RECEIVE_UPDATE_FEATURE_FLAG_ERROR mutation', (done) => {
testAction(
receiveUpdateFeatureFlagError,
'There was an error',
@@ -200,7 +200,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('success', () => {
- it('dispatches requestFeatureFlag and receiveFeatureFlagSuccess ', done => {
+ it('dispatches requestFeatureFlag and receiveFeatureFlagSuccess ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, { id: 1 });
testAction(
@@ -223,7 +223,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('error', () => {
- it('dispatches requestFeatureFlag and receiveUpdateFeatureFlagError ', done => {
+ it('dispatches requestFeatureFlag and receiveUpdateFeatureFlagError ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {});
testAction(
@@ -246,7 +246,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('requestFeatureFlag', () => {
- it('should commit REQUEST_FEATURE_FLAG mutation', done => {
+ it('should commit REQUEST_FEATURE_FLAG mutation', (done) => {
testAction(
requestFeatureFlag,
null,
@@ -259,7 +259,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('receiveFeatureFlagSuccess', () => {
- it('should commit RECEIVE_FEATURE_FLAG_SUCCESS mutation', done => {
+ it('should commit RECEIVE_FEATURE_FLAG_SUCCESS mutation', (done) => {
testAction(
receiveFeatureFlagSuccess,
{ id: 1 },
@@ -272,7 +272,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('receiveFeatureFlagError', () => {
- it('should commit RECEIVE_FEATURE_FLAG_ERROR mutation', done => {
+ it('should commit RECEIVE_FEATURE_FLAG_ERROR mutation', (done) => {
testAction(
receiveFeatureFlagError,
null,
@@ -289,7 +289,7 @@ describe('Feature flags Edit Module actions', () => {
});
describe('toggelActive', () => {
- it('should commit TOGGLE_ACTIVE mutation', done => {
+ it('should commit TOGGLE_ACTIVE mutation', (done) => {
testAction(
toggleActive,
true,
diff --git a/spec/frontend/feature_flags/store/index/actions_spec.js b/spec/frontend/feature_flags/store/index/actions_spec.js
index d223bb2c292..82e16958d33 100644
--- a/spec/frontend/feature_flags/store/index/actions_spec.js
+++ b/spec/frontend/feature_flags/store/index/actions_spec.js
@@ -40,7 +40,7 @@ describe('Feature flags actions', () => {
});
describe('setFeatureFlagsOptions', () => {
- it('should commit SET_FEATURE_FLAGS_OPTIONS mutation', done => {
+ it('should commit SET_FEATURE_FLAGS_OPTIONS mutation', (done) => {
testAction(
setFeatureFlagsOptions,
{ page: '1', scope: 'all' },
@@ -65,7 +65,7 @@ describe('Feature flags actions', () => {
});
describe('success', () => {
- it('dispatches requestFeatureFlags and receiveFeatureFlagsSuccess ', done => {
+ it('dispatches requestFeatureFlags and receiveFeatureFlagsSuccess ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, getRequestData, {});
testAction(
@@ -88,7 +88,7 @@ describe('Feature flags actions', () => {
});
describe('error', () => {
- it('dispatches requestFeatureFlags and receiveFeatureFlagsError ', done => {
+ it('dispatches requestFeatureFlags and receiveFeatureFlagsError ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {});
testAction(
@@ -111,7 +111,7 @@ describe('Feature flags actions', () => {
});
describe('requestFeatureFlags', () => {
- it('should commit RECEIVE_FEATURE_FLAGS_SUCCESS mutation', done => {
+ it('should commit RECEIVE_FEATURE_FLAGS_SUCCESS mutation', (done) => {
testAction(
requestFeatureFlags,
null,
@@ -124,7 +124,7 @@ describe('Feature flags actions', () => {
});
describe('receiveFeatureFlagsSuccess', () => {
- it('should commit RECEIVE_FEATURE_FLAGS_SUCCESS mutation', done => {
+ it('should commit RECEIVE_FEATURE_FLAGS_SUCCESS mutation', (done) => {
testAction(
receiveFeatureFlagsSuccess,
{ data: getRequestData, headers: {} },
@@ -142,7 +142,7 @@ describe('Feature flags actions', () => {
});
describe('receiveFeatureFlagsError', () => {
- it('should commit RECEIVE_FEATURE_FLAGS_ERROR mutation', done => {
+ it('should commit RECEIVE_FEATURE_FLAGS_ERROR mutation', (done) => {
testAction(
receiveFeatureFlagsError,
null,
@@ -160,7 +160,7 @@ describe('Feature flags actions', () => {
});
describe('success', () => {
- it('dispatches requestUserLists and receiveUserListsSuccess ', done => {
+ it('dispatches requestUserLists and receiveUserListsSuccess ', (done) => {
testAction(
fetchUserLists,
null,
@@ -181,7 +181,7 @@ describe('Feature flags actions', () => {
});
describe('error', () => {
- it('dispatches requestUserLists and receiveUserListsError ', done => {
+ it('dispatches requestUserLists and receiveUserListsError ', (done) => {
Api.fetchFeatureFlagUserLists.mockRejectedValue();
testAction(
@@ -204,7 +204,7 @@ describe('Feature flags actions', () => {
});
describe('requestUserLists', () => {
- it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', done => {
+ it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => {
testAction(
requestUserLists,
null,
@@ -217,7 +217,7 @@ describe('Feature flags actions', () => {
});
describe('receiveUserListsSuccess', () => {
- it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', done => {
+ it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => {
testAction(
receiveUserListsSuccess,
{ data: [userList], headers: {} },
@@ -235,7 +235,7 @@ describe('Feature flags actions', () => {
});
describe('receiveUserListsError', () => {
- it('should commit RECEIVE_USER_LISTS_ERROR mutation', done => {
+ it('should commit RECEIVE_USER_LISTS_ERROR mutation', (done) => {
testAction(
receiveUserListsError,
null,
@@ -260,7 +260,7 @@ describe('Feature flags actions', () => {
});
describe('success', () => {
- it('dispatches requestRotateInstanceId and receiveRotateInstanceIdSuccess ', done => {
+ it('dispatches requestRotateInstanceId and receiveRotateInstanceIdSuccess ', (done) => {
mock.onPost(`${TEST_HOST}/endpoint.json`).replyOnce(200, rotateData, {});
testAction(
@@ -283,7 +283,7 @@ describe('Feature flags actions', () => {
});
describe('error', () => {
- it('dispatches requestRotateInstanceId and receiveRotateInstanceIdError ', done => {
+ it('dispatches requestRotateInstanceId and receiveRotateInstanceIdError ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {});
testAction(
@@ -306,7 +306,7 @@ describe('Feature flags actions', () => {
});
describe('requestRotateInstanceId', () => {
- it('should commit REQUEST_ROTATE_INSTANCE_ID mutation', done => {
+ it('should commit REQUEST_ROTATE_INSTANCE_ID mutation', (done) => {
testAction(
requestRotateInstanceId,
null,
@@ -319,7 +319,7 @@ describe('Feature flags actions', () => {
});
describe('receiveRotateInstanceIdSuccess', () => {
- it('should commit RECEIVE_ROTATE_INSTANCE_ID_SUCCESS mutation', done => {
+ it('should commit RECEIVE_ROTATE_INSTANCE_ID_SUCCESS mutation', (done) => {
testAction(
receiveRotateInstanceIdSuccess,
{ data: rotateData, headers: {} },
@@ -337,7 +337,7 @@ describe('Feature flags actions', () => {
});
describe('receiveRotateInstanceIdError', () => {
- it('should commit RECEIVE_ROTATE_INSTANCE_ID_ERROR mutation', done => {
+ it('should commit RECEIVE_ROTATE_INSTANCE_ID_ERROR mutation', (done) => {
testAction(
receiveRotateInstanceIdError,
null,
@@ -353,7 +353,7 @@ describe('Feature flags actions', () => {
let mock;
beforeEach(() => {
- mockedState.featureFlags = getRequestData.feature_flags.map(flag => ({
+ mockedState.featureFlags = getRequestData.feature_flags.map((flag) => ({
...flag,
scopes: mapToScopesViewModel(flag.scopes || []),
}));
@@ -364,7 +364,7 @@ describe('Feature flags actions', () => {
mock.restore();
});
describe('success', () => {
- it('dispatches updateFeatureFlag and receiveUpdateFeatureFlagSuccess', done => {
+ it('dispatches updateFeatureFlag and receiveUpdateFeatureFlagSuccess', (done) => {
mock.onPut(featureFlag.update_path).replyOnce(200, featureFlag, {});
testAction(
@@ -387,7 +387,7 @@ describe('Feature flags actions', () => {
});
});
describe('error', () => {
- it('dispatches updateFeatureFlag and receiveUpdateFeatureFlagSuccess', done => {
+ it('dispatches updateFeatureFlag and receiveUpdateFeatureFlagSuccess', (done) => {
mock.onPut(featureFlag.update_path).replyOnce(500);
testAction(
@@ -412,13 +412,13 @@ describe('Feature flags actions', () => {
});
describe('updateFeatureFlag', () => {
beforeEach(() => {
- mockedState.featureFlags = getRequestData.feature_flags.map(f => ({
+ mockedState.featureFlags = getRequestData.feature_flags.map((f) => ({
...f,
scopes: mapToScopesViewModel(f.scopes || []),
}));
});
- it('commits UPDATE_FEATURE_FLAG with the given flag', done => {
+ it('commits UPDATE_FEATURE_FLAG with the given flag', (done) => {
testAction(
updateFeatureFlag,
featureFlag,
@@ -436,13 +436,13 @@ describe('Feature flags actions', () => {
});
describe('receiveUpdateFeatureFlagSuccess', () => {
beforeEach(() => {
- mockedState.featureFlags = getRequestData.feature_flags.map(f => ({
+ mockedState.featureFlags = getRequestData.feature_flags.map((f) => ({
...f,
scopes: mapToScopesViewModel(f.scopes || []),
}));
});
- it('commits RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS with the given flag', done => {
+ it('commits RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS with the given flag', (done) => {
testAction(
receiveUpdateFeatureFlagSuccess,
featureFlag,
@@ -460,13 +460,13 @@ describe('Feature flags actions', () => {
});
describe('receiveUpdateFeatureFlagError', () => {
beforeEach(() => {
- mockedState.featureFlags = getRequestData.feature_flags.map(f => ({
+ mockedState.featureFlags = getRequestData.feature_flags.map((f) => ({
...f,
scopes: mapToScopesViewModel(f.scopes || []),
}));
});
- it('commits RECEIVE_UPDATE_FEATURE_FLAG_ERROR with the given flag id', done => {
+ it('commits RECEIVE_UPDATE_FEATURE_FLAG_ERROR with the given flag id', (done) => {
testAction(
receiveUpdateFeatureFlagError,
featureFlag.id,
@@ -492,7 +492,7 @@ describe('Feature flags actions', () => {
Api.deleteFeatureFlagUserList.mockResolvedValue();
});
- it('should refresh the user lists', done => {
+ it('should refresh the user lists', (done) => {
testAction(
deleteUserList,
userList,
@@ -509,7 +509,7 @@ describe('Feature flags actions', () => {
Api.deleteFeatureFlagUserList.mockRejectedValue({ response: { data: 'some error' } });
});
- it('should dispatch receiveDeleteUserListError', done => {
+ it('should dispatch receiveDeleteUserListError', (done) => {
testAction(
deleteUserList,
userList,
@@ -529,7 +529,7 @@ describe('Feature flags actions', () => {
});
describe('receiveDeleteUserListError', () => {
- it('should commit RECEIVE_DELETE_USER_LIST_ERROR with the given list', done => {
+ it('should commit RECEIVE_DELETE_USER_LIST_ERROR with the given list', (done) => {
testAction(
receiveDeleteUserListError,
{ list: userList, error: 'mock error' },
@@ -547,7 +547,7 @@ describe('Feature flags actions', () => {
});
describe('clearAlert', () => {
- it('should commit RECEIVE_CLEAR_ALERT', done => {
+ it('should commit RECEIVE_CLEAR_ALERT', (done) => {
const alertIndex = 3;
testAction(
diff --git a/spec/frontend/feature_flags/store/index/mutations_spec.js b/spec/frontend/feature_flags/store/index/mutations_spec.js
index 376c7b069fa..eec56800a8d 100644
--- a/spec/frontend/feature_flags/store/index/mutations_spec.js
+++ b/spec/frontend/feature_flags/store/index/mutations_spec.js
@@ -50,7 +50,7 @@ describe('Feature flags store Mutations', () => {
});
it('should set featureFlags with the transformed data', () => {
- const expected = getRequestData.feature_flags.map(flag => ({
+ const expected = getRequestData.feature_flags.map((flag) => ({
...flag,
scopes: mapToScopesViewModel(flag.scopes || []),
}));
@@ -183,7 +183,7 @@ describe('Feature flags store Mutations', () => {
describe('UPDATE_FEATURE_FLAG', () => {
beforeEach(() => {
- stateCopy.featureFlags = getRequestData.feature_flags.map(flag => ({
+ stateCopy.featureFlags = getRequestData.feature_flags.map((flag) => ({
...flag,
scopes: mapToScopesViewModel(flag.scopes || []),
}));
@@ -209,7 +209,7 @@ describe('Feature flags store Mutations', () => {
describe('RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS', () => {
const runUpdate = (stateCount, flagState, featureFlagUpdateParams) => {
- stateCopy.featureFlags = getRequestData.feature_flags.map(flag => ({
+ stateCopy.featureFlags = getRequestData.feature_flags.map((flag) => ({
...flag,
...flagState,
scopes: mapToScopesViewModel(flag.scopes || []),
@@ -237,7 +237,7 @@ describe('Feature flags store Mutations', () => {
describe('RECEIVE_UPDATE_FEATURE_FLAG_ERROR', () => {
beforeEach(() => {
- stateCopy.featureFlags = getRequestData.feature_flags.map(flag => ({
+ stateCopy.featureFlags = getRequestData.feature_flags.map((flag) => ({
...flag,
scopes: mapToScopesViewModel(flag.scopes || []),
}));
diff --git a/spec/frontend/feature_flags/store/new/actions_spec.js b/spec/frontend/feature_flags/store/new/actions_spec.js
index 130c5235aa0..9168f11fdfb 100644
--- a/spec/frontend/feature_flags/store/new/actions_spec.js
+++ b/spec/frontend/feature_flags/store/new/actions_spec.js
@@ -59,7 +59,7 @@ describe('Feature flags New Module Actions', () => {
});
describe('success', () => {
- it('dispatches requestCreateFeatureFlag and receiveCreateFeatureFlagSuccess ', done => {
+ it('dispatches requestCreateFeatureFlag and receiveCreateFeatureFlagSuccess ', (done) => {
const convertedActionParams = mapFromScopesViewModel(actionParams);
mock.onPost(`${TEST_HOST}/endpoint.json`, convertedActionParams).replyOnce(200);
@@ -81,7 +81,7 @@ describe('Feature flags New Module Actions', () => {
);
});
- it('sends strategies for new style feature flags', done => {
+ it('sends strategies for new style feature flags', (done) => {
const newVersionFlagParams = {
name: 'name',
description: 'description',
@@ -120,7 +120,7 @@ describe('Feature flags New Module Actions', () => {
});
describe('error', () => {
- it('dispatches requestCreateFeatureFlag and receiveCreateFeatureFlagError ', done => {
+ it('dispatches requestCreateFeatureFlag and receiveCreateFeatureFlagError ', (done) => {
const convertedActionParams = mapFromScopesViewModel(actionParams);
mock
@@ -148,7 +148,7 @@ describe('Feature flags New Module Actions', () => {
});
describe('requestCreateFeatureFlag', () => {
- it('should commit REQUEST_CREATE_FEATURE_FLAG mutation', done => {
+ it('should commit REQUEST_CREATE_FEATURE_FLAG mutation', (done) => {
testAction(
requestCreateFeatureFlag,
null,
@@ -161,7 +161,7 @@ describe('Feature flags New Module Actions', () => {
});
describe('receiveCreateFeatureFlagSuccess', () => {
- it('should commit RECEIVE_CREATE_FEATURE_FLAG_SUCCESS mutation', done => {
+ it('should commit RECEIVE_CREATE_FEATURE_FLAG_SUCCESS mutation', (done) => {
testAction(
receiveCreateFeatureFlagSuccess,
null,
@@ -178,7 +178,7 @@ describe('Feature flags New Module Actions', () => {
});
describe('receiveCreateFeatureFlagError', () => {
- it('should commit RECEIVE_CREATE_FEATURE_FLAG_ERROR mutation', done => {
+ it('should commit RECEIVE_CREATE_FEATURE_FLAG_ERROR mutation', (done) => {
testAction(
receiveCreateFeatureFlagError,
'There was an error',
diff --git a/spec/frontend/feature_highlight/feature_highlight_helper_spec.js b/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
index 2c3c3e3267a..beae5041156 100644
--- a/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
+++ b/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
@@ -44,7 +44,7 @@ describe('feature highlight helper', () => {
});
describe('inserted', () => {
- it('registers click event callback', done => {
+ it('registers click event callback', (done) => {
const context = {
getAttribute: () => 'popoverId',
dataset: {
@@ -52,7 +52,7 @@ describe('feature highlight helper', () => {
},
};
- jest.spyOn($.fn, 'on').mockImplementation(event => {
+ jest.spyOn($.fn, 'on').mockImplementation((event) => {
expect(event).toEqual('click');
done();
});
diff --git a/spec/frontend/filterable_list_spec.js b/spec/frontend/filterable_list_spec.js
index 67d18611661..8c6a71abad7 100644
--- a/spec/frontend/filterable_list_spec.js
+++ b/spec/frontend/filterable_list_spec.js
@@ -1,5 +1,5 @@
+import { getJSONFixture, setHTMLFixture } from 'helpers/fixtures';
import FilterableList from '~/filterable_list';
-import { getJSONFixture, setHTMLFixture } from './helpers/fixtures';
describe('FilterableList', () => {
let List;
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 158f70f7d47..f1cff02261d 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
@@ -10,7 +10,7 @@ describe('Recent Searches Dropdown Content', () => {
const findDropdownItems = () => wrapper.findAll({ ref: 'dropdownItem' });
const findDropdownNote = () => wrapper.find({ ref: 'dropdownNote' });
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(RecentSearchesDropdownContent, {
propsData: {
allowedKeys: IssuableFilteredSearchTokenKeys.getKeys(),
@@ -84,18 +84,11 @@ describe('Recent Searches Dropdown Content', () => {
});
it('expect second dropdown to have 2 tokens', () => {
- expect(
- findDropdownItems()
- .at(1)
- .findAll('.js-dropdown-token'),
- ).toHaveLength(2);
+ expect(findDropdownItems().at(1).findAll('.js-dropdown-token')).toHaveLength(2);
});
it('emits recentSearchesItemSelected on dropdown item click', () => {
- findDropdownItems()
- .at(0)
- .find('.js-dropdown-button')
- .trigger('click');
+ findDropdownItems().at(0).find('.js-dropdown-button').trigger('click');
expect(onRecentSearchesItemSelectedSpy).toHaveBeenCalledWith('foo');
});
diff --git a/spec/frontend/filtered_search/dropdown_utils_spec.js b/spec/frontend/filtered_search/dropdown_utils_spec.js
index 3320b6b0942..32d1f909d0b 100644
--- a/spec/frontend/filtered_search/dropdown_utils_spec.js
+++ b/spec/frontend/filtered_search/dropdown_utils_spec.js
@@ -1,7 +1,7 @@
+import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
import DropdownUtils from '~/filtered_search/dropdown_utils';
import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Dropdown Utils', () => {
const issueListFixture = 'issues/issue_list.html';
diff --git a/spec/frontend/filtered_search/filtered_search_manager_spec.js b/spec/frontend/filtered_search/filtered_search_manager_spec.js
index b1c299ba91f..def0aa14349 100644
--- a/spec/frontend/filtered_search/filtered_search_manager_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_manager_spec.js
@@ -1,5 +1,6 @@
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';
@@ -7,7 +8,6 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
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 FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
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';
@@ -188,11 +188,11 @@ describe('Filtered Search Manager', () => {
const defaultParams = '?scope=all&utf8=%E2%9C%93';
const defaultState = '&state=opened';
- it('should search with a single word', done => {
+ it('should search with a single word', (done) => {
initializeManager();
input.value = 'searchTerm';
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&search=searchTerm`);
done();
});
@@ -200,11 +200,11 @@ describe('Filtered Search Manager', () => {
manager.search();
});
- it('sets default state', done => {
+ it('sets default state', (done) => {
initializeManager({ useDefaultState: true });
input.value = 'searchTerm';
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}${defaultState}&search=searchTerm`);
done();
});
@@ -212,11 +212,11 @@ describe('Filtered Search Manager', () => {
manager.search();
});
- it('should search with multiple words', done => {
+ it('should search with multiple words', (done) => {
initializeManager();
input.value = 'awesome search terms';
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
done();
});
@@ -224,11 +224,11 @@ describe('Filtered Search Manager', () => {
manager.search();
});
- it('should search with special characters', done => {
+ it('should search with special characters', (done) => {
initializeManager();
input.value = '~!@#$%^&*()_+{}:<>,.?/';
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(
`${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`,
);
@@ -238,13 +238,13 @@ describe('Filtered Search Manager', () => {
manager.search();
});
- it('should use replacement URL for condition', done => {
+ it('should use replacement URL for condition', (done) => {
initializeManager();
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', '13', true),
);
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&milestone_title=replaced`);
done();
});
@@ -259,14 +259,14 @@ describe('Filtered Search Manager', () => {
manager.search();
});
- it('removes duplicated tokens', done => {
+ it('removes duplicated tokens', (done) => {
initializeManager();
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
`);
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&label_name[]=bug`);
done();
});
@@ -605,7 +605,7 @@ describe('Filtered Search Manager', () => {
it('correctly modifies params when custom modifier is passed', () => {
const modifedParams = manager.getAllParams.call(
{
- modifyUrlParams: params => params.reverse(),
+ modifyUrlParams: (params) => params.reverse(),
},
[].concat(paramsArr),
);
diff --git a/spec/frontend/filtered_search/filtered_search_token_keys_spec.js b/spec/frontend/filtered_search/filtered_search_token_keys_spec.js
index f24d2b118c2..da6d9ac3ff2 100644
--- a/spec/frontend/filtered_search/filtered_search_token_keys_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_token_keys_spec.js
@@ -33,7 +33,7 @@ describe('Filtered Search Token Keys', () => {
describe('getKeys', () => {
it('should return keys', () => {
const getKeys = new FilteredSearchTokenKeys(tokenKeys).getKeys();
- const keys = new FilteredSearchTokenKeys(tokenKeys).get().map(i => i.key);
+ const keys = new FilteredSearchTokenKeys(tokenKeys).get().map((i) => i.key);
keys.forEach((key, i) => {
expect(key).toEqual(getKeys[i]);
diff --git a/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js b/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
index 6a00065c9fe..44f67f269a2 100644
--- a/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
@@ -1,13 +1,13 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Visual Tokens', () => {
let mock;
const subject = FilteredSearchVisualTokens;
- const findElements = tokenElement => {
+ const findElements = (tokenElement) => {
const tokenNameElement = tokenElement.querySelector('.name');
const tokenOperatorElement = tokenElement.querySelector('.operator');
const tokenValueContainer = tokenElement.querySelector('.value-container');
diff --git a/spec/frontend/filtered_search/issues_filtered_search_token_keys_spec.js b/spec/frontend/filtered_search/issues_filtered_search_token_keys_spec.js
index c7be900ba2c..2041bc3d959 100644
--- a/spec/frontend/filtered_search/issues_filtered_search_token_keys_spec.js
+++ b/spec/frontend/filtered_search/issues_filtered_search_token_keys_spec.js
@@ -23,7 +23,7 @@ describe('Issues Filtered Search Token Keys', () => {
});
it('should return assignee as a string', () => {
- const assignee = tokenKeys.find(tokenKey => tokenKey.key === 'assignee');
+ const assignee = tokenKeys.find((tokenKey) => tokenKey.key === 'assignee');
expect(assignee.type).toEqual('string');
});
@@ -32,7 +32,7 @@ describe('Issues Filtered Search Token Keys', () => {
describe('getKeys', () => {
it('should return keys', () => {
const getKeys = IssuableFilteredSearchTokenKeys.getKeys();
- const keys = IssuableFilteredSearchTokenKeys.get().map(i => i.key);
+ const keys = IssuableFilteredSearchTokenKeys.get().map((i) => i.key);
keys.forEach((key, i) => {
expect(key).toEqual(getKeys[i]);
@@ -145,4 +145,25 @@ describe('Issues Filtered Search Token Keys', () => {
expect(result).toEqual(conditions[0]);
});
});
+
+ describe('removeTokensForKeys', () => {
+ let initTokenKeys;
+
+ beforeEach(() => {
+ initTokenKeys = [...IssuableFilteredSearchTokenKeys.get()];
+ });
+
+ it('should remove the tokenKeys corresponding to the given keys', () => {
+ const [firstTokenKey, secondTokenKey, ...restTokens] = initTokenKeys;
+ IssuableFilteredSearchTokenKeys.removeTokensForKeys(firstTokenKey.key, secondTokenKey.key);
+
+ expect(IssuableFilteredSearchTokenKeys.get()).toEqual(restTokens);
+ });
+
+ it('should do nothing when key is not found', () => {
+ IssuableFilteredSearchTokenKeys.removeTokensForKeys('bogus');
+
+ expect(IssuableFilteredSearchTokenKeys.get()).toEqual(initTokenKeys);
+ });
+ });
});
diff --git a/spec/frontend/filtered_search/recent_searches_root_spec.js b/spec/frontend/filtered_search/recent_searches_root_spec.js
index 281d406e013..6bb9e68d591 100644
--- a/spec/frontend/filtered_search/recent_searches_root_spec.js
+++ b/spec/frontend/filtered_search/recent_searches_root_spec.js
@@ -16,7 +16,7 @@ describe('RecentSearchesRoot', () => {
},
};
- Vue.mockImplementation(options => {
+ Vue.mockImplementation((options) => {
({ data, template } = options);
});
diff --git a/spec/frontend/filtered_search/services/recent_searches_service_spec.js b/spec/frontend/filtered_search/services/recent_searches_service_spec.js
index afeca54b949..6711ce03d40 100644
--- a/spec/frontend/filtered_search/services/recent_searches_service_spec.js
+++ b/spec/frontend/filtered_search/services/recent_searches_service_spec.js
@@ -18,49 +18,49 @@ describe('RecentSearchesService', () => {
jest.spyOn(RecentSearchesService, 'isAvailable').mockReturnValue(true);
});
- it('should default to empty array', done => {
+ it('should default to empty array', (done) => {
const fetchItemsPromise = service.fetch();
fetchItemsPromise
- .then(items => {
+ .then((items) => {
expect(items).toEqual([]);
})
.then(done)
.catch(done.fail);
});
- it('should reject when unable to parse', done => {
+ it('should reject when unable to parse', (done) => {
jest.spyOn(localStorage, 'getItem').mockReturnValue('fail');
const fetchItemsPromise = service.fetch();
fetchItemsPromise
.then(done.fail)
- .catch(error => {
+ .catch((error) => {
expect(error).toEqual(expect.any(SyntaxError));
})
.then(done)
.catch(done.fail);
});
- it('should reject when service is unavailable', done => {
+ it('should reject when service is unavailable', (done) => {
RecentSearchesService.isAvailable.mockReturnValue(false);
service
.fetch()
.then(done.fail)
- .catch(error => {
+ .catch((error) => {
expect(error).toEqual(expect.any(Error));
})
.then(done)
.catch(done.fail);
});
- it('should return items from localStorage', done => {
+ it('should return items from localStorage', (done) => {
jest.spyOn(localStorage, 'getItem').mockReturnValue('["foo", "bar"]');
const fetchItemsPromise = service.fetch();
fetchItemsPromise
- .then(items => {
+ .then((items) => {
expect(items).toEqual(['foo', 'bar']);
})
.then(done)
@@ -74,11 +74,11 @@ describe('RecentSearchesService', () => {
jest.spyOn(Storage.prototype, 'getItem').mockImplementation(() => {});
});
- it('should not call .getItem', done => {
+ it('should not call .getItem', (done) => {
RecentSearchesService.prototype
.fetch()
.then(done.fail)
- .catch(err => {
+ .catch((err) => {
expect(err).toEqual(new RecentSearchesServiceError());
expect(localStorage.getItem).not.toHaveBeenCalled();
})
diff --git a/spec/frontend/filtered_search/visual_token_value_spec.js b/spec/frontend/filtered_search/visual_token_value_spec.js
index e2855b29b70..2a76c4a27df 100644
--- a/spec/frontend/filtered_search/visual_token_value_spec.js
+++ b/spec/frontend/filtered_search/visual_token_value_spec.js
@@ -1,13 +1,13 @@
import { escape } from 'lodash';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
+import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
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';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Visual Tokens', () => {
- const findElements = tokenElement => {
+ const findElements = (tokenElement) => {
const tokenNameElement = tokenElement.querySelector('.name');
const tokenValueContainer = tokenElement.querySelector('.value-container');
const tokenValueElement = tokenValueContainer.querySelector('.value');
@@ -39,15 +39,15 @@ describe('Filtered Search Visual Tokens', () => {
let usersCacheSpy;
beforeEach(() => {
- jest.spyOn(UsersCache, 'retrieve').mockImplementation(username => usersCacheSpy(username));
+ jest.spyOn(UsersCache, 'retrieve').mockImplementation((username) => usersCacheSpy(username));
});
- it('ignores error if UsersCache throws', done => {
+ it('ignores error if UsersCache throws', (done) => {
jest.spyOn(window, 'Flash').mockImplementation(() => {});
const dummyError = new Error('Earth rotated backwards');
const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
+ usersCacheSpy = (username) => {
expect(`@${username}`).toBe(tokenValue);
return Promise.reject(dummyError);
};
@@ -61,10 +61,10 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('does nothing if user cannot be found', done => {
+ it('does nothing if user cannot be found', (done) => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
+ usersCacheSpy = (username) => {
expect(`@${username}`).toBe(tokenValue);
return Promise.resolve(undefined);
};
@@ -78,14 +78,14 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('replaces author token with avatar and display name', done => {
+ it('replaces author token with avatar and display name', (done) => {
const dummyUser = {
name: 'Important Person',
avatar_url: 'https://host.invalid/mypics/avatar.png',
};
const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
+ usersCacheSpy = (username) => {
expect(`@${username}`).toBe(tokenValue);
return Promise.resolve(dummyUser);
};
@@ -104,14 +104,14 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('escapes user name when creating token', done => {
+ it('escapes user name when creating token', (done) => {
const dummyUser = {
name: '<script>',
avatar_url: `${TEST_HOST}/mypics/avatar.png`,
};
const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
+ usersCacheSpy = (username) => {
expect(`@${username}`).toBe(tokenValue);
return Promise.resolve(dummyUser);
};
@@ -168,7 +168,7 @@ describe('Filtered Search Visual Tokens', () => {
AjaxCache.internalStorage[`${filteredSearchInput.dataset.labelsEndpoint}.json`] = labelData;
});
- const parseColor = color => {
+ const parseColor = (color) => {
const dummyElement = document.createElement('div');
dummyElement.style.color = color;
return dummyElement.style.color;
@@ -180,10 +180,10 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueContainer.style.color).toBe(parseColor(label.text_color));
};
- const findLabel = tokenValue =>
- labelData.find(label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
+ const findLabel = (tokenValue) =>
+ labelData.find((label) => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
- it('updates the color of a label token', done => {
+ it('updates the color of a label token', (done) => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
@@ -197,7 +197,7 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('updates the color of a label token with spaces', done => {
+ it('updates the color of a label token with spaces', (done) => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
@@ -211,7 +211,7 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('does not change color of a missing label', done => {
+ it('does not change color of a missing label', (done) => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
@@ -260,7 +260,7 @@ describe('Filtered Search Visual Tokens', () => {
});
describe('render', () => {
- const setupSpies = subject => {
+ const setupSpies = (subject) => {
jest.spyOn(subject, 'updateLabelTokenColor').mockImplementation(() => {});
const updateLabelTokenColorSpy = subject.updateLabelTokenColor;
diff --git a/spec/frontend/fixtures/static/create_item_dropdown.html b/spec/frontend/fixtures/static/create_item_dropdown.html
index aac7d3397ce..63e342d5d0c 100644
--- a/spec/frontend/fixtures/static/create_item_dropdown.html
+++ b/spec/frontend/fixtures/static/create_item_dropdown.html
@@ -7,21 +7,26 @@
data-toggle="dropdown"
>
<span class="dropdown-toggle-text ">some label</span
- ><i aria-hidden="true" data-hidden="true" class="fa fa-chevron-down"></i>
+ >
+ <svg data-testid="chevron-down-icon" class="gl-icon s16">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#chevron-down"
+ ></use>
+ </svg>
</button>
<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
<div class="dropdown-input">
- <input type="search" id="" class="dropdown-input-field" autocomplete="off" /><i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-search dropdown-input-search"
- ></i
- ><i
- aria-hidden="true"
- data-hidden="true"
- role="button"
- class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
- ></i>
+ <input type="search" id="" class="dropdown-input-field" autocomplete="off" />
+ <svg data-testid="search-icon" class="gl-icon s16 dropdown-input-search">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#search"
+ ></use>
+ </svg>
+ <svg data-testid="close-icon" class="gl-icon s16 dropdown-input-clear js-dropdown-input-clear">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#close"
+ ></use>
+ </svg>
</div>
<div class="dropdown-content js-dropdown-content"></div>
<div class="dropdown-footer">
diff --git a/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html b/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html
index 41e7170b5c6..0f243653d46 100644
--- a/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html
+++ b/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html
@@ -9,7 +9,11 @@
<div class="dropdown-toggle-text">
Projects
</div>
- <i class="fa fa-chevron-down dropdown-toggle-caret js-projects-dropdown-toggle"></i>
+ <svg data-testid="chevron-down-icon" class="gl-icon s16 dropdown-toggle-caret js-projects-dropdown-toggle">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#chevron-down"
+ ></use>
+ </svg>
</button>
<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
<div class="dropdown-title gl-display-flex gl-align-items-center">
@@ -28,7 +32,11 @@
</div>
<div class="dropdown-input">
<input class="dropdown-input-field" placeholder="Filter results" type="search" />
- <i class="fa fa-search dropdown-input-search"></i>
+ <svg data-testid="search-icon" class="gl-icon s16 dropdown-input-search">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#search"
+ ></use>
+ </svg>
</div>
<div class="dropdown-content"></div>
<div class="dropdown-loading">
diff --git a/spec/frontend/fixtures/static/line_highlighter.html b/spec/frontend/fixtures/static/line_highlighter.html
index 897a25d6760..1667097bc3b 100644
--- a/spec/frontend/fixtures/static/line_highlighter.html
+++ b/spec/frontend/fixtures/static/line_highlighter.html
@@ -2,103 +2,153 @@
<div class="file-content">
<div class="line-numbers">
<a data-line-number="1" href="#L1" id="L1">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
1
</a>
<a data-line-number="2" href="#L2" id="L2">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
2
</a>
<a data-line-number="3" href="#L3" id="L3">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
3
</a>
<a data-line-number="4" href="#L4" id="L4">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
4
</a>
<a data-line-number="5" href="#L5" id="L5">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
5
</a>
<a data-line-number="6" href="#L6" id="L6">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
6
</a>
<a data-line-number="7" href="#L7" id="L7">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
7
</a>
<a data-line-number="8" href="#L8" id="L8">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
8
</a>
<a data-line-number="9" href="#L9" id="L9">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
9
</a>
<a data-line-number="10" href="#L10" id="L10">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
10
</a>
<a data-line-number="11" href="#L11" id="L11">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
11
</a>
<a data-line-number="12" href="#L12" id="L12">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
12
</a>
<a data-line-number="13" href="#L13" id="L13">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
13
</a>
<a data-line-number="14" href="#L14" id="L14">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
14
</a>
<a data-line-number="15" href="#L15" id="L15">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
15
</a>
<a data-line-number="16" href="#L16" id="L16">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
16
</a>
<a data-line-number="17" href="#L17" id="L17">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
17
</a>
<a data-line-number="18" href="#L18" id="L18">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
18
</a>
<a data-line-number="19" href="#L19" id="L19">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
19
</a>
<a data-line-number="20" href="#L20" id="L20">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
20
</a>
<a data-line-number="21" href="#L21" id="L21">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
21
</a>
<a data-line-number="22" href="#L22" id="L22">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
22
</a>
<a data-line-number="23" href="#L23" id="L23">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
23
</a>
<a data-line-number="24" href="#L24" id="L24">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
24
</a>
<a data-line-number="25" href="#L25" id="L25">
-<i class="fa fa-link"></i>
+<svg data-testid="link-icon" class="s12">
+<use href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#link"></use>
+</svg>
25
</a>
</div>
diff --git a/spec/frontend/fixtures/static/project_select_combo_button.html b/spec/frontend/fixtures/static/project_select_combo_button.html
index f13f9075706..444e0bc84a2 100644
--- a/spec/frontend/fixtures/static/project_select_combo_button.html
+++ b/spec/frontend/fixtures/static/project_select_combo_button.html
@@ -4,6 +4,10 @@
<span class="gl-spinner"></span>
</a>
<a class="new-project-item-select-button">
- <i class="fa fa-caret-down"></i>
+ <svg data-testid="chevron-down-icon" class="gl-icon s16">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#chevron-down"
+ ></use>
+ </svg>
</a>
</div>
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index a37d57b03fd..228c897ab00 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -325,7 +325,7 @@ describe('Flash', () => {
`;
});
- it('removes global flash on click', done => {
+ it('removes global flash on click', (done) => {
const flashEl = document.querySelector('.flash');
removeFlashClickListener(flashEl, false);
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index 439a410eaa1..b74e4ac45cf 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -65,7 +65,7 @@ describe('Frequent Items App Component', () => {
storage[storageKey] = value;
});
- localStorage.getItem.mockImplementation(storageKey => {
+ localStorage.getItem.mockImplementation((storageKey) => {
if (storage[storageKey]) {
return storage[storageKey];
}
@@ -160,7 +160,7 @@ describe('Frequent Items App Component', () => {
});
describe('created', () => {
- it('should bind event listeners on eventHub', done => {
+ it('should bind event listeners on eventHub', (done) => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
createComponentWithStore().$mount();
@@ -173,7 +173,7 @@ describe('Frequent Items App Component', () => {
});
describe('beforeDestroy', () => {
- it('should unbind event listeners on eventHub', done => {
+ it('should unbind event listeners on eventHub', (done) => {
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
vm.$mount();
@@ -191,7 +191,7 @@ describe('Frequent Items App Component', () => {
expect(vm.$el.querySelector('.search-input-container')).toBeDefined();
});
- it('should render loading animation', done => {
+ it('should render loading animation', (done) => {
vm.$store.dispatch('fetchSearchedItems');
Vue.nextTick(() => {
@@ -204,7 +204,7 @@ describe('Frequent Items App Component', () => {
});
});
- it('should render frequent projects list header', done => {
+ it('should render frequent projects list header', (done) => {
Vue.nextTick(() => {
const sectionHeaderEl = vm.$el.querySelector('.section-header');
@@ -214,7 +214,7 @@ describe('Frequent Items App Component', () => {
});
});
- it('should render frequent projects list', done => {
+ it('should render frequent projects list', (done) => {
const expectedResult = getTopFrequentItems(mockFrequentProjects);
localStorage.getItem.mockImplementation(() => JSON.stringify(mockFrequentProjects));
@@ -229,7 +229,7 @@ describe('Frequent Items App Component', () => {
});
});
- it('should render searched projects list', done => {
+ it('should render searched projects list', (done) => {
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects);
expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(1);
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 1160ed5c84b..19095c4474e 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
@@ -114,7 +114,7 @@ describe('FrequentItemsListItemComponent', () => {
const link = wrapper.find('a');
// NOTE: this listener is required to prevent the click from going through and causing:
// `Error: Not implemented: navigation ...`
- link.element.addEventListener('click', e => {
+ link.element.addEventListener('click', (e) => {
e.preventDefault();
});
link.trigger('click');
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 f5e654e6bcb..cdd8b127676 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
@@ -46,7 +46,7 @@ describe('FrequentItemsSearchInputComponent', () => {
});
describe('mounted', () => {
- it('should listen `dropdownOpen` event', done => {
+ it('should listen `dropdownOpen` event', (done) => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
const vmX = createComponent().vm;
@@ -61,7 +61,7 @@ describe('FrequentItemsSearchInputComponent', () => {
});
describe('beforeDestroy', () => {
- it('should unbind event listeners on eventHub', done => {
+ it('should unbind event listeners on eventHub', (done) => {
const vmX = createComponent().vm;
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
diff --git a/spec/frontend/frequent_items/store/actions_spec.js b/spec/frontend/frequent_items/store/actions_spec.js
index 304098e85f1..351fde25f49 100644
--- a/spec/frontend/frequent_items/store/actions_spec.js
+++ b/spec/frontend/frequent_items/store/actions_spec.js
@@ -29,7 +29,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('setNamespace', () => {
- it('should set namespace', done => {
+ it('should set namespace', (done) => {
testAction(
actions.setNamespace,
mockNamespace,
@@ -42,7 +42,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('setStorageKey', () => {
- it('should set storage key', done => {
+ it('should set storage key', (done) => {
testAction(
actions.setStorageKey,
mockStorageKey,
@@ -55,7 +55,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('requestFrequentItems', () => {
- it('should request frequent items', done => {
+ it('should request frequent items', (done) => {
testAction(
actions.requestFrequentItems,
null,
@@ -68,7 +68,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('receiveFrequentItemsSuccess', () => {
- it('should set frequent items', done => {
+ it('should set frequent items', (done) => {
testAction(
actions.receiveFrequentItemsSuccess,
mockFrequentProjects,
@@ -81,7 +81,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('receiveFrequentItemsError', () => {
- it('should set frequent items error state', done => {
+ it('should set frequent items error state', (done) => {
testAction(
actions.receiveFrequentItemsError,
null,
@@ -94,7 +94,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('fetchFrequentItems', () => {
- it('should dispatch `receiveFrequentItemsSuccess`', done => {
+ it('should dispatch `receiveFrequentItemsSuccess`', (done) => {
mockedState.namespace = mockNamespace;
mockedState.storageKey = mockStorageKey;
@@ -108,7 +108,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
);
});
- it('should dispatch `receiveFrequentItemsError`', done => {
+ it('should dispatch `receiveFrequentItemsError`', (done) => {
jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockReturnValue(false);
mockedState.namespace = mockNamespace;
mockedState.storageKey = mockStorageKey;
@@ -125,7 +125,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('requestSearchedItems', () => {
- it('should request searched items', done => {
+ it('should request searched items', (done) => {
testAction(
actions.requestSearchedItems,
null,
@@ -138,7 +138,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('receiveSearchedItemsSuccess', () => {
- it('should set searched items', done => {
+ it('should set searched items', (done) => {
testAction(
actions.receiveSearchedItemsSuccess,
mockSearchedProjects,
@@ -151,7 +151,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('receiveSearchedItemsError', () => {
- it('should set searched items error state', done => {
+ it('should set searched items error state', (done) => {
testAction(
actions.receiveSearchedItemsError,
null,
@@ -168,7 +168,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
gon.api_version = 'v4';
});
- it('should dispatch `receiveSearchedItemsSuccess`', done => {
+ it('should dispatch `receiveSearchedItemsSuccess`', (done) => {
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects, {});
testAction(
@@ -187,7 +187,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
);
});
- it('should dispatch `receiveSearchedItemsError`', done => {
+ it('should dispatch `receiveSearchedItemsError`', (done) => {
gon.api_version = 'v4';
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(500);
@@ -203,7 +203,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('setSearchQuery', () => {
- it('should commit query and dispatch `fetchSearchedItems` when query is present', done => {
+ it('should commit query and dispatch `fetchSearchedItems` when query is present', (done) => {
testAction(
actions.setSearchQuery,
{ query: 'test' },
@@ -214,7 +214,7 @@ describe('Frequent Items Dropdown Store Actions', () => {
);
});
- it('should commit query and dispatch `fetchFrequentItems` when query is empty', done => {
+ it('should commit query and dispatch `fetchFrequentItems` when query is empty', (done) => {
testAction(
actions.setSearchQuery,
null,
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index eb9343847f1..c2ff66f6afc 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -8,7 +8,7 @@ import GfmAutoComplete, { membersBeforeSave } from 'ee_else_ce/gfm_auto_complete
import { TEST_HOST } from 'helpers/test_constants';
import { getJSONFixture } from 'helpers/fixtures';
-import waitForPromises from 'jest/helpers/wait_for_promises';
+import waitForPromises from 'helpers/wait_for_promises';
import MockAdapter from 'axios-mock-adapter';
import AjaxCache from '~/lib/utils/ajax_cache';
@@ -164,7 +164,7 @@ describe('GfmAutoComplete', () => {
});
});
- it.each([200, 500])('should set the loading state', async responseStatus => {
+ it.each([200, 500])('should set the loading state', async (responseStatus) => {
mock.onGet('vulnerabilities_autocomplete_url').replyOnce(responseStatus);
fetchData.call(context, {}, '[vulnerability:', 'query');
@@ -371,9 +371,9 @@ describe('GfmAutoComplete', () => {
const jointAllowedSymbols = allowedSymbols.join('');
describe('should match regular symbols', () => {
- flagsUseDefaultMatcher.forEach(flag => {
- allowedSymbols.forEach(symbol => {
- argumentSize.forEach(size => {
+ flagsUseDefaultMatcher.forEach((flag) => {
+ allowedSymbols.forEach((symbol) => {
+ argumentSize.forEach((size) => {
const query = new Array(size + 1).join(symbol);
const subtext = flag + query;
@@ -395,8 +395,8 @@ describe('GfmAutoComplete', () => {
const shouldNotBeFollowedBy = flags.concat(['\x00', '\x10', '\x3f', '\n', ' ']);
const shouldNotBePrependedBy = ['`'];
- flagsUseDefaultMatcher.forEach(atSign => {
- shouldNotBeFollowedBy.forEach(followedSymbol => {
+ flagsUseDefaultMatcher.forEach((atSign) => {
+ shouldNotBeFollowedBy.forEach((followedSymbol) => {
const seq = atSign + followedSymbol;
it(`should not match ${JSON.stringify(seq)}`, () => {
@@ -404,7 +404,7 @@ describe('GfmAutoComplete', () => {
});
});
- shouldNotBePrependedBy.forEach(prependedSymbol => {
+ shouldNotBePrependedBy.forEach((prependedSymbol) => {
const seq = prependedSymbol + atSign;
it(`should not match "${seq}"`, () => {
@@ -638,8 +638,8 @@ describe('GfmAutoComplete', () => {
};
const allLabels = labelsFixture;
- const assignedLabels = allLabels.filter(label => label.set);
- const unassignedLabels = allLabels.filter(label => !label.set);
+ const assignedLabels = allLabels.filter((label) => label.set);
+ const unassignedLabels = allLabels.filter((label) => !label.set);
let autocomplete;
let $textarea;
@@ -655,11 +655,8 @@ describe('GfmAutoComplete', () => {
autocomplete.destroy();
});
- const triggerDropdown = text => {
- $textarea
- .trigger('focus')
- .val(text)
- .caret('pos', -1);
+ const triggerDropdown = (text) => {
+ $textarea.trigger('focus').val(text).caret('pos', -1);
$textarea.trigger('keyup');
return new Promise(window.requestAnimationFrame);
@@ -668,12 +665,12 @@ describe('GfmAutoComplete', () => {
const getDropdownItems = () => {
const dropdown = document.getElementById('at-view-labels');
const items = dropdown.getElementsByTagName('li');
- return [].map.call(items, item => item.textContent.trim());
+ return [].map.call(items, (item) => item.textContent.trim());
};
const expectLabels = ({ input, output }) =>
triggerDropdown(input).then(() => {
- expect(getDropdownItems()).toEqual(output.map(label => label.title));
+ expect(getDropdownItems()).toEqual(output.map((label) => label.title));
});
describe('with no labels assigned', () => {
@@ -742,9 +739,9 @@ describe('GfmAutoComplete', () => {
});
describe.each`
- name | inputFormat | assert
- ${'insertTemplateFunction'} | ${name => ({ name })} | ${assertInserted}
- ${'templateFunction'} | ${name => name} | ${assertTemplated}
+ name | inputFormat | assert
+ ${'insertTemplateFunction'} | ${(name) => ({ name })} | ${assertInserted}
+ ${'templateFunction'} | ${(name) => name} | ${assertTemplated}
`('Emoji.$name', ({ name, inputFormat, assert }) => {
const execute = (accessor, input, emoji) =>
assert({
@@ -811,7 +808,7 @@ describe('GfmAutoComplete', () => {
const item = GfmAutoComplete.Emoji.templateFunction('heart')
.replace(/(<gl-emoji)\s+(data-name)/, '$1 $2')
- .replace(/>\s+|\s+</g, s => s.trim());
+ .replace(/>\s+|\s+</g, (s) => s.trim());
expect(item).toEqual(
`<li>${heart.name}<gl-emoji data-name="${heart.name}"></gl-emoji></li>`,
);
@@ -823,7 +820,7 @@ describe('GfmAutoComplete', () => {
const item = GfmAutoComplete.Emoji.templateFunction('star')
.replace(/(<gl-emoji)\s+(data-name)/, '$1 $2')
- .replace(/>\s+|\s+</g, s => s.trim());
+ .replace(/>\s+|\s+</g, (s) => s.trim());
expect(item).toEqual(`<li>${star.name}<gl-emoji data-name="${star.name}"></gl-emoji></li>`);
});
});
diff --git a/spec/frontend/gl_field_errors_spec.js b/spec/frontend/gl_field_errors_spec.js
index 078659bf429..a1737211252 100644
--- a/spec/frontend/gl_field_errors_spec.js
+++ b/spec/frontend/gl_field_errors_spec.js
@@ -33,7 +33,7 @@ describe('GL Style Field Errors', () => {
expect(customErrorElem.length).toBe(1);
- const customErrors = testContext.fieldErrors.state.inputs.filter(input => {
+ const customErrors = testContext.fieldErrors.state.inputs.filter((input) => {
return input.inputElement.hasClass(customErrorFlag);
});
@@ -41,18 +41,9 @@ describe('GL Style Field Errors', () => {
});
it('should not show any errors before submit attempt', () => {
- testContext.$form
- .find('.email')
- .val('not-a-valid-email')
- .keyup();
- testContext.$form
- .find('.text-required')
- .val('')
- .keyup();
- testContext.$form
- .find('.alphanumberic')
- .val('?---*')
- .keyup();
+ testContext.$form.find('.email').val('not-a-valid-email').keyup();
+ testContext.$form.find('.text-required').val('').keyup();
+ testContext.$form.find('.alphanumberic').val('?---*').keyup();
const errorsShown = testContext.$form.find('.gl-field-error-outline');
@@ -60,18 +51,9 @@ describe('GL Style Field Errors', () => {
});
it('should show errors when input valid is submitted', () => {
- testContext.$form
- .find('.email')
- .val('not-a-valid-email')
- .keyup();
- testContext.$form
- .find('.text-required')
- .val('')
- .keyup();
- testContext.$form
- .find('.alphanumberic')
- .val('?---*')
- .keyup();
+ testContext.$form.find('.email').val('not-a-valid-email').keyup();
+ testContext.$form.find('.text-required').val('').keyup();
+ testContext.$form.find('.alphanumberic').val('?---*').keyup();
testContext.$form.submit();
diff --git a/spec/frontend/gl_form_spec.js b/spec/frontend/gl_form_spec.js
index 52e1693f8a6..d9a01f7bcc1 100644
--- a/spec/frontend/gl_form_spec.js
+++ b/spec/frontend/gl_form_spec.js
@@ -8,7 +8,7 @@ describe('GLForm', () => {
const testContext = {};
describe('when instantiated', () => {
- beforeEach(done => {
+ beforeEach((done) => {
window.gl = window.gl || {};
testContext.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>');
@@ -28,7 +28,7 @@ describe('GLForm', () => {
});
describe('setupAutosize', () => {
- beforeEach(done => {
+ beforeEach((done) => {
testContext.glForm.setupAutosize();
setImmediate(() => {
@@ -114,6 +114,26 @@ describe('GLForm', () => {
});
});
+ describe('autofocus', () => {
+ it('focus the textarea when autofocus is true', () => {
+ testContext.textarea.data('autofocus', true);
+ jest.spyOn($.prototype, 'focus');
+
+ testContext.glForm = new GLForm(testContext.form, false);
+
+ expect($.prototype.focus).toHaveBeenCalled();
+ });
+
+ it("doesn't focus the textarea when autofocus is false", () => {
+ testContext.textarea.data('autofocus', false);
+ jest.spyOn($.prototype, 'focus');
+
+ testContext.glForm = new GLForm(testContext.form, false);
+
+ expect($.prototype.focus).not.toHaveBeenCalled();
+ });
+ });
+
describe('supportsQuickActions', () => {
it('should return false if textarea does not support quick actions', () => {
const glForm = new GLForm(testContext.form, false);
diff --git a/spec/frontend/gpg_badges_spec.js b/spec/frontend/gpg_badges_spec.js
index 644b687aa19..7c1f83e577c 100644
--- a/spec/frontend/gpg_badges_spec.js
+++ b/spec/frontend/gpg_badges_spec.js
@@ -36,7 +36,7 @@ describe('GpgBadges', () => {
mock.restore();
});
- it('does not make a request if there is no container element', done => {
+ it('does not make a request if there is no container element', (done) => {
setFixtures('');
jest.spyOn(axios, 'get').mockImplementation(() => {});
@@ -48,13 +48,13 @@ describe('GpgBadges', () => {
.catch(done.fail);
});
- it('throws an error if the endpoint is missing', done => {
+ it('throws an error if the endpoint is missing', (done) => {
setFixtures('<div class="js-signature-container"></div>');
jest.spyOn(axios, 'get').mockImplementation(() => {});
GpgBadges.fetch()
.then(() => done.fail('Expected error to be thrown'))
- .catch(error => {
+ .catch((error) => {
expect(error.message).toBe('Missing commit signatures endpoint!');
expect(axios.get).not.toHaveBeenCalled();
})
@@ -62,7 +62,7 @@ describe('GpgBadges', () => {
.catch(done.fail);
});
- it('displays a loading spinner', done => {
+ it('displays a loading spinner', (done) => {
mock.onGet(dummyUrl).replyOnce(200);
GpgBadges.fetch()
@@ -76,7 +76,7 @@ describe('GpgBadges', () => {
.catch(done.fail);
});
- it('replaces the loading spinner', done => {
+ it('replaces the loading spinner', (done) => {
mock.onGet(dummyUrl).replyOnce(200, dummyResponse);
GpgBadges.fetch()
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 9e3ee8a2cb1..4ec739122c8 100644
--- a/spec/frontend/group_settings/components/shared_runners_form_spec.js
+++ b/spec/frontend/group_settings/components/shared_runners_form_spec.js
@@ -32,7 +32,7 @@ describe('group_settings/components/shared_runners_form', () => {
const findErrorAlert = () => wrapper.find(GlAlert);
const findEnabledToggle = () => wrapper.find('[data-testid="enable-runners-toggle"]');
const findOverrideToggle = () => wrapper.find('[data-testid="override-runners-toggle"]');
- const changeToggle = toggle => toggle.vm.$emit('change', !toggle.props('value'));
+ const changeToggle = (toggle) => toggle.vm.$emit('change', !toggle.props('value'));
const getRequestPayload = () => JSON.parse(mock.history.put[0].data);
const isLoadingIconVisible = () => findLoadingIcon().exists();
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index 72d8e23f28b..9244e4f331e 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -1,5 +1,4 @@
import '~/flash';
-import $ from 'jquery';
import Vue from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import { GlModal, GlLoadingIcon } from '@gitlab/ui';
@@ -123,12 +122,12 @@ describe('AppComponent', () => {
it('should show flash error when request fails', () => {
mock.onGet('/dashboard/groups.json').reply(400);
- jest.spyOn($, 'scrollTo').mockImplementation(() => {});
+ jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
jest.spyOn(window, 'Flash').mockImplementation(() => {});
return vm.fetchGroups({}).then(() => {
expect(vm.isLoading).toBe(false);
- expect($.scrollTo).toHaveBeenCalledWith(0);
+ expect(window.scrollTo).toHaveBeenCalledWith({ behavior: 'smooth', top: 0 });
expect(window.Flash).toHaveBeenCalledWith('An error occurred. Please try again.');
});
});
@@ -180,7 +179,7 @@ describe('AppComponent', () => {
it('should fetch groups for provided page details and update window state', () => {
jest.spyOn(urlUtilities, 'mergeUrlParams');
jest.spyOn(window.history, 'replaceState').mockImplementation(() => {});
- jest.spyOn($, 'scrollTo').mockImplementation(() => {});
+ jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
const fetchPagePromise = vm.fetchPage(2, null, null, true);
@@ -195,7 +194,7 @@ describe('AppComponent', () => {
return fetchPagePromise.then(() => {
expect(vm.isLoading).toBe(false);
- expect($.scrollTo).toHaveBeenCalledWith(0);
+ expect(window.scrollTo).toHaveBeenCalledWith({ behavior: 'smooth', top: 0 });
expect(urlUtilities.mergeUrlParams).toHaveBeenCalledWith({ page: 2 }, expect.any(String));
expect(window.history.replaceState).toHaveBeenCalledWith(
{
@@ -308,14 +307,14 @@ describe('AppComponent', () => {
const notice = `You left the "${childGroupItem.fullName}" group.`;
jest.spyOn(vm.service, 'leaveGroup').mockResolvedValue({ data: { notice } });
jest.spyOn(vm.store, 'removeGroup');
- jest.spyOn($, 'scrollTo').mockImplementation(() => {});
+ jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
vm.leaveGroup();
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(vm.targetGroup.leavePath);
return waitForPromises().then(() => {
- expect($.scrollTo).toHaveBeenCalledWith(0);
+ expect(window.scrollTo).toHaveBeenCalledWith({ behavior: 'smooth', top: 0 });
expect(vm.store.removeGroup).toHaveBeenCalledWith(vm.targetGroup, vm.targetParentGroup);
expect($toast.show).toHaveBeenCalledWith(notice);
});
diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js
index 32bae812c86..d70ea709dee 100644
--- a/spec/frontend/groups/components/group_item_spec.js
+++ b/spec/frontend/groups/components/group_item_spec.js
@@ -31,7 +31,7 @@ describe('GroupItemComponent', () => {
vm.$destroy();
});
- const withMicrodata = group => ({
+ const withMicrodata = (group) => ({
...group,
microdata: getGroupItemMicrodata(group),
});
@@ -49,7 +49,7 @@ describe('GroupItemComponent', () => {
const { rowClass } = vm;
expect(Object.keys(rowClass).length).toBe(classes.length);
- Object.keys(rowClass).forEach(className => {
+ Object.keys(rowClass).forEach((className) => {
expect(classes.indexOf(className)).toBeGreaterThan(-1);
});
});
@@ -220,13 +220,13 @@ describe('GroupItemComponent', () => {
});
describe('schema.org props', () => {
describe('when showSchemaMarkup is disabled on the group', () => {
- it.each(['itemprop', 'itemtype', 'itemscope'], 'it does not set %s', attr => {
+ it.each(['itemprop', 'itemtype', 'itemscope'], 'it does not set %s', (attr) => {
expect(vm.$el.getAttribute(attr)).toBeNull();
});
it.each(
['.js-group-avatar', '.js-group-name', '.js-group-description'],
'it does not set `itemprop` on sub-nodes',
- selector => {
+ (selector) => {
expect(vm.$el.querySelector(selector).getAttribute('itemprop')).toBeNull();
},
);
diff --git a/spec/frontend/groups/components/invite_members_banner_spec.js b/spec/frontend/groups/components/invite_members_banner_spec.js
index 95003b211fd..4e69f3cd433 100644
--- a/spec/frontend/groups/components/invite_members_banner_spec.js
+++ b/spec/frontend/groups/components/invite_members_banner_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlBanner } from '@gitlab/ui';
+import { GlBanner, GlButton } from '@gitlab/ui';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { setCookie, parseBoolean } from '~/lib/utils/common_utils';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
@@ -107,14 +107,12 @@ describe('InviteMembersBanner', () => {
});
describe('dismissing', () => {
- const findButton = () => {
- return wrapper.find('button');
- };
+ const findButton = () => wrapper.findAll(GlButton).at(1);
beforeEach(() => {
wrapper = createComponent({ GlBanner });
- findButton().trigger('click');
+ findButton().vm.$emit('click');
});
it('sets iDismissed to true', () => {
@@ -138,7 +136,7 @@ describe('InviteMembersBanner', () => {
});
it('does not render the banner', () => {
- expect(wrapper.contains(GlBanner)).toBe(false);
+ expect(wrapper.find(GlBanner).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/groups/components/item_stats_spec.js b/spec/frontend/groups/components/item_stats_spec.js
index d8c88a608ac..f350012ebed 100644
--- a/spec/frontend/groups/components/item_stats_spec.js
+++ b/spec/frontend/groups/components/item_stats_spec.js
@@ -44,7 +44,7 @@ describe('ItemStats', () => {
expect(findItemStatsValue().exists()).toBe(true);
expect(findItemStatsValue().props('cssClass')).toBe('project-stars');
- expect(wrapper.contains('.last-updated')).toBe(true);
+ expect(wrapper.find('.last-updated').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/groups/components/visibility_level_dropdown_spec.js b/spec/frontend/groups/components/visibility_level_dropdown_spec.js
index bf9508dc768..61b7bbb0833 100644
--- a/spec/frontend/groups/components/visibility_level_dropdown_spec.js
+++ b/spec/frontend/groups/components/visibility_level_dropdown_spec.js
@@ -11,7 +11,7 @@ describe('Visibility Level Dropdown', () => {
];
const defaultLevel = 0;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(Component, {
propsData,
});
@@ -33,7 +33,7 @@ describe('Visibility Level Dropdown', () => {
wrapper.find("input[name='group[visibility_level]']").attributes('value');
const dropdownText = () => wrapper.find(GlDropdown).props('text');
const findDropdownItems = () =>
- wrapper.findAll(GlDropdownItem).wrappers.map(option => ({
+ wrapper.findAll(GlDropdownItem).wrappers.map((option) => ({
text: option.text(),
secondaryText: option.props('secondaryText'),
}));
@@ -56,10 +56,7 @@ describe('Visibility Level Dropdown', () => {
describe('Selecting an option', () => {
beforeEach(() => {
- wrapper
- .findAll(GlDropdownItem)
- .at(1)
- .vm.$emit('click');
+ wrapper.findAll(GlDropdownItem).at(1).vm.$emit('click');
});
it('sets the value of the hidden input to the selected value', () => {
diff --git a/spec/frontend/groups/members/components/app_spec.js b/spec/frontend/groups/members/components/app_spec.js
index 208e2fc35b6..9847dacbec8 100644
--- a/spec/frontend/groups/members/components/app_spec.js
+++ b/spec/frontend/groups/members/components/app_spec.js
@@ -87,21 +87,9 @@ describe('GroupMembersApp', () => {
});
});
- describe.each`
- featureFlagValue | exists
- ${true} | ${true}
- ${false} | ${false}
- `(
- 'when `group_members_filtered_search` feature flag is $featureFlagValue',
- ({ featureFlagValue, exists }) => {
- it(`${exists ? 'renders' : 'does not render'} FilterSortContainer`, () => {
- createComponent(
- {},
- { provide: { glFeatures: { groupMembersFilteredSearch: featureFlagValue } } },
- );
-
- expect(findFilterSortContainer().exists()).toBe(exists);
- });
- },
- );
+ it('renders `FilterSortContainer`', () => {
+ createComponent();
+
+ expect(findFilterSortContainer().exists()).toBe(true);
+ });
});
diff --git a/spec/frontend/helpers/README.md b/spec/frontend/helpers/README.md
new file mode 100644
index 00000000000..22f9ea3442d
--- /dev/null
+++ b/spec/frontend/helpers/README.md
@@ -0,0 +1,3 @@
+This folder should only contain specs for '~/helpers' application code.
+
+If you want to create a helper to be used in tests, please place it under [__helpers__](../__helpers__).
diff --git a/spec/frontend/helpers/backoff_helper.js b/spec/frontend/helpers/backoff_helper.js
deleted file mode 100644
index e5c0308d3fb..00000000000
--- a/spec/frontend/helpers/backoff_helper.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * A mock version of a commonUtils `backOff` to test multiple
- * retries.
- *
- * Usage:
- *
- * ```
- * import * as commonUtils from '~/lib/utils/common_utils';
- * import { backoffMockImplementation } from '../../helpers/backoff_helper';
- *
- * beforeEach(() => {
- * // ...
- * jest.spyOn(commonUtils, 'backOff').mockImplementation(backoffMockImplementation);
- * });
- * ```
- *
- * @param {Function} callback
- */
-export const backoffMockImplementation = callback => {
- const q = new Promise((resolve, reject) => {
- const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg));
- const next = () => callback(next, stop);
- // Define a timeout based on a mock timer
- setTimeout(() => {
- callback(next, stop);
- });
- });
- // Run all resolved promises in chain
- jest.runOnlyPendingTimers();
- return q;
-};
-
-export default { backoffMockImplementation };
diff --git a/spec/frontend/helpers/dom_events_helper.js b/spec/frontend/helpers/dom_events_helper.js
deleted file mode 100644
index 423e5c58bb4..00000000000
--- a/spec/frontend/helpers/dom_events_helper.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export const triggerDOMEvent = type => {
- window.document.dispatchEvent(
- new Event(type, {
- bubbles: true,
- cancelable: true,
- }),
- );
-};
diff --git a/spec/frontend/helpers/dom_shims/size_properties.js b/spec/frontend/helpers/dom_shims/size_properties.js
deleted file mode 100644
index a2d5940bd1e..00000000000
--- a/spec/frontend/helpers/dom_shims/size_properties.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const convertFromStyle = style => {
- if (style.match(/[0-9](px|rem)/g)) {
- return Number(style.replace(/[^0-9]/g, ''));
- }
-
- return 0;
-};
-
-Object.defineProperty(global.HTMLElement.prototype, 'offsetWidth', {
- get() {
- return convertFromStyle(this.style.width || '0px');
- },
-});
-
-Object.defineProperty(global.HTMLElement.prototype, 'offsetHeight', {
- get() {
- return convertFromStyle(this.style.height || '0px');
- },
-});
diff --git a/spec/frontend/helpers/emoji.js b/spec/frontend/helpers/emoji.js
deleted file mode 100644
index e8a93e21818..00000000000
--- a/spec/frontend/helpers/emoji.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
-
-export const emojiFixtureMap = {
- atom: {
- moji: 'âš›',
- description: 'atom symbol',
- unicodeVersion: '4.1',
- aliases: ['atom_symbol'],
- },
- bomb: {
- moji: '💣',
- unicodeVersion: '6.0',
- description: 'bomb',
- },
- construction_worker_tone5: {
- moji: '👷ðŸ¿',
- unicodeVersion: '8.0',
- description: 'construction worker tone 5',
- },
- five: {
- moji: '5ï¸âƒ£',
- unicodeVersion: '3.0',
- description: 'keycap digit five',
- },
- grey_question: {
- moji: 'â”',
- 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',
- description: 'black heart',
- },
- heart: {
- moji: 'â¤',
- unicodeVersion: '1.1',
- description: 'heavy black heart',
- },
- custard: {
- moji: 'ðŸ®',
- unicodeVersion: '6.0',
- description: 'custard',
- },
- star: {
- moji: 'â­',
- unicodeVersion: '5.1',
- description: 'white medium star',
- },
-};
-
-Object.keys(emojiFixtureMap).forEach(k => {
- emojiFixtureMap[k].name = k;
- if (!emojiFixtureMap[k].aliases) {
- emojiFixtureMap[k].aliases = [];
- }
-});
-
-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 }];
- }),
- );
-
- const mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(emojiData));
-
- 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/event_hub_factory_spec.js b/spec/frontend/helpers/event_hub_factory_spec.js
index c4f63ff6049..2491e8d5dda 100644
--- a/spec/frontend/helpers/event_hub_factory_spec.js
+++ b/spec/frontend/helpers/event_hub_factory_spec.js
@@ -93,7 +93,7 @@ describe('event bus factory', () => {
describe('$off', () => {
beforeEach(() => {
- otherHandlers.forEach(x => eventBus.$on(TEST_EVENT, x));
+ otherHandlers.forEach((x) => eventBus.$on(TEST_EVENT, x));
eventBus.$on(TEST_EVENT, handler);
});
@@ -115,7 +115,7 @@ describe('event bus factory', () => {
eventBus.$emit(TEST_EVENT);
expect(handler).not.toHaveBeenCalled();
- expect(otherHandlers.map(x => x.mock.calls.length)).toEqual(otherHandlers.map(() => 1));
+ expect(otherHandlers.map((x) => x.mock.calls.length)).toEqual(otherHandlers.map(() => 1));
});
it('without a handler, will no longer call any handlers', () => {
@@ -124,13 +124,13 @@ describe('event bus factory', () => {
eventBus.$emit(TEST_EVENT);
expect(handler).not.toHaveBeenCalled();
- expect(otherHandlers.map(x => x.mock.calls.length)).toEqual(otherHandlers.map(() => 0));
+ expect(otherHandlers.map((x) => x.mock.calls.length)).toEqual(otherHandlers.map(() => 0));
});
});
describe('$emit', () => {
beforeEach(() => {
- otherHandlers.forEach(x => eventBus.$on(TEST_EVENT_2, x));
+ otherHandlers.forEach((x) => eventBus.$on(TEST_EVENT_2, x));
eventBus.$on(TEST_EVENT, handler);
});
@@ -138,7 +138,7 @@ describe('event bus factory', () => {
eventBus.$emit(TEST_EVENT, 'arg1');
expect(handler).toHaveBeenCalledWith('arg1');
- expect(otherHandlers.map(x => x.mock.calls.length)).toEqual(otherHandlers.map(() => 0));
+ expect(otherHandlers.map((x) => x.mock.calls.length)).toEqual(otherHandlers.map(() => 0));
});
});
});
diff --git a/spec/frontend/helpers/fake_date.js b/spec/frontend/helpers/fake_date.js
deleted file mode 100644
index 387747ab5bd..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_request_animation_frame.js b/spec/frontend/helpers/fake_request_animation_frame.js
deleted file mode 100644
index f6fc29df4dc..00000000000
--- a/spec/frontend/helpers/fake_request_animation_frame.js
+++ /dev/null
@@ -1,12 +0,0 @@
-export const useFakeRequestAnimationFrame = () => {
- let orig;
-
- beforeEach(() => {
- orig = global.requestAnimationFrame;
- global.requestAnimationFrame = cb => cb();
- });
-
- afterEach(() => {
- global.requestAnimationFrame = orig;
- });
-};
diff --git a/spec/frontend/helpers/fixtures.js b/spec/frontend/helpers/fixtures.js
deleted file mode 100644
index a89ceab3f8e..00000000000
--- a/spec/frontend/helpers/fixtures.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-
-import { ErrorWithStack } from 'jest-util';
-
-export function getFixture(relativePath) {
- const basePath = relativePath.startsWith('static/')
- ? global.staticFixturesBasePath
- : global.fixturesBasePath;
- const absolutePath = path.join(basePath, relativePath);
- if (!fs.existsSync(absolutePath)) {
- throw new ErrorWithStack(
- `Fixture file ${relativePath} does not exist.
-
-Did you run bin/rake frontend:fixtures?`,
- getFixture,
- );
- }
-
- return fs.readFileSync(absolutePath, 'utf8');
-}
-
-export const getJSONFixture = relativePath => JSON.parse(getFixture(relativePath));
-
-export const resetHTMLFixture = () => {
- document.head.innerHTML = '';
- document.body.innerHTML = '';
-};
-
-export const setHTMLFixture = (htmlContent, resetHook = afterEach) => {
- document.body.innerHTML = htmlContent;
- resetHook(resetHTMLFixture);
-};
-
-export const loadHTMLFixture = (relativePath, resetHook = afterEach) => {
- const fileContent = getFixture(relativePath);
- setHTMLFixture(fileContent, resetHook);
-};
diff --git a/spec/frontend/helpers/help_page_helper_spec.js b/spec/frontend/helpers/help_page_helper_spec.js
new file mode 100644
index 00000000000..09c1a113a96
--- /dev/null
+++ b/spec/frontend/helpers/help_page_helper_spec.js
@@ -0,0 +1,29 @@
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+describe('help page helper', () => {
+ it.each`
+ relative_url_root | path | anchor | expected
+ ${undefined} | ${'administration/index'} | ${undefined} | ${'/help/administration/index'}
+ ${''} | ${'administration/index'} | ${undefined} | ${'/help/administration/index'}
+ ${'/'} | ${'administration/index'} | ${undefined} | ${'/help/administration/index'}
+ ${'/gitlab'} | ${'administration/index'} | ${undefined} | ${'/gitlab/help/administration/index'}
+ ${'/gitlab/'} | ${'administration/index'} | ${undefined} | ${'/gitlab/help/administration/index'}
+ ${undefined} | ${'administration/index'} | ${undefined} | ${'/help/administration/index'}
+ ${'/'} | ${'administration/index'} | ${undefined} | ${'/help/administration/index'}
+ ${''} | ${'administration/index.md'} | ${undefined} | ${'/help/administration/index.md'}
+ ${''} | ${'administration/index.md'} | ${'installing-gitlab'} | ${'/help/administration/index.md#installing-gitlab'}
+ ${''} | ${'administration/index'} | ${'installing-gitlab'} | ${'/help/administration/index#installing-gitlab'}
+ ${''} | ${'administration/index'} | ${'#installing-gitlab'} | ${'/help/administration/index#installing-gitlab'}
+ ${''} | ${'/administration/index'} | ${undefined} | ${'/help/administration/index'}
+ ${''} | ${'administration/index/'} | ${undefined} | ${'/help/administration/index/'}
+ ${''} | ${'/administration/index/'} | ${undefined} | ${'/help/administration/index/'}
+ ${'/'} | ${'/administration/index'} | ${undefined} | ${'/help/administration/index'}
+ `(
+ 'generates correct URL when path is `$path`, relative url is `$relative_url_root` and anchor is `$anchor`',
+ ({ relative_url_root, anchor, path, expected }) => {
+ window.gon = { relative_url_root };
+
+ expect(helpPagePath(path, { anchor })).toBe(expected);
+ },
+ );
+});
diff --git a/spec/frontend/helpers/jest_helpers.js b/spec/frontend/helpers/jest_helpers.js
deleted file mode 100644
index 0b623e0a59b..00000000000
--- a/spec/frontend/helpers/jest_helpers.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-@module
-
-This method provides convenience functions to help migrating from Karma/Jasmine to Jest.
-
-Try not to use these in new tests - this module is provided primarily for convenience of migrating tests.
- */
-
-/**
- * Creates a plain JS object pre-populated with Jest spy functions. Useful for making simple mocks classes.
- *
- * @see https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3EcreateSpyObj%3C/code%3E
- * @param {string} baseName Human-readable name of the object. This is used for reporting purposes.
- * @param methods {string[]} List of method names that will be added to the spy object.
- */
-export function createSpyObj(baseName, methods) {
- const obj = {};
- methods.forEach(method => {
- obj[method] = jest.fn().mockName(`${baseName}#${method}`);
- });
- return obj;
-}
diff --git a/spec/frontend/helpers/local_storage_helper.js b/spec/frontend/helpers/local_storage_helper.js
deleted file mode 100644
index 0318b80aaef..00000000000
--- a/spec/frontend/helpers/local_storage_helper.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Manage the instance of a custom `window.localStorage`
- *
- * This only encapsulates the setup / teardown logic so that it can easily be
- * reused with different implementations (i.e. a spy or a [fake][1])
- *
- * [1]: https://stackoverflow.com/a/41434763/1708147
- *
- * @param {() => any} fn Function that returns the object to use for localStorage
- */
-const useLocalStorage = fn => {
- const origLocalStorage = window.localStorage;
- let currentLocalStorage = origLocalStorage;
-
- Object.defineProperty(window, 'localStorage', {
- get: () => currentLocalStorage,
- });
-
- beforeEach(() => {
- currentLocalStorage = fn();
- });
-
- afterEach(() => {
- currentLocalStorage = origLocalStorage;
- });
-};
-
-/**
- * Create an object with the localStorage interface but `jest.fn()` implementations.
- */
-export const createLocalStorageSpy = () => {
- let storage = {};
-
- return {
- clear: jest.fn(() => {
- storage = {};
- }),
- getItem: jest.fn(key => (key in storage ? storage[key] : null)),
- setItem: jest.fn((key, value) => {
- storage[key] = value;
- }),
- removeItem: jest.fn(key => delete storage[key]),
- };
-};
-
-/**
- * Before each test, overwrite `window.localStorage` with a spy implementation.
- */
-export const useLocalStorageSpy = () => useLocalStorage(createLocalStorageSpy);
diff --git a/spec/frontend/helpers/locale_helper.js b/spec/frontend/helpers/locale_helper.js
deleted file mode 100644
index 283d9bc14c9..00000000000
--- a/spec/frontend/helpers/locale_helper.js
+++ /dev/null
@@ -1,9 +0,0 @@
-export const setLanguage = languageCode => {
- const htmlElement = document.querySelector('html');
-
- if (languageCode) {
- htmlElement.setAttribute('lang', languageCode);
- } else {
- htmlElement.removeAttribute('lang');
- }
-};
diff --git a/spec/frontend/helpers/mock_window_location_helper.js b/spec/frontend/helpers/mock_window_location_helper.js
deleted file mode 100644
index 175044d1fce..00000000000
--- a/spec/frontend/helpers/mock_window_location_helper.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Manage the instance of a custom `window.location`
- *
- * This only encapsulates the setup / teardown logic so that it can easily be
- * reused with different implementations (i.e. a spy or a [fake][1])
- *
- * [1]: https://stackoverflow.com/a/41434763/1708147
- *
- * @param {() => any} fn Function that returns the object to use for window.location
- */
-const useMockLocation = fn => {
- const origWindowLocation = window.location;
- let currentWindowLocation;
-
- Object.defineProperty(window, 'location', {
- get: () => currentWindowLocation,
- });
-
- beforeEach(() => {
- currentWindowLocation = fn();
- });
-
- afterEach(() => {
- currentWindowLocation = origWindowLocation;
- });
-};
-
-/**
- * Create an object with the location interface but `jest.fn()` implementations.
- */
-export const createWindowLocationSpy = () => {
- return {
- assign: jest.fn(),
- reload: jest.fn(),
- replace: jest.fn(),
- toString: jest.fn(),
- };
-};
-
-/**
- * Before each test, overwrite `window.location` with a spy implementation.
- */
-export const useMockLocationHelper = () => useMockLocation(createWindowLocationSpy);
diff --git a/spec/frontend/helpers/monitor_helper_spec.js b/spec/frontend/helpers/monitor_helper_spec.js
index 219b05e312b..ef2a9fb0665 100644
--- a/spec/frontend/helpers/monitor_helper_spec.js
+++ b/spec/frontend/helpers/monitor_helper_spec.js
@@ -3,7 +3,11 @@ import { getSeriesLabel, makeDataSeries } from '~/helpers/monitor_helper';
describe('monitor helper', () => {
const defaultConfig = { default: true, name: 'default name' };
const name = 'data name';
- const series = [[1, 1], [2, 2], [3, 3]];
+ const series = [
+ [1, 1],
+ [2, 2],
+ [3, 3],
+ ];
describe('getSeriesLabel', () => {
const metricAttributes = { __name__: 'up', app: 'prometheus' };
diff --git a/spec/frontend/helpers/set_timeout_promise_helper.js b/spec/frontend/helpers/set_timeout_promise_helper.js
deleted file mode 100644
index 47087619187..00000000000
--- a/spec/frontend/helpers/set_timeout_promise_helper.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export default (time = 0) =>
- new Promise(resolve => {
- setTimeout(resolve, time);
- });
diff --git a/spec/frontend/helpers/set_window_location_helper_spec.js b/spec/frontend/helpers/set_window_location_helper_spec.js
deleted file mode 100644
index da609b6bbf0..00000000000
--- a/spec/frontend/helpers/set_window_location_helper_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import setWindowLocation from './set_window_location_helper';
-
-describe('setWindowLocation', () => {
- const originalLocation = window.location;
-
- afterEach(() => {
- window.location = originalLocation;
- });
-
- it.each`
- url | property | value
- ${'https://gitlab.com#foo'} | ${'hash'} | ${'#foo'}
- ${'http://gitlab.com'} | ${'host'} | ${'gitlab.com'}
- ${'http://gitlab.org'} | ${'hostname'} | ${'gitlab.org'}
- ${'http://gitlab.org/foo#bar'} | ${'href'} | ${'http://gitlab.org/foo#bar'}
- ${'http://gitlab.com'} | ${'origin'} | ${'http://gitlab.com'}
- ${'http://gitlab.com/foo/bar/baz'} | ${'pathname'} | ${'/foo/bar/baz'}
- ${'https://gitlab.com'} | ${'protocol'} | ${'https:'}
- ${'http://gitlab.com#foo'} | ${'protocol'} | ${'http:'}
- ${'http://gitlab.com:8080'} | ${'port'} | ${'8080'}
- ${'http://gitlab.com?foo=bar&bar=foo'} | ${'search'} | ${'?foo=bar&bar=foo'}
- `(
- 'sets "window.location.$property" to be "$value" when called with: "$url"',
- ({ url, property, value }) => {
- expect(window.location).toBe(originalLocation);
-
- setWindowLocation(url);
-
- expect(window.location[property]).toBe(value);
- },
- );
-
- it.each([null, 1, undefined, false, '', 'gitlab.com'])(
- 'throws an error when called with an invalid url: "%s"',
- invalidUrl => {
- expect(() => setWindowLocation(invalidUrl)).toThrow(/Invalid URL/);
- expect(window.location).toBe(originalLocation);
- },
- );
-});
diff --git a/spec/frontend/helpers/startup_css_helper_spec.js b/spec/frontend/helpers/startup_css_helper_spec.js
index 2d560c43fa5..703bdbd342f 100644
--- a/spec/frontend/helpers/startup_css_helper_spec.js
+++ b/spec/frontend/helpers/startup_css_helper_spec.js
@@ -39,24 +39,7 @@ describe('waitForCSSLoaded', () => {
});
});
- describe('with startup css disabled', () => {
- gon.features = {
- startupCss: false,
- };
-
- it('should invoke the action right away', async () => {
- const events = waitForCSSLoaded(mockedCallback);
- await events;
-
- expect(mockedCallback).toHaveBeenCalledTimes(1);
- });
- });
-
describe('with startup css enabled', () => {
- gon.features = {
- startupCss: true,
- };
-
it('should dispatch CSSLoaded when the assets are cached or already loaded', async () => {
setFixtures(`
<link href="one.css" data-startupcss="loaded">
@@ -75,7 +58,7 @@ describe('waitForCSSLoaded', () => {
const events = waitForCSSLoaded(mockedCallback);
document
.querySelectorAll('[data-startupcss="loading"]')
- .forEach(elem => elem.setAttribute('data-startupcss', 'loaded'));
+ .forEach((elem) => elem.setAttribute('data-startupcss', 'loaded'));
document.dispatchEvent(new CustomEvent('CSSStartupLinkLoaded'));
await events;
diff --git a/spec/frontend/helpers/stub_children.js b/spec/frontend/helpers/stub_children.js
deleted file mode 100644
index 91171eb3d8c..00000000000
--- a/spec/frontend/helpers/stub_children.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function stubChildren(Component) {
- return Object.fromEntries(Object.keys(Component.components).map(c => [c, true]));
-}
diff --git a/spec/frontend/helpers/text_helper.js b/spec/frontend/helpers/text_helper.js
deleted file mode 100644
index e0fe18e5560..00000000000
--- a/spec/frontend/helpers/text_helper.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Replaces line break with an empty space
- * @param {*} data
- */
-export const removeBreakLine = data => data.replace(/\r?\n|\r/g, ' ');
-
-/**
- * Removes line breaks, spaces and trims the given text
- * @param {String} str
- * @returns {String}
- */
-export const trimText = str =>
- str
- .replace(/\r?\n|\r/g, '')
- .replace(/\s\s+/g, ' ')
- .trim();
-
-export const removeWhitespace = str => str.replace(/\s\s+/g, ' ');
diff --git a/spec/frontend/helpers/timeout.js b/spec/frontend/helpers/timeout.js
deleted file mode 100644
index 702ef0be5aa..00000000000
--- a/spec/frontend/helpers/timeout.js
+++ /dev/null
@@ -1,59 +0,0 @@
-const NS_PER_SEC = 1e9;
-const NS_PER_MS = 1e6;
-const IS_DEBUGGING = process.execArgv.join(' ').includes('--inspect-brk');
-
-let testTimeoutNS;
-
-export const setTestTimeout = newTimeoutMS => {
- const newTimeoutNS = newTimeoutMS * NS_PER_MS;
- // never accept a smaller timeout than the default
- if (newTimeoutNS < testTimeoutNS) {
- return;
- }
-
- testTimeoutNS = newTimeoutNS;
- jest.setTimeout(newTimeoutMS);
-};
-
-// Allows slow tests to set their own timeout.
-// Useful for tests with jQuery, which is very slow in big DOMs.
-let temporaryTimeoutNS = null;
-export const setTestTimeoutOnce = newTimeoutMS => {
- const newTimeoutNS = newTimeoutMS * NS_PER_MS;
- // never accept a smaller timeout than the default
- if (newTimeoutNS < testTimeoutNS) {
- return;
- }
-
- temporaryTimeoutNS = newTimeoutNS;
-};
-
-export const initializeTestTimeout = defaultTimeoutMS => {
- setTestTimeout(defaultTimeoutMS);
-
- let testStartTime;
-
- // https://github.com/facebook/jest/issues/6947
- beforeEach(() => {
- testStartTime = process.hrtime();
- });
-
- afterEach(() => {
- let timeoutNS = testTimeoutNS;
- if (Number.isFinite(temporaryTimeoutNS)) {
- timeoutNS = temporaryTimeoutNS;
- temporaryTimeoutNS = null;
- }
-
- const [seconds, remainingNs] = process.hrtime(testStartTime);
- const elapsedNS = seconds * NS_PER_SEC + remainingNs;
-
- // Disable the timeout error when debugging. It is meaningless because
- // debugging always takes longer than the test timeout.
- if (elapsedNS > timeoutNS && !IS_DEBUGGING) {
- throw new Error(
- `Test took too long (${elapsedNS / NS_PER_MS}ms > ${timeoutNS / NS_PER_MS}ms)!`,
- );
- }
- });
-};
diff --git a/spec/frontend/helpers/tracking_helper.js b/spec/frontend/helpers/tracking_helper.js
deleted file mode 100644
index bd3bd24028c..00000000000
--- a/spec/frontend/helpers/tracking_helper.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import Tracking from '~/tracking';
-
-export default Tracking;
-
-let document;
-let handlers;
-
-export function mockTracking(category = '_category_', documentOverride, spyMethod) {
- document = documentOverride || window.document;
- window.snowplow = () => {};
- handlers = Tracking.bindDocument(category, document);
- return spyMethod ? spyMethod(Tracking, 'event') : null;
-}
-
-export function unmockTracking() {
- window.snowplow = undefined;
- handlers.forEach(event => document.removeEventListener(event.name, event.func));
-}
-
-export function triggerEvent(selectorOrEl, eventName = 'click') {
- const event = new Event(eventName, { bubbles: true });
- const el = typeof selectorOrEl === 'string' ? document.querySelector(selectorOrEl) : selectorOrEl;
-
- el.dispatchEvent(event);
-}
diff --git a/spec/frontend/helpers/user_mock_data_helper.js b/spec/frontend/helpers/user_mock_data_helper.js
deleted file mode 100644
index a6adc9dc3a0..00000000000
--- a/spec/frontend/helpers/user_mock_data_helper.js
+++ /dev/null
@@ -1,34 +0,0 @@
-let id = 1;
-
-// Code taken from: https://gist.github.com/6174/6062387
-const getRandomString = () =>
- Math.random()
- .toString(36)
- .substring(2, 15) +
- Math.random()
- .toString(36)
- .substring(2, 15);
-
-const getRandomUrl = () => `https://${getRandomString()}.com/${getRandomString()}`;
-
-export default {
- createNumberRandomUsers(numberUsers) {
- const users = [];
- for (let i = 0; i < numberUsers; i += 1) {
- users.push({
- avatar_url: getRandomUrl(),
- id: id + 1,
- name: getRandomString(),
- username: getRandomString(),
- user_path: getRandomUrl(),
- });
-
- id += 1;
- }
- return users;
- },
-
- createRandomUser() {
- return this.createNumberRandomUsers(1)[0];
- },
-};
diff --git a/spec/frontend/helpers/vue_mock_directive.js b/spec/frontend/helpers/vue_mock_directive.js
deleted file mode 100644
index 28d4708835d..00000000000
--- a/spec/frontend/helpers/vue_mock_directive.js
+++ /dev/null
@@ -1,25 +0,0 @@
-export const getKey = name => `$_gl_jest_${name}`;
-
-export const getBinding = (el, name) => el[getKey(name)];
-
-const writeBindingToElement = (el, { name, value, arg, modifiers }) => {
- el[getKey(name)] = {
- value,
- arg,
- modifiers,
- };
-};
-
-export const createMockDirective = () => ({
- bind(el, binding) {
- writeBindingToElement(el, binding);
- },
-
- update(el, binding) {
- writeBindingToElement(el, binding);
- },
-
- unbind(el, { name }) {
- delete el[getKey(name)];
- },
-});
diff --git a/spec/frontend/helpers/vue_test_utils_helper.js b/spec/frontend/helpers/vue_test_utils_helper.js
deleted file mode 100644
index 0e9127b5c65..00000000000
--- a/spec/frontend/helpers/vue_test_utils_helper.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import { isArray } from 'lodash';
-
-const vNodeContainsText = (vnode, text) =>
- (vnode.text && vnode.text.includes(text)) ||
- (vnode.children && vnode.children.filter(child => vNodeContainsText(child, text)).length);
-
-/**
- * Determines whether a `shallowMount` Wrapper contains text
- * within one of it's slots. This will also work on Wrappers
- * acquired with `find()`, but only if it's parent Wrapper
- * was shallowMounted.
- * NOTE: Prefer checking the rendered output of a component
- * wherever possible using something like `text()` instead.
- * @param {Wrapper} shallowWrapper - Vue test utils wrapper (shallowMounted)
- * @param {String} slotName
- * @param {String} text
- */
-export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) =>
- Boolean(
- shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length,
- );
-
-/**
- * Returns a promise that waits for a mutation to be fired before resolving
- * NOTE: There's no reject action here so it will hang if it waits for a mutation that won't happen.
- * @param {Object} store - The Vue store that contains the mutations
- * @param {String} expectedMutationType - The Mutation to wait for
- */
-export const waitForMutation = (store, expectedMutationType) =>
- new Promise(resolve => {
- const unsubscribe = store.subscribe(mutation => {
- if (mutation.type === expectedMutationType) {
- unsubscribe();
- resolve();
- }
- });
- });
-
-export const extendedWrapper = wrapper => {
- if (isArray(wrapper) || !wrapper?.find) {
- // eslint-disable-next-line no-console
- console.warn(
- '[vue-test-utils-helper]: you are trying to extend an object that is not a VueWrapper.',
- );
- return wrapper;
- }
-
- return Object.defineProperty(wrapper, 'findByTestId', {
- value(id) {
- return this.find(`[data-testid="${id}"]`);
- },
- });
-};
diff --git a/spec/frontend/helpers/vuex_action_helper.js b/spec/frontend/helpers/vuex_action_helper.js
deleted file mode 100644
index 64dd3888d47..00000000000
--- a/spec/frontend/helpers/vuex_action_helper.js
+++ /dev/null
@@ -1,128 +0,0 @@
-const noop = () => {};
-
-/**
- * Helper for testing action with expected mutations inspired in
- * https://vuex.vuejs.org/en/testing.html
- *
- * @param {(Function|Object)} action to be tested, or object of named parameters
- * @param {Object} payload will be provided to the action
- * @param {Object} state will be provided to the action
- * @param {Array} [expectedMutations=[]] mutations expected to be committed
- * @param {Array} [expectedActions=[]] actions expected to be dispatched
- * @param {Function} [done=noop] to be executed after the tests
- * @return {Promise}
- *
- * @example
- * testAction(
- * actions.actionName, // action
- * { }, // mocked payload
- * state, //state
- * // expected mutations
- * [
- * { type: types.MUTATION}
- * { type: types.MUTATION_1, payload: expect.any(Number)}
- * ],
- * // expected actions
- * [
- * { type: 'actionName', payload: {param: 'foobar'}},
- * { type: 'actionName1'}
- * ]
- * done,
- * );
- *
- * @example
- * testAction(
- * actions.actionName, // action
- * { }, // mocked payload
- * state, //state
- * [ { type: types.MUTATION} ], // expected mutations
- * [], // expected actions
- * ).then(done)
- * .catch(done.fail);
- *
- * @example
- * await testAction({
- * action: actions.actionName,
- * payload: { deleteListId: 1 },
- * state: { lists: [1, 2, 3] },
- * expectedMutations: [ { type: types.MUTATION} ],
- * expectedActions: [],
- * })
- */
-export default (
- actionArg,
- payloadArg,
- stateArg,
- expectedMutationsArg = [],
- expectedActionsArg = [],
- doneArg = noop,
-) => {
- let action = actionArg;
- let payload = payloadArg;
- let state = stateArg;
- let expectedMutations = expectedMutationsArg;
- let expectedActions = expectedActionsArg;
- let done = doneArg;
-
- if (typeof actionArg !== 'function') {
- ({
- action,
- payload,
- state,
- expectedMutations = [],
- expectedActions = [],
- done = noop,
- } = actionArg);
- }
-
- const mutations = [];
- const actions = [];
-
- // mock commit
- const commit = (type, mutationPayload) => {
- const mutation = { type };
-
- if (typeof mutationPayload !== 'undefined') {
- mutation.payload = mutationPayload;
- }
-
- mutations.push(mutation);
- };
-
- // mock dispatch
- const dispatch = (type, actionPayload) => {
- const dispatchedAction = { type };
-
- if (typeof actionPayload !== 'undefined') {
- dispatchedAction.payload = actionPayload;
- }
-
- actions.push(dispatchedAction);
- };
-
- const validateResults = () => {
- expect({
- mutations,
- actions,
- }).toEqual({
- mutations: expectedMutations,
- actions: expectedActions,
- });
- done();
- };
-
- const result = action(
- { commit, state, dispatch, rootState: state, rootGetters: state, getters: state },
- payload,
- );
-
- return (result || new Promise(resolve => setImmediate(resolve)))
- .catch(error => {
- validateResults();
- throw error;
- })
- .then(data => {
- validateResults();
- return data;
- });
-};
diff --git a/spec/frontend/helpers/vuex_action_helper_spec.js b/spec/frontend/helpers/vuex_action_helper_spec.js
deleted file mode 100644
index 4d7bf21820a..00000000000
--- a/spec/frontend/helpers/vuex_action_helper_spec.js
+++ /dev/null
@@ -1,174 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import testActionFn from './vuex_action_helper';
-
-const testActionFnWithOptionsArg = (...args) => {
- const [action, payload, state, expectedMutations, expectedActions, done] = args;
- return testActionFn({ action, payload, state, expectedMutations, expectedActions, done });
-};
-
-describe.each([testActionFn, testActionFnWithOptionsArg])(
- 'VueX test helper (testAction)',
- testAction => {
- let originalExpect;
- let assertion;
- let mock;
- const noop = () => {};
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- /**
- * In order to test the helper properly, we need to overwrite the Jest
- * `expect` helper. We test that the testAction helper properly passes the
- * dispatched actions/committed mutations to the Jest helper.
- */
- originalExpect = expect;
- assertion = null;
- global.expect = actual => ({
- toEqual: () => {
- originalExpect(actual).toEqual(assertion);
- },
- });
- });
-
- afterEach(() => {
- mock.restore();
- global.expect = originalExpect;
- });
-
- it('properly passes state and payload to action', () => {
- const exampleState = { FOO: 12, BAR: 3 };
- const examplePayload = { BAZ: 73, BIZ: 55 };
-
- const action = ({ state }, payload) => {
- originalExpect(state).toEqual(exampleState);
- originalExpect(payload).toEqual(examplePayload);
- };
-
- assertion = { mutations: [], actions: [] };
-
- testAction(action, examplePayload, exampleState);
- });
-
- describe('given a sync action', () => {
- it('mocks committing mutations', () => {
- const action = ({ commit }) => {
- commit('MUTATION');
- };
-
- assertion = { mutations: [{ type: 'MUTATION' }], actions: [] };
-
- testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
- });
-
- it('mocks dispatching actions', () => {
- const action = ({ dispatch }) => {
- dispatch('ACTION');
- };
-
- assertion = { actions: [{ type: 'ACTION' }], mutations: [] };
-
- testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
- });
-
- it('works with done callback once finished', done => {
- assertion = { mutations: [], actions: [] };
-
- testAction(noop, null, {}, assertion.mutations, assertion.actions, done);
- });
-
- it('returns a promise', done => {
- assertion = { mutations: [], actions: [] };
-
- testAction(noop, null, {}, assertion.mutations, assertion.actions)
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('given an async action (returning a promise)', () => {
- let lastError;
- const data = { FOO: 'BAR' };
-
- const asyncAction = ({ commit, dispatch }) => {
- dispatch('ACTION');
-
- return axios
- .get(TEST_HOST)
- .catch(error => {
- commit('ERROR');
- lastError = error;
- throw error;
- })
- .then(() => {
- commit('SUCCESS');
- return data;
- });
- };
-
- beforeEach(() => {
- lastError = null;
- });
-
- it('works with done callback once finished', done => {
- mock.onGet(TEST_HOST).replyOnce(200, 42);
-
- assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
-
- testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
- });
-
- it('returns original data of successful promise while checking actions/mutations', done => {
- mock.onGet(TEST_HOST).replyOnce(200, 42);
-
- assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
-
- testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
- .then(res => {
- originalExpect(res).toEqual(data);
- done();
- })
- .catch(done.fail);
- });
-
- it('returns original error of rejected promise while checking actions/mutations', done => {
- mock.onGet(TEST_HOST).replyOnce(500, '');
-
- assertion = { mutations: [{ type: 'ERROR' }], actions: [{ type: 'ACTION' }] };
-
- testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
- .then(done.fail)
- .catch(error => {
- originalExpect(error).toBe(lastError);
- done();
- });
- });
- });
-
- it('works with async actions not returning promises', done => {
- const data = { FOO: 'BAR' };
-
- const asyncAction = ({ commit, dispatch }) => {
- dispatch('ACTION');
-
- axios
- .get(TEST_HOST)
- .then(() => {
- commit('SUCCESS');
- return data;
- })
- .catch(error => {
- commit('ERROR');
- throw error;
- });
- };
-
- mock.onGet(TEST_HOST).replyOnce(200, 42);
-
- assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
-
- testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
- });
- },
-);
diff --git a/spec/frontend/helpers/wait_for_promises.js b/spec/frontend/helpers/wait_for_promises.js
deleted file mode 100644
index 1d2b53fc770..00000000000
--- a/spec/frontend/helpers/wait_for_promises.js
+++ /dev/null
@@ -1 +0,0 @@
-export default () => new Promise(resolve => requestAnimationFrame(resolve));
diff --git a/spec/frontend/helpers/wait_using_real_timer.js b/spec/frontend/helpers/wait_using_real_timer.js
deleted file mode 100644
index ddf23cd97b4..00000000000
--- a/spec/frontend/helpers/wait_using_real_timer.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/* useful for timing promises when jest fakeTimers are not reliable enough */
-export default timeout =>
- new Promise(resolve => {
- jest.useRealTimers();
- setTimeout(resolve, timeout);
- jest.useFakeTimers();
- });
diff --git a/spec/frontend/ide/components/activity_bar_spec.js b/spec/frontend/ide/components/activity_bar_spec.js
index 762f3c5dad1..1a4b6ca0b71 100644
--- a/spec/frontend/ide/components/activity_bar_spec.js
+++ b/spec/frontend/ide/components/activity_bar_spec.js
@@ -1,8 +1,8 @@
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 { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
describe('IDE activity bar', () => {
const Component = Vue.extend(ActivityBar);
@@ -59,7 +59,7 @@ describe('IDE activity bar', () => {
expect(vm.$el.querySelector('.js-ide-edit-mode').classList).toContain('active');
});
- it('sets commit item active', done => {
+ it('sets commit item active', (done) => {
vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js
index fe142d70698..85776f8cc0e 100644
--- a/spec/frontend/ide/components/branches/search_list_spec.js
+++ b/spec/frontend/ide/components/branches/search_list_spec.js
@@ -71,7 +71,7 @@ describe('IDE branches search list', () => {
it('renders check next to active branch', () => {
const activeBranch = 'regular';
createComponent({ branches }, activeBranch);
- const items = wrapper.findAll(Item).filter(w => w.props('isActive'));
+ const items = wrapper.findAll(Item).filter((w) => w.props('isActive'));
expect(items.length).toBe(1);
expect(items.at(0).props('item').name).toBe(activeBranch);
diff --git a/spec/frontend/ide/components/commit_sidebar/actions_spec.js b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
index 0003e13c92f..91751bd34ea 100644
--- a/spec/frontend/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
@@ -30,7 +30,7 @@ describe('IDE commit sidebar actions', () => {
vm.$store.state.currentProjectId = 'abcproject';
const proj = { ...projectData };
- proj.branches[currentBranchId] = branches.find(branch => branch.name === currentBranchId);
+ proj.branches[currentBranchId] = branches.find((branch) => branch.name === currentBranchId);
proj.empty_repo = emptyRepo;
Vue.set(vm.$store.state.projects, 'abcproject', proj);
@@ -72,7 +72,7 @@ describe('IDE commit sidebar actions', () => {
expect(findText()).toContain('Commit to master branch');
});
- it('hides merge request option when project merge requests are disabled', done => {
+ it('hides merge request option when project merge requests are disabled', (done) => {
createComponent({ hasMR: false });
vm.$nextTick(() => {
@@ -106,7 +106,7 @@ describe('IDE commit sidebar actions', () => {
expect(vm.$store.dispatch).not.toHaveBeenCalled();
});
- it('calls again after staged changes', done => {
+ it('calls again after staged changes', (done) => {
createComponent({ currentBranchId: null });
vm.$store.state.currentBranchId = 'master';
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 dbb43e43c19..c1dab4a04b6 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 { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
describe('IDE commit panel empty state', () => {
let vm;
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 7ce628d4da7..baa25a11c2a 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
@@ -41,7 +41,7 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(findPathText()).toContain(f.path);
});
- it('correctly renders renamed entries', done => {
+ it('correctly renders renamed entries', (done) => {
Vue.set(vm.file, 'prevName', 'Old name');
vm.$nextTick()
@@ -52,7 +52,7 @@ describe('Multi-file editor commit sidebar list item', () => {
.catch(done.fail);
});
- it('correctly renders entry, the name of which did not change after rename (as within a folder)', done => {
+ it('correctly renders entry, the name of which did not change after rename (as within a folder)', (done) => {
Vue.set(vm.file, 'prevName', f.name);
vm.$nextTick()
@@ -63,7 +63,7 @@ describe('Multi-file editor commit sidebar list item', () => {
.catch(done.fail);
});
- it('opens a closed file in the editor when clicking the file path', done => {
+ it('opens a closed file in the editor when clicking the file path', (done) => {
jest.spyOn(vm, 'openPendingTab');
jest.spyOn(router, 'push').mockImplementation(() => {});
@@ -77,7 +77,7 @@ describe('Multi-file editor commit sidebar list item', () => {
});
});
- it('calls updateViewer with diff when clicking file', done => {
+ it('calls updateViewer with diff when clicking file', (done) => {
jest.spyOn(vm, 'openFileInEditor');
jest.spyOn(vm, 'updateViewer');
jest.spyOn(router, 'push').mockImplementation(() => {});
@@ -134,7 +134,7 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(vm.$el.querySelector('.is-active')).toBe(null);
});
- it('adds active class when keys match', done => {
+ it('adds active class when keys match', (done) => {
vm.keyPrefix = 'staged';
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/commit_sidebar/list_spec.js b/spec/frontend/ide/components/commit_sidebar/list_spec.js
index 636dfbf0b2a..898ec4bebce 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_spec.js
@@ -31,7 +31,7 @@ describe('Multi-file editor commit sidebar list', () => {
});
describe('with a list of files', () => {
- beforeEach(done => {
+ beforeEach((done) => {
const f = file('file name');
f.changed = true;
vm.fileList.push(f);
diff --git a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
index d6ea8b9a4bd..1514fbc2c3b 100644
--- a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
@@ -23,7 +23,7 @@ describe('IDE commit message field', () => {
vm.$destroy();
});
- it('adds is-focused class on focus', done => {
+ it('adds is-focused class on focus', (done) => {
vm.$el.querySelector('textarea').focus();
vm.$nextTick(() => {
@@ -33,7 +33,7 @@ describe('IDE commit message field', () => {
});
});
- it('removed is-focused class on blur', done => {
+ it('removed is-focused class on blur', (done) => {
vm.$el.querySelector('textarea').focus();
vm.$nextTick()
@@ -66,7 +66,7 @@ describe('IDE commit message field', () => {
describe('highlights', () => {
describe('subject line', () => {
- it('does not highlight less than 50 characters', done => {
+ it('does not highlight less than 50 characters', (done) => {
vm.text = 'text less than 50 chars';
vm.$nextTick()
@@ -81,7 +81,7 @@ describe('IDE commit message field', () => {
.catch(done.fail);
});
- it('highlights characters over 50 length', done => {
+ it('highlights characters over 50 length', (done) => {
vm.text =
'text less than 50 chars that should not highlighted. text more than 50 should be highlighted';
@@ -102,7 +102,7 @@ describe('IDE commit message field', () => {
});
describe('body text', () => {
- it('does not highlight body text less tan 72 characters', done => {
+ it('does not highlight body text less tan 72 characters', (done) => {
vm.text = 'subject line\nbody content';
vm.$nextTick()
@@ -114,7 +114,7 @@ describe('IDE commit message field', () => {
.catch(done.fail);
});
- it('highlights body text more than 72 characters', done => {
+ it('highlights body text more than 72 characters', (done) => {
vm.text =
'subject line\nbody content that will be highlighted when it is more than 72 characters in length';
@@ -128,7 +128,7 @@ describe('IDE commit message field', () => {
.catch(done.fail);
});
- it('highlights body text & subject line', done => {
+ it('highlights body text & subject line', (done) => {
vm.text =
'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length';
@@ -147,7 +147,7 @@ describe('IDE commit message field', () => {
});
describe('scrolling textarea', () => {
- it('updates transform of highlights', done => {
+ it('updates transform of highlights', (done) => {
vm.text = 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content';
vm.$nextTick()
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 7cbf5ebc61a..50da64abbbe 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
@@ -17,7 +17,7 @@ describe('create new MR checkbox', () => {
] = { foo: 'bar' };
};
- const setPermissions = permissions => {
+ const setPermissions = (permissions) => {
store.state.projects[store.state.currentProjectId].userPermissions = permissions;
};
@@ -33,7 +33,7 @@ describe('create new MR checkbox', () => {
vm.$store.state.currentBranchId = currentBranchId;
store.state.projects.abcproject.branches[currentBranchId] = branches.find(
- branch => branch.name === currentBranchId,
+ (branch) => branch.name === currentBranchId,
);
return vm.$mount();
@@ -69,7 +69,7 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('has new MR', done => {
+ it('has new MR', (done) => {
setMR();
vm.$nextTick()
@@ -93,7 +93,7 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).toBe('');
});
- it('has new MR', done => {
+ it('has new MR', (done) => {
setMR();
vm.$nextTick()
@@ -118,7 +118,7 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('is rendered if MR exists', done => {
+ it('is rendered if MR exists', (done) => {
setMR();
vm.$nextTick()
@@ -141,7 +141,7 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('is hidden if MR exists', done => {
+ it('is hidden if MR exists', (done) => {
setMR();
vm.$nextTick()
@@ -165,7 +165,7 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
- it('is hidden if MR exists', done => {
+ it('is hidden if MR exists', (done) => {
setMR();
vm.$nextTick()
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 bf61f4bbe77..73d811f99b8 100644
--- a/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
@@ -7,7 +7,7 @@ describe('IDE commit sidebar radio group', () => {
let vm;
let store;
- beforeEach(done => {
+ beforeEach((done) => {
store = createStore();
const Component = Vue.extend(radioGroup);
@@ -33,7 +33,7 @@ describe('IDE commit sidebar radio group', () => {
expect(vm.$el.textContent).toContain('test');
});
- it('uses slot if label is not present', done => {
+ it('uses slot if label is not present', (done) => {
vm.$destroy();
vm = new Vue({
@@ -41,7 +41,7 @@ describe('IDE commit sidebar radio group', () => {
radioGroup,
},
store,
- render: createElement =>
+ render: (createElement) =>
createElement('radio-group', { props: { value: '1' } }, 'Testing slot'),
});
@@ -54,7 +54,7 @@ describe('IDE commit sidebar radio group', () => {
});
});
- it('updates store when changing radio button', done => {
+ it('updates store when changing radio button', (done) => {
vm.$el.querySelector('input').dispatchEvent(new Event('change'));
Vue.nextTick(() => {
@@ -65,7 +65,7 @@ describe('IDE commit sidebar radio group', () => {
});
describe('with input', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.$destroy();
const Component = Vue.extend(radioGroup);
@@ -89,7 +89,7 @@ describe('IDE commit sidebar radio group', () => {
expect(vm.$el.querySelector('.form-control')).not.toBeNull();
});
- it('hides input when commitAction doesnt match value', done => {
+ it('hides input when commitAction doesnt match value', (done) => {
store.state.commit.commitAction = '2';
Vue.nextTick(() => {
@@ -98,7 +98,7 @@ describe('IDE commit sidebar radio group', () => {
});
});
- it('updates branch name in store on input', done => {
+ it('updates branch name in store on input', (done) => {
const input = vm.$el.querySelector('.form-control');
input.value = 'testing-123';
input.dispatchEvent(new Event('input'));
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 db13c90fbb9..b116321efb3 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 { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
describe('IDE commit panel successful commit state', () => {
let vm;
@@ -23,7 +23,7 @@ describe('IDE commit panel successful commit state', () => {
vm.$destroy();
});
- it('renders last commit message when it exists', done => {
+ it('renders last commit message when it exists', (done) => {
vm.$store.state.lastCommitMsg = 'testing commit message';
Vue.nextTick(() => {
diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js
index 8b7e7da3b51..fa6816d3546 100644
--- a/spec/frontend/ide/components/error_message_spec.js
+++ b/spec/frontend/ide/components/error_message_spec.js
@@ -10,7 +10,7 @@ describe('IDE error message component', () => {
let wrapper;
const setErrorMessageMock = jest.fn();
- const createComponent = messageProps => {
+ const createComponent = (messageProps) => {
const fakeStore = new Vuex.Store({
actions: { setErrorMessage: setErrorMessageMock },
});
@@ -103,7 +103,7 @@ describe('IDE error message component', () => {
let resolveAction;
actionMock.mockImplementation(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolveAction = resolve;
}),
);
diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js
index 2a106ad37c0..275b98bc154 100644
--- a/spec/frontend/ide/components/file_row_extra_spec.js
+++ b/spec/frontend/ide/components/file_row_extra_spec.js
@@ -45,15 +45,16 @@ describe('IDE extra file row component', () => {
expect(vm.folderChangesTooltip).toBe(undefined);
});
- [{ input: 1, output: '1 changed file' }, { input: 2, output: '2 changed files' }].forEach(
- ({ input, output }) => {
- it('returns changed files count if changes count is not 0', () => {
- changesCount = input;
-
- expect(vm.folderChangesTooltip).toBe(output);
- });
- },
- );
+ [
+ { input: 1, output: '1 changed file' },
+ { input: 2, output: '2 changed files' },
+ ].forEach(({ input, output }) => {
+ it('returns changed files count if changes count is not 0', () => {
+ changesCount = input;
+
+ expect(vm.folderChangesTooltip).toBe(output);
+ });
+ });
});
describe('show tree changes count', () => {
@@ -69,7 +70,7 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
});
- it('does not show when tree is open', done => {
+ it('does not show when tree is open', (done) => {
vm.file.type = 'tree';
vm.file.opened = true;
changesCount = 1;
@@ -81,7 +82,7 @@ describe('IDE extra file row component', () => {
});
});
- it('shows for trees with changes', done => {
+ it('shows for trees with changes', (done) => {
vm.file.type = 'tree';
vm.file.opened = false;
changesCount = 1;
@@ -99,7 +100,7 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
});
- it('shows when file is changed', done => {
+ it('shows when file is changed', (done) => {
vm.file.changed = true;
vm.$nextTick(() => {
@@ -109,7 +110,7 @@ describe('IDE extra file row component', () => {
});
});
- it('shows when file is staged', done => {
+ it('shows when file is staged', (done) => {
vm.file.staged = true;
vm.$nextTick(() => {
@@ -119,7 +120,7 @@ describe('IDE extra file row component', () => {
});
});
- it('shows when file is a tempFile', done => {
+ it('shows when file is a tempFile', (done) => {
vm.file.tempFile = true;
vm.$nextTick(() => {
@@ -129,7 +130,7 @@ describe('IDE extra file row component', () => {
});
});
- it('shows when file is renamed', done => {
+ it('shows when file is renamed', (done) => {
vm.file.prevPath = 'original-file';
vm.$nextTick(() => {
@@ -139,7 +140,7 @@ describe('IDE extra file row component', () => {
});
});
- it('hides when file is renamed', done => {
+ it('hides when file is renamed', (done) => {
vm.file.prevPath = 'original-file';
vm.file.type = 'tree';
@@ -156,7 +157,7 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null);
});
- it('shows when a merge request change', done => {
+ it('shows when a merge request change', (done) => {
vm.file.mrChange = true;
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/file_templates/bar_spec.js b/spec/frontend/ide/components/file_templates/bar_spec.js
index 5a33837fb14..158995c9c9c 100644
--- a/spec/frontend/ide/components/file_templates/bar_spec.js
+++ b/spec/frontend/ide/components/file_templates/bar_spec.js
@@ -46,7 +46,7 @@ describe('IDE file templates bar component', () => {
});
describe('template dropdown', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.$store.state.fileTemplates.templates = [
{
name: 'test',
@@ -67,10 +67,7 @@ describe('IDE file templates bar component', () => {
it('calls fetchTemplate on click', () => {
jest.spyOn(vm, 'fetchTemplate').mockImplementation();
- vm.$el
- .querySelectorAll('.dropdown-content')[1]
- .querySelector('button')
- .click();
+ vm.$el.querySelectorAll('.dropdown-content')[1].querySelector('button').click();
expect(vm.fetchTemplate).toHaveBeenCalledWith({
name: 'test',
@@ -78,7 +75,7 @@ describe('IDE file templates bar component', () => {
});
});
- it('shows undo button if updateSuccess is true', done => {
+ it('shows undo button if updateSuccess is true', (done) => {
vm.$store.state.fileTemplates.updateSuccess = true;
vm.$nextTick(() => {
@@ -96,7 +93,7 @@ describe('IDE file templates bar component', () => {
expect(vm.undoFileTemplate).toHaveBeenCalled();
});
- it('calls setSelectedTemplateType if activeFile name matches a template', done => {
+ it('calls setSelectedTemplateType if activeFile name matches a template', (done) => {
const fileName = '.gitlab-ci.yml';
jest.spyOn(vm, 'setSelectedTemplateType').mockImplementation(() => {});
diff --git a/spec/frontend/ide/components/file_templates/dropdown_spec.js b/spec/frontend/ide/components/file_templates/dropdown_spec.js
index 3cffbc3362f..628580103a4 100644
--- a/spec/frontend/ide/components/file_templates/dropdown_spec.js
+++ b/spec/frontend/ide/components/file_templates/dropdown_spec.js
@@ -109,7 +109,7 @@ describe('IDE file templates dropdown component', () => {
});
const items = findItemButtons();
- expect(items.wrappers.map(x => x.text())).toEqual(templates.map(x => x.name));
+ expect(items.wrappers.map((x) => x.text())).toEqual(templates.map((x) => x.name));
});
it('searches template data', () => {
@@ -124,7 +124,7 @@ describe('IDE file templates dropdown component', () => {
const items = findItemButtons();
expect(items.length).toBe(matches.length);
- expect(items.wrappers.map(x => x.text())).toEqual(matches);
+ expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
});
@@ -151,7 +151,7 @@ describe('IDE file templates dropdown component', () => {
const items = findItemButtons();
expect(items.length).toBe(data.length);
- expect(items.wrappers.map(x => x.text())).toEqual(data.map(x => x.name));
+ expect(items.wrappers.map((x) => x.text())).toEqual(data.map((x) => x.name));
});
it('renders input when `searchable` is true', () => {
@@ -169,7 +169,7 @@ describe('IDE file templates dropdown component', () => {
const items = findItemButtons();
expect(items.length).toBe(matches.length);
- expect(items.wrappers.map(x => x.text())).toEqual(matches);
+ expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
});
});
diff --git a/spec/frontend/ide/components/ide_review_spec.js b/spec/frontend/ide/components/ide_review_spec.js
index bcc98669427..37f34a96495 100644
--- a/spec/frontend/ide/components/ide_review_spec.js
+++ b/spec/frontend/ide/components/ide_review_spec.js
@@ -1,11 +1,11 @@
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 EditorModeDropdown from '~/ide/components/editor_mode_dropdown.vue';
import { createStore } from '~/ide/stores';
-import { trimText } from '../../helpers/text_helper';
-import { keepAlive } from '../../helpers/keep_alive_component_helper';
import { file } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/frontend/ide/components/ide_sidebar_nav_spec.js b/spec/frontend/ide/components/ide_sidebar_nav_spec.js
index 49d476b56e4..6b4cb9bd03d 100644
--- a/spec/frontend/ide/components/ide_sidebar_nav_spec.js
+++ b/spec/frontend/ide/components/ide_sidebar_nav_spec.js
@@ -48,7 +48,7 @@ describe('ide/components/ide_sidebar_nav', () => {
const findButtons = () => wrapper.findAll('li button');
const findButtonsData = () =>
- findButtons().wrappers.map(button => {
+ findButtons().wrappers.map((button) => {
return {
title: button.attributes('title'),
ariaLabel: button.attributes('aria-label'),
@@ -58,10 +58,7 @@ describe('ide/components/ide_sidebar_nav', () => {
tooltip: getBinding(button.element, 'tooltip').value,
};
});
- const clickTab = () =>
- findButtons()
- .at(TEST_CURRENT_INDEX)
- .trigger('click');
+ const clickTab = () => findButtons().at(TEST_CURRENT_INDEX).trigger('click');
describe.each`
isOpen | side | otherSide | classes | classesObj | emitEvent | emitArg
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index 315298eaf26..805fa898611 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -25,7 +25,7 @@ describe('WebIDE', () => {
tree: [],
loading: false,
};
- Object.keys(state).forEach(key => {
+ Object.keys(state).forEach((key) => {
store.state[key] = state[key];
});
diff --git a/spec/frontend/ide/components/ide_status_bar_spec.js b/spec/frontend/ide/components/ide_status_bar_spec.js
index bc8144f544c..47506bb87e8 100644
--- a/spec/frontend/ide/components/ide_status_bar_spec.js
+++ b/spec/frontend/ide/components/ide_status_bar_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import _ from 'lodash';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { TEST_HOST } from '../../helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import { createStore } from '~/ide/stores';
import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
import { rightSidebarViews } from '~/ide/constants';
@@ -73,7 +73,7 @@ describe('ideStatusBar', () => {
});
describe('pipeline status', () => {
- it('opens right sidebar on clicking icon', done => {
+ it('opens right sidebar on clicking icon', (done) => {
jest.spyOn(vm, 'openRightPane').mockImplementation(() => {});
Vue.set(vm.$store.state.pipelines, 'latestPipeline', {
details: {
diff --git a/spec/frontend/ide/components/ide_status_mr_spec.js b/spec/frontend/ide/components/ide_status_mr_spec.js
index 4d9ad61201d..ac1be4b21c0 100644
--- a/spec/frontend/ide/components/ide_status_mr_spec.js
+++ b/spec/frontend/ide/components/ide_status_mr_spec.js
@@ -9,7 +9,7 @@ const TEST_URL = `${TEST_HOST}merge-requests/9001`;
describe('ide/components/ide_status_mr', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(IdeStatusMr, {
propsData: props,
});
diff --git a/spec/frontend/ide/components/ide_tree_list_spec.js b/spec/frontend/ide/components/ide_tree_list_spec.js
index dd57a5c5f4d..c8153ea339e 100644
--- a/spec/frontend/ide/components/ide_tree_list_spec.js
+++ b/spec/frontend/ide/components/ide_tree_list_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeTreeList from '~/ide/components/ide_tree_list.vue';
import { createStore } from '~/ide/stores';
-import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
import { file } from '../helpers';
import { projectData } from '../mock_data';
@@ -41,7 +41,7 @@ describe('IDE tree list', () => {
vm.$mount();
});
- it('renders loading indicator', done => {
+ it('renders loading indicator', (done) => {
store.state.trees['abcproject/master'].loading = true;
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/ide_tree_spec.js b/spec/frontend/ide/components/ide_tree_spec.js
index ad00dec2e48..c5934b032c4 100644
--- a/spec/frontend/ide/components/ide_tree_spec.js
+++ b/spec/frontend/ide/components/ide_tree_spec.js
@@ -1,9 +1,9 @@
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';
-import { keepAlive } from '../../helpers/keep_alive_component_helper';
import { file } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/frontend/ide/components/jobs/detail/description_spec.js b/spec/frontend/ide/components/jobs/detail/description_spec.js
index 5554738336a..786a7661d97 100644
--- a/spec/frontend/ide/components/jobs/detail/description_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/description_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import Description from '~/ide/components/jobs/detail/description.vue';
-import mountComponent from '../../../../helpers/vue_mount_component_helper';
import { jobs } from '../../../mock_data';
describe('IDE job description', () => {
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 57174181a3d..b323ad8320c 100644
--- a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
@@ -5,7 +5,7 @@ import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue';
describe('IDE job log scroll button', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(ScrollButton, {
propsData: {
direction: 'up',
diff --git a/spec/frontend/ide/components/jobs/detail_spec.js b/spec/frontend/ide/components/jobs/detail_spec.js
index 496d8284fdd..79ac0a8122a 100644
--- a/spec/frontend/ide/components/jobs/detail_spec.js
+++ b/spec/frontend/ide/components/jobs/detail_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
+import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import JobDetail from '~/ide/components/jobs/detail.vue';
import { createStore } from '~/ide/stores';
-import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
import { jobs } from '../../mock_data';
describe('IDE jobs detail view', () => {
@@ -48,7 +48,7 @@ describe('IDE jobs detail view', () => {
expect(vm.$el.querySelector('.bash').textContent).toContain('testing');
});
- it('renders empty message output', done => {
+ it('renders empty message output', (done) => {
vm.$store.state.pipelines.detailJob.output = '';
vm.$nextTick(() => {
@@ -68,7 +68,7 @@ describe('IDE jobs detail view', () => {
expect(vm.$el.querySelector('.bash').style.display).toBe('none');
});
- it('hide loading icon when isLoading is false', done => {
+ it('hide loading icon when isLoading is false', (done) => {
vm.$store.state.pipelines.detailJob.isLoading = false;
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/jobs/item_spec.js b/spec/frontend/ide/components/jobs/item_spec.js
index 93c01640b54..7343fc80a03 100644
--- a/spec/frontend/ide/components/jobs/item_spec.js
+++ b/spec/frontend/ide/components/jobs/item_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import JobItem from '~/ide/components/jobs/item.vue';
-import mountComponent from '../../../helpers/vue_mount_component_helper';
import { jobs } from '../../mock_data';
describe('IDE jobs item', () => {
@@ -27,7 +27,7 @@ describe('IDE jobs item', () => {
expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null);
});
- it('does not render view logs button if not started', done => {
+ it('does not render view logs button if not started', (done) => {
vm.job.started = false;
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js
index e821a585e18..5c5c6602374 100644
--- a/spec/frontend/ide/components/jobs/list_spec.js
+++ b/spec/frontend/ide/components/jobs/list_spec.js
@@ -36,7 +36,7 @@ describe('IDE stages list', () => {
status: { icon: 'status_success' },
}));
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(StageList, {
propsData: {
...defaultProps,
@@ -48,7 +48,7 @@ describe('IDE stages list', () => {
};
afterEach(() => {
- Object.values(storeActions).forEach(actionMock => actionMock.mockClear());
+ Object.values(storeActions).forEach((actionMock) => actionMock.mockClear());
});
afterAll(() => {
diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js
index 3a47571ee13..e80215b9d13 100644
--- a/spec/frontend/ide/components/jobs/stage_spec.js
+++ b/spec/frontend/ide/components/jobs/stage_spec.js
@@ -20,7 +20,7 @@ describe('IDE pipeline stage', () => {
const findHeader = () => wrapper.find({ ref: 'cardHeader' });
const findJobList = () => wrapper.find({ ref: 'jobList' });
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(Stage, {
propsData: {
...defaultProps,
@@ -60,10 +60,7 @@ describe('IDE pipeline stage', () => {
it('emits clickViewLog entity with job', () => {
const [job] = defaultProps.stage.jobs;
createComponent();
- wrapper
- .findAll(Item)
- .at(0)
- .vm.$emit('clickViewLog', job);
+ wrapper.findAll(Item).at(0).vm.$emit('clickViewLog', job);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
});
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index 80dcd861451..f0ac852fa67 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -82,9 +82,7 @@ describe('IDE merge requests list', () => {
return wrapper.vm
.$nextTick()
.then(() => {
- findSearchTypeButtons()
- .at(0)
- .trigger('click');
+ findSearchTypeButtons().at(0).trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
@@ -153,8 +151,8 @@ describe('IDE merge requests list', () => {
it('shows search types', () => {
const buttons = findSearchTypeButtons();
- expect(buttons.wrappers.map(x => x.text().trim())).toEqual(
- wrapper.vm.$options.searchTypes.map(x => x.label),
+ expect(buttons.wrappers.map((x) => x.text().trim())).toEqual(
+ wrapper.vm.$options.searchTypes.map((x) => x.label),
);
});
@@ -168,9 +166,7 @@ describe('IDE merge requests list', () => {
describe('with search type', () => {
beforeEach(() => {
- findSearchTypeButtons()
- .at(0)
- .trigger('click');
+ findSearchTypeButtons().at(0).trigger('click');
return wrapper.vm
.$nextTick()
diff --git a/spec/frontend/ide/components/nav_dropdown_button_spec.js b/spec/frontend/ide/components/nav_dropdown_button_spec.js
index c98aa313f40..a02bfa5c391 100644
--- a/spec/frontend/ide/components/nav_dropdown_button_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_button_spec.js
@@ -23,7 +23,7 @@ describe('NavDropdown', () => {
vm.$mount();
};
- const findIcon = name => vm.$el.querySelector(`[data-testid="${name}-icon"]`);
+ const findIcon = (name) => vm.$el.querySelector(`[data-testid="${name}-icon"]`);
const findMRIcon = () => findIcon('merge-request');
const findBranchIcon = () => findIcon('branch');
@@ -36,7 +36,7 @@ describe('NavDropdown', () => {
expect(trimText(vm.$el.textContent)).toEqual('- -');
});
- it('renders branch name, if state has currentBranchId', done => {
+ it('renders branch name, if state has currentBranchId', (done) => {
vm.$store.state.currentBranchId = TEST_BRANCH_ID;
vm.$nextTick()
@@ -47,7 +47,7 @@ describe('NavDropdown', () => {
.catch(done.fail);
});
- it('renders mr id, if state has currentMergeRequestId', done => {
+ it('renders mr id, if state has currentMergeRequestId', (done) => {
vm.$store.state.currentMergeRequestId = TEST_MR_ID;
vm.$nextTick()
@@ -58,7 +58,7 @@ describe('NavDropdown', () => {
.catch(done.fail);
});
- it('renders branch and mr, if state has both', done => {
+ it('renders branch and mr, if state has both', (done) => {
vm.$store.state.currentBranchId = TEST_BRANCH_ID;
vm.$store.state.currentMergeRequestId = TEST_MR_ID;
diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js
index 2f91ab7af0a..12a1a4c8013 100644
--- a/spec/frontend/ide/components/nav_dropdown_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_spec.js
@@ -39,7 +39,7 @@ describe('IDE NavDropdown', () => {
});
};
- const findIcon = name => wrapper.find(`[data-testid="${name}-icon"]`);
+ const findIcon = (name) => wrapper.find(`[data-testid="${name}-icon"]`);
const findMRIcon = () => findIcon('merge-request');
const findNavForm = () => wrapper.find('.ide-nav-form');
const showDropdown = () => {
@@ -58,7 +58,7 @@ describe('IDE NavDropdown', () => {
expect(findNavForm().exists()).toBe(false);
});
- it('renders nav form when show.bs.dropdown', done => {
+ it('renders nav form when show.bs.dropdown', (done) => {
showDropdown();
wrapper.vm
@@ -70,7 +70,7 @@ describe('IDE NavDropdown', () => {
.catch(done.fail);
});
- it('destroys nav form when closed', done => {
+ it('destroys nav form when closed', (done) => {
showDropdown();
hideDropdown();
diff --git a/spec/frontend/ide/components/new_dropdown/button_spec.js b/spec/frontend/ide/components/new_dropdown/button_spec.js
index 66317296ee9..32fa2babcdb 100644
--- a/spec/frontend/ide/components/new_dropdown/button_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/button_spec.js
@@ -37,7 +37,7 @@ describe('IDE new entry dropdown button component', () => {
expect(vm.$emit).toHaveBeenCalledWith('click');
});
- it('hides label if showLabel is false', done => {
+ it('hides label if showLabel is false', (done) => {
vm.showLabel = false;
vm.$nextTick(() => {
@@ -52,7 +52,7 @@ describe('IDE new entry dropdown button component', () => {
expect(vm.tooltipTitle).toBe('');
});
- it('returns label', done => {
+ it('returns label', (done) => {
vm.showLabel = false;
vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index c6cebf36de3..793d950b3e0 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -57,7 +57,7 @@ describe('new dropdown component', () => {
});
describe('isOpen', () => {
- it('scrolls dropdown into view', done => {
+ it('scrolls dropdown into view', (done) => {
jest.spyOn(vm.$refs.dropdownMenu, 'scrollIntoView').mockImplementation(() => {});
vm.isOpen = true;
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index ea8ba24c9d0..06434081e39 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -19,7 +19,7 @@ describe('new file modal component', () => {
${'tree'} | ${'Create new directory'} | ${'Create directory'} | ${false}
${'blob'} | ${'Create new file'} | ${'Create file'} | ${true}
`('$entryType', ({ entryType, modalTitle, btnTitle, showsFileTemplates }) => {
- beforeEach(done => {
+ beforeEach((done) => {
const store = createStore();
vm = createComponentWithStore(Component, store).$mount();
diff --git a/spec/frontend/ide/components/new_dropdown/upload_spec.js b/spec/frontend/ide/components/new_dropdown/upload_spec.js
index 3f3784dbb3a..7303f81aad0 100644
--- a/spec/frontend/ide/components/new_dropdown/upload_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/upload_spec.js
@@ -62,15 +62,15 @@ describe('new dropdown upload', () => {
result: 'base64,8PDw8A==', // ðððð
};
- const textFile = new File(['plain text'], 'textFile');
- const binaryFile = new File(['😺'], 'binaryFile');
+ const textFile = new File(['plain text'], 'textFile', { type: 'test/mime-text' });
+ const binaryFile = new File(['😺'], 'binaryFile', { type: 'test/mime-binary' });
beforeEach(() => {
jest.spyOn(FileReader.prototype, 'readAsText');
});
- it('calls readAsText and creates file in plain text (without encoding) if the file content is plain text', done => {
- const waitForCreate = new Promise(resolve => vm.$on('create', resolve));
+ it('calls readAsText and creates file in plain text (without encoding) if the file content is plain text', (done) => {
+ const waitForCreate = new Promise((resolve) => vm.$on('create', resolve));
vm.createFile(textTarget, textFile);
@@ -83,6 +83,7 @@ describe('new dropdown upload', () => {
type: 'blob',
content: 'plain text',
rawPath: '',
+ mimeType: 'test/mime-text',
});
})
.then(done)
@@ -99,6 +100,7 @@ describe('new dropdown upload', () => {
type: 'blob',
content: 'ðððð',
rawPath: 'blob:https://gitlab.com/048c7ac1-98de-4a37-ab1b-0206d0ea7e1b',
+ mimeType: 'test/mime-binary',
});
});
});
diff --git a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
index bb9ba32a699..c3da2a46858 100644
--- a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
+++ b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
@@ -15,7 +15,7 @@ describe('ide/components/panes/collapsible_sidebar.vue', () => {
const width = 350;
const fakeComponentName = 'fake-component';
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(CollapsibleSidebar, {
localVue,
store,
@@ -47,7 +47,7 @@ describe('ide/components/panes/collapsible_sidebar.vue', () => {
beforeEach(() => {
const FakeComponent = localVue.component(fakeComponentName, {
- render: () => {},
+ render: () => null,
});
fakeView = {
diff --git a/spec/frontend/ide/components/panes/right_spec.js b/spec/frontend/ide/components/panes/right_spec.js
index 203d35ed335..57fd0e49e94 100644
--- a/spec/frontend/ide/components/panes/right_spec.js
+++ b/spec/frontend/ide/components/panes/right_spec.js
@@ -14,7 +14,7 @@ describe('ide/components/panes/right.vue', () => {
let wrapper;
let store;
- const createComponent = props => {
+ const createComponent = (props) => {
extendStore(store, document.createElement('div'));
wrapper = shallowMount(RightPane, {
diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js
index c1744fefe20..a1fbfd96c31 100644
--- a/spec/frontend/ide/components/pipelines/list_spec.js
+++ b/spec/frontend/ide/components/pipelines/list_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { GlLoadingIcon, GlTab } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
@@ -8,8 +9,7 @@ import JobsList from '~/ide/components/jobs/list.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import IDEServices from '~/ide/services';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
jest.mock('~/ide/services', () => ({
pingUsage: jest.fn(),
@@ -59,9 +59,6 @@ describe('IDE pipelines list', () => {
failedStages: failedStagesGetterMock,
pipelineFailed: () => false,
},
- methods: {
- fetchLatestPipeline: jest.fn(),
- },
},
},
});
@@ -69,7 +66,6 @@ describe('IDE pipelines list', () => {
const createComponent = (state = {}, pipelinesState = {}) => {
wrapper = shallowMount(List, {
- localVue,
store: createStore(state, pipelinesState),
});
};
@@ -165,11 +161,7 @@ describe('IDE pipelines list', () => {
const isLoadingJobs = true;
createComponent({}, { ...withLatestPipelineState, stages, isLoadingJobs });
- const jobProps = wrapper
- .findAll(GlTab)
- .at(0)
- .find(JobsList)
- .props();
+ const jobProps = wrapper.findAll(GlTab).at(0).find(JobsList).props();
expect(jobProps.stages).toBe(stages);
expect(jobProps.loading).toBe(isLoadingJobs);
});
@@ -180,11 +172,7 @@ describe('IDE pipelines list', () => {
const isLoadingJobs = true;
createComponent({}, { ...withLatestPipelineState, isLoadingJobs });
- const jobProps = wrapper
- .findAll(GlTab)
- .at(1)
- .find(JobsList)
- .props();
+ const jobProps = wrapper.findAll(GlTab).at(1).find(JobsList).props();
expect(jobProps.stages).toBe(failedStages);
expect(jobProps.loading).toBe(isLoadingJobs);
});
diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js
index 7b22f75cee4..220982e1fd9 100644
--- a/spec/frontend/ide/components/preview/clientside_spec.js
+++ b/spec/frontend/ide/components/preview/clientside_spec.js
@@ -3,6 +3,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import smooshpack from 'smooshpack';
import Clientside from '~/ide/components/preview/clientside.vue';
+import eventHub from '~/ide/eventhub';
jest.mock('smooshpack', () => ({
Manager: jest.fn(),
@@ -70,6 +71,17 @@ describe('IDE clientside preview', () => {
});
};
+ const createInitializedComponent = () => {
+ createComponent();
+ wrapper.setData({
+ sandpackReady: true,
+ manager: {
+ listener: jest.fn(),
+ updatePreview: jest.fn(),
+ },
+ });
+ };
+
afterEach(() => {
wrapper.destroy();
});
@@ -293,33 +305,33 @@ describe('IDE clientside preview', () => {
});
describe('update', () => {
- beforeEach(() => {
- createComponent();
- wrapper.setData({ sandpackReady: true });
- });
-
it('initializes manager if manager is empty', () => {
createComponent({ getters: { packageJson: dummyPackageJson } });
wrapper.setData({ sandpackReady: true });
wrapper.vm.update();
- jest.advanceTimersByTime(250);
-
return waitForCalls().then(() => {
expect(smooshpack.Manager).toHaveBeenCalled();
});
});
it('calls updatePreview', () => {
- wrapper.setData({
- manager: {
- listener: jest.fn(),
- updatePreview: jest.fn(),
- },
- });
+ createInitializedComponent();
+
wrapper.vm.update();
- jest.advanceTimersByTime(250);
+ expect(wrapper.vm.manager.updatePreview).toHaveBeenCalledWith(wrapper.vm.sandboxOpts);
+ });
+ });
+
+ describe('on ide.files.change event', () => {
+ beforeEach(() => {
+ createInitializedComponent();
+
+ eventHub.$emit('ide.files.change');
+ });
+
+ it('calls updatePreview', () => {
expect(wrapper.vm.manager.updatePreview).toHaveBeenCalledWith(wrapper.vm.sandboxOpts);
});
});
@@ -355,4 +367,18 @@ describe('IDE clientside preview', () => {
});
});
});
+
+ describe('when destroyed', () => {
+ let spy;
+
+ beforeEach(() => {
+ createInitializedComponent();
+ spy = wrapper.vm.manager.updatePreview;
+ wrapper.destroy();
+ });
+
+ it('does not call updatePreview', () => {
+ expect(spy).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/ide/components/repo_commit_section_spec.js b/spec/frontend/ide/components/repo_commit_section_spec.js
index 096079308cd..e91debee4ca 100644
--- a/spec/frontend/ide/components/repo_commit_section_spec.js
+++ b/spec/frontend/ide/components/repo_commit_section_spec.js
@@ -1,7 +1,7 @@
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 { keepAlive } from '../../helpers/keep_alive_component_helper';
import RepoCommitSection from '~/ide/components/repo_commit_section.vue';
import EmptyState from '~/ide/components/commit_sidebar/empty_state.vue';
import { stageKeys } from '~/ide/constants';
@@ -32,7 +32,7 @@ describe('RepoCommitSection', () => {
},
};
- const files = [file('file1'), file('file2')].map(f =>
+ const files = [file('file1'), file('file2')].map((f) =>
Object.assign(f, {
type: 'blob',
content: 'orginal content',
@@ -42,7 +42,7 @@ describe('RepoCommitSection', () => {
store.state.currentBranch = 'master';
store.state.changedFiles = [];
store.state.stagedFiles = [{ ...files[0] }, { ...files[1] }];
- store.state.stagedFiles.forEach(f =>
+ store.state.stagedFiles.forEach((f) =>
Object.assign(f, {
changed: true,
staged: true,
@@ -50,7 +50,7 @@ describe('RepoCommitSection', () => {
}),
);
- files.forEach(f => {
+ files.forEach((f) => {
store.state.entries[f.path] = f;
});
}
@@ -77,18 +77,8 @@ describe('RepoCommitSection', () => {
});
it('renders no changes text', () => {
- expect(
- wrapper
- .find(EmptyState)
- .text()
- .trim(),
- ).toContain('No changes');
- expect(
- wrapper
- .find(EmptyState)
- .find('img')
- .attributes('src'),
- ).toBe(TEST_NO_CHANGES_SVG);
+ expect(wrapper.find(EmptyState).text().trim()).toContain('No changes');
+ expect(wrapper.find(EmptyState).find('img').attributes('src')).toBe(TEST_NO_CHANGES_SVG);
});
});
@@ -115,9 +105,9 @@ describe('RepoCommitSection', () => {
const allFiles = store.state.changedFiles.concat(store.state.stagedFiles);
const changedFileNames = wrapper
.findAll('.multi-file-commit-list > li')
- .wrappers.map(x => x.text().trim());
+ .wrappers.map((x) => x.text().trim());
- expect(changedFileNames).toEqual(allFiles.map(x => x.path));
+ expect(changedFileNames).toEqual(allFiles.map((x) => x.path));
});
it('does not show empty state', () => {
@@ -151,7 +141,7 @@ describe('RepoCommitSection', () => {
beforeEach(() => {
setupDefaultState();
- store.state.changedFiles = store.state.stagedFiles.map(x =>
+ store.state.changedFiles = store.state.stagedFiles.map((x) =>
Object.assign(x, { staged: false }),
);
store.state.stagedFiles = [];
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 71a4f08cfb4..89a7f423e34 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -5,6 +5,7 @@ import '~/behaviors/markdown/render_gfm';
import { Range } from 'monaco-editor';
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';
@@ -16,7 +17,6 @@ import {
FILE_VIEW_MODE_PREVIEW,
viewerTypes,
} from '~/ide/constants';
-import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
import { file } from '../helpers';
import { exampleConfigs, exampleFiles } from '../lib/editorconfig/mock_data';
@@ -25,7 +25,7 @@ describe('RepoEditor', () => {
let store;
const waitForEditorSetup = () =>
- new Promise(resolve => {
+ new Promise((resolve) => {
vm.$once('editorSetup', resolve);
});
@@ -43,7 +43,7 @@ describe('RepoEditor', () => {
vm.$mount();
};
- const createOpenFile = path => {
+ const createOpenFile = (path) => {
const origFile = store.state.openFiles[0];
const newFile = { ...origFile, path, key: path, name: 'myfile.txt', content: 'hello world' };
@@ -91,7 +91,7 @@ describe('RepoEditor', () => {
});
const findEditor = () => vm.$el.querySelector('.multi-file-editor-holder');
- const changeViewMode = viewMode =>
+ const changeViewMode = (viewMode) =>
store.dispatch('editor/updateFileEditor', { path: vm.file.path, data: { viewMode } });
describe('default', () => {
@@ -119,7 +119,7 @@ describe('RepoEditor', () => {
expect(findEditor()).not.toHaveCss({ display: 'none' });
});
- it('renders only an edit tab', done => {
+ it('renders only an edit tab', (done) => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
@@ -157,7 +157,7 @@ describe('RepoEditor', () => {
mock.restore();
});
- it('renders an Edit and a Preview Tab', done => {
+ it('renders an Edit and a Preview Tab', (done) => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
@@ -169,7 +169,7 @@ describe('RepoEditor', () => {
});
});
- it('renders markdown for tempFile', done => {
+ it('renders markdown for tempFile', (done) => {
vm.file.tempFile = true;
vm.$nextTick()
@@ -202,9 +202,11 @@ describe('RepoEditor', () => {
});
describe('when open file is binary and not raw', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.file.name = 'file.dat';
vm.file.content = 'ðŸ±'; // non-ascii binary content
+ jest.spyOn(vm.editor, 'createInstance').mockImplementation();
+ jest.spyOn(vm.editor, 'createDiffInstance').mockImplementation();
vm.$nextTick(done);
});
@@ -212,10 +214,20 @@ describe('RepoEditor', () => {
it('does not render the IDE', () => {
expect(vm.shouldHideEditor).toBeTruthy();
});
+
+ it('does not call createInstance', async () => {
+ // Mirror the act's in the `createEditorInstance`
+ vm.createEditorInstance();
+
+ await vm.$nextTick();
+
+ expect(vm.editor.createInstance).not.toHaveBeenCalled();
+ expect(vm.editor.createDiffInstance).not.toHaveBeenCalled();
+ });
});
describe('createEditorInstance', () => {
- it('calls createInstance when viewer is editor', done => {
+ it('calls createInstance when viewer is editor', (done) => {
jest.spyOn(vm.editor, 'createInstance').mockImplementation();
vm.createEditorInstance();
@@ -227,7 +239,7 @@ describe('RepoEditor', () => {
});
});
- it('calls createDiffInstance when viewer is diff', done => {
+ it('calls createDiffInstance when viewer is diff', (done) => {
vm.$store.state.viewer = 'diff';
jest.spyOn(vm.editor, 'createDiffInstance').mockImplementation();
@@ -241,7 +253,7 @@ describe('RepoEditor', () => {
});
});
- it('calls createDiffInstance when viewer is a merge request diff', done => {
+ it('calls createDiffInstance when viewer is a merge request diff', (done) => {
vm.$store.state.viewer = 'mrdiff';
jest.spyOn(vm.editor, 'createDiffInstance').mockImplementation();
@@ -342,7 +354,7 @@ describe('RepoEditor', () => {
jest.spyOn(vm.editor, 'updateDiffView').mockImplementation();
});
- it('calls updateDimensions when panelResizing is false', done => {
+ it('calls updateDimensions when panelResizing is false', (done) => {
vm.$store.state.panelResizing = true;
vm.$nextTick()
@@ -358,7 +370,7 @@ describe('RepoEditor', () => {
.catch(done.fail);
});
- it('does not call updateDimensions when panelResizing is true', done => {
+ it('does not call updateDimensions when panelResizing is true', (done) => {
vm.$store.state.panelResizing = true;
vm.$nextTick(() => {
@@ -369,7 +381,7 @@ describe('RepoEditor', () => {
});
});
- it('calls updateDimensions when rightPane is opened', done => {
+ it('calls updateDimensions when rightPane is opened', (done) => {
vm.$store.state.rightPane.isOpen = true;
vm.$nextTick(() => {
@@ -386,7 +398,7 @@ describe('RepoEditor', () => {
expect(vm.$el.querySelector('.nav-links')).not.toBe(null);
});
- it('hides tabs in review mode', done => {
+ it('hides tabs in review mode', (done) => {
vm.$store.state.currentActivityView = leftSidebarViews.review.name;
vm.$nextTick(() => {
@@ -396,7 +408,7 @@ describe('RepoEditor', () => {
});
});
- it('hides tabs in commit mode', done => {
+ it('hides tabs in commit mode', (done) => {
vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
vm.$nextTick(() => {
@@ -408,7 +420,7 @@ describe('RepoEditor', () => {
});
describe('when files view mode is preview', () => {
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(vm.editor, 'updateDimensions').mockImplementation();
changeViewMode(FILE_VIEW_MODE_PREVIEW);
vm.file.name = 'myfile.md';
@@ -440,7 +452,7 @@ describe('RepoEditor', () => {
jest.spyOn(vm, 'shouldHideEditor', 'get').mockReturnValue(true);
});
- it('does not fetch file information for temp entries', done => {
+ it('does not fetch file information for temp entries', (done) => {
vm.file.tempFile = true;
vm.initEditor();
@@ -452,7 +464,7 @@ describe('RepoEditor', () => {
.catch(done.fail);
});
- it('is being initialised for files without content even if shouldHideEditor is `true`', done => {
+ it('is being initialised for files without content even if shouldHideEditor is `true`', (done) => {
vm.file.content = '';
vm.file.raw = '';
@@ -467,7 +479,7 @@ describe('RepoEditor', () => {
.catch(done.fail);
});
- it('does not initialize editor for files already with content', done => {
+ it('does not initialize editor for files already with content', (done) => {
vm.file.content = 'foo';
vm.initEditor();
@@ -487,7 +499,7 @@ describe('RepoEditor', () => {
jest.spyOn(vm, 'initEditor').mockImplementation();
});
- it('calls removePendingTab when old file is pending', done => {
+ it('calls removePendingTab when old file is pending', (done) => {
jest.spyOn(vm, 'shouldHideEditor', 'get').mockReturnValue(true);
jest.spyOn(vm, 'removePendingTab').mockImplementation();
@@ -507,7 +519,7 @@ describe('RepoEditor', () => {
.catch(done.fail);
});
- it('does not call initEditor if the file did not change', done => {
+ it('does not call initEditor if the file did not change', (done) => {
Vue.set(vm, 'file', vm.file);
vm.$nextTick()
@@ -518,7 +530,7 @@ describe('RepoEditor', () => {
.catch(done.fail);
});
- it('calls initEditor when file key is changed', done => {
+ it('calls initEditor when file key is changed', (done) => {
expect(vm.initEditor).not.toHaveBeenCalled();
Vue.set(vm, 'file', {
@@ -540,7 +552,7 @@ describe('RepoEditor', () => {
vm.getRawFileData.mockRestore();
});
- const createRemoteFile = name => ({
+ const createRemoteFile = (name) => ({
...file(name),
tmpFile: false,
});
@@ -593,7 +605,7 @@ describe('RepoEditor', () => {
});
describe('onPaste', () => {
- const setFileName = name => {
+ const setFileName = (name) => {
Vue.set(vm, 'file', {
...vm.file,
content: 'hello world\n',
@@ -615,8 +627,8 @@ describe('RepoEditor', () => {
);
};
- const watchState = watched =>
- new Promise(resolve => {
+ const watchState = (watched) =>
+ new Promise((resolve) => {
const unwatch = vm.$store.watch(watched, () => {
unwatch();
resolve();
@@ -626,7 +638,7 @@ describe('RepoEditor', () => {
// Pasting an image does a lot of things like using the FileReader API,
// so, waitForPromises isn't very reliable (and causes a flaky spec)
// Read more about state.watch: https://vuex.vuejs.org/api/#watch
- const waitForFileContentChange = () => watchState(s => s.entries['foo/bar.md'].content);
+ const waitForFileContentChange = () => watchState((s) => s.entries['foo/bar.md'].content);
beforeEach(() => {
setFileName('bar.md');
diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js
index b251f207853..45a17c37667 100644
--- a/spec/frontend/ide/components/repo_tabs_spec.js
+++ b/spec/frontend/ide/components/repo_tabs_spec.js
@@ -30,7 +30,7 @@ describe('RepoTabs', () => {
wrapper.destroy();
});
- it('renders a list of tabs', done => {
+ it('renders a list of tabs', (done) => {
store.state.openFiles[0].active = true;
wrapper.vm.$nextTick(() => {
diff --git a/spec/frontend/ide/components/resizable_panel_spec.js b/spec/frontend/ide/components/resizable_panel_spec.js
index 7368de0cee7..b1a1212371e 100644
--- a/spec/frontend/ide/components/resizable_panel_spec.js
+++ b/spec/frontend/ide/components/resizable_panel_spec.js
@@ -38,7 +38,7 @@ describe('~/ide/components/resizable_panel', () => {
};
const findResizer = () => wrapper.find(PanelResizer);
const findInlineStyle = () => wrapper.element.style.cssText;
- const createInlineStyle = width => `width: ${width}px;`;
+ const createInlineStyle = (width) => `width: ${width}px;`;
describe.each`
props | showResizer | resizerSide | expectedStyle
diff --git a/spec/frontend/ide/components/shared/tokened_input_spec.js b/spec/frontend/ide/components/shared/tokened_input_spec.js
index e687216bd06..837bfe6b574 100644
--- a/spec/frontend/ide/components/shared/tokened_input_spec.js
+++ b/spec/frontend/ide/components/shared/tokened_input_spec.js
@@ -44,9 +44,9 @@ describe('IDE shared/TokenedInput', () => {
});
it('renders tokens', () => {
- const renderedTokens = getTokenElements(vm).map(x => x.textContent.trim());
+ const renderedTokens = getTokenElements(vm).map((x) => x.textContent.trim());
- expect(renderedTokens).toEqual(TEST_TOKENS.map(x => x.label));
+ expect(renderedTokens).toEqual(TEST_TOKENS.map((x) => x.label));
});
it('renders input', () => {
@@ -54,7 +54,7 @@ describe('IDE shared/TokenedInput', () => {
expect(vm.$refs.input).toHaveValue(TEST_VALUE);
});
- it('renders placeholder, when tokens are empty', done => {
+ it('renders placeholder, when tokens are empty', (done) => {
vm.tokens = [];
vm.$nextTick()
diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js
index 3ca37166ac4..5653c8bf14d 100644
--- a/spec/frontend/ide/components/terminal/session_spec.js
+++ b/spec/frontend/ide/components/terminal/session_spec.js
@@ -67,7 +67,7 @@ describe('IDE TerminalSession', () => {
});
});
- [STARTING, PENDING, RUNNING].forEach(status => {
+ [STARTING, PENDING, RUNNING].forEach((status) => {
it(`show stop button when status is ${status}`, () => {
state.session = { status };
factory();
@@ -82,7 +82,7 @@ describe('IDE TerminalSession', () => {
});
});
- [STOPPING, STOPPED].forEach(status => {
+ [STOPPING, STOPPED].forEach((status) => {
it(`show stop button when status is ${status}`, () => {
state.session = { status };
factory();
diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
index c22063e1d72..99182710218 100644
--- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
@@ -17,7 +17,7 @@ describe('IDE TerminalControls', () => {
it('shows an up and down scroll button', () => {
factory();
- expect(buttons.wrappers.map(x => x.props())).toEqual([
+ expect(buttons.wrappers.map((x) => x.props())).toEqual([
expect.objectContaining({ direction: 'up', disabled: true }),
expect.objectContaining({ direction: 'down', disabled: true }),
]);
diff --git a/spec/frontend/ide/components/terminal/terminal_spec.js b/spec/frontend/ide/components/terminal/terminal_spec.js
index 3095288bb28..9cfe167d2f6 100644
--- a/spec/frontend/ide/components/terminal/terminal_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import Terminal from '~/ide/components/terminal/terminal.vue';
@@ -14,24 +15,25 @@ import GLTerminal from '~/terminal/terminal';
const TEST_TERMINAL_PATH = 'terminal/path';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
jest.mock('~/terminal/terminal', () =>
- jest.fn().mockImplementation(() => ({
- dispose: jest.fn(),
- disable: jest.fn(),
- addScrollListener: jest.fn(),
- scrollToTop: jest.fn(),
- scrollToBottom: jest.fn(),
- })),
+ jest.fn().mockImplementation(function FakeTerminal() {
+ Object.assign(this, {
+ dispose: jest.fn(),
+ disable: jest.fn(),
+ addScrollListener: jest.fn(),
+ scrollToTop: jest.fn(),
+ scrollToBottom: jest.fn(),
+ });
+ }),
);
describe('IDE Terminal', () => {
let wrapper;
let state;
- const factory = propsData => {
+ const factory = (propsData) => {
const store = new Vuex.Store({
state,
mutations: {
@@ -41,13 +43,12 @@ describe('IDE Terminal', () => {
},
});
- wrapper = shallowMount(localVue.extend(Terminal), {
+ wrapper = shallowMount(Terminal, {
propsData: {
status: RUNNING,
terminalPath: TEST_TERMINAL_PATH,
...propsData,
},
- localVue,
store,
});
};
@@ -63,7 +64,7 @@ describe('IDE Terminal', () => {
});
describe('loading text', () => {
- [STARTING, PENDING].forEach(status => {
+ [STARTING, PENDING].forEach((status) => {
it(`shows when starting (${status})`, () => {
factory({ status });
@@ -79,7 +80,7 @@ describe('IDE Terminal', () => {
expect(wrapper.find('.top-bar').text()).toBe('Stopping...');
});
- [RUNNING, STOPPED].forEach(status => {
+ [RUNNING, STOPPED].forEach((status) => {
it('hides when not loading', () => {
factory({ status });
@@ -102,7 +103,7 @@ describe('IDE Terminal', () => {
factory();
wrapper.vm.createTerminal();
- return localVue.nextTick();
+ return nextTick();
});
it('is visible if terminal is created', () => {
@@ -129,7 +130,7 @@ describe('IDE Terminal', () => {
wrapper.setData({ canScrollUp: true, canScrollDown: true });
- return localVue.nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.find(TerminalControls).props()).toEqual({
canScrollUp: true,
canScrollDown: true,
@@ -139,30 +140,24 @@ describe('IDE Terminal', () => {
});
describe('refresh', () => {
- let createTerminal;
- let stopTerminal;
-
- beforeEach(() => {
- createTerminal = jest.fn().mockName('createTerminal');
- stopTerminal = jest.fn().mockName('stopTerminal');
- });
-
it('creates the terminal if running', () => {
factory({ status: RUNNING, terminalPath: TEST_TERMINAL_PATH });
- wrapper.setMethods({ createTerminal });
wrapper.vm.refresh();
- expect(createTerminal).toHaveBeenCalled();
+ expect(GLTerminal.mock.instances).toHaveLength(1);
});
- it('stops the terminal if stopping', () => {
- factory({ status: STOPPING });
+ it('stops the terminal if stopping', async () => {
+ factory({ status: RUNNING, terminalPath: TEST_TERMINAL_PATH });
- wrapper.setMethods({ stopTerminal });
wrapper.vm.refresh();
- expect(stopTerminal).toHaveBeenCalled();
+ const terminal = GLTerminal.mock.instances[0];
+ wrapper.setProps({ status: STOPPING });
+ await nextTick();
+
+ expect(terminal.disable).toHaveBeenCalled();
});
});
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 9adf5848f9d..d15583f81e4 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
@@ -26,7 +26,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => {
namespaced: true,
state: moduleState,
mutations: {
- [START_LOADING]: state => {
+ [START_LOADING]: (state) => {
state.isLoading = true;
},
},
diff --git a/spec/frontend/ide/file_helpers.js b/spec/frontend/ide/file_helpers.js
index 326f8b9716d..19604b9d570 100644
--- a/spec/frontend/ide/file_helpers.js
+++ b/spec/frontend/ide/file_helpers.js
@@ -26,7 +26,7 @@ export const createMovedFile = (path, prevPath, content) =>
prevPath,
});
-export const createEntries = path =>
+export const createEntries = (path) =>
path.split('/').reduce((acc, part, idx, parts) => {
const parentPath = parts.slice(0, idx).join('/');
const fullPath = parentPath ? `${parentPath}/${part}` : part;
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index 6b65dd96ef4..f815c3d090e 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -12,9 +12,9 @@ export const file = (name = 'name', id = name, type = '', parent = null) =>
parentPath: parent ? parent.path : '',
});
-export const createEntriesFromPaths = paths =>
+export const createEntriesFromPaths = (paths) =>
paths
- .map(path => ({
+ .map((path) => ({
name: pathUtils.basename(path),
dir: pathUtils.dirname(path),
ext: pathUtils.extname(path),
@@ -30,7 +30,7 @@ export const createEntriesFromPaths = paths =>
};
}, {});
-export const createTriggerChangeAction = payload => ({
+export const createTriggerChangeAction = (payload) => ({
type: 'triggerFilesChange',
...(payload ? { payload } : {}),
});
@@ -41,5 +41,10 @@ export const createTriggerRenamePayload = (path, newPath) => ({
newPath,
});
+export const createTriggerUpdatePayload = (path) => ({
+ type: commitActionTypes.update,
+ path,
+});
+
export const createTriggerRenameAction = (path, newPath) =>
createTriggerChangeAction(createTriggerRenamePayload(path, newPath));
diff --git a/spec/frontend/ide/ide_router_extension_spec.js b/spec/frontend/ide/ide_router_extension_spec.js
index 3e29ecc4a90..976b127ac83 100644
--- a/spec/frontend/ide/ide_router_extension_spec.js
+++ b/spec/frontend/ide/ide_router_extension_spec.js
@@ -4,7 +4,7 @@ import IdeRouter from '~/ide/ide_router_extension';
jest.mock('vue-router');
describe('IDE overrides of VueRouter', () => {
- const paths = branch => [
+ const paths = (branch) => [
`${branch}`,
`/${branch}`,
`/${branch}/-/`,
@@ -35,7 +35,7 @@ describe('IDE overrides of VueRouter', () => {
${'test-#-hash'} | ${'test-%23-hash'}
${'test/hash#123'} | ${'test/hash%23123'}
`('finds project path when route is $path', ({ path, expected }) => {
- paths(path).forEach(route => {
+ paths(path).forEach((route) => {
const expectedPath = route.replace(path, expected);
router.push(route);
diff --git a/spec/frontend/ide/ide_router_spec.js b/spec/frontend/ide/ide_router_spec.js
index a4fe00883cf..acab2c6aeef 100644
--- a/spec/frontend/ide/ide_router_spec.js
+++ b/spec/frontend/ide/ide_router_spec.js
@@ -32,7 +32,7 @@ describe('IDE router', () => {
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
- ].forEach(route => {
+ ].forEach((route) => {
it(`finds project path when route is "${route}"`, () => {
router.push(route);
diff --git a/spec/frontend/ide/lib/common/model_spec.js b/spec/frontend/ide/lib/common/model_spec.js
index df46b7774b0..51df1e2e42f 100644
--- a/spec/frontend/ide/lib/common/model_spec.js
+++ b/spec/frontend/ide/lib/common/model_spec.js
@@ -81,7 +81,7 @@ describe('Multi-file editor library model', () => {
});
describe('onChange', () => {
- it('calls callback on change', done => {
+ it('calls callback on change', (done) => {
const spy = jest.fn();
model.onChange(spy);
diff --git a/spec/frontend/ide/lib/create_diff_spec.js b/spec/frontend/ide/lib/create_diff_spec.js
index 273f9ee27bd..76494f9af1b 100644
--- a/spec/frontend/ide/lib/create_diff_spec.js
+++ b/spec/frontend/ide/lib/create_diff_spec.js
@@ -145,12 +145,12 @@ new file mode 100644
--- /dev/null
+++ b/${PATH_LOREM}
@@ -0,0 +1,${LINES.length} @@
-${LINES.map(line => `+${line}`).join('\n')}
+${LINES.map((line) => `+${line}`).join('\n')}
diff --git "a/${PATH_IPSUM}" "b/${PATH_IPSUM}"
--- a/${PATH_IPSUM}
+++ b/${PATH_IPSUM}
@@ -1,${LINES.length} +1,1 @@
-${LINES.map(line => `-${line}`).join('\n')}
+${LINES.map((line) => `-${line}`).join('\n')}
+That's all folks!
\\ No newline at end of file
`;
@@ -167,10 +167,10 @@ ${LINES.map(line => `-${line}`).join('\n')}
const deletedFiles = ['foo/bar/zed/test.md', 'foo/bar/zed/test2.md'];
const entries = deletedFiles.reduce((acc, path) => Object.assign(acc, createEntries(path)), {});
const allDeleted = [...deletedFiles, 'foo/bar/zed', 'foo/bar'];
- allDeleted.forEach(path => {
+ allDeleted.forEach((path) => {
entries[path].deleted = true;
});
- const changedFiles = deletedFiles.map(x => entries[x]);
+ const changedFiles = deletedFiles.map((x) => entries[x]);
const result = createDiff({ changedFiles, entries });
diff --git a/spec/frontend/ide/lib/create_file_diff_spec.js b/spec/frontend/ide/lib/create_file_diff_spec.js
index 4b428468a6d..294f0a926aa 100644
--- a/spec/frontend/ide/lib/create_file_diff_spec.js
+++ b/spec/frontend/ide/lib/create_file_diff_spec.js
@@ -21,11 +21,7 @@ const spliceLines = (content, lineNumber, deleteCount = 0, newLines = []) => {
return lines.join('\n');
};
-const mapLines = (content, mapFn) =>
- content
- .split('\n')
- .map(mapFn)
- .join('\n');
+const mapLines = (content, mapFn) => content.split('\n').map(mapFn).join('\n');
describe('IDE lib/create_file_diff', () => {
it('returns empty string with "garbage" action', () => {
@@ -55,7 +51,7 @@ describe('IDE lib/create_file_diff', () => {
const expectedHead = `diff --git "a/${PATH}" "b/${PATH}"
new file mode 100644`;
- const expectedChunkHead = lineCount => `--- /dev/null
+ const expectedChunkHead = (lineCount) => `--- /dev/null
+++ b/${PATH}
@@ -0,0 +1,${lineCount} @@`;
@@ -90,7 +86,7 @@ ${expectedChunkHead(1)}
expect(result).toBe(`${expectedHead}
${expectedChunkHead(TEXT_LINE_COUNT)}
-${mapLines(TEXT, line => `+${line}`)}
+${mapLines(TEXT, (line) => `+${line}`)}
`);
});
});
@@ -99,7 +95,7 @@ ${mapLines(TEXT, line => `+${line}`)}
const expectedHead = `diff --git "a/${PATH}" "b/${PATH}"
deleted file mode 100644`;
- const expectedChunkHead = lineCount => `--- a/${PATH}
+ const expectedChunkHead = (lineCount) => `--- a/${PATH}
+++ /dev/null
@@ -1,${lineCount} +0,0 @@`;
@@ -115,7 +111,7 @@ deleted file mode 100644`;
expect(result).toBe(`${expectedHead}
${expectedChunkHead(TEXT_LINE_COUNT)}
-${mapLines(TEXT, line => `-${line}`)}
+${mapLines(TEXT, (line) => `-${line}`)}
`);
});
});
diff --git a/spec/frontend/ide/lib/diff/controller_spec.js b/spec/frontend/ide/lib/diff/controller_spec.js
index 8ee6388a760..57c134620c0 100644
--- a/spec/frontend/ide/lib/diff/controller_spec.js
+++ b/spec/frontend/ide/lib/diff/controller_spec.js
@@ -37,7 +37,7 @@ describe('Multi-file editor library dirty diff controller', () => {
});
describe('getDiffChangeType', () => {
- ['added', 'removed', 'modified'].forEach(type => {
+ ['added', 'removed', 'modified'].forEach((type) => {
it(`returns ${type}`, () => {
const change = {
[type]: true,
@@ -49,7 +49,7 @@ describe('Multi-file editor library dirty diff controller', () => {
});
describe('getDecorator', () => {
- ['added', 'removed', 'modified'].forEach(type => {
+ ['added', 'removed', 'modified'].forEach((type) => {
it(`returns with linesDecorationsClassName for ${type}`, () => {
const change = {
[type]: true,
diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js
index 01c2eab33a5..12779c61dc3 100644
--- a/spec/frontend/ide/lib/editor_spec.js
+++ b/spec/frontend/ide/lib/editor_spec.js
@@ -15,7 +15,7 @@ describe('Multi-file editor library', () => {
let holder;
let store;
- const setNodeOffsetWidth = val => {
+ const setNodeOffsetWidth = (val) => {
Object.defineProperty(instance.instance.getDomNode(), 'offsetWidth', {
get() {
return val;
diff --git a/spec/frontend/ide/lib/editorconfig/parser_spec.js b/spec/frontend/ide/lib/editorconfig/parser_spec.js
index f99410236e1..c2b4a8e6c49 100644
--- a/spec/frontend/ide/lib/editorconfig/parser_spec.js
+++ b/spec/frontend/ide/lib/editorconfig/parser_spec.js
@@ -2,14 +2,14 @@ import { getRulesWithTraversal } from '~/ide/lib/editorconfig/parser';
import { exampleConfigs, exampleFiles } from './mock_data';
describe('~/ide/lib/editorconfig/parser', () => {
- const getExampleConfigContent = path =>
- Promise.resolve(exampleConfigs.find(x => x.path === path)?.content);
+ const getExampleConfigContent = (path) =>
+ Promise.resolve(exampleConfigs.find((x) => x.path === path)?.content);
describe('getRulesWithTraversal', () => {
it.each(exampleFiles)(
'traverses through all editorconfig files in parent directories (until root=true is hit) and finds rules for this file (case %#)',
({ path, rules }) => {
- return getRulesWithTraversal(path, getExampleConfigContent).then(result => {
+ return getRulesWithTraversal(path, getExampleConfigContent).then((result) => {
expect(result).toEqual(rules);
});
},
diff --git a/spec/frontend/ide/lib/errors_spec.js b/spec/frontend/ide/lib/errors_spec.js
index 733d5a5da3c..2e4acdb8a63 100644
--- a/spec/frontend/ide/lib/errors_spec.js
+++ b/spec/frontend/ide/lib/errors_spec.js
@@ -14,7 +14,7 @@ const CODEOWNERS_MESSAGE =
const CHANGED_MESSAGE = 'Things changed since you started editing';
describe('~/ide/lib/errors', () => {
- const createResponseError = message => ({
+ const createResponseError = (message) => ({
response: {
data: {
message,
diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js
index 8ca6f01d9a6..50738af0e33 100644
--- a/spec/frontend/ide/lib/files_spec.js
+++ b/spec/frontend/ide/lib/files_spec.js
@@ -1,7 +1,9 @@
import { decorateFiles, splitParent } from '~/ide/lib/files';
import { decorateData } from '~/ide/stores/utils';
-const createEntries = paths => {
+const TEST_BLOB_DATA = { mimeType: 'test/mime' };
+
+const createEntries = (paths) => {
const createEntry = (acc, { path, type, children }) => {
const { name, parent } = splitParent(path);
@@ -13,7 +15,8 @@ const createEntries = paths => {
type,
parentPath: parent,
}),
- tree: children.map(childName => expect.objectContaining({ name: childName })),
+ tree: children.map((childName) => expect.objectContaining({ name: childName })),
+ ...(type === 'blob' ? TEST_BLOB_DATA : {}),
};
return acc;
@@ -43,14 +46,14 @@ describe('IDE lib decorate files', () => {
{ path: 'README.md', type: 'blob', children: [] },
]);
- const { entries, treeList } = decorateFiles({ data });
+ const { entries, treeList } = decorateFiles({ data, blobData: TEST_BLOB_DATA });
// Here we test the keys and then each key/value individually because `expect(entries).toEqual(expectedEntries)`
// was taking a very long time for some reason. Probably due to large objects and nested `expect.objectContaining`.
const entryKeys = Object.keys(entries);
expect(entryKeys).toEqual(Object.keys(expectedEntries));
- entryKeys.forEach(key => {
+ entryKeys.forEach((key) => {
expect(entries[key]).toEqual(expectedEntries[key]);
});
diff --git a/spec/frontend/ide/lib/languages/hcl_spec.js b/spec/frontend/ide/lib/languages/hcl_spec.js
index a39673a3225..c6ebad6a4f4 100644
--- a/spec/frontend/ide/lib/languages/hcl_spec.js
+++ b/spec/frontend/ide/lib/languages/hcl_spec.js
@@ -284,6 +284,42 @@ describe('tokenization for .tf files', () => {
],
],
],
+ [
+ ` foo = <<-EOF
+ bar
+ EOF`,
+ [
+ [
+ { language: 'hcl', offset: 0, type: '' },
+ { language: 'hcl', offset: 2, type: 'variable.hcl' },
+ { language: 'hcl', offset: 5, type: '' },
+ { language: 'hcl', offset: 6, type: 'operator.hcl' },
+ { language: 'hcl', offset: 7, type: '' },
+ { language: 'hcl', offset: 8, type: 'string.heredoc.delimiter.hcl' },
+ ],
+ [{ language: 'hcl', offset: 0, type: 'string.heredoc.hcl' }],
+ [
+ { language: 'hcl', offset: 0, type: 'string.heredoc.hcl' },
+ { language: 'hcl', offset: 2, type: 'string.heredoc.delimiter.hcl' },
+ ],
+ ],
+ ],
+ [
+ `foo = <<-EOF
+bar
+EOF`,
+ [
+ [
+ { language: 'hcl', offset: 0, type: 'variable.hcl' },
+ { language: 'hcl', offset: 3, type: '' },
+ { language: 'hcl', offset: 4, type: 'operator.hcl' },
+ { language: 'hcl', offset: 5, type: '' },
+ { language: 'hcl', offset: 6, type: 'string.heredoc.delimiter.hcl' },
+ ],
+ [{ language: 'hcl', offset: 0, type: 'string.heredoc.hcl' }],
+ [{ language: 'hcl', offset: 0, type: 'string.heredoc.delimiter.hcl' }],
+ ],
+ ],
])('%s', (string, tokens) => {
expect(editor.tokenize(string, 'hcl')).toEqual(tokens);
});
diff --git a/spec/frontend/ide/lib/mirror_spec.js b/spec/frontend/ide/lib/mirror_spec.js
index 21bed5948f3..8f417ea54dc 100644
--- a/spec/frontend/ide/lib/mirror_spec.js
+++ b/spec/frontend/ide/lib/mirror_spec.js
@@ -72,7 +72,7 @@ describe('ide/lib/mirror', () => {
});
const waitForConnection = (delay = SERVICE_DELAY) => {
- const wait = new Promise(resolve => {
+ const wait = new Promise((resolve) => {
setTimeout(resolve, 10);
});
@@ -82,7 +82,7 @@ describe('ide/lib/mirror', () => {
};
const connectPass = () => waitForConnection().then(() => mockWebSocket.onopen());
const connectFail = () => waitForConnection().then(() => mockWebSocket.onerror());
- const sendResponse = msg => {
+ const sendResponse = (msg) => {
mockWebSocket.onmessage(msg);
};
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index d2c32a81811..c3d6182bd78 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -51,7 +51,7 @@ describe('IDE services', () => {
raw: 'raw content',
};
- return services.getRawFileData(file).then(raw => {
+ return services.getRawFileData(file).then((raw) => {
expect(raw).toBe('content');
});
});
@@ -65,7 +65,7 @@ describe('IDE services', () => {
raw: 'raw content',
};
- return services.getRawFileData(file).then(raw => {
+ return services.getRawFileData(file).then((raw) => {
expect(raw).toBe('raw content');
});
});
@@ -77,7 +77,7 @@ describe('IDE services', () => {
raw: 'raw content',
};
- return services.getRawFileData(file).then(raw => {
+ return services.getRawFileData(file).then((raw) => {
expect(raw).toBe('raw content');
});
});
@@ -89,7 +89,7 @@ describe('IDE services', () => {
raw: '',
};
- return services.getRawFileData(file).then(raw => {
+ return services.getRawFileData(file).then((raw) => {
expect(raw).toBe('');
});
});
@@ -116,7 +116,22 @@ describe('IDE services', () => {
});
it('sends a request to file.rawPath', () => {
- return services.getRawFileData(file).then(raw => {
+ return services.getRawFileData(file).then((raw) => {
+ expect(axios.get).toHaveBeenCalledWith(file.rawPath, {
+ transformResponse: [expect.any(Function)],
+ });
+ expect(raw).toEqual('raw content');
+ });
+ });
+
+ it('returns arraybuffer for binary files', () => {
+ file.binary = true;
+
+ return services.getRawFileData(file).then((raw) => {
+ expect(axios.get).toHaveBeenCalledWith(file.rawPath, {
+ transformResponse: [expect.any(Function)],
+ responseType: 'arraybuffer',
+ });
expect(raw).toEqual('raw content');
});
});
@@ -146,7 +161,7 @@ describe('IDE services', () => {
it('gives back file.baseRaw for files with that property present', () => {
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then((content) => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -155,7 +170,7 @@ describe('IDE services', () => {
file.tempFile = true;
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then((content) => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -192,7 +207,7 @@ describe('IDE services', () => {
});
it('fetches file content', () =>
- services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
+ services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then((content) => {
expect(content).toEqual(TEST_FILE_CONTENTS);
}));
},
@@ -209,7 +224,7 @@ describe('IDE services', () => {
Api.project.mockReturnValue(Promise.resolve({ data: { ...projectData } }));
query.mockReturnValue(Promise.resolve({ data: { project: gqlProjectData } }));
- return services.getProjectData(TEST_NAMESPACE, TEST_PROJECT).then(response => {
+ return services.getProjectData(TEST_NAMESPACE, TEST_PROJECT).then((response) => {
expect(response).toEqual({ data: { ...projectData, ...gqlProjectData } });
expect(Api.project).toHaveBeenCalledWith(TEST_PROJECT_ID);
expect(query).toHaveBeenCalledWith({
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 744ac086b5f..9d367714bbe 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -7,7 +7,7 @@ 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 { file, createTriggerRenameAction } from '../../helpers';
+import { file, createTriggerRenameAction, createTriggerUpdatePayload } from '../../helpers';
const ORIGINAL_CONTENT = 'original content';
const RELATIVE_URL_ROOT = '/gitlab';
@@ -75,7 +75,7 @@ describe('IDE store file actions', () => {
});
});
- it('closes file & opens next available file', () => {
+ it('switches to the next available file before closing the current one ', () => {
const f = file('newOpenFile');
store.state.openFiles.push(f);
@@ -90,10 +90,12 @@ describe('IDE store file actions', () => {
});
it('removes file if it pending', () => {
- store.state.openFiles.push({
- ...localFile,
- pending: true,
- });
+ store.state.openFiles = [
+ {
+ ...localFile,
+ pending: true,
+ },
+ ];
return store.dispatch('closeFile', localFile).then(() => {
expect(store.state.openFiles.length).toBe(0);
@@ -189,7 +191,7 @@ describe('IDE store file actions', () => {
});
describe('call to service', () => {
- const callExpectation = serviceCalled => {
+ const callExpectation = (serviceCalled) => {
store.dispatch('getFileData', { path: localFile.path });
if (serviceCalled) {
@@ -422,11 +424,11 @@ describe('IDE store file actions', () => {
loadingWhenGettingRawData = undefined;
loadingWhenGettingBaseRawData = undefined;
- jest.spyOn(service, 'getRawFileData').mockImplementation(f => {
+ jest.spyOn(service, 'getRawFileData').mockImplementation((f) => {
loadingWhenGettingRawData = f.loading;
return Promise.resolve('raw');
});
- jest.spyOn(service, 'getBaseRawFileData').mockImplementation(f => {
+ jest.spyOn(service, 'getBaseRawFileData').mockImplementation((f) => {
loadingWhenGettingBaseRawData = f.loading;
return Promise.resolve('rawBase');
});
@@ -510,12 +512,15 @@ describe('IDE store file actions', () => {
describe('changeFileContent', () => {
let tmpFile;
+ let onFilesChange;
beforeEach(() => {
tmpFile = file('tmpFile');
tmpFile.content = '\n';
tmpFile.raw = '\n';
store.state.entries[tmpFile.path] = tmpFile;
+ onFilesChange = jest.fn();
+ eventHub.$on('ide.files.change', onFilesChange);
});
it('updates file content', () => {
@@ -580,6 +585,17 @@ describe('IDE store file actions', () => {
expect(store.state.changedFiles.length).toBe(0);
});
});
+
+ it('triggers ide.files.change', async () => {
+ expect(onFilesChange).not.toHaveBeenCalled();
+
+ await store.dispatch('changeFileContent', {
+ path: tmpFile.path,
+ content: 'content\n',
+ });
+
+ expect(onFilesChange).toHaveBeenCalledWith(createTriggerUpdatePayload(tmpFile.path));
+ });
});
describe('with changed file', () => {
@@ -743,7 +759,7 @@ describe('IDE store file actions', () => {
});
it('returns true when opened', () => {
- return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(added => {
+ return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then((added) => {
expect(added).toBe(true);
});
});
@@ -755,7 +771,7 @@ describe('IDE store file actions', () => {
key: `pending-${f.key}`,
});
- return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(added => {
+ return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then((added) => {
expect(added).toBe(false);
});
});
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index b1cceda9d85..9b17d95ea35 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -49,7 +49,7 @@ describe('IDE store merge request actions', () => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, mockData);
});
- it('calls getProjectMergeRequests service method', done => {
+ it('calls getProjectMergeRequests service method', (done) => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
@@ -66,19 +66,19 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('sets the "Merge Request" Object', done => {
+ it('sets the "Merge Request" Object', (done) => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
expect(store.state.projects.abcproject.mergeRequests).toEqual({
- '2': expect.objectContaining(mrData),
+ 2: expect.objectContaining(mrData),
});
done();
})
.catch(done.fail);
});
- it('sets "Current Merge Request" object to the most recent MR', done => {
+ it('sets "Current Merge Request" object to the most recent MR', (done) => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
@@ -88,7 +88,7 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('does nothing if user cannot read MRs', done => {
+ it('does nothing if user cannot read MRs', (done) => {
store.state.projects[TEST_PROJECT].userPermissions[PERMISSION_READ_MR] = false;
store
@@ -108,7 +108,7 @@ describe('IDE store merge request actions', () => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, []);
});
- it('does not fail if there are no merge requests for current branch', done => {
+ it('does not fail if there are no merge requests for current branch', (done) => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'foo' })
.then(() => {
@@ -126,7 +126,7 @@ describe('IDE store merge request actions', () => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).networkError();
});
- it('flashes message, if error', done => {
+ it('flashes message, if error', (done) => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.catch(() => {
@@ -149,7 +149,7 @@ describe('IDE store merge request actions', () => {
.reply(200, { title: 'mergerequest' });
});
- it('calls getProjectMergeRequestData service method', done => {
+ it('calls getProjectMergeRequestData service method', (done) => {
store
.dispatch('getMergeRequestData', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
@@ -160,7 +160,7 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('sets the Merge Request Object', done => {
+ it('sets the Merge Request Object', (done) => {
store
.dispatch('getMergeRequestData', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
@@ -180,7 +180,7 @@ describe('IDE store merge request actions', () => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1/).networkError();
});
- it('dispatches error action', done => {
+ it('dispatches error action', (done) => {
const dispatch = jest.fn();
getMergeRequestData(
@@ -224,7 +224,7 @@ describe('IDE store merge request actions', () => {
.reply(200, { title: 'mergerequest' });
});
- it('calls getProjectMergeRequestChanges service method', done => {
+ it('calls getProjectMergeRequestChanges service method', (done) => {
store
.dispatch('getMergeRequestChanges', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
@@ -235,7 +235,7 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('sets the Merge Request Changes Object', done => {
+ it('sets the Merge Request Changes Object', (done) => {
store
.dispatch('getMergeRequestChanges', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
@@ -253,7 +253,7 @@ describe('IDE store merge request actions', () => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/changes/).networkError();
});
- it('dispatches error action', done => {
+ it('dispatches error action', (done) => {
const dispatch = jest.fn();
getMergeRequestChanges(
@@ -296,7 +296,7 @@ describe('IDE store merge request actions', () => {
jest.spyOn(service, 'getProjectMergeRequestVersions');
});
- it('calls getProjectMergeRequestVersions service method', done => {
+ it('calls getProjectMergeRequestVersions service method', (done) => {
store
.dispatch('getMergeRequestVersions', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
@@ -307,7 +307,7 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('sets the Merge Request Versions Object', done => {
+ it('sets the Merge Request Versions Object', (done) => {
store
.dispatch('getMergeRequestVersions', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
@@ -323,7 +323,7 @@ describe('IDE store merge request actions', () => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/versions/).networkError();
});
- it('dispatches error action', done => {
+ it('dispatches error action', (done) => {
const dispatch = jest.fn();
getMergeRequestVersions(
@@ -422,7 +422,7 @@ describe('IDE store merge request actions', () => {
);
});
- it('dispatches actions for merge request data', done => {
+ it('dispatches actions for merge request data', (done) => {
openMergeRequest({ state: store.state, dispatch: store.dispatch, getters: mockGetters }, mr)
.then(() => {
expect(store.dispatch.mock.calls).toEqual([
@@ -451,7 +451,7 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('updates activity bar view and gets file data, if changes are found', done => {
+ it('updates activity bar view and gets file data, if changes are found', (done) => {
store.state.entries.foo = {
type: 'blob',
};
@@ -490,7 +490,7 @@ describe('IDE store merge request actions', () => {
.catch(done.fail);
});
- it('flashes message, if error', done => {
+ it('flashes message, if error', (done) => {
store.dispatch.mockRejectedValue();
openMergeRequest(store, mr)
diff --git a/spec/frontend/ide/stores/actions/project_spec.js b/spec/frontend/ide/stores/actions/project_spec.js
index ca3687307a9..1244c8af91a 100644
--- a/spec/frontend/ide/stores/actions/project_spec.js
+++ b/spec/frontend/ide/stores/actions/project_spec.js
@@ -53,7 +53,7 @@ describe('IDE store project actions', () => {
});
});
- it('calls the service', done => {
+ it('calls the service', (done) => {
store
.dispatch('refreshLastCommitData', {
projectId: store.state.currentProjectId,
@@ -67,7 +67,7 @@ describe('IDE store project actions', () => {
.catch(done.fail);
});
- it('commits getBranchData', done => {
+ it('commits getBranchData', (done) => {
testAction(
refreshLastCommitData,
{
@@ -94,7 +94,7 @@ describe('IDE store project actions', () => {
});
describe('showBranchNotFoundError', () => {
- it('dispatches setErrorMessage', done => {
+ it('dispatches setErrorMessage', (done) => {
testAction(
showBranchNotFoundError,
'master',
@@ -123,7 +123,7 @@ describe('IDE store project actions', () => {
jest.spyOn(api, 'createBranch').mockResolvedValue();
});
- it('calls API', done => {
+ it('calls API', (done) => {
createNewBranchFromDefault(
{
state: {
@@ -148,7 +148,7 @@ describe('IDE store project actions', () => {
.catch(done.fail);
});
- it('clears error message', done => {
+ it('clears error message', (done) => {
const dispatchSpy = jest.fn().mockName('dispatch');
createNewBranchFromDefault(
@@ -172,7 +172,7 @@ describe('IDE store project actions', () => {
.catch(done.fail);
});
- it('reloads window', done => {
+ it('reloads window', (done) => {
createNewBranchFromDefault(
{
state: {
@@ -196,7 +196,7 @@ describe('IDE store project actions', () => {
});
describe('loadEmptyBranch', () => {
- it('creates a blank tree and sets loading state to false', done => {
+ it('creates a blank tree and sets loading state to false', (done) => {
testAction(
loadEmptyBranch,
{ projectId: TEST_PROJECT_ID, branchId: 'master' },
@@ -213,7 +213,7 @@ describe('IDE store project actions', () => {
);
});
- it('does nothing, if tree already exists', done => {
+ it('does nothing, if tree already exists', (done) => {
const trees = { [`${TEST_PROJECT_ID}/master`]: [] };
testAction(
@@ -279,7 +279,7 @@ describe('IDE store project actions', () => {
const branchId = '123-lorem';
const ref = 'abcd2322';
- it('when empty repo, loads empty branch', done => {
+ it('when empty repo, loads empty branch', (done) => {
const mockGetters = { emptyRepo: true };
testAction(
@@ -292,13 +292,13 @@ describe('IDE store project actions', () => {
);
});
- it('when branch already exists, does nothing', done => {
+ it('when branch already exists, does nothing', (done) => {
store.state.projects[projectId].branches[branchId] = {};
testAction(loadBranch, { projectId, branchId }, store.state, [], [], done);
});
- it('fetches branch data', done => {
+ it('fetches branch data', (done) => {
const mockGetters = { findBranch: () => ({ commit: { id: ref } }) };
jest.spyOn(store, 'dispatch').mockResolvedValue();
@@ -317,7 +317,7 @@ describe('IDE store project actions', () => {
.catch(done.fail);
});
- it('shows an error if branch can not be fetched', done => {
+ it('shows an error if branch can not be fetched', (done) => {
jest.spyOn(store, 'dispatch').mockReturnValue(Promise.reject());
loadBranch(store, { projectId, branchId })
@@ -356,7 +356,7 @@ describe('IDE store project actions', () => {
jest.spyOn(store, 'dispatch').mockResolvedValue();
});
- it('dispatches branch actions', done => {
+ it('dispatches branch actions', (done) => {
openBranch(store, branch)
.then(() => {
expect(store.dispatch.mock.calls).toEqual([
@@ -375,9 +375,9 @@ describe('IDE store project actions', () => {
jest.spyOn(store, 'dispatch').mockReturnValue(Promise.reject());
});
- it('dispatches correct branch actions', done => {
+ it('dispatches correct branch actions', (done) => {
openBranch(store, branch)
- .then(val => {
+ .then((val) => {
expect(store.dispatch.mock.calls).toEqual([
['setCurrentBranchId', branchId],
['loadBranch', { projectId, branchId }],
diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js
index 0eabd982d57..7831df9f3a4 100644
--- a/spec/frontend/ide/stores/actions/tree_spec.js
+++ b/spec/frontend/ide/stores/actions/tree_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import { showTreeEntry, getFiles, setDirectoryData } from '~/ide/stores/actions/tree';
import * as types from '~/ide/stores/mutation_types';
import axios from '~/lib/utils/axios_utils';
@@ -57,26 +57,15 @@ describe('Multi-file store tree actions', () => {
});
it('calls service getFiles', () => {
- return (
- store
- .dispatch('getFiles', basicCallParameters)
- // getFiles actions calls lodash.defer
- .then(() => jest.runOnlyPendingTimers())
- .then(() => {
- expect(service.getFiles).toHaveBeenCalledWith('foo/abcproject', '12345678');
- })
- );
+ return store.dispatch('getFiles', basicCallParameters).then(() => {
+ expect(service.getFiles).toHaveBeenCalledWith('foo/abcproject', '12345678');
+ });
});
- it('adds data into tree', done => {
+ it('adds data into tree', (done) => {
store
.dispatch('getFiles', basicCallParameters)
.then(() => {
- // The populating of the tree is deferred for performance reasons.
- // See this merge request for details: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/25700
- jest.advanceTimersByTime(1);
- })
- .then(() => {
projectTree = store.state.trees['abcproject/master'];
expect(projectTree.tree.length).toBe(2);
@@ -93,7 +82,7 @@ describe('Multi-file store tree actions', () => {
});
describe('error', () => {
- it('dispatches error action', done => {
+ it('dispatches error action', (done) => {
const dispatch = jest.fn();
store.state.projects = {
@@ -148,7 +137,7 @@ describe('Multi-file store tree actions', () => {
store.state.entries[tree.path] = tree;
});
- it('toggles the tree open', done => {
+ it('toggles the tree open', (done) => {
store
.dispatch('toggleTreeOpen', tree.path)
.then(() => {
@@ -174,7 +163,7 @@ describe('Multi-file store tree actions', () => {
Object.assign(store.state.entries, createEntriesFromPaths(paths));
});
- it('opens the parents', done => {
+ it('opens the parents', (done) => {
testAction(
showTreeEntry,
'grandparent/parent/child.txt',
@@ -187,7 +176,7 @@ describe('Multi-file store tree actions', () => {
});
describe('setDirectoryData', () => {
- it('sets tree correctly if there are no opened files yet', done => {
+ it('sets tree correctly if there are no opened files yet', (done) => {
const treeFile = file({ name: 'README.md' });
store.state.trees['abcproject/master'] = {};
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index 04128c27e70..036bc91cd11 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -1,4 +1,5 @@
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 { createRouter } from '~/ide/ide_router';
@@ -20,7 +21,6 @@ import {
import axios from '~/lib/utils/axios_utils';
import * as types from '~/ide/stores/mutation_types';
import { file, createTriggerRenameAction, createTriggerChangeAction } from '../helpers';
-import testAction from '../../helpers/vuex_action_helper';
import eventHub from '~/ide/eventhub';
jest.mock('~/lib/utils/url_utility', () => ({
@@ -42,7 +42,7 @@ describe('Multi-file store actions', () => {
});
describe('redirectToUrl', () => {
- it('calls visitUrl', done => {
+ it('calls visitUrl', (done) => {
store
.dispatch('redirectToUrl', 'test')
.then(() => {
@@ -55,7 +55,7 @@ describe('Multi-file store actions', () => {
});
describe('setInitialData', () => {
- it('commits initial data', done => {
+ it('commits initial data', (done) => {
store
.dispatch('setInitialData', { canCommit: true })
.then(() => {
@@ -70,7 +70,7 @@ describe('Multi-file store actions', () => {
const paths = ['to_discard', 'another_one_to_discard'];
beforeEach(() => {
- paths.forEach(path => {
+ paths.forEach((path) => {
const f = file(path);
f.changed = true;
@@ -81,14 +81,14 @@ describe('Multi-file store actions', () => {
});
it('discards all changes in file', () => {
- const expectedCalls = paths.map(path => ['restoreOriginalFile', path]);
+ const expectedCalls = paths.map((path) => ['restoreOriginalFile', path]);
discardAllChanges(store);
expect(store.dispatch.mock.calls).toEqual(expect.arrayContaining(expectedCalls));
});
- it('removes all files from changedFiles state', done => {
+ it('removes all files from changedFiles state', (done) => {
store
.dispatch('discardAllChanges')
.then(() => {
@@ -120,7 +120,7 @@ describe('Multi-file store actions', () => {
});
describe('tree', () => {
- it('creates temp tree', done => {
+ it('creates temp tree', (done) => {
store
.dispatch('createTempEntry', {
name: 'test',
@@ -137,7 +137,7 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('creates new folder inside another tree', done => {
+ it('creates new folder inside another tree', (done) => {
const tree = {
type: 'tree',
name: 'testing',
@@ -162,7 +162,7 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('does not create new tree if already exists', done => {
+ it('does not create new tree if already exists', (done) => {
const tree = {
type: 'tree',
path: 'testing',
@@ -188,18 +188,20 @@ describe('Multi-file store actions', () => {
});
describe('blob', () => {
- it('creates temp file', done => {
+ it('creates temp file', (done) => {
const name = 'test';
store
.dispatch('createTempEntry', {
name,
type: 'blob',
+ mimeType: 'test/mime',
})
.then(() => {
const f = store.state.entries[name];
expect(f.tempFile).toBeTruthy();
+ expect(f.mimeType).toBe('test/mime');
expect(store.state.trees['abcproject/mybranch'].tree.length).toBe(1);
done();
@@ -207,7 +209,7 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('adds tmp file to open files', done => {
+ it('adds tmp file to open files', (done) => {
const name = 'test';
store
@@ -226,7 +228,7 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('adds tmp file to staged files', done => {
+ it('adds tmp file to staged files', (done) => {
const name = 'test';
store
@@ -248,7 +250,7 @@ describe('Multi-file store actions', () => {
expect(store.dispatch).toHaveBeenCalledWith('setFileActive', 'test');
});
- it('creates flash message if file already exists', done => {
+ it('creates flash message if file already exists', (done) => {
const f = file('test', '1', 'blob');
store.state.trees['abcproject/mybranch'].tree = [f];
store.state.entries[f.path] = f;
@@ -271,7 +273,7 @@ describe('Multi-file store actions', () => {
});
describe('scrollToTab', () => {
- it('focuses the current active element', done => {
+ it('focuses the current active element', (done) => {
document.body.innerHTML +=
'<div id="tabs"><div class="active"><div class="repo-tab"></div></div></div>';
const el = document.querySelector('.repo-tab');
@@ -376,7 +378,7 @@ describe('Multi-file store actions', () => {
});
describe('updateViewer', () => {
- it('updates viewer state', done => {
+ it('updates viewer state', (done) => {
store
.dispatch('updateViewer', 'diff')
.then(() => {
@@ -388,7 +390,7 @@ describe('Multi-file store actions', () => {
});
describe('updateActivityBarView', () => {
- it('commits UPDATE_ACTIVITY_BAR_VIEW', done => {
+ it('commits UPDATE_ACTIVITY_BAR_VIEW', (done) => {
testAction(
updateActivityBarView,
'test',
@@ -401,7 +403,7 @@ describe('Multi-file store actions', () => {
});
describe('setEmptyStateSvgs', () => {
- it('commits setEmptyStateSvgs', done => {
+ it('commits setEmptyStateSvgs', (done) => {
testAction(
setEmptyStateSvgs,
'svg',
@@ -414,7 +416,7 @@ describe('Multi-file store actions', () => {
});
describe('updateTempFlagForEntry', () => {
- it('commits UPDATE_TEMP_FLAG', done => {
+ it('commits UPDATE_TEMP_FLAG', (done) => {
const f = {
...file(),
path: 'test',
@@ -432,7 +434,7 @@ describe('Multi-file store actions', () => {
);
});
- it('commits UPDATE_TEMP_FLAG and dispatches for parent', done => {
+ it('commits UPDATE_TEMP_FLAG and dispatches for parent', (done) => {
const parent = {
...file(),
path: 'testing',
@@ -455,7 +457,7 @@ describe('Multi-file store actions', () => {
);
});
- it('does not dispatch for parent, if parent does not exist', done => {
+ it('does not dispatch for parent, if parent does not exist', (done) => {
const f = {
...file(),
path: 'test',
@@ -475,7 +477,7 @@ describe('Multi-file store actions', () => {
});
describe('setCurrentBranchId', () => {
- it('commits setCurrentBranchId', done => {
+ it('commits setCurrentBranchId', (done) => {
testAction(
setCurrentBranchId,
'branchId',
@@ -488,7 +490,7 @@ describe('Multi-file store actions', () => {
});
describe('toggleFileFinder', () => {
- it('commits TOGGLE_FILE_FINDER', done => {
+ it('commits TOGGLE_FILE_FINDER', (done) => {
testAction(
toggleFileFinder,
true,
@@ -501,7 +503,7 @@ describe('Multi-file store actions', () => {
});
describe('setErrorMessage', () => {
- it('commis error messsage', done => {
+ it('commis error messsage', (done) => {
testAction(
setErrorMessage,
'error',
@@ -514,7 +516,7 @@ describe('Multi-file store actions', () => {
});
describe('deleteEntry', () => {
- it('commits entry deletion', done => {
+ it('commits entry deletion', (done) => {
store.state.entries.path = 'testing';
testAction(
@@ -527,7 +529,7 @@ describe('Multi-file store actions', () => {
);
});
- it('does not delete a folder after it is emptied', done => {
+ it('does not delete a folder after it is emptied', (done) => {
const testFolder = {
type: 'tree',
tree: [],
@@ -573,7 +575,7 @@ describe('Multi-file store actions', () => {
});
describe('and previous does not exist', () => {
- it('reverts the rename before deleting', done => {
+ it('reverts the rename before deleting', (done) => {
testAction(
deleteEntry,
testEntry.path,
@@ -608,7 +610,7 @@ describe('Multi-file store actions', () => {
store.state.entries[oldEntry.path] = oldEntry;
});
- it('does not revert rename before deleting', done => {
+ it('does not revert rename before deleting', (done) => {
testAction(
deleteEntry,
testEntry.path,
@@ -619,7 +621,7 @@ describe('Multi-file store actions', () => {
);
});
- it('when previous is deleted, it reverts rename before deleting', done => {
+ it('when previous is deleted, it reverts rename before deleting', (done) => {
store.state.entries[testEntry.prevPath].deleted = true;
testAction(
@@ -654,7 +656,7 @@ describe('Multi-file store actions', () => {
jest.spyOn(eventHub, '$emit').mockImplementation();
});
- it('does not purge model cache for temporary entries that got renamed', done => {
+ it('does not purge model cache for temporary entries that got renamed', (done) => {
Object.assign(store.state.entries, {
test: {
...file('test'),
@@ -676,7 +678,7 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('purges model cache for renamed entry', done => {
+ it('purges model cache for renamed entry', (done) => {
Object.assign(store.state.entries, {
test: {
...file('test'),
@@ -735,7 +737,7 @@ describe('Multi-file store actions', () => {
]);
});
- it('if not changed, completely unstages and discards entry if renamed to original', done => {
+ it('if not changed, completely unstages and discards entry if renamed to original', (done) => {
testAction(
renameEntry,
{ path: 'renamed', name: 'orig' },
@@ -759,7 +761,7 @@ describe('Multi-file store actions', () => {
);
});
- it('if already in changed, does not add to change', done => {
+ it('if already in changed, does not add to change', (done) => {
store.state.changedFiles.push(renamedEntry);
testAction(
@@ -772,7 +774,7 @@ describe('Multi-file store actions', () => {
);
});
- it('routes to the renamed file if the original file has been opened', done => {
+ it('routes to the renamed file if the original file has been opened', (done) => {
store.state.currentProjectId = 'test/test';
store.state.currentBranchId = 'master';
@@ -813,7 +815,7 @@ describe('Multi-file store actions', () => {
});
});
- it('updates entries in a folder correctly, when folder is renamed', done => {
+ it('updates entries in a folder correctly, when folder is renamed', (done) => {
store
.dispatch('renameEntry', {
path: 'folder',
@@ -831,7 +833,7 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('discards renaming of an entry if the root folder is renamed back to a previous name', done => {
+ it('discards renaming of an entry if the root folder is renamed back to a previous name', (done) => {
const rootFolder = file('old-folder', 'old-folder', 'tree');
const testEntry = file('test', 'test', 'blob', rootFolder);
@@ -923,7 +925,7 @@ describe('Multi-file store actions', () => {
});
});
- it('creates new directory', done => {
+ it('creates new directory', (done) => {
expect(store.state.entries[newParentPath]).toBeUndefined();
store
@@ -953,7 +955,7 @@ describe('Multi-file store actions', () => {
rootDir.tree.push(newDir);
});
- it('inserts in new directory', done => {
+ it('inserts in new directory', (done) => {
expect(newDir.tree).toEqual([]);
store
@@ -969,11 +971,11 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
- it('when new directory is deleted, it undeletes it', done => {
+ it('when new directory is deleted, it undeletes it', (done) => {
store.dispatch('deleteEntry', newParentPath);
expect(store.state.entries[newParentPath].deleted).toBe(true);
- expect(rootDir.tree.some(x => x.path === newParentPath)).toBe(false);
+ expect(rootDir.tree.some((x) => x.path === newParentPath)).toBe(false);
store
.dispatch('renameEntry', {
@@ -983,7 +985,7 @@ describe('Multi-file store actions', () => {
})
.then(() => {
expect(store.state.entries[newParentPath].deleted).toBe(false);
- expect(rootDir.tree.some(x => x.path === newParentPath)).toBe(true);
+ expect(rootDir.tree.some((x) => x.path === newParentPath)).toBe(true);
})
.then(done)
.catch(done.fail);
@@ -1027,12 +1029,12 @@ describe('Multi-file store actions', () => {
document.querySelector('.flash-container').remove();
});
- it('passes the error further unchanged without dispatching any action when response is 404', done => {
+ it('passes the error further unchanged without dispatching any action when response is 404', (done) => {
mock.onGet(/(.*)/).replyOnce(404);
getBranchData(...callParams)
.then(done.fail)
- .catch(e => {
+ .catch((e) => {
expect(dispatch.mock.calls).toHaveLength(0);
expect(e.response.status).toEqual(404);
expect(document.querySelector('.flash-alert')).toBeNull();
@@ -1040,12 +1042,12 @@ describe('Multi-file store actions', () => {
});
});
- it('does not pass the error further and flashes an alert if error is not 404', done => {
+ it('does not pass the error further and flashes an alert if error is not 404', (done) => {
mock.onGet(/(.*)/).replyOnce(418);
getBranchData(...callParams)
.then(done.fail)
- .catch(e => {
+ .catch((e) => {
expect(dispatch.mock.calls).toHaveLength(0);
expect(e.response).toBeUndefined();
expect(document.querySelector('.flash-alert')).not.toBeNull();
diff --git a/spec/frontend/ide/stores/extend_spec.js b/spec/frontend/ide/stores/extend_spec.js
index b0f1063153e..ffb00f9ef5b 100644
--- a/spec/frontend/ide/stores/extend_spec.js
+++ b/spec/frontend/ide/stores/extend_spec.js
@@ -15,7 +15,7 @@ describe('ide/stores/extend', () => {
store = {};
el = {};
- [terminalPlugin, terminalSyncPlugin].forEach(x => {
+ [terminalPlugin, terminalSyncPlugin].forEach((x) => {
const plugin = jest.fn();
x.mockImplementation(() => plugin);
@@ -28,7 +28,7 @@ describe('ide/stores/extend', () => {
terminalSyncPlugin.mockClear();
});
- const withGonFeatures = features => {
+ const withGonFeatures = (features) => {
global.gon = { ...global.gon, features };
};
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index 5ae87f5f9cd..1787f9e9361 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -407,7 +407,7 @@ describe('IDE store getters', () => {
${'canCreateMergeRequests'} | ${'createMergeRequestIn'}
${'canPushCode'} | ${'pushCode'}
`('$getterName', ({ getterName, permissionKey }) => {
- it.each([true, false])('finds permission for current project (%s)', val => {
+ it.each([true, false])('finds permission for current project (%s)', (val) => {
localState.projects[TEST_PROJECT_ID] = {
userPermissions: {
[permissionKey]: val,
diff --git a/spec/frontend/ide/stores/integration_spec.js b/spec/frontend/ide/stores/integration_spec.js
index b6a7c7fd02d..388bd3b99d2 100644
--- a/spec/frontend/ide/stores/integration_spec.js
+++ b/spec/frontend/ide/stores/integration_spec.js
@@ -84,7 +84,7 @@ describe('IDE store integration', () => {
store.dispatch('commit/updateFilesAfterCommit', { data: {} });
expect(store.state.entries[TEST_PATH]).toEqual(expected);
- expect(store.state.entries[TEST_PATH_DIR].tree.find(x => x.path === TEST_PATH)).toEqual(
+ expect(store.state.entries[TEST_PATH_DIR].tree.find((x) => x.path === TEST_PATH)).toEqual(
expected,
);
});
diff --git a/spec/frontend/ide/stores/modules/branches/actions_spec.js b/spec/frontend/ide/stores/modules/branches/actions_spec.js
index 2ab4126cccf..b1c077c4082 100644
--- a/spec/frontend/ide/stores/modules/branches/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/branches/actions_spec.js
@@ -42,7 +42,7 @@ describe('IDE branches actions', () => {
});
describe('requestBranches', () => {
- it('should commit request', done => {
+ it('should commit request', (done) => {
testAction(
requestBranches,
null,
@@ -55,7 +55,7 @@ describe('IDE branches actions', () => {
});
describe('receiveBranchesError', () => {
- it('should commit error', done => {
+ it('should commit error', (done) => {
testAction(
receiveBranchesError,
{ search: TEST_SEARCH },
@@ -78,7 +78,7 @@ describe('IDE branches actions', () => {
});
describe('receiveBranchesSuccess', () => {
- it('should commit received data', done => {
+ it('should commit received data', (done) => {
testAction(
receiveBranchesSuccess,
branches,
@@ -110,7 +110,7 @@ describe('IDE branches actions', () => {
});
});
- it('dispatches success with received data', done => {
+ it('dispatches success with received data', (done) => {
testAction(
fetchBranches,
{ search: TEST_SEARCH },
@@ -131,7 +131,7 @@ describe('IDE branches actions', () => {
mock.onGet(/\/api\/v4\/projects\/\d+\/repository\/branches(.*)$/).replyOnce(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
testAction(
fetchBranches,
{ search: TEST_SEARCH },
@@ -148,7 +148,7 @@ describe('IDE branches actions', () => {
});
describe('resetBranches', () => {
- it('commits reset', done => {
+ it('commits reset', (done) => {
testAction(
resetBranches,
null,
diff --git a/spec/frontend/ide/stores/modules/branches/mutations_spec.js b/spec/frontend/ide/stores/modules/branches/mutations_spec.js
index ed8e05bf299..ddf55479be9 100644
--- a/spec/frontend/ide/stores/modules/branches/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/branches/mutations_spec.js
@@ -28,7 +28,7 @@ describe('IDE branches mutations', () => {
describe('RECEIVE_BRANCHES_SUCCESS', () => {
it('sets branches', () => {
- const expectedBranches = branches.map(branch => ({
+ const expectedBranches = branches.map((branch) => ({
name: branch.name,
committedDate: branch.commit.committed_date,
}));
diff --git a/spec/frontend/ide/stores/modules/clientside/actions_spec.js b/spec/frontend/ide/stores/modules/clientside/actions_spec.js
index a47bc0bd711..05627f8ed0e 100644
--- a/spec/frontend/ide/stores/modules/clientside/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/clientside/actions_spec.js
@@ -25,7 +25,7 @@ describe('IDE store module clientside actions', () => {
});
describe('pingUsage', () => {
- it('posts to usage endpoint', done => {
+ it('posts to usage endpoint', (done) => {
const usageSpy = jest.fn(() => [200]);
mock.onPost(TEST_USAGE_URL).reply(() => usageSpy());
diff --git a/spec/frontend/ide/stores/modules/commit/actions_spec.js b/spec/frontend/ide/stores/modules/commit/actions_spec.js
index cfe2bddf76c..5be0e22a9fc 100644
--- a/spec/frontend/ide/stores/modules/commit/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/actions_spec.js
@@ -1,6 +1,7 @@
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';
@@ -11,7 +12,6 @@ import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
import * as actions from '~/ide/stores/modules/commit/actions';
import { createUnexpectedCommitError } from '~/ide/lib/errors';
import { commitActionTypes, PERMISSION_CREATE_MR } from '~/ide/constants';
-import testAction from '../../../../helpers/vuex_action_helper';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
@@ -19,6 +19,17 @@ jest.mock('~/lib/utils/url_utility', () => ({
}));
const TEST_COMMIT_SHA = '123456789';
+const COMMIT_RESPONSE = {
+ id: '123456',
+ short_id: '123',
+ message: 'test message',
+ committed_date: 'date',
+ parent_ids: [],
+ stats: {
+ additions: '1',
+ deletions: '2',
+ },
+};
describe('IDE commit module actions', () => {
let mock;
@@ -32,7 +43,9 @@ describe('IDE commit module actions', () => {
mock = new MockAdapter(axios);
jest.spyOn(router, 'push').mockImplementation();
- mock.onGet('/api/v1/projects/abcproject/repository/branches/master').reply(200);
+ mock
+ .onGet('/api/v1/projects/abcproject/repository/branches/master')
+ .reply(200, { commit: COMMIT_RESPONSE });
});
afterEach(() => {
@@ -41,7 +54,7 @@ describe('IDE commit module actions', () => {
});
describe('updateCommitMessage', () => {
- it('updates store with new commit message', done => {
+ it('updates store with new commit message', (done) => {
store
.dispatch('commit/updateCommitMessage', 'testing')
.then(() => {
@@ -53,7 +66,7 @@ describe('IDE commit module actions', () => {
});
describe('discardDraft', () => {
- it('resets commit message to blank', done => {
+ it('resets commit message to blank', (done) => {
store.state.commit.commitMessage = 'testing';
store
@@ -67,7 +80,7 @@ describe('IDE commit module actions', () => {
});
describe('updateCommitAction', () => {
- it('updates store with new commit action', done => {
+ it('updates store with new commit action', (done) => {
store
.dispatch('commit/updateCommitAction', '1')
.then(() => {
@@ -123,7 +136,7 @@ describe('IDE commit module actions', () => {
});
});
- it('updates commit message with short_id', done => {
+ it('updates commit message with short_id', (done) => {
store
.dispatch('commit/setLastCommitMessage', { short_id: '123' })
.then(() => {
@@ -135,7 +148,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('updates commit message with stats', done => {
+ it('updates commit message with stats', (done) => {
store
.dispatch('commit/setLastCommitMessage', {
short_id: '123',
@@ -200,12 +213,12 @@ describe('IDE commit module actions', () => {
});
store.state.openFiles = store.state.stagedFiles;
- store.state.stagedFiles.forEach(stagedFile => {
+ store.state.stagedFiles.forEach((stagedFile) => {
store.state.entries[stagedFile.path] = stagedFile;
});
});
- it('updates stores working reference', done => {
+ it('updates stores working reference', (done) => {
store
.dispatch('commit/updateFilesAfterCommit', {
data,
@@ -218,14 +231,14 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('resets all files changed status', done => {
+ it('resets all files changed status', (done) => {
store
.dispatch('commit/updateFilesAfterCommit', {
data,
branch,
})
.then(() => {
- store.state.openFiles.forEach(entry => {
+ store.state.openFiles.forEach((entry) => {
expect(entry.changed).toBeFalsy();
});
})
@@ -233,7 +246,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('sets files commit data', done => {
+ it('sets files commit data', (done) => {
store
.dispatch('commit/updateFilesAfterCommit', {
data,
@@ -246,7 +259,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('updates raw content for changed file', done => {
+ it('updates raw content for changed file', (done) => {
store
.dispatch('commit/updateFilesAfterCommit', {
data,
@@ -259,7 +272,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('emits changed event for file', done => {
+ it('emits changed event for file', (done) => {
store
.dispatch('commit/updateFilesAfterCommit', {
data,
@@ -319,7 +332,7 @@ describe('IDE commit module actions', () => {
store.state.commit.commitAction = '2';
store.state.commit.commitMessage = 'testing 123';
- store.state.openFiles.forEach(localF => {
+ store.state.openFiles.forEach((localF) => {
store.state.entries[localF.path] = localF;
});
});
@@ -329,23 +342,11 @@ describe('IDE commit module actions', () => {
});
describe('success', () => {
- const COMMIT_RESPONSE = {
- id: '123456',
- short_id: '123',
- message: 'test message',
- committed_date: 'date',
- parent_ids: '321',
- stats: {
- additions: '1',
- deletions: '2',
- },
- };
-
beforeEach(() => {
jest.spyOn(service, 'commit').mockResolvedValue({ data: COMMIT_RESPONSE });
});
- it('calls service', done => {
+ it('calls service', (done) => {
store
.dispatch('commit/commitChanges')
.then(() => {
@@ -370,7 +371,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('sends lastCommit ID when not creating new branch', done => {
+ it('sends lastCommit ID when not creating new branch', (done) => {
store.state.commit.commitAction = '1';
store
@@ -397,7 +398,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('sets last Commit Msg', done => {
+ it('sets last Commit Msg', (done) => {
store
.dispatch('commit/commitChanges')
.then(() => {
@@ -410,7 +411,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('adds commit data to files', done => {
+ it('adds commit data to files', (done) => {
store
.dispatch('commit/commitChanges')
.then(() => {
@@ -423,7 +424,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('resets stores commit actions', done => {
+ it('resets stores commit actions', (done) => {
store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
store
@@ -435,7 +436,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('removes all staged files', done => {
+ it('removes all staged files', (done) => {
store
.dispatch('commit/commitChanges')
.then(() => {
@@ -446,7 +447,7 @@ describe('IDE commit module actions', () => {
});
describe('merge request', () => {
- it('redirects to new merge request page', done => {
+ it('redirects to new merge request page', (done) => {
jest.spyOn(eventHub, '$on').mockImplementation();
store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
@@ -456,9 +457,7 @@ describe('IDE commit module actions', () => {
.dispatch('commit/commitChanges')
.then(() => {
expect(visitUrl).toHaveBeenCalledWith(
- `webUrl/-/merge_requests/new?merge_request[source_branch]=${
- store.getters['commit/placeholderBranchName']
- }&merge_request[target_branch]=master&nav_source=webide`,
+ `webUrl/-/merge_requests/new?merge_request[source_branch]=${store.getters['commit/placeholderBranchName']}&merge_request[target_branch]=master&nav_source=webide`,
);
done();
@@ -466,7 +465,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('does not redirect to new merge request page when shouldCreateMR is not checked', done => {
+ 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;
@@ -512,7 +511,7 @@ describe('IDE commit module actions', () => {
});
});
- it('shows failed message', done => {
+ it('shows failed message', (done) => {
store
.dispatch('commit/commitChanges')
.then(() => {
@@ -546,19 +545,7 @@ describe('IDE commit module actions', () => {
});
describe('first commit of a branch', () => {
- const COMMIT_RESPONSE = {
- id: '123456',
- short_id: '123',
- message: 'test message',
- committed_date: 'date',
- parent_ids: [],
- stats: {
- additions: '1',
- deletions: '2',
- },
- };
-
- it('commits TOGGLE_EMPTY_STATE mutation on empty repo', done => {
+ it('commits TOGGLE_EMPTY_STATE mutation on empty repo', (done) => {
jest.spyOn(service, 'commit').mockResolvedValue({ data: COMMIT_RESPONSE });
jest.spyOn(store, 'commit');
@@ -575,7 +562,7 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('does not commmit TOGGLE_EMPTY_STATE mutation on existing project', done => {
+ it('does not commmit TOGGLE_EMPTY_STATE mutation on existing project', (done) => {
COMMIT_RESPONSE.parent_ids.push('1234');
jest.spyOn(service, 'commit').mockResolvedValue({ data: COMMIT_RESPONSE });
jest.spyOn(store, 'commit');
@@ -596,7 +583,7 @@ describe('IDE commit module actions', () => {
});
describe('toggleShouldCreateMR', () => {
- it('commits both toggle and interacting with MR checkbox actions', done => {
+ it('commits both toggle and interacting with MR checkbox actions', (done) => {
testAction(
actions.toggleShouldCreateMR,
{},
diff --git a/spec/frontend/ide/stores/modules/commit/getters_spec.js b/spec/frontend/ide/stores/modules/commit/getters_spec.js
index adbfd7c6835..66ed51dbd13 100644
--- a/spec/frontend/ide/stores/modules/commit/getters_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/getters_spec.js
@@ -103,7 +103,7 @@ describe('IDE commit module getters', () => {
expect(getters.preBuiltCommitMessage(state, null, rootState)).toBe('test commit message');
});
- ['changedFiles', 'stagedFiles'].forEach(key => {
+ ['changedFiles', 'stagedFiles'].forEach((key) => {
it('returns commitMessage with updated file', () => {
rootState[key].push({
path: 'test-file',
diff --git a/spec/frontend/ide/stores/modules/editor/setup_spec.js b/spec/frontend/ide/stores/modules/editor/setup_spec.js
index 71b5d7590c5..659bfb2742f 100644
--- a/spec/frontend/ide/stores/modules/editor/setup_spec.js
+++ b/spec/frontend/ide/stores/modules/editor/setup_spec.js
@@ -1,8 +1,9 @@
+import { cloneDeep } from 'lodash';
import Vuex from 'vuex';
import eventHub from '~/ide/eventhub';
import { createStoreOptions } from '~/ide/stores';
import { setupFileEditorsSync } from '~/ide/stores/modules/editor/setup';
-import { createTriggerRenamePayload } from '../../../helpers';
+import { createTriggerRenamePayload, createTriggerUpdatePayload } from '../../../helpers';
describe('~/ide/stores/modules/editor/setup', () => {
let store;
@@ -33,6 +34,14 @@ describe('~/ide/stores/modules/editor/setup', () => {
});
});
+ it('when files update is emitted, does nothing', () => {
+ const origState = cloneDeep(store.state);
+
+ eventHub.$emit('ide.files.change', createTriggerUpdatePayload('foo'));
+
+ expect(store.state).toEqual(origState);
+ });
+
it('when files rename is emitted, renames fileEditor', () => {
eventHub.$emit('ide.files.change', createTriggerRenamePayload('foo', 'foo_new'));
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 6c1fa163a91..76898e83c7a 100644
--- a/spec/frontend/ide/stores/modules/file_templates/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/file_templates/actions_spec.js
@@ -20,7 +20,7 @@ describe('IDE file templates actions', () => {
});
describe('requestTemplateTypes', () => {
- it('commits REQUEST_TEMPLATE_TYPES', done => {
+ it('commits REQUEST_TEMPLATE_TYPES', (done) => {
testAction(
actions.requestTemplateTypes,
null,
@@ -33,7 +33,7 @@ describe('IDE file templates actions', () => {
});
describe('receiveTemplateTypesError', () => {
- it('commits RECEIVE_TEMPLATE_TYPES_ERROR and dispatches setErrorMessage', done => {
+ it('commits RECEIVE_TEMPLATE_TYPES_ERROR and dispatches setErrorMessage', (done) => {
testAction(
actions.receiveTemplateTypesError,
null,
@@ -55,7 +55,7 @@ describe('IDE file templates actions', () => {
});
describe('receiveTemplateTypesSuccess', () => {
- it('commits RECEIVE_TEMPLATE_TYPES_SUCCESS', done => {
+ it('commits RECEIVE_TEMPLATE_TYPES_SUCCESS', (done) => {
testAction(
actions.receiveTemplateTypesSuccess,
'test',
@@ -81,7 +81,7 @@ describe('IDE file templates actions', () => {
});
});
- it('rejects if selectedTemplateType is empty', done => {
+ it('rejects if selectedTemplateType is empty', (done) => {
const dispatch = jest.fn().mockName('dispatch');
actions
@@ -94,7 +94,7 @@ describe('IDE file templates actions', () => {
});
});
- it('dispatches actions', done => {
+ it('dispatches actions', (done) => {
state.selectedTemplateType = { key: 'licenses' };
testAction(
@@ -121,7 +121,7 @@ describe('IDE file templates actions', () => {
mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(500);
});
- it('dispatches actions', done => {
+ it('dispatches actions', (done) => {
state.selectedTemplateType = { key: 'licenses' };
testAction(
@@ -184,7 +184,7 @@ describe('IDE file templates actions', () => {
});
describe('receiveTemplateError', () => {
- it('dispatches setErrorMessage', done => {
+ it('dispatches setErrorMessage', (done) => {
testAction(
actions.receiveTemplateError,
'test',
@@ -217,7 +217,7 @@ describe('IDE file templates actions', () => {
.replyOnce(200, { content: 'testing content' });
});
- it('dispatches setFileTemplate if template already has content', done => {
+ it('dispatches setFileTemplate if template already has content', (done) => {
const template = { content: 'already has content' };
testAction(
@@ -230,7 +230,7 @@ describe('IDE file templates actions', () => {
);
});
- it('dispatches success', done => {
+ it('dispatches success', (done) => {
const template = { key: 'mit' };
state.selectedTemplateType = { key: 'licenses' };
@@ -245,7 +245,7 @@ describe('IDE file templates actions', () => {
);
});
- it('dispatches success and uses name key for API call', done => {
+ it('dispatches success and uses name key for API call', (done) => {
const template = { name: 'testing' };
state.selectedTemplateType = { key: 'licenses' };
@@ -266,7 +266,7 @@ describe('IDE file templates actions', () => {
mock.onGet(/api\/(.*)\/templates\/licenses\/mit/).replyOnce(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
const template = { name: 'testing' };
state.selectedTemplateType = { key: 'licenses' };
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 ec472ab418f..6594d65f558 100644
--- a/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js
@@ -1,4 +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';
@@ -10,7 +11,6 @@ import {
resetMergeRequests,
} from '~/ide/stores/modules/merge_requests/actions';
import { mergeRequests } from '../../../mock_data';
-import testAction from '../../../../helpers/vuex_action_helper';
describe('IDE merge requests actions', () => {
let mockedState;
@@ -28,7 +28,7 @@ describe('IDE merge requests actions', () => {
});
describe('requestMergeRequests', () => {
- it('should commit request', done => {
+ it('should commit request', (done) => {
testAction(
requestMergeRequests,
null,
@@ -41,7 +41,7 @@ describe('IDE merge requests actions', () => {
});
describe('receiveMergeRequestsError', () => {
- it('should commit error', done => {
+ it('should commit error', (done) => {
testAction(
receiveMergeRequestsError,
{ type: 'created', search: '' },
@@ -64,7 +64,7 @@ describe('IDE merge requests actions', () => {
});
describe('receiveMergeRequestsSuccess', () => {
- it('should commit received data', done => {
+ it('should commit received data', (done) => {
testAction(
receiveMergeRequestsSuccess,
mergeRequests,
@@ -118,7 +118,7 @@ describe('IDE merge requests actions', () => {
});
});
- it('dispatches success with received data', done => {
+ it('dispatches success with received data', (done) => {
testAction(
fetchMergeRequests,
{ type: 'created' },
@@ -156,7 +156,7 @@ describe('IDE merge requests actions', () => {
);
});
- it('dispatches success with received data', done => {
+ it('dispatches success with received data', (done) => {
testAction(
fetchMergeRequests,
{ type: null },
@@ -177,7 +177,7 @@ describe('IDE merge requests actions', () => {
mock.onGet(/\/api\/v4\/merge_requests(.*)$/).replyOnce(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
testAction(
fetchMergeRequests,
{ type: 'created', search: '' },
@@ -195,7 +195,7 @@ describe('IDE merge requests actions', () => {
});
describe('resetMergeRequests', () => {
- it('commits reset', done => {
+ it('commits reset', (done) => {
testAction(
resetMergeRequests,
null,
diff --git a/spec/frontend/ide/stores/modules/pane/actions_spec.js b/spec/frontend/ide/stores/modules/pane/actions_spec.js
index 8c56714e0ed..42fe8b400b8 100644
--- a/spec/frontend/ide/stores/modules/pane/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/pane/actions_spec.js
@@ -7,18 +7,18 @@ describe('IDE pane module actions', () => {
const TEST_VIEW_KEEP_ALIVE = { name: 'test-keep-alive', keepAlive: true };
describe('toggleOpen', () => {
- it('dispatches open if closed', done => {
+ it('dispatches open if closed', (done) => {
testAction(actions.toggleOpen, TEST_VIEW, { isOpen: false }, [], [{ type: 'open' }], done);
});
- it('dispatches close if opened', done => {
+ it('dispatches close if opened', (done) => {
testAction(actions.toggleOpen, TEST_VIEW, { isOpen: true }, [], [{ type: 'close' }], done);
});
});
describe('open', () => {
describe('with a view specified', () => {
- it('commits SET_OPEN and SET_CURRENT_VIEW', done => {
+ it('commits SET_OPEN and SET_CURRENT_VIEW', (done) => {
testAction(
actions.open,
TEST_VIEW,
@@ -32,7 +32,7 @@ describe('IDE pane module actions', () => {
);
});
- it('commits KEEP_ALIVE_VIEW if keepAlive is true', done => {
+ it('commits KEEP_ALIVE_VIEW if keepAlive is true', (done) => {
testAction(
actions.open,
TEST_VIEW_KEEP_ALIVE,
@@ -49,7 +49,7 @@ describe('IDE pane module actions', () => {
});
describe('without a view specified', () => {
- it('commits SET_OPEN', done => {
+ it('commits SET_OPEN', (done) => {
testAction(
actions.open,
undefined,
@@ -63,7 +63,7 @@ describe('IDE pane module actions', () => {
});
describe('close', () => {
- it('commits SET_OPEN', done => {
+ it('commits SET_OPEN', (done) => {
testAction(actions.close, null, {}, [{ type: types.SET_OPEN, payload: false }], [], done);
});
});
diff --git a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
index 8511843cc92..b7ed257e954 100644
--- a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
@@ -1,6 +1,7 @@
import Visibility from 'visibilityjs';
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 {
requestLatestPipeline,
@@ -24,7 +25,6 @@ import {
import state from '~/ide/stores/modules/pipelines/state';
import * as types from '~/ide/stores/modules/pipelines/mutation_types';
import { rightSidebarViews } from '~/ide/constants';
-import testAction from '../../../../helpers/vuex_action_helper';
import { pipelines, jobs } from '../../../mock_data';
describe('IDE pipelines actions', () => {
@@ -44,7 +44,7 @@ describe('IDE pipelines actions', () => {
});
describe('requestLatestPipeline', () => {
- it('commits request', done => {
+ it('commits request', (done) => {
testAction(
requestLatestPipeline,
null,
@@ -57,7 +57,7 @@ describe('IDE pipelines actions', () => {
});
describe('receiveLatestPipelineError', () => {
- it('commits error', done => {
+ it('commits error', (done) => {
testAction(
receiveLatestPipelineError,
{ status: 404 },
@@ -68,7 +68,7 @@ describe('IDE pipelines actions', () => {
);
});
- it('dispatches setErrorMessage is not 404', done => {
+ it('dispatches setErrorMessage is not 404', (done) => {
testAction(
receiveLatestPipelineError,
{ status: 500 },
@@ -123,7 +123,7 @@ describe('IDE pipelines actions', () => {
.reply(200, { data: { foo: 'bar' } }, { 'poll-interval': '10000' });
});
- it('dispatches request', done => {
+ it('dispatches request', (done) => {
jest.spyOn(axios, 'get');
jest.spyOn(Visibility, 'hidden').mockReturnValue(false);
@@ -139,7 +139,7 @@ describe('IDE pipelines actions', () => {
jest.advanceTimersByTime(1000);
- new Promise(resolve => requestAnimationFrame(resolve))
+ new Promise((resolve) => requestAnimationFrame(resolve))
.then(() => {
expect(axios.get).toHaveBeenCalled();
expect(axios.get).toHaveBeenCalledTimes(1);
@@ -150,7 +150,7 @@ describe('IDE pipelines actions', () => {
jest.advanceTimersByTime(10000);
})
- .then(() => new Promise(resolve => requestAnimationFrame(resolve)))
+ .then(() => new Promise((resolve) => requestAnimationFrame(resolve)))
.then(() => {
expect(axios.get).toHaveBeenCalled();
expect(axios.get).toHaveBeenCalledTimes(2);
@@ -169,7 +169,7 @@ describe('IDE pipelines actions', () => {
mock.onGet('/abc/def/commit/abc123def456ghi789jkl/pipelines').reply(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
const dispatch = jest.fn().mockName('dispatch');
const rootGetters = {
lastCommit: { id: 'abc123def456ghi789jkl' },
@@ -180,7 +180,7 @@ describe('IDE pipelines actions', () => {
jest.advanceTimersByTime(1500);
- new Promise(resolve => requestAnimationFrame(resolve))
+ new Promise((resolve) => requestAnimationFrame(resolve))
.then(() => {
expect(dispatch).toHaveBeenCalledWith('receiveLatestPipelineError', expect.anything());
})
@@ -191,13 +191,13 @@ describe('IDE pipelines actions', () => {
});
describe('requestJobs', () => {
- it('commits request', done => {
+ it('commits request', (done) => {
testAction(requestJobs, 1, mockedState, [{ type: types.REQUEST_JOBS, payload: 1 }], [], done);
});
});
describe('receiveJobsError', () => {
- it('commits error', done => {
+ it('commits error', (done) => {
testAction(
receiveJobsError,
{ id: 1 },
@@ -220,7 +220,7 @@ describe('IDE pipelines actions', () => {
});
describe('receiveJobsSuccess', () => {
- it('commits data', done => {
+ it('commits data', (done) => {
testAction(
receiveJobsSuccess,
{ id: 1, data: jobs },
@@ -240,7 +240,7 @@ describe('IDE pipelines actions', () => {
mock.onGet(stage.dropdownPath).replyOnce(200, jobs);
});
- it('dispatches request', done => {
+ it('dispatches request', (done) => {
testAction(
fetchJobs,
stage,
@@ -260,7 +260,7 @@ describe('IDE pipelines actions', () => {
mock.onGet(stage.dropdownPath).replyOnce(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
testAction(
fetchJobs,
stage,
@@ -277,7 +277,7 @@ describe('IDE pipelines actions', () => {
});
describe('toggleStageCollapsed', () => {
- it('commits collapse', done => {
+ it('commits collapse', (done) => {
testAction(
toggleStageCollapsed,
1,
@@ -290,7 +290,7 @@ describe('IDE pipelines actions', () => {
});
describe('setDetailJob', () => {
- it('commits job', done => {
+ it('commits job', (done) => {
testAction(
setDetailJob,
'job',
@@ -301,7 +301,7 @@ describe('IDE pipelines actions', () => {
);
});
- it('dispatches rightPane/open as pipeline when job is null', done => {
+ it('dispatches rightPane/open as pipeline when job is null', (done) => {
testAction(
setDetailJob,
null,
@@ -312,7 +312,7 @@ describe('IDE pipelines actions', () => {
);
});
- it('dispatches rightPane/open as job', done => {
+ it('dispatches rightPane/open as job', (done) => {
testAction(
setDetailJob,
'job',
@@ -325,13 +325,13 @@ describe('IDE pipelines actions', () => {
});
describe('requestJobLogs', () => {
- it('commits request', done => {
+ it('commits request', (done) => {
testAction(requestJobLogs, null, mockedState, [{ type: types.REQUEST_JOB_LOGS }], [], done);
});
});
describe('receiveJobLogsError', () => {
- it('commits error', done => {
+ it('commits error', (done) => {
testAction(
receiveJobLogsError,
null,
@@ -354,7 +354,7 @@ describe('IDE pipelines actions', () => {
});
describe('receiveJobLogsSuccess', () => {
- it('commits data', done => {
+ it('commits data', (done) => {
testAction(
receiveJobLogsSuccess,
'data',
@@ -377,7 +377,7 @@ describe('IDE pipelines actions', () => {
mock.onGet(`${TEST_HOST}/project/builds/trace`).replyOnce(200, { html: 'html' });
});
- it('dispatches request', done => {
+ it('dispatches request', (done) => {
testAction(
fetchJobLogs,
null,
@@ -408,7 +408,7 @@ describe('IDE pipelines actions', () => {
mock.onGet(`${TEST_HOST}/project/builds/trace`).replyOnce(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
testAction(
fetchJobLogs,
null,
@@ -422,7 +422,7 @@ describe('IDE pipelines actions', () => {
});
describe('resetLatestPipeline', () => {
- it('commits reset mutations', done => {
+ it('commits reset mutations', (done) => {
testAction(
resetLatestPipeline,
null,
diff --git a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
index 7d2f5d5d710..d820bf0291e 100644
--- a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
@@ -137,7 +137,7 @@ describe('IDE pipelines mutations', () => {
mutations[types.RECEIVE_JOBS_SUCCESS](mockedState, { id: mockedState.stages[0].id, data });
expect(mockedState.stages[0].jobs.length).toBe(jobs.length);
expect(mockedState.stages[0].jobs).toEqual(
- jobs.map(job => ({
+ jobs.map((job) => ({
id: job.id,
name: job.name,
status: job.status,
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 242b1579be7..05935f1db38 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
@@ -102,7 +102,7 @@ describe('IDE store terminal check actions', () => {
);
});
- [httpStatus.FORBIDDEN, httpStatus.NOT_FOUND].forEach(status => {
+ [httpStatus.FORBIDDEN, httpStatus.NOT_FOUND].forEach((status) => {
it(`hides tab, when status is ${status}`, () => {
const payload = { response: { 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 d0ac2af3ffd..dd51786745f 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
@@ -281,7 +281,7 @@ describe('IDE store terminal session controls actions', () => {
);
});
- [httpStatus.NOT_FOUND, httpStatus.UNPROCESSABLE_ENTITY].forEach(status => {
+ [httpStatus.NOT_FOUND, httpStatus.UNPROCESSABLE_ENTITY].forEach((status) => {
it(`dispatches request and startSession on ${status}`, () => {
mock
.onPost(state.session.retryPath, { branch: rootState.currentBranchId, format: 'json' })
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 e25746e1dd1..0e123dce798 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
@@ -98,7 +98,7 @@ describe('IDE store terminal session controls actions', () => {
);
});
- [STOPPING, STOPPED, 'unexpected'].forEach(status => {
+ [STOPPING, STOPPED, 'unexpected'].forEach((status) => {
it(`kills session if status is ${status}`, () => {
return testAction(
actions.receiveSessionStatusSuccess,
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 3fa57bde415..2ae7e8a8727 100644
--- a/spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js
@@ -22,7 +22,7 @@ describe('ide/stores/modules/terminal_sync/actions', () => {
});
describe('upload', () => {
- it('uploads to mirror and sets success', done => {
+ it('uploads to mirror and sets success', (done) => {
mirror.upload.mockReturnValue(Promise.resolve());
testAction(
@@ -38,7 +38,7 @@ describe('ide/stores/modules/terminal_sync/actions', () => {
);
});
- it('sets error when failed', done => {
+ it('sets error when failed', (done) => {
const err = { message: 'it failed!' };
mirror.upload.mockReturnValue(Promise.reject(err));
@@ -54,7 +54,7 @@ describe('ide/stores/modules/terminal_sync/actions', () => {
});
describe('stop', () => {
- it('disconnects from mirror', done => {
+ it('disconnects from mirror', (done) => {
testAction(actions.stop, null, rootState, [{ type: types.STOP }], [], () => {
expect(mirror.disconnect).toHaveBeenCalled();
done();
@@ -83,7 +83,7 @@ describe('ide/stores/modules/terminal_sync/actions', () => {
};
});
- it('connects to mirror and sets success', done => {
+ it('connects to mirror and sets success', (done) => {
mirror.connect.mockReturnValue(Promise.resolve());
testAction(
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index fd39cf21635..9bbdac0ae25 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -128,7 +128,7 @@ describe('IDE store file mutations', () => {
localState.changedFiles[0],
localState.openFiles[0],
localFile,
- ].forEach(f => {
+ ].forEach((f) => {
expect(f).toEqual(
expect.objectContaining({
path,
@@ -142,7 +142,7 @@ describe('IDE store file mutations', () => {
});
describe('SET_FILE_RAW_DATA', () => {
- const callMutationForFile = f => {
+ const callMutationForFile = (f) => {
mutations.SET_FILE_RAW_DATA(localState, {
file: f,
raw: 'testing',
diff --git a/spec/frontend/ide/stores/plugins/terminal_sync_spec.js b/spec/frontend/ide/stores/plugins/terminal_sync_spec.js
index 2aa3e770e7d..0e5f4184679 100644
--- a/spec/frontend/ide/stores/plugins/terminal_sync_spec.js
+++ b/spec/frontend/ide/stores/plugins/terminal_sync_spec.js
@@ -4,6 +4,7 @@ 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');
@@ -51,6 +52,14 @@ describe('IDE stores/plugins/mirror', () => {
expect(store.dispatch).toHaveBeenCalledWith(ACTION_UPLOAD);
});
+ it('does nothing when ide.files.change is emitted with "update"', () => {
+ eventHub.$emit(FILES_CHANGE_EVENT, createTriggerUpdatePayload('foo'));
+
+ jest.runAllTimers();
+
+ expect(store.dispatch).not.toHaveBeenCalledWith(ACTION_UPLOAD);
+ });
+
describe('when session stops', () => {
beforeEach(() => {
store.commit(`terminal/${SET_SESSION_STATUS}`, STOPPING);
diff --git a/spec/frontend/ide/sync_router_and_store_spec.js b/spec/frontend/ide/sync_router_and_store_spec.js
index 20fd77c4dfb..ac0f6aefb69 100644
--- a/spec/frontend/ide/sync_router_and_store_spec.js
+++ b/spec/frontend/ide/sync_router_and_store_spec.js
@@ -17,7 +17,7 @@ describe('~/ide/sync_router_and_store', () => {
const getRouterCurrentPath = () => router.currentRoute.fullPath;
const getStoreCurrentPath = () => store.state.router.fullPath;
- const updateRouter = async path => {
+ const updateRouter = async (path) => {
if (getRouterCurrentPath() === path) {
return;
}
@@ -25,7 +25,7 @@ describe('~/ide/sync_router_and_store', () => {
router.push(path);
await waitForPromises();
};
- const updateStore = path => {
+ const updateStore = (path) => {
store.dispatch('router/push', path);
return waitForPromises();
};
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index 3b772c0b259..f467d174eeb 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -263,7 +263,7 @@ describe('WebIDE utils', () => {
it('reads a file and returns its output as a data url', () => {
const file = new File(['foo'], 'foo.png', { type: 'image/png' });
- return readFileAsDataURL(file).then(contents => {
+ return readFileAsDataURL(file).then((contents) => {
expect(contents).toBe('data:image/png;base64,Zm9v');
});
});
diff --git a/spec/frontend/image_diff/helpers/comment_indicator_helper_spec.js b/spec/frontend/image_diff/helpers/comment_indicator_helper_spec.js
index 98c05d648b8..6548f9959c5 100644
--- a/spec/frontend/image_diff/helpers/comment_indicator_helper_spec.js
+++ b/spec/frontend/image_diff/helpers/comment_indicator_helper_spec.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import * as commentIndicatorHelper from '~/image_diff/helpers/comment_indicator_helper';
import * as mockData from '../mock_data';
diff --git a/spec/frontend/image_diff/helpers/utils_helper_spec.js b/spec/frontend/image_diff/helpers/utils_helper_spec.js
index 7f2376826c2..29bebaf6905 100644
--- a/spec/frontend/image_diff/helpers/utils_helper_spec.js
+++ b/spec/frontend/image_diff/helpers/utils_helper_spec.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import * as utilsHelper from '~/image_diff/helpers/utils_helper';
import ImageBadge from '~/image_diff/image_badge';
import * as mockData from '../mock_data';
diff --git a/spec/frontend/image_diff/image_diff_spec.js b/spec/frontend/image_diff/image_diff_spec.js
index d89e4312344..e14f8dc774f 100644
--- a/spec/frontend/image_diff/image_diff_spec.js
+++ b/spec/frontend/image_diff/image_diff_spec.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import ImageDiff from '~/image_diff/image_diff';
import * as imageUtility from '~/lib/utils/image_utility';
import imageDiffHelper from '~/image_diff/helpers/index';
diff --git a/spec/frontend/image_diff/init_discussion_tab_spec.js b/spec/frontend/image_diff/init_discussion_tab_spec.js
index f459fdf5a08..f96d00230ee 100644
--- a/spec/frontend/image_diff/init_discussion_tab_spec.js
+++ b/spec/frontend/image_diff/init_discussion_tab_spec.js
@@ -11,7 +11,7 @@ describe('initDiscussionTab', () => {
`);
});
- it('should pass canCreateNote as false to initImageDiff', done => {
+ it('should pass canCreateNote as false to initImageDiff', (done) => {
jest
.spyOn(initImageDiffHelper, 'initImageDiff')
.mockImplementation((diffFileEl, canCreateNote) => {
@@ -22,7 +22,7 @@ describe('initDiscussionTab', () => {
initDiscussionTab();
});
- it('should pass renderCommentBadge as true to initImageDiff', done => {
+ it('should pass renderCommentBadge as true to initImageDiff', (done) => {
jest
.spyOn(initImageDiffHelper, 'initImageDiff')
.mockImplementation((diffFileEl, canCreateNote, renderCommentBadge) => {
diff --git a/spec/frontend/image_diff/replaced_image_diff_spec.js b/spec/frontend/image_diff/replaced_image_diff_spec.js
index 10827d76e55..16be4b82ad7 100644
--- a/spec/frontend/image_diff/replaced_image_diff_spec.js
+++ b/spec/frontend/image_diff/replaced_image_diff_spec.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import ReplacedImageDiff from '~/image_diff/replaced_image_diff';
import ImageDiff from '~/image_diff/image_diff';
import { viewTypes } from '~/image_diff/view_types';
@@ -176,8 +176,8 @@ describe('ReplacedImageDiff', () => {
expect(ImageDiff.prototype.bindEvents).toHaveBeenCalled();
});
- it('should register click eventlistener to 2-up view mode', done => {
- jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation(viewMode => {
+ it('should register click eventlistener to 2-up view mode', (done) => {
+ jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation((viewMode) => {
expect(viewMode).toEqual(viewTypes.TWO_UP);
done();
});
@@ -186,8 +186,8 @@ describe('ReplacedImageDiff', () => {
replacedImageDiff.viewModesEls[viewTypes.TWO_UP].click();
});
- it('should register click eventlistener to swipe view mode', done => {
- jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation(viewMode => {
+ it('should register click eventlistener to swipe view mode', (done) => {
+ jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation((viewMode) => {
expect(viewMode).toEqual(viewTypes.SWIPE);
done();
});
@@ -196,8 +196,8 @@ describe('ReplacedImageDiff', () => {
replacedImageDiff.viewModesEls[viewTypes.SWIPE].click();
});
- it('should register click eventlistener to onion skin view mode', done => {
- jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation(viewMode => {
+ it('should register click eventlistener to onion skin view mode', (done) => {
+ jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation((viewMode) => {
expect(viewMode).toEqual(viewTypes.SWIPE);
done();
});
@@ -325,7 +325,7 @@ describe('ReplacedImageDiff', () => {
setupImageFrameEls();
});
- it('should pass showCommentIndicator normalized indicator values', done => {
+ it('should pass showCommentIndicator normalized indicator values', (done) => {
jest.spyOn(imageDiffHelper, 'showCommentIndicator').mockImplementation(() => {});
jest
.spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement')
@@ -339,7 +339,7 @@ describe('ReplacedImageDiff', () => {
replacedImageDiff.renderNewView(indicator);
});
- it('should call showCommentIndicator', done => {
+ it('should call showCommentIndicator', (done) => {
const normalized = {
normalized: true,
};
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 d88a31a0e47..ac8b73aeb49 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
@@ -5,7 +5,7 @@ import ImportTableRow from '~/import_entities/import_groups/components/import_ta
import { STATUSES } from '~/import_entities/constants';
import { availableNamespacesFixture } from '../graphql/fixtures';
-const getFakeGroup = status => ({
+const getFakeGroup = (status) => ({
web_url: 'https://fake.host/',
full_path: 'fake_group_1',
full_name: 'fake_name_1',
@@ -22,13 +22,13 @@ describe('import table row', () => {
let group;
const findByText = (cmp, text) => {
- return wrapper.findAll(cmp).wrappers.find(node => node.text().indexOf(text) === 0);
+ return wrapper.findAll(cmp).wrappers.find((node) => node.text().indexOf(text) === 0);
};
const findImportButton = () => findByText(GlButton, 'Import');
const findNameInput = () => wrapper.find(GlFormInput);
const findNamespaceDropdown = () => wrapper.find(Select2Select);
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(ImportTableRow, {
propsData: {
availableNamespaces: availableNamespacesFixture,
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 0ca721cd951..cd184bb65cc 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
@@ -2,7 +2,7 @@ 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 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue';
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';
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 cacbe358a62..514ed411138 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
@@ -63,7 +63,7 @@ describe('Bulk import resolvers', () => {
});
it('mirrors REST endpoint response fields', () => {
- const extractRelevantFields = obj => ({ id: obj.id, full_path: obj.full_path });
+ const extractRelevantFields = (obj) => ({ id: obj.id, full_path: obj.full_path });
expect(results.map(extractRelevantFields)).toStrictEqual(
availableNamespacesFixture.map(extractRelevantFields),
@@ -89,20 +89,20 @@ describe('Bulk import resolvers', () => {
expect(
results.every((r, idx) =>
MIRRORED_FIELDS.every(
- field => r[field] === statusEndpointFixture.importable_data[idx][field],
+ (field) => r[field] === statusEndpointFixture.importable_data[idx][field],
),
),
).toBe(true);
});
it('populates each result instance with status field default to none', () => {
- expect(results.every(r => r.status === STATUSES.NONE)).toBe(true);
+ 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,
+ (r) => r.import_target.target_namespace === availableNamespacesFixture[0].full_path,
),
).toBe(true);
});
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 8eb1ffb3cd0..e7f1626f81d 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
@@ -23,7 +23,7 @@ describe('Bulk import status poller', () => {
let clientMock;
const listQueryCacheCalls = () =>
- clientMock.readQuery.mock.calls.filter(call => call[0].query === bulkImportSourceGroupsQuery);
+ clientMock.readQuery.mock.calls.filter((call) => call[0].query === bulkImportSourceGroupsQuery);
beforeEach(() => {
clientMock = createMockClient({
@@ -142,9 +142,11 @@ describe('Bulk import status poller', () => {
clientMock.cache.writeQuery({
query: bulkImportSourceGroupsQuery,
data: {
- bulkImportSourceGroups: [STARTED_GROUP_1, NOT_STARTED_GROUP, STARTED_GROUP_2].map(group =>
- generateFakeEntry(group),
- ),
+ bulkImportSourceGroups: [
+ STARTED_GROUP_1,
+ NOT_STARTED_GROUP,
+ STARTED_GROUP_2,
+ ].map((group) => generateFakeEntry(group)),
},
});
@@ -155,9 +157,9 @@ describe('Bulk import status poller', () => {
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.every((field) => field.name.value === 'group')).toBeTruthy();
expect(selections).toHaveLength(2);
- expect(selections.map(sel => sel.arguments[0].value.value)).toStrictEqual([
+ 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}`,
]);
@@ -167,7 +169,7 @@ describe('Bulk import status poller', () => {
clientMock.cache.writeQuery({
query: bulkImportSourceGroupsQuery,
data: {
- bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map(group =>
+ bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map((group) =>
generateFakeEntry(group),
),
},
@@ -189,7 +191,7 @@ describe('Bulk import status poller', () => {
clientMock.cache.writeQuery({
query: bulkImportSourceGroupsQuery,
data: {
- bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map(group =>
+ bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map((group) =>
generateFakeEntry(group),
),
},
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 b4ac11b4404..27f642d15c8 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
@@ -27,7 +27,7 @@ describe('ImportProjectsTable', () => {
const findImportAllButton = () =>
wrapper
.findAll(GlButton)
- .filter(w => w.props().variant === 'success')
+ .filter((w) => w.props().variant === 'success')
.at(0);
const findImportAllModal = () => wrapper.find({ ref: 'importAllModal' });
@@ -112,7 +112,7 @@ describe('ImportProjectsTable', () => {
expect(
wrapper
.findAll('th')
- .filter(w => w.text() === `From ${providerTitle}`)
+ .filter((w) => w.text() === `From ${providerTitle}`)
.exists(),
).toBe(true);
@@ -142,6 +142,29 @@ describe('ImportProjectsTable', () => {
},
);
+ it.each`
+ importingRepoCount | buttonMessage
+ ${1} | ${'Importing 1 repository'}
+ ${5} | ${'Importing 5 repositories'}
+ `(
+ 'sets the button text to "$buttonMessage" when importing repos',
+ ({ importingRepoCount, buttonMessage }) => {
+ createComponent({
+ state: {
+ providerRepos: [providerRepo],
+ },
+ getters: {
+ hasIncompatibleRepos: () => false,
+ importAllCount: () => 10,
+ isImportingAnyRepo: () => true,
+ importingRepoCount: () => importingRepoCount,
+ },
+ });
+
+ expect(findImportAllButton().text()).toBe(buttonMessage);
+ },
+ );
+
it('renders an empty state if there are no repositories available', () => {
createComponent({ state: { repositories: [] } });
@@ -168,7 +191,7 @@ describe('ImportProjectsTable', () => {
});
it('shows loading spinner when import is in progress', () => {
- createComponent({ getters: { isImportingAnyRepo: () => true } });
+ createComponent({ getters: { isImportingAnyRepo: () => true, importallCount: () => 1 } });
expect(findImportAllButton().props().loading).toBe(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 aa003226050..2ed11ae277e 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
@@ -34,7 +34,7 @@ describe('ProviderRepoTableRow', () => {
}
const findImportButton = () => {
- const buttons = wrapper.findAll('button').filter(node => node.text() === 'Import');
+ const buttons = wrapper.findAll('button').filter((node) => node.text() === 'Import');
return buttons.length ? buttons.at(0) : buttons;
};
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 5d4e73a17a3..bd731dc3929 100644
--- a/spec/frontend/import_entities/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/actions_spec.js
@@ -123,7 +123,7 @@ describe('import_projects store actions', () => {
it('includes page in url query params', async () => {
let requestedUrl;
- mock.onGet().reply(config => {
+ mock.onGet().reply((config) => {
requestedUrl = config.url;
return [200, payload];
});
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 6329a84ff6e..8212776742c 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -158,17 +158,11 @@ describe('Incidents List', () => {
describe('Assignees', () => {
it('shows Unassigned when there are no assignees', () => {
- expect(
- findAssignees()
- .at(0)
- .text(),
- ).toBe(I18N.unassigned);
+ expect(findAssignees().at(0).text()).toBe(I18N.unassigned);
});
it('renders an avatar component when there is an assignee', () => {
- const avatar = findAssignees()
- .at(1)
- .find(GlAvatar);
+ const avatar = findAssignees().at(1).find(GlAvatar);
const { src, label } = avatar.attributes();
const { name, avatarUrl } = mockIncidents[1].assignees.nodes[0];
@@ -189,9 +183,7 @@ describe('Incidents List', () => {
});
it('contains a link to the incident details page', async () => {
- findTableRows()
- .at(0)
- .trigger('click');
+ findTableRows().at(0).trigger('click');
expect(visitUrl).toHaveBeenCalledWith(
joinPaths(`/project/issues/incident`, mockIncidents[0].iid),
);
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
index c3fd4a9bab2..82d7f691efd 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
@@ -50,6 +50,7 @@ exports[`Alert integration settings form default state should match the default
category="primary"
data-qa-selector="incident_templates_dropdown"
headertext=""
+ hideheaderborder="true"
id="alert-integration-settings-issue-template"
size="medium"
text="selecte_tmpl"
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
index f0eb54c1b3a..79ad5ad1bb9 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
@@ -52,6 +52,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
</gl-button-stub>
<gl-modal-stub
+ dismisslabel="Close"
modalclass=""
modalid="resetWebhookModal"
ok-title="Reset webhook URL"
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 11b9eda2585..c80d9ad2e5b 100644
--- a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
+++ b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
@@ -39,19 +39,12 @@ describe('IncidentsSettingTabs', () => {
});
it('should render the tab for each active integration', () => {
- const activeTabs = wrapper.vm.$options.tabs.filter(tab => tab.active);
+ const activeTabs = wrapper.vm.$options.tabs.filter((tab) => tab.active);
expect(findIntegrationTabs().length).toBe(activeTabs.length);
activeTabs.forEach((tab, index) => {
+ expect(findIntegrationTabs().at(index).attributes('title')).toBe(tab.title);
expect(
- findIntegrationTabs()
- .at(index)
- .attributes('title'),
- ).toBe(tab.title);
- expect(
- findIntegrationTabs()
- .at(index)
- .find(`[data-testid="${tab.component}-tab"]`)
- .exists(),
+ findIntegrationTabs().at(index).find(`[data-testid="${tab.component}-tab"]`).exists(),
).toBe(true);
});
});
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index 53234419f5f..ecd03103992 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -37,153 +37,142 @@ describe('DynamicField', () => {
const findGlFormTextarea = () => wrapper.find(GlFormTextarea);
describe('template', () => {
- describe.each([[true, 'disabled', 'readonly'], [false, undefined, undefined]])(
- 'dynamic field, when isInheriting = `%p`',
- (isInheriting, disabled, readonly) => {
- describe('type is checkbox', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'checkbox',
- },
- isInheriting,
- );
- });
-
- it(`renders GlFormCheckbox, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
- expect(findGlFormCheckbox().exists()).toBe(true);
- expect(
- findGlFormCheckbox()
- .find('[type=checkbox]')
- .attributes('disabled'),
- ).toBe(disabled);
- });
+ describe.each([
+ [true, 'disabled', 'readonly'],
+ [false, undefined, undefined],
+ ])('dynamic field, when isInheriting = `%p`', (isInheriting, disabled, readonly) => {
+ describe('type is checkbox', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'checkbox',
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
- expect(findGlFormInput().exists()).toBe(false);
- });
+ it(`renders GlFormCheckbox, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
+ expect(findGlFormCheckbox().exists()).toBe(true);
+ expect(findGlFormCheckbox().find('[type=checkbox]').attributes('disabled')).toBe(
+ disabled,
+ );
});
- describe('type is select', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'select',
- choices: [['all', 'All details'], ['standard', 'Standard']],
- },
- isInheriting,
- );
- });
+ it('does not render other types of input', () => {
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ expect(findGlFormInput().exists()).toBe(false);
+ });
+ });
- it(`renders GlFormSelect, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
- expect(findGlFormSelect().exists()).toBe(true);
- expect(findGlFormSelect().findAll('option')).toHaveLength(2);
- expect(
- findGlFormSelect()
- .find('select')
- .attributes('disabled'),
- ).toBe(disabled);
- });
+ describe('type is select', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'select',
+ choices: [
+ ['all', 'All details'],
+ ['standard', 'Standard'],
+ ],
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
- expect(findGlFormInput().exists()).toBe(false);
- });
+ it(`renders GlFormSelect, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
+ expect(findGlFormSelect().exists()).toBe(true);
+ expect(findGlFormSelect().findAll('option')).toHaveLength(2);
+ expect(findGlFormSelect().find('select').attributes('disabled')).toBe(disabled);
});
- describe('type is textarea', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'textarea',
- },
- isInheriting,
- );
- });
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ expect(findGlFormInput().exists()).toBe(false);
+ });
+ });
- it(`renders GlFormTextarea, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
- expect(findGlFormTextarea().exists()).toBe(true);
- expect(
- findGlFormTextarea()
- .find('textarea')
- .attributes('readonly'),
- ).toBe(readonly);
- });
+ describe('type is textarea', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'textarea',
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormInput().exists()).toBe(false);
- });
+ it(`renders GlFormTextarea, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
+ expect(findGlFormTextarea().exists()).toBe(true);
+ expect(findGlFormTextarea().find('textarea').attributes('readonly')).toBe(readonly);
});
- describe('type is password', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'password',
- },
- isInheriting,
- );
- });
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormInput().exists()).toBe(false);
+ });
+ });
- it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
- expect(findGlFormInput().exists()).toBe(true);
- expect(findGlFormInput().attributes('type')).toBe('password');
- expect(findGlFormInput().attributes('readonly')).toBe(readonly);
- });
+ describe('type is password', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'password',
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
- });
+ it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
+ expect(findGlFormInput().exists()).toBe(true);
+ expect(findGlFormInput().attributes('type')).toBe('password');
+ expect(findGlFormInput().attributes('readonly')).toBe(readonly);
});
- describe('type is text', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'text',
- required: true,
- },
- isInheriting,
- );
- });
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ });
+ });
- it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
- expect(findGlFormInput().exists()).toBe(true);
- expect(findGlFormInput().attributes()).toMatchObject({
+ describe('type is text', () => {
+ beforeEach(() => {
+ createComponent(
+ {
type: 'text',
- id: 'service_project_url',
- name: 'service[project_url]',
- placeholder: defaultProps.placeholder,
- required: 'required',
- });
- expect(findGlFormInput().attributes('readonly')).toBe(readonly);
- });
+ required: true,
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
+ it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
+ expect(findGlFormInput().exists()).toBe(true);
+ expect(findGlFormInput().attributes()).toMatchObject({
+ type: 'text',
+ id: 'service_project_url',
+ name: 'service[project_url]',
+ placeholder: defaultProps.placeholder,
+ required: 'required',
});
+ expect(findGlFormInput().attributes('readonly')).toBe(readonly);
});
- },
- );
+
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ });
+ });
+ });
describe('help text', () => {
it('renders description with help text', () => {
createComponent();
- expect(
- findGlFormGroup()
- .find('small')
- .text(),
- ).toBe(defaultProps.help);
+ expect(findGlFormGroup().find('small').text()).toBe(defaultProps.help);
});
it('renders description with help text as HTML', () => {
@@ -193,11 +182,7 @@ describe('DynamicField', () => {
help: helpHTML,
});
- expect(
- findGlFormGroup()
- .find('small')
- .html(),
- ).toContain(helpHTML);
+ expect(findGlFormGroup().find('small').html()).toContain(helpHTML);
});
});
@@ -205,11 +190,7 @@ describe('DynamicField', () => {
it('renders label with title', () => {
createComponent();
- expect(
- findGlFormGroup()
- .find('label')
- .text(),
- ).toBe(defaultProps.title);
+ expect(findGlFormGroup().find('label').text()).toBe(defaultProps.title);
});
describe('for password field with some value (hidden by backend)', () => {
@@ -219,11 +200,7 @@ describe('DynamicField', () => {
value: 'true',
});
- expect(
- findGlFormGroup()
- .find('label')
- .text(),
- ).toBe(`Enter new ${defaultProps.title}`);
+ expect(findGlFormGroup().find('label').text()).toBe(`Enter new ${defaultProps.title}`);
});
});
});
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 a727bb9c734..eaeed2703d1 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -12,7 +12,7 @@ describe('JiraIssuesFields', () => {
editProjectPath: '/edit',
};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = mount(JiraIssuesFields, {
propsData: { ...defaultProps, ...props },
});
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 782930eb6a2..a69e8d6e163 100644
--- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
@@ -57,9 +57,7 @@ describe('JiraTriggerFields', () => {
// browsers don't include unchecked boxes in form submissions.
it('includes comment settings as false even if unchecked', () => {
expect(
- findCommentSettings()
- .find('input[name="service[comment_on_event_enabled]"]')
- .exists(),
+ findCommentSettings().find('input[name="service[comment_on_event_enabled]"]').exists(),
).toBe(true);
});
@@ -106,11 +104,11 @@ describe('JiraTriggerFields', () => {
true,
);
- wrapper.findAll('[type=checkbox]').wrappers.forEach(checkbox => {
+ wrapper.findAll('[type=checkbox]').wrappers.forEach((checkbox) => {
expect(checkbox.attributes('disabled')).toBe('disabled');
});
- wrapper.findAll('[type=radio]').wrappers.forEach(radio => {
+ wrapper.findAll('[type=radio]').wrappers.forEach((radio) => {
expect(radio.attributes('disabled')).toBe('disabled');
});
});
diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
index df12c70f9f5..3fa1e5b5f5a 100644
--- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
@@ -29,7 +29,7 @@ describe('TriggerFields', () => {
const findAllGlFormCheckboxes = () => wrapper.findAll(GlFormCheckbox);
const findAllGlFormInputs = () => wrapper.findAll(GlFormInput);
- describe.each([true, false])('template, isInheriting = `%p`', isInheriting => {
+ describe.each([true, false])('template, isInheriting = `%p`', (isInheriting) => {
it('renders a label with text "Trigger"', () => {
createComponent();
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 1d0adb3ab4c..1140c2a9475 100644
--- a/spec/frontend/invite_member/components/invite_member_modal_spec.js
+++ b/spec/frontend/invite_member/components/invite_member_modal_spec.js
@@ -1,18 +1,22 @@
import { shallowMount } from '@vue/test-utils';
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlModal } from '@gitlab/ui';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
+import { stubComponent } from 'helpers/stub_component';
import InviteMemberModal from '~/invite_member/components/invite_member_modal.vue';
const memberPath = 'member_path';
+const GlEmoji = { template: '<img />' };
const createComponent = () => {
return shallowMount(InviteMemberModal, {
provide: {
membersPath: memberPath,
},
stubs: {
- 'gl-emoji': '<img/>',
- 'gl-modal': '<div><slot name="modal-title"></slot><slot></slot></div>',
+ GlEmoji,
+ GlModal: stubComponent(GlModal, {
+ template: '<div><slot name="modal-title"></slot><slot></slot></div>',
+ }),
},
});
};
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 4ac2a28105c..fc039bdf6da 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,7 @@
import { shallowMount } from '@vue/test-utils';
-import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink, GlModal } from '@gitlab/ui';
+import { stubComponent } from 'helpers/stub_component';
+import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
@@ -10,6 +12,15 @@ const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, O
const defaultAccessLevel = '10';
const helpLink = 'https://example.com';
+const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
+const user2 = { id: 2, name: 'Name Two', username: 'one_2', avatar_url: '' };
+const user3 = {
+ id: 'user-defined-token',
+ name: 'email@example.com',
+ username: 'one_2',
+ avatar_url: '',
+};
+
const createComponent = (data = {}) => {
return shallowMount(InviteMembersModal, {
propsData: {
@@ -24,9 +35,12 @@ const createComponent = (data = {}) => {
return data;
},
stubs: {
- 'gl-modal': '<div><slot name="modal-footer"></slot><slot></slot></div>',
- 'gl-dropdown': true,
- 'gl-dropdown-item': true,
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ GlDropdown: true,
+ GlDropdownItem: true,
GlSprintf,
},
});
@@ -46,6 +60,7 @@ describe('InviteMembersModal', () => {
const findLink = () => wrapper.find(GlLink);
const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
const findInviteButton = () => wrapper.find({ ref: 'inviteButton' });
+ const clickInviteButton = () => findInviteButton().vm.$emit('click');
describe('rendering the modal', () => {
beforeEach(() => {
@@ -53,7 +68,7 @@ describe('InviteMembersModal', () => {
});
it('renders the modal with the correct title', () => {
- expect(wrapper.attributes('title')).toBe('Invite team members');
+ expect(wrapper.find(GlModal).props('title')).toBe('Invite team members');
});
it('renders the Cancel button text correctly', () => {
@@ -88,78 +103,184 @@ describe('InviteMembersModal', () => {
});
describe('submitting the invite form', () => {
- const postData = {
- user_id: '1',
- access_level: '10',
- expires_at: new Date(),
- format: 'json',
- };
+ const apiErrorMessage = 'Member already exists';
+
+ describe('when inviting an existing user to group by user ID', () => {
+ const postData = {
+ user_id: '1',
+ access_level: '10',
+ expires_at: undefined,
+ format: 'json',
+ };
+
+ describe('when invites are sent successfully', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user1] });
- describe('when the invite was sent successfully', () => {
- beforeEach(() => {
- wrapper = createComponent();
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
+ jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
- wrapper.vm.$toast = { show: jest.fn() };
- jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
+ clickInviteButton();
+ });
- wrapper.vm.submitForm(postData);
+ it('calls Api addGroupMembersByUserId with the correct params', () => {
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, postData);
+ });
+
+ it('displays the successful toastMessage', () => {
+ expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ });
});
- it('displays the successful toastMessage', () => {
- const toastMessageSuccessful = 'Members were successfully added';
+ describe('when the invite received an api error message', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user1] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'addGroupMembersByUserId')
+ .mockRejectedValue({ response: { data: { message: apiErrorMessage } } });
+ jest.spyOn(wrapper.vm, 'showToastMessageError');
+
+ clickInviteButton();
+ });
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
- toastMessageSuccessful,
- wrapper.vm.toastOptions,
- );
+ it('displays the apiErrorMessage in the toastMessage', async () => {
+ await waitForPromises();
+
+ expect(wrapper.vm.showToastMessageError).toHaveBeenCalledWith({
+ response: { data: { message: apiErrorMessage } },
+ });
+ });
});
- it('calls Api inviteGroupMember with the correct params', () => {
- expect(Api.inviteGroupMember).toHaveBeenCalledWith(id, postData);
+ describe('when any invite failed for any other reason', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user1, user2] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'addGroupMembersByUserId')
+ .mockRejectedValue({ response: { data: { success: false } } });
+ jest.spyOn(wrapper.vm, 'showToastMessageError');
+
+ clickInviteButton();
+ });
+
+ it('displays the generic error toastMessage', async () => {
+ await waitForPromises();
+
+ expect(wrapper.vm.showToastMessageError).toHaveBeenCalled();
+ });
});
});
- describe('when sending the invite for a single member returned an api error', () => {
- const apiErrorMessage = 'Members already exists';
+ describe('when inviting a new user by email address', () => {
+ const postData = {
+ access_level: '10',
+ expires_at: undefined,
+ email: 'email@example.com',
+ format: 'json',
+ };
+
+ describe('when invites are sent successfully', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user3] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
+ jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
- beforeEach(() => {
- wrapper = createComponent({ newUsersToInvite: '123' });
+ clickInviteButton();
+ });
- wrapper.vm.$toast = { show: jest.fn() };
- jest
- .spyOn(Api, 'inviteGroupMember')
- .mockRejectedValue({ response: { data: { message: apiErrorMessage } } });
+ it('calls Api inviteGroupMembersByEmail with the correct params', () => {
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, postData);
+ });
- findInviteButton().vm.$emit('click');
+ it('displays the successful toastMessage', () => {
+ expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ });
});
- it('displays the api error message for the toastMessage', () => {
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
- apiErrorMessage,
- wrapper.vm.toastOptions,
- );
+ describe('when any invite failed for any reason', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user1, user2] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'addGroupMembersByUserId')
+ .mockRejectedValue({ response: { data: { success: false } } });
+ jest.spyOn(wrapper.vm, 'showToastMessageError');
+
+ clickInviteButton();
+ });
+
+ it('displays the generic error toastMessage', async () => {
+ await waitForPromises();
+
+ expect(wrapper.vm.showToastMessageError).toHaveBeenCalled();
+ });
});
});
- describe('when sending the invite for multiple members returned any error', () => {
- const genericErrorMessage = 'Some of the members could not be added';
+ describe('when inviting members and non-members in same click', () => {
+ const postData = {
+ access_level: '10',
+ expires_at: undefined,
+ format: 'json',
+ };
+
+ const emailPostData = { ...postData, email: 'email@example.com' };
+ const idPostData = { ...postData, user_id: '1' };
+
+ describe('when invites are sent successfully', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user1, user3] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
+ jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
+ jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
- beforeEach(() => {
- wrapper = createComponent({ newUsersToInvite: '123' });
+ clickInviteButton();
+ });
- wrapper.vm.$toast = { show: jest.fn() };
- jest
- .spyOn(Api, 'inviteGroupMember')
- .mockRejectedValue({ response: { data: { success: false } } });
+ it('calls Api inviteGroupMembersByEmail with the correct params', () => {
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, emailPostData);
+ });
- findInviteButton().vm.$emit('click');
+ it('calls Api addGroupMembersByUserId with the correct params', () => {
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, idPostData);
+ });
+
+ it('displays the successful toastMessage', () => {
+ expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ });
});
- it('displays the expected toastMessage', () => {
- expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
- genericErrorMessage,
- wrapper.vm.toastOptions,
- );
+ describe('when any invite failed for any reason', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user1, user3] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+
+ jest
+ .spyOn(Api, 'inviteGroupMembersByEmail')
+ .mockRejectedValue({ response: { data: { success: false } } });
+
+ jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
+ jest.spyOn(wrapper.vm, 'showToastMessageError');
+
+ clickInviteButton();
+ });
+
+ it('displays the generic error toastMessage', async () => {
+ await waitForPromises();
+
+ expect(wrapper.vm.showToastMessageError).toHaveBeenCalled();
+ });
});
});
});
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 106a2df783d..ff123a13ce7 100644
--- a/spec/frontend/invite_members/components/members_token_select_spec.js
+++ b/spec/frontend/invite_members/components/members_token_select_spec.js
@@ -3,13 +3,13 @@ import { nextTick } from 'vue';
import { GlTokenSelector } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import { stubComponent } from 'helpers/stub_component';
-import Api from '~/api';
+import * as UserApi from '~/api/user_api';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
const label = 'testgroup';
const placeholder = 'Search for a member';
-const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
-const user2 = { id: 2, name: 'Name Two', username: 'two_2', avatar_url: '' };
+const user1 = { id: 1, name: 'John Smith', username: 'one_1', avatar_url: '' };
+const user2 = { id: 2, name: 'Jane Doe', username: 'two_2', avatar_url: '' };
const allUsers = [user1, user2];
const createComponent = () => {
@@ -28,7 +28,7 @@ describe('MembersTokenSelect', () => {
let wrapper;
beforeEach(() => {
- jest.spyOn(Api, 'users').mockResolvedValue({ data: allUsers });
+ jest.spyOn(UserApi, 'getUsers').mockResolvedValue({ data: allUsers });
wrapper = createComponent();
});
@@ -57,7 +57,7 @@ describe('MembersTokenSelect', () => {
await waitForPromises();
- expect(Api.users).not.toHaveBeenCalled();
+ expect(UserApi.getUsers).not.toHaveBeenCalled();
});
});
@@ -77,27 +77,42 @@ describe('MembersTokenSelect', () => {
});
describe('when text input is typed in', () => {
+ let tokenSelector;
+
+ beforeEach(() => {
+ tokenSelector = findTokenSelector();
+ });
+
it('calls the API with search parameter', async () => {
const searchParam = 'One';
- const tokenSelector = findTokenSelector();
tokenSelector.vm.$emit('text-input', searchParam);
await waitForPromises();
- expect(Api.users).toHaveBeenCalledWith(searchParam, wrapper.vm.$options.queryOptions);
+ expect(UserApi.getUsers).toHaveBeenCalledWith(
+ searchParam,
+ wrapper.vm.$options.queryOptions,
+ );
expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
});
+
+ describe('when input text is an email', () => {
+ it('allows user defined tokens', async () => {
+ tokenSelector.vm.$emit('text-input', 'foo@bar.com');
+
+ await nextTick();
+
+ expect(tokenSelector.props('allowUserDefinedTokens')).toBe(true);
+ });
+ });
});
describe('when user is selected', () => {
it('emits `input` event with selected users', () => {
- findTokenSelector().vm.$emit('input', [
- { id: 1, name: 'John Smith' },
- { id: 2, name: 'Jane Doe' },
- ]);
+ findTokenSelector().vm.$emit('input', [user1, user2]);
- expect(wrapper.emitted().input[0][0]).toBe('1,2');
+ expect(wrapper.emitted().input[0][0]).toEqual([user1, user2]);
});
});
});
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 17a195df494..de2671816d8 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
@@ -22,13 +22,14 @@ const issuable2 = {
const pathIdSeparator = PathIdSeparator.Issue;
-const findFormInput = wrapper => wrapper.find('.js-add-issuable-form-input').element;
+const findFormInput = (wrapper) => wrapper.find('.js-add-issuable-form-input').element;
-const findRadioInput = (inputs, value) => inputs.filter(input => input.element.value === value)[0];
+const findRadioInput = (inputs, value) =>
+ inputs.filter((input) => input.element.value === value)[0];
-const findRadioInputs = wrapper => wrapper.findAll('[name="linked-issue-type-radio"]');
+const findRadioInputs = (wrapper) => wrapper.findAll('[name="linked-issue-type-radio"]');
-const constructWrapper = props => {
+const constructWrapper = (props) => {
return shallowMount(AddIssuableForm, {
propsData: {
inputValue: '',
@@ -192,7 +193,7 @@ describe('AddIssuableForm', () => {
});
describe('when the form is submitted', () => {
- it('emits an event with a "relates_to" link type when the "relates to" radio input selected', done => {
+ it('emits an event with a "relates_to" link type when the "relates to" radio input selected', (done) => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.RELATES_TO;
@@ -207,7 +208,7 @@ describe('AddIssuableForm', () => {
});
});
- it('emits an event with a "blocks" link type when the "blocks" radio input selected', done => {
+ it('emits an event with a "blocks" link type when the "blocks" radio input selected', (done) => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.BLOCKS;
@@ -222,7 +223,7 @@ describe('AddIssuableForm', () => {
});
});
- it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', done => {
+ it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', (done) => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.IS_BLOCKED_BY;
@@ -237,7 +238,7 @@ describe('AddIssuableForm', () => {
});
});
- it('shows error message when error is present', done => {
+ it('shows error message when error is present', (done) => {
const itemAddFailureMessage = 'Something went wrong while submitting.';
wrapper.setProps({
hasError: true,
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 dd05f49b458..c0889b09adc 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
@@ -130,11 +130,8 @@ describe('RelatedIssuesBlock', () => {
describe('showCategorizedIssues prop', () => {
const issueList = () => wrapper.findAll('.js-related-issues-token-list-item');
const categorizedHeadings = () => wrapper.findAll('h4');
- const headingTextAt = index =>
- categorizedHeadings()
- .at(index)
- .text();
- const mountComponent = showCategorizedIssues => {
+ const headingTextAt = (index) => categorizedHeadings().at(index).text();
+ const mountComponent = (showCategorizedIssues) => {
wrapper = mount(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
index 39bc244297b..ffd9683cd6b 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
@@ -182,12 +182,7 @@ describe('RelatedIssuesList', () => {
});
it('shows due date', () => {
- expect(
- wrapper
- .find(IssueDueDate)
- .find('.board-card-info-text')
- .text(),
- ).toBe('Nov 22, 2010');
+ expect(wrapper.find(IssueDueDate).find('.board-card-info-text').text()).toBe('Nov 22, 2010');
});
});
});
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 2c02e1e1de4..93fe321957c 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
@@ -315,9 +315,7 @@ describe('RelatedIssuesRoot', () => {
const input = 23;
wrapper.vm.onInput({
- untouchedRawReferences: String(input)
- .trim()
- .split(/\s/),
+ untouchedRawReferences: String(input).trim().split(/\s/),
touchedReference: input,
});
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
index 3a9a0d3fd59..3c01bf2d319 100644
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -252,12 +252,9 @@ describe('IssuableItem', () => {
await wrapper.vm.$nextTick();
- expect(
- wrapper
- .find('[data-testid="issuable-title"]')
- .find(GlLink)
- .attributes('target'),
- ).toBe('_blank');
+ expect(wrapper.find('[data-testid="issuable-title"]').find(GlLink).attributes('target')).toBe(
+ '_blank',
+ );
});
it('renders issuable reference', () => {
diff --git a/spec/frontend/issuable_show/components/issuable_body_spec.js b/spec/frontend/issuable_show/components/issuable_body_spec.js
index 5708eaf4a31..4ffbbad4f37 100644
--- a/spec/frontend/issuable_show/components/issuable_body_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_body_spec.js
@@ -98,10 +98,7 @@ describe('IssuableBody', () => {
it('renders issuable edit info', () => {
const editedEl = wrapper.find('small');
- const sanitizedText = editedEl
- .text()
- .replace(/\n/g, ' ')
- .replace(/\s+/g, ' ');
+ const sanitizedText = editedEl.text().replace(/\n/g, ' ').replace(/\s+/g, ' ');
expect(sanitizedText).toContain('Edited');
expect(sanitizedText).toContain('ago');
@@ -138,7 +135,7 @@ describe('IssuableBody', () => {
it.each(['keydown-title', 'keydown-description'])(
'component emits `%s` event with event object and issuableMeta params via issuable-edit-form',
- async eventName => {
+ async (eventName) => {
const eventObj = {
preventDefault: jest.fn(),
stopPropagation: jest.fn(),
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 a865bdb5608..522374f2e9c 100644
--- a/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
@@ -28,7 +28,7 @@ const createComponent = ({ propsData = issuableEditFormProps } = {}) =>
describe('IssuableEditForm', () => {
let wrapper;
- const assertEvent = eventSpy => {
+ const assertEvent = (eventSpy) => {
expect(eventSpy).toHaveBeenNthCalledWith(1, 'update.issuable', expect.any(Function));
expect(eventSpy).toHaveBeenNthCalledWith(2, 'close.form', expect.any(Function));
};
diff --git a/spec/frontend/issuable_show/components/issuable_header_spec.js b/spec/frontend/issuable_show/components/issuable_header_spec.js
index fad8ec8a891..f9c20ab04b8 100644
--- a/spec/frontend/issuable_show/components/issuable_header_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_header_spec.js
@@ -24,7 +24,7 @@ const createComponent = (propsData = issuableHeaderProps) =>
describe('IssuableHeader', () => {
let wrapper;
- const findByTestId = testId => wrapper.find(`[data-testid="${testId}"]`);
+ const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
beforeEach(() => {
wrapper = createComponent();
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 ca0aefc1083..6cebfc150f9 100644
--- a/spec/frontend/issuable_show/components/issuable_show_root_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_show_root_spec.js
@@ -121,7 +121,7 @@ describe('IssuableShowRoot', () => {
it.each(['keydown-title', 'keydown-description'])(
'component emits `%s` event with event object and issuableMeta params via issuable-body',
- eventName => {
+ (eventName) => {
const eventObj = {
preventDefault: jest.fn(),
stopPropagation: jest.fn(),
diff --git a/spec/frontend/issuable_spec.js b/spec/frontend/issuable_spec.js
index 63c1fda2fb4..6712b8bfd34 100644
--- a/spec/frontend/issuable_spec.js
+++ b/spec/frontend/issuable_spec.js
@@ -49,7 +49,7 @@ describe('Issuable', () => {
mock.restore();
});
- it('should send request to reset email token', done => {
+ it('should send request to reset email token', (done) => {
jest.spyOn(axios, 'put');
document.querySelector('.incoming-email-token-reset').click();
diff --git a/spec/frontend/issuable_suggestions/components/app_spec.js b/spec/frontend/issuable_suggestions/components/app_spec.js
index 0cb5b9c90ba..fb8ef00567c 100644
--- a/spec/frontend/issuable_suggestions/components/app_spec.js
+++ b/spec/frontend/issuable_suggestions/components/app_spec.js
@@ -85,12 +85,7 @@ describe('Issuable suggestions app component', () => {
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
- expect(
- wrapper
- .findAll('li')
- .at(0)
- .classes(),
- ).toContain('gl-mb-3');
+ expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
});
});
@@ -98,12 +93,7 @@ describe('Issuable suggestions app component', () => {
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
- expect(
- wrapper
- .findAll('li')
- .at(1)
- .classes(),
- ).not.toContain('gl-mb-3');
+ expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
});
});
});
diff --git a/spec/frontend/issuable_suggestions/components/item_spec.js b/spec/frontend/issuable_suggestions/components/item_spec.js
index 9912e77d5fe..d0dde256edd 100644
--- a/spec/frontend/issuable_suggestions/components/item_spec.js
+++ b/spec/frontend/issuable_suggestions/components/item_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlTooltip, GlLink, GlIcon } from '@gitlab/ui';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+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 mockData from '../mock_data';
diff --git a/spec/frontend/issuable_suggestions/mock_data.js b/spec/frontend/issuable_suggestions/mock_data.js
index 4ce35ad5196..74b569d9833 100644
--- a/spec/frontend/issuable_suggestions/mock_data.js
+++ b/spec/frontend/issuable_suggestions/mock_data.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
function getDate(daysMinus) {
const today = new Date();
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index dde4e8458d5..ec2055ca7d1 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -47,6 +47,7 @@ describe('Issuable output', () => {
provide: {
fullPath: 'gitlab-org/incidents',
iid: '19',
+ uploadMetricsFeatureAvailable: false,
},
stubs: {
HighlightBar: true,
@@ -398,8 +399,8 @@ describe('Issuable output', () => {
wrapper.vm.poll.makeRequest();
- return new Promise(resolve => {
- wrapper.vm.$watch('formState.lockedWarningVisible', value => {
+ return new Promise((resolve) => {
+ wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
if (value) {
resolve();
}
@@ -507,13 +508,6 @@ describe('Issuable output', () => {
expect(wrapper.vm.issueChanged).toBe(false);
});
- it('returns false when `initialTitleText` is null and `formState.title` is empty string', () => {
- wrapper.vm.store.formState.title = '';
- wrapper.setProps({ initialTitleText: null });
-
- expect(wrapper.vm.issueChanged).toBe(false);
- });
-
it('returns true when description is changed', () => {
wrapper.vm.store.formState.description = 'RandomText';
diff --git a/spec/frontend/issue_show/components/description_spec.js b/spec/frontend/issue_show/components/description_spec.js
index bc7511225a0..de53d98e6be 100644
--- a/spec/frontend/issue_show/components/description_spec.js
+++ b/spec/frontend/issue_show/components/description_spec.js
@@ -74,7 +74,7 @@ describe('Description component', () => {
let modal;
const recaptchaChild = vm.$children.find(
// eslint-disable-next-line no-underscore-dangle
- child => child.$options._componentTag === 'recaptcha-modal',
+ (child) => child.$options._componentTag === 'recaptcha-modal',
);
recaptchaChild.scriptSrc = '//scriptsrc';
diff --git a/spec/frontend/issue_show/components/edit_actions_spec.js b/spec/frontend/issue_show/components/edit_actions_spec.js
index 79a2bcd5eab..6a00eec4b1f 100644
--- a/spec/frontend/issue_show/components/edit_actions_spec.js
+++ b/spec/frontend/issue_show/components/edit_actions_spec.js
@@ -6,7 +6,7 @@ import Store from '~/issue_show/stores';
describe('Edit Actions components', () => {
let vm;
- beforeEach(done => {
+ beforeEach((done) => {
const Component = Vue.extend(editActions);
const store = new Store({
titleHtml: '',
@@ -34,7 +34,7 @@ describe('Edit Actions components', () => {
expect(vm.$el.querySelectorAll('[disabled]').length).toBe(0);
});
- it('does not render delete button if canUpdate is false', done => {
+ it('does not render delete button if canUpdate is false', (done) => {
vm.canDestroy = false;
Vue.nextTick(() => {
@@ -44,7 +44,7 @@ describe('Edit Actions components', () => {
});
});
- it('disables submit button when title is blank', done => {
+ it('disables submit button when title is blank', (done) => {
vm.formState.title = '';
Vue.nextTick(() => {
@@ -54,7 +54,7 @@ describe('Edit Actions components', () => {
});
});
- it('should not show delete button if showDeleteButton is false', done => {
+ it('should not show delete button if showDeleteButton is false', (done) => {
vm.showDeleteButton = false;
Vue.nextTick(() => {
@@ -70,7 +70,7 @@ describe('Edit Actions components', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
- it('disabled button after clicking save button', done => {
+ it('disabled button after clicking save button', (done) => {
vm.$el.querySelector('.btn-success').click();
Vue.nextTick(() => {
@@ -97,7 +97,7 @@ describe('Edit Actions components', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable', { destroy_confirm: true });
});
- it('does no actions when confirm is false', done => {
+ it('does no actions when confirm is false', (done) => {
jest.spyOn(window, 'confirm').mockReturnValue(false);
vm.$el.querySelector('.btn-danger').click();
diff --git a/spec/frontend/issue_show/components/fields/description_spec.js b/spec/frontend/issue_show/components/fields/description_spec.js
index 8ea326ad1ee..96c81c419d0 100644
--- a/spec/frontend/issue_show/components/fields/description_spec.js
+++ b/spec/frontend/issue_show/components/fields/description_spec.js
@@ -8,7 +8,7 @@ describe('Description field component', () => {
let vm;
let store;
- beforeEach(done => {
+ beforeEach((done) => {
const Component = Vue.extend(descriptionField);
const el = document.createElement('div');
store = new Store({
@@ -38,7 +38,7 @@ describe('Description field component', () => {
expect(vm.$el.querySelector('.md-area textarea').value).toBe('test');
});
- it('renders markdown field with a markdown description', done => {
+ it('renders markdown field with a markdown description', (done) => {
store.formState.description = '**test**';
Vue.nextTick(() => {
diff --git a/spec/frontend/issue_show/components/form_spec.js b/spec/frontend/issue_show/components/form_spec.js
index b06a3a89d3b..4e123f606f6 100644
--- a/spec/frontend/issue_show/components/form_spec.js
+++ b/spec/frontend/issue_show/components/form_spec.js
@@ -26,7 +26,7 @@ describe('Inline edit form component', () => {
vm.$destroy();
});
- const createComponent = props => {
+ const createComponent = (props) => {
const Component = Vue.extend(formComponent);
vm = mountComponent(Component, {
diff --git a/spec/frontend/issue_show/components/header_actions_spec.js b/spec/frontend/issue_show/components/header_actions_spec.js
index b9836ae7240..4df62ec8717 100644
--- a/spec/frontend/issue_show/components/header_actions_spec.js
+++ b/spec/frontend/issue_show/components/header_actions_spec.js
@@ -62,7 +62,7 @@ describe('HeaderActions component', () => {
const findToggleIssueStateButton = () => wrapper.find(GlButton);
- const findDropdownAt = index => wrapper.findAll(GlDropdown).at(index);
+ const findDropdownAt = (index) => wrapper.findAll(GlDropdown).at(index);
const findMobileDropdownItems = () => findDropdownAt(0).findAll(GlDropdownItem);
@@ -70,10 +70,7 @@ describe('HeaderActions component', () => {
const findModal = () => wrapper.find(GlModal);
- const findModalLinkAt = index =>
- findModal()
- .findAll(GlLink)
- .at(index);
+ const findModalLinkAt = (index) => findModal().findAll(GlLink).at(index);
const mountComponent = ({
props = {},
@@ -208,7 +205,7 @@ describe('HeaderActions component', () => {
it(`${isItemVisible ? 'shows' : 'hides'} "${itemText}" item`, () => {
expect(
findDropdownItems()
- .filter(item => item.text() === itemText)
+ .filter((item) => item.text() === itemText)
.exists(),
).toBe(isItemVisible);
});
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 c1ab4433761..112cb4d4c3a 100644
--- a/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
+++ b/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
@@ -17,7 +17,7 @@ describe('Highlight Bar', () => {
title: 'Alert 1',
};
- const mountComponent = options => {
+ const mountComponent = (options) => {
wrapper = shallowMount(
HighlightBar,
merge(
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 c6200fd69bf..416870d1408 100644
--- a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
+++ b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
@@ -1,5 +1,7 @@
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';
@@ -18,36 +20,45 @@ const mockAlert = {
describe('Incident Tabs component', () => {
let wrapper;
- const mountComponent = (data = {}) => {
- wrapper = shallowMount(IncidentTabs, {
- propsData: {
- ...descriptionProps,
- },
- stubs: {
- DescriptionComponent: true,
- },
- provide: {
- fullPath: '',
- iid: '',
- },
- data() {
- return { alert: mockAlert, ...data };
- },
- mocks: {
- $apollo: {
- queries: {
- alert: {
- loading: true,
+ const mountComponent = (data = {}, options = {}) => {
+ wrapper = shallowMount(
+ IncidentTabs,
+ merge(
+ {
+ propsData: {
+ ...descriptionProps,
+ },
+ stubs: {
+ DescriptionComponent: true,
+ MetricsTab: true,
+ },
+ provide: {
+ fullPath: '',
+ iid: '',
+ uploadMetricsFeatureAvailable: true,
+ },
+ data() {
+ return { alert: mockAlert, ...data };
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ alert: {
+ loading: true,
+ },
+ },
},
},
},
- },
- });
+ options,
+ ),
+ );
};
const findTabs = () => wrapper.findAll(GlTab);
const findSummaryTab = () => findTabs().at(0);
- const findAlertDetailsTab = () => findTabs().at(1);
+ const findMetricsTab = () => wrapper.find('[data-testid="metrics-tab"]');
+ const findAlertDetailsTab = () => wrapper.find('[data-testid="alert-details-tab"]');
const findAlertDetailsComponent = () => wrapper.find(AlertDetailsTable);
const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
const findHighlightBarComponent = () => wrapper.find(HighlightBar);
@@ -100,6 +111,24 @@ describe('Incident Tabs component', () => {
});
});
+ describe('upload metrics feature available', () => {
+ it('shows the metric tab when metrics are available', async () => {
+ mountComponent({}, { provide: { uploadMetricsFeatureAvailable: true } });
+
+ await waitForPromises();
+
+ expect(findMetricsTab().exists()).toBe(true);
+ });
+
+ it('hides the tab when metrics are not available', async () => {
+ mountComponent({}, { provide: { uploadMetricsFeatureAvailable: false } });
+
+ await waitForPromises();
+
+ expect(findMetricsTab().exists()).toBe(false);
+ });
+ });
+
describe('Snowplow tracking', () => {
beforeEach(() => {
jest.spyOn(Tracking, 'event');
diff --git a/spec/frontend/issue_show/components/pinned_links_spec.js b/spec/frontend/issue_show/components/pinned_links_spec.js
index bb67feee601..2d140fd068a 100644
--- a/spec/frontend/issue_show/components/pinned_links_spec.js
+++ b/spec/frontend/issue_show/components/pinned_links_spec.js
@@ -11,7 +11,7 @@ describe('PinnedLinks', () => {
const findButtons = () => wrapper.findAll(GlButton);
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(PinnedLinks, {
propsData: {
zoomMeetingUrl: '',
@@ -26,11 +26,7 @@ describe('PinnedLinks', () => {
zoomMeetingUrl: `<a href="${plainZoomUrl}">Zoom</a>`,
});
- expect(
- findButtons()
- .at(0)
- .text(),
- ).toBe(JOIN_ZOOM_MEETING);
+ expect(findButtons().at(0).text()).toBe(JOIN_ZOOM_MEETING);
});
it('displays Status link', () => {
@@ -38,11 +34,7 @@ describe('PinnedLinks', () => {
publishedIncidentUrl: `<a href="${plainStatusUrl}">Status</a>`,
});
- expect(
- findButtons()
- .at(0)
- .text(),
- ).toBe(STATUS_PAGE_PUBLISHED);
+ expect(findButtons().at(0).text()).toBe(STATUS_PAGE_PUBLISHED);
});
it('does not render if there are no links', () => {
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
index cee9969d26a..818f501882b 100644
--- a/spec/frontend/issue_show/issue_spec.js
+++ b/spec/frontend/issue_show/issue_spec.js
@@ -14,7 +14,7 @@ useMockIntersectionObserver();
jest.mock('~/lib/utils/poll');
-const setupHTML = initialData => {
+const setupHTML = (initialData) => {
document.body.innerHTML = `<div id="js-issuable-app"></div>`;
document.getElementById('js-issuable-app').dataset.initial = JSON.stringify(initialData);
};
diff --git a/spec/frontend/issue_spec.js b/spec/frontend/issue_spec.js
index 00595736821..303267e784f 100644
--- a/spec/frontend/issue_spec.js
+++ b/spec/frontend/issue_spec.js
@@ -41,7 +41,7 @@ describe('Issue', () => {
expect($boxOpen).toHaveText('Open');
}
- [true, false].forEach(isIssueInitiallyOpen => {
+ [true, false].forEach((isIssueInitiallyOpen) => {
describe(`with ${isIssueInitiallyOpen ? 'open' : 'closed'} issue`, () => {
const action = isIssueInitiallyOpen ? 'close' : 'reopen';
let mock;
diff --git a/spec/frontend/issues_list/components/issuable_spec.js b/spec/frontend/issues_list/components/issuable_spec.js
index 6e584152551..b47a84ad7f6 100644
--- a/spec/frontend/issues_list/components/issuable_spec.js
+++ b/spec/frontend/issues_list/components/issuable_spec.js
@@ -72,9 +72,9 @@ describe('Issuable component', () => {
window.Date = DateOrig;
});
- const checkExists = findFn => () => findFn().exists();
+ const checkExists = (findFn) => () => findFn().exists();
const hasIcon = (iconName, iconWrapper = wrapper) =>
- iconWrapper.findAll(GlIcon).wrappers.some(icon => icon.props('name') === iconName);
+ iconWrapper.findAll(GlIcon).wrappers.some((icon) => icon.props('name') === iconName);
const hasConfidentialIcon = () => hasIcon('eye-slash');
const findTaskStatus = () => wrapper.find('.task-status');
const findOpenedAgoContainer = () => wrapper.find('[data-testid="openedByMessage"]');
@@ -91,8 +91,8 @@ describe('Issuable component', () => {
const findDownvotes = () => wrapper.find('[data-testid="downvotes"]');
const findNotes = () => wrapper.find('[data-testid="notes-count"]');
const findBulkCheckbox = () => wrapper.find('input.selected-issuable');
- const findScopedLabels = () => findLabels().filter(w => isScopedLabel({ title: w.text() }));
- const findUnscopedLabels = () => findLabels().filter(w => !isScopedLabel({ title: w.text() }));
+ const findScopedLabels = () => findLabels().filter((w) => isScopedLabel({ title: w.text() }));
+ const findUnscopedLabels = () => findLabels().filter((w) => !isScopedLabel({ title: w.text() }));
const findIssuableTitle = () => wrapper.find('[data-testid="issuable-title"]');
const findIssuableStatus = () => wrapper.find('[data-testid="issuable-status"]');
const containsJiraLogo = () => wrapper.find('[data-testid="jira-logo"]').exists();
@@ -336,13 +336,13 @@ describe('Issuable component', () => {
it('renders labels', () => {
factory({ issuable });
- const labels = findLabels().wrappers.map(label => ({
+ const labels = findLabels().wrappers.map((label) => ({
href: label.props('target'),
text: label.text(),
tooltip: label.attributes('description'),
}));
- const expected = testLabels.map(label => ({
+ const expected = testLabels.map((label) => ({
href: mergeUrlParams({ 'label_name[]': label.name }, TEST_BASE_URL),
text: label.name,
tooltip: label.description,
@@ -363,13 +363,13 @@ describe('Issuable component', () => {
it('renders labels', () => {
factory({ issuable });
- const labels = findLabels().wrappers.map(label => ({
+ const labels = findLabels().wrappers.map((label) => ({
href: label.props('target'),
text: label.text(),
tooltip: label.attributes('description'),
}));
- const expected = testLabels.map(label => ({
+ const expected = testLabels.map((label) => ({
href: mergeUrlParams({ 'labels[]': label.name }, TEST_BASE_URL),
text: label.name,
tooltip: label.description,
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 1f80b4fc54a..9d603099ff7 100644
--- a/spec/frontend/issues_list/components/issuables_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issuables_list_app_spec.js
@@ -27,7 +27,7 @@ const TEST_ENDPOINT = '/issues';
const TEST_CREATE_ISSUES_PATH = '/createIssue';
const TEST_SVG_PATH = '/emptySvg';
-const setUrl = query => {
+const setUrl = (query) => {
window.location.href = `${TEST_LOCATION}${query}`;
window.location.search = query;
};
@@ -45,10 +45,10 @@ describe('Issuables list component', () => {
let wrapper;
let apiSpy;
- const setupApiMock = cb => {
+ const setupApiMock = (cb) => {
apiSpy = jest.fn(cb);
- mockAxios.onGet(TEST_ENDPOINT).reply(cfg => apiSpy(cfg));
+ mockAxios.onGet(TEST_ENDPOINT).reply((cfg) => apiSpy(cfg));
};
const factory = (props = { sortKey: 'priority' }) => {
@@ -238,15 +238,15 @@ describe('Issuables list component', () => {
wrapper.vm.onSelectIssuable({ issuable: i0, selected: false });
expect(wrapper.vm.selection).toEqual({});
wrapper.vm.onSelectIssuable({ issuable: i1, selected: true });
- expect(wrapper.vm.selection).toEqual({ '1': true });
+ expect(wrapper.vm.selection).toEqual({ 1: true });
wrapper.vm.onSelectIssuable({ issuable: i0, selected: true });
- expect(wrapper.vm.selection).toEqual({ '1': true, '0': true });
+ expect(wrapper.vm.selection).toEqual({ 1: true, 0: true });
wrapper.vm.onSelectIssuable({ issuable: i2, selected: true });
- expect(wrapper.vm.selection).toEqual({ '1': true, '0': true, '2': true });
+ expect(wrapper.vm.selection).toEqual({ 1: true, 0: true, 2: true });
wrapper.vm.onSelectIssuable({ issuable: i2, selected: true });
- expect(wrapper.vm.selection).toEqual({ '1': true, '0': true, '2': true });
+ expect(wrapper.vm.selection).toEqual({ 1: true, 0: true, 2: true });
wrapper.vm.onSelectIssuable({ issuable: i0, selected: false });
- expect(wrapper.vm.selection).toEqual({ '1': true, '2': true });
+ expect(wrapper.vm.selection).toEqual({ 1: true, 2: true });
});
it('broadcasts a message to the bulk edit sidebar when a value is added to selection', () => {
diff --git a/spec/frontend/jira_connect/api_spec.js b/spec/frontend/jira_connect/api_spec.js
new file mode 100644
index 00000000000..8fecbee9ca7
--- /dev/null
+++ b/spec/frontend/jira_connect/api_spec.js
@@ -0,0 +1,107 @@
+import MockAdapter from 'axios-mock-adapter';
+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;
+
+ const mockAddPath = 'addPath';
+ const mockRemovePath = 'removePath';
+ const mockNamespace = 'namespace';
+ const mockJwt = 'jwt';
+ const mockResponse = { success: true };
+
+ const tokenSpy = jest.fn().mockReturnValue(mockJwt);
+
+ window.AP = {
+ context: {
+ getToken: tokenSpy,
+ },
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ response = null;
+ });
+
+ describe('addSubscription', () => {
+ const makeRequest = () => addSubscription(mockAddPath, mockNamespace);
+
+ it('returns success response', async () => {
+ jest.spyOn(axios, 'post');
+ mock
+ .onPost(mockAddPath, {
+ jwt: mockJwt,
+ namespace_path: mockNamespace,
+ })
+ .replyOnce(httpStatus.OK, mockResponse);
+
+ response = await makeRequest();
+
+ expect(tokenSpy).toHaveBeenCalled();
+ expect(axios.post).toHaveBeenCalledWith(mockAddPath, {
+ jwt: mockJwt,
+ namespace_path: mockNamespace,
+ });
+ expect(response.data).toEqual(mockResponse);
+ });
+ });
+
+ describe('removeSubscription', () => {
+ const makeRequest = () => removeSubscription(mockRemovePath);
+
+ it('returns success response', async () => {
+ jest.spyOn(axios, 'delete');
+ mock.onDelete(mockRemovePath).replyOnce(httpStatus.OK, mockResponse);
+
+ response = await makeRequest();
+
+ expect(tokenSpy).toHaveBeenCalled();
+ expect(axios.delete).toHaveBeenCalledWith(mockRemovePath, {
+ params: {
+ jwt: mockJwt,
+ },
+ });
+ expect(response.data).toEqual(mockResponse);
+ });
+ });
+
+ describe('fetchGroups', () => {
+ const mockGroupsPath = 'groupsPath';
+ const mockPage = 1;
+ const mockPerPage = 10;
+
+ const makeRequest = () =>
+ fetchGroups(mockGroupsPath, {
+ page: mockPage,
+ perPage: mockPerPage,
+ });
+
+ it('returns success response', async () => {
+ jest.spyOn(axios, 'get');
+ mock
+ .onGet(mockGroupsPath, {
+ page: mockPage,
+ per_page: mockPerPage,
+ })
+ .replyOnce(httpStatus.OK, mockResponse);
+
+ response = await makeRequest();
+
+ expect(axios.get).toHaveBeenCalledWith(mockGroupsPath, {
+ params: {
+ page: mockPage,
+ per_page: mockPerPage,
+ },
+ });
+ expect(response.data).toEqual(mockResponse);
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/components/app_spec.js b/spec/frontend/jira_connect/components/app_spec.js
new file mode 100644
index 00000000000..be990d5061c
--- /dev/null
+++ b/spec/frontend/jira_connect/components/app_spec.js
@@ -0,0 +1,80 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+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);
+
+describe('JiraConnectApp', () => {
+ let wrapper;
+ let store;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findHeader = () => wrapper.findByTestId('new-jira-connect-ui-heading');
+ const findHeaderText = () => findHeader().text();
+
+ const createComponent = (options = {}) => {
+ store = createStore();
+
+ wrapper = extendedWrapper(
+ shallowMount(JiraConnectApp, {
+ store,
+ provide: {
+ glFeatures: { newJiraConnectUi: true },
+ },
+ ...options,
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('template', () => {
+ it('renders new UI', () => {
+ createComponent();
+
+ expect(findHeader().exists()).toBe(true);
+ expect(findHeaderText()).toBe('Linked namespaces');
+ });
+
+ describe('newJiraConnectUi is false', () => {
+ it('does not render new UI', () => {
+ createComponent({
+ provide: {
+ glFeatures: { newJiraConnectUi: false },
+ },
+ });
+
+ expect(findHeader().exists()).toBe(false);
+ });
+ });
+
+ it.each`
+ errorMessage | errorShouldRender
+ ${'Test error'} | ${true}
+ ${''} | ${false}
+ ${undefined} | ${false}
+ `(
+ 'renders correct alert when errorMessage is `$errorMessage`',
+ async ({ errorMessage, errorShouldRender }) => {
+ createComponent();
+
+ store.commit(SET_ERROR_MESSAGE, errorMessage);
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().exists()).toBe(errorShouldRender);
+ if (errorShouldRender) {
+ expect(findAlert().isVisible()).toBe(errorShouldRender);
+ expect(findAlert().html()).toContain(errorMessage);
+ }
+ },
+ );
+ });
+});
diff --git a/spec/frontend/jira_connect/components/groups_list_item_spec.js b/spec/frontend/jira_connect/components/groups_list_item_spec.js
new file mode 100644
index 00000000000..77577c53cf4
--- /dev/null
+++ b/spec/frontend/jira_connect/components/groups_list_item_spec.js
@@ -0,0 +1,46 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlAvatar } from '@gitlab/ui';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { mockGroup1 } from '../mock_data';
+
+import GroupsListItem from '~/jira_connect/components/groups_list_item.vue';
+
+describe('GroupsListItem', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = extendedWrapper(
+ shallowMount(GroupsListItem, {
+ propsData: {
+ group: mockGroup1,
+ },
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGlAvatar = () => wrapper.find(GlAvatar);
+ const findGroupName = () => wrapper.findByTestId('group-list-item-name');
+ const findGroupDescription = () => wrapper.findByTestId('group-list-item-description');
+
+ 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 description', () => {
+ expect(findGroupDescription().text()).toBe(mockGroup1.description);
+ });
+});
diff --git a/spec/frontend/jira_connect/components/groups_list_spec.js b/spec/frontend/jira_connect/components/groups_list_spec.js
new file mode 100644
index 00000000000..94f158e6344
--- /dev/null
+++ b/spec/frontend/jira_connect/components/groups_list_spec.js
@@ -0,0 +1,71 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import { fetchGroups } from '~/jira_connect/api';
+import GroupsList from '~/jira_connect/components/groups_list.vue';
+import GroupsListItem from '~/jira_connect/components/groups_list_item.vue';
+import { mockGroup1, mockGroup2 } from '../mock_data';
+
+jest.mock('~/jira_connect/api', () => {
+ return {
+ fetchGroups: jest.fn(),
+ };
+});
+describe('GroupsList', () => {
+ let wrapper;
+
+ const mockEmptyResponse = { data: [] };
+
+ const createComponent = (options = {}) => {
+ wrapper = shallowMount(GroupsList, {
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findAllItems = () => wrapper.findAll(GroupsListItem);
+ const findFirstItem = () => findAllItems().at(0);
+ const findSecondItem = () => findAllItems().at(1);
+
+ describe('isLoading is true', () => {
+ it('renders loading icon', async () => {
+ fetchGroups.mockResolvedValue(mockEmptyResponse);
+ createComponent();
+
+ wrapper.setData({ isLoading: true });
+ await wrapper.vm.$nextTick();
+
+ expect(findGlLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('no groups returned', () => {
+ it('renders empty state', async () => {
+ fetchGroups.mockResolvedValue(mockEmptyResponse);
+ createComponent();
+
+ await waitForPromises();
+
+ expect(wrapper.text()).toContain('No available namespaces');
+ });
+ });
+
+ describe('with groups returned', () => {
+ it('renders groups list', async () => {
+ fetchGroups.mockResolvedValue({ data: [mockGroup1, mockGroup2] });
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findAllItems().length).toBe(2);
+ expect(findFirstItem().props('group')).toBe(mockGroup1);
+ expect(findSecondItem().props('group')).toBe(mockGroup2);
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/mock_data.js b/spec/frontend/jira_connect/mock_data.js
new file mode 100644
index 00000000000..31565912489
--- /dev/null
+++ b/spec/frontend/jira_connect/mock_data.js
@@ -0,0 +1,15 @@
+export const mockGroup1 = {
+ id: 1,
+ avatar_url: 'avatar.png',
+ name: 'Gitlab Org',
+ full_name: 'Gitlab Org',
+ description: 'Open source software to collaborate on code',
+};
+
+export const mockGroup2 = {
+ id: 2,
+ avatar_url: 'avatar.png',
+ name: 'Gitlab Com',
+ full_name: 'Gitlab Com',
+ description: 'For GitLab company related projects',
+};
diff --git a/spec/frontend/jira_connect/store/mutations_spec.js b/spec/frontend/jira_connect/store/mutations_spec.js
new file mode 100644
index 00000000000..d1f9d22b3de
--- /dev/null
+++ b/spec/frontend/jira_connect/store/mutations_spec.js
@@ -0,0 +1,18 @@
+import mutations from '~/jira_connect/store/mutations';
+import state from '~/jira_connect/store/state';
+
+describe('JiraConnect store mutations', () => {
+ let localState;
+
+ beforeEach(() => {
+ localState = state();
+ });
+
+ describe('SET_ERROR_MESSAGE', () => {
+ it('sets error message', () => {
+ mutations.SET_ERROR_MESSAGE(localState, 'test error');
+
+ expect(localState.errorMessage).toBe('test error');
+ });
+ });
+});
diff --git a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
index c40b7c90c72..bea27c8877d 100644
--- a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
+++ b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
@@ -114,49 +114,59 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
role="menu"
tabindex="-1"
>
- <!---->
-
<div
- class="gl-search-box-by-type"
+ class="gl-new-dropdown-inner"
>
- <svg
- aria-hidden="true"
- class="gl-search-box-by-type-search-icon gl-icon s16"
- data-testid="search-icon"
- >
- <use
- href="#search"
- />
- </svg>
-
- <input
- aria-label="Search"
- class="gl-form-input gl-search-box-by-type-input form-control"
- placeholder="Search"
- type="text"
- />
+ <!---->
<div
- class="gl-search-box-by-type-right-icons"
- >
- <!---->
-
- <!---->
- </div>
- </div>
-
- <li
- class="gl-new-dropdown-text text-secondary"
- role="presentation"
- >
- <p
- class="b-dropdown-text"
+ class="gl-new-dropdown-contents"
>
-
+ <div
+ class="gl-search-box-by-type"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-search-box-by-type-search-icon gl-icon s16"
+ data-testid="search-icon"
+ >
+ <use
+ href="#search"
+ />
+ </svg>
+
+ <input
+ aria-label="Search"
+ class="gl-form-input gl-search-box-by-type-input form-control"
+ placeholder="Search"
+ type="text"
+ />
+
+ <div
+ class="gl-search-box-by-type-right-icons"
+ >
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+
+ <li
+ class="gl-new-dropdown-text text-secondary"
+ role="presentation"
+ >
+ <p
+ class="b-dropdown-text"
+ >
+
No matches found
- </p>
- </li>
+ </p>
+ </li>
+ </div>
+
+ <!---->
+ </div>
</ul>
</div>
@@ -229,49 +239,59 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
role="menu"
tabindex="-1"
>
- <!---->
-
<div
- class="gl-search-box-by-type"
+ class="gl-new-dropdown-inner"
>
- <svg
- aria-hidden="true"
- class="gl-search-box-by-type-search-icon gl-icon s16"
- data-testid="search-icon"
- >
- <use
- href="#search"
- />
- </svg>
-
- <input
- aria-label="Search"
- class="gl-form-input gl-search-box-by-type-input form-control"
- placeholder="Search"
- type="text"
- />
+ <!---->
<div
- class="gl-search-box-by-type-right-icons"
- >
- <!---->
-
- <!---->
- </div>
- </div>
-
- <li
- class="gl-new-dropdown-text text-secondary"
- role="presentation"
- >
- <p
- class="b-dropdown-text"
+ class="gl-new-dropdown-contents"
>
-
+ <div
+ class="gl-search-box-by-type"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-search-box-by-type-search-icon gl-icon s16"
+ data-testid="search-icon"
+ >
+ <use
+ href="#search"
+ />
+ </svg>
+
+ <input
+ aria-label="Search"
+ class="gl-form-input gl-search-box-by-type-input form-control"
+ placeholder="Search"
+ type="text"
+ />
+
+ <div
+ class="gl-search-box-by-type-right-icons"
+ >
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+
+ <li
+ class="gl-new-dropdown-text text-secondary"
+ role="presentation"
+ >
+ <p
+ class="b-dropdown-text"
+ >
+
No matches found
- </p>
- </li>
+ </p>
+ </li>
+ </div>
+
+ <!---->
+ </div>
</ul>
</div>
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 d184c054b8a..00fb8f5435e 100644
--- a/spec/frontend/jira_import/components/jira_import_form_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_form_spec.js
@@ -37,7 +37,7 @@ describe('JiraImportForm', () => {
const getUserDropdown = () => getTable().find(GlDropdown);
- const getHeader = name => getByRole(wrapper.element, 'columnheader', { name });
+ const getHeader = (name) => getByRole(wrapper.element, 'columnheader', { name });
const findLoadMoreUsersButton = () => wrapper.find('[data-testid="load-more-users-button"]');
diff --git a/spec/frontend/jira_import/components/jira_import_progress_spec.js b/spec/frontend/jira_import/components/jira_import_progress_spec.js
index ed7e1824fa3..b56230e94fc 100644
--- a/spec/frontend/jira_import/components/jira_import_progress_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_progress_spec.js
@@ -8,7 +8,7 @@ describe('JiraImportProgress', () => {
const importProject = 'JIRAPROJECT';
- const getGlEmptyStateProp = attribute => wrapper.find(GlEmptyState).props(attribute);
+ const getGlEmptyStateProp = (attribute) => wrapper.find(GlEmptyState).props(attribute);
const getParagraphText = () => wrapper.find('p').text();
diff --git a/spec/frontend/jira_import/components/jira_import_setup_spec.js b/spec/frontend/jira_import/components/jira_import_setup_spec.js
index 7c84d4a166a..320e270b493 100644
--- a/spec/frontend/jira_import/components/jira_import_setup_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_setup_spec.js
@@ -6,7 +6,7 @@ import { illustration, jiraIntegrationPath } from '../mock_data';
describe('JiraImportSetup', () => {
let wrapper;
- const getGlEmptyStateProp = attribute => wrapper.find(GlEmptyState).props(attribute);
+ const getGlEmptyStateProp = (attribute) => wrapper.find(GlEmptyState).props(attribute);
beforeEach(() => {
wrapper = shallowMount(JiraImportSetup, {
diff --git a/spec/frontend/jobs/components/artifacts_block_spec.js b/spec/frontend/jobs/components/artifacts_block_spec.js
index a709a59cadd..134463c6763 100644
--- a/spec/frontend/jobs/components/artifacts_block_spec.js
+++ b/spec/frontend/jobs/components/artifacts_block_spec.js
@@ -1,12 +1,12 @@
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 { trimText } from '../../helpers/text_helper';
describe('Artifacts block', () => {
let wrapper;
- const createWrapper = propsData =>
+ const createWrapper = (propsData) =>
mount(ArtifactsBlock, {
propsData: {
helpUrl: 'help-url',
diff --git a/spec/frontend/jobs/components/commit_block_spec.js b/spec/frontend/jobs/components/commit_block_spec.js
index 4e2d0053831..13261317b48 100644
--- a/spec/frontend/jobs/components/commit_block_spec.js
+++ b/spec/frontend/jobs/components/commit_block_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/jobs/components/commit_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Commit block', () => {
const Component = Vue.extend(component);
diff --git a/spec/frontend/jobs/components/empty_state_spec.js b/spec/frontend/jobs/components/empty_state_spec.js
index 29d0c4e07aa..c9de110ce06 100644
--- a/spec/frontend/jobs/components/empty_state_spec.js
+++ b/spec/frontend/jobs/components/empty_state_spec.js
@@ -12,7 +12,7 @@ describe('Empty State', () => {
variablesSettingsUrl: '',
};
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = mount(EmptyState, {
propsData: {
...defaultProps,
@@ -46,11 +46,7 @@ describe('Empty State', () => {
});
it('renders provided title', () => {
- expect(
- findTitle()
- .text()
- .trim(),
- ).toBe(defaultProps.title);
+ expect(findTitle().text().trim()).toBe(defaultProps.title);
});
});
@@ -60,11 +56,7 @@ describe('Empty State', () => {
});
it('renders content', () => {
- expect(
- findContent()
- .text()
- .trim(),
- ).toBe(content);
+ expect(findContent().text().trim()).toBe(content);
});
});
diff --git a/spec/frontend/jobs/components/erased_block_spec.js b/spec/frontend/jobs/components/erased_block_spec.js
index d66ee71df6a..b3e1d28eb16 100644
--- a/spec/frontend/jobs/components/erased_block_spec.js
+++ b/spec/frontend/jobs/components/erased_block_spec.js
@@ -10,7 +10,7 @@ describe('Erased block', () => {
const timeago = getTimeago();
const formattedDate = timeago.format(erasedAt);
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = mount(ErasedBlock, {
propsData: props,
});
diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js
index 94653d4d4c7..657687b5e2a 100644
--- a/spec/frontend/jobs/components/job_app_spec.js
+++ b/spec/frontend/jobs/components/job_app_spec.js
@@ -3,7 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { getJSONFixture } from 'helpers/fixtures';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import JobApp from '~/jobs/components/job_app.vue';
import Sidebar from '~/jobs/components/sidebar.vue';
@@ -133,13 +133,9 @@ describe('Job App', () => {
});
it('should render provided job information', () => {
- expect(
- wrapper
- .find('.header-main-content')
- .text()
- .replace(/\s+/g, ' ')
- .trim(),
- ).toContain('passed Job #4757 triggered 1 year ago by Root');
+ expect(wrapper.find('.header-main-content').text().replace(/\s+/g, ' ').trim()).toContain(
+ 'passed Job #4757 triggered 1 year ago by Root',
+ );
});
it('should render new issue link', () => {
@@ -151,11 +147,7 @@ describe('Job App', () => {
it('should render created key', () =>
setupAndMount().then(() => {
expect(
- wrapper
- .find('.header-main-content')
- .text()
- .replace(/\s+/g, ' ')
- .trim(),
+ wrapper.find('.header-main-content').text().replace(/\s+/g, ' ').trim(),
).toContain('passed Job #4757 created 3 weeks ago by Root');
}));
});
@@ -383,7 +375,7 @@ describe('Job App', () => {
});
describe('sidebar', () => {
- it('has no blank blocks', done => {
+ it('has no blank blocks', (done) => {
setupAndMount({
jobData: {
duration: null,
@@ -400,7 +392,7 @@ describe('Job App', () => {
const blocks = wrapper.findAll('.blocks-container > *').wrappers;
expect(blocks.length).toBeGreaterThan(0);
- blocks.forEach(block => {
+ blocks.forEach((block) => {
expect(block.text().trim()).not.toBe('');
});
})
diff --git a/spec/frontend/jobs/components/job_container_item_spec.js b/spec/frontend/jobs/components/job_container_item_spec.js
index 41b399fa32b..af7ce100d83 100644
--- a/spec/frontend/jobs/components/job_container_item_spec.js
+++ b/spec/frontend/jobs/components/job_container_item_spec.js
@@ -82,7 +82,7 @@ describe('JobContainerItem', () => {
);
});
- it('displays remaining time in tooltip', done => {
+ it('displays remaining time in tooltip', (done) => {
vm = mountComponent(Component, {
job: delayedJobFixture,
isActive: false,
diff --git a/spec/frontend/jobs/components/job_log_controllers_spec.js b/spec/frontend/jobs/components/job_log_controllers_spec.js
index 233cef05622..97b0333cb32 100644
--- a/spec/frontend/jobs/components/job_log_controllers_spec.js
+++ b/spec/frontend/jobs/components/job_log_controllers_spec.js
@@ -21,7 +21,7 @@ describe('Job log controllers', () => {
isTraceSizeVisible: true,
};
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = mount(JobLogControllers, {
propsData: {
...defaultProps,
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 be684769b46..bc0d455c309 100644
--- a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
+++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
@@ -1,8 +1,8 @@
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 createStore from '~/jobs/store';
-import { extendedWrapper } from '../../helpers/vue_test_utils_helper';
import job from '../mock_data';
describe('Job Sidebar Details Container', () => {
@@ -37,7 +37,7 @@ describe('Job Sidebar Details Container', () => {
it('should render an empty container', () => {
createWrapper();
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
@@ -55,7 +55,6 @@ describe('Job Sidebar Details Container', () => {
await store.dispatch('receiveJobSuccess', { [detail]: job[detail] });
const detailsRow = findAllDetailsRow();
- expect(wrapper.isEmpty()).toBe(false);
expect(detailsRow).toHaveLength(1);
expect(detailsRow.at(0).text()).toBe(value);
});
@@ -65,7 +64,6 @@ describe('Job Sidebar Details Container', () => {
await store.dispatch('receiveJobSuccess', { tags });
const tagsComponent = findJobTags();
- expect(wrapper.isEmpty()).toBe(false);
expect(tagsComponent.text()).toBe('Tags: tag');
});
});
@@ -91,7 +89,7 @@ describe('Job Sidebar Details Container', () => {
await store.dispatch('receiveJobSuccess', { metadata });
const detailsRow = findAllDetailsRow();
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
expect(detailsRow.exists()).toBe(false);
});
@@ -100,7 +98,6 @@ describe('Job Sidebar Details Container', () => {
await store.dispatch('receiveJobSuccess', { metadata });
const detailsRow = findAllDetailsRow();
- expect(wrapper.isEmpty()).toBe(false);
expect(detailsRow).toHaveLength(1);
expect(detailsRow.at(0).text()).toBe('Timeout: 1m 40s');
});
diff --git a/spec/frontend/jobs/components/jobs_container_spec.js b/spec/frontend/jobs/components/jobs_container_spec.js
index 119b18b7557..9a336489101 100644
--- a/spec/frontend/jobs/components/jobs_container_spec.js
+++ b/spec/frontend/jobs/components/jobs_container_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/jobs/components/jobs_container.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Jobs List block', () => {
const Component = Vue.extend(component);
diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js
index 914ae2424c8..367154e7f82 100644
--- a/spec/frontend/jobs/components/log/line_spec.js
+++ b/spec/frontend/jobs/components/log/line_spec.js
@@ -34,10 +34,7 @@ describe('Job Log Line', () => {
const findLine = () => wrapper.find('span');
const findLink = () => findLine().find('a');
const findLinks = () => findLine().findAll('a');
- const findLinkAttributeByIndex = i =>
- findLinks()
- .at(i)
- .attributes();
+ const findLinkAttributeByIndex = (i) => findLinks().at(i).attributes();
beforeEach(() => {
data = mockProps();
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
index 015d5e01a46..f662ffa1780 100644
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ b/spec/frontend/jobs/components/log/log_spec.js
@@ -62,11 +62,7 @@ describe('Job Log', () => {
});
it('renders an icon with the open state', () => {
- expect(
- findCollapsibleLine()
- .find('[data-testid="angle-down-icon"]')
- .exists(),
- ).toBe(true);
+ expect(findCollapsibleLine().find('[data-testid="angle-down-icon"]').exists()).toBe(true);
});
describe('on click header section', () => {
diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js
index 547f146cf88..f6c37407e2b 100644
--- a/spec/frontend/jobs/components/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/manual_variables_form_spec.js
@@ -27,7 +27,7 @@ describe('Manual Variables Form', () => {
factory(requiredProps);
});
- afterEach(done => {
+ afterEach((done) => {
// The component has a `nextTick` callback after some events so we need
// to wait for those to finish before destroying.
setImmediate(() => {
@@ -54,7 +54,7 @@ describe('Manual Variables Form', () => {
});
describe('when adding a new variable', () => {
- it('creates a new variable when user types a new key and resets the form', done => {
+ it('creates a new variable when user types a new key and resets the form', (done) => {
wrapper.vm
.$nextTick()
.then(() => wrapper.find({ ref: 'inputKey' }).setValue('new key'))
@@ -67,7 +67,7 @@ describe('Manual Variables Form', () => {
.catch(done.fail);
});
- it('creates a new variable when user types a new value and resets the form', done => {
+ it('creates a new variable when user types a new value and resets the form', (done) => {
wrapper.vm
.$nextTick()
.then(() => wrapper.find({ ref: 'inputSecretValue' }).setValue('new value'))
@@ -82,7 +82,7 @@ describe('Manual Variables Form', () => {
});
describe('when deleting a variable', () => {
- beforeEach(done => {
+ beforeEach((done) => {
wrapper.vm.variables = [
{
key: 'new key',
diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js
index 1d4be2fb81e..22d555ffec7 100644
--- a/spec/frontend/jobs/components/sidebar_spec.js
+++ b/spec/frontend/jobs/components/sidebar_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { 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';
@@ -6,7 +7,6 @@ import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_
import JobRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
import createStore from '~/jobs/store';
import job, { jobsInStage } from '../mock_data';
-import { extendedWrapper } from '../../helpers/vue_test_utils_helper';
describe('Sidebar details block', () => {
let store;
diff --git a/spec/frontend/jobs/components/stages_dropdown_spec.js b/spec/frontend/jobs/components/stages_dropdown_spec.js
index e8fa6094c25..72d5d0f9d44 100644
--- a/spec/frontend/jobs/components/stages_dropdown_spec.js
+++ b/spec/frontend/jobs/components/stages_dropdown_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { trimText } from 'helpers/text_helper';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/jobs/components/stages_dropdown.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Stages Dropdown', () => {
const Component = Vue.extend(component);
diff --git a/spec/frontend/jobs/components/stuck_block_spec.js b/spec/frontend/jobs/components/stuck_block_spec.js
index 926286bf75a..4db73eaaaec 100644
--- a/spec/frontend/jobs/components/stuck_block_spec.js
+++ b/spec/frontend/jobs/components/stuck_block_spec.js
@@ -12,7 +12,7 @@ describe('Stuck Block Job component', () => {
}
});
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = shallowMount(StuckBlock, {
propsData: {
...props,
diff --git a/spec/frontend/jobs/components/trigger_block_spec.js b/spec/frontend/jobs/components/trigger_block_spec.js
index 448197b82c0..16ea276ee4a 100644
--- a/spec/frontend/jobs/components/trigger_block_spec.js
+++ b/spec/frontend/jobs/components/trigger_block_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/jobs/components/trigger_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Trigger block', () => {
const Component = Vue.extend(component);
@@ -32,7 +32,7 @@ describe('Trigger block', () => {
describe('with variables', () => {
describe('hide/reveal variables', () => {
- it('should toggle variables on click', done => {
+ it('should toggle variables on click', (done) => {
vm = mountComponent(Component, {
trigger: {
short_token: 'bd7e',
diff --git a/spec/frontend/jobs/store/actions_spec.js b/spec/frontend/jobs/store/actions_spec.js
index 91bd5521f70..2d757ce76bf 100644
--- a/spec/frontend/jobs/store/actions_spec.js
+++ b/spec/frontend/jobs/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 { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import {
setJobEndpoint,
@@ -39,7 +39,7 @@ describe('Job State actions', () => {
});
describe('setJobEndpoint', () => {
- it('should commit SET_JOB_ENDPOINT mutation', done => {
+ it('should commit SET_JOB_ENDPOINT mutation', (done) => {
testAction(
setJobEndpoint,
'job/872324.json',
@@ -52,7 +52,7 @@ describe('Job State actions', () => {
});
describe('setTraceOptions', () => {
- it('should commit SET_TRACE_OPTIONS mutation', done => {
+ it('should commit SET_TRACE_OPTIONS mutation', (done) => {
testAction(
setTraceOptions,
{ pagePath: 'job/872324/trace.json' },
@@ -65,26 +65,26 @@ describe('Job State actions', () => {
});
describe('hideSidebar', () => {
- it('should commit HIDE_SIDEBAR mutation', done => {
+ it('should commit HIDE_SIDEBAR mutation', (done) => {
testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], [], done);
});
});
describe('showSidebar', () => {
- it('should commit HIDE_SIDEBAR mutation', done => {
+ it('should commit HIDE_SIDEBAR mutation', (done) => {
testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], [], done);
});
});
describe('toggleSidebar', () => {
describe('when isSidebarOpen is true', () => {
- it('should dispatch hideSidebar', done => {
+ it('should dispatch hideSidebar', (done) => {
testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }], done);
});
});
describe('when isSidebarOpen is false', () => {
- it('should dispatch showSidebar', done => {
+ it('should dispatch showSidebar', (done) => {
mockedState.isSidebarOpen = false;
testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }], done);
@@ -93,7 +93,7 @@ describe('Job State actions', () => {
});
describe('requestJob', () => {
- it('should commit REQUEST_JOB mutation', done => {
+ it('should commit REQUEST_JOB mutation', (done) => {
testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], [], done);
});
});
@@ -113,7 +113,7 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches requestJob and receiveJobSuccess ', done => {
+ it('dispatches requestJob and receiveJobSuccess ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, { id: 121212, name: 'karma' });
testAction(
@@ -140,7 +140,7 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
});
- it('dispatches requestJob and receiveJobError ', done => {
+ it('dispatches requestJob and receiveJobError ', (done) => {
testAction(
fetchJob,
null,
@@ -161,7 +161,7 @@ describe('Job State actions', () => {
});
describe('receiveJobSuccess', () => {
- it('should commit RECEIVE_JOB_SUCCESS mutation', done => {
+ it('should commit RECEIVE_JOB_SUCCESS mutation', (done) => {
testAction(
receiveJobSuccess,
{ id: 121232132 },
@@ -174,25 +174,25 @@ describe('Job State actions', () => {
});
describe('receiveJobError', () => {
- it('should commit RECEIVE_JOB_ERROR mutation', done => {
+ it('should commit RECEIVE_JOB_ERROR mutation', (done) => {
testAction(receiveJobError, null, mockedState, [{ type: types.RECEIVE_JOB_ERROR }], [], done);
});
});
describe('scrollTop', () => {
- it('should dispatch toggleScrollButtons action', done => {
+ it('should dispatch toggleScrollButtons action', (done) => {
testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
});
});
describe('scrollBottom', () => {
- it('should dispatch toggleScrollButtons action', done => {
+ it('should dispatch toggleScrollButtons action', (done) => {
testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
});
});
describe('requestTrace', () => {
- it('should commit REQUEST_TRACE mutation', done => {
+ it('should commit REQUEST_TRACE mutation', (done) => {
testAction(requestTrace, null, mockedState, [{ type: types.REQUEST_TRACE }], [], done);
});
});
@@ -212,7 +212,7 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches requestTrace, receiveTraceSuccess and stopPollingTrace when job is complete', done => {
+ it('dispatches requestTrace, receiveTraceSuccess and stopPollingTrace when job is complete', (done) => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, {
html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
complete: true,
@@ -255,7 +255,7 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, tracePayload);
});
- it('dispatches startPollingTrace', done => {
+ it('dispatches startPollingTrace', (done) => {
testAction(
fetchTrace,
null,
@@ -270,7 +270,7 @@ describe('Job State actions', () => {
);
});
- it('does not dispatch startPollingTrace when timeout is non-empty', done => {
+ it('does not dispatch startPollingTrace when timeout is non-empty', (done) => {
mockedState.traceTimeout = 1;
testAction(
@@ -293,7 +293,7 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).reply(500);
});
- it('dispatches requestTrace and receiveTraceError ', done => {
+ it('dispatches requestTrace and receiveTraceError ', (done) => {
testAction(
fetchTrace,
null,
@@ -358,7 +358,7 @@ describe('Job State actions', () => {
window.clearTimeout = origTimeout;
});
- it('should commit STOP_POLLING_TRACE mutation ', done => {
+ it('should commit STOP_POLLING_TRACE mutation ', (done) => {
const traceTimeout = 7;
testAction(
@@ -377,7 +377,7 @@ describe('Job State actions', () => {
});
describe('receiveTraceSuccess', () => {
- it('should commit RECEIVE_TRACE_SUCCESS mutation ', done => {
+ it('should commit RECEIVE_TRACE_SUCCESS mutation ', (done) => {
testAction(
receiveTraceSuccess,
'hello world',
@@ -390,13 +390,13 @@ describe('Job State actions', () => {
});
describe('receiveTraceError', () => {
- it('should commit stop polling trace', done => {
+ it('should commit stop polling trace', (done) => {
testAction(receiveTraceError, null, mockedState, [], [{ type: 'stopPollingTrace' }], done);
});
});
describe('toggleCollapsibleLine', () => {
- it('should commit TOGGLE_COLLAPSIBLE_LINE mutation ', done => {
+ it('should commit TOGGLE_COLLAPSIBLE_LINE mutation ', (done) => {
testAction(
toggleCollapsibleLine,
{ isClosed: true },
@@ -409,7 +409,7 @@ describe('Job State actions', () => {
});
describe('requestJobsForStage', () => {
- it('should commit REQUEST_JOBS_FOR_STAGE mutation ', done => {
+ it('should commit REQUEST_JOBS_FOR_STAGE mutation ', (done) => {
testAction(
requestJobsForStage,
{ name: 'deploy' },
@@ -433,7 +433,7 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', done => {
+ it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', (done) => {
mock
.onGet(`${TEST_HOST}/jobs.json`)
.replyOnce(200, { latest_statuses: [{ id: 121212, name: 'build' }], retried: [] });
@@ -463,7 +463,7 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/jobs.json`).reply(500);
});
- it('dispatches requestJobsForStage and receiveJobsForStageError', done => {
+ it('dispatches requestJobsForStage and receiveJobsForStageError', (done) => {
testAction(
fetchJobsForStage,
{ dropdown_path: `${TEST_HOST}/jobs.json` },
@@ -485,7 +485,7 @@ describe('Job State actions', () => {
});
describe('receiveJobsForStageSuccess', () => {
- it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation ', done => {
+ it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation ', (done) => {
testAction(
receiveJobsForStageSuccess,
[{ id: 121212, name: 'karma' }],
@@ -498,7 +498,7 @@ describe('Job State actions', () => {
});
describe('receiveJobsForStageError', () => {
- it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation ', done => {
+ it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation ', (done) => {
testAction(
receiveJobsForStageError,
null,
diff --git a/spec/frontend/jobs/store/helpers.js b/spec/frontend/jobs/store/helpers.js
index 78e33394b63..402ae58971a 100644
--- a/spec/frontend/jobs/store/helpers.js
+++ b/spec/frontend/jobs/store/helpers.js
@@ -1,5 +1,5 @@
import state from '~/jobs/store/state';
-export const resetStore = store => {
+export const resetStore = (store) => {
store.replaceState(state());
};
diff --git a/spec/frontend/lazy_loader_spec.js b/spec/frontend/lazy_loader_spec.js
index 5eb09bc2359..f8ac7568724 100644
--- a/spec/frontend/lazy_loader_spec.js
+++ b/spec/frontend/lazy_loader_spec.js
@@ -1,10 +1,10 @@
import { noop } from 'lodash';
import { TEST_HOST } from 'helpers/test_constants';
import { useMockMutationObserver, useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import waitForPromises from 'helpers/wait_for_promises';
import LazyLoader from '~/lazy_loader';
-import waitForPromises from './helpers/wait_for_promises';
-const execImmediately = callback => {
+const execImmediately = (callback) => {
callback();
};
@@ -20,7 +20,7 @@ describe('LazyLoader', () => {
triggerMutation(document.body, { options: { childList: true, subtree: true } });
};
- const triggerIntersectionWithRatio = img => {
+ const triggerIntersectionWithRatio = (img) => {
triggerIntersection(img, { entry: { intersectionRatio: 0.1 } });
};
diff --git a/spec/frontend/lib/dompurify_spec.js b/spec/frontend/lib/dompurify_spec.js
index ee1971a4931..a01f86678e9 100644
--- a/spec/frontend/lib/dompurify_spec.js
+++ b/spec/frontend/lib/dompurify_spec.js
@@ -15,8 +15,8 @@ const absoluteGon = {
const expectedSanitized = '<svg><use></use></svg>';
const safeUrls = {
- root: Object.values(rootGon).map(url => `${url}#ellipsis_h`),
- absolute: Object.values(absoluteGon).map(url => `${url}#ellipsis_h`),
+ root: Object.values(rootGon).map((url) => `${url}#ellipsis_h`),
+ absolute: Object.values(absoluteGon).map((url) => `${url}#ellipsis_h`),
};
const unsafeUrls = [
@@ -60,7 +60,7 @@ describe('~/lib/dompurify', () => {
expect(sanitize(htmlHref)).toBe(htmlHref);
});
- it.each(safeUrls[type])('allows safe URL %s', url => {
+ it.each(safeUrls[type])('allows safe URL %s', (url) => {
const htmlHref = `<svg><use href="${url}"></use></svg>`;
expect(sanitize(htmlHref)).toBe(htmlHref);
@@ -68,7 +68,7 @@ describe('~/lib/dompurify', () => {
expect(sanitize(htmlXlink)).toBe(htmlXlink);
});
- it.each(unsafeUrls)('sanitizes unsafe URL %s', url => {
+ it.each(unsafeUrls)('sanitizes unsafe URL %s', (url) => {
const htmlHref = `<svg><use href="${url}"></use></svg>`;
const htmlXlink = `<svg><use xlink:href="${url}"></use></svg>`;
@@ -87,7 +87,7 @@ describe('~/lib/dompurify', () => {
window.gon = originalGon;
});
- it.each([...safeUrls.root, ...safeUrls.absolute, ...unsafeUrls])('sanitizes URL %s', url => {
+ it.each([...safeUrls.root, ...safeUrls.absolute, ...unsafeUrls])('sanitizes URL %s', (url) => {
const htmlHref = `<svg><use href="${url}"></use></svg>`;
const htmlXlink = `<svg><use xlink:href="${url}"></use></svg>`;
diff --git a/spec/frontend/lib/utils/ajax_cache_spec.js b/spec/frontend/lib/utils/ajax_cache_spec.js
index e2ee70b9d69..641dd3684fa 100644
--- a/spec/frontend/lib/utils/ajax_cache_spec.js
+++ b/spec/frontend/lib/utils/ajax_cache_spec.js
@@ -104,7 +104,7 @@ describe('AjaxCache', () => {
it('stores and returns data from Ajax call if cache is empty', () => {
mock.onGet(dummyEndpoint).reply(200, dummyResponse);
- return AjaxCache.retrieve(dummyEndpoint).then(data => {
+ return AjaxCache.retrieve(dummyEndpoint).then((data) => {
expect(data).toEqual(dummyResponse);
expect(AjaxCache.internalStorage[dummyEndpoint]).toEqual(dummyResponse);
});
@@ -126,7 +126,7 @@ describe('AjaxCache', () => {
mock.onGet(dummyEndpoint).networkError();
expect.assertions(2);
- return AjaxCache.retrieve(dummyEndpoint).catch(error => {
+ return AjaxCache.retrieve(dummyEndpoint).catch((error) => {
expect(error.message).toBe(`${dummyEndpoint}: ${errorMessage}`);
expect(error.textStatus).toBe(errorMessage);
});
@@ -135,7 +135,7 @@ describe('AjaxCache', () => {
it('makes no Ajax call if matching data exists', () => {
AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
- return AjaxCache.retrieve(dummyEndpoint).then(data => {
+ return AjaxCache.retrieve(dummyEndpoint).then((data) => {
expect(data).toBe(dummyResponse);
expect(axios.get).not.toHaveBeenCalled();
});
@@ -153,7 +153,7 @@ describe('AjaxCache', () => {
return Promise.all([
AjaxCache.retrieve(dummyEndpoint),
AjaxCache.retrieve(dummyEndpoint, true),
- ]).then(data => {
+ ]).then((data) => {
expect(data).toEqual([oldDummyResponse, dummyResponse]);
});
});
diff --git a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
index faead3ff8fe..c0e5b06651f 100644
--- a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
+++ b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js
@@ -58,9 +58,9 @@ describe('StartupJSLink', () => {
link = ApolloLink.from([startupLink, new ApolloLink(() => Observable.of(FORWARDED_RESPONSE))]);
};
- it('forwards requests if no calls are set up', done => {
+ it('forwards requests if no calls are set up', (done) => {
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls).toBe(null);
expect(startupLink.request).toEqual(StartupJSLink.noopRequest);
@@ -68,7 +68,7 @@ describe('StartupJSLink', () => {
});
});
- it('forwards requests if the operation is not pre-loaded', done => {
+ it('forwards requests if the operation is not pre-loaded', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -79,7 +79,7 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ operationName: 'notLoaded' })).subscribe(result => {
+ link.request(mockOperation({ operationName: 'notLoaded' })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(1);
done();
@@ -87,7 +87,7 @@ describe('StartupJSLink', () => {
});
describe('variable match errors: ', () => {
- it('forwards requests if the variables are not matching', done => {
+ it('forwards requests if the variables are not matching', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -98,14 +98,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('forwards requests if more variables are set in the operation', done => {
+ it('forwards requests if more variables are set in the operation', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -115,14 +115,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('forwards requests if less variables are set in the operation', done => {
+ it('forwards requests if less variables are set in the operation', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -133,14 +133,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => {
+ link.request(mockOperation({ variables: { id: 3 } })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('forwards requests if different variables are set', done => {
+ it('forwards requests if different variables are set', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -151,14 +151,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => {
+ link.request(mockOperation({ variables: { id: 3 } })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('forwards requests if array variables have a different order', done => {
+ it('forwards requests if array variables have a different order', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -169,7 +169,7 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ variables: { id: [4, 3] } })).subscribe(result => {
+ link.request(mockOperation({ variables: { id: [4, 3] } })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
@@ -178,7 +178,7 @@ describe('StartupJSLink', () => {
});
describe('error handling', () => {
- it('forwards the call if the fetchCall is failing with a HTTP Error', done => {
+ it('forwards the call if the fetchCall is failing with a HTTP Error', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -189,14 +189,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('forwards the call if it errors (e.g. failing JSON)', done => {
+ it('forwards the call if it errors (e.g. failing JSON)', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -207,14 +207,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('forwards the call if the response contains an error', done => {
+ it('forwards the call if the response contains an error', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -225,14 +225,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it("forwards the call if the response doesn't contain a data object", done => {
+ it("forwards the call if the response doesn't contain a data object", (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -243,7 +243,7 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
@@ -251,7 +251,7 @@ describe('StartupJSLink', () => {
});
});
- it('resolves the request if the operation is matching', done => {
+ it('resolves the request if the operation is matching', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -262,14 +262,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('resolves the request exactly once', done => {
+ it('resolves the request exactly once', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -280,17 +280,17 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation()).subscribe(result => {
+ link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
- link.request(mockOperation()).subscribe(result2 => {
+ link.request(mockOperation()).subscribe((result2) => {
expect(result2).toEqual(FORWARDED_RESPONSE);
done();
});
});
});
- it('resolves the request if the variables have a different order', done => {
+ it('resolves the request if the variables have a different order', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -301,14 +301,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ variables: { name: 'foo', id: 3 } })).subscribe(result => {
+ link.request(mockOperation({ variables: { name: 'foo', id: 3 } })).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('resolves the request if the variables have undefined values', done => {
+ it('resolves the request if the variables have undefined values', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -321,14 +321,14 @@ describe('StartupJSLink', () => {
setupLink();
link
.request(mockOperation({ variables: { name: 'foo', undef: undefined } }))
- .subscribe(result => {
+ .subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('resolves the request if the variables are of an array format', done => {
+ it('resolves the request if the variables are of an array format', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -339,14 +339,14 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ variables: { id: [3, 4] } })).subscribe(result => {
+ link.request(mockOperation({ variables: { id: [3, 4] } })).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
- it('resolves multiple requests correctly', done => {
+ it('resolves multiple requests correctly', (done) => {
window.gl = {
startup_graphql_calls: [
{
@@ -362,10 +362,10 @@ describe('StartupJSLink', () => {
],
};
setupLink();
- link.request(mockOperation({ operationName: OPERATION_NAME_TWO })).subscribe(result => {
+ link.request(mockOperation({ operationName: OPERATION_NAME_TWO })).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE_TWO);
expect(startupLink.startupCalls.size).toBe(1);
- link.request(mockOperation({ operationName: OPERATION_NAME })).subscribe(result2 => {
+ link.request(mockOperation({ operationName: OPERATION_NAME })).subscribe((result2) => {
expect(result2).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
diff --git a/spec/frontend/lib/utils/chart_utils_spec.js b/spec/frontend/lib/utils/chart_utils_spec.js
index e811b8405fb..65bb68c5017 100644
--- a/spec/frontend/lib/utils/chart_utils_spec.js
+++ b/spec/frontend/lib/utils/chart_utils_spec.js
@@ -3,7 +3,11 @@ import { firstAndLastY } from '~/lib/utils/chart_utils';
describe('Chart utils', () => {
describe('firstAndLastY', () => {
it('returns the first and last y-values of a given data set as an array', () => {
- const data = [['', 1], ['', 2], ['', 3]];
+ const data = [
+ ['', 1],
+ ['', 2],
+ ['', 3],
+ ];
expect(firstAndLastY(data)).toEqual([1, 3]);
});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index 433fb368f55..90222f0f718 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import * as commonUtils from '~/lib/utils/common_utils';
describe('common_utils', () => {
@@ -214,60 +213,90 @@ describe('common_utils', () => {
describe('scrollToElement*', () => {
let elem;
- const windowHeight = 1000;
+ const windowHeight = 550;
const elemTop = 100;
+ const id = 'scroll_test';
beforeEach(() => {
elem = document.createElement('div');
+ elem.id = id;
+ document.body.appendChild(elem);
window.innerHeight = windowHeight;
window.mrTabs = { currentAction: 'show' };
- jest.spyOn($.fn, 'animate');
- jest.spyOn($.fn, 'offset').mockReturnValue({ top: elemTop });
+ jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
+ jest.spyOn(Element.prototype, 'getBoundingClientRect').mockReturnValue({ top: elemTop });
});
afterEach(() => {
- $.fn.animate.mockRestore();
- $.fn.offset.mockRestore();
+ window.scrollTo.mockRestore();
+ Element.prototype.getBoundingClientRect.mockRestore();
+ elem.remove();
});
- describe('scrollToElement', () => {
+ describe('scrollToElement with HTMLElement', () => {
it('scrolls to element', () => {
commonUtils.scrollToElement(elem);
- expect($.fn.animate).toHaveBeenCalledWith(
- {
- scrollTop: elemTop,
- },
- expect.any(Number),
- );
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elemTop,
+ });
});
it('scrolls to element with offset', () => {
const offset = 50;
commonUtils.scrollToElement(elem, { offset });
- expect($.fn.animate).toHaveBeenCalledWith(
- {
- scrollTop: elemTop + offset,
- },
- expect.any(Number),
- );
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elemTop + offset,
+ });
+ });
+ });
+
+ describe('scrollToElement with Selector', () => {
+ it('scrolls to element', () => {
+ commonUtils.scrollToElement(`#${id}`);
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elemTop,
+ });
+ });
+
+ it('scrolls to element with offset', () => {
+ const offset = 50;
+ commonUtils.scrollToElement(`#${id}`, { offset });
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elemTop + offset,
+ });
});
});
describe('scrollToElementWithContext', () => {
- it('scrolls with context', () => {
- commonUtils.scrollToElementWithContext();
- expect($.fn.animate).toHaveBeenCalledWith(
- {
- scrollTop: elemTop - windowHeight * 0.1,
- },
- expect.any(Number),
- );
+ // This is what the implementation of scrollToElementWithContext
+ // scrolls to, in case we change tha implementation
+ // it needs to be adjusted
+ const elementTopWithContext = elemTop - windowHeight * 0.1;
+
+ it('with HTMLElement scrolls with context', () => {
+ commonUtils.scrollToElementWithContext(elem);
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elementTopWithContext,
+ });
+ });
+
+ it('with Selector scrolls with context', () => {
+ commonUtils.scrollToElementWithContext(`#${id}`);
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elementTopWithContext,
+ });
});
});
});
describe('debounceByAnimationFrame', () => {
- it('debounces a function to allow a maximum of one call per animation frame', done => {
+ it('debounces a function to allow a maximum of one call per animation frame', (done) => {
const spy = jest.fn();
const debouncedSpy = commonUtils.debounceByAnimationFrame(spy);
window.requestAnimationFrame(() => {
@@ -404,54 +433,54 @@ describe('common_utils', () => {
describe('backOff', () => {
beforeEach(() => {
// shortcut our timeouts otherwise these tests will take a long time to finish
- jest.spyOn(window, 'setTimeout').mockImplementation(cb => setImmediate(cb, 0));
+ jest.spyOn(window, 'setTimeout').mockImplementation((cb) => setImmediate(cb, 0));
});
- it('solves the promise from the callback', done => {
+ it('solves the promise from the callback', (done) => {
const expectedResponseValue = 'Success!';
commonUtils
.backOff((next, stop) =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve(expectedResponseValue);
})
- .then(resp => {
+ .then((resp) => {
stop(resp);
})
.catch(done.fail),
)
- .then(respBackoff => {
+ .then((respBackoff) => {
expect(respBackoff).toBe(expectedResponseValue);
done();
})
.catch(done.fail);
});
- it('catches the rejected promise from the callback ', done => {
+ it('catches the rejected promise from the callback ', (done) => {
const errorMessage = 'Mistakes were made!';
commonUtils
.backOff((next, stop) => {
new Promise((resolve, reject) => {
reject(new Error(errorMessage));
})
- .then(resp => {
+ .then((resp) => {
stop(resp);
})
- .catch(err => stop(err));
+ .catch((err) => stop(err));
})
- .catch(errBackoffResp => {
+ .catch((errBackoffResp) => {
expect(errBackoffResp instanceof Error).toBe(true);
expect(errBackoffResp.message).toBe(errorMessage);
done();
});
});
- it('solves the promise correctly after retrying a third time', done => {
+ it('solves the promise correctly after retrying a third time', (done) => {
let numberOfCalls = 1;
const expectedResponseValue = 'Success!';
commonUtils
.backOff((next, stop) =>
Promise.resolve(expectedResponseValue)
- .then(resp => {
+ .then((resp) => {
if (numberOfCalls < 3) {
numberOfCalls += 1;
next();
@@ -461,7 +490,7 @@ describe('common_utils', () => {
})
.catch(done.fail),
)
- .then(respBackoff => {
+ .then((respBackoff) => {
const timeouts = window.setTimeout.mock.calls.map(([, timeout]) => timeout);
expect(timeouts).toEqual([2000, 4000]);
@@ -471,10 +500,10 @@ describe('common_utils', () => {
.catch(done.fail);
});
- it('rejects the backOff promise after timing out', done => {
+ it('rejects the backOff promise after timing out', (done) => {
commonUtils
- .backOff(next => next(), 64000)
- .catch(errBackoffResp => {
+ .backOff((next) => next(), 64000)
+ .catch((errBackoffResp) => {
const timeouts = window.setTimeout.mock.calls.map(([, timeout]) => timeout);
expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
@@ -485,27 +514,6 @@ describe('common_utils', () => {
});
});
- describe('resetFavicon', () => {
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('data-original-href', 'default/favicon');
- document.body.appendChild(favicon);
- });
-
- afterEach(() => {
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should reset page favicon to the default icon', () => {
- const favicon = document.getElementById('favicon');
- favicon.setAttribute('href', 'new/favicon');
- commonUtils.resetFavicon();
-
- expect(document.getElementById('favicon').getAttribute('href')).toEqual('default/favicon');
- });
- });
-
describe('spriteIcon', () => {
let beforeGon;
@@ -533,8 +541,8 @@ describe('common_utils', () => {
});
describe('convertObjectProps*', () => {
- const mockConversionFunction = prop => `${prop}_converted`;
- const isEmptyObject = obj =>
+ const mockConversionFunction = (prop) => `${prop}_converted`;
+ const isEmptyObject = (obj) =>
typeof obj === 'object' && obj !== null && Object.keys(obj).length === 0;
const mockObjects = {
diff --git a/spec/frontend/lib/utils/datetime_range_spec.js b/spec/frontend/lib/utils/datetime_range_spec.js
index 8b1f284615d..996a8e2e47b 100644
--- a/spec/frontend/lib/utils/datetime_range_spec.js
+++ b/spec/frontend/lib/utils/datetime_range_spec.js
@@ -64,7 +64,7 @@ describe('Date time range utils', () => {
};
Object.entries(rangeTypes).forEach(([type, examples]) => {
- examples.forEach(example => expect(getRangeType(example)).toEqual(type));
+ examples.forEach((example) => expect(getRangeType(example)).toEqual(type));
});
});
});
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index 6092b44720f..66efd43262b 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -566,7 +566,7 @@ describe('getDatesInRange', () => {
it('applies mapper function if provided fro each item in range', () => {
const d1 = new Date('2019-01-01');
const d2 = new Date('2019-01-31');
- const formatter = date => date.getDate();
+ const formatter = (date) => date.getDate();
const range = datetimeUtility.getDatesInRange(d1, d2, formatter);
@@ -608,6 +608,92 @@ describe('secondsToDays', () => {
});
});
+describe('nDaysAfter', () => {
+ const date = new Date('2019-07-16T00:00:00.000Z');
+
+ 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);
+ });
+});
+
+describe('nDaysBefore', () => {
+ const date = new Date('2019-07-16T00:00:00.000Z');
+
+ 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('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');
+
+ 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('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');
+
+ 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('approximateDuration', () => {
it.each`
seconds
@@ -731,3 +817,83 @@ describe('datesMatch', () => {
expect(datetimeUtility.datesMatch(date1, date2)).toBe(expected);
});
});
+
+describe('format24HourTimeStringFromInt', () => {
+ const expectedFormattedTimes = [
+ [0, '00:00'],
+ [2, '02:00'],
+ [6, '06:00'],
+ [9, '09:00'],
+ [10, '10:00'],
+ [16, '16:00'],
+ [22, '22:00'],
+ [32, ''],
+ [NaN, ''],
+ ['Invalid Int', ''],
+ [null, ''],
+ [undefined, ''],
+ ];
+
+ expectedFormattedTimes.forEach(([timeInt, expectedTimeStringIn24HourNotation]) => {
+ it(`formats ${timeInt} as ${expectedTimeStringIn24HourNotation}`, () => {
+ expect(datetimeUtility.format24HourTimeStringFromInt(timeInt)).toBe(
+ expectedTimeStringIn24HourNotation,
+ );
+ });
+ });
+});
+
+describe('getOverlappingDaysInPeriods', () => {
+ const start = new Date(2021, 0, 11);
+ const end = new Date(2021, 0, 13);
+
+ describe('when date periods overlap', () => {
+ 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', () => {
+ expect(
+ datetimeUtility.getOverlappingDaysInPeriods(
+ { start, end },
+ { start: givenPeriodLeft, end: givenPeriodRight },
+ ),
+ ).toEqual({
+ daysOverlap: 2,
+ overlapStartDate: givenPeriodLeft.getTime(),
+ overlapEndDate: end.getTime(),
+ });
+ });
+ });
+
+ describe('when date periods do not overlap', () => {
+ const givenPeriodLeft = new Date(2021, 0, 9);
+ const givenPeriodRight = new Date(2021, 0, 10);
+
+ it('returns an overlap object that contains a 0 value for days overlapping', () => {
+ expect(
+ datetimeUtility.getOverlappingDaysInPeriods(
+ { start, end },
+ { start: givenPeriodLeft, end: givenPeriodRight },
+ ),
+ ).toEqual({ daysOverlap: 0 });
+ });
+ });
+
+ describe('when date periods contain an invalid Date', () => {
+ const startInvalid = new Date(NaN);
+ const endInvalid = new Date(NaN);
+ const error = __('Invalid period');
+
+ it('throws an exception when the left period contains an invalid date', () => {
+ expect(() =>
+ datetimeUtility.getOverlappingDaysInPeriods({ 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 }),
+ ).toThrow(error);
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js
index f5c2a797df5..7c4c20e651f 100644
--- a/spec/frontend/lib/utils/dom_utils_spec.js
+++ b/spec/frontend/lib/utils/dom_utils_spec.js
@@ -45,7 +45,7 @@ describe('DOM Utils', () => {
});
describe('canScrollUp', () => {
- [1, 100].forEach(scrollTop => {
+ [1, 100].forEach((scrollTop) => {
it(`is true if scrollTop is > 0 (${scrollTop})`, () => {
expect(
canScrollUp({
@@ -55,7 +55,7 @@ describe('DOM Utils', () => {
});
});
- [0, -10].forEach(scrollTop => {
+ [0, -10].forEach((scrollTop) => {
it(`is false if scrollTop is <= 0 (${scrollTop})`, () => {
expect(
canScrollUp({
diff --git a/spec/frontend/lib/utils/favicon_ci_spec.js b/spec/frontend/lib/utils/favicon_ci_spec.js
new file mode 100644
index 00000000000..e35b008b862
--- /dev/null
+++ b/spec/frontend/lib/utils/favicon_ci_spec.js
@@ -0,0 +1,50 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon';
+import { setCiStatusFavicon } from '~/lib/utils/favicon_ci';
+
+jest.mock('~/lib/utils/favicon');
+
+const TEST_URL = '/test/pipelinable/1';
+const TEST_FAVICON = '/favicon.test.ico';
+
+describe('~/lib/utils/favicon_ci', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ mock = null;
+ });
+
+ describe('setCiStatusFavicon', () => {
+ it.each`
+ response | setFaviconOverlayCalls | resetFaviconCalls
+ ${{}} | ${[]} | ${[[]]}
+ ${{ favicon: TEST_FAVICON }} | ${[[TEST_FAVICON]]} | ${[]}
+ `(
+ 'with response=$response',
+ async ({ response, setFaviconOverlayCalls, resetFaviconCalls }) => {
+ mock.onGet(TEST_URL).replyOnce(200, response);
+
+ expect(setFaviconOverlay).not.toHaveBeenCalled();
+ expect(resetFavicon).not.toHaveBeenCalled();
+
+ await setCiStatusFavicon(TEST_URL);
+
+ expect(setFaviconOverlay.mock.calls).toEqual(setFaviconOverlayCalls);
+ expect(resetFavicon.mock.calls).toEqual(resetFaviconCalls);
+ },
+ );
+
+ it('with error', async () => {
+ mock.onGet(TEST_URL).replyOnce(500);
+
+ await expect(setCiStatusFavicon(TEST_URL)).rejects.toEqual(expect.any(Error));
+ expect(resetFavicon).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/favicon_spec.js b/spec/frontend/lib/utils/favicon_spec.js
new file mode 100644
index 00000000000..1b986432b8a
--- /dev/null
+++ b/spec/frontend/lib/utils/favicon_spec.js
@@ -0,0 +1,39 @@
+import { FaviconOverlayManager } from '@gitlab/favicon-overlay';
+import * as faviconUtils from '~/lib/utils/favicon';
+
+jest.mock('@gitlab/favicon-overlay');
+
+describe('~/lib/utils/favicon', () => {
+ afterEach(() => {
+ faviconUtils.clearMemoizeCache();
+ });
+
+ describe.each`
+ fnName | managerFn | args
+ ${'setFaviconOverlay'} | ${FaviconOverlayManager.setFaviconOverlay} | ${['test']}
+ ${'resetFavicon'} | ${FaviconOverlayManager.resetFaviconOverlay} | ${[]}
+ `('$fnName', ({ fnName, managerFn, args }) => {
+ const call = () => faviconUtils[fnName](...args);
+
+ it('initializes only once when called', async () => {
+ expect(FaviconOverlayManager.initialize).not.toHaveBeenCalled();
+
+ // Call twice so we can make sure initialize is only called once
+ await call();
+ await call();
+
+ expect(FaviconOverlayManager.initialize).toHaveBeenCalledWith({
+ faviconSelector: '#favicon',
+ });
+ expect(FaviconOverlayManager.initialize).toHaveBeenCalledTimes(1);
+ });
+
+ it('passes call to manager', async () => {
+ expect(managerFn).not.toHaveBeenCalled();
+
+ await call();
+
+ expect(managerFn).toHaveBeenCalledWith(...args);
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/forms_spec.js b/spec/frontend/lib/utils/forms_spec.js
index a69be99ab98..f65bd8ffe0c 100644
--- a/spec/frontend/lib/utils/forms_spec.js
+++ b/spec/frontend/lib/utils/forms_spec.js
@@ -1,7 +1,7 @@
import { serializeForm, serializeFormObject, isEmptyValue } from '~/lib/utils/forms';
describe('lib/utils/forms', () => {
- const createDummyForm = inputs => {
+ const createDummyForm = (inputs) => {
const form = document.createElement('form');
form.innerHTML = inputs
@@ -9,7 +9,7 @@ describe('lib/utils/forms', () => {
let str = ``;
if (type === 'select') {
str = `<select name="${name}">`;
- value.forEach(v => {
+ value.forEach((v) => {
if (v.length > 0) {
str += `<option value="${v}"></option> `;
}
@@ -81,8 +81,8 @@ describe('lib/utils/forms', () => {
jest
.spyOn(FormData.prototype, 'getAll')
- .mockImplementation(name =>
- formData.map(elem => (elem.name === name ? elem.value : undefined)),
+ .mockImplementation((name) =>
+ formData.map((elem) => (elem.name === name ? elem.value : undefined)),
);
const data = serializeForm(form);
diff --git a/spec/frontend/lib/utils/highlight_spec.js b/spec/frontend/lib/utils/highlight_spec.js
index 638bbf65ae9..f34e203f9a4 100644
--- a/spec/frontend/lib/utils/highlight_spec.js
+++ b/spec/frontend/lib/utils/highlight_spec.js
@@ -8,13 +8,13 @@ describe('highlight', () => {
});
it(`should return an empty string in the case of invalid inputs`, () => {
- [null, undefined].forEach(input => {
+ [null, undefined].forEach((input) => {
expect(highlight(input, 'match')).toBe('');
});
});
it(`should return the original value if match is null, undefined, or ''`, () => {
- [null, undefined].forEach(match => {
+ [null, undefined].forEach((match) => {
expect(highlight('gitlab', match)).toBe('gitlab');
});
});
diff --git a/spec/frontend/lib/utils/icon_utils_spec.js b/spec/frontend/lib/utils/icon_utils_spec.js
index f798dc6744d..db1f174703b 100644
--- a/spec/frontend/lib/utils/icon_utils_spec.js
+++ b/spec/frontend/lib/utils/icon_utils_spec.js
@@ -34,13 +34,13 @@ describe('Icon utils', () => {
});
it('extracts svg icon path content from sprite icons', () => {
- return getSvgIconPathContent(mockName).then(path => {
+ return getSvgIconPathContent(mockName).then((path) => {
expect(path).toBe(mockPath);
});
});
it('returns null if icon path content does not exist', () => {
- return getSvgIconPathContent('missing-icon').then(path => {
+ return getSvgIconPathContent('missing-icon').then((path) => {
expect(path).toBe(null);
});
});
@@ -58,22 +58,22 @@ describe('Icon utils', () => {
});
it('returns null', () => {
- return getSvgIconPathContent(mockName).then(path => {
+ return getSvgIconPathContent(mockName).then((path) => {
expect(path).toBe(null);
});
});
it('extracts svg icon path content, after 2 attempts', () => {
return getSvgIconPathContent(mockName)
- .then(path1 => {
+ .then((path1) => {
expect(path1).toBe(null);
return getSvgIconPathContent(mockName);
})
- .then(path2 => {
+ .then((path2) => {
expect(path2).toBe(null);
return getSvgIconPathContent(mockName);
})
- .then(path3 => {
+ .then((path3) => {
expect(path3).toBe(mockPath);
});
});
diff --git a/spec/frontend/lib/utils/mock_data.js b/spec/frontend/lib/utils/mock_data.js
index c466b0cd1ed..df1f79529e7 100644
--- a/spec/frontend/lib/utils/mock_data.js
+++ b/spec/frontend/lib/utils/mock_data.js
@@ -3,6 +3,3 @@ export const faviconDataUrl =
export const overlayDataUrl =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA85JREFUWAntVllIVGEUPv/9b46O41KplYN7PeRkti8TjQlhCUGh3MmeQugpIsGKAi2soIcIooiohxYKK2daqDAlIpIiWwxtQaJcaHE0d5tMrbn37z9XRqfR0TvVW56Hudf//uec72zfEWBCJjIwkYGJDPzvGSD/KgExN3Oi2Q+2DJgSDYQEMwItVGH1iZGmJw/Si1y+/PwVAMYYib22MYc/8hVQFgKDEfYoId0KYzagAQebsos/ewMZoeB9wdffcTYpQSaCTWHKoqSQaDk7zkIt0+aCUR8BelEHrf3dUNv9AcqbnsHtT5UKB/hTASh0SLYjnjb/CIDRJi0XiFAaJOpCD8zLpdb4NB66b1OfelthX815dtdRRfiti2aAXLvVLiMQ6olGyztGDkSo4JGGXk8/QFdGpYzpHG2GBQTDhtgVhPEaVbbVpvI6GJz22rv4TcAfrYI1x7Rj5MWWAppomKFVVb2302SFzUkZHAbkG+0b1+Gh77yNYjrmqnWTrLBLRxdvBWv8qlFujH/kYjJYyvLkj71t78zAUvzMAMnHhpN4zf9UREJhd8omyssxu1IgazQDwDnHUcNuH6vhPIE1fmuBzHt74Hn7W89jWGtcAjoaIDOFrdcMYJBkgOCoaRF0Lj0oglddDbCj6tRvKjphEpgjkzEQs2YAKsNxMzjn3nKurhzK+Ly7xe28ua8TwgMMcHJZnvvT0BPtEEKM4tDJ+C8GvIIk4ylINIXVZ0EUKJxYuh3mhCeokbudl6TtVc88dfBdLwbyaWB6zQCYQJpBYSrDGQxBQ/ZWRM2B+VNmQnVnHWx7elyNuL2/R336co7KyJR8CL9oLgEuFlREevWUkEl6uGwpVEG4FBm0OEf9N10NMgPlvWYAuNVwsWDKvcUNYsHUWTCZ13ysyFEXe6TO6aC8CUr9IiK+A05TQrc8yjwmxARHeeMAPlfQJw+AQRwu0YhL/GDXi9NwufG+S8dYkuYMqIb4SsWthotlNMOUCOM6r+G9cqXxPmd1dqrBav/o1zJy2l5/NUjJA/VORwYuFnOUaTQcPs9wMqwV++Xv8oADxKAcZ8nLPr8AoGW+xR6HSqYk3GodAz2QNj0V+Gr26dT9ASNH5239Pf0gktVNWZca8ZvfAFBprWS6hSu1pqt++Y0PD+WIwDAhIWQGtzvSHDbcodfFUFB9hg1Gjs5LXqIdFL+acFBl+FddqYwdxsWC3I70OvgfUaA65zhq2O2c8VxYcyIGFTVlXegYtvCXANCQZJMobjVcLMjtSK/IcEgyOOe8Ve5w7ryKDefp2P3+C/5ohv8HZmVLAAAAAElFTkSuQmCC';
-
-export const faviconWithOverlayDataUrl =
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGtElEQVRYR8WXf3CT9R3H35/nSdIQIktrCf0RStI0FYRjVBAccxTq5MDBKUoz4ZyjbPO87q4yBsPDMdExTjlvIsdQexyI0oMBeuKhdjsNHhwcMgpjIlublLIm/UlJKZSSJs/z/e6+T5v0CQ22wB/7/pPck8/383l9fj6fEOec8H88NAjAS1LwknsFSVLU8WXd1rtm85LUeKnwGQKzjj3s33azvsEAAEIlnn8ByHL4/Pa7BgAQLCm8QOBOh88vDQkQeMxjMkcQEYKqYsyJWWPhgs/80TsFafzROJtkNIXFfYI0pfXqPeennjqlxPUNikBoTuEmEF+lCRBV3G0aQiWFrwH8d30AWJubGdiEfZzdGqDEEwbICnADQGGHry7zTr0X94IlnnMACggwAWh0+PxOvb5EBGqmTTNkj7ySxWS62C+g5Usm1Zn95YXG24UQ+r5n75Li6Ux4LBkyc7/4t5YSLSr6Lgg9UvBLcKocMEYKON/gGB3YoA/bcGFCczzLQdieLE9bHL66FakBSjzCU0cSAHDa4at7aLhG9XLBEk8zAVnxZxyIEhBy+PwFgwAafpxvNzK5NZUhrX28JA07Cl6SmtvcOUwm4ZAouHj7ad+jMrN1dqb3iG7oS4EYPh2etQS+XiesC8TQ3ZD3yZJsHuUPgbMcI+ej5v3ncv5PasNlk1p7JJnzJL+I0/O5h+u0VCdqIDi78AQRHuirft3hYJzQPvawPydVdPI+/OnTnNNKBjYVXHRa8rFFGeb4w1he0wZ7d/84IXTEhxzxUsgitB2LPFGwvgGUfLSeZUpEXqEqrIdz0nr4iHOUfeOccb/tNMtutzWHPeWcJc0aMxm5lkxYDGloj1zB+Sv/RXXTSXzaeBwSY3j+bHNv2bdtMYCbpHtRkNFd36xFQN3tXkZhvgP1fdPi5kMEXL4oIXKVAA58M8aCVQs84BYLXi5aDq+zGJTqYr+i4PV2vHxmJ/7WUoOn2i/jz6yhW7JjrdSV8U4fQFV+I2Q4UIsedMCSSlcsgp72WtnSajOhzDsBNtsYfFD8e+Rbs4fdIG98uw9vnj+AX7FWvk4NHZOXXphF/INx2SpJIU2L8L4GDAoMwlP9kWSg6awcKVs83tyUnY5Dj75+W8bjutae3o5d9X/HTiWAuUtOS6RUOR8Hp48TxjgU/AMSeKJ1Ej/tMWXG1sxwGt98sBxe5+xhe64XVLiK2Z9XwNgdRLXyzQsC4ENwelIHAFxDBOdh1qdCdNLCoon8RnY+HZ6/+TtzPhTZweAxlJ94C5VqoI2U3a7rACzJjQqgBd24CGscos1kxPQZ38fqSU/jhQkDvN9lrKG7FeUnNuPVKcvwYOb4hGgvi2HSx8vwRKyJkVLl+hk43gdBAcfADBD1cA4RXIdZ1EN1Zjqem+DGoUc2oigjMUlvaV8YL/1qPVpuhOG+JwdH5m1Okn3m6Eacaz3V2jeI9uTbVYY6AKOSKw8MX0MBg2lXjh3r3Hk4s7ASdrMtSWxnoBpZIzIwP3e69lxv3Gay4q/F6zDJ5kq6s6amEnsafJ0Db8P9JKkx1w5wPJuY36IToojgNMzb8rLwmsuB2kW7YDWMSCgTg+YXx9+AQZKxdUaFZiju+a2Mi8uvnH0f2/2f9g4AVE4z4LlTilrlehag9xIpEam4jO4DXfdaV97nwtH5byW137VYD5Yc2YAz4YAGIYx2RLq0z1Sex8l//fUWfBI83jh4Kd1PEuAwqVGjWEwSS+nJJmt0sWu86d0frMQCR/LbWQ8hDAxlXMgUV69Q67ubv0q5FUNAlHKmVLnXE/gfREpUiaQHqAizXbO0UN98BMTSo39Cw7UW7E2Rc728qJGHP68ASbQyNYCQTkAUzCSwQ+CwvSjnsQPGLOnI/C0YO3Lwxq5yhhtqb1KNpGqT1TXvigJU0jh33xpAf7NymoGNDJ9sJtPkYuNkqTh7KnY8vGaoeZPy93+GA1joe4kzzv/SVLqvYngA/dFgVfnlb8tjtm6Ux+I39y/Gqone24IQM+GxL15UO3q7WrhsnhJatCs8PAC9md3OrPK0goaDyEj7uXsuXi0qg4HkIUGE52XHNqmXIl0RGOiHoUV7xb+v5K14SC39At79Ximdhc8ekjImuiyjsXryUszLnY40yThIhSi4bbUHsbfBJ6ZKE5dpQdz4HQOgf2a8tLvklY+M6cuvSnJummxSZ46+X+7biMzaRnSu84IauNYsE5HCOX+HDCPWi7DrKW8/BTcVZ2UN8Me57kc5448TaCYR5XJwC0BtHMwPjs/SgAP1pfuCqSL8Pxhr/wunLWAOAAAAAElFTkSuQmCC';
diff --git a/spec/frontend/lib/utils/poll_spec.js b/spec/frontend/lib/utils/poll_spec.js
index 135c752b5cb..f2ca5df3672 100644
--- a/spec/frontend/lib/utils/poll_spec.js
+++ b/spec/frontend/lib/utils/poll_spec.js
@@ -50,7 +50,7 @@ describe('Poll', () => {
};
});
- it('calls the success callback when no header for interval is provided', done => {
+ it('calls the success callback when no header for interval is provided', (done) => {
mockServiceCall({ status: 200 });
setup();
@@ -62,7 +62,7 @@ describe('Poll', () => {
});
});
- it('calls the error callback when the http request returns an error', done => {
+ it('calls the error callback when the http request returns an error', (done) => {
mockServiceCall({ status: 500 }, true);
setup();
@@ -74,7 +74,7 @@ describe('Poll', () => {
});
});
- it('skips the error callback when request is aborted', done => {
+ it('skips the error callback when request is aborted', (done) => {
mockServiceCall({ status: 0 }, true);
setup();
@@ -87,7 +87,7 @@ describe('Poll', () => {
});
});
- it('should call the success callback when the interval header is -1', done => {
+ it('should call the success callback when the interval header is -1', (done) => {
mockServiceCall({ status: 200, headers: { 'poll-interval': -1 } });
setup()
.then(() => {
@@ -100,8 +100,8 @@ describe('Poll', () => {
});
describe('for 2xx status code', () => {
- successCodes.forEach(httpCode => {
- it(`starts polling when http status is ${httpCode} and interval header is provided`, done => {
+ successCodes.forEach((httpCode) => {
+ it(`starts polling when http status is ${httpCode} and interval header is provided`, (done) => {
mockServiceCall({ status: httpCode, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
@@ -129,7 +129,7 @@ describe('Poll', () => {
});
describe('with delayed initial request', () => {
- it('delays the first request', async done => {
+ it('delays the first request', async (done) => {
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
@@ -158,7 +158,7 @@ describe('Poll', () => {
});
describe('stop', () => {
- it('stops polling when method is called', done => {
+ it('stops polling when method is called', (done) => {
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
@@ -186,7 +186,7 @@ describe('Poll', () => {
});
describe('enable', () => {
- it('should enable polling upon a response', done => {
+ it('should enable polling upon a response', (done) => {
mockServiceCall({ status: 200 });
const Polling = new Poll({
resource: service,
@@ -212,7 +212,7 @@ describe('Poll', () => {
});
describe('restart', () => {
- it('should restart polling when its called', done => {
+ it('should restart polling when its called', (done) => {
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
diff --git a/spec/frontend/lib/utils/poll_until_complete_spec.js b/spec/frontend/lib/utils/poll_until_complete_spec.js
index c1df30756fd..38203c460e3 100644
--- a/spec/frontend/lib/utils/poll_until_complete_spec.js
+++ b/spec/frontend/lib/utils/poll_until_complete_spec.js
@@ -70,7 +70,7 @@ describe('pollUntilComplete', () => {
});
it('rejects with the error response', () =>
- pollUntilComplete(endpoint).catch(error => {
+ pollUntilComplete(endpoint).catch((error) => {
expect(error.response.data).toBe(errorMessage);
}));
});
diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js
index 9c50bf577dc..1f3659b5c76 100644
--- a/spec/frontend/lib/utils/text_utility_spec.js
+++ b/spec/frontend/lib/utils/text_utility_spec.js
@@ -300,13 +300,13 @@ describe('text_utility', () => {
});
it(`should return an empty string for invalid inputs`, () => {
- [undefined, null, 4, {}, true, new Date()].forEach(input => {
+ [undefined, null, 4, {}, true, new Date()].forEach((input) => {
expect(textUtils.truncateNamespace(input)).toBe('');
});
});
it(`should not alter strings that aren't formatted as namespaces`, () => {
- ['', ' ', '\t', 'a', 'a \\ b'].forEach(input => {
+ ['', ' ', '\t', 'a', 'a \\ b'].forEach((input) => {
expect(textUtils.truncateNamespace(input)).toBe(input);
});
});
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index 0f9290e36b5..5846acbdb79 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -15,7 +15,7 @@ const shas = {
],
};
-const setWindowLocation = value => {
+const setWindowLocation = (value) => {
Object.defineProperty(window, 'location', {
writable: true,
value,
@@ -337,7 +337,7 @@ describe('URL utility', () => {
describe('urlContainsSha', () => {
it('returns true when there is a valid 40-character SHA1 hash in the URL', () => {
- shas.valid.forEach(sha => {
+ shas.valid.forEach((sha) => {
expect(
urlUtils.urlContainsSha({ url: `http://urlstuff/${sha}/moreurlstuff` }),
).toBeTruthy();
@@ -345,7 +345,7 @@ describe('URL utility', () => {
});
it('returns false when there is not a valid 40-character SHA1 hash in the URL', () => {
- shas.invalid.forEach(str => {
+ shas.invalid.forEach((str) => {
expect(urlUtils.urlContainsSha({ url: `http://urlstuff/${str}/moreurlstuff` })).toBeFalsy();
});
});
@@ -356,8 +356,8 @@ describe('URL utility', () => {
let invalidUrls = [];
beforeAll(() => {
- validUrls = shas.valid.map(sha => `http://urlstuff/${sha}/moreurlstuff`);
- invalidUrls = shas.invalid.map(str => `http://urlstuff/${str}/moreurlstuff`);
+ validUrls = shas.valid.map((sha) => `http://urlstuff/${sha}/moreurlstuff`);
+ invalidUrls = shas.invalid.map((str) => `http://urlstuff/${str}/moreurlstuff`);
});
it('returns the valid 40-character SHA1 hash from the URL', () => {
@@ -367,7 +367,7 @@ describe('URL utility', () => {
});
it('returns null from a URL with no valid 40-character SHA1 hash', () => {
- invalidUrls.forEach(url => {
+ invalidUrls.forEach((url) => {
expect(urlUtils.getShaFromUrl({ url })).toBeNull();
});
});
@@ -589,11 +589,11 @@ describe('URL utility', () => {
];
describe('with URL constructor support', () => {
- it.each(safeUrls)('returns true for %s', url => {
+ it.each(safeUrls)('returns true for %s', (url) => {
expect(urlUtils.isSafeURL(url)).toBe(true);
});
- it.each(unsafeUrls)('returns false for %s', url => {
+ it.each(unsafeUrls)('returns false for %s', (url) => {
expect(urlUtils.isSafeURL(url)).toBe(false);
});
});
@@ -807,7 +807,7 @@ describe('URL utility', () => {
it.each([[httpProtocol], [httpsProtocol]])(
'when no url passed, returns correct protocol for %i from window location',
- protocol => {
+ (protocol) => {
setWindowLocation({
protocol,
});
diff --git a/spec/frontend/lib/utils/users_cache_spec.js b/spec/frontend/lib/utils/users_cache_spec.js
index 7ed87123482..4034f39ee9c 100644
--- a/spec/frontend/lib/utils/users_cache_spec.js
+++ b/spec/frontend/lib/utils/users_cache_spec.js
@@ -1,4 +1,4 @@
-import Api from '~/api';
+import * as UserApi from '~/api/user_api';
import UsersCache from '~/lib/utils/users_cache';
describe('UsersCache', () => {
@@ -88,10 +88,12 @@ describe('UsersCache', () => {
let apiSpy;
beforeEach(() => {
- jest.spyOn(Api, 'users').mockImplementation((query, options) => apiSpy(query, options));
+ jest
+ .spyOn(UserApi, 'getUsers')
+ .mockImplementation((query, options) => apiSpy(query, options));
});
- it('stores and returns data from API call if cache is empty', done => {
+ it('stores and returns data from API call if cache is empty', (done) => {
apiSpy = (query, options) => {
expect(query).toBe('');
expect(options).toEqual({
@@ -104,7 +106,7 @@ describe('UsersCache', () => {
};
UsersCache.retrieve(dummyUsername)
- .then(user => {
+ .then((user) => {
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUsername]).toBe(dummyUser);
})
@@ -112,7 +114,7 @@ describe('UsersCache', () => {
.catch(done.fail);
});
- it('returns undefined if Ajax call fails and cache is empty', done => {
+ it('returns undefined if Ajax call fails and cache is empty', (done) => {
const dummyError = new Error('server exploded');
apiSpy = (query, options) => {
@@ -125,21 +127,21 @@ describe('UsersCache', () => {
};
UsersCache.retrieve(dummyUsername)
- .then(user => done.fail(`Received unexpected user: ${JSON.stringify(user)}`))
- .catch(error => {
+ .then((user) => done.fail(`Received unexpected user: ${JSON.stringify(user)}`))
+ .catch((error) => {
expect(error).toBe(dummyError);
})
.then(done)
.catch(done.fail);
});
- it('makes no Ajax call if matching data exists', done => {
+ it('makes no Ajax call if matching data exists', (done) => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
apiSpy = () => done.fail(new Error('expected no Ajax call!'));
UsersCache.retrieve(dummyUsername)
- .then(user => {
+ .then((user) => {
expect(user).toBe(dummyUser);
})
.then(done)
@@ -151,11 +153,11 @@ describe('UsersCache', () => {
let apiSpy;
beforeEach(() => {
- jest.spyOn(Api, 'user').mockImplementation(id => apiSpy(id));
+ jest.spyOn(UserApi, 'getUser').mockImplementation((id) => apiSpy(id));
});
- it('stores and returns data from API call if cache is empty', done => {
- apiSpy = id => {
+ it('stores and returns data from API call if cache is empty', (done) => {
+ apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.resolve({
@@ -164,7 +166,7 @@ describe('UsersCache', () => {
};
UsersCache.retrieveById(dummyUserId)
- .then(user => {
+ .then((user) => {
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUserId]).toBe(dummyUser);
})
@@ -172,31 +174,31 @@ describe('UsersCache', () => {
.catch(done.fail);
});
- it('returns undefined if Ajax call fails and cache is empty', done => {
+ it('returns undefined if Ajax call fails and cache is empty', (done) => {
const dummyError = new Error('server exploded');
- apiSpy = id => {
+ apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.reject(dummyError);
};
UsersCache.retrieveById(dummyUserId)
- .then(user => done.fail(`Received unexpected user: ${JSON.stringify(user)}`))
- .catch(error => {
+ .then((user) => done.fail(`Received unexpected user: ${JSON.stringify(user)}`))
+ .catch((error) => {
expect(error).toBe(dummyError);
})
.then(done)
.catch(done.fail);
});
- it('makes no Ajax call if matching data exists', done => {
+ it('makes no Ajax call if matching data exists', (done) => {
UsersCache.internalStorage[dummyUserId] = dummyUser;
apiSpy = () => done.fail(new Error('expected no Ajax call!'));
UsersCache.retrieveById(dummyUserId)
- .then(user => {
+ .then((user) => {
expect(user).toBe(dummyUser);
})
.then(done)
@@ -208,11 +210,11 @@ describe('UsersCache', () => {
let apiSpy;
beforeEach(() => {
- jest.spyOn(Api, 'userStatus').mockImplementation(id => apiSpy(id));
+ jest.spyOn(UserApi, 'getUserStatus').mockImplementation((id) => apiSpy(id));
});
- it('stores and returns data from API call if cache is empty', done => {
- apiSpy = id => {
+ it('stores and returns data from API call if cache is empty', (done) => {
+ apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.resolve({
@@ -221,7 +223,7 @@ describe('UsersCache', () => {
};
UsersCache.retrieveStatusById(dummyUserId)
- .then(userStatus => {
+ .then((userStatus) => {
expect(userStatus).toBe(dummyUserStatus);
expect(UsersCache.internalStorage[dummyUserId].status).toBe(dummyUserStatus);
})
@@ -229,25 +231,25 @@ describe('UsersCache', () => {
.catch(done.fail);
});
- it('returns undefined if Ajax call fails and cache is empty', done => {
+ it('returns undefined if Ajax call fails and cache is empty', (done) => {
const dummyError = new Error('server exploded');
- apiSpy = id => {
+ apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.reject(dummyError);
};
UsersCache.retrieveStatusById(dummyUserId)
- .then(userStatus => done.fail(`Received unexpected user: ${JSON.stringify(userStatus)}`))
- .catch(error => {
+ .then((userStatus) => done.fail(`Received unexpected user: ${JSON.stringify(userStatus)}`))
+ .catch((error) => {
expect(error).toBe(dummyError);
})
.then(done)
.catch(done.fail);
});
- it('makes no Ajax call if matching data exists', done => {
+ it('makes no Ajax call if matching data exists', (done) => {
UsersCache.internalStorage[dummyUserId] = {
status: dummyUserStatus,
};
@@ -255,7 +257,7 @@ describe('UsersCache', () => {
apiSpy = () => done.fail(new Error('expected no Ajax call!'));
UsersCache.retrieveStatusById(dummyUserId)
- .then(userStatus => {
+ .then((userStatus) => {
expect(userStatus).toBe(dummyUserStatus);
})
.then(done)
diff --git a/spec/frontend/line_highlighter_spec.js b/spec/frontend/line_highlighter_spec.js
index 0da1ea1df2d..1091bbf8aba 100644
--- a/spec/frontend/line_highlighter_spec.js
+++ b/spec/frontend/line_highlighter_spec.js
@@ -2,6 +2,7 @@
import $ from 'jquery';
import LineHighlighter from '~/line_highlighter';
+import * as utils from '~/lib/utils/common_utils';
describe('LineHighlighter', () => {
const testContext = {};
@@ -50,10 +51,10 @@ describe('LineHighlighter', () => {
});
it('scrolls to the first highlighted line on initial load', () => {
- const spy = jest.spyOn($, 'scrollTo');
+ jest.spyOn(utils, 'scrollToElement');
new LineHighlighter({ hash: '#L5-25' });
- expect(spy).toHaveBeenCalledWith('#L5', expect.anything());
+ expect(utils.scrollToElement).toHaveBeenCalledWith('#L5', expect.anything());
});
it('discards click events', () => {
@@ -88,9 +89,7 @@ describe('LineHighlighter', () => {
describe('clickHandler', () => {
it('handles clicking on a child icon element', () => {
const spy = jest.spyOn(testContext.class, 'setHash');
- $('#L13 i')
- .mousedown()
- .click();
+ $('#L13 [data-testid="link-icon"]').mousedown().click();
expect(spy).toHaveBeenCalledWith(13);
expect($('#LC13')).toHaveClass(testContext.css);
diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js
index e32deaea993..351ff317feb 100644
--- a/spec/frontend/logs/components/environment_logs_spec.js
+++ b/spec/frontend/logs/components/environment_logs_spec.js
@@ -20,7 +20,7 @@ jest.mock('~/lib/utils/scroll_utils');
const module = 'environmentLogs';
jest.mock('lodash/throttle', () =>
- jest.fn(func => {
+ jest.fn((func) => {
return func;
}),
);
@@ -59,7 +59,7 @@ describe('EnvironmentLogs', () => {
const findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' });
const findLogTrace = () => wrapper.find({ ref: 'logTrace' });
const findLogFooter = () => wrapper.find({ ref: 'logFooter' });
- const getInfiniteScrollAttr = attr => parseInt(findInfiniteScroll().attributes(attr), 10);
+ const getInfiniteScrollAttr = (attr) => parseInt(findInfiniteScroll().attributes(attr), 10);
const mockSetInitData = () => {
state.pods.options = mockPods;
@@ -181,11 +181,7 @@ describe('EnvironmentLogs', () => {
it('shows a logs trace', () => {
expect(findLogTrace().text()).toBe('');
- expect(
- findLogTrace()
- .find('.js-build-loader-animation')
- .isVisible(),
- ).toBe(true);
+ expect(findLogTrace().find('.js-build-loader-animation').isVisible()).toBe(true);
});
});
@@ -217,7 +213,7 @@ describe('EnvironmentLogs', () => {
describe('state with data', () => {
beforeEach(() => {
- dispatch.mockImplementation(actionName => {
+ dispatch.mockImplementation((actionName) => {
if (actionName === `${module}/setInitData`) {
mockSetInitData();
} else if (actionName === `${module}/showPodLogs`) {
diff --git a/spec/frontend/logs/components/log_advanced_filters_spec.js b/spec/frontend/logs/components/log_advanced_filters_spec.js
index 3a3c23c95b8..dfa8913a301 100644
--- a/spec/frontend/logs/components/log_advanced_filters_spec.js
+++ b/spec/frontend/logs/components/log_advanced_filters_spec.js
@@ -18,10 +18,10 @@ describe('LogAdvancedFilters', () => {
const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
const findTimeRangePicker = () => wrapper.find({ ref: 'dateTimePicker' });
- const getSearchToken = type =>
+ const getSearchToken = (type) =>
findFilteredSearch()
.props('availableTokens')
- .filter(token => token.type === type)[0];
+ .filter((token) => token.type === type)[0];
const mockStateLoading = () => {
state.timeRange.selected = defaultTimeRange;
@@ -73,6 +73,8 @@ describe('LogAdvancedFilters', () => {
});
it('displays search tokens', () => {
+ initWrapper();
+
expect(getSearchToken(TOKEN_TYPE_POD_NAME)).toMatchObject({
title: 'Pod name',
unique: true,
diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js
index dff38ecb15e..55b28445786 100644
--- a/spec/frontend/logs/components/log_control_buttons_spec.js
+++ b/spec/frontend/logs/components/log_control_buttons_spec.js
@@ -9,7 +9,7 @@ describe('LogControlButtons', () => {
const findScrollToBottom = () => wrapper.find('.js-scroll-to-bottom');
const findRefreshBtn = () => wrapper.find('.js-refresh-log');
- const initWrapper = opts => {
+ const initWrapper = (opts) => {
wrapper = shallowMount(LogControlButtons, {
listeners: {
scrollUp: () => {},
diff --git a/spec/frontend/logs/components/log_simple_filters_spec.js b/spec/frontend/logs/components/log_simple_filters_spec.js
index b819f0d25a8..5bd42fd7dbc 100644
--- a/spec/frontend/logs/components/log_simple_filters_spec.js
+++ b/spec/frontend/logs/components/log_simple_filters_spec.js
@@ -18,7 +18,7 @@ describe('LogSimpleFilters', () => {
const findPodsDropdownItems = () =>
findPodsDropdown()
.findAll(GlDropdownItem)
- .filter(item => !('disabled' in item.attributes()));
+ .filter((item) => !('disabled' in item.attributes()));
const mockPodsLoading = () => {
state.pods.options = [];
diff --git a/spec/frontend/logs/stores/actions_spec.js b/spec/frontend/logs/stores/actions_spec.js
index e4501abdc76..bc58f1e677f 100644
--- a/spec/frontend/logs/stores/actions_spec.js
+++ b/spec/frontend/logs/stores/actions_spec.js
@@ -62,7 +62,7 @@ describe('Logs Store actions', () => {
const latestGetParams = () => mock.history.get[mock.history.get.length - 1].params;
- convertToFixedRange.mockImplementation(range => {
+ convertToFixedRange.mockImplementation((range) => {
if (range === defaultTimeRange) {
return { ...mockDefaultRange };
}
diff --git a/spec/frontend/logs/stores/mutations_spec.js b/spec/frontend/logs/stores/mutations_spec.js
index 4a095e0f26e..51f6494b011 100644
--- a/spec/frontend/logs/stores/mutations_spec.js
+++ b/spec/frontend/logs/stores/mutations_spec.js
@@ -23,7 +23,7 @@ describe('Logs Store Mutations', () => {
});
it('ensures mutation types are correctly named', () => {
- Object.keys(types).forEach(k => {
+ Object.keys(types).forEach((k) => {
expect(k).toEqual(types[k]);
});
});
diff --git a/spec/frontend/matchers.js b/spec/frontend/matchers.js
index 50feba86a61..945abdafe9a 100644
--- a/spec/frontend/matchers.js
+++ b/spec/frontend/matchers.js
@@ -10,7 +10,7 @@ export default {
const iconReferences = [].slice.apply(element.querySelectorAll('svg use'));
const matchingIcon = iconReferences.find(
- reference => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`,
+ (reference) => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`,
);
const pass = Boolean(matchingIcon);
@@ -21,7 +21,7 @@ export default {
} else {
message = `${element.outerHTML} does not contain the sprite icon "${iconName}"!`;
- const existingIcons = iconReferences.map(reference => {
+ const existingIcons = iconReferences.map((reference) => {
const iconUrl = reference.getAttribute('href');
return `"${iconUrl.replace(/^.+#/, '')}"`;
});
@@ -40,10 +40,7 @@ export default {
let clearMatch;
try {
- clearReceived = received
- .replace(/\s\s+/gm, ' ')
- .replace(/\s\./gm, '.')
- .trim();
+ clearReceived = received.replace(/\s\s+/gm, ' ').replace(/\s\./gm, '.').trim();
} catch (e) {
return { actual: received, message: 'The received value is not a string', pass: false };
}
diff --git a/spec/frontend/matchers_spec.js b/spec/frontend/matchers_spec.js
index 0a2478f978a..dfd6f754c72 100644
--- a/spec/frontend/matchers_spec.js
+++ b/spec/frontend/matchers_spec.js
@@ -3,7 +3,7 @@ describe('Custom jest matchers', () => {
describe('malformed input', () => {
it.each([null, 1, Symbol, Array, Object])(
'fails graciously if the expected value is %s',
- expected => {
+ (expected) => {
expect(expected).not.toMatchInterpolatedText('null');
},
);
@@ -11,7 +11,7 @@ describe('Custom jest matchers', () => {
describe('malformed matcher', () => {
it.each([null, 1, Symbol, Array, Object])(
'fails graciously if the matcher is %s',
- matcher => {
+ (matcher) => {
expect('null').not.toMatchInterpolatedText(matcher);
},
);
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 9a8434a1222..30166e2d5ae 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
@@ -49,7 +49,7 @@ describe('AccessRequestActionButtons', () => {
describe('when member is the current user', () => {
it('sets `message` prop correctly', () => {
expect(findRemoveMemberButton().props('message')).toBe(
- `Are you sure you want to withdraw your access request for "${member.source.name}"`,
+ `Are you sure you want to withdraw your access request for "${member.source.fullName}"`,
);
});
});
@@ -64,7 +64,7 @@ describe('AccessRequestActionButtons', () => {
});
expect(findRemoveMemberButton().props('message')).toBe(
- `Are you sure you want to deny ${member.user.name}'s request to join "${member.source.name}"`,
+ `Are you sure you want to deny ${member.user.name}'s request to join "${member.source.fullName}"`,
);
});
});
diff --git a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
index 887b21dc1d0..fe63f9bfaa7 100644
--- a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
@@ -39,7 +39,7 @@ describe('InviteActionButtons', () => {
it('sets props correctly', () => {
expect(findRemoveMemberButton().props()).toEqual({
memberId: member.id,
- message: `Are you sure you want to revoke the invitation for ${member.invite.email} to join "${member.source.name}"`,
+ message: `Are you sure you want to revoke the invitation for ${member.invite.email} to join "${member.source.fullName}"`,
title: 'Revoke invite',
isAccessRequest: false,
icon: 'remove',
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 a48942dd277..05ea0dc2886 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
@@ -57,10 +57,8 @@ describe('ResendInviteButton', () => {
it('displays form with correct action and inputs', () => {
expect(findForm().attributes('action')).toBe('/groups/foo-bar/-/group_members/1/resend_invite');
- expect(
- findForm()
- .find('input[name="authenticity_token"]')
- .attributes('value'),
- ).toBe('mock-csrf-token');
+ expect(findForm().find('input[name="authenticity_token"]').attributes('value')).toBe(
+ 'mock-csrf-token',
+ );
});
});
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 b03e80a537d..f28e5040006 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
@@ -39,7 +39,7 @@ describe('UserActionButtons', () => {
it('sets props correctly', () => {
expect(findRemoveMemberButton().props()).toEqual({
memberId: member.id,
- message: `Are you sure you want to remove ${member.user.name} from "${member.source.name}"`,
+ message: `Are you sure you want to remove ${member.user.name} from "${member.source.fullName}"`,
title: 'Remove member',
isAccessRequest: false,
icon: 'remove',
@@ -56,7 +56,7 @@ describe('UserActionButtons', () => {
});
expect(findRemoveMemberButton().props('message')).toBe(
- `Are you sure you want to remove this orphaned member from "${orphanedMember.source.name}"`,
+ `Are you sure you want to remove this orphaned member from "${orphanedMember.source.fullName}"`,
);
});
});
diff --git a/spec/frontend/members/components/avatars/user_avatar_spec.js b/spec/frontend/members/components/avatars/user_avatar_spec.js
index 7d6a9065975..411ec1a54de 100644
--- a/spec/frontend/members/components/avatars/user_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/user_avatar_spec.js
@@ -22,7 +22,7 @@ describe('UserAvatar', () => {
const getByText = (text, options) =>
createWrapper(within(wrapper.element).findByText(text, options));
- const findStatusEmoji = emoji => wrapper.find(`gl-emoji[data-name="${emoji}"]`);
+ const findStatusEmoji = (emoji) => wrapper.find(`gl-emoji[data-name="${emoji}"]`);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
index 91277ae6d03..0d9f9acbbeb 100644
--- a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
+++ b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
@@ -10,7 +10,7 @@ localVue.use(Vuex);
describe('FilterSortContainer', () => {
let wrapper;
- const createComponent = state => {
+ const createComponent = (state) => {
const store = new Vuex.Store({
state: {
filteredSearchBar: {
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 ca885000c2f..2bed1e803ca 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
@@ -10,7 +10,7 @@ localVue.use(Vuex);
describe('MembersFilteredSearchBar', () => {
let wrapper;
- const createComponent = state => {
+ const createComponent = (state) => {
const store = new Vuex.Store({
state: {
sourceId: 1,
@@ -86,7 +86,10 @@ describe('MembersFilteredSearchBar', () => {
token: GlFilteredSearchToken,
unique: true,
operators: [{ value: '=', description: 'is' }],
- options: [{ value: 'exclude', title: 'Direct' }, { value: 'only', title: 'Inherited' }],
+ options: [
+ { value: 'exclude', title: 'Direct' },
+ { value: 'only', title: 'Inherited' },
+ ],
},
]);
});
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 6fe67aded3d..d98c9116512 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -12,7 +12,7 @@ describe('SortDropdown', () => {
const URL_HOST = 'https://localhost/';
- const createComponent = state => {
+ const createComponent = (state) => {
const store = new Vuex.Store({
state: {
sourceId: 1,
@@ -38,10 +38,10 @@ describe('SortDropdown', () => {
const findSortDirectionToggle = () =>
findSortingComponent().find('button[title="Sort direction"]');
const findDropdownToggle = () => wrapper.find('button[aria-haspopup="true"]');
- const findDropdownItemByText = text =>
+ const findDropdownItemByText = (text) =>
wrapper
.findAll(GlSortingItem)
- .wrappers.find(dropdownItemWrapper => dropdownItemWrapper.text() === text);
+ .wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.text() === text);
describe('dropdown options', () => {
beforeEach(() => {
@@ -76,7 +76,7 @@ describe('SortDropdown', () => {
createComponent();
- expectedDropdownItems.forEach(expectedDropdownItem => {
+ expectedDropdownItems.forEach((expectedDropdownItem) => {
const dropdownItem = findDropdownItemByText(expectedDropdownItem.label);
expect(dropdownItem).not.toBe(null);
diff --git a/spec/frontend/members/components/modals/leave_modal_spec.js b/spec/frontend/members/components/modals/leave_modal_spec.js
index d7acf12212c..dca47d1f6af 100644
--- a/spec/frontend/members/components/modals/leave_modal_spec.js
+++ b/spec/frontend/members/components/modals/leave_modal_spec.js
@@ -60,11 +60,11 @@ describe('LeaveModal', () => {
});
it('displays modal title', () => {
- expect(getByText(`Leave "${member.source.name}"`).exists()).toBe(true);
+ expect(getByText(`Leave "${member.source.fullName}"`).exists()).toBe(true);
});
it('displays modal body', () => {
- expect(getByText(`Are you sure you want to leave "${member.source.name}"?`).exists()).toBe(
+ expect(getByText(`Are you sure you want to leave "${member.source.fullName}"?`).exists()).toBe(
true,
);
});
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 593dbcd28ba..234857419b6 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
@@ -31,7 +31,7 @@ describe('RemoveGroupLinkModal', () => {
});
};
- const createComponent = state => {
+ const createComponent = (state) => {
wrapper = mount(RemoveGroupLinkModal, {
localVue,
store: createStore(state),
diff --git a/spec/frontend/members/components/table/created_at_spec.js b/spec/frontend/members/components/table/created_at_spec.js
index a9f809cd805..dc1f62722ab 100644
--- a/spec/frontend/members/components/table/created_at_spec.js
+++ b/spec/frontend/members/components/table/created_at_spec.js
@@ -13,7 +13,7 @@ describe('CreatedAt', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = mount(CreatedAt, {
propsData: {
date,
diff --git a/spec/frontend/members/components/table/expiration_datepicker_spec.js b/spec/frontend/members/components/table/expiration_datepicker_spec.js
index ba1b2256e76..0caaafb8d7b 100644
--- a/spec/frontend/members/components/table/expiration_datepicker_spec.js
+++ b/spec/frontend/members/components/table/expiration_datepicker_spec.js
@@ -25,7 +25,7 @@ describe('ExpirationDatepicker', () => {
actions = {
updateMemberExpiration: jest.fn(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolveUpdateMemberExpiration = resolve;
}),
),
@@ -72,11 +72,9 @@ describe('ExpirationDatepicker', () => {
});
it('sets `minDate` prop as tomorrow', () => {
- expect(
- findDatepicker()
- .props('minDate')
- .toISOString(),
- ).toBe(new Date('2020-3-16').toISOString());
+ expect(findDatepicker().props('minDate').toISOString()).toBe(
+ new Date('2020-3-16').toISOString(),
+ );
});
it('sets `target` prop as `null` so datepicker opens on focus', () => {
diff --git a/spec/frontend/members/components/table/expires_at_spec.js b/spec/frontend/members/components/table/expires_at_spec.js
index cf0fc78656e..321008727cd 100644
--- a/spec/frontend/members/components/table/expires_at_spec.js
+++ b/spec/frontend/members/components/table/expires_at_spec.js
@@ -10,7 +10,7 @@ describe('ExpiresAt', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = mount(ExpiresAt, {
propsData,
directives: {
@@ -22,7 +22,7 @@ describe('ExpiresAt', () => {
const getByText = (text, options) =>
createWrapper(within(wrapper.element).getByText(text, options));
- const getTooltipDirective = elementWrapper => getBinding(elementWrapper.element, 'gl-tooltip');
+ const getTooltipDirective = (elementWrapper) => getBinding(elementWrapper.element, 'gl-tooltip');
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/members/components/table/member_avatar_spec.js b/spec/frontend/members/components/table/member_avatar_spec.js
index 98177893c18..4341dfbbaf9 100644
--- a/spec/frontend/members/components/table/member_avatar_spec.js
+++ b/spec/frontend/members/components/table/member_avatar_spec.js
@@ -9,7 +9,7 @@ import InviteAvatar from '~/members/components/avatars/invite_avatar.vue';
describe('MemberList', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(MemberAvatar, {
propsData: {
isCurrentUser: false,
diff --git a/spec/frontend/members/components/table/member_source_spec.js b/spec/frontend/members/components/table/member_source_spec.js
index 48ac06f32f6..95547090aed 100644
--- a/spec/frontend/members/components/table/member_source_spec.js
+++ b/spec/frontend/members/components/table/member_source_spec.js
@@ -6,12 +6,12 @@ import MemberSource from '~/members/components/table/member_source.vue';
describe('MemberSource', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = mount(MemberSource, {
propsData: {
memberSource: {
id: 102,
- name: 'Foo bar',
+ fullName: 'Foo bar',
webUrl: 'https://gitlab.com/groups/foo-bar',
},
...propsData,
@@ -25,7 +25,7 @@ describe('MemberSource', () => {
const getByText = (text, options) =>
createWrapper(getByTextHelper(wrapper.element, text, options));
- const getTooltipDirective = elementWrapper => getBinding(elementWrapper.element, 'gl-tooltip');
+ const getTooltipDirective = (elementWrapper) => getBinding(elementWrapper.element, 'gl-tooltip');
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 9945cc7ee57..dbaccde069c 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -39,7 +39,7 @@ describe('MembersTable', () => {
});
};
- const createComponent = state => {
+ const createComponent = (state) => {
wrapper = mount(MembersTable, {
localVue,
store: createStore(state),
@@ -63,6 +63,10 @@ describe('MembersTable', () => {
createWrapper(getByTestIdHelper(wrapper.element, id, options));
const findTable = () => wrapper.find(GlTable);
+ const findTableCellByMemberId = (tableCellLabel, memberId) =>
+ getByTestId(`members-table-row-${memberId}`).find(
+ `[data-label="${tableCellLabel}"][role="cell"]`,
+ );
afterEach(() => {
wrapper.destroy();
@@ -100,10 +104,7 @@ describe('MembersTable', () => {
if (expectedComponent) {
expect(
- wrapper
- .find(`[data-label="${label}"][role="cell"]`)
- .find(expectedComponent)
- .exists(),
+ wrapper.find(`[data-label="${label}"][role="cell"]`).find(expectedComponent).exists(),
).toBe(true);
}
});
@@ -117,10 +118,7 @@ describe('MembersTable', () => {
expect(actionField.exists()).toBe(true);
expect(actionField.classes('gl-sr-only')).toBe(true);
expect(
- wrapper
- .find(`[data-label="Actions"][role="cell"]`)
- .find(MemberActionButtons)
- .exists(),
+ wrapper.find(`[data-label="Actions"][role="cell"]`).find(MemberActionButtons).exists(),
).toBe(true);
});
@@ -137,16 +135,30 @@ describe('MembersTable', () => {
canRemove: true,
};
+ const memberNoPermissions = {
+ ...memberMock,
+ id: 2,
+ };
+
describe.each`
permission | members
- ${'canUpdate'} | ${[memberCanUpdate]}
- ${'canRemove'} | ${[memberCanRemove]}
- ${'canResend'} | ${[invite]}
+ ${'canUpdate'} | ${[memberNoPermissions, memberCanUpdate]}
+ ${'canRemove'} | ${[memberNoPermissions, memberCanRemove]}
+ ${'canResend'} | ${[memberNoPermissions, invite]}
`('when one of the members has $permission permissions', ({ members }) => {
it('renders the "Actions" field', () => {
createComponent({ members, tableFields: ['actions'] });
expect(getByTestId('col-actions').exists()).toBe(true);
+
+ expect(findTableCellByMemberId('Actions', members[0].id).classes()).toStrictEqual([
+ 'col-actions',
+ 'gl-display-none!',
+ 'gl-display-lg-table-cell!',
+ ]);
+ expect(findTableCellByMemberId('Actions', members[1].id).classes()).toStrictEqual([
+ 'col-actions',
+ ]);
});
});
@@ -177,12 +189,9 @@ describe('MembersTable', () => {
it('renders badge in "Max role" field', () => {
createComponent({ members: [memberMock], tableFields: ['maxRole'] });
- expect(
- wrapper
- .find(`[data-label="Max role"][role="cell"]`)
- .find(GlBadge)
- .text(),
- ).toBe(memberMock.accessLevel.stringValue);
+ expect(wrapper.find(`[data-label="Max role"][role="cell"]`).find(GlBadge).text()).toBe(
+ memberMock.accessLevel.stringValue,
+ );
});
});
@@ -203,10 +212,6 @@ describe('MembersTable', () => {
it('adds QA selector to table row', () => {
createComponent();
- expect(
- findTable()
- .find('tbody tr')
- .attributes('data-qa-selector'),
- ).toBe('member_row');
+ expect(findTable().find('tbody tr').attributes('data-qa-selector')).toBe('member_row');
});
});
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index 6c6abf35bd7..96a388614f3 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -44,7 +44,7 @@ describe('RoleDropdown', () => {
const getDropdownMenu = () => within(wrapper.element).getByRole('menu');
const getByTextInDropdownMenu = (text, options = {}) =>
createWrapper(within(getDropdownMenu()).getByText(text, options));
- const getDropdownItemByText = text =>
+ const getDropdownItemByText = (text) =>
createWrapper(
within(getDropdownMenu())
.getByText(text, { selector: '[role="menuitem"] p' })
@@ -53,7 +53,7 @@ describe('RoleDropdown', () => {
const getCheckedDropdownItem = () =>
wrapper
.findAll(GlDropdownItem)
- .wrappers.find(dropdownItemWrapper => dropdownItemWrapper.props('isChecked'));
+ .wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.props('isChecked'));
const findDropdownToggle = () => wrapper.find('button[aria-haspopup="true"]');
const findDropdown = () => wrapper.find(GlDropdown);
@@ -63,7 +63,7 @@ describe('RoleDropdown', () => {
});
describe('when dropdown is open', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent();
findDropdownToggle().trigger('click');
@@ -73,7 +73,7 @@ describe('RoleDropdown', () => {
});
it('renders all valid roles', () => {
- Object.keys(member.validRoles).forEach(role => {
+ Object.keys(member.validRoles).forEach((role) => {
expect(getDropdownItemByText(role).exists()).toBe(true);
});
});
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index 5674929716d..e668f2a1998 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -7,7 +7,7 @@ export const member = {
accessLevel: { integerValue: 50, stringValue: 'Owner' },
source: {
id: 178,
- name: 'Foo Bar',
+ fullName: 'Foo Bar',
webUrl: 'https://gitlab.com/groups/foo-bar',
},
user: {
diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js
index 7bbfddf8fc6..7cd4e735b55 100644
--- a/spec/frontend/members/utils_spec.js
+++ b/spec/frontend/members/utils_spec.js
@@ -24,7 +24,7 @@ describe('Members Utils', () => {
it('has correct properties for each badge', () => {
const badges = generateBadges(memberMock, true);
- badges.forEach(badge => {
+ badges.forEach((badge) => {
expect(badge).toEqual(
expect.objectContaining({
show: expect.any(Boolean),
diff --git a/spec/frontend/merge_request/components/status_box_spec.js b/spec/frontend/merge_request/components/status_box_spec.js
new file mode 100644
index 00000000000..e6b6512476b
--- /dev/null
+++ b/spec/frontend/merge_request/components/status_box_spec.js
@@ -0,0 +1,81 @@
+import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf } from '@gitlab/ui';
+import StatusBox from '~/merge_request/components/status_box.vue';
+import mrEventHub from '~/merge_request/eventhub';
+
+let wrapper;
+
+function factory(propsData) {
+ wrapper = shallowMount(StatusBox, { propsData, stubs: { GlSprintf } });
+}
+
+const testCases = [
+ {
+ name: 'Open',
+ state: 'opened',
+ class: 'status-box-open',
+ icon: 'issue-open-m',
+ },
+ {
+ name: 'Closed',
+ state: 'closed',
+ class: 'status-box-mr-closed',
+ icon: 'close',
+ },
+ {
+ name: 'Merged',
+ state: 'merged',
+ class: 'status-box-mr-merged',
+ icon: 'git-merge',
+ },
+];
+
+describe('Merge request status box component', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ testCases.forEach((testCase) => {
+ describe(`when merge request is ${testCase.name}`, () => {
+ it('renders human readable test', () => {
+ factory({
+ initialState: testCase.state,
+ });
+
+ expect(wrapper.text()).toContain(testCase.name);
+ });
+
+ it('sets css class', () => {
+ factory({
+ initialState: testCase.state,
+ });
+
+ expect(wrapper.classes()).toContain(testCase.class);
+ });
+
+ it('renders icon', () => {
+ factory({
+ initialState: testCase.state,
+ });
+
+ expect(wrapper.find('[data-testid="status-icon"]').props('name')).toBe(testCase.icon);
+ });
+ });
+ });
+
+ it('updates with eventhub event', async () => {
+ factory({
+ initialState: 'opened',
+ });
+
+ expect(wrapper.text()).toContain('Open');
+
+ mrEventHub.$emit('mr.state.updated', { state: 'closed' });
+
+ await nextTick();
+
+ expect(wrapper.text()).toContain('Closed');
+ });
+});
diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js
index 1cb7206b97f..5624043260a 100644
--- a/spec/frontend/merge_request_spec.js
+++ b/spec/frontend/merge_request_spec.js
@@ -28,14 +28,11 @@ describe('MergeRequest', () => {
mock.restore();
});
- it('modifies the Markdown field', done => {
+ it('modifies the Markdown field', (done) => {
jest.spyOn($, 'ajax').mockImplementation();
const changeEvent = document.createEvent('HTMLEvents');
changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .first()
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
+ $('input[type=checkbox]').first().attr('checked', true)[0].dispatchEvent(changeEvent);
setImmediate(() => {
expect($('.js-task-list-field').val()).toBe(
'- [x] Task List Item\n- [ ]\n- [ ] Task List Item 2\n',
@@ -44,15 +41,12 @@ describe('MergeRequest', () => {
});
});
- it('ensure that task with only spaces does not get checked incorrectly', done => {
+ it('ensure that task with only spaces does not get checked incorrectly', (done) => {
// fixed in 'deckar01-task_list', '2.2.1' gem
jest.spyOn($, 'ajax').mockImplementation();
const changeEvent = document.createEvent('HTMLEvents');
changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .last()
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
+ $('input[type=checkbox]').last().attr('checked', true)[0].dispatchEvent(changeEvent);
setImmediate(() => {
expect($('.js-task-list-field').val()).toBe(
'- [ ] Task List Item\n- [ ]\n- [x] Task List Item 2\n',
@@ -67,7 +61,7 @@ describe('MergeRequest', () => {
const index = 3;
const checked = true;
- it('submits an ajax request on tasklist:changed', done => {
+ it('submits an ajax request on tasklist:changed', (done) => {
$('.js-task-list-field').trigger({
type: 'tasklist:changed',
detail: { lineNumber, lineSource, index, checked },
@@ -89,7 +83,7 @@ describe('MergeRequest', () => {
});
});
- it('shows an error notification when tasklist update failed', done => {
+ it('shows an error notification when tasklist update failed', (done) => {
mock
.onPatch(`${TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`)
.reply(409, {});
diff --git a/spec/frontend/merge_request_tabs_spec.js b/spec/frontend/merge_request_tabs_spec.js
index 85a4ee8974e..82462036219 100644
--- a/spec/frontend/merge_request_tabs_spec.js
+++ b/spec/frontend/merge_request_tabs_spec.js
@@ -5,7 +5,6 @@ import axios from '~/lib/utils/axios_utils';
import MergeRequestTabs from '~/merge_request_tabs';
import '~/commit/pipelines/pipelines_bundle';
import '~/lib/utils/common_utils';
-import 'vendor/jquery.scrollTo';
jest.mock('~/lib/utils/webpack', () => ({
resetServiceWorkersPublicPath: jest.fn(),
@@ -14,7 +13,7 @@ jest.mock('~/lib/utils/webpack', () => ({
describe('MergeRequestTabs', () => {
const testContext = {};
const stubLocation = {};
- const setLocation = stubs => {
+ const setLocation = (stubs) => {
const defaults = {
pathname: '',
search: '',
@@ -265,7 +264,7 @@ describe('MergeRequestTabs', () => {
beforeEach(() => {
jest.spyOn(mainContent, 'getBoundingClientRect').mockReturnValue({ top: 10 });
jest.spyOn(tabContent, 'getBoundingClientRect').mockReturnValue({ top: 100 });
- jest.spyOn(document, 'querySelector').mockImplementation(selector => {
+ jest.spyOn(document, 'querySelector').mockImplementation((selector) => {
return selector === '.content-wrapper' ? mainContent : tabContent;
});
testContext.class.currentAction = 'commits';
diff --git a/spec/frontend/milestones/milestone_combobox_spec.js b/spec/frontend/milestones/milestone_combobox_spec.js
index 047484f117f..8c519abe382 100644
--- a/spec/frontend/milestones/milestone_combobox_spec.js
+++ b/spec/frontend/milestones/milestone_combobox_spec.js
@@ -1,9 +1,9 @@
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
-import { s__ } from '~/locale';
import { ENTER_KEY } from '~/lib/utils/keys';
import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
import { projectMilestones, groupMilestones } from './mock_data';
@@ -14,8 +14,7 @@ const extraLinks = [
{ text: 'Manage milestones', url: '/h5bp/html5-boilerplate/-/milestones' },
];
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Milestone combobox component', () => {
const projectId = '8';
@@ -29,26 +28,31 @@ describe('Milestone combobox component', () => {
let searchApiCallSpy;
const createComponent = (props = {}, attrs = {}) => {
+ const propsData = {
+ projectId,
+ groupId,
+ groupMilestonesAvailable,
+ extraLinks,
+ value: [],
+ ...props,
+ };
+
wrapper = mount(MilestoneCombobox, {
- propsData: {
- projectId,
- groupId,
- groupMilestonesAvailable,
- extraLinks,
- value: [],
- ...props,
- },
+ propsData,
attrs,
listeners: {
// simulate a parent component v-model binding
- input: selectedMilestone => {
+ input: (selectedMilestone) => {
+ // ugly hack because setProps plays bad with immediate watchers
+ // see https://github.com/vuejs/vue-test-utils/issues/1140 and
+ // https://github.com/vuejs/vue-test-utils/pull/1752
+ propsData.value = selectedMilestone;
wrapper.setProps({ value: selectedMilestone });
},
},
stubs: {
GlSearchBoxByType: true,
},
- localVue,
store: createStore(),
});
};
@@ -71,13 +75,13 @@ describe('Milestone combobox component', () => {
mock
.onGet(`/api/v4/projects/${projectId}/milestones`)
- .reply(config => projectMilestonesApiCallSpy(config));
+ .reply((config) => projectMilestonesApiCallSpy(config));
mock
.onGet(`/api/v4/groups/${groupId}/milestones`)
- .reply(config => groupMilestonesApiCallSpy(config));
+ .reply((config) => groupMilestonesApiCallSpy(config));
- mock.onGet(`/api/v4/projects/${projectId}/search`).reply(config => searchApiCallSpy(config));
+ mock.onGet(`/api/v4/projects/${projectId}/search`).reply((config) => searchApiCallSpy(config));
});
afterEach(() => {
@@ -115,7 +119,7 @@ describe('Milestone combobox component', () => {
return projectMilestoneSection
.text()
- .includes(s__('MilestoneCombobox|An error occurred while searching for milestones'));
+ .includes('An error occurred while searching for milestones');
};
const groupMilestoneSectionContainsErrorMessage = () => {
@@ -123,13 +127,13 @@ describe('Milestone combobox component', () => {
return groupMilestoneSection
.text()
- .includes(s__('MilestoneCombobox|An error occurred while searching for milestones'));
+ .includes('An error occurred while searching for milestones');
};
//
// Convenience methods
//
- const updateQuery = newQuery => {
+ const updateQuery = (newQuery) => {
findSearchBox().vm.$emit('input', newQuery);
};
@@ -141,13 +145,13 @@ describe('Milestone combobox component', () => {
findFirstGroupMilestonesDropdownItem().vm.$emit('click');
};
- const waitForRequests = ({ andClearMocks } = { andClearMocks: false }) =>
- axios.waitForAll().then(() => {
- if (andClearMocks) {
- projectMilestonesApiCallSpy.mockClear();
- groupMilestonesApiCallSpy.mockClear();
- }
- });
+ const waitForRequests = async ({ andClearMocks } = { andClearMocks: false }) => {
+ await axios.waitForAll();
+ if (andClearMocks) {
+ projectMilestonesApiCallSpy.mockClear();
+ groupMilestonesApiCallSpy.mockClear();
+ }
+ };
describe('initialization behavior', () => {
beforeEach(createComponent);
@@ -250,7 +254,7 @@ describe('Milestone combobox component', () => {
describe('when the search query is empty', () => {
it('renders a "no results" message', () => {
- expect(findNoResults().text()).toBe(s__('MilestoneCombobox|No matching results'));
+ expect(findNoResults().text()).toBe('No matching results');
});
});
});
@@ -333,23 +337,19 @@ describe('Milestone combobox component', () => {
it('renders a checkmark by the selected item', async () => {
selectFirstProjectMilestone();
- await localVue.nextTick();
+ await nextTick();
expect(
- findFirstProjectMilestonesDropdownItem()
- .find('span')
- .classes('selected-item'),
- ).toBe(false);
+ findFirstProjectMilestonesDropdownItem().find('span').classes('selected-item'),
+ ).toBe(true);
selectFirstProjectMilestone();
- await localVue.nextTick();
+ await nextTick();
expect(
- findFirstProjectMilestonesDropdownItem()
- .find('span')
- .classes('selected-item'),
- ).toBe(true);
+ findFirstProjectMilestonesDropdownItem().find('span').classes('selected-item'),
+ ).toBe(false);
});
describe('when a project milestones is selected', () => {
@@ -364,22 +364,21 @@ describe('Milestone combobox component', () => {
it("displays the project milestones name in the dropdown's button", async () => {
selectFirstProjectMilestone();
- await localVue.nextTick();
+ await nextTick();
- expect(findButtonContent().text()).toBe(s__('MilestoneCombobox|No milestone'));
+ expect(findButtonContent().text()).toBe('v1.0');
selectFirstProjectMilestone();
+ await nextTick();
- await localVue.nextTick();
- expect(findButtonContent().text()).toBe('v1.0');
+ expect(findButtonContent().text()).toBe('No milestone');
});
- it('updates the v-model binding with the project milestone title', () => {
- expect(wrapper.vm.value).toEqual([]);
-
+ it('updates the v-model binding with the project milestone title', async () => {
selectFirstProjectMilestone();
+ await nextTick();
- expect(wrapper.vm.value).toEqual(['v1.0']);
+ expect(wrapper.emitted().input[0][0]).toStrictEqual(['v1.0']);
});
});
});
@@ -463,23 +462,19 @@ describe('Milestone combobox component', () => {
it('renders a checkmark by the selected item', async () => {
selectFirstGroupMilestone();
- await localVue.nextTick();
+ await nextTick();
- expect(
- findFirstGroupMilestonesDropdownItem()
- .find('span')
- .classes('selected-item'),
- ).toBe(false);
+ expect(findFirstGroupMilestonesDropdownItem().find('span').classes('selected-item')).toBe(
+ true,
+ );
selectFirstGroupMilestone();
- await localVue.nextTick();
+ await nextTick();
- expect(
- findFirstGroupMilestonesDropdownItem()
- .find('span')
- .classes('selected-item'),
- ).toBe(true);
+ expect(findFirstGroupMilestonesDropdownItem().find('span').classes('selected-item')).toBe(
+ false,
+ );
});
describe('when a group milestones is selected', () => {
@@ -494,22 +489,21 @@ describe('Milestone combobox component', () => {
it("displays the group milestones name in the dropdown's button", async () => {
selectFirstGroupMilestone();
- await localVue.nextTick();
+ await nextTick();
- expect(findButtonContent().text()).toBe(s__('MilestoneCombobox|No milestone'));
+ expect(findButtonContent().text()).toBe('group-v1.0');
selectFirstGroupMilestone();
+ await nextTick();
- await localVue.nextTick();
- expect(findButtonContent().text()).toBe('group-v1.0');
+ expect(findButtonContent().text()).toBe('No milestone');
});
- it('updates the v-model binding with the group milestone title', () => {
- expect(wrapper.vm.value).toEqual([]);
-
+ it('updates the v-model binding with the group milestone title', async () => {
selectFirstGroupMilestone();
+ await nextTick();
- expect(wrapper.vm.value).toEqual(['group-v1.0']);
+ expect(wrapper.emitted().input[0][0]).toStrictEqual(['group-v1.0']);
});
});
});
diff --git a/spec/frontend/mini_pipeline_graph_dropdown_spec.js b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
index 1ecf01894af..b21ddabbfb1 100644
--- a/spec/frontend/mini_pipeline_graph_dropdown_spec.js
+++ b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
-import waitForPromises from './helpers/wait_for_promises';
describe('Mini Pipeline Graph Dropdown', () => {
preloadFixtures('static/mini_dropdown_graph.html');
@@ -64,7 +64,7 @@ describe('Mini Pipeline Graph Dropdown', () => {
expect(ajaxSpy.mock.calls[0][0]).toEqual('foobar');
});
- it('should not close when user uses cmd/ctrl + click', done => {
+ it('should not close when user uses cmd/ctrl + click', (done) => {
mock.onGet('foobar').reply(200, {
html: `<li>
<a class="mini-pipeline-graph-dropdown-item" href="#">
@@ -90,7 +90,7 @@ describe('Mini Pipeline Graph Dropdown', () => {
.catch(done.fail);
});
- it('should close the dropdown when request returns an error', done => {
+ it('should close the dropdown when request returns an error', (done) => {
mock.onGet('foobar').networkError();
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
diff --git a/spec/frontend/mocks/ce/lib/utils/axios_utils.js b/spec/frontend/mocks/ce/lib/utils/axios_utils.js
index 85fad231d28..674563b9f28 100644
--- a/spec/frontend/mocks/ce/lib/utils/axios_utils.js
+++ b/spec/frontend/mocks/ce/lib/utils/axios_utils.js
@@ -5,7 +5,7 @@ const axios = jest.requireActual('~/lib/utils/axios_utils').default;
axios.isMock = true;
// Fail tests for unmocked requests
-axios.defaults.adapter = config => {
+axios.defaults.adapter = (config) => {
const message =
`Unexpected unmocked request: ${JSON.stringify(config, null, 2)}\n` +
'Consider using the `axios-mock-adapter` module in tests.';
@@ -23,7 +23,7 @@ const onRequest = () => {
};
// Use setImmediate to alloow the response interceptor to finish
-const onResponse = config => {
+const onResponse = (config) => {
activeRequests -= 1;
setImmediate(() => {
events.emit('response', config);
@@ -31,7 +31,7 @@ const onResponse = config => {
};
const subscribeToResponse = (predicate = () => true) =>
- new Promise(resolve => {
+ new Promise((resolve) => {
const listener = (config = {}) => {
if (predicate(config)) {
events.off('response', listener);
@@ -49,7 +49,7 @@ const subscribeToResponse = (predicate = () => true) =>
/**
* Registers a callback function to be run after a request to the given URL finishes.
*/
-axios.waitFor = url => subscribeToResponse(({ url: configUrl }) => configUrl === url);
+axios.waitFor = (url) => subscribeToResponse(({ url: configUrl }) => configUrl === url);
/**
* Registers a callback function to be run after all requests have finished. If there are no requests waiting, the callback is executed immediately.
@@ -58,18 +58,18 @@ axios.waitForAll = () => subscribeToResponse(() => activeRequests === 0);
axios.countActiveRequests = () => activeRequests;
-axios.interceptors.request.use(config => {
+axios.interceptors.request.use((config) => {
onRequest();
return config;
});
// Remove the global counter
axios.interceptors.response.use(
- response => {
+ (response) => {
onResponse(response.config);
return response;
},
- err => {
+ (err) => {
onResponse(err.config);
return Promise.reject(err);
},
diff --git a/spec/frontend/mocks/mocks_helper.js b/spec/frontend/mocks/mocks_helper.js
index 0aa80331434..295483cd64c 100644
--- a/spec/frontend/mocks/mocks_helper.js
+++ b/spec/frontend/mocks/mocks_helper.js
@@ -19,9 +19,9 @@ const prefixMap = [
// { mocksRoot: 'virtual', requirePrefix: '' }, // We'll deal with virtual mocks later
];
-const mockFileFilter = stats => stats.isFile() && stats.path.endsWith('.js');
+const mockFileFilter = (stats) => stats.isFile() && stats.path.endsWith('.js');
-const getMockFiles = root => readdir.sync(root, { deep: MAX_DEPTH, filter: mockFileFilter });
+const getMockFiles = (root) => readdir.sync(root, { deep: MAX_DEPTH, filter: mockFileFilter });
// Function that performs setting a mock. This has to be overridden by the unit test, because
// jest.setMock can't be overwritten across files.
@@ -36,7 +36,7 @@ export const setupManualMocks = function setupManualMocks(setMock = defaultSetMo
return;
}
- getMockFiles(path.join(__dirname, mocksRoot)).forEach(mockPath => {
+ getMockFiles(path.join(__dirname, mocksRoot)).forEach((mockPath) => {
const mockPathNoExt = mockPath.substring(0, mockPath.length - path.extname(mockPath).length);
const sourcePath = path.join(requirePrefix, mockPathNoExt);
const mockPathRelative = `./${path.join(mocksRoot, mockPathNoExt)}`;
diff --git a/spec/frontend/mocks/mocks_helper_spec.js b/spec/frontend/mocks/mocks_helper_spec.js
index a91e8ecfa4a..0abe5c6b949 100644
--- a/spec/frontend/mocks/mocks_helper_spec.js
+++ b/spec/frontend/mocks/mocks_helper_spec.js
@@ -47,13 +47,13 @@ describe('mocks_helper.js', () => {
const readdirSpy = readdir.sync;
expect(readdirSpy).toHaveBeenCalled();
- readdirSpy.mock.calls.forEach(call => {
+ readdirSpy.mock.calls.forEach((call) => {
expect(call[1].deep).toBeLessThan(100);
});
});
it('sets up mocks for CE (the ~/ prefix)', () => {
- fs.existsSync.mockImplementation(root => root.endsWith('ce'));
+ fs.existsSync.mockImplementation((root) => root.endsWith('ce'));
readdir.sync.mockReturnValue(['root.js', 'lib/utils/util.js']);
setupManualMocks();
@@ -72,7 +72,7 @@ describe('mocks_helper.js', () => {
};
fs.existsSync.mockReturnValue(true);
- readdir.sync.mockImplementation(root => files[root]);
+ readdir.sync.mockImplementation((root) => files[root]);
setupManualMocks();
expect(readdir.sync).toHaveBeenCalledTimes(1);
@@ -84,7 +84,7 @@ describe('mocks_helper.js', () => {
});
it('fails when given a virtual mock', () => {
- fs.existsSync.mockImplementation(p => p.endsWith('ce'));
+ fs.existsSync.mockImplementation((p) => p.endsWith('ce'));
readdir.sync.mockReturnValue(['virtual', 'shouldntBeImported']);
setMock.mockImplementation(() => {
throw new Error('Could not locate module');
@@ -106,7 +106,7 @@ describe('mocks_helper.js', () => {
});
});
- it('survives jest.isolateModules()', done => {
+ it('survives jest.isolateModules()', (done) => {
jest.isolateModules(() => {
const axios2 = require('~/lib/utils/axios_utils').default;
expect(axios2.isMock).toBe(true);
diff --git a/spec/frontend/monitoring/alert_widget_spec.js b/spec/frontend/monitoring/alert_widget_spec.js
index d004b1da0b6..fd9fb374274 100644
--- a/spec/frontend/monitoring/alert_widget_spec.js
+++ b/spec/frontend/monitoring/alert_widget_spec.js
@@ -28,12 +28,20 @@ describe('AlertWidget', () => {
const nonFiringAlertResult = [
{
- values: [[0, 1], [1, 42], [2, 41]],
+ values: [
+ [0, 1],
+ [1, 42],
+ [2, 41],
+ ],
},
];
const firingAlertResult = [
{
- values: [[0, 42], [1, 43], [2, 44]],
+ values: [
+ [0, 42],
+ [1, 43],
+ [2, 44],
+ ],
},
];
const metricId = '5';
@@ -75,7 +83,7 @@ describe('AlertWidget', () => {
},
};
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(AlertWidget, {
stubs: { GlTooltip, GlSprintf },
propsData: {
@@ -88,10 +96,7 @@ describe('AlertWidget', () => {
const findWidgetForm = () => wrapper.find({ ref: 'widgetForm' });
const findAlertErrorMessage = () => wrapper.find({ ref: 'alertErrorMessage' });
const findCurrentSettingsText = () =>
- wrapper
- .find({ ref: 'alertCurrentSetting' })
- .text()
- .replace(/\s\s+/g, ' ');
+ wrapper.find({ ref: 'alertCurrentSetting' }).text().replace(/\s\s+/g, ' ');
const findBadge = () => wrapper.find(GlBadge);
const findTooltip = () => wrapper.find(GlTooltip);
@@ -103,7 +108,7 @@ describe('AlertWidget', () => {
it('displays a loading spinner and disables form when fetching alerts', () => {
let resolveReadAlert;
mockReadAlert.mockReturnValue(
- new Promise(resolve => {
+ new Promise((resolve) => {
resolveReadAlert = resolve;
}),
);
@@ -126,7 +131,7 @@ describe('AlertWidget', () => {
it('does not render loading spinner if showLoadingState is false', () => {
let resolveReadAlert;
mockReadAlert.mockReturnValue(
- new Promise(resolve => {
+ new Promise((resolve) => {
resolveReadAlert = resolve;
}),
);
@@ -300,11 +305,7 @@ describe('AlertWidget', () => {
createComponent(propsWithManyAlerts);
return waitForPromises().then(() => {
- expect(
- findTooltip()
- .text()
- .replace(/\s\s+/g, ' '),
- ).toEqual('Firing: alert-label > 42');
+ expect(findTooltip().text().replace(/\s\s+/g, ' ')).toEqual('Firing: alert-label > 42');
});
});
});
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index 17720aeb702..e873edaad3b 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -37,6 +37,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
class="flex-grow-1"
data-qa-selector="environments_dropdown"
headertext=""
+ hideheaderborder="true"
id="monitor-environments-dropdown"
menu-class="monitor-environment-dropdown-menu"
size="medium"
diff --git a/spec/frontend/monitoring/components/alert_widget_form_spec.js b/spec/frontend/monitoring/components/alert_widget_form_spec.js
index 6d71a9b09e5..6d87fb85f4d 100644
--- a/spec/frontend/monitoring/components/alert_widget_form_spec.js
+++ b/spec/frontend/monitoring/components/alert_widget_form_spec.js
@@ -76,11 +76,15 @@ describe('AlertWidgetForm', () => {
});
it('shows correct title and button text', () => {
+ createComponent();
+
expect(modalTitle()).toBe('Add alert');
expect(submitButton().text()).toBe('Add');
});
it('sets tracking options for create alert', () => {
+ createComponent();
+
expect(submitButtonTrackingOpts()).toEqual(dataTrackingOptions.create);
});
diff --git a/spec/frontend/monitoring/components/charts/annotations_spec.js b/spec/frontend/monitoring/components/charts/annotations_spec.js
index fc90175d307..1eac0935fe4 100644
--- a/spec/frontend/monitoring/components/charts/annotations_spec.js
+++ b/spec/frontend/monitoring/components/charts/annotations_spec.js
@@ -36,7 +36,7 @@ describe('annotations spec', () => {
}),
);
- annotations.data.forEach(annotation => {
+ annotations.data.forEach((annotation) => {
expect(annotation).toEqual(expect.any(Object));
});
@@ -58,7 +58,7 @@ describe('annotations spec', () => {
}),
);
- annotations.markLine.data.forEach(annotation => {
+ annotations.markLine.data.forEach((annotation) => {
expect(annotation).toEqual(expect.any(Object));
});
@@ -83,7 +83,7 @@ describe('annotations spec', () => {
}),
);
- annotations.markLine.data.forEach(annotation => {
+ annotations.markLine.data.forEach((annotation) => {
expect(annotation).toEqual(expect.any(Object));
});
diff --git a/spec/frontend/monitoring/components/charts/anomaly_spec.js b/spec/frontend/monitoring/components/charts/anomaly_spec.js
index ebb49a2a0aa..dad3003d536 100644
--- a/spec/frontend/monitoring/components/charts/anomaly_spec.js
+++ b/spec/frontend/monitoring/components/charts/anomaly_spec.js
@@ -15,7 +15,7 @@ const TEST_LOWER = 9;
describe('Anomaly chart component', () => {
let wrapper;
- const setupAnomalyChart = props => {
+ const setupAnomalyChart = (props) => {
wrapper = shallowMount(Anomaly, {
propsData: { ...props },
});
@@ -91,7 +91,7 @@ describe('Anomaly chart component', () => {
expect(series.length).toEqual(2); // 1 upper + 1 lower boundaries
expect(series[0].stack).toEqual(series[1].stack);
- series.forEach(s => {
+ series.forEach((s) => {
expect(s.type).toBe('line');
expect(s.lineStyle.width).toBe(0);
expect(s.lineStyle.color).toMatch(/rgba\(.+\)/);
diff --git a/spec/frontend/monitoring/components/charts/bar_spec.js b/spec/frontend/monitoring/components/charts/bar_spec.js
index a363fafdc31..40edde5f666 100644
--- a/spec/frontend/monitoring/components/charts/bar_spec.js
+++ b/spec/frontend/monitoring/components/charts/bar_spec.js
@@ -44,7 +44,7 @@ describe('Bar component', () => {
it('should return chartData as array of arrays', () => {
expect(chartData).toBeInstanceOf(Array);
- chartData.forEach(item => {
+ chartData.forEach((item) => {
expect(item).toBeInstanceOf(Array);
});
});
diff --git a/spec/frontend/monitoring/components/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index fbcff33d692..0c4b6e8990d 100644
--- a/spec/frontend/monitoring/components/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -45,7 +45,7 @@ describe('Column component', () => {
});
};
const findChart = () => wrapper.find(GlColumnChart);
- const chartProps = prop => findChart().props(prop);
+ const chartProps = (prop) => findChart().props(prop);
beforeEach(() => {
createWrapper();
@@ -58,7 +58,7 @@ describe('Column component', () => {
describe('xAxisLabel', () => {
const mockDate = Date.UTC(2020, 4, 26, 20); // 8:00 PM in GMT
- const useXAxisFormatter = date => {
+ const useXAxisFormatter = (date) => {
const { xAxis } = chartProps('option');
const { formatter } = xAxis.axisLabel;
return formatter(date);
diff --git a/spec/frontend/monitoring/components/charts/gauge_spec.js b/spec/frontend/monitoring/components/charts/gauge_spec.js
index 850e2ca87db..9215f2e411f 100644
--- a/spec/frontend/monitoring/components/charts/gauge_spec.js
+++ b/spec/frontend/monitoring/components/charts/gauge_spec.js
@@ -49,7 +49,7 @@ describe('Gauge Chart component', () => {
it.each(invalidCases)(
'if min has invalid value, defaults are used for both min and max',
- invalidValue => {
+ (invalidValue) => {
createWrapper({ minValue: invalidValue });
expect(findGaugeChart().props('min')).toBe(MIN_DEFAULT);
@@ -59,7 +59,7 @@ describe('Gauge Chart component', () => {
it.each(invalidCases)(
'if max has invalid value, defaults are used for both min and max',
- invalidValue => {
+ (invalidValue) => {
createWrapper({ minValue: invalidValue });
expect(findGaugeChart().props('min')).toBe(MIN_DEFAULT);
diff --git a/spec/frontend/monitoring/components/charts/options_spec.js b/spec/frontend/monitoring/components/charts/options_spec.js
index 3372d27e4f9..064ce6f204c 100644
--- a/spec/frontend/monitoring/components/charts/options_spec.js
+++ b/spec/frontend/monitoring/components/charts/options_spec.js
@@ -145,7 +145,7 @@ describe('options spec', () => {
expect(thresholds).toEqual([]);
});
- it.each(invalidCases)('invalid values for thresholds are filtered out', invalidValue => {
+ it.each(invalidCases)('invalid values for thresholds are filtered out', (invalidValue) => {
thresholds = getValidThresholds({
mode: 'absolute',
range: { min: 0, max: 100 },
@@ -197,7 +197,7 @@ describe('options spec', () => {
it.each(invalidCases)(
'when min has invalid value, empty result is returned',
- invalidValue => {
+ (invalidValue) => {
thresholds = getValidThresholds({
mode: 'absolute',
range: { min: invalidValue, max: 100 },
@@ -210,7 +210,7 @@ describe('options spec', () => {
it.each(invalidCases)(
'when max has invalid value, empty result is returned',
- invalidValue => {
+ (invalidValue) => {
thresholds = getValidThresholds({
mode: 'absolute',
range: { min: 0, max: invalidValue },
@@ -244,7 +244,7 @@ describe('options spec', () => {
it.each(invalidCases)(
'if invalid values are passed, empty result is returned',
- invalidValue => {
+ (invalidValue) => {
thresholds = getValidThresholds({
mode: 'absolute',
range: { min: 0, max: 100 },
@@ -259,7 +259,7 @@ describe('options spec', () => {
describe('mode', () => {
it.each(invalidCases)(
'if invalid values are passed, empty result is returned',
- invalidValue => {
+ (invalidValue) => {
thresholds = getValidThresholds({
mode: invalidValue,
range: { min: 0, max: 100 },
@@ -305,7 +305,7 @@ describe('options spec', () => {
const outOfPercentBoundsValues = [-1, 0, 100, 101];
it.each(outOfPercentBoundsValues)(
'when values out of 0-100 range are passed, empty result is returned',
- invalidValue => {
+ (invalidValue) => {
thresholds = getValidThresholds({
mode: 'percentage',
range: { min: 0, max: 1000 },
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
index 2032258730a..4d4224a8b11 100644
--- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -6,7 +6,7 @@ import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vu
import { stackedColumnGraphData } from '../../graph_data';
jest.mock('~/lib/utils/icon_utils', () => ({
- getSvgIconPathContent: jest.fn().mockImplementation(icon => Promise.resolve(`${icon}-content`)),
+ getSvgIconPathContent: jest.fn().mockImplementation((icon) => Promise.resolve(`${icon}-content`)),
}));
describe('Stacked column chart component', () => {
@@ -26,7 +26,7 @@ describe('Stacked column chart component', () => {
stubs: {
GlPopover: true,
},
- attachToDocument: true,
+ attachTo: document.body,
});
beforeEach(() => {
@@ -48,7 +48,7 @@ describe('Stacked column chart component', () => {
data.forEach((series, index) => {
const { values } = stackedColumnMockedData.metrics[index].result[0];
- expect(series.data).toEqual(values.map(value => value[1]));
+ expect(series.data).toEqual(values.map((value) => value[1]));
});
});
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index 8fcee80a2d8..b7e1cb91987 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -2,7 +2,7 @@ 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 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import {
GlAreaChart,
GlLineChart,
@@ -23,14 +23,14 @@ import { timeSeriesGraphData } from '../../graph_data';
jest.mock('lodash/throttle', () =>
// this throttle mock executes immediately
- jest.fn(func => {
+ jest.fn((func) => {
// eslint-disable-next-line no-param-reassign
func.cancel = jest.fn();
return func;
}),
);
jest.mock('~/lib/utils/icon_utils', () => ({
- getSvgIconPathContent: jest.fn().mockImplementation(icon => Promise.resolve(`${icon}-content`)),
+ getSvgIconPathContent: jest.fn().mockImplementation((icon) => Promise.resolve(`${icon}-content`)),
}));
describe('Time series component', () => {
@@ -53,7 +53,7 @@ describe('Time series component', () => {
stubs: {
GlPopover: true,
},
- attachToDocument: true,
+ attachTo: document.body,
});
};
@@ -122,7 +122,7 @@ describe('Time series component', () => {
},
],
}),
- off: jest.fn(eChartEvent => {
+ off: jest.fn((eChartEvent) => {
delete eChartMock.handlers[eChartEvent];
}),
on: jest.fn((eChartEvent, fn) => {
@@ -193,7 +193,7 @@ describe('Time series component', () => {
it('does not throw error if data point is outside the zoom range', () => {
const seriesDataWithoutValue = {
...mockLineSeriesData(),
- seriesData: mockLineSeriesData().seriesData.map(data => ({
+ seriesData: mockLineSeriesData().seriesData.map((data) => ({
...data,
value: undefined,
})),
@@ -270,7 +270,7 @@ describe('Time series component', () => {
beforeEach(() => {
wrapper.vm.formatTooltipText({
...mockAnnotationsSeriesData,
- seriesData: mockAnnotationsSeriesData.seriesData.map(data => ({
+ seriesData: mockAnnotationsSeriesData.seriesData.map((data) => ({
...data,
data: annotationsMetadata,
})),
@@ -546,7 +546,7 @@ describe('Time series component', () => {
describe('xAxisLabel', () => {
const mockDate = Date.UTC(2020, 4, 26, 20); // 8:00 PM in GMT
- const useXAxisFormatter = date => {
+ const useXAxisFormatter = (date) => {
const { xAxis } = getChartOptions();
const { formatter } = xAxis.axisLabel;
return formatter(date);
@@ -620,7 +620,7 @@ describe('Time series component', () => {
},
];
- glChartComponents.forEach(dynamicComponent => {
+ glChartComponents.forEach((dynamicComponent) => {
describe(`GitLab UI: ${dynamicComponent.chartType}`, () => {
const findChartComponent = () => wrapper.find(dynamicComponent.component);
@@ -705,7 +705,7 @@ describe('Time series component', () => {
let lineColors;
beforeEach(() => {
- lineColors = wrapper.find(GlAreaChart).vm.series.map(item => item.lineStyle.color);
+ lineColors = wrapper.find(GlAreaChart).vm.series.map((item) => item.lineStyle.color);
});
it('should contain different colors for contiguous time series', () => {
@@ -727,7 +727,7 @@ describe('Time series component', () => {
const legendColors = wrapper
.find(GlChartLegend)
.props('seriesInfo')
- .map(item => item.color);
+ .map((item) => item.color);
lineColors.forEach((color, index) => {
expect(color).toBe(legendColors[index]);
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
index b22e05ec30a..43d5937a3a1 100644
--- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
@@ -107,7 +107,7 @@ describe('Actions menu', () => {
describe('adding new metric from modal', () => {
let origPage;
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(Tracking, 'event').mockReturnValue();
createShallowWrapper();
@@ -123,7 +123,7 @@ describe('Actions menu', () => {
document.body.dataset.page = origPage;
});
- it('is tracked', done => {
+ it('is tracked', (done) => {
const submitButton = findAddMetricModalSubmitButton().vm;
wrapper.vm.$nextTick(() => {
@@ -219,7 +219,7 @@ describe('Actions menu', () => {
});
});
- describe.each(ootbDashboards)('when current dashboard is OOTB', dashboard => {
+ describe.each(ootbDashboards)('when current dashboard is OOTB', (dashboard) => {
beforeEach(() => {
setupAllDashboards(store, dashboard.path);
});
@@ -240,7 +240,7 @@ describe('Actions menu', () => {
createShallowWrapper();
});
- describe.each(ootbDashboards)('when current dashboard is OOTB', dashboard => {
+ describe.each(ootbDashboards)('when current dashboard is OOTB', (dashboard) => {
beforeEach(() => {
setupAllDashboards(store, dashboard.path);
});
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js
index f9a7a4d5a93..32fd9c45e8d 100644
--- a/spec/frontend/monitoring/components/dashboard_header_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_header_spec.js
@@ -41,7 +41,7 @@ describe('Dashboard header', () => {
const findActionsMenu = () => wrapper.find(ActionsMenu);
- const setSearchTerm = searchTerm => {
+ const setSearchTerm = (searchTerm) => {
store.commit(`monitoringDashboard/${types.SET_ENVIRONMENTS_FILTER}`, searchTerm);
};
@@ -147,13 +147,13 @@ describe('Dashboard header', () => {
it('environments dropdown items can be checked', () => {
const items = findEnvsDropdownItems();
- const checkItems = findEnvsDropdownItems().filter(item => item.props('isCheckItem'));
+ const checkItems = findEnvsDropdownItems().filter((item) => item.props('isCheckItem'));
expect(items).toHaveLength(checkItems.length);
});
it('checks the currently selected environment', () => {
- const selectedItems = findEnvsDropdownItems().filter(item => item.props('isChecked'));
+ const selectedItems = findEnvsDropdownItems().filter((item) => item.props('isChecked'));
expect(selectedItems).toHaveLength(1);
expect(selectedItems.at(0).text()).toBe(currentEnvironmentName);
@@ -218,7 +218,7 @@ describe('Dashboard header', () => {
});
describe('timezone setting', () => {
- const setupWithTimezone = value => {
+ const setupWithTimezone = (value) => {
store = createStore({ dashboardTimezone: value });
createShallowWrapper();
};
@@ -295,7 +295,7 @@ describe('Dashboard header', () => {
});
describe('adding metrics prop', () => {
- it.each(ootbDashboards)('gets passed true if current dashboard is OOTB', dashboardPath => {
+ it.each(ootbDashboards)('gets passed true if current dashboard is OOTB', (dashboardPath) => {
createShallowWrapper({ customMetricsAvailable: true });
store.state.monitoringDashboard.emptyState = false;
@@ -308,7 +308,7 @@ describe('Dashboard header', () => {
it.each(customDashboards)(
'gets passed false if current dashboard is custom',
- dashboardPath => {
+ (dashboardPath) => {
createShallowWrapper({ customMetricsAvailable: true });
store.state.monitoringDashboard.emptyState = false;
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index 1808faf8f0e..f64e05d3a2c 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -57,7 +57,7 @@ describe('Dashboard Panel', () => {
const findTitle = () => wrapper.find({ ref: 'graphTitle' });
const findCtxMenu = () => wrapper.find({ ref: 'contextualMenu' });
const findMenuItems = () => wrapper.findAll(GlDropdownItem);
- const findMenuItemByText = text => findMenuItems().filter(i => i.text() === text);
+ const findMenuItemByText = (text) => findMenuItems().filter((i) => i.text() === text);
const findAlertsWidget = () => wrapper.find(AlertWidget);
const createWrapper = (props, { mountFn = shallowMount, ...options } = {}) => {
@@ -82,7 +82,7 @@ describe('Dashboard Panel', () => {
});
};
- const setMetricsSavedToDb = val =>
+ const setMetricsSavedToDb = (val) =>
monitoringDashboard.getters.metricsSavedToDb.mockReturnValue(val);
beforeEach(() => {
@@ -214,7 +214,7 @@ describe('Dashboard Panel', () => {
});
describe('Supports different panel types', () => {
- const dataWithType = type => {
+ const dataWithType = (type) => {
return {
...graphData,
type,
@@ -777,11 +777,7 @@ describe('Dashboard Panel', () => {
await wrapper.vm.$nextTick();
expect(findRunbookLinks().length).toBe(1);
- expect(
- findRunbookLinks()
- .at(0)
- .attributes('href'),
- ).toBe(invalidUrl);
+ expect(findRunbookLinks().at(0).attributes('href')).toBe(invalidUrl);
});
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 27e479ba498..db35f1cdde3 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -126,7 +126,7 @@ describe('Dashboard', () => {
});
describe('panel containers layout', () => {
- const findPanelLayoutWrapperAt = index => {
+ const findPanelLayoutWrapperAt = (index) => {
return wrapper
.find(GraphGroup)
.findAll('[data-testid="dashboard-panel-layout-wrapper"]')
@@ -225,7 +225,7 @@ describe('Dashboard', () => {
describe('when the URL contains a reference to a panel', () => {
let location;
- const setSearch = search => {
+ const setSearch = (search) => {
window.location = { ...location, search };
};
@@ -391,7 +391,7 @@ describe('Dashboard', () => {
});
describe('when all panels in the first group are loading', () => {
- const findGroupAt = i => wrapper.findAll(GraphGroup).at(i);
+ const findGroupAt = (i) => wrapper.findAll(GraphGroup).at(i);
beforeEach(() => {
setupStoreWithDashboard(store);
@@ -434,7 +434,7 @@ describe('Dashboard', () => {
setupStoreWithData(store);
wrapper.vm.$nextTick(() => {
- wrapper.findAll(GraphGroup).wrappers.forEach(groupWrapper => {
+ wrapper.findAll(GraphGroup).wrappers.forEach((groupWrapper) => {
expect(groupWrapper.props('isLoading')).toBe(false);
});
});
@@ -505,7 +505,7 @@ describe('Dashboard', () => {
let group;
let panel;
- const mockKeyup = key => window.dispatchEvent(new KeyboardEvent('keyup', { key }));
+ const mockKeyup = (key) => window.dispatchEvent(new KeyboardEvent('keyup', { key }));
const MockPanel = {
template: `<div><slot name="top-left"/></div>`,
@@ -532,7 +532,7 @@ describe('Dashboard', () => {
it('displays a single panel and others are hidden', () => {
const panels = wrapper.findAll(MockPanel);
- const visiblePanels = panels.filter(w => w.isVisible());
+ const visiblePanels = panels.filter((w) => w.isVisible());
expect(findExpandedPanel().isVisible()).toBe(true);
// v-show for hiding panels is more performant than v-if
@@ -587,18 +587,15 @@ describe('Dashboard', () => {
});
it('group empty area displays a NO_DATA state', () => {
- expect(
- wrapper
- .findAll({ ref: 'empty-group' })
- .at(0)
- .props('selectedState'),
- ).toEqual(metricStates.NO_DATA);
+ expect(wrapper.findAll({ ref: 'empty-group' }).at(0).props('selectedState')).toEqual(
+ metricStates.NO_DATA,
+ );
});
});
describe('drag and drop function', () => {
const findDraggables = () => wrapper.findAll(VueDraggable);
- const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled'));
+ const findEnabledDraggables = () => findDraggables().filter((f) => !f.attributes('disabled'));
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
@@ -634,9 +631,7 @@ describe('Dashboard', () => {
describe('when rearrange button is clicked', () => {
const findFirstDraggableRemoveButton = () =>
- findDraggablePanels()
- .at(0)
- .find('.js-draggable-remove');
+ findDraggablePanels().at(0).find('.js-draggable-remove');
beforeEach(() => {
findRearrangeButton().vm.$emit('click');
@@ -668,11 +663,7 @@ describe('Dashboard', () => {
});
it('shows a remove button, which removes a panel', () => {
- expect(
- findFirstDraggableRemoveButton()
- .find('a')
- .exists(),
- ).toBe(true);
+ expect(findFirstDraggableRemoveButton().find('a').exists()).toBe(true);
expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount);
findFirstDraggableRemoveButton().trigger('click');
@@ -772,10 +763,7 @@ describe('Dashboard', () => {
const panelIndex = 1; // skip expanded panel
const getClipboardTextFirstPanel = () =>
- wrapper
- .findAll(DashboardPanel)
- .at(panelIndex)
- .props('clipboardText');
+ wrapper.findAll(DashboardPanel).at(panelIndex).props('clipboardText');
beforeEach(() => {
setupStoreWithData(store);
diff --git a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
index ef5784183b2..6ed190051ce 100644
--- a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
+++ b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem, GlIcon } from '@gitlab/ui';
@@ -27,18 +28,17 @@ describe('DashboardsDropdown', () => {
...props,
defaultBranch,
},
- sync: false,
...storeOpts,
...opts,
});
}
const findItems = () => wrapper.findAll(GlDropdownItem);
- const findItemAt = i => wrapper.findAll(GlDropdownItem).at(i);
+ const findItemAt = (i) => wrapper.findAll(GlDropdownItem).at(i);
const findSearchInput = () => wrapper.find({ ref: 'monitorDashboardsDropdownSearch' });
const findNoItemsMsg = () => wrapper.find({ ref: 'monitorDashboardsDropdownMsg' });
const findStarredListDivider = () => wrapper.find({ ref: 'starredListDivider' });
- const setSearchTerm = searchTerm => wrapper.setData({ searchTerm });
+ const setSearchTerm = (searchTerm) => wrapper.setData({ searchTerm });
beforeEach(() => {
mockDashboards = dashboardGitResponse;
@@ -72,22 +72,20 @@ describe('DashboardsDropdown', () => {
expect(findNoItemsMsg().isVisible()).toBe(false);
});
- it('filters dropdown items when searched for item exists in the list', () => {
+ it('filters dropdown items when searched for item exists in the list', async () => {
const searchTerm = 'Overview';
setSearchTerm(searchTerm);
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(findItems()).toHaveLength(1);
- });
+ expect(findItems()).toHaveLength(1);
});
- it('shows no items found message when searched for item does not exists in the list', () => {
+ it('shows no items found message when searched for item does not exists in the list', async () => {
const searchTerm = 'does-not-exist';
setSearchTerm(searchTerm);
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(findNoItemsMsg().isVisible()).toBe(true);
- });
+ expect(findNoItemsMsg().isVisible()).toBe(true);
});
});
@@ -105,7 +103,7 @@ describe('DashboardsDropdown', () => {
describe('when the dashboard is missing a display name', () => {
beforeEach(() => {
- mockDashboards = dashboardGitResponse.map(d => ({ ...d, display_name: undefined }));
+ mockDashboards = dashboardGitResponse.map((d) => ({ ...d, display_name: undefined }));
createComponent();
});
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
index 29115ffb817..4abb5b2e27b 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_form.vue';
@@ -9,20 +10,19 @@ const createMountedWrapper = (props = {}) => {
// Use `mount` to render native input elements
wrapper = mount(DuplicateDashboardForm, {
propsData: { ...props },
- sync: false,
// We need to attach to document, so that `document.activeElement` is properly set in jsdom
- attachToDocument: true,
+ attachTo: document.body,
});
};
describe('DuplicateDashboardForm', () => {
const defaultBranch = 'master';
- const findByRef = ref => wrapper.find({ ref });
+ const findByRef = (ref) => wrapper.find({ ref });
const setValue = (ref, val) => {
findByRef(ref).setValue(val);
};
- const setChecked = value => {
+ const setChecked = (value) => {
const input = wrapper.find(`.form-check-input[value="${value}"]`);
input.element.checked = true;
input.trigger('click');
@@ -47,34 +47,34 @@ describe('DuplicateDashboardForm', () => {
describe('validates the file name', () => {
const findInvalidFeedback = () => findByRef('fileNameFormGroup').find('.invalid-feedback');
- it('when is empty', () => {
+ it('when is empty', async () => {
setValue('fileName', '');
- return wrapper.vm.$nextTick(() => {
- expect(findByRef('fileNameFormGroup').classes()).toContain('is-valid');
- expect(findInvalidFeedback().exists()).toBe(false);
- });
+ await nextTick();
+
+ expect(findByRef('fileNameFormGroup').classes()).toContain('is-valid');
+ expect(findInvalidFeedback().exists()).toBe(false);
});
- it('when is valid', () => {
+ it('when is valid', async () => {
setValue('fileName', 'my_dashboard.yml');
- return wrapper.vm.$nextTick(() => {
- expect(findByRef('fileNameFormGroup').classes()).toContain('is-valid');
- expect(findInvalidFeedback().exists()).toBe(false);
- });
+ await nextTick();
+
+ expect(findByRef('fileNameFormGroup').classes()).toContain('is-valid');
+ expect(findInvalidFeedback().exists()).toBe(false);
});
- it('when is not valid', () => {
+ it('when is not valid', async () => {
setValue('fileName', 'my_dashboard.exe');
- return wrapper.vm.$nextTick(() => {
- expect(findByRef('fileNameFormGroup').classes()).toContain('is-invalid');
- expect(findInvalidFeedback().text()).toBeTruthy();
- });
+ await nextTick();
+
+ expect(findByRef('fileNameFormGroup').classes()).toContain('is-invalid');
+ expect(findInvalidFeedback().text()).toBeTruthy();
});
});
describe('emits `change` event', () => {
const lastChange = () =>
- wrapper.vm.$nextTick().then(() => {
+ nextTick().then(() => {
wrapper.find('form').trigger('change');
// Resolves to the last emitted change
@@ -133,19 +133,19 @@ describe('DuplicateDashboardForm', () => {
expect(lastChange()).resolves.toMatchObject({
branch: defaultBranch,
}),
- wrapper.vm.$nextTick(() => {
+ nextTick(() => {
expect(findByRef('branchName').isVisible()).toBe(false);
}),
]);
});
- it('when `new` branch option is chosen, focuses on the branch name input', () => {
+ it('when `new` branch option is chosen, focuses on the branch name input', async () => {
setChecked(wrapper.vm.$options.radioVals.NEW);
- return wrapper.vm.$nextTick().then(() => {
- wrapper.find('form').trigger('change');
- expect(document.activeElement).toBe(findByRef('branchName').element);
- });
+ await nextTick();
+
+ wrapper.find('form').trigger('change');
+ expect(document.activeElement).toBe(findByRef('branchName').element);
});
});
});
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
index d8ffb4443ac..7e7065da179 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
@@ -1,3 +1,5 @@
+import Vuex from 'vuex';
+import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon, GlModal } from '@gitlab/ui';
@@ -8,6 +10,8 @@ import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_
import { dashboardGitResponse } from '../mock_data';
+Vue.use(Vuex);
+
describe('duplicate dashboard modal', () => {
let wrapper;
let mockDashboards;
@@ -15,25 +19,28 @@ describe('duplicate dashboard modal', () => {
let duplicateDashboardAction;
let okEvent;
- function createComponent(opts = {}) {
- const storeOpts = {
- methods: {
- duplicateSystemDashboard: jest.fn(),
- },
- computed: {
- allDashboards: () => mockDashboards,
- selectedDashboard: () => mockSelectedDashboard,
+ function createComponent() {
+ const store = new Vuex.Store({
+ modules: {
+ monitoringDashboard: {
+ namespaced: true,
+ actions: {
+ duplicateSystemDashboard: duplicateDashboardAction,
+ },
+ getters: {
+ allDashboards: () => mockDashboards,
+ selectedDashboard: () => mockSelectedDashboard,
+ },
+ },
},
- };
+ });
return shallowMount(DuplicateDashboardModal, {
propsData: {
defaultBranch: 'master',
modalId: 'id',
},
- sync: false,
- ...storeOpts,
- ...opts,
+ store,
});
}
@@ -51,12 +58,7 @@ describe('duplicate dashboard modal', () => {
preventDefault: jest.fn(),
};
- wrapper = createComponent({
- methods: {
- // Mock vuex actions
- duplicateSystemDashboard: duplicateDashboardAction,
- },
- });
+ wrapper = createComponent();
wrapper.vm.$refs.duplicateDashboardModal.hide = jest.fn();
});
@@ -65,34 +67,33 @@ describe('duplicate dashboard modal', () => {
expect(findDuplicateDashboardForm().exists()).toBe(true);
});
- it('saves a new dashboard', () => {
+ it('saves a new dashboard', async () => {
findModal().vm.$emit('ok', okEvent);
- return waitForPromises().then(() => {
- expect(okEvent.preventDefault).toHaveBeenCalled();
- expect(wrapper.emitted().dashboardDuplicated).toBeTruthy();
- expect(wrapper.emitted().dashboardDuplicated[0]).toEqual([dashboardGitResponse[0]]);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.vm.$refs.duplicateDashboardModal.hide).toHaveBeenCalled();
- expect(findAlert().exists()).toBe(false);
- });
+ await waitForPromises();
+ expect(okEvent.preventDefault).toHaveBeenCalled();
+ expect(wrapper.emitted().dashboardDuplicated).toBeTruthy();
+ expect(wrapper.emitted().dashboardDuplicated[0]).toEqual([dashboardGitResponse[0]]);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.vm.$refs.duplicateDashboardModal.hide).toHaveBeenCalled();
+ expect(findAlert().exists()).toBe(false);
});
- it('handles error when a new dashboard is not saved', () => {
+ it('handles error when a new dashboard is not saved', async () => {
const errMsg = 'An error occurred';
duplicateDashboardAction.mockRejectedValueOnce(errMsg);
findModal().vm.$emit('ok', okEvent);
- return waitForPromises().then(() => {
- expect(okEvent.preventDefault).toHaveBeenCalled();
+ await waitForPromises();
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(errMsg);
+ expect(okEvent.preventDefault).toHaveBeenCalled();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.vm.$refs.duplicateDashboardModal.hide).not.toHaveBeenCalled();
- });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(errMsg);
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.vm.$refs.duplicateDashboardModal.hide).not.toHaveBeenCalled();
});
it('updates the form on changes', () => {
@@ -101,9 +102,7 @@ describe('duplicate dashboard modal', () => {
commitMessage: 'A commit message',
};
- findModal()
- .find(DuplicateDashboardForm)
- .vm.$emit('change', formVals);
+ findModal().find(DuplicateDashboardForm).vm.$emit('change', formVals);
// Binding's second argument contains the modal id
expect(wrapper.vm.form).toEqual(formVals);
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
index 01089752933..cb06a1a6b64 100644
--- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -76,7 +76,7 @@ describe('Embed Group', () => {
expect(wrapper.find('.gl-card-body').classes()).not.toContain('d-none');
});
- it('collapses when clicked', done => {
+ it('collapses when clicked', (done) => {
metricsWithDataGetter.mockReturnValue([1]);
mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
@@ -134,7 +134,7 @@ describe('Embed Group', () => {
});
it('passes the correct props to the Embed components', () => {
- expect(wrapper.findAll(MetricEmbed).wrappers.map(item => item.props())).toEqual(
+ expect(wrapper.findAll(MetricEmbed).wrappers.map((item) => item.props())).toEqual(
multipleEmbedProps(),
);
});
diff --git a/spec/frontend/monitoring/components/graph_group_spec.js b/spec/frontend/monitoring/components/graph_group_spec.js
index ebcd6c0df3a..c57461c2d09 100644
--- a/spec/frontend/monitoring/components/graph_group_spec.js
+++ b/spec/frontend/monitoring/components/graph_group_spec.js
@@ -11,7 +11,7 @@ describe('Graph group component', () => {
const findCaretIcon = () => wrapper.find(GlIcon);
const findToggleButton = () => wrapper.find('[data-testid="group-toggle-button"]');
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(GraphGroup, {
propsData,
});
diff --git a/spec/frontend/monitoring/components/group_empty_state_spec.js b/spec/frontend/monitoring/components/group_empty_state_spec.js
index 4a550efe23c..1dd2ed4e141 100644
--- a/spec/frontend/monitoring/components/group_empty_state_spec.js
+++ b/spec/frontend/monitoring/components/group_empty_state_spec.js
@@ -35,7 +35,7 @@ describe('GroupEmptyState', () => {
metricStates.LOADING,
metricStates.UNKNOWN_ERROR,
'FOO STATE', // does not fail with unknown states
- ])('given state %s', selectedState => {
+ ])('given state %s', (selectedState) => {
beforeEach(() => {
wrapper = createComponent({ selectedState });
});
diff --git a/spec/frontend/monitoring/components/links_section_spec.js b/spec/frontend/monitoring/components/links_section_spec.js
index b771d63d51f..2daad77d513 100644
--- a/spec/frontend/monitoring/components/links_section_spec.js
+++ b/spec/frontend/monitoring/components/links_section_spec.js
@@ -12,7 +12,7 @@ describe('Links Section component', () => {
store,
});
};
- const setState = links => {
+ const setState = (links) => {
store.state.monitoringDashboard = {
...store.state.monitoringDashboard,
emptyState: null,
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index 8a478362b5e..a03d29309d4 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -17,9 +17,9 @@ describe('RefreshButton', () => {
const findRefreshBtn = () => wrapper.find(GlButton);
const findDropdown = () => wrapper.find(GlDropdown);
const findOptions = () => findDropdown().findAll(GlDropdownItem);
- const findOptionAt = index => findOptions().at(index);
+ const findOptionAt = (index) => findOptions().at(index);
- const expectFetchDataToHaveBeenCalledTimes = times => {
+ const expectFetchDataToHaveBeenCalledTimes = (times) => {
const refreshCalls = dispatch.mock.calls.filter(([action, payload]) => {
return action === 'monitoringDashboard/fetchDashboardData' && payload === undefined;
});
diff --git a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
index cc384aef231..f5db17ce367 100644
--- a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
@@ -10,11 +10,14 @@ describe('Custom variable component', () => {
label: 'Select environment',
value: 'Production',
options: {
- values: [{ text: 'Production', value: 'prod' }, { text: 'Canary', value: 'canary' }],
+ values: [
+ { text: 'Production', value: 'prod' },
+ { text: 'Canary', value: 'canary' },
+ ],
},
};
- const createShallowWrapper = props => {
+ const createShallowWrapper = (props) => {
wrapper = shallowMount(DropdownField, {
propsData: {
...defaultProps,
@@ -54,9 +57,7 @@ describe('Custom variable component', () => {
createShallowWrapper();
jest.spyOn(wrapper.vm, '$emit');
- findDropdownItems()
- .at(1)
- .vm.$emit('click');
+ findDropdownItems().at(1).vm.$emit('click');
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary');
diff --git a/spec/frontend/monitoring/fixture_data.js b/spec/frontend/monitoring/fixture_data.js
index 18ec74550b4..0f3dbaac493 100644
--- a/spec/frontend/monitoring/fixture_data.js
+++ b/spec/frontend/monitoring/fixture_data.js
@@ -35,7 +35,7 @@ const firstPanel = metricsDashboardViewModel.panelGroups[0].panels[0];
export const graphData = {
...firstPanel,
- metrics: firstPanel.metrics.map(metric => ({
+ metrics: firstPanel.metrics.map((metric) => ({
...metric,
result: metricsResult,
state: metricStates.OK,
@@ -44,7 +44,7 @@ export const graphData = {
export const graphDataEmpty = {
...firstPanel,
- metrics: firstPanel.metrics.map(metric => ({
+ metrics: firstPanel.metrics.map((metric) => ({
...metric,
result: [],
state: metricStates.NO_DATA,
diff --git a/spec/frontend/monitoring/graph_data.js b/spec/frontend/monitoring/graph_data.js
index 494fdb1b159..0b23ee41927 100644
--- a/spec/frontend/monitoring/graph_data.js
+++ b/spec/frontend/monitoring/graph_data.js
@@ -4,8 +4,8 @@ import { panelTypes, metricStates } from '~/monitoring/constants';
const initTime = 1435781450; // "Wed, 01 Jul 2015 20:10:50 GMT"
const intervalSeconds = 120;
-const makeValue = val => [initTime, val];
-const makeValues = vals => vals.map((val, i) => [initTime + intervalSeconds * i, val]);
+const makeValue = (val) => [initTime, val];
+const makeValues = (vals) => vals.map((val, i) => [initTime + intervalSeconds * i, val]);
// Raw Promethues Responses
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index aea8815fb10..ca06c96c7d6 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -1,7 +1,8 @@
+// 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';
// 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
-import { TEST_HOST } from '../helpers/test_constants';
export const mockProjectDir = '/frontend-fixtures/environments-project';
export const mockApiEndpoint = `${TEST_HOST}/monitoring/mock`;
diff --git a/spec/frontend/monitoring/requests/index_spec.js b/spec/frontend/monitoring/requests/index_spec.js
index a91c209875a..078de5f15d1 100644
--- a/spec/frontend/monitoring/requests/index_spec.js
+++ b/spec/frontend/monitoring/requests/index_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import { backoffMockImplementation } from 'jest/helpers/backoff_helper';
+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';
@@ -31,7 +31,7 @@ describe('monitoring metrics_requests', () => {
it('returns a dashboard response', () => {
mock.onGet(dashboardEndpoint).reply(statusCodes.OK, response);
- return getDashboard(dashboardEndpoint, params).then(data => {
+ return getDashboard(dashboardEndpoint, params).then((data) => {
expect(data).toEqual(metricsDashboardResponse);
});
});
@@ -41,7 +41,7 @@ describe('monitoring metrics_requests', () => {
mock.onGet(dashboardEndpoint).replyOnce(statusCodes.NO_CONTENT);
mock.onGet(dashboardEndpoint).reply(statusCodes.OK, response);
- return getDashboard(dashboardEndpoint, params).then(data => {
+ return getDashboard(dashboardEndpoint, params).then((data) => {
expect(data).toEqual(metricsDashboardResponse);
expect(mock.history.get).toHaveLength(3);
});
@@ -50,7 +50,7 @@ describe('monitoring metrics_requests', () => {
it('rejects after getting an error', () => {
mock.onGet(dashboardEndpoint).reply(500);
- return getDashboard(dashboardEndpoint, params).catch(error => {
+ return getDashboard(dashboardEndpoint, params).catch((error) => {
expect(error).toEqual(expect.any(Error));
expect(mock.history.get).toHaveLength(1);
});
@@ -74,7 +74,7 @@ describe('monitoring metrics_requests', () => {
it('returns a dashboard response', () => {
mock.onGet(prometheusEndpoint).reply(statusCodes.OK, response);
- return getPrometheusQueryData(prometheusEndpoint, params).then(data => {
+ return getPrometheusQueryData(prometheusEndpoint, params).then((data) => {
expect(data).toEqual(response.data);
});
});
@@ -85,7 +85,7 @@ describe('monitoring metrics_requests', () => {
mock.onGet(prometheusEndpoint).replyOnce(statusCodes.NO_CONTENT);
mock.onGet(prometheusEndpoint).reply(statusCodes.OK, response); // 3rd attempt
- return getPrometheusQueryData(prometheusEndpoint, params).then(data => {
+ return getPrometheusQueryData(prometheusEndpoint, params).then((data) => {
expect(data).toEqual(response.data);
expect(mock.history.get).toHaveLength(3);
});
@@ -97,7 +97,7 @@ describe('monitoring metrics_requests', () => {
error: 'An error ocurred',
});
- return getPrometheusQueryData(prometheusEndpoint, params).catch(error => {
+ return getPrometheusQueryData(prometheusEndpoint, params).catch((error) => {
expect(error).toEqual(new Error('Request failed with status code 500'));
});
});
@@ -109,7 +109,7 @@ describe('monitoring metrics_requests', () => {
error: 'An error ocurred',
});
- return getPrometheusQueryData(prometheusEndpoint, params).catch(error => {
+ return getPrometheusQueryData(prometheusEndpoint, params).catch((error) => {
expect(error).toEqual(new Error('Request failed with status code 401'));
});
});
@@ -123,7 +123,7 @@ describe('monitoring metrics_requests', () => {
error: 'An error ocurred',
}); // 3rd attempt
- return getPrometheusQueryData(prometheusEndpoint, params).catch(error => {
+ return getPrometheusQueryData(prometheusEndpoint, params).catch((error) => {
expect(error).toEqual(new Error('Request failed with status code 500'));
expect(mock.history.get).toHaveLength(3);
});
@@ -140,7 +140,7 @@ describe('monitoring metrics_requests', () => {
error: reason,
});
- return getPrometheusQueryData(prometheusEndpoint, params).catch(error => {
+ return getPrometheusQueryData(prometheusEndpoint, params).catch((error) => {
expect(error).toEqual(new Error(reason));
expect(mock.history.get).toHaveLength(1);
});
diff --git a/spec/frontend/monitoring/router_spec.js b/spec/frontend/monitoring/router_spec.js
index 8b97c8ed125..c30c4c56a6c 100644
--- a/spec/frontend/monitoring/router_spec.js
+++ b/spec/frontend/monitoring/router_spec.js
@@ -63,12 +63,7 @@ describe('Monitoring router', () => {
});
expect(wrapper.find(DashboardPage).exists()).toBe(true);
- expect(
- wrapper
- .find(DashboardPage)
- .find(Dashboard)
- .exists(),
- ).toBe(true);
+ expect(wrapper.find(DashboardPage).find(Dashboard).exists()).toBe(true);
});
});
@@ -91,12 +86,7 @@ describe('Monitoring router', () => {
});
expect(wrapper.find(DashboardPage).exists()).toBe(true);
- expect(
- wrapper
- .find(DashboardPage)
- .find(Dashboard)
- .exists(),
- ).toBe(true);
+ expect(wrapper.find(DashboardPage).find(Dashboard).exists()).toBe(true);
});
});
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index 5c7ab4e6a1f..319441b5ba2 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { backoffMockImplementation } from 'jest/helpers/backoff_helper';
+import { backoffMockImplementation } from 'helpers/backoff_helper';
import Tracking from '~/tracking';
import axios from '~/lib/utils/axios_utils';
import statusCodes from '~/lib/utils/http_status';
@@ -88,7 +88,7 @@ describe('Monitoring store actions', () => {
// Setup
describe('setGettingStartedEmptyState', () => {
- it('should commit SET_GETTING_STARTED_EMPTY_STATE mutation', done => {
+ it('should commit SET_GETTING_STARTED_EMPTY_STATE mutation', (done) => {
testAction(
setGettingStartedEmptyState,
null,
@@ -105,7 +105,7 @@ describe('Monitoring store actions', () => {
});
describe('setInitialState', () => {
- it('should commit SET_INITIAL_STATE mutation', done => {
+ it('should commit SET_INITIAL_STATE mutation', (done) => {
testAction(
setInitialState,
{
@@ -233,7 +233,7 @@ describe('Monitoring store actions', () => {
};
});
- it('dispatches a failure', done => {
+ it('dispatches a failure', (done) => {
result()
.then(() => {
expect(commit).toHaveBeenCalledWith(
@@ -250,7 +250,7 @@ describe('Monitoring store actions', () => {
.catch(done.fail);
});
- it('dispatches a failure action when a message is returned', done => {
+ it('dispatches a failure action when a message is returned', (done) => {
result()
.then(() => {
expect(dispatch).toHaveBeenCalledWith(
@@ -265,7 +265,7 @@ describe('Monitoring store actions', () => {
.catch(done.fail);
});
- it('does not show a flash error when showErrorBanner is disabled', done => {
+ it('does not show a flash error when showErrorBanner is disabled', (done) => {
state.showErrorBanner = false;
result()
@@ -322,7 +322,7 @@ describe('Monitoring store actions', () => {
state.timeRange = defaultTimeRange;
});
- it('commits empty state when state.groups is empty', done => {
+ it('commits empty state when state.groups is empty', (done) => {
const localGetters = {
metricsWithData: () => [],
};
@@ -353,7 +353,7 @@ describe('Monitoring store actions', () => {
.catch(done.fail);
});
- it('dispatches fetchPrometheusMetric for each panel query', done => {
+ it('dispatches fetchPrometheusMetric for each panel query', (done) => {
state.dashboard.panelGroups = convertObjectPropsToCamelCase(
metricsDashboardResponse.dashboard.panel_groups,
);
@@ -390,7 +390,7 @@ describe('Monitoring store actions', () => {
done();
});
- it('dispatches fetchPrometheusMetric for each panel query, handles an error', done => {
+ it('dispatches fetchPrometheusMetric for each panel query, handles an error', (done) => {
state.dashboard.panelGroups = metricsDashboardViewModel.panelGroups;
const metric = state.dashboard.panelGroups[0].panels[0].metrics[0];
@@ -449,7 +449,7 @@ describe('Monitoring store actions', () => {
};
});
- it('commits result', done => {
+ it('commits result', (done) => {
mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt
testAction(
@@ -485,7 +485,7 @@ describe('Monitoring store actions', () => {
step: 60,
};
- it('uses calculated step', done => {
+ it('uses calculated step', (done) => {
mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt
testAction(
@@ -527,7 +527,7 @@ describe('Monitoring store actions', () => {
step: 7,
};
- it('uses metric step', done => {
+ it('uses metric step', (done) => {
mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt
testAction(
@@ -558,7 +558,7 @@ describe('Monitoring store actions', () => {
});
});
- it('commits failure, when waiting for results and getting a server error', done => {
+ it('commits failure, when waiting for results and getting a server error', (done) => {
mock.onGet(prometheusEndpointPath).reply(500);
const error = new Error('Request failed with status code 500');
@@ -583,7 +583,7 @@ describe('Monitoring store actions', () => {
},
],
[],
- ).catch(e => {
+ ).catch((e) => {
expect(e).toEqual(error);
done();
});
@@ -991,7 +991,7 @@ describe('Monitoring store actions', () => {
state.dashboardsEndpoint = '/dashboards.json';
});
- it('Succesful POST request resolves', done => {
+ it('Succesful POST request resolves', (done) => {
mock.onPost(state.dashboardsEndpoint).reply(statusCodes.CREATED, {
dashboard: dashboardGitResponse[1],
});
@@ -1004,7 +1004,7 @@ describe('Monitoring store actions', () => {
.catch(done.fail);
});
- it('Succesful POST request resolves to a dashboard', done => {
+ it('Succesful POST request resolves to a dashboard', (done) => {
const mockCreatedDashboard = dashboardGitResponse[1];
const params = {
@@ -1026,7 +1026,7 @@ describe('Monitoring store actions', () => {
});
testAction(duplicateSystemDashboard, params, state, [], [])
- .then(result => {
+ .then((result) => {
expect(mock.history.post).toHaveLength(1);
expect(mock.history.post[0].data).toEqual(expectedPayload);
expect(result).toEqual(mockCreatedDashboard);
@@ -1036,10 +1036,10 @@ describe('Monitoring store actions', () => {
.catch(done.fail);
});
- it('Failed POST request throws an error', done => {
+ it('Failed POST request throws an error', (done) => {
mock.onPost(state.dashboardsEndpoint).reply(statusCodes.BAD_REQUEST);
- testAction(duplicateSystemDashboard, {}, state, [], []).catch(err => {
+ testAction(duplicateSystemDashboard, {}, state, [], []).catch((err) => {
expect(mock.history.post).toHaveLength(1);
expect(err).toEqual(expect.any(String));
@@ -1047,14 +1047,14 @@ describe('Monitoring store actions', () => {
});
});
- it('Failed POST request throws an error with a description', done => {
+ it('Failed POST request throws an error with a description', (done) => {
const backendErrorMsg = 'This file already exists!';
mock.onPost(state.dashboardsEndpoint).reply(statusCodes.BAD_REQUEST, {
error: backendErrorMsg,
});
- testAction(duplicateSystemDashboard, {}, state, [], []).catch(err => {
+ testAction(duplicateSystemDashboard, {}, state, [], []).catch((err) => {
expect(mock.history.post).toHaveLength(1);
expect(err).toEqual(expect.any(String));
expect(err).toEqual(expect.stringContaining(backendErrorMsg));
@@ -1067,7 +1067,7 @@ describe('Monitoring store actions', () => {
// Variables manipulation
describe('updateVariablesAndFetchData', () => {
- it('should commit UPDATE_VARIABLE_VALUE mutation and fetch data', done => {
+ it('should commit UPDATE_VARIABLE_VALUE mutation and fetch data', (done) => {
testAction(
updateVariablesAndFetchData,
{ pod: 'POD' },
diff --git a/spec/frontend/monitoring/store/getters_spec.js b/spec/frontend/monitoring/store/getters_spec.js
index 509de8a4596..771ec0ea549 100644
--- a/spec/frontend/monitoring/store/getters_spec.js
+++ b/spec/frontend/monitoring/store/getters_spec.js
@@ -365,7 +365,7 @@ describe('Monitoring store Getters', () => {
describe('selectedDashboard', () => {
const { selectedDashboard } = getters;
- const localGetters = localState => ({
+ const localGetters = (localState) => ({
fullDashboardPath: getters.fullDashboardPath(localState),
});
diff --git a/spec/frontend/monitoring/store/mutations_spec.js b/spec/frontend/monitoring/store/mutations_spec.js
index 8d1351fc909..571828eb67c 100644
--- a/spec/frontend/monitoring/store/mutations_spec.js
+++ b/spec/frontend/monitoring/store/mutations_spec.js
@@ -465,7 +465,10 @@ describe('Monitoring mutations', () => {
});
expect(variable.options).toEqual({
- values: [{ text: 'prometheus', value: 'prometheus' }, { text: 'node', value: 'node' }],
+ values: [
+ { text: 'prometheus', value: 'prometheus' },
+ { text: 'node', value: 'node' },
+ ],
});
});
});
@@ -509,7 +512,7 @@ describe('Monitoring mutations', () => {
});
describe('panel preview metric', () => {
- const getPreviewMetricAt = i => stateCopy.panelPreviewGraphData.metrics[i];
+ const getPreviewMetricAt = (i) => stateCopy.panelPreviewGraphData.metrics[i];
beforeEach(() => {
stateCopy.panelPreviewGraphData = {
diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js
index b97948fa1bf..58bb87cb332 100644
--- a/spec/frontend/monitoring/store/utils_spec.js
+++ b/spec/frontend/monitoring/store/utils_spec.js
@@ -127,7 +127,7 @@ describe('mapToDashboardViewModel', () => {
let dashboard;
- const setupWithPanel = panel => {
+ const setupWithPanel = (panel) => {
dashboard = {
panel_groups: [
{
@@ -340,7 +340,7 @@ describe('mapToDashboardViewModel', () => {
],
});
- const getMappedMetric = dashboard => {
+ const getMappedMetric = (dashboard) => {
return mapToDashboardViewModel(dashboard).panelGroups[0].panels[0].metrics[0];
};
@@ -775,7 +775,11 @@ describe('normalizeQueryResponseData', () => {
job: 'prometheus',
instance: 'localhost:9090',
},
- values: [[1435781430.781, '1'], [1435781445.781, '2'], [1435781460.781, '3']],
+ values: [
+ [1435781430.781, '1'],
+ [1435781445.781, '2'],
+ [1435781460.781, '3'],
+ ],
},
{
metric: {
@@ -783,7 +787,11 @@ describe('normalizeQueryResponseData', () => {
job: 'node',
instance: 'localhost:9091',
},
- values: [[1435781430.781, '4'], [1435781445.781, '5'], [1435781460.781, '6']],
+ values: [
+ [1435781430.781, '4'],
+ [1435781445.781, '5'],
+ [1435781460.781, '6'],
+ ],
},
],
};
@@ -840,7 +848,10 @@ describe('normalizeQueryResponseData', () => {
job: 'prometheus',
instance: 'localhost:9090',
},
- values: [[1435781430.781, '1'], [1435781460.781, 'NaN']],
+ values: [
+ [1435781430.781, '1'],
+ [1435781460.781, 'NaN'],
+ ],
},
],
};
@@ -849,7 +860,10 @@ describe('normalizeQueryResponseData', () => {
{
metric: { __name__: 'up', instance: 'localhost:9090', job: 'prometheus' },
value: ['2015-07-01T20:11:00.781Z', NaN],
- values: [['2015-07-01T20:10:30.781Z', 1], ['2015-07-01T20:11:00.781Z', NaN]],
+ values: [
+ ['2015-07-01T20:10:30.781Z', 1],
+ ['2015-07-01T20:11:00.781Z', NaN],
+ ],
},
]);
});
diff --git a/spec/frontend/monitoring/store_utils.js b/spec/frontend/monitoring/store_utils.js
index 6c8267e6a3c..911ccc78f7b 100644
--- a/spec/frontend/monitoring/store_utils.js
+++ b/spec/frontend/monitoring/store_utils.js
@@ -15,7 +15,7 @@ export const setMetricResult = ({ store, result, group = 0, panel = 0, metric =
});
};
-const setEnvironmentData = store => {
+const setEnvironmentData = (store) => {
store.commit(`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, environmentData);
};
@@ -28,14 +28,14 @@ export const setupAllDashboards = (store, path) => {
}
};
-export const setupStoreWithDashboard = store => {
+export const setupStoreWithDashboard = (store) => {
store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DASHBOARD_SUCCESS}`,
metricsDashboardPayload,
);
};
-export const setupStoreWithLinks = store => {
+export const setupStoreWithLinks = (store) => {
store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DASHBOARD_SUCCESS}`, {
...metricsDashboardPayload,
links: [
@@ -47,7 +47,7 @@ export const setupStoreWithLinks = store => {
});
};
-export const setupStoreWithData = store => {
+export const setupStoreWithData = (store) => {
setupAllDashboards(store);
setupStoreWithDashboard(store);
diff --git a/spec/frontend/monitoring/utils_spec.js b/spec/frontend/monitoring/utils_spec.js
index fd7d09f7f72..cd49e4c7968 100644
--- a/spec/frontend/monitoring/utils_spec.js
+++ b/spec/frontend/monitoring/utils_spec.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+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';
@@ -295,7 +295,7 @@ describe('monitoring/utils', () => {
${'NOT_A_GROUP'} | ${title} | ${yLabel} | ${'group'}
${group} | ${'NOT_A_TITLE'} | ${yLabel} | ${'title'}
${group} | ${title} | ${'NOT_A_Y_LABEL'} | ${'y_label'}
- `('throws an error when $missingField is incorrect', params => {
+ `('throws an error when $missingField is incorrect', (params) => {
const search = `?group=${params.group}&title=${params.title}&y_label=${params.yLabel}`;
expect(() => expandedPanelPayloadFromUrl(metricsDashboardViewModel, search)).toThrow();
});
@@ -308,7 +308,7 @@ describe('monitoring/utils', () => {
const [panelGroup] = metricsDashboardViewModel.panelGroups;
const [panel] = panelGroup.panels;
- const getUrlParams = url => urlUtils.queryToObject(url.split('?')[1]);
+ const getUrlParams = (url) => urlUtils.queryToObject(url.split('?')[1]);
it('returns URL for a panel when query parameters are given', () => {
const params = getUrlParams(panelToUrl(dashboard, {}, panelGroup.group, panel));
diff --git a/spec/frontend/mr_popover/index_spec.js b/spec/frontend/mr_popover/index_spec.js
index b9db2342687..fd8ced17aea 100644
--- a/spec/frontend/mr_popover/index_spec.js
+++ b/spec/frontend/mr_popover/index_spec.js
@@ -1,5 +1,5 @@
+import { setHTMLFixture } from 'helpers/fixtures';
import * as createDefaultClient from '~/lib/graphql';
-import { setHTMLFixture } from '../helpers/fixtures';
import initMRPopovers from '~/mr_popover/index';
createDefaultClient.default = jest.fn();
diff --git a/spec/frontend/new_branch_spec.js b/spec/frontend/new_branch_spec.js
index cff7ec1a9ee..7e6b8a78d4f 100644
--- a/spec/frontend/new_branch_spec.js
+++ b/spec/frontend/new_branch_spec.js
@@ -12,9 +12,7 @@ describe('Branch', () => {
preloadFixtures('branches/new_branch.html');
function fillNameWith(value) {
- $('.js-branch-name')
- .val(value)
- .trigger('blur');
+ $('.js-branch-name').val(value).trigger('blur');
}
function expectToHaveError(error) {
@@ -23,7 +21,7 @@ describe('Branch', () => {
beforeEach(() => {
loadFixtures('branches/new_branch.html');
- $('form').on('submit', e => e.preventDefault());
+ $('form').on('submit', (e) => e.preventDefault());
testContext.form = new NewBranchForm($('.js-create-branch-form'), []);
});
diff --git a/spec/frontend/notebook/cells/code_spec.js b/spec/frontend/notebook/cells/code_spec.js
index 33dabe2b6dc..e14767f2594 100644
--- a/spec/frontend/notebook/cells/code_spec.js
+++ b/spec/frontend/notebook/cells/code_spec.js
@@ -11,7 +11,7 @@ describe('Code component', () => {
json = getJSONFixture('blob/notebook/basic.json');
});
- const setupComponent = cell => {
+ const setupComponent = (cell) => {
const comp = new Component({
propsData: {
cell,
@@ -22,7 +22,7 @@ describe('Code component', () => {
};
describe('without output', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = setupComponent(json.cells[0]);
setImmediate(() => {
@@ -36,7 +36,7 @@ describe('Code component', () => {
});
describe('with output', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = setupComponent(json.cells[2]);
setImmediate(() => {
diff --git a/spec/frontend/notebook/cells/output/index_spec.js b/spec/frontend/notebook/cells/output/index_spec.js
index b9a2dfb8f34..2985abf0f4f 100644
--- a/spec/frontend/notebook/cells/output/index_spec.js
+++ b/spec/frontend/notebook/cells/output/index_spec.js
@@ -7,7 +7,7 @@ describe('Output component', () => {
let vm;
let json;
- const createComponent = output => {
+ const createComponent = (output) => {
vm = new Component({
propsData: {
outputs: [].concat(output),
@@ -18,12 +18,14 @@ describe('Output component', () => {
};
beforeEach(() => {
+ // This is the output after rendering a jupyter notebook
json = getJSONFixture('blob/notebook/basic.json');
});
describe('text output', () => {
- beforeEach(done => {
- createComponent(json.cells[2].outputs[0]);
+ beforeEach((done) => {
+ const textType = json.cells[2];
+ createComponent(textType.outputs[0]);
setImmediate(() => {
done();
@@ -40,8 +42,9 @@ describe('Output component', () => {
});
describe('image output', () => {
- beforeEach(done => {
- createComponent(json.cells[3].outputs[0]);
+ beforeEach((done) => {
+ const imageType = json.cells[3];
+ createComponent(imageType.outputs[0]);
setImmediate(() => {
done();
@@ -55,23 +58,42 @@ describe('Output component', () => {
describe('html output', () => {
it('renders raw HTML', () => {
- createComponent(json.cells[4].outputs[0]);
+ const htmlType = json.cells[4];
+ createComponent(htmlType.outputs[0]);
expect(vm.$el.querySelector('p')).not.toBeNull();
- expect(vm.$el.querySelectorAll('p').length).toBe(1);
+ expect(vm.$el.querySelectorAll('p')).toHaveLength(1);
expect(vm.$el.textContent.trim()).toContain('test');
});
it('renders multiple raw HTML outputs', () => {
- createComponent([json.cells[4].outputs[0], json.cells[4].outputs[0]]);
+ const htmlType = json.cells[4];
+ createComponent([htmlType.outputs[0], htmlType.outputs[0]]);
- expect(vm.$el.querySelectorAll('p').length).toBe(2);
+ expect(vm.$el.querySelectorAll('p')).toHaveLength(2);
+ });
+ });
+
+ describe('LaTeX output', () => {
+ it('renders LaTeX', () => {
+ const output = {
+ data: {
+ 'text/latex': ['$$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$$'],
+ 'text/plain': ['<IPython.core.display.Latex object>'],
+ },
+ metadata: {},
+ output_type: 'display_data',
+ };
+ createComponent(output);
+
+ expect(vm.$el.querySelector('.MathJax')).not.toBeNull();
});
});
describe('svg output', () => {
- beforeEach(done => {
- createComponent(json.cells[5].outputs[0]);
+ beforeEach((done) => {
+ const svgType = json.cells[5];
+ createComponent(svgType.outputs[0]);
setImmediate(() => {
done();
@@ -84,8 +106,9 @@ describe('Output component', () => {
});
describe('default to plain text', () => {
- beforeEach(done => {
- createComponent(json.cells[6].outputs[0]);
+ beforeEach((done) => {
+ const unknownType = json.cells[6];
+ createComponent(unknownType.outputs[0]);
setImmediate(() => {
done();
@@ -101,8 +124,9 @@ describe('Output component', () => {
expect(vm.$el.querySelector('.prompt span')).not.toBeNull();
});
- it("renders as plain text when doesn't recognise other types", done => {
- createComponent(json.cells[7].outputs[0]);
+ it("renders as plain text when doesn't recognise other types", (done) => {
+ const unknownType = json.cells[7];
+ createComponent(unknownType.outputs[0]);
setImmediate(() => {
expect(vm.$el.querySelector('pre')).not.toBeNull();
diff --git a/spec/frontend/notebook/cells/output/latex_spec.js b/spec/frontend/notebook/cells/output/latex_spec.js
new file mode 100644
index 00000000000..848d2069421
--- /dev/null
+++ b/spec/frontend/notebook/cells/output/latex_spec.js
@@ -0,0 +1,40 @@
+import { shallowMount } from '@vue/test-utils';
+import LatexOutput from '~/notebook/cells/output/latex.vue';
+import Prompt from '~/notebook/cells/prompt.vue';
+
+describe('LaTeX output cell', () => {
+ beforeEach(() => {
+ window.MathJax = {
+ tex2svg: jest.fn((code) => ({ outerHTML: code })),
+ };
+ });
+
+ const inlineLatex = '$$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$$';
+ const count = 12345;
+
+ const createComponent = (rawCode, index) =>
+ shallowMount(LatexOutput, {
+ propsData: {
+ count,
+ index,
+ rawCode,
+ },
+ });
+
+ it.each`
+ index | expectation
+ ${0} | ${true}
+ ${1} | ${false}
+ `('sets `Prompt.show-output` to $expectation when index is $index', ({ index, expectation }) => {
+ const wrapper = createComponent(inlineLatex, index);
+ const prompt = wrapper.find(Prompt);
+
+ expect(prompt.props().count).toEqual(count);
+ expect(prompt.props().showOutput).toEqual(expectation);
+ });
+
+ it('strips the `$$` delimter from LaTeX', () => {
+ createComponent(inlineLatex, 0);
+ expect(window.MathJax.tex2svg).toHaveBeenCalledWith(expect.not.stringContaining('$$'));
+ });
+});
diff --git a/spec/frontend/notebook/cells/prompt_spec.js b/spec/frontend/notebook/cells/prompt_spec.js
index cf5a7a603c6..8cdcd1f84de 100644
--- a/spec/frontend/notebook/cells/prompt_spec.js
+++ b/spec/frontend/notebook/cells/prompt_spec.js
@@ -7,7 +7,7 @@ describe('Prompt component', () => {
let vm;
describe('input', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
type: 'In',
@@ -31,7 +31,7 @@ describe('Prompt component', () => {
});
describe('output', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
type: 'Out',
diff --git a/spec/frontend/notebook/index_spec.js b/spec/frontend/notebook/index_spec.js
index 36b092be976..945af08e4d5 100644
--- a/spec/frontend/notebook/index_spec.js
+++ b/spec/frontend/notebook/index_spec.js
@@ -14,7 +14,7 @@ describe('Notebook component', () => {
});
describe('without JSON', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
notebook: {},
@@ -33,7 +33,7 @@ describe('Notebook component', () => {
});
describe('with JSON', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
notebook: json,
@@ -65,7 +65,7 @@ describe('Notebook component', () => {
});
describe('with worksheets', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
notebook: jsonWithWorksheet,
diff --git a/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap b/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
deleted file mode 100644
index 13af29821d8..00000000000
--- a/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
+++ /dev/null
@@ -1,21 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`JumpToNextDiscussionButton matches the snapshot 1`] = `
-<div
- class="btn-group"
- role="group"
->
- <button
- class="btn btn-default discussion-next-btn"
- data-track-event="click_button"
- data-track-label="mr_next_unresolved_thread"
- data-track-property="click_next_unresolved_thread"
- title="Jump to next unresolved thread"
- >
- <gl-icon-stub
- name="comment-next"
- size="16"
- />
- </button>
-</div>
-`;
diff --git a/spec/frontend/notes/components/comment_field_layout_spec.js b/spec/frontend/notes/components/comment_field_layout_spec.js
new file mode 100644
index 00000000000..4d9b4ea8c6f
--- /dev/null
+++ b/spec/frontend/notes/components/comment_field_layout_spec.js
@@ -0,0 +1,137 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommentFieldLayout from '~/notes/components/comment_field_layout.vue';
+import EmailParticipantsWarning from '~/notes/components/email_participants_warning.vue';
+import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
+
+describe('Comment Field Layout Component', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const LOCKED_DISCUSSION_DOCS_PATH = 'docs/locked/path';
+ const CONFIDENTIAL_ISSUES_DOCS_PATH = 'docs/confidential/path';
+
+ const noteableDataMock = {
+ confidential: false,
+ discussion_locked: false,
+ locked_discussion_docs_path: LOCKED_DISCUSSION_DOCS_PATH,
+ confidential_issues_docs_path: CONFIDENTIAL_ISSUES_DOCS_PATH,
+ };
+
+ const findIssuableNoteWarning = () => wrapper.find(NoteableWarning);
+ const findEmailParticipantsWarning = () => wrapper.find(EmailParticipantsWarning);
+ const findErrorAlert = () => wrapper.findByTestId('comment-field-alert-container');
+
+ const createWrapper = (props = {}, slots = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommentFieldLayout, {
+ propsData: {
+ noteableData: noteableDataMock,
+ ...props,
+ },
+ slots,
+ }),
+ );
+ };
+
+ describe('.error-alert', () => {
+ it('does not exist by default', () => {
+ createWrapper();
+
+ expect(findErrorAlert().exists()).toBe(false);
+ });
+
+ it('exists when withAlertContainer is true', () => {
+ createWrapper({ withAlertContainer: true });
+
+ expect(findErrorAlert().isVisible()).toBe(true);
+ });
+ });
+
+ describe('issue is not confidential and not locked', () => {
+ it('does not show IssuableNoteWarning', () => {
+ createWrapper();
+
+ expect(findIssuableNoteWarning().exists()).toBe(false);
+ });
+ });
+
+ describe('issue is confidential', () => {
+ beforeEach(() => {
+ createWrapper({
+ noteableData: { ...noteableDataMock, confidential: true },
+ });
+ });
+
+ it('shows IssuableNoteWarning', () => {
+ expect(findIssuableNoteWarning().isVisible()).toBe(true);
+ });
+
+ it('sets IssuableNoteWarning props', () => {
+ expect(findIssuableNoteWarning().props()).toMatchObject({
+ isLocked: false,
+ isConfidential: true,
+ lockedNoteableDocsPath: LOCKED_DISCUSSION_DOCS_PATH,
+ confidentialNoteableDocsPath: CONFIDENTIAL_ISSUES_DOCS_PATH,
+ });
+ });
+ });
+
+ describe('issue is locked', () => {
+ beforeEach(() => {
+ createWrapper({
+ noteableData: { ...noteableDataMock, discussion_locked: true },
+ });
+ });
+
+ it('shows IssuableNoteWarning', () => {
+ expect(findIssuableNoteWarning().isVisible()).toBe(true);
+ });
+
+ it('sets IssuableNoteWarning props', () => {
+ expect(findIssuableNoteWarning().props()).toMatchObject({
+ isConfidential: false,
+ isLocked: true,
+ lockedNoteableDocsPath: LOCKED_DISCUSSION_DOCS_PATH,
+ confidentialNoteableDocsPath: CONFIDENTIAL_ISSUES_DOCS_PATH,
+ });
+ });
+ });
+
+ describe('issue has no email participants', () => {
+ it('does not show EmailParticipantsWarning', () => {
+ createWrapper();
+
+ expect(findEmailParticipantsWarning().exists()).toBe(false);
+ });
+ });
+
+ describe('issue has email participants', () => {
+ beforeEach(() => {
+ createWrapper({
+ noteableData: {
+ ...noteableDataMock,
+ issue_email_participants: [
+ { email: 'someone@gitlab.com' },
+ { email: 'another@gitlab.com' },
+ ],
+ },
+ });
+ });
+
+ it('shows EmailParticipantsWarning', () => {
+ expect(findEmailParticipantsWarning().isVisible()).toBe(true);
+ });
+
+ it('sets EmailParticipantsWarning props', () => {
+ expect(findEmailParticipantsWarning().props('emails')).toEqual([
+ 'someone@gitlab.com',
+ 'another@gitlab.com',
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index fca1beca999..002c4f206cb 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -181,7 +181,7 @@ describe('issue_comment_form component', () => {
describe('edit mode', () => {
beforeEach(() => {
- mountComponent();
+ mountComponent({ mountFunction: mount });
});
it('should enter edit mode when arrow up is pressed', () => {
@@ -200,7 +200,7 @@ describe('issue_comment_form component', () => {
describe('event enter', () => {
beforeEach(() => {
- mountComponent();
+ mountComponent({ mountFunction: mount });
});
it('should save note when cmd+enter is pressed', () => {
@@ -368,17 +368,6 @@ describe('issue_comment_form component', () => {
});
});
});
-
- describe('issue is confidential', () => {
- it('shows information warning', () => {
- mountComponent({
- noteableData: { ...noteableDataMock, confidential: true },
- mountFunction: mount,
- });
-
- expect(wrapper.find('[data-testid="confidential-warning"]').exists()).toBe(true);
- });
- });
});
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 9162bee2078..3940439a32b 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -45,7 +45,7 @@ describe('diff_discussion_header component', () => {
const truncatedCommitId = commitId.substr(0, 8);
let commitElement;
- beforeEach(done => {
+ beforeEach((done) => {
store.state.diffs = {
projectPath: 'something',
};
@@ -72,7 +72,7 @@ describe('diff_discussion_header component', () => {
});
describe('for diff threads without a commit id', () => {
- it('should show started a thread on the diff text', done => {
+ it('should show started a thread on the diff text', (done) => {
Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
@@ -85,7 +85,7 @@ describe('diff_discussion_header component', () => {
});
});
- it('should show thread on older version text', done => {
+ it('should show thread on older version text', (done) => {
Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
@@ -109,7 +109,7 @@ describe('diff_discussion_header component', () => {
});
describe('for diff thread with a commit id', () => {
- it('should display started thread on commit header', done => {
+ it('should display started thread on commit header', (done) => {
wrapper.vm.discussion.for_commit = false;
wrapper.vm.$nextTick(() => {
@@ -121,7 +121,7 @@ describe('diff_discussion_header component', () => {
});
});
- it('should display outdated change on commit header', done => {
+ it('should display outdated change on commit header', (done) => {
wrapper.vm.discussion.for_commit = false;
wrapper.vm.discussion.active = false;
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index b26eb00bfdc..48e569720e9 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -4,7 +4,6 @@ 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 JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
import createStore from '~/notes/stores';
// NOTE: clone mock_data so that it is not accidentally mutated
@@ -21,7 +20,7 @@ const createUnallowedNote = () =>
describe('DiscussionActions', () => {
let wrapper;
- const createComponentFactory = (shallow = true) => (props, options) => {
+ const createComponentFactory = (shallow = true) => (props) => {
const store = createStore();
const mountFn = shallow ? shallowMount : mount;
@@ -35,11 +34,6 @@ describe('DiscussionActions', () => {
shouldShowJumpToNextDiscussion: true,
...props,
},
- provide: {
- glFeatures: {
- hideJumpToNextUnresolvedInThreads: options?.hideJumpToNextUnresolvedInThreads,
- },
- },
});
};
@@ -55,7 +49,6 @@ describe('DiscussionActions', () => {
expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(true);
expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(true);
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(true);
});
it('only renders reply placholder if disccusion is not resolvable', () => {
@@ -66,7 +59,6 @@ describe('DiscussionActions', () => {
expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false);
expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
});
it('does not render resolve with issue button if resolveWithIssuePath is falsy', () => {
@@ -75,12 +67,6 @@ describe('DiscussionActions', () => {
expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
});
- it('does not render jump to next discussion button if shouldShowJumpToNextDiscussion is false', () => {
- createComponent({ shouldShowJumpToNextDiscussion: false });
-
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
- });
-
describe.each`
desc | notes | shouldRender
${'with no notes'} | ${[]} | ${true}
@@ -101,13 +87,6 @@ describe('DiscussionActions', () => {
});
});
- it('does not render jump to next discussion button if feature flag is enabled', () => {
- const createComponent = createComponentFactory();
- createComponent({}, { hideJumpToNextUnresolvedInThreads: true });
-
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
- });
-
describe('events handling', () => {
const createComponent = createComponentFactory(false);
@@ -117,19 +96,13 @@ describe('DiscussionActions', () => {
it('emits showReplyForm event when clicking on reply placeholder', () => {
jest.spyOn(wrapper.vm, '$emit');
- wrapper
- .find(ReplyPlaceholder)
- .find('button')
- .trigger('click');
+ wrapper.find(ReplyPlaceholder).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm');
});
it('emits resolve event when clicking on resolve button', () => {
jest.spyOn(wrapper.vm, '$emit');
- wrapper
- .find(ResolveDiscussionButton)
- .find('button')
- .trigger('click');
+ wrapper.find(ResolveDiscussionButton).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve');
});
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index d82590c7e9e..ebf7d52f38b 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -95,7 +95,7 @@ describe('DiscussionCounter component', () => {
describe('toggle all threads button', () => {
let toggleAllButton;
- const updateStoreWithExpanded = expanded => {
+ const updateStoreWithExpanded = (expanded) => {
const discussion = { ...discussionMock, expanded };
store.commit(types.SET_INITIAL_DISCUSSIONS, [discussion]);
store.dispatch('updateResolvableDiscussionsCounts');
diff --git a/spec/frontend/notes/components/discussion_filter_note_spec.js b/spec/frontend/notes/components/discussion_filter_note_spec.js
index d35f8f7c28d..9ae3f08df77 100644
--- a/spec/frontend/notes/components/discussion_filter_note_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_note_spec.js
@@ -31,20 +31,14 @@ describe('DiscussionFilterNote component', () => {
it('emits `dropdownSelect` event with 0 parameter on clicking Show all activity button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper
- .findAll(GlButton)
- .at(0)
- .vm.$emit('click');
+ wrapper.findAll(GlButton).at(0).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 0);
});
it('emits `dropdownSelect` event with 1 parameter on clicking Show comments only button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper
- .findAll(GlButton)
- .at(1)
- .vm.$emit('click');
+ wrapper.findAll(GlButton).at(1).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 1);
});
diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js
index 9f3655c53b9..aeba8e8056c 100644
--- a/spec/frontend/notes/components/discussion_filter_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_spec.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import createEventHub from '~/helpers/event_hub_factory';
import axios from '~/lib/utils/axios_utils';
@@ -25,7 +25,8 @@ describe('DiscussionFilter component', () => {
const filterDiscussion = jest.fn();
- const findFilter = filterType => wrapper.find(`.dropdown-item[data-filter-type="${filterType}"]`);
+ const findFilter = (filterType) =>
+ wrapper.find(`.dropdown-item[data-filter-type="${filterType}"]`);
const mountComponent = () => {
const discussions = [
@@ -82,12 +83,9 @@ describe('DiscussionFilter component', () => {
});
it('renders the default selected item', () => {
- expect(
- wrapper
- .find('#discussion-filter-dropdown .dropdown-item')
- .text()
- .trim(),
- ).toBe(discussionFiltersMock[0].title);
+ expect(wrapper.find('#discussion-filter-dropdown .dropdown-item').text().trim()).toBe(
+ discussionFiltersMock[0].title,
+ );
});
it('updates to the selected item', () => {
@@ -148,7 +146,7 @@ describe('DiscussionFilter component', () => {
window.mrTabs = undefined;
});
- it('only renders when discussion tab is active', done => {
+ it('only renders when discussion tab is active', (done) => {
eventHub.$emit('MergeRequestTabChange', 'commit');
wrapper.vm.$nextTick(() => {
@@ -163,7 +161,7 @@ describe('DiscussionFilter component', () => {
window.location.hash = '';
});
- it('updates the filter when the URL links to a note', done => {
+ it('updates the filter when the URL links to a note', (done) => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.currentValue = discussionFiltersMock[2].value;
wrapper.vm.handleLocationHash();
@@ -174,7 +172,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('does not update the filter when the current filter is "Show all activity"', done => {
+ it('does not update the filter when the current filter is "Show all activity"', (done) => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.handleLocationHash();
@@ -184,7 +182,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('only updates filter when the URL links to a note', done => {
+ it('only updates filter when the URL links to a note', (done) => {
window.location.hash = `testing123`;
wrapper.vm.handleLocationHash();
@@ -194,7 +192,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('fetches discussions when there is a hash', done => {
+ it('fetches discussions when there is a hash', (done) => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.currentValue = discussionFiltersMock[2].value;
jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
@@ -206,7 +204,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('does not fetch discussions when there is no hash', done => {
+ it('does not fetch discussions when there is no hash', (done) => {
window.location.hash = '';
jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
wrapper.vm.handleLocationHash();
diff --git a/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js b/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
deleted file mode 100644
index 183966cf435..00000000000
--- a/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
-import { mockTracking } from '../../helpers/tracking_helper';
-
-describe('JumpToNextDiscussionButton', () => {
- const fromDiscussionId = 'abc123';
- let wrapper;
- let trackingSpy;
- let jumpFn;
-
- beforeEach(() => {
- jumpFn = jest.fn();
- wrapper = shallowMount(JumpToNextDiscussionButton, {
- propsData: { fromDiscussionId },
- });
- wrapper.setMethods({ jumpToNextRelativeDiscussion: jumpFn });
-
- trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('matches the snapshot', () => {
- expect(wrapper.vm.$el).toMatchSnapshot();
- });
-
- it('calls jumpToNextRelativeDiscussion when clicked', () => {
- wrapper.find({ ref: 'button' }).trigger('click');
-
- expect(jumpFn).toHaveBeenCalledWith(fromDiscussionId);
- });
-
- it('sends the correct tracking event when clicked', () => {
- wrapper.find({ ref: 'button' }).trigger('click');
-
- expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
- label: 'mr_next_unresolved_thread',
- property: 'click_next_unresolved_thread',
- });
- });
-});
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index 8cc98f978c2..e803dcb7b4a 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -122,12 +122,11 @@ describe('DiscussionNotes', () => {
describe('events', () => {
describe('with groupped notes and replies expanded', () => {
- const findNoteAtIndex = index => {
+ const findNoteAtIndex = (index) => {
const noteComponents = [NoteableNote, SystemNote, PlaceholderNote, PlaceholderSystemNote];
- const allowedNames = noteComponents.map(c => c.name);
return wrapper
.findAll('.notes *')
- .filter(w => allowedNames.includes(w.name()))
+ .filter((w) => noteComponents.some((Component) => w.is(Component)))
.at(index);
};
diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js
index 41701e54dfa..5105e1013d3 100644
--- a/spec/frontend/notes/components/discussion_resolve_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js
@@ -7,7 +7,7 @@ const buttonTitle = 'Resolve discussion';
describe('resolveDiscussionButton', () => {
let wrapper;
- const factory = options => {
+ const factory = (options) => {
wrapper = shallowMount(resolveDiscussionButton, {
...options,
});
diff --git a/spec/frontend/notes/components/email_participants_warning_spec.js b/spec/frontend/notes/components/email_participants_warning_spec.js
new file mode 100644
index 00000000000..ab1a6b152a4
--- /dev/null
+++ b/spec/frontend/notes/components/email_participants_warning_spec.js
@@ -0,0 +1,70 @@
+import { mount } from '@vue/test-utils';
+import EmailParticipantsWarning from '~/notes/components/email_participants_warning.vue';
+
+describe('Email Participants Warning Component', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findMoreButton = () => wrapper.find('button');
+
+ const createWrapper = (emails) => {
+ wrapper = mount(EmailParticipantsWarning, {
+ propsData: { emails },
+ });
+ };
+
+ describe('with 3 or less emails', () => {
+ beforeEach(() => {
+ createWrapper(['a@gitlab.com', 'b@gitlab.com', 'c@gitlab.com']);
+ });
+
+ it('more button does not exist', () => {
+ expect(findMoreButton().exists()).toBe(false);
+ });
+
+ it('all emails are displayed', () => {
+ expect(wrapper.text()).toBe(
+ 'a@gitlab.com, b@gitlab.com, and c@gitlab.com will be notified of your comment.',
+ );
+ });
+ });
+
+ describe('with more than 3 emails', () => {
+ beforeEach(() => {
+ createWrapper(['a@gitlab.com', 'b@gitlab.com', 'c@gitlab.com', 'd@gitlab.com']);
+ });
+
+ it('only displays first 3 emails', () => {
+ expect(wrapper.text()).toContain('a@gitlab.com, b@gitlab.com, c@gitlab.com');
+ expect(wrapper.text()).not.toContain('d@gitlab.com');
+ });
+
+ it('more button does exist', () => {
+ expect(findMoreButton().exists()).toBe(true);
+ });
+
+ it('more button displays the correct wordage', () => {
+ expect(findMoreButton().text()).toBe('and 1 more');
+ });
+
+ describe('when more button clicked', () => {
+ beforeEach(() => {
+ findMoreButton().trigger('click');
+ });
+
+ it('more button no longer exists', () => {
+ expect(findMoreButton().exists()).toBe(false);
+ });
+
+ it('all emails are displayed', () => {
+ expect(wrapper.text()).toBe(
+ 'a@gitlab.com, b@gitlab.com, c@gitlab.com, and d@gitlab.com will be notified of your comment.',
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/multiline_comment_form_spec.js b/spec/frontend/notes/components/multiline_comment_form_spec.js
new file mode 100644
index 00000000000..081fd6e10ef
--- /dev/null
+++ b/spec/frontend/notes/components/multiline_comment_form_spec.js
@@ -0,0 +1,89 @@
+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';
+
+describe('MultilineCommentForm', () => {
+ Vue.use(Vuex);
+ const setSelectedCommentPosition = jest.fn();
+ const testLine = {
+ line_code: 'test',
+ type: 'test',
+ old_line: 'test',
+ new_line: 'test',
+ };
+
+ const createWrapper = (props = {}, state) => {
+ setSelectedCommentPosition.mockReset();
+
+ const store = new Vuex.Store({
+ modules: { notes: notesModule() },
+ actions: { setSelectedCommentPosition },
+ });
+ if (state) store.replaceState({ ...store.state, ...state });
+
+ const propsData = {
+ line: { ...testLine },
+ commentLineOptions: [{ text: '1' }],
+ ...props,
+ };
+ return mount(MultilineCommentForm, { propsData, store });
+ };
+
+ describe('created', () => {
+ it('sets commentLineStart to line', () => {
+ const line = { ...testLine };
+ const wrapper = createWrapper({ line });
+
+ expect(wrapper.vm.commentLineStart).toEqual(line);
+ expect(setSelectedCommentPosition).toHaveBeenCalled();
+ });
+
+ it('sets commentLineStart to lineRange', () => {
+ const lineRange = {
+ start: { ...testLine },
+ };
+ const wrapper = createWrapper({ lineRange });
+
+ expect(wrapper.vm.commentLineStart).toEqual(lineRange.start);
+ expect(setSelectedCommentPosition).toHaveBeenCalled();
+ });
+
+ it('sets commentLineStart to selectedCommentPosition', () => {
+ const notes = {
+ selectedCommentPosition: {
+ start: { ...testLine },
+ },
+ };
+ const wrapper = createWrapper({}, { notes });
+
+ expect(wrapper.vm.commentLineStart).toEqual(wrapper.vm.selectedCommentPosition.start);
+ expect(setSelectedCommentPosition).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('destroyed', () => {
+ it('calls setSelectedCommentPosition', () => {
+ const wrapper = createWrapper();
+ wrapper.destroy();
+
+ // Once during created, once during destroyed
+ expect(setSelectedCommentPosition).toHaveBeenCalledTimes(2);
+ });
+ });
+
+ it('handles changing the start line', () => {
+ const line = { ...testLine };
+ const wrapper = createWrapper({ line });
+ const glSelect = wrapper.findComponent(GlFormSelect);
+
+ glSelect.vm.$emit('change', { ...testLine });
+
+ expect(wrapper.vm.commentLineStart).toEqual(line);
+ expect(wrapper.emitted('input')).toBeTruthy();
+ // Once during created, once during updateCommentLineStart
+ expect(setSelectedCommentPosition).toHaveBeenCalledTimes(2);
+ });
+});
diff --git a/spec/frontend/notes/components/multiline_comment_utils_spec.js b/spec/frontend/notes/components/multiline_comment_utils_spec.js
index 99b33e7cd5f..05faff02a6c 100644
--- a/spec/frontend/notes/components/multiline_comment_utils_spec.js
+++ b/spec/frontend/notes/components/multiline_comment_utils_spec.js
@@ -7,7 +7,7 @@ import {
describe('Multiline comment utilities', () => {
describe('get start & end line numbers', () => {
- const lineRanges = ['old', 'new', null].map(type => ({
+ const lineRanges = ['old', 'new', null].map((type) => ({
start: { new_line: 1, old_line: 1, type },
end: { new_line: 2, old_line: 2, type },
}));
@@ -35,7 +35,7 @@ describe('Multiline comment utilities', () => {
});
});
const inlineDiffLines = [{ line_code: '1' }, { line_code: '2' }, { line_code: '3' }];
- const parallelDiffLines = inlineDiffLines.map(line => ({
+ const parallelDiffLines = inlineDiffLines.map((line) => ({
left: { ...line },
right: { ...line },
}));
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index f01c6c6b84e..3cfc1445cb8 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -65,23 +65,11 @@ describe('noteActions', () => {
});
it('should render noteable author badge', () => {
- expect(
- wrapper
- .findAll('.note-role')
- .at(0)
- .text()
- .trim(),
- ).toEqual('Author');
+ expect(wrapper.findAll('.note-role').at(0).text().trim()).toEqual('Author');
});
it('should render access level badge', () => {
- expect(
- wrapper
- .findAll('.note-role')
- .at(1)
- .text()
- .trim(),
- ).toEqual(props.accessLevel);
+ expect(wrapper.findAll('.note-role').at(1).text().trim()).toEqual(props.accessLevel);
});
it('should render contributor badge', () => {
@@ -91,13 +79,7 @@ describe('noteActions', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(
- wrapper
- .findAll('.note-role')
- .at(1)
- .text()
- .trim(),
- ).toBe('Contributor');
+ expect(wrapper.findAll('.note-role').at(1).text().trim()).toBe('Contributor');
});
});
@@ -119,7 +101,7 @@ describe('noteActions', () => {
expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(true);
});
- it('should not show copy link action when `noteUrl` prop is empty', done => {
+ it('should not show copy link action when `noteUrl` prop is empty', (done) => {
wrapper.setProps({
...props,
author: {
@@ -145,7 +127,7 @@ describe('noteActions', () => {
expect(wrapper.find('.js-note-delete').exists()).toBe(true);
});
- it('closes tooltip when dropdown opens', done => {
+ it('closes tooltip when dropdown opens', (done) => {
wrapper.find('.more-actions-toggle').trigger('click');
const rootWrapper = createWrapper(wrapper.vm.$root);
diff --git a/spec/frontend/notes/components/note_attachment_spec.js b/spec/frontend/notes/components/note_attachment_spec.js
index 9d1051676e1..d47c2beaaf8 100644
--- a/spec/frontend/notes/components/note_attachment_spec.js
+++ b/spec/frontend/notes/components/note_attachment_spec.js
@@ -7,7 +7,7 @@ describe('Issue note attachment', () => {
const findImage = () => wrapper.find({ ref: 'attachmentImage' });
const findUrl = () => wrapper.find({ ref: 'attachmentUrl' });
- const createComponent = attachment => {
+ const createComponent = (attachment) => {
wrapper = shallowMount(NoteAttachment, {
propsData: {
attachment,
diff --git a/spec/frontend/notes/components/note_awards_list_spec.js b/spec/frontend/notes/components/note_awards_list_spec.js
index 5ab183e5452..13a817902e6 100644
--- a/spec/frontend/notes/components/note_awards_list_spec.js
+++ b/spec/frontend/notes/components/note_awards_list_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+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';
@@ -106,7 +106,7 @@ describe('note_awards_list component', () => {
awardsMock = [...new Array(1)].map(createAwardEmoji);
mountComponent();
- awardsMock.forEach(award => {
+ awardsMock.forEach((award) => {
expect(findTooltip()).toContain(award.user.name);
});
});
@@ -115,7 +115,7 @@ describe('note_awards_list component', () => {
awardsMock = [...new Array(2)].map(createAwardEmoji);
mountComponent();
- awardsMock.forEach(award => {
+ awardsMock.forEach((award) => {
expect(findTooltip()).toContain(award.user.name);
});
});
@@ -125,7 +125,7 @@ describe('note_awards_list component', () => {
mountComponent();
// Testing only the first 10 awards since 11 onward will not be displayed.
- awardsMock.slice(0, 10).forEach(award => {
+ awardsMock.slice(0, 10).forEach((award) => {
expect(findTooltip()).toContain(award.user.name);
});
});
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index efad0785afe..3c11c266f90 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -38,7 +38,7 @@ describe('issue_note_body component', () => {
});
describe('isEditing', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.isEditing = true;
Vue.nextTick(done);
});
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index cc434d6c952..e64a75bede9 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+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';
@@ -18,17 +19,14 @@ describe('issue_note_form component', () => {
let props;
const createComponentWrapper = () => {
- const localVue = createLocalVue();
- return shallowMount(localVue.extend(NoteForm), {
+ return mount(NoteForm, {
store,
propsData: props,
- // see https://gitlab.com/gitlab-org/gitlab-foss/issues/56317 for the following
- localVue,
});
};
beforeEach(() => {
- getDraft.mockImplementation(key => {
+ getDraft.mockImplementation((key) => {
if (key === dummyAutosaveKey) {
return dummyDraft;
}
@@ -60,15 +58,14 @@ describe('issue_note_form component', () => {
expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`);
});
- it('return note hash as `#` when `noteId` is empty', () => {
+ it('return note hash as `#` when `noteId` is empty', async () => {
wrapper.setProps({
...props,
noteId: '',
});
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.noteHash).toBe('#');
- });
+ expect(wrapper.vm.noteHash).toBe('#');
});
});
@@ -77,7 +74,7 @@ describe('issue_note_form component', () => {
wrapper = createComponentWrapper();
});
- it('should show conflict message if note changes outside the component', () => {
+ it('should show conflict message if note changes outside the component', async () => {
wrapper.setProps({
...props,
isEditing: true,
@@ -87,17 +84,12 @@ describe('issue_note_form component', () => {
const message =
'This comment has changed since you started editing, please review the updated comment to ensure information is not lost.';
- return wrapper.vm.$nextTick().then(() => {
- const conflictWarning = wrapper.find('.js-conflict-edit-warning');
+ await nextTick();
- expect(conflictWarning.exists()).toBe(true);
- expect(
- conflictWarning
- .text()
- .replace(/\s+/g, ' ')
- .trim(),
- ).toBe(message);
- });
+ const conflictWarning = wrapper.find('.js-conflict-edit-warning');
+
+ expect(conflictWarning.exists()).toBe(true);
+ expect(conflictWarning.text().replace(/\s+/g, ' ').trim()).toBe(message);
});
});
@@ -161,36 +153,33 @@ describe('issue_note_form component', () => {
});
describe('actions', () => {
- it('should be possible to cancel', () => {
- const cancelHandler = jest.fn();
+ it('should be possible to cancel', async () => {
wrapper.setProps({
...props,
isEditing: true,
});
- wrapper.setMethods({ cancelHandler });
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- const cancelButton = wrapper.find('[data-testid="cancel"]');
- cancelButton.trigger('click');
+ const cancelButton = wrapper.find('[data-testid="cancel"]');
+ cancelButton.trigger('click');
+ await nextTick();
- expect(cancelHandler).toHaveBeenCalledWith(true);
- });
+ expect(wrapper.emitted().cancelForm).toHaveLength(1);
});
- it('should be possible to update the note', () => {
+ it('should be possible to update the note', async () => {
wrapper.setProps({
...props,
isEditing: true,
});
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- const textarea = wrapper.find('textarea');
- textarea.setValue('Foo');
- const saveButton = wrapper.find('.js-vue-issue-save');
- saveButton.trigger('click');
+ const textarea = wrapper.find('textarea');
+ textarea.setValue('Foo');
+ const saveButton = wrapper.find('.js-vue-issue-save');
+ saveButton.trigger('click');
- expect(wrapper.vm.isSubmitting).toBe(true);
- });
+ expect(wrapper.vm.isSubmitting).toBe(true);
});
});
});
@@ -204,7 +193,7 @@ describe('issue_note_form component', () => {
});
wrapper = createComponentWrapper();
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('displays the draft in textarea', () => {
@@ -222,7 +211,7 @@ describe('issue_note_form component', () => {
});
wrapper = createComponentWrapper();
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('leaves the textarea empty', () => {
@@ -278,15 +267,14 @@ describe('issue_note_form component', () => {
});
});
- it('should be possible to cancel', () => {
+ it('should be possible to cancel', async () => {
jest.spyOn(wrapper.vm, 'cancelHandler');
- return wrapper.vm.$nextTick().then(() => {
- const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
- cancelButton.trigger('click');
+ await nextTick();
+ const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
+ cancelButton.trigger('click');
- expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
- });
+ expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
});
it('shows resolve checkbox', () => {
@@ -299,7 +287,7 @@ describe('issue_note_form component', () => {
discussion: {
...discussionMock,
notes: [
- ...discussionMock.notes.map(n => ({
+ ...discussionMock.notes.map((n) => ({
...n,
resolvable: true,
current_user: { ...n.current_user, can_resolve_discussion: false },
@@ -309,7 +297,7 @@ describe('issue_note_form component', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(false);
});
@@ -317,7 +305,7 @@ describe('issue_note_form component', () => {
it('hides actions for commits', () => {
wrapper.setProps({ discussion: { for_commit: true } });
- return wrapper.vm.$nextTick(() => {
+ return nextTick(() => {
expect(wrapper.find('.note-form-actions').text()).not.toContain('Start a review');
});
});
@@ -331,7 +319,7 @@ describe('issue_note_form component', () => {
textarea.setValue('Foo');
textarea.trigger('keydown.enter', { metaKey: true });
- return wrapper.vm.$nextTick(() => {
+ return 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 1c6d0bafda8..132e3d8aa7e 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -41,7 +41,7 @@ describe('NoteHeader component', () => {
},
};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(NoteHeader, {
localVue,
store: new Vuex.Store({
@@ -252,7 +252,7 @@ describe('NoteHeader component', () => {
});
describe('when author username link is hovered', () => {
- it('toggles hover specific CSS classes on author name link', done => {
+ it('toggles hover specific CSS classes on author name link', (done) => {
createComponent({ author });
const authorUsernameLink = wrapper.find({ ref: 'authorUsernameLink' });
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 1c6603899d3..b87c6cd7f2b 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -1,8 +1,10 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { trimText } from 'helpers/text_helper';
import createStore from '~/notes/stores';
-import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
+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';
@@ -17,8 +19,6 @@ import {
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
-const localVue = createLocalVue();
-
describe('noteable_discussion component', () => {
let store;
let wrapper;
@@ -32,10 +32,9 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- wrapper = mount(localVue.extend(noteableDiscussion), {
+ wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- localVue,
});
});
@@ -47,63 +46,58 @@ describe('noteable_discussion component', () => {
expect(wrapper.find('.discussion-header').exists()).toBe(false);
});
- it('should render thread header', () => {
+ it('should render thread header', async () => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true;
discussion.expanded = false;
wrapper.setProps({ discussion });
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.discussion-header').exists()).toBe(true);
- });
+ expect(wrapper.find('.discussion-header').exists()).toBe(true);
});
describe('actions', () => {
- it('should toggle reply form', () => {
- const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+ it('should toggle reply form', async () => {
+ await nextTick();
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.vm.isReplying).toEqual(false);
+ expect(wrapper.vm.isReplying).toEqual(false);
- replyPlaceholder.vm.$emit('onClick');
- })
- .then(() => wrapper.vm.$nextTick())
- .then(() => {
- expect(wrapper.vm.isReplying).toEqual(true);
+ const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+ replyPlaceholder.vm.$emit('onClick');
+ await nextTick();
- const noteForm = wrapper.find(NoteForm);
+ expect(wrapper.vm.isReplying).toEqual(true);
- expect(noteForm.exists()).toBe(true);
+ const noteForm = wrapper.find(NoteForm);
- const noteFormProps = noteForm.props();
+ expect(noteForm.exists()).toBe(true);
- expect(noteFormProps.discussion).toBe(discussionMock);
- expect(noteFormProps.isEditing).toBe(false);
- expect(noteFormProps.line).toBe(null);
- expect(noteFormProps.saveButtonTitle).toBe('Comment');
- expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
- });
+ const noteFormProps = noteForm.props();
+
+ expect(noteFormProps.discussion).toBe(discussionMock);
+ expect(noteFormProps.isEditing).toBe(false);
+ expect(noteFormProps.line).toBe(null);
+ expect(noteFormProps.saveButtonTitle).toBe('Comment');
+ expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
});
it('should expand discussion', async () => {
- const expandDiscussion = jest.fn();
- const discussion = { ...discussionMock };
- discussion.expanded = false;
+ const discussion = { ...discussionMock, expanded: false };
wrapper.setProps({ discussion });
- wrapper.setMethods({ expandDiscussion });
+ store.dispatch = jest.fn();
- await wrapper.vm.$nextTick();
+ await nextTick();
- wrapper.vm.showReplyForm();
+ wrapper.find(DiscussionNotes).vm.$emit('startReplying');
- await wrapper.vm.$nextTick();
+ await nextTick();
- expect(expandDiscussion).toHaveBeenCalledWith({ discussionId: discussion.id });
+ expect(store.dispatch).toHaveBeenCalledWith('expandDiscussion', {
+ discussionId: discussion.id,
+ });
});
it('does not render jump to thread button', () => {
@@ -132,7 +126,7 @@ describe('noteable_discussion component', () => {
...getJSONFixture(discussionWithTwoUnresolvedNotes)[0],
expanded: true,
};
- discussion.notes = discussion.notes.map(note => ({
+ discussion.notes = discussion.notes.map((note) => ({
...note,
resolved: false,
current_user: {
@@ -143,7 +137,7 @@ describe('noteable_discussion component', () => {
wrapper.setProps({ discussion });
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('displays a button to resolve with issue', () => {
@@ -169,10 +163,9 @@ describe('noteable_discussion component', () => {
window.gon.current_user_id = userDataMock.id;
store.dispatch('setUserData', userDataMock);
- wrapper = mount(localVue.extend(noteableDiscussion), {
+ wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- localVue,
});
});
@@ -188,10 +181,9 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', loggedOutnoteableData);
store.dispatch('setNotesData', notesDataMock);
- wrapper = mount(localVue.extend(noteableDiscussion), {
+ wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- localVue,
});
});
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index a08e86d92d3..6f06665f412 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -208,7 +208,7 @@ describe('issue_note', () => {
expect(noteBodyProps.helpPagePath).toBe('');
});
- it('prevents note preview xss', done => {
+ it('prevents note preview xss', (done) => {
const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`;
const alertSpy = jest.spyOn(window, 'alert');
@@ -230,7 +230,7 @@ describe('issue_note', () => {
});
describe('cancel edit', () => {
- it('restores content of updated note', done => {
+ it('restores content of updated note', (done) => {
const updatedText = 'updated note text';
store.hotUpdate({
actions: {
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index e905a12919e..e495a4738e0 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -36,16 +36,16 @@ describe('note_app', () => {
const getComponentOrder = () => {
return wrapper
.findAll('#notes-list,.js-comment-form')
- .wrappers.map(node => (node.is(CommentForm) ? TYPE_COMMENT_FORM : TYPE_NOTES_LIST));
+ .wrappers.map((node) => (node.is(CommentForm) ? TYPE_COMMENT_FORM : TYPE_NOTES_LIST));
};
/**
* waits for fetchNotes() to complete
*/
const waitForDiscussionsRequest = () =>
- new Promise(resolve => {
+ new Promise((resolve) => {
const { vm } = wrapper.find(NotesApp);
- const unwatch = vm.$watch('isFetching', isFetching => {
+ const unwatch = vm.$watch('isFetching', (isFetching) => {
if (isFetching) {
return;
}
@@ -129,18 +129,15 @@ describe('note_app', () => {
'/gitlab-org/gitlab-foss/issues/26/discussions.json'
][0].notes[0];
- expect(
- wrapper
- .find('.main-notes-list .note-header-author-name')
- .text()
- .trim(),
- ).toEqual(note.author.name);
+ expect(wrapper.find('.main-notes-list .note-header-author-name').text().trim()).toEqual(
+ note.author.name,
+ );
expect(wrapper.find('.main-notes-list .note-text').html()).toContain(note.note_html);
});
it('should render form', () => {
- expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form').element.tagName).toBe('FORM');
expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
'Write a comment or drag your files here…',
);
@@ -205,7 +202,7 @@ describe('note_app', () => {
});
it('should render form', () => {
- expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form').element.tagName).toBe('FORM');
expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
'Write a comment or drag your files here…',
);
@@ -272,23 +269,15 @@ describe('note_app', () => {
it('should render markdown docs url', () => {
const { markdownDocsPath } = mockData.notesDataMock;
- expect(
- wrapper
- .find(`a[href="${markdownDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('Markdown');
+ expect(wrapper.find(`a[href="${markdownDocsPath}"]`).text().trim()).toEqual('Markdown');
});
it('should render quick action docs url', () => {
const { quickActionsDocsPath } = mockData.notesDataMock;
- expect(
- wrapper
- .find(`a[href="${quickActionsDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('quick actions');
+ expect(wrapper.find(`a[href="${quickActionsDocsPath}"]`).text().trim()).toEqual(
+ 'quick actions',
+ );
});
});
@@ -304,12 +293,9 @@ describe('note_app', () => {
const { markdownDocsPath } = mockData.notesDataMock;
return Vue.nextTick().then(() => {
- expect(
- wrapper
- .find(`.edit-note a[href="${markdownDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('Markdown is supported');
+ expect(wrapper.find(`.edit-note a[href="${markdownDocsPath}"]`).text().trim()).toEqual(
+ 'Markdown is supported',
+ );
});
});
diff --git a/spec/frontend/notes/components/toggle_replies_widget_spec.js b/spec/frontend/notes/components/toggle_replies_widget_spec.js
index b4f68b039cf..409e1bc3951 100644
--- a/spec/frontend/notes/components/toggle_replies_widget_spec.js
+++ b/spec/frontend/notes/components/toggle_replies_widget_spec.js
@@ -3,7 +3,7 @@ import mountComponent from 'helpers/vue_mount_component_helper';
import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import { note } from '../mock_data';
-const deepCloneObject = obj => JSON.parse(JSON.stringify(obj));
+const deepCloneObject = (obj) => JSON.parse(JSON.stringify(obj));
describe('toggle replies widget for notes', () => {
let vm;
diff --git a/spec/frontend/notes/helpers.js b/spec/frontend/notes/helpers.js
index c8168a49a5b..ed34f985e94 100644
--- a/spec/frontend/notes/helpers.js
+++ b/spec/frontend/notes/helpers.js
@@ -1,4 +1,4 @@
-export const resetStore = store => {
+export const resetStore = (store) => {
store.replaceState({
notes: [],
targetNoteHash: null,
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 4114df618e5..9c9a648d213 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -34,7 +34,7 @@ describe('Discussion navigation mixin', () => {
setHTMLFixture(
[...'abcde']
.map(
- id =>
+ (id) =>
`<ul class="notes" data-discussion-id="${id}"></ul>
<div class="discussion" data-discussion-id="${id}"></div>`,
)
diff --git a/spec/frontend/notes/old_notes_spec.js b/spec/frontend/notes/old_notes_spec.js
index dee4f93f0ce..00821980e8a 100644
--- a/spec/frontend/notes/old_notes_spec.js
+++ b/spec/frontend/notes/old_notes_spec.js
@@ -82,9 +82,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
it('modifies the Markdown field', () => {
const changeEvent = document.createEvent('HTMLEvents');
changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
+ $('input[type=checkbox]').attr('checked', true)[0].dispatchEvent(changeEvent);
expect($('.js-task-list-field.original-task-list').val()).toBe('- [x] Task List Item');
});
@@ -129,7 +127,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
jest.spyOn(notes, 'renderNote');
- $('.js-comment-button').on('click', e => {
+ $('.js-comment-button').on('click', (e) => {
const $form = $(this);
e.preventDefault();
notes.addNote($form, {});
@@ -552,7 +550,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
});
- it('should remove placeholder note when new comment is done posting', done => {
+ it('should remove placeholder note when new comment is done posting', (done) => {
mockNotesPost();
$('.js-comment-button').click();
@@ -564,7 +562,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
describe('postComment', () => {
- it('disables the submit button', done => {
+ it('disables the submit button', (done) => {
const $submitButton = $form.find('.js-comment-submit-button');
expect($submitButton).not.toBeDisabled();
@@ -587,7 +585,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
});
- it('should show actual note element when new comment is done posting', done => {
+ it('should show actual note element when new comment is done posting', (done) => {
mockNotesPost();
$('.js-comment-button').click();
@@ -598,7 +596,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
});
- it('should reset Form when new comment is done posting', done => {
+ it('should reset Form when new comment is done posting', (done) => {
mockNotesPost();
$('.js-comment-button').click();
@@ -609,7 +607,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
});
- it('should show flash error message when new comment failed to be posted', done => {
+ it('should show flash error message when new comment failed to be posted', (done) => {
mockNotesPostError();
jest.spyOn(notes, 'addFlash');
@@ -660,7 +658,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
$form.find('textarea.js-note-text').val(sampleComment);
});
- it('should remove quick action placeholder when comment with quick actions is done posting', done => {
+ it('should remove quick action placeholder when comment with quick actions is done posting', (done) => {
jest.spyOn(gl.awardsHandler, 'addAwardToEmojiBar');
$('.js-comment-button').click();
@@ -695,7 +693,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
$form.find('textarea.js-note-text').val(sampleComment);
});
- it('should show message placeholder including lines starting with slash', done => {
+ it('should show message placeholder including lines starting with slash', (done) => {
$('.js-comment-button').click();
expect($notesContainer.find('.note.being-posted').length).toEqual(1); // Placeholder shown
@@ -733,7 +731,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
$form.find('textarea.js-note-text').html(sampleComment);
});
- it('should not render a script tag', done => {
+ it('should not render a script tag', (done) => {
$('.js-comment-button').click();
setImmediate(() => {
@@ -746,12 +744,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
.find(`#note_${note.id}`)
.find('.js-task-list-container');
- expect(
- $updatedNoteEl
- .find('.note-text')
- .text()
- .trim(),
- ).toEqual('');
+ expect($updatedNoteEl.find('.note-text').text().trim()).toEqual('');
done();
});
@@ -912,26 +905,15 @@ describe.skip('Old Notes (~/notes.js)', () => {
expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual(currentUserFullname);
-
- expect(
- $tempNoteHeader
- .find('.note-headline-light')
- .text()
- .trim(),
- ).toEqual(`@${currentUsername}`);
-
- expect(
- $tempNote
- .find('.note-body .note-text p')
- .text()
- .trim(),
- ).toEqual(sampleComment);
+ expect($tempNoteHeader.find('.d-none.d-sm-inline-block').text().trim()).toEqual(
+ currentUserFullname,
+ );
+
+ expect($tempNoteHeader.find('.note-headline-light').text().trim()).toEqual(
+ `@${currentUsername}`,
+ );
+
+ expect($tempNote.find('.note-body .note-text p').text().trim()).toEqual(sampleComment);
});
it('should return constructed placeholder element for discussion note based on form contents', () => {
@@ -959,12 +941,9 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
const $tempNoteHeader = $tempNote.find('.note-header');
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual('Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;');
+ expect($tempNoteHeader.find('.d-none.d-sm-inline-block').text().trim()).toEqual(
+ 'Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;',
+ );
});
});
@@ -987,12 +966,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
expect($tempNote.attr('id')).toEqual(uniqueId);
expect($tempNote.hasClass('being-posted')).toBeTruthy();
expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
- expect(
- $tempNote
- .find('.timeline-content i')
- .text()
- .trim(),
- ).toEqual(sampleCommandDescription);
+ expect($tempNote.find('.timeline-content i').text().trim()).toEqual(sampleCommandDescription);
});
});
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index c9912621785..f0e6a0a68dd 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -1,5 +1,6 @@
import { TEST_HOST } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as actions from '~/notes/stores/actions';
@@ -8,7 +9,6 @@ import * as mutationTypes from '~/notes/stores/mutation_types';
import * as notesConstants from '~/notes/constants';
import createStore from '~/notes/stores';
import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub';
-import testAction from '../../helpers/vuex_action_helper';
import { resetStore } from '../helpers';
import {
discussionMock,
@@ -53,7 +53,7 @@ describe('Actions Notes Store', () => {
});
describe('setNotesData', () => {
- it('should set received notes data', done => {
+ it('should set received notes data', (done) => {
testAction(
actions.setNotesData,
notesDataMock,
@@ -66,7 +66,7 @@ describe('Actions Notes Store', () => {
});
describe('setNoteableData', () => {
- it('should set received issue data', done => {
+ it('should set received issue data', (done) => {
testAction(
actions.setNoteableData,
noteableDataMock,
@@ -79,7 +79,7 @@ describe('Actions Notes Store', () => {
});
describe('setUserData', () => {
- it('should set received user data', done => {
+ it('should set received user data', (done) => {
testAction(
actions.setUserData,
userDataMock,
@@ -92,7 +92,7 @@ describe('Actions Notes Store', () => {
});
describe('setLastFetchedAt', () => {
- it('should set received timestamp', done => {
+ it('should set received timestamp', (done) => {
testAction(
actions.setLastFetchedAt,
'timestamp',
@@ -105,7 +105,7 @@ describe('Actions Notes Store', () => {
});
describe('setInitialNotes', () => {
- it('should set initial notes', done => {
+ it('should set initial notes', (done) => {
testAction(
actions.setInitialNotes,
[individualNote],
@@ -118,7 +118,7 @@ describe('Actions Notes Store', () => {
});
describe('setTargetNoteHash', () => {
- it('should set target note hash', done => {
+ it('should set target note hash', (done) => {
testAction(
actions.setTargetNoteHash,
'hash',
@@ -131,7 +131,7 @@ describe('Actions Notes Store', () => {
});
describe('toggleDiscussion', () => {
- it('should toggle discussion', done => {
+ it('should toggle discussion', (done) => {
testAction(
actions.toggleDiscussion,
{ discussionId: discussionMock.id },
@@ -144,7 +144,7 @@ describe('Actions Notes Store', () => {
});
describe('expandDiscussion', () => {
- it('should expand discussion', done => {
+ it('should expand discussion', (done) => {
testAction(
actions.expandDiscussion,
{ discussionId: discussionMock.id },
@@ -157,7 +157,7 @@ describe('Actions Notes Store', () => {
});
describe('collapseDiscussion', () => {
- it('should commit collapse discussion', done => {
+ it('should commit collapse discussion', (done) => {
testAction(
actions.collapseDiscussion,
{ discussionId: discussionMock.id },
@@ -175,7 +175,7 @@ describe('Actions Notes Store', () => {
});
describe('closeMergeRequest', () => {
- it('sets state as closed', done => {
+ it('sets state as closed', (done) => {
store
.dispatch('closeIssuable', { notesData: { closeIssuePath: '' } })
.then(() => {
@@ -188,7 +188,7 @@ describe('Actions Notes Store', () => {
});
describe('reopenMergeRequest', () => {
- it('sets state as reopened', done => {
+ it('sets state as reopened', (done) => {
store
.dispatch('reopenIssuable', { notesData: { reopenIssuePath: '' } })
.then(() => {
@@ -203,7 +203,7 @@ describe('Actions Notes Store', () => {
describe('emitStateChangedEvent', () => {
it('emits an event on the document', () => {
- document.addEventListener('issuable_vue_app:change', event => {
+ document.addEventListener('issuable_vue_app:change', (event) => {
expect(event.detail.data).toEqual({ id: '1', state: 'closed' });
expect(event.detail.isClosed).toEqual(false);
});
@@ -213,7 +213,7 @@ describe('Actions Notes Store', () => {
});
describe('toggleStateButtonLoading', () => {
- it('should set loading as true', done => {
+ it('should set loading as true', (done) => {
testAction(
actions.toggleStateButtonLoading,
true,
@@ -224,7 +224,7 @@ describe('Actions Notes Store', () => {
);
});
- it('should set loading as false', done => {
+ it('should set loading as false', (done) => {
testAction(
actions.toggleStateButtonLoading,
false,
@@ -237,11 +237,11 @@ describe('Actions Notes Store', () => {
});
describe('toggleIssueLocalState', () => {
- it('sets issue state as closed', done => {
+ it('sets issue state as closed', (done) => {
testAction(actions.toggleIssueLocalState, 'closed', {}, [{ type: 'CLOSE_ISSUE' }], [], done);
});
- it('sets issue state as reopened', done => {
+ it('sets issue state as reopened', (done) => {
testAction(
actions.toggleIssueLocalState,
'reopened',
@@ -297,24 +297,21 @@ describe('Actions Notes Store', () => {
});
describe('poll', () => {
- beforeEach(done => {
+ beforeEach((done) => {
axiosMock
.onGet(notesDataMock.notesPath)
.reply(200, { notes: [], last_fetched_at: '123456' }, { 'poll-interval': '1000' });
- store
- .dispatch('setNotesData', notesDataMock)
- .then(done)
- .catch(done.fail);
+ store.dispatch('setNotesData', notesDataMock).then(done).catch(done.fail);
});
- it('calls service with last fetched state', done => {
+ it('calls service with last fetched state', (done) => {
store
.dispatch('poll')
.then(() => {
jest.advanceTimersByTime(2);
})
- .then(() => new Promise(resolve => requestAnimationFrame(resolve)))
+ .then(() => new Promise((resolve) => requestAnimationFrame(resolve)))
.then(() => {
expect(store.state.lastFetchedAt).toBe('123456');
@@ -322,7 +319,7 @@ describe('Actions Notes Store', () => {
})
.then(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
requestAnimationFrame(resolve);
}),
)
@@ -340,7 +337,7 @@ describe('Actions Notes Store', () => {
});
describe('setNotesFetchedState', () => {
- it('should set notes fetched state', done => {
+ it('should set notes fetched state', (done) => {
testAction(
actions.setNotesFetchedState,
true,
@@ -367,7 +364,7 @@ describe('Actions Notes Store', () => {
document.body.setAttribute('data-page', '');
});
- it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', done => {
+ it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', (done) => {
const note = { path: endpoint, id: 1 };
testAction(
@@ -392,7 +389,7 @@ describe('Actions Notes Store', () => {
);
});
- it('dispatches removeDiscussionsFromDiff on merge request page', done => {
+ it('dispatches removeDiscussionsFromDiff on merge request page', (done) => {
const note = { path: endpoint, id: 1 };
document.body.setAttribute('data-page', 'projects:merge_requests:show');
@@ -438,7 +435,7 @@ describe('Actions Notes Store', () => {
document.body.setAttribute('data-page', '');
});
- it('dispatches removeNote', done => {
+ it('dispatches removeNote', (done) => {
const note = { path: endpoint, id: 1 };
testAction(
@@ -471,7 +468,7 @@ describe('Actions Notes Store', () => {
axiosMock.onAny().reply(200, res);
});
- it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', done => {
+ it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', (done) => {
testAction(
actions.createNewNote,
{ endpoint: `${TEST_HOST}`, data: {} },
@@ -507,7 +504,7 @@ describe('Actions Notes Store', () => {
axiosMock.onAny().replyOnce(200, res);
});
- it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', done => {
+ it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', (done) => {
testAction(
actions.createNewNote,
{ endpoint: `${TEST_HOST}`, data: {} },
@@ -530,7 +527,7 @@ describe('Actions Notes Store', () => {
});
describe('as note', () => {
- it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', done => {
+ it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', (done) => {
testAction(
actions.toggleResolveNote,
{ endpoint: `${TEST_HOST}`, isResolved: true, discussion: false },
@@ -555,7 +552,7 @@ describe('Actions Notes Store', () => {
});
describe('as discussion', () => {
- it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', done => {
+ it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', (done) => {
testAction(
actions.toggleResolveNote,
{ endpoint: `${TEST_HOST}`, isResolved: true, discussion: true },
@@ -591,7 +588,7 @@ describe('Actions Notes Store', () => {
});
describe('setCommentsDisabled', () => {
- it('should set comments disabled state', done => {
+ it('should set comments disabled state', (done) => {
testAction(
actions.setCommentsDisabled,
true,
@@ -604,7 +601,7 @@ describe('Actions Notes Store', () => {
});
describe('updateResolvableDiscussionsCounts', () => {
- it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', done => {
+ it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', (done) => {
testAction(
actions.updateResolvableDiscussionsCounts,
null,
@@ -617,7 +614,7 @@ describe('Actions Notes Store', () => {
});
describe('convertToDiscussion', () => {
- it('commits CONVERT_TO_DISCUSSION with noteId', done => {
+ it('commits CONVERT_TO_DISCUSSION with noteId', (done) => {
const noteId = 'dummy-note-id';
testAction(
actions.convertToDiscussion,
@@ -721,7 +718,7 @@ describe('Actions Notes Store', () => {
describe('replyToDiscussion', () => {
const payload = { endpoint: TEST_HOST, data: {} };
- it('updates discussion if response contains disussion', done => {
+ it('updates discussion if response contains disussion', (done) => {
const discussion = { notes: [] };
axiosMock.onAny().reply(200, { discussion });
@@ -741,7 +738,7 @@ describe('Actions Notes Store', () => {
);
});
- it('adds a reply to a discussion', done => {
+ it('adds a reply to a discussion', (done) => {
const res = {};
axiosMock.onAny().reply(200, res);
@@ -759,7 +756,7 @@ describe('Actions Notes Store', () => {
});
describe('removeConvertedDiscussion', () => {
- it('commits CONVERT_TO_DISCUSSION with noteId', done => {
+ it('commits CONVERT_TO_DISCUSSION with noteId', (done) => {
const noteId = 'dummy-id';
testAction(
actions.removeConvertedDiscussion,
@@ -784,7 +781,7 @@ describe('Actions Notes Store', () => {
};
});
- it('when unresolved, dispatches action', done => {
+ it('when unresolved, dispatches action', (done) => {
testAction(
actions.resolveDiscussion,
{ discussionId },
@@ -804,8 +801,8 @@ describe('Actions Notes Store', () => {
);
});
- it('when resolved, does nothing', done => {
- getters.isDiscussionResolved = id => id === discussionId;
+ it('when resolved, does nothing', (done) => {
+ getters.isDiscussionResolved = (id) => id === discussionId;
testAction(
actions.resolveDiscussion,
@@ -826,7 +823,7 @@ describe('Actions Notes Store', () => {
const res = { errors: { something: ['went wrong'] } };
const error = { message: 'Unprocessable entity', response: { data: res } };
- it('throws an error', done => {
+ it('throws an error', (done) => {
actions
.saveNote(
{
@@ -836,7 +833,7 @@ describe('Actions Notes Store', () => {
payload,
)
.then(() => done.fail('Expected error to be thrown!'))
- .catch(err => {
+ .catch((err) => {
expect(err).toBe(error);
expect(Flash).not.toHaveBeenCalled();
})
@@ -849,7 +846,7 @@ describe('Actions Notes Store', () => {
const res = { errors: { base: ['something went wrong'] } };
const error = { message: 'Unprocessable entity', response: { data: res } };
- it('sets flash alert using errors.base message', done => {
+ it('sets flash alert using errors.base message', (done) => {
actions
.saveNote(
{
@@ -858,7 +855,7 @@ describe('Actions Notes Store', () => {
},
{ ...payload, flashContainer },
)
- .then(resp => {
+ .then((resp) => {
expect(resp.hasFlash).toBe(true);
expect(Flash).toHaveBeenCalledWith(
'Your comment could not be submitted because something went wrong',
@@ -875,7 +872,7 @@ describe('Actions Notes Store', () => {
describe('if response contains no errors', () => {
const res = { valid: true };
- it('returns the response', done => {
+ it('returns the response', (done) => {
actions
.saveNote(
{
@@ -884,7 +881,7 @@ describe('Actions Notes Store', () => {
},
payload,
)
- .then(data => {
+ .then((data) => {
expect(data).toBe(res);
expect(Flash).not.toHaveBeenCalled();
})
@@ -917,11 +914,10 @@ describe('Actions Notes Store', () => {
.catch(done.fail);
};
- it('when service success, commits and resolves discussion', done => {
+ it('when service success, commits and resolves discussion', (done) => {
testSubmitSuggestion(done, () => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
- [mutationTypes.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]);
@@ -934,7 +930,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, flashes error message', done => {
+ it('when service fails, flashes error message', (done) => {
const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
Api.applySuggestion.mockReturnValue(Promise.reject(response));
@@ -949,7 +945,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, and no error message available, uses default message', done => {
+ it('when service fails, and no error message available, uses default message', (done) => {
const response = { response: 'foo' };
Api.applySuggestion.mockReturnValue(Promise.reject(response));
@@ -968,7 +964,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when resolve discussion fails, fail gracefully', done => {
+ it('when resolve discussion fails, fail gracefully', (done) => {
dispatch.mockReturnValue(Promise.reject());
testSubmitSuggestion(done, () => {
@@ -999,13 +995,11 @@ describe('Actions Notes Store', () => {
.catch(done.fail);
};
- it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', done => {
+ it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', (done) => {
testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]],
[mutationTypes.CLEAR_SUGGESTION_BATCH],
[mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
@@ -1022,7 +1016,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, flashes error message, resets applying batch state', done => {
+ it('when service fails, flashes error message, resets applying batch state', (done) => {
const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
Api.applySuggestionBatch.mockReturnValue(Promise.reject(response));
@@ -1040,7 +1034,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, and no error message available, uses default message', done => {
+ it('when service fails, and no error message available, uses default message', (done) => {
const response = { response: 'foo' };
Api.applySuggestionBatch.mockReturnValue(Promise.reject(response));
@@ -1062,15 +1056,13 @@ describe('Actions Notes Store', () => {
});
});
- it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', done => {
+ it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', (done) => {
dispatch.mockReturnValue(Promise.reject());
testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]],
[mutationTypes.CLEAR_SUGGESTION_BATCH],
[mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
@@ -1084,7 +1076,7 @@ describe('Actions Notes Store', () => {
describe('addSuggestionInfoToBatch', () => {
const suggestionInfo = batchSuggestionsInfoMock[0];
- it("adds a suggestion's info to the current batch", done => {
+ it("adds a suggestion's info to the current batch", (done) => {
testAction(
actions.addSuggestionInfoToBatch,
suggestionInfo,
@@ -1099,7 +1091,7 @@ describe('Actions Notes Store', () => {
describe('removeSuggestionInfoFromBatch', () => {
const suggestionInfo = batchSuggestionsInfoMock[0];
- it("removes a suggestion's info the current batch", done => {
+ it("removes a suggestion's info the current batch", (done) => {
testAction(
actions.removeSuggestionInfoFromBatch,
suggestionInfo.suggestionId,
@@ -1139,7 +1131,7 @@ describe('Actions Notes Store', () => {
});
describe('setDiscussionSortDirection', () => {
- it('calls the correct mutation with the correct args', done => {
+ it('calls the correct mutation with the correct args', (done) => {
testAction(
actions.setDiscussionSortDirection,
{ direction: notesConstants.DESC, persist: false },
@@ -1157,7 +1149,7 @@ describe('Actions Notes Store', () => {
});
describe('setSelectedCommentPosition', () => {
- it('calls the correct mutation with the correct args', done => {
+ it('calls the correct mutation with the correct args', (done) => {
testAction(
actions.setSelectedCommentPosition,
{},
@@ -1178,7 +1170,7 @@ describe('Actions Notes Store', () => {
};
describe('if response contains no errors', () => {
- it('dispatches requestDeleteDescriptionVersion', done => {
+ it('dispatches requestDeleteDescriptionVersion', (done) => {
axiosMock.onDelete(endpoint).replyOnce(200);
testAction(
actions.softDeleteDescriptionVersion,
@@ -1201,7 +1193,7 @@ describe('Actions Notes Store', () => {
describe('if response contains errors', () => {
const errorMessage = 'Request failed with status code 503';
- it('dispatches receiveDeleteDescriptionVersionError and throws an error', done => {
+ it('dispatches receiveDeleteDescriptionVersionError and throws an error', (done) => {
axiosMock.onDelete(endpoint).replyOnce(503);
testAction(
actions.softDeleteDescriptionVersion,
@@ -1236,7 +1228,7 @@ describe('Actions Notes Store', () => {
});
describe('updateAssignees', () => {
- it('update the assignees state', done => {
+ it('update the assignees state', (done) => {
testAction(
actions.updateAssignees,
[userDataMock.id],
@@ -1351,7 +1343,7 @@ describe('Actions Notes Store', () => {
});
describe('updateDiscussionPosition', () => {
- it('update the assignees state', done => {
+ it('update the assignees state', (done) => {
const updatedPosition = { discussionId: 1, position: { test: true } };
testAction(
actions.updateDiscussionPosition,
diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js
index 1a369caee49..fd04d08b6a5 100644
--- a/spec/frontend/notes/stores/getters_spec.js
+++ b/spec/frontend/notes/stores/getters_spec.js
@@ -72,7 +72,7 @@ describe('Getters Notes Store', () => {
state.isTimelineEnabled = true;
expect(getters.discussions(state).length).toEqual(discussionMock.notes.length);
- getters.discussions(state).forEach(discussion => {
+ getters.discussions(state).forEach((discussion) => {
expect(discussion.individual_note).toBe(true);
expect(discussion.id).toBe(discussion.notes[0].id);
expect(discussion.created_at).toBe(discussion.notes[0].created_at);
@@ -298,17 +298,18 @@ describe('Getters Notes Store', () => {
};
});
- [{ step: 1, id: '123', expected: '123' }, { step: -1, id: '123', expected: '123' }].forEach(
- ({ step, id, expected }) => {
- it(`with step ${step} and match, returns only value`, () => {
- const params = createDiscussionNeighborParams(id, true, step);
-
- expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe(
- expected,
- );
- });
- },
- );
+ [
+ { step: 1, id: '123', expected: '123' },
+ { step: -1, id: '123', expected: '123' },
+ ].forEach(({ step, id, expected }) => {
+ it(`with step ${step} and match, returns only value`, () => {
+ const params = createDiscussionNeighborParams(id, true, step);
+
+ expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe(
+ expected,
+ );
+ });
+ });
it('with no match, returns only value', () => {
const params = createDiscussionNeighborParams('bogus', true, 1);
diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js
index ec4de925721..66fc74525ad 100644
--- a/spec/frontend/notes/stores/mutation_spec.js
+++ b/spec/frontend/notes/stores/mutation_spec.js
@@ -357,7 +357,7 @@ describe('Notes Store mutations', () => {
mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds, expanded: true });
- state.discussions.forEach(discussion => {
+ state.discussions.forEach((discussion) => {
expect(discussion.expanded).toEqual(true);
});
});
@@ -371,7 +371,7 @@ describe('Notes Store mutations', () => {
mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds, expanded: false });
- state.discussions.forEach(discussion => {
+ state.discussions.forEach((discussion) => {
expect(discussion.expanded).toEqual(false);
});
});
@@ -698,7 +698,7 @@ describe('Notes Store mutations', () => {
});
describe('SET_APPLYING_BATCH_STATE', () => {
- const buildDiscussions = suggestionsInfo => {
+ const buildDiscussions = (suggestionsInfo) => {
const suggestions = suggestionsInfo.map(({ suggestionId }) => ({ id: suggestionId }));
const notes = suggestionsInfo.map(({ noteId }, index) => ({
@@ -738,7 +738,7 @@ describe('Notes Store mutations', () => {
const expectedSuggestions = [updatedSuggestion, suggestions[1]];
const actualSuggestions = state.discussions
- .map(discussion => discussion.notes.map(n => n.suggestions))
+ .map((discussion) => discussion.notes.map((n) => n.suggestions))
.flat(2);
expect(actualSuggestions).toEqual(expectedSuggestions);
diff --git a/spec/frontend/oauth_remember_me_spec.js b/spec/frontend/oauth_remember_me_spec.js
index e12db05ac43..910676a97ed 100644
--- a/spec/frontend/oauth_remember_me_spec.js
+++ b/spec/frontend/oauth_remember_me_spec.js
@@ -2,10 +2,8 @@ import $ from 'jquery';
import OAuthRememberMe from '~/pages/sessions/new/oauth_remember_me';
describe('OAuthRememberMe', () => {
- const findFormAction = selector => {
- return $(`#oauth-container .oauth-login${selector}`)
- .parent('form')
- .attr('action');
+ const findFormAction = (selector) => {
+ return $(`#oauth-container .oauth-login${selector}`).parent('form').attr('action');
};
preloadFixtures('static/oauth_remember_me.html');
diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js
index c7ea23f9913..3216eece391 100644
--- a/spec/frontend/operation_settings/components/metrics_settings_spec.js
+++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js
@@ -61,6 +61,7 @@ describe('operation settings external dashboard component', () => {
describe('expand/collapse button', () => {
it('renders as an expand button by default', () => {
+ mountComponent();
const button = wrapper.find(GlButton);
expect(button.text()).toBe('Expand');
diff --git a/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap
index d317264bdae..318cea98b92 100644
--- a/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap
@@ -9,7 +9,7 @@ exports[`PackageTitle renders with tags 1`] = `
class="gl-display-flex gl-justify-content-space-between gl-py-3"
>
<div
- class="gl-flex-direction-column"
+ class="gl-flex-direction-column gl-flex-grow-1"
>
<div
class="gl-display-flex"
@@ -54,6 +54,7 @@ exports[`PackageTitle renders with tags 1`] = `
link=""
size="s"
text="maven"
+ texttooltip=""
/>
</div>
<div
@@ -65,6 +66,7 @@ exports[`PackageTitle renders with tags 1`] = `
link=""
size="s"
text="300 bytes"
+ texttooltip=""
/>
</div>
<div
@@ -95,7 +97,7 @@ exports[`PackageTitle renders without tags 1`] = `
class="gl-display-flex gl-justify-content-space-between gl-py-3"
>
<div
- class="gl-flex-direction-column"
+ class="gl-flex-direction-column gl-flex-grow-1"
>
<div
class="gl-display-flex"
@@ -140,6 +142,7 @@ exports[`PackageTitle renders without tags 1`] = `
link=""
size="s"
text="maven"
+ texttooltip=""
/>
</div>
<div
@@ -151,6 +154,7 @@ exports[`PackageTitle renders without tags 1`] = `
link=""
size="s"
text="300 bytes"
+ texttooltip=""
/>
</div>
</div>
diff --git a/spec/frontend/packages/details/components/additional_metadata_spec.js b/spec/frontend/packages/details/components/additional_metadata_spec.js
index 111e4205abb..8466a630ecb 100644
--- a/spec/frontend/packages/details/components/additional_metadata_spec.js
+++ b/spec/frontend/packages/details/components/additional_metadata_spec.js
@@ -11,7 +11,7 @@ describe('Package Additional Metadata', () => {
packageEntity: { ...mavenPackage },
};
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(component, {
propsData: { ...defaultProps, ...props },
stubs: {
@@ -33,7 +33,7 @@ describe('Package Additional Metadata', () => {
const findConanRecipe = () => wrapper.find('[data-testid="conan-recipe"]');
const findMavenApp = () => wrapper.find('[data-testid="maven-app"]');
const findMavenGroup = () => wrapper.find('[data-testid="maven-group"]');
- const findElementLink = container => container.find(GlLink);
+ const findElementLink = (container) => container.find(GlLink);
it('has the correct title', () => {
mountComponent();
diff --git a/spec/frontend/packages/details/components/conan_installation_spec.js b/spec/frontend/packages/details/components/conan_installation_spec.js
index c79d1bb50dd..92c1f8e7f4a 100644
--- a/spec/frontend/packages/details/components/conan_installation_spec.js
+++ b/spec/frontend/packages/details/components/conan_installation_spec.js
@@ -48,21 +48,13 @@ describe('ConanInstallation', () => {
describe('installation commands', () => {
it('renders the correct command', () => {
- expect(
- findCodeInstructions()
- .at(0)
- .props('instruction'),
- ).toBe(conanInstallationCommandStr);
+ expect(findCodeInstructions().at(0).props('instruction')).toBe(conanInstallationCommandStr);
});
});
describe('setup commands', () => {
it('renders the correct command', () => {
- expect(
- findCodeInstructions()
- .at(1)
- .props('instruction'),
- ).toBe(conanSetupCommandStr);
+ expect(findCodeInstructions().at(1).props('instruction')).toBe(conanSetupCommandStr);
});
});
});
diff --git a/spec/frontend/packages/details/components/maven_installation_spec.js b/spec/frontend/packages/details/components/maven_installation_spec.js
index f301a03a7f3..ff62969e709 100644
--- a/spec/frontend/packages/details/components/maven_installation_spec.js
+++ b/spec/frontend/packages/details/components/maven_installation_spec.js
@@ -51,11 +51,7 @@ describe('MavenInstallation', () => {
describe('installation commands', () => {
it('renders the correct xml block', () => {
- expect(
- findCodeInstructions()
- .at(0)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(0).props()).toMatchObject({
instruction: xmlCodeBlock,
multiline: true,
trackingAction: TrackingActions.COPY_MAVEN_XML,
@@ -63,11 +59,7 @@ describe('MavenInstallation', () => {
});
it('renders the correct maven command', () => {
- expect(
- findCodeInstructions()
- .at(1)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(1).props()).toMatchObject({
instruction: mavenCommandStr,
multiline: false,
trackingAction: TrackingActions.COPY_MAVEN_COMMAND,
@@ -77,11 +69,7 @@ describe('MavenInstallation', () => {
describe('setup commands', () => {
it('renders the correct xml block', () => {
- expect(
- findCodeInstructions()
- .at(2)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(2).props()).toMatchObject({
instruction: mavenSetupXml,
multiline: true,
trackingAction: TrackingActions.COPY_MAVEN_SETUP,
diff --git a/spec/frontend/packages/details/components/npm_installation_spec.js b/spec/frontend/packages/details/components/npm_installation_spec.js
index 4223a05453c..dd6e62185a9 100644
--- a/spec/frontend/packages/details/components/npm_installation_spec.js
+++ b/spec/frontend/packages/details/components/npm_installation_spec.js
@@ -47,11 +47,7 @@ describe('NpmInstallation', () => {
describe('installation commands', () => {
it('renders the correct npm command', () => {
- expect(
- findCodeInstructions()
- .at(0)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(0).props()).toMatchObject({
instruction: 'npm i @Test/package',
multiline: false,
trackingAction: TrackingActions.COPY_NPM_INSTALL_COMMAND,
@@ -59,11 +55,7 @@ describe('NpmInstallation', () => {
});
it('renders the correct yarn command', () => {
- expect(
- findCodeInstructions()
- .at(1)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(1).props()).toMatchObject({
instruction: 'yarn add @Test/package',
multiline: false,
trackingAction: TrackingActions.COPY_YARN_INSTALL_COMMAND,
@@ -73,11 +65,7 @@ describe('NpmInstallation', () => {
describe('setup commands', () => {
it('renders the correct npm command', () => {
- expect(
- findCodeInstructions()
- .at(2)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(2).props()).toMatchObject({
instruction: 'echo @Test:registry=undefined/ >> .npmrc',
multiline: false,
trackingAction: TrackingActions.COPY_NPM_SETUP_COMMAND,
@@ -85,11 +73,7 @@ describe('NpmInstallation', () => {
});
it('renders the correct yarn command', () => {
- expect(
- findCodeInstructions()
- .at(3)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(3).props()).toMatchObject({
instruction: 'echo \\"@Test:registry\\" \\"undefined/\\" >> .yarnrc',
multiline: false,
trackingAction: TrackingActions.COPY_YARN_SETUP_COMMAND,
diff --git a/spec/frontend/packages/details/components/nuget_installation_spec.js b/spec/frontend/packages/details/components/nuget_installation_spec.js
index b381d131e94..685d0808dd9 100644
--- a/spec/frontend/packages/details/components/nuget_installation_spec.js
+++ b/spec/frontend/packages/details/components/nuget_installation_spec.js
@@ -49,11 +49,7 @@ describe('NugetInstallation', () => {
describe('installation commands', () => {
it('renders the correct command', () => {
- expect(
- findCodeInstructions()
- .at(0)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(0).props()).toMatchObject({
instruction: nugetInstallationCommandStr,
trackingAction: TrackingActions.COPY_NUGET_INSTALL_COMMAND,
});
@@ -62,11 +58,7 @@ describe('NugetInstallation', () => {
describe('setup commands', () => {
it('renders the correct command', () => {
- expect(
- findCodeInstructions()
- .at(1)
- .props(),
- ).toMatchObject({
+ expect(findCodeInstructions().at(1).props()).toMatchObject({
instruction: nugetSetupCommandStr,
trackingAction: TrackingActions.COPY_NUGET_SETUP_COMMAND,
});
diff --git a/spec/frontend/packages/details/components/package_files_spec.js b/spec/frontend/packages/details/components/package_files_spec.js
index 813a2170154..9bcf6ed9235 100644
--- a/spec/frontend/packages/details/components/package_files_spec.js
+++ b/spec/frontend/packages/details/components/package_files_spec.js
@@ -24,7 +24,6 @@ describe('Package Files', () => {
stubs: {
...stubChildren(component),
GlTable: false,
- GlLink: '<div><slot></slot></div>',
},
});
};
diff --git a/spec/frontend/packages/details/components/package_history_spec.js b/spec/frontend/packages/details/components/package_history_spec.js
index c43ac9b9c40..5a6b386e2ca 100644
--- a/spec/frontend/packages/details/components/package_history_spec.js
+++ b/spec/frontend/packages/details/components/package_history_spec.js
@@ -15,10 +15,10 @@ describe('Package History', () => {
packageEntity: { ...mavenPackage },
};
- const createPipelines = amount =>
+ const createPipelines = (amount) =>
[...Array(amount)].map((x, index) => ({ ...mockPipelineInfo, id: index + 1 }));
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(component, {
propsData: { ...defaultProps, ...props },
stubs: {
@@ -35,9 +35,9 @@ describe('Package History', () => {
wrapper = null;
});
- const findHistoryElement = testId => wrapper.find(`[data-testid="${testId}"]`);
- const findElementLink = container => container.find(GlLink);
- const findElementTimeAgo = container => container.find(TimeAgoTooltip);
+ const findHistoryElement = (testId) => wrapper.find(`[data-testid="${testId}"]`);
+ const findElementLink = (container) => container.find(GlLink);
+ const findElementTimeAgo = (container) => container.find(TimeAgoTooltip);
const findTitle = () => wrapper.find('[data-testid="title"]');
const findTimeline = () => wrapper.find('[data-testid="timeline"]');
diff --git a/spec/frontend/packages/details/store/actions_spec.js b/spec/frontend/packages/details/store/actions_spec.js
index 70f87d18bcb..e823a00ebc4 100644
--- a/spec/frontend/packages/details/store/actions_spec.js
+++ b/spec/frontend/packages/details/store/actions_spec.js
@@ -12,7 +12,7 @@ jest.mock('~/api.js');
describe('Actions Package details store', () => {
describe('fetchPackageVersions', () => {
- it('should fetch the package versions', done => {
+ it('should fetch the package versions', (done) => {
Api.projectPackage = jest.fn().mockResolvedValue({ data: packageEntity });
testAction(
@@ -35,14 +35,17 @@ describe('Actions Package details store', () => {
);
});
- it("does not set the versions if they don't exist", done => {
+ it("does not set the versions if they don't exist", (done) => {
Api.projectPackage = jest.fn().mockResolvedValue({ data: { packageEntity, versions: null } });
testAction(
fetchPackageVersions,
undefined,
{ packageEntity },
- [{ type: types.SET_LOADING, payload: true }, { type: types.SET_LOADING, payload: false }],
+ [
+ { type: types.SET_LOADING, payload: true },
+ { type: types.SET_LOADING, payload: false },
+ ],
[],
() => {
expect(Api.projectPackage).toHaveBeenCalledWith(
@@ -54,14 +57,17 @@ describe('Actions Package details store', () => {
);
});
- it('should create flash on API error', done => {
+ it('should create flash on API error', (done) => {
Api.projectPackage = jest.fn().mockRejectedValue();
testAction(
fetchPackageVersions,
undefined,
{ packageEntity },
- [{ type: types.SET_LOADING, payload: true }, { type: types.SET_LOADING, payload: false }],
+ [
+ { type: types.SET_LOADING, payload: true },
+ { type: types.SET_LOADING, payload: false },
+ ],
[],
() => {
expect(Api.projectPackage).toHaveBeenCalledWith(
@@ -76,7 +82,7 @@ describe('Actions Package details store', () => {
});
describe('deletePackage', () => {
- it('should call Api.deleteProjectPackage', done => {
+ it('should call Api.deleteProjectPackage', (done) => {
Api.deleteProjectPackage = jest.fn().mockResolvedValue();
testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
expect(Api.deleteProjectPackage).toHaveBeenCalledWith(
@@ -86,7 +92,7 @@ describe('Actions Package details store', () => {
done();
});
});
- it('should create flash on API error', done => {
+ it('should create flash on API error', (done) => {
Api.deleteProjectPackage = jest.fn().mockRejectedValue();
testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
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 c51130dae00..b2df1ac5ab6 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
@@ -34,7 +34,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -95,7 +95,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Composer packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -156,7 +156,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Conan packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -217,7 +217,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Generic packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -278,7 +278,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Maven packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -339,7 +339,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no NPM packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -400,7 +400,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no NuGet packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -461,7 +461,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no PyPI packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
diff --git a/spec/frontend/packages/list/components/packages_sort_spec.js b/spec/frontend/packages/list/components/packages_sort_spec.js
index 5c4794d8f63..d15ad9bd542 100644
--- a/spec/frontend/packages/list/components/packages_sort_spec.js
+++ b/spec/frontend/packages/list/components/packages_sort_spec.js
@@ -16,7 +16,7 @@ describe('packages_sort', () => {
const findPackageListSorting = () => wrapper.find(GlSorting);
const findSortingItems = () => wrapper.findAll(GlSortingItem);
- const createStore = isGroupPage => {
+ const createStore = (isGroupPage) => {
const state = {
config: {
isGroupPage,
diff --git a/spec/frontend/packages/list/stores/actions_spec.js b/spec/frontend/packages/list/stores/actions_spec.js
index cf205ecbac4..05e1fe57cae 100644
--- a/spec/frontend/packages/list/stores/actions_spec.js
+++ b/spec/frontend/packages/list/stores/actions_spec.js
@@ -30,7 +30,7 @@ describe('Actions Package list store', () => {
sort: 'asc',
orderBy: 'version',
};
- it('should fetch the project packages list when isGroupPage is false', done => {
+ it('should fetch the project packages list when isGroupPage is false', (done) => {
testAction(
actions.requestPackagesList,
undefined,
@@ -50,7 +50,7 @@ describe('Actions Package list store', () => {
);
});
- it('should fetch the group packages list when isGroupPage is true', done => {
+ it('should fetch the group packages list when isGroupPage is true', (done) => {
testAction(
actions.requestPackagesList,
undefined,
@@ -70,7 +70,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 selectedType is present', (done) => {
const packageType = 'maven';
testAction(
@@ -102,14 +102,17 @@ describe('Actions Package list store', () => {
);
});
- it('should create flash on API error', done => {
+ it('should create flash on API error', (done) => {
Api.projectPackages = jest.fn().mockRejectedValue();
testAction(
actions.requestPackagesList,
undefined,
{ config: { isGroupPage: false, resourceId: 2 }, sorting },
[],
- [{ type: 'setLoading', payload: true }, { type: 'setLoading', payload: false }],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'setLoading', payload: false },
+ ],
() => {
expect(createFlash).toHaveBeenCalled();
done();
@@ -119,7 +122,7 @@ describe('Actions Package list store', () => {
});
describe('receivePackagesListSuccess', () => {
- it('should set received packages', done => {
+ it('should set received packages', (done) => {
const data = 'foo';
testAction(
@@ -137,7 +140,7 @@ describe('Actions Package list store', () => {
});
describe('setInitialState', () => {
- it('should commit setInitialState', done => {
+ it('should commit setInitialState', (done) => {
testAction(
actions.setInitialState,
'1',
@@ -150,7 +153,7 @@ describe('Actions Package list store', () => {
});
describe('setLoading', () => {
- it('should commit set main loading', done => {
+ it('should commit set main loading', (done) => {
testAction(
actions.setLoading,
true,
@@ -168,7 +171,7 @@ describe('Actions Package list store', () => {
delete_api_path: 'foo',
},
};
- it('should perform a delete operation on _links.delete_api_path', done => {
+ it('should perform a delete operation on _links.delete_api_path', (done) => {
mock.onDelete(payload._links.delete_api_path).replyOnce(200);
Api.projectPackages = jest.fn().mockResolvedValue({ data: 'foo' });
@@ -185,14 +188,17 @@ describe('Actions Package list store', () => {
);
});
- it('should stop the loading and call create flash on api error', done => {
+ it('should stop the loading and call create flash on api error', (done) => {
mock.onDelete(payload._links.delete_api_path).replyOnce(400);
testAction(
actions.requestDeletePackage,
payload,
null,
[],
- [{ type: 'setLoading', payload: true }, { type: 'setLoading', payload: false }],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'setLoading', payload: false },
+ ],
() => {
expect(createFlash).toHaveBeenCalled();
done();
@@ -205,7 +211,7 @@ describe('Actions Package list store', () => {
${'_links'} | ${{}}
${'delete_api_path'} | ${{ _links: {} }}
`('should reject and createFlash when $property is missing', ({ actionPayload }, done) => {
- testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch(e => {
+ testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
expect(e).toEqual(new Error(MISSING_DELETE_PATH_ERROR));
expect(createFlash).toHaveBeenCalledWith(DELETE_PACKAGE_ERROR_MESSAGE);
done();
@@ -214,7 +220,7 @@ describe('Actions Package list store', () => {
});
describe('setSorting', () => {
- it('should commit SET_SORTING', done => {
+ it('should commit SET_SORTING', (done) => {
testAction(
actions.setSorting,
'foo',
@@ -227,7 +233,7 @@ describe('Actions Package list store', () => {
});
describe('setFilter', () => {
- it('should commit SET_FILTER', done => {
+ it('should commit SET_FILTER', (done) => {
testAction(
actions.setFilter,
'foo',
diff --git a/spec/frontend/packages/shared/components/package_path_spec.js b/spec/frontend/packages/shared/components/package_path_spec.js
index 40d455ac77c..3c9cd3387ba 100644
--- a/spec/frontend/packages/shared/components/package_path_spec.js
+++ b/spec/frontend/packages/shared/components/package_path_spec.js
@@ -21,8 +21,8 @@ describe('PackagePath', () => {
const ELLIPSIS_CHEVRON = 'ellipsis-chevron';
const LEAF_LINK = 'leaf-link';
- const findItem = name => wrapper.find(`[data-testid="${name}"]`);
- const findTooltip = w => getBinding(w.element, 'gl-tooltip');
+ const findItem = (name) => wrapper.find(`[data-testid="${name}"]`);
+ const findTooltip = (w) => getBinding(w.element, 'gl-tooltip');
afterEach(() => {
wrapper.destroy();
@@ -64,13 +64,13 @@ describe('PackagePath', () => {
}
if (shouldExist.length) {
- it.each(shouldExist)(`should have %s`, element => {
+ it.each(shouldExist)(`should have %s`, (element) => {
expect(findItem(element).exists()).toBe(true);
});
}
if (shouldNotExist.length) {
- it.each(shouldNotExist)(`should not have %s`, element => {
+ it.each(shouldNotExist)(`should not have %s`, (element) => {
expect(findItem(element).exists()).toBe(false);
});
}
diff --git a/spec/frontend/packages/shared/components/package_tags_spec.js b/spec/frontend/packages/shared/components/package_tags_spec.js
index cc49a9a9244..d26e4e76b87 100644
--- a/spec/frontend/packages/shared/components/package_tags_spec.js
+++ b/spec/frontend/packages/shared/components/package_tags_spec.js
@@ -75,11 +75,7 @@ describe('PackageTags', () => {
const expectedStyle = [...defaultStyle, 'gl-display-flex', 'gl-ml-3'];
- expect(
- tagBadges()
- .at(0)
- .classes(),
- ).toEqual(expect.arrayContaining(expectedStyle));
+ expect(tagBadges().at(0).classes()).toEqual(expect.arrayContaining(expectedStyle));
});
it('shows tag badge for medium or heigher resolutions', () => {
@@ -87,11 +83,7 @@ describe('PackageTags', () => {
const expectedStyle = [...defaultStyle, 'd-md-flex'];
- expect(
- tagBadges()
- .at(1)
- .classes(),
- ).toEqual(expect.arrayContaining(expectedStyle));
+ expect(tagBadges().at(1).classes()).toEqual(expect.arrayContaining(expectedStyle));
});
it('correctly prepends left and appends right when there is more than one tag', () => {
diff --git a/spec/frontend/packages/shared/utils_spec.js b/spec/frontend/packages/shared/utils_spec.js
index 3e4ce8eb323..590e3814bee 100644
--- a/spec/frontend/packages/shared/utils_spec.js
+++ b/spec/frontend/packages/shared/utils_spec.js
@@ -13,7 +13,7 @@ describe('Packages shared utils', () => {
expect(packageTypeToTrackCategory()).toMatchInlineSnapshot(`"UI::undefined"`);
});
- it.each(Object.keys(PackageType))('returns a correct category string for %s', packageKey => {
+ it.each(Object.keys(PackageType))('returns a correct category string for %s', (packageKey) => {
const packageName = PackageType[packageKey];
expect(packageTypeToTrackCategory(packageName)).toBe(
`UI::${TrackingCategories[packageName]}`,
diff --git a/spec/frontend/pager_spec.js b/spec/frontend/pager_spec.js
index 8b60f872bfd..c8a129e38e7 100644
--- a/spec/frontend/pager_spec.js
+++ b/spec/frontend/pager_spec.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+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';
@@ -89,7 +89,7 @@ describe('pager', () => {
Pager.init();
});
- it('shows loader while loading next page', done => {
+ it('shows loader while loading next page', (done) => {
mockSuccess();
jest.spyOn(Pager.loading, 'show').mockImplementation(() => {});
@@ -102,7 +102,7 @@ describe('pager', () => {
});
});
- it('hides loader on success', done => {
+ it('hides loader on success', (done) => {
mockSuccess();
jest.spyOn(Pager.loading, 'hide').mockImplementation(() => {});
@@ -115,7 +115,7 @@ describe('pager', () => {
});
});
- it('hides loader on error', done => {
+ it('hides loader on error', (done) => {
mockError();
jest.spyOn(Pager.loading, 'hide').mockImplementation(() => {});
@@ -128,7 +128,7 @@ describe('pager', () => {
});
});
- it('sends request to url with offset and limit params', done => {
+ it('sends request to url with offset and limit params', (done) => {
Pager.offset = 100;
Pager.limit = 20;
Pager.getOld();
@@ -149,7 +149,7 @@ describe('pager', () => {
});
});
- it('disables if return count is less than limit', done => {
+ it('disables if return count is less than limit', (done) => {
Pager.offset = 0;
Pager.limit = 20;
diff --git a/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
index 7e9aec84016..2c76adf761f 100644
--- a/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
+++ b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
@@ -8,10 +8,10 @@ describe('Abuse Reports', () => {
let $messages;
- const assertMaxLength = $message => {
+ const assertMaxLength = ($message) => {
expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH);
};
- const findMessage = searchText =>
+ const findMessage = (searchText) =>
$messages.filter((index, element) => element.innerText.indexOf(searchText) > -1).first();
preloadFixtures(FIXTURE);
diff --git a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
index 6a239e307e9..8816609d1d2 100644
--- a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
+++ b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
@@ -24,7 +24,7 @@ describe('AccountAndLimits', () => {
expect($userInternalRegex.readOnly).toBeTruthy();
});
- it('is checked', done => {
+ it('is checked', (done) => {
if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click();
expect($userDefaultExternal.prop('checked')).toBeTruthy();
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 c662fb7ba4a..81750b4827f 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,6 +1,6 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import { redirectTo } from '~/lib/utils/url_utility';
import axios from '~/lib/utils/axios_utils';
import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
@@ -26,9 +26,9 @@ describe('stop_jobs_modal.vue', () => {
});
describe('onSubmit', () => {
- it('stops jobs and redirects to overview page', done => {
+ it('stops jobs and redirects to overview page', (done) => {
const responseURL = `${TEST_HOST}/stop_jobs_modal.vue/jobs`;
- jest.spyOn(axios, 'post').mockImplementation(url => {
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(props.url);
return Promise.resolve({
request: {
@@ -45,16 +45,16 @@ describe('stop_jobs_modal.vue', () => {
.catch(done.fail);
});
- it('displays error if stopping jobs failed', done => {
+ it('displays error if stopping jobs failed', (done) => {
const dummyError = new Error('stopping jobs failed');
- jest.spyOn(axios, 'post').mockImplementation(url => {
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(props.url);
return Promise.reject(dummyError);
});
vm.onSubmit()
.then(done.fail)
- .catch(error => {
+ .catch((error) => {
expect(error).toBe(dummyError);
expect(redirectTo).not.toHaveBeenCalled();
})
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 3efefa8137f..d203a8ea0e0 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
@@ -11,10 +11,10 @@ describe('User Operation confirmation modal', () => {
let wrapper;
let formSubmitSpy;
- const findButton = variant =>
+ const findButton = (variant) =>
wrapper
.findAll(GlButton)
- .filter(w => w.attributes('variant') === variant)
+ .filter((w) => w.attributes('variant') === variant)
.at(0);
const findForm = () => wrapper.find('form');
const findUsernameInput = () => wrapper.find(GlFormInput);
@@ -25,7 +25,7 @@ describe('User Operation confirmation modal', () => {
const getMethodParam = () => new FormData(findForm().element).get('_method');
const getFormAction = () => findForm().attributes('action');
- const setUsername = username => {
+ const setUsername = (username) => {
findUsernameInput().vm.$emit('input', username);
};
diff --git a/spec/frontend/pages/admin/users/new/index_spec.js b/spec/frontend/pages/admin/users/new/index_spec.js
index 3896323eef7..60482860e84 100644
--- a/spec/frontend/pages/admin/users/new/index_spec.js
+++ b/spec/frontend/pages/admin/users/new/index_spec.js
@@ -20,7 +20,7 @@ describe('UserInternalRegexHandler', () => {
});
describe('Behaviour of userExternal checkbox when', () => {
- it('matches email as internal', done => {
+ it('matches email as internal', (done) => {
expect($warningMessage.hasClass('hidden')).toBeTruthy();
$userEmail.val('test@').trigger('input');
@@ -30,7 +30,7 @@ describe('UserInternalRegexHandler', () => {
done();
});
- it('matches email as external', done => {
+ it('matches email as external', (done) => {
expect($warningMessage.hasClass('hidden')).toBeTruthy();
$userEmail.val('test.ext@').trigger('input');
diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
index 5ecb7860103..5018b0c4f73 100644
--- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js
+++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
@@ -31,10 +31,10 @@ describe('Todos', () => {
});
describe('goToTodoUrl', () => {
- it('opens the todo url', done => {
+ it('opens the todo url', (done) => {
const todoLink = todoItem.dataset.url;
- visitUrl.mockImplementation(url => {
+ visitUrl.mockImplementation((url) => {
expect(url).toEqual(todoLink);
done();
});
@@ -61,7 +61,7 @@ describe('Todos', () => {
});
it('run native funcionality when avatar is clicked', () => {
- $('.todos-list a').on('click', e => e.preventDefault());
+ $('.todos-list a').on('click', (e) => e.preventDefault());
$('.todos-list img').trigger(metakeyEvent);
expect(visitUrl).not.toHaveBeenCalled();
@@ -72,7 +72,7 @@ describe('Todos', () => {
describe('on done todo click', () => {
let onToggleSpy;
- beforeEach(done => {
+ beforeEach((done) => {
const el = document.querySelector('.js-done-todo');
const path = el.dataset.href;
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 695d1b686a5..a91fc5abe09 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
@@ -15,7 +15,7 @@ describe('BitbucketServerStatusTable', () => {
const findReconfigureButton = () =>
wrapper
.findAll(GlButton)
- .filter(w => w.props().variant === 'info')
+ .filter((w) => w.props().variant === 'info')
.at(0);
afterEach(() => {
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 f969808d78b..19807313c77 100644
--- a/spec/frontend/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/frontend/pages/labels/components/promote_label_modal_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
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';
@@ -50,9 +50,9 @@ describe('Promote label modal', () => {
vm.$destroy();
});
- it('redirects when a label is promoted', done => {
+ it('redirects when a label is promoted', (done) => {
const responseURL = `${TEST_HOST}/dummy/endpoint`;
- jest.spyOn(axios, 'post').mockImplementation(url => {
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(labelMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteLabelModal.requestStarted',
@@ -76,10 +76,10 @@ describe('Promote label modal', () => {
.catch(done.fail);
});
- it('displays an error if promoting a label failed', done => {
+ it('displays an error if promoting a label failed', (done) => {
const dummyError = new Error('promoting label failed');
dummyError.response = { status: 500 };
- jest.spyOn(axios, 'post').mockImplementation(url => {
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(labelMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteLabelModal.requestStarted',
@@ -89,7 +89,7 @@ describe('Promote label modal', () => {
});
vm.onSubmit()
- .catch(error => {
+ .catch((error) => {
expect(error).toBe(dummyError);
expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
labelUrl: labelMockData.url,
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 1d9a964c3c3..7bb637356c2 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,6 +1,6 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import { redirectTo } from '~/lib/utils/url_utility';
import axios from '~/lib/utils/axios_utils';
import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
@@ -32,9 +32,9 @@ describe('delete_milestone_modal.vue', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
- it('deletes milestone and redirects to overview page', done => {
+ it('deletes milestone and redirects to overview page', (done) => {
const responseURL = `${TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
- jest.spyOn(axios, 'delete').mockImplementation(url => {
+ jest.spyOn(axios, 'delete').mockImplementation((url) => {
expect(url).toBe(props.milestoneUrl);
expect(eventHub.$emit).toHaveBeenCalledWith(
'deleteMilestoneModal.requestStarted',
@@ -60,10 +60,10 @@ describe('delete_milestone_modal.vue', () => {
.catch(done.fail);
});
- it('displays error if deleting milestone failed', done => {
+ it('displays error if deleting milestone failed', (done) => {
const dummyError = new Error('deleting milestone failed');
dummyError.response = { status: 418 };
- jest.spyOn(axios, 'delete').mockImplementation(url => {
+ jest.spyOn(axios, 'delete').mockImplementation((url) => {
expect(url).toBe(props.milestoneUrl);
expect(eventHub.$emit).toHaveBeenCalledWith(
'deleteMilestoneModal.requestStarted',
@@ -74,7 +74,7 @@ describe('delete_milestone_modal.vue', () => {
});
vm.onSubmit()
- .catch(error => {
+ .catch((error) => {
expect(error).toBe(dummyError);
expect(redirectTo).not.toHaveBeenCalled();
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
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 e8a6e259837..7cd94deb3da 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,99 +1,109 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import { TEST_HOST } from 'jest/helpers/test_constants';
-import promoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
-import eventHub from '~/pages/milestones/shared/event_hub';
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { TEST_HOST } from 'helpers/test_constants';
+import { setHTMLFixture } from 'helpers/fixtures';
+import waitForPromises from 'helpers/wait_for_promises';
+import PromoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
import axios from '~/lib/utils/axios_utils';
+import * as urlUtils from '~/lib/utils/url_utility';
+import * as flash from '~/flash';
+
+jest.mock('~/lib/utils/url_utility');
+jest.mock('~/flash');
describe('Promote milestone modal', () => {
- let vm;
- const Component = Vue.extend(promoteMilestoneModal);
+ let wrapper;
const milestoneMockData = {
milestoneTitle: 'v1.0',
url: `${TEST_HOST}/dummy/promote/milestones`,
groupName: 'group',
};
- describe('Modal title and description', () => {
- beforeEach(() => {
- vm = mountComponent(Component, milestoneMockData);
+ const promoteButton = () => document.querySelector('.js-promote-project-milestone-button');
+
+ beforeEach(() => {
+ setHTMLFixture(`<button
+ class="js-promote-project-milestone-button"
+ data-group-name="${milestoneMockData.groupName}"
+ data-milestone-title="${milestoneMockData.milestoneTitle}"
+ data-url="${milestoneMockData.url}">
+ Promote
+ </button>`);
+ wrapper = shallowMount(PromoteMilestoneModal);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Modal opener button', () => {
+ it('button gets disabled when the modal opens', () => {
+ expect(promoteButton().disabled).toBe(false);
+
+ promoteButton().click();
+
+ expect(promoteButton().disabled).toBe(true);
+ });
+
+ it('button gets enabled when the modal closes', () => {
+ promoteButton().click();
+
+ wrapper.findComponent(GlModal).vm.$emit('hide');
+
+ expect(promoteButton().disabled).toBe(false);
});
+ });
- afterEach(() => {
- vm.$destroy();
+ describe('Modal title and description', () => {
+ beforeEach(() => {
+ promoteButton().click();
});
it('contains the proper description', () => {
- expect(vm.text).toContain(
+ expect(wrapper.vm.text).toContain(
`Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`,
);
});
it('contains the correct title', () => {
- expect(vm.title).toEqual('Promote v1.0 to group milestone?');
+ expect(wrapper.vm.title).toBe('Promote v1.0 to group milestone?');
});
});
describe('When requesting a milestone promotion', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- ...milestoneMockData,
- });
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- });
-
- afterEach(() => {
- vm.$destroy();
+ promoteButton().click();
});
- it('redirects when a milestone is promoted', done => {
+ it('redirects when a milestone is promoted', async () => {
const responseURL = `${TEST_HOST}/dummy/endpoint`;
- jest.spyOn(axios, 'post').mockImplementation(url => {
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(milestoneMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteMilestoneModal.requestStarted',
- milestoneMockData.url,
- );
return Promise.resolve({
- request: {
- responseURL,
+ data: {
+ url: responseURL,
},
});
});
- vm.onSubmit()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', {
- milestoneUrl: milestoneMockData.url,
- successful: true,
- });
- })
- .then(done)
- .catch(done.fail);
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+ await waitForPromises();
+
+ expect(urlUtils.visitUrl).toHaveBeenCalledWith(responseURL);
});
- it('displays an error if promoting a milestone failed', done => {
+ it('displays an error if promoting a milestone failed', async () => {
const dummyError = new Error('promoting milestone failed');
dummyError.response = { status: 500 };
- jest.spyOn(axios, 'post').mockImplementation(url => {
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(milestoneMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteMilestoneModal.requestStarted',
- milestoneMockData.url,
- );
return Promise.reject(dummyError);
});
- vm.onSubmit()
- .catch(error => {
- expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', {
- milestoneUrl: milestoneMockData.url,
- successful: false,
- });
- })
- .then(done)
- .catch(done.fail);
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+ await waitForPromises();
+
+ expect(flash.deprecatedCreateFlash).toHaveBeenCalledWith(dummyError);
});
});
});
diff --git a/spec/frontend/pages/profiles/show/emoji_menu_spec.js b/spec/frontend/pages/profiles/show/emoji_menu_spec.js
index 08fc0b92424..f35fb57aec7 100644
--- a/spec/frontend/pages/profiles/show/emoji_menu_spec.js
+++ b/spec/frontend/pages/profiles/show/emoji_menu_spec.js
@@ -46,7 +46,7 @@ describe('EmojiMenu', () => {
const dummyEmoji = 'tropical_fish';
const dummyVotesBlock = () => $('<div />');
- it('calls selectEmojiCallback', done => {
+ it('calls selectEmojiCallback', (done) => {
expect(dummySelectEmojiCallback).not.toHaveBeenCalled();
emojiMenu.addAward(dummyVotesBlock(), dummyAwardUrl, dummyEmoji, false, () => {
@@ -55,7 +55,7 @@ describe('EmojiMenu', () => {
});
});
- it('does not make an axios request', done => {
+ it('does not make an axios request', (done) => {
jest.spyOn(axios, 'request').mockReturnValue();
emojiMenu.addAward(dummyVotesBlock(), dummyAwardUrl, dummyEmoji, false, () => {
diff --git a/spec/frontend/pages/projects/edit/mount_search_settings_spec.js b/spec/frontend/pages/projects/edit/mount_search_settings_spec.js
new file mode 100644
index 00000000000..b48809b3d00
--- /dev/null
+++ b/spec/frontend/pages/projects/edit/mount_search_settings_spec.js
@@ -0,0 +1,25 @@
+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 73e3c385d33..b90c07a335b 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
@@ -30,7 +30,7 @@ describe('Fork groups list item component', () => {
const DUMMY_PATH = '/dummy/path';
- const createWrapper = propsData => {
+ const createWrapper = (propsData) => {
wrapper = shallowMount(ForkGroupsListItem, {
propsData: {
...DEFAULT_PROPS,
@@ -70,7 +70,7 @@ describe('Fork groups list item component', () => {
expect(
wrapper
.findAll(GlLink)
- .filter(w => w.text() === DUMMY_FULL_NAME)
+ .filter((w) => w.text() === DUMMY_FULL_NAME)
.at(0)
.attributes().href,
).toBe(DUMMY_PATH);
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 9993e4da980..91740c7ce3b 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
@@ -21,7 +21,7 @@ describe('Fork groups list component', () => {
const replyWith = (...args) => axiosMock.onGet(DEFAULT_PROPS.endpoint).reply(...args);
- const createWrapper = propsData => {
+ const createWrapper = (propsData) => {
wrapper = shallowMount(ForkGroupsList, {
propsData: {
...DEFAULT_PROPS,
@@ -104,12 +104,10 @@ describe('Fork groups list component', () => {
expect(wrapper.findAll(ForkGroupsListItem)).toHaveLength(namespaces.length);
namespaces.forEach((namespace, idx) => {
- expect(
- wrapper
- .findAll(ForkGroupsListItem)
- .at(idx)
- .props(),
- ).toStrictEqual({ group: namespace, hasReachedProjectLimit });
+ expect(wrapper.findAll(ForkGroupsListItem).at(idx).props()).toStrictEqual({
+ group: namespace,
+ hasReachedProjectLimit,
+ });
});
});
@@ -123,11 +121,6 @@ describe('Fork groups list component', () => {
await nextTick();
expect(wrapper.findAll(ForkGroupsListItem)).toHaveLength(1);
- expect(
- wrapper
- .findAll(ForkGroupsListItem)
- .at(0)
- .props().group.name,
- ).toBe('otherdummy');
+ expect(wrapper.findAll(ForkGroupsListItem).at(0).props().group.name).toBe('otherdummy');
});
});
diff --git a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
index 324c9788309..c4c48ea7517 100644
--- a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
+++ b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
@@ -12,6 +12,7 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`]
<gl-dropdown-stub
category="primary"
headertext=""
+ hideheaderborder="true"
size="medium"
text="rspec"
variant="default"
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
index 9a119377542..27cd0fe34bf 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
@@ -26,7 +26,7 @@ describe('Interval Pattern Input Component', () => {
const findCustomInput = () => wrapper.find('#schedule_cron');
const findAllLabels = () => wrapper.findAll('label');
const findSelectedRadio = () =>
- wrapper.findAll('input[type="radio"]').wrappers.find(x => x.element.checked);
+ wrapper.findAll('input[type="radio"]').wrappers.find((x) => x.element.checked);
const findSelectedRadioKey = () => findSelectedRadio()?.attributes('data-testid');
const selectEveryDayRadio = () => findEveryDayRadio().trigger('click');
const selectEveryWeekRadio = () => findEveryWeekRadio().trigger('click');
@@ -129,7 +129,7 @@ describe('Interval Pattern Input Component', () => {
});
it('renders each label for radio options properly', () => {
- const labels = findAllLabels().wrappers.map(el => trimText(el.text()));
+ const labels = findAllLabels().wrappers.map((el) => trimText(el.text()));
expect(labels).toEqual([
'Every day (at 4:00am)',
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index 5efcedf678b..de63409b181 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
@@ -47,7 +47,7 @@ describe('Timezone Dropdown', () => {
const data = $dropdownEl.data('data');
const formatted = $wrapper.find(tzListSel).text();
- data.forEach(item => {
+ data.forEach((item) => {
expect(formatted).toContain(formatTimezone(item));
});
});
@@ -88,10 +88,7 @@ describe('Timezone Dropdown', () => {
onSelectTimezone,
});
- $wrapper
- .find(tzListSel)
- .first()
- .trigger('click');
+ $wrapper.find(tzListSel).first().trigger('click');
expect(onSelectTimezone).toHaveBeenCalled();
});
@@ -103,7 +100,7 @@ describe('Timezone Dropdown', () => {
new TimezoneDropdown({
$inputEl,
$dropdownEl,
- displayFormat: selectedItem => formatTimezone(selectedItem),
+ displayFormat: (selectedItem) => formatTimezone(selectedItem),
});
expect($wrapper.find(tzDropdownToggleText).html()).toEqual('[UTC - 2.5] Newfoundland');
@@ -118,10 +115,7 @@ describe('Timezone Dropdown', () => {
displayFormat,
});
- $wrapper
- .find(tzListSel)
- .first()
- .trigger('click');
+ $wrapper.find(tzListSel).first().trigger('click');
expect(displayFormat).toHaveBeenCalled();
});
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 1fd9d285610..c90ebd47b08 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
@@ -6,13 +6,20 @@ import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
describe('Project Feature Settings', () => {
const defaultProps = {
name: 'Test',
- options: [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]],
+ options: [
+ [1, 1],
+ [2, 2],
+ [3, 3],
+ [4, 4],
+ [5, 5],
+ ],
value: 1,
disabledInput: false,
+ showToggle: true,
};
let wrapper;
- const mountComponent = customProps => {
+ const mountComponent = (customProps) => {
const propsData = { ...defaultProps, ...customProps };
return shallowMount(projectFeatureSetting, { propsData });
};
@@ -40,6 +47,14 @@ describe('Project Feature Settings', () => {
});
describe('Feature toggle', () => {
+ it('should be hidden if "showToggle" is passed false', async () => {
+ wrapper.setProps({ showToggle: false });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(projectFeatureToggle).element).toBeUndefined();
+ });
+
it('should enable the feature toggle if the value is not 0', () => {
expect(wrapper.find(projectFeatureToggle).props().value).toBe(true);
});
@@ -73,10 +88,7 @@ describe('Project Feature Settings', () => {
wrapper = mount(projectFeatureSetting, { propsData: defaultProps });
expect(wrapper.emitted().change).toBeUndefined();
- wrapper
- .find(projectFeatureToggle)
- .find('button')
- .trigger('click');
+ wrapper.find(projectFeatureToggle).find('button').trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().change.length).toBe(1);
@@ -110,10 +122,7 @@ describe('Project Feature Settings', () => {
it('should emit the change when a new option is selected', () => {
expect(wrapper.emitted().change).toBeUndefined();
- wrapper
- .findAll('option')
- .at(1)
- .trigger('change');
+ wrapper.findAll('option').at(1).trigger('change');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().change.length).toBe(1);
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 0b58260ed1c..9aee6ec7ace 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
@@ -20,6 +20,7 @@ const defaultProps = {
buildsAccessLevel: 20,
wikiAccessLevel: 20,
snippetsAccessLevel: 20,
+ operationsAccessLevel: 20,
pagesAccessLevel: 10,
analyticsAccessLevel: 20,
containerRegistryEnabled: true,
@@ -68,8 +69,12 @@ describe('Settings Panel', () => {
});
};
- const overrideCurrentSettings = (currentSettingsProps, extraProps = {}) => {
- return mountComponent({ ...extraProps, currentSettings: currentSettingsProps });
+ const overrideCurrentSettings = (
+ currentSettingsProps,
+ extraProps = {},
+ mountFn = shallowMount,
+ ) => {
+ return mountComponent({ ...extraProps, currentSettings: currentSettingsProps }, mountFn);
};
const findLFSSettingsRow = () => wrapper.find({ ref: 'git-lfs-settings' });
@@ -362,7 +367,7 @@ describe('Settings Panel', () => {
const repositoryFeatureToggleButton = findRepositoryFeatureSetting().find('button');
const lfsFeatureToggleButton = findLFSFeatureToggle().find('button');
- const isToggleButtonChecked = toggleButton => toggleButton.classes('is-checked');
+ const isToggleButtonChecked = (toggleButton) => toggleButton.classes('is-checked');
// assert the initial state
expect(isToggleButtonChecked(lfsFeatureToggleButton)).toBe(true);
@@ -523,28 +528,30 @@ describe('Settings Panel', () => {
});
});
- it('should set the visibility level description based upon the selected visibility level', () => {
- wrapper
- .find('[name="project[project_feature_attributes][metrics_dashboard_access_level]"]')
- .setValue(visibilityOptions.PUBLIC);
-
- expect(wrapper.vm.metricsDashboardAccessLevel).toBe(visibilityOptions.PUBLIC);
- });
-
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',
);
});
- it('should disable the metrics visibility dropdown when the project visibility level changes to private', () => {
- wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PRIVATE });
+ 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'}
+ `(
+ 'should disable the metrics visibility dropdown when #scenario',
+ ({ scenario, selectedOption, selectedOptionLabel }) => {
+ wrapper = overrideCurrentSettings(scenario, {}, mount);
- const metricsSettingsRow = wrapper.find({ ref: 'metrics-visibility-settings' });
+ const select = wrapper.find({ ref: 'metrics-visibility-settings' }).find('select');
+ const option = select.find('option');
- expect(wrapper.vm.metricsOptionsDropdownEnabled).toBe(true);
- expect(metricsSettingsRow.find('select').attributes('disabled')).toBe('disabled');
- });
+ expect(select.attributes('disabled')).toBe('disabled');
+ expect(select.element.value).toBe(selectedOption);
+ expect(option.attributes('value')).toBe(selectedOption);
+ expect(option.text()).toBe(selectedOptionLabel);
+ },
+ );
});
describe('Settings panel with feature flags', () => {
@@ -568,4 +575,12 @@ describe('Settings Panel', () => {
expect(findAnalyticsRow().exists()).toBe(true);
});
});
+
+ describe('Operations', () => {
+ it('should show the operations toggle', async () => {
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find({ ref: 'operations-settings' }).exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/pages/search/show/refresh_counts_spec.js b/spec/frontend/pages/search/show/refresh_counts_spec.js
index ead268b3971..81c9bf74308 100644
--- a/spec/frontend/pages/search/show/refresh_counts_spec.js
+++ b/spec/frontend/pages/search/show/refresh_counts_spec.js
@@ -4,8 +4,11 @@ import axios from '~/lib/utils/axios_utils';
import refreshCounts from '~/pages/search/show/refresh_counts';
const URL = `${TEST_HOST}/search/count?search=lorem+ipsum&project_id=3`;
-const urlWithScope = scope => `${URL}&scope=${scope}`;
-const counts = [{ scope: 'issues', count: 4 }, { scope: 'merge_requests', count: 5 }];
+const urlWithScope = (scope) => `${URL}&scope=${scope}`;
+const counts = [
+ { scope: 'issues', count: 4 },
+ { scope: 'merge_requests', count: 5 },
+];
const fixture = `<div class="badge">22</div>
<div class="badge js-search-count hidden" data-url="${urlWithScope('issues')}"></div>
<div class="badge js-search-count hidden" data-url="${urlWithScope('merge_requests')}"></div>`;
diff --git a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
index 4b50342bf84..8632c852720 100644
--- a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
+++ b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
@@ -2,10 +2,8 @@ import $ from 'jquery';
import preserveUrlFragment from '~/pages/sessions/new/preserve_url_fragment';
describe('preserve_url_fragment', () => {
- const findFormAction = selector => {
- return $(`.omniauth-container ${selector}`)
- .parent('form')
- .attr('action');
+ const findFormAction = (selector) => {
+ return $(`.omniauth-container ${selector}`).parent('form').attr('action');
};
preloadFixtures('sessions/new.html');
diff --git a/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js b/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js
index 589ec0ae047..f04c16d2ddb 100644
--- a/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js
+++ b/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js
@@ -56,7 +56,7 @@ describe('SigninTabsMemoizer', () => {
};
jest
.spyOn(document, 'querySelector')
- .mockImplementation(selector =>
+ .mockImplementation((selector) =>
selector === `${tabSelector} a[href="#bogus"]` ? null : fakeTab,
);
diff --git a/spec/frontend/pdf/index_spec.js b/spec/frontend/pdf/index_spec.js
index 0d8caa28fd1..1ae77a62675 100644
--- a/spec/frontend/pdf/index_spec.js
+++ b/spec/frontend/pdf/index_spec.js
@@ -14,7 +14,7 @@ const Component = Vue.extend(PDFLab);
describe('PDF component', () => {
let vm;
- const checkLoaded = done => {
+ const checkLoaded = (done) => {
if (vm.loading) {
setTimeout(() => {
checkLoaded(done);
@@ -25,7 +25,7 @@ describe('PDF component', () => {
};
describe('without PDF data', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
pdf: '',
@@ -43,7 +43,7 @@ describe('PDF component', () => {
});
describe('with PDF data', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = new Component({
propsData: {
pdf,
diff --git a/spec/frontend/pdf/page_spec.js b/spec/frontend/pdf/page_spec.js
index f9d94781265..4e0a6f78b63 100644
--- a/spec/frontend/pdf/page_spec.js
+++ b/spec/frontend/pdf/page_spec.js
@@ -14,7 +14,7 @@ describe('Page component', () => {
vm.$destroy();
});
- it('renders the page when mounting', done => {
+ it('renders the page when mounting', (done) => {
const promise = Promise.resolve();
const testPage = {
render: jest.fn().mockReturnValue({ promise: Promise.resolve() }),
diff --git a/spec/frontend/performance_bar/components/detailed_metric_spec.js b/spec/frontend/performance_bar/components/detailed_metric_spec.js
index 739b45e2193..754ffcc12e3 100644
--- a/spec/frontend/performance_bar/components/detailed_metric_spec.js
+++ b/spec/frontend/performance_bar/components/detailed_metric_spec.js
@@ -7,7 +7,7 @@ import RequestWarning from '~/performance_bar/components/request_warning.vue';
describe('detailedMetric', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(DetailedMetric, {
propsData: {
...props,
@@ -16,9 +16,9 @@ describe('detailedMetric', () => {
};
const findAllTraceBlocks = () => wrapper.findAll('pre');
- const findTraceBlockAtIndex = index => findAllTraceBlocks().at(index);
+ const findTraceBlockAtIndex = (index) => findAllTraceBlocks().at(index);
const findExpandBacktraceBtns = () => wrapper.findAll('[data-testid="backtrace-expand-btn"]');
- const findExpandedBacktraceBtnAtIndex = index => findExpandBacktraceBtns().at(index);
+ const findExpandedBacktraceBtnAtIndex = (index) => findExpandBacktraceBtns().at(index);
afterEach(() => {
wrapper.destroy();
@@ -95,7 +95,7 @@ describe('detailedMetric', () => {
expect(wrapper.find('.js-toggle-button')).not.toBeNull();
- wrapper.findAll('.performance-bar-modal td:nth-child(2)').wrappers.forEach(request => {
+ wrapper.findAll('.performance-bar-modal td:nth-child(2)').wrappers.forEach((request) => {
expect(request.text()).toContain('world');
});
});
diff --git a/spec/frontend/performance_bar/index_spec.js b/spec/frontend/performance_bar/index_spec.js
index bcd2cbbd530..8d9c32b7f12 100644
--- a/spec/frontend/performance_bar/index_spec.js
+++ b/spec/frontend/performance_bar/index_spec.js
@@ -4,25 +4,23 @@ import '~/performance_bar/components/performance_bar_app.vue';
import performanceBar from '~/performance_bar';
import PerformanceBarService from '~/performance_bar/services/performance_bar_service';
+jest.mock('~/performance_bar/performance_bar_log');
+
describe('performance bar wrapper', () => {
let mock;
let vm;
beforeEach(() => {
+ setFixtures('<div id="js-peek"></div>');
+ const peekWrapper = document.getElementById('js-peek');
performance.getEntriesByType = jest.fn().mockReturnValue([]);
- // clear html so that elements from previous tests don't mess with this test
- document.body.innerHTML = '';
- const peekWrapper = document.createElement('div');
-
peekWrapper.setAttribute('id', 'js-peek');
peekWrapper.setAttribute('data-env', 'development');
peekWrapper.setAttribute('data-request-id', '123');
peekWrapper.setAttribute('data-peek-url', '/-/peek/results');
peekWrapper.setAttribute('data-profile-url', '?lineprofiler=true');
- document.body.appendChild(peekWrapper);
-
mock = new MockAdapter(axios);
mock.onGet('/-/peek/results').reply(
@@ -48,6 +46,7 @@ describe('performance bar wrapper', () => {
afterEach(() => {
vm.$destroy();
+ document.getElementById('js-peek').remove();
mock.restore();
});
diff --git a/spec/frontend/performance_bar/stores/performance_bar_store_spec.js b/spec/frontend/performance_bar/stores/performance_bar_store_spec.js
index 56bab71540c..94dc1237cb0 100644
--- a/spec/frontend/performance_bar/stores/performance_bar_store_spec.js
+++ b/spec/frontend/performance_bar/stores/performance_bar_store_spec.js
@@ -3,7 +3,7 @@ import PerformanceBarStore from '~/performance_bar/stores/performance_bar_store'
describe('PerformanceBarStore', () => {
describe('truncateUrl', () => {
let store;
- const findUrl = id => store.findRequest(id).truncatedUrl;
+ const findUrl = (id) => store.findRequest(id).truncatedUrl;
beforeEach(() => {
store = new PerformanceBarStore();
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 ae2a9e5065d..aae25a3aa6d 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
@@ -16,8 +16,8 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
...props,
},
- // attachToDocument is required for input/submit events
- attachToDocument: mountFn === mount,
+ // attachTo is required for input/submit events
+ attachTo: mountFn === mount ? document.body : null,
});
};
diff --git a/spec/frontend/pipeline_editor/components/info/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/info/validation_segment_spec.js
new file mode 100644
index 00000000000..8a991d82018
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/info/validation_segment_spec.js
@@ -0,0 +1,113 @@
+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 e9c6ed60860..5e9471376bd 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
@@ -25,24 +25,51 @@ describe('CI Lint Results', () => {
};
const findTable = () => wrapper.find(GlTable);
- const findByTestId = selector => () => wrapper.find(`[data-testid="ci-lint-${selector}"]`);
- const findAllByTestId = selector => () => wrapper.findAll(`[data-testid="ci-lint-${selector}"]`);
+ const findByTestId = (selector) => () => wrapper.find(`[data-testid="ci-lint-${selector}"]`);
+ const findAllByTestId = (selector) => () =>
+ wrapper.findAll(`[data-testid="ci-lint-${selector}"]`);
const findLinkToDoc = () => wrapper.find(GlLink);
const findErrors = findByTestId('errors');
const findWarnings = findByTestId('warnings');
const findStatus = findByTestId('status');
const findOnlyExcept = findByTestId('only-except');
const findLintParameters = findAllByTestId('parameter');
+ const findLintValues = findAllByTestId('value');
const findBeforeScripts = findAllByTestId('before-script');
const findScripts = findAllByTestId('script');
const findAfterScripts = findAllByTestId('after-script');
- const filterEmptyScripts = property => mockJobs.filter(job => job[property].length !== 0);
+ const filterEmptyScripts = (property) => mockJobs.filter((job) => job[property].length !== 0);
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
+ describe('Empty results', () => {
+ it('renders with no jobs, errors or warnings defined', () => {
+ createComponent({ jobs: undefined, errors: undefined, warnings: undefined }, shallowMount);
+ expect(findTable().exists()).toBe(true);
+ });
+
+ it('renders when job has no properties defined', () => {
+ // job with no attributes such as `tagList` or `environment`
+ const job = {
+ stage: 'Stage Name',
+ name: 'test job',
+ };
+ createComponent({ jobs: [job] }, mount);
+
+ const param = findLintParameters().at(0);
+ const value = findLintValues().at(0);
+
+ expect(param.text()).toBe(`${job.stage} Job - ${job.name}`);
+
+ // This test should be updated once properties of each job are shown
+ // See https://gitlab.com/gitlab-org/gitlab/-/issues/291031
+ expect(value.text()).toBe('');
+ });
+ });
+
describe('Invalid results', () => {
beforeEach(() => {
createComponent({ valid: false, errors: mockErrors, warnings: mockWarnings }, mount);
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
new file mode 100644
index 00000000000..5ccf4bbdab4
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
@@ -0,0 +1,81 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import { GlAlert, GlLink } from '@gitlab/ui';
+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';
+
+describe('~/pipeline_editor/components/lint/ci_lint.vue', () => {
+ let wrapper;
+
+ const createComponent = (props = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(CiLint, {
+ provide: {
+ lintHelpPagePath: mockLintHelpPagePath,
+ },
+ propsData: {
+ ciConfig: mergeUnwrappedCiConfig(),
+ ...props,
+ },
+ });
+ };
+
+ const findAllByTestId = (selector) => wrapper.findAll(`[data-testid="${selector}"]`);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findLintParameters = () => findAllByTestId('ci-lint-parameter');
+ const findLintParameterAt = (i) => findLintParameters().at(i);
+ const findLintValueAt = (i) => findAllByTestId('ci-lint-value').at(i);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('Valid Results', () => {
+ beforeEach(() => {
+ createComponent({}, mount);
+ });
+
+ it('displays valid results', () => {
+ expect(findAlert().text()).toMatch('Status: Syntax is correct.');
+ });
+
+ it('displays link to the right help page', () => {
+ expect(findAlert().find(GlLink).attributes('href')).toBe(mockLintHelpPagePath);
+ });
+
+ it('displays jobs', () => {
+ expect(findLintParameters()).toHaveLength(3);
+
+ expect(findLintParameterAt(0).text()).toBe('Test Job - job_test_1');
+ expect(findLintParameterAt(1).text()).toBe('Test Job - job_test_2');
+ expect(findLintParameterAt(2).text()).toBe('Build Job - job_build');
+ });
+
+ it('displays jobs details', () => {
+ expect(findLintParameters()).toHaveLength(3);
+
+ expect(findLintValueAt(0).text()).toMatchInterpolatedText(
+ 'echo "test 1" Only policy: branches, tags When: on_success',
+ );
+ expect(findLintValueAt(1).text()).toMatchInterpolatedText(
+ 'echo "test 2" Only policy: branches, tags When: on_success',
+ );
+ expect(findLintValueAt(2).text()).toMatchInterpolatedText(
+ 'echo "build" Only policy: branches, tags When: on_success',
+ );
+ });
+
+ it('displays invalid results', () => {
+ createComponent(
+ {
+ ciConfig: mergeUnwrappedCiConfig({
+ status: CI_CONFIG_STATUS_INVALID,
+ }),
+ },
+ mount,
+ );
+
+ expect(findAlert().text()).toMatch('Status: Syntax is incorrect.');
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/text_editor_spec.js b/spec/frontend/pipeline_editor/components/text_editor_spec.js
index 18f71ebc95c..9221d64c44b 100644
--- a/spec/frontend/pipeline_editor/components/text_editor_spec.js
+++ b/spec/frontend/pipeline_editor/components/text_editor_spec.js
@@ -1,30 +1,69 @@
import { shallowMount } from '@vue/test-utils';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
-import { mockCiYml } from '../mock_data';
+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;
- const editorReadyListener = jest.fn();
- const createComponent = (attrs = {}, mountFn = shallowMount) => {
+ 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,
- ...attrs,
},
listeners: {
'editor-ready': editorReadyListener,
},
+ stubs: {
+ EditorLite: MockEditorLite,
+ },
+ ...opts,
});
};
- const findEditor = () => wrapper.find(EditorLite);
+ const findEditor = () => wrapper.find(MockEditorLite);
+
+ beforeEach(() => {
+ editorReadyListener = jest.fn();
+ mockUse = jest.fn();
+ mockRegisterCiSchema = jest.fn();
- it('contains an editor', () => {
createComponent();
+ });
+ it('contains an editor', () => {
expect(findEditor().exists()).toBe(true);
});
@@ -32,8 +71,18 @@ describe('~/pipeline_editor/components/text_editor.vue', () => {
expect(findEditor().props('value')).toBe(mockCiYml);
});
- it('editor is configured for .yml', () => {
- expect(findEditor().props('fileName')).toBe('*.yml');
+ 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', () => {
diff --git a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
new file mode 100644
index 00000000000..d3d9bf08209
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
@@ -0,0 +1,91 @@
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+import { GlTabs } from '@gitlab/ui';
+
+import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
+
+const mockContent1 = 'MOCK CONTENT 1';
+const mockContent2 = 'MOCK CONTENT 2';
+
+describe('~/pipeline_editor/components/ui/editor_tab.vue', () => {
+ let wrapper;
+ let mockChildMounted = jest.fn();
+
+ const MockChild = {
+ props: ['content'],
+ template: '<div>{{content}}</div>',
+ mounted() {
+ mockChildMounted(this.content);
+ },
+ };
+
+ const MockTabbedContent = {
+ components: {
+ EditorTab,
+ GlTabs,
+ MockChild,
+ },
+ template: `
+ <gl-tabs>
+ <editor-tab :title-link-attributes="{ 'data-testid': 'tab1-btn' }" :lazy="true">
+ <mock-child content="${mockContent1}"/>
+ </editor-tab>
+ <editor-tab :title-link-attributes="{ 'data-testid': 'tab2-btn' }" :lazy="true">
+ <mock-child content="${mockContent2}"/>
+ </editor-tab>
+ </gl-tabs>
+ `,
+ };
+
+ const createWrapper = () => {
+ wrapper = mount(MockTabbedContent);
+ };
+
+ beforeEach(() => {
+ mockChildMounted = jest.fn();
+ });
+
+ it('tabs are mounted lazily', async () => {
+ createWrapper();
+
+ expect(mockChildMounted).toHaveBeenCalledTimes(0);
+ });
+
+ it('first tab is only mounted after nextTick', async () => {
+ createWrapper();
+
+ await nextTick();
+
+ expect(mockChildMounted).toHaveBeenCalledTimes(1);
+ expect(mockChildMounted).toHaveBeenCalledWith(mockContent1);
+ });
+
+ describe('user interaction', () => {
+ const clickTab = async (testid) => {
+ wrapper.find(`[data-testid="${testid}"]`).trigger('click');
+ await nextTick();
+ };
+
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ it('mounts a tab once after selecting it', async () => {
+ await clickTab('tab2-btn');
+
+ expect(mockChildMounted).toHaveBeenCalledTimes(2);
+ expect(mockChildMounted).toHaveBeenNthCalledWith(1, mockContent1);
+ expect(mockChildMounted).toHaveBeenNthCalledWith(2, mockContent2);
+ });
+
+ it('mounts each tab once after selecting each', async () => {
+ await clickTab('tab2-btn');
+ await clickTab('tab1-btn');
+ await clickTab('tab2-btn');
+
+ expect(mockChildMounted).toHaveBeenCalledTimes(2);
+ expect(mockChildMounted).toHaveBeenNthCalledWith(1, mockContent1);
+ expect(mockChildMounted).toHaveBeenNthCalledWith(2, mockContent2);
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/graphql/__snapshots__/resolvers_spec.js.snap b/spec/frontend/pipeline_editor/graphql/__snapshots__/resolvers_spec.js.snap
index d7d4d0af90c..8670c44f6f6 100644
--- a/spec/frontend/pipeline_editor/graphql/__snapshots__/resolvers_spec.js.snap
+++ b/spec/frontend/pipeline_editor/graphql/__snapshots__/resolvers_spec.js.snap
@@ -27,7 +27,7 @@ Object {
"echo 'script 1'",
],
"stage": "test",
- "tagList": Array [
+ "tags": Array [
"tag 1",
],
"when": "on_success",
@@ -61,7 +61,7 @@ Object {
"echo 'script 2'",
],
"stage": "test",
- "tagList": Array [
+ "tags": Array [
"tag 2",
],
"when": "on_success",
diff --git a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
index b531f8af797..3e008527415 100644
--- a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
+++ b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
@@ -5,7 +5,7 @@ import {
mockCiYml,
mockDefaultBranch,
mockLintResponse,
- mockProjectPath,
+ mockProjectFullPath,
} from '../mock_data';
import httpStatus from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
@@ -32,12 +32,12 @@ describe('~/pipeline_editor/graphql/resolvers', () => {
it('resolves lint data with type names', async () => {
const result = resolvers.Query.blobContent(null, {
- projectPath: mockProjectPath,
+ projectPath: mockProjectFullPath,
path: mockCiConfigPath,
ref: mockDefaultBranch,
});
- expect(Api.getRawFile).toHaveBeenCalledWith(mockProjectPath, mockCiConfigPath, {
+ expect(Api.getRawFile).toHaveBeenCalledWith(mockProjectFullPath, mockCiConfigPath, {
ref: mockDefaultBranch,
});
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index d882490c272..3eacc467c51 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -1,27 +1,142 @@
-export const mockProjectPath = 'user1/project1';
+import { CI_CONFIG_STATUS_VALID } from '~/pipeline_editor/constants';
+import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
+
+export const mockProjectNamespace = 'user1';
+export const mockProjectPath = 'project1';
+export const mockProjectFullPath = `${mockProjectNamespace}/${mockProjectPath}`;
export const mockDefaultBranch = 'master';
export const mockNewMergeRequestPath = '/-/merge_requests/new';
-export const mockCommitId = 'aabbccdd';
+export const mockCommitSha = 'aabbccdd';
+export const mockCommitNextSha = 'eeffgghh';
+export const mockLintHelpPagePath = '/-/lint-help';
+export const mockYmlHelpPagePath = '/-/yml-help';
export const mockCommitMessage = 'My commit message';
export const mockCiConfigPath = '.gitlab-ci.yml';
export const mockCiYml = `
-job1:
+stages:
+ - test
+ - build
+
+job_test_1:
stage: test
- script:
- - echo 'test'
+ script:
+ - echo "test 1"
+
+job_test_2:
+ stage: test
+ script:
+ - echo "test 2"
+
+job_build:
+ stage: build
+ script:
+ - echo "build"
+ needs: ["job_test_2"]
`;
+const mockJobFields = {
+ beforeScript: [],
+ afterScript: [],
+ environment: null,
+ allowFailure: false,
+ tags: [],
+ when: 'on_success',
+ only: { refs: ['branches', 'tags'], __typename: 'CiJobLimitType' },
+ except: null,
+ needs: { nodes: [], __typename: 'CiConfigNeedConnection' },
+ __typename: 'CiConfigJob',
+};
+
+// Mock result of the graphql query at:
+// app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
export const mockCiConfigQueryResponse = {
data: {
ciConfig: {
errors: [],
- stages: [],
- status: '',
+ status: CI_CONFIG_STATUS_VALID,
+ stages: {
+ __typename: 'CiConfigStageConnection',
+ nodes: [
+ {
+ name: 'test',
+ groups: {
+ nodes: [
+ {
+ name: 'job_test_1',
+ size: 1,
+ jobs: {
+ nodes: [
+ {
+ name: 'job_test_1',
+ script: ['echo "test 1"'],
+ ...mockJobFields,
+ },
+ ],
+ __typename: 'CiConfigJobConnection',
+ },
+ __typename: 'CiConfigGroup',
+ },
+ {
+ name: 'job_test_2',
+ size: 1,
+ jobs: {
+ nodes: [
+ {
+ name: 'job_test_2',
+ script: ['echo "test 2"'],
+ ...mockJobFields,
+ },
+ ],
+ __typename: 'CiConfigJobConnection',
+ },
+ __typename: 'CiConfigGroup',
+ },
+ ],
+ __typename: 'CiConfigGroupConnection',
+ },
+ __typename: 'CiConfigStage',
+ },
+ {
+ name: 'build',
+ groups: {
+ nodes: [
+ {
+ name: 'job_build',
+ size: 1,
+ jobs: {
+ nodes: [
+ {
+ name: 'job_build',
+ script: ['echo "build"'],
+ ...mockJobFields,
+ },
+ ],
+ __typename: 'CiConfigJobConnection',
+ },
+ __typename: 'CiConfigGroup',
+ },
+ ],
+ __typename: 'CiConfigGroupConnection',
+ },
+ __typename: 'CiConfigStage',
+ },
+ ],
+ },
+ __typename: 'CiConfig',
},
},
};
+export const mergeUnwrappedCiConfig = (mergedConfig) => {
+ const { ciConfig } = mockCiConfigQueryResponse.data;
+ return {
+ ...ciConfig,
+ stages: unwrapStagesWithNeeds(ciConfig.stages.nodes),
+ ...mergedConfig,
+ };
+};
+
export const mockLintResponse = {
valid: true,
errors: [],
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index 14d6b03645c..d6b90900600 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -1,32 +1,29 @@
import { nextTick } from 'vue';
import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
-import {
- GlAlert,
- GlButton,
- GlFormInput,
- GlFormTextarea,
- GlLoadingIcon,
- GlTabs,
- GlTab,
-} from '@gitlab/ui';
+import { GlAlert, GlButton, GlFormInput, GlFormTextarea, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import httpStatusCodes from '~/lib/utils/http_status';
import { objectToQuery, redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility';
import {
mockCiConfigPath,
mockCiConfigQueryResponse,
mockCiYml,
- mockCommitId,
+ mockCommitSha,
+ mockCommitNextSha,
mockCommitMessage,
mockDefaultBranch,
mockProjectPath,
+ mockProjectFullPath,
+ mockProjectNamespace,
mockNewMergeRequestPath,
} from './mock_data';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
-import getCiConfig from '~/pipeline_editor/graphql/queries/ci_config.graphql';
+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';
@@ -41,6 +38,19 @@ jest.mock('~/lib/utils/url_utility', () => ({
mergeUrlParams: jest.requireActual('~/lib/utils/url_utility').mergeUrlParams,
}));
+const MockEditorLite = {
+ template: '<div/>',
+};
+
+const mockProvide = {
+ projectFullPath: mockProjectFullPath,
+ projectPath: mockProjectPath,
+ projectNamespace: mockProjectNamespace,
+ glFeatures: {
+ ciConfigVisualizationTab: true,
+ },
+};
+
describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
let wrapper;
@@ -55,17 +65,15 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
lintLoading = false,
options = {},
mountFn = shallowMount,
- provide = {
- glFeatures: {
- ciConfigVisualizationTab: true,
- },
- },
+ provide = mockProvide,
} = {}) => {
mockMutate = jest.fn().mockResolvedValue({
data: {
commitCreate: {
errors: [],
- commit: {},
+ commit: {
+ sha: mockCommitNextSha,
+ },
},
},
});
@@ -73,9 +81,8 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
wrapper = mountFn(PipelineEditorApp, {
propsData: {
ciConfigPath: mockCiConfigPath,
- commitId: mockCommitId,
+ commitSha: mockCommitSha,
defaultBranch: mockDefaultBranch,
- projectPath: mockProjectPath,
newMergeRequestPath: mockNewMergeRequestPath,
...props,
},
@@ -84,9 +91,7 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
GlTabs,
GlButton,
CommitForm,
- EditorLite: {
- template: '<div/>',
- },
+ EditorLite: MockEditorLite,
TextEditor,
},
mocks: {
@@ -102,14 +107,14 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
mutate: mockMutate,
},
},
- // attachToDocument is required for input/submit events
- attachToDocument: mountFn === mount,
+ // attachTo is required for input/submit events
+ attachTo: mountFn === mount ? document.body : null,
...options,
});
};
const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
- const handlers = [[getCiConfig, mockCiConfigData]];
+ const handlers = [[getCiConfigData, mockCiConfigData]];
const resolvers = {
Query: {
blobContent() {
@@ -134,17 +139,17 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findAlert = () => wrapper.find(GlAlert);
- const findBlobFailureAlert = () => wrapper.find(GlAlert);
- const findTabAt = i => wrapper.findAll(GlTab).at(i);
+ 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);
beforeEach(() => {
mockBlobContentData = jest.fn();
- mockCiConfigData = jest.fn().mockResolvedValue(mockCiConfigQueryResponse);
+ mockCiConfigData = jest.fn();
});
afterEach(() => {
@@ -167,26 +172,14 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
describe('tabs', () => {
describe('editor tab', () => {
- beforeEach(() => {
- createComponent();
- });
+ it('displays editor only after the tab is mounted', async () => {
+ createComponent({ mountFn: mount });
- it('displays the tab and its content', async () => {
- expect(
- findTabAt(0)
- .find(TextEditor)
- .exists(),
- ).toBe(true);
- });
-
- it('displays tab lazily, until editor is ready', async () => {
- expect(findTabAt(0).attributes('lazy')).toBe('true');
-
- findTextEditor().vm.$emit('editor-ready');
+ expect(findTabAt(0).find(TextEditor).exists()).toBe(false);
await nextTick();
- expect(findTabAt(0).attributes('lazy')).toBe(undefined);
+ expect(findTabAt(0).find(TextEditor).exists()).toBe(true);
});
});
@@ -210,7 +203,12 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
describe('with feature flag off', () => {
beforeEach(() => {
- createComponent({ provide: { glFeatures: { ciConfigVisualizationTab: false } } });
+ createComponent({
+ provide: {
+ ...mockProvide,
+ glFeatures: { ciConfigVisualizationTab: false },
+ },
+ });
});
it('does not display the tab', () => {
@@ -224,28 +222,36 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
beforeEach(async () => {
createComponent({ mountFn: mount });
- await wrapper.setData({
+ wrapper.setData({
content: mockCiYml,
contentModel: mockCiYml,
});
+
+ await waitForPromises();
});
it('displays content after the query loads', () => {
expect(findLoadingIcon().exists()).toBe(false);
- expect(findTextEditor().attributes('value')).toBe(mockCiYml);
+
+ 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: mockCommitId,
+ lastCommitId: mockCommitSha,
message: mockCommitMessage,
- projectPath: mockProjectPath,
+ projectPath: mockProjectFullPath,
startBranch: mockDefaultBranch,
};
- const findInForm = selector => findCommitForm().find(selector);
+ const findInForm = (selector) => findCommitForm().find(selector);
const submitCommit = async ({
message = mockCommitMessage,
@@ -280,13 +286,29 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
});
});
- it('refreshes the page', () => {
- expect(refreshCurrentPage).toHaveBeenCalled();
+ 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', () => {
@@ -307,10 +329,6 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
},
});
});
-
- it('refreshes the page', () => {
- expect(refreshCurrentPage).toHaveBeenCalledWith();
- });
});
describe('when the user commits changes to open a new merge request', () => {
@@ -349,7 +367,7 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
});
describe('when the commit fails', () => {
- it('shows a the error message', async () => {
+ it('shows an error message', async () => {
mockMutate.mockRejectedValueOnce(new Error('commit failed'));
await submitCommit();
@@ -385,61 +403,90 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
it('content is restored after cancel is called', async () => {
await cancelCommitForm();
- expect(findTextEditor().attributes('value')).toBe(mockCiYml);
+ expect(findEditorLite().attributes('value')).toBe(mockCiYml);
});
});
});
});
- describe('displays fetch content errors', () => {
- it('no error is shown when data is set', async () => {
+ describe('when queries are called', () => {
+ beforeEach(() => {
mockBlobContentData.mockResolvedValue(mockCiYml);
- createComponentWithApollo();
+ mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
+ });
- await waitForPromises();
+ describe('when file exists', () => {
+ beforeEach(async () => {
+ createComponentWithApollo();
- expect(findBlobFailureAlert().exists()).toBe(false);
- expect(findTextEditor().attributes('value')).toBe(mockCiYml);
- });
+ await waitForPromises();
+ });
- it('shows a 404 error message', async () => {
- mockBlobContentData.mockRejectedValueOnce({
- response: {
- status: 404,
- },
+ it('shows editor and commit form', () => {
+ expect(findEditorLite().exists()).toBe(true);
+ expect(findTextEditor().exists()).toBe(true);
});
- createComponentWithApollo();
- await waitForPromises();
+ it('no error is shown when data is set', async () => {
+ expect(findAlert().exists()).toBe(false);
+ expect(findEditorLite().attributes('value')).toBe(mockCiYml);
+ });
+
+ it('ci config query is called with correct variables', async () => {
+ createComponentWithApollo();
- expect(findBlobFailureAlert().text()).toBe(
- 'No CI file found in this repository, please add one.',
- );
+ await waitForPromises();
+
+ expect(mockCiConfigData).toHaveBeenCalledWith({
+ content: mockCiYml,
+ projectPath: mockProjectFullPath,
+ });
+ });
});
- it('shows a 400 error message', async () => {
- mockBlobContentData.mockRejectedValueOnce({
- response: {
- status: 400,
- },
+ describe('when no file exists', () => {
+ const expectedAlertMsg =
+ '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 () => {
+ mockBlobContentData.mockRejectedValueOnce({
+ response: {
+ status: httpStatusCodes.NOT_FOUND,
+ },
+ });
+ createComponentWithApollo();
+
+ await waitForPromises();
+
+ expect(findAlert().text()).toBe(expectedAlertMsg);
+ expect(findEditorLite().exists()).toBe(false);
+ expect(findTextEditor().exists()).toBe(false);
});
- createComponentWithApollo();
- await waitForPromises();
+ it('shows a 400 error message and does not show editor or commit form', async () => {
+ mockBlobContentData.mockRejectedValueOnce({
+ response: {
+ status: httpStatusCodes.BAD_REQUEST,
+ },
+ });
+ createComponentWithApollo();
- expect(findBlobFailureAlert().text()).toBe(
- 'Repository does not have a default branch, please set one.',
- );
- });
+ await waitForPromises();
- it('shows a unkown error message', async () => {
- mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
- createComponentWithApollo();
- await waitForPromises();
+ expect(findAlert().text()).toBe(expectedAlertMsg);
+ expect(findEditorLite().exists()).toBe(false);
+ expect(findTextEditor().exists()).toBe(false);
+ });
+
+ it('shows a unkown error message', async () => {
+ mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
+ createComponentWithApollo();
+ await waitForPromises();
- expect(findBlobFailureAlert().text()).toBe(
- 'The CI configuration was not loaded, please try again.',
- );
+ expect(findAlert().text()).toBe('The CI configuration was not loaded, please try again.');
+ expect(findEditorLite().exists()).toBe(true);
+ expect(findTextEditor().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 b42339f626e..421ad9f4939 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -44,10 +44,7 @@ describe('Pipeline New Form', () => {
const findWarnings = () => wrapper.findAll('[data-testid="run-pipeline-warning"]');
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const getExpectedPostParams = () => JSON.parse(mock.history.post[0].data);
- const changeRef = i =>
- findDropdownItems()
- .at(i)
- .vm.$emit('click');
+ const changeRef = (i) => findDropdownItems().at(i).vm.$emit('click');
const createComponent = (term = '', props = {}, method = shallowMount) => {
wrapper = method(PipelineNewForm, {
@@ -99,11 +96,7 @@ describe('Pipeline New Form', () => {
createComponent('master');
expect(findDropdownItems()).toHaveLength(1);
- expect(
- findDropdownItems()
- .at(0)
- .text(),
- ).toBe('master');
+ expect(findDropdownItems().at(0).text()).toBe('master');
});
});
@@ -136,9 +129,7 @@ describe('Pipeline New Form', () => {
});
it('removes ci variable row on remove icon button click', async () => {
- findRemoveIcons()
- .at(1)
- .trigger('click');
+ findRemoveIcons().at(1).trigger('click');
await wrapper.vm.$nextTick();
@@ -298,26 +289,16 @@ describe('Pipeline New Form', () => {
});
it('adds a description to the first variable from yml', () => {
- expect(
- findVariableRows()
- .at(0)
- .text(),
- ).toContain(mockYmlDesc);
+ expect(findVariableRows().at(0).text()).toContain(mockYmlDesc);
});
it('removes the description when a variable key changes', async () => {
findKeyInputs().at(0).element.value = 'yml_var_modified';
- findKeyInputs()
- .at(0)
- .trigger('change');
+ findKeyInputs().at(0).trigger('change');
await wrapper.vm.$nextTick();
- expect(
- findVariableRows()
- .at(0)
- .text(),
- ).not.toContain(mockYmlDesc);
+ expect(findVariableRows().at(0).text()).not.toContain(mockYmlDesc);
});
});
diff --git a/spec/frontend/pipelines/blank_state_spec.js b/spec/frontend/pipelines/blank_state_spec.js
index bb069fdc2c8..c09d9232569 100644
--- a/spec/frontend/pipelines/blank_state_spec.js
+++ b/spec/frontend/pipelines/blank_state_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/pipelines/components/pipelines_list/blank_state.vue';
-import mountComponent from '../helpers/vue_mount_component_helper';
describe('Pipelines Blank State', () => {
let vm;
diff --git a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
index 5747c91bee8..80807c0b330 100644
--- a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
@@ -66,11 +66,7 @@ describe('The DAG annotations', () => {
expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
Object.values(multiNote).forEach((item, idx) => {
- expect(
- getAllTextBlocks()
- .at(idx)
- .text(),
- ).toBe(`${item.source.name} → ${item.target.name}`);
+ expect(getAllTextBlocks().at(idx).text()).toBe(`${item.source.name} → ${item.target.name}`);
});
});
diff --git a/spec/frontend/pipelines/components/dag/dag_graph_spec.js b/spec/frontend/pipelines/components/dag/dag_graph_spec.js
index 7786212cb69..ccfb2ae7cee 100644
--- a/spec/frontend/pipelines/components/dag/dag_graph_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_graph_spec.js
@@ -20,7 +20,7 @@ describe('The DAG graph', () => {
}
wrapper = shallowMount(DagGraph, {
- attachToDocument: true,
+ attachTo: document.body,
propsData,
data() {
return {
@@ -88,17 +88,13 @@ describe('The DAG graph', () => {
});
it('renders the title as text', () => {
- expect(
- getAllLabels()
- .at(0)
- .text(),
- ).toBe(parsedData.nodes[0].name);
+ expect(getAllLabels().at(0).text()).toBe(parsedData.nodes[0].name);
});
});
});
describe('interactions', () => {
- const strokeOpacity = opacity => `stroke-opacity: ${opacity};`;
+ const strokeOpacity = (opacity) => `stroke-opacity: ${opacity};`;
const baseOpacity = () => wrapper.vm.$options.viewOptions.baseOpacity;
describe('links', () => {
@@ -168,10 +164,10 @@ describe('The DAG graph', () => {
describe('nodes', () => {
const liveNode = () => getAllNodes().at(10);
const anotherLiveNode = () => getAllNodes().at(5);
- const nodesNotHighlighted = () => getAllNodes().filter(n => !n.classes(IS_HIGHLIGHTED));
- const linksNotHighlighted = () => getAllLinks().filter(n => !n.classes(IS_HIGHLIGHTED));
- const nodesHighlighted = () => getAllNodes().filter(n => n.classes(IS_HIGHLIGHTED));
- const linksHighlighted = () => getAllLinks().filter(n => n.classes(IS_HIGHLIGHTED));
+ const nodesNotHighlighted = () => getAllNodes().filter((n) => !n.classes(IS_HIGHLIGHTED));
+ const linksNotHighlighted = () => getAllLinks().filter((n) => !n.classes(IS_HIGHLIGHTED));
+ const nodesHighlighted = () => getAllNodes().filter((n) => n.classes(IS_HIGHLIGHTED));
+ const linksHighlighted = () => getAllLinks().filter((n) => n.classes(IS_HIGHLIGHTED));
describe('on click', () => {
it('highlights the clicked node and predecessors', () => {
@@ -180,19 +176,19 @@ describe('The DAG graph', () => {
expect(nodesNotHighlighted().length < getAllNodes().length).toBe(true);
expect(linksNotHighlighted().length < getAllLinks().length).toBe(true);
- linksHighlighted().wrappers.forEach(link => {
+ linksHighlighted().wrappers.forEach((link) => {
expect(link.attributes('style')).toBe(strokeOpacity(highlightIn));
});
- nodesHighlighted().wrappers.forEach(node => {
+ nodesHighlighted().wrappers.forEach((node) => {
expect(node.attributes('stroke')).not.toBe('#f2f2f2');
});
- linksNotHighlighted().wrappers.forEach(link => {
+ linksNotHighlighted().wrappers.forEach((link) => {
expect(link.attributes('style')).toBe(strokeOpacity(highlightOut));
});
- nodesNotHighlighted().wrappers.forEach(node => {
+ nodesNotHighlighted().wrappers.forEach((node) => {
expect(node.attributes('stroke')).toBe('#f2f2f2');
});
});
diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js
index 08a43199594..f6195e30e44 100644
--- a/spec/frontend/pipelines/components/dag/dag_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_spec.js
@@ -21,7 +21,7 @@ describe('Pipeline DAG graph wrapper', () => {
const getAllAlerts = () => wrapper.findAll(GlAlert);
const getGraph = () => wrapper.find(DagGraph);
const getNotes = () => wrapper.find(DagAnnotations);
- const getErrorText = type => wrapper.vm.$options.errorTexts[type];
+ const getErrorText = (type) => wrapper.vm.$options.errorTexts[type];
const getEmptyState = () => wrapper.find(GlEmptyState);
const createComponent = ({
diff --git a/spec/frontend/pipelines/components/dag/parsing_utils_spec.js b/spec/frontend/pipelines/components/dag/parsing_utils_spec.js
index ceb6b64d4ad..5d3f680a57c 100644
--- a/spec/frontend/pipelines/components/dag/parsing_utils_spec.js
+++ b/spec/frontend/pipelines/components/dag/parsing_utils_spec.js
@@ -30,7 +30,10 @@ describe('DAG visualization parsing utilities', () => {
{ source: 'job2', target: 'job4' },
];
- const dedupedLinks = [{ source: 'job1', target: 'job2' }, { source: 'job2', target: 'job4' }];
+ const dedupedLinks = [
+ { source: 'job1', target: 'job2' },
+ { source: 'job2', target: 'job4' },
+ ];
const nodeLookup = {
job1: {
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index 8a6586a7d7d..00fe9e784b3 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -11,10 +11,10 @@ describe('Pipelines filtered search', () => {
let mock;
const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
- const getSearchToken = type =>
+ const getSearchToken = (type) =>
findFilteredSearch()
.props('availableTokens')
- .find(token => token.type === type);
+ .find((token) => token.type === type);
const findBranchToken = () => getSearchToken('ref');
const findTagToken = () => getSearchToken('tag');
const findUserToken = () => getSearchToken('username');
@@ -26,7 +26,7 @@ describe('Pipelines filtered search', () => {
projectId: '21',
params,
},
- attachToDocument: true,
+ attachTo: document.body,
});
};
diff --git a/spec/frontend/pipelines/empty_state_spec.js b/spec/frontend/pipelines/empty_state_spec.js
index 28a73c8863c..7e42a3b5ae9 100644
--- a/spec/frontend/pipelines/empty_state_spec.js
+++ b/spec/frontend/pipelines/empty_state_spec.js
@@ -1,5 +1,7 @@
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;
@@ -38,15 +40,104 @@ describe('Pipelines Empty State', () => {
expect(findGetStartedButton().attributes('href')).toBe('foo');
});
- 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',
- );
+ 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 a button', () => {
- expect(findGetStartedButton().text()).toBe('Get started with Pipelines');
+ 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();
+ });
+ });
});
});
});
diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js
index ab477292bc1..95d96e127c6 100644
--- a/spec/frontend/pipelines/graph/action_component_spec.js
+++ b/spec/frontend/pipelines/graph/action_component_spec.js
@@ -33,7 +33,7 @@ describe('pipeline graph action component', () => {
expect(wrapper.attributes('title')).toBe('bar');
});
- it('should update bootstrap tooltip when title changes', done => {
+ it('should update bootstrap tooltip when title changes', (done) => {
wrapper.setProps({ tooltipText: 'changed' });
wrapper.vm
@@ -51,7 +51,7 @@ describe('pipeline graph action component', () => {
});
describe('on click', () => {
- it('emits `pipelineActionRequestComplete` after a successful request', done => {
+ it('emits `pipelineActionRequestComplete` after a successful request', (done) => {
jest.spyOn(wrapper.vm, '$emit');
findButton().trigger('click');
@@ -64,7 +64,7 @@ describe('pipeline graph action component', () => {
.catch(done.fail);
});
- it('renders a loading icon while waiting for request', done => {
+ it('renders a loading icon while waiting for request', (done) => {
findButton().trigger('click');
wrapper.vm.$nextTick(() => {
diff --git a/spec/frontend/pipelines/graph/graph_component_legacy_spec.js b/spec/frontend/pipelines/graph/graph_component_legacy_spec.js
index 3b1909b6564..840b1f8baf5 100644
--- a/spec/frontend/pipelines/graph/graph_component_legacy_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_legacy_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import { setHTMLFixture } from 'helpers/fixtures';
@@ -18,7 +18,7 @@ describe('graph component', () => {
const findExpandPipelineBtn = () => wrapper.find('[data-testid="expand-pipeline-button"]');
const findAllExpandPipelineBtns = () => wrapper.findAll('[data-testid="expand-pipeline-button"]');
const findStageColumns = () => wrapper.findAll(StageColumnComponentLegacy);
- const findStageColumnAt = i => findStageColumns().at(i);
+ const findStageColumnAt = (i) => findStageColumns().at(i);
beforeEach(() => {
mediator = new PipelinesMediator({ endpoint: '' });
@@ -104,11 +104,9 @@ describe('graph component', () => {
});
it('should include the left-connector class in the build of the second child', () => {
- expect(
- findStageColumnAt(1)
- .find('.build:nth-child(1)')
- .classes('left-connector'),
- ).toBe(true);
+ expect(findStageColumnAt(1).find('.build:nth-child(1)').classes('left-connector')).toBe(
+ true,
+ );
});
it('should include the js-has-linked-pipelines flag', () => {
@@ -119,12 +117,7 @@ describe('graph component', () => {
describe('computeds and methods', () => {
describe('capitalizeStageName', () => {
it('it capitalizes the stage name', () => {
- expect(
- wrapper
- .findAll('.stage-column .stage-name')
- .at(1)
- .text(),
- ).toBe('Prebuild');
+ expect(wrapper.findAll('.stage-column .stage-name').at(1).text()).toBe('Prebuild');
});
});
@@ -160,21 +153,20 @@ describe('graph component', () => {
describe('triggered by', () => {
describe('on click', () => {
- it('should emit `onClickUpstreamPipeline` when triggered by linked pipeline is clicked', () => {
+ it('should emit `onClickUpstreamPipeline` when triggered by linked pipeline is clicked', async () => {
const btnWrapper = findExpandPipelineBtn();
btnWrapper.trigger('click');
- btnWrapper.vm.$nextTick(() => {
- expect(wrapper.emitted().onClickUpstreamPipeline).toEqual([
- store.state.pipeline.triggered_by,
- ]);
- });
+ await nextTick();
+ expect(wrapper.emitted().onClickUpstreamPipeline).toEqual([
+ store.state.pipeline.triggered_by,
+ ]);
});
});
describe('with expanded pipeline', () => {
- it('should render expanded pipeline', done => {
+ it('should render expanded pipeline', async () => {
// expand the pipeline
store.state.pipeline.triggered_by[0].isExpanded = true;
@@ -186,40 +178,46 @@ describe('graph component', () => {
},
});
- Vue.nextTick()
- .then(() => {
- expect(wrapper.find('.js-upstream-pipeline-12').exists()).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(wrapper.find('.js-upstream-pipeline-12').exists()).toBe(true);
});
});
});
describe('triggered', () => {
describe('on click', () => {
- it('should emit `onClickTriggered`', () => {
- // We have to mock this method since we do both style change and
- // emit and event, not mocking returns an error.
- wrapper.setMethods({
- handleClickedDownstream: jest.fn(() =>
- wrapper.vm.$emit('onClickTriggered', ...store.state.pipeline.triggered),
- ),
+ // We have to mock this property of HTMLElement since component relies on it
+ let offsetParentDescriptor;
+ beforeAll(() => {
+ offsetParentDescriptor = Object.getOwnPropertyDescriptor(
+ HTMLElement.prototype,
+ 'offsetParent',
+ );
+ Object.defineProperty(HTMLElement.prototype, 'offsetParent', {
+ get() {
+ return this.parentNode;
+ },
});
+ });
+ afterAll(() => {
+ Object.defineProperty(HTMLElement.prototype, offsetParentDescriptor);
+ });
+ it('should emit `onClickDownstreamPipeline`', async () => {
const btnWrappers = findAllExpandPipelineBtns();
const downstreamBtnWrapper = btnWrappers.at(btnWrappers.length - 1);
downstreamBtnWrapper.trigger('click');
- downstreamBtnWrapper.vm.$nextTick(() => {
- expect(wrapper.emitted().onClickTriggered).toEqual([store.state.pipeline.triggered]);
- });
+ await nextTick();
+ expect(wrapper.emitted().onClickDownstreamPipeline).toEqual([
+ [store.state.pipeline.triggered[1]],
+ ]);
});
});
describe('with expanded pipeline', () => {
- it('should render expanded pipeline', done => {
+ it('should render expanded pipeline', async () => {
// expand the pipeline
store.state.pipeline.triggered[0].isExpanded = true;
@@ -231,12 +229,8 @@ describe('graph component', () => {
},
});
- Vue.nextTick()
- .then(() => {
- expect(wrapper.find('.js-downstream-pipeline-34993051')).not.toBeNull();
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(wrapper.find('.js-downstream-pipeline-34993051')).not.toBeNull();
});
});
diff --git a/spec/frontend/pipelines/graph/graph_component_spec.js b/spec/frontend/pipelines/graph/graph_component_spec.js
index 7572dd83798..cfc3b7af282 100644
--- a/spec/frontend/pipelines/graph/graph_component_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_spec.js
@@ -1,7 +1,9 @@
import { mount, shallowMount } from '@vue/test-utils';
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 LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
import { GRAPHQL } from '~/pipelines/components/graph/constants';
import {
generateResponse,
@@ -13,21 +15,37 @@ describe('graph component', () => {
let wrapper;
const findLinkedColumns = () => wrapper.findAll(LinkedPipelinesColumn);
+ const findLinksLayer = () => wrapper.find(LinksLayer);
const findStageColumns = () => wrapper.findAll(StageColumnComponent);
const defaultProps = {
pipeline: generateResponse(mockPipelineResponse, 'root/fungi-xoxo'),
};
- const createComponent = ({ mountFn = shallowMount, props = {} } = {}) => {
+ const createComponent = ({
+ data = {},
+ mountFn = shallowMount,
+ props = {},
+ stubOverride = {},
+ } = {}) => {
wrapper = mountFn(PipelineGraph, {
propsData: {
...defaultProps,
...props,
},
+ data() {
+ return { ...data };
+ },
provide: {
dataMethod: GRAPHQL,
},
+ stubs: {
+ 'links-inner': true,
+ 'linked-pipeline': true,
+ 'job-item': true,
+ 'job-group-dropdown': true,
+ ...stubOverride,
+ },
});
};
@@ -45,17 +63,36 @@ describe('graph component', () => {
expect(findStageColumns()).toHaveLength(defaultProps.pipeline.stages.length);
});
+ it('renders the links layer', () => {
+ expect(findLinksLayer().exists()).toBe(true);
+ });
+
describe('when column requests a refresh', () => {
beforeEach(() => {
- findStageColumns()
- .at(0)
- .vm.$emit('refreshPipelineGraph');
+ findStageColumns().at(0).vm.$emit('refreshPipelineGraph');
});
it('refreshPipelineGraph is emitted', () => {
expect(wrapper.emitted().refreshPipelineGraph).toHaveLength(1);
});
});
+
+ describe('when links are present', () => {
+ beforeEach(async () => {
+ createComponent({
+ mountFn: mount,
+ stubOverride: { 'job-item': false },
+ data: { hoveredJobName: 'test_a' },
+ });
+ findLinksLayer().vm.$emit('highlightedJobsChange', ['test_c', 'build_c']);
+ });
+
+ it('dims unrelated jobs', () => {
+ const unrelatedJob = wrapper.find(JobItem);
+ expect(findLinksLayer().emitted().highlightedJobsChange).toHaveLength(1);
+ expect(unrelatedJob.classes('gl-opacity-3')).toBe(true);
+ });
+ });
});
describe('when linked pipelines are not present', () => {
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 875aaa48037..54593c527cb 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -2,10 +2,10 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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 getPipelineDetails from '~/pipelines/graphql/queries/get_pipeline_details.query.graphql';
import { mockPipelineResponse } from './mock_data';
const defaultProvide = {
diff --git a/spec/frontend/pipelines/graph/job_item_spec.js b/spec/frontend/pipelines/graph/job_item_spec.js
index 8aabb2f9cdd..cb2837cbb39 100644
--- a/spec/frontend/pipelines/graph/job_item_spec.js
+++ b/spec/frontend/pipelines/graph/job_item_spec.js
@@ -7,7 +7,7 @@ describe('pipeline graph job item', () => {
const findJobWithoutLink = () => wrapper.find('[data-testid="job-without-link"]');
const findJobWithLink = () => wrapper.find('[data-testid="job-with-link"]');
- const createWrapper = propsData => {
+ const createWrapper = (propsData) => {
wrapper = mount(JobItem, {
propsData,
});
@@ -52,7 +52,7 @@ describe('pipeline graph job item', () => {
});
describe('name with link', () => {
- it('should render the job name and status with a link', done => {
+ it('should render the job name and status with a link', (done) => {
createWrapper({ job: mockJob });
wrapper.vm.$nextTick(() => {
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
index 37eb5f900dd..6db152f2607 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
@@ -1,10 +1,10 @@
import VueApollo from 'vue-apollo';
import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
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 getPipelineDetails from '~/pipelines/graphql/queries/get_pipeline_details.query.graphql';
import { DOWNSTREAM, GRAPHQL } from '~/pipelines/components/graph/constants';
import { LOAD_FAILURE } from '~/pipelines/constants';
import {
diff --git a/spec/frontend/pipelines/graph/mock_data.js b/spec/frontend/pipelines/graph/mock_data.js
index d53a11eea0e..7650cbd2d5c 100644
--- a/spec/frontend/pipelines/graph/mock_data.js
+++ b/spec/frontend/pipelines/graph/mock_data.js
@@ -56,7 +56,7 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
},
@@ -96,7 +96,7 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
},
@@ -136,7 +136,7 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
},
@@ -176,7 +176,7 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
},
@@ -200,7 +200,7 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
},
@@ -224,7 +224,7 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
},
@@ -277,18 +277,18 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_c',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_b',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -331,26 +331,26 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_d 3/3',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_d 2/3',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_d 1/3',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_b',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -377,26 +377,26 @@ export const mockPipelineResponse = {
},
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_d 3/3',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_d 2/3',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_d 1/3',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_b',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -433,18 +433,18 @@ export const mockPipelineResponse = {
action: null,
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_c',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_b',
},
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -481,10 +481,10 @@ export const mockPipelineResponse = {
action: null,
},
needs: {
- __typename: 'CiJobConnection',
+ __typename: 'CiBuildNeedConnection',
nodes: [
{
- __typename: 'CiJob',
+ __typename: 'CiBuildNeed',
name: 'build_b',
},
],
@@ -578,41 +578,54 @@ export const upstream = {
export const wrappedPipelineReturn = {
data: {
project: {
+ __typename: 'Project',
pipeline: {
+ __typename: 'Pipeline',
id: 'gid://gitlab/Ci::Pipeline/175',
iid: '38',
downstream: {
+ __typename: 'PipelineConnection',
nodes: [],
},
upstream: {
id: 'gid://gitlab/Ci::Pipeline/174',
iid: '37',
path: '/root/elemenohpee/-/pipelines/174',
+ __typename: 'Pipeline',
status: {
+ __typename: 'DetailedStatus',
group: 'success',
label: 'passed',
icon: 'status_success',
},
sourceJob: {
name: 'test_c',
+ __typename: 'CiJob',
},
project: {
id: 'gid://gitlab/Project/25',
name: 'elemenohpee',
fullPath: 'root/elemenohpee',
+ __typename: 'Project',
},
},
stages: {
+ __typename: 'CiStageConnection',
nodes: [
{
name: 'build',
+ __typename: 'CiStage',
status: {
action: null,
+ __typename: 'DetailedStatus',
},
groups: {
+ __typename: 'CiGroupConnection',
nodes: [
{
+ __typename: 'CiGroup',
status: {
+ __typename: 'DetailedStatus',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -620,20 +633,25 @@ export const wrappedPipelineReturn = {
name: 'build_n',
size: 1,
jobs: {
+ __typename: 'CiJobConnection',
nodes: [
{
+ __typename: 'CiJob',
name: 'build_n',
scheduledAt: null,
needs: {
+ __typename: 'CiBuildNeedConnection',
nodes: [],
},
status: {
+ __typename: 'DetailedStatus',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
detailsPath: '/root/elemenohpee/-/jobs/1662',
group: 'success',
action: {
+ __typename: 'StatusAction',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/elemenohpee/-/jobs/1662/retry',
@@ -656,7 +674,7 @@ export const wrappedPipelineReturn = {
export const generateResponse = (raw, mockPath) => unwrapPipelineData(mockPath, raw.data);
-export const pipelineWithUpstreamDownstream = base => {
+export const pipelineWithUpstreamDownstream = (base) => {
const pip = { ...base };
pip.data.project.pipeline.downstream = downstream;
pip.data.project.pipeline.upstream = upstream;
diff --git a/spec/frontend/pipelines/graph/stage_column_component_legacy_spec.js b/spec/frontend/pipelines/graph/stage_column_component_legacy_spec.js
index 463e4c12c7d..2965325ea7c 100644
--- a/spec/frontend/pipelines/graph/stage_column_component_legacy_spec.js
+++ b/spec/frontend/pipelines/graph/stage_column_component_legacy_spec.js
@@ -40,12 +40,7 @@ describe('stage column component', () => {
});
it('should render provided title', () => {
- expect(
- wrapper
- .find('.stage-name')
- .text()
- .trim(),
- ).toBe('foo');
+ expect(wrapper.find('.stage-name').text().trim()).toBe('foo');
});
it('should render the provided groups', () => {
diff --git a/spec/frontend/pipelines/graph/stage_column_component_spec.js b/spec/frontend/pipelines/graph/stage_column_component_spec.js
index 44803929f6d..202e25ccda3 100644
--- a/spec/frontend/pipelines/graph/stage_column_component_spec.js
+++ b/spec/frontend/pipelines/graph/stage_column_component_spec.js
@@ -30,6 +30,7 @@ const mockGroups = Array(4)
const defaultProps = {
title: 'Fish',
groups: mockGroups,
+ pipelineId: 159,
};
describe('stage column component', () => {
@@ -92,36 +93,51 @@ describe('stage column component', () => {
});
describe('job', () => {
- beforeEach(() => {
- createComponent({
- method: mount,
- props: {
- groups: [
- {
- id: 4259,
- name: '<img src=x onerror=alert(document.domain)>',
- status: {
- icon: 'status_success',
- label: 'success',
- tooltip: '<img src=x onerror=alert(document.domain)>',
+ describe('text handling', () => {
+ beforeEach(() => {
+ createComponent({
+ method: mount,
+ props: {
+ groups: [
+ {
+ id: 4259,
+ name: '<img src=x onerror=alert(document.domain)>',
+ status: {
+ icon: 'status_success',
+ label: 'success',
+ tooltip: '<img src=x onerror=alert(document.domain)>',
+ },
},
- },
- ],
- title: 'test <img src=x onerror=alert(document.domain)>',
- },
+ ],
+ title: 'test <img src=x onerror=alert(document.domain)>',
+ },
+ });
});
- });
- it('capitalizes and escapes name', () => {
- expect(findStageColumnTitle().text()).toBe(
- 'Test &lt;img src=x onerror=alert(document.domain)&gt;',
- );
+ it('capitalizes and escapes name', () => {
+ expect(findStageColumnTitle().text()).toBe(
+ 'Test &lt;img src=x onerror=alert(document.domain)&gt;',
+ );
+ });
+
+ it('escapes id', () => {
+ expect(findStageColumnGroup().attributes('id')).toBe(
+ 'ci-badge-&lt;img src=x onerror=alert(document.domain)&gt;',
+ );
+ });
});
- it('escapes id', () => {
- expect(findStageColumnGroup().attributes('id')).toBe(
- 'ci-badge-&lt;img src=x onerror=alert(document.domain)&gt;',
- );
+ describe('interactions', () => {
+ beforeEach(() => {
+ createComponent({ method: mount });
+ });
+
+ it('emits jobHovered event on mouseenter and mouseleave', async () => {
+ await findStageColumnGroup().trigger('mouseenter');
+ expect(wrapper.emitted().jobHover).toEqual([[defaultProps.groups[0].name]]);
+ await findStageColumnGroup().trigger('mouseleave');
+ expect(wrapper.emitted().jobHover).toEqual([[defaultProps.groups[0].name], ['']]);
+ });
});
});
diff --git a/spec/frontend/pipelines/nav_controls_spec.js b/spec/frontend/pipelines/nav_controls_spec.js
index 139d53881c8..305dc557b39 100644
--- a/spec/frontend/pipelines/nav_controls_spec.js
+++ b/spec/frontend/pipelines/nav_controls_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import navControlsComp from '~/pipelines/components/pipelines_list/nav_controls.vue';
-import mountComponent from '../helpers/vue_mount_component_helper';
describe('Pipelines Nav Controls', () => {
let NavControlsComponent;
diff --git a/spec/frontend/pipelines/pipeline_graph/mock_data.js b/spec/frontend/pipelines/pipeline_graph/mock_data.js
index a77973b293c..7d1a7a79c7f 100644
--- a/spec/frontend/pipelines/pipeline_graph/mock_data.js
+++ b/spec/frontend/pipelines/pipeline_graph/mock_data.js
@@ -1,4 +1,4 @@
-import { createUniqueLinkId } from '~/pipelines/utils';
+import { createUniqueLinkId } from '~/pipelines/components/graph_shared/drawing_utils';
export const yamlString = `stages:
- empty
@@ -78,18 +78,12 @@ export const pipelineData = {
groups: [
{
name: 'deploy_1',
- jobs: [{ script: 'yarn magick', stage: 'deploy' }],
+ jobs: [{ script: 'yarn magick', stage: 'deploy', needs: ['test_1'] }],
id: jobId4,
},
],
},
],
- jobs: {
- [jobId1]: {},
- [jobId2]: {},
- [jobId3]: {},
- [jobId4]: {},
- },
};
export const singleStageData = {
diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
index 6704ee06c1a..b6b0a964383 100644
--- a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlAlert } from '@gitlab/ui';
import { pipelineData, singleStageData } from './mock_data';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
+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 PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import StagePill from '~/pipelines/components/pipeline_graph/stage_pill.vue';
@@ -23,7 +23,7 @@ describe('pipeline graph component', () => {
const findAlert = () => wrapper.find(GlAlert);
const findAllStagePills = () => wrapper.findAll(StagePill);
const findAllStageBackgroundElements = () => wrapper.findAll('[data-testid="stage-background"]');
- const findStageBackgroundElementAt = index => findAllStageBackgroundElements().at(index);
+ const findStageBackgroundElementAt = (index) => findAllStageBackgroundElements().at(index);
const findAllJobPills = () => wrapper.findAll(JobPill);
afterEach(() => {
@@ -37,7 +37,7 @@ describe('pipeline graph component', () => {
});
it('renders an empty section', () => {
- expect(wrapper.text()).toBe(wrapper.vm.$options.warningTexts[EMPTY_PIPELINE_DATA]);
+ expect(wrapper.text()).toBe(wrapper.vm.$options.errorTexts[EMPTY_PIPELINE_DATA]);
expect(findPipelineGraph().exists()).toBe(false);
expect(findAllStagePills()).toHaveLength(0);
expect(findAllJobPills()).toHaveLength(0);
@@ -51,23 +51,25 @@ describe('pipeline graph component', () => {
it('renders an error message and does not render the graph', () => {
expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(wrapper.vm.$options.warningTexts[INVALID_CI_CONFIG]);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[INVALID_CI_CONFIG]);
expect(findPipelineGraph().exists()).toBe(false);
});
});
- describe('without `INVALID` status', () => {
+ describe('with `VALID` status', () => {
beforeEach(() => {
- wrapper = createComponent();
+ wrapper = createComponent({
+ pipelineData: { status: CI_CONFIG_STATUS_VALID, stages: [{ name: 'hello', groups: [] }] },
+ });
});
it('renders the graph with no status error', () => {
- expect(findAlert().text()).not.toBe(wrapper.vm.$options.warningTexts[INVALID_CI_CONFIG]);
+ expect(findAlert().exists()).toBe(false);
expect(findPipelineGraph().exists()).toBe(true);
});
});
- describe('with error while rendering the links', () => {
+ describe('with error while rendering the links with needs', () => {
beforeEach(() => {
wrapper = createComponent();
});
diff --git a/spec/frontend/pipelines/pipeline_graph/utils_spec.js b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
index 12154df6fcf..070d3bf7dac 100644
--- a/spec/frontend/pipelines/pipeline_graph/utils_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
@@ -68,10 +68,10 @@ describe('utils functions', () => {
it('returns a hash with the jobname as key and all its data as value', () => {
const jobs = {
- [jobName1]: job1,
- [jobName2]: job2,
- [jobName3]: job3,
- [jobName4]: job4,
+ [jobName1]: { jobs: [job1], name: jobName1, needs: [] },
+ [jobName2]: { jobs: [job2], name: jobName2, needs: [] },
+ [jobName3]: { jobs: [job3], name: jobName3, needs: job3.needs },
+ [jobName4]: { jobs: [job4], name: jobName4, needs: job4.needs },
};
expect(createJobsHash(pipelineGraphData.stages)).toEqual(jobs);
@@ -110,5 +110,41 @@ describe('utils functions', () => {
[jobName4]: [jobName3, jobName1, jobName2],
});
});
+
+ it('handles parallel jobs by adding the group name as a need', () => {
+ const size = 3;
+ const jobOptimize1 = 'optimize_1';
+ const jobPrepareA = 'prepare_a';
+ const jobPrepareA1 = `${jobPrepareA} 1/${size}`;
+ const jobPrepareA2 = `${jobPrepareA} 2/${size}`;
+ const jobPrepareA3 = `${jobPrepareA} 3/${size}`;
+
+ const jobsParallel = {
+ [jobOptimize1]: {
+ jobs: [job1],
+ name: [jobOptimize1],
+ needs: [jobPrepareA1, jobPrepareA2, jobPrepareA3],
+ },
+ [jobPrepareA]: { jobs: [], name: jobPrepareA, needs: [], size },
+ [jobPrepareA1]: { jobs: [], name: jobPrepareA, needs: [], size },
+ [jobPrepareA2]: { jobs: [], name: jobPrepareA, needs: [], size },
+ [jobPrepareA3]: { jobs: [], name: jobPrepareA, needs: [], size },
+ };
+
+ expect(generateJobNeedsDict(jobsParallel)).toEqual({
+ [jobOptimize1]: [
+ jobPrepareA1,
+ // This is the important part, the `jobPrepareA` group name has been
+ // added to our list of needs.
+ jobPrepareA,
+ jobPrepareA2,
+ jobPrepareA3,
+ ],
+ [jobPrepareA]: [],
+ [jobPrepareA1]: [],
+ [jobPrepareA2]: [],
+ [jobPrepareA3]: [],
+ });
+ });
});
});
diff --git a/spec/frontend/pipelines/pipeline_url_spec.js b/spec/frontend/pipelines/pipeline_url_spec.js
index fc45af2c254..47315bd42e6 100644
--- a/spec/frontend/pipelines/pipeline_url_spec.js
+++ b/spec/frontend/pipelines/pipeline_url_spec.js
@@ -28,7 +28,7 @@ describe('Pipeline Url Component', () => {
pipelineScheduleUrl: 'foo',
};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(PipelineUrlComponent, {
propsData: { ...defaultProps, ...props },
provide: {
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index 071a2b24889..69c1b7ce43d 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -55,11 +55,7 @@ describe('Pipelines Actions dropdown', () => {
});
it("renders a disabled action when it's not playable", () => {
- expect(
- findAllDropdownItems()
- .at(1)
- .attributes('disabled'),
- ).toBe('true');
+ expect(findAllDropdownItems().at(1).attributes('disabled')).toBe('true');
});
describe('on click', () => {
@@ -100,9 +96,7 @@ describe('Pipelines Actions dropdown', () => {
mock.onPost(scheduledJobAction.path).reply(200);
jest.spyOn(window, 'confirm').mockReturnValue(true);
- findAllDropdownItems()
- .at(0)
- .vm.$emit('click');
+ findAllDropdownItems().at(0).vm.$emit('click');
expect(window.confirm).toHaveBeenCalled();
@@ -115,28 +109,20 @@ describe('Pipelines Actions dropdown', () => {
mock.onPost(scheduledJobAction.path).reply(200);
jest.spyOn(window, 'confirm').mockReturnValue(false);
- findAllDropdownItems()
- .at(0)
- .vm.$emit('click');
+ findAllDropdownItems().at(0).vm.$emit('click');
expect(window.confirm).toHaveBeenCalled();
expect(mock.history.post.length).toBe(0);
});
it('displays the remaining time in the dropdown', () => {
- expect(
- findAllCountdowns()
- .at(0)
- .props('endDateString'),
- ).toBe(scheduledJobAction.scheduled_at);
+ expect(findAllCountdowns().at(0).props('endDateString')).toBe(
+ scheduledJobAction.scheduled_at,
+ );
});
it('displays 00:00:00 for expired jobs in the dropdown', () => {
- expect(
- findAllCountdowns()
- .at(1)
- .props('endDateString'),
- ).toBe(expiredJobAction.scheduled_at);
+ expect(findAllCountdowns().at(1).props('endDateString')).toBe(expiredJobAction.scheduled_at);
});
});
});
diff --git a/spec/frontend/pipelines/pipelines_artifacts_spec.js b/spec/frontend/pipelines/pipelines_artifacts_spec.js
index 83f6cb68eba..4f4c15fd4cc 100644
--- a/spec/frontend/pipelines/pipelines_artifacts_spec.js
+++ b/spec/frontend/pipelines/pipelines_artifacts_spec.js
@@ -1,12 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlLink } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
describe('Pipelines Artifacts dropdown', () => {
let wrapper;
const createComponent = () => {
- wrapper = shallowMount(PipelineArtifacts, {
+ wrapper = mount(PipelineArtifacts, {
propsData: {
artifacts: [
{
@@ -22,8 +22,8 @@ describe('Pipelines Artifacts dropdown', () => {
});
};
- const findGlLink = () => wrapper.find(GlLink);
- const findAllGlLinks = () => wrapper.find('.dropdown-menu').findAll(GlLink);
+ const findFirstGlDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findAllGlDropdownItems = () => wrapper.find(GlDropdown).findAll(GlDropdownItem);
beforeEach(() => {
createComponent();
@@ -35,12 +35,12 @@ describe('Pipelines Artifacts dropdown', () => {
});
it('should render a dropdown with all the provided artifacts', () => {
- expect(findAllGlLinks()).toHaveLength(2);
+ expect(findAllGlDropdownItems()).toHaveLength(2);
});
it('should render a link with the provided path', () => {
- expect(findGlLink().attributes('href')).toEqual('/download/path');
+ expect(findFirstGlDropdownItem().find('a').attributes('href')).toEqual('/download/path');
- expect(findGlLink().text()).toContain('artifact');
+ expect(findFirstGlDropdownItem().text()).toContain('artifact');
});
});
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index ce0e76ba22d..5d82669b0b8 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
@@ -57,10 +58,10 @@ describe('Pipelines', () => {
};
const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
- const findByTestId = id => wrapper.find(`[data-testid="${id}"]`);
+ 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 findTab = (tab) => findByTestId(`pipelines-tab-${tab}`);
const findRunPipelineButton = () => findByTestId('run-pipeline-button');
const findCiLintButton = () => findByTestId('ci-lint-button');
@@ -72,7 +73,7 @@ describe('Pipelines', () => {
const findTablePagination = () => wrapper.find(TablePagination);
- const createComponent = (props = defaultProps, methods) => {
+ const createComponent = (props = defaultProps) => {
wrapper = mount(PipelinesComponent, {
propsData: {
store: new Store(),
@@ -80,13 +81,15 @@ describe('Pipelines', () => {
params: {},
...props,
},
- methods: {
- ...methods,
- },
});
};
beforeEach(() => {
+ delete window.location;
+ });
+
+ beforeEach(() => {
+ window.location = { search: '' };
mock = new MockAdapter(axios);
pipelines = getJSONFixture(jsonFixtureName);
@@ -170,7 +173,7 @@ describe('Pipelines', () => {
it('renders tab empty state finished scope', () => {
wrapper.vm.scope = 'finished';
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findBlankState().text()).toBe('There are currently no finished pipelines.');
});
});
@@ -194,16 +197,8 @@ describe('Pipelines', () => {
});
it('renders empty state', () => {
- expect(
- findEmptyState()
- .find('h4')
- .text(),
- ).toBe('Build with confidence');
- expect(
- findEmptyState()
- .find(GlButton)
- .attributes('href'),
- ).toBe(paths.helpPagePath);
+ expect(findEmptyState().find('h4').text()).toBe('Build with confidence');
+ expect(findEmptyState().find(GlButton).attributes('href')).toBe(paths.helpPagePath);
});
it('does not render tabs nor buttons', () => {
@@ -320,11 +315,7 @@ describe('Pipelines', () => {
'This project is not currently set up to run pipelines.',
);
- expect(
- findEmptyState()
- .find(GlButton)
- .exists(),
- ).toBeFalsy();
+ expect(findEmptyState().find(GlButton).exists()).toBeFalsy();
});
it('does not render tabs or buttons', () => {
@@ -394,30 +385,23 @@ describe('Pipelines', () => {
});
it('should make an API request when using tabs', () => {
- const updateContentMock = jest.fn(() => {});
- createComponent(
- { hasGitlabCi: true, canCreatePipeline: true, ...paths },
- {
- updateContent: updateContentMock,
- },
- );
+ createComponent({ hasGitlabCi: true, canCreatePipeline: true, ...paths });
+ jest.spyOn(wrapper.vm.service, 'getPipelines');
return waitForPromises().then(() => {
findTab('finished').trigger('click');
- expect(updateContentMock).toHaveBeenCalledWith({ scope: 'finished', page: '1' });
+ expect(wrapper.vm.service.getPipelines).toHaveBeenCalledWith({
+ scope: 'finished',
+ page: '1',
+ });
});
});
describe('with pagination', () => {
it('should make an API request when using pagination', () => {
- const updateContentMock = jest.fn(() => {});
- createComponent(
- { hasGitlabCi: true, canCreatePipeline: true, ...paths },
- {
- updateContent: updateContentMock,
- },
- );
+ createComponent({ hasGitlabCi: true, canCreatePipeline: true, ...paths });
+ jest.spyOn(wrapper.vm.service, 'getPipelines');
return waitForPromises()
.then(() => {
@@ -430,12 +414,14 @@ describe('Pipelines', () => {
totalPages: 5,
};
- return wrapper.vm.$nextTick();
+ return nextTick();
})
.then(() => {
wrapper.find('.next-page-item').trigger('click');
-
- expect(updateContentMock).toHaveBeenCalledWith({ scope: 'all', page: '2' });
+ expect(wrapper.vm.service.getPipelines).toHaveBeenCalledWith({
+ scope: 'all',
+ page: '2',
+ });
});
});
});
@@ -554,7 +540,7 @@ describe('Pipelines', () => {
wrapper.vm.hasError = true;
wrapper.vm.isLoading = false;
- return wrapper.vm.$nextTick().then(() => {
+ 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.',
);
@@ -566,7 +552,7 @@ describe('Pipelines', () => {
wrapper.vm.hasError = false;
wrapper.vm.state.pipelines = pipelines.pipelines;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.find(PipelinesTableComponent).exists()).toBe(true);
});
});
@@ -575,7 +561,7 @@ describe('Pipelines', () => {
wrapper.vm.state.count.all = 10;
wrapper.vm.isLoading = false;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findBlankState().exists()).toBe(true);
expect(findBlankState().props('message')).toBe('There are currently no pipelines.');
});
@@ -584,7 +570,7 @@ describe('Pipelines', () => {
it('shows empty tab when project has CI', () => {
wrapper.vm.isLoading = false;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findBlankState().exists()).toBe(true);
expect(findBlankState().props('message')).toBe('There are currently no pipelines.');
});
@@ -595,7 +581,7 @@ describe('Pipelines', () => {
wrapper.vm.isLoading = false;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(wrapper.find(EmptyState).exists()).toBe(true);
});
});
@@ -606,7 +592,7 @@ describe('Pipelines', () => {
wrapper.vm.isLoading = true;
wrapper.vm.hasMadeRequest = true;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationTabs().exists()).toBe(true);
});
});
@@ -616,7 +602,7 @@ describe('Pipelines', () => {
wrapper.vm.state.pipelines = pipelines.pipelines;
wrapper.vm.hasMadeRequest = true;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationTabs().exists()).toBe(true);
});
});
@@ -626,7 +612,7 @@ describe('Pipelines', () => {
wrapper.vm.hasError = true;
wrapper.vm.hasMadeRequest = true;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationTabs().exists()).toBe(true);
});
});
@@ -636,7 +622,7 @@ describe('Pipelines', () => {
wrapper.vm.state.count.all = 10;
wrapper.vm.hasMadeRequest = true;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationTabs().exists()).toBe(true);
});
});
@@ -644,7 +630,7 @@ describe('Pipelines', () => {
it('returns false when has not made first request', () => {
wrapper.vm.hasMadeRequest = false;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationTabs().exists()).toBe(false);
});
});
@@ -655,7 +641,7 @@ describe('Pipelines', () => {
wrapper.vm.isLoading = false;
wrapper.vm.hasMadeRequest = true;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationTabs().exists()).toBe(false);
});
});
@@ -665,7 +651,7 @@ describe('Pipelines', () => {
it('returns true when it has paths & has made the first request', () => {
wrapper.vm.hasMadeRequest = true;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationControls().exists()).toBe(true);
});
});
@@ -673,7 +659,7 @@ describe('Pipelines', () => {
it('returns false when it has not made the first request', () => {
wrapper.vm.hasMadeRequest = false;
- return wrapper.vm.$nextTick().then(() => {
+ return nextTick().then(() => {
expect(findNavigationControls().exists()).toBe(false);
});
});
@@ -692,7 +678,7 @@ describe('Pipelines', () => {
return waitForPromises();
});
- it('updates request data and query params on filter submit', () => {
+ it('updates request data and query params on filter submit', async () => {
const expectedQueryParams = {
page: '1',
scope: 'all',
@@ -702,15 +688,17 @@ describe('Pipelines', () => {
};
findFilteredSearch().vm.$emit('submit', mockSearch);
+ await nextTick();
expect(wrapper.vm.requestData).toEqual(expectedQueryParams);
expect(updateContentMock).toHaveBeenCalledWith(expectedQueryParams);
});
- it('does not add query params if raw text search is used', () => {
+ it('does not add query params if raw text search is used', async () => {
const expectedQueryParams = { page: '1', scope: 'all' };
findFilteredSearch().vm.$emit('submit', ['rawText']);
+ await nextTick();
expect(wrapper.vm.requestData).toEqual(expectedQueryParams);
expect(updateContentMock).toHaveBeenCalledWith(expectedQueryParams);
diff --git a/spec/frontend/pipelines/pipelines_store_spec.js b/spec/frontend/pipelines/pipelines_store_spec.js
index ce21f788ed5..f374ecd0c0a 100644
--- a/spec/frontend/pipelines/pipelines_store_spec.js
+++ b/spec/frontend/pipelines/pipelines_store_spec.js
@@ -21,7 +21,10 @@ describe('Pipelines Store', () => {
});
it('should store the provided array', () => {
- const array = [{ id: 1, status: 'running' }, { id: 2, status: 'success' }];
+ const array = [
+ { id: 1, status: 'running' },
+ { id: 2, status: 'success' },
+ ];
store.storePipelines(array);
expect(store.state.pipelines).toEqual(array);
diff --git a/spec/frontend/pipelines/pipelines_table_row_spec.js b/spec/frontend/pipelines/pipelines_table_row_spec.js
index 32d53c0f1f8..9cdd24b2ab5 100644
--- a/spec/frontend/pipelines/pipelines_table_row_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_row_spec.js
@@ -5,7 +5,7 @@ import eventHub from '~/pipelines/event_hub';
describe('Pipelines Table Row', () => {
const jsonFixtureName = 'pipelines/pipelines.json';
- const createWrapper = pipeline =>
+ const createWrapper = (pipeline) =>
mount(PipelinesTableRowComponent, {
propsData: {
pipeline,
@@ -24,9 +24,9 @@ describe('Pipelines Table Row', () => {
beforeEach(() => {
const { pipelines } = getJSONFixture(jsonFixtureName);
- pipeline = pipelines.find(p => p.user !== null && p.commit !== null);
- pipelineWithoutAuthor = pipelines.find(p => p.user === null && p.commit !== null);
- pipelineWithoutCommit = pipelines.find(p => p.user === null && p.commit === null);
+ pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
+ pipelineWithoutAuthor = pipelines.find((p) => p.user === null && p.commit !== null);
+ pipelineWithoutCommit = pipelines.find((p) => p.user === null && p.commit === null);
});
afterEach(() => {
@@ -82,10 +82,7 @@ describe('Pipelines Table Row', () => {
).toEqual(pipeline.user.path);
expect(
- wrapper
- .find('.table-section:nth-child(3) .js-user-avatar-image-toolip')
- .text()
- .trim(),
+ wrapper.find('.table-section:nth-child(3) .js-user-avatar-image-tooltip').text().trim(),
).toEqual(pipeline.user.name);
});
});
@@ -112,7 +109,7 @@ describe('Pipelines Table Row', () => {
const commitAuthorLink = commitAuthorElement.attributes('href');
const commitAuthorName = commitAuthorElement
- .find('.js-user-avatar-image-toolip')
+ .find('.js-user-avatar-image-tooltip')
.text()
.trim();
@@ -190,7 +187,7 @@ describe('Pipelines Table Row', () => {
});
it('emits `retryPipeline` event when retry button is clicked and toggles loading', () => {
- eventHub.$on('retryPipeline', endpoint => {
+ eventHub.$on('retryPipeline', (endpoint) => {
expect(endpoint).toBe('/retry');
});
@@ -199,7 +196,7 @@ describe('Pipelines Table Row', () => {
});
it('emits `openConfirmationModal` event when cancel button is clicked and toggles loading', () => {
- eventHub.$once('openConfirmationModal', data => {
+ eventHub.$once('openConfirmationModal', (data) => {
const { id, ref, commit } = pipeline;
expect(data.endpoint).toBe('/cancel');
@@ -215,7 +212,7 @@ describe('Pipelines Table Row', () => {
wrapper.find('.js-pipelines-cancel-button').trigger('click');
});
- it('renders a loading icon when `cancelingPipeline` matches pipeline id', done => {
+ it('renders a loading icon when `cancelingPipeline` matches pipeline id', (done) => {
wrapper.setProps({ cancelingPipeline: pipeline.id });
wrapper.vm
.$nextTick()
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index c7d104bbde8..fd73d507919 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -24,7 +24,7 @@ describe('Pipelines Table', () => {
beforeEach(() => {
const { pipelines } = getJSONFixture(jsonFixtureName);
- pipeline = pipelines.find(p => p.user !== null && p.commit !== null);
+ pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
createComponent();
});
diff --git a/spec/frontend/pipelines/shared/links_layer_spec.js b/spec/frontend/pipelines/shared/links_layer_spec.js
new file mode 100644
index 00000000000..9ef5233dbce
--- /dev/null
+++ b/spec/frontend/pipelines/shared/links_layer_spec.js
@@ -0,0 +1,99 @@
+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 e134b81856b..e4782a1dab1 100644
--- a/spec/frontend/pipelines/stage_spec.js
+++ b/spec/frontend/pipelines/stage_spec.js
@@ -1,6 +1,6 @@
+import 'bootstrap/js/dist/dropdown';
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 StageComponent from '~/pipelines/components/pipelines_list/stage.vue';
import eventHub from '~/pipelines/event_hub';
@@ -22,8 +22,11 @@ describe('Pipelines stage component', () => {
updateDropdown: false,
};
+ const isDropdownOpen = () => wrapper.classes('show');
+
const createComponent = (props = {}) => {
wrapper = mount(StageComponent, {
+ attachTo: document.body,
propsData: {
...defaultProps,
...props,
@@ -60,38 +63,29 @@ describe('Pipelines stage component', () => {
createComponent();
});
- it('should render the received data and emit `clickedDropdown` event', () => {
+ it('should render the received data and emit `clickedDropdown` event', async () => {
jest.spyOn(eventHub, '$emit');
wrapper.find('button').trigger('click');
- return waitForPromises().then(() => {
- expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
- stageReply.latest_statuses[0].name,
- );
+ await axios.waitForAll();
+ expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
+ stageReply.latest_statuses[0].name,
+ );
- expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
});
});
- describe('when request fails', () => {
- beforeEach(() => {
- mock.onGet('path.json').reply(500);
- createComponent();
- });
+ 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);
- it('should close the dropdown', () => {
- wrapper.setMethods({
- closeDropdown: jest.fn(),
- isDropdownOpen: jest.fn().mockReturnValue(false),
- });
+ wrapper.find('button').trigger('click');
+ await axios.waitForAll();
- wrapper.find('button').trigger('click');
-
- return waitForPromises().then(() => {
- expect(wrapper.vm.closeDropdown).toHaveBeenCalled();
- });
- });
+ expect(isDropdownOpen()).toBe(false);
});
describe('update endpoint correctly', () => {
@@ -109,47 +103,38 @@ describe('Pipelines stage component', () => {
dropdown_path: 'bar.json',
},
});
+ return axios.waitForAll();
});
- it('should update the stage to request the new endpoint provided', () => {
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.find('button').trigger('click');
- return waitForPromises();
- })
- .then(() => {
- expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
- 'this is the updated content',
- );
- });
+ 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);
createComponent({ type: 'PIPELINES_TABLE' });
});
describe('within pipeline table', () => {
- it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', () => {
+ it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
jest.spyOn(eventHub, '$emit');
wrapper.find('button').trigger('click');
+ await axios.waitForAll();
- return waitForPromises()
- .then(() => {
- wrapper.find('.js-ci-action').trigger('click');
+ wrapper.find('.js-ci-action').trigger('click');
+ await axios.waitForAll();
- return waitForPromises();
- })
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
});
});
});
diff --git a/spec/frontend/pipelines/stores/pipeline_store_spec.js b/spec/frontend/pipelines/stores/pipeline_store_spec.js
index 68d438109b3..2daf7e4b324 100644
--- a/spec/frontend/pipelines/stores/pipeline_store_spec.js
+++ b/spec/frontend/pipelines/stores/pipeline_store_spec.js
@@ -32,14 +32,14 @@ describe('EE Pipeline store', () => {
describe('triggered', () => {
it('adds isExpanding & isLoading keys set to false for each triggered pipeline', () => {
- store.state.pipeline.triggered.forEach(pipeline => {
+ store.state.pipeline.triggered.forEach((pipeline) => {
expect(pipeline.isExpanded).toEqual(false);
expect(pipeline.isLoading).toEqual(false);
});
});
it('parses nested triggered pipelines', () => {
- store.state.pipeline.triggered[1].triggered.forEach(pipeline => {
+ store.state.pipeline.triggered[1].triggered.forEach((pipeline) => {
expect(pipeline.isExpanded).toEqual(false);
expect(pipeline.isLoading).toEqual(false);
});
diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
index 1809f15a6e6..f7ff36c0a46 100644
--- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
@@ -1,10 +1,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 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 { TEST_HOST } from '../../../helpers/test_constants';
-import testAction from '../../../helpers/vuex_action_helper';
import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash.js');
@@ -39,7 +39,7 @@ describe('Actions TestReports Store', () => {
mock.onGet(summaryEndpoint).replyOnce(200, summary, {});
});
- it('sets testReports and shows tests', done => {
+ it('sets testReports and shows tests', (done) => {
testAction(
actions.fetchSummary,
null,
@@ -50,7 +50,7 @@ describe('Actions TestReports Store', () => {
);
});
- it('should create flash on API error', done => {
+ it('should create flash on API error', (done) => {
testAction(
actions.fetchSummary,
null,
@@ -75,7 +75,7 @@ describe('Actions TestReports Store', () => {
.replyOnce(200, testReports.test_suites[0], {});
});
- it('sets test suite and shows tests', done => {
+ it('sets test suite and shows tests', (done) => {
const suite = testReports.test_suites[0];
const index = 0;
@@ -89,7 +89,7 @@ describe('Actions TestReports Store', () => {
);
});
- it('should create flash on API error', done => {
+ it('should create flash on API error', (done) => {
const index = 0;
testAction(
@@ -106,7 +106,7 @@ describe('Actions TestReports Store', () => {
});
describe('when we already have the suite data', () => {
- it('should not fetch suite', done => {
+ it('should not fetch suite', (done) => {
const index = 0;
testReports.test_suites[0].hasFullSuite = true;
@@ -116,7 +116,7 @@ describe('Actions TestReports Store', () => {
});
describe('set selected suite index', () => {
- it('sets selectedSuiteIndex', done => {
+ it('sets selectedSuiteIndex', (done) => {
const selectedSuiteIndex = 0;
testAction(
@@ -131,7 +131,7 @@ describe('Actions TestReports Store', () => {
});
describe('remove selected suite index', () => {
- it('sets selectedSuiteIndex to null', done => {
+ it('sets selectedSuiteIndex to null', (done) => {
testAction(
actions.removeSelectedSuiteIndex,
{},
@@ -144,11 +144,11 @@ describe('Actions TestReports Store', () => {
});
describe('toggles loading', () => {
- it('sets isLoading to true', done => {
+ it('sets isLoading to true', (done) => {
testAction(actions.toggleLoading, {}, state, [{ type: types.TOGGLE_LOADING }], [], done);
});
- it('toggles isLoading to false', done => {
+ it('toggles isLoading to false', (done) => {
testAction(
actions.toggleLoading,
{},
diff --git a/spec/frontend/pipelines/test_reports/stores/getters_spec.js b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
index 8cef499fdb9..7382a6beefa 100644
--- a/spec/frontend/pipelines/test_reports/stores/getters_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
@@ -40,7 +40,7 @@ describe('Getters TestReports Store', () => {
setupState();
const suites = getters.getTestSuites(state);
- const expected = testReports.test_suites.map(x => ({
+ const expected = testReports.test_suites.map((x) => ({
...x,
formattedTime: formattedTime(x.total_time),
}));
@@ -72,7 +72,7 @@ describe('Getters TestReports Store', () => {
const cases = getters.getSuiteTests(state);
const expected = testReports.test_suites[0].test_cases
- .map(x => ({
+ .map((x) => ({
...x,
formattedTime: formattedTime(x.execution_time),
icon: iconForTestStatus(x.status),
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 9e66012818e..bfb8b43778d 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -44,7 +44,7 @@ describe('Test case details', () => {
});
it('renders the test case classname as modal title', () => {
- expect(findModal().attributes('title')).toBe(defaultTestCase.classname);
+ expect(findModal().props('title')).toBe(defaultTestCase.classname);
});
it('renders the test case name', () => {
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 0e00ca670a7..b8fd056610b 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -23,7 +23,7 @@ describe('Test reports suite table', () => {
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 findCaseRowAtIndex = (index) => wrapper.findAll('.js-case-row').at(index);
const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuite, perPage = 20) => {
@@ -73,8 +73,8 @@ describe('Test reports suite table', () => {
TestStatus.SKIPPED,
TestStatus.SUCCESS,
'unknown',
- ])('renders the correct icon for test case with %s status', status => {
- const test = testCases.findIndex(x => x.status === status);
+ ])('renders the correct icon for test case with %s status', (status) => {
+ const test = testCases.findIndex((x) => x.status === status);
const row = findCaseRowAtIndex(test);
expect(findIconForRow(row, status).exists()).toBe(true);
diff --git a/spec/frontend/pipelines/test_reports/test_summary_spec.js b/spec/frontend/pipelines/test_reports/test_summary_spec.js
index dc5af7b160c..df404d87c99 100644
--- a/spec/frontend/pipelines/test_reports/test_summary_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_summary_spec.js
@@ -22,7 +22,7 @@ describe('Test reports summary', () => {
showBack: false,
};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = mount(Summary, {
propsData: {
...defaultProps,
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 375325c0c6a..371ba5a4f9b 100644
--- a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
+++ b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
@@ -26,7 +26,7 @@ describe('Pipeline Trigger Author Token', () => {
},
};
- const createComponent = data => {
+ const createComponent = (data) => {
wrapper = shallowMount(PipelineTriggerAuthorToken, {
propsData: {
...defaultProps,
diff --git a/spec/frontend/pipelines/unwrapping_utils_spec.js b/spec/frontend/pipelines/unwrapping_utils_spec.js
index 3533599611f..cd16ed7262e 100644
--- a/spec/frontend/pipelines/unwrapping_utils_spec.js
+++ b/spec/frontend/pipelines/unwrapping_utils_spec.js
@@ -1,5 +1,4 @@
import {
- unwrapArrayOfJobs,
unwrapGroups,
unwrapNodesWithName,
unwrapStagesWithNeeds,
@@ -89,35 +88,12 @@ const completeMock = [
{
...basicStageInfo,
groups: {
- nodes: groupsArray.map(group => ({ ...group, jobs: { nodes: jobArrayWithNeeds } })),
+ nodes: groupsArray.map((group) => ({ ...group, jobs: { nodes: jobArrayWithNeeds } })),
},
},
];
describe('Shared pipeline unwrapping utils', () => {
- describe('unwrapArrayOfJobs', () => {
- it('returns an empty array if the input is an empty undefined', () => {
- expect(unwrapArrayOfJobs(undefined)).toEqual([]);
- });
-
- it('returns an empty array if the input is an empty array', () => {
- expect(unwrapArrayOfJobs([])).toEqual([]);
- });
-
- it('returns a flatten array of each job with their data and stage name', () => {
- expect(
- unwrapArrayOfJobs([
- { name: 'build', groups: [{ name: 'job_a_1' }, { name: 'job_a_2' }] },
- { name: 'test', groups: [{ name: 'job_b' }] },
- ]),
- ).toMatchObject([
- { category: 'build', name: 'job_a_1' },
- { category: 'build', name: 'job_a_2' },
- { category: 'test', name: 'job_b' },
- ]);
- });
- });
-
describe('unwrapGroups', () => {
it('takes stages without nodes and returns the unwrapped groups', () => {
expect(unwrapGroups(stagesAndGroups)[0].groups).toEqual(groupsArray);
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 7834456f7c4..63e27473979 100644
--- a/spec/frontend/profile/account/components/delete_account_modal_spec.js
+++ b/spec/frontend/profile/account/components/delete_account_modal_spec.js
@@ -56,7 +56,7 @@ describe('DeleteAccountModal component', () => {
const findModal = () => wrapper.find(GlModalStub);
describe('with password confirmation', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createWrapper({
propsData: {
confirmWithPassword: true,
@@ -65,12 +65,10 @@ describe('DeleteAccountModal component', () => {
vm.isOpen = true;
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ Vue.nextTick().then(done).catch(done.fail);
});
- it('does not accept empty password', done => {
+ it('does not accept empty password', (done) => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = '';
@@ -88,7 +86,7 @@ describe('DeleteAccountModal component', () => {
.catch(done.fail);
});
- it('submits form with password', done => {
+ it('submits form with password', (done) => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'anything';
@@ -108,7 +106,7 @@ describe('DeleteAccountModal component', () => {
});
describe('with username confirmation', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createWrapper({
propsData: {
confirmWithPassword: false,
@@ -117,12 +115,10 @@ describe('DeleteAccountModal component', () => {
vm.isOpen = true;
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ Vue.nextTick().then(done).catch(done.fail);
});
- it('does not accept wrong username', done => {
+ it('does not accept wrong username', (done) => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'this is wrong';
@@ -140,7 +136,7 @@ describe('DeleteAccountModal component', () => {
.catch(done.fail);
});
- it('submits form with correct username', done => {
+ it('submits form with correct username', (done) => {
const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = username;
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index 45e5e0f885f..91c3c81ab30 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -84,7 +84,7 @@ describe('UpdateUsername component', () => {
it('confirmation modal contains proper header and body', async () => {
const { modal } = findElements();
- expect(modal.attributes('title')).toBe('Change username?');
+ expect(modal.props('title')).toBe('Change username?');
expect(modal.text()).toContain(
`You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`,
);
diff --git a/spec/frontend/project_find_file_spec.js b/spec/frontend/project_find_file_spec.js
index 6a50f68a4e9..1af97dbca0a 100644
--- a/spec/frontend/project_find_file_spec.js
+++ b/spec/frontend/project_find_file_spec.js
@@ -7,7 +7,7 @@ import axios from '~/lib/utils/axios_utils';
jest.mock('~/lib/dompurify', () => ({
addHook: jest.fn(),
- sanitize: jest.fn(val => val),
+ sanitize: jest.fn((val) => val),
}));
const BLOB_URL_TEMPLATE = `${TEST_HOST}/namespace/project/blob/master`;
@@ -39,7 +39,7 @@ describe('ProjectFindFile', () => {
element
.find('.tree-table tr')
.toArray()
- .map(el => ({
+ .map((el) => ({
text: el.textContent,
href: el.querySelector('a').href,
}));
@@ -53,12 +53,15 @@ describe('ProjectFindFile', () => {
{ path: 'folde?rC/fil#F.txt', escaped: 'folde%3FrC/fil%23F.txt' },
];
- beforeEach(done => {
+ beforeEach((done) => {
// Create a mock adapter for stubbing axios API requests
mock = new MockAdapter(axios);
element = $(TEMPLATE);
- mock.onGet(FILE_FIND_URL).replyOnce(200, files.map(x => x.path));
+ mock.onGet(FILE_FIND_URL).replyOnce(
+ 200,
+ files.map((x) => x.path),
+ );
getProjectFindFileInstance(); // This triggers a load / axios call + subsequent render in the constructor
setImmediate(done);
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
new file mode 100644
index 00000000000..9fa7d658405
--- /dev/null
+++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
@@ -0,0 +1,166 @@
+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);
+
+describe('BranchesDropdown', () => {
+ let wrapper;
+ let store;
+ const spyFetchBranches = jest.fn();
+
+ const createComponent = (term, state = { isFetching: false }) => {
+ store = new Vuex.Store({
+ getters: {
+ joinedBranches: () => ['_master_', '_branch_1_', '_branch_2_'],
+ },
+ actions: {
+ fetchBranches: spyFetchBranches,
+ },
+ state,
+ });
+
+ wrapper = extendedWrapper(
+ shallowMount(BranchesDropdown, {
+ store,
+ propsData: {
+ value: term,
+ },
+ }),
+ );
+ };
+
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
+ const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
+ const findNoResults = () => wrapper.findByTestId('empty-result-message');
+ const findLoading = () => wrapper.findByTestId('dropdown-text-loading-icon');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ spyFetchBranches.mockReset();
+ });
+
+ describe('On mount', () => {
+ beforeEach(() => {
+ createComponent('');
+ });
+
+ it('invokes fetchBranches', () => {
+ expect(spyFetchBranches).toHaveBeenCalled();
+ });
+ });
+
+ describe('Loading states', () => {
+ it('shows loading icon while fetching', () => {
+ createComponent('', { isFetching: true });
+
+ expect(findLoading().isVisible()).toBe(true);
+ });
+
+ it('does not show loading icon', () => {
+ createComponent('');
+
+ expect(findLoading().isVisible()).toBe(false);
+ });
+ });
+
+ describe('No branches found', () => {
+ beforeEach(() => {
+ createComponent('_non_existent_branch_');
+ });
+
+ it('renders empty results message', () => {
+ expect(findNoResults().text()).toBe('No matching results');
+ });
+
+ it('shows GlSearchBoxByType with default attributes', () => {
+ expect(findSearchBoxByType().exists()).toBe(true);
+ expect(findSearchBoxByType().vm.$attrs).toMatchObject({
+ placeholder: 'Search branches',
+ debounce: 250,
+ });
+ });
+ });
+
+ describe('Search term is empty', () => {
+ beforeEach(() => {
+ createComponent('');
+ });
+
+ it('renders all branches when search term is empty', () => {
+ expect(findAllDropdownItems()).toHaveLength(3);
+ expect(findDropdownItemByIndex(0).text()).toBe('_master_');
+ expect(findDropdownItemByIndex(1).text()).toBe('_branch_1_');
+ expect(findDropdownItemByIndex(2).text()).toBe('_branch_2_');
+ });
+
+ it('should not be selected on the inactive branch', () => {
+ expect(wrapper.vm.isSelected('_master_')).toBe(false);
+ });
+ });
+
+ describe('When searching', () => {
+ beforeEach(() => {
+ createComponent('');
+ });
+
+ it('invokes fetchBranches', async () => {
+ const spy = jest.spyOn(wrapper.vm, 'fetchBranches');
+
+ findSearchBoxByType().vm.$emit('input', '_anything_');
+
+ await wrapper.vm.$nextTick();
+
+ expect(spy).toHaveBeenCalledWith('_anything_');
+ expect(wrapper.vm.searchTerm).toBe('_anything_');
+ });
+ });
+
+ describe('Branches found', () => {
+ beforeEach(() => {
+ createComponent('_branch_1_', { branch: '_branch_1_' });
+ });
+
+ it('renders only the branch searched for', () => {
+ expect(findAllDropdownItems()).toHaveLength(1);
+ expect(findDropdownItemByIndex(0).text()).toBe('_branch_1_');
+ });
+
+ it('should not display empty results message', () => {
+ expect(findNoResults().exists()).toBe(false);
+ });
+
+ it('should signify this branch is selected', () => {
+ expect(wrapper.vm.isSelected('_branch_1_')).toBe(true);
+ });
+
+ it('should signify the branch is not selected', () => {
+ expect(wrapper.vm.isSelected('_not_selected_branch_')).toBe(false);
+ });
+
+ describe('Custom events', () => {
+ it('should emit selectBranch if an branch is clicked', () => {
+ findDropdownItemByIndex(0).vm.$emit('click');
+
+ expect(wrapper.emitted('selectBranch')).toEqual([['_branch_1_']]);
+ expect(wrapper.vm.searchTerm).toBe('_branch_1_');
+ });
+ });
+ });
+
+ describe('Case insensitive for search term', () => {
+ beforeEach(() => {
+ createComponent('_BrAnCh_1_');
+ });
+
+ it('renders only the branch searched for', () => {
+ expect(findAllDropdownItems()).toHaveLength(1);
+ expect(findDropdownItemByIndex(0).text()).toBe('_branch_1_');
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
new file mode 100644
index 00000000000..1c37b82fed3
--- /dev/null
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -0,0 +1,155 @@
+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 axios from '~/lib/utils/axios_utils';
+import eventHub from '~/projects/commit/event_hub';
+import CommitFormModal from '~/projects/commit/components/form_modal.vue';
+import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue';
+import createStore from '~/projects/commit/store';
+import mockData from '../mock_data';
+
+describe('CommitFormModal', () => {
+ let wrapper;
+ let store;
+ let axiosMock;
+
+ const createComponent = (method, state = {}, provide = {}) => {
+ store = createStore({ ...mockData.mockModal, ...state });
+ wrapper = extendedWrapper(
+ method(CommitFormModal, {
+ provide,
+ propsData: { ...mockData.modalPropsData },
+ store,
+ attrs: {
+ static: true,
+ visible: true,
+ },
+ }),
+ );
+ };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findStartBranch = () => wrapper.find('#start_branch');
+ const findDropdown = () => wrapper.findComponent(BranchesDropdown);
+ const findForm = () => findModal().findComponent(GlForm);
+ const findCheckBox = () => findForm().findComponent(GlFormCheckbox);
+ const findPrependedText = () => wrapper.findByTestId('prepended-text');
+ const findAppendedText = () => wrapper.findByTestId('appended-text');
+ const getByText = (text, options) =>
+ createWrapper(within(findModal().element).getByText(text, options));
+
+ beforeEach(() => {
+ axiosMock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ axiosMock.restore();
+ });
+
+ describe('Basic interactions', () => {
+ it('Listens for opening of modal on mount', () => {
+ jest.spyOn(eventHub, '$on');
+
+ createComponent(shallowMount);
+
+ expect(eventHub.$on).toHaveBeenCalledWith(mockData.modalPropsData.openModal, wrapper.vm.show);
+ });
+
+ it('Shows modal', () => {
+ createComponent(shallowMount);
+ const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit');
+
+ wrapper.vm.show();
+
+ expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', mockData.modalPropsData.modalId);
+ });
+
+ it('Clears the modal state once modal is hidden', () => {
+ createComponent(shallowMount);
+ jest.spyOn(store, 'dispatch').mockImplementation();
+ wrapper.vm.checked = false;
+
+ findModal().vm.$emit('hidden');
+
+ expect(store.dispatch).toHaveBeenCalledWith('clearModal');
+ expect(store.dispatch).toHaveBeenCalledWith('setSelectedBranch', '');
+ expect(wrapper.vm.checked).toBe(true);
+ });
+
+ it('Shows the checkbox for new merge request', () => {
+ createComponent(shallowMount);
+
+ expect(findCheckBox().exists()).toBe(true);
+ });
+
+ it('Shows the prepended text', () => {
+ createComponent(shallowMount, {}, { prependedText: '_prepended_text_' });
+
+ expect(findPrependedText().exists()).toBe(true);
+ expect(findPrependedText().find(GlSprintf).attributes('message')).toBe('_prepended_text_');
+ });
+
+ it('Does not show prepended text', () => {
+ createComponent(shallowMount);
+
+ expect(findPrependedText().exists()).toBe(false);
+ });
+
+ it('Does not show extra message text', () => {
+ createComponent(shallowMount);
+
+ expect(findModal().find('[data-testid="appended-text"]').exists()).toBe(false);
+ });
+
+ it('Does not show the checkbox for new merge request', () => {
+ createComponent(shallowMount, { pushCode: false });
+
+ expect(findCheckBox().exists()).toBe(false);
+ });
+
+ it('Shows the branch in fork message', () => {
+ createComponent(shallowMount, { pushCode: false });
+
+ expect(findAppendedText().exists()).toBe(true);
+ expect(findAppendedText().find(GlSprintf).attributes('message')).toContain(
+ mockData.modalPropsData.i18n.branchInFork,
+ );
+ });
+
+ it('Shows the branch collaboration message', () => {
+ createComponent(shallowMount, { pushCode: false, branchCollaboration: true });
+
+ expect(findAppendedText().exists()).toBe(true);
+ expect(findAppendedText().find(GlSprintf).attributes('message')).toContain(
+ mockData.modalPropsData.i18n.existingBranch,
+ );
+ });
+ });
+
+ describe('Taking action on the form', () => {
+ beforeEach(() => {
+ createComponent(mount);
+ });
+
+ it('Action primary button dispatches submit action', () => {
+ const submitSpy = jest.spyOn(findForm().element, 'submit');
+
+ getByText(mockData.modalPropsData.i18n.actionPrimaryText).trigger('click');
+
+ expect(submitSpy).toHaveBeenCalled();
+
+ submitSpy.mockRestore();
+ });
+
+ it('Changes the start_branch input value', async () => {
+ findDropdown().vm.$emit('selectBranch', '_changed_branch_value_');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findStartBranch().attributes('value')).toBe('_changed_branch_value_');
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/components/form_trigger_spec.js b/spec/frontend/projects/commit/components/form_trigger_spec.js
new file mode 100644
index 00000000000..ca51419d6a5
--- /dev/null
+++ b/spec/frontend/projects/commit/components/form_trigger_spec.js
@@ -0,0 +1,44 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import FormTrigger from '~/projects/commit/components/form_trigger.vue';
+import eventHub from '~/projects/commit/event_hub';
+
+const displayText = '_display_text_';
+
+const createComponent = () => {
+ return shallowMount(FormTrigger, {
+ provide: { displayText },
+ propsData: { openModal: '_open_modal_' },
+ });
+};
+
+describe('FormTrigger', () => {
+ let wrapper;
+ let spy;
+
+ beforeEach(() => {
+ spy = jest.spyOn(eventHub, '$emit');
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findLink = () => wrapper.find(GlLink);
+
+ describe('displayText', () => {
+ it('includes the correct displayText for the link', () => {
+ expect(findLink().text()).toBe(displayText);
+ });
+ });
+
+ describe('clicking the link', () => {
+ it('emits openModal', () => {
+ findLink().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith('_open_modal_');
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/mock_data.js b/spec/frontend/projects/commit/mock_data.js
new file mode 100644
index 00000000000..2b3b5a14c98
--- /dev/null
+++ b/spec/frontend/projects/commit/mock_data.js
@@ -0,0 +1,27 @@
+import { I18N_MODAL } from '~/projects/commit/constants';
+
+export default {
+ mockModal: {
+ modalTitle: '_modal_title_',
+ endpoint: '_endpoint_',
+ branch: '_branch_',
+ pushCode: true,
+ defaultBranch: '_branch_',
+ existingBranch: '_existing_branch',
+ branchesEndpoint: '_branches_endpoint_',
+ },
+ modalPropsData: {
+ i18n: {
+ branchLabel: '_branch_label_',
+ actionPrimaryText: '_action_primary_text_',
+ startMergeRequest: '_start_merge_request_',
+ existingBranch: I18N_MODAL.existingBranch,
+ branchInFork: '_new_branch_in_fork_message_',
+ newMergeRequest: '_new merge request_',
+ actionCancelText: '_action_cancel_text_',
+ },
+ modalId: '_modal_id_',
+ openModal: '_open_modal_',
+ },
+ mockBranches: ['_branch_1', '_abc_', '_master_'],
+};
diff --git a/spec/frontend/projects/commit/store/actions_spec.js b/spec/frontend/projects/commit/store/actions_spec.js
new file mode 100644
index 00000000000..ec528d4ee88
--- /dev/null
+++ b/spec/frontend/projects/commit/store/actions_spec.js
@@ -0,0 +1,111 @@
+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 * as actions from '~/projects/commit/store/actions';
+import * as types from '~/projects/commit/store/mutation_types';
+import mockData from '../mock_data';
+import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants';
+
+jest.mock('~/flash.js');
+
+describe('Commit form modal store actions', () => {
+ let axiosMock;
+ let state;
+
+ beforeEach(() => {
+ axiosMock = new MockAdapter(axios);
+ state = getInitialState();
+ });
+
+ afterEach(() => {
+ axiosMock.restore();
+ });
+
+ describe('clearModal', () => {
+ it('commits CLEAR_MODAL mutation', () => {
+ testAction(actions.clearModal, {}, {}, [
+ {
+ type: types.CLEAR_MODAL,
+ },
+ ]);
+ });
+ });
+
+ describe('requestBranches', () => {
+ it('commits REQUEST_BRANCHES mutation', () => {
+ testAction(actions.requestBranches, {}, {}, [
+ {
+ type: types.REQUEST_BRANCHES,
+ },
+ ]);
+ });
+ });
+
+ describe('fetchBranches', () => {
+ it('dispatch correct actions on fetchBranches', (done) => {
+ jest
+ .spyOn(axios, 'get')
+ .mockImplementation(() => Promise.resolve({ data: mockData.mockBranches }));
+
+ testAction(
+ actions.fetchBranches,
+ {},
+ state,
+ [
+ {
+ type: types.RECEIVE_BRANCHES_SUCCESS,
+ payload: mockData.mockBranches,
+ },
+ ],
+ [{ type: 'requestBranches' }],
+ () => {
+ done();
+ },
+ );
+ });
+
+ it('should show flash error and set error in state on fetchBranches failure', (done) => {
+ jest.spyOn(axios, 'get').mockRejectedValue();
+
+ testAction(actions.fetchBranches, {}, state, [], [{ type: 'requestBranches' }], () => {
+ expect(createFlash).toHaveBeenCalledWith({ message: PROJECT_BRANCHES_ERROR });
+ done();
+ });
+ });
+ });
+
+ describe('setBranch', () => {
+ it('commits SET_BRANCH mutation', () => {
+ testAction(
+ actions.setBranch,
+ {},
+ {},
+ [
+ {
+ type: types.SET_BRANCH,
+ payload: {},
+ },
+ ],
+ [
+ {
+ type: 'setSelectedBranch',
+ payload: {},
+ },
+ ],
+ );
+ });
+ });
+
+ describe('setSelectedBranch', () => {
+ it('commits SET_SELECTED_BRANCH mutation', () => {
+ testAction(actions.setSelectedBranch, {}, {}, [
+ {
+ type: types.SET_SELECTED_BRANCH,
+ payload: {},
+ },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/store/getters_spec.js b/spec/frontend/projects/commit/store/getters_spec.js
new file mode 100644
index 00000000000..bd0cb356854
--- /dev/null
+++ b/spec/frontend/projects/commit/store/getters_spec.js
@@ -0,0 +1,21 @@
+import * as getters from '~/projects/commit/store/getters';
+import mockData from '../mock_data';
+
+describe('Commit form modal getters', () => {
+ describe('joinedBranches', () => {
+ it('should join fetched branches with variable branches', () => {
+ const state = {
+ branches: mockData.mockBranches,
+ };
+
+ expect(getters.joinedBranches(state)).toEqual(mockData.mockBranches.sort());
+ });
+
+ it('should provide a uniq list of branches', () => {
+ const branches = ['_branch_', '_branch_', '_different_branch'];
+ const state = { branches };
+
+ expect(getters.joinedBranches(state)).toEqual(branches.slice(1));
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/store/mutations_spec.js b/spec/frontend/projects/commit/store/mutations_spec.js
new file mode 100644
index 00000000000..59ab3d9a74a
--- /dev/null
+++ b/spec/frontend/projects/commit/store/mutations_spec.js
@@ -0,0 +1,57 @@
+import mutations from '~/projects/commit/store/mutations';
+import * as types from '~/projects/commit/store/mutation_types';
+
+describe('Commit form modal mutations', () => {
+ let stateCopy;
+
+ describe('REQUEST_BRANCHES', () => {
+ it('should set isFetching to true', () => {
+ stateCopy = { isFetching: false };
+
+ mutations[types.REQUEST_BRANCHES](stateCopy);
+
+ expect(stateCopy.isFetching).toBe(true);
+ });
+ });
+
+ describe('RECEIVE_BRANCHES_SUCCESS', () => {
+ it('should set branches', () => {
+ stateCopy = { branch: '_existing_branch_', isFetching: true };
+
+ mutations[types.RECEIVE_BRANCHES_SUCCESS](stateCopy, ['_branch_1_', '_branch_2_']);
+
+ expect(stateCopy.branches).toEqual(['_existing_branch_', '_branch_1_', '_branch_2_']);
+ expect(stateCopy.isFetching).toEqual(false);
+ });
+ });
+
+ describe('CLEAR_MODAL', () => {
+ it('should clear modal state ', () => {
+ stateCopy = { branch: '_master_', defaultBranch: '_default_branch_' };
+
+ mutations[types.CLEAR_MODAL](stateCopy);
+
+ expect(stateCopy.branch).toEqual('_default_branch_');
+ });
+ });
+
+ describe('SET_BRANCH', () => {
+ it('should set branch', () => {
+ stateCopy = { branch: '_master_' };
+
+ mutations[types.SET_BRANCH](stateCopy, '_changed_branch_');
+
+ expect(stateCopy.branch).toBe('_changed_branch_');
+ });
+ });
+
+ describe('SET_SELECTED_BRANCH', () => {
+ it('should set selectedBranch', () => {
+ stateCopy = { selectedBranch: '_master_' };
+
+ mutations[types.SET_SELECTED_BRANCH](stateCopy, '_changed_branch_');
+
+ expect(stateCopy.selectedBranch).toBe('_changed_branch_');
+ });
+ });
+});
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index 68c285a4097..63920ddfd72 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -139,11 +139,7 @@ describe('Author Select', () => {
});
it('has a "Any Author" as the first list item', () => {
- expect(
- findDropdownItems()
- .at(0)
- .text(),
- ).toBe('Any Author');
+ expect(findDropdownItems().at(0).text()).toBe('Any Author');
});
it('displays the project authors', () => {
@@ -163,21 +159,13 @@ describe('Author Select', () => {
wrapper.setData({ currentAuthor });
return wrapper.vm.$nextTick().then(() => {
- expect(
- findDropdownItems()
- .at(1)
- .props(),
- ).toEqual(expect.objectContaining(result));
+ expect(findDropdownItems().at(1).props()).toEqual(expect.objectContaining(result));
});
});
it("display the author's name", () => {
return wrapper.vm.$nextTick().then(() => {
- expect(
- findDropdownItems()
- .at(1)
- .text(),
- ).toBe(currentAuthor);
+ expect(findDropdownItems().at(1).text()).toBe(currentAuthor);
});
});
@@ -186,9 +174,7 @@ describe('Author Select', () => {
const spy = jest.spyOn(urlUtility, 'redirectTo');
spy.mockImplementation(() => 'mock');
- findDropdownItems()
- .at(1)
- .vm.$emit('click');
+ findDropdownItems().at(1).vm.$emit('click');
expect(spy).toHaveBeenCalledWith(redirectToUrl);
});
@@ -198,9 +184,7 @@ describe('Author Select', () => {
const spy = jest.spyOn(urlUtility, 'redirectTo');
spy.mockImplementation();
- findDropdownItems()
- .at(0)
- .vm.$emit('click');
+ findDropdownItems().at(0).vm.$emit('click');
expect(spy).toHaveBeenCalledWith(redirectToUrl);
});
});
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 4eb5060cb0a..0b9f095a700 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
@@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
<gl-modal-stub
actioncancel="[object Object]"
actionprimary="[object Object]"
+ dismisslabel="Close"
footer-class="gl-bg-gray-10 gl-p-5"
modalclass=""
modalid="fakeUniqueId"
diff --git a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
index 4630415f61c..dd54db7dc0a 100644
--- a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
@@ -29,24 +29,12 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
Delete project
</gl-button-stub>
- <b-modal-stub
- canceltitle="Cancel"
- cancelvariant="secondary"
- footerclass="gl-bg-gray-10 gl-p-5"
- headerclosecontent="&times;"
- headercloselabel="Close"
- id="delete-project-modal-2"
- ignoreenforcefocusselector=""
- lazy="true"
- modalclass="gl-modal,"
- oktitle="OK"
- okvariant="danger"
- size="sm"
- title=""
- titleclass="gl-text-red-500"
- titletag="h4"
+ <div
+ footer-class="gl-bg-gray-10 gl-p-5"
+ ok-variant="danger"
+ title-class="gl-text-red-500"
>
-
+ Delete project. Are you ABSOLUTELY SURE?
<div>
<p
@@ -70,49 +58,6 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
/>
</div>
-
- <template />
-
- <template>
- Delete project. Are you ABSOLUTELY SURE?
- </template>
-
- <template />
-
- <template />
-
- <template />
-
- <template>
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-modal-action-cancel"
- icon=""
- size="medium"
- variant="default"
- >
-
- Cancel, keep project
-
- </gl-button-stub>
-
- <!---->
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-modal-action-primary"
- disabled="true"
- icon=""
- size="medium"
- variant="danger"
- >
-
- Yes, delete project
-
- </gl-button-stub>
- </template>
- </b-modal-stub>
+ </div>
</form>
`;
diff --git a/spec/frontend/projects/components/shared/delete_button_spec.js b/spec/frontend/projects/components/shared/delete_button_spec.js
index a6394a50011..cf7e41a2df2 100644
--- a/spec/frontend/projects/components/shared/delete_button_spec.js
+++ b/spec/frontend/projects/components/shared/delete_button_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { stubComponent } from 'helpers/stub_component';
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' }));
@@ -17,12 +18,19 @@ describe('Project remove modal', () => {
formPath: 'some/path',
};
- const createComponent = (data = {}) => {
+ const createComponent = (data = {}, stubs = {}) => {
wrapper = shallowMount(SharedDeleteButton, {
propsData: defaultProps,
data: () => data,
stubs: {
- GlModal,
+ GlModal: stubComponent(GlModal, {
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <slot></slot>
+ </div>`,
+ }),
+ ...stubs,
},
});
};
@@ -52,7 +60,7 @@ describe('Project remove modal', () => {
describe('when the user input does not match the confirmPhrase', () => {
beforeEach(() => {
- createComponent({ userInput: 'bar' });
+ createComponent({ userInput: 'bar' }, { GlModal });
});
it('the confirm button is disabled', () => {
@@ -62,7 +70,7 @@ describe('Project remove modal', () => {
describe('when the user input matches the confirmPhrase', () => {
beforeEach(() => {
- createComponent({ userInput: defaultProps.confirmPhrase });
+ createComponent({ userInput: defaultProps.confirmPhrase }, { GlModal });
});
it('the confirm button is not disabled', () => {
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 a1e1e4554e2..9a5f200f5a9 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
@@ -7,7 +7,7 @@ import LegacyContainer from '~/projects/experiment_new_project_creation/componen
describe('Experimental new project creation app', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(App, { propsData });
};
@@ -53,6 +53,28 @@ describe('Experimental new project creation app', () => {
});
});
+ describe('display custom new project guideline text', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ });
+
+ it('does not render new project guideline if undefined', () => {
+ createComponent();
+ expect(wrapper.find('div#new-project-guideline').exists()).toBe(false);
+ });
+
+ it('render new project guideline if defined', () => {
+ const guidelineSelector = 'div#new-project-guideline';
+
+ createComponent({
+ newProjectGuidelines: '<h4>Internal Guidelines</h4><p>lorem ipsum</p>',
+ });
+ expect(wrapper.find(guidelineSelector).exists()).toBe(true);
+ expect(wrapper.find(guidelineSelector).html()).toContain('<h4>Internal Guidelines</h4>');
+ expect(wrapper.find(guidelineSelector).html()).toContain('<p>lorem ipsum</p>');
+ });
+ });
+
it('renders relevant container when hash changes', () => {
createComponent();
expect(wrapper.find(WelcomePage).exists()).toBe(true);
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/legacy_container_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/legacy_container_spec.js
index 42a7aa6bc88..6fc36d6362c 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/legacy_container_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/legacy_container_spec.js
@@ -6,7 +6,7 @@ describe('Legacy container component', () => {
let wrapper;
let dummy;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(LegacyContainer, { propsData });
};
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
index cf23ba281f9..d6764f75262 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
@@ -6,7 +6,7 @@ describe('Welcome page', () => {
let wrapper;
let trackingSpy;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(WelcomePage, { propsData });
};
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
new file mode 100644
index 00000000000..fc51825f15b
--- /dev/null
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
@@ -0,0 +1,27 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CiCdAnalyticsAreaChart matches the snapshot 1`] = `
+<div
+ class="gl-mt-3"
+>
+ <p>
+ Some title
+ </p>
+
+ <div>
+ <glareachart-stub
+ annotations=""
+ data="[object Object],[object Object]"
+ height="300"
+ legendaveragetext="Avg"
+ legendcurrenttext="Current"
+ legendlayout="inline"
+ legendmaxtext="Max"
+ legendmintext="Min"
+ option="[object Object]"
+ thresholds=""
+ width="0"
+ />
+ </div>
+</div>
+`;
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap
deleted file mode 100644
index d68e009f46e..00000000000
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap
+++ /dev/null
@@ -1,27 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PipelinesAreaChart matches the snapshot 1`] = `
-<div
- class="gl-mt-3"
->
- <p>
- Some title
- </p>
-
- <div>
- <glareachart-stub
- annotations=""
- data="[object Object],[object Object]"
- height="300"
- legendaveragetext="Avg"
- legendcurrenttext="Current"
- legendlayout="inline"
- legendmaxtext="Max"
- legendmintext="Min"
- option="[object Object]"
- thresholds=""
- width="0"
- />
- </div>
-</div>
-`;
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
index c7e760486c0..be3716c24e6 100644
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
@@ -38,14 +38,5 @@ exports[`StatisticsList displays the counts data with labels 1`] = `
50.00%
</strong>
</li>
- <li>
- <span>
- Total duration:
- </span>
-
- <strong>
- 00:01:56
- </strong>
- </li>
</ul>
`;
diff --git a/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js b/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js
deleted file mode 100644
index c03b571eb26..00000000000
--- a/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import Component from '~/projects/pipelines/charts/components/app_legacy.vue';
-import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
-import PipelinesAreaChart from '~/projects/pipelines/charts/components/pipelines_area_chart.vue';
-import {
- counts,
- timesChartData,
- areaChartData as lastWeekChartData,
- areaChartData as lastMonthChartData,
- lastYearChartData,
-} from '../mock_data';
-
-describe('ProjectsPipelinesChartsApp', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = shallowMount(Component, {
- propsData: {
- counts,
- timesChartData,
- lastWeekChartData,
- lastMonthChartData,
- lastYearChartData,
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('overall statistics', () => {
- it('displays the statistics list', () => {
- const list = wrapper.find(StatisticsList);
-
- expect(list.exists()).toBeTruthy();
- expect(list.props('counts')).toBe(counts);
- });
-
- it('displays the commit duration chart', () => {
- const chart = wrapper.find(GlColumnChart);
-
- expect(chart.exists()).toBeTruthy();
- expect(chart.props('yAxisTitle')).toBe('Minutes');
- expect(chart.props('xAxisTitle')).toBe('Commit');
- expect(chart.props('bars')).toBe(wrapper.vm.timesChartTransformedData);
- expect(chart.props('option')).toBe(wrapper.vm.$options.timesChartOptions);
- });
- });
-
- describe('pipelines charts', () => {
- it('displays 3 area charts', () => {
- expect(wrapper.findAll(PipelinesAreaChart).length).toBe(3);
- });
-
- describe('displays individual correctly', () => {
- it('renders with the correct data', () => {
- const charts = wrapper.findAll(PipelinesAreaChart);
-
- 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);
- }
- });
- });
- });
-});
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index f8737dda5f6..44329944097 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -1,10 +1,10 @@
+import { merge } from 'lodash';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
-import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import { GlTabs, GlTab } from '@gitlab/ui';
+import createMockApollo from 'helpers/mock_apollo_helper';
import Component from '~/projects/pipelines/charts/components/app.vue';
-import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
-import PipelinesAreaChart from '~/projects/pipelines/charts/components/pipelines_area_chart.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';
@@ -13,6 +13,8 @@ const projectPath = 'gitlab-org/gitlab';
const localVue = createLocalVue();
localVue.use(VueApollo);
+const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
+
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
@@ -25,21 +27,29 @@ describe('ProjectsPipelinesChartsApp', () => {
return createMockApollo(requestHandlers);
}
- function createComponent(options = {}) {
- const { fakeApollo } = options;
-
- return shallowMount(Component, {
- provide: {
- projectPath,
- },
- localVue,
- apolloProvider: fakeApollo,
- });
+ function createComponent(mountOptions = {}) {
+ wrapper = shallowMount(
+ Component,
+ merge(
+ {},
+ {
+ provide: {
+ projectPath,
+ shouldRenderDeploymentFrequencyCharts: false,
+ },
+ localVue,
+ apolloProvider: createMockApolloProvider(),
+ stubs: {
+ DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
+ },
+ },
+ mountOptions,
+ ),
+ );
}
beforeEach(() => {
- const fakeApollo = createMockApolloProvider();
- wrapper = createComponent({ fakeApollo });
+ createComponent();
});
afterEach(() => {
@@ -47,50 +57,74 @@ describe('ProjectsPipelinesChartsApp', () => {
wrapper = null;
});
- describe('overall statistics', () => {
- it('displays the statistics list', () => {
- const list = wrapper.find(StatisticsList);
-
- expect(list.exists()).toBe(true);
- expect(list.props('counts')).toMatchObject({
- failed: 1,
- success: 23,
- total: 34,
- successRatio: 95.83333333333334,
- totalDuration: 2471,
- });
- });
+ describe('pipelines charts', () => {
+ it('displays the pipeline charts', () => {
+ const chart = wrapper.find(PipelineCharts);
+ const analytics = mockPipelineStatistics.data.project.pipelineAnalytics;
- it('displays the commit duration chart', () => {
- const chart = wrapper.find(GlColumnChart);
+ const {
+ totalPipelines: total,
+ successfulPipelines: success,
+ failedPipelines: failed,
+ } = mockPipelineCount.data.project;
expect(chart.exists()).toBe(true);
- expect(chart.props('yAxisTitle')).toBe('Minutes');
- expect(chart.props('xAxisTitle')).toBe('Commit');
- expect(chart.props('bars')).toBe(wrapper.vm.timesChartTransformedData);
- expect(chart.props('option')).toBe(wrapper.vm.$options.timesChartOptions);
+ 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,
+ },
+ });
});
});
- describe('pipelines charts', () => {
- it('displays 3 area charts', () => {
- expect(wrapper.findAll(PipelinesAreaChart)).toHaveLength(3);
+ const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
+ const findGlTabs = () => wrapper.find(GlTabs);
+ const findAllGlTab = () => wrapper.findAll(GlTab);
+ const findGlTabAt = (i) => findAllGlTab().at(i);
+
+ describe('when shouldRenderDeploymentFrequencyCharts is true', () => {
+ beforeEach(() => {
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
});
- describe('displays individual correctly', () => {
- it('renders with the correct data', () => {
- const charts = wrapper.findAll(PipelinesAreaChart);
+ it('renders the deployment frequency charts in a tab', () => {
+ expect(findGlTabs().exists()).toBe(true);
+ expect(findGlTabAt(0).attributes('title')).toBe('Pipelines');
+ expect(findGlTabAt(1).attributes('title')).toBe('Deployments');
+ expect(findDeploymentFrequencyCharts().exists()).toBe(true);
+ });
+ });
- for (let i = 0; i < charts.length; i += 1) {
- const chart = charts.at(i);
+ describe('when shouldRenderDeploymentFrequencyCharts is false', () => {
+ beforeEach(() => {
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: false } });
+ });
- expect(chart.exists()).toBe(true);
- // TODO: Refactor this to use the mocked data instead of the vm data
- // https://gitlab.com/gitlab-org/gitlab/-/issues/292085
- expect(chart.props('chartData')).toBe(wrapper.vm.areaCharts[i].data);
- expect(chart.text()).toBe(wrapper.vm.areaCharts[i].title);
- }
- });
+ it('does not render the deployment frequency charts in a tab', () => {
+ expect(findGlTabs().exists()).toBe(false);
+ expect(findDeploymentFrequencyCharts().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js
new file mode 100644
index 00000000000..64f80300237
--- /dev/null
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js
@@ -0,0 +1,39 @@
+import { mount } from '@vue/test-utils';
+import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
+import { transformedAreaChartData } from '../mock_data';
+
+describe('CiCdAnalyticsAreaChart', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = mount(CiCdAnalyticsAreaChart, {
+ propsData: {
+ chartData: transformedAreaChartData,
+ areaChartOptions: {
+ xAxis: {
+ name: 'X axis title',
+ type: 'category',
+ },
+ yAxis: {
+ name: 'Y axis title',
+ },
+ },
+ },
+ slots: {
+ default: 'Some title',
+ },
+ stubs: {
+ GlAreaChart: true,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('matches the snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
new file mode 100644
index 00000000000..598055d5828
--- /dev/null
+++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
@@ -0,0 +1,78 @@
+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 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';
+
+describe('ProjectsPipelinesChartsApp', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = shallowMount(PipelineCharts, {
+ propsData: {
+ counts,
+ timesChart,
+ lastWeek,
+ lastMonth,
+ lastYear,
+ },
+ provide: {
+ projectPath: 'test/project',
+ shouldRenderDeploymentFrequencyCharts: true,
+ },
+ stubs: {
+ DeploymentFrequencyCharts: true,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('overall statistics', () => {
+ it('displays the statistics list', () => {
+ const list = wrapper.find(StatisticsList);
+
+ expect(list.exists()).toBe(true);
+ expect(list.props('counts')).toBe(counts);
+ });
+
+ it('displays the commit duration chart', () => {
+ const chart = wrapper.find(GlColumnChart);
+
+ expect(chart.exists()).toBeTruthy();
+ expect(chart.props('yAxisTitle')).toBe('Minutes');
+ expect(chart.props('xAxisTitle')).toBe('Commit');
+ expect(chart.props('bars')).toBe(wrapper.vm.timesChartTransformedData);
+ expect(chart.props('option')).toBe(wrapper.vm.$options.timesChartOptions);
+ });
+ });
+
+ describe('pipelines charts', () => {
+ it('displays 3 area charts', () => {
+ expect(wrapper.findAll(CiCdAnalyticsAreaChart)).toHaveLength(3);
+ });
+
+ 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);
+ }
+ });
+ });
+ });
+});
diff --git a/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js b/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js
deleted file mode 100644
index aea25903023..00000000000
--- a/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { mount } from '@vue/test-utils';
-import Component from '~/projects/pipelines/charts/components/pipelines_area_chart.vue';
-import { transformedAreaChartData } from '../mock_data';
-
-describe('PipelinesAreaChart', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = mount(Component, {
- propsData: {
- chartData: transformedAreaChartData,
- },
- slots: {
- default: 'Some title',
- },
- stubs: {
- GlAreaChart: true,
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('matches the snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-});
diff --git a/spec/frontend/projects/pipelines/charts/mock_data.js b/spec/frontend/projects/pipelines/charts/mock_data.js
index da055536fcc..3bc09f0b0a0 100644
--- a/spec/frontend/projects/pipelines/charts/mock_data.js
+++ b/spec/frontend/projects/pipelines/charts/mock_data.js
@@ -25,11 +25,23 @@ export const lastYearChartData = {
export const transformedAreaChartData = [
{
name: 'all',
- data: [['01 Jan', 4], ['02 Jan', 6], ['03 Jan', 3], ['04 Jan', 6], ['05 Jan', 7]],
+ data: [
+ ['01 Jan', 4],
+ ['02 Jan', 6],
+ ['03 Jan', 3],
+ ['04 Jan', 6],
+ ['05 Jan', 7],
+ ],
},
{
name: 'success',
- data: [['01 Jan', 3], ['02 Jan', 3], ['03 Jan', 3], ['04 Jan', 3], ['05 Jan', 5]],
+ data: [
+ ['01 Jan', 3],
+ ['02 Jan', 3],
+ ['03 Jan', 3],
+ ['04 Jan', 3],
+ ['05 Jan', 5],
+ ],
},
];
diff --git a/spec/frontend/projects/project_import_gitlab_project_spec.js b/spec/frontend/projects/project_import_gitlab_project_spec.js
index 3c94934699d..aaf8a81f626 100644
--- a/spec/frontend/projects/project_import_gitlab_project_spec.js
+++ b/spec/frontend/projects/project_import_gitlab_project_spec.js
@@ -4,7 +4,7 @@ describe('Import Gitlab project', () => {
const pathName = 'my-project';
const projectName = 'My Project';
- const setTestFixtures = url => {
+ const setTestFixtures = (url) => {
window.history.pushState({}, null, url);
setFixtures(`
diff --git a/spec/frontend/projects/project_new_spec.js b/spec/frontend/projects/project_new_spec.js
index c32979dcd74..d2936cb9efe 100644
--- a/spec/frontend/projects/project_new_spec.js
+++ b/spec/frontend/projects/project_new_spec.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import projectNew from '~/projects/project_new';
describe('New Project', () => {
@@ -38,10 +38,7 @@ describe('New Project', () => {
beforeEach(() => {
projectNew.bindEvents();
- $projectPath
- .val('')
- .keyup()
- .val(dummyImportUrl);
+ $projectPath.val('').keyup().val(dummyImportUrl);
});
it('does not change project path for disabled $projectImportUrl', () => {
diff --git a/spec/frontend/projects/projects_filterable_list_spec.js b/spec/frontend/projects/projects_filterable_list_spec.js
index e756fb3ab56..377d347623a 100644
--- a/spec/frontend/projects/projects_filterable_list_spec.js
+++ b/spec/frontend/projects/projects_filterable_list_spec.js
@@ -1,5 +1,5 @@
+import { getJSONFixture, setHTMLFixture } from 'helpers/fixtures';
import ProjectsFilterableList from '~/projects/projects_filterable_list';
-import { getJSONFixture, setHTMLFixture } from '../helpers/fixtures';
describe('ProjectsFilterableList', () => {
let List;
diff --git a/spec/frontend/projects/settings/access_dropdown_spec.js b/spec/frontend/projects/settings/access_dropdown_spec.js
index 41b9c0c3763..8a57930ac83 100644
--- a/spec/frontend/projects/settings/access_dropdown_spec.js
+++ b/spec/frontend/projects/settings/access_dropdown_spec.js
@@ -72,7 +72,7 @@ describe('AccessDropdown', () => {
describe('with only role', () => {
beforeEach(() => {
- dropdown.setSelectedItems(dummyItems.filter(item => item.type === LEVEL_TYPES.ROLE));
+ dropdown.setSelectedItems(dummyItems.filter((item) => item.type === LEVEL_TYPES.ROLE));
$dropdownToggleText.addClass('is-default');
});
@@ -86,7 +86,7 @@ describe('AccessDropdown', () => {
describe('with only users', () => {
beforeEach(() => {
- dropdown.setSelectedItems(dummyItems.filter(item => item.type === LEVEL_TYPES.USER));
+ dropdown.setSelectedItems(dummyItems.filter((item) => item.type === LEVEL_TYPES.USER));
$dropdownToggleText.addClass('is-default');
});
@@ -100,7 +100,7 @@ describe('AccessDropdown', () => {
describe('with only groups', () => {
beforeEach(() => {
- dropdown.setSelectedItems(dummyItems.filter(item => item.type === LEVEL_TYPES.GROUP));
+ dropdown.setSelectedItems(dummyItems.filter((item) => item.type === LEVEL_TYPES.GROUP));
$dropdownToggleText.addClass('is-default');
});
@@ -115,7 +115,7 @@ describe('AccessDropdown', () => {
describe('with users and groups', () => {
beforeEach(() => {
const selectedTypes = [LEVEL_TYPES.GROUP, LEVEL_TYPES.USER];
- dropdown.setSelectedItems(dummyItems.filter(item => selectedTypes.includes(item.type)));
+ dropdown.setSelectedItems(dummyItems.filter((item) => selectedTypes.includes(item.type)));
$dropdownToggleText.addClass('is-default');
});
@@ -130,7 +130,7 @@ describe('AccessDropdown', () => {
describe('with users and deploy keys', () => {
beforeEach(() => {
const selectedTypes = [LEVEL_TYPES.DEPLOY_KEY, LEVEL_TYPES.USER];
- dropdown.setSelectedItems(dummyItems.filter(item => selectedTypes.includes(item.type)));
+ dropdown.setSelectedItems(dummyItems.filter((item) => selectedTypes.includes(item.type)));
$dropdownToggleText.addClass('is-default');
});
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 7e74a5deee1..c83b1852147 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
@@ -137,7 +137,7 @@ describe('ServiceDeskRoot', () => {
.$nextTick()
.then(waitForPromises)
.then(() => {
- expect(wrapper.html()).toContain('Changes were successfully made.');
+ expect(wrapper.html()).toContain('Changes saved.');
});
});
@@ -160,7 +160,7 @@ describe('ServiceDeskRoot', () => {
.$nextTick()
.then(waitForPromises)
.then(() => {
- expect(wrapper.html()).toContain('An error occured while making the changes:');
+ expect(wrapper.html()).toContain('An error occured while saving changes:');
});
});
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 173a7fc4e11..ddd9a7b2fad 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
@@ -185,7 +185,9 @@ describe('ServiceDeskSetting', () => {
const expectedTemplates = [''].concat(templates);
const dropdown = findTemplateDropdown();
- const dropdownList = Array.from(dropdown.element.children).map(option => option.innerText);
+ const dropdownList = Array.from(dropdown.element.children).map(
+ (option) => option.innerText,
+ );
expect(dropdown.element.children).toHaveLength(expectedTemplates.length);
expect(dropdownList.includes('Bug')).toEqual(true);
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
index 3b960a95db4..d5340df03fe 100644
--- 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
@@ -23,7 +23,7 @@ describe('ServiceDeskService', () => {
it('makes a request to set service desk', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
- return service.toggleServiceDesk(true).then(response => {
+ return service.toggleServiceDesk(true).then((response) => {
expect(response.data).toEqual(dummyResponse);
});
});
@@ -31,7 +31,7 @@ describe('ServiceDeskService', () => {
it('fails on error response', () => {
axiosMock.onPut(endpoint).networkError();
- return service.toggleServiceDesk(true).catch(error => {
+ return service.toggleServiceDesk(true).catch((error) => {
expect(error.message).toBe(errorMessage);
});
});
@@ -63,7 +63,7 @@ describe('ServiceDeskService', () => {
},
true,
)
- .then(response => {
+ .then((response) => {
expect(response.data).toEqual(dummyResponse);
});
});
@@ -79,7 +79,7 @@ describe('ServiceDeskService', () => {
},
true,
)
- .catch(error => {
+ .catch((error) => {
expect(error.message).toBe(errorMessage);
});
});
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index 2460851a6a4..f6b2780e167 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -91,12 +91,7 @@ describe('PrometheusMetrics', () => {
);
expect($metricsListLi.length).toEqual(metrics.length);
- expect(
- $metricsListLi
- .first()
- .find('.badge')
- .text(),
- ).toEqual(`${metrics[0].active_metrics}`);
+ expect($metricsListLi.first().find('.badge').text()).toEqual(`${metrics[0].active_metrics}`);
});
it('should show missing environment variables list', () => {
@@ -138,7 +133,7 @@ describe('PrometheusMetrics', () => {
mock.restore();
});
- it('should show loader animation while response is being loaded and hide it when request is complete', done => {
+ it('should show loader animation while response is being loaded and hide it when request is complete', (done) => {
mockSuccess();
prometheusMetrics.loadActiveMetrics();
@@ -152,7 +147,7 @@ describe('PrometheusMetrics', () => {
});
});
- it('should show empty state if response failed to load', done => {
+ it('should show empty state if response failed to load', (done) => {
mockError();
prometheusMetrics.loadActiveMetrics();
@@ -164,7 +159,7 @@ describe('PrometheusMetrics', () => {
});
});
- it('should populate metrics list once response is loaded', done => {
+ it('should populate metrics list once response is loaded', (done) => {
jest.spyOn(prometheusMetrics, 'populateActiveMetrics').mockImplementation();
mockSuccess();
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index 7f0a4c7d3f4..7efb6e9ba4a 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -37,7 +37,7 @@ describe('Ref selector component', () => {
attrs,
listeners: {
// simulate a parent component v-model binding
- input: selectedRef => {
+ input: (selectedRef) => {
wrapper.setProps({ value: selectedRef });
},
},
@@ -61,13 +61,13 @@ describe('Ref selector component', () => {
mock
.onGet(`/api/v4/projects/${projectId}/repository/branches`)
- .reply(config => branchesApiCallSpy(config));
+ .reply((config) => branchesApiCallSpy(config));
mock
.onGet(`/api/v4/projects/${projectId}/repository/tags`)
- .reply(config => tagsApiCallSpy(config));
+ .reply((config) => tagsApiCallSpy(config));
mock
.onGet(new RegExp(`/api/v4/projects/${projectId}/repository/commits/.*`))
- .reply(config => commitApiCallSpy(config));
+ .reply((config) => commitApiCallSpy(config));
});
afterEach(() => {
@@ -122,7 +122,7 @@ describe('Ref selector component', () => {
//
// Convenience methods
//
- const updateQuery = newQuery => {
+ const updateQuery = (newQuery) => {
findSearchBox().vm.$emit('input', newQuery);
};
@@ -313,9 +313,7 @@ describe('Ref selector component', () => {
it('renders the "Branches" heading with a total number indicator', () => {
expect(
- findBranchesSection()
- .find('[data-testid="section-header"]')
- .text(),
+ findBranchesSection().find('[data-testid="section-header"]').text(),
).toMatchInterpolatedText('Branches 123');
});
@@ -336,7 +334,7 @@ describe('Ref selector component', () => {
it('renders the default branch as a selectable item with a "default" badge', () => {
const dropdownItems = findBranchDropdownItems();
- const defaultBranch = fixtures.branches.find(b => b.default);
+ const defaultBranch = fixtures.branches.find((b) => b.default);
const defaultBranchIndex = fixtures.branches.indexOf(defaultBranch);
expect(trimText(dropdownItems.at(defaultBranchIndex).text())).toBe(
@@ -392,9 +390,7 @@ describe('Ref selector component', () => {
it('renders the "Tags" heading with a total number indicator', () => {
expect(
- findTagsSection()
- .find('[data-testid="section-header"]')
- .text(),
+ findTagsSection().find('[data-testid="section-header"]').text(),
).toMatchInterpolatedText('Tags 456');
});
@@ -460,9 +456,7 @@ describe('Ref selector component', () => {
it('renders the "Commits" heading with a total number indicator', () => {
expect(
- findCommitsSection()
- .find('[data-testid="section-header"]')
- .text(),
+ findCommitsSection().find('[data-testid="section-header"]').text(),
).toMatchInterpolatedText('Commits 1');
});
diff --git a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
index feae2f629b7..4be4fce1abf 100644
--- a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
@@ -1,28 +1,71 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
-<ul>
- <li
- class="foo bar"
+exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
+<div
+ class="gl-breadcrumbs"
+>
+ <ol
+ class="breadcrumb gl-breadcrumb-list"
>
- baz
- </li>
- <li
- class="foo bar"
+
+ <li
+ class="breadcrumb-item gl-breadcrumb-item"
+ >
+ <a
+ class=""
+ href="/"
+ target="_self"
+ />
+ </li>
+
+ <span
+ class="gl-breadcrumb-separator"
+ data-testid="separator"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-icon s8"
+ data-testid="angle-right-icon"
+ >
+ <use
+ href="#angle-right"
+ />
+ </svg>
+ </span>
+ <li
+ class="breadcrumb-item gl-breadcrumb-item"
+ >
+ <a
+ class=""
+ href="#"
+ target="_self"
+ />
+ </li>
+
+ <!---->
+ </ol>
+</div>
+`;
+
+exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
+<div
+ class="gl-breadcrumbs"
+>
+ <ol
+ class="breadcrumb gl-breadcrumb-list"
>
- foo
- </li>
-
- <!---->
-
- <li>
- <a
- class="foo"
+
+ <li
+ class="breadcrumb-item gl-breadcrumb-item"
>
- <a>
-
- </a>
- </a>
- </li>
-</ul>
+ <a
+ class=""
+ href="/"
+ target="_self"
+ />
+ </li>
+
+ <!---->
+ </ol>
+</div>
`;
diff --git a/spec/frontend/registry/explorer/components/delete_button_spec.js b/spec/frontend/registry/explorer/components/delete_button_spec.js
index a79ca77a464..cd43e97009b 100644
--- a/spec/frontend/registry/explorer/components/delete_button_spec.js
+++ b/spec/frontend/registry/explorer/components/delete_button_spec.js
@@ -13,7 +13,7 @@ describe('delete_button', () => {
const findButton = () => wrapper.find(GlButton);
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(component, {
propsData: {
...defaultProps,
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 5d54986978b..6a7fbbe367a 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
@@ -15,7 +15,7 @@ describe('Delete alert', () => {
const findAlert = () => wrapper.find(GlAlert);
const findLink = () => wrapper.find(GlLink);
- const mountComponent = propsData => {
+ const mountComponent = (propsData) => {
wrapper = shallowMount(component, { stubs: { GlSprintf }, propsData });
};
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 c77f7a54d34..636e0a285a6 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
@@ -13,7 +13,7 @@ describe('Delete Modal', () => {
const findModal = () => wrapper.find(GlModal);
const findDescription = () => wrapper.find('[data-testid="description"]');
- const mountComponent = propsData => {
+ const mountComponent = (propsData) => {
wrapper = shallowMount(component, {
propsData,
stubs: {
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 f642c66832b..337235e3de5 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
@@ -3,7 +3,18 @@ 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 } from '~/registry/explorer/constants';
+import {
+ DETAILS_PAGE_TITLE,
+ UNSCHEDULED_STATUS,
+ SCHEDULED_STATUS,
+ ONGOING_STATUS,
+ UNFINISHED_STATUS,
+ CLEANUP_DISABLED_TEXT,
+ CLEANUP_DISABLED_TOOLTIP,
+ CLEANUP_SCHEDULED_TOOLTIP,
+ CLEANUP_ONGOING_TOOLTIP,
+ CLEANUP_UNFINISHED_TOOLTIP,
+} from '~/registry/explorer/constants';
describe('Details Header', () => {
let wrapper;
@@ -11,15 +22,22 @@ describe('Details Header', () => {
const defaultImage = {
name: 'foo',
updatedAt: '2020-11-03T13:29:21Z',
+ tagsCount: 10,
project: {
visibility: 'public',
+ containerExpirationPolicy: {
+ enabled: false,
+ },
},
};
// set the date to Dec 4, 2020
useFakeDate(2020, 11, 4);
+ const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
- const findLastUpdatedAndVisibility = () => wrapper.find('[data-testid="updated-and-visibility"]');
+ const findLastUpdatedAndVisibility = () => findByTestId('updated-and-visibility');
+ const findTagsCount = () => findByTestId('tags-count');
+ const findCleanup = () => findByTestId('cleanup');
const waitForMetadataItems = async () => {
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
@@ -54,25 +72,96 @@ describe('Details Header', () => {
expect(wrapper.text()).toContain('foo');
});
- it('has a metadata item with last updated text', async () => {
- mountComponent();
- await waitForMetadataItems();
+ describe('metadata items', () => {
+ describe('tags count', () => {
+ it('when there is more than one tag has the correct text', async () => {
+ mountComponent();
+ await waitForMetadataItems();
- expect(findLastUpdatedAndVisibility().props('text')).toBe('Last updated 1 month ago');
- });
+ expect(findTagsCount().props('text')).toBe('10 tags');
+ });
+
+ it('when there is one tag has the correct text', async () => {
+ mountComponent({ ...defaultImage, tagsCount: 1 });
+ await waitForMetadataItems();
+
+ expect(findTagsCount().props('text')).toBe('1 tag');
+ });
+
+ it('has the correct icon', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findTagsCount().props('icon')).toBe('tag');
+ });
+ });
- describe('visibility icon', () => {
- it('shows an eye when the project is public', async () => {
- mountComponent();
- await waitForMetadataItems();
+ describe('cleanup metadata item', () => {
+ it('has the correct icon', async () => {
+ mountComponent();
+ await waitForMetadataItems();
- expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye');
+ expect(findCleanup().props('icon')).toBe('expire');
+ });
+
+ it('when the expiration policy is disabled', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findCleanup().props()).toMatchObject({
+ text: CLEANUP_DISABLED_TEXT,
+ textTooltip: CLEANUP_DISABLED_TOOLTIP,
+ });
+ });
+
+ it.each`
+ status | text | tooltip
+ ${UNSCHEDULED_STATUS} | ${'Cleanup will run in 1 month'} | ${''}
+ ${SCHEDULED_STATUS} | ${'Cleanup pending'} | ${CLEANUP_SCHEDULED_TOOLTIP}
+ ${ONGOING_STATUS} | ${'Cleanup in progress'} | ${CLEANUP_ONGOING_TOOLTIP}
+ ${UNFINISHED_STATUS} | ${'Cleanup incomplete'} | ${CLEANUP_UNFINISHED_TOOLTIP}
+ `(
+ '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' },
+ },
+ });
+ await waitForMetadataItems();
+
+ expect(findCleanup().props()).toMatchObject({
+ text,
+ textTooltip: tooltip,
+ });
+ },
+ );
});
- it('shows an eye slashed when the project is not public', async () => {
- mountComponent({ ...defaultImage, project: { visibility: 'private' } });
- await waitForMetadataItems();
- expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye-slash');
+ describe('visibility and updated at ', () => {
+ it('has last updated text', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findLastUpdatedAndVisibility().props('text')).toBe('Last updated 1 month ago');
+ });
+
+ describe('visibility icon', () => {
+ it('shows an eye when the project is public', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye');
+ });
+ it('shows an eye slashed when the project is not public', async () => {
+ mountComponent({ ...defaultImage, project: { visibility: 'private' } });
+ await waitForMetadataItems();
+
+ expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye-slash');
+ });
+ });
});
});
});
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 94944643e8b..c2efc71c159 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
@@ -312,11 +312,7 @@ describe('tags list row', () => {
});
it(`is ${clipboard} that clipboard button exist`, () => {
- expect(
- finderFunction()
- .find(ClipboardButton)
- .exists(),
- ).toBe(clipboard);
+ expect(finderFunction().find(ClipboardButton).exists()).toBe(clipboard);
});
});
});
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 035b59731c9..413795a7a57 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
@@ -8,7 +8,7 @@ import { tagsMock } from '../../mock_data';
describe('Tags List', () => {
let wrapper;
const tags = [...tagsMock];
- const readOnlyTags = tags.map(t => ({ ...t, canDelete: false }));
+ const readOnlyTags = tags.map((t) => ({ ...t, canDelete: false }));
const findTagsListRow = () => wrapper.findAll(TagsListRow);
const findDeleteButton = () => wrapper.find(GlButton);
@@ -78,18 +78,14 @@ describe('Tags List', () => {
it('is enabled when at least one item is selected', async () => {
mountComponent();
- findTagsListRow()
- .at(0)
- .vm.$emit('select');
+ findTagsListRow().at(0).vm.$emit('select');
await wrapper.vm.$nextTick();
expect(findDeleteButton().attributes('disabled')).toBe(undefined);
});
it('click event emits a deleted event with selected items', () => {
mountComponent();
- findTagsListRow()
- .at(0)
- .vm.$emit('select');
+ findTagsListRow().at(0).vm.$emit('select');
findDeleteButton().vm.$emit('click');
expect(wrapper.emitted('delete')).toEqual([[{ 'beta-24753': true }]]);
@@ -116,22 +112,14 @@ describe('Tags List', () => {
describe('events', () => {
it('select event update the selected items', async () => {
mountComponent();
- findTagsListRow()
- .at(0)
- .vm.$emit('select');
+ findTagsListRow().at(0).vm.$emit('select');
await wrapper.vm.$nextTick();
- expect(
- findTagsListRow()
- .at(0)
- .attributes('selected'),
- ).toBe('true');
+ expect(findTagsListRow().at(0).attributes('selected')).toBe('true');
});
it('delete event emit a delete event', () => {
mountComponent();
- findTagsListRow()
- .at(0)
- .vm.$emit('delete');
+ findTagsListRow().at(0).vm.$emit('delete');
expect(wrapper.emitted('delete')).toEqual([[{ 'beta-24753': true }]]);
});
});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
index b27d3e2c042..40d84d9d4a5 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
@@ -32,11 +32,7 @@ describe('TagsLoader component', () => {
it('has the correct props', () => {
mountComponent();
- expect(
- findGlSkeletonLoaders()
- .at(0)
- .props(),
- ).toMatchObject({
+ expect(findGlSkeletonLoaders().at(0).props()).toMatchObject({
width: component.loader.width,
height: component.loader.height,
});
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap b/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
index bab6b25cc15..46b07b4c2d6 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
@@ -56,7 +56,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
</p>
<gl-form-input-group-stub
- class="gl-mb-4 "
+ class="gl-mb-4"
predefinedoptions="[object Object]"
value=""
>
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 b9839d92f1d..a06c4795b2e 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,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlIcon, GlSprintf } from '@gitlab/ui';
+import { GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -23,12 +23,13 @@ describe('Image List Row', () => {
const [item] = imagesListResponse;
const findDetailsLink = () => wrapper.find('[data-testid="details-link"]');
- const findTagsCount = () => wrapper.find('[data-testid="tagsCount"]');
+ const findTagsCount = () => wrapper.find('[data-testid="tags-count"]');
const findDeleteBtn = () => wrapper.find(DeleteButton);
const findClipboardButton = () => wrapper.find(ClipboardButton);
const findWarningIcon = () => wrapper.find('[data-testid="warning-icon"]');
+ const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(Component, {
stubs: {
RouterLink,
@@ -164,6 +165,20 @@ describe('Image List Row', () => {
expect(icon.props('name')).toBe('tag');
});
+ describe('loading state', () => {
+ it('shows a loader when metadataLoading is true', () => {
+ mountComponent({ metadataLoading: true });
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ });
+
+ it('hides the tags count while loading', () => {
+ mountComponent({ metadataLoading: true });
+
+ expect(findTagsCount().exists()).toBe(false);
+ });
+ });
+
describe('tags count text', () => {
it('with one tag in the image', () => {
mountComponent({ item: { ...item, tagsCount: 1 } });
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 54befc9973a..61c362f4d78 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
@@ -11,11 +11,12 @@ describe('Image List', () => {
const findRow = () => wrapper.findAll(ImageListRow);
const findPagination = () => wrapper.find(GlKeysetPagination);
- const mountComponent = (pageInfo = defaultPageInfo) => {
+ const mountComponent = (props) => {
wrapper = shallowMount(Component, {
propsData: {
images: imagesListResponse,
- pageInfo,
+ pageInfo: defaultPageInfo,
+ ...props,
},
});
};
@@ -35,11 +36,14 @@ describe('Image List', () => {
it('when delete event is emitted on the row it emits up a delete event', () => {
mountComponent();
- findRow()
- .at(0)
- .vm.$emit('delete', 'foo');
+ findRow().at(0).vm.$emit('delete', 'foo');
expect(wrapper.emitted('delete')).toEqual([['foo']]);
});
+
+ it('passes down the metadataLoading prop', () => {
+ mountComponent({ metadataLoading: true });
+ expect(findRow().at(0).props('metadataLoading')).toBe(true);
+ });
});
describe('pagination', () => {
@@ -57,7 +61,7 @@ describe('Image List', () => {
`(
'when hasNextPage is $hasNextPage and hasPreviousPage is $hasPreviousPage: is $isVisible that the component is visible',
({ hasNextPage, hasPreviousPage, isVisible }) => {
- mountComponent({ hasNextPage, hasPreviousPage });
+ mountComponent({ pageInfo: { ...defaultPageInfo, hasNextPage, hasPreviousPage } });
expect(findPagination().exists()).toBe(isVisible);
expect(findPagination().props('hasPreviousPage')).toBe(hasPreviousPage);
@@ -66,7 +70,7 @@ describe('Image List', () => {
);
it('emits "prev-page" when the user clicks the back page button', () => {
- mountComponent({ hasPreviousPage: true });
+ mountComponent();
findPagination().vm.$emit('prev');
@@ -74,7 +78,7 @@ describe('Image List', () => {
});
it('emits "next-page" when the user clicks the forward page button', () => {
- mountComponent({ hasNextPage: true });
+ mountComponent();
findPagination().vm.$emit('next');
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 3c997093d46..58439c185e3 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
@@ -41,9 +41,12 @@ describe('registry_header', () => {
describe('header', () => {
it('has a title', () => {
- mountComponent();
+ mountComponent({ metadataLoading: true });
- expect(findTitleArea().props('title')).toBe(CONTAINER_REGISTRY_TITLE);
+ expect(findTitleArea().props()).toMatchObject({
+ title: CONTAINER_REGISTRY_TITLE,
+ metadataLoading: true,
+ });
});
it('has a commands slot', () => {
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
index fb0b98ba004..487f33594c1 100644
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
@@ -1,4 +1,4 @@
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import component from '~/registry/explorer/components/registry_breadcrumb.vue';
@@ -6,45 +6,13 @@ describe('Registry Breadcrumb', () => {
let wrapper;
const nameGenerator = jest.fn();
- const crumb = {
- className: 'foo bar',
- tagName: 'div',
- innerHTML: 'baz',
- querySelector: jest.fn(),
- children: [
- {
- tagName: 'a',
- className: 'foo',
- },
- ],
- };
-
- const querySelectorReturnValue = {
- classList: ['js-divider'],
- tagName: 'svg',
- innerHTML: 'foo',
- };
-
- const crumbs = [crumb, { ...crumb, innerHTML: 'foo' }, { ...crumb, className: 'baz' }];
-
const routes = [
- { name: 'foo', meta: { nameGenerator, root: true } },
- { name: 'baz', meta: { nameGenerator } },
+ { name: 'list', path: '/', meta: { nameGenerator, root: true } },
+ { name: 'details', path: '/:id', meta: { nameGenerator } },
];
- const findDivider = () => wrapper.find('.js-divider');
- const findRootRoute = () => wrapper.find({ ref: 'rootRouteLink' });
- const findChildRoute = () => wrapper.find({ ref: 'childRouteLink' });
- const findLastCrumb = () => wrapper.find({ ref: 'lastCrumb' });
-
- const mountComponent = $route => {
- wrapper = shallowMount(component, {
- propsData: {
- crumbs,
- },
- stubs: {
- 'router-link': { name: 'router-link', template: '<a><slot></slot></a>', props: ['to'] },
- },
+ const mountComponent = ($route) => {
+ wrapper = mount(component, {
mocks: {
$route,
$router: {
@@ -58,7 +26,6 @@ describe('Registry Breadcrumb', () => {
beforeEach(() => {
nameGenerator.mockClear();
- crumb.querySelector = jest.fn();
});
afterEach(() => {
@@ -75,8 +42,11 @@ describe('Registry Breadcrumb', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('contains a router-link for the child route', () => {
- expect(findChildRoute().exists()).toBe(true);
+ it('contains only a single router-link to list', () => {
+ const links = wrapper.findAll('a');
+
+ expect(links).toHaveLength(1);
+ expect(links.at(0).attributes('href')).toBe('/');
});
it('the link text is calculated by nameGenerator', () => {
@@ -86,52 +56,23 @@ describe('Registry Breadcrumb', () => {
describe('when is not rootRoute', () => {
beforeEach(() => {
- crumb.querySelector.mockReturnValue(querySelectorReturnValue);
mountComponent(routes[1]);
});
- it('renders a divider', () => {
- expect(findDivider().exists()).toBe(true);
+ it('renders', () => {
+ expect(wrapper.element).toMatchSnapshot();
});
- it('contains a router-link for the root route', () => {
- expect(findRootRoute().exists()).toBe(true);
- });
+ it('contains two router-links to list and details', () => {
+ const links = wrapper.findAll('a');
- it('contains a router-link for the child route', () => {
- expect(findChildRoute().exists()).toBe(true);
+ expect(links).toHaveLength(2);
+ expect(links.at(0).attributes('href')).toBe('/');
+ expect(links.at(1).attributes('href')).toBe('#');
});
it('the link text is calculated by nameGenerator', () => {
expect(nameGenerator).toHaveBeenCalledTimes(2);
});
});
-
- describe('last crumb', () => {
- const lastChildren = crumb.children[0];
- beforeEach(() => {
- nameGenerator.mockReturnValue('foo');
- mountComponent(routes[0]);
- });
-
- it('has the same tag as the last children of the crumbs', () => {
- expect(findLastCrumb().element.tagName).toBe(lastChildren.tagName.toUpperCase());
- });
-
- it('has the same classes as the last children of the crumbs', () => {
- expect(
- findLastCrumb()
- .classes()
- .join(' '),
- ).toEqual(lastChildren.className);
- });
-
- it('has a link to the current route', () => {
- expect(findChildRoute().props('to')).toEqual({ to: routes[0].name });
- });
-
- it('the link has the correct text', () => {
- expect(findChildRoute().text()).toEqual('foo');
- });
- });
});
diff --git a/spec/frontend/registry/explorer/mock_data.js b/spec/frontend/registry/explorer/mock_data.js
index 72a9bff8a47..b0fc009872c 100644
--- a/spec/frontend/registry/explorer/mock_data.js
+++ b/spec/frontend/registry/explorer/mock_data.js
@@ -8,7 +8,6 @@ export const imagesListResponse = [
location: '0.0.0.0:5000/gitlab-org/gitlab-test/rails-12009',
canDelete: true,
createdAt: '2020-11-03T13:29:21Z',
- tagsCount: 18,
expirationPolicyStartedAt: null,
},
{
@@ -20,7 +19,6 @@ export const imagesListResponse = [
location: '0.0.0.0:5000/gitlab-org/gitlab-test/rails-20572',
canDelete: true,
createdAt: '2020-09-21T06:57:43Z',
- tagsCount: 1,
expirationPolicyStartedAt: null,
},
];
@@ -117,8 +115,13 @@ export const containerRepositoryMock = {
updatedAt: '2020-11-03T13:29:21Z',
tagsCount: 13,
expirationPolicyStartedAt: null,
+ expirationPolicyCleanupStatus: 'UNSCHEDULED',
project: {
visibility: 'public',
+ containerExpirationPolicy: {
+ enabled: false,
+ nextRunAt: '2020-11-27T08:59:27Z',
+ },
__typename: 'Project',
},
};
@@ -158,7 +161,7 @@ export const tagsMock = [
},
];
-export const graphQLImageDetailsMock = override => ({
+export const graphQLImageDetailsMock = (override) => ({
data: {
containerRepository: {
...containerRepositoryMock,
@@ -209,3 +212,26 @@ export const dockerCommands = {
dockerPushCommand: 'barbar',
dockerLoginCommand: 'bazbaz',
};
+
+export const graphQLProjectImageRepositoriesDetailsMock = {
+ data: {
+ project: {
+ containerRepositories: {
+ nodes: [
+ {
+ id: 'gid://gitlab/ContainerRepository/26',
+ tagsCount: 4,
+ __typename: 'ContainerRepository',
+ },
+ {
+ id: 'gid://gitlab/ContainerRepository/11',
+ tagsCount: 1,
+ __typename: 'ContainerRepository',
+ },
+ ],
+ __typename: 'ContainerRepositoryConnection',
+ },
+ __typename: 'Project',
+ },
+ },
+};
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index d307dfe590c..1746a6a63b6 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -1,7 +1,7 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlKeysetPagination } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
@@ -15,6 +15,8 @@ import EmptyTagsState from '~/registry/explorer/components/details_page/empty_ta
import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
import deleteContainerRepositoryTagsMutation from '~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
+import { UNFINISHED_STATUS } from '~/registry/explorer/constants/index';
+
import {
graphQLImageDetailsMock,
graphQLImageDetailsEmptyTagsMock,
@@ -46,7 +48,7 @@ describe('Details Page', () => {
updateName: jest.fn(),
};
- const cleanTags = tagsMock.map(t => {
+ const cleanTags = tagsMock.map((t) => {
const result = { ...t };
// eslint-disable-next-line no-underscore-dangle
delete result.__typename;
@@ -58,7 +60,7 @@ describe('Details Page', () => {
await wrapper.vm.$nextTick();
};
- const tagsArrayToSelectedTags = tags =>
+ const tagsArrayToSelectedTags = (tags) =>
tags.reduce((acc, c) => {
acc[c.name] = true;
return acc;
@@ -334,7 +336,7 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('confirmDelete');
expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: tagsMock.map(t => t.name) }),
+ expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
);
});
});
@@ -353,10 +355,13 @@ describe('Details Page', () => {
mountComponent();
await waitForApolloRequestRender();
- expect(findDetailsHeader().props('image')).toMatchObject({
- name: containerRepositoryMock.name,
- project: {
- visibility: containerRepositoryMock.project.visibility,
+ expect(findDetailsHeader().props()).toMatchObject({
+ metadataLoading: false,
+ image: {
+ name: containerRepositoryMock.name,
+ project: {
+ visibility: containerRepositoryMock.project.visibility,
+ },
},
});
});
@@ -398,13 +403,13 @@ describe('Details Page', () => {
cleanupPoliciesHelpPagePath: 'bar',
};
- describe('when expiration_policy_started is not null', () => {
+ describe(`when expirationPolicyCleanupStatus is ${UNFINISHED_STATUS}`, () => {
let resolver;
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(
graphQLImageDetailsMock({
- expirationPolicyStartedAt: Date.now().toString(),
+ expirationPolicyCleanupStatus: UNFINISHED_STATUS,
}),
);
});
@@ -439,7 +444,7 @@ describe('Details Page', () => {
});
});
- describe('when expiration_policy_started is null', () => {
+ describe(`when expirationPolicyCleanupStatus is not ${UNFINISHED_STATUS}`, () => {
it('the component is hidden', async () => {
mountComponent();
await waitForApolloRequestRender();
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index 7d32a667011..c4556934934 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -1,8 +1,9 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { GlSkeletonLoader, GlSprintf, GlAlert, GlSearchBoxByClick } from '@gitlab/ui';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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 CliCommands from '~/registry/explorer/components/list_page/cli_commands.vue';
@@ -19,8 +20,7 @@ import {
SEARCH_PLACEHOLDER_TEXT,
} from '~/registry/explorer/constants';
-import getProjectContainerRepositoriesQuery from '~/registry/explorer/graphql/queries/get_project_container_repositories.query.graphql';
-import getGroupContainerRepositoriesQuery from '~/registry/explorer/graphql/queries/get_group_container_repositories.query.graphql';
+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 {
@@ -31,6 +31,8 @@ import {
graphQLEmptyImageListMock,
graphQLEmptyGroupImageListMock,
pageInfo,
+ graphQLProjectImageRepositoriesDetailsMock,
+ dockerCommands,
} from '../mock_data';
import { GlModal, GlEmptyState } from '../stubs';
import { $toast } from '../../shared/mocks';
@@ -58,6 +60,7 @@ describe('List Page', () => {
const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
const waitForApolloRequestRender = async () => {
+ jest.runOnlyPendingTimers();
await waitForPromises();
await wrapper.vm.$nextTick();
};
@@ -65,15 +68,15 @@ describe('List Page', () => {
const mountComponent = ({
mocks,
resolver = jest.fn().mockResolvedValue(graphQLImageListMock),
- groupResolver = jest.fn().mockResolvedValue(graphQLImageListMock),
+ detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock),
mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock),
- config = {},
+ config = { isGroupPage: false },
} = {}) => {
localVue.use(VueApollo);
const requestHandlers = [
- [getProjectContainerRepositoriesQuery, resolver],
- [getGroupContainerRepositoriesQuery, groupResolver],
+ [getContainerRepositoriesQuery, resolver],
+ [getContainerRepositoriesDetails, detailsResolver],
[deleteContainerRepositoryMutation, mutationResolver],
];
@@ -99,6 +102,7 @@ describe('List Page', () => {
provide() {
return {
config,
+ ...dockerCommands,
};
},
});
@@ -116,6 +120,7 @@ describe('List Page', () => {
expect(findRegistryHeader().exists()).toBe(true);
expect(findRegistryHeader().props()).toMatchObject({
imagesCount: 2,
+ metadataLoading: false,
});
});
@@ -124,6 +129,7 @@ describe('List Page', () => {
characterError: true,
containersErrorImage: 'foo',
helpPagePath: 'bar',
+ isGroupPage: false,
};
it('should show an empty state', () => {
@@ -170,6 +176,12 @@ describe('List Page', () => {
expect(findCliCommands().exists()).toBe(false);
});
+
+ it('title has the metadataLoading props set to true', () => {
+ mountComponent();
+
+ expect(findRegistryHeader().props('metadataLoading')).toBe(true);
+ });
});
describe('list is empty', () => {
@@ -192,15 +204,16 @@ describe('List Page', () => {
expect(findProjectEmptyState().exists()).toBe(true);
});
});
+
describe('group page', () => {
- const groupResolver = jest.fn().mockResolvedValue(graphQLEmptyGroupImageListMock);
+ const resolver = jest.fn().mockResolvedValue(graphQLEmptyGroupImageListMock);
const config = {
isGroupPage: true,
};
it('group empty state is visible', async () => {
- mountComponent({ groupResolver, config });
+ mountComponent({ resolver, config });
await waitForApolloRequestRender();
@@ -208,7 +221,7 @@ describe('List Page', () => {
});
it('cli commands is not visible', async () => {
- mountComponent({ groupResolver, config });
+ mountComponent({ resolver, config });
await waitForApolloRequestRender();
@@ -216,7 +229,7 @@ describe('List Page', () => {
});
it('list header is not visible', async () => {
- mountComponent({ groupResolver, config });
+ mountComponent({ resolver, config });
await waitForApolloRequestRender();
@@ -253,6 +266,39 @@ describe('List Page', () => {
expect(header.text()).toBe(IMAGE_REPOSITORY_LIST_LABEL);
});
+ describe('additional metadata', () => {
+ it('is called on component load', async () => {
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ detailsResolver });
+
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+
+ expect(detailsResolver).toHaveBeenCalled();
+ });
+
+ it('does not block the list ui to show', async () => {
+ const detailsResolver = jest.fn().mockRejectedValue();
+ mountComponent({ detailsResolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findImageList().exists()).toBe(true);
+ });
+
+ it('loading state is passed to list component', async () => {
+ // this is a promise that never resolves, to trick apollo to think that this request is still loading
+ const detailsResolver = jest.fn().mockImplementation(() => new Promise(() => {}));
+
+ mountComponent({ detailsResolver });
+ await waitForApolloRequestRender();
+
+ expect(findImageList().props('metadataLoading')).toBe(true);
+ });
+ });
+
describe('delete image', () => {
const deleteImage = async () => {
await wrapper.vm.$nextTick();
@@ -274,7 +320,7 @@ describe('List Page', () => {
const updatedImage = findImageList()
.props('images')
- .find(i => i.id === deletedContainerRepository.id);
+ .find((i) => i.id === deletedContainerRepository.id);
expect(updatedImage.status).toBe(deletedContainerRepository.status);
});
@@ -350,9 +396,15 @@ describe('List Page', () => {
it('when search result is empty displays an empty search message', async () => {
const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- mountComponent({ resolver });
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ resolver, detailsResolver });
+
+ await waitForApolloRequestRender();
resolver.mockResolvedValue(graphQLEmptyImageListMock);
+ detailsResolver.mockResolvedValue(graphQLEmptyImageListMock);
await doSearch();
@@ -363,28 +415,42 @@ describe('List Page', () => {
describe('pagination', () => {
it('prev-page event triggers a fetchMore request', async () => {
const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- mountComponent({ resolver });
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ resolver, detailsResolver });
await waitForApolloRequestRender();
findImageList().vm.$emit('prev-page');
+ await wrapper.vm.$nextTick();
expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ first: null, before: pageInfo.startCursor }),
+ expect.objectContaining({ before: pageInfo.startCursor }),
+ );
+ expect(detailsResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ before: pageInfo.startCursor }),
);
});
it('next-page event triggers a fetchMore request', async () => {
const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- mountComponent({ resolver });
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ resolver, detailsResolver });
await waitForApolloRequestRender();
findImageList().vm.$emit('next-page');
+ await wrapper.vm.$nextTick();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ after: pageInfo.endCursor }),
);
+ expect(detailsResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ after: pageInfo.endCursor }),
+ );
});
});
});
@@ -411,7 +477,7 @@ describe('List Page', () => {
mountComponent();
});
- const testTrackingCall = action => {
+ const testTrackingCall = (action) => {
expect(Tracking.event).toHaveBeenCalledWith(undefined, action, {
label: 'registry_repository_delete',
});
diff --git a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap
index d7f89ce070e..7a52b4a5d0f 100644
--- a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap
+++ b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap
@@ -32,7 +32,7 @@ exports[`Settings Form Keep N matches snapshot 1`] = `
exports[`Settings Form Keep Regex matches snapshot 1`] = `
<expiration-input-stub
data-testid="keep-regex-input"
- description="Tags with names that match this regex pattern are kept. %{linkStart}More information%{linkEnd}"
+ description="Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
error=""
label="Keep tags matching:"
name="keep-regex"
@@ -54,7 +54,7 @@ exports[`Settings Form OlderThan matches snapshot 1`] = `
exports[`Settings Form Remove regex matches snapshot 1`] = `
<expiration-input-stub
data-testid="remove-regex-input"
- description="Tags with names that match this regex pattern are removed. %{linkStart}More information%{linkEnd}"
+ description="Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
error=""
label="Remove tags matching:"
name="remove-regex"
diff --git a/spec/frontend/registry/settings/components/expiration_dropdown_spec.js b/spec/frontend/registry/settings/components/expiration_dropdown_spec.js
index e0cac317ad6..f777f7ec9de 100644
--- a/spec/frontend/registry/settings/components/expiration_dropdown_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_dropdown_spec.js
@@ -8,14 +8,17 @@ describe('ExpirationDropdown', () => {
const defaultProps = {
name: 'foo',
label: 'label-bar',
- formOptions: [{ key: 'foo', label: 'bar' }, { key: 'baz', label: 'zab' }],
+ formOptions: [
+ { key: 'foo', label: 'bar' },
+ { key: 'baz', label: 'zab' },
+ ],
};
const findFormSelect = () => wrapper.find(GlFormSelect);
const findFormGroup = () => wrapper.find(GlFormGroup);
const findOptions = () => wrapper.findAll('[data-testid="option"]');
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(component, {
stubs: {
GlFormGroup,
diff --git a/spec/frontend/registry/settings/components/expiration_input_spec.js b/spec/frontend/registry/settings/components/expiration_input_spec.js
index 849f85aa265..383158067dc 100644
--- a/spec/frontend/registry/settings/components/expiration_input_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_input_spec.js
@@ -22,7 +22,7 @@ describe('ExpirationInput', () => {
const findDescription = () => wrapper.find('[data-testid="description"]');
const findDescriptionLink = () => wrapper.find(GlLink);
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(component, {
stubs: {
GlSprintf,
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 c594b1f449d..d74ee2d1c18 100644
--- a/spec/frontend/registry/settings/components/expiration_run_text_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_run_text_spec.js
@@ -11,7 +11,7 @@ describe('ExpirationToggle', () => {
const findInput = () => wrapper.find(GlFormInput);
const findFormGroup = () => wrapper.find(GlFormGroup);
- const mountComponent = propsData => {
+ const mountComponent = (propsData) => {
wrapper = shallowMount(component, {
stubs: {
GlFormGroup,
diff --git a/spec/frontend/registry/settings/components/expiration_toggle_spec.js b/spec/frontend/registry/settings/components/expiration_toggle_spec.js
index 99ff7a7f77a..ce016e852ee 100644
--- a/spec/frontend/registry/settings/components/expiration_toggle_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_toggle_spec.js
@@ -13,7 +13,7 @@ describe('ExpirationToggle', () => {
const findToggle = () => wrapper.find(GlToggle);
const findDescription = () => wrapper.find('[data-testid="description"]');
- const mountComponent = propsData => {
+ const mountComponent = (propsData) => {
wrapper = shallowMount(component, {
stubs: {
GlFormGroup,
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 c31c7bdf99b..32d4f16221d 100644
--- a/spec/frontend/registry/settings/components/registry_settings_app_spec.js
+++ b/spec/frontend/registry/settings/components/registry_settings_app_spec.js
@@ -1,7 +1,7 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
@@ -59,7 +59,7 @@ describe('Registry Settings App', () => {
apolloProvider: fakeApollo,
});
- return requestHandlers.map(request => request[1]);
+ return requestHandlers.map((request) => request[1]);
};
afterEach(() => {
diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js
index b89269c0ae4..626f4fcc9f5 100644
--- a/spec/frontend/registry/settings/components/settings_form_spec.js
+++ b/spec/frontend/registry/settings/components/settings_form_spec.js
@@ -1,6 +1,6 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+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';
@@ -103,7 +103,7 @@ describe('Settings Form', () => {
},
});
- return requestHandlers.map(resolvers => resolvers[1]);
+ return requestHandlers.map((resolvers) => resolvers[1]);
};
beforeEach(() => {
diff --git a/spec/frontend/registry/settings/mock_data.js b/spec/frontend/registry/settings/mock_data.js
index 7cc645fcf55..9778f409010 100644
--- a/spec/frontend/registry/settings/mock_data.js
+++ b/spec/frontend/registry/settings/mock_data.js
@@ -8,7 +8,7 @@ export const containerExpirationPolicyData = () => ({
nextRunAt: '2020-11-19T07:37:03.941Z',
});
-export const expirationPolicyPayload = override => ({
+export const expirationPolicyPayload = (override) => ({
data: {
project: {
containerExpirationPolicy: {
diff --git a/spec/frontend/registry/settings/utils_spec.js b/spec/frontend/registry/settings/utils_spec.js
index f92d51db307..7bc627908af 100644
--- a/spec/frontend/registry/settings/utils_spec.js
+++ b/spec/frontend/registry/settings/utils_spec.js
@@ -11,7 +11,10 @@ describe('Utils', () => {
[{ variable: 1 }, { variable: 2 }],
olderThanTranslationGenerator,
);
- expect(result).toEqual([{ variable: 1, label: '1 day' }, { variable: 2, label: '2 days' }]);
+ expect(result).toEqual([
+ { variable: 1, label: '1 day' },
+ { variable: 2, label: '2 days' },
+ ]);
});
});
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 db33a9cdce1..c084410c65b 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
@@ -14,7 +14,7 @@ describe('RelatedMergeRequests', () => {
let mock;
let mockData;
- beforeEach(done => {
+ beforeEach((done) => {
loadFixtures(FIXTURE_PATH);
mockData = getJSONFixture(FIXTURE_PATH);
@@ -73,10 +73,7 @@ describe('RelatedMergeRequests', () => {
expect(wrapper.find('.js-items-count').text()).toEqual('2');
expect(wrapper.findAll(RelatedIssuableItem).length).toEqual(2);
- const props = wrapper
- .findAll(RelatedIssuableItem)
- .at(1)
- .props();
+ const props = wrapper.findAll(RelatedIssuableItem).at(1).props();
const data = mockData[1];
expect(props.idKey).toEqual(data.id);
diff --git a/spec/frontend/related_merge_requests/store/actions_spec.js b/spec/frontend/related_merge_requests/store/actions_spec.js
index fa031a91c83..a4257d67176 100644
--- a/spec/frontend/related_merge_requests/store/actions_spec.js
+++ b/spec/frontend/related_merge_requests/store/actions_spec.js
@@ -23,7 +23,7 @@ describe('RelatedMergeRequest store actions', () => {
});
describe('setInitialState', () => {
- it('commits types.SET_INITIAL_STATE with given props', done => {
+ it('commits types.SET_INITIAL_STATE with given props', (done) => {
const props = { a: 1, b: 2 };
testAction(
@@ -38,13 +38,13 @@ describe('RelatedMergeRequest store actions', () => {
});
describe('requestData', () => {
- it('commits types.REQUEST_DATA', done => {
+ it('commits types.REQUEST_DATA', (done) => {
testAction(actions.requestData, null, {}, [{ type: types.REQUEST_DATA }], [], done);
});
});
describe('receiveDataSuccess', () => {
- it('commits types.RECEIVE_DATA_SUCCESS with data', done => {
+ it('commits types.RECEIVE_DATA_SUCCESS with data', (done) => {
const data = { a: 1, b: 2 };
testAction(
@@ -59,7 +59,7 @@ describe('RelatedMergeRequest store actions', () => {
});
describe('receiveDataError', () => {
- it('commits types.RECEIVE_DATA_ERROR', done => {
+ it('commits types.RECEIVE_DATA_ERROR', (done) => {
testAction(
actions.receiveDataError,
null,
@@ -73,7 +73,7 @@ describe('RelatedMergeRequest store actions', () => {
describe('fetchMergeRequests', () => {
describe('for a successful request', () => {
- it('should dispatch success action', done => {
+ it('should dispatch success action', (done) => {
const data = { a: 1 };
mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(200, data, { 'x-total': 2 });
@@ -89,7 +89,7 @@ describe('RelatedMergeRequest store actions', () => {
});
describe('for a failing request', () => {
- it('should dispatch error action', done => {
+ it('should dispatch error action', (done) => {
mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(400);
testAction(
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
index f49d3d7b716..c9f84be97c4 100644
--- a/spec/frontend/releases/__snapshots__/util_spec.js.snap
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -89,18 +89,6 @@ Object {
],
"milestones": Array [
Object {
- "description": "The 12.4 milestone",
- "id": "gid://gitlab/Milestone/124",
- "issueStats": Object {
- "closed": 1,
- "total": 4,
- },
- "stats": undefined,
- "title": "12.4",
- "webPath": undefined,
- "webUrl": "/releases-namespace/releases-project/-/milestones/2",
- },
- Object {
"description": "The 12.3 milestone",
"id": "gid://gitlab/Milestone/123",
"issueStats": Object {
@@ -112,6 +100,18 @@ Object {
"webPath": undefined,
"webUrl": "/releases-namespace/releases-project/-/milestones/1",
},
+ Object {
+ "description": "The 12.4 milestone",
+ "id": "gid://gitlab/Milestone/124",
+ "issueStats": Object {
+ "closed": 1,
+ "total": 4,
+ },
+ "stats": undefined,
+ "title": "12.4",
+ "webPath": undefined,
+ "webUrl": "/releases-namespace/releases-project/-/milestones/2",
+ },
],
"name": "The first release",
"releasedAt": "2018-12-10T00:00:00Z",
@@ -217,18 +217,6 @@ Object {
],
"milestones": Array [
Object {
- "description": "The 12.4 milestone",
- "id": "gid://gitlab/Milestone/124",
- "issueStats": Object {
- "closed": 1,
- "total": 4,
- },
- "stats": undefined,
- "title": "12.4",
- "webPath": undefined,
- "webUrl": "/releases-namespace/releases-project/-/milestones/2",
- },
- Object {
"description": "The 12.3 milestone",
"id": "gid://gitlab/Milestone/123",
"issueStats": Object {
@@ -240,6 +228,18 @@ Object {
"webPath": undefined,
"webUrl": "/releases-namespace/releases-project/-/milestones/1",
},
+ Object {
+ "description": "The 12.4 milestone",
+ "id": "gid://gitlab/Milestone/124",
+ "issueStats": Object {
+ "closed": 1,
+ "total": 4,
+ },
+ "stats": undefined,
+ "title": "12.4",
+ "webPath": undefined,
+ "webUrl": "/releases-namespace/releases-project/-/milestones/2",
+ },
],
"name": "The first release",
"releasedAt": "2018-12-10T00:00:00Z",
diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js
index 1d409b5b590..828d1b46a80 100644
--- a/spec/frontend/releases/components/app_edit_new_spec.js
+++ b/spec/frontend/releases/components/app_edit_new_spec.js
@@ -71,7 +71,7 @@ describe('Release edit/new component', () => {
await wrapper.vm.$nextTick();
- wrapper.element.querySelectorAll('input').forEach(input => jest.spyOn(input, 'focus'));
+ wrapper.element.querySelectorAll('input').forEach((input) => jest.spyOn(input, 'focus'));
};
beforeEach(() => {
@@ -104,7 +104,7 @@ describe('Release edit/new component', () => {
const firstEnabledInput = wrapper.element.querySelector('input:enabled');
const allInputs = wrapper.element.querySelectorAll('input');
- allInputs.forEach(input => {
+ allInputs.forEach((input) => {
const expectedFocusCalls = input === firstEnabledInput ? 1 : 0;
expect(input.focus).toHaveBeenCalledTimes(expectedFocusCalls);
});
@@ -152,7 +152,7 @@ describe('Release edit/new component', () => {
beforeEach(async () => {
commonUtils.getParameterByName = jest
.fn()
- .mockImplementation(paramToGet => ({ [BACK_URL_PARAM]: backUrl }[paramToGet]));
+ .mockImplementation((paramToGet) => ({ [BACK_URL_PARAM]: backUrl }[paramToGet]));
await factory();
});
diff --git a/spec/frontend/releases/components/app_index_spec.js b/spec/frontend/releases/components/app_index_spec.js
index 9f1577c2f1e..1481dd30fd4 100644
--- a/spec/frontend/releases/components/app_index_spec.js
+++ b/spec/frontend/releases/components/app_index_spec.js
@@ -13,7 +13,7 @@ import ReleasesPagination from '~/releases/components/releases_pagination.vue';
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
- getParameterByName: jest.fn().mockImplementation(paramName => {
+ getParameterByName: jest.fn().mockImplementation((paramName) => {
return `${paramName}_param_value`;
}),
}));
@@ -28,7 +28,7 @@ describe('Releases App ', () => {
let wrapper;
let fetchReleaseSpy;
- const paginatedReleases = rge(21).map(index => ({
+ const paginatedReleases = rge(21).map((index) => ({
...convertObjectPropsToCamelCase(release, { deep: true }),
tagName: `${index}.00`,
}));
@@ -98,10 +98,10 @@ describe('Releases App ', () => {
});
it('renders loading icon', () => {
- expect(wrapper.contains('.js-loading')).toBe(true);
- expect(wrapper.contains('.js-empty-state')).toBe(false);
- expect(wrapper.contains('.js-success-state')).toBe(false);
- expect(wrapper.contains(ReleasesPagination)).toBe(false);
+ expect(wrapper.find('.js-loading').exists()).toBe(true);
+ expect(wrapper.find('.js-empty-state').exists()).toBe(false);
+ expect(wrapper.find('.js-success-state').exists()).toBe(false);
+ expect(wrapper.find(ReleasesPagination).exists()).toBe(false);
});
});
@@ -115,10 +115,10 @@ describe('Releases App ', () => {
});
it('renders success state', () => {
- expect(wrapper.contains('.js-loading')).toBe(false);
- expect(wrapper.contains('.js-empty-state')).toBe(false);
- expect(wrapper.contains('.js-success-state')).toBe(true);
- expect(wrapper.contains(ReleasesPagination)).toBe(true);
+ expect(wrapper.find('.js-loading').exists()).toBe(false);
+ expect(wrapper.find('.js-empty-state').exists()).toBe(false);
+ expect(wrapper.find('.js-success-state').exists()).toBe(true);
+ expect(wrapper.find(ReleasesPagination).exists()).toBe(true);
});
});
@@ -132,10 +132,10 @@ describe('Releases App ', () => {
});
it('renders success state', () => {
- expect(wrapper.contains('.js-loading')).toBe(false);
- expect(wrapper.contains('.js-empty-state')).toBe(false);
- expect(wrapper.contains('.js-success-state')).toBe(true);
- expect(wrapper.contains(ReleasesPagination)).toBe(true);
+ expect(wrapper.find('.js-loading').exists()).toBe(false);
+ expect(wrapper.find('.js-empty-state').exists()).toBe(false);
+ expect(wrapper.find('.js-success-state').exists()).toBe(true);
+ expect(wrapper.find(ReleasesPagination).exists()).toBe(true);
});
});
@@ -147,9 +147,9 @@ describe('Releases App ', () => {
});
it('renders empty state', () => {
- expect(wrapper.contains('.js-loading')).toBe(false);
- expect(wrapper.contains('.js-empty-state')).toBe(true);
- expect(wrapper.contains('.js-success-state')).toBe(false);
+ expect(wrapper.find('.js-loading').exists()).toBe(false);
+ expect(wrapper.find('.js-empty-state').exists()).toBe(true);
+ expect(wrapper.find('.js-success-state').exists()).toBe(false);
});
});
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index 181fa0150f1..b1f94ca9859 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -17,7 +17,7 @@ describe('Release show component', () => {
release = convertObjectPropsToCamelCase(originalRelease);
});
- const factory = state => {
+ const factory = (state) => {
actions = {
fetchRelease: jest.fn(),
};
diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js
index 6794a56debc..2b2ad0150ab 100644
--- a/spec/frontend/releases/components/asset_links_form_spec.js
+++ b/spec/frontend/releases/components/asset_links_form_spec.js
@@ -30,7 +30,7 @@ describe('Release edit component', () => {
updateAssetLinkName: jest.fn(),
updateAssetLinkType: jest.fn(),
removeAssetLink: jest.fn().mockImplementation((_context, linkId) => {
- state.release.assets.links = state.release.assets.links.filter(l => l.id !== linkId);
+ state.release.assets.links = state.release.assets.links.filter((l) => l.id !== linkId);
}),
};
@@ -104,7 +104,7 @@ describe('Release edit component', () => {
expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled();
};
- const dispatchKeydowEvent = eventParams => {
+ const dispatchKeydowEvent = (eventParams) => {
const event = new KeyboardEvent('keydown', eventParams);
input.dispatchEvent(event);
@@ -162,7 +162,7 @@ describe('Release edit component', () => {
expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled();
};
- const dispatchKeydowEvent = eventParams => {
+ const dispatchKeydowEvent = (eventParams) => {
const event = new KeyboardEvent('keydown', eventParams);
input.dispatchEvent(event);
diff --git a/spec/frontend/releases/components/issuable_stats_spec.js b/spec/frontend/releases/components/issuable_stats_spec.js
index d8211ec2adc..8fc0779da14 100644
--- a/spec/frontend/releases/components/issuable_stats_spec.js
+++ b/spec/frontend/releases/components/issuable_stats_spec.js
@@ -7,7 +7,7 @@ describe('~/releases/components/issuable_stats.vue', () => {
let wrapper;
let defaultProps;
- const createComponent = propUpdates => {
+ const createComponent = (propUpdates) => {
wrapper = mount(IssuableStats, {
propsData: {
...defaultProps,
diff --git a/spec/frontend/releases/components/release_block_assets_spec.js b/spec/frontend/releases/components/release_block_assets_spec.js
index 126ca27e8a6..77bd35f94aa 100644
--- a/spec/frontend/releases/components/release_block_assets_spec.js
+++ b/spec/frontend/releases/components/release_block_assets_spec.js
@@ -26,8 +26,8 @@ describe('Release block assets', () => {
});
};
- const findSectionHeading = type =>
- wrapper.findAll('h5').filter(h5 => h5.text() === sections[type]);
+ const findSectionHeading = (type) =>
+ wrapper.findAll('h5').filter((h5) => h5.text() === sections[type]);
beforeEach(() => {
defaultProps = { assets: convertObjectPropsToCamelCase(assets, { deep: true }) };
@@ -53,7 +53,7 @@ describe('Release block assets', () => {
});
it('renders sources with the expected text and URL', () => {
- defaultProps.assets.sources.forEach(s => {
+ defaultProps.assets.sources.forEach((s) => {
const sourceLink = wrapper.find(`li>a[href="${s.url}"]`);
expect(sourceLink.exists()).toBe(true);
@@ -62,7 +62,7 @@ describe('Release block assets', () => {
});
it('renders a heading for each assets type (except sources)', () => {
- Object.keys(sections).forEach(type => {
+ Object.keys(sections).forEach((type) => {
const sectionHeadings = findSectionHeading(type);
expect(sectionHeadings).toHaveLength(1);
@@ -70,7 +70,7 @@ describe('Release block assets', () => {
});
it('renders asset links with the expected text and URL', () => {
- defaultProps.assets.links.forEach(l => {
+ defaultProps.assets.links.forEach((l) => {
const sourceLink = wrapper.find(`li>a[href="${l.directAssetUrl}"]`);
expect(sourceLink.exists()).toBe(true);
@@ -84,7 +84,7 @@ describe('Release block assets', () => {
beforeEach(() => {
defaultProps.assets.links = defaultProps.assets.links.filter(
- l => l.linkType !== typeToExclude,
+ (l) => l.linkType !== typeToExclude,
);
createComponent(defaultProps);
});
@@ -98,7 +98,7 @@ describe('Release block assets', () => {
describe('sources', () => {
const testSources = ({ shouldSourcesBeRendered }) => {
- assets.sources.forEach(s => {
+ assets.sources.forEach((s) => {
expect(wrapper.find(`a[href="${s.url}"]`).exists()).toBe(shouldSourcesBeRendered);
});
};
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 bb34693c757..4eb15e9da12 100644
--- a/spec/frontend/releases/components/release_block_milestone_info_spec.js
+++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js
@@ -12,7 +12,7 @@ describe('Release block milestone info', () => {
let wrapper;
let milestones;
- const factory = props => {
+ const factory = (props) => {
wrapper = mount(ReleaseBlockMilestoneInfo, {
propsData: props,
});
@@ -54,22 +54,10 @@ describe('Release block milestone info', () => {
});
it('renders a list of links to all associated milestones', () => {
- // The API currently returns the milestones in a non-deterministic order,
- // which causes the frontend fixture used by this test to return the
- // milestones in one order locally and a different order in the CI pipeline.
- // This is a bug and is tracked here: https://gitlab.com/gitlab-org/gitlab/-/issues/259012
- // When this bug is fixed this expectation should be updated to
- // assert the expected order.
- const containerText = trimText(milestoneListContainer().text());
- expect(
- containerText.includes('Milestones 12.4 • 12.3') ||
- containerText.includes('Milestones 12.3 • 12.4'),
- ).toBe(true);
+ expect(milestoneListContainer().text()).toMatchInterpolatedText('Milestones 12.3 • 12.4');
milestones.forEach((m, i) => {
- const milestoneLink = milestoneListContainer()
- .findAll(GlLink)
- .at(i);
+ const milestoneLink = milestoneListContainer().findAll(GlLink).at(i);
expect(milestoneLink.text()).toBe(m.title);
expect(milestoneLink.attributes('href')).toBe(m.webUrl);
@@ -108,19 +96,17 @@ describe('Release block milestone info', () => {
});
}
- fullListString = lotsOfMilestones.map(m => m.title).join(' • ');
+ fullListString = lotsOfMilestones.map((m) => m.title).join(' • ');
abbreviatedListString = lotsOfMilestones
.slice(0, MAX_MILESTONES_TO_DISPLAY)
- .map(m => m.title)
+ .map((m) => m.title)
.join(' • ');
return factory({ milestones: lotsOfMilestones });
});
const clickShowMoreFewerButton = () => {
- milestoneListContainer()
- .find(GlButton)
- .trigger('click');
+ milestoneListContainer().find(GlButton).trigger('click');
return wrapper.vm.$nextTick();
};
@@ -161,7 +147,7 @@ describe('Release block milestone info', () => {
/** Ensures we don't have any issues with dividing by zero when computing percentages */
describe('when all issue counts are zero', () => {
beforeEach(() => {
- milestones = milestones.map(m => ({
+ milestones = milestones.map((m) => ({
...m,
issueStats: {
...m.issueStats,
@@ -178,7 +164,7 @@ describe('Release block milestone info', () => {
describe('if the API response is missing the "issue_stats" property', () => {
beforeEach(() => {
- milestones = milestones.map(m => ({
+ milestones = milestones.map((m) => ({
...m,
issueStats: undefined,
}));
@@ -199,7 +185,7 @@ describe('Release block milestone info', () => {
describe('if the API response includes the "mr_stats" property', () => {
beforeEach(() => {
- milestones = milestones.map(m => ({
+ milestones = milestones.map((m) => ({
...m,
mrStats: {
total: 15,
diff --git a/spec/frontend/releases/components/releases_pagination_graphql_spec.js b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
index bba5e532e5e..cee5e72e1c0 100644
--- a/spec/frontend/releases/components/releases_pagination_graphql_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
@@ -24,7 +24,7 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
const projectPath = 'my/project';
- const createComponent = pageInfo => {
+ const createComponent = (pageInfo) => {
listModule = createListModule({ projectPath });
listModule.state.graphQlPageInfo = pageInfo;
@@ -72,7 +72,7 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
});
it('does not render anything', () => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
diff --git a/spec/frontend/releases/components/releases_pagination_rest_spec.js b/spec/frontend/releases/components/releases_pagination_rest_spec.js
index 59c0c31413a..b015792c96b 100644
--- a/spec/frontend/releases/components/releases_pagination_rest_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_rest_spec.js
@@ -17,7 +17,7 @@ describe('~/releases/components/releases_pagination_rest.vue', () => {
const projectId = 19;
- const createComponent = pageInfo => {
+ const createComponent = (pageInfo) => {
listModule = createListModule({ projectId });
listModule.state.restPageInfo = pageInfo;
diff --git a/spec/frontend/releases/components/releases_pagination_spec.js b/spec/frontend/releases/components/releases_pagination_spec.js
index 2466fb53a68..1d47da31f38 100644
--- a/spec/frontend/releases/components/releases_pagination_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_spec.js
@@ -10,7 +10,7 @@ localVue.use(Vuex);
describe('~/releases/components/releases_pagination.vue', () => {
let wrapper;
- const createComponent = useGraphQLEndpoint => {
+ const createComponent = (useGraphQLEndpoint) => {
const store = new Vuex.Store({
getters: {
useGraphQLEndpoint: () => useGraphQLEndpoint,
diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js
index b6ebc496f33..eba0e286b27 100644
--- a/spec/frontend/releases/components/tag_field_new_spec.js
+++ b/spec/frontend/releases/components/tag_field_new_spec.js
@@ -83,7 +83,7 @@ describe('releases/components/tag_field_new', () => {
* @param {'shown' | 'hidden'} state The expected state of the validation message.
* Should be passed either 'shown' or 'hidden'
*/
- const expectValidationMessageToBe = state => {
+ const expectValidationMessageToBe = (state) => {
return wrapper.vm.$nextTick().then(() => {
expect(findTagNameFormGroup().element).toHaveClass(
state === 'shown' ? 'is-invalid' : 'is-valid',
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index abd0db6a589..396e7bd8745 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -435,7 +435,7 @@ describe('Release detail actions', () => {
expect(api.deleteReleaseLink).toHaveBeenCalledTimes(
getters.releaseLinksToDelete.length,
);
- getters.releaseLinksToDelete.forEach(link => {
+ getters.releaseLinksToDelete.forEach((link) => {
expect(api.deleteReleaseLink).toHaveBeenCalledWith(
state.projectId,
state.tagName,
@@ -446,7 +446,7 @@ describe('Release detail actions', () => {
expect(api.createReleaseLink).toHaveBeenCalledTimes(
getters.releaseLinksToCreate.length,
);
- getters.releaseLinksToCreate.forEach(link => {
+ getters.releaseLinksToCreate.forEach((link) => {
expect(api.createReleaseLink).toHaveBeenCalledWith(
state.projectId,
state.tagName,
diff --git a/spec/frontend/releases/stores/modules/list/helpers.js b/spec/frontend/releases/stores/modules/list/helpers.js
index 3ca255eaf8c..3913eba31b8 100644
--- a/spec/frontend/releases/stores/modules/list/helpers.js
+++ b/spec/frontend/releases/stores/modules/list/helpers.js
@@ -1,5 +1,5 @@
import state from '~/releases/stores/modules/list/state';
-export const resetStore = store => {
+export const resetStore = (store) => {
store.replaceState(state());
};
diff --git a/spec/frontend/reports/accessibility_report/store/actions_spec.js b/spec/frontend/reports/accessibility_report/store/actions_spec.js
index 9f210659cfd..4e607fa5a76 100644
--- a/spec/frontend/reports/accessibility_report/store/actions_spec.js
+++ b/spec/frontend/reports/accessibility_report/store/actions_spec.js
@@ -17,7 +17,7 @@ describe('Accessibility Reports actions', () => {
});
describe('setEndpoints', () => {
- it('should commit SET_ENDPOINTS mutation', done => {
+ it('should commit SET_ENDPOINTS mutation', (done) => {
const endpoint = 'endpoint.json';
testAction(
@@ -46,7 +46,7 @@ describe('Accessibility Reports actions', () => {
});
describe('success', () => {
- it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', done => {
+ it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', (done) => {
const data = { report: { summary: {} } };
mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, data);
@@ -67,7 +67,7 @@ describe('Accessibility Reports actions', () => {
});
describe('error', () => {
- it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', done => {
+ it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
testAction(
@@ -83,7 +83,7 @@ describe('Accessibility Reports actions', () => {
});
describe('receiveReportSuccess', () => {
- it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', done => {
+ it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', (done) => {
testAction(
actions.receiveReportSuccess,
{ status: 200, data: mockReport },
@@ -94,7 +94,7 @@ describe('Accessibility Reports actions', () => {
);
});
- it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', done => {
+ it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', (done) => {
testAction(
actions.receiveReportSuccess,
{ status: 204, data: mockReport },
@@ -107,7 +107,7 @@ describe('Accessibility Reports actions', () => {
});
describe('receiveReportError', () => {
- it('should commit RECEIVE_REPORT_ERROR mutation', done => {
+ it('should commit RECEIVE_REPORT_ERROR mutation', (done) => {
testAction(
actions.receiveReportError,
null,
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 77d7c6f8678..ecb657af6f1 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
@@ -139,11 +139,7 @@ describe('Grouped code quality reports app', () => {
});
it('renders a help icon with more information', () => {
- expect(
- findWidget()
- .find('[data-testid="question-icon"]')
- .exists(),
- ).toBe(true);
+ expect(findWidget().find('[data-testid="question-icon"]').exists()).toBe(true);
});
});
@@ -157,11 +153,7 @@ describe('Grouped code quality reports app', () => {
});
it('does not render a help icon', () => {
- expect(
- findWidget()
- .find('[data-testid="question-icon"]')
- .exists(),
- ).toBe(false);
+ expect(findWidget().find('[data-testid="question-icon"]').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/reports/codequality_report/store/actions_spec.js b/spec/frontend/reports/codequality_report/store/actions_spec.js
index 7d9e4bbbe9f..321785cb85a 100644
--- a/spec/frontend/reports/codequality_report/store/actions_spec.js
+++ b/spec/frontend/reports/codequality_report/store/actions_spec.js
@@ -33,7 +33,7 @@ describe('Codequality Reports actions', () => {
});
describe('setPaths', () => {
- it('should commit SET_PATHS mutation', done => {
+ it('should commit SET_PATHS mutation', (done) => {
const paths = {
basePath: 'basePath',
headPath: 'headPath',
@@ -67,7 +67,7 @@ describe('Codequality Reports actions', () => {
});
describe('on success', () => {
- it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', done => {
+ 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);
@@ -91,7 +91,7 @@ describe('Codequality Reports actions', () => {
});
describe('on error', () => {
- it('commits REQUEST_REPORTS and dispatches receiveReportsError', done => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
mock.onGet(`${TEST_HOST}/head.json`).reply(500);
testAction(
@@ -106,7 +106,7 @@ describe('Codequality Reports actions', () => {
});
describe('with no base path', () => {
- it('commits REQUEST_REPORTS and dispatches receiveReportsError', done => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
localState.basePath = null;
testAction(
@@ -122,7 +122,7 @@ describe('Codequality Reports actions', () => {
});
describe('receiveReportsSuccess', () => {
- it('commits RECEIVE_REPORTS_SUCCESS', done => {
+ it('commits RECEIVE_REPORTS_SUCCESS', (done) => {
const data = { issues: [] };
testAction(
@@ -137,7 +137,7 @@ describe('Codequality Reports actions', () => {
});
describe('receiveReportsError', () => {
- it('commits RECEIVE_REPORTS_ERROR', done => {
+ it('commits RECEIVE_REPORTS_ERROR', (done) => {
testAction(
actions.receiveReportsError,
null,
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 5dd69d3c4d4..085d697672d 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
@@ -11,17 +11,17 @@ jest.mock('~/reports/codequality_report/workers/codequality_comparison_worker',
addEventListener: (_, callback) => {
mockPostMessageCallback = callback;
},
- postMessage: data => {
+ postMessage: (data) => {
if (!data.headIssues) return mockPostMessageCallback({ data: {} });
if (!data.baseIssues) throw new Error();
const key = 'fingerprint';
return mockPostMessageCallback({
data: {
newIssues: data.headIssues.filter(
- item => !data.baseIssues.find(el => el[key] === item[key]),
+ (item) => !data.baseIssues.find((el) => el[key] === item[key]),
),
resolvedIssues: data.baseIssues.filter(
- item => !data.headIssues.find(el => el[key] === item[key]),
+ (item) => !data.headIssues.find((el) => el[key] === item[key]),
),
},
});
diff --git a/spec/frontend/reports/components/grouped_issues_list_spec.js b/spec/frontend/reports/components/grouped_issues_list_spec.js
index 1172e514707..c6eebf05dd7 100644
--- a/spec/frontend/reports/components/grouped_issues_list_spec.js
+++ b/spec/frontend/reports/components/grouped_issues_list_spec.js
@@ -13,7 +13,7 @@ describe('Grouped Issues List', () => {
});
};
- const findHeading = groupName => wrapper.find(`[data-testid="${groupName}Heading"`);
+ const findHeading = (groupName) => wrapper.find(`[data-testid="${groupName}Heading"`);
afterEach(() => {
wrapper.destroy();
@@ -37,7 +37,7 @@ describe('Grouped Issues List', () => {
describe('without data', () => {
beforeEach(createComponent);
- it.each(['unresolved', 'resolved'])('does not a render a header for %s issues', issueName => {
+ it.each(['unresolved', 'resolved'])('does not a render a header for %s issues', (issueName) => {
expect(findHeading(issueName).exists()).toBe(false);
});
@@ -59,7 +59,7 @@ describe('Grouped Issues List', () => {
expect(findHeading(groupName).text()).toBe(givenHeading);
});
- it.each(['resolved', 'unresolved'])('renders all %s issues', issueName => {
+ it.each(['resolved', 'unresolved'])('renders all %s issues', (issueName) => {
const issues = [{ name: 'foo' }, { name: 'bar' }];
createComponent({
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 66d429017b2..492192988fb 100644
--- a/spec/frontend/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
@@ -22,7 +22,7 @@ describe('Grouped test reports app', () => {
let wrapper;
let mockStore;
- const mountComponent = ({ props = { pipelinePath }, testFailureHistory = false } = {}) => {
+ const mountComponent = ({ props = { pipelinePath } } = {}) => {
wrapper = mount(Component, {
store: mockStore,
localVue,
@@ -31,15 +31,10 @@ describe('Grouped test reports app', () => {
pipelinePath,
...props,
},
- provide: {
- glFeatures: {
- testFailureHistory,
- },
- },
});
};
- const setReports = reports => {
+ const setReports = (reports) => {
mockStore.state.status = reports.status;
mockStore.state.summary = reports.summary;
mockStore.state.reports = reports.suites;
@@ -232,11 +227,9 @@ describe('Grouped test reports app', () => {
});
it('renders resolved errors', () => {
- expect(
- findAllIssueDescriptions()
- .at(2)
- .text(),
- ).toContain(resolvedFailures.suites[0].resolved_errors[0].name);
+ expect(findAllIssueDescriptions().at(2).text()).toContain(
+ resolvedFailures.suites[0].resolved_errors[0].name,
+ );
});
});
@@ -244,50 +237,25 @@ describe('Grouped test reports app', () => {
describe('with recent failures counts', () => {
beforeEach(() => {
setReports(recentFailuresTestReports);
+ mountComponent();
});
- describe('with feature flag enabled', () => {
- beforeEach(() => {
- mountComponent({ testFailureHistory: true });
- });
-
- it('renders the recently failed tests summary', () => {
- expect(findHeader().text()).toContain(
- '2 out of 3 failed tests have failed more than once in the last 14 days',
- );
- });
-
- it('renders the recently failed count on the test suite', () => {
- expect(findSummaryDescription().text()).toContain(
- '1 out of 2 failed tests has failed more than once in the last 14 days',
- );
- });
-
- it('renders the recent failures count on the test case', () => {
- expect(findIssueDescription().text()).toContain(
- 'Failed 8 times in master in the last 14 days',
- );
- });
+ it('renders the recently failed tests summary', () => {
+ expect(findHeader().text()).toContain(
+ '2 out of 3 failed tests have failed more than once in the last 14 days',
+ );
});
- describe('with feature flag disabled', () => {
- beforeEach(() => {
- mountComponent({ testFailureHistory: false });
- });
-
- it('does not render the recently failed tests summary', () => {
- expect(findHeader().text()).not.toContain('failed more than once in the last 14 days');
- });
-
- it('does not render the recently failed count on the test suite', () => {
- expect(findSummaryDescription().text()).not.toContain(
- 'failed more than once in the last 14 days',
- );
- });
+ it('renders the recently failed count on the test suite', () => {
+ expect(findSummaryDescription().text()).toContain(
+ '1 out of 2 failed tests has failed more than once in the last 14 days',
+ );
+ });
- it('renders the recent failures count on the test case', () => {
- expect(findIssueDescription().text()).not.toContain('in the last 14 days');
- });
+ it('renders the recent failures count on the test case', () => {
+ expect(findIssueDescription().text()).toContain(
+ 'Failed 8 times in master in the last 14 days',
+ );
});
});
diff --git a/spec/frontend/reports/components/issue_status_icon_spec.js b/spec/frontend/reports/components/issue_status_icon_spec.js
index 3a55ff0a9e3..8706f2f8d83 100644
--- a/spec/frontend/reports/components/issue_status_icon_spec.js
+++ b/spec/frontend/reports/components/issue_status_icon_spec.js
@@ -20,7 +20,7 @@ describe('IssueStatusIcon', () => {
it.each([STATUS_SUCCESS, STATUS_NEUTRAL, STATUS_FAILED])(
'renders "%s" state correctly',
- status => {
+ (status) => {
createComponent({ status });
expect(wrapper.element).toMatchSnapshot();
diff --git a/spec/frontend/reports/components/modal_open_name_spec.js b/spec/frontend/reports/components/modal_open_name_spec.js
deleted file mode 100644
index d59f3571c4b..00000000000
--- a/spec/frontend/reports/components/modal_open_name_spec.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
-import component from '~/reports/components/modal_open_name.vue';
-
-Vue.use(Vuex);
-
-describe('Modal open name', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const store = new Vuex.Store({
- actions: {
- openModal: () => {},
- },
- state: {},
- mutations: {},
- });
-
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- store,
- props: {
- issue: {
- title: 'Issue',
- },
- status: 'failed',
- },
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders the issue name', () => {
- expect(vm.$el.textContent.trim()).toEqual('Issue');
- });
-
- it('calls openModal actions when button is clicked', () => {
- jest.spyOn(vm, 'openModal').mockImplementation(() => {});
-
- vm.$el.click();
-
- expect(vm.openModal).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/reports/components/modal_spec.js b/spec/frontend/reports/components/modal_spec.js
index ff046e64b6e..39b84d1ee05 100644
--- a/spec/frontend/reports/components/modal_spec.js
+++ b/spec/frontend/reports/components/modal_spec.js
@@ -1,54 +1,63 @@
-import Vue from 'vue';
-import component from '~/reports/components/modal.vue';
+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 mountComponent from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
+
+const StubbedGlModal = { template: '<div><slot></slot></div>', name: 'GlModal', props: ['title'] };
describe('Grouped Test Reports Modal', () => {
- const Component = Vue.extend(component);
const modalDataStructure = state().modal.data;
+ const title = 'Test#sum when a is 1 and b is 2 returns summary';
// populate data
modalDataStructure.execution_time.value = 0.009411;
modalDataStructure.system_output.value = 'Failure/Error: is_expected.to eq(3)\n\n';
modalDataStructure.class.value = 'link';
- let vm;
+ let wrapper;
beforeEach(() => {
- vm = mountComponent(Component, {
- title: 'Test#sum when a is 1 and b is 2 returns summary',
- modalData: modalDataStructure,
- });
+ wrapper = extendedWrapper(
+ shallowMount(ReportsModal, {
+ propsData: {
+ title,
+ modalData: modalDataStructure,
+ visible: true,
+ },
+ stubs: { GlModal: StubbedGlModal, GlSprintf },
+ }),
+ );
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders code block', () => {
- expect(vm.$el.querySelector('code').textContent).toEqual(
- modalDataStructure.system_output.value,
- );
+ expect(wrapper.find(CodeBlock).props().code).toEqual(modalDataStructure.system_output.value);
});
it('renders link', () => {
- expect(vm.$el.querySelector('.js-modal-link').getAttribute('href')).toEqual(
- modalDataStructure.class.value,
- );
+ const link = wrapper.findComponent(GlLink);
- expect(trimText(vm.$el.querySelector('.js-modal-link').textContent)).toEqual(
- modalDataStructure.class.value,
- );
+ expect(link.attributes().href).toEqual(modalDataStructure.class.value);
+
+ expect(link.text()).toEqual(modalDataStructure.class.value);
});
it('renders seconds', () => {
- expect(vm.$el.textContent).toContain(`${modalDataStructure.execution_time.value} s`);
+ expect(wrapper.text()).toContain(`${modalDataStructure.execution_time.value} s`);
});
it('render title', () => {
- expect(trimText(vm.$el.querySelector('.modal-title').textContent)).toEqual(
- 'Test#sum when a is 1 and b is 2 returns summary',
- );
+ expect(wrapper.findComponent(StubbedGlModal).props().title).toEqual(title);
+ });
+
+ it('re-emits hide event', () => {
+ wrapper.findComponent(StubbedGlModal).vm.$emit('hide');
+ expect(wrapper.emitted().hide).toEqual([[]]);
});
});
diff --git a/spec/frontend/reports/components/report_link_spec.js b/spec/frontend/reports/components/report_link_spec.js
index f879899e9c5..fc21515ded6 100644
--- a/spec/frontend/reports/components/report_link_spec.js
+++ b/spec/frontend/reports/components/report_link_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/reports/components/report_link.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
describe('report link', () => {
let vm;
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index 2d228313a9b..c3219b34057 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -29,7 +29,7 @@ describe('Report section', () => {
alwaysOpen: false,
};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(reportSection, {
propsData: {
...defaultProps,
@@ -67,7 +67,7 @@ describe('Report section', () => {
const issues = hasIssues ? 'has issues' : 'has no issues';
const open = alwaysOpen ? 'is always open' : 'is not always open';
- it(`is ${isCollapsible}, if the report ${issues} and ${open}`, done => {
+ it(`is ${isCollapsible}, if the report ${issues} and ${open}`, (done) => {
vm.hasIssues = hasIssues;
vm.alwaysOpen = alwaysOpen;
@@ -93,7 +93,7 @@ describe('Report section', () => {
const issues = isCollapsed ? 'is collapsed' : 'is not collapsed';
const open = alwaysOpen ? 'is always open' : 'is not always open';
- it(`is ${isExpanded}, if the report ${issues} and ${open}`, done => {
+ it(`is ${isExpanded}, if the report ${issues} and ${open}`, (done) => {
vm.isCollapsed = isCollapsed;
vm.alwaysOpen = alwaysOpen;
@@ -144,7 +144,7 @@ describe('Report section', () => {
describe('toggleCollapsed', () => {
const hiddenCss = { display: 'none' };
- it('toggles issues', done => {
+ it('toggles issues', (done) => {
vm.$el.querySelector('button').click();
Vue.nextTick()
@@ -163,7 +163,7 @@ describe('Report section', () => {
.catch(done.fail);
});
- it('is always expanded, if always-open is set to true', done => {
+ it('is always expanded, if always-open is set to true', (done) => {
vm.alwaysOpen = true;
Vue.nextTick()
.then(() => {
@@ -177,7 +177,7 @@ describe('Report section', () => {
});
describe('snowplow events', () => {
- it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', done => {
+ it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', (done) => {
createComponent({ hasIssues: true, shouldEmitToggleEvent: true });
expect(wrapper.emitted().toggleEvent).toBeUndefined();
@@ -192,7 +192,7 @@ describe('Report section', () => {
.catch(done.fail);
});
- it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', done => {
+ it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', (done) => {
createComponent({ hasIssues: true });
expect(wrapper.emitted().toggleEvent).toBeUndefined();
@@ -207,7 +207,7 @@ describe('Report section', () => {
.catch(done.fail);
});
- it('does not emit an event if always-open is set to true', done => {
+ it('does not emit an event if always-open is set to true', (done) => {
createComponent({ alwaysOpen: true, hasIssues: true, shouldEmitToggleEvent: true });
wrapper.vm
@@ -259,7 +259,7 @@ describe('Report section', () => {
});
describe('Success and Error slots', () => {
- const createComponentWithSlots = status => {
+ const createComponentWithSlots = (status) => {
vm = mountComponentWithSlots(ReportSection, {
props: {
status,
diff --git a/spec/frontend/reports/components/test_issue_body_spec.js b/spec/frontend/reports/components/test_issue_body_spec.js
index ff81020a4eb..c13a3599fef 100644
--- a/spec/frontend/reports/components/test_issue_body_spec.js
+++ b/spec/frontend/reports/components/test_issue_body_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { trimText } from 'helpers/text_helper';
import component from '~/reports/components/test_issue_body.vue';
import createStore from '~/reports/store';
-import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
import { issue } from '../mock_data/mock_data';
describe('Test Issue body', () => {
diff --git a/spec/frontend/reports/store/actions_spec.js b/spec/frontend/reports/store/actions_spec.js
index 3f189736922..b7c4a31b1c8 100644
--- a/spec/frontend/reports/store/actions_spec.js
+++ b/spec/frontend/reports/store/actions_spec.js
@@ -11,7 +11,7 @@ import {
receiveReportsSuccess,
receiveReportsError,
openModal,
- setModalData,
+ closeModal,
} from '~/reports/store/actions';
import state from '~/reports/store/state';
import * as types from '~/reports/store/mutation_types';
@@ -24,7 +24,7 @@ describe('Reports Store Actions', () => {
});
describe('setEndpoint', () => {
- it('should commit SET_ENDPOINT mutation', done => {
+ it('should commit SET_ENDPOINT mutation', (done) => {
testAction(
setEndpoint,
'endpoint.json',
@@ -37,7 +37,7 @@ describe('Reports Store Actions', () => {
});
describe('requestReports', () => {
- it('should commit REQUEST_REPORTS mutation', done => {
+ it('should commit REQUEST_REPORTS mutation', (done) => {
testAction(requestReports, null, mockedState, [{ type: types.REQUEST_REPORTS }], [], done);
});
});
@@ -57,7 +57,7 @@ describe('Reports Store Actions', () => {
});
describe('success', () => {
- it('dispatches requestReports and receiveReportsSuccess ', done => {
+ it('dispatches requestReports and receiveReportsSuccess ', (done) => {
mock
.onGet(`${TEST_HOST}/endpoint.json`)
.replyOnce(200, { summary: {}, suites: [{ name: 'rspec' }] });
@@ -86,7 +86,7 @@ describe('Reports Store Actions', () => {
mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
});
- it('dispatches requestReports and receiveReportsError ', done => {
+ it('dispatches requestReports and receiveReportsError ', (done) => {
testAction(
fetchReports,
null,
@@ -107,7 +107,7 @@ describe('Reports Store Actions', () => {
});
describe('receiveReportsSuccess', () => {
- it('should commit RECEIVE_REPORTS_SUCCESS mutation with 200', done => {
+ it('should commit RECEIVE_REPORTS_SUCCESS mutation with 200', (done) => {
testAction(
receiveReportsSuccess,
{ data: { summary: {} }, status: 200 },
@@ -118,7 +118,7 @@ describe('Reports Store Actions', () => {
);
});
- it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', done => {
+ it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', (done) => {
testAction(
receiveReportsSuccess,
{ data: { summary: {} }, status: 204 },
@@ -131,7 +131,7 @@ describe('Reports Store Actions', () => {
});
describe('receiveReportsError', () => {
- it('should commit RECEIVE_REPORTS_ERROR mutation', done => {
+ it('should commit RECEIVE_REPORTS_ERROR mutation', (done) => {
testAction(
receiveReportsError,
null,
@@ -144,25 +144,25 @@ describe('Reports Store Actions', () => {
});
describe('openModal', () => {
- it('should dispatch setModalData', done => {
+ it('should commit SET_ISSUE_MODAL_DATA', (done) => {
testAction(
openModal,
{ name: 'foo' },
mockedState,
+ [{ type: types.SET_ISSUE_MODAL_DATA, payload: { name: 'foo' } }],
[],
- [{ type: 'setModalData', payload: { name: 'foo' } }],
done,
);
});
});
- describe('setModalData', () => {
- it('should commit SET_ISSUE_MODAL_DATA', done => {
+ describe('closeModal', () => {
+ it('should commit RESET_ISSUE_MODAL_DATA', (done) => {
testAction(
- setModalData,
- { name: 'foo' },
+ closeModal,
+ {},
mockedState,
- [{ type: types.SET_ISSUE_MODAL_DATA, payload: { name: 'foo' } }],
+ [{ type: types.RESET_ISSUE_MODAL_DATA, payload: {} }],
[],
done,
);
diff --git a/spec/frontend/reports/store/mutations_spec.js b/spec/frontend/reports/store/mutations_spec.js
index c1c5862a37c..59065d1151f 100644
--- a/spec/frontend/reports/store/mutations_spec.js
+++ b/spec/frontend/reports/store/mutations_spec.js
@@ -127,5 +127,32 @@ describe('Reports Store Mutations', () => {
expect(stateCopy.modal.data.execution_time.value).toEqual(issue.execution_time);
expect(stateCopy.modal.data.system_output.value).toEqual(issue.system_output);
});
+
+ it('should open modal', () => {
+ expect(stateCopy.modal.open).toEqual(true);
+ });
+ });
+
+ describe('RESET_ISSUE_MODAL_DATA', () => {
+ beforeEach(() => {
+ mutations[types.SET_ISSUE_MODAL_DATA](stateCopy, {
+ issue,
+ });
+
+ mutations[types.RESET_ISSUE_MODAL_DATA](stateCopy);
+ });
+
+ it('should reset modal title', () => {
+ expect(stateCopy.modal.title).toEqual(null);
+ });
+
+ it('should reset modal data', () => {
+ expect(stateCopy.modal.data.execution_time.value).toEqual(null);
+ expect(stateCopy.modal.data.system_output.value).toEqual(null);
+ });
+
+ it('should close modal', () => {
+ expect(stateCopy.modal.open).toEqual(false);
+ });
});
});
diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js
index 38e5c9aaca5..a0dc608ddc9 100644
--- a/spec/frontend/repository/components/breadcrumbs_spec.js
+++ b/spec/frontend/repository/components/breadcrumbs_spec.js
@@ -36,23 +36,15 @@ describe('Repository breadcrumbs component', () => {
it('escapes hash in directory path', () => {
factory('app/assets/javascripts#');
- expect(
- vm
- .findAll(RouterLinkStub)
- .at(3)
- .props('to'),
- ).toEqual('/-/tree/app/assets/javascripts%23');
+ expect(vm.findAll(RouterLinkStub).at(3).props('to')).toEqual(
+ '/-/tree/app/assets/javascripts%23',
+ );
});
it('renders last link as active', () => {
factory('app/assets');
- expect(
- vm
- .findAll(RouterLinkStub)
- .at(2)
- .attributes('aria-current'),
- ).toEqual('page');
+ expect(vm.findAll(RouterLinkStub).at(2).attributes('aria-current')).toEqual('page');
});
it('does not render add to tree dropdown when permissions are false', () => {
diff --git a/spec/frontend/repository/components/directory_download_links_spec.js b/spec/frontend/repository/components/directory_download_links_spec.js
index 4d70b44de08..72c4165c2e9 100644
--- a/spec/frontend/repository/components/directory_download_links_spec.js
+++ b/spec/frontend/repository/components/directory_download_links_spec.js
@@ -7,7 +7,10 @@ function factory(currentPath) {
vm = shallowMount(DirectoryDownloadLinks, {
propsData: {
currentPath,
- links: [{ text: 'zip', path: 'http://test.com/' }, { text: 'tar', path: 'http://test.com/' }],
+ links: [
+ { text: 'zip', path: 'http://test.com/' },
+ { text: 'tar', path: 'http://test.com/' },
+ ],
},
});
}
diff --git a/spec/frontend/repository/components/last_commit_spec.js b/spec/frontend/repository/components/last_commit_spec.js
index ccba0982c26..fe77057c3d4 100644
--- a/spec/frontend/repository/components/last_commit_spec.js
+++ b/spec/frontend/repository/components/last_commit_spec.js
@@ -131,6 +131,16 @@ describe('Repository last commit component', () => {
});
});
+ it('strips the first newline of the description', async () => {
+ factory(createCommitData({ descriptionHtml: '&#x000A;Update ADOPTERS.md' }));
+
+ await vm.vm.$nextTick();
+
+ expect(vm.find('.commit-row-description').html()).toBe(
+ '<pre class="commit-row-description gl-mb-3">Update ADOPTERS.md</pre>',
+ );
+ });
+
it('renders the signature HTML as returned by the backend', () => {
factory(createCommitData({ signatureHtml: '<button>Verified</button>' }));
diff --git a/spec/frontend/repository/utils/dom_spec.js b/spec/frontend/repository/utils/dom_spec.js
index 26ed57f0392..f9e619a82d1 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 { setHTMLFixture } from 'helpers/fixtures';
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 3490a99afb4..1b31030cb92 100644
--- a/spec/frontend/right_sidebar_spec.js
+++ b/spec/frontend/right_sidebar_spec.js
@@ -12,7 +12,7 @@ let $collapseIcon = null;
let $page = null;
let $labelsIcon = null;
-const assertSidebarState = state => {
+const assertSidebarState = (state) => {
const shouldBeExpanded = state === 'expanded';
const shouldBeCollapsed = state === 'collapsed';
expect($aside.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded);
@@ -67,7 +67,7 @@ describe('RightSidebar', () => {
assertSidebarState('collapsed');
});
- it('should broadcast todo:toggle event when add todo clicked', done => {
+ it('should broadcast todo:toggle event when add todo clicked', (done) => {
const todos = getJSONFixture('todos/todos.json');
mock.onPost(/(.*)\/todos$/).reply(200, todos);
@@ -84,7 +84,7 @@ describe('RightSidebar', () => {
});
it('should not hide collapsed icons', () => {
- [].forEach.call(document.querySelectorAll('.sidebar-collapsed-icon'), el => {
+ [].forEach.call(document.querySelectorAll('.sidebar-collapsed-icon'), (el) => {
expect(el.querySelector('.fa, svg').classList.contains('hidden')).toBeFalsy();
});
});
diff --git a/spec/frontend/search/index_spec.js b/spec/frontend/search/index_spec.js
index 31b5aa3686b..023cd341345 100644
--- a/spec/frontend/search/index_spec.js
+++ b/spec/frontend/search/index_spec.js
@@ -8,7 +8,7 @@ jest.mock('~/search/sidebar');
describe('initSearchApp', () => {
let defaultLocation;
- const setUrl = query => {
+ const setUrl = (query) => {
window.location.href = `https://localhost:3000/search${query}`;
window.location.search = query;
};
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
index d2c0081080c..94a39b90d02 100644
--- a/spec/frontend/search/sidebar/components/app_spec.js
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -17,7 +17,7 @@ describe('GlobalSearchSidebar', () => {
resetQuery: jest.fn(),
};
- const createComponent = initialState => {
+ const createComponent = (initialState) => {
const store = new Vuex.Store({
state: {
query: MOCK_QUERY,
diff --git a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
index 68d20b2480e..42fcc859308 100644
--- a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
@@ -15,7 +15,7 @@ describe('ConfidentialityFilter', () => {
resetQuery: jest.fn(),
};
- const createComponent = initialState => {
+ const createComponent = (initialState) => {
const store = new Vuex.Store({
state: {
query: MOCK_QUERY,
diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js
index 31a4a8859ee..9918af54cfe 100644
--- a/spec/frontend/search/sidebar/components/radio_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js
@@ -46,7 +46,7 @@ describe('RadioFilter', () => {
const findGlRadioButtonGroup = () => wrapper.find(GlFormRadioGroup);
const findGlRadioButtons = () => findGlRadioButtonGroup().findAll(GlFormRadio);
- const findGlRadioButtonsText = () => findGlRadioButtons().wrappers.map(w => w.text());
+ const findGlRadioButtonsText = () => findGlRadioButtons().wrappers.map((w) => w.text());
describe('template', () => {
beforeEach(() => {
@@ -61,7 +61,7 @@ describe('RadioFilter', () => {
describe('Status Filter', () => {
it('renders a radio button for each filterOption', () => {
expect(findGlRadioButtonsText()).toStrictEqual(
- stateFilterData.filterByScope[stateFilterData.scopes.ISSUES].map(f => {
+ stateFilterData.filterByScope[stateFilterData.scopes.ISSUES].map((f) => {
return f.value === stateFilterData.filters.ANY.value
? `Any ${stateFilterData.header.toLowerCase()}`
: f.label;
@@ -87,7 +87,7 @@ describe('RadioFilter', () => {
it('renders a radio button for each filterOption', () => {
expect(findGlRadioButtonsText()).toStrictEqual(
- confidentialFilterData.filterByScope[confidentialFilterData.scopes.ISSUES].map(f => {
+ confidentialFilterData.filterByScope[confidentialFilterData.scopes.ISSUES].map((f) => {
return f.value === confidentialFilterData.filters.ANY.value
? `Any ${confidentialFilterData.header.toLowerCase()}`
: f.label;
diff --git a/spec/frontend/search/sidebar/components/status_filter_spec.js b/spec/frontend/search/sidebar/components/status_filter_spec.js
index 188d47b38cd..21fc663397e 100644
--- a/spec/frontend/search/sidebar/components/status_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/status_filter_spec.js
@@ -15,7 +15,7 @@ describe('StatusFilter', () => {
resetQuery: jest.fn(),
};
- const createComponent = initialState => {
+ const createComponent = (initialState) => {
const store = new Vuex.Store({
state: {
query: MOCK_QUERY,
diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
index c4ebaabbf96..86e29571d0f 100644
--- a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
+++ b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
@@ -47,7 +47,7 @@ describe('Global Search Searchable Dropdown', () => {
const findGlDropdownSearch = () => findGlDropdown().find(GlSearchBoxByType);
const findDropdownText = () => findGlDropdown().find('.dropdown-toggle-text');
const findDropdownItems = () => findGlDropdown().findAll(GlDropdownItem);
- const findDropdownItemsText = () => findDropdownItems().wrappers.map(w => w.text());
+ const findDropdownItemsText = () => findDropdownItems().wrappers.map((w) => w.text());
const findAnyDropdownItem = () => findDropdownItems().at(0);
const findFirstGroupDropdownItem = () => findDropdownItems().at(1);
const findLoader = () => wrapper.find(GlSkeletonLoader);
@@ -94,7 +94,7 @@ describe('Global Search Searchable Dropdown', () => {
});
it('renders an instance for each namespace', () => {
- const resultsIncludeAny = ['Any'].concat(MOCK_GROUPS.map(n => n.full_name));
+ const resultsIncludeAny = ['Any'].concat(MOCK_GROUPS.map((n) => n.full_name));
expect(findDropdownItemsText()).toStrictEqual(resultsIncludeAny);
});
});
diff --git a/spec/frontend/search_autocomplete_spec.js b/spec/frontend/search_autocomplete_spec.js
index 3240664f5aa..e844bc96e05 100644
--- a/spec/frontend/search_autocomplete_spec.js
+++ b/spec/frontend/search_autocomplete_spec.js
@@ -32,7 +32,7 @@ describe('Search autocomplete dropdown', () => {
// Add required attributes to body before starting the test.
// section would be dashboard|group|project
- const addBodyAttributes = section => {
+ const addBodyAttributes = (section) => {
if (section == null) {
section = 'dashboard';
}
@@ -213,10 +213,10 @@ describe('Search autocomplete dropdown', () => {
});
function triggerAutocomplete() {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
const dropdown = widget.searchInput.data('deprecatedJQueryDropdown');
const filterCallback = dropdown.filter.options.callback;
- dropdown.filter.options.callback = jest.fn(data => {
+ dropdown.filter.options.callback = jest.fn((data) => {
filterCallback(data);
resolve();
@@ -227,7 +227,7 @@ describe('Search autocomplete dropdown', () => {
});
}
- it('suggest Projects', done => {
+ it('suggest Projects', (done) => {
// eslint-disable-next-line promise/catch-or-return
triggerAutocomplete().finally(() => {
const list = widget.wrap.find('.dropdown-menu').find('ul');
@@ -242,7 +242,7 @@ describe('Search autocomplete dropdown', () => {
jest.runOnlyPendingTimers();
});
- it('suggest Groups', done => {
+ it('suggest Groups', (done) => {
// eslint-disable-next-line promise/catch-or-return
triggerAutocomplete().finally(() => {
const list = widget.wrap.find('.dropdown-menu').find('ul');
diff --git a/spec/frontend/search_settings/components/search_settings_spec.js b/spec/frontend/search_settings/components/search_settings_spec.js
new file mode 100644
index 00000000000..b80f9b15abf
--- /dev/null
+++ b/spec/frontend/search_settings/components/search_settings_spec.js
@@ -0,0 +1,106 @@
+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';
+
+describe('search_settings/components/search_settings.vue', () => {
+ const ROOT_ID = 'content-body';
+ const SECTION_SELECTOR = 'section.settings';
+ const SEARCH_TERM = 'Delete project';
+ const GENERAL_SETTINGS_ID = 'js-general-settings';
+ const ADVANCED_SETTINGS_ID = 'js-advanced-settings';
+ let wrapper;
+
+ const buildWrapper = () => {
+ wrapper = shallowMount(SearchSettings, {
+ propsData: {
+ searchRoot: document.querySelector(`#${ROOT_ID}`),
+ sectionSelector: SECTION_SELECTOR,
+ },
+ });
+ };
+
+ const sections = () => Array.from(document.querySelectorAll(SECTION_SELECTOR));
+ const sectionsCount = () => sections().length;
+ const visibleSectionsCount = () =>
+ document.querySelectorAll(`${SECTION_SELECTOR}:not(.${HIDE_CLASS})`).length;
+ const highlightedElementsCount = () => document.querySelectorAll(`.${HIGHLIGHT_CLASS}`).length;
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
+ const search = (term) => {
+ findSearchBox().vm.$emit('input', term);
+ };
+ const clearSearch = () => search('');
+
+ beforeEach(() => {
+ setFixtures(`
+ <div>
+ <div class="js-search-app"></div>
+ <div id="${ROOT_ID}">
+ <section id="${GENERAL_SETTINGS_ID}" class="settings">
+ <span>General</span>
+ </section>
+ <section id="${ADVANCED_SETTINGS_ID}" class="settings">
+ <span>${SEARCH_TERM}</span>
+ </section>
+ </div>
+ </div>
+ `);
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ 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);
+
+ expect(visibleSectionsCount()).toBe(1);
+ expect(hiddenSection.classList).toContain(HIDE_CLASS);
+ });
+
+ it('expands section that matches the search term', () => {
+ const section = document.querySelector(`#${ADVANCED_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);
+ });
+
+ it('highlight elements that match the search term', () => {
+ search(SEARCH_TERM);
+
+ 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());
+ });
+
+ it('removes the highlight from all elements', () => {
+ expect(highlightedElementsCount()).toBe(1);
+ clearSearch();
+ expect(highlightedElementsCount()).toBe(0);
+ });
+ });
+});
diff --git a/spec/frontend/search_settings/index_spec.js b/spec/frontend/search_settings/index_spec.js
new file mode 100644
index 00000000000..122ee1251bb
--- /dev/null
+++ b/spec/frontend/search_settings/index_spec.js
@@ -0,0 +1,36 @@
+import $ from 'jquery';
+import { setHTMLFixture } from 'helpers/fixtures';
+import initSearch from '~/search_settings';
+import { expandSection, closeSection } from '~/settings_panels';
+
+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 });
+ });
+
+ 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/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
index 02d5ca6bdb3..bd05eb69080 100644
--- a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
+++ b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
@@ -60,6 +60,7 @@ exports[`self monitor component When the self monitor project has not been creat
<gl-modal-stub
cancel-title="Cancel"
category="primary"
+ dismisslabel="Close"
modalclass=""
modalid="delete-self-monitor-modal"
ok-title="Delete project"
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 618cc16cdf4..dfa961c5115 100644
--- a/spec/frontend/self_monitor/components/self_monitor_form_spec.js
+++ b/spec/frontend/self_monitor/components/self_monitor_form_spec.js
@@ -79,10 +79,7 @@ describe('self monitor component', () => {
wrapper = shallowMount(SelfMonitor, { store });
expect(
- wrapper
- .find({ ref: 'selfMonitoringFormText' })
- .find('a')
- .attributes('href'),
+ wrapper.find({ ref: 'selfMonitoringFormText' }).find('a').attributes('href'),
).toEqual(`${TEST_HOST}/instance-administrators-random/gitlab-self-monitoring`);
});
});
diff --git a/spec/frontend/self_monitor/store/actions_spec.js b/spec/frontend/self_monitor/store/actions_spec.js
index 0326ca6f415..29181e15680 100644
--- a/spec/frontend/self_monitor/store/actions_spec.js
+++ b/spec/frontend/self_monitor/store/actions_spec.js
@@ -16,7 +16,7 @@ describe('self monitor actions', () => {
});
describe('setSelfMonitor', () => {
- it('commits the SET_ENABLED mutation', done => {
+ it('commits the SET_ENABLED mutation', (done) => {
testAction(
actions.setSelfMonitor,
null,
@@ -29,7 +29,7 @@ describe('self monitor actions', () => {
});
describe('resetAlert', () => {
- it('commits the SET_ENABLED mutation', done => {
+ it('commits the SET_ENABLED mutation', (done) => {
testAction(
actions.resetAlert,
null,
@@ -54,7 +54,7 @@ describe('self monitor actions', () => {
});
});
- it('dispatches status request with job data', done => {
+ it('dispatches status request with job data', (done) => {
testAction(
actions.requestCreateProject,
null,
@@ -75,7 +75,7 @@ describe('self monitor actions', () => {
);
});
- it('dispatches success with project path', done => {
+ it('dispatches success with project path', (done) => {
testAction(
actions.requestCreateProjectStatus,
null,
@@ -98,7 +98,7 @@ describe('self monitor actions', () => {
mock.onPost(state.createProjectEndpoint).reply(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
testAction(
actions.requestCreateProject,
null,
@@ -121,7 +121,7 @@ describe('self monitor actions', () => {
});
describe('requestCreateProjectSuccess', () => {
- it('should commit the received data', done => {
+ it('should commit the received data', (done) => {
testAction(
actions.requestCreateProjectSuccess,
{ project_full_path: '/self-monitor-url' },
@@ -165,7 +165,7 @@ describe('self monitor actions', () => {
});
});
- it('dispatches status request with job data', done => {
+ it('dispatches status request with job data', (done) => {
testAction(
actions.requestDeleteProject,
null,
@@ -186,7 +186,7 @@ describe('self monitor actions', () => {
);
});
- it('dispatches success with status', done => {
+ it('dispatches success with status', (done) => {
testAction(
actions.requestDeleteProjectStatus,
null,
@@ -209,7 +209,7 @@ describe('self monitor actions', () => {
mock.onDelete(state.deleteProjectEndpoint).reply(500);
});
- it('dispatches error', done => {
+ it('dispatches error', (done) => {
testAction(
actions.requestDeleteProject,
null,
@@ -232,7 +232,7 @@ describe('self monitor actions', () => {
});
describe('requestDeleteProjectSuccess', () => {
- it('should commit mutations to remove previously set data', done => {
+ it('should commit mutations to remove previously set data', (done) => {
testAction(
actions.requestDeleteProjectSuccess,
null,
diff --git a/spec/frontend/sentry/sentry_config_spec.js b/spec/frontend/sentry/sentry_config_spec.js
index ed30e4774d9..5ee261f480a 100644
--- a/spec/frontend/sentry/sentry_config_spec.js
+++ b/spec/frontend/sentry/sentry_config_spec.js
@@ -4,7 +4,7 @@ import SentryConfig from '~/sentry/sentry_config';
describe('SentryConfig', () => {
describe('IGNORE_ERRORS', () => {
it('should be an array of strings', () => {
- const areStrings = SentryConfig.IGNORE_ERRORS.every(error => typeof error === 'string');
+ const areStrings = SentryConfig.IGNORE_ERRORS.every((error) => typeof error === 'string');
expect(areStrings).toBe(true);
});
@@ -12,7 +12,7 @@ describe('SentryConfig', () => {
describe('BLACKLIST_URLS', () => {
it('should be an array of regexps', () => {
- const areRegExps = SentryConfig.BLACKLIST_URLS.every(url => url instanceof RegExp);
+ const areRegExps = SentryConfig.BLACKLIST_URLS.every((url) => url instanceof RegExp);
expect(areRegExps).toBe(true);
});
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 e5f83b6fa49..135a3844e78 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
@@ -78,10 +78,5 @@ describe('Sentry Error Stack Trace', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
});
-
- it('should not show stacktrace if it does not exist', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
- });
});
});
diff --git a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
index 6b3d65ff037..4b827301943 100644
--- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
+++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
@@ -3,7 +3,7 @@
exports[`EmptyStateComponent should render content 1`] = `
"<section class=\\"row empty-state text-center\\">
<div class=\\"col-12\\">
- <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"Getting started with serverless\\" class=\\"gl-max-w-full\\"></div>
+ <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"\\" class=\\"gl-max-w-full\\"></div>
</div>
<div class=\\"col-12\\">
<div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\">
diff --git a/spec/frontend/serverless/components/area_spec.js b/spec/frontend/serverless/components/area_spec.js
index 8b6f664ae25..05c9ee44307 100644
--- a/spec/frontend/serverless/components/area_spec.js
+++ b/spec/frontend/serverless/components/area_spec.js
@@ -34,7 +34,7 @@ describe('Area component', () => {
describe('methods', () => {
describe('formatTooltipText', () => {
const mockDate = mockNormalizedMetrics.queries[0].result[0].values[0].time;
- const generateSeriesData = type => ({
+ const generateSeriesData = (type) => ({
seriesData: [
{
componentSubType: type,
@@ -91,7 +91,7 @@ describe('Area component', () => {
expect(
data.filter(
- datum => new Date(datum.time).getTime() > 0 && typeof datum.value === 'number',
+ (datum) => new Date(datum.time).getTime() > 0 && typeof datum.value === 'number',
).length,
).toBe(data.length);
});
diff --git a/spec/frontend/serverless/components/function_row_spec.js b/spec/frontend/serverless/components/function_row_spec.js
index 76a9e149302..081edd33b3b 100644
--- a/spec/frontend/serverless/components/function_row_spec.js
+++ b/spec/frontend/serverless/components/function_row_spec.js
@@ -7,7 +7,7 @@ import { mockServerlessFunction } from '../mock_data';
describe('functionRowComponent', () => {
let wrapper;
- const createComponent = func => {
+ const createComponent = (func) => {
wrapper = shallowMount(functionRowComponent, {
propsData: { func },
});
diff --git a/spec/frontend/serverless/components/missing_prometheus_spec.js b/spec/frontend/serverless/components/missing_prometheus_spec.js
index 0bd2e96a068..ffdb1f13111 100644
--- a/spec/frontend/serverless/components/missing_prometheus_spec.js
+++ b/spec/frontend/serverless/components/missing_prometheus_spec.js
@@ -6,7 +6,7 @@ import missingPrometheusComponent from '~/serverless/components/missing_promethe
describe('missingPrometheusComponent', () => {
let wrapper;
- const createComponent = missingData => {
+ const createComponent = (missingData) => {
const store = createStore({ clustersPath: '/clusters', helpPath: '/help' });
wrapper = shallowMount(missingPrometheusComponent, { store, propsData: { missingData } });
diff --git a/spec/frontend/serverless/components/pod_box_spec.js b/spec/frontend/serverless/components/pod_box_spec.js
index 495d11bd9ec..cf0c14a2cac 100644
--- a/spec/frontend/serverless/components/pod_box_spec.js
+++ b/spec/frontend/serverless/components/pod_box_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import podBoxComponent from '~/serverless/components/pod_box.vue';
-const createComponent = count =>
+const createComponent = (count) =>
shallowMount(podBoxComponent, {
propsData: {
count,
diff --git a/spec/frontend/serverless/components/url_spec.js b/spec/frontend/serverless/components/url_spec.js
index 92e4938c2cd..c43933e5b94 100644
--- a/spec/frontend/serverless/components/url_spec.js
+++ b/spec/frontend/serverless/components/url_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import urlComponent from '~/serverless/components/url.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-const createComponent = uri =>
+const createComponent = (uri) =>
shallowMount(Vue.extend(urlComponent), {
propsData: {
uri,
diff --git a/spec/frontend/serverless/mock_data.js b/spec/frontend/serverless/mock_data.js
index ef616ceb37f..1816ad62a04 100644
--- a/spec/frontend/serverless/mock_data.js
+++ b/spec/frontend/serverless/mock_data.js
@@ -102,7 +102,10 @@ export const mockMetrics = {
result: [
{
metric: {},
- values: [[1551352298.756, '0'], [1551352358.756, '0']],
+ values: [
+ [1551352298.756, '0'],
+ [1551352358.756, '0'],
+ ],
},
],
},
diff --git a/spec/frontend/serverless/store/actions_spec.js b/spec/frontend/serverless/store/actions_spec.js
index aac57c75a4f..32e30a57d4b 100644
--- a/spec/frontend/serverless/store/actions_spec.js
+++ b/spec/frontend/serverless/store/actions_spec.js
@@ -1,14 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
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 testAction from '../../helpers/vuex_action_helper';
import { adjustMetricQuery } from '../utils';
describe('ServerlessActions', () => {
describe('fetchFunctions', () => {
- it('should successfully fetch functions', done => {
+ it('should successfully fetch functions', (done) => {
const endpoint = '/functions';
const mock = new MockAdapter(axios);
mock.onGet(endpoint).reply(statusCodes.OK, JSON.stringify(mockServerlessFunctions));
@@ -29,12 +29,12 @@ describe('ServerlessActions', () => {
);
});
- it('should successfully retry', done => {
+ it('should successfully retry', (done) => {
const endpoint = '/functions';
const mock = new MockAdapter(axios);
mock
.onGet(endpoint)
- .reply(() => new Promise(resolve => setTimeout(() => resolve(200), Infinity)));
+ .reply(() => new Promise((resolve) => setTimeout(() => resolve(200), Infinity)));
testAction(
fetchFunctions,
@@ -51,7 +51,7 @@ describe('ServerlessActions', () => {
});
describe('fetchMetrics', () => {
- it('should return no prometheus', done => {
+ it('should return no prometheus', (done) => {
const endpoint = '/metrics';
const mock = new MockAdapter(axios);
mock.onGet(endpoint).reply(statusCodes.NO_CONTENT);
@@ -69,7 +69,7 @@ describe('ServerlessActions', () => {
);
});
- it('should successfully fetch metrics', done => {
+ it('should successfully fetch metrics', (done) => {
const endpoint = '/metrics';
const mock = new MockAdapter(axios);
mock.onGet(endpoint).reply(statusCodes.OK, JSON.stringify(mockMetrics));
diff --git a/spec/frontend/serverless/utils.js b/spec/frontend/serverless/utils.js
index 4af3eda1ffb..7caf7da231e 100644
--- a/spec/frontend/serverless/utils.js
+++ b/spec/frontend/serverless/utils.js
@@ -1,9 +1,9 @@
-export const adjustMetricQuery = data => {
+export const adjustMetricQuery = (data) => {
const updatedMetric = data.metrics;
- const queries = data.metrics.queries.map(query => ({
+ const queries = data.metrics.queries.map((query) => ({
...query,
- result: query.result.map(result => ({
+ result: query.result.map((result) => ({
...result,
values: result.values.map(([timestamp, value]) => ({
time: new Date(timestamp * 1000).toISOString(),
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 fad23aa05a4..f3085fb7ffb 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,13 +1,12 @@
import { shallowMount } from '@vue/test-utils';
import { GlModal, GlFormCheckbox } from '@gitlab/ui';
import { initEmojiMock } from 'helpers/emoji';
-import Api from '~/api';
+import * as UserApi from '~/api/user_api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import SetStatusModalWrapper, {
AVAILABILITY_STATUS,
} from '~/set_status_modal/set_status_modal_wrapper.vue';
-jest.mock('~/api');
jest.mock('~/flash');
describe('SetStatusModalWrapper', () => {
@@ -40,7 +39,7 @@ describe('SetStatusModalWrapper', () => {
};
const findModal = () => wrapper.find(GlModal);
- const findFormField = field => wrapper.find(`[name="user[status][${field}]"]`);
+ const findFormField = (field) => wrapper.find(`[name="user[status][${field}]"]`);
const findClearStatusButton = () => wrapper.find('.js-clear-user-status-button');
const findNoEmojiPlaceholder = () => wrapper.find('.js-no-emoji-placeholder');
const findToggleEmojiButton = () => wrapper.find('.js-toggle-emoji-menu');
@@ -150,7 +149,7 @@ describe('SetStatusModalWrapper', () => {
describe('update status', () => {
describe('succeeds', () => {
beforeEach(() => {
- jest.spyOn(Api, 'postUserStatus').mockResolvedValue();
+ jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
});
it('clicking "removeStatus" clears the emoji and message fields', async () => {
@@ -173,12 +172,12 @@ describe('SetStatusModalWrapper', () => {
const commonParams = { emoji: defaultEmoji, message: defaultMessage };
- expect(Api.postUserStatus).toHaveBeenCalledTimes(2);
- expect(Api.postUserStatus).toHaveBeenNthCalledWith(1, {
+ expect(UserApi.updateUserStatus).toHaveBeenCalledTimes(2);
+ expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(1, {
availability: AVAILABILITY_STATUS.NOT_SET,
...commonParams,
});
- expect(Api.postUserStatus).toHaveBeenNthCalledWith(2, {
+ expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(2, {
availability: AVAILABILITY_STATUS.BUSY,
...commonParams,
});
@@ -196,7 +195,7 @@ describe('SetStatusModalWrapper', () => {
beforeEach(async () => {
mockEmoji = await initEmojiMock();
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
- jest.spyOn(Api, 'postUserStatus').mockResolvedValue();
+ jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
return initModal({ mockOnUpdateSuccess: false });
});
@@ -204,16 +203,13 @@ describe('SetStatusModalWrapper', () => {
findModal().vm.$emit('ok');
await wrapper.vm.$nextTick();
- expect($toast.show).toHaveBeenCalledWith('Status updated', {
- position: 'top-center',
- type: 'success',
- });
+ expect($toast.show).toHaveBeenCalledWith('Status updated');
});
});
describe('with errors', () => {
beforeEach(() => {
- jest.spyOn(Api, 'postUserStatus').mockRejectedValue();
+ jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
});
it('calls the "onUpdateFail" handler', async () => {
@@ -228,7 +224,7 @@ describe('SetStatusModalWrapper', () => {
beforeEach(async () => {
mockEmoji = await initEmojiMock();
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
- jest.spyOn(Api, 'postUserStatus').mockRejectedValue();
+ jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
return initModal({ mockOnUpdateFailure: false });
});
diff --git a/spec/frontend/shared/popover_spec.js b/spec/frontend/shared/popover_spec.js
index bbde936185e..59b0b3b006c 100644
--- a/spec/frontend/shared/popover_spec.js
+++ b/spec/frontend/shared/popover_spec.js
@@ -22,14 +22,14 @@ describe('popover', () => {
expect(togglePopover.call(context, true)).toEqual(false);
});
- it('shows popover', done => {
+ it('shows popover', (done) => {
const context = {
hasClass: () => false,
popover: () => {},
toggleClass: () => {},
};
- jest.spyOn(context, 'popover').mockImplementation(method => {
+ jest.spyOn(context, 'popover').mockImplementation((method) => {
expect(method).toEqual('show');
done();
});
@@ -37,7 +37,7 @@ describe('popover', () => {
togglePopover.call(context, true);
});
- it('adds disable-animation and js-popover-show class', done => {
+ it('adds disable-animation and js-popover-show class', (done) => {
const context = {
hasClass: () => false,
popover: () => {},
@@ -73,14 +73,14 @@ describe('popover', () => {
expect(togglePopover.call(context, false)).toEqual(false);
});
- it('hides popover', done => {
+ it('hides popover', (done) => {
const context = {
hasClass: () => true,
popover: () => {},
toggleClass: () => {},
};
- jest.spyOn(context, 'popover').mockImplementation(method => {
+ jest.spyOn(context, 'popover').mockImplementation((method) => {
expect(method).toEqual('hide');
done();
});
@@ -88,7 +88,7 @@ describe('popover', () => {
togglePopover.call(context, false);
});
- it('removes disable-animation and js-popover-show class', done => {
+ it('removes disable-animation and js-popover-show class', (done) => {
const context = {
hasClass: () => true,
popover: () => {},
@@ -114,7 +114,7 @@ describe('popover', () => {
jest
.spyOn($.fn, 'init')
- .mockImplementation(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
+ .mockImplementation((selector) => (selector === '.popover:hover' ? fakeJquery : $.fn));
jest.spyOn(togglePopover, 'call').mockImplementation(() => {});
mouseleave();
@@ -128,7 +128,7 @@ describe('popover', () => {
jest
.spyOn($.fn, 'init')
- .mockImplementation(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
+ .mockImplementation((selector) => (selector === '.popover:hover' ? fakeJquery : $.fn));
jest.spyOn(togglePopover, 'call').mockImplementation(() => {});
mouseleave();
@@ -146,9 +146,9 @@ describe('popover', () => {
expect(togglePopover.call).toHaveBeenCalledWith(expect.any(Object), true);
});
- it('registers mouseleave event if popover is showed', done => {
+ it('registers mouseleave event if popover is showed', (done) => {
jest.spyOn(togglePopover, 'call').mockReturnValue(true);
- jest.spyOn($.fn, 'on').mockImplementation(eventName => {
+ jest.spyOn($.fn, 'on').mockImplementation((eventName) => {
expect(eventName).toEqual('mouseleave');
done();
});
diff --git a/spec/frontend/shortcuts_spec.js b/spec/frontend/shortcuts_spec.js
index 538b3afa50f..1650dd2c1ca 100644
--- a/spec/frontend/shortcuts_spec.js
+++ b/spec/frontend/shortcuts_spec.js
@@ -85,13 +85,13 @@ describe('Shortcuts', () => {
});
it('attaches a Mousetrap handler for every markdown shortcut specified with md-shortcuts', () => {
- const expectedCalls = shortcuts.map(s => [s, expect.any(Function)]);
+ const expectedCalls = shortcuts.map((s) => [s, expect.any(Function)]);
expect(mockMousetrap.bind.mock.calls).toEqual(expectedCalls);
});
it('attaches a stopCallback that allows each markdown shortcut specified with md-shortcuts', () => {
- flatten(shortcuts).forEach(s => {
+ flatten(shortcuts).forEach((s) => {
expect(mockMousetrap.stopCallback(null, null, s)).toBe(false);
});
});
@@ -108,7 +108,7 @@ describe('Shortcuts', () => {
Shortcuts.initMarkdownEditorShortcuts($('.edit-note textarea'));
Shortcuts.removeMarkdownEditorShortcuts($('.edit-note textarea'));
- const expectedCalls = shortcuts.map(s => [s]);
+ const expectedCalls = shortcuts.map((s) => [s]);
expect(mockMousetrap.unbind.mock.calls).toEqual(expectedCalls);
});
diff --git a/spec/frontend/sidebar/assignee_title_spec.js b/spec/frontend/sidebar/assignee_title_spec.js
index b5d1e5216f8..9f5d51c7795 100644
--- a/spec/frontend/sidebar/assignee_title_spec.js
+++ b/spec/frontend/sidebar/assignee_title_spec.js
@@ -6,7 +6,7 @@ import Component from '~/sidebar/components/assignees/assignee_title.vue';
describe('AssigneeTitle component', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
return shallowMount(Component, {
propsData: {
numberOfAssignees: 0,
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index d1810ada97a..23e82171fe9 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -1,9 +1,9 @@
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';
-import UsersMockHelper from '../helpers/user_mock_data_helper';
describe('Assignee component', () => {
const getDefaultProps = () => ({
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 907d6144415..8e158c99971 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
@@ -101,7 +101,7 @@ describe('CollapsedAssigneeList component', () => {
beforeEach(() => {
users = UsersMockHelper.createNumberRandomUsers(3);
- userNames = users.map(x => x.name).join(', ');
+ userNames = users.map((x) => x.name).join(', ');
});
describe('default', () => {
diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
index 49a6d9e8ae6..ee1f8ed8d2b 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
@@ -28,12 +28,7 @@ describe('CollapsedAssignee assignee component', () => {
it('has author name', () => {
createComponent();
- expect(
- wrapper
- .find('.author')
- .text()
- .trim(),
- ).toEqual(TEST_USER.name);
+ expect(wrapper.find('.author').text().trim()).toEqual(TEST_USER.name);
});
it('has assignee avatar', () => {
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 1cf0af48bef..da69f56d442 100644
--- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
@@ -1,9 +1,9 @@
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 userDataMock from '../../user_data_mock';
-import UsersMockHelper from '../../../helpers/user_mock_data_helper';
const DEFAULT_RENDER_COUNT = 5;
diff --git a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
new file mode 100644
index 00000000000..b9132fa4450
--- /dev/null
+++ b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
@@ -0,0 +1,22 @@
+import { mount } from '@vue/test-utils';
+import { getByText } from '@testing-library/dom';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CopyEmailToClipboard from '~/sidebar/components/copy_email_to_clipboard.vue';
+
+describe('CopyEmailToClipboard component', () => {
+ const sampleEmail = 'sample+email@test.com';
+
+ const wrapper = mount(CopyEmailToClipboard, {
+ propsData: {
+ copyText: sampleEmail,
+ },
+ });
+
+ it('renders the Issue email text with the forwardable email', () => {
+ expect(getByText(wrapper.element, `Issue email: ${sampleEmail}`)).not.toBeNull();
+ });
+
+ it('finds ClipboardButton with the correct props', () => {
+ expect(wrapper.find(ClipboardButton).props('text')).toBe(sampleEmail);
+ });
+});
diff --git a/spec/frontend/sidebar/components/severity/severity_spec.js b/spec/frontend/sidebar/components/severity/severity_spec.js
index b6690f11d6b..ba7cea0919c 100644
--- a/spec/frontend/sidebar/components/severity/severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/severity_spec.js
@@ -24,7 +24,7 @@ describe('SeverityToken', () => {
const findIcon = () => wrapper.find(GlIcon);
it('renders severity token for each severity type', () => {
- Object.values(INCIDENT_SEVERITY).forEach(severity => {
+ Object.values(INCIDENT_SEVERITY).forEach((severity) => {
createComponent({ severity });
expect(findIcon().classes()).toContain(`icon-${severity.icon}`);
expect(findIcon().attributes('name')).toBe(`severity-${severity.icon}`);
diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
index 638d3706d12..fa40d75d4e9 100644
--- a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
@@ -94,7 +94,7 @@ describe('SidebarSeverity', () => {
let resolvePromise;
wrapper.vm.$apollo.mutate = jest.fn(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolvePromise = resolve;
}),
);
@@ -119,21 +119,11 @@ describe('SidebarSeverity', () => {
});
it('should display only icon with a tooltip', () => {
- expect(
- findSeverityToken()
- .at(0)
- .attributes('icononly'),
- ).toBe('true');
- expect(
- findSeverityToken()
- .at(0)
- .attributes('iconsize'),
- ).toBe('14');
- expect(
- findTooltip()
- .text()
- .replace(/\s+/g, ' '),
- ).toContain(`Severity: ${INCIDENT_SEVERITY[severity].label}`);
+ expect(findSeverityToken().at(0).attributes('icononly')).toBe('true');
+ expect(findSeverityToken().at(0).attributes('iconsize')).toBe('14');
+ expect(findTooltip().text().replace(/\s+/g, ' ')).toContain(
+ `Severity: ${INCIDENT_SEVERITY[severity].label}`,
+ );
});
it('should expand the dropdown on collapsed icon click', async () => {
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 bcd2c14f2fa..0b6a2e6ceb9 100644
--- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
@@ -1,11 +1,12 @@
import { createMockDirective } from 'helpers/vue_mock_directive';
import { mount } from '@vue/test-utils';
+import { stubTransition } from 'helpers/stub_transition';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
describe('Issuable Time Tracker', () => {
let wrapper;
- const findByTestId = testId => wrapper.find(`[data-testid=${testId}]`);
+ const findByTestId = (testId) => wrapper.find(`[data-testid=${testId}]`);
const findComparisonMeter = () => findByTestId('compareMeter').attributes('title');
const findCollapsedState = () => findByTestId('collapsedState');
const findTimeRemainingProgress = () => findByTestId('timeRemainingProgress');
@@ -22,6 +23,9 @@ describe('Issuable Time Tracker', () => {
mount(TimeTracker, {
propsData: { ...defaultProps, ...props },
directives: { GlTooltip: createMockDirective() },
+ stubs: {
+ transition: stubTransition(),
+ },
});
afterEach(() => {
@@ -213,14 +217,12 @@ describe('Issuable Time Tracker', () => {
findHelpButton().trigger('click');
await wrapper.vm.$nextTick();
- expect(findByTestId('helpPane').classes('help-state-toggle-enter')).toBe(true);
- expect(findByTestId('helpPane').classes('help-state-toggle-leave')).toBe(false);
+ expect(findByTestId('helpPane').exists()).toBe(true);
findCloseHelpButton().trigger('click');
await wrapper.vm.$nextTick();
- expect(findByTestId('helpPane').classes('help-state-toggle-leave')).toBe(true);
- expect(findByTestId('helpPane').classes('help-state-toggle-enter')).toBe(false);
+ expect(findByTestId('helpPane').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/confidential/edit_form_spec.js b/spec/frontend/sidebar/confidential/edit_form_spec.js
index 56f163eecd1..6b571df10ae 100644
--- a/spec/frontend/sidebar/confidential/edit_form_spec.js
+++ b/spec/frontend/sidebar/confidential/edit_form_spec.js
@@ -6,7 +6,7 @@ describe('Edit Form Dropdown', () => {
const toggleForm = () => {};
const updateConfidentialAttribute = () => {};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(EditForm, {
propsData: {
...props,
diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
index 913646c8f8d..a14ca711204 100644
--- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
@@ -15,7 +15,7 @@ describe('EditFormButtons', () => {
let issuableType;
let issuableDisplayName;
- const setIssuableType = pageType => {
+ const setIssuableType = (pageType) => {
issuableType = pageType;
issuableDisplayName = issuableType.replace(/_/g, ' ');
};
diff --git a/spec/frontend/sidebar/lock/edit_form_spec.js b/spec/frontend/sidebar/lock/edit_form_spec.js
index b1c3bfe3ef5..4ae9025ee39 100644
--- a/spec/frontend/sidebar/lock/edit_form_spec.js
+++ b/spec/frontend/sidebar/lock/edit_form_spec.js
@@ -7,7 +7,7 @@ describe('Edit Form Dropdown', () => {
let issuableType; // Either ISSUABLE_TYPE_ISSUE or ISSUABLE_TYPE_MR
let issuableDisplayName;
- const setIssuableType = pageType => {
+ const setIssuableType = (pageType) => {
issuableType = pageType;
issuableDisplayName = issuableType.replace(/_/g, ' ');
};
diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
index e8091dcb51d..92cdba4f1f2 100644
--- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
+++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
@@ -12,7 +12,7 @@ describe('IssuableLockForm', () => {
let store;
let issuableType; // Either ISSUABLE_TYPE_ISSUE or ISSUABLE_TYPE_MR
- const setIssuableType = pageType => {
+ const setIssuableType = (pageType) => {
issuableType = pageType;
};
@@ -23,7 +23,7 @@ describe('IssuableLockForm', () => {
const findSidebarLockStatusTooltip = () =>
getBinding(findSidebarCollapseIcon().element, 'gl-tooltip');
- const initStore = isLocked => {
+ const initStore = (isLocked) => {
if (issuableType === ISSUABLE_TYPE_ISSUE) {
store = createStore();
store.getters.getNoteableData.targetType = 'issue';
diff --git a/spec/frontend/sidebar/participants_spec.js b/spec/frontend/sidebar/participants_spec.js
index 93c9b3b84c3..1210f7c9531 100644
--- a/spec/frontend/sidebar/participants_spec.js
+++ b/spec/frontend/sidebar/participants_spec.js
@@ -21,7 +21,7 @@ describe('Participants', () => {
const getCollapsedParticipantsCount = () => wrapper.find('[data-testid="collapsed-count"]');
- const mountComponent = propsData =>
+ const mountComponent = (propsData) =>
shallowMount(Participants, {
propsData,
});
diff --git a/spec/frontend/sidebar/reviewer_title_spec.js b/spec/frontend/sidebar/reviewer_title_spec.js
index eae266688d5..cbd36040579 100644
--- a/spec/frontend/sidebar/reviewer_title_spec.js
+++ b/spec/frontend/sidebar/reviewer_title_spec.js
@@ -6,7 +6,7 @@ import Component from '~/sidebar/components/reviewers/reviewer_title.vue';
describe('ReviewerTitle component', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
return shallowMount(Component, {
propsData: {
numberOfReviewers: 0,
@@ -41,27 +41,6 @@ describe('ReviewerTitle component', () => {
});
});
- describe('gutter toggle', () => {
- it('does not show toggle by default', () => {
- wrapper = createComponent({
- numberOfReviewers: 2,
- editable: false,
- });
-
- expect(wrapper.vm.$el.querySelector('.gutter-toggle')).toBeNull();
- });
-
- it('shows toggle when showToggle is true', () => {
- wrapper = createComponent({
- numberOfReviewers: 2,
- editable: false,
- showToggle: true,
- });
-
- expect(wrapper.vm.$el.querySelector('.gutter-toggle')).toEqual(expect.any(Object));
- });
- });
-
it('does not render spinner by default', () => {
wrapper = createComponent({
numberOfReviewers: 0,
diff --git a/spec/frontend/sidebar/reviewers_spec.js b/spec/frontend/sidebar/reviewers_spec.js
index effcac266f0..91f28e85f3b 100644
--- a/spec/frontend/sidebar/reviewers_spec.js
+++ b/spec/frontend/sidebar/reviewers_spec.js
@@ -1,9 +1,9 @@
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';
-import UsersMockHelper from '../helpers/user_mock_data_helper';
describe('Reviewer component', () => {
const getDefaultProps = () => ({
diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js
index dc4560d2ae8..f1c13a5f818 100644
--- a/spec/frontend/sidebar/sidebar_assignees_spec.js
+++ b/spec/frontend/sidebar/sidebar_assignees_spec.js
@@ -29,7 +29,7 @@ describe('sidebar assignees', () => {
},
},
// Attaching to document is required because this component emits something from the parent element :/
- attachToDocument: true,
+ attachTo: document.body,
});
};
diff --git a/spec/frontend/sidebar/sidebar_mediator_spec.js b/spec/frontend/sidebar/sidebar_mediator_spec.js
index 0892d452966..019ded87093 100644
--- a/spec/frontend/sidebar/sidebar_mediator_spec.js
+++ b/spec/frontend/sidebar/sidebar_mediator_spec.js
@@ -33,7 +33,7 @@ describe('Sidebar mediator', () => {
it('saves assignees', () => {
mock.onPut(mediatorMockData.endpoint).reply(200, {});
- return mediator.saveAssignees('issue[assignee_ids]').then(resp => {
+ return mediator.saveAssignees('issue[assignee_ids]').then((resp) => {
expect(resp.status).toEqual(200);
});
});
diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js
index ad919f69546..24bb5a8e916 100644
--- a/spec/frontend/sidebar/sidebar_move_issue_spec.js
+++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js
@@ -74,7 +74,7 @@ describe('SidebarMoveIssue', () => {
expect(test.sidebarMoveIssue.$dropdownToggle.data('deprecatedJQueryDropdown')).toBeTruthy();
});
- it('escapes html from project name', done => {
+ it('escapes html from project name', (done) => {
test.$toggleButton.dropdown('toggle');
setImmediate(() => {
@@ -98,7 +98,7 @@ describe('SidebarMoveIssue', () => {
expect(test.$confirmButton.hasClass('is-loading')).toBe(true);
});
- it('should remove loading state from confirm button on failure', done => {
+ it('should remove loading state from confirm button on failure', (done) => {
jest.spyOn(window, 'Flash').mockImplementation(() => {});
jest.spyOn(test.mediator, 'moveIssue').mockReturnValue(Promise.reject());
test.mediator.setMoveToProjectId(7);
@@ -125,7 +125,7 @@ describe('SidebarMoveIssue', () => {
});
});
- it('should set moveToProjectId on dropdown item "No project" click', done => {
+ it('should set moveToProjectId on dropdown item "No project" click', (done) => {
jest.spyOn(test.mediator, 'setMoveToProjectId').mockImplementation(() => {});
// Open the dropdown
@@ -133,10 +133,7 @@ describe('SidebarMoveIssue', () => {
// Wait for the autocomplete request to finish
setImmediate(() => {
- test.$content
- .find('.js-move-issue-dropdown-item')
- .eq(0)
- .trigger('click');
+ test.$content.find('.js-move-issue-dropdown-item').eq(0).trigger('click');
expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(0);
expect(test.$confirmButton.prop('disabled')).toBeTruthy();
@@ -144,7 +141,7 @@ describe('SidebarMoveIssue', () => {
});
});
- it('should set moveToProjectId on dropdown item click', done => {
+ it('should set moveToProjectId on dropdown item click', (done) => {
jest.spyOn(test.mediator, 'setMoveToProjectId').mockImplementation(() => {});
// Open the dropdown
@@ -152,10 +149,7 @@ describe('SidebarMoveIssue', () => {
// Wait for the autocomplete request to finish
setImmediate(() => {
- test.$content
- .find('.js-move-issue-dropdown-item')
- .eq(1)
- .trigger('click');
+ test.$content.find('.js-move-issue-dropdown-item').eq(1).trigger('click');
expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(20);
expect(test.$confirmButton.attr('disabled')).toBe(undefined);
diff --git a/spec/frontend/sidebar/sidebar_store_spec.js b/spec/frontend/sidebar/sidebar_store_spec.js
index 7c18222f300..7b73dc868b7 100644
--- a/spec/frontend/sidebar/sidebar_store_spec.js
+++ b/spec/frontend/sidebar/sidebar_store_spec.js
@@ -1,6 +1,6 @@
+import UsersMockHelper from 'helpers/user_mock_data_helper';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data';
-import UsersMockHelper from '../helpers/user_mock_data_helper';
const ASSIGNEE = {
id: 2,
diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js
index 428441656b3..043ffd972da 100644
--- a/spec/frontend/sidebar/subscriptions_spec.js
+++ b/spec/frontend/sidebar/subscriptions_spec.js
@@ -8,7 +8,7 @@ describe('Subscriptions', () => {
const findToggleButton = () => wrapper.find(ToggleButton);
- const mountComponent = propsData =>
+ const mountComponent = (propsData) =>
shallowMount(Subscriptions, {
propsData,
});
diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js
index b0e94f16dd7..4adfaf7ad7b 100644
--- a/spec/frontend/sidebar/todo_spec.js
+++ b/spec/frontend/sidebar/todo_spec.js
@@ -42,12 +42,7 @@ describe('SidebarTodo', () => {
({ isTodo, iconClass, label, icon }) => {
createComponent({ isTodo });
- expect(
- wrapper
- .find(GlIcon)
- .classes()
- .join(' '),
- ).toStrictEqual(iconClass);
+ expect(wrapper.find(GlIcon).classes().join(' ')).toStrictEqual(iconClass);
expect(wrapper.find(GlIcon).props('name')).toStrictEqual(icon);
expect(wrapper.find('button').text()).toBe(label);
},
diff --git a/spec/frontend/snippet/collapsible_input_spec.js b/spec/frontend/snippet/collapsible_input_spec.js
index aa017964437..3f14a9cd1a1 100644
--- a/spec/frontend/snippet/collapsible_input_spec.js
+++ b/spec/frontend/snippet/collapsible_input_spec.js
@@ -38,12 +38,12 @@ describe('~/snippet/collapsible_input', () => {
setupCollapsibleInputs();
});
- const findInput = el => el.querySelector('textarea,input');
- const findCollapsed = el => el.querySelector('.js-collapsed');
- const findExpanded = el => el.querySelector('.js-expanded');
- const findCollapsedInput = el => findInput(findCollapsed(el));
- const findExpandedInput = el => findInput(findExpanded(el));
- const focusIn = target => target.dispatchEvent(new Event('focusin', { bubbles: true }));
+ const findInput = (el) => el.querySelector('textarea,input');
+ const findCollapsed = (el) => el.querySelector('.js-collapsed');
+ const findExpanded = (el) => el.querySelector('.js-expanded');
+ const findCollapsedInput = (el) => findInput(findCollapsed(el));
+ const findExpandedInput = (el) => findInput(findExpanded(el));
+ const focusIn = (target) => target.dispatchEvent(new Event('focusin', { bubbles: true }));
const expectIsCollapsed = (el, isCollapsed) => {
expect(findCollapsed(el).classList.contains('d-none')).toEqual(!isCollapsed);
expect(findExpanded(el).classList.contains('d-none')).toEqual(isCollapsed);
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index 3521733ee5e..b818f98efb1 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -2,7 +2,7 @@ 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 createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as urlUtils from '~/lib/utils/url_utility';
@@ -149,9 +149,11 @@ describe('Snippet Edit app', () => {
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 => {
- wrapper.vm.$el.innerHTML = paths.map(path => `<input name="files[]" value="${path}">`).join('');
+ const triggerBlobActions = (actions) => findBlobActions().vm.$emit('actions', actions);
+ const setUploadFilesHtml = (paths) => {
+ wrapper.vm.$el.innerHTML = paths
+ .map((path) => `<input name="files[]" value="${path}">`)
+ .join('');
};
const getApiData = ({
id,
@@ -189,7 +191,7 @@ describe('Snippet Edit app', () => {
it.each([[{}], [{ snippetGid: '' }]])(
'should render all required components with %s',
- props => {
+ (props) => {
createComponent(props);
expect(wrapper.find(TitleField).exists()).toBe(true);
@@ -257,7 +259,7 @@ describe('Snippet Edit app', () => {
describe('default visibility', () => {
it.each([SNIPPET_VISIBILITY_PRIVATE, SNIPPET_VISIBILITY_INTERNAL, SNIPPET_VISIBILITY_PUBLIC])(
'marks %s visibility by default',
- async visibility => {
+ async (visibility) => {
createComponent({
props: { snippetGid: '' },
selectedLevel: visibility,
diff --git a/spec/frontend/snippets/components/embed_dropdown_spec.js b/spec/frontend/snippets/components/embed_dropdown_spec.js
index 8eb44965692..f1eb7d43409 100644
--- a/spec/frontend/snippets/components/embed_dropdown_spec.js
+++ b/spec/frontend/snippets/components/embed_dropdown_spec.js
@@ -26,7 +26,7 @@ describe('snippets/components/embed_dropdown', () => {
const sections = [];
let current = {};
- wrapper.findAll('[data-testid="header"],[data-testid="input"]').wrappers.forEach(x => {
+ wrapper.findAll('[data-testid="header"],[data-testid="input"]').wrappers.forEach((x) => {
const type = x.attributes('data-testid');
if (type === 'header') {
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 055168a1711..08056e788de 100644
--- a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js
@@ -14,7 +14,7 @@ const TEST_BLOBS = [
createBlobFromTestEntry(testEntries.deleted),
];
-const TEST_BLOBS_UNLOADED = TEST_BLOBS.map(blob => ({ ...blob, content: '', isLoaded: false }));
+const TEST_BLOBS_UNLOADED = TEST_BLOBS.map((blob) => ({ ...blob, content: '', isLoaded: false }));
describe('snippets/components/snippet_blob_actions_edit', () => {
let wrapper;
@@ -31,7 +31,7 @@ describe('snippets/components/snippet_blob_actions_edit', () => {
const findLabel = () => wrapper.find('label');
const findBlobEdits = () => wrapper.findAll(SnippetBlobEdit);
const findBlobsData = () =>
- findBlobEdits().wrappers.map(x => ({
+ findBlobEdits().wrappers.map((x) => ({
blob: x.props('blob'),
classes: x.classes(),
}));
@@ -42,7 +42,7 @@ describe('snippets/components/snippet_blob_actions_edit', () => {
return events[events.length - 1]?.[0];
};
- const buildBlobsDataExpectation = blobs =>
+ const buildBlobsDataExpectation = (blobs) =>
blobs.map((blob, index) => ({
blob: {
...blob,
@@ -50,14 +50,8 @@ describe('snippets/components/snippet_blob_actions_edit', () => {
},
classes: index > 0 ? ['gl-mt-3'] : [],
}));
- const triggerBlobDelete = idx =>
- findBlobEdits()
- .at(idx)
- .vm.$emit('delete');
- const triggerBlobUpdate = (idx, props) =>
- findBlobEdits()
- .at(idx)
- .vm.$emit('blob-updated', props);
+ const triggerBlobDelete = (idx) => findBlobEdits().at(idx).vm.$emit('delete');
+ const triggerBlobUpdate = (idx, props) => findBlobEdits().at(idx).vm.$emit('blob-updated', props);
afterEach(() => {
wrapper.destroy();
@@ -213,11 +207,7 @@ describe('snippets/components/snippet_blob_actions_edit', () => {
it('disables delete button', () => {
expect(findBlobEdits()).toHaveLength(1);
- expect(
- findBlobEdits()
- .at(0)
- .props(),
- ).toMatchObject({
+ expect(findBlobEdits().at(0).props()).toMatchObject({
showDelete: true,
canDelete: false,
});
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index 5836de1fdbe..93a66db32c6 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -17,6 +17,8 @@ describe('Snippet header component', () => {
let err;
const originalRelativeUrlRoot = gon.relative_url_root;
+ const GlEmoji = { template: '<img/>' };
+
function createComponent({
loading = false,
permissions = {},
@@ -47,10 +49,15 @@ describe('Snippet header component', () => {
},
stubs: {
ApolloMutation,
+ GlEmoji,
},
});
}
+ const findAuthorEmoji = () => wrapper.find(GlEmoji);
+ const findAuthoredMessage = () => wrapper.find('[data-testid="authored-message"]').text();
+ const buttonCount = () => wrapper.findAll(GlButton).length;
+
beforeEach(() => {
gon.relative_url_root = '/foo/';
snippet = {
@@ -66,6 +73,7 @@ describe('Snippet header component', () => {
project: null,
author: {
name: 'Thor Odinson',
+ status: null,
},
blobs: [Blob],
createdAt: new Date(differenceInMilliseconds(32 * 24 * 3600 * 1000)).toISOString(),
@@ -100,17 +108,36 @@ describe('Snippet header component', () => {
it('renders a message showing snippet creation date and author', () => {
createComponent();
- const text = wrapper.find('[data-testid="authored-message"]').text();
+ const text = findAuthoredMessage();
expect(text).toContain('Authored 1 month ago by');
expect(text).toContain('Thor Odinson');
});
+ describe('author status', () => {
+ it('is rendered when it is set', () => {
+ snippet.author.status = {
+ message: 'At work',
+ emoji: 'hammer',
+ };
+ createComponent();
+
+ expect(findAuthorEmoji().attributes('title')).toBe(snippet.author.status.message);
+ expect(findAuthorEmoji().attributes('data-name')).toBe(snippet.author.status.emoji);
+ });
+
+ it('is not rendered when the user has no status', () => {
+ createComponent();
+
+ expect(findAuthorEmoji().exists()).toBe(false);
+ });
+ });
+
it('renders a message showing only snippet creation date if author is null', () => {
snippet.author = null;
createComponent();
- const text = wrapper.find('[data-testid="authored-message"]').text();
+ const text = findAuthoredMessage();
expect(text).toBe('Authored 1 month ago');
});
@@ -121,7 +148,7 @@ describe('Snippet header component', () => {
updateSnippet: false,
},
});
- expect(wrapper.findAll(GlButton).length).toEqual(0);
+ expect(buttonCount()).toEqual(0);
createComponent({
permissions: {
@@ -129,7 +156,7 @@ describe('Snippet header component', () => {
updateSnippet: false,
},
});
- expect(wrapper.findAll(GlButton).length).toEqual(1);
+ expect(buttonCount()).toEqual(1);
createComponent({
permissions: {
@@ -137,7 +164,7 @@ describe('Snippet header component', () => {
updateSnippet: true,
},
});
- expect(wrapper.findAll(GlButton).length).toEqual(2);
+ expect(buttonCount()).toEqual(2);
createComponent({
permissions: {
@@ -149,7 +176,7 @@ describe('Snippet header component', () => {
canCreateSnippet: true,
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlButton).length).toEqual(3);
+ expect(buttonCount()).toEqual(3);
});
});
diff --git a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
index 3151090f388..62d1ac9b476 100644
--- a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
@@ -40,7 +40,7 @@ describe('Snippet Visibility Edit component', () => {
const findLink = () => wrapper.find('label').find(GlLink);
const findRadios = () => wrapper.find(GlFormRadioGroup).findAll(GlFormRadio);
const findRadiosData = () =>
- findRadios().wrappers.map(x => {
+ findRadios().wrappers.map((x) => {
return {
value: x.find('input').attributes('value'),
icon: x.find(GlIcon).props('name'),
diff --git a/spec/frontend/snippets/utils/blob_spec.js b/spec/frontend/snippets/utils/blob_spec.js
index c20cf2e6102..4c6cee32614 100644
--- a/spec/frontend/snippets/utils/blob_spec.js
+++ b/spec/frontend/snippets/utils/blob_spec.js
@@ -2,7 +2,7 @@ import { cloneDeep } from 'lodash';
import { decorateBlob, createBlob, diffAll } from '~/snippets/utils/blob';
import { testEntries, createBlobsFromTestEntries } from '../test_utils';
-jest.mock('lodash/uniqueId', () => arg => `${arg}fakeUniqueId`);
+jest.mock('lodash/uniqueId', () => (arg) => `${arg}fakeUniqueId`);
const TEST_RAW_BLOB = {
rawPath: '/test/blob/7/raw',
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 ed33f93ec51..07097d00cc5 100644
--- a/spec/frontend/static_site_editor/components/edit_area_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -1,4 +1,6 @@
+import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
+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';
@@ -22,7 +24,7 @@ import {
imageRoot,
} from '../mock_data';
-jest.mock('~/static_site_editor/services/formatter', () => jest.fn(str => `${str} format-pass`));
+jest.mock('~/static_site_editor/services/formatter', () => jest.fn((str) => `${str} format-pass`));
describe('~/static_site_editor/components/edit_area.vue', () => {
let wrapper;
@@ -30,6 +32,12 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
const savingChanges = true;
const newBody = `new ${body}`;
+ const RichContentEditorStub = stubComponent(RichContentEditor, {
+ methods: {
+ resetInitialValue: jest.fn(),
+ },
+ });
+
const buildWrapper = (propsData = {}) => {
wrapper = shallowMount(EditArea, {
propsData: {
@@ -44,6 +52,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
savingChanges,
...propsData,
},
+ stubs: { RichContentEditor: RichContentEditorStub },
});
};
@@ -94,7 +103,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
beforeEach(() => {
findRichContentEditor().vm.$emit('input', newBody);
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('updates parsedSource with new content', () => {
@@ -114,30 +123,21 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
expect(findUnsavedChangesConfirmDialog().props('modified')).toBe(true);
});
- it('sets publish toolbar as not saveable when content changes are rollback', () => {
+ it('sets publish toolbar as not saveable when content changes are rollback', async () => {
findRichContentEditor().vm.$emit('input', formattedBody);
- return wrapper.vm.$nextTick().then(() => {
- expect(findPublishToolbar().props('saveable')).toBe(false);
- });
+ await nextTick();
+ expect(findPublishToolbar().props('saveable')).toBe(false);
});
});
describe('when the mode changes', () => {
- let resetInitialValue;
-
- const setInitialMode = mode => {
+ const setInitialMode = (mode) => {
wrapper.setData({ editorMode: mode });
};
- const buildResetInitialValue = () => {
- resetInitialValue = jest.fn();
- findRichContentEditor().setMethods({ resetInitialValue });
- };
-
afterEach(() => {
setInitialMode(EDITOR_TYPES.wysiwyg);
- resetInitialValue = null;
});
it.each`
@@ -148,21 +148,20 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
'sets editorMode from $initialMode to $targetMode',
({ initialMode, targetMode, resetValue }) => {
setInitialMode(initialMode);
- buildResetInitialValue();
findRichContentEditor().vm.$emit('modeChange', targetMode);
- expect(resetInitialValue).toHaveBeenCalledWith(resetValue);
+ expect(RichContentEditorStub.methods.resetInitialValue).toHaveBeenCalledWith(resetValue);
expect(wrapper.vm.editorMode).toBe(targetMode);
},
);
it('should format the content', () => {
- buildResetInitialValue();
-
findRichContentEditor().vm.$emit('modeChange', EDITOR_TYPES.markdown);
- expect(resetInitialValue).toHaveBeenCalledWith(`${content} format-pass format-pass`);
+ expect(RichContentEditorStub.methods.resetInitialValue).toHaveBeenCalledWith(
+ `${content} format-pass format-pass`,
+ );
});
});
@@ -172,30 +171,27 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
expect(findEditDrawer().props('isOpen')).toBe(false);
});
- it('opens the edit drawer', () => {
+ it('opens the edit drawer', async () => {
findPublishToolbar().vm.$emit('editSettings');
- return wrapper.vm.$nextTick().then(() => {
- expect(findEditDrawer().props('isOpen')).toBe(true);
- });
+ await nextTick();
+ expect(findEditDrawer().props('isOpen')).toBe(true);
});
- it('closes the edit drawer', () => {
+ it('closes the edit drawer', async () => {
findEditDrawer().vm.$emit('close');
- return wrapper.vm.$nextTick().then(() => {
- expect(findEditDrawer().props('isOpen')).toBe(false);
- });
+ await nextTick();
+ expect(findEditDrawer().props('isOpen')).toBe(false);
});
- it('forwards the matter settings when the drawer is open', () => {
+ it('forwards the matter settings when the drawer is open', async () => {
findPublishToolbar().vm.$emit('editSettings');
jest.spyOn(wrapper.vm.parsedSource, 'matter').mockReturnValueOnce(headerSettings);
- return wrapper.vm.$nextTick().then(() => {
- expect(findEditDrawer().props('settings')).toEqual(headerSettings);
- });
+ await nextTick();
+ expect(findEditDrawer().props('settings')).toEqual(headerSettings);
});
it('enables toolbar submit button', () => {
@@ -211,16 +207,15 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
expect(spySyncParsedSource).toHaveBeenCalledWith(newSettings);
});
- it('syncs matter changes to content in markdown mode', () => {
+ it('syncs matter changes to content in markdown mode', async () => {
wrapper.setData({ editorMode: EDITOR_TYPES.markdown });
const newSettings = { title: 'test' };
findEditDrawer().vm.$emit('updateSettings', newSettings);
- return wrapper.vm.$nextTick().then(() => {
- expect(findRichContentEditor().props('content')).toContain('title: test');
- });
+ await nextTick();
+ expect(findRichContentEditor().props('content')).toContain('title: test');
});
});
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 b887570e947..cf82efc3d0b 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
@@ -35,7 +35,7 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => {
const findGlFormInputTitle = () => wrapper.find(GlFormInput);
const findGlDropdownDescriptionTemplate = () => wrapper.find(GlDropdown);
const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
- const findDropdownItemByIndex = index => findAllDropdownItems().at(index);
+ const findDropdownItemByIndex = (index) => findAllDropdownItems().at(index);
const findGlFormTextAreaDescription = () => wrapper.find(GlFormTextarea);
diff --git a/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
index 24651543650..83ad23f7dcf 100644
--- a/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
+++ b/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
@@ -14,7 +14,7 @@ describe('static_site_editor/graphql/resolvers/file', () => {
it('returns file content and title when fetching file successfully', () => {
loadSourceContent.mockResolvedValueOnce({ title, content });
- return fileResolver({ fullPath: projectId }, { path: sourcePath }).then(file => {
+ return fileResolver({ fullPath: projectId }, { path: sourcePath }).then((file) => {
expect(file).toEqual({
__typename: 'File',
title,
diff --git a/spec/frontend/static_site_editor/services/load_source_content_spec.js b/spec/frontend/static_site_editor/services/load_source_content_spec.js
index 54061b7a503..98d437698c4 100644
--- a/spec/frontend/static_site_editor/services/load_source_content_spec.js
+++ b/spec/frontend/static_site_editor/services/load_source_content_spec.js
@@ -16,7 +16,7 @@ describe('loadSourceContent', () => {
beforeEach(() => {
jest.spyOn(Api, 'getRawFile').mockResolvedValue({ data: sourceContent });
- return loadSourceContent({ projectId, sourcePath }).then(_result => {
+ return loadSourceContent({ projectId, sourcePath }).then((_result) => {
result = _result;
});
});
diff --git a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
index 6c2bff6740a..d4cbc5d235e 100644
--- a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
+++ b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
@@ -188,7 +188,7 @@ describe('submitContentChanges', () => {
let result;
beforeEach(() => {
- return submitContentChanges(buildPayload()).then(_result => {
+ return submitContentChanges(buildPayload()).then((_result) => {
result = _result;
});
});
diff --git a/spec/frontend/syntax_highlight_spec.js b/spec/frontend/syntax_highlight_spec.js
index d2fb5983f7b..418679e7d18 100644
--- a/spec/frontend/syntax_highlight_spec.js
+++ b/spec/frontend/syntax_highlight_spec.js
@@ -4,7 +4,7 @@ import $ from 'jquery';
import syntaxHighlight from '~/syntax_highlight';
describe('Syntax Highlighter', () => {
- const stubUserColorScheme = value => {
+ const stubUserColorScheme = (value) => {
if (window.gon == null) {
window.gon = {};
}
diff --git a/spec/frontend/task_list_spec.js b/spec/frontend/task_list_spec.js
index 1261833e3ec..a8bdc506102 100644
--- a/spec/frontend/task_list_spec.js
+++ b/spec/frontend/task_list_spec.js
@@ -93,7 +93,7 @@ describe('TaskList', () => {
});
describe('update', () => {
- it('should disable task list items and make a patch request then enable them again', done => {
+ it('should disable task list items and make a patch request then enable them again', (done) => {
const response = { data: { lock_version: 3 } };
jest.spyOn(taskList, 'enableTaskListItems').mockImplementation(() => {});
jest.spyOn(taskList, 'disableTaskListItems').mockImplementation(() => {});
@@ -137,7 +137,7 @@ describe('TaskList', () => {
});
});
- it('should handle request error and enable task list items', done => {
+ it('should handle request error and enable task list items', (done) => {
const response = { data: { error: 1 } };
jest.spyOn(taskList, 'enableTaskListItems').mockImplementation(() => {});
jest.spyOn(taskList, 'onError').mockImplementation(() => {});
diff --git a/spec/frontend/terraform/components/states_table_actions_spec.js b/spec/frontend/terraform/components/states_table_actions_spec.js
index 264f4b7939a..3f5df8a96f8 100644
--- a/spec/frontend/terraform/components/states_table_actions_spec.js
+++ b/spec/frontend/terraform/components/states_table_actions_spec.js
@@ -1,6 +1,6 @@
import { GlDropdown, GlModal, GlSprintf } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import VueApollo from 'vue-apollo';
import StateActions from '~/terraform/components/states_table_actions.vue';
import lockStateMutation from '~/terraform/graphql/mutations/lock_state.mutation.graphql';
diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js
index b31afecc816..fb56a7135a3 100644
--- a/spec/frontend/terraform/components/terraform_list_spec.js
+++ b/spec/frontend/terraform/components/terraform_list_spec.js
@@ -1,6 +1,6 @@
import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import VueApollo from 'vue-apollo';
import EmptyState from '~/terraform/components/empty_state.vue';
import StatesTable from '~/terraform/components/states_table.vue';
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 2a3eddf7b4e..a122b06fdda 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -4,15 +4,18 @@ import 'jquery';
import * as jqueryMatchers from 'custom-jquery-matchers';
import { config as testUtilsConfig } from '@vue/test-utils';
import Translate from '~/vue_shared/translate';
-import { initializeTestTimeout } from './helpers/timeout';
-import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './helpers/fixtures';
+import { initializeTestTimeout } from './__helpers__/timeout';
+import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './__helpers__/fixtures';
import { setupManualMocks } from './mocks/mocks_helper';
import customMatchers from './matchers';
-import './helpers/dom_shims';
-import './helpers/jquery';
+import './__helpers__/dom_shims';
+import './__helpers__/jquery';
import '~/commons/bootstrap';
+// This module has some fairly decent visual test coverage in it's own repository.
+jest.mock('@gitlab/favicon-overlay');
+
process.on('unhandledRejection', global.promiseRejectionHandler);
setupManualMocks();
@@ -25,7 +28,7 @@ afterEach(() =>
}),
);
-initializeTestTimeout(process.env.CI ? 6000 : 5000);
+initializeTestTimeout(process.env.CI ? 6000 : 500);
Vue.config.devtools = false;
Vue.config.productionTip = false;
@@ -58,8 +61,18 @@ Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
expect.extend(customMatchers);
-// Tech debt issue TBD
-testUtilsConfig.logModifiedComponents = false;
+testUtilsConfig.deprecationWarningHandler = (method, message) => {
+ const ALLOWED_DEPRECATED_METHODS = [
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/295679
+ 'finding components with `find` or `get`',
+
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/295680
+ 'finding components with `findAll`',
+ ];
+ if (!ALLOWED_DEPRECATED_METHODS.includes(method)) {
+ global.console.error(message);
+ }
+};
Object.assign(global, {
requestIdleCallback(cb) {
diff --git a/spec/frontend/toggle_buttons_spec.js b/spec/frontend/toggle_buttons_spec.js
index 09a4bd53c09..435fd35744f 100644
--- a/spec/frontend/toggle_buttons_spec.js
+++ b/spec/frontend/toggle_buttons_spec.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
+import waitForPromises from 'helpers/wait_for_promises';
import setupToggleButtons from '~/toggle_buttons';
-import waitForPromises from './helpers/wait_for_promises';
function generateMarkup(isChecked = true) {
return `
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
index 50848ca2978..3a894427643 100644
--- a/spec/frontend/tooltips/components/tooltips_spec.js
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -18,7 +18,7 @@ describe('tooltips/components/tooltips.vue', () => {
...attributes,
};
- Object.keys(defaults).forEach(name => {
+ Object.keys(defaults).forEach((name) => {
target.setAttribute(name, defaults[name]);
});
@@ -51,6 +51,16 @@ describe('tooltips/components/tooltips.vue', () => {
expect(wrapper.find(GlTooltip).props('target')).toBe(target);
});
+ it('does not attach a tooltip to a target with empty title', async () => {
+ target.setAttribute('title', '');
+
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).exists()).toBe(false);
+ });
+
it('does not attach a tooltip twice to the same element', async () => {
wrapper.vm.addTooltips([target]);
wrapper.vm.addTooltips([target]);
diff --git a/spec/frontend/tooltips/index_spec.js b/spec/frontend/tooltips/index_spec.js
index 511003fdb8f..bff9ee0c7f2 100644
--- a/spec/frontend/tooltips/index_spec.js
+++ b/spec/frontend/tooltips/index_spec.js
@@ -20,7 +20,7 @@ describe('tooltips/index.js', () => {
title: 'default title',
};
- Object.keys(attributes).forEach(name => {
+ Object.keys(attributes).forEach((name) => {
target.setAttribute(name, attributes[name]);
});
@@ -42,11 +42,11 @@ describe('tooltips/index.js', () => {
};
beforeEach(() => {
- window.gon.glTooltipsEnabled = true;
+ window.gon.features = { glTooltips: true };
});
afterEach(() => {
- document.body.childNodes.forEach(node => node.remove());
+ document.body.childNodes.forEach((node) => node.remove());
destroy();
});
@@ -149,7 +149,7 @@ describe('tooltips/index.js', () => {
describe('when glTooltipsEnabled feature flag is disabled', () => {
beforeEach(() => {
- window.gon.glTooltipsEnabled = false;
+ window.gon.features.glTooltips = false;
});
it.each`
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index d4b97532cdd..a516a4a8269 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -1,4 +1,4 @@
-import { setHTMLFixture } from './helpers/fixtures';
+import { setHTMLFixture } from 'helpers/fixtures';
import Tracking, { initUserTracking, initDefaultTrackers } from '~/tracking';
describe('Tracking', () => {
diff --git a/spec/frontend/transfer_edit_spec.js b/spec/frontend/transfer_edit_spec.js
index dc9455a569d..ad8c9c68f37 100644
--- a/spec/frontend/transfer_edit_spec.js
+++ b/spec/frontend/transfer_edit_spec.js
@@ -13,41 +13,19 @@ describe('setupTransferEdit', () => {
});
it('disables submit button on load', () => {
- expect(
- $(formSelector)
- .find(':submit')
- .prop('disabled'),
- ).toBe(true);
+ expect($(formSelector).find(':submit').prop('disabled')).toBe(true);
});
it('enables submit button when selection changes to non-empty value', () => {
- const nonEmptyValue = $(formSelector)
- .find(targetSelector)
- .find('option')
- .not(':empty')
- .val();
- $(formSelector)
- .find(targetSelector)
- .val(nonEmptyValue)
- .trigger('change');
-
- expect(
- $(formSelector)
- .find(':submit')
- .prop('disabled'),
- ).toBeFalsy();
+ const nonEmptyValue = $(formSelector).find(targetSelector).find('option').not(':empty').val();
+ $(formSelector).find(targetSelector).val(nonEmptyValue).trigger('change');
+
+ expect($(formSelector).find(':submit').prop('disabled')).toBeFalsy();
});
it('disables submit button when selection changes to empty value', () => {
- $(formSelector)
- .find(targetSelector)
- .val('')
- .trigger('change');
-
- expect(
- $(formSelector)
- .find(':submit')
- .prop('disabled'),
- ).toBe(true);
+ $(formSelector).find(targetSelector).val('').trigger('change');
+
+ expect($(formSelector).find(':submit').prop('disabled')).toBe(true);
});
});
diff --git a/spec/frontend/user_lists/components/add_user_modal_spec.js b/spec/frontend/user_lists/components/add_user_modal_spec.js
index 82ce195d7cd..c9ad40ed228 100644
--- a/spec/frontend/user_lists/components/add_user_modal_spec.js
+++ b/spec/frontend/user_lists/components/add_user_modal_spec.js
@@ -4,7 +4,7 @@ import AddUserModal from '~/user_lists/components/add_user_modal.vue';
describe('Add User Modal', () => {
let wrapper;
- const click = testId => wrapper.find(`[data-testid="${testId}"]`).trigger('click');
+ const click = (testId) => wrapper.find(`[data-testid="${testId}"]`).trigger('click');
beforeEach(() => {
wrapper = mount(AddUserModal, {
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 51a38e12916..958e86ac050 100644
--- a/spec/frontend/user_lists/components/edit_user_list_spec.js
+++ b/spec/frontend/user_lists/components/edit_user_list_spec.js
@@ -19,9 +19,9 @@ localVue.use(Vuex);
describe('user_lists/components/edit_user_list', () => {
let wrapper;
- const setInputValue = value => wrapper.find('[data-testid="user-list-name"]').setValue(value);
+ const setInputValue = (value) => wrapper.find('[data-testid="user-list-name"]').setValue(value);
- const click = button => wrapper.find(`[data-testid="${button}"]`).trigger('click');
+ const click = (button) => wrapper.find(`[data-testid="${button}"]`).trigger('click');
const clickSave = () => click('save-user-list');
const destroy = () => wrapper?.destroy();
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 62fb0ca0859..421b49f40e9 100644
--- a/spec/frontend/user_lists/components/new_user_list_spec.js
+++ b/spec/frontend/user_lists/components/new_user_list_spec.js
@@ -18,9 +18,9 @@ localVue.use(Vuex);
describe('user_lists/components/new_user_list', () => {
let wrapper;
- const setInputValue = value => wrapper.find('[data-testid="user-list-name"]').setValue(value);
+ const setInputValue = (value) => wrapper.find('[data-testid="user-list-name"]').setValue(value);
- const click = button => wrapper.find(`[data-testid="${button}"]`).trigger('click');
+ const click = (button) => wrapper.find(`[data-testid="${button}"]`).trigger('click');
beforeEach(() => {
wrapper = mount(NewUserList, {
diff --git a/spec/frontend/user_lists/components/user_list_spec.js b/spec/frontend/user_lists/components/user_list_spec.js
index 5f9b7967846..cd00c421154 100644
--- a/spec/frontend/user_lists/components/user_list_spec.js
+++ b/spec/frontend/user_lists/components/user_list_spec.js
@@ -16,7 +16,7 @@ Vue.use(Vuex);
describe('User List', () => {
let wrapper;
- const click = testId => wrapper.find(`[data-testid="${testId}"]`).trigger('click');
+ const click = (testId) => wrapper.find(`[data-testid="${testId}"]`).trigger('click');
const findUserIds = () => wrapper.findAll('[data-testid="user-id"]');
@@ -38,7 +38,7 @@ describe('User List', () => {
beforeEach(() => {
Api.fetchFeatureFlagUserList.mockReturnValue(
- new Promise(resolve => {
+ new Promise((resolve) => {
resolveFn = resolve;
}),
);
@@ -110,15 +110,15 @@ describe('User List', () => {
});
it('should add user IDs to the user list', () => {
- newIds.forEach(id => expect(receivedUserIds).toContain(id));
+ newIds.forEach((id) => expect(receivedUserIds).toContain(id));
});
it('should not remove existing user ids', () => {
- userIds.forEach(id => expect(receivedUserIds).toContain(id));
+ userIds.forEach((id) => expect(receivedUserIds).toContain(id));
});
it('should not submit empty IDs', () => {
- parsedReceivedUserIds.forEach(id => expect(id).not.toBe(''));
+ parsedReceivedUserIds.forEach((id) => expect(id).not.toBe(''));
});
it('should not create duplicate entries', () => {
@@ -127,8 +127,8 @@ describe('User List', () => {
it('should display the new IDs', () => {
const userIdWrappers = findUserIds();
- newIds.forEach(id => {
- const userIdWrapper = userIdWrappers.wrappers.find(w => w.text() === id);
+ newIds.forEach((id) => {
+ const userIdWrapper = userIdWrappers.wrappers.find((w) => w.text() === id);
expect(userIdWrapper.exists()).toBe(true);
});
});
@@ -150,7 +150,7 @@ describe('User List', () => {
it('should not display the deleted user', () => {
const userIdWrappers = findUserIds();
- const userIdWrapper = userIdWrappers.wrappers.find(w => w.text() === userIds[0]);
+ const userIdWrapper = userIdWrappers.wrappers.find((w) => w.text() === userIds[0]);
expect(userIdWrapper).toBeUndefined();
});
});
diff --git a/spec/frontend/user_lists/store/show/mutations_spec.js b/spec/frontend/user_lists/store/show/mutations_spec.js
index 364cc6a0225..cd379641ee1 100644
--- a/spec/frontend/user_lists/store/show/mutations_spec.js
+++ b/spec/frontend/user_lists/store/show/mutations_spec.js
@@ -57,7 +57,7 @@ describe('User Lists Show Mutations', () => {
});
it('adds the new IDs to the state unless empty', () => {
- newIds.filter(id => id).forEach(id => expect(mockState.userIds).toContain(id));
+ newIds.filter((id) => id).forEach((id) => expect(mockState.userIds).toContain(id));
});
it('does not add duplicate IDs to the state', () => {
@@ -80,7 +80,9 @@ describe('User Lists Show Mutations', () => {
});
it('should leave the rest of the IDs alone', () => {
- userIds.filter(id => id !== removedId).forEach(id => expect(mockState.userIds).toContain(id));
+ userIds
+ .filter((id) => id !== removedId)
+ .forEach((id) => expect(mockState.userIds).toContain(id));
});
});
});
diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js
index 0367b9cc924..1e0c4dd29ee 100644
--- a/spec/frontend/user_popovers_spec.js
+++ b/spec/frontend/user_popovers_spec.js
@@ -26,12 +26,12 @@ describe('User Popovers', () => {
loadFixtures(fixtureTemplate);
const usersCacheSpy = () => Promise.resolve(dummyUser);
- jest.spyOn(UsersCache, 'retrieveById').mockImplementation(userId => usersCacheSpy(userId));
+ jest.spyOn(UsersCache, 'retrieveById').mockImplementation((userId) => usersCacheSpy(userId));
const userStatusCacheSpy = () => Promise.resolve(dummyUserStatus);
jest
.spyOn(UsersCache, 'retrieveStatusById')
- .mockImplementation(userId => userStatusCacheSpy(userId));
+ .mockImplementation((userId) => userStatusCacheSpy(userId));
popovers = initUserPopovers(document.querySelectorAll(selector));
});
diff --git a/spec/frontend/version_check_image_spec.js b/spec/frontend/version_check_image_spec.js
index 2ab157105a1..13bd104a91c 100644
--- a/spec/frontend/version_check_image_spec.js
+++ b/spec/frontend/version_check_image_spec.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
+import ClassSpecHelper from 'helpers/class_spec_helper';
import VersionCheckImage from '~/version_check_image';
-import ClassSpecHelper from './helpers/class_spec_helper';
describe('VersionCheckImage', () => {
let testContext;
@@ -19,7 +19,7 @@ describe('VersionCheckImage', () => {
it('registers an error event', () => {
jest.spyOn($.prototype, 'on').mockImplementation(() => {});
// eslint-disable-next-line func-names
- jest.spyOn($.prototype, 'off').mockImplementation(function() {
+ jest.spyOn($.prototype, 'off').mockImplementation(function () {
return this;
});
diff --git a/spec/frontend/vue_alerts_spec.js b/spec/frontend/vue_alerts_spec.js
index b52737e6106..16eb2d44e4d 100644
--- a/spec/frontend/vue_alerts_spec.js
+++ b/spec/frontend/vue_alerts_spec.js
@@ -27,7 +27,7 @@ describe('VueAlerts', () => {
setHTMLFixture(
alerts
.map(
- x => `
+ (x) => `
<div class="js-vue-alert"
data-dismissible="${x.dismissible}"
data-title="${x.title}"
@@ -42,15 +42,15 @@ describe('VueAlerts', () => {
const findJsHooks = () => document.querySelectorAll('.js-vue-alert');
const findAlerts = () => document.querySelectorAll('.gl-alert');
- const findAlertDismiss = alert => alert.querySelector('.gl-alert-dismiss');
+ const findAlertDismiss = (alert) => alert.querySelector('.gl-alert-dismiss');
- const serializeAlert = alert => ({
+ const serializeAlert = (alert) => ({
title: alert.querySelector('.gl-alert-title').textContent.trim(),
html: alert.querySelector('.gl-alert-body div').innerHTML,
dismissible: Boolean(alert.querySelector('.gl-alert-dismiss')),
primaryButtonText: alert.querySelector('.gl-alert-action').textContent.trim(),
primaryButtonLink: alert.querySelector('.gl-alert-action').href,
- variant: [...alert.classList].find(x => x.match('gl-alert-')).replace('gl-alert-', ''),
+ variant: [...alert.classList].find((x) => x.match('gl-alert-')).replace('gl-alert-', ''),
});
it('starts with only JsHooks', () => {
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 65ca3639dcc..fd8b0dddc61 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
+++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
@@ -15,10 +15,10 @@ import eventHub from '~/vue_merge_request_widget/event_hub';
jest.mock('~/flash');
const TEST_HELP_PATH = 'help/path';
-const testApprovedBy = () => [1, 7, 10].map(id => ({ id }));
+const testApprovedBy = () => [1, 7, 10].map((id) => ({ id }));
const testApprovals = () => ({
approved: false,
- approved_by: testApprovedBy().map(user => ({ user })),
+ approved_by: testApprovedBy().map((user) => ({ user })),
approval_rules_left: [],
approvals_left: 4,
suggested_approvers: [],
@@ -31,10 +31,7 @@ const testApprovalRulesResponse = () => ({ rules: [{ id: 2 }] });
// For some reason, the `Promise.resolve()` needs to be deferred
// or the timing doesn't work.
const tick = () => Promise.resolve();
-const waitForTick = done =>
- tick()
- .then(done)
- .catch(done.fail);
+const waitForTick = (done) => tick().then(done).catch(done.fail);
describe('MRWidget approvals', () => {
let wrapper;
@@ -117,7 +114,7 @@ describe('MRWidget approvals', () => {
});
describe('when fetch approvals error', () => {
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(service, 'fetchApprovals').mockReturnValue(Promise.reject());
createComponent();
waitForTick(done);
@@ -134,7 +131,7 @@ describe('MRWidget approvals', () => {
describe('action button', () => {
describe('when mr is closed', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.isOpen = false;
mr.approvals.user_has_approved = false;
mr.approvals.user_can_approve = true;
@@ -149,7 +146,7 @@ describe('MRWidget approvals', () => {
});
describe('when user cannot approve', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.approvals.user_has_approved = false;
mr.approvals.user_can_approve = false;
@@ -169,7 +166,7 @@ describe('MRWidget approvals', () => {
});
describe('and MR is unapproved', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent();
waitForTick(done);
});
@@ -189,7 +186,7 @@ describe('MRWidget approvals', () => {
});
describe('with no approvers', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.approvals.approved_by = [];
createComponent();
waitForTick(done);
@@ -205,7 +202,7 @@ describe('MRWidget approvals', () => {
});
describe('with approvers', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.approvals.approved_by = [{ user: { id: 7 } }];
createComponent();
waitForTick(done);
@@ -222,7 +219,7 @@ describe('MRWidget approvals', () => {
});
describe('when approve action is clicked', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent();
waitForTick(done);
});
@@ -241,7 +238,7 @@ describe('MRWidget approvals', () => {
});
describe('and after loading', () => {
- beforeEach(done => {
+ beforeEach((done) => {
findAction().vm.$emit('click');
waitForTick(done);
});
@@ -260,7 +257,7 @@ describe('MRWidget approvals', () => {
});
describe('and error', () => {
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(service, 'approveMergeRequest').mockReturnValue(Promise.reject());
findAction().vm.$emit('click');
waitForTick(done);
@@ -274,7 +271,7 @@ describe('MRWidget approvals', () => {
});
describe('when user has approved', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.approvals.user_has_approved = true;
mr.approvals.user_can_approve = false;
@@ -292,7 +289,7 @@ describe('MRWidget approvals', () => {
describe('when revoke action is clicked', () => {
describe('and successful', () => {
- beforeEach(done => {
+ beforeEach((done) => {
findAction().vm.$emit('click');
waitForTick(done);
});
@@ -311,7 +308,7 @@ describe('MRWidget approvals', () => {
});
describe('and error', () => {
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(service, 'unapproveMergeRequest').mockReturnValue(Promise.reject());
findAction().vm.$emit('click');
waitForTick(done);
@@ -334,7 +331,7 @@ describe('MRWidget approvals', () => {
});
describe('and can approve', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.approvals.user_can_approve = true;
createComponent();
@@ -351,7 +348,7 @@ describe('MRWidget approvals', () => {
});
describe('and cannot approve', () => {
- beforeEach(done => {
+ beforeEach((done) => {
mr.approvals.user_can_approve = false;
createComponent();
@@ -370,7 +367,7 @@ describe('MRWidget approvals', () => {
});
describe('approvals summary', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent();
waitForTick(done);
});
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 822d075f28f..b8ba619fbb1 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
@@ -4,7 +4,7 @@ import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/ap
import { toNounSeriesText } from '~/lib/utils/grammar';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
-const testApprovers = () => Array.from({ length: 5 }, (_, i) => i).map(id => ({ id }));
+const testApprovers = () => Array.from({ length: 5 }, (_, i) => i).map((id) => ({ id }));
const testRulesLeft = () => ['Lorem', 'Ipsum', 'dolar & sit'];
const TEST_APPROVALS_LEFT = 3;
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 1401308f7f0..2e1e21299b3 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,19 +1,20 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+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 { TEST_HOST } from 'helpers/test_constants';
+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';
-import createStore from '~/vue_merge_request_widget/stores/artifacts_list';
-import { artifactsList } from './mock_data';
+import { getStoreConfig } from '~/vue_merge_request_widget/stores/artifacts_list';
+import { artifacts } from '../mock_data';
+
+Vue.use(Vuex);
describe('Merge Requests Artifacts list app', () => {
let wrapper;
+ let store;
let mock;
- const store = createStore();
- const localVue = createLocalVue();
- localVue.use(Vuex);
const actionSpies = {
fetchArtifacts: jest.fn(),
@@ -29,15 +30,20 @@ describe('Merge Requests Artifacts list app', () => {
});
const createComponent = () => {
+ const storeConfig = getStoreConfig();
+ store = new Vuex.Store({
+ ...storeConfig,
+ actions: {
+ ...storeConfig.actions,
+ ...actionSpies,
+ },
+ });
+
wrapper = mount(ArtifactsListApp, {
propsData: {
- endpoint: TEST_HOST,
+ endpoint: FAKE_ENDPOINT,
},
store,
- methods: {
- ...actionSpies,
- },
- localVue,
});
};
@@ -50,7 +56,7 @@ describe('Merge Requests Artifacts list app', () => {
beforeEach(() => {
createComponent();
store.dispatch('requestArtifacts');
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('renders a loading icon', () => {
@@ -72,12 +78,12 @@ describe('Merge Requests Artifacts list app', () => {
describe('with results', () => {
beforeEach(() => {
createComponent();
- mock.onGet(wrapper.vm.$store.state.endpoint).reply(200, artifactsList, {});
+ mock.onGet(FAKE_ENDPOINT).reply(200, artifacts, {});
store.dispatch('receiveArtifactsSuccess', {
- data: artifactsList,
+ data: artifacts,
status: 200,
});
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('renders a title with the number of artifacts', () => {
@@ -91,11 +97,11 @@ describe('Merge Requests Artifacts list app', () => {
});
describe('on click', () => {
- it('renders the list of artifacts', () => {
+ it('renders the list of artifacts', async () => {
findTitle().trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(findTableRows().length).toEqual(2);
- });
+ await nextTick();
+
+ expect(findTableRows().length).toEqual(2);
});
});
});
@@ -103,9 +109,9 @@ describe('Merge Requests Artifacts list app', () => {
describe('with error', () => {
beforeEach(() => {
createComponent();
- mock.onGet(wrapper.vm.$store.state.endpoint).reply(500, {}, {});
+ mock.onGet(FAKE_ENDPOINT).reply(500, {}, {});
store.dispatch('receiveArtifactsError');
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('renders the error state', () => {
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 1b1624e3e8f..fd432381512 100644
--- a/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js
+++ b/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js
@@ -1,16 +1,16 @@
import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
import ArtifactsList from '~/vue_merge_request_widget/components/artifacts_list.vue';
-import { artifactsList } from './mock_data';
+import { artifacts } from '../mock_data';
describe('Artifacts List', () => {
let wrapper;
const data = {
- artifacts: artifactsList,
+ artifacts,
};
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(ArtifactsList, {
propsData: {
...props,
@@ -39,20 +39,10 @@ describe('Artifacts List', () => {
});
it('renders job url', () => {
- expect(
- wrapper
- .findAll(GlLink)
- .at(1)
- .attributes('href'),
- ).toEqual(data.artifacts[0].job_path);
+ expect(wrapper.findAll(GlLink).at(1).attributes('href')).toEqual(data.artifacts[0].job_path);
});
it('renders job name', () => {
- expect(
- wrapper
- .findAll(GlLink)
- .at(1)
- .text(),
- ).toEqual(data.artifacts[0].job_name);
+ expect(wrapper.findAll(GlLink).at(1).text()).toEqual(data.artifacts[0].job_name);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mock_data.js b/spec/frontend/vue_mr_widget/components/mock_data.js
deleted file mode 100644
index 73e254f2b1a..00000000000
--- a/spec/frontend/vue_mr_widget/components/mock_data.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const artifactsList = [
- {
- text: 'result.txt',
- url: 'bar',
- job_name: 'generate-artifact',
- job_path: 'bar',
- },
- {
- text: 'foo.txt',
- url: 'foo',
- job_name: 'foo-artifact',
- job_path: 'foo',
- },
-];
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 8a604355625..ba2a8ee0a41 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
@@ -8,7 +8,7 @@ describe('Merge Request Collapsible Extension', () => {
title: 'View artifacts',
};
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = mount(MrCollapsibleSection, {
propsData: {
...props,
@@ -65,18 +65,8 @@ describe('Merge Request Collapsible Extension', () => {
});
it('renders the buttons disabled', () => {
- expect(
- wrapper
- .findAll('button')
- .at(0)
- .attributes('disabled'),
- ).toEqual('disabled');
- expect(
- wrapper
- .findAll('button')
- .at(1)
- .attributes('disabled'),
- ).toEqual('disabled');
+ expect(wrapper.findAll('button').at(0).attributes('disabled')).toEqual('disabled');
+ expect(wrapper.findAll('button').at(1).attributes('disabled')).toEqual('disabled');
});
it('renders loading spinner', () => {
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 f78fcfb52b4..720ce613b85 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
@@ -19,7 +19,7 @@ describe('MrWidgetAlertMessage', () => {
});
describe('when type is not provided', () => {
- it('should render a red message', done => {
+ it('should render a red message', (done) => {
wrapper.vm.$nextTick(() => {
expect(wrapper.classes()).toContain('danger_message');
expect(wrapper.classes()).not.toContain('warning_message');
@@ -29,7 +29,7 @@ describe('MrWidgetAlertMessage', () => {
});
describe('when type === "danger"', () => {
- it('should render a red message', done => {
+ it('should render a red message', (done) => {
wrapper.setProps({ type: 'danger' });
wrapper.vm.$nextTick(() => {
expect(wrapper.classes()).toContain('danger_message');
@@ -40,7 +40,7 @@ describe('MrWidgetAlertMessage', () => {
});
describe('when type === "warning"', () => {
- it('should render a red message', done => {
+ it('should render a red message', (done) => {
wrapper.setProps({ type: 'warning' });
wrapper.vm.$nextTick(() => {
expect(wrapper.classes()).toContain('warning_message');
@@ -51,7 +51,7 @@ describe('MrWidgetAlertMessage', () => {
});
describe('when helpPath is not provided', () => {
- it('should not render a help icon/link', done => {
+ it('should not render a help icon/link', (done) => {
wrapper.vm.$nextTick(() => {
const link = wrapper.find(GlLink);
@@ -62,7 +62,7 @@ describe('MrWidgetAlertMessage', () => {
});
describe('when helpPath is provided', () => {
- it('should render a help icon/link', done => {
+ it('should render a help icon/link', (done) => {
wrapper.setProps({ helpPath: '/path/to/help/docs' });
wrapper.vm.$nextTick(() => {
const link = wrapper.find(GlLink);
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js
index f9b6ac721d2..db884dfe015 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js
@@ -187,7 +187,7 @@ describe('MRWidgetHeader', () => {
expect(link.getAttribute('href')).toBeNull();
});
- it('renders web ide button with blank query string if target & source project branch', done => {
+ it('renders web ide button with blank query string if target & source project branch', (done) => {
vm.mr.targetProjectFullPath = 'root/gitlab-ce';
vm.$nextTick(() => {
@@ -202,7 +202,7 @@ describe('MRWidgetHeader', () => {
});
});
- it('renders web ide button with relative URL', done => {
+ it('renders web ide button with relative URL', (done) => {
gon.relative_url_root = '/gitlab';
vm.mr.iid = 2;
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 ea8b33495ab..4bcae904ddc 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
@@ -20,7 +20,7 @@ describe('MrWidgetIcon', () => {
});
it('renders icon and container', () => {
- expect(wrapper.is('.circle-icon-container')).toBe(true);
+ expect(wrapper.element.className).toContain('circle-icon-container');
expect(wrapper.find(GlIcon).props('name')).toEqual(TEST_ICON);
});
});
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 7a932feb3a7..79a0dd1e760 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
@@ -153,13 +153,13 @@ describe('MemoryUsage', () => {
describe('loadMetrics', () => {
const returnServicePromise = () =>
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
data: metricsMockData,
});
});
- it('should load metrics data using MRWidgetService', done => {
+ it('should load metrics data using MRWidgetService', (done) => {
jest.spyOn(MRWidgetService, 'fetchMetrics').mockReturnValue(returnServicePromise(true));
jest.spyOn(vm, 'computeGraphData').mockImplementation(() => {});
@@ -179,7 +179,7 @@ describe('MemoryUsage', () => {
expect(el.querySelector('.js-usage-info')).toBeDefined();
});
- it('should show loading metrics message while metrics are being loaded', done => {
+ it('should show loading metrics message while metrics are being loaded', (done) => {
vm.loadingMetrics = true;
vm.hasMetrics = false;
vm.loadFailed = false;
@@ -194,7 +194,7 @@ describe('MemoryUsage', () => {
});
});
- it('should show deployment memory usage when metrics are loaded', done => {
+ it('should show deployment memory usage when metrics are loaded', (done) => {
// ignore BoostrapVue warnings
jest.spyOn(console, 'warn').mockImplementation();
@@ -210,7 +210,7 @@ describe('MemoryUsage', () => {
});
});
- it('should show failure message when metrics loading failed', done => {
+ it('should show failure message when metrics loading failed', (done) => {
vm.loadingMetrics = false;
vm.hasMetrics = false;
vm.loadFailed = true;
@@ -223,7 +223,7 @@ describe('MemoryUsage', () => {
});
});
- it('should show metrics unavailable message when metrics loading failed', done => {
+ it('should show metrics unavailable message when metrics loading failed', (done) => {
vm.loadingMetrics = false;
vm.hasMetrics = false;
vm.loadFailed = false;
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 d67f1adadf2..85468c5b0db 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
@@ -46,7 +46,7 @@ describe('MrWidgetPipelineContainer', () => {
});
it('renders deployments', () => {
- const expectedProps = mockStore.deployments.map(dep =>
+ const expectedProps = mockStore.deployments.map((dep) =>
expect.objectContaining({
deployment: dep,
showMetrics: false,
@@ -55,7 +55,7 @@ describe('MrWidgetPipelineContainer', () => {
const deployments = wrapper.findAll('.mr-widget-extension .js-pre-deployment');
- expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
+ expect(deployments.wrappers.map((x) => x.props())).toEqual(expectedProps);
});
});
@@ -79,7 +79,7 @@ describe('MrWidgetPipelineContainer', () => {
});
it('renders deployments', () => {
- const expectedProps = mockStore.postMergeDeployments.map(dep =>
+ const expectedProps = mockStore.postMergeDeployments.map((dep) =>
expect.objectContaining({
deployment: dep,
showMetrics: true,
@@ -88,12 +88,14 @@ describe('MrWidgetPipelineContainer', () => {
const deployments = wrapper.findAll('.mr-widget-extension .js-post-deployment');
- expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
+ expect(deployments.wrappers.map((x) => x.props())).toEqual(expectedProps);
});
});
describe('with artifacts path', () => {
it('renders the artifacts app', () => {
+ factory();
+
expect(wrapper.find(ArtifactsApp).isVisible()).toBe(true);
});
});
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 7ecd8629607..3e5ab5cd32d 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
@@ -72,21 +72,13 @@ describe('MRWidgetPipeline', () => {
});
it('should render pipeline ID', () => {
- expect(
- findPipelineID()
- .text()
- .trim(),
- ).toBe(`#${mockData.pipeline.id}`);
+ expect(findPipelineID().text().trim()).toBe(`#${mockData.pipeline.id}`);
});
it('should render pipeline status and commit id', () => {
expect(findPipelineInfoContainer().text()).toMatch(mockData.pipeline.details.status.label);
- expect(
- findCommitLink()
- .text()
- .trim(),
- ).toBe(mockData.pipeline.commit.short_id);
+ expect(findCommitLink().text().trim()).toBe(mockData.pipeline.commit.short_id);
expect(findCommitLink().attributes('href')).toBe(mockData.pipeline.commit.commit_path);
});
@@ -130,7 +122,7 @@ describe('MRWidgetPipeline', () => {
it.each(mockData.buildsWithCoverage)(
'should have name and coverage for build %s listed in tooltip',
- build => {
+ (build) => {
const tooltipText = findPipelineCoverageTooltipText();
expect(tooltipText).toContain(`${build.name} (${build.coverage}%)`);
@@ -148,11 +140,7 @@ describe('MRWidgetPipeline', () => {
});
it('should render pipeline ID', () => {
- expect(
- findPipelineID()
- .text()
- .trim(),
- ).toBe(`#${mockData.pipeline.id}`);
+ expect(findPipelineID().text().trim()).toBe(`#${mockData.pipeline.id}`);
});
it('should render pipeline status', () => {
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 9923434a7dd..bdd038edd71 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,135 +1,181 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
import eventHub from '~/vue_merge_request_widget/event_hub';
-import component from '~/vue_merge_request_widget/components/states/mr_widget_rebase.vue';
+import WidgetRebase from '~/vue_merge_request_widget/components/states/mr_widget_rebase.vue';
+
+let wrapper;
+
+function factory(propsData, mergeRequestWidgetGraphql) {
+ wrapper = shallowMount(WidgetRebase, {
+ propsData,
+ data() {
+ return {
+ state: {
+ rebaseInProgress: propsData.mr.rebaseInProgress,
+ targetBranch: propsData.mr.targetBranch,
+ userPermissions: {
+ pushToSourceBranch: propsData.mr.canPushToSourceBranch,
+ },
+ },
+ };
+ },
+ provide: { glFeatures: { mergeRequestWidgetGraphql } },
+ mocks: {
+ $apollo: {
+ queries: {
+ state: { loading: false },
+ },
+ },
+ },
+ });
+}
describe('Merge request widget rebase component', () => {
- let Component;
- let vm;
-
- const findRebaseMessageEl = () => vm.$el.querySelector('[data-testid="rebase-message"]');
- const findRebaseMessageElText = () => findRebaseMessageEl().textContent.trim();
-
- beforeEach(() => {
- Component = Vue.extend(component);
- });
+ const findRebaseMessageEl = () => wrapper.find('[data-testid="rebase-message"]');
+ const findRebaseMessageElText = () => findRebaseMessageEl().text();
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- describe('While rebasing', () => {
- it('should show progress message', () => {
- vm = mountComponent(Component, {
- mr: { rebaseInProgress: true },
- service: {},
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
+ describe(`widget graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'dislabed'}`, () => {
+ describe('While rebasing', () => {
+ it('should show progress message', () => {
+ factory(
+ {
+ mr: { rebaseInProgress: true },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ expect(findRebaseMessageElText()).toContain('Rebase in progress');
+ });
});
- expect(findRebaseMessageElText()).toContain('Rebase in progress');
- });
- });
-
- describe('With permissions', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: true,
- },
- service: {},
- });
- });
-
- it('it should render rebase button and warning message', () => {
- const text = findRebaseMessageElText();
-
- expect(text).toContain('Fast-forward merge is not possible.');
- expect(text.replace(/\s\s+/g, ' ')).toContain(
- 'Rebase the source branch onto the target branch.',
- );
- });
+ describe('With permissions', () => {
+ it('it should render rebase button and warning message', () => {
+ factory(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: true,
+ },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ const text = findRebaseMessageElText();
+
+ expect(text).toContain('Fast-forward merge is not possible.');
+ expect(text.replace(/\s\s+/g, ' ')).toContain(
+ 'Rebase the source branch onto the target branch.',
+ );
+ });
+
+ it('it should render error message when it fails', async () => {
+ factory(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: true,
+ },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
- it('it should render error message when it fails', done => {
- vm.rebasingError = 'Something went wrong!';
+ wrapper.setData({ rebasingError: 'Something went wrong!' });
- Vue.nextTick(() => {
- expect(findRebaseMessageElText()).toContain('Something went wrong!');
- done();
+ await nextTick();
+ expect(findRebaseMessageElText()).toContain('Something went wrong!');
+ });
});
- });
- });
- describe('Without permissions', () => {
- it('should render a message explaining user does not have permissions', () => {
- vm = mountComponent(Component, {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: false,
- targetBranch: 'foo',
- },
- service: {},
- });
-
- const text = findRebaseMessageElText();
+ describe('Without permissions', () => {
+ it('should render a message explaining user does not have permissions', () => {
+ factory(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: false,
+ targetBranch: 'foo',
+ },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ const text = findRebaseMessageElText();
+
+ expect(text).toContain('Fast-forward merge is not possible.');
+ expect(text).toContain('Rebase the source branch onto');
+ expect(text).toContain('foo');
+ expect(text.replace(/\s\s+/g, ' ')).toContain(
+ 'to allow this merge request to be merged.',
+ );
+ });
+
+ it('should render the correct target branch name', () => {
+ const targetBranch = 'fake-branch-to-test-with';
+ factory(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: false,
+ targetBranch,
+ },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
- expect(text).toContain('Fast-forward merge is not possible.');
- expect(text).toContain('Rebase the source branch onto');
- expect(text).toContain('foo');
- expect(text.replace(/\s\s+/g, ' ')).toContain('to allow this merge request to be merged.');
- });
+ const elem = findRebaseMessageEl();
- it('should render the correct target branch name', () => {
- const targetBranch = 'fake-branch-to-test-with';
- vm = mountComponent(Component, {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: false,
- targetBranch,
- },
- service: {},
+ expect(elem.text()).toContain(
+ `Fast-forward merge is not possible. Rebase the source branch onto ${targetBranch} to allow this merge request to be merged.`,
+ );
+ });
});
- const elem = findRebaseMessageEl();
-
- expect(elem.innerHTML).toContain(
- `Fast-forward merge is not possible. Rebase the source branch onto <span class="label-branch">${targetBranch}</span> to allow this merge request to be merged.`,
- );
- });
- });
-
- describe('methods', () => {
- it('checkRebaseStatus', done => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- vm = mountComponent(Component, {
- mr: {},
- service: {
- rebase() {
- return Promise.resolve();
- },
- poll() {
- return Promise.resolve({
- data: {
- rebase_in_progress: false,
- merge_error: null,
+ describe('methods', () => {
+ it('checkRebaseStatus', async () => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ factory(
+ {
+ mr: {},
+ service: {
+ rebase() {
+ return Promise.resolve();
+ },
+ poll() {
+ return Promise.resolve({
+ data: {
+ rebase_in_progress: false,
+ merge_error: null,
+ },
+ });
+ },
},
- });
- },
- },
- });
+ },
+ mergeRequestWidgetGraphql,
+ );
- vm.rebase();
+ wrapper.vm.rebase();
+
+ // Wait for the rebase request
+ await nextTick();
+ // Wait for the polling request
+ await nextTick();
+ // Wait for the eventHub to be called
+ await nextTick();
- // Wait for the rebase request
- vm.$nextTick()
- // Wait for the polling request
- .then(vm.$nextTick())
- // Wait for the eventHub to be called
- .then(vm.$nextTick())
- .then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetRebaseSuccess');
- })
- .then(done)
- .catch(done.fail);
+ });
+ });
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js
index 0c4ec7ed99b..a33401c5ba9 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js
@@ -5,7 +5,7 @@ import relatedLinksComponent from '~/vue_merge_request_widget/components/mr_widg
describe('MRWidgetRelatedLinks', () => {
let vm;
- const createComponent = data => {
+ const createComponent = (data) => {
const Component = Vue.extend(relatedLinksComponent);
return mountComponent(Component, data);
diff --git a/spec/frontend/vue_mr_widget/components/review_app_link_spec.js b/spec/frontend/vue_mr_widget/components/review_app_link_spec.js
index 7d47621c64a..81a52890db7 100644
--- a/spec/frontend/vue_mr_widget/components/review_app_link_spec.js
+++ b/spec/frontend/vue_mr_widget/components/review_app_link_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/vue_merge_request_widget/components/review_app_link.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
describe('review app link', () => {
const Component = Vue.extend(component);
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
new file mode 100644
index 00000000000..c425a3a86a9
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -0,0 +1,183 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have correct elements 1`] = `
+<div
+ class="mr-widget-body media"
+>
+ <status-icon-stub
+ status="success"
+ />
+
+ <div
+ class="media-body"
+ >
+ <h4
+ class="gl-display-flex"
+ >
+ <span
+ class="gl-mr-3"
+ >
+ <span
+ class="js-status-text-before-author"
+ data-testid="beforeStatusText"
+ >
+ Set by
+ </span>
+
+ <mr-widget-author-stub
+ author="[object Object]"
+ showauthorname="true"
+ />
+
+ <span
+ class="js-status-text-after-author"
+ data-testid="afterStatusText"
+ >
+ to be merged automatically when the pipeline succeeds
+ </span>
+ </span>
+
+ <a
+ class="btn btn-sm btn-default js-cancel-auto-merge"
+ data-testid="cancelAutomaticMergeButton"
+ href="#"
+ role="button"
+ >
+ <!---->
+
+ Cancel automatic merge
+
+ </a>
+ </h4>
+
+ <section
+ class="mr-info-list"
+ >
+ <p>
+
+ The changes will be merged into
+
+ <a
+ class="label-branch"
+ href="/foo/bar"
+ >
+ foo
+ </a>
+ </p>
+
+ <p
+ class="gl-display-flex"
+ >
+ <span
+ class="gl-mr-3"
+ >
+ The source branch will not be deleted
+ </span>
+
+ <a
+ class="btn btn-sm btn-default js-remove-source-branch"
+ data-testid="removeSourceBranchButton"
+ href="#"
+ role="button"
+ >
+ <!---->
+
+ Delete source branch
+
+ </a>
+ </p>
+ </section>
+ </div>
+</div>
+`;
+
+exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have correct elements 1`] = `
+<div
+ class="mr-widget-body media"
+>
+ <status-icon-stub
+ status="success"
+ />
+
+ <div
+ class="media-body"
+ >
+ <h4
+ class="gl-display-flex"
+ >
+ <span
+ class="gl-mr-3"
+ >
+ <span
+ class="js-status-text-before-author"
+ data-testid="beforeStatusText"
+ >
+ Set by
+ </span>
+
+ <mr-widget-author-stub
+ author="[object Object]"
+ showauthorname="true"
+ />
+
+ <span
+ class="js-status-text-after-author"
+ data-testid="afterStatusText"
+ >
+ to be merged automatically when the pipeline succeeds
+ </span>
+ </span>
+
+ <a
+ class="btn btn-sm btn-default js-cancel-auto-merge"
+ data-testid="cancelAutomaticMergeButton"
+ href="#"
+ role="button"
+ >
+ <!---->
+
+ Cancel automatic merge
+
+ </a>
+ </h4>
+
+ <section
+ class="mr-info-list"
+ >
+ <p>
+
+ The changes will be merged into
+
+ <a
+ class="label-branch"
+ href="/foo/bar"
+ >
+ foo
+ </a>
+ </p>
+
+ <p
+ class="gl-display-flex"
+ >
+ <span
+ class="gl-mr-3"
+ >
+ The source branch will not be deleted
+ </span>
+
+ <a
+ class="btn btn-sm btn-default js-remove-source-branch"
+ data-testid="removeSourceBranchButton"
+ href="#"
+ role="button"
+ >
+ <!---->
+
+ Delete source branch
+
+ </a>
+ </p>
+ </section>
+ </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 ae0f605c419..850bbd93df5 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,20 +1,81 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
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';
+let wrapper;
+let mergeRequestWidgetGraphqlEnabled = false;
+
+function convertPropsToGraphqlState(props) {
+ return {
+ autoMergeStrategy: props.autoMergeStrategy,
+ cancelAutoMergePath: 'http://text.com',
+ mergeUser: {
+ id: props.mergeUserId,
+ ...props.setToAutoMergeBy,
+ },
+ targetBranch: props.targetBranch,
+ targetBranchCommitsPath: props.targetBranchPath,
+ shouldRemoveSourceBranch: props.shouldRemoveSourceBranch,
+ forceRemoveSourceBranch: props.shouldRemoveSourceBranch,
+ userPermissions: {
+ removeSourceBranch: props.canRemoveSourceBranch,
+ },
+ };
+}
+
+function factory(propsData) {
+ let state = {};
+
+ if (mergeRequestWidgetGraphqlEnabled) {
+ state = convertPropsToGraphqlState(propsData);
+ }
+
+ wrapper = extendedWrapper(
+ shallowMount(autoMergeEnabledComponent, {
+ propsData: {
+ mr: propsData,
+ service: new MRWidgetService({}),
+ },
+ data() {
+ return { state };
+ },
+ provide: { glFeatures: { mergeRequestWidgetGraphql: mergeRequestWidgetGraphqlEnabled } },
+ mocks: {
+ $apollo: {
+ queries: {
+ state: { loading: false },
+ },
+ },
+ },
+ }),
+ );
+}
+
+const targetBranchPath = '/foo/bar';
+const targetBranch = 'foo';
+const sha = '1EA2EZ34';
+const defaultMrProps = () => ({
+ shouldRemoveSourceBranch: false,
+ canRemoveSourceBranch: true,
+ canCancelAutomaticMerge: true,
+ mergeUserId: 1,
+ currentUserId: 1,
+ setToAutoMergeBy: {},
+ sha,
+ targetBranchPath,
+ targetBranch,
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+});
+
describe('MRWidgetAutoMergeEnabled', () => {
- let vm;
let oldWindowGl;
- const targetBranchPath = '/foo/bar';
- const targetBranch = 'foo';
- const sha = '1EA2EZ34';
beforeEach(() => {
- const Component = Vue.extend(autoMergeEnabledComponent);
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
oldWindowGl = window.gl;
@@ -23,216 +84,234 @@ describe('MRWidgetAutoMergeEnabled', () => {
defaultAvatarUrl: 'no_avatar.png',
},
};
-
- vm = mountComponent(Component, {
- mr: {
- shouldRemoveSourceBranch: false,
- canRemoveSourceBranch: true,
- canCancelAutomaticMerge: true,
- mergeUserId: 1,
- currentUserId: 1,
- setToAutoMergeBy: {},
- sha,
- targetBranchPath,
- targetBranch,
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
- },
- service: new MRWidgetService({}),
- });
});
afterEach(() => {
- vm.$destroy();
window.gl = oldWindowGl;
+ wrapper.destroy();
+ wrapper = null;
});
- describe('computed', () => {
- describe('canRemoveSourceBranch', () => {
- it('should return true when user is able to remove source branch', () => {
- expect(vm.canRemoveSourceBranch).toBeTruthy();
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
+ describe(`when graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'disabled'}`, () => {
+ beforeEach(() => {
+ mergeRequestWidgetGraphqlEnabled = mergeRequestWidgetGraphql;
});
- it('should return false when user id is not the same with who set the MWPS', () => {
- vm.mr.mergeUserId = 2;
-
- expect(vm.canRemoveSourceBranch).toBeFalsy();
-
- vm.mr.currentUserId = 2;
-
- expect(vm.canRemoveSourceBranch).toBeTruthy();
+ describe('computed', () => {
+ describe('canRemoveSourceBranch', () => {
+ it('should return true when user is able to remove source branch', () => {
+ factory({
+ ...defaultMrProps(),
+ });
- vm.mr.currentUserId = 3;
+ expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true);
+ });
- expect(vm.canRemoveSourceBranch).toBeFalsy();
- });
+ it.each`
+ mergeUserId | currentUserId
+ ${2} | ${1}
+ ${1} | ${2}
+ `(
+ 'should return false when user id is not the same with who set the MWPS',
+ ({ mergeUserId, currentUserId }) => {
+ factory({
+ ...defaultMrProps(),
+ mergeUserId,
+ currentUserId,
+ });
+
+ expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
+ },
+ );
- it('should return false when shouldRemoveSourceBranch set to false', () => {
- vm.mr.shouldRemoveSourceBranch = true;
+ it('should return false when shouldRemoveSourceBranch set to false', () => {
+ factory({
+ ...defaultMrProps(),
+ shouldRemoveSourceBranch: true,
+ });
- expect(vm.canRemoveSourceBranch).toBeFalsy();
- });
+ expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
+ });
- it('should return false if user is not able to remove the source branch', () => {
- vm.mr.canRemoveSourceBranch = false;
+ it('should return false if user is not able to remove the source branch', () => {
+ factory({
+ ...defaultMrProps(),
+ canRemoveSourceBranch: false,
+ });
- expect(vm.canRemoveSourceBranch).toBeFalsy();
- });
- });
+ expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
+ });
+ });
- describe('statusTextBeforeAuthor', () => {
- it('should return "Set by" if the MWPS is selected', () => {
- Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+ describe('statusTextBeforeAuthor', () => {
+ it('should return "Set by" if the MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
- expect(vm.statusTextBeforeAuthor).toBe('Set by');
- });
- });
+ expect(wrapper.findByTestId('beforeStatusText').text()).toBe('Set by');
+ });
+ });
- describe('statusTextAfterAuthor', () => {
- it('should return "to be merged automatically..." if MWPS is selected', () => {
- Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+ describe('statusTextAfterAuthor', () => {
+ it('should return "to be merged automatically..." if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
- expect(vm.statusTextAfterAuthor).toBe(
- 'to be merged automatically when the pipeline succeeds',
- );
- });
- });
+ expect(wrapper.findByTestId('afterStatusText').text()).toBe(
+ 'to be merged automatically when the pipeline succeeds',
+ );
+ });
+ });
- describe('cancelButtonText', () => {
- it('should return "Cancel automatic merge" if MWPS is selected', () => {
- Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+ describe('cancelButtonText', () => {
+ it('should return "Cancel automatic merge" if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
- expect(vm.cancelButtonText).toBe('Cancel automatic merge');
+ expect(wrapper.findByTestId('cancelAutomaticMergeButton').text()).toBe(
+ 'Cancel automatic merge',
+ );
+ });
+ });
});
- });
- });
- describe('methods', () => {
- describe('cancelAutomaticMerge', () => {
- it('should set flag and call service then tell main component to update the widget with data', done => {
- const mrObj = {
- is_new_mr_data: true,
- };
- jest.spyOn(vm.service, 'cancelAutomaticMerge').mockReturnValue(
- new Promise(resolve => {
- resolve({
- data: mrObj,
+ describe('methods', () => {
+ describe('cancelAutomaticMerge', () => {
+ it('should set flag and call service then tell main component to update the widget with data', (done) => {
+ factory({
+ ...defaultMrProps(),
});
- }),
- );
-
- vm.cancelAutomaticMerge();
- setImmediate(() => {
- expect(vm.isCancellingAutoMerge).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- done();
+ const mrObj = {
+ is_new_mr_data: true,
+ };
+ jest.spyOn(wrapper.vm.service, 'cancelAutomaticMerge').mockReturnValue(
+ new Promise((resolve) => {
+ resolve({
+ data: mrObj,
+ });
+ }),
+ );
+
+ wrapper.vm.cancelAutomaticMerge();
+ setImmediate(() => {
+ expect(wrapper.vm.isCancellingAutoMerge).toBeTruthy();
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ done();
+ });
+ });
});
- });
- });
- describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', done => {
- jest.spyOn(vm.service, 'merge').mockReturnValue(
- Promise.resolve({
- data: {
- status: MWPS_MERGE_STRATEGY,
- },
- }),
- );
-
- vm.removeSourceBranch();
- setImmediate(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(vm.service.merge).toHaveBeenCalledWith({
- sha,
- auto_merge_strategy: MWPS_MERGE_STRATEGY,
- should_remove_source_branch: true,
- });
- done();
+ describe('removeSourceBranch', () => {
+ it('should set flag and call service then request main component to update the widget', (done) => {
+ factory({
+ ...defaultMrProps(),
+ });
+ jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(
+ Promise.resolve({
+ data: {
+ status: MWPS_MERGE_STRATEGY,
+ },
+ }),
+ );
+
+ wrapper.vm.removeSourceBranch();
+ setImmediate(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(wrapper.vm.service.merge).toHaveBeenCalledWith({
+ sha,
+ auto_merge_strategy: MWPS_MERGE_STRATEGY,
+ should_remove_source_branch: true,
+ });
+ done();
+ });
+ });
});
});
- });
- });
- describe('template', () => {
- it('should have correct elements', () => {
- expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds');
+ describe('template', () => {
+ it('should have correct elements', () => {
+ factory({
+ ...defaultMrProps(),
+ });
- expect(vm.$el.innerText).toContain('The changes will be merged into');
- expect(vm.$el.innerText).toContain(targetBranch);
- expect(vm.$el.innerText).toContain('The source branch will not be deleted');
- expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain(
- 'Cancel automatic merge',
- );
+ expect(wrapper.element).toMatchSnapshot();
+ });
- expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
- expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain(
- 'Delete source branch',
- );
+ it('should disable cancel auto merge button when the action is in progress', async () => {
+ factory({
+ ...defaultMrProps(),
+ });
+ wrapper.setData({
+ isCancellingAutoMerge: true,
+ });
- expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy();
- });
+ await nextTick();
- it('should disable cancel auto merge button when the action is in progress', done => {
- vm.isCancellingAutoMerge = true;
+ expect(wrapper.find('.js-cancel-auto-merge').attributes('disabled')).toBe('disabled');
+ });
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeTruthy();
- done();
- });
- });
+ it('should show source branch will be deleted text when it source branch set to remove', () => {
+ factory({
+ ...defaultMrProps(),
+ shouldRemoveSourceBranch: true,
+ });
- it('should show source branch will be deleted text when it source branch set to remove', done => {
- vm.mr.shouldRemoveSourceBranch = true;
+ const normalizedText = wrapper.text().replace(/\s+/g, ' ');
- Vue.nextTick(() => {
- const normalizedText = vm.$el.innerText.replace(/\s+/g, ' ');
+ expect(normalizedText).toContain('The source branch will be deleted');
+ expect(normalizedText).not.toContain('The source branch will not be deleted');
+ });
- expect(normalizedText).toContain('The source branch will be deleted');
- expect(normalizedText).not.toContain('The source branch will not be deleted');
- done();
- });
- });
+ it('should not show delete source branch button when user not able to delete source branch', () => {
+ factory({
+ ...defaultMrProps(),
+ currentUserId: 4,
+ });
- it('should not show delete source branch button when user not able to delete source branch', done => {
- vm.mr.currentUserId = 4;
+ expect(wrapper.find('.js-remove-source-branch').exists()).toBe(false);
+ });
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-remove-source-branch')).toEqual(null);
- done();
- });
- });
+ it('should disable delete source branch button when the action is in progress', async () => {
+ factory({
+ ...defaultMrProps(),
+ });
+ wrapper.setData({
+ isRemovingSourceBranch: true,
+ });
- it('should disable delete source branch button when the action is in progress', done => {
- vm.isRemovingSourceBranch = true;
+ await nextTick();
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled'),
- ).toBeTruthy();
- done();
- });
- });
+ expect(wrapper.find('.js-remove-source-branch').attributes('disabled')).toBe('disabled');
+ });
- it('should render the status text as "...to merged automatically" if MWPS is selected', done => {
- Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+ it('should render the status text as "...to merged automatically" if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
- Vue.nextTick(() => {
- const statusText = trimText(vm.$el.querySelector('.js-status-text-after-author').innerText);
+ const statusText = trimText(wrapper.find('.js-status-text-after-author').text());
- expect(statusText).toBe('to be merged automatically when the pipeline succeeds');
- done();
- });
- });
+ expect(statusText).toBe('to be merged automatically when the pipeline succeeds');
+ });
- it('should render the cancel button as "Cancel automatic merge" if MWPS is selected', done => {
- Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+ it('should render the cancel button as "Cancel automatic merge" if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
- Vue.nextTick(() => {
- const cancelButtonText = trimText(vm.$el.querySelector('.js-cancel-auto-merge').innerText);
+ const cancelButtonText = trimText(wrapper.find('.js-cancel-auto-merge').text());
- expect(cancelButtonText).toBe('Cancel automatic merge');
- done();
+ expect(cancelButtonText).toBe('Cancel automatic merge');
+ });
});
});
});
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 aae9b8660e2..dca3798f7ea 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,3 +1,4 @@
+import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlButton } from '@gitlab/ui';
import AutoMergeFailedComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue';
@@ -8,43 +9,60 @@ describe('MRWidgetAutoMergeFailed', () => {
const mergeError = 'This is the merge error';
const findButton = () => wrapper.find(GlButton);
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, mergeRequestWidgetGraphql = false) => {
wrapper = shallowMount(AutoMergeFailedComponent, {
propsData: { ...props },
- });
- };
+ data() {
+ if (mergeRequestWidgetGraphql) {
+ return { mergeError: props.mr?.mergeError };
+ }
- beforeEach(() => {
- createComponent({
- mr: { mergeError },
+ return {};
+ },
+ provide: {
+ glFeatures: { mergeRequestWidgetGraphql },
+ },
});
- });
+ };
afterEach(() => {
wrapper.destroy();
});
- it('renders failed message', () => {
- expect(wrapper.text()).toContain('This merge request failed to be merged automatically');
- });
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
+ describe(`when graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'dislabed'}`, () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ mr: { mergeError },
+ },
+ mergeRequestWidgetGraphql,
+ );
+ });
- it('renders merge error provided', () => {
- expect(wrapper.text()).toContain(mergeError);
- });
+ it('renders failed message', () => {
+ expect(wrapper.text()).toContain('This merge request failed to be merged automatically');
+ });
- it('render refresh button', () => {
- expect(findButton().text()).toEqual('Refresh');
- });
+ it('renders merge error provided', () => {
+ expect(wrapper.text()).toContain(mergeError);
+ });
+
+ it('render refresh button', () => {
+ expect(findButton().text()).toBe('Refresh');
+ });
+
+ it('emits event and shows loading icon when button is clicked', async () => {
+ jest.spyOn(eventHub, '$emit');
+ findButton().vm.$emit('click');
- it('emits event and shows loading icon when button is clicked', () => {
- jest.spyOn(eventHub, '$emit');
- findButton().vm.$emit('click');
+ expect(eventHub.$emit.mock.calls[0][0]).toBe('MRWidgetUpdateRequested');
- expect(eventHub.$emit.mock.calls[0][0]).toBe('MRWidgetUpdateRequested');
+ await nextTick();
- return wrapper.vm.$nextTick(() => {
- expect(findButton().attributes('disabled')).toBe('true');
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(findButton().attributes('disabled')).toBe('true');
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
index 322f440763c..55d7e2391b2 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
@@ -39,10 +39,7 @@ describe('MRWidgetClosed', () => {
it('renders closed by information with author and time', () => {
expect(
- vm.$el
- .querySelector('.js-mr-widget-author')
- .textContent.trim()
- .replace(/\s\s+/g, ' '),
+ vm.$el.querySelector('.js-mr-widget-author').textContent.trim().replace(/\s\s+/g, ' '),
).toContain('Closed by Administrator less than a minute ago');
});
@@ -54,10 +51,7 @@ describe('MRWidgetClosed', () => {
it('renders information about the changes not being merged', () => {
expect(
- vm.$el
- .querySelector('.mr-info-list')
- .textContent.trim()
- .replace(/\s\s+/g, ' '),
+ vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' '),
).toContain('The changes were not merged into so_long_jquery');
});
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 56832f82b05..706d60368b5 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
@@ -47,7 +47,8 @@ describe('Commits message dropdown component', () => {
});
it('should have correct message for the first dropdown list element', () => {
- expect(findFirstDropdownElement().text()).toBe('78d5b7 Commit 1');
+ expect(findFirstDropdownElement().text()).toContain('78d5b7');
+ expect(findFirstDropdownElement().text()).toContain('Commit 1');
});
it('should emit a commit title on selecting commit', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
index 62fc3330444..e4123b2ca83 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
@@ -4,7 +4,7 @@ import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_
describe('Commits header component', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(CommitsHeader, {
propsData: {
isSquashEnabled: false,
@@ -98,6 +98,8 @@ describe('Commits header component', () => {
});
it('does has merge commit part of the message', () => {
+ createComponent();
+
expect(findHeaderWrapper().text()).toContain('1 merge commit');
});
});
@@ -108,21 +110,21 @@ describe('Commits header component', () => {
wrapper.setData({ expanded: true });
});
- it('toggle has aria-label equal to collapse', done => {
+ it('toggle has aria-label equal to collapse', (done) => {
wrapper.vm.$nextTick(() => {
expect(findCommitToggle().attributes('aria-label')).toBe('Collapse');
done();
});
});
- it('has a chevron-down icon', done => {
+ it('has a chevron-down icon', (done) => {
wrapper.vm.$nextTick(() => {
expect(findCommitToggle().props('icon')).toBe('chevron-down');
done();
});
});
- it('has a collapse text', done => {
+ it('has a collapse text', (done) => {
wrapper.vm.$nextTick(() => {
expect(findHeaderWrapper().text()).toBe('Collapse');
done();
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 ad21e6e6f4f..f5a059698b6 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
@@ -54,7 +54,7 @@ describe('MRWidgetConflicts', () => {
vm.destroy();
});
- [false, true].forEach(featureEnabled => {
+ [false, true].forEach((featureEnabled) => {
describe(`with GraphQL feature flag ${featureEnabled ? 'enabled' : 'disabled'}`, () => {
beforeEach(() => {
mergeRequestWidgetGraphql = featureEnabled;
@@ -167,12 +167,9 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(
- vm
- .text()
- .trim()
- .replace(/\s\s+/g, ' '),
- ).toContain('ask someone with write access');
+ expect(vm.text().trim().replace(/\s\s+/g, ' ')).toContain(
+ 'ask someone with write access',
+ );
});
it('should not have action buttons', async () => {
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 6778a8f4a1f..48c1a9eedf9 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
@@ -49,7 +49,7 @@ describe('MRWidgetFailedToMerge', () => {
});
describe('mergeError', () => {
- it('removes forced line breaks', done => {
+ it('removes forced line breaks', (done) => {
mr.mergeError = 'contains<br />line breaks<br />';
Vue.nextTick()
@@ -98,7 +98,7 @@ describe('MRWidgetFailedToMerge', () => {
});
describe('while it is refreshing', () => {
- it('renders Refresing now', done => {
+ it('renders Refresing now', (done) => {
vm.isRefreshing = true;
Vue.nextTick(() => {
@@ -139,7 +139,7 @@ describe('MRWidgetFailedToMerge', () => {
});
});
- it('should just generic merge failed message if merge_error is not available', done => {
+ it('should just generic merge failed message if merge_error is not available', (done) => {
vm.mr.mergeError = null;
Vue.nextTick(() => {
@@ -149,7 +149,7 @@ describe('MRWidgetFailedToMerge', () => {
});
});
- it('should show refresh label when refresh requested', done => {
+ it('should show refresh label when refresh requested', (done) => {
vm.refresh();
Vue.nextTick(() => {
expect(vm.$el.innerText).not.toContain('Merge failed. Refreshing');
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 9b51e8583ba..36c4174c03d 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
@@ -123,9 +123,9 @@ describe('MRWidgetMerged', () => {
describe('methods', () => {
describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', done => {
+ it('should set flag and call service then request main component to update the widget', (done) => {
jest.spyOn(vm.service, 'removeSourceBranch').mockReturnValue(
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
data: {
message: 'Branch was deleted',
@@ -173,7 +173,7 @@ describe('MRWidgetMerged', () => {
);
});
- it('hides button to copy commit SHA if SHA does not exist', done => {
+ it('hides button to copy commit SHA if SHA does not exist', (done) => {
vm.mr.mergeCommitSha = null;
Vue.nextTick(() => {
@@ -189,7 +189,7 @@ describe('MRWidgetMerged', () => {
expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath);
});
- it('should not show source branch deleted text', done => {
+ it('should not show source branch deleted text', (done) => {
vm.mr.sourceBranchRemoved = false;
Vue.nextTick(() => {
@@ -199,7 +199,7 @@ describe('MRWidgetMerged', () => {
});
});
- it('should show source branch deleting text', done => {
+ it('should show source branch deleting text', (done) => {
vm.mr.isRemovingSourceBranch = true;
vm.mr.sourceBranchRemoved = false;
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
index f45368bf443..848677bf4d2 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
@@ -25,7 +25,7 @@ describe('MRWidgetMissingBranch', () => {
wrapper.destroy();
});
- [true, false].forEach(mergeRequestWidgetGraphql => {
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
describe(`widget GraphQL feature flag is ${
mergeRequestWidgetGraphql ? 'enabled' : 'disabled'
}`, () => {
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 9057ffaea45..8eddf59820c 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
@@ -20,7 +20,7 @@ jest.mock('~/commons/nav/user_merge_requests', () => ({
const commitMessage = 'This is the commit message';
const squashCommitMessage = 'This is the squash commit message';
const commitMessageWithDescription = 'This is the commit message description';
-const createTestMr = customConfig => {
+const createTestMr = (customConfig) => {
const mr = {
isPipelineActive: false,
pipeline: null,
@@ -346,8 +346,8 @@ describe('ReadyToMerge', () => {
});
describe('handleMergeButtonClick', () => {
- const returnPromise = status =>
- new Promise(resolve => {
+ const returnPromise = (status) =>
+ new Promise((resolve) => {
resolve({
data: {
status,
@@ -355,7 +355,7 @@ describe('ReadyToMerge', () => {
});
});
- it('should handle merge when pipeline succeeds', done => {
+ it('should handle merge when pipeline succeeds', (done) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest
.spyOn(vm.service, 'merge')
@@ -381,7 +381,7 @@ describe('ReadyToMerge', () => {
});
});
- it('should handle merge failed', done => {
+ it('should handle merge failed', (done) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'merge').mockReturnValue(returnPromise('failed'));
vm.handleMergeButtonClick(false, true);
@@ -398,7 +398,7 @@ describe('ReadyToMerge', () => {
});
});
- it('should handle merge action accepted case', done => {
+ it('should handle merge action accepted case', (done) => {
jest.spyOn(vm.service, 'merge').mockReturnValue(returnPromise('success'));
jest.spyOn(vm, 'initiateMergePolling').mockImplementation(() => {});
vm.handleMergeButtonClick();
@@ -433,8 +433,8 @@ describe('ReadyToMerge', () => {
});
describe('handleMergePolling', () => {
- const returnPromise = state =>
- new Promise(resolve => {
+ const returnPromise = (state) =>
+ new Promise((resolve) => {
resolve({
data: {
state,
@@ -447,7 +447,7 @@ describe('ReadyToMerge', () => {
loadFixtures('merge_requests/merge_request_of_current_user.html');
});
- it('should call start and stop polling when MR merged', done => {
+ it('should call start and stop polling when MR merged', (done) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('merged'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
@@ -476,11 +476,14 @@ describe('ReadyToMerge', () => {
});
});
- it('updates status box', done => {
+ it('updates status box', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('merged'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
- vm.handleMergePolling(() => {}, () => {});
+ vm.handleMergePolling(
+ () => {},
+ () => {},
+ );
setImmediate(() => {
const statusBox = document.querySelector('.status-box');
@@ -492,11 +495,14 @@ describe('ReadyToMerge', () => {
});
});
- it('updates merge request count badge', done => {
+ it('updates merge request count badge', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('merged'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
- vm.handleMergePolling(() => {}, () => {});
+ vm.handleMergePolling(
+ () => {},
+ () => {},
+ );
setImmediate(() => {
expect(document.querySelector('.js-merge-counter').textContent).toBe('0');
@@ -505,7 +511,7 @@ describe('ReadyToMerge', () => {
});
});
- it('should continue polling until MR is merged', done => {
+ it('should continue polling until MR is merged', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('some_other_state'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
@@ -541,8 +547,8 @@ describe('ReadyToMerge', () => {
});
describe('handleRemoveBranchPolling', () => {
- const returnPromise = state =>
- new Promise(resolve => {
+ const returnPromise = (state) =>
+ new Promise((resolve) => {
resolve({
data: {
source_branch_exists: state,
@@ -550,7 +556,7 @@ describe('ReadyToMerge', () => {
});
});
- it('should call start and stop polling when MR merged', done => {
+ it('should call start and stop polling when MR merged', (done) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise(false));
@@ -583,7 +589,7 @@ describe('ReadyToMerge', () => {
});
});
- it('should continue polling until MR is merged', done => {
+ it('should continue polling until MR is merged', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise(true));
let cpc = false; // continuePollingCalled
@@ -657,10 +663,7 @@ describe('ReadyToMerge', () => {
const findCommitsHeaderElement = () => wrapper.find(CommitsHeader);
const findCommitEditElements = () => wrapper.findAll(CommitEdit);
const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
- const findFirstCommitEditLabel = () =>
- findCommitEditElements()
- .at(0)
- .props('label');
+ const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label');
describe('squash checkbox', () => {
it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
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 f9490ac77ff..cc160f6182d 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
@@ -8,7 +8,7 @@ const localVue = createLocalVue();
describe('Squash before merge component', () => {
let wrapper;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(localVue.extend(SquashBeforeMerge), {
localVue,
propsData: {
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 907906ebe98..6d63d4b1be3 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
@@ -47,12 +47,12 @@ describe('Wip', () => {
};
describe('handleRemoveWIP', () => {
- it('should make a request to service and handle response', done => {
+ it('should make a request to service and handle response', (done) => {
const vm = createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'removeWIP').mockReturnValue(
- new Promise(resolve => {
+ new Promise((resolve) => {
resolve({
data: mrObj,
});
@@ -92,7 +92,7 @@ describe('Wip', () => {
);
});
- it('should not show removeWIP button is user cannot update MR', done => {
+ it('should not show removeWIP button is user cannot update MR', (done) => {
vm.mr.removeWIPPath = '';
Vue.nextTick(() => {
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 7fe6b44ecc7..8da0d0f16d6 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
@@ -15,7 +15,7 @@ describe('MrWidgetTerraformConainer', () => {
const propsData = { endpoint: '/path/to/terraform/report.json' };
const findHeader = () => wrapper.find('[data-testid="terraform-header-text"]');
- const findPlans = () => wrapper.findAll(TerraformPlan).wrappers.map(x => x.props('plan'));
+ const findPlans = () => wrapper.findAll(TerraformPlan).wrappers.map((x) => x.props('plan'));
const mockPollingApi = (response, body, header) => {
mock.onGet(propsData.endpoint).reply(response, body, header);
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 cc68ba0d9df..ea4eb44ebfe 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
@@ -14,7 +14,7 @@ describe('TerraformPlan', () => {
const findIcon = () => wrapper.find('[data-testid="change-type-icon"]');
const findLogButton = () => wrapper.find('[data-testid="terraform-report-link"]');
- const mountWrapper = propsData => {
+ const mountWrapper = (propsData) => {
wrapper = shallowMount(TerraformPlan, { stubs: { GlLink, GlSprintf }, propsData });
};
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
index 19a5566c3b1..87bf32351bd 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
@@ -116,7 +116,7 @@ describe('Deployment component', () => {
if (actionButtons.length > 0) {
describe('renders the expected button group', () => {
- actionButtons.forEach(button => {
+ actionButtons.forEach((button) => {
it(`renders ${button}`, () => {
expect(wrapper.find(button).exists()).toBe(true);
});
@@ -126,7 +126,7 @@ describe('Deployment component', () => {
if (actionButtons.length === 0) {
describe('does not render the button group', () => {
- defaultGroup.forEach(button => {
+ defaultGroup.forEach((button) => {
it(`does not render ${button}`, () => {
expect(wrapper.find(button).exists()).toBe(false);
});
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js
index a12757d4cce..a5d91468ef2 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js
@@ -90,7 +90,7 @@ describe('Deployment View App button', () => {
it('renders all the links to the review apps', () => {
const allUrls = wrapper.findAll('.js-deploy-url-menu-item').wrappers;
- const expectedUrls = deploymentMockData.changes.map(change => change.external_url);
+ const expectedUrls = deploymentMockData.changes.map((change) => change.external_url);
expectedUrls.forEach((expectedUrl, idx) => {
const deployUrl = allUrls[idx];
diff --git a/spec/frontend/vue_mr_widget/mock_data.js b/spec/frontend/vue_mr_widget/mock_data.js
index 8ee920f06a1..aa2345abccf 100644
--- a/spec/frontend/vue_mr_widget/mock_data.js
+++ b/spec/frontend/vue_mr_widget/mock_data.js
@@ -1,5 +1,20 @@
import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants';
+export const artifacts = [
+ {
+ text: 'result.txt',
+ url: 'bar',
+ job_name: 'generate-artifact',
+ job_path: 'bar',
+ },
+ {
+ text: 'foo.txt',
+ url: 'foo',
+ job_name: 'foo-artifact',
+ job_path: 'foo',
+ },
+];
+
export default {
id: 132,
iid: 22,
@@ -84,6 +99,7 @@ export default {
coverage: '92.16',
path: '/root/acets-app/pipelines/172',
details: {
+ artifacts,
status: {
icon: 'status_success',
favicon: 'favicon_status_success',
@@ -127,7 +143,6 @@ export default {
dropdown_path: '/root/acets-app/pipelines/172/stage.json?stage=review',
},
],
- artifacts: [],
manual_actions: [
{
name: 'stop_review',
@@ -194,7 +209,10 @@ export default {
updated_at: '2017-04-07T15:28:44.800Z',
},
pipelineCoverageDelta: '15.25',
- buildsWithCoverage: [{ name: 'karma', coverage: '40.2' }, { name: 'rspec', coverage: '80.4' }],
+ buildsWithCoverage: [
+ { name: 'karma', coverage: '40.2' },
+ { name: 'rspec', coverage: '80.4' },
+ ],
work_in_progress: false,
source_branch_exists: false,
mergeable_discussions_state: true,
@@ -272,6 +290,7 @@ export const mockStore = {
pipeline: {
id: 0,
details: {
+ artifacts,
status: {
details_path: '/root/review-app-tester/pipelines/66',
favicon:
@@ -291,6 +310,7 @@ export const mockStore = {
mergePipeline: {
id: 1,
details: {
+ artifacts,
status: {
details_path: '/root/review-app-tester/pipelines/66',
favicon:
diff --git a/spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js b/spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js
index aaaee3327a8..bd22183cbea 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js
@@ -50,19 +50,11 @@ describe('MRWidgetHowToMerge', () => {
it('should render different instructions based on if the user can merge', () => {
mountComponent({ props: { canMerge: true } });
- expect(
- findInstructionsFields()
- .at(2)
- .text(),
- ).toContain('git push origin');
+ expect(findInstructionsFields().at(2).text()).toContain('git push origin');
});
it('should render different instructions based on if the merge is based off a fork', () => {
mountComponent({ props: { isFork: true } });
- expect(
- findInstructionsFields()
- .at(0)
- .text(),
- ).toContain('FETCH_HEAD');
+ expect(findInstructionsFields().at(0).text()).toContain('FETCH_HEAD');
});
});
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 a20cd5b4400..1ea7fe1fbfe 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -1,12 +1,13 @@
-import Vue from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import mountComponent from 'helpers/vue_mount_component_helper';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
-import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
+import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
import notify from '~/lib/utils/notify';
import SmartInterval from '~/smart_interval';
+import { setFaviconOverlay } from '~/lib/utils/favicon';
import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
import mockData from './mock_data';
import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
@@ -14,58 +15,56 @@ import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/consta
jest.mock('~/smart_interval');
-const returnPromise = data =>
- new Promise(resolve => {
+jest.mock('~/lib/utils/favicon');
+
+const returnPromise = (data) =>
+ new Promise((resolve) => {
resolve({
data,
});
});
-describe('mrWidgetOptions', () => {
- let vm;
+describe('MrWidgetOptions', () => {
+ let wrapper;
let mock;
- let MrWidgetOptions;
const COLLABORATION_MESSAGE = 'Allows commits from members who can merge to the target branch';
beforeEach(() => {
- // Prevent component mounting
- delete mrWidgetOptions.el;
-
gl.mrWidgetData = { ...mockData };
gon.features = { asyncMrWidget: true };
mock = new MockAdapter(axios);
mock.onGet(mockData.merge_request_widget_path).reply(() => [200, { ...mockData }]);
mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, { ...mockData }]);
-
- MrWidgetOptions = Vue.extend(mrWidgetOptions);
});
afterEach(() => {
mock.restore();
- vm.$destroy();
- vm = null;
+ wrapper.destroy();
+ wrapper = null;
gl.mrWidgetData = {};
gon.features = {};
});
const createComponent = (mrData = mockData) => {
- if (vm) {
- vm.$destroy();
+ if (wrapper) {
+ wrapper.destroy();
}
- vm = mountComponent(MrWidgetOptions, {
- mrData: { ...mrData },
+ wrapper = mount(MrWidgetOptions, {
+ propsData: {
+ mrData: { ...mrData },
+ },
});
return axios.waitForAll();
};
- const findSuggestPipeline = () => vm.$el.querySelector('[data-testid="mr-suggest-pipeline"]');
- const findSuggestPipelineButton = () => findSuggestPipeline().querySelector('button');
- const findSecurityMrWidget = () => vm.$el.querySelector('[data-testid="security-mr-widget"]');
+ const findSuggestPipeline = () => wrapper.find('[data-testid="mr-suggest-pipeline"]');
+ const findSuggestPipelineButton = () => findSuggestPipeline().find('button');
+ const findSecurityMrWidget = () => wrapper.find('[data-testid="security-mr-widget"]');
describe('default', () => {
beforeEach(() => {
@@ -74,147 +73,147 @@ describe('mrWidgetOptions', () => {
describe('data', () => {
it('should instantiate Store and Service', () => {
- expect(vm.mr).toBeDefined();
- expect(vm.service).toBeDefined();
+ expect(wrapper.vm.mr).toBeDefined();
+ expect(wrapper.vm.service).toBeDefined();
});
});
describe('computed', () => {
describe('componentName', () => {
it('should return merged component', () => {
- expect(vm.componentName).toEqual('mr-widget-merged');
+ expect(wrapper.vm.componentName).toEqual('mr-widget-merged');
});
it('should return conflicts component', () => {
- vm.mr.state = 'conflicts';
+ wrapper.vm.mr.state = 'conflicts';
- expect(vm.componentName).toEqual('mr-widget-conflicts');
+ expect(wrapper.vm.componentName).toEqual('mr-widget-conflicts');
});
});
describe('shouldRenderMergeHelp', () => {
it('should return false for the initial merged state', () => {
- expect(vm.shouldRenderMergeHelp).toBeFalsy();
+ expect(wrapper.vm.shouldRenderMergeHelp).toBeFalsy();
});
it('should return true for a state which requires help widget', () => {
- vm.mr.state = 'conflicts';
+ wrapper.vm.mr.state = 'conflicts';
- expect(vm.shouldRenderMergeHelp).toBeTruthy();
+ expect(wrapper.vm.shouldRenderMergeHelp).toBeTruthy();
});
});
describe('shouldRenderPipelines', () => {
it('should return true when hasCI is true', () => {
- vm.mr.hasCI = true;
+ wrapper.vm.mr.hasCI = true;
- expect(vm.shouldRenderPipelines).toBeTruthy();
+ expect(wrapper.vm.shouldRenderPipelines).toBeTruthy();
});
it('should return false when hasCI is false', () => {
- vm.mr.hasCI = false;
+ wrapper.vm.mr.hasCI = false;
- expect(vm.shouldRenderPipelines).toBeFalsy();
+ expect(wrapper.vm.shouldRenderPipelines).toBeFalsy();
});
});
describe('shouldRenderRelatedLinks', () => {
it('should return false for the initial data', () => {
- expect(vm.shouldRenderRelatedLinks).toBeFalsy();
+ expect(wrapper.vm.shouldRenderRelatedLinks).toBeFalsy();
});
it('should return true if there is relatedLinks in MR', () => {
- Vue.set(vm.mr, 'relatedLinks', {});
+ Vue.set(wrapper.vm.mr, 'relatedLinks', {});
- expect(vm.shouldRenderRelatedLinks).toBeTruthy();
+ expect(wrapper.vm.shouldRenderRelatedLinks).toBeTruthy();
});
});
describe('shouldRenderSourceBranchRemovalStatus', () => {
beforeEach(() => {
- vm.mr.state = 'readyToMerge';
+ wrapper.vm.mr.state = 'readyToMerge';
});
it('should return true when cannot remove source branch and branch will be removed', () => {
- vm.mr.canRemoveSourceBranch = false;
- vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
- expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(true);
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(true);
});
it('should return false when can remove source branch and branch will be removed', () => {
- vm.mr.canRemoveSourceBranch = true;
- vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.canRemoveSourceBranch = true;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
- expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
});
it('should return false when cannot remove source branch and branch will not be removed', () => {
- vm.mr.canRemoveSourceBranch = false;
- vm.mr.shouldRemoveSourceBranch = false;
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = false;
- expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
});
it('should return false when in merged state', () => {
- vm.mr.canRemoveSourceBranch = false;
- vm.mr.shouldRemoveSourceBranch = true;
- vm.mr.state = 'merged';
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.state = 'merged';
- expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
});
it('should return false when in nothing to merge state', () => {
- vm.mr.canRemoveSourceBranch = false;
- vm.mr.shouldRemoveSourceBranch = true;
- vm.mr.state = 'nothingToMerge';
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.state = 'nothingToMerge';
- expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
});
});
describe('shouldRenderCollaborationStatus', () => {
describe('when collaboration is allowed', () => {
beforeEach(() => {
- vm.mr.allowCollaboration = true;
+ wrapper.vm.mr.allowCollaboration = true;
});
describe('when merge request is opened', () => {
- beforeEach(done => {
- vm.mr.isOpen = true;
- vm.$nextTick(done);
+ beforeEach((done) => {
+ wrapper.vm.mr.isOpen = true;
+ nextTick(done);
});
it('should render collaboration status', () => {
- expect(vm.$el.textContent).toContain(COLLABORATION_MESSAGE);
+ expect(wrapper.text()).toContain(COLLABORATION_MESSAGE);
});
});
describe('when merge request is not opened', () => {
- beforeEach(done => {
- vm.mr.isOpen = false;
- vm.$nextTick(done);
+ beforeEach((done) => {
+ wrapper.vm.mr.isOpen = false;
+ nextTick(done);
});
it('should not render collaboration status', () => {
- expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE);
+ expect(wrapper.text()).not.toContain(COLLABORATION_MESSAGE);
});
});
});
describe('when collaboration is not allowed', () => {
beforeEach(() => {
- vm.mr.allowCollaboration = false;
+ wrapper.vm.mr.allowCollaboration = false;
});
describe('when merge request is opened', () => {
- beforeEach(done => {
- vm.mr.isOpen = true;
- vm.$nextTick(done);
+ beforeEach((done) => {
+ wrapper.vm.mr.isOpen = true;
+ nextTick(done);
});
it('should not render collaboration status', () => {
- expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE);
+ expect(wrapper.text()).not.toContain(COLLABORATION_MESSAGE);
});
});
});
@@ -222,56 +221,56 @@ describe('mrWidgetOptions', () => {
describe('showMergePipelineForkWarning', () => {
describe('when the source project and target project are the same', () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'mergePipelinesEnabled', true);
- Vue.set(vm.mr, 'sourceProjectId', 1);
- Vue.set(vm.mr, 'targetProjectId', 1);
- vm.$nextTick(done);
+ beforeEach((done) => {
+ Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true);
+ Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
+ Vue.set(wrapper.vm.mr, 'targetProjectId', 1);
+ nextTick(done);
});
it('should be false', () => {
- expect(vm.showMergePipelineForkWarning).toEqual(false);
+ expect(wrapper.vm.showMergePipelineForkWarning).toEqual(false);
});
});
describe('when merge pipelines are not enabled', () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'mergePipelinesEnabled', false);
- Vue.set(vm.mr, 'sourceProjectId', 1);
- Vue.set(vm.mr, 'targetProjectId', 2);
- vm.$nextTick(done);
+ beforeEach((done) => {
+ Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', false);
+ Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
+ Vue.set(wrapper.vm.mr, 'targetProjectId', 2);
+ nextTick(done);
});
it('should be false', () => {
- expect(vm.showMergePipelineForkWarning).toEqual(false);
+ expect(wrapper.vm.showMergePipelineForkWarning).toEqual(false);
});
});
describe('when merge pipelines are enabled _and_ the source project and target project are different', () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'mergePipelinesEnabled', true);
- Vue.set(vm.mr, 'sourceProjectId', 1);
- Vue.set(vm.mr, 'targetProjectId', 2);
- vm.$nextTick(done);
+ beforeEach((done) => {
+ Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true);
+ Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
+ Vue.set(wrapper.vm.mr, 'targetProjectId', 2);
+ nextTick(done);
});
it('should be true', () => {
- expect(vm.showMergePipelineForkWarning).toEqual(true);
+ expect(wrapper.vm.showMergePipelineForkWarning).toEqual(true);
});
});
});
describe('formattedHumanAccess', () => {
it('when user is a tool admin but not a member of project', () => {
- vm.mr.humanAccess = null;
+ wrapper.vm.mr.humanAccess = null;
- expect(vm.formattedHumanAccess).toEqual('');
+ expect(wrapper.vm.formattedHumanAccess).toEqual('');
});
it('when user a member of the project', () => {
- vm.mr.humanAccess = 'Owner';
+ wrapper.vm.mr.humanAccess = 'Owner';
- expect(vm.formattedHumanAccess).toEqual('owner');
+ expect(wrapper.vm.formattedHumanAccess).toEqual('owner');
});
});
});
@@ -282,9 +281,9 @@ describe('mrWidgetOptions', () => {
let isCbExecuted;
beforeEach(() => {
- jest.spyOn(vm.service, 'checkStatus').mockReturnValue(returnPromise(mockData));
- jest.spyOn(vm.mr, 'setData').mockImplementation(() => {});
- jest.spyOn(vm, 'handleNotification').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'checkStatus').mockReturnValue(returnPromise(mockData));
+ jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'handleNotification').mockImplementation(() => {});
isCbExecuted = false;
cb = () => {
@@ -293,12 +292,12 @@ describe('mrWidgetOptions', () => {
});
it('should tell service to check status if document is visible', () => {
- vm.checkStatus(cb);
+ wrapper.vm.checkStatus(cb);
- return vm.$nextTick().then(() => {
- expect(vm.service.checkStatus).toHaveBeenCalled();
- expect(vm.mr.setData).toHaveBeenCalled();
- expect(vm.handleNotification).toHaveBeenCalledWith(mockData);
+ return nextTick().then(() => {
+ expect(wrapper.vm.service.checkStatus).toHaveBeenCalled();
+ expect(wrapper.vm.mr.setData).toHaveBeenCalled();
+ expect(wrapper.vm.handleNotification).toHaveBeenCalledWith(mockData);
expect(isCbExecuted).toBeTruthy();
});
});
@@ -306,11 +305,11 @@ describe('mrWidgetOptions', () => {
describe('initPolling', () => {
it('should call SmartInterval', () => {
- vm.initPolling();
+ wrapper.vm.initPolling();
expect(SmartInterval).toHaveBeenCalledWith(
expect.objectContaining({
- callback: vm.checkStatus,
+ callback: wrapper.vm.checkStatus,
}),
);
});
@@ -318,11 +317,11 @@ describe('mrWidgetOptions', () => {
describe('initDeploymentsPolling', () => {
it('should call SmartInterval', () => {
- vm.initDeploymentsPolling();
+ wrapper.vm.initDeploymentsPolling();
expect(SmartInterval).toHaveBeenCalledWith(
expect.objectContaining({
- callback: vm.fetchPreMergeDeployments,
+ callback: wrapper.vm.fetchPreMergeDeployments,
}),
);
});
@@ -331,15 +330,15 @@ describe('mrWidgetOptions', () => {
describe('fetchDeployments', () => {
it('should fetch deployments', () => {
jest
- .spyOn(vm.service, 'fetchDeployments')
+ .spyOn(wrapper.vm.service, 'fetchDeployments')
.mockReturnValue(returnPromise([{ id: 1, status: SUCCESS }]));
- vm.fetchPreMergeDeployments();
+ wrapper.vm.fetchPreMergeDeployments();
- return vm.$nextTick().then(() => {
- expect(vm.service.fetchDeployments).toHaveBeenCalled();
- expect(vm.mr.deployments.length).toEqual(1);
- expect(vm.mr.deployments[0].id).toBe(1);
+ return nextTick().then(() => {
+ expect(wrapper.vm.service.fetchDeployments).toHaveBeenCalled();
+ expect(wrapper.vm.mr.deployments.length).toEqual(1);
+ expect(wrapper.vm.mr.deployments[0].id).toBe(1);
});
});
});
@@ -347,13 +346,13 @@ describe('mrWidgetOptions', () => {
describe('fetchActionsContent', () => {
it('should fetch content of Cherry Pick and Revert modals', () => {
jest
- .spyOn(vm.service, 'fetchMergeActionsContent')
+ .spyOn(wrapper.vm.service, 'fetchMergeActionsContent')
.mockReturnValue(returnPromise('hello world'));
- vm.fetchActionsContent();
+ wrapper.vm.fetchActionsContent();
- return vm.$nextTick().then(() => {
- expect(vm.service.fetchMergeActionsContent).toHaveBeenCalled();
+ return nextTick().then(() => {
+ expect(wrapper.vm.service.fetchMergeActionsContent).toHaveBeenCalled();
expect(document.body.textContent).toContain('hello world');
});
});
@@ -362,46 +361,46 @@ describe('mrWidgetOptions', () => {
describe('bindEventHubListeners', () => {
it.each`
event | method | methodArgs
- ${'MRWidgetUpdateRequested'} | ${'checkStatus'} | ${x => [x]}
- ${'MRWidgetRebaseSuccess'} | ${'checkStatus'} | ${x => [x, true]}
+ ${'MRWidgetUpdateRequested'} | ${'checkStatus'} | ${(x) => [x]}
+ ${'MRWidgetRebaseSuccess'} | ${'checkStatus'} | ${(x) => [x, true]}
${'FetchActionsContent'} | ${'fetchActionsContent'} | ${() => []}
${'EnablePolling'} | ${'resumePolling'} | ${() => []}
${'DisablePolling'} | ${'stopPolling'} | ${() => []}
`('should bind to $event', ({ event, method, methodArgs }) => {
- jest.spyOn(vm, method).mockImplementation();
+ jest.spyOn(wrapper.vm, method).mockImplementation();
const eventArg = {};
eventHub.$emit(event, eventArg);
- expect(vm[method]).toHaveBeenCalledWith(...methodArgs(eventArg));
+ expect(wrapper.vm[method]).toHaveBeenCalledWith(...methodArgs(eventArg));
});
it('should bind to SetBranchRemoveFlag', () => {
- expect(vm.mr.isRemovingSourceBranch).toBe(false);
+ expect(wrapper.vm.mr.isRemovingSourceBranch).toBe(false);
eventHub.$emit('SetBranchRemoveFlag', [true]);
- expect(vm.mr.isRemovingSourceBranch).toBe(true);
+ expect(wrapper.vm.mr.isRemovingSourceBranch).toBe(true);
});
it('should bind to FailedToMerge', () => {
- vm.mr.state = '';
- vm.mr.mergeError = '';
+ wrapper.vm.mr.state = '';
+ wrapper.vm.mr.mergeError = '';
const mergeError = 'Something bad happened!';
eventHub.$emit('FailedToMerge', mergeError);
- expect(vm.mr.state).toBe('failedToMerge');
- expect(vm.mr.mergeError).toBe(mergeError);
+ expect(wrapper.vm.mr.state).toBe('failedToMerge');
+ expect(wrapper.vm.mr.mergeError).toBe(mergeError);
});
it('should bind to UpdateWidgetData', () => {
- jest.spyOn(vm.mr, 'setData').mockImplementation();
+ jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation();
const data = { ...mockData };
eventHub.$emit('UpdateWidgetData', data);
- expect(vm.mr.setData).toHaveBeenCalledWith(data);
+ expect(wrapper.vm.mr.setData).toHaveBeenCalledWith(data);
});
});
@@ -421,26 +420,18 @@ describe('mrWidgetOptions', () => {
document.body.removeChild(document.getElementById('favicon'));
});
- it('should call setFavicon method', done => {
- vm.mr.ciStatusFaviconPath = overlayDataUrl;
- vm.setFaviconHelper()
- .then(() => {
- /*
- It would be better if we'd could mock commonUtils.setFaviconURL
- with a spy and test that it was called. We are doing the following
- tests as a proxy to show that the function has been called
- */
- expect(faviconElement.getAttribute('href')).not.toEqual(null);
- expect(faviconElement.getAttribute('href')).not.toEqual(overlayDataUrl);
- expect(faviconElement.getAttribute('href')).not.toEqual(faviconDataUrl);
- })
- .then(done)
- .catch(done.fail);
+ it('should call setFavicon method', async () => {
+ wrapper.vm.mr.ciStatusFaviconPath = overlayDataUrl;
+
+ await wrapper.vm.setFaviconHelper();
+
+ expect(setFaviconOverlay).toHaveBeenCalledWith(overlayDataUrl);
});
- it('should not call setFavicon when there is no ciStatusFaviconPath', done => {
- vm.mr.ciStatusFaviconPath = null;
- vm.setFaviconHelper()
+ it('should not call setFavicon when there is no ciStatusFaviconPath', (done) => {
+ wrapper.vm.mr.ciStatusFaviconPath = null;
+ wrapper.vm
+ .setFaviconHelper()
.then(() => {
expect(faviconElement.getAttribute('href')).toEqual(null);
done();
@@ -459,12 +450,12 @@ describe('mrWidgetOptions', () => {
beforeEach(() => {
jest.spyOn(notify, 'notifyMe').mockImplementation(() => {});
- vm.mr.ciStatus = 'failed';
- vm.mr.gitlabLogo = 'logo.png';
+ wrapper.vm.mr.ciStatus = 'failed';
+ wrapper.vm.mr.gitlabLogo = 'logo.png';
});
it('should call notifyMe', () => {
- vm.handleNotification(data);
+ wrapper.vm.handleNotification(data);
expect(notify.notifyMe).toHaveBeenCalledWith(
'Pipeline running-label',
@@ -474,15 +465,15 @@ describe('mrWidgetOptions', () => {
});
it('should not call notifyMe if the status has not changed', () => {
- vm.mr.ciStatus = data.ci_status;
+ wrapper.vm.mr.ciStatus = data.ci_status;
- vm.handleNotification(data);
+ wrapper.vm.handleNotification(data);
expect(notify.notifyMe).not.toHaveBeenCalled();
});
it('should not notify if no pipeline provided', () => {
- vm.handleNotification({
+ wrapper.vm.handleNotification({
...data,
pipeline: undefined,
});
@@ -493,63 +484,65 @@ describe('mrWidgetOptions', () => {
describe('resumePolling', () => {
it('should call stopTimer on pollingInterval', () => {
- jest.spyOn(vm.pollingInterval, 'resume').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.pollingInterval, 'resume').mockImplementation(() => {});
- vm.resumePolling();
+ wrapper.vm.resumePolling();
- expect(vm.pollingInterval.resume).toHaveBeenCalled();
+ expect(wrapper.vm.pollingInterval.resume).toHaveBeenCalled();
});
});
describe('stopPolling', () => {
it('should call stopTimer on pollingInterval', () => {
- jest.spyOn(vm.pollingInterval, 'stopTimer').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.pollingInterval, 'stopTimer').mockImplementation(() => {});
- vm.stopPolling();
+ wrapper.vm.stopPolling();
- expect(vm.pollingInterval.stopTimer).toHaveBeenCalled();
+ expect(wrapper.vm.pollingInterval.stopTimer).toHaveBeenCalled();
});
});
});
describe('rendering relatedLinks', () => {
- beforeEach(done => {
- vm.mr.relatedLinks = {
- assignToMe: null,
- closing: `
- <a class="close-related-link" href="#">
- Close
- </a>
- `,
- mentioned: '',
- };
- Vue.nextTick(done);
+ beforeEach(() => {
+ createComponent({
+ ...mockData,
+ issues_links: {
+ closing: `
+ <a class="close-related-link" href="#">
+ Close
+ </a>
+ `,
+ },
+ });
+
+ return nextTick();
});
it('renders if there are relatedLinks', () => {
- expect(vm.$el.querySelector('.close-related-link')).toBeDefined();
+ expect(wrapper.find('.close-related-link').exists()).toBe(true);
});
- it('does not render if state is nothingToMerge', done => {
- vm.mr.state = stateKey.nothingToMerge;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.close-related-link')).toBeNull();
+ it('does not render if state is nothingToMerge', (done) => {
+ wrapper.vm.mr.state = stateKey.nothingToMerge;
+ nextTick(() => {
+ expect(wrapper.find('.close-related-link').exists()).toBe(false);
done();
});
});
});
describe('rendering source branch removal status', () => {
- it('renders when user cannot remove branch and branch should be removed', done => {
- vm.mr.canRemoveSourceBranch = false;
- vm.mr.shouldRemoveSourceBranch = true;
- vm.mr.state = 'readyToMerge';
+ it('renders when user cannot remove branch and branch should be removed', (done) => {
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.state = 'readyToMerge';
- vm.$nextTick(() => {
- const tooltip = vm.$el.querySelector('[data-testid="question-o-icon"]');
+ nextTick(() => {
+ const tooltip = wrapper.find('[data-testid="question-o-icon"]');
- expect(vm.$el.textContent).toContain('Deletes source branch');
- expect(tooltip.getAttribute('title')).toBe(
+ expect(wrapper.text()).toContain('Deletes source branch');
+ expect(tooltip.attributes('title')).toBe(
'A user with write access to the source branch selected this option',
);
@@ -557,14 +550,14 @@ describe('mrWidgetOptions', () => {
});
});
- it('does not render in merged state', done => {
- vm.mr.canRemoveSourceBranch = false;
- vm.mr.shouldRemoveSourceBranch = true;
- vm.mr.state = 'merged';
+ it('does not render in merged state', (done) => {
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.state = 'merged';
- vm.$nextTick(() => {
- expect(vm.$el.textContent).toContain('The source branch has been deleted');
- expect(vm.$el.textContent).not.toContain('Deletes source branch');
+ nextTick(() => {
+ expect(wrapper.text()).toContain('The source branch has been deleted');
+ expect(wrapper.text()).not.toContain('Deletes source branch');
done();
});
@@ -601,8 +594,8 @@ describe('mrWidgetOptions', () => {
status: SUCCESS,
};
- beforeEach(done => {
- vm.mr.deployments.push(
+ beforeEach((done) => {
+ wrapper.vm.mr.deployments.push(
{
...deploymentMockData,
},
@@ -612,33 +605,32 @@ describe('mrWidgetOptions', () => {
},
);
- vm.$nextTick(done);
+ nextTick(done);
});
it('renders multiple deployments', () => {
- expect(vm.$el.querySelectorAll('.deploy-heading').length).toBe(2);
+ expect(wrapper.findAll('.deploy-heading').length).toBe(2);
});
it('renders dropdpown with multiple file changes', () => {
expect(
- vm.$el
- .querySelector('.js-mr-wigdet-deployment-dropdown')
- .querySelectorAll('.js-filtered-dropdown-result').length,
+ wrapper.find('.js-mr-wigdet-deployment-dropdown').findAll('.js-filtered-dropdown-result')
+ .length,
).toEqual(changes.length);
});
});
describe('code quality widget', () => {
it('renders the component', () => {
- expect(vm.$el.querySelector('.js-codequality-widget')).toExist();
+ expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
});
});
describe('pipeline for target branch after merge', () => {
describe('with information for target branch pipeline', () => {
- beforeEach(done => {
- vm.mr.state = 'merged';
- vm.mr.mergePipeline = {
+ beforeEach((done) => {
+ wrapper.vm.mr.state = 'merged';
+ wrapper.vm.mr.mergePipeline = {
id: 127,
user: {
id: 1,
@@ -744,16 +736,16 @@ describe('mrWidgetOptions', () => {
},
cancel_path: '/root/ci-web-terminal/pipelines/127/cancel',
};
- vm.$nextTick(done);
+ nextTick(done);
});
it('renders pipeline block', () => {
- expect(vm.$el.querySelector('.js-post-merge-pipeline')).not.toBeNull();
+ expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(true);
});
describe('with post merge deployments', () => {
- beforeEach(done => {
- vm.mr.postMergeDeployments = [
+ beforeEach((done) => {
+ wrapper.vm.mr.postMergeDeployments = [
{
id: 15,
name: 'review/diplo',
@@ -785,46 +777,46 @@ describe('mrWidgetOptions', () => {
},
];
- vm.$nextTick(done);
+ nextTick(done);
});
it('renders post deployment information', () => {
- expect(vm.$el.querySelector('.js-post-deployment')).not.toBeNull();
+ expect(wrapper.find('.js-post-deployment').exists()).toBe(true);
});
});
});
describe('without information for target branch pipeline', () => {
- beforeEach(done => {
- vm.mr.state = 'merged';
+ beforeEach((done) => {
+ wrapper.vm.mr.state = 'merged';
- vm.$nextTick(done);
+ nextTick(done);
});
it('does not render pipeline block', () => {
- expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull();
+ expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(false);
});
});
describe('when state is not merged', () => {
- beforeEach(done => {
- vm.mr.state = 'archived';
+ beforeEach((done) => {
+ wrapper.vm.mr.state = 'archived';
- vm.$nextTick(done);
+ nextTick(done);
});
it('does not render pipeline block', () => {
- expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull();
+ expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(false);
});
it('does not render post deployment information', () => {
- expect(vm.$el.querySelector('.js-post-deployment')).toBeNull();
+ expect(wrapper.find('.js-post-deployment').exists()).toBe(false);
});
});
});
it('should not suggest pipelines when feature flag is not present', () => {
- expect(findSuggestPipeline()).toBeNull();
+ expect(findSuggestPipeline().exists()).toBe(false);
});
});
@@ -853,11 +845,11 @@ describe('mrWidgetOptions', () => {
if (shouldRender) {
it('renders', () => {
- expect(findSecurityMrWidget()).toEqual(expect.any(HTMLElement));
+ expect(findSecurityMrWidget().exists()).toBe(true);
});
} else {
it('does not render', () => {
- expect(findSecurityMrWidget()).toBeNull();
+ expect(findSecurityMrWidget().exists()).toBe(false);
});
}
});
@@ -866,41 +858,35 @@ describe('mrWidgetOptions', () => {
describe('suggestPipeline', () => {
beforeEach(() => {
mock.onAny().reply(200);
-
- // This is needed because some grandchildren Bootstrap components throw warnings
- // https://gitlab.com/gitlab-org/gitlab/issues/208458
- jest.spyOn(console, 'warn').mockImplementation();
});
describe('given feature flag is enabled', () => {
beforeEach(() => {
createComponent();
- vm.mr.hasCI = false;
+ wrapper.vm.mr.hasCI = false;
});
it('should suggest pipelines when none exist', () => {
- expect(findSuggestPipeline()).toEqual(expect.any(Element));
+ expect(findSuggestPipeline().exists()).toBe(true);
});
it.each([
{ isDismissedSuggestPipeline: true },
{ mergeRequestAddCiConfigPath: null },
{ hasCI: true },
- ])('with %s, should not suggest pipeline', async obj => {
- Object.assign(vm.mr, obj);
+ ])('with %s, should not suggest pipeline', async (obj) => {
+ Object.assign(wrapper.vm.mr, obj);
- await vm.$nextTick();
+ await nextTick();
- expect(findSuggestPipeline()).toBeNull();
+ expect(findSuggestPipeline().exists()).toBe(false);
});
it('should allow dismiss of the suggest pipeline message', async () => {
- findSuggestPipelineButton().click();
-
- await vm.$nextTick();
+ await findSuggestPipelineButton().trigger('click');
- expect(findSuggestPipeline()).toBeNull();
+ expect(findSuggestPipeline().exists()).toBe(false);
});
});
});
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 026ea0e4d0a..1dfa7564535 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
@@ -22,7 +22,7 @@ describe('Artifacts App Store Actions', () => {
});
describe('setEndpoint', () => {
- it('should commit SET_ENDPOINT mutation', done => {
+ it('should commit SET_ENDPOINT mutation', (done) => {
testAction(
setEndpoint,
'endpoint.json',
@@ -35,7 +35,7 @@ describe('Artifacts App Store Actions', () => {
});
describe('requestArtifacts', () => {
- it('should commit REQUEST_ARTIFACTS mutation', done => {
+ it('should commit REQUEST_ARTIFACTS mutation', (done) => {
testAction(
requestArtifacts,
null,
@@ -62,7 +62,7 @@ describe('Artifacts App Store Actions', () => {
});
describe('success', () => {
- it('dispatches requestArtifacts and receiveArtifactsSuccess ', done => {
+ it('dispatches requestArtifacts and receiveArtifactsSuccess ', (done) => {
mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, [
{
text: 'result.txt',
@@ -106,7 +106,7 @@ describe('Artifacts App Store Actions', () => {
mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
});
- it('dispatches requestArtifacts and receiveArtifactsError ', done => {
+ it('dispatches requestArtifacts and receiveArtifactsError ', (done) => {
testAction(
fetchArtifacts,
null,
@@ -127,7 +127,7 @@ describe('Artifacts App Store Actions', () => {
});
describe('receiveArtifactsSuccess', () => {
- it('should commit RECEIVE_ARTIFACTS_SUCCESS mutation with 200', done => {
+ it('should commit RECEIVE_ARTIFACTS_SUCCESS mutation with 200', (done) => {
testAction(
receiveArtifactsSuccess,
{ data: { summary: {} }, status: 200 },
@@ -138,7 +138,7 @@ describe('Artifacts App Store Actions', () => {
);
});
- it('should not commit RECEIVE_ARTIFACTS_SUCCESS mutation with 204', done => {
+ it('should not commit RECEIVE_ARTIFACTS_SUCCESS mutation with 204', (done) => {
testAction(
receiveArtifactsSuccess,
{ data: { summary: {} }, status: 204 },
@@ -151,7 +151,7 @@ describe('Artifacts App Store Actions', () => {
});
describe('receiveArtifactsError', () => {
- it('should commit RECEIVE_ARTIFACTS_ERROR mutation', done => {
+ it('should commit RECEIVE_ARTIFACTS_ERROR mutation', (done) => {
testAction(
receiveArtifactsError,
null,
diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js b/spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js
index 62ee6f5f189..dc90fef63c6 100644
--- a/spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js
@@ -1,6 +1,6 @@
import { title } from '~/vue_merge_request_widget/stores/artifacts_list/getters';
import state from '~/vue_merge_request_widget/stores/artifacts_list/state';
-import { artifactsList } from '../../components/mock_data';
+import { artifacts } from '../../mock_data';
describe('Artifacts Store Getters', () => {
let localState;
@@ -24,7 +24,7 @@ describe('Artifacts Store Getters', () => {
});
describe('when it has artifacts', () => {
it('returns artifacts message', () => {
- localState.artifacts = artifactsList;
+ localState.artifacts = artifacts;
expect(title(localState)).toBe('View 2 exposed artifacts');
});
});
diff --git a/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
index 8b2c10ec50a..cfc846075ea 100644
--- a/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -156,7 +156,7 @@ describe('MergeRequestStore', () => {
it.each(['sast_comparison_path', 'secret_scanning_comparison_path'])(
'should set %s path',
- property => {
+ (property) => {
// Ensure something is set in the mock data
expect(property in mockData).toBe(true);
const expectedValue = mockData[property];
diff --git a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
index 63d38e7587a..1bf757ea312 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
@@ -4,6 +4,7 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
<gl-dropdown-stub
category="primary"
headertext=""
+ hideheaderborder="true"
right="true"
size="medium"
text="Clone"
diff --git a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap
index dd88ba9a6fb..c4f351eb58d 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap
@@ -4,6 +4,7 @@ exports[`SplitButton renders actionItems 1`] = `
<gl-dropdown-stub
category="primary"
headertext=""
+ hideheaderborder="true"
menu-class=""
size="medium"
split="true"
diff --git a/spec/frontend/vue_shared/components/actions_button_spec.js b/spec/frontend/vue_shared/components/actions_button_spec.js
index 6e7ed9d612b..2ac4bfda29a 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, GlButton } from '@gitlab/ui';
+import { GlDropdown, GlDropdownDivider, GlButton } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ActionsButton from '~/vue_shared/components/actions_button.vue';
@@ -40,7 +40,7 @@ describe('Actions button component', () => {
wrapper.destroy();
});
- const getTooltip = child => {
+ const getTooltip = (child) => {
const directiveBinding = getBinding(child.element, 'gl-tooltip');
return directiveBinding.value;
@@ -52,8 +52,8 @@ describe('Actions button component', () => {
const parseDropdownItems = () =>
findDropdown()
.findAll('gl-dropdown-item-stub,gl-dropdown-divider-stub')
- .wrappers.map(x => {
- if (x.is('gl-dropdown-divider-stub')) {
+ .wrappers.map((x) => {
+ if (x.is(GlDropdownDivider)) {
return { type: 'divider' };
}
diff --git a/spec/frontend/vue_shared/components/alert_details_table_spec.js b/spec/frontend/vue_shared/components/alert_details_table_spec.js
index ef7815f9e9e..49b82cb4d4e 100644
--- a/spec/frontend/vue_shared/components/alert_details_table_spec.js
+++ b/spec/frontend/vue_shared/components/alert_details_table_spec.js
@@ -45,13 +45,13 @@ describe('AlertDetails', () => {
const findTableComponent = () => wrapper.find(GlTable);
const findTableKeys = () => findTableComponent().findAll('tbody td:first-child');
- const findTableFieldValueByKey = fieldKey =>
+ const findTableFieldValueByKey = (fieldKey) =>
findTableComponent()
.findAll('tbody tr')
- .filter(row => row.text().includes(fieldKey))
+ .filter((row) => row.text().includes(fieldKey))
.at(0)
.find('td:nth-child(2)');
- const findTableField = (fields, fieldName) => fields.filter(row => row.text() === fieldName);
+ const findTableField = (fields, fieldName) => fields.filter((row) => row.text() === fieldName);
describe('Alert details', () => {
describe('empty state', () => {
diff --git a/spec/frontend/vue_shared/components/awards_list_spec.js b/spec/frontend/vue_shared/components/awards_list_spec.js
index d20de81c446..550ac4a9d38 100644
--- a/spec/frontend/vue_shared/components/awards_list_spec.js
+++ b/spec/frontend/vue_shared/components/awards_list_spec.js
@@ -58,10 +58,10 @@ describe('vue_shared/components/awards_list', () => {
wrapper = mount(AwardsList, { propsData: props });
};
- const matchingEmojiTag = name => expect.stringMatching(`gl-emoji data-name="${name}"`);
+ const matchingEmojiTag = (name) => expect.stringMatching(`gl-emoji data-name="${name}"`);
const findAwardButtons = () => wrapper.findAll('[data-testid="award-button"]');
const findAwardsData = () =>
- findAwardButtons().wrappers.map(x => {
+ findAwardButtons().wrappers.map((x) => {
return {
classes: x.classes(),
title: x.attributes('title'),
@@ -135,9 +135,7 @@ describe('vue_shared/components/awards_list', () => {
it('with award clicked, it emits award', () => {
expect(wrapper.emitted().award).toBeUndefined();
- findAwardButtons()
- .at(2)
- .vm.$emit('click');
+ findAwardButtons().at(2).vm.$emit('click');
expect(wrapper.emitted().award).toEqual([[EMOJI_SMILE]]);
});
@@ -162,9 +160,7 @@ describe('vue_shared/components/awards_list', () => {
it('when clicked, it emits award as number', () => {
expect(wrapper.emitted().award).toBeUndefined();
- findAwardButtons()
- .at(0)
- .vm.$emit('click');
+ findAwardButtons().at(0).vm.$emit('click');
expect(wrapper.emitted().award).toEqual([[Number(EMOJI_100)]]);
});
@@ -209,7 +205,7 @@ describe('vue_shared/components/awards_list', () => {
const buttons = findAwardButtons();
expect(buttons.length).toBe(7);
- expect(buttons.wrappers.every(x => x.classes('disabled'))).toBe(true);
+ expect(buttons.wrappers.every((x) => x.classes('disabled'))).toBe(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 f656bb0b60d..a633ef65aa4 100644
--- a/spec/frontend/vue_shared/components/ci_badge_link_spec.js
+++ b/spec/frontend/vue_shared/components/ci_badge_link_spec.js
@@ -81,7 +81,7 @@ describe('CI Badge Link Component', () => {
});
it('should render each status badge', () => {
- Object.keys(statuses).map(status => {
+ Object.keys(statuses).map((status) => {
vm = mountComponent(CIBadge, { status: statuses[status] });
expect(vm.$el.getAttribute('href')).toEqual(statuses[status].details_path);
diff --git a/spec/frontend/vue_shared/components/clipboard_button_spec.js b/spec/frontend/vue_shared/components/clipboard_button_spec.js
index ac0be1537b7..0d4266ce82f 100644
--- a/spec/frontend/vue_shared/components/clipboard_button_spec.js
+++ b/spec/frontend/vue_shared/components/clipboard_button_spec.js
@@ -1,6 +1,7 @@
import { mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import initCopyToClipboard from '~/behaviors/copy_to_clipboard';
describe('clipboard button', () => {
let wrapper;
@@ -87,4 +88,25 @@ describe('clipboard button', () => {
expect(onClick).toHaveBeenCalled();
});
+
+ describe('integration', () => {
+ it('actually copies to clipboard', () => {
+ initCopyToClipboard();
+
+ document.execCommand = () => {};
+ jest.spyOn(document, 'execCommand').mockImplementation(() => true);
+
+ createWrapper(
+ {
+ text: 'copy me',
+ title: 'Copy this value',
+ },
+ { attachTo: document.body },
+ );
+
+ findButton().trigger('click');
+
+ expect(document.execCommand).toHaveBeenCalledWith('copy');
+ });
+ });
});
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 a50a4b742b3..c8fe6c3131c 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
@@ -130,9 +130,7 @@ describe('ColorPicker', () => {
it('has preset color selected', async () => {
createComponent();
- await presetColors()
- .at(0)
- .trigger('click');
+ await presetColors().at(0).trigger('click');
expect(wrapper.vm.$data.selectedColor).toBe(setColor);
});
diff --git a/spec/frontend/vue_shared/components/commit_spec.js b/spec/frontend/vue_shared/components/commit_spec.js
index 9b5c0941a0d..6f3c97f7194 100644
--- a/spec/frontend/vue_shared/components/commit_spec.js
+++ b/spec/frontend/vue_shared/components/commit_spec.js
@@ -7,14 +7,14 @@ describe('Commit component', () => {
let props;
let wrapper;
- const findIcon = name => {
- const icons = wrapper.findAll(GlIcon).filter(c => c.attributes('name') === name);
+ const findIcon = (name) => {
+ const icons = wrapper.findAll(GlIcon).filter((c) => c.attributes('name') === name);
return icons.length ? icons.at(0) : icons;
};
const findUserAvatar = () => wrapper.find(UserAvatarLink);
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(CommitComponent, {
propsData,
});
@@ -43,12 +43,7 @@ describe('Commit component', () => {
},
});
- expect(
- wrapper
- .find('.icon-container')
- .find(GlIcon)
- .exists(),
- ).toBe(true);
+ expect(wrapper.find('.icon-container').find(GlIcon).exists()).toBe(true);
});
describe('Given all the props', () => {
diff --git a/spec/frontend/vue_shared/components/confirm_modal_spec.js b/spec/frontend/vue_shared/components/confirm_modal_spec.js
index 96ccf56cbc6..db8d0674121 100644
--- a/spec/frontend/vue_shared/components/confirm_modal_spec.js
+++ b/spec/frontend/vue_shared/components/confirm_modal_spec.js
@@ -53,7 +53,7 @@ describe('vue_shared/components/confirm_modal', () => {
const findFormData = () =>
findForm()
.findAll('input')
- .wrappers.map(x => ({ name: x.attributes('name'), value: x.attributes('value') }));
+ .wrappers.map((x) => ({ name: x.attributes('name'), value: x.attributes('value') }));
describe('template', () => {
describe('when modal data is set', () => {
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 c75891c9ed3..22ee6acfed8 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
@@ -9,7 +9,7 @@ describe('MarkdownViewer', () => {
let wrapper;
let mock;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = mount(MarkdownViewer, {
propsData: {
...props,
diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js
index e46c63a1a32..10eacff630d 100644
--- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js
+++ b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js
@@ -71,7 +71,7 @@ describe('date time picker lib', () => {
'2019-19-23',
'2019-09-23 x',
'2019-09-29 24:24:24',
- ].forEach(input => {
+ ].forEach((input) => {
it(`throws error for invalid input like ${input}`, () => {
expect(() => inputStringToIsoDate(input)).toThrow();
});
diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js
index afd1f1a3123..33667a1bb71 100644
--- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js
+++ b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js
@@ -17,7 +17,7 @@ describe('DateTimePicker', () => {
const applyButtonElement = () => wrapper.find('button.btn-success').element;
const findQuickRangeItems = () => wrapper.findAll('.dropdown-item');
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = mount(DateTimePicker, {
propsData: {
...props,
@@ -235,7 +235,7 @@ describe('DateTimePicker', () => {
it('unchecks quick range when text is input is clicked', () => {
const findActiveItems = () =>
- findQuickRangeItems().filter(w => w.classes().includes('active'));
+ findQuickRangeItems().filter((w) => w.classes().includes('active'));
expect(findActiveItems().length).toBe(1);
diff --git a/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js b/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js
new file mode 100644
index 00000000000..b812ced72c9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/deployment_instance/deployment_instance_spec.js
@@ -0,0 +1,103 @@
+import { shallowMount } from '@vue/test-utils';
+import DeployBoardInstance from '~/vue_shared/components/deployment_instance.vue';
+import { folder } from './mock_data';
+
+describe('Deploy Board Instance', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) =>
+ shallowMount(DeployBoardInstance, {
+ propsData: {
+ status: 'succeeded',
+ ...props,
+ },
+ });
+
+ describe('as a non-canary deployment', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render a div with the correct css status and tooltip data', () => {
+ wrapper = createComponent({
+ logsPath: folder.logs_path,
+ tooltipText: 'This is a pod',
+ });
+
+ expect(wrapper.classes('deployment-instance-succeeded')).toBe(true);
+ expect(wrapper.attributes('title')).toEqual('This is a pod');
+ });
+
+ it('should render a div without tooltip data', (done) => {
+ wrapper = createComponent({
+ status: 'deploying',
+ tooltipText: '',
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.classes('deployment-instance-deploying')).toBe(true);
+ expect(wrapper.attributes('title')).toEqual('');
+ done();
+ });
+ });
+
+ it('should have a log path computed with a pod name as a parameter', () => {
+ wrapper = createComponent({
+ logsPath: folder.logs_path,
+ podName: 'tanuki-1',
+ });
+
+ expect(wrapper.vm.computedLogPath).toEqual(
+ '/root/review-app/-/logs?environment_name=foo&pod_name=tanuki-1',
+ );
+ });
+ });
+
+ describe('as a canary deployment', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render a div with canary class when stable prop is provided as false', (done) => {
+ wrapper = createComponent({
+ stable: false,
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.classes('deployment-instance-canary')).toBe(true);
+ done();
+ });
+ });
+ });
+
+ describe('as a legend item', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should not be a link without a logsPath prop', (done) => {
+ wrapper = createComponent({
+ stable: false,
+ logsPath: '',
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.computedLogPath).toBeNull();
+ expect(wrapper.vm.isLink).toBeFalsy();
+ done();
+ });
+ });
+
+ it('should render a link without href if path is not passed', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.attributes('href')).toBeUndefined();
+ });
+
+ it('should not have a tooltip', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.attributes('title')).toEqual('');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/deployment_instance/mock_data.js b/spec/frontend/vue_shared/components/deployment_instance/mock_data.js
new file mode 100644
index 00000000000..6618c57948c
--- /dev/null
+++ b/spec/frontend/vue_shared/components/deployment_instance/mock_data.js
@@ -0,0 +1,144 @@
+export const environmentsList = [
+ {
+ name: 'DEV',
+ size: 1,
+ id: 7,
+ state: 'available',
+ external_url: null,
+ environment_type: null,
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/root/review-app/environments/7',
+ stop_path: '/root/review-app/environments/7/stop',
+ created_at: '2017-01-31T10:53:46.894Z',
+ updated_at: '2017-01-31T10:53:46.894Z',
+ project_path: '/root/review-app',
+ rollout_status: {},
+ },
+ {
+ folderName: 'build',
+ size: 5,
+ id: 12,
+ name: 'build/update-README',
+ state: 'available',
+ external_url: null,
+ environment_type: 'build',
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/root/review-app/environments/12',
+ stop_path: '/root/review-app/environments/12/stop',
+ created_at: '2017-02-01T19:42:18.400Z',
+ updated_at: '2017-02-01T19:42:18.400Z',
+ project_path: '/root/review-app',
+ rollout_status: {},
+ },
+];
+
+export const serverData = [
+ {
+ name: 'DEV',
+ size: 1,
+ latest: {
+ id: 7,
+ name: 'DEV',
+ state: 'available',
+ external_url: null,
+ environment_type: null,
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/root/review-app/environments/7',
+ stop_path: '/root/review-app/environments/7/stop',
+ created_at: '2017-01-31T10:53:46.894Z',
+ updated_at: '2017-01-31T10:53:46.894Z',
+ rollout_status: {},
+ },
+ },
+ {
+ name: 'build',
+ size: 5,
+ latest: {
+ id: 12,
+ name: 'build/update-README',
+ state: 'available',
+ external_url: null,
+ environment_type: 'build',
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/root/review-app/environments/12',
+ stop_path: '/root/review-app/environments/12/stop',
+ created_at: '2017-02-01T19:42:18.400Z',
+ updated_at: '2017-02-01T19:42:18.400Z',
+ },
+ },
+ {
+ name: 'build',
+ size: 1,
+ latest: {
+ id: 12,
+ name: 'build/update-README',
+ state: 'available',
+ external_url: null,
+ environment_type: 'build',
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/root/review-app/environments/12',
+ stop_path: '/root/review-app/environments/12/stop',
+ created_at: '2017-02-01T19:42:18.400Z',
+ updated_at: '2017-02-01T19:42:18.400Z',
+ },
+ },
+];
+
+export const deployBoardMockData = {
+ instances: [
+ { status: 'finished', tooltip: 'tanuki-2334 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2335 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2336 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2337 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2338 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2339 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2340 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2334 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2335 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2336 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2337 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2338 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2339 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2340 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2341 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2342 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2343 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'failed', tooltip: 'tanuki-2344 Failed', pod_name: 'production-tanuki-1' },
+ { status: 'ready', tooltip: 'tanuki-2345 Ready', pod_name: 'production-tanuki-1' },
+ { status: 'ready', tooltip: 'tanuki-2346 Ready', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2348 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2349 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2350 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2353 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2354 Waiting', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2355 Waiting', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2356 Waiting', pod_name: 'production-tanuki-1' },
+ ],
+ abort_url: 'url',
+ rollback_url: 'url',
+ completion: 100,
+ status: 'found',
+};
+
+export const folder = {
+ folderName: 'build',
+ size: 5,
+ id: 12,
+ name: 'build/update-README',
+ state: 'available',
+ external_url: null,
+ environment_type: 'build',
+ last_deployment: null,
+ has_stop_action: false,
+ environment_path: '/root/review-app/environments/12',
+ stop_path: '/root/review-app/environments/12/stop',
+ created_at: '2017-02-01T19:42:18.400Z',
+ updated_at: '2017-02-01T19:42:18.400Z',
+ rollout_status: {},
+ logs_path: '/root/review-app/-/logs?environment_name=foo',
+};
diff --git a/spec/frontend/vue_shared/components/deprecated_modal_2_spec.js b/spec/frontend/vue_shared/components/deprecated_modal_2_spec.js
deleted file mode 100644
index c37a44df6f8..00000000000
--- a/spec/frontend/vue_shared/components/deprecated_modal_2_spec.js
+++ /dev/null
@@ -1,258 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
-
-const modalComponent = Vue.extend(DeprecatedModal2);
-
-describe('DeprecatedModal2', () => {
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('props', () => {
- describe('with id', () => {
- const props = {
- id: 'my-modal',
- };
-
- beforeEach(() => {
- vm = mountComponent(modalComponent, props);
- });
-
- it('assigns the id to the modal', () => {
- expect(vm.$el.id).toBe(props.id);
- });
- });
-
- describe('without id', () => {
- beforeEach(() => {
- vm = mountComponent(modalComponent, {});
- });
-
- it('does not add an id attribute to the modal', () => {
- expect(vm.$el.hasAttribute('id')).toBe(false);
- });
- });
-
- describe('with headerTitleText', () => {
- const props = {
- headerTitleText: 'my title text',
- };
-
- beforeEach(() => {
- vm = mountComponent(modalComponent, props);
- });
-
- it('sets the modal title', () => {
- const modalTitle = vm.$el.querySelector('.modal-title');
-
- expect(modalTitle.innerHTML.trim()).toBe(props.headerTitleText);
- });
- });
-
- describe('with footerPrimaryButtonVariant', () => {
- const props = {
- footerPrimaryButtonVariant: 'danger',
- };
-
- beforeEach(() => {
- vm = mountComponent(modalComponent, props);
- });
-
- it('sets the primary button class', () => {
- const primaryButton = vm.$el.querySelector('.modal-footer button:last-of-type');
-
- expect(primaryButton).toHaveClass(`btn-${props.footerPrimaryButtonVariant}`);
- });
- });
-
- describe('with footerPrimaryButtonText', () => {
- const props = {
- footerPrimaryButtonText: 'my button text',
- };
-
- beforeEach(() => {
- vm = mountComponent(modalComponent, props);
- });
-
- it('sets the primary button text', () => {
- const primaryButton = vm.$el.querySelector('.js-modal-primary-action .gl-button-text');
-
- expect(primaryButton.innerHTML.trim()).toBe(props.footerPrimaryButtonText);
- });
- });
- });
-
- it('works with data-toggle="modal"', () => {
- setFixtures(`
- <button id="modal-button" data-toggle="modal" data-target="#my-modal"></button>
- <div id="modal-container"></div>
- `);
-
- const modalContainer = document.getElementById('modal-container');
- const modalButton = document.getElementById('modal-button');
- vm = mountComponent(
- modalComponent,
- {
- id: 'my-modal',
- },
- modalContainer,
- );
- const modalElement = document.getElementById('my-modal');
-
- modalButton.click();
-
- expect(modalElement).not.toHaveClass('show');
-
- // let the modal fade in
- jest.runOnlyPendingTimers();
-
- expect(modalElement).toHaveClass('show');
- });
-
- describe('methods', () => {
- const dummyEvent = 'not really an event';
-
- beforeEach(() => {
- vm = mountComponent(modalComponent, {});
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- });
-
- describe('emitCancel', () => {
- it('emits a cancel event', () => {
- vm.emitCancel(dummyEvent);
-
- expect(vm.$emit).toHaveBeenCalledWith('cancel', dummyEvent);
- });
- });
-
- describe('emitSubmit', () => {
- it('emits a submit event', () => {
- vm.emitSubmit(dummyEvent);
-
- expect(vm.$emit).toHaveBeenCalledWith('submit', dummyEvent);
- });
- });
-
- describe('opened', () => {
- it('emits a open event', () => {
- vm.opened();
-
- expect(vm.$emit).toHaveBeenCalledWith('open');
- });
- });
-
- describe('closed', () => {
- it('emits a closed event', () => {
- vm.closed();
-
- expect(vm.$emit).toHaveBeenCalledWith('closed');
- });
- });
- });
-
- describe('slots', () => {
- const slotContent = 'this should go into the slot';
-
- const modalWithSlot = slot => {
- return Vue.extend({
- components: {
- DeprecatedModal2,
- },
- render: h =>
- h('deprecated-modal-2', [slot ? h('template', { slot }, slotContent) : slotContent]),
- });
- };
-
- describe('default slot', () => {
- beforeEach(() => {
- vm = mountComponent(modalWithSlot());
- });
-
- it('sets the modal body', () => {
- const modalBody = vm.$el.querySelector('.modal-body');
-
- expect(modalBody.innerHTML).toBe(slotContent);
- });
- });
-
- describe('header slot', () => {
- beforeEach(() => {
- vm = mountComponent(modalWithSlot('header'));
- });
-
- it('sets the modal header', () => {
- const modalHeader = vm.$el.querySelector('.modal-header');
-
- expect(modalHeader.innerHTML).toBe(slotContent);
- });
- });
-
- describe('title slot', () => {
- beforeEach(() => {
- vm = mountComponent(modalWithSlot('title'));
- });
-
- it('sets the modal title', () => {
- const modalTitle = vm.$el.querySelector('.modal-title');
-
- expect(modalTitle.innerHTML).toBe(slotContent);
- });
- });
-
- describe('footer slot', () => {
- beforeEach(() => {
- vm = mountComponent(modalWithSlot('footer'));
- });
-
- it('sets the modal footer', () => {
- const modalFooter = vm.$el.querySelector('.modal-footer');
-
- expect(modalFooter.innerHTML).toBe(slotContent);
- });
- });
- });
-
- describe('handling sizes', () => {
- it('should render modal-sm', () => {
- vm = mountComponent(modalComponent, {
- modalSize: 'sm',
- });
-
- expect(vm.$el.querySelector('.modal-dialog').classList.contains('modal-sm')).toEqual(true);
- });
-
- it('should render modal-lg', () => {
- vm = mountComponent(modalComponent, {
- modalSize: 'lg',
- });
-
- expect(vm.$el.querySelector('.modal-dialog').classList.contains('modal-lg')).toEqual(true);
- });
-
- it('should render modal-xl', () => {
- vm = mountComponent(modalComponent, {
- modalSize: 'xl',
- });
-
- expect(vm.$el.querySelector('.modal-dialog').classList.contains('modal-xl')).toEqual(true);
- });
-
- it('should not add modal size classes when md size is passed', () => {
- vm = mountComponent(modalComponent, {
- modalSize: 'md',
- });
-
- expect(vm.$el.querySelector('.modal-dialog').classList.contains('modal-md')).toEqual(false);
- });
-
- it('should not add modal size classes by default', () => {
- vm = mountComponent(modalComponent, {});
-
- expect(vm.$el.querySelector('.modal-dialog').classList.contains('modal-sm')).toEqual(false);
- expect(vm.$el.querySelector('.modal-dialog').classList.contains('modal-lg')).toEqual(false);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
index a6e4d812c3c..68e3ee11a0d 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -26,7 +26,7 @@ describe('DiffViewer', () => {
vm.$destroy();
});
- it('renders image diff', done => {
+ it('renders image diff', (done) => {
window.gon = {
relative_url_root: '',
};
@@ -46,7 +46,7 @@ describe('DiffViewer', () => {
});
});
- it('renders fallback download diff display', done => {
+ it('renders fallback download diff display', (done) => {
createComponent({
...requiredProps,
diffViewerMode: 'added',
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 f364f374887..b6bffbcc6f3 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
@@ -51,7 +51,7 @@ describe('ImageDiffViewer', () => {
wrapper.destroy();
});
- it('renders image diff for replaced', done => {
+ it('renders image diff for replaced', (done) => {
createComponent({ ...allProps });
vm.$nextTick(() => {
@@ -78,7 +78,7 @@ describe('ImageDiffViewer', () => {
});
});
- it('renders image diff for new', done => {
+ it('renders image diff for new', (done) => {
createComponent({ ...allProps, diffMode: 'new', oldPath: '' });
setImmediate(() => {
@@ -91,7 +91,7 @@ describe('ImageDiffViewer', () => {
});
});
- it('renders image diff for deleted', done => {
+ it('renders image diff for deleted', (done) => {
createComponent({ ...allProps, diffMode: 'deleted', newPath: '' });
setImmediate(() => {
@@ -104,7 +104,7 @@ describe('ImageDiffViewer', () => {
});
});
- it('renders image diff for renamed', done => {
+ it('renders image diff for renamed', (done) => {
vm = new Vue({
components: {
imageDiffViewer,
@@ -139,7 +139,7 @@ describe('ImageDiffViewer', () => {
});
describe('swipeMode', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent({ ...requiredProps });
setImmediate(() => {
@@ -147,7 +147,7 @@ describe('ImageDiffViewer', () => {
});
});
- it('switches to Swipe Mode', done => {
+ it('switches to Swipe Mode', (done) => {
vm.$el.querySelector('.view-modes-menu li:nth-child(2)').click();
vm.$nextTick(() => {
@@ -158,7 +158,7 @@ describe('ImageDiffViewer', () => {
});
describe('onionSkin', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent({ ...requiredProps });
setImmediate(() => {
@@ -166,7 +166,7 @@ describe('ImageDiffViewer', () => {
});
});
- it('switches to Onion Skin Mode', done => {
+ it('switches to Onion Skin Mode', (done) => {
vm.$el.querySelector('.view-modes-menu li:nth-child(3)').click();
vm.$nextTick(() => {
@@ -177,7 +177,7 @@ describe('ImageDiffViewer', () => {
});
});
- it('has working drag handler', done => {
+ it('has working drag handler', (done) => {
vm.$el.querySelector('.view-modes-menu li:nth-child(3)').click();
vm.$nextTick(() => {
diff --git a/spec/frontend/vue_shared/components/dismissible_container_spec.js b/spec/frontend/vue_shared/components/dismissible_container_spec.js
index e49ca1e2285..2c0e363fa0e 100644
--- a/spec/frontend/vue_shared/components/dismissible_container_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_container_spec.js
@@ -43,7 +43,7 @@ describe('DismissibleContainer', () => {
default: 'default slot',
};
- it.each(Object.keys(slots))('renders the %s slot', slot => {
+ it.each(Object.keys(slots))('renders the %s slot', (slot) => {
const slotContent = slots[slot];
wrapper = shallowMount(dismissibleContainer, {
propsData,
diff --git a/spec/frontend/vue_shared/components/editor_lite_spec.js b/spec/frontend/vue_shared/components/editor_lite_spec.js
index 52502fcf64f..70fdd8e24a5 100644
--- a/spec/frontend/vue_shared/components/editor_lite_spec.js
+++ b/spec/frontend/vue_shared/components/editor_lite_spec.js
@@ -7,20 +7,22 @@ jest.mock('~/editor/editor_lite');
describe('Editor Lite component', () => {
let wrapper;
- const onDidChangeModelContent = jest.fn();
- const updateModelLanguage = jest.fn();
- const getValue = jest.fn();
- const setValue = jest.fn();
+ let mockInstance;
+
const value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
const fileName = 'lorem.txt';
const fileGlobalId = 'snippet_777';
- const createInstanceMock = jest.fn().mockImplementation(() => ({
- onDidChangeModelContent,
- updateModelLanguage,
- getValue,
- setValue,
- dispose: jest.fn(),
- }));
+ const createInstanceMock = jest.fn().mockImplementation(() => {
+ mockInstance = {
+ onDidChangeModelContent: jest.fn(),
+ updateModelLanguage: jest.fn(),
+ getValue: jest.fn(),
+ setValue: jest.fn(),
+ dispose: jest.fn(),
+ };
+ return mockInstance;
+ });
+
Editor.mockImplementation(() => {
return {
createInstance: createInstanceMock,
@@ -45,9 +47,9 @@ describe('Editor Lite component', () => {
wrapper.destroy();
});
- const triggerChangeContent = val => {
- getValue.mockReturnValue(val);
- const [cb] = onDidChangeModelContent.mock.calls[0];
+ const triggerChangeContent = (val) => {
+ mockInstance.getValue.mockReturnValue(val);
+ const [cb] = mockInstance.onDidChangeModelContent.mock.calls[0];
cb();
@@ -92,12 +94,12 @@ describe('Editor Lite component', () => {
});
return nextTick().then(() => {
- expect(updateModelLanguage).toHaveBeenCalledWith(newFileName);
+ expect(mockInstance.updateModelLanguage).toHaveBeenCalledWith(newFileName);
});
});
it('registers callback with editor onChangeContent', () => {
- expect(onDidChangeModelContent).toHaveBeenCalledWith(expect.any(Function));
+ expect(mockInstance.onDidChangeModelContent).toHaveBeenCalledWith(expect.any(Function));
});
it('emits input event when the blob content is changed', () => {
@@ -117,6 +119,10 @@ describe('Editor Lite component', () => {
expect(wrapper.emitted()['editor-ready']).toBeDefined();
});
+ it('component API `getEditor()` returns the editor instance', () => {
+ expect(wrapper.vm.getEditor()).toBe(mockInstance);
+ });
+
describe('reaction to the value update', () => {
it('reacts to the changes in the passed value', async () => {
const newValue = 'New Value';
@@ -126,7 +132,7 @@ describe('Editor Lite component', () => {
});
await nextTick();
- expect(setValue).toHaveBeenCalledWith(newValue);
+ expect(mockInstance.setValue).toHaveBeenCalledWith(newValue);
});
it("does not update value if the passed one is exactly the same as the editor's content", async () => {
@@ -137,7 +143,7 @@ describe('Editor Lite component', () => {
});
await nextTick();
- expect(setValue).not.toHaveBeenCalled();
+ expect(mockInstance.setValue).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/vue_shared/components/expand_button_spec.js b/spec/frontend/vue_shared/components/expand_button_spec.js
index aea90e5b31f..724405a109f 100644
--- a/spec/frontend/vue_shared/components/expand_button_spec.js
+++ b/spec/frontend/vue_shared/components/expand_button_spec.js
@@ -41,12 +41,7 @@ describe('Expand button', () => {
});
it('does not render expanded text', () => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).not.toBe(text.short);
+ expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.short);
});
describe('when short text is provided', () => {
@@ -60,12 +55,7 @@ describe('Expand button', () => {
});
it('renders short text', () => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).toBe(text.short);
+ expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
});
it('renders button before text', () => {
@@ -76,7 +66,7 @@ describe('Expand button', () => {
});
describe('on click', () => {
- beforeEach(done => {
+ beforeEach((done) => {
expanderPrependEl().trigger('click');
Vue.nextTick(done);
});
@@ -95,7 +85,7 @@ describe('Expand button', () => {
});
describe('when short text is provided', () => {
- beforeEach(done => {
+ beforeEach((done) => {
factory({
slots: {
expanded: `<p>${text.expanded}</p>`,
@@ -108,12 +98,7 @@ describe('Expand button', () => {
});
it('only renders expanded text', () => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).toBe(text.expanded);
+ expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
});
it('renders button after text', () => {
@@ -125,7 +110,7 @@ describe('Expand button', () => {
});
describe('append button', () => {
- beforeEach(done => {
+ beforeEach((done) => {
expanderPrependEl().trigger('click');
Vue.nextTick(done);
});
@@ -140,26 +125,16 @@ describe('Expand button', () => {
});
it('clicking hides expanded text', () => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).toBe(text.expanded);
+ expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
expanderAppendEl().trigger('click');
return wrapper.vm.$nextTick().then(() => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).not.toBe(text.expanded);
+ expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.expanded);
});
});
describe('when short text is provided', () => {
- beforeEach(done => {
+ beforeEach((done) => {
factory({
slots: {
expanded: `<p>${text.expanded}</p>`,
@@ -172,21 +147,11 @@ describe('Expand button', () => {
});
it('clicking reveals short text', () => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).toBe(text.expanded);
+ expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
expanderAppendEl().trigger('click');
return wrapper.vm.$nextTick().then(() => {
- expect(
- wrapper
- .find(ExpandButton)
- .text()
- .trim(),
- ).toBe(text.short);
+ expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
});
});
});
diff --git a/spec/frontend/vue_shared/components/file_finder/index_spec.js b/spec/frontend/vue_shared/components/file_finder/index_spec.js
index 40026021777..238a5440664 100644
--- a/spec/frontend/vue_shared/components/file_finder/index_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/index_spec.js
@@ -31,7 +31,7 @@ describe('File finder item spec', () => {
});
describe('with entries', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent({
files: [
{
@@ -57,7 +57,7 @@ describe('File finder item spec', () => {
expect(vm.$el.textContent).not.toContain('folder');
});
- it('filters entries', done => {
+ it('filters entries', (done) => {
vm.searchText = 'index';
setImmediate(() => {
@@ -68,7 +68,7 @@ describe('File finder item spec', () => {
});
});
- it('shows clear button when searchText is not empty', done => {
+ it('shows clear button when searchText is not empty', (done) => {
vm.searchText = 'index';
setImmediate(() => {
@@ -79,7 +79,7 @@ describe('File finder item spec', () => {
});
});
- it('clear button resets searchText', done => {
+ it('clear button resets searchText', (done) => {
vm.searchText = 'index';
waitForPromises()
@@ -94,7 +94,7 @@ describe('File finder item spec', () => {
.catch(done.fail);
});
- it('clear button focuses search input', done => {
+ it('clear button focuses search input', (done) => {
jest.spyOn(vm.$refs.searchInput, 'focus').mockImplementation(() => {});
vm.searchText = 'index';
@@ -111,7 +111,7 @@ describe('File finder item spec', () => {
});
describe('listShowCount', () => {
- it('returns 1 when no filtered entries exist', done => {
+ it('returns 1 when no filtered entries exist', (done) => {
vm.searchText = 'testing 123';
setImmediate(() => {
@@ -131,7 +131,7 @@ describe('File finder item spec', () => {
expect(vm.listHeight).toBe(55);
});
- it('returns 33 when entries dont exist', done => {
+ it('returns 33 when entries dont exist', (done) => {
vm.searchText = 'testing 123';
setImmediate(() => {
@@ -143,7 +143,7 @@ describe('File finder item spec', () => {
});
describe('filteredBlobsLength', () => {
- it('returns length of filtered blobs', done => {
+ it('returns length of filtered blobs', (done) => {
vm.searchText = 'index';
setImmediate(() => {
@@ -156,7 +156,7 @@ describe('File finder item spec', () => {
describe('watches', () => {
describe('searchText', () => {
- it('resets focusedIndex when updated', done => {
+ it('resets focusedIndex when updated', (done) => {
vm.focusedIndex = 1;
vm.searchText = 'test';
@@ -169,7 +169,7 @@ describe('File finder item spec', () => {
});
describe('visible', () => {
- it('returns searchText when false', done => {
+ it('returns searchText when false', (done) => {
vm.searchText = 'test';
vm.visible = true;
@@ -206,7 +206,7 @@ describe('File finder item spec', () => {
});
describe('onKeyup', () => {
- it('opens file on enter key', done => {
+ it('opens file on enter key', (done) => {
const event = new CustomEvent('keyup');
event.keyCode = ENTER_KEY_CODE;
@@ -221,7 +221,7 @@ describe('File finder item spec', () => {
});
});
- it('closes file finder on esc key', done => {
+ it('closes file finder on esc key', (done) => {
const event = new CustomEvent('keyup');
event.keyCode = ESC_KEY_CODE;
@@ -300,7 +300,7 @@ describe('File finder item spec', () => {
});
describe('keyboard shortcuts', () => {
- beforeEach(done => {
+ beforeEach((done) => {
createComponent();
jest.spyOn(vm, 'toggle').mockImplementation(() => {});
@@ -308,7 +308,7 @@ describe('File finder item spec', () => {
vm.$nextTick(done);
});
- it('calls toggle on `t` key press', done => {
+ it('calls toggle on `t` key press', (done) => {
Mousetrap.trigger('t');
vm.$nextTick()
@@ -319,7 +319,7 @@ describe('File finder item spec', () => {
.catch(done.fail);
});
- it('calls toggle on `mod+p` key press', done => {
+ it('calls toggle on `mod+p` key press', (done) => {
Mousetrap.trigger('mod+p');
vm.$nextTick()
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 5a45a5dbba1..c60e6335389 100644
--- a/spec/frontend/vue_shared/components/file_finder/item_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/item_spec.js
@@ -37,7 +37,7 @@ describe('File finder item spec', () => {
expect(vm.$el.classList).toContain('is-focused');
});
- it('does not have is-focused class when not focused', done => {
+ it('does not have is-focused class when not focused', (done) => {
vm.focused = false;
vm.$nextTick(() => {
@@ -53,7 +53,7 @@ describe('File finder item spec', () => {
expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
});
- it('renders when a changed file', done => {
+ it('renders when a changed file', (done) => {
vm.file.changed = true;
vm.$nextTick(() => {
@@ -63,7 +63,7 @@ describe('File finder item spec', () => {
});
});
- it('renders when a temp file', done => {
+ it('renders when a temp file', (done) => {
vm.file.tempFile = true;
vm.$nextTick(() => {
@@ -85,7 +85,7 @@ describe('File finder item spec', () => {
describe('path', () => {
let el;
- beforeEach(done => {
+ beforeEach((done) => {
vm.searchText = 'file';
el = vm.$el.querySelector('.diff-changed-file-path');
@@ -97,7 +97,7 @@ describe('File finder item spec', () => {
expect(el.querySelectorAll('.highlighted').length).toBe(4);
});
- it('adds ellipsis to long text', done => {
+ it('adds ellipsis to long text', (done) => {
vm.file.path = new Array(70)
.fill()
.map((_, i) => `${i}-`)
@@ -113,7 +113,7 @@ describe('File finder item spec', () => {
describe('name', () => {
let el;
- beforeEach(done => {
+ beforeEach((done) => {
vm.searchText = 'file';
el = vm.$el.querySelector('.diff-changed-file-name');
@@ -125,7 +125,7 @@ describe('File finder item spec', () => {
expect(el.querySelectorAll('.highlighted').length).toBe(4);
});
- it('does not add ellipsis to long text', done => {
+ it('does not add ellipsis to long text', (done) => {
vm.file.name = new Array(70)
.fill()
.map((_, i) => `${i}-`)
diff --git a/spec/frontend/vue_shared/components/file_tree_spec.js b/spec/frontend/vue_shared/components/file_tree_spec.js
index 38979d9d844..7a4982fd29b 100644
--- a/spec/frontend/vue_shared/components/file_tree_spec.js
+++ b/spec/frontend/vue_shared/components/file_tree_spec.js
@@ -28,7 +28,7 @@ describe('File Tree component', () => {
const findFileRow = () => wrapper.find(MockFileRow);
const findChildrenTrees = () => wrapper.findAll(FileTree).wrappers.slice(1);
const findChildrenTreeProps = () =>
- findChildrenTrees().map(x => ({
+ findChildrenTrees().map((x) => ({
...x.props(),
...pick(x.attributes(), Object.keys(TEST_EXTA_ARGS)),
}));
@@ -61,7 +61,7 @@ describe('File Tree component', () => {
describe('file tree', () => {
const createChildren = () => [{ id: 1 }, { id: 2 }];
const createChildrenExpectation = (props = {}) =>
- createChildren().map(file => ({
+ createChildren().map((file) => ({
fileRowComponent: MockFileRow,
file,
...TEST_EXTA_ARGS,
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 8cc5d6775a7..b58ce0083c0 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
@@ -25,10 +25,11 @@ import {
tokenValueLabel,
tokenValueMilestone,
tokenValueMembership,
+ tokenValueConfidential,
} from './mock_data';
jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', () => ({
- uniqueTokens: jest.fn().mockImplementation(tokens => tokens),
+ uniqueTokens: jest.fn().mockImplementation((tokens) => tokens),
stripQuotes: jest.requireActual(
'~/vue_shared/components/filtered_search_bar/filtered_search_utils',
).stripQuotes,
@@ -227,12 +228,13 @@ describe('FilteredSearchBarRoot', () => {
});
describe('removeQuotesEnclosure', () => {
- const mockFilters = [tokenValueAuthor, tokenValueLabel, 'foo'];
+ const mockFilters = [tokenValueAuthor, tokenValueLabel, tokenValueConfidential, 'foo'];
it('returns filter array with unescaped strings for values which have spaces', () => {
expect(wrapper.vm.removeQuotesEnclosure(mockFilters)).toEqual([
tokenValueAuthor,
tokenValueLabel,
+ tokenValueConfidential,
'foo',
]);
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
index 4869e75a2f3..9e96c154546 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
@@ -82,7 +82,10 @@ describe('prepareTokens', () => {
],
[
'assignees',
- [{ value: 'krillin', operator: '=' }, { value: 'piccolo', operator: '!=' }],
+ [
+ { value: 'krillin', operator: '=' },
+ { value: 'piccolo', operator: '!=' },
+ ],
[
{ type: 'assignees', value: { data: 'krillin', operator: '=' } },
{ type: 'assignees', value: { data: 'piccolo', operator: '!=' } },
@@ -90,7 +93,10 @@ describe('prepareTokens', () => {
],
[
'foo',
- [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '!=' }],
+ [
+ { value: 'bar', operator: '!=' },
+ { value: 'baz', operator: '!=' },
+ ],
[
{ type: 'foo', value: { data: 'bar', operator: '!=' } },
{ type: 'foo', value: { data: 'baz', operator: '!=' } },
@@ -112,7 +118,10 @@ describe('processFilters', () => {
expect(result).toStrictEqual({
foo: [{ value: 'foo', operator: '=' }],
- bar: [{ value: 'bar1', operator: '=' }, { value: 'bar2', operator: '!=' }],
+ bar: [
+ { value: 'bar1', operator: '=' },
+ { value: 'bar2', operator: '!=' },
+ ],
});
});
@@ -164,17 +173,26 @@ describe('filterToQueryObject', () => {
],
[
'foo',
- [{ value: 'bar', operator: '=' }, { value: 'baz', operator: '=' }],
+ [
+ { value: 'bar', operator: '=' },
+ { value: 'baz', operator: '=' },
+ ],
{ foo: ['bar', 'baz'], 'not[foo]': null },
],
[
'foo',
- [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '!=' }],
+ [
+ { value: 'bar', operator: '!=' },
+ { value: 'baz', operator: '!=' },
+ ],
{ foo: null, 'not[foo]': ['bar', 'baz'] },
],
[
'foo',
- [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '=' }],
+ [
+ { value: 'bar', operator: '!=' },
+ { value: 'baz', operator: '=' },
+ ],
{ foo: ['baz'], 'not[foo]': ['bar'] },
],
])('gathers filter values %s=%j into query object=%j', (token, value, result) => {
@@ -200,15 +218,30 @@ describe('urlQueryToFilter', () => {
['not[foo]=bar&foo=baz', { foo: { value: 'baz', operator: '=' } }],
[
'foo[]=bar&foo[]=baz&not[foo]=',
- { foo: [{ value: 'bar', operator: '=' }, { value: 'baz', operator: '=' }] },
+ {
+ foo: [
+ { value: 'bar', operator: '=' },
+ { value: 'baz', operator: '=' },
+ ],
+ },
],
[
'foo[]=&not[foo][]=bar&not[foo][]=baz',
- { foo: [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '!=' }] },
+ {
+ foo: [
+ { value: 'bar', operator: '!=' },
+ { value: 'baz', operator: '!=' },
+ ],
+ },
],
[
'foo[]=baz&not[foo][]=bar',
- { foo: [{ value: 'baz', operator: '=' }, { value: 'bar', operator: '!=' }] },
+ {
+ foo: [
+ { value: 'baz', operator: '=' },
+ { value: 'bar', operator: '!=' },
+ ],
+ },
],
['not[foo][]=bar', { foo: [{ value: 'bar', operator: '!=' }] }],
])('gathers filter values %s into query object=%j', (query, result) => {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index 64fbe70696d..7606b3bd91c 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -110,7 +110,10 @@ export const mockMembershipToken = {
token: GlFilteredSearchToken,
unique: true,
operators: [{ value: '=', description: 'is' }],
- options: [{ value: 'exclude', title: 'Direct' }, { value: 'only', title: 'Inherited' }],
+ options: [
+ { value: 'exclude', title: 'Direct' },
+ { value: 'only', title: 'Inherited' },
+ ],
};
export const mockMembershipTokenOptionsWithoutTitles = {
@@ -152,6 +155,14 @@ export const tokenValueMembership = {
},
};
+export const tokenValueConfidential = {
+ type: 'confidential',
+ value: {
+ operator: '=',
+ data: true,
+ },
+};
+
export const tokenValuePlain = {
type: 'filtered-search-term',
value: { data: 'foo' },
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper.js b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper.js
index 1b7c80a5252..84297923df3 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper.js
@@ -1,11 +1,11 @@
export function getFilterParams(tokens, options = {}) {
const { key = 'value', operator = '=', prop = 'title' } = options;
- return tokens.map(token => {
+ return tokens.map((token) => {
return { [key]: token[prop], operator };
});
}
export function getFilterValues(tokens, options = {}) {
const { prop = 'title' } = options;
- return tokens.map(token => token[prop]);
+ return tokens.map((token) => token[prop]);
}
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 3fd1d8b7f42..3997d6a99a6 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
@@ -189,8 +189,8 @@ describe('AuthorToken', () => {
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
- expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
- expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_LABEL_ANY` as default suggestions', async () => {
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 5b7f7d242e9..35f487330be 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
@@ -189,8 +189,8 @@ describe('BranchToken', () => {
});
await showSuggestions();
- expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
- expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
});
it('renders no suggestions as default', async () => {
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 74172db81c2..dda0ad39bbc 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
@@ -181,12 +181,9 @@ describe('LabelToken', () => {
expect(tokenSegments).toHaveLength(3); // Label, =, "Foo Label"
expect(tokenSegments.at(2).text()).toBe(`~${mockRegularLabel.title}`); // "Foo Label"
- expect(
- tokenSegments
- .at(2)
- .find('.gl-token')
- .attributes('style'),
- ).toBe('background-color: rgb(186, 218, 85); color: rgb(255, 255, 255);');
+ expect(tokenSegments.at(2).find('.gl-token').attributes('style')).toBe(
+ 'background-color: rgb(186, 218, 85); color: rgb(255, 255, 255);',
+ );
});
it('renders provided defaultLabels as suggestions', async () => {
@@ -219,8 +216,8 @@ describe('LabelToken', () => {
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
- expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
- expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_LABELS` as default suggestions', async () => {
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 67f9a9c70cc..164561f6244 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
@@ -140,7 +140,10 @@ describe('MilestoneToken', () => {
});
describe('template', () => {
- const defaultMilestones = [{ text: 'foo', value: 'foo' }, { text: 'bar', value: 'baz' }];
+ const defaultMilestones = [
+ { text: 'foo', value: 'foo' },
+ { text: 'bar', value: 'baz' },
+ ];
beforeEach(async () => {
wrapper = createComponent({ value: { data: `"${mockRegularMilestone.title}"` } });
@@ -193,8 +196,8 @@ describe('MilestoneToken', () => {
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
- expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
- expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_MILESTONES` as default suggestions', async () => {
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 d0fa2086fdc..d8e6e37bb89 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,5 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`gfm_autocomplete/utils emojis config shows the emoji name and icon in the menu item 1`] = `
+"raised_hands
+ <gl-emoji
+
+ data-name=\\"raised_hands\\"></gl-emoji>
+ "
+`;
+
exports[`gfm_autocomplete/utils issues config shows the iid and title in the menu item within a project context 1`] = `"<small>123456</small> Project context issue title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
exports[`gfm_autocomplete/utils issues config shows the reference and title in the menu item within a group context 1`] = `"<small>gitlab#987654</small> Group context issue title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
@@ -44,4 +52,9 @@ exports[`gfm_autocomplete/utils merge requests config shows the reference and ti
exports[`gfm_autocomplete/utils milestones config shows the title in the menu item 1`] = `"13.2 &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
+exports[`gfm_autocomplete/utils quick actions config shows the name, aliases, params and description in the menu item 1`] = `
+"<div>/unlabel <small>(or /remove_label)</small> <small>~label1 ~\\"label 2\\"</small></div>
+ <div><small><em>Remove all or specific label(s)</em></small></div>"
+`;
+
exports[`gfm_autocomplete/utils snippets config shows the id and title in the menu item 1`] = `"<small>123456</small> Snippet title &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;"`;
diff --git a/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js b/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js
index 647f8c6e000..7ec3fbd4e3b 100644
--- a/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js
+++ b/spec/frontend/vue_shared/components/gfm_autocomplete/utils_spec.js
@@ -2,6 +2,31 @@ import { escape, last } from 'lodash';
import { GfmAutocompleteType, tributeConfig } from '~/vue_shared/components/gfm_autocomplete/utils';
describe('gfm_autocomplete/utils', () => {
+ describe('emojis config', () => {
+ const emojisConfig = tributeConfig[GfmAutocompleteType.Emojis].config;
+ const emoji = 'raised_hands';
+
+ it('uses : as the trigger', () => {
+ expect(emojisConfig.trigger).toBe(':');
+ });
+
+ it('searches using the emoji name', () => {
+ expect(emojisConfig.lookup(emoji)).toBe(emoji);
+ });
+
+ it('limits the number of rendered items to 100', () => {
+ expect(emojisConfig.menuItemLimit).toBe(100);
+ });
+
+ it('shows the emoji name and icon in the menu item', () => {
+ expect(emojisConfig.menuItemTemplate({ original: emoji })).toMatchSnapshot();
+ });
+
+ it('inserts the emoji name on autocomplete selection', () => {
+ expect(emojisConfig.selectTemplate({ original: emoji })).toBe(`:${emoji}:`);
+ });
+ });
+
describe('issues config', () => {
const issuesConfig = tributeConfig[GfmAutocompleteType.Issues].config;
const groupContextIssue = {
@@ -26,6 +51,10 @@ describe('gfm_autocomplete/utils', () => {
);
});
+ it('limits the number of rendered items to 100', () => {
+ expect(issuesConfig.menuItemLimit).toBe(100);
+ });
+
it('shows the reference and title in the menu item within a group context', () => {
expect(issuesConfig.menuItemTemplate({ original: groupContextIssue })).toMatchSnapshot();
});
@@ -77,6 +106,10 @@ describe('gfm_autocomplete/utils', () => {
expect(labelsConfig.lookup).toBe('title');
});
+ it('limits the number of rendered items to 100', () => {
+ expect(labelsConfig.menuItemLimit).toBe(100);
+ });
+
it('shows the title in the menu item', () => {
expect(labelsConfig.menuItemTemplate({ original: label })).toMatchSnapshot();
});
@@ -180,6 +213,10 @@ describe('gfm_autocomplete/utils', () => {
expect(membersConfig.lookup(groupMember)).toBe(last(groupMember.name.split(' / ')));
});
+ it('limits the items in the autocomplete menu to 10', () => {
+ expect(membersConfig.menuItemLimit).toBe(10);
+ });
+
it('shows the avatar, name and username in the menu item for a user', () => {
expect(membersConfig.menuItemTemplate({ original: userMember })).toMatchSnapshot();
});
@@ -266,6 +303,10 @@ describe('gfm_autocomplete/utils', () => {
);
});
+ it('limits the number of rendered items to 100', () => {
+ expect(mergeRequestsConfig.menuItemLimit).toBe(100);
+ });
+
it('shows the reference and title in the menu item within a group context', () => {
expect(
mergeRequestsConfig.menuItemTemplate({ original: groupContextMergeRequest }),
@@ -307,6 +348,10 @@ describe('gfm_autocomplete/utils', () => {
expect(milestonesConfig.lookup).toBe('title');
});
+ it('limits the number of rendered items to 100', () => {
+ expect(milestonesConfig.menuItemLimit).toBe(100);
+ });
+
it('shows the title in the menu item', () => {
expect(milestonesConfig.menuItemTemplate({ original: milestone })).toMatchSnapshot();
});
@@ -318,6 +363,40 @@ describe('gfm_autocomplete/utils', () => {
});
});
+ describe('quick actions config', () => {
+ const quickActionsConfig = tributeConfig[GfmAutocompleteType.QuickActions].config;
+ const quickAction = {
+ name: 'unlabel',
+ aliases: ['remove_label'],
+ description: 'Remove all or specific label(s)',
+ warning: '',
+ icon: '',
+ params: ['~label1 ~"label 2"'],
+ };
+
+ it('uses / as the trigger', () => {
+ expect(quickActionsConfig.trigger).toBe('/');
+ });
+
+ it('inserts the name on autocomplete selection', () => {
+ expect(quickActionsConfig.fillAttr).toBe('name');
+ });
+
+ it('searches using both the name and aliases', () => {
+ expect(quickActionsConfig.lookup(quickAction)).toBe(
+ `${quickAction.name}${quickAction.aliases.join(', /')}`,
+ );
+ });
+
+ it('limits the number of rendered items to 100', () => {
+ expect(quickActionsConfig.menuItemLimit).toBe(100);
+ });
+
+ it('shows the name, aliases, params and description in the menu item', () => {
+ expect(quickActionsConfig.menuItemTemplate({ original: quickAction })).toMatchSnapshot();
+ });
+ });
+
describe('snippets config', () => {
const snippetsConfig = tributeConfig[GfmAutocompleteType.Snippets].config;
const snippet = {
@@ -337,6 +416,10 @@ describe('gfm_autocomplete/utils', () => {
expect(snippetsConfig.lookup(snippet)).toBe(`${snippet.id}${snippet.title}`);
});
+ it('limits the number of rendered items to 100', () => {
+ expect(snippetsConfig.menuItemLimit).toBe(100);
+ });
+
it('shows the id and title in the menu item', () => {
expect(snippetsConfig.menuItemTemplate({ original: snippet })).toMatchSnapshot();
});
diff --git a/spec/frontend/vue_shared/components/gl_countdown_spec.js b/spec/frontend/vue_shared/components/gl_countdown_spec.js
index 365c9fad478..fcc5c0cd310 100644
--- a/spec/frontend/vue_shared/components/gl_countdown_spec.js
+++ b/spec/frontend/vue_shared/components/gl_countdown_spec.js
@@ -17,21 +17,19 @@ describe('GlCountdown', () => {
});
describe('when there is time remaining', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = mountComponent(Component, {
endDateString: '2000-01-01T01:02:03Z',
});
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ Vue.nextTick().then(done).catch(done.fail);
});
it('displays remaining time', () => {
expect(vm.$el.textContent).toContain('01:02:03');
});
- it('updates remaining time', done => {
+ it('updates remaining time', (done) => {
now = '2000-01-01T00:00:01Z';
jest.advanceTimersByTime(1000);
@@ -45,14 +43,12 @@ describe('GlCountdown', () => {
});
describe('when there is no time remaining', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm = mountComponent(Component, {
endDateString: '1900-01-01T00:00:00Z',
});
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ Vue.nextTick().then(done).catch(done.fail);
});
it('displays 00:00:00', () => {
diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
index 93f4db5df18..6802499ed52 100644
--- a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
+++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
@@ -118,7 +118,7 @@ describe('GlModalVuex', () => {
expect(actions.hide).toHaveBeenCalledTimes(1);
});
- it('calls bootstrap show when isVisible changes', done => {
+ it('calls bootstrap show when isVisible changes', (done) => {
state.isVisible = false;
factory();
@@ -135,7 +135,7 @@ describe('GlModalVuex', () => {
.catch(done.fail);
});
- it('calls bootstrap hide when isVisible changes', done => {
+ it('calls bootstrap hide when isVisible changes', (done) => {
state.isVisible = true;
factory();
@@ -154,7 +154,7 @@ describe('GlModalVuex', () => {
it.each(['ok', 'cancel'])(
'passes an "%s" handler to the "modal-footer" slot scope',
- handlerName => {
+ (handlerName) => {
state.isVisible = true;
const modalFooterSlotContent = jest.fn();
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 2f910a10bc6..a03a3915e1b 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
@@ -17,13 +17,13 @@ describe('IssuableHeaderWarnings', () => {
const findConfidentialIcon = () => wrapper.find('[data-testid="confidential"]');
const findLockedIcon = () => wrapper.find('[data-testid="locked"]');
- const renderTestMessage = renders => (renders ? 'renders' : 'does not render');
+ const renderTestMessage = (renders) => (renders ? 'renders' : 'does not render');
- const setLock = locked => {
+ const setLock = (locked) => {
store.getters.getNoteableData.discussion_locked = locked;
};
- const setConfidential = confidential => {
+ const setConfidential = (confidential) => {
store.getters.getNoteableData.confidential = confidential;
};
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 192e33d8b00..5f614bfc751 100644
--- a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
@@ -11,7 +11,7 @@ describe('IssueAssigneesComponent', () => {
let wrapper;
let vm;
- const factory = props => {
+ const factory = (props) => {
wrapper = shallowMount(IssueAssignees, {
propsData: {
assignees: mockAssigneesList,
@@ -99,11 +99,11 @@ describe('IssueAssigneesComponent', () => {
});
it('renders assignee', () => {
- const data = findAvatars().wrappers.map(x => ({
+ const data = findAvatars().wrappers.map((x) => ({
...x.props(),
}));
- const expected = mockAssigneesList.slice(0, TEST_MAX_VISIBLE - 1).map(x =>
+ const expected = mockAssigneesList.slice(0, TEST_MAX_VISIBLE - 1).map((x) =>
expect.objectContaining({
linkHref: x.web_url,
imgAlt: `Avatar for ${x.name}`,
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 d1bfc180082..ffcb891c4fc 100644
--- a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
@@ -19,7 +19,7 @@ describe('IssueMilestoneComponent', () => {
let wrapper;
let vm;
- beforeEach(done => {
+ beforeEach((done) => {
wrapper = createComponent();
({ vm } = wrapper);
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 2319bf61482..3dc34583118 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,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
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';
@@ -115,9 +115,7 @@ describe('RelatedIssuableItem', () => {
const tokenMetadata = () => wrapper.find('.item-meta');
it('renders item path and ID', () => {
- const pathAndID = tokenMetadata()
- .find('.item-path-id')
- .text();
+ const pathAndID = tokenMetadata().find('.item-path-id').text();
expect(pathAndID).toContain('gitlab-org/gitlab-test');
expect(pathAndID).toContain('#1');
diff --git a/spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js b/spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js
index 17813f2833d..6cdb945ec20 100644
--- a/spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js
+++ b/spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js
@@ -1,4 +1,4 @@
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
export const defaultProps = {
endpoint: '/foo/bar/issues/1/related_issues',
diff --git a/spec/frontend/vue_shared/components/local_storage_sync_spec.js b/spec/frontend/vue_shared/components/local_storage_sync_spec.js
index 464fe3411dd..4c5a0c1e601 100644
--- a/spec/frontend/vue_shared/components/local_storage_sync_spec.js
+++ b/spec/frontend/vue_shared/components/local_storage_sync_spec.js
@@ -49,7 +49,7 @@ describe('Local Storage Sync', () => {
it.each('foo', 3, true, ['foo', 'bar'], { foo: 'bar' })(
'saves updated value to localStorage',
- newValue => {
+ (newValue) => {
createComponent({
props: {
storageKey,
diff --git a/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap b/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
index b8a9143bc79..c454166e30b 100644
--- a/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
+++ b/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
@@ -7,6 +7,7 @@ exports[`Suggestion Diff component matches snapshot 1`] = `
<suggestion-diff-header-stub
batchsuggestionscount="1"
class="qa-suggestion-diff-header js-suggestion-diff-header"
+ defaultcommitmessage="Apply suggestion"
helppagepath="path_to_docs"
isapplyingbatch="true"
isbatched="true"
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 0598506891b..b9f0d88548d 100644
--- a/spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js
@@ -3,10 +3,10 @@ import { GlDropdown, GlFormTextarea, GlButton } from '@gitlab/ui';
import ApplySuggestionComponent from '~/vue_shared/components/markdown/apply_suggestion.vue';
describe('Apply Suggestion component', () => {
- const propsData = { fileName: 'test.js', disabled: false };
+ const propsData = { defaultCommitMessage: 'Apply suggestion', disabled: false };
let wrapper;
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = shallowMount(ApplySuggestionComponent, { propsData: { ...propsData, ...props } });
};
@@ -27,7 +27,6 @@ describe('Apply Suggestion component', () => {
expect(dropdown.exists()).toBe(true);
expect(dropdown.props('text')).toBe('Apply suggestion');
- expect(dropdown.props('headerText')).toBe('Apply suggestion commit message');
expect(dropdown.props('disabled')).toBe(false);
});
@@ -35,7 +34,7 @@ describe('Apply Suggestion component', () => {
const textArea = findTextArea();
expect(textArea.exists()).toBe(true);
- expect(textArea.attributes('placeholder')).toBe('Apply suggestion on test.js');
+ expect(textArea.attributes('placeholder')).toBe('Apply suggestion');
});
it('renders an apply button', () => {
@@ -55,11 +54,11 @@ describe('Apply Suggestion component', () => {
});
describe('apply suggestion', () => {
- it('emits an apply event with a default message if no message was added', () => {
+ it('emits an apply event with no message if no message was added', () => {
findTextArea().vm.$emit('input', null);
findApplyButton().vm.$emit('click');
- expect(wrapper.emitted('apply')).toEqual([['Apply suggestion on test.js']]);
+ expect(wrapper.emitted('apply')).toEqual([[null]]);
});
it('emits an apply event with a user-defined message', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index 82bc9b9fe08..077c2174571 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -6,7 +6,7 @@ import ToolbarButton from '~/vue_shared/components/markdown/toolbar_button.vue';
describe('Markdown field header component', () => {
let wrapper;
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = shallowMount(HeaderComponent, {
propsData: {
previewMarkdown: false,
@@ -18,7 +18,7 @@ describe('Markdown field header component', () => {
const findToolbarButtons = () => wrapper.findAll(ToolbarButton);
const findToolbarButtonByProp = (prop, value) =>
findToolbarButtons()
- .filter(button => button.props(prop) === value)
+ .filter((button) => button.props(prop) === value)
.at(0);
beforeEach(() => {
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
index c0a000690f8..bf65adc866d 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
@@ -9,6 +9,7 @@ const DEFAULT_PROPS = {
isBatched: false,
isApplyingBatch: false,
helpPagePath: 'path_to_docs',
+ defaultCommitMessage: 'Apply suggestion',
};
describe('Suggestion Diff component', () => {
@@ -91,7 +92,7 @@ describe('Suggestion Diff component', () => {
});
it('emits apply', () => {
- expect(wrapper.emitted().apply).toEqual([[expect.any(Function)]]);
+ expect(wrapper.emitted().apply).toEqual([[expect.any(Function), undefined]]);
});
it('does not render apply suggestion and add to batch buttons', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js
index b67f4cf12bf..f9a8b64f89b 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js
@@ -61,11 +61,7 @@ describe('SuggestionDiffRow', () => {
});
expect(wrapper.classes()).toContain('line_holder');
- expect(
- findSuggestionContent()
- .find('span')
- .classes(),
- ).toContain('line');
+ expect(findSuggestionContent().find('span').classes()).toContain('line');
});
it('renders the rich text when it is available', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
index 232feb126dc..5bd6bda2d2c 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
@@ -42,6 +42,7 @@ const MOCK_DATA = {
is_applying_batch: true,
},
helpPagePath: 'path_to_docs',
+ defaultCommitMessage: 'Apply suggestion',
batchSuggestionsInfo: [{ suggestionId }],
};
diff --git a/spec/frontend/vue_shared/components/markdown/suggestions_spec.js b/spec/frontend/vue_shared/components/markdown/suggestions_spec.js
index 34ccdf38b00..6fcac2df0b6 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestions_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestions_spec.js
@@ -44,13 +44,14 @@ const MOCK_DATA = {
`,
isApplied: false,
helpPagePath: 'path_to_docs',
+ defaultCommitMessage: 'Apply suggestion',
};
describe('Suggestion component', () => {
let vm;
let diffTable;
- beforeEach(done => {
+ beforeEach((done) => {
const Component = Vue.extend(SuggestionsComponent);
vm = new Component({
@@ -86,7 +87,7 @@ describe('Suggestion component', () => {
});
it('generates a diff table that contains contents the suggested lines', () => {
- MOCK_DATA.suggestions[0].diff_lines.forEach(line => {
+ MOCK_DATA.suggestions[0].diff_lines.forEach((line) => {
const text = line.text.substring(1);
expect(diffTable.innerHTML.includes(text)).toBe(true);
diff --git a/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
index 8a7946fd7b1..786dfabb990 100644
--- a/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
@@ -10,7 +10,7 @@ describe('toolbar_button', () => {
tag: 'test tag',
};
- const createComponent = propUpdates => {
+ const createComponent = (propUpdates) => {
wrapper = shallowMount(ToolbarButton, {
propsData: {
...defaultProps,
diff --git a/spec/frontend/vue_shared/components/navigation_tabs_spec.js b/spec/frontend/vue_shared/components/navigation_tabs_spec.js
index 561456d614e..b1119bfb150 100644
--- a/spec/frontend/vue_shared/components/navigation_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/navigation_tabs_spec.js
@@ -1,64 +1,68 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import navigationTabs from '~/vue_shared/components/navigation_tabs.vue';
+import { mount } from '@vue/test-utils';
+import { GlTab } from '@gitlab/ui';
+import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
describe('navigation tabs component', () => {
- let vm;
- let Component;
- let data;
+ let wrapper;
- beforeEach(() => {
- data = [
- {
- name: 'All',
- scope: 'all',
- count: 1,
- isActive: true,
- },
- {
- name: 'Pending',
- scope: 'pending',
- count: 0,
- isActive: false,
- },
- {
- name: 'Running',
- scope: 'running',
- isActive: false,
+ const data = [
+ {
+ name: 'All',
+ scope: 'all',
+ count: 1,
+ isActive: true,
+ },
+ {
+ name: 'Pending',
+ scope: 'pending',
+ count: 0,
+ isActive: false,
+ },
+ {
+ name: 'Running',
+ scope: 'running',
+ isActive: false,
+ },
+ ];
+
+ const createComponent = () => {
+ wrapper = mount(NavigationTabs, {
+ propsData: {
+ tabs: data,
+ scope: 'pipelines',
},
- ];
+ });
+ };
- Component = Vue.extend(navigationTabs);
- vm = mountComponent(Component, { tabs: data, scope: 'pipelines' });
+ beforeEach(() => {
+ createComponent();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
it('should render tabs', () => {
- expect(vm.$el.querySelectorAll('li').length).toEqual(data.length);
+ expect(wrapper.findAll(GlTab)).toHaveLength(data.length);
});
it('should render active tab', () => {
- expect(vm.$el.querySelector('.active .js-pipelines-tab-all')).toBeDefined();
+ expect(wrapper.find('.js-pipelines-tab-all').classes('active')).toBe(true);
});
it('should render badge', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-all .badge').textContent.trim()).toEqual('1');
- expect(vm.$el.querySelector('.js-pipelines-tab-pending .badge').textContent.trim()).toEqual(
- '0',
- );
+ expect(wrapper.find('.js-pipelines-tab-all').text()).toContain('1');
+ expect(wrapper.find('.js-pipelines-tab-pending').text()).toContain('0');
});
it('should not render badge', () => {
- expect(vm.$el.querySelector('.js-pipelines-tab-running .badge')).toEqual(null);
+ expect(wrapper.find('.js-pipelines-tab-running .badge').exists()).toBe(false);
});
- it('should trigger onTabClick', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.$el.querySelector('.js-pipelines-tab-pending').click();
+ it('should trigger onTabClick', async () => {
+ await wrapper.find('.js-pipelines-tab-pending').trigger('click');
- expect(vm.$emit).toHaveBeenCalledWith('onChangeTab', 'pending');
+ expect(wrapper.emitted('onChangeTab')).toEqual([['pending']]);
});
});
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 61660f79b71..cc9f05beb06 100644
--- a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
+++ b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
@@ -10,7 +10,7 @@ describe('Issue Warning Component', () => {
const findConfidentialBlock = (w = wrapper) => w.find({ ref: 'confidential' });
const findLockedAndConfidentialBlock = (w = wrapper) => w.find({ ref: 'lockedAndConfidential' });
- const createComponent = props =>
+ const createComponent = (props) =>
shallowMount(NoteableWarning, {
propsData: {
...props,
diff --git a/spec/frontend/vue_shared/components/ordered_layout_spec.js b/spec/frontend/vue_shared/components/ordered_layout_spec.js
index eec153c3792..21588569d6a 100644
--- a/spec/frontend/vue_shared/components/ordered_layout_spec.js
+++ b/spec/frontend/vue_shared/components/ordered_layout_spec.js
@@ -29,7 +29,7 @@ describe('Ordered Layout', () => {
const verifyOrder = () =>
wrapper
.findAll('footer,header')
- .wrappers.map(x => (x.element.tagName === 'FOOTER' ? 'footer' : 'header'));
+ .wrappers.map((x) => (x.element.tagName === 'FOOTER' ? 'footer' : 'header'));
const createComponent = (props = {}) => {
wrapper = mount(TestComponent, {
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 0f7c8e97635..491f783622a 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
@@ -124,7 +124,10 @@ describe('AlertManagementEmptyState', () => {
it('renders the tabs selection with valid tabs', () => {
mountComponent({
props: {
- statusTabs: [{ status: 'opened', title: 'Open' }, { status: 'closed', title: 'Closed' }],
+ statusTabs: [
+ { status: 'opened', title: 'Open' },
+ { status: 'closed', title: 'Closed' },
+ ],
},
});
@@ -216,12 +219,7 @@ describe('AlertManagementEmptyState', () => {
findPagination().vm.$emit('input', 3);
await wrapper.vm.$nextTick();
- expect(
- findPagination()
- .findAll('.page-item')
- .at(0)
- .text(),
- ).toBe('Prev');
+ expect(findPagination().findAll('.page-item').at(0).text()).toBe('Prev');
});
it('returns prevPage number', async () => {
@@ -244,12 +242,7 @@ describe('AlertManagementEmptyState', () => {
findPagination().vm.$emit('input', 3);
await wrapper.vm.$nextTick();
- expect(
- findPagination()
- .findAll('.page-item')
- .at(1)
- .text(),
- ).toBe('Next');
+ expect(findPagination().findAll('.page-item').at(1).text()).toBe('Next');
});
it('returns nextPage number', async () => {
diff --git a/spec/frontend/vue_shared/components/pagination_links_spec.js b/spec/frontend/vue_shared/components/pagination_links_spec.js
index bf004c83c4f..ad82aee0098 100644
--- a/spec/frontend/vue_shared/components/pagination_links_spec.js
+++ b/spec/frontend/vue_shared/components/pagination_links_spec.js
@@ -49,7 +49,7 @@ describe('Pagination links component', () => {
});
it('should provide translated text to GitLab UI pagination', () => {
- Object.entries(translations).forEach(entry => {
+ Object.entries(translations).forEach((entry) => {
expect(glPagination.vm[entry[0]]).toBe(entry[1]);
});
});
diff --git a/spec/frontend/vue_shared/components/pikaday_spec.js b/spec/frontend/vue_shared/components/pikaday_spec.js
index 639b4828a09..1c6876c282c 100644
--- a/spec/frontend/vue_shared/components/pikaday_spec.js
+++ b/spec/frontend/vue_shared/components/pikaday_spec.js
@@ -1,42 +1,41 @@
import { shallowMount } from '@vue/test-utils';
+import { GlDatepicker } from '@gitlab/ui';
import datePicker from '~/vue_shared/components/pikaday.vue';
describe('datePicker', () => {
let wrapper;
- beforeEach(() => {
+
+ const buildWrapper = (propsData = {}) => {
wrapper = shallowMount(datePicker, {
- propsData: {
- label: 'label',
- },
- attachToDocument: true,
+ propsData,
});
- });
+ };
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
+ it('should emit newDateSelected when GlDatePicker emits the input event', () => {
+ const minDate = new Date();
+ const maxDate = new Date();
+ const selectedDate = new Date();
+ const theDate = selectedDate.toISOString().slice(0, 10);
- it('should render label text', () => {
- expect(
- wrapper
- .find('.dropdown-toggle-text')
- .text()
- .trim(),
- ).toEqual('label');
- });
+ buildWrapper({ minDate, maxDate, selectedDate });
- it('should show calendar', () => {
- expect(wrapper.find('.pika-single').element).toBeDefined();
+ expect(wrapper.find(GlDatepicker).props()).toMatchObject({
+ minDate,
+ maxDate,
+ value: selectedDate,
+ });
+ wrapper.find(GlDatepicker).vm.$emit('input', selectedDate);
+ expect(wrapper.emitted('newDateSelected')[0][0]).toBe(theDate);
});
+ it('should emit the hidePicker event when GlDatePicker emits the close event', () => {
+ buildWrapper();
- it('should emit hidePicker event when dropdown is clicked', () => {
- // Removing the bootstrap data-toggle property,
- // because it interfers with our click event
- delete wrapper.find('.dropdown-menu-toggle').element.dataset.toggle;
-
- wrapper.find('.dropdown-menu-toggle').trigger('click');
+ wrapper.find(GlDatepicker).vm.$emit('close');
- expect(wrapper.emitted('hidePicker')).toEqual([[]]);
+ expect(wrapper.emitted('hidePicker')).toHaveLength(1);
});
});
diff --git a/spec/frontend/vue_shared/components/project_avatar/default_spec.js b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
index 090f8b69213..0daadeebc20 100644
--- a/spec/frontend/vue_shared/components/project_avatar/default_spec.js
+++ b/spec/frontend/vue_shared/components/project_avatar/default_spec.js
@@ -19,7 +19,7 @@ describe('ProjectAvatarDefault component', () => {
vm.$destroy();
});
- it('renders identicon if project has no avatar_url', done => {
+ it('renders identicon if project has no avatar_url', (done) => {
const expectedText = getFirstCharacterCapitalized(projectData.name);
vm.project = {
@@ -38,7 +38,7 @@ describe('ProjectAvatarDefault component', () => {
.catch(done.fail);
});
- it('renders avatar image if project has avatar_url', done => {
+ it('renders avatar image if project has avatar_url', (done) => {
const avatarUrl = `${TEST_HOST}/images/home/nasa.svg`;
vm.project = {
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 6d1ebe85aa0..016622fd0bb 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
@@ -18,6 +18,13 @@ describe('ProjectSelector component', () => {
selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));
const findSearchInput = () => wrapper.find(GlSearchBoxByType).find('input');
+ const findLegendText = () => wrapper.find('[data-testid="legend-text"]').text();
+ const search = (query) => {
+ const searchInput = findSearchInput();
+
+ searchInput.setValue(query);
+ searchInput.trigger('input');
+ };
beforeEach(() => {
wrapper = mount(Vue.extend(ProjectSelector), {
@@ -31,7 +38,7 @@ describe('ProjectSelector component', () => {
showSearchErrorMessage: false,
totalResults: searchResults.length,
},
- attachToDocument: true,
+ attachTo: document.body,
});
({ vm } = wrapper);
@@ -48,10 +55,7 @@ describe('ProjectSelector component', () => {
it(`triggers a search when the search input value changes`, () => {
jest.spyOn(vm, '$emit').mockImplementation(() => {});
const query = 'my test query!';
- const searchInput = findSearchInput();
-
- searchInput.setValue(query);
- searchInput.trigger('input');
+ search(query);
expect(vm.$emit).toHaveBeenCalledWith('searched', query);
});
@@ -121,15 +125,21 @@ describe('ProjectSelector component', () => {
`(
'is "$expected" given $count results are showing out of $total',
({ count, total, expected }) => {
+ search('gitlab ui');
+
wrapper.setProps({
projectSearchResults: searchResults.slice(0, count),
totalResults: total,
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.text()).toContain(expected);
+ expect(findLegendText()).toBe(expected);
});
},
);
+
+ it('is not rendered without searching', () => {
+ expect(findLegendText()).toBe('');
+ });
});
});
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 16a55b84787..09dacfae363 100644
--- a/spec/frontend/vue_shared/components/registry/details_row_spec.js
+++ b/spec/frontend/vue_shared/components/registry/details_row_spec.js
@@ -8,7 +8,7 @@ describe('DetailsRow', () => {
const findIcon = () => wrapper.find(GlIcon);
const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(component, {
propsData: {
icon: 'clock',
diff --git a/spec/frontend/vue_shared/components/registry/list_item_spec.js b/spec/frontend/vue_shared/components/registry/list_item_spec.js
index 2a48bf4f2d6..33c9c808dc3 100644
--- a/spec/frontend/vue_shared/components/registry/list_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/list_item_spec.js
@@ -11,7 +11,7 @@ describe('list item', () => {
const findRightPrimarySlot = () => wrapper.find('[data-testid="right-primary"]');
const findRightSecondarySlot = () => wrapper.find('[data-testid="right-secondary"]');
const findRightActionSlot = () => wrapper.find('[data-testid="right-action"]');
- const findDetailsSlot = name => wrapper.find(`[data-testid="${name}"]`);
+ const findDetailsSlot = (name) => wrapper.find(`[data-testid="${name}"]`);
const findToggleDetailsButton = () => wrapper.find(GlButton);
const mountComponent = (propsData, slots) => {
@@ -74,14 +74,14 @@ describe('list item', () => {
findToggleDetailsButton().vm.$emit('click');
await wrapper.vm.$nextTick();
- slotNames.forEach(name => {
+ slotNames.forEach((name) => {
expect(findDetailsSlot(name).exists()).toBe(true);
});
});
it('are not visible when details are not shown', () => {
mountComponent({}, slotMocks);
- slotNames.forEach(name => {
+ slotNames.forEach((name) => {
expect(findDetailsSlot(name).exists()).toBe(false);
});
});
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 ff968ff1831..3d3cfbe13e3 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,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlLink } from '@gitlab/ui';
+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';
@@ -12,6 +13,9 @@ describe('Metadata Item', () => {
const mountComponent = (propsData = defaultProps) => {
wrapper = shallowMount(component, {
propsData,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
});
};
@@ -24,8 +28,9 @@ describe('Metadata Item', () => {
const findLink = (w = wrapper) => w.find(GlLink);
const findText = () => wrapper.find('[data-testid="metadata-item-text"]');
const findTooltipOnTruncate = (w = wrapper) => w.find(TooltipOnTruncate);
+ const findTextTooltip = () => wrapper.find('[data-testid="text-tooltip-container"]');
- describe.each(['xs', 's', 'm', 'l', 'xl'])('size class', size => {
+ describe.each(['xs', 's', 'm', 'l', 'xl'])('size class', (size) => {
const className = `mw-${size}`;
it(`${size} is assigned correctly to text`, () => {
@@ -55,6 +60,22 @@ describe('Metadata Item', () => {
expect(tooltip.exists()).toBe(true);
expect(tooltip.attributes('title')).toBe(defaultProps.text);
});
+
+ describe('with tooltip prop set to something', () => {
+ const textTooltip = 'foo';
+ it('hides tooltip_on_truncate', () => {
+ mountComponent({ ...defaultProps, textTooltip });
+
+ expect(findTooltipOnTruncate(findText()).exists()).toBe(false);
+ });
+
+ it('set the tooltip on the text', () => {
+ mountComponent({ ...defaultProps, textTooltip });
+
+ const tooltip = getBinding(findTextTooltip().element, 'gl-tooltip');
+ expect(tooltip.value.title).toBe(textTooltip);
+ });
+ });
});
describe('link', () => {
diff --git a/spec/frontend/vue_shared/components/registry/title_area_spec.js b/spec/frontend/vue_shared/components/registry/title_area_spec.js
index b743a663f06..fb0009ebb8d 100644
--- a/spec/frontend/vue_shared/components/registry/title_area_spec.js
+++ b/spec/frontend/vue_shared/components/registry/title_area_spec.js
@@ -1,4 +1,4 @@
-import { GlAvatar, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlAvatar, GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import component from '~/vue_shared/components/registry/title_area.vue';
@@ -9,12 +9,13 @@ describe('title area', () => {
const findSubHeaderSlot = () => wrapper.find('[data-testid="sub-header"]');
const findRightActionsSlot = () => wrapper.find('[data-testid="right-actions"]');
- const findMetadataSlot = name => wrapper.find(`[data-testid="${name}"]`);
+ const findMetadataSlot = (name) => wrapper.find(`[data-testid="${name}"]`);
const findTitle = () => wrapper.find('[data-testid="title"]');
const findAvatar = () => wrapper.find(GlAvatar);
const findInfoMessages = () => wrapper.findAll('[data-testid="info-message"]');
const findDynamicSlot = () => wrapper.find(`[data-testid="${DYNAMIC_SLOT}`);
const findSlotOrderElements = () => wrapper.findAll('[slot-test]');
+ const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
const mountComponent = ({ propsData = { title: 'foo' }, slots } = {}) => {
wrapper = shallowMount(component, {
@@ -96,10 +97,33 @@ describe('title area', () => {
mountComponent({ slots: slotMocks });
await wrapper.vm.$nextTick();
- slotNames.forEach(name => {
+ slotNames.forEach((name) => {
expect(findMetadataSlot(name).exists()).toBe(true);
});
});
+
+ it('is/are hidden when metadata-loading is true', async () => {
+ mountComponent({ slots: slotMocks, propsData: { title: 'foo', metadataLoading: true } });
+
+ await wrapper.vm.$nextTick();
+ slotNames.forEach((name) => {
+ expect(findMetadataSlot(name).exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('metadata skeleton loader', () => {
+ it('is hidden when metadata loading is false', () => {
+ mountComponent();
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ });
+
+ it('is shown when metadata loading is true', () => {
+ mountComponent({ propsData: { metadataLoading: true } });
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ });
});
describe('dynamic slots', () => {
@@ -142,16 +166,8 @@ describe('title area', () => {
await wrapper.vm.$nextTick();
- expect(
- findSlotOrderElements()
- .at(0)
- .attributes('data-testid'),
- ).toBe(DYNAMIC_SLOT);
- expect(
- findSlotOrderElements()
- .at(1)
- .attributes('data-testid'),
- ).toBe('metadata-foo');
+ expect(findSlotOrderElements().at(0).attributes('data-testid')).toBe(DYNAMIC_SLOT);
+ expect(findSlotOrderElements().at(1).attributes('data-testid')).toBe('metadata-foo');
});
});
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 d79df4d0557..51619cd9578 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
@@ -20,7 +20,7 @@ describe('Editor Service', () => {
let mockInstance;
let event;
let handler;
- const parseHtml = str => {
+ const parseHtml = (str) => {
const wrapper = document.createElement('div');
wrapper.innerHTML = str;
return wrapper.firstChild;
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js
index ded490b2568..81fd059ce4f 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js
@@ -10,7 +10,7 @@ describe('Upload Image Tab', () => {
afterEach(() => wrapper.destroy());
- const triggerInputEvent = size => {
+ const triggerInputEvent = (size) => {
const file = { size, name: 'file-name.png' };
const mockEvent = new Event('input');
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 be3a4030b1d..d59d4cc1de9 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
@@ -8,7 +8,7 @@ describe('Insert Video Modal', () => {
const findModal = () => wrapper.find(GlModal);
const findUrlInput = () => wrapper.find({ ref: 'urlInput' });
- const triggerInsertVideo = url => {
+ const triggerInsertVideo = (url) => {
const preventDefault = jest.fn();
findUrlInput().vm.$emit('input', url);
findModal().vm.$emit('primary', { preventDefault });
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 cd1157a1c2e..2eb353a1801 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,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { mockEditorApi } from '@toast-ui/vue-editor';
+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';
@@ -17,16 +17,17 @@ import {
insertVideo,
registerHTMLToMarkdownRenderer,
getEditorOptions,
+ getMarkdown,
} from '~/vue_shared/components/rich_content_editor/services/editor_service';
jest.mock('~/vue_shared/components/rich_content_editor/services/editor_service', () => ({
- ...jest.requireActual('~/vue_shared/components/rich_content_editor/services/editor_service'),
addCustomEventListener: jest.fn(),
removeCustomEventListener: jest.fn(),
addImage: jest.fn(),
insertVideo: jest.fn(),
registerHTMLToMarkdownRenderer: jest.fn(),
getEditorOptions: jest.fn(),
+ getMarkdown: jest.fn(),
}));
describe('Rich Content Editor', () => {
@@ -38,9 +39,12 @@ describe('Rich Content Editor', () => {
const findAddImageModal = () => wrapper.find(AddImageModal);
const findInsertVideoModal = () => wrapper.find(InsertVideoModal);
- const buildWrapper = () => {
+ const buildWrapper = async () => {
wrapper = shallowMount(RichContentEditor, {
propsData: { content, imageRoot },
+ stubs: {
+ ToastEditor: Editor,
+ },
});
};
@@ -89,9 +93,8 @@ describe('Rich Content Editor', () => {
it('emits an input event with the changed content', () => {
const changedMarkdown = '## Changed Markdown';
- const getMarkdownMock = jest.fn().mockReturnValueOnce(changedMarkdown);
+ getMarkdown.mockReturnValueOnce(changedMarkdown);
- findEditor().setMethods({ invoke: getMarkdownMock });
findEditor().vm.$emit('change');
expect(wrapper.emitted().input[0][0]).toBe(changedMarkdown);
@@ -147,6 +150,7 @@ describe('Rich Content Editor', () => {
});
it('emits load event with the markdown formatted by Toast UI', () => {
+ mockEditorApi.getMarkdown.mockReturnValueOnce(formattedMarkdown);
expect(mockEditorApi.getMarkdown).toHaveBeenCalled();
expect(wrapper.emitted('load')[0]).toEqual([{ formattedMarkdown }]);
});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
index 85516eae4cf..3caf03dabba 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
@@ -8,9 +8,9 @@ describe('rich_content_editor/services/html_to_markdown_renderer', () => {
beforeEach(() => {
baseRenderer = {
- trim: jest.fn(input => `trimmed ${input}`),
- getSpaceCollapsedText: jest.fn(input => `space collapsed ${input}`),
- getSpaceControlled: jest.fn(input => `space controlled ${input}`),
+ trim: jest.fn((input) => `trimmed ${input}`),
+ getSpaceCollapsedText: jest.fn((input) => `space collapsed ${input}`),
+ getSpaceControlled: jest.fn((input) => `space controlled ${input}`),
convert: jest.fn(),
};
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js
index 5cf3961819e..407072fb596 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js
@@ -1,12 +1,12 @@
// Node spec helpers
-export const buildMockTextNode = literal => ({ literal, type: 'text' });
+export const buildMockTextNode = (literal) => ({ literal, type: 'text' });
export const normalTextNode = buildMockTextNode('This is just normal text.');
// Token spec helpers
-const buildMockUneditableOpenToken = type => {
+const buildMockUneditableOpenToken = (type) => {
return {
type: 'openTag',
tagName: type,
@@ -17,7 +17,7 @@ const buildMockUneditableOpenToken = type => {
};
};
-const buildMockTextToken = content => {
+const buildMockTextToken = (content) => {
return {
type: 'text',
tagName: null,
@@ -25,7 +25,7 @@ const buildMockTextToken = content => {
};
};
-const buildMockUneditableCloseToken = type => ({ type: 'closeTag', tagName: type });
+const buildMockUneditableCloseToken = (type) => ({ type: 'closeTag', tagName: type });
export const originToken = buildMockTextToken('{:.no_toc .hidden-md .hidden-lg}');
const uneditableOpenToken = buildMockUneditableOpenToken('div');
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 2897929f1bf..521885f5687 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
@@ -36,7 +36,7 @@ describe('Render Identifier Instance Text renderer', () => {
`(
'should return inline editable, uneditable, and editable tokens in sequence',
({ start, middle, end }) => {
- const buildMockTextToken = content => ({ type: 'text', tagName: null, content });
+ const buildMockTextToken = (content) => ({ type: 'text', tagName: null, content });
const startToken = buildMockTextToken(start);
const middleToken = buildMockTextToken(middle);
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
index b3d9576f38b..470cf9bddaa 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
@@ -2,7 +2,7 @@ import renderer from '~/vue_shared/components/rich_content_editor/services/rende
import { buildMockTextNode } from './mock_data';
-const buildMockParagraphNode = literal => {
+const buildMockParagraphNode = (literal) => {
return {
firstChild: buildMockTextNode(literal),
type: 'paragraph',
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 2db15a71215..0e6f951bd53 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
@@ -9,7 +9,7 @@ describe('Toolbar Item', () => {
const findIcon = () => wrapper.find(GlIcon);
const findButton = () => wrapper.find('button');
- const buildWrapper = propsData => {
+ const buildWrapper = (propsData) => {
wrapper = shallowMount(ToolbarItem, {
propsData,
directives: {
diff --git a/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js b/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js
index 60203493cbd..ae86106d86e 100644
--- a/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js
+++ b/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js
@@ -8,7 +8,7 @@ const discoverProjectSecurityPath = '/discoverProjectSecurityPath';
describe('HelpIcon component', () => {
let wrapper;
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = shallowMount(HelpIcon, {
propsData: {
helpPath,
diff --git a/spec/frontend/vue_shared/components/security_reports/security_summary_spec.js b/spec/frontend/vue_shared/components/security_reports/security_summary_spec.js
index e57152c3cbf..f186eb848f2 100644
--- a/spec/frontend/vue_shared/components/security_reports/security_summary_spec.js
+++ b/spec/frontend/vue_shared/components/security_reports/security_summary_spec.js
@@ -6,7 +6,7 @@ import { groupedTextBuilder } from '~/vue_shared/security_reports/store/utils';
describe('SecuritySummary component', () => {
let wrapper;
- const createWrapper = message => {
+ const createWrapper = (message) => {
wrapper = shallowMount(SecuritySummary, {
propsData: { message },
stubs: {
@@ -26,7 +26,7 @@ describe('SecuritySummary component', () => {
groupedTextBuilder({ reportType: 'Security scanning', critical: 1, high: 0, total: 1 }),
groupedTextBuilder({ reportType: 'Security scanning', critical: 0, high: 1, total: 1 }),
groupedTextBuilder({ reportType: 'Security scanning', critical: 1, high: 2, total: 3 }),
- ])('given the message %p', message => {
+ ])('given the message %p', (message) => {
beforeEach(() => {
createWrapper(message);
});
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
index 08fc822577e..230442ec547 100644
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
@@ -12,7 +12,7 @@ describe('collapsedGroupedDatePicker', () => {
});
describe('toggleCollapse events', () => {
- beforeEach(done => {
+ beforeEach((done) => {
jest.spyOn(vm, 'toggleSidebar').mockImplementation(() => {});
vm.minDate = new Date('07/17/2016');
Vue.nextTick(done);
@@ -26,7 +26,7 @@ describe('collapsedGroupedDatePicker', () => {
});
describe('minDate and maxDate', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.minDate = new Date('07/17/2016');
vm.maxDate = new Date('07/17/2017');
Vue.nextTick(done);
@@ -42,7 +42,7 @@ describe('collapsedGroupedDatePicker', () => {
});
describe('minDate', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.minDate = new Date('07/17/2016');
Vue.nextTick(done);
});
@@ -56,7 +56,7 @@ describe('collapsedGroupedDatePicker', () => {
});
describe('maxDate', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.maxDate = new Date('07/17/2017');
Vue.nextTick(done);
});
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 47edfbe3115..fc1fa3fc1c1 100644
--- a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
@@ -46,12 +46,7 @@ describe('SidebarDatePicker', () => {
it('should render None if there is no selectedDate', () => {
mountComponent();
- expect(
- wrapper
- .find('.value-content span')
- .text()
- .trim(),
- ).toEqual('None');
+ expect(wrapper.find('.value-content span').text().trim()).toEqual('None');
});
it('should render date-picker when editing', () => {
@@ -63,12 +58,7 @@ describe('SidebarDatePicker', () => {
it('should render label', () => {
const label = 'label';
mountComponent({ label });
- expect(
- wrapper
- .find('.title')
- .text()
- .trim(),
- ).toEqual(label);
+ expect(wrapper.find('.title').text().trim()).toEqual(label);
});
it('should render loading-icon when isLoading', () => {
@@ -82,12 +72,7 @@ describe('SidebarDatePicker', () => {
});
it('should render edit button', () => {
- expect(
- wrapper
- .find('.title .btn-blank')
- .text()
- .trim(),
- ).toEqual('Edit');
+ expect(wrapper.find('.title .btn-blank').text().trim()).toEqual('Edit');
});
it('should enable editing when edit button is clicked', async () => {
@@ -102,12 +87,7 @@ describe('SidebarDatePicker', () => {
it('should render date if selectedDate', () => {
mountComponent({ selectedDate: new Date('07/07/2017') });
- expect(
- wrapper
- .find('.value-content strong')
- .text()
- .trim(),
- ).toEqual('Jul 7, 2017');
+ expect(wrapper.find('.value-content strong').text().trim()).toEqual('Jul 7, 2017');
});
describe('selectedDate and editable', () => {
@@ -116,12 +96,7 @@ describe('SidebarDatePicker', () => {
});
it('should render remove button if selectedDate and editable', () => {
- expect(
- wrapper
- .find('.value-content .btn-blank')
- .text()
- .trim(),
- ).toEqual('remove');
+ expect(wrapper.find('.value-content .btn-blank').text().trim()).toEqual('remove');
});
it('should emit saveDate with null when remove button is clicked', () => {
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 a97e26caf53..256b3cff525 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
@@ -184,11 +184,7 @@ describe('IssuableMoveDropdown', () => {
});
it('renders gl-dropdown-form component', () => {
- expect(
- findDropdownEl()
- .find(GlDropdownForm)
- .exists(),
- ).toBe(true);
+ expect(findDropdownEl().find(GlDropdownForm).exists()).toBe(true);
});
it('renders header element', () => {
@@ -216,11 +212,7 @@ describe('IssuableMoveDropdown', () => {
await wrapper.vm.$nextTick();
- expect(
- findDropdownEl()
- .find(GlLoadingIcon)
- .exists(),
- ).toBe(true);
+ expect(findDropdownEl().find(GlLoadingIcon).exists()).toBe(true);
});
it('renders gl-dropdown-item components for available projects', async () => {
@@ -288,10 +280,7 @@ describe('IssuableMoveDropdown', () => {
await wrapper.vm.$nextTick();
expect(
- wrapper
- .find('[data-testid="footer"]')
- .find(GlButton)
- .attributes('disabled'),
+ wrapper.find('[data-testid="footer"]').find(GlButton).attributes('disabled'),
).not.toBeDefined();
});
});
@@ -331,10 +320,7 @@ describe('IssuableMoveDropdown', () => {
});
it('close icon in dropdown header closes the dropdown when clicked', () => {
- wrapper
- .find('[data-testid="header"]')
- .find(GlButton)
- .vm.$emit('click', mockEvent);
+ wrapper.find('[data-testid="header"]').find(GlButton).vm.$emit('click', mockEvent);
expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalled();
});
@@ -346,10 +332,7 @@ describe('IssuableMoveDropdown', () => {
await wrapper.vm.$nextTick();
- wrapper
- .findAll(GlDropdownItem)
- .at(0)
- .vm.$emit('click', mockEvent);
+ wrapper.findAll(GlDropdownItem).at(0).vm.$emit('click', mockEvent);
expect(wrapper.vm.selectedProject).toBe(mockProjects[0]);
});
@@ -361,10 +344,7 @@ describe('IssuableMoveDropdown', () => {
await wrapper.vm.$nextTick();
- wrapper
- .find('[data-testid="footer"]')
- .find(GlButton)
- .vm.$emit('click');
+ wrapper.find('[data-testid="footer"]').find(GlButton).vm.$emit('click');
expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalled();
expect(wrapper.emitted('move-issuable')).toBeTruthy();
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 596cb22fca5..a55ad37c498 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
@@ -15,7 +15,7 @@ describe('BaseComponent', () => {
let wrapper;
let vm;
- beforeEach(done => {
+ beforeEach((done) => {
wrapper = createComponent();
({ vm } = wrapper);
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 c2091a681f2..4b4d265800b 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
@@ -5,7 +5,7 @@ import dropdownCreateLabelComponent from '~/vue_shared/components/sidebar/labels
import { mockSuggestedColors } from './mock_data';
-const createComponent = headerTitle => {
+const createComponent = (headerTitle) => {
const Component = Vue.extend(dropdownCreateLabelComponent);
return mountComponent(Component, {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
index 71c040c6633..003f3d2b4e6 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
@@ -37,7 +37,7 @@ describe('DropdownValueCollapsedComponent', () => {
const labels = mockLabels.concat(mockLabels);
const vmMoreLabels = createComponent(labels);
- const expectedText = labels.map(label => label.title).join(', ');
+ const expectedText = labels.map((label) => label.title).join(', ');
expect(vmMoreLabels.labelsList).toBe(expectedText);
vmMoreLabels.$destroy();
@@ -53,7 +53,7 @@ describe('DropdownValueCollapsedComponent', () => {
const expectedText = `${mockMoreLabels
.slice(0, 5)
- .map(label => label.title)
+ .map((label) => label.title)
.join(', ')}, and ${mockMoreLabels.length - 5} more`;
expect(vmMoreLabels.labelsList).toBe(expectedText);
@@ -61,7 +61,7 @@ describe('DropdownValueCollapsedComponent', () => {
});
it('returns first label name when `labels` prop has only one item present', () => {
- const text = mockLabels.map(label => label.title).join(', ');
+ const text = mockLabels.map((label) => label.title).join(', ');
expect(vm.labelsList).toBe(text);
});
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 53e8a0e1278..ecb3c3a42c8 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
@@ -71,12 +71,7 @@ describe('DropdownValueComponent', () => {
it('render slot content inside component when `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
- expect(
- vmEmptyLabels
- .find('.text-secondary')
- .text()
- .trim(),
- ).toBe(mockConfig.emptyValueText);
+ expect(vmEmptyLabels.find('.text-secondary').text().trim()).toBe(mockConfig.emptyValueText);
vmEmptyLabels.destroy();
});
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 04320a72be6..0f49fe4fc5b 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
@@ -24,7 +24,7 @@ const createComponent = (initialState = mockConfig) => {
describe('DropdownContentsCreateView', () => {
let wrapper;
- const colors = Object.keys(mockSuggestedColors).map(color => ({
+ const colors = Object.keys(mockSuggestedColors).map((color) => ({
[color]: mockSuggestedColors[color],
}));
@@ -125,10 +125,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders dropdown back button element', () => {
- const backBtnEl = wrapper
- .find('.dropdown-title')
- .findAll(GlButton)
- .at(0);
+ const backBtnEl = wrapper.find('.dropdown-title').findAll(GlButton).at(0);
expect(backBtnEl.exists()).toBe(true);
expect(backBtnEl.attributes('aria-label')).toBe('Go back');
@@ -143,10 +140,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders dropdown close button element', () => {
- const closeBtnEl = wrapper
- .find('.dropdown-title')
- .findAll(GlButton)
- .at(1);
+ const closeBtnEl = wrapper.find('.dropdown-title').findAll(GlButton).at(1);
expect(closeBtnEl.exists()).toBe(true);
expect(closeBtnEl.attributes('aria-label')).toBe('Close');
@@ -190,10 +184,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders create button element', () => {
- const createBtnEl = wrapper
- .find('.dropdown-actions')
- .findAll(GlButton)
- .at(0);
+ const createBtnEl = wrapper.find('.dropdown-actions').findAll(GlButton).at(0);
expect(createBtnEl.exists()).toBe(true);
expect(createBtnEl.text()).toContain('Create');
@@ -211,10 +202,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders cancel button element', () => {
- const cancelBtnEl = wrapper
- .find('.dropdown-actions')
- .findAll(GlButton)
- .at(1);
+ const cancelBtnEl = wrapper.find('.dropdown-actions').findAll(GlButton).at(1);
expect(cancelBtnEl.exists()).toBe(true);
expect(cancelBtnEl.text()).toContain('Cancel');
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 78367b3a5b4..989cd256e26 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
@@ -371,9 +371,7 @@ describe('DropdownContentsLabelsView', () => {
wrapper.vm.$store.state.allowLabelCreate = false;
return wrapper.vm.$nextTick(() => {
- const createLabelLink = findDropdownFooter()
- .findAll(GlLink)
- .at(0);
+ const createLabelLink = findDropdownFooter().findAll(GlLink).at(0);
expect(createLabelLink.text()).not.toBe('Create label');
});
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 c742220ba8a..4909c43bc96 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
@@ -19,7 +19,7 @@ describe('LabelsSelect Actions', () => {
});
describe('setInitialState', () => {
- it('sets initial store state', done => {
+ it('sets initial store state', (done) => {
testAction(
actions.setInitialState,
mockInitialState,
@@ -32,7 +32,7 @@ describe('LabelsSelect Actions', () => {
});
describe('toggleDropdownButton', () => {
- it('toggles dropdown button', done => {
+ it('toggles dropdown button', (done) => {
testAction(
actions.toggleDropdownButton,
{},
@@ -45,7 +45,7 @@ describe('LabelsSelect Actions', () => {
});
describe('toggleDropdownContents', () => {
- it('toggles dropdown contents', done => {
+ it('toggles dropdown contents', (done) => {
testAction(
actions.toggleDropdownContents,
{},
@@ -58,7 +58,7 @@ describe('LabelsSelect Actions', () => {
});
describe('toggleDropdownContentsCreateView', () => {
- it('toggles dropdown create view', done => {
+ it('toggles dropdown create view', (done) => {
testAction(
actions.toggleDropdownContentsCreateView,
{},
@@ -71,13 +71,13 @@ describe('LabelsSelect Actions', () => {
});
describe('requestLabels', () => {
- it('sets value of `state.labelsFetchInProgress` to `true`', done => {
+ it('sets value of `state.labelsFetchInProgress` to `true`', (done) => {
testAction(actions.requestLabels, {}, state, [{ type: types.REQUEST_LABELS }], [], done);
});
});
describe('receiveLabelsSuccess', () => {
- it('sets provided labels to `state.labels`', done => {
+ it('sets provided labels to `state.labels`', (done) => {
const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
testAction(
@@ -96,7 +96,7 @@ describe('LabelsSelect Actions', () => {
setFixtures('<div class="flash-container"></div>');
});
- it('sets value `state.labelsFetchInProgress` to `false`', done => {
+ it('sets value `state.labelsFetchInProgress` to `false`', (done) => {
testAction(
actions.receiveLabelsFailure,
{},
@@ -129,7 +129,7 @@ describe('LabelsSelect Actions', () => {
});
describe('on success', () => {
- it('dispatches `requestLabels` & `receiveLabelsSuccess` actions', done => {
+ it('dispatches `requestLabels` & `receiveLabelsSuccess` actions', (done) => {
const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
mock.onGet(/labels.json/).replyOnce(200, labels);
@@ -145,7 +145,7 @@ describe('LabelsSelect Actions', () => {
});
describe('on failure', () => {
- it('dispatches `requestLabels` & `receiveLabelsFailure` actions', done => {
+ it('dispatches `requestLabels` & `receiveLabelsFailure` actions', (done) => {
mock.onGet(/labels.json/).replyOnce(500, {});
testAction(
@@ -161,7 +161,7 @@ describe('LabelsSelect Actions', () => {
});
describe('requestCreateLabel', () => {
- it('sets value `state.labelCreateInProgress` to `true`', done => {
+ it('sets value `state.labelCreateInProgress` to `true`', (done) => {
testAction(
actions.requestCreateLabel,
{},
@@ -174,7 +174,7 @@ describe('LabelsSelect Actions', () => {
});
describe('receiveCreateLabelSuccess', () => {
- it('sets value `state.labelCreateInProgress` to `false`', done => {
+ it('sets value `state.labelCreateInProgress` to `false`', (done) => {
testAction(
actions.receiveCreateLabelSuccess,
{},
@@ -191,7 +191,7 @@ describe('LabelsSelect Actions', () => {
setFixtures('<div class="flash-container"></div>');
});
- it('sets value `state.labelCreateInProgress` to `false`', done => {
+ it('sets value `state.labelCreateInProgress` to `false`', (done) => {
testAction(
actions.receiveCreateLabelFailure,
{},
@@ -224,7 +224,7 @@ describe('LabelsSelect Actions', () => {
});
describe('on success', () => {
- it('dispatches `requestCreateLabel`, `receiveCreateLabelSuccess` & `toggleDropdownContentsCreateView` actions', done => {
+ it('dispatches `requestCreateLabel`, `receiveCreateLabelSuccess` & `toggleDropdownContentsCreateView` actions', (done) => {
const label = { id: 1 };
mock.onPost(/labels.json/).replyOnce(200, label);
@@ -244,7 +244,7 @@ describe('LabelsSelect Actions', () => {
});
describe('on failure', () => {
- it('dispatches `requestCreateLabel` & `receiveCreateLabelFailure` actions', done => {
+ it('dispatches `requestCreateLabel` & `receiveCreateLabelFailure` actions', (done) => {
mock.onPost(/labels.json/).replyOnce(500, {});
testAction(
@@ -260,7 +260,7 @@ describe('LabelsSelect Actions', () => {
});
describe('updateSelectedLabels', () => {
- it('updates `state.labels` based on provided `labels` param', done => {
+ it('updates `state.labels` based on provided `labels` param', (done) => {
const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
testAction(
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/getters_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/getters_spec.js
index 52116f757c5..1f899e84897 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/getters_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/getters_spec.js
@@ -26,7 +26,10 @@ describe('LabelsSelect Getters', () => {
});
it('returns first label title and remaining labels count when state.labels has more than 1 label', () => {
- const labels = [{ id: 1, title: 'Foo', set: true }, { id: 2, title: 'Bar', set: true }];
+ const labels = [
+ { id: 1, title: 'Foo', set: true },
+ { id: 2, title: 'Bar', set: true },
+ ];
expect(getters.dropdownButtonText({ labels }, { isDropdownVariantSidebar: true })).toBe(
'Foo +1 more',
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 8081806e314..208f2f2d42d 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
@@ -93,14 +93,14 @@ describe('LabelsSelect Mutations', () => {
});
it('sets provided `labels` to `state.labels` along with `set` prop based on `state.selectedLabels`', () => {
- const selectedLabelIds = selectedLabels.map(label => label.id);
+ const selectedLabelIds = selectedLabels.map((label) => label.id);
const state = {
selectedLabels,
labelsFetchInProgress: true,
};
mutations[types.RECEIVE_SET_LABELS_SUCCESS](state, labels);
- state.labels.forEach(label => {
+ state.labels.forEach((label) => {
if (selectedLabelIds.includes(label.id)) {
expect(label.set).toBe(true);
}
@@ -162,7 +162,7 @@ describe('LabelsSelect Mutations', () => {
};
mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: 2 }] });
- state.labels.forEach(label => {
+ state.labels.forEach((label) => {
if (updatedLabelIds.includes(label.id)) {
expect(label.touched).toBe(true);
expect(label.set).toBe(true);
diff --git a/spec/frontend/vue_shared/components/slot_switch_spec.js b/spec/frontend/vue_shared/components/slot_switch_spec.js
index 73307b5573f..f25b9877aba 100644
--- a/spec/frontend/vue_shared/components/slot_switch_spec.js
+++ b/spec/frontend/vue_shared/components/slot_switch_spec.js
@@ -10,14 +10,14 @@ describe('SlotSwitch', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(SlotSwitch, {
propsData,
slots,
});
};
- const getChildrenHtml = () => wrapper.findAll('* *').wrappers.map(c => c.html());
+ const getChildrenHtml = () => wrapper.findAll('* *').wrappers.map((c) => c.html());
afterEach(() => {
if (wrapper) {
diff --git a/spec/frontend/vue_shared/components/split_button_spec.js b/spec/frontend/vue_shared/components/split_button_spec.js
index e09bc073042..ad11e6519c4 100644
--- a/spec/frontend/vue_shared/components/split_button_spec.js
+++ b/spec/frontend/vue_shared/components/split_button_spec.js
@@ -19,18 +19,15 @@ const mockActionItems = [
describe('SplitButton', () => {
let wrapper;
- const createComponent = propsData => {
+ const createComponent = (propsData) => {
wrapper = shallowMount(SplitButton, {
propsData,
});
};
const findDropdown = () => wrapper.find(GlDropdown);
- const findDropdownItem = (index = 0) =>
- findDropdown()
- .findAll(GlDropdownItem)
- .at(index);
- const selectItem = index => {
+ const findDropdownItem = (index = 0) => findDropdown().findAll(GlDropdownItem).at(index);
+ const selectItem = (index) => {
findDropdownItem(index).vm.$emit('click');
return wrapper.vm.$nextTick();
@@ -87,7 +84,7 @@ describe('SplitButton', () => {
const addChangeEventHandler = () => {
changeEventHandler = jest.fn();
- wrapper.vm.$once('change', item => changeEventHandler(item));
+ wrapper.vm.$once('change', (item) => changeEventHandler(item));
};
it('defaults to first actionItems event', () => {
diff --git a/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js b/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
index 0786882f527..c6f01efa71a 100644
--- a/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
+++ b/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
@@ -3,7 +3,7 @@ import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import stackedProgressBarComponent from '~/vue_shared/components/stacked_progress_bar.vue';
-const createComponent = config => {
+const createComponent = (config) => {
const Component = Vue.extend(stackedProgressBarComponent);
const defaultConfig = {
successLabel: 'Synced',
@@ -29,11 +29,12 @@ describe('StackedProgressBarComponent', () => {
vm.$destroy();
});
- const findSuccessBarText = wrapper => wrapper.$el.querySelector('.status-green').innerText.trim();
- const findNeutralBarText = wrapper =>
+ const findSuccessBarText = (wrapper) =>
+ wrapper.$el.querySelector('.status-green').innerText.trim();
+ const findNeutralBarText = (wrapper) =>
wrapper.$el.querySelector('.status-neutral').innerText.trim();
- const findFailureBarText = wrapper => wrapper.$el.querySelector('.status-red').innerText.trim();
- const findUnavailableBarText = wrapper =>
+ const findFailureBarText = (wrapper) => wrapper.$el.querySelector('.status-red').innerText.trim();
+ const findUnavailableBarText = (wrapper) =>
wrapper.$el.querySelector('.status-unavailable').innerText.trim();
describe('computed', () => {
diff --git a/spec/frontend/vue_shared/components/table_pagination_spec.js b/spec/frontend/vue_shared/components/table_pagination_spec.js
index 058dfcdbde2..12c47637358 100644
--- a/spec/frontend/vue_shared/components/table_pagination_spec.js
+++ b/spec/frontend/vue_shared/components/table_pagination_spec.js
@@ -6,7 +6,7 @@ describe('Pagination component', () => {
let wrapper;
let spy;
- const mountComponent = props => {
+ const mountComponent = (props) => {
wrapper = shallowMount(TablePagination, {
propsData: props,
});
diff --git a/spec/frontend/vue_shared/components/tabs/tab_spec.js b/spec/frontend/vue_shared/components/tabs/tab_spec.js
index 8cf07a9177c..ee0c983c764 100644
--- a/spec/frontend/vue_shared/components/tabs/tab_spec.js
+++ b/spec/frontend/vue_shared/components/tabs/tab_spec.js
@@ -10,7 +10,7 @@ describe('Tab component', () => {
vm = mountComponent(Component);
});
- it('sets localActive to equal active', done => {
+ it('sets localActive to equal active', (done) => {
vm.active = true;
vm.$nextTick(() => {
@@ -20,7 +20,7 @@ describe('Tab component', () => {
});
});
- it('sets active class', done => {
+ it('sets active class', (done) => {
vm.active = true;
vm.$nextTick(() => {
diff --git a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
index 175abf5aae0..27c9b099306 100644
--- a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
+++ b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
@@ -18,7 +18,7 @@ describe('TooltipOnTruncate component', () => {
const createComponent = ({ propsData, ...options } = {}) => {
wrapper = shallowMount(TooltipOnTruncate, {
- attachToDocument: true,
+ attachTo: document.body,
propsData: {
...propsData,
},
@@ -44,7 +44,7 @@ describe('TooltipOnTruncate component', () => {
},
{
propsData: { ...propsData },
- attachToDocument: true,
+ attachTo: document.body,
...options,
},
);
@@ -139,7 +139,7 @@ describe('TooltipOnTruncate component', () => {
createComponent({
propsData: {
title: DUMMY_TEXT,
- truncateTarget: el => el.childNodes[1],
+ truncateTarget: (el) => el.childNodes[1],
},
slots: {
default: [createChildElement(), createChildElement()],
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
index 663d0af4cc4..2c3fc70e116 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
@@ -91,11 +91,11 @@ describe('User Avatar Image Component', () => {
});
it('renders the tooltip slot', () => {
- expect(wrapper.find('.js-user-avatar-image-toolip').exists()).toBe(true);
+ expect(wrapper.find('.js-user-avatar-image-tooltip').exists()).toBe(true);
});
it('renders the tooltip content', () => {
- expect(wrapper.find('.js-user-avatar-image-toolip').text()).toContain(slots.default[0]);
+ expect(wrapper.find('.js-user-avatar-image-tooltip').text()).toContain(slots.default[0]);
});
it('does not render tooltip data attributes for on avatar image', () => {
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 84e7a6a162e..d151cd15bc4 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
@@ -20,7 +20,7 @@ describe('User Avatar Link Component', () => {
username: 'username',
};
- const createWrapper = props => {
+ const createWrapper = (props) => {
wrapper = shallowMount(UserAvatarLink, {
propsData: {
...defaultProps,
@@ -83,7 +83,7 @@ describe('User Avatar Link Component', () => {
describe('username', () => {
it('should not render avatar image tooltip', () => {
- expect(wrapper.find('.js-user-avatar-image-toolip').exists()).toBe(false);
+ expect(wrapper.find('.js-user-avatar-image-tooltip').exists()).toBe(false);
});
it('should render username prop in <span>', () => {
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 6f66d1cafb9..e3cd2bb9aaa 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
@@ -9,13 +9,13 @@ const TEST_BREAKPOINT = 5;
const TEST_EMPTY_MESSAGE = 'Lorem ipsum empty';
const DEFAULT_EMPTY_MESSAGE = 'None';
-const createUser = id => ({
+const createUser = (id) => ({
id,
name: 'Lorem',
web_url: `${TEST_HOST}/${id}`,
avatar_url: `${TEST_HOST}/${id}/avatar`,
});
-const createList = n =>
+const createList = (n) =>
Array(n)
.fill(1)
.map((x, id) => createUser(id));
@@ -79,10 +79,10 @@ describe('UserAvatarList', () => {
factory({ propsData: { items } });
const links = wrapper.findAll(UserAvatarLink);
- const linkProps = links.wrappers.map(x => x.props());
+ const linkProps = links.wrappers.map((x) => x.props());
expect(linkProps).toEqual(
- items.map(x =>
+ items.map((x) =>
expect.objectContaining({
linkHref: x.web_url,
imgSrc: x.avatar_url,
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 7d58a865ba3..435c3a5406e 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
@@ -33,7 +33,7 @@ describe('User Popover Component', () => {
wrapper.destroy();
});
- const findByTestId = testid => wrapper.find(`[data-testid="${testid}"]`);
+ 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);
@@ -81,6 +81,7 @@ describe('User Popover Component', () => {
});
it('shows icon for location', () => {
+ createWrapper();
const iconEl = wrapper.find(GlIcon);
expect(iconEl.props('name')).toEqual('location');
@@ -147,7 +148,7 @@ describe('User Popover Component', () => {
createWrapper({ user });
expect(
- wrapper.findAll(GlIcon).filter(icon => icon.props('name') === 'profile').length,
+ wrapper.findAll(GlIcon).filter((icon) => icon.props('name') === 'profile').length,
).toEqual(1);
});
@@ -159,9 +160,9 @@ describe('User Popover Component', () => {
createWrapper({ user });
- expect(wrapper.findAll(GlIcon).filter(icon => icon.props('name') === 'work').length).toEqual(
- 1,
- );
+ expect(
+ wrapper.findAll(GlIcon).filter((icon) => icon.props('name') === 'work').length,
+ ).toEqual(1);
});
});
diff --git a/spec/frontend/vue_shared/directives/tooltip_spec.js b/spec/frontend/vue_shared/directives/tooltip_spec.js
index 4217b8d3c02..28ec23ad4c1 100644
--- a/spec/frontend/vue_shared/directives/tooltip_spec.js
+++ b/spec/frontend/vue_shared/directives/tooltip_spec.js
@@ -19,7 +19,7 @@ describe('Tooltip directive', () => {
data: () => ({ tooltip: text }),
template,
},
- { attachToDocument: true },
+ { attachTo: document.body },
);
}
@@ -151,11 +151,7 @@ describe('Tooltip directive', () => {
});
it('should have tooltip plugin applied to all instances', () => {
- expect(
- $(wrapper.vm.$el)
- .find('.js-look-for-tooltip')
- .data('bs.tooltip'),
- ).toBeDefined();
+ expect($(wrapper.vm.$el).find('.js-look-for-tooltip').data('bs.tooltip')).toBeDefined();
});
});
});
diff --git a/spec/frontend/vue_shared/directives/validation_spec.js b/spec/frontend/vue_shared/directives/validation_spec.js
index 814d6f43589..2764a71d204 100644
--- a/spec/frontend/vue_shared/directives/validation_spec.js
+++ b/spec/frontend/vue_shared/directives/validation_spec.js
@@ -36,7 +36,7 @@ describe('validation directive', () => {
`,
};
- wrapper = shallowMount(component, { attachToDocument: true });
+ wrapper = shallowMount(component, { attachTo: document.body });
};
afterEach(() => {
@@ -50,7 +50,7 @@ describe('validation directive', () => {
describe.each([true, false])(
'with fields untouched and "showValidation" set to "%s"',
- showValidation => {
+ (showValidation) => {
beforeEach(() => {
createComponent({ showValidation });
});
@@ -78,7 +78,7 @@ describe('validation directive', () => {
`(
'with input-attributes set to $inputAttributes',
({ inputAttributes, validValue, invalidValue }) => {
- const setValueAndTriggerValidation = value => {
+ const setValueAndTriggerValidation = (value) => {
const input = findInput();
input.setValue(value);
input.trigger('blur');
diff --git a/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js b/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
index 7e70407655a..9138d2d3f4c 100644
--- a/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
@@ -6,7 +6,7 @@ describe('SecurityReportDownloadDropdown component', () => {
let wrapper;
let artifacts;
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(SecurityReportDownloadDropdown, {
propsData: { ...props },
});
diff --git a/spec/frontend/vue_shared/security_reports/mock_data.js b/spec/frontend/vue_shared/security_reports/mock_data.js
index e93ca8329e7..b3ff7daef2b 100644
--- a/spec/frontend/vue_shared/security_reports/mock_data.js
+++ b/spec/frontend/vue_shared/security_reports/mock_data.js
@@ -392,6 +392,33 @@ export const securityReportDownloadPathsQueryResponse = {
},
__typename: 'CiJob',
},
+ {
+ name: 'all_artifacts',
+ artifacts: {
+ nodes: [
+ {
+ downloadPath:
+ '/gitlab-org/secrets-detection-test/-/jobs/1402/artifacts/download?file_type=archive',
+ fileType: 'ARCHIVE',
+ __typename: 'CiJobArtifact',
+ },
+ {
+ downloadPath:
+ '/gitlab-org/secrets-detection-test/-/jobs/1402/artifacts/download?file_type=trace',
+ fileType: 'TRACE',
+ __typename: 'CiJobArtifact',
+ },
+ {
+ downloadPath:
+ '/gitlab-org/secrets-detection-test/-/jobs/1402/artifacts/download?file_type=metadata',
+ fileType: 'METADATA',
+ __typename: 'CiJobArtifact',
+ },
+ ],
+ __typename: 'CiJobArtifactConnection',
+ },
+ __typename: 'CiJob',
+ },
],
__typename: 'CiJobConnection',
},
@@ -435,3 +462,51 @@ export const expectedDownloadDropdownProps = {
loading: false,
artifacts: [...secretDetectionArtifacts, ...sastArtifacts],
};
+
+/**
+ * These correspond to any jobs with zip archives in the securityReportDownloadPathsQueryResponse above.
+ */
+export const archiveArtifacts = [
+ {
+ name: 'all_artifacts Archive',
+ path: '/gitlab-org/secrets-detection-test/-/jobs/1402/artifacts/download?file_type=archive',
+ reportType: 'ARCHIVE',
+ },
+];
+
+/**
+ * These correspond to any jobs with trace data in the securityReportDownloadPathsQueryResponse above.
+ */
+export const traceArtifacts = [
+ {
+ name: 'secret_detection Trace',
+ path: '/gitlab-org/secrets-detection-test/-/jobs/1399/artifacts/download?file_type=trace',
+ reportType: 'TRACE',
+ },
+ {
+ name: 'bandit-sast Trace',
+ path: '/gitlab-org/secrets-detection-test/-/jobs/1400/artifacts/download?file_type=trace',
+ reportType: 'TRACE',
+ },
+ {
+ name: 'eslint-sast Trace',
+ path: '/gitlab-org/secrets-detection-test/-/jobs/1401/artifacts/download?file_type=trace',
+ reportType: 'TRACE',
+ },
+ {
+ name: 'all_artifacts Trace',
+ path: '/gitlab-org/secrets-detection-test/-/jobs/1402/artifacts/download?file_type=trace',
+ reportType: 'TRACE',
+ },
+];
+
+/**
+ * These correspond to any jobs with metadata data in the securityReportDownloadPathsQueryResponse above.
+ */
+export const metadataArtifacts = [
+ {
+ name: 'all_artifacts Metadata',
+ path: '/gitlab-org/secrets-detection-test/-/jobs/1402/artifacts/download?file_type=metadata',
+ reportType: 'METADATA',
+ },
+];
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 c440081a0c4..50d1d130675 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
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { merge } from 'lodash';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import { trimText } from 'helpers/text_helper';
import waitForPromises from 'helpers/wait_for_promises';
import {
@@ -42,7 +42,7 @@ describe('Security reports app', () => {
discoverProjectSecurityPath: '/discoverProjectSecurityPath',
};
- const createComponent = options => {
+ const createComponent = (options) => {
wrapper = mount(
SecurityReportsApp,
merge(
@@ -61,7 +61,7 @@ describe('Security reports app', () => {
const pendingHandler = () => new Promise(() => {});
const successHandler = () => Promise.resolve({ data: securityReportDownloadPathsQueryResponse });
const failureHandler = () => Promise.resolve({ errors: [{ message: 'some error' }] });
- const createMockApolloProvider = handler => {
+ const createMockApolloProvider = (handler) => {
localVue.use(VueApollo);
const requestHandlers = [[securityReportDownloadPathsQuery, handler]];
@@ -74,7 +74,7 @@ describe('Security reports app', () => {
const findDownloadDropdown = () => wrapper.find(SecurityReportDownloadDropdown);
const findPipelinesTabAnchor = () => wrapper.find('[data-testid="show-pipelines"]');
const findHelpIconComponent = () => wrapper.find(HelpIcon);
- const setupMockJobArtifact = reportType => {
+ const setupMockJobArtifact = (reportType) => {
jest
.spyOn(Api, 'pipelineJobs')
.mockResolvedValue({ data: [{ artifacts: [{ file_type: reportType }] }] });
@@ -93,8 +93,8 @@ describe('Security reports app', () => {
describe.each([false, true])(
'given the coreSecurityMrWidgetCounts feature flag is %p',
- coreSecurityMrWidgetCounts => {
- const createComponentWithFlag = options =>
+ (coreSecurityMrWidgetCounts) => {
+ const createComponentWithFlag = (options) =>
createComponent(
merge(
{
@@ -108,7 +108,7 @@ describe('Security reports app', () => {
),
);
- describe.each(SecurityReportsApp.reportTypes)('given a report type %p', reportType => {
+ describe.each(SecurityReportsApp.reportTypes)('given a report type %p', (reportType) => {
beforeEach(() => {
window.mrTabs = { tabShown: jest.fn() };
setupMockJobArtifact(reportType);
@@ -245,7 +245,7 @@ describe('Security reports app', () => {
describe('given the coreSecurityMrWidgetCounts feature flag is enabled', () => {
let mock;
- const createComponentWithFlagEnabled = options =>
+ const createComponentWithFlagEnabled = (options) =>
createComponent(
merge(options, {
provide: {
@@ -350,7 +350,7 @@ describe('Security reports app', () => {
});
describe('given coreSecurityMrWidgetDownloads feature flag is enabled', () => {
- const createComponentWithFlagEnabled = options =>
+ const createComponentWithFlagEnabled = (options) =>
createComponent(
merge(options, {
provide: {
@@ -371,7 +371,7 @@ describe('Security reports app', () => {
// TODO: Remove this assertion as part of
// https://gitlab.com/gitlab-org/gitlab/-/issues/273431
it('initially renders nothing', () => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
@@ -415,7 +415,7 @@ describe('Security reports app', () => {
// TODO: Remove this assertion as part of
// https://gitlab.com/gitlab-org/gitlab/-/issues/273431
it('renders nothing', () => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
});
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 8de704be455..b146a281d7b 100644
--- a/spec/frontend/vue_shared/security_reports/store/getters_spec.js
+++ b/spec/frontend/vue_shared/security_reports/store/getters_spec.js
@@ -13,7 +13,7 @@ import {
} from '~/vue_shared/security_reports/store/getters';
import { CRITICAL, HIGH, LOW } from '~/vulnerabilities/constants';
-const generateVuln = severity => ({ severity });
+const generateVuln = (severity) => ({ severity });
describe('Security reports getters', () => {
let state;
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 a11f4e05913..c9d1db8a504 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
@@ -26,7 +26,7 @@ describe('sast report actions', () => {
});
describe('setDiffEndpoint', () => {
- it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, done => {
+ it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, (done) => {
testAction(
actions.setDiffEndpoint,
diffEndpoint,
@@ -44,13 +44,13 @@ describe('sast report actions', () => {
});
describe('requestDiff', () => {
- it(`should commit ${types.REQUEST_DIFF}`, done => {
+ it(`should commit ${types.REQUEST_DIFF}`, (done) => {
testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], [], done);
});
});
describe('receiveDiffSuccess', () => {
- it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, done => {
+ it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, (done) => {
testAction(
actions.receiveDiffSuccess,
reports,
@@ -68,7 +68,7 @@ describe('sast report actions', () => {
});
describe('receiveDiffError', () => {
- it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, done => {
+ it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, (done) => {
testAction(
actions.receiveDiffError,
error,
@@ -107,7 +107,7 @@ describe('sast report actions', () => {
.replyOnce(200, reports.enrichData);
});
- it('should dispatch the `receiveDiffSuccess` action', done => {
+ it('should dispatch the `receiveDiffSuccess` action', (done) => {
const { diff, enrichData } = reports;
testAction(
actions.fetchDiff,
@@ -135,7 +135,7 @@ describe('sast report actions', () => {
mock.onGet(diffEndpoint).replyOnce(200, reports.diff);
});
- it('should dispatch the `receiveDiffSuccess` action with empty enrich data', done => {
+ it('should dispatch the `receiveDiffSuccess` action with empty enrich data', (done) => {
const { diff } = reports;
const enrichData = [];
testAction(
@@ -167,7 +167,7 @@ describe('sast report actions', () => {
.replyOnce(404);
});
- it('should dispatch the `receiveError` action', done => {
+ it('should dispatch the `receiveError` action', (done) => {
testAction(
actions.fetchDiff,
{},
@@ -188,7 +188,7 @@ describe('sast report actions', () => {
.replyOnce(200, reports.enrichData);
});
- it('should dispatch the `receiveDiffError` action', done => {
+ it('should dispatch the `receiveDiffError` action', (done) => {
testAction(
actions.fetchDiff,
{},
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 bbcdfb5cd99..beda1a55438 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
@@ -26,7 +26,7 @@ describe('secret detection report actions', () => {
});
describe('setDiffEndpoint', () => {
- it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, done => {
+ it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, (done) => {
testAction(
actions.setDiffEndpoint,
diffEndpoint,
@@ -44,13 +44,13 @@ describe('secret detection report actions', () => {
});
describe('requestDiff', () => {
- it(`should commit ${types.REQUEST_DIFF}`, done => {
+ it(`should commit ${types.REQUEST_DIFF}`, (done) => {
testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], [], done);
});
});
describe('receiveDiffSuccess', () => {
- it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, done => {
+ it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, (done) => {
testAction(
actions.receiveDiffSuccess,
reports,
@@ -68,7 +68,7 @@ describe('secret detection report actions', () => {
});
describe('receiveDiffError', () => {
- it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, done => {
+ it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, (done) => {
testAction(
actions.receiveDiffError,
error,
@@ -107,7 +107,7 @@ describe('secret detection report actions', () => {
.replyOnce(200, reports.enrichData);
});
- it('should dispatch the `receiveDiffSuccess` action', done => {
+ it('should dispatch the `receiveDiffSuccess` action', (done) => {
const { diff, enrichData } = reports;
testAction(
actions.fetchDiff,
@@ -135,7 +135,7 @@ describe('secret detection report actions', () => {
mock.onGet(diffEndpoint).replyOnce(200, reports.diff);
});
- it('should dispatch the `receiveDiffSuccess` action with empty enrich data', done => {
+ it('should dispatch the `receiveDiffSuccess` action with empty enrich data', (done) => {
const { diff } = reports;
const enrichData = [];
testAction(
@@ -167,7 +167,7 @@ describe('secret detection report actions', () => {
.replyOnce(404);
});
- it('should dispatch the `receiveDiffError` action', done => {
+ it('should dispatch the `receiveDiffError` action', (done) => {
testAction(
actions.fetchDiff,
{},
@@ -188,7 +188,7 @@ describe('secret detection report actions', () => {
.replyOnce(200, reports.enrichData);
});
- it('should dispatch the `receiveDiffError` action', done => {
+ it('should dispatch the `receiveDiffError` action', (done) => {
testAction(
actions.fetchDiff,
{},
diff --git a/spec/frontend/vue_shared/security_reports/utils_spec.js b/spec/frontend/vue_shared/security_reports/utils_spec.js
index ea54644796a..7e5a27694ef 100644
--- a/spec/frontend/vue_shared/security_reports/utils_spec.js
+++ b/spec/frontend/vue_shared/security_reports/utils_spec.js
@@ -2,11 +2,15 @@ import { extractSecurityReportArtifacts } from '~/vue_shared/security_reports/ut
import {
REPORT_TYPE_SAST,
REPORT_TYPE_SECRET_DETECTION,
+ REPORT_FILE_TYPES,
} from '~/vue_shared/security_reports/constants';
import {
securityReportDownloadPathsQueryResponse,
sastArtifacts,
secretDetectionArtifacts,
+ archiveArtifacts,
+ traceArtifacts,
+ metadataArtifacts,
} from './mock_data';
describe('extractSecurityReportArtifacts', () => {
@@ -17,6 +21,9 @@ describe('extractSecurityReportArtifacts', () => {
${[REPORT_TYPE_SAST]} | ${sastArtifacts}
${[REPORT_TYPE_SECRET_DETECTION]} | ${secretDetectionArtifacts}
${[REPORT_TYPE_SAST, REPORT_TYPE_SECRET_DETECTION]} | ${[...secretDetectionArtifacts, ...sastArtifacts]}
+ ${[REPORT_FILE_TYPES.ARCHIVE]} | ${archiveArtifacts}
+ ${[REPORT_FILE_TYPES.TRACE]} | ${traceArtifacts}
+ ${[REPORT_FILE_TYPES.METADATA]} | ${metadataArtifacts}
`(
'returns the expected artifacts given report types $reportTypes',
({ reportTypes, expectedArtifacts }) => {
diff --git a/spec/frontend/vuex_shared/modules/modal/actions_spec.js b/spec/frontend/vuex_shared/modules/modal/actions_spec.js
index 353dbcb522f..a8269194c0b 100644
--- a/spec/frontend/vuex_shared/modules/modal/actions_spec.js
+++ b/spec/frontend/vuex_shared/modules/modal/actions_spec.js
@@ -4,7 +4,7 @@ import * as actions from '~/vuex_shared/modules/modal/actions';
describe('Vuex ModalModule actions', () => {
describe('open', () => {
- it('works', done => {
+ it('works', (done) => {
const data = { id: 7 };
testAction(actions.open, data, {}, [{ type: types.OPEN, payload: data }], [], done);
@@ -12,19 +12,19 @@ describe('Vuex ModalModule actions', () => {
});
describe('close', () => {
- it('works', done => {
+ it('works', (done) => {
testAction(actions.close, null, {}, [{ type: types.CLOSE }], [], done);
});
});
describe('show', () => {
- it('works', done => {
+ it('works', (done) => {
testAction(actions.show, null, {}, [{ type: types.SHOW }], [], done);
});
});
describe('hide', () => {
- it('works', done => {
+ it('works', (done) => {
testAction(actions.hide, null, {}, [{ type: types.HIDE }], [], done);
});
});
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index 7a9340da87a..13e6bec47ab 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -103,7 +103,7 @@ describe('App', () => {
expect(actions.closeDrawer).toHaveBeenCalled();
});
- it.each([true, false])('passes open property', async openState => {
+ it.each([true, false])('passes open property', async (openState) => {
wrapper.vm.$store.state.open = openState;
await wrapper.vm.$nextTick();
@@ -183,7 +183,7 @@ describe('App', () => {
const clickSecondTab = async () => {
const secondTab = wrapper.findAll('.nav-link').at(1);
await secondTab.trigger('click');
- await new Promise(resolve => requestAnimationFrame(resolve));
+ await new Promise((resolve) => requestAnimationFrame(resolve));
};
beforeEach(() => {
diff --git a/spec/frontend/wikis_spec.js b/spec/frontend/wikis_spec.js
index cf1ea972697..c4a2bf1a69a 100644
--- a/spec/frontend/wikis_spec.js
+++ b/spec/frontend/wikis_spec.js
@@ -1,128 +1,160 @@
import { escape } from 'lodash';
+import { setHTMLFixture } from 'helpers/fixtures';
import Wikis from '~/pages/shared/wikis/wikis';
import Tracking from '~/tracking';
-import { setHTMLFixture } from './helpers/fixtures';
describe('Wikis', () => {
- describe('setting the commit message when the title changes', () => {
- const editFormHtmlFixture = args => `<form class="wiki-form ${
- args.newPage ? 'js-new-wiki-page' : ''
- }">
- <input type="text" id="wiki_title" value="My title" />
- <input type="text" id="wiki_message" />
- <select class="form-control select-control" name="wiki[format]" id="wiki_format">
- <option value="markdown">Markdown</option>
- <option selected="selected" value="rdoc">RDoc</option>
- <option value="asciidoc">AsciiDoc</option>
- <option value="org">Org</option>
- </select>
- <textarea id="wiki_content"></textarea>
- <code class="js-markup-link-example">{Link title}[link:page-slug]</code>
- </form>
- `;
-
- let wikis;
- let titleInput;
- let messageInput;
- let changeFormatSelect;
- let linkExample;
-
- const findBeforeUnloadWarning = () => window.onbeforeunload?.();
- const findContent = () => document.getElementById('wiki_content');
- const findForm = () => document.querySelector('.wiki-form');
-
- describe('when the wiki page is being created', () => {
- const formHtmlFixture = editFormHtmlFixture({ newPage: true });
+ const editFormHtmlFixture = (args) => `<form class="wiki-form ${
+ args.newPage ? 'js-new-wiki-page' : ''
+ }">
+ <input type="text" id="wiki_title" value="My title" />
+ <input type="text" id="wiki_message" />
+ <select class="form-control select-control" name="wiki[format]" id="wiki_format">
+ <option value="markdown">Markdown</option>
+ <option selected="selected" value="rdoc">RDoc</option>
+ <option value="asciidoc">AsciiDoc</option>
+ <option value="org">Org</option>
+ </select>
+ <textarea id="wiki_content"></textarea>
+ <code class="js-markup-link-example">{Link title}[link:page-slug]</code>
+ <input type="submit" class="js-wiki-btn-submit">
+ </input>
+ </form>
+ `;
+
+ let wikis;
+ let titleInput;
+ let contentInput;
+ let messageInput;
+ let changeFormatSelect;
+ let linkExample;
+
+ const findBeforeUnloadWarning = () => window.onbeforeunload?.();
+ const findForm = () => document.querySelector('.wiki-form');
+ const findSubmitButton = () => document.querySelector('.js-wiki-btn-submit');
+
+ describe('when the wiki page is being created', () => {
+ const formHtmlFixture = editFormHtmlFixture({ newPage: true });
- beforeEach(() => {
- setHTMLFixture(formHtmlFixture);
+ beforeEach(() => {
+ setHTMLFixture(formHtmlFixture);
- titleInput = document.getElementById('wiki_title');
- messageInput = document.getElementById('wiki_message');
- changeFormatSelect = document.querySelector('#wiki_format');
- linkExample = document.querySelector('.js-markup-link-example');
- wikis = new Wikis();
- });
+ titleInput = document.getElementById('wiki_title');
+ messageInput = document.getElementById('wiki_message');
+ changeFormatSelect = document.querySelector('#wiki_format');
+ linkExample = document.querySelector('.js-markup-link-example');
+ wikis = new Wikis();
+ });
- it('binds an event listener to the title input', () => {
- wikis.handleWikiTitleChange = jest.fn();
+ it('binds an event listener to the title input', () => {
+ wikis.handleWikiTitleChange = jest.fn();
- titleInput.dispatchEvent(new Event('keyup'));
+ titleInput.dispatchEvent(new Event('keyup'));
- expect(wikis.handleWikiTitleChange).toHaveBeenCalled();
- });
+ expect(wikis.handleWikiTitleChange).toHaveBeenCalled();
+ });
- it('sets the commit message when title changes', () => {
- titleInput.value = 'My title';
- messageInput.value = '';
+ it('sets the commit message when title changes', () => {
+ titleInput.value = 'My title';
+ messageInput.value = '';
- titleInput.dispatchEvent(new Event('keyup'));
+ titleInput.dispatchEvent(new Event('keyup'));
- expect(messageInput.value).toEqual('Create My title');
- });
+ expect(messageInput.value).toEqual('Create My title');
+ });
- it('replaces hyphens with spaces', () => {
- titleInput.value = 'my-hyphenated-title';
- titleInput.dispatchEvent(new Event('keyup'));
+ it('replaces hyphens with spaces', () => {
+ titleInput.value = 'my-hyphenated-title';
+ titleInput.dispatchEvent(new Event('keyup'));
- expect(messageInput.value).toEqual('Create my hyphenated title');
- });
+ expect(messageInput.value).toEqual('Create my hyphenated title');
});
+ });
- describe('when the wiki page is being updated', () => {
- const formHtmlFixture = editFormHtmlFixture({ newPage: false });
+ describe('when the wiki page is being updated', () => {
+ const formHtmlFixture = editFormHtmlFixture({ newPage: false });
- beforeEach(() => {
- setHTMLFixture(formHtmlFixture);
+ beforeEach(() => {
+ setHTMLFixture(formHtmlFixture);
- titleInput = document.getElementById('wiki_title');
- messageInput = document.getElementById('wiki_message');
- wikis = new Wikis();
- });
+ titleInput = document.getElementById('wiki_title');
+ messageInput = document.getElementById('wiki_message');
+ wikis = new Wikis();
+ });
- it('sets the commit message when title changes, prefixing with "Update"', () => {
- titleInput.value = 'My title';
- messageInput.value = '';
+ it('sets the commit message when title changes, prefixing with "Update"', () => {
+ titleInput.value = 'My title';
+ messageInput.value = '';
- titleInput.dispatchEvent(new Event('keyup'));
+ titleInput.dispatchEvent(new Event('keyup'));
- expect(messageInput.value).toEqual('Update My title');
+ expect(messageInput.value).toEqual('Update My title');
+ });
+
+ it.each`
+ value | text
+ ${'markdown'} | ${'[Link Title](page-slug)'}
+ ${'rdoc'} | ${'{Link title}[link:page-slug]'}
+ ${'asciidoc'} | ${'link:page-slug[Link title]'}
+ ${'org'} | ${'[[page-slug]]'}
+ `('updates a message when value=$value is selected', ({ value, text }) => {
+ changeFormatSelect.value = value;
+ changeFormatSelect.dispatchEvent(new Event('change'));
+
+ expect(linkExample.innerHTML).toBe(text);
+ });
+
+ it('starts with no unload warning', () => {
+ expect(findBeforeUnloadWarning()).toBeUndefined();
+ });
+
+ describe('when wiki content is updated', () => {
+ beforeEach(() => {
+ contentInput = document.getElementById('wiki_content');
+ contentInput.value = 'Lorem ipsum dolar sit!';
+ contentInput.dispatchEvent(new Event('input'));
});
- it.each`
- value | text
- ${'markdown'} | ${'[Link Title](page-slug)'}
- ${'rdoc'} | ${'{Link title}[link:page-slug]'}
- ${'asciidoc'} | ${'link:page-slug[Link title]'}
- ${'org'} | ${'[[page-slug]]'}
- `('updates a message when value=$value is selected', ({ value, text }) => {
- changeFormatSelect.value = value;
- changeFormatSelect.dispatchEvent(new Event('change'));
-
- expect(linkExample.innerHTML).toBe(text);
+ it('sets before unload warning', () => {
+ expect(findBeforeUnloadWarning()).toBe('');
});
- it('starts with no unload warning', () => {
+ it('when form submitted, unsets before unload warning', () => {
+ findForm().dispatchEvent(new Event('submit'));
expect(findBeforeUnloadWarning()).toBeUndefined();
});
+ });
+ });
- describe('when wiki content is updated', () => {
- beforeEach(() => {
- const content = findContent();
- content.value = 'Lorem ipsum dolar sit!';
- content.dispatchEvent(new Event('input'));
- });
-
- it('sets before unload warning', () => {
- expect(findBeforeUnloadWarning()).toBe('');
- });
-
- it('when form submitted, unsets before unload warning', () => {
- findForm().dispatchEvent(new Event('submit'));
- expect(findBeforeUnloadWarning()).toBeUndefined();
- });
- });
+ describe('submit button state', () => {
+ beforeEach(() => {
+ setHTMLFixture(editFormHtmlFixture({ newPage: true }));
+
+ titleInput = document.getElementById('wiki_title');
+ contentInput = document.getElementById('wiki_content');
+
+ wikis = new Wikis();
});
+
+ it.each`
+ title | text | buttonState | disabledAttr
+ ${'something'} | ${'something'} | ${'enabled'} | ${null}
+ ${''} | ${'something'} | ${'disabled'} | ${'true'}
+ ${'something'} | ${''} | ${'disabled'} | ${'true'}
+ ${''} | ${''} | ${'disabled'} | ${'true'}
+ ${' '} | ${' '} | ${'disabled'} | ${'true'}
+ `(
+ "when title='$title', content='$content', then, buttonState='$buttonState'",
+ ({ title, text, disabledAttr }) => {
+ titleInput.value = title;
+ titleInput.dispatchEvent(new Event('keyup'));
+
+ contentInput.value = text;
+ contentInput.dispatchEvent(new Event('input'));
+
+ expect(findSubmitButton().getAttribute('disabled')).toBe(disabledAttr);
+ },
+ );
});
describe('trackPageView', () => {
diff --git a/spec/frontend/zen_mode_spec.js b/spec/frontend/zen_mode_spec.js
index 8e0d170289b..e874d018e92 100644
--- a/spec/frontend/zen_mode_spec.js
+++ b/spec/frontend/zen_mode_spec.js
@@ -3,6 +3,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Dropzone from 'dropzone';
import Mousetrap from 'mousetrap';
+import * as utils from '~/lib/utils/common_utils';
import ZenMode from '~/zen_mode';
import initNotes from '~/init_notes';
@@ -103,10 +104,10 @@ describe('ZenMode', () => {
});
it('restores the scroll position', () => {
- jest.spyOn(zen, 'scrollTo').mockImplementation(() => {});
+ jest.spyOn(utils, 'scrollToElement');
exitZen();
- expect(zen.scrollTo).toHaveBeenCalled();
+ expect(utils.scrollToElement).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js
index fe8d5f93794..8d5d047b146 100644
--- a/spec/frontend_integration/ide/helpers/ide_helper.js
+++ b/spec/frontend_integration/ide/helpers/ide_helper.js
@@ -8,11 +8,11 @@ import {
findByText,
} from '@testing-library/dom';
-const isFolderRowOpen = row => row.matches('.folder.is-open');
+const isFolderRowOpen = (row) => row.matches('.folder.is-open');
const getLeftSidebar = () => screen.getByTestId('left-sidebar');
-export const switchLeftSidebarTab = name => {
+export const switchLeftSidebarTab = (name) => {
const sidebar = getLeftSidebar();
const button = getByLabelText(sidebar, name);
@@ -23,7 +23,7 @@ export const switchLeftSidebarTab = name => {
export const getStatusBar = () => document.querySelector('.ide-status-bar');
export const waitForMonacoEditor = () =>
- new Promise(resolve => window.monaco.editor.onDidCreateEditor(resolve));
+ new Promise((resolve) => window.monaco.editor.onDidCreateEditor(resolve));
export const findMonacoEditor = () =>
screen.findAllByLabelText(/Editor content;/).then(([x]) => x.closest('.monaco-editor'));
@@ -31,7 +31,7 @@ export const findMonacoEditor = () =>
export const findMonacoDiffEditor = () =>
screen.findAllByLabelText(/Editor content;/).then(([x]) => x.closest('.monaco-diff-editor'));
-export const findAndSetEditorValue = async value => {
+export const findAndSetEditorValue = async (value) => {
const editor = await findMonacoEditor();
const uri = editor.getAttribute('data-uri');
@@ -45,9 +45,9 @@ export const getEditorValue = async () => {
return window.monaco.editor.getModel(uri).getValue();
};
-const findTreeBody = () => screen.findByTestId('ide-tree-body', {}, { timeout: 5000 });
+const findTreeBody = () => screen.findByTestId('ide-tree-body');
-const findRootActions = () => screen.findByTestId('ide-root-actions', {}, { timeout: 7000 });
+const findRootActions = () => screen.findByTestId('ide-root-actions');
const findFileRowContainer = (row = null) =>
row ? Promise.resolve(row.parentElement) : findTreeBody();
@@ -56,10 +56,12 @@ const findFileChild = async (row, name, index = 0) => {
const container = await findFileRowContainer(row);
const children = await findAllByText(container, name, { selector: '.file-row-name' });
- return children.map(x => x.closest('.file-row')).find(x => x.dataset.level === index.toString());
+ return children
+ .map((x) => x.closest('.file-row'))
+ .find((x) => x.dataset.level === index.toString());
};
-const openFileRow = row => {
+const openFileRow = (row) => {
if (!row || isFolderRowOpen(row)) {
return;
}
@@ -101,7 +103,7 @@ const fillFileNameModal = async (value, submitText = 'Create file') => {
createButton.click();
};
-const findAndClickRootAction = async name => {
+const findAndClickRootAction = async (name) => {
const container = await findRootActions();
const button = getByLabelText(container, name);
@@ -112,20 +114,17 @@ export const clickPreviewMarkdown = () => {
screen.getByText('Preview Markdown').click();
};
-export const openFile = async path => {
+export const openFile = async (path) => {
const row = await findAndTraverseToPath(path);
openFileRow(row);
};
-export const waitForTabToOpen = fileName =>
+export const waitForTabToOpen = (fileName) =>
findByText(document.querySelector('.multi-file-edit-pane'), fileName);
export const createFile = async (path, content) => {
- const parentPath = path
- .split('/')
- .slice(0, -1)
- .join('/');
+ const parentPath = path.split('/').slice(0, -1).join('/');
const parentRow = await findAndTraverseToPath(parentPath);
@@ -139,11 +138,16 @@ export const createFile = async (path, content) => {
await findAndSetEditorValue(content);
};
+export const updateFile = async (path, content) => {
+ await openFile(path);
+ await findAndSetEditorValue(content);
+};
+
export const getFilesList = () => {
- return screen.getAllByTestId('file-row-name-container').map(e => e.textContent.trim());
+ return screen.getAllByTestId('file-row-name-container').map((e) => e.textContent.trim());
};
-export const deleteFile = async path => {
+export const deleteFile = async (path) => {
const row = await findAndTraverseToPath(path);
clickFileRowAction(row, 'Delete');
};
@@ -155,7 +159,7 @@ export const renameFile = async (path, newPath) => {
await fillFileNameModal(newPath, 'Rename file');
};
-export const closeFile = async path => {
+export const closeFile = async (path) => {
const button = await screen.getByLabelText(`Close ${path}`, {
selector: '.multi-file-tabs button',
});
@@ -163,11 +167,33 @@ export const closeFile = async path => {
button.click();
};
-export const commit = async () => {
+/**
+ * Fill out and submit the commit form in the Web IDE
+ *
+ * @param {Object} options - Used to fill out the commit form in the IDE
+ * @param {Boolean} options.newBranch - Flag for the "Create a new branch" radio.
+ * @param {Boolean} options.newMR - Flag for the "Start a new merge request" checkbox.
+ * @param {String} options.newBranchName - Value to put in the new branch name input field. The Web IDE supports leaving this field blank.
+ */
+export const commit = async ({ newBranch = false, newMR = false, newBranchName = '' } = {}) => {
switchLeftSidebarTab('Commit');
screen.getByTestId('begin-commit-button').click();
- await screen.findByLabelText(/Commit to .+ branch/).then(x => x.click());
+ if (!newBranch) {
+ const option = await screen.findByLabelText(/Commit to .+ branch/);
+ option.click();
+ } else {
+ const option = await screen.findByLabelText('Create a new branch');
+ option.click();
+
+ const branchNameInput = await screen.findByTestId('ide-new-branch-name');
+ fireEvent.input(branchNameInput, { target: { value: newBranchName } });
+
+ const mrCheck = await screen.findByLabelText('Start a new merge request');
+ if (Boolean(mrCheck.checked) !== newMR) {
+ mrCheck.click();
+ }
+ }
screen.getByText('Commit').click();
};
diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js
index 9dc9649e1bf..43a996286e7 100644
--- a/spec/frontend_integration/ide/helpers/start.js
+++ b/spec/frontend_integration/ide/helpers/start.js
@@ -2,6 +2,7 @@ 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';
export default (container, { isRepoEmpty = false, path = '' } = {}) => {
global.jsdom.reconfigure({
@@ -13,5 +14,16 @@ export default (container, { isRepoEmpty = false, path = '' } = {}) => {
const el = document.createElement('div');
Object.assign(el.dataset, IDE_DATASET);
container.appendChild(el);
- return initIde(el, { extendStore });
+ const vm = initIde(el, { extendStore });
+
+ // We need to dispose of editor Singleton things or tests will bump into eachother
+ vm.$on('destroy', () => {
+ if (Editor.editorInstance) {
+ Editor.editorInstance.modelManager.dispose();
+ Editor.editorInstance.dispose();
+ Editor.editorInstance = null;
+ }
+ });
+
+ return vm;
};
diff --git a/spec/frontend_integration/ide/ide_integration_spec.js b/spec/frontend_integration/ide/ide_integration_spec.js
index dacc538d5ba..00a73661d14 100644
--- a/spec/frontend_integration/ide/ide_integration_spec.js
+++ b/spec/frontend_integration/ide/ide_integration_spec.js
@@ -1,5 +1,6 @@
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 { createCommitId } from 'test_helpers/factories/commit_id';
import * as ideHelper from './helpers/ide_helper';
@@ -12,6 +13,9 @@ describe('WebIDE', () => {
let container;
beforeEach(() => {
+ // For some reason these tests were timing out in CI.
+ // We will investigate in https://gitlab.com/gitlab-org/gitlab/-/issues/298714
+ setTestTimeout(20000);
setFixtures('<div class="webide-container"></div>');
container = document.querySelector('.webide-container');
});
@@ -55,6 +59,25 @@ describe('WebIDE', () => {
});
});
+ it('user commits changes to new branch', async () => {
+ vm = startWebIDE(container);
+
+ expect(window.location.pathname).toBe('/-/ide/project/gitlab-test/lorem-ipsum/tree/master/-/');
+
+ await ideHelper.updateFile('README.md', 'Lorem dolar si amit\n');
+ await ideHelper.commit({ newBranch: true, newMR: false, newBranchName: 'test-hello-world' });
+
+ await waitForText('All changes are committed');
+
+ // Wait for IDE to load new commit
+ await waitForText('10000000', document.querySelector('.ide-status-bar'));
+
+ // It's important that the new branch is now in the route
+ expect(window.location.pathname).toBe(
+ '/-/ide/project/gitlab-test/lorem-ipsum/blob/test-hello-world/-/README.md',
+ );
+ });
+
it('user adds file that starts with +', async () => {
vm = startWebIDE(container);
@@ -66,7 +89,7 @@ describe('WebIDE', () => {
// Assert that +test is the only open tab
const tabs = Array.from(document.querySelectorAll('.multi-file-tab'));
- expect(tabs.map(x => x.textContent.trim())).toEqual(['+test']);
+ expect(tabs.map((x) => x.textContent.trim())).toEqual(['+test']);
});
describe('editor info', () => {
diff --git a/spec/frontend_integration/ide/user_opens_file_spec.js b/spec/frontend_integration/ide/user_opens_file_spec.js
index 98a73c7a029..7fa6dcecc9e 100644
--- a/spec/frontend_integration/ide/user_opens_file_spec.js
+++ b/spec/frontend_integration/ide/user_opens_file_spec.js
@@ -3,9 +3,7 @@ import { screen } from '@testing-library/dom';
import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
-// https://gitlab.com/gitlab-org/gitlab/-/issues/293654#note_466432769
-// eslint-disable-next-line jest/no-disabled-tests
-describe.skip('IDE: User opens a file in the Web IDE', () => {
+describe('IDE: User opens a file in the Web IDE', () => {
useOverclockTimers();
let vm;
diff --git a/spec/frontend_integration/test_helpers/factories/commit_id.js b/spec/frontend_integration/test_helpers/factories/commit_id.js
index 9fa278c9dde..815da19a2d9 100644
--- a/spec/frontend_integration/test_helpers/factories/commit_id.js
+++ b/spec/frontend_integration/test_helpers/factories/commit_id.js
@@ -1,7 +1,5 @@
const COMMIT_ID_LENGTH = 40;
-const DEFAULT_COMMIT_ID = Array(COMMIT_ID_LENGTH)
- .fill('0')
- .join('');
+const DEFAULT_COMMIT_ID = Array(COMMIT_ID_LENGTH).fill('0').join('');
export const createCommitId = (index = 0) =>
`${index}${DEFAULT_COMMIT_ID}`.substr(0, COMMIT_ID_LENGTH);
diff --git a/spec/frontend_integration/test_helpers/fixtures.js b/spec/frontend_integration/test_helpers/fixtures.js
index 46946ed71f2..fde3fd8cb63 100644
--- a/spec/frontend_integration/test_helpers/fixtures.js
+++ b/spec/frontend_integration/test_helpers/fixtures.js
@@ -10,9 +10,9 @@ const createFactoryWithDefault = (fn, defaultValue) => () => {
};
const factory = {
- json: fn => createFactoryWithDefault(fn, { error: 'fixture not found' }),
- text: fn => createFactoryWithDefault(fn, 'Hello world\nHow are you today?\n'),
- binary: fn => createFactoryWithDefault(fn, ''),
+ json: (fn) => createFactoryWithDefault(fn, { error: 'fixture not found' }),
+ text: (fn) => createFactoryWithDefault(fn, 'Hello world\nHow are you today?\n'),
+ binary: (fn) => createFactoryWithDefault(fn, ''),
};
export const getProject = factory.json(() => require('test_fixtures/api/projects/get.json'));
diff --git a/spec/frontend_integration/test_helpers/mock_server/index.js b/spec/frontend_integration/test_helpers/mock_server/index.js
index 6f090565635..2aebdefaafb 100644
--- a/spec/frontend_integration/test_helpers/mock_server/index.js
+++ b/spec/frontend_integration/test_helpers/mock_server/index.js
@@ -26,7 +26,7 @@ export const createMockServerOptions = () => ({
},
seeds(schema) {
schema.db.loadData({
- files: getRepositoryFiles().map(path => ({ path })),
+ files: getRepositoryFiles().map((path) => ({ path })),
projects: [getProject(), getEmptyProject()],
branches: [getBranch()],
mergeRequests: getMergeRequests(),
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 9e08016577b..bc8edba927e 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/404.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/404.js
@@ -1,5 +1,5 @@
-export default server => {
- ['get', 'post', 'put', 'delete', 'patch'].forEach(method => {
+export default (server) => {
+ ['get', 'post', 'put', 'delete', 'patch'].forEach((method) => {
server[method]('*', () => {
return new Response(404);
});
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/ci.js b/spec/frontend_integration/test_helpers/mock_server/routes/ci.js
index 83951f09c56..6f1593a2cf9 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/ci.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/ci.js
@@ -1,6 +1,6 @@
import { getPipelinesEmptyResponse } from 'test_helpers/fixtures';
-export default server => {
+export default (server) => {
server.get('*/commit/:id/pipelines', () => {
return getPipelinesEmptyResponse();
});
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/graphql.js b/spec/frontend_integration/test_helpers/mock_server/routes/graphql.js
index ebb5415ba97..a22763dcb45 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/graphql.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/graphql.js
@@ -1,6 +1,6 @@
import { graphqlQuery } from '../graphql';
-export default server => {
+export default (server) => {
server.post('/api/graphql', (schema, request) => {
const batches = JSON.parse(request.requestBody);
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/index.js b/spec/frontend_integration/test_helpers/mock_server/routes/index.js
index eea196b5158..e30fecf2f06 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/index.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/index.js
@@ -1,5 +1,5 @@
/* eslint-disable global-require */
-export default server => {
+export default (server) => {
[
require('./graphql'),
require('./projects'),
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 f4d8ce4b23d..de37aa98eee 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/projects.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/projects.js
@@ -1,6 +1,6 @@
import { withKeys } from 'test_helpers/utils/obj';
-export default server => {
+export default (server) => {
server.get('/api/v4/projects/:id', (schema, request) => {
const { id } = request.params;
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/repository.js b/spec/frontend_integration/test_helpers/mock_server/routes/repository.js
index 166c0cc32db..ba36463cad8 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/repository.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/repository.js
@@ -1,9 +1,9 @@
import { createNewCommit, createCommitIdGenerator } from 'test_helpers/factories';
-export default server => {
+export default (server) => {
const commitIdGenerator = createCommitIdGenerator();
- server.get('/api/v4/projects/:id/repository/branches', schema => {
+ server.get('/api/v4/projects/:id/repository/branches', (schema) => {
return schema.db.branches;
});
@@ -15,7 +15,7 @@ export default server => {
return branch.attrs;
});
- server.get('*/-/files/:id', schema => {
+ server.get('*/-/files/:id', (schema) => {
return schema.db.files.map(({ path }) => path);
});
@@ -37,13 +37,23 @@ export default server => {
);
const branch = schema.branches.findBy({ name: branchName });
+ const prevCommit = branch
+ ? branch.attrs.commit
+ : schema.branches.findBy({ name: 'master' }).attrs.commit;
const commit = {
- ...createNewCommit({ id: commitIdGenerator.next(), message }, branch.attrs.commit),
+ ...createNewCommit({ id: commitIdGenerator.next(), message }, prevCommit),
__actions: actions,
};
- branch.update({ commit });
+ if (branch) {
+ branch.update({ commit });
+ } else {
+ schema.branches.create({
+ name: branchName,
+ commit,
+ });
+ }
return commit;
});
diff --git a/spec/frontend_integration/test_helpers/setup/index.js b/spec/frontend_integration/test_helpers/setup/index.js
index ba1d256e16e..946ccbec00c 100644
--- a/spec/frontend_integration/test_helpers/setup/index.js
+++ b/spec/frontend_integration/test_helpers/setup/index.js
@@ -3,3 +3,4 @@ import './setup_globals';
import './setup_axios';
import './setup_serializers';
import './setup_mock_server';
+import './setup_testing_library';
diff --git a/spec/frontend_integration/test_helpers/setup/setup_testing_library.js b/spec/frontend_integration/test_helpers/setup/setup_testing_library.js
new file mode 100644
index 00000000000..5081b1c3b62
--- /dev/null
+++ b/spec/frontend_integration/test_helpers/setup/setup_testing_library.js
@@ -0,0 +1,3 @@
+import { configure } from '@testing-library/dom';
+
+configure({ asyncUtilTimeout: 10000 });
diff --git a/spec/frontend_integration/test_helpers/snapshot_serializer.js b/spec/frontend_integration/test_helpers/snapshot_serializer.js
index 8c4f95a9156..aacd144217f 100644
--- a/spec/frontend_integration/test_helpers/snapshot_serializer.js
+++ b/spec/frontend_integration/test_helpers/snapshot_serializer.js
@@ -4,7 +4,7 @@ export default {
},
print(element, serialize) {
element.$_hit = true;
- element.querySelectorAll('[style]').forEach(el => {
+ element.querySelectorAll('[style]').forEach((el) => {
el.$_hit = true;
if (el.style.display === 'none') {
el.textContent = '(jest: contents hidden)';
diff --git a/spec/frontend_integration/test_helpers/utils/obj_spec.js b/spec/frontend_integration/test_helpers/utils/obj_spec.js
index 0ad7b4a1a4c..614250ccddc 100644
--- a/spec/frontend_integration/test_helpers/utils/obj_spec.js
+++ b/spec/frontend_integration/test_helpers/utils/obj_spec.js
@@ -3,9 +3,9 @@ import { withKeys, withValues } from './obj';
describe('frontend_integration/test_helpers/utils/obj', () => {
describe('withKeys', () => {
it('picks and maps keys', () => {
- expect(withKeys({ a: '123', b: 456, c: 'd' }, { b: 'lorem', c: 'ipsum', z: 'zed ' })).toEqual(
- { lorem: 456, ipsum: 'd' },
- );
+ expect(
+ withKeys({ a: '123', b: 456, c: 'd' }, { b: 'lorem', c: 'ipsum', z: 'zed ' }),
+ ).toEqual({ lorem: 456, ipsum: 'd' });
});
});
diff --git a/spec/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/graphql/mutations/namespace/package_settings/update_spec.rb
new file mode 100644
index 00000000000..bd0d38cb49f
--- /dev/null
+++ b/spec/graphql/mutations/namespace/package_settings/update_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Namespace::PackageSettings::Update do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:namespace) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ let(:params) { { namespace_path: namespace.full_path } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:create_package_settings) }
+
+ describe '#resolve' do
+ subject { described_class.new(object: namespace, context: { current_user: user }, field: nil).resolve(**params) }
+
+ RSpec.shared_examples 'returning a success' do
+ it 'returns the namespace package setting with no errors' do
+ expect(subject).to eq(
+ package_settings: package_settings,
+ errors: []
+ )
+ end
+ end
+
+ RSpec.shared_examples 'updating the namespace package setting' do
+ it_behaves_like 'updating the namespace package setting attributes', from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' }
+
+ it_behaves_like 'returning a success'
+
+ context 'with invalid params' do
+ let_it_be(:params) { { namespace_path: namespace.full_path, maven_duplicate_exception_regex: '[' } }
+
+ it_behaves_like 'not creating the namespace package setting'
+
+ it 'doesn\'t update the maven_duplicates_allowed' do
+ expect { subject }
+ .not_to change { package_settings.reload.maven_duplicates_allowed }
+ end
+
+ it 'returns an error' do
+ expect(subject).to eq(
+ package_settings: nil,
+ errors: ['Maven duplicate exception regex not valid RE2 syntax: missing ]: [']
+ )
+ end
+ end
+ end
+
+ RSpec.shared_examples 'denying access to namespace package setting' do
+ it 'raises Gitlab::Graphql::Errors::ResourceNotAvailable' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with existing namespace package setting' do
+ let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) }
+ let_it_be(:params) { { namespace_path: namespace.full_path, maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' } }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'updating the namespace package setting'
+ :developer | 'updating the namespace package setting'
+ :reporter | 'denying access to namespace package setting'
+ :guest | 'denying access to namespace package setting'
+ :anonymous | 'denying access to namespace package setting'
+ end
+
+ with_them do
+ before do
+ namespace.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+
+ context 'without existing namespace package setting' do
+ let_it_be(:package_settings) { namespace.package_settings }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'creating the namespace package setting'
+ :developer | 'creating the namespace package setting'
+ :reporter | 'denying access to namespace package setting'
+ :guest | 'denying access to namespace package setting'
+ :anonymous | 'denying access to namespace package setting'
+ end
+
+ with_them do
+ before do
+ namespace.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/releases/create_spec.rb b/spec/graphql/mutations/releases/create_spec.rb
index d6305691dac..7776f968346 100644
--- a/spec/graphql/mutations/releases/create_spec.rb
+++ b/spec/graphql/mutations/releases/create_spec.rb
@@ -88,12 +88,9 @@ RSpec.describe Mutations::Releases::Create do
it 'creates the release with the correct milestone associations' do
expected_milestone_titles = [milestone_12_3.title, milestone_12_4.title]
- actual_milestone_titles = new_release.milestones.map { |m| m.title }
+ actual_milestone_titles = new_release.milestones.order_by_dates_and_title.map { |m| m.title }
- # Right now the milestones are returned in a non-deterministic order.
- # `match_array` should be updated to `eq` once
- # https://gitlab.com/gitlab-org/gitlab/-/issues/259012 is addressed.
- expect(actual_milestone_titles).to match_array(expected_milestone_titles)
+ expect(actual_milestone_titles).to eq(expected_milestone_titles)
end
describe 'asset links' do
diff --git a/spec/graphql/mutations/releases/update_spec.rb b/spec/graphql/mutations/releases/update_spec.rb
index 0406e9c96f3..c541afd53a1 100644
--- a/spec/graphql/mutations/releases/update_spec.rb
+++ b/spec/graphql/mutations/releases/update_spec.rb
@@ -48,12 +48,7 @@ RSpec.describe Mutations::Releases::Update do
expect(updated_release.name).to eq(name) unless except_for == :name
expect(updated_release.description).to eq(description) unless except_for == :description
expect(updated_release.released_at).to eq(released_at) unless except_for == :released_at
-
- # Right now the milestones are returned in a non-deterministic order.
- # Because of this, we need to allow for milestones to be returned in any order.
- # Once https://gitlab.com/gitlab-org/gitlab/-/issues/259012 has been
- # fixed, this can be updated to expect a specific order.
- expect(updated_release.milestones).to match_array([milestone_12_3, milestone_12_4]) unless except_for == :milestones
+ expect(updated_release.milestones.order_by_dates_and_title).to eq([milestone_12_3, milestone_12_4]) unless except_for == :milestones
end
end
diff --git a/spec/graphql/resolvers/ci/config_resolver_spec.rb b/spec/graphql/resolvers/ci/config_resolver_spec.rb
index 6911acdb4ec..ca7ae73fef8 100644
--- a/spec/graphql/resolvers/ci/config_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/config_resolver_spec.rb
@@ -7,16 +7,26 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
describe '#resolve' do
before do
- yaml_processor_double = instance_double(::Gitlab::Ci::YamlProcessor)
- allow(yaml_processor_double).to receive(:execute).and_return(fake_result)
+ ci_lint_double = instance_double(::Gitlab::Ci::Lint)
+ allow(ci_lint_double).to receive(:validate).and_return(fake_result)
- allow(::Gitlab::Ci::YamlProcessor).to receive(:new).and_return(yaml_processor_double)
+ allow(::Gitlab::Ci::Lint).to receive(:new).and_return(ci_lint_double)
+ end
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
+
+ subject(:response) do
+ resolve(described_class,
+ args: { project_path: project.full_path, content: content },
+ ctx: { current_user: user })
end
context 'with a valid .gitlab-ci.yml' do
let(:fake_result) do
- ::Gitlab::Ci::YamlProcessor::Result.new(
- ci_config: ::Gitlab::Ci::Config.new(content),
+ ::Gitlab::Ci::Lint::Result.new(
+ merged_yaml: content,
+ jobs: [],
errors: [],
warnings: []
)
@@ -27,8 +37,6 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
end
it 'lints the ci config file' do
- response = resolve(described_class, args: { content: content }, ctx: {})
-
expect(response[:status]).to eq(:valid)
expect(response[:errors]).to be_empty
end
@@ -38,16 +46,15 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
let(:content) { 'invalid' }
let(:fake_result) do
- Gitlab::Ci::YamlProcessor::Result.new(
- ci_config: nil,
+ Gitlab::Ci::Lint::Result.new(
+ jobs: [],
+ merged_yaml: content,
errors: ['Invalid configuration format'],
warnings: []
)
end
it 'responds with errors about invalid syntax' do
- response = resolve(described_class, args: { content: content }, ctx: {})
-
expect(response[:status]).to eq(:invalid)
expect(response[:errors]).to eq(['Invalid configuration format'])
end
diff --git a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
index 46ee74a5f7e..c44f6b623d7 100644
--- a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe Resolvers::Ci::JobsResolver do
include GraphqlHelpers
- let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
before_all do
create(:ci_build, name: 'Normal job', pipeline: pipeline)
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index f6f746a8572..269ee9eabf9 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -264,13 +264,13 @@ RSpec.describe Resolvers::IssuesResolver do
end
it 'finds a specific issue with iid', :request_store do
- result = batch_sync(max_queries: 2) { resolve_issues(iid: issue1.iid) }
+ result = batch_sync(max_queries: 4) { resolve_issues(iid: issue1.iid) }
expect(result).to contain_exactly(issue1)
end
it 'batches queries that only include IIDs', :request_store do
- result = batch_sync(max_queries: 2) do
+ result = batch_sync(max_queries: 4) do
[issue1, issue2]
.map { |issue| resolve_issues(iid: issue.iid.to_s) }
.flat_map(&:to_a)
@@ -280,7 +280,7 @@ RSpec.describe Resolvers::IssuesResolver do
end
it 'finds a specific issue with iids', :request_store do
- result = batch_sync(max_queries: 2) do
+ result = batch_sync(max_queries: 4) do
resolve_issues(iids: [issue1.iid])
end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index 63fbd04848d..50b9243efa5 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -231,6 +231,16 @@ RSpec.describe Resolvers::MergeRequestsResolver do
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]
end
+
+ context 'when label filter is given and the optimized_issuable_label_filter feature flag is off' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: false)
+ end
+
+ it 'does not raise PG::GroupingError' do
+ expect { resolve_mr(project, sort: :merged_at_desc, labels: %w[a b]) }.not_to raise_error
+ end
+ end
end
end
end
diff --git a/spec/graphql/resolvers/package_details_resolver_spec.rb b/spec/graphql/resolvers/package_details_resolver_spec.rb
new file mode 100644
index 00000000000..825b2aed40a
--- /dev/null
+++ b/spec/graphql/resolvers/package_details_resolver_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::PackageDetailsResolver do
+ include GraphqlHelpers
+
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:package) { create(:composer_package, project: project) }
+
+ describe '#resolve' do
+ let(:args) do
+ { id: package.to_global_id.to_s }
+ end
+
+ subject { resolve(described_class, ctx: { current_user: user }, args: args).sync }
+
+ it { is_expected.to eq(package) }
+ end
+end
diff --git a/spec/graphql/resolvers/projects_resolver_spec.rb b/spec/graphql/resolvers/projects_resolver_spec.rb
index 3de54c7e410..34ddc9cd8cb 100644
--- a/spec/graphql/resolvers/projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects_resolver_spec.rb
@@ -129,7 +129,7 @@ RSpec.describe Resolvers::ProjectsResolver do
let(:filters) { { search: 'projA', sort: 'similarity' } }
it 'returns projects in order of similarity to search' do
- stub_feature_flags(project_finder_similarity_sort: true)
+ stub_feature_flags(project_finder_similarity_sort: current_user)
is_expected.to eq([named_project3, named_project1, named_project2])
end
diff --git a/spec/graphql/resolvers/release_milestones_resolver_spec.rb b/spec/graphql/resolvers/release_milestones_resolver_spec.rb
new file mode 100644
index 00000000000..5f66cba859d
--- /dev/null
+++ b/spec/graphql/resolvers/release_milestones_resolver_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::ReleaseMilestonesResolver do
+ include GraphqlHelpers
+
+ let_it_be(:release) { create(:release, :with_milestones, milestones_count: 2) }
+
+ let(:resolved) do
+ resolve(described_class, obj: release)
+ end
+
+ describe '#resolve' do
+ it "returns an OffsetActiveRecordRelationConnection" do
+ expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
+ end
+
+ it "includes the release's milestones in the returned OffsetActiveRecordRelationConnection" do
+ expect(resolved.items).to eq(release.milestones.order_by_dates_and_title)
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/user_notes_count_resolver_spec.rb b/spec/graphql/resolvers/user_notes_count_resolver_spec.rb
index 3cb0810c698..6cf23a2f57f 100644
--- a/spec/graphql/resolvers/user_notes_count_resolver_spec.rb
+++ b/spec/graphql/resolvers/user_notes_count_resolver_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Resolvers::UserNotesCountResolver do
context 'when a user does not have permission to view notes' do
subject { batch_sync { resolve_user_notes_count(private_issue) } }
- it 'returns no notes' do
+ it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
@@ -80,7 +80,7 @@ RSpec.describe Resolvers::UserNotesCountResolver do
context 'when a user does not have permission to view notes' do
subject { batch_sync { resolve_user_notes_count(private_merge_request) } }
- it 'returns no notes' do
+ it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
diff --git a/spec/graphql/resolvers/users_resolver_spec.rb b/spec/graphql/resolvers/users_resolver_spec.rb
index 1aa24055a89..031d7c99eef 100644
--- a/spec/graphql/resolvers/users_resolver_spec.rb
+++ b/spec/graphql/resolvers/users_resolver_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Resolvers::UsersResolver do
context 'when both ids and usernames are passed ' do
it 'raises an error' do
- expect { resolve_users(ids: [user1.to_global_id.to_s], usernames: [user1.username]) }
+ expect { resolve_users( args: { ids: [user1.to_global_id.to_s], usernames: [user1.username] } ) }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end
@@ -35,7 +35,7 @@ RSpec.describe Resolvers::UsersResolver do
context 'when a set of IDs is passed' do
it 'returns those users' do
expect(
- resolve_users(ids: [user1.to_global_id.to_s, user2.to_global_id.to_s])
+ resolve_users( args: { ids: [user1.to_global_id.to_s, user2.to_global_id.to_s] } )
).to contain_exactly(user1, user2)
end
end
@@ -43,21 +43,31 @@ RSpec.describe Resolvers::UsersResolver do
context 'when a set of usernames is passed' do
it 'returns those users' do
expect(
- resolve_users(usernames: [user1.username, user2.username])
+ resolve_users( args: { usernames: [user1.username, user2.username] } )
).to contain_exactly(user1, user2)
end
end
+ context 'when admins is true', :enable_admin_mode do
+ let(:admin_user) { create(:user, :admin) }
+
+ it 'returns only admins' do
+ expect(
+ resolve_users( args: { admins: true }, ctx: { current_user: admin_user } )
+ ).to contain_exactly(admin_user)
+ end
+ end
+
context 'when a search term is passed' do
it 'returns all users who match', :aggregate_failures do
- expect(resolve_users(search: "some")).to contain_exactly(user1, user2)
- expect(resolve_users(search: "123784")).to contain_exactly(user2)
- expect(resolve_users(search: "someperson")).to contain_exactly(user1)
+ expect(resolve_users( args: { search: "some" } )).to contain_exactly(user1, user2)
+ expect(resolve_users( args: { search: "123784" } )).to contain_exactly(user2)
+ expect(resolve_users( args: { search: "someperson" } )).to contain_exactly(user1)
end
end
end
- def resolve_users(args = {})
- resolve(described_class, args: args)
+ def resolve_users(args: {}, ctx: {})
+ resolve(described_class, args: args, ctx: ctx)
end
end
diff --git a/spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb b/spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb
index de8143a5466..ffb1a0f30c9 100644
--- a/spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb
+++ b/spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb
@@ -8,4 +8,48 @@ RSpec.describe GitlabSchema.types['InstanceStatisticsMeasurement'] do
it { is_expected.to have_graphql_field(:recorded_at) }
it { is_expected.to have_graphql_field(:identifier) }
it { is_expected.to have_graphql_field(:count) }
+
+ describe 'authorization' do
+ let_it_be(:measurement) { create(:instance_statistics_measurement, :project_count) }
+ let(:user) { create(:user) }
+
+ let(:query) do
+ <<~GRAPHQL
+ query instanceStatisticsMeasurements($identifier: MeasurementIdentifier!) {
+ instanceStatisticsMeasurements(identifier: $identifier) {
+ nodes {
+ count
+ identifier
+ }
+ }
+ }
+ GRAPHQL
+ end
+
+ subject do
+ GitlabSchema.execute(
+ query,
+ variables: { identifier: 'PROJECTS' },
+ context: { current_user: user }
+ ).to_h
+ end
+
+ context 'when the user is not admin' do
+ it 'returns no data' do
+ expect(subject.dig('data', 'instanceStatisticsMeasurements')).to be_nil
+ end
+ end
+
+ context 'when user is an admin' do
+ let(:user) { create(:user, :admin) }
+
+ before do
+ stub_feature_flags(user_mode_in_session: false)
+ end
+
+ it 'returns data' do
+ expect(subject.dig('data', 'instanceStatisticsMeasurements', 'nodes')).not_to be_empty
+ end
+ end
+ end
end
diff --git a/spec/graphql/types/base_enum_spec.rb b/spec/graphql/types/base_enum_spec.rb
index b7adcf217f6..744aee40044 100644
--- a/spec/graphql/types/base_enum_spec.rb
+++ b/spec/graphql/types/base_enum_spec.rb
@@ -3,7 +3,75 @@
require 'spec_helper'
RSpec.describe Types::BaseEnum do
- describe '#enum' do
+ describe '.declarative_enum' do
+ let(:use_name) { true }
+ let(:use_description) { true }
+ let(:enum_type) do
+ Class.new(described_class) do
+ graphql_name 'OriginalName'
+ description 'Original description'
+ end
+ end
+
+ let(:enum_module) do
+ Module.new do
+ extend DeclarativeEnum
+
+ name 'Name'
+ description 'Description'
+
+ define do
+ foo value: 0, description: 'description of foo'
+ end
+ end
+ end
+
+ subject(:set_declarative_enum) { enum_type.declarative_enum(enum_module, use_name: use_name, use_description: use_description) }
+
+ describe '#graphql_name' do
+ context 'when the use_name is `true`' do
+ it 'changes the graphql_name' do
+ expect { set_declarative_enum }.to change { enum_type.graphql_name }.from('OriginalName').to('Name')
+ end
+ end
+
+ context 'when the use_name is `false`' do
+ let(:use_name) { false }
+
+ it 'does not change the graphql_name' do
+ expect { set_declarative_enum }.not_to change { enum_type.graphql_name }.from('OriginalName')
+ end
+ end
+ end
+
+ describe '#description' do
+ context 'when the use_description is `true`' do
+ it 'changes the description' do
+ expect { set_declarative_enum }.to change { enum_type.description }.from('Original description').to('Description')
+ end
+ end
+
+ context 'when the use_description is `false`' do
+ let(:use_description) { false }
+
+ it 'does not change the description' do
+ expect { set_declarative_enum }.not_to change { enum_type.description }.from('Original description')
+ end
+ end
+ end
+
+ describe '#values' do
+ it 'sets the values defined by the declarative enum' do
+ set_declarative_enum
+
+ expect(enum_type.values.keys).to eq(['FOO'])
+ expect(enum_type.values.values.map(&:description)).to eq(['description of foo'])
+ expect(enum_type.values.values.map(&:value)).to eq([0])
+ end
+ end
+ end
+
+ describe '.enum' do
let(:enum) do
Class.new(described_class) do
value 'TEST', value: 3
diff --git a/spec/graphql/types/board_type_spec.rb b/spec/graphql/types/board_type_spec.rb
index b02b342390d..5ea87d5f473 100644
--- a/spec/graphql/types/board_type_spec.rb
+++ b/spec/graphql/types/board_type_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['Board'] do
specify { expect(described_class).to require_graphql_authorizations(:read_board) }
it 'has specific fields' do
- expected_fields = %w[id name]
+ expected_fields = %w[id name web_url web_path]
expect(described_class).to include_graphql_fields(*expected_fields)
end
diff --git a/spec/graphql/types/ci/config/job_restriction_type_spec.rb b/spec/graphql/types/ci/config/job_restriction_type_spec.rb
new file mode 100644
index 00000000000..dd46a38b7c2
--- /dev/null
+++ b/spec/graphql/types/ci/config/job_restriction_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::Config::JobRestrictionType do
+ specify { expect(described_class.graphql_name).to eq('CiConfigJobRestriction') }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[refs]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/config/job_type_spec.rb b/spec/graphql/types/ci/config/job_type_spec.rb
index 600d665a84b..de4e167f69c 100644
--- a/spec/graphql/types/ci/config/job_type_spec.rb
+++ b/spec/graphql/types/ci/config/job_type_spec.rb
@@ -7,10 +7,19 @@ RSpec.describe Types::Ci::Config::JobType do
it 'exposes the expected fields' do
expected_fields = %i[
+ afterScript
+ allowFailure
+ beforeScript
+ environment
+ except
+ script
name
+ only
group_name
stage
+ tags
needs
+ when
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/ci/job_type_spec.rb b/spec/graphql/types/ci/job_type_spec.rb
index 441a719df8c..e277916f5cb 100644
--- a/spec/graphql/types/ci/job_type_spec.rb
+++ b/spec/graphql/types/ci/job_type_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Types::Ci::JobType do
specify { expect(described_class.graphql_name).to eq('CiJob') }
+ specify { expect(described_class).to require_graphql_authorizations(:read_commit_status) }
it 'exposes the expected fields' do
expected_fields = %i[
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index 558fc479af1..21fc530149c 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -17,7 +17,8 @@ RSpec.describe GitlabSchema.types['Issue'] do
fields = %i[id iid title description state reference author assignees updated_by participants labels milestone due_date
confidential discussion_locked upvotes downvotes user_notes_count user_discussions_count web_path web_url relative_position
emails_disabled subscribed time_estimate total_time_spent human_time_estimate human_total_time_spent closed_at created_at updated_at task_completion_status
- design_collection alert_management_alert severity current_user_todos moved moved_to]
+ design_collection alert_management_alert severity current_user_todos moved moved_to
+ create_note_email]
fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name)
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index 51e7b4029d5..63d288934e5 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -25,21 +25,15 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
merge_ongoing mergeable_discussions_state web_url
source_branch_exists target_branch_exists
upvotes downvotes head_pipeline pipelines task_completion_status
- milestone assignees participants subscribed labels discussion_locked time_estimate
+ milestone assignees reviewers participants subscribed labels discussion_locked time_estimate
total_time_spent reference author merged_at commit_count current_user_todos
conflicts auto_merge_enabled approved_by source_branch_protected
default_merge_commit_message_with_description squash_on_merge available_auto_merge_strategies
- has_ci mergeable commits_without_merge_commits security_auto_fix
+ has_ci mergeable commits_without_merge_commits squash security_auto_fix default_squash_commit_message
+ auto_merge_strategy merge_user
]
- if Gitlab.ee?
- expected_fields << 'approved'
- expected_fields << 'approvals_left'
- expected_fields << 'approvals_required'
- expected_fields << 'merge_trains_count'
- end
-
- expect(described_class).to have_graphql_fields(*expected_fields)
+ expect(described_class).to have_graphql_fields(*expected_fields).at_least
end
describe '#pipelines' do
diff --git a/spec/graphql/types/namespace/package_settings_type_spec.rb b/spec/graphql/types/namespace/package_settings_type_spec.rb
new file mode 100644
index 00000000000..b9592d230ca
--- /dev/null
+++ b/spec/graphql/types/namespace/package_settings_type_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageSettings'] do
+ specify { expect(described_class.graphql_name).to eq('PackageSettings') }
+
+ specify { expect(described_class.description).to eq('Namespace-level Package Registry settings') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_package_settings) }
+
+ describe 'maven_duplicate_exception_regex field' do
+ subject { described_class.fields['mavenDuplicateExceptionRegex'] }
+
+ it { is_expected.to have_graphql_type(Types::UntrustedRegexp) }
+ end
+end
diff --git a/spec/graphql/types/notes/note_type_spec.rb b/spec/graphql/types/notes/note_type_spec.rb
index 180d13d35d2..03ff7828cf5 100644
--- a/spec/graphql/types/notes/note_type_spec.rb
+++ b/spec/graphql/types/notes/note_type_spec.rb
@@ -22,6 +22,7 @@ RSpec.describe GitlabSchema.types['Note'] do
system_note_icon_name
updated_at
user_permissions
+ url
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/package_type_spec.rb b/spec/graphql/types/package_type_spec.rb
deleted file mode 100644
index 22048e7a693..00000000000
--- a/spec/graphql/types/package_type_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-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
- ]
-
- expect(described_class).to include_graphql_fields(*expected_fields)
- end
-end
diff --git a/spec/graphql/types/packages/composer/details_type_spec.rb b/spec/graphql/types/packages/composer/details_type_spec.rb
new file mode 100644
index 00000000000..2e4cb965ded
--- /dev/null
+++ b/spec/graphql/types/packages/composer/details_type_spec.rb
@@ -0,0 +1,23 @@
+# 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/json_type_spec.rb b/spec/graphql/types/packages/composer/json_type_spec.rb
new file mode 100644
index 00000000000..af5194ffb49
--- /dev/null
+++ b/spec/graphql/types/packages/composer/json_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageComposerJsonType'] do
+ it { expect(described_class.graphql_name).to eq('PackageComposerJsonType') }
+
+ it 'includes composer json files' do
+ expected_fields = %w[
+ name type license version
+ ]
+
+ 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
new file mode 100644
index 00000000000..0f47d8f1812
--- /dev/null
+++ b/spec/graphql/types/packages/composer/metadatum_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageComposerMetadatumType'] do
+ it { expect(described_class.graphql_name).to eq('PackageComposerMetadatumType') }
+
+ it 'includes composer metadatum fields' do
+ expected_fields = %w[
+ target_sha composer_json
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/package_type_enum_spec.rb b/spec/graphql/types/packages/package_type_enum_spec.rb
index 407d5786f65..407d5786f65 100644
--- a/spec/graphql/types/package_type_enum_spec.rb
+++ b/spec/graphql/types/packages/package_type_enum_spec.rb
diff --git a/spec/graphql/types/packages/package_type_spec.rb b/spec/graphql/types/packages/package_type_spec.rb
new file mode 100644
index 00000000000..7003a4d4d07
--- /dev/null
+++ b/spec/graphql/types/packages/package_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+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
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/tag_type_spec.rb b/spec/graphql/types/packages/tag_type_spec.rb
new file mode 100644
index 00000000000..83b705157d8
--- /dev/null
+++ b/spec/graphql/types/packages/tag_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageTag'] do
+ it { expect(described_class.graphql_name).to eq('PackageTag') }
+
+ it 'includes all the package tag fields' do
+ expected_fields = %w[
+ id name created_at updated_at
+ ]
+
+ 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 b3028e034cc..9d0d7a3918a 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -31,7 +31,7 @@ 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 total_pipeline_duration squash_read_only
+ pipeline_analytics squash_read_only
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/projects/service_type_spec.rb b/spec/graphql/types/projects/service_type_spec.rb
index f110322ac89..cca7c49e132 100644
--- a/spec/graphql/types/projects/service_type_spec.rb
+++ b/spec/graphql/types/projects/service_type_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Types::Projects::ServiceType do
it 'resolves the corresponding type for objects' do
expect(described_class.resolve_type(build(:jira_service), {})).to eq(Types::Projects::Services::JiraServiceType)
expect(described_class.resolve_type(build(:service), {})).to eq(Types::Projects::Services::BaseServiceType)
- expect(described_class.resolve_type(build(:alerts_service), {})).to eq(Types::Projects::Services::BaseServiceType)
+ expect(described_class.resolve_type(build(:drone_ci_service), {})).to eq(Types::Projects::Services::BaseServiceType)
expect(described_class.resolve_type(build(:custom_issue_tracker_service), {})).to eq(Types::Projects::Services::BaseServiceType)
end
end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index 7a0b3035607..3e716865e56 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -94,4 +94,10 @@ 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'] }
+
+ it { is_expected.to have_graphql_type(Types::Packages::Composer::DetailsType) }
+ end
end
diff --git a/spec/graphql/types/repository_type_spec.rb b/spec/graphql/types/repository_type_spec.rb
index 27780476421..e9199bd286e 100644
--- a/spec/graphql/types/repository_type_spec.rb
+++ b/spec/graphql/types/repository_type_spec.rb
@@ -10,4 +10,6 @@ RSpec.describe GitlabSchema.types['Repository'] do
specify { expect(described_class).to have_graphql_field(:root_ref) }
specify { expect(described_class).to have_graphql_field(:tree) }
+
+ specify { expect(described_class).to have_graphql_field(:exists, calls_gitaly?: true, complexity: 2) }
end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 764c582e987..b584a906565 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe BlobHelper do
end
end
- describe "#edit_blob_link" do
+ describe "#edit_blob_button" do
let(:namespace) { create(:namespace, name: 'gitlab') }
let(:project) { create(:project, :repository, namespace: namespace) }
@@ -28,12 +28,13 @@ RSpec.describe BlobHelper do
allow(helper).to receive(:can_collaborate_with_project?).and_return(true)
end
- it 'verifies blob is text' do
+ it 'does not render edit button when blob is not text' do
expect(helper).not_to receive(:blob_text_viewable?)
- button = helper.edit_blob_button(project, 'refs/heads/master', 'README.md')
+ # RADME.md is not a valid file.
+ button = helper.edit_blob_button(project, 'refs/heads/master', 'RADME.md')
- expect(button).to start_with('<button')
+ expect(button).to eq(nil)
end
it 'uses the passed blob instead retrieve from repository' do
@@ -94,7 +95,7 @@ RSpec.describe BlobHelper do
context 'viewer related' do
include FakeBlobHelpers
- let(:project) { build(:project, lfs_enabled: true) }
+ let_it_be(:project) { create(:project, lfs_enabled: true) }
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
diff --git a/spec/helpers/ci/pipelines_helper_spec.rb b/spec/helpers/ci/pipelines_helper_spec.rb
index a96d6e7711f..94b5e707d73 100644
--- a/spec/helpers/ci/pipelines_helper_spec.rb
+++ b/spec/helpers/ci/pipelines_helper_spec.rb
@@ -52,4 +52,23 @@ RSpec.describe Ci::PipelinesHelper do
end
end
end
+
+ describe 'has_gitlab_ci?' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject(:has_gitlab_ci?) { helper.has_gitlab_ci?(project) }
+
+ let(:project) { double(:project, has_ci?: has_ci?, builds_enabled?: builds_enabled?) }
+
+ where(:builds_enabled?, :has_ci?, :result) do
+ true | true | true
+ true | false | false
+ false | true | false
+ false | false | false
+ end
+
+ with_them do
+ it { expect(has_gitlab_ci?).to eq(result) }
+ end
+ end
end
diff --git a/spec/helpers/ci/triggers_helper_spec.rb b/spec/helpers/ci/triggers_helper_spec.rb
new file mode 100644
index 00000000000..5e43dbfdd5c
--- /dev/null
+++ b/spec/helpers/ci/triggers_helper_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::TriggersHelper do
+ let(:project_id) { 1 }
+
+ describe '.builds_trigger_url' do
+ subject { helper.builds_trigger_url(project_id, ref: ref) }
+
+ context 'with no ref' do
+ let(:ref) { nil }
+
+ specify { expect(subject).to eq "#{Settings.gitlab.url}/api/v4/projects/1/trigger/pipeline" }
+ end
+
+ context 'with ref' do
+ let(:ref) { 'master' }
+
+ specify { expect(subject).to eq "#{Settings.gitlab.url}/api/v4/projects/1/ref/master/trigger/pipeline" }
+ end
+ end
+
+ describe '.service_trigger_url' do
+ subject { helper.service_trigger_url(service) }
+
+ let(:service) { double(project_id: 1, to_param: 'param') }
+
+ specify { expect(subject).to eq "#{Settings.gitlab.url}/api/v4/projects/1/services/param/trigger" }
+ end
+end
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index cc318a21fc9..8a570bf9a90 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -3,6 +3,39 @@
require 'spec_helper'
RSpec.describe CommitsHelper do
+ describe '#revert_commit_link' 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)
+
+ expect(result).to include('js-revert-commit-trigger')
+ end
+
+ it 'does not render a div for Vue' do
+ result = helper.revert_commit_link('_commit_', '_path_')
+
+ expect(result).not_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(double('Commit'), '_path_')
+
+ expect(result).to be_nil
+ end
+ end
+ end
+
describe 'commit_author_link' do
it 'escapes the author email' do
commit = double(
diff --git a/spec/helpers/dashboard_helper_spec.rb b/spec/helpers/dashboard_helper_spec.rb
index 65182dcb729..8a76771be0a 100644
--- a/spec/helpers/dashboard_helper_spec.rb
+++ b/spec/helpers/dashboard_helper_spec.rb
@@ -89,4 +89,10 @@ RSpec.describe DashboardHelper do
it { is_expected.to eq(false) }
end
+
+ describe '#reviewer_mrs_dashboard_path' do
+ subject { helper.reviewer_mrs_dashboard_path }
+
+ it { is_expected.to eq(merge_requests_dashboard_path(reviewer_username: user.username)) }
+ end
end
diff --git a/spec/helpers/graph_helper_spec.rb b/spec/helpers/graph_helper_spec.rb
index 3c7e4f970c3..682f6365481 100644
--- a/spec/helpers/graph_helper_spec.rb
+++ b/spec/helpers/graph_helper_spec.rb
@@ -15,4 +15,16 @@ RSpec.describe GraphHelper do
expect(refs).to match('master')
end
end
+
+ describe '#should_render_deployment_frequency_charts' do
+ let(:project) { create(:project, :private) }
+
+ before do
+ self.instance_variable_set(:@project, project)
+ end
+
+ it 'always returns false' do
+ expect(should_render_deployment_frequency_charts).to be(false)
+ end
+ end
end
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index 222cca43860..d75124b6da7 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -34,38 +34,38 @@ RSpec.describe Groups::GroupMembersHelper do
end
describe '#members_data_json' do
- shared_examples 'group_members.json' do
+ shared_examples 'members.json' do
it 'matches json schema' do
json = helper.members_data_json(group, present_members([group_member]))
- expect(json).to match_schema('group_members')
+ expect(json).to match_schema('members')
end
end
context 'for a group member' do
let(:group_member) { create(:group_member, group: group, created_by: current_user) }
- it_behaves_like 'group_members.json'
+ it_behaves_like 'members.json'
context 'with user status set' do
let(:user) { create(:user) }
let!(:status) { create(:user_status, user: user) }
let(:group_member) { create(:group_member, group: group, user: user, created_by: current_user) }
- it_behaves_like 'group_members.json'
+ it_behaves_like 'members.json'
end
end
context 'for an invited group member' do
let(:group_member) { create(:group_member, :invited, group: group, created_by: current_user) }
- it_behaves_like 'group_members.json'
+ it_behaves_like 'members.json'
end
context 'for an access request' do
let(:group_member) { create(:group_member, :access_request, group: group, created_by: current_user) }
- it_behaves_like 'group_members.json'
+ it_behaves_like 'members.json'
end
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index d75b3c9f2e3..914d0931476 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -114,4 +114,69 @@ RSpec.describe InviteMembersHelper do
end
end
end
+
+ describe '#dropdown_invite_members_link' do
+ shared_examples_for 'dropdown invite members link' do
+ let(:link_regex) do
+ /data-track-event="click_link".*data-track-property="_track_property_".*Invite members/
+ end
+
+ before do
+ allow(helper).to receive(:experiment_tracking_category_and_group) { '_track_property_' }
+ allow(helper).to receive(:tracking_label).with(owner)
+ allow(helper).to receive(:current_user) { owner }
+ end
+
+ it 'records the experiment' do
+ allow(helper).to receive(:experiment_enabled?)
+
+ helper.dropdown_invite_members_link(form_model)
+
+ expect(helper).to have_received(:experiment_tracking_category_and_group)
+ .with(:invite_members_new_dropdown, subject: owner)
+ end
+
+ context 'with experiment enabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { true }
+ end
+
+ it 'returns link' do
+ link = helper.dropdown_invite_members_link(form_model)
+
+ expect(link).to match(link_regex)
+ expect(link).to include(link_href)
+ expect(link).to include('gl-emoji')
+ end
+ end
+
+ context 'with no experiment enabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { false }
+ end
+
+ it 'returns link' do
+ link = helper.dropdown_invite_members_link(form_model)
+
+ expect(link).to match(link_regex)
+ expect(link).to include(link_href)
+ expect(link).not_to include('gl-emoji')
+ end
+ end
+ end
+
+ context 'with a project' do
+ let_it_be(:form_model) { project }
+ let(:link_href) { "href=\"#{project_project_members_path(form_model)}\"" }
+
+ it_behaves_like 'dropdown invite members link'
+ end
+
+ context 'with a group' do
+ let_it_be(:form_model) { create(:group) }
+ let(:link_href) { "href=\"#{group_group_members_path(form_model)}\"" }
+
+ it_behaves_like 'dropdown invite members link'
+ end
+ end
end
diff --git a/spec/helpers/jira_connect_helper_spec.rb b/spec/helpers/jira_connect_helper_spec.rb
new file mode 100644
index 00000000000..a99072527c8
--- /dev/null
+++ b/spec/helpers/jira_connect_helper_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnectHelper do
+ describe '#jira_connect_app_data' do
+ subject { helper.jira_connect_app_data }
+
+ it 'includes Jira Connect app attributes' do
+ is_expected.to include(
+ :groups_path
+ )
+ end
+ end
+end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 377e2c43a72..821faaab194 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -67,4 +67,37 @@ RSpec.describe MergeRequestsHelper do
end
end
end
+
+ describe '#user_merge_requests_counts' do
+ let(:user) do
+ double(
+ assigned_open_merge_requests_count: 1,
+ review_requested_open_merge_requests_count: 2
+ )
+ end
+
+ subject { helper.user_merge_requests_counts }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it "returns assigned, review requested and total merge request counts" do
+ expect(subject).to eq(
+ assigned: user.assigned_open_merge_requests_count,
+ review_requested: user.review_requested_open_merge_requests_count,
+ 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/projects/project_members_helper_spec.rb b/spec/helpers/projects/project_members_helper_spec.rb
new file mode 100644
index 00000000000..cc290367e34
--- /dev/null
+++ b/spec/helpers/projects/project_members_helper_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ProjectMembersHelper do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ let(:allow_admin_project) { nil }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(helper).to receive(:can?).with(current_user, :admin_project_member, project).and_return(allow_admin_project)
+ end
+
+ shared_examples 'when `current_user` does not have `admin_project_member` permissions' do
+ let(:allow_admin_project) { false }
+
+ it { is_expected.to be(false) }
+ end
+
+ describe '#can_manage_project_members?' do
+ subject { helper.can_manage_project_members?(project) }
+
+ context 'when `current_user` has `admin_project_member` permissions' do
+ let(:allow_admin_project) { true }
+
+ it { is_expected.to be(true) }
+ end
+
+ include_examples 'when `current_user` does not have `admin_project_member` permissions'
+ end
+
+ describe '#show_groups?' do
+ subject { helper.show_groups?(project.project_group_links) }
+
+ context 'when group links exist' do
+ let!(:project_group_link) { create(:project_group_link, project: project) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when `search_groups` param is set' do
+ before do
+ allow(helper).to receive(:params).and_return({ search_groups: 'foo' })
+ end
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when `search_groups` param is not set and group links do not exist' do
+ it { is_expected.to be(false) }
+ end
+ end
+
+ describe '#show_invited_members?' do
+ subject { helper.show_invited_members?(project, project.project_members.invite) }
+
+ context 'when `current_user` has `admin_project_member` permissions' do
+ let(:allow_admin_project) { true }
+
+ context 'when invited members exist' do
+ let!(:invite) { create(:project_member, :invited, project: project) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when invited members do not exist' do
+ it { is_expected.to be(false) }
+ end
+ end
+
+ include_examples 'when `current_user` does not have `admin_project_member` permissions'
+ end
+
+ describe '#show_access_requests?' do
+ subject { helper.show_access_requests?(project, project.requesters) }
+
+ context 'when `current_user` has `admin_project_member` permissions' do
+ let(:allow_admin_project) { true }
+
+ context 'when access requests exist' do
+ let!(:access_request) { create(:project_member, :access_request, project: project) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when access requests do not exist' do
+ it { is_expected.to be(false) }
+ end
+ end
+
+ include_examples 'when `current_user` does not have `admin_project_member` permissions'
+ end
+
+ describe '#groups_tab_active?' do
+ subject { helper.groups_tab_active? }
+
+ context 'when `search_groups` param is set' do
+ before do
+ allow(helper).to receive(:params).and_return({ search_groups: 'foo' })
+ end
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when `search_groups` param is not set' do
+ it { is_expected.to be(false) }
+ end
+ end
+
+ describe '#current_user_is_group_owner?' do
+ let(:group) { create(:group) }
+
+ subject { helper.current_user_is_group_owner?(project2) }
+
+ describe "when current user is the owner of the project's parent group" do
+ let(:project2) { create(:project, namespace: group) }
+
+ before do
+ group.add_owner(current_user)
+ end
+
+ it { is_expected.to be(true) }
+ end
+
+ describe "when current user is not the owner of the project's parent group" do
+ let_it_be(:user) { create(:user) }
+ let(:project2) { create(:project, namespace: group) }
+
+ before do
+ group.add_owner(user)
+ end
+
+ it { is_expected.to be(false) }
+ end
+
+ describe "when project does not have a parent group" do
+ let(:user) { create(:user) }
+ let(:project2) { create(:project, namespace: user.namespace) }
+
+ it { is_expected.to be(false) }
+ end
+ end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index d28d5ecda1b..b920e2e5600 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -92,37 +92,11 @@ RSpec.describe ProjectsHelper do
expect(helper.can_change_visibility_level?(project, user)).to be_falsey
end
- it "returns true if there are permissions and it is not fork" do
+ it "returns true if there are permissions" do
allow(helper).to receive(:can?) { true }
expect(helper.can_change_visibility_level?(project, user)).to be_truthy
end
-
- it 'allows visibility level to be changed if the project is forked' do
- allow(helper).to receive(:can?).with(user, :change_visibility_level, project) { true }
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- fork_project(project)
-
- expect(helper.can_change_visibility_level?(project, user)).to be_truthy
- end
-
- context "forks" do
- it "returns false if there are permissions and origin project is PRIVATE" do
- allow(helper).to receive(:can?) { true }
-
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
-
- expect(helper.can_change_visibility_level?(forked_project, user)).to be_falsey
- end
-
- it "returns true if there are permissions and origin project is INTERNAL" do
- allow(helper).to receive(:can?) { true }
-
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
-
- expect(helper.can_change_visibility_level?(forked_project, user)).to be_truthy
- end
- end
end
describe '#can_disable_emails?' do
@@ -459,6 +433,7 @@ RSpec.describe ProjectsHelper do
context 'when project has external wiki' do
it 'includes external wiki tab' do
project.create_external_wiki_service(active: true, properties: { 'external_wiki_url' => 'https://gitlab.com' })
+ project.reload
is_expected.to include(:external_wiki)
end
diff --git a/spec/helpers/services_helper_spec.rb b/spec/helpers/services_helper_spec.rb
index 650642f8982..534f33d9b5a 100644
--- a/spec/helpers/services_helper_spec.rb
+++ b/spec/helpers/services_helper_spec.rb
@@ -25,6 +25,10 @@ RSpec.describe ServicesHelper do
:integration_level
)
end
+
+ specify do
+ expect(subject[:reset_path]).to eq(helper.scoped_reset_integration_path(integration))
+ end
end
end
@@ -47,52 +51,12 @@ RSpec.describe ServicesHelper do
is_expected.to eq(reset_group_settings_integration_path(group, integration))
end
end
- end
-
- describe '#reset_integration?' do
- let(:group) { nil }
-
- subject { helper.reset_integration?(integration, group: group) }
-
- context 'when integration is existing record' do
- let_it_be(:integration) { create(:jira_service) }
-
- context 'when `reset_integrations` is not enabled' do
- it 'returns false' do
- stub_feature_flags(reset_integrations: false)
-
- is_expected.to eq(false)
- end
- end
- context 'when `reset_integrations` is enabled' do
- it 'returns true' do
- stub_feature_flags(reset_integrations: true)
-
- is_expected.to eq(true)
- end
- end
-
- context 'when `reset_integrations` is enabled for a group' do
- let(:group) { build_stubbed(:group) }
-
- it 'returns true' do
- stub_feature_flags(reset_integrations: group)
-
- is_expected.to eq(true)
- end
- end
- end
-
- context 'when integration is a new record' do
+ context 'when a new integration is not persisted' do
let_it_be(:integration) { build(:jira_service) }
- context 'when `reset_integrations` is enabled' do
- it 'returns false' do
- stub_feature_flags(reset_integrations: true)
-
- is_expected.to eq(false)
- end
+ it 'returns an empty string' do
+ is_expected.to eq('')
end
end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index 136ec07e73d..6cb9894e306 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -330,9 +330,8 @@ RSpec.describe TreeHelper do
end
end
- context 'gitpod feature is enabled' do
+ context 'gitpod settings is enabled' do
before do
- stub_feature_flags(gitpod: true)
allow(Gitlab::CurrentSettings)
.to receive(:gitpod_enabled)
.and_return(true)
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index c92c6e6e78e..f0f09408249 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -337,10 +337,14 @@ RSpec.describe UsersHelper do
describe '#admin_users_data_attributes' do
subject(:data) { helper.admin_users_data_attributes([user]) }
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
it 'users matches the serialized json' do
entity = double
expect_next_instance_of(Admin::UserSerializer) do |instance|
- expect(instance).to receive(:represent).with([user]).and_return(entity)
+ expect(instance).to receive(:represent).with([user], current_user: user).and_return(entity)
end
expect(entity).to receive(:to_json).and_return("{\"username\":\"admin\"}")
expect(data[:users]).to eq "{\"username\":\"admin\"}"
diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb
index 86b0693af92..10e0815918f 100644
--- a/spec/helpers/visibility_level_helper_spec.rb
+++ b/spec/helpers/visibility_level_helper_spec.rb
@@ -35,29 +35,33 @@ RSpec.describe VisibilityLevelHelper do
describe 'visibility_level_description' do
context 'used with a Project' do
- it 'delegates projects to #project_visibility_level_description' do
- expect(visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, project))
- .to match /project/i
+ let(:descriptions) do
+ [
+ visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, project),
+ visibility_level_description(Gitlab::VisibilityLevel::INTERNAL, project),
+ visibility_level_description(Gitlab::VisibilityLevel::PUBLIC, project)
+ ]
end
- end
- context 'used with a Group' do
- it 'delegates groups to #group_visibility_level_description' do
- expect(visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, group))
- .to match /group/i
+ it 'returns different project related descriptions depending on visibility level' do
+ expect(descriptions.uniq.size).to eq(descriptions.size)
+ expect(descriptions).to all match /project/i
end
end
- end
- describe "#project_visibility_level_description" do
- it "describes private projects" do
- expect(project_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE))
- .to eq _('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.')
- end
+ context 'used with a Group' do
+ let(:descriptions) do
+ [
+ visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, group),
+ visibility_level_description(Gitlab::VisibilityLevel::INTERNAL, group),
+ visibility_level_description(Gitlab::VisibilityLevel::PUBLIC, group)
+ ]
+ end
- it "describes public projects" do
- expect(project_visibility_level_description(Gitlab::VisibilityLevel::PUBLIC))
- .to eq _('The project can be accessed without any authentication.')
+ it 'returns different group related descriptions depending on visibility level' do
+ expect(descriptions.uniq.size).to eq(descriptions.size)
+ expect(descriptions).to all match /group/i
+ end
end
end
diff --git a/spec/initializers/carrierwave_patch_spec.rb b/spec/initializers/carrierwave_patch_spec.rb
index c4a7bfa59c6..cbdad4aa9ac 100644
--- a/spec/initializers/carrierwave_patch_spec.rb
+++ b/spec/initializers/carrierwave_patch_spec.rb
@@ -6,38 +6,95 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' do
let(:uploader_class) { Class.new(CarrierWave::Uploader::Base) }
let(:uploader) { uploader_class.new }
let(:storage) { CarrierWave::Storage::Fog.new(uploader) }
- let(:azure_options) do
- {
- azure_storage_account_name: 'AZURE_ACCOUNT_NAME',
- azure_storage_access_key: 'AZURE_ACCESS_KEY',
- provider: 'AzureRM'
- }
- end
+ let(:bucket_name) { 'some-bucket' }
+ let(:connection) { ::Fog::Storage.new(connection_options) }
+ let(:bucket) { connection.directories.new(key: bucket_name )}
+ let(:test_filename) { 'test' }
+ let(:test_data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
- subject { CarrierWave::Storage::Fog::File.new(uploader, storage, 'test') }
+ subject { CarrierWave::Storage::Fog::File.new(uploader, storage, test_filename) }
before do
require 'fog/azurerm'
- allow(uploader).to receive(:fog_credentials).and_return(azure_options)
- Fog.mock!
+ require 'fog/aws'
+
+ stub_object_storage(connection_params: connection_options, remote_directory: bucket_name)
+
+ allow(uploader).to receive(:fog_directory).and_return(bucket_name)
+ allow(uploader).to receive(:fog_credentials).and_return(connection_options)
+
+ bucket.files.create(key: test_filename, body: test_data) # rubocop:disable Rails/SaveBang
end
- describe '#authenticated_url' do
- context 'with Azure' do
+ context 'AWS' do
+ let(:connection_options) do
+ {
+ provider: 'AWS',
+ aws_access_key_id: 'AWS_ACCESS_KEY',
+ aws_secret_access_key: 'AWS_SECRET_KEY'
+ }
+ end
+
+ describe '#copy_to' do
+ let(:dest_filename) { 'copied.txt'}
+
+ it 'copies the file' do
+ fog_file = subject.send(:file)
+
+ expect(fog_file).to receive(:concurrency=).with(10).and_call_original
+ # multipart_chunk_size must be explicitly set in order to leverage
+ # multithreaded, multipart transfers for files below 5GB.
+ expect(fog_file).to receive(:multipart_chunk_size=).with(10.megabytes).and_call_original
+ expect(fog_file).to receive(:copy).with(bucket_name, dest_filename, anything).and_call_original
+
+ result = subject.copy_to(dest_filename)
+
+ expect(result.exists?).to be true
+ expect(result.read).to eq(test_data)
+
+ # Sanity check that the file actually is there
+ copied = bucket.files.get(dest_filename)
+ expect(copied).to be_present
+ expect(copied.body).to eq(test_data)
+ end
+ end
+ end
+
+ context 'Azure' do
+ let(:connection_options) do
+ {
+ provider: 'AzureRM',
+ azure_storage_account_name: 'AZURE_ACCOUNT_NAME',
+ azure_storage_access_key: 'AZURE_ACCESS_KEY'
+ }
+ end
+
+ describe '#copy_to' do
+ let(:dest_filename) { 'copied.txt'}
+
+ it 'copies the file' do
+ result = subject.copy_to(dest_filename)
+
+ # Fog Azure provider doesn't mock the actual copied data
+ expect(result.exists?).to be true
+ end
+ end
+
+ describe '#authenticated_url' do
it 'has an authenticated URL' do
expect(subject.authenticated_url).to eq("https://sa.blob.core.windows.net/test_container/test_blob?token")
end
- end
- context 'with custom expire_at' do
- it 'properly sets expires param' do
- expire_at = 24.hours.from_now
+ context 'with custom expire_at' do
+ it 'properly sets expires param' do
+ expire_at = 24.hours.from_now
- expect_next_instance_of(Fog::Storage::AzureRM::File) do |file|
- expect(file).to receive(:url).with(expire_at).and_call_original
- end
+ expect_next_instance_of(Fog::Storage::AzureRM::File) do |file|
+ expect(file).to receive(:url).with(expire_at).and_call_original
+ end
- expect(subject.authenticated_url(expire_at: expire_at)).to eq("https://sa.blob.core.windows.net/test_container/test_blob?token")
+ expect(subject.authenticated_url(expire_at: expire_at)).to eq("https://sa.blob.core.windows.net/test_container/test_blob?token")
+ 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 f84cee72042..f92994594a9 100644
--- a/spec/javascripts/fly_out_nav_browser_spec.js
+++ b/spec/javascripts/fly_out_nav_browser_spec.js
@@ -157,7 +157,7 @@ describe('Fly out sidebar navigation', () => {
'<div class="sidebar-sub-level-items" style="position: absolute; top: 0; left: 100px; height: 200px;"></div>';
});
- it('shows sub-items after 0ms if no menu is open', done => {
+ it('shows sub-items after 0ms if no menu is open', (done) => {
mouseEnterTopItems(el);
expect(getHideSubItemsInterval()).toBe(0);
@@ -169,7 +169,7 @@ describe('Fly out sidebar navigation', () => {
});
});
- it('shows sub-items after 300ms if a menu is currently open', done => {
+ it('shows sub-items after 300ms if a menu is currently open', (done) => {
documentMouseMove({
clientX: el.getBoundingClientRect().left,
clientY: el.getBoundingClientRect().top,
@@ -255,8 +255,9 @@ describe('Fly out sidebar navigation', () => {
showSubLevelItems(el);
expect(subItems.style.transform).toBe(
- `translate3d(200px, ${Math.floor(el.getBoundingClientRect().top) -
- getHeaderHeight()}px, 0px)`,
+ `translate3d(200px, ${
+ Math.floor(el.getBoundingClientRect().top) - getHeaderHeight()
+ }px, 0px)`,
);
});
diff --git a/spec/javascripts/lib/utils/browser_spec.js b/spec/javascripts/lib/utils/browser_spec.js
index 6b1074a3b4f..f41fa2503b1 100644
--- a/spec/javascripts/lib/utils/browser_spec.js
+++ b/spec/javascripts/lib/utils/browser_spec.js
@@ -5,30 +5,8 @@
* 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 MockAdapter from 'axios-mock-adapter';
import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils';
-import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
-import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data';
-
-const PIXEL_TOLERANCE = 0.2;
-
-/**
- * Loads a data URL as the src of an
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image|Image}
- * and resolves to that Image once loaded.
- *
- * @param url
- * @returns {Promise}
- */
-const urlToImage = url =>
- new Promise(resolve => {
- const img = new Image();
- img.onload = function() {
- resolve(img);
- };
- img.src = url;
- });
describe('common_utils browser specific specs', () => {
describe('contentTop', () => {
@@ -63,90 +41,6 @@ describe('common_utils browser specific specs', () => {
});
});
- describe('createOverlayIcon', () => {
- it('should return the favicon with the overlay', done => {
- commonUtils
- .createOverlayIcon(faviconDataUrl, overlayDataUrl)
- .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
- .then(([actual, expected]) => {
- expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('setFaviconOverlay', () => {
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('data-original-href', faviconDataUrl);
- document.body.appendChild(favicon);
- });
-
- afterEach(() => {
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should set page favicon to provided favicon overlay', done => {
- commonUtils
- .setFaviconOverlay(overlayDataUrl)
- .then(() => document.getElementById('favicon').getAttribute('href'))
- .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
- .then(([actual, expected]) => {
- expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('setCiStatusFavicon', () => {
- const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1/status.json`;
- let mock;
-
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('href', 'null');
- favicon.setAttribute('data-original-href', faviconDataUrl);
- document.body.appendChild(favicon);
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should reset favicon in case of error', done => {
- mock.onGet(BUILD_URL).replyOnce(500);
-
- commonUtils.setCiStatusFavicon(BUILD_URL).catch(() => {
- const favicon = document.getElementById('favicon');
-
- expect(favicon.getAttribute('href')).toEqual(faviconDataUrl);
- done();
- });
- });
-
- it('should set page favicon to CI status favicon based on provided status', done => {
- mock.onGet(BUILD_URL).reply(200, {
- favicon: overlayDataUrl,
- });
-
- commonUtils
- .setCiStatusFavicon(BUILD_URL)
- .then(() => document.getElementById('favicon').getAttribute('href'))
- .then(url => Promise.all([urlToImage(url), urlToImage(faviconWithOverlayDataUrl)]))
- .then(([actual, expected]) => {
- expect(actual).toImageDiffEqual(expected, PIXEL_TOLERANCE);
- done();
- })
- .catch(done.fail);
- });
- });
-
describe('isInViewport', () => {
let el;
diff --git a/spec/javascripts/matchers.js b/spec/javascripts/matchers.js
index 5b7b7dc78b1..ae005e152ed 100644
--- a/spec/javascripts/matchers.js
+++ b/spec/javascripts/matchers.js
@@ -2,7 +2,7 @@ import pixelmatch from 'pixelmatch';
export default {
toImageDiffEqual: () => {
- const getImageData = img => {
+ const getImageData = (img) => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
@@ -32,8 +32,9 @@ export default {
return {
pass: differentPixels < 20,
- message: `${differentPixels} pixels differ more than ${threshold *
- 100} percent between input and output.`,
+ message: `${differentPixels} pixels differ more than ${
+ threshold * 100
+ } percent between input and output.`,
};
},
};
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index b37a53515a6..59136de0b0d 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -30,7 +30,7 @@ Vue.config.warnHandler = (msg, vm, trace) => {
const currentStack = new Error().stack;
const isInVueTestUtils = currentStack
.split('\n')
- .some(line => line.startsWith(' at VueWrapper.setProps ('));
+ .some((line) => line.startsWith(' at VueWrapper.setProps ('));
if (isInVueTestUtils) {
return;
}
@@ -40,7 +40,7 @@ Vue.config.warnHandler = (msg, vm, trace) => {
};
let hasVueErrors = false;
-Vue.config.errorHandler = function(err) {
+Vue.config.errorHandler = function (err) {
hasVueErrors = true;
fail(err);
};
@@ -75,7 +75,7 @@ gon.relative_url_root = '';
let hasUnhandledPromiseRejections = false;
-window.addEventListener('unhandledrejection', event => {
+window.addEventListener('unhandledrejection', (event) => {
hasUnhandledPromiseRejections = true;
console.error('Unhandled promise rejection:');
console.error(event.reason.stack || event.reason);
@@ -87,11 +87,11 @@ window.addEventListener('unhandledrejection', event => {
// 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());
+beforeEach((done) => done());
let longRunningTestTimeoutHandle;
-beforeEach(done => {
+beforeEach((done) => {
longRunningTestTimeoutHandle = setTimeout(() => {
done.fail('Test is running too long!');
}, 4000);
@@ -111,15 +111,15 @@ if (process.env.IS_EE) {
testContexts.push(require.context('ee_spec', true, /_spec$/));
}
-testContexts.forEach(context => {
- context.keys().forEach(path => {
+testContexts.forEach((context) => {
+ context.keys().forEach((path) => {
try {
context(path);
} catch (err) {
console.log(err);
console.error('[GL SPEC RUNNER ERROR] Unable to load spec: ', path);
- describe('Test bundle', function() {
- it(`includes '${path}'`, function() {
+ describe('Test bundle', function () {
+ it(`includes '${path}'`, function () {
expect(err).toBeNull();
});
});
@@ -128,7 +128,7 @@ testContexts.forEach(context => {
});
describe('test errors', () => {
- beforeAll(done => {
+ beforeAll((done) => {
if (hasUnhandledPromiseRejections || hasVueWarnings || hasVueErrors) {
setTimeout(done, 1000);
} else {
diff --git a/spec/javascripts/test_constants.js b/spec/javascripts/test_constants.js
index 51c0716b99d..de7b3a0e80c 100644
--- a/spec/javascripts/test_constants.js
+++ b/spec/javascripts/test_constants.js
@@ -1 +1 @@
-export * from '../frontend/helpers/test_constants';
+export * from '../frontend/__helpers__/test_constants';
diff --git a/spec/lib/api/entities/snippet_repository_storage_move_spec.rb b/spec/lib/api/entities/snippet_repository_storage_move_spec.rb
new file mode 100644
index 00000000000..8086be3ffa7
--- /dev/null
+++ b/spec/lib/api/entities/snippet_repository_storage_move_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::SnippetRepositoryStorageMove do
+ describe '#as_json' do
+ subject { entity.as_json }
+
+ let(:default_storage) { 'default' }
+ let(:second_storage) { 'test_second_storage' }
+ let(:storage_move) { create(:snippet_repository_storage_move, :scheduled, destination_storage_name: second_storage) }
+ let(:entity) { described_class.new(storage_move) }
+
+ it 'includes basic fields' do
+ allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%W[#{default_storage} #{second_storage}])
+
+ is_expected.to include(
+ state: 'scheduled',
+ source_storage_name: default_storage,
+ destination_storage_name: second_storage,
+ snippet: a_kind_of(Hash)
+ )
+ end
+ end
+end
diff --git a/spec/lib/api/helpers/authentication_spec.rb b/spec/lib/api/helpers/authentication_spec.rb
new file mode 100644
index 00000000000..461b0d2f6f9
--- /dev/null
+++ b/spec/lib/api/helpers/authentication_spec.rb
@@ -0,0 +1,207 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Helpers::Authentication do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :public) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+
+ describe 'class methods' do
+ subject { Class.new.include(described_class::ClassMethods).new }
+
+ describe '.authenticate_with' do
+ it 'sets namespace_inheritable :authentication to correctly when body is empty' do
+ expect(subject).to receive(:namespace_inheritable).with(:authentication, {})
+
+ subject.authenticate_with { |allow| }
+ end
+
+ it 'sets namespace_inheritable :authentication to correctly when body is not empty' do
+ expect(subject).to receive(:namespace_inheritable).with(:authentication, { basic: [:pat, :job], oauth: [:pat, :job] })
+
+ subject.authenticate_with { |allow| allow.token_type(:pat, :job).sent_through(:basic, :oauth) }
+ end
+ end
+ end
+
+ describe 'helper methods' do
+ let(:object) do
+ cls = Class.new
+
+ class << cls
+ def helpers(*modules, &block)
+ modules.each { |m| include m }
+ include Module.new.tap { |m| m.class_eval(&block) } if block_given?
+ end
+ end
+
+ cls.define_method(:unauthorized!) { raise '401' }
+ cls.define_method(:bad_request!) { |m| raise "400 - #{m}" }
+
+ # Include the helper class methods, as instance methods
+ cls.include described_class::ClassMethods
+
+ # Include the methods under test
+ cls.include described_class
+
+ cls.new
+ end
+
+ describe '#token_from_namespace_inheritable' do
+ let(:object) do
+ o = super()
+
+ o.instance_eval do
+ # It doesn't matter what this returns as long as the method is defined
+ def current_request
+ nil
+ end
+
+ # Spoof Grape's namespace inheritable system
+ def namespace_inheritable(key, value = nil)
+ return unless key == :authentication
+
+ if value
+ @authentication = value
+ else
+ @authentication
+ end
+ end
+ end
+
+ o
+ end
+
+ let(:authentication) do
+ object.authenticate_with { |allow| allow.token_types(*resolvers).sent_through(*locators) }
+ end
+
+ subject { object.token_from_namespace_inheritable }
+
+ before do
+ # Skip validation of token transports and types to simplify testing
+ allow(Gitlab::APIAuthentication::TokenLocator).to receive(:new) { |type| type }
+ allow(Gitlab::APIAuthentication::TokenResolver).to receive(:new) { |type| type }
+
+ authentication
+ end
+
+ shared_examples 'stops early' do |response_method|
+ it "calls ##{response_method}" do
+ errcls = Class.new(StandardError)
+ expect(object).to receive(response_method).and_raise(errcls)
+ expect { subject }.to raise_error(errcls)
+ end
+ end
+
+ shared_examples 'an anonymous request' do
+ it 'returns nil' do
+ expect(subject).to be(nil)
+ end
+ end
+
+ shared_examples 'an authenticated request' do
+ it 'returns the token' do
+ expect(subject).to be(token)
+ end
+ end
+
+ shared_examples 'an unauthorized request' do
+ it_behaves_like 'stops early', :unauthorized!
+ end
+
+ context 'with no allowed authentication strategies' do
+ let(:authentication) { nil }
+
+ it_behaves_like 'an anonymous request'
+ end
+
+ context 'with no located credentials' do
+ let(:locators) { [double(extract: nil)] }
+ let(:resolvers) { [] }
+
+ it_behaves_like 'an anonymous request'
+ end
+
+ context 'with one set of located credentials' do
+ let(:locators) { [double(extract: true)] }
+
+ context 'when the credentials contain a valid token' do
+ let(:token) { double }
+ let(:resolvers) { [double(resolve: token)] }
+
+ it_behaves_like 'an authenticated request'
+ end
+
+ context 'when the credentials do not contain a valid token' do
+ let(:resolvers) { [double(resolve: nil)] }
+
+ it_behaves_like 'an unauthorized request'
+ end
+ end
+
+ context 'with multiple located credentials' do
+ let(:locators) { [double(extract: true), double(extract: true)] }
+ let(:resolvers) { [] }
+
+ it_behaves_like 'stops early', :bad_request!
+ end
+
+ context 'when a resolver raises UnauthorizedError' do
+ let(:locators) { [double(extract: true)] }
+ let(:resolvers) do
+ r = double
+ expect(r).to receive(:resolve).and_raise(Gitlab::Auth::UnauthorizedError)
+ r
+ end
+
+ it_behaves_like 'an unauthorized request'
+ end
+ end
+
+ describe '#access_token_from_namespace_inheritable' do
+ subject { object.access_token_from_namespace_inheritable }
+
+ it 'returns #token_from_namespace_inheritable if it is a personal access token' do
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(personal_access_token)
+ expect(subject).to be(personal_access_token)
+ end
+
+ it 'returns nil if #token_from_namespace_inheritable is not a personal access token' do
+ token = double
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(token)
+ expect(subject).to be(nil)
+ end
+ end
+
+ describe '#user_from_namespace_inheritable' do
+ subject { object.user_from_namespace_inheritable }
+
+ it 'returns #token_from_namespace_inheritable if it is a deploy token' do
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(deploy_token)
+ expect(subject).to be(deploy_token)
+ end
+
+ it 'returns #token_from_namespace_inheritable.user if the token is not a deploy token' do
+ user = double
+ token = double(user: user)
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(token)
+
+ expect(subject).to be(user)
+ end
+
+ it 'falls back to #find_user_from_warden if #token_from_namespace_inheritable.user is nil' do
+ token = double(user: nil)
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(token)
+ subject
+ end
+
+ it 'falls back to #find_user_from_warden if #token_from_namespace_inheritable is nil' do
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(nil)
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index be5f0cc9f9a..bdf04fafaae 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -205,7 +205,7 @@ RSpec.describe API::Helpers do
end
it 'tracks redis hll event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(value, event_name)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
subject.increment_unique_values(event_name, value)
end
@@ -363,4 +363,49 @@ RSpec.describe API::Helpers do
end
end
end
+
+ describe '#present_disk_file!' do
+ let_it_be(:dummy_class) do
+ Class.new do
+ attr_reader :headers
+ alias_method :header, :headers
+
+ def initialize
+ @headers = {}
+ end
+ end
+ end
+
+ let(:dummy_instance) { dummy_class.include(described_class).new }
+ let(:path) { '/tmp/file.txt' }
+ let(:filename) { 'file.txt' }
+
+ subject { dummy_instance.present_disk_file!(path, filename) }
+
+ before do
+ expect(dummy_instance).to receive(:content_type).with('application/octet-stream')
+ end
+
+ context 'with X-Sendfile supported' do
+ before do
+ dummy_instance.headers['X-Sendfile-Type'] = 'X-Sendfile'
+ end
+
+ it 'sends the file using X-Sendfile' do
+ expect(dummy_instance).to receive(:body).with('')
+
+ subject
+
+ expect(dummy_instance.headers['X-Sendfile']).to eq(path)
+ end
+ end
+
+ context 'without X-Sendfile supported' do
+ it 'sends the file' do
+ expect(dummy_instance).to receive(:sendfile).with(path)
+
+ subject
+ 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 6a161854dfb..21ee40f22fe 100644
--- a/spec/lib/atlassian/jira_connect/client_spec.rb
+++ b/spec/lib/atlassian/jira_connect/client_spec.rb
@@ -8,6 +8,15 @@ RSpec.describe Atlassian::JiraConnect::Client do
subject { described_class.new('https://gitlab-test.atlassian.net', 'sample_secret') }
let_it_be(:project) { create_default(:project, :repository) }
+ let_it_be(:mrs_by_title) { create_list(:merge_request, 4, :unique_branches, :jira_title) }
+ let_it_be(:mrs_by_branch) { create_list(:merge_request, 2, :jira_branch) }
+ let_it_be(:red_herrings) { create_list(:merge_request, 1, :unique_branches) }
+
+ let_it_be(:pipelines) do
+ (red_herrings + mrs_by_branch + mrs_by_title).map do |mr|
+ create(:ci_pipeline, merge_request: mr)
+ end
+ end
around do |example|
freeze_time { example.run }
@@ -22,13 +31,25 @@ RSpec.describe Atlassian::JiraConnect::Client do
end
describe '#send_info' do
- it 'calls store_build_info and store_dev_info as appropriate' do
+ it 'calls more specific methods as appropriate' do
+ expect(subject).to receive(:store_ff_info).with(
+ project: project,
+ update_sequence_id: :x,
+ feature_flags: :r
+ ).and_return(:ff_stored)
+
expect(subject).to receive(:store_build_info).with(
project: project,
update_sequence_id: :x,
pipelines: :y
).and_return(:build_stored)
+ expect(subject).to receive(:store_deploy_info).with(
+ project: project,
+ update_sequence_id: :x,
+ deployments: :q
+ ).and_return(:deploys_stored)
+
expect(subject).to receive(:store_dev_info).with(
project: project,
update_sequence_id: :x,
@@ -43,10 +64,13 @@ RSpec.describe Atlassian::JiraConnect::Client do
commits: :a,
branches: :b,
merge_requests: :c,
- pipelines: :y
+ pipelines: :y,
+ deployments: :q,
+ feature_flags: :r
}
- expect(subject.send_info(**args)).to contain_exactly(:dev_stored, :build_stored)
+ expect(subject.send_info(**args))
+ .to contain_exactly(:dev_stored, :build_stored, :deploys_stored, :ff_stored)
end
it 'only calls methods that we need to call' do
@@ -83,31 +107,263 @@ RSpec.describe Atlassian::JiraConnect::Client do
}
end
- describe '#store_build_info' do
- let_it_be(:mrs_by_title) { create_list(:merge_request, 4, :unique_branches, :jira_title) }
- let_it_be(:mrs_by_branch) { create_list(:merge_request, 2, :jira_branch) }
- let_it_be(:red_herrings) { create_list(:merge_request, 1, :unique_branches) }
+ describe '#handle_response' do
+ let(:errors) { [{ 'message' => 'X' }, { 'message' => 'Y' }] }
+ let(:processed) { subject.send(:handle_response, response, 'foo') { |x| [:data, x] } }
+
+ context 'the response is 200 OK' do
+ let(:response) { double(code: 200, parsed_response: :foo) }
+
+ it 'yields to the block' do
+ expect(processed).to eq [:data, :foo]
+ end
+ end
+
+ context 'the response is 400 bad request' do
+ let(:response) { double(code: 400, parsed_response: errors) }
+
+ it 'extracts the errors messages' do
+ expect(processed).to eq('errorMessages' => %w(X Y))
+ end
+ end
+
+ context 'the response is 401 forbidden' do
+ let(:response) { double(code: 401, parsed_response: nil) }
+
+ it 'reports that our JWT is wrong' do
+ expect(processed).to eq('errorMessages' => ['Invalid JWT'])
+ end
+ end
+
+ context 'the response is 403' do
+ let(:response) { double(code: 403, parsed_response: nil) }
+
+ it 'reports that the App is misconfigured' do
+ expect(processed).to eq('errorMessages' => ['App does not support foo'])
+ end
+ end
+
+ context 'the response is 413' do
+ let(:response) { double(code: 413, parsed_response: errors) }
+
+ it 'extracts the errors messages' do
+ expect(processed).to eq('errorMessages' => ['Data too large', 'X', 'Y'])
+ end
+ end
+
+ context 'the response is 429' do
+ let(:response) { double(code: 429, parsed_response: nil) }
+
+ it 'reports that we exceeded the rate limit' do
+ expect(processed).to eq('errorMessages' => ['Rate limit exceeded'])
+ end
+ end
+
+ context 'the response is 503' do
+ let(:response) { double(code: 503, parsed_response: nil) }
- let_it_be(:pipelines) do
- (red_herrings + mrs_by_branch + mrs_by_title).map do |mr|
- create(:ci_pipeline, merge_request: mr)
+ it 'reports that the service is unavailable' do
+ expect(processed).to eq('errorMessages' => ['Service unavailable'])
end
end
+ context 'the response is anything else' do
+ let(:response) { double(code: 1000, parsed_response: :something) }
+
+ it 'reports that this was unanticipated' do
+ expect(processed).to eq('errorMessages' => ['Unknown error'], 'response' => :something)
+ end
+ end
+ end
+
+ describe '#store_deploy_info' do
+ let_it_be(:environment) { create(:environment, name: 'DEV', project: project) }
+ let_it_be(:deployments) do
+ pipelines.map do |p|
+ build = create(:ci_build, environment: environment.name, pipeline: p, project: project)
+ create(:deployment, deployable: build, environment: environment)
+ end
+ end
+
+ let(:schema) do
+ Atlassian::Schemata.deploy_info_payload
+ end
+
+ let(:body) do
+ matcher = be_valid_json.and match_schema(schema)
+
+ ->(text) { matcher.matches?(text) }
+ end
+
+ let(:rejections) { [] }
+ let(:response_body) do
+ {
+ acceptedDeployments: [],
+ rejectedDeployments: rejections,
+ unknownIssueKeys: []
+ }.to_json
+ end
+
+ before do
+ path = '/rest/deployments/0.1/bulk'
+ stub_full_request('https://gitlab-test.atlassian.net' + path, method: :post)
+ .with(body: body, headers: expected_headers(path))
+ .to_return(body: response_body, headers: { 'Content-Type': 'application/json' })
+ end
+
+ it "calls the API with auth headers" do
+ subject.send(:store_deploy_info, project: project, deployments: deployments)
+ end
+
+ it 'only sends information about relevant MRs' do
+ expect(subject).to receive(:post).with('/rest/deployments/0.1/bulk', { deployments: have_attributes(size: 6) }).and_call_original
+
+ subject.send(:store_deploy_info, project: project, deployments: deployments)
+ end
+
+ it 'does not call the API if there is nothing to report' do
+ expect(subject).not_to receive(:post)
+
+ subject.send(:store_deploy_info, project: project, deployments: deployments.take(1))
+ end
+
+ context 'there are errors' do
+ let(:rejections) do
+ [{ errors: [{ message: 'X' }, { message: 'Y' }] }, { errors: [{ message: 'Z' }] }]
+ end
+
+ it 'reports the errors' do
+ response = subject.send(:store_deploy_info, project: project, deployments: deployments)
+
+ 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
+ let_it_be(:feature_flags) { create_list(:operations_feature_flag, 3, project: project) }
+
+ let(:schema) do
+ Atlassian::Schemata.ff_info_payload
+ end
+
+ let(:body) do
+ matcher = be_valid_json.and match_schema(schema)
+
+ ->(text) { matcher.matches?(text) }
+ end
+
+ let(:failures) { {} }
+ let(:response_body) do
+ {
+ acceptedFeatureFlags: [],
+ failedFeatureFlags: failures,
+ unknownIssueKeys: []
+ }.to_json
+ end
+
+ before do
+ feature_flags.first.update!(description: 'RELEVANT-123')
+ feature_flags.second.update!(description: 'RELEVANT-123')
+ path = '/rest/featureflags/0.1/bulk'
+ stub_full_request('https://gitlab-test.atlassian.net' + path, method: :post)
+ .with(body: body, headers: expected_headers(path))
+ .to_return(body: response_body, headers: { 'Content-Type': 'application/json' })
+ end
+
+ it "calls the API with auth headers" do
+ subject.send(:store_ff_info, project: project, feature_flags: feature_flags)
+ end
+
+ it 'only sends information about relevant MRs' do
+ expect(subject).to receive(:post).with('/rest/featureflags/0.1/bulk', {
+ flags: have_attributes(size: 2), properties: Hash
+ }).and_call_original
+
+ subject.send(:store_ff_info, project: project, feature_flags: feature_flags)
+ end
+
+ it 'does not call the API if there is nothing to report' do
+ expect(subject).not_to receive(:post)
+
+ subject.send(:store_ff_info, project: project, feature_flags: [feature_flags.last])
+ end
+
+ context 'there are errors' do
+ let(:failures) do
+ {
+ a: [{ message: 'X' }, { message: 'Y' }],
+ b: [{ message: 'Z' }]
+ }
+ end
+
+ it 'reports the errors' do
+ response = subject.send(:store_ff_info, project: project, feature_flags: feature_flags)
+
+ 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
let(:build_info_payload_schema) do
Atlassian::Schemata.build_info_payload
end
let(:body) do
- matcher = be_valid_json.according_to_schema(build_info_payload_schema)
+ matcher = be_valid_json.and match_schema(build_info_payload_schema)
->(text) { matcher.matches?(text) }
end
+ let(:failures) { [] }
+ let(:response_body) do
+ {
+ acceptedBuilds: [],
+ rejectedBuilds: failures,
+ unknownIssueKeys: []
+ }.to_json
+ end
+
before do
path = '/rest/builds/0.1/bulk'
stub_full_request('https://gitlab-test.atlassian.net' + path, method: :post)
.with(body: body, headers: expected_headers(path))
+ .to_return(body: response_body, headers: { 'Content-Type': 'application/json' })
end
it "calls the API with auth headers" do
@@ -115,7 +371,9 @@ RSpec.describe Atlassian::JiraConnect::Client do
end
it 'only sends information about relevant MRs' do
- expect(subject).to receive(:post).with('/rest/builds/0.1/bulk', { builds: have_attributes(size: 6) })
+ expect(subject).to receive(:post)
+ .with('/rest/builds/0.1/bulk', { builds: have_attributes(size: 6) })
+ .and_call_original
subject.send(:store_build_info, project: project, pipelines: pipelines)
end
@@ -137,12 +395,28 @@ RSpec.describe Atlassian::JiraConnect::Client do
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 })
+ 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' }] }]
+ end
+
+ it 'reports the errors' do
+ response = subject.send(:store_build_info, project: project, pipelines: pipelines)
+
+ expect(response['errorMessages']).to eq(%w(X Y Z))
+ end
+ end
+
it 'avoids N+1 database queries' do
+ pending 'https://gitlab.com/gitlab-org/gitlab/-/issues/292818'
+
baseline = ActiveRecord::QueryRecorder.new do
subject.send(:store_build_info, project: project, pipelines: pipelines)
end
diff --git a/spec/lib/atlassian/jira_connect/serializers/build_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/build_entity_spec.rb
index 52e475d20ca..4bbd654655d 100644
--- a/spec/lib/atlassian/jira_connect/serializers/build_entity_spec.rb
+++ b/spec/lib/atlassian/jira_connect/serializers/build_entity_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::BuildEntity do
end
it 'is invalid, since it has no issue keys' do
- expect(subject.to_json).not_to be_valid_json.according_to_schema(Atlassian::Schemata.build_info)
+ expect(subject.to_json).not_to match_schema(Atlassian::Schemata.build_info)
end
end
end
@@ -43,7 +43,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::BuildEntity do
describe '#to_json' do
it 'is valid according to the build info schema' do
- expect(subject.to_json).to be_valid_json.according_to_schema(Atlassian::Schemata.build_info)
+ expect(subject.to_json).to be_valid_json.and match_schema(Atlassian::Schemata.build_info)
end
end
end
diff --git a/spec/lib/atlassian/jira_connect/serializers/deployment_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/deployment_entity_spec.rb
new file mode 100644
index 00000000000..82bcbdc4561
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/deployment_entity_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::DeploymentEntity do
+ let_it_be(:user) { create_default(:user) }
+ let_it_be(:project) { create_default(:project, :repository) }
+ let_it_be(:environment) { create(:environment, name: 'prod', project: project) }
+ let_it_be_with_reload(:deployment) { create(:deployment, environment: environment) }
+
+ subject { described_class.represent(deployment) }
+
+ context 'when the deployment does not belong to any Jira issue' do
+ describe '#issue_keys' do
+ it 'is empty' do
+ expect(subject.issue_keys).to be_empty
+ end
+ end
+
+ describe '#to_json' do
+ it 'can encode the object' do
+ expect(subject.to_json).to be_valid_json
+ end
+
+ it 'is invalid, since it has no issue keys' do
+ expect(subject.to_json).not_to match_schema(Atlassian::Schemata.deployment_info)
+ end
+ end
+ end
+
+ context 'this is an external deployment' do
+ before do
+ deployment.update!(deployable: nil)
+ end
+
+ it 'does not raise errors when serializing' do
+ expect { subject.to_json }.not_to raise_error
+ end
+
+ it 'returns an empty list of issue keys' do
+ expect(subject.issue_keys).to be_empty
+ end
+ end
+
+ describe 'environment type' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:env_name, :env_type) do
+ 'prod' | 'production'
+ 'test' | 'testing'
+ 'staging' | 'staging'
+ 'dev' | 'development'
+ 'review/app' | 'development'
+ 'something-else' | 'unmapped'
+ end
+
+ with_them do
+ before do
+ environment.update!(name: env_name)
+ end
+
+ let(:exposed_type) { subject.send(:environment_entity).send(:type) }
+
+ it 'has the correct environment type' do
+ expect(exposed_type).to eq(env_type)
+ end
+ end
+ end
+
+ context 'when the deployment can be linked to a Jira issue' do
+ let(:pipeline) { create(:ci_pipeline, merge_request: merge_request) }
+
+ before do
+ subject.deployable.update!(pipeline: pipeline)
+ end
+
+ %i[jira_branch jira_title].each do |trait|
+ context "because it belongs to an MR with a #{trait}" do
+ let(:merge_request) { create(:merge_request, trait) }
+
+ describe '#issue_keys' do
+ it 'is not empty' do
+ expect(subject.issue_keys).not_to be_empty
+ end
+ end
+
+ describe '#to_json' do
+ it 'is valid according to the deployment info schema' do
+ expect(subject.to_json).to be_valid_json.and match_schema(Atlassian::Schemata.deployment_info)
+ end
+ end
+ end
+ end
+ end
+end
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
new file mode 100644
index 00000000000..964801338cf
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::FeatureFlagEntity do
+ let_it_be(:user) { create_default(:user) }
+ let_it_be(:project) { create_default(:project) }
+
+ 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) }
+
+ describe '#issue_keys' do
+ it 'is empty' do
+ expect(subject.issue_keys).to be_empty
+ end
+ end
+
+ describe '#to_json' do
+ it 'can encode the object' do
+ expect(subject.to_json).to be_valid_json
+ end
+
+ it 'is invalid, since it has no issue keys' do
+ expect(subject.to_json).not_to match_schema(Atlassian::Schemata.feature_flag_info)
+ end
+ end
+ end
+
+ context 'when the feature flag does belong to a Jira issue' do
+ let(:feature_flag) do
+ create(:operations_feature_flag, description: 'THING-123')
+ end
+
+ describe '#issue_keys' do
+ it 'is not empty' do
+ expect(subject.issue_keys).not_to be_empty
+ end
+ end
+
+ describe '#to_json' do
+ it 'is valid according to the feature flag info schema' do
+ expect(subject.to_json).to be_valid_json.and match_schema(Atlassian::Schemata.feature_flag_info)
+ end
+ end
+
+ context 'it has a percentage strategy' do
+ let!(:scopes) do
+ strat = create(:operations_strategy,
+ feature_flag: feature_flag,
+ name: ::Operations::FeatureFlags::Strategy::STRATEGY_GRADUALROLLOUTUSERID,
+ parameters: { 'percentage' => '50', 'groupId' => 'abcde' })
+
+ [
+ create(:operations_scope, strategy: strat, environment_scope: 'production in live'),
+ create(:operations_scope, strategy: strat, environment_scope: 'staging'),
+ create(:operations_scope, strategy: strat)
+ ]
+ end
+
+ let(:entity) { Gitlab::Json.parse(subject.to_json) }
+
+ it 'is valid according to the feature flag info schema' do
+ expect(subject.to_json).to be_valid_json.and match_schema(Atlassian::Schemata.feature_flag_info)
+ end
+
+ it 'has the correct summary' do
+ expect(entity.dig('summary', 'status')).to eq(
+ 'enabled' => true,
+ 'defaultValue' => '',
+ 'rollout' => { 'percentage' => 50.0, 'text' => 'Percent of users' }
+ )
+ end
+
+ it 'includes the correct environments' do
+ expect(entity['details']).to contain_exactly(
+ include('environment' => { 'name' => 'production in live', 'type' => 'production' }),
+ include('environment' => { 'name' => 'staging', 'type' => 'staging' }),
+ include('environment' => { 'name' => scopes.last.environment_scope })
+ )
+ end
+ end
+ 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 2a4ee28130b..1f886059bf6 100644
--- a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb
+++ b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb
@@ -35,8 +35,8 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do
expect(Gitlab.config.asset_proxy.enabled).to be_truthy
expect(Gitlab.config.asset_proxy.secret_key).to eq 'shared-secret'
expect(Gitlab.config.asset_proxy.url).to eq 'https://assets.example.com'
- expect(Gitlab.config.asset_proxy.whitelist).to eq %w(gitlab.com *.mydomain.com)
- expect(Gitlab.config.asset_proxy.domain_regexp).to eq /^(gitlab\.com|.*?\.mydomain\.com)$/i
+ expect(Gitlab.config.asset_proxy.allowlist).to eq %w(gitlab.com *.mydomain.com)
+ expect(Gitlab.config.asset_proxy.domain_regexp).to eq(/^(gitlab\.com|.*?\.mydomain\.com)$/i)
end
context 'when whitelist is empty' do
@@ -46,7 +46,7 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do
described_class.initialize_settings
- expect(Gitlab.config.asset_proxy.whitelist).to eq [Gitlab.config.gitlab.host]
+ expect(Gitlab.config.asset_proxy.allowlist).to eq [Gitlab.config.gitlab.host]
end
end
end
@@ -56,8 +56,8 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do
stub_asset_proxy_setting(enabled: true)
stub_asset_proxy_setting(secret_key: 'shared-secret')
stub_asset_proxy_setting(url: 'https://assets.example.com')
- stub_asset_proxy_setting(whitelist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host}))
- stub_asset_proxy_setting(domain_regexp: described_class.compile_whitelist(Gitlab.config.asset_proxy.whitelist))
+ stub_asset_proxy_setting(allowlist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host}))
+ stub_asset_proxy_setting(domain_regexp: described_class.compile_allowlist(Gitlab.config.asset_proxy.allowlist))
@context = described_class.transform_context({})
end
diff --git a/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb b/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb
index 1f65268bd3c..67b480f8973 100644
--- a/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb
@@ -5,9 +5,9 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::BroadcastMessageSanitizationFilter do
include FilterSpecHelper
- it_behaves_like 'default whitelist'
+ it_behaves_like 'default allowlist'
- describe 'custom whitelist' do
+ describe 'custom allowlist' do
it_behaves_like 'XSS prevention'
it_behaves_like 'sanitize link'
@@ -26,19 +26,19 @@ RSpec.describe Banzai::Filter::BroadcastMessageSanitizationFilter do
end
context 'when `a` elements have `style` attribute' do
- let(:whitelisted_style) { 'color: red; border: blue; background: green; padding: 10px; margin: 10px; text-decoration: underline;' }
+ let(:allowed_style) { 'color: red; border: blue; background: green; padding: 10px; margin: 10px; text-decoration: underline;' }
context 'allows specific properties' do
- let(:exp) { %{<a href="#" style="#{whitelisted_style}">Stylish Link</a>} }
+ let(:exp) { %{<a href="#" style="#{allowed_style}">Stylish Link</a>} }
it { is_expected.to eq(exp) }
end
it 'disallows other properties in `style` attribute on `a` elements' do
- style = [whitelisted_style, 'position: fixed'].join(';')
+ style = [allowed_style, 'position: fixed'].join(';')
doc = filter(%{<a href="#" style="#{style}">Stylish Link</a>})
- expect(doc.at_css('a')['style']).to eq(whitelisted_style)
+ expect(doc.at_css('a')['style']).to eq(allowed_style)
end
end
diff --git a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
index ac1cabb34cc..d0336e9e059 100644
--- a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
@@ -143,15 +143,32 @@ RSpec.describe Banzai::Filter::ReferenceRedactorFilter do
expect(doc.css('a').length).to eq 1
end
- it 'allows references for admin' do
- admin = create(:admin)
- project = create(:project, :public)
- issue = create(:issue, :confidential, project: project)
- link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+ context 'for admin' do
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'allows references' do
+ admin = create(:admin)
+ project = create(:project, :public)
+ issue = create(:issue, :confidential, project: project)
+ link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
+ doc = filter(link, current_user: admin)
+
+ expect(doc.css('a').length).to eq 1
+ end
+ end
- doc = filter(link, current_user: admin)
+ context 'when admin mode is disabled' do
+ it 'removes references' do
+ admin = create(:admin)
+ project = create(:project, :public)
+ issue = create(:issue, :confidential, project: project)
+ link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
- expect(doc.css('a').length).to eq 1
+ doc = filter(link, current_user: admin)
+
+ expect(doc.css('a').length).to eq 0
+ end
+ end
end
context "when a confidential issue is moved from a public project to a private one" do
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index 09dcd5518ff..bc4b60dfe60 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -5,31 +5,31 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::SanitizationFilter do
include FilterSpecHelper
- it_behaves_like 'default whitelist'
+ it_behaves_like 'default allowlist'
- describe 'custom whitelist' do
+ describe 'custom allowlist' do
it_behaves_like 'XSS prevention'
it_behaves_like 'sanitize link'
- it 'customizes the whitelist only once' do
+ it 'customizes the allowlist only once' do
instance = described_class.new('Foo')
- control_count = instance.whitelist[:transformers].size
+ control_count = instance.allowlist[:transformers].size
- 3.times { instance.whitelist }
+ 3.times { instance.allowlist }
- expect(instance.whitelist[:transformers].size).to eq control_count
+ expect(instance.allowlist[:transformers].size).to eq control_count
end
- it 'customizes the whitelist only once for different instances' do
+ it 'customizes the allowlist only once for different instances' do
instance1 = described_class.new('Foo1')
instance2 = described_class.new('Foo2')
- control_count = instance1.whitelist[:transformers].size
+ control_count = instance1.allowlist[:transformers].size
- instance1.whitelist
- instance2.whitelist
+ instance1.allowlist
+ instance2.allowlist
- expect(instance1.whitelist[:transformers].size).to eq control_count
- expect(instance2.whitelist[:transformers].size).to eq control_count
+ expect(instance1.allowlist[:transformers].size).to eq control_count
+ expect(instance2.allowlist[:transformers].size).to eq control_count
end
it 'sanitizes `class` attribute from all elements' do
diff --git a/spec/lib/banzai/filter/truncate_source_filter_spec.rb b/spec/lib/banzai/filter/truncate_source_filter_spec.rb
new file mode 100644
index 00000000000..b0c6d91daa8
--- /dev/null
+++ b/spec/lib/banzai/filter/truncate_source_filter_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::TruncateSourceFilter do
+ include FilterSpecHelper
+
+ let(:short_text) { 'foo' * 10 }
+ let(:long_text) { ([short_text] * 10).join(' ') }
+
+ it 'does nothing when limit is unspecified' do
+ output = filter(long_text)
+
+ expect(output).to eq(long_text)
+ end
+
+ it 'does nothing to a short-enough text' do
+ output = filter(short_text, limit: short_text.bytesize)
+
+ expect(output).to eq(short_text)
+ end
+
+ it 'truncates UTF-8 text by bytes, on a character boundary' do
+ utf8_text = '日本語ã®æ–‡å­—ãŒå¤§ãã„'
+ truncated = '日…'
+
+ expect(filter(utf8_text, limit: truncated.bytesize)).to eq(truncated)
+ expect(filter(utf8_text, limit: utf8_text.bytesize)).to eq(utf8_text)
+ expect(filter(utf8_text, limit: utf8_text.mb_chars.size)).not_to eq(utf8_text)
+ end
+end
diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb
index 82d4f883e0d..be553433e9e 100644
--- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Banzai::Pipeline::DescriptionPipeline do
stub_commonmark_sourcepos_disabled
end
- it 'uses a limited whitelist' do
+ it 'uses a limited allowlist' do
doc = parse('# Description')
expect(doc.strip).to eq 'Description'
diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
index 247f4591632..31047b9494a 100644
--- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
@@ -176,8 +176,8 @@ RSpec.describe Banzai::Pipeline::GfmPipeline do
stub_asset_proxy_setting(enabled: true)
stub_asset_proxy_setting(secret_key: 'shared-secret')
stub_asset_proxy_setting(url: 'https://assets.example.com')
- stub_asset_proxy_setting(whitelist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host}))
- stub_asset_proxy_setting(domain_regexp: Banzai::Filter::AssetProxyFilter.compile_whitelist(Gitlab.config.asset_proxy.whitelist))
+ stub_asset_proxy_setting(allowlist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host}))
+ stub_asset_proxy_setting(domain_regexp: Banzai::Filter::AssetProxyFilter.compile_allowlist(Gitlab.config.asset_proxy.allowlist))
end
it 'replaces a lazy loaded img src' do
diff --git a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
index fc74c592867..f0498f41b61 100644
--- a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
@@ -24,4 +24,12 @@ RSpec.describe Banzai::Pipeline::PreProcessPipeline do
expect(result[:output]).to include "> blockquote\n"
end
end
+
+ it 'truncates the text if requested' do
+ text = (['foo'] * 10).join(' ')
+
+ result = described_class.call(text, limit: 12)
+
+ expect(result[:output]).to eq('foo foo f…')
+ 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 a7a19fb73fc..2abd3df20fd 100644
--- a/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
+++ b/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
@@ -27,11 +27,8 @@ RSpec.describe BulkImports::Common::Extractors::GraphqlExtractor do
allow(graphql_client).to receive(:execute).and_return(response)
end
- it 'returns an enumerator with fetched results' do
- response = subject.extract(context)
-
- expect(response).to be_instance_of(Enumerator)
- expect(response.first).to eq({ foo: :bar })
+ it 'returns original hash' do
+ expect(subject.extract(context)).to eq({ foo: :bar })
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 c9b481388c3..1a91f3d7a78 100644
--- a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
@@ -75,13 +75,11 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
it 'has extractors' do
- expect(described_class.extractors)
- .to contain_exactly(
- {
- klass: BulkImports::Common::Extractors::GraphqlExtractor,
- options: {
- query: BulkImports::Groups::Graphql::GetGroupQuery
- }
+ expect(described_class.get_extractor)
+ .to eq(
+ klass: BulkImports::Common::Extractors::GraphqlExtractor,
+ options: {
+ query: BulkImports::Groups::Graphql::GetGroupQuery
}
)
end
@@ -97,9 +95,7 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
end
it 'has loaders' do
- expect(described_class.loaders).to contain_exactly({
- klass: BulkImports::Groups::Loaders::GroupLoader, options: nil
- })
+ expect(described_class.get_loader).to eq(klass: BulkImports::Groups::Loaders::GroupLoader, options: nil)
end
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 788a6e98c45..e5a8ed7f47d 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
@@ -58,10 +58,7 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
it 'has extractors' do
- expect(described_class.extractors).to contain_exactly(
- klass: BulkImports::Groups::Extractors::SubgroupsExtractor,
- options: nil
- )
+ expect(described_class.get_extractor).to eq(klass: BulkImports::Groups::Extractors::SubgroupsExtractor, options: nil)
end
it 'has transformers' do
@@ -72,10 +69,7 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
end
it 'has loaders' do
- expect(described_class.loaders).to contain_exactly(
- klass: BulkImports::Common::Loaders::EntityLoader,
- options: nil
- )
+ expect(described_class.get_loader).to eq(klass: BulkImports::Common::Loaders::EntityLoader, options: nil)
end
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 95dca7fc486..87baf1b8026 100644
--- a/spec/lib/bulk_imports/importers/group_importer_spec.rb
+++ b/spec/lib/bulk_imports/importers/group_importer_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe BulkImports::Importers::GroupImporter do
let(:user) { create(:user) }
let(:bulk_import) { create(:bulk_import) }
- let(:bulk_import_entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
+ let(:bulk_import_entity) { create(:bulk_import_entity, :started, bulk_import: bulk_import) }
let(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
let(:context) do
BulkImports::Pipeline::Context.new(
@@ -18,14 +18,13 @@ RSpec.describe BulkImports::Importers::GroupImporter do
subject { described_class.new(bulk_import_entity) }
before do
- allow(Gitlab).to receive(:ee?).and_return(false)
allow(BulkImports::Pipeline::Context).to receive(:new).and_return(context)
end
describe '#execute' do
it 'starts the entity and run its pipelines' do
- expect(bulk_import_entity).to receive(:start).and_call_original
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
subject.execute
diff --git a/spec/lib/bulk_imports/importers/groups_importer_spec.rb b/spec/lib/bulk_imports/importers/groups_importer_spec.rb
deleted file mode 100644
index 4865034b0cd..00000000000
--- a/spec/lib/bulk_imports/importers/groups_importer_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Importers::GroupsImporter do
- let_it_be(:bulk_import) { create(:bulk_import) }
-
- subject { described_class.new(bulk_import.id) }
-
- describe '#execute' do
- context "when there is entities to be imported" do
- let!(:bulk_import_entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
-
- it "starts the bulk_import and imports its entities" do
- expect(BulkImports::Importers::GroupImporter).to receive(:new)
- .with(bulk_import_entity).and_return(double(execute: true))
- expect(BulkImportWorker).to receive(:perform_async).with(bulk_import.id)
-
- subject.execute
-
- expect(bulk_import.reload).to be_started
- end
- end
-
- context "when there is no entities to be imported" do
- it "starts the bulk_import and imports its entities" do
- expect(BulkImports::Importers::GroupImporter).not_to receive(:new)
- expect(BulkImportWorker).not_to receive(:perform_async)
-
- subject.execute
-
- expect(bulk_import.reload).to be_finished
- end
- end
- end
-end
diff --git a/spec/lib/bulk_imports/pipeline_spec.rb b/spec/lib/bulk_imports/pipeline_spec.rb
index 94052be7df2..3811a02a7fd 100644
--- a/spec/lib/bulk_imports/pipeline_spec.rb
+++ b/spec/lib/bulk_imports/pipeline_spec.rb
@@ -24,9 +24,9 @@ RSpec.describe BulkImports::Pipeline do
describe 'getters' do
it 'retrieves class attributes' do
- expect(BulkImports::MyPipeline.extractors).to contain_exactly({ klass: BulkImports::Extractor, options: { foo: :bar } })
+ expect(BulkImports::MyPipeline.get_extractor).to eq({ klass: BulkImports::Extractor, options: { foo: :bar } })
expect(BulkImports::MyPipeline.transformers).to contain_exactly({ klass: BulkImports::Transformer, options: { foo: :bar } })
- expect(BulkImports::MyPipeline.loaders).to contain_exactly({ klass: BulkImports::Loader, options: { foo: :bar } })
+ expect(BulkImports::MyPipeline.get_loader).to eq({ klass: BulkImports::Loader, options: { foo: :bar } })
expect(BulkImports::MyPipeline.abort_on_failure?).to eq(true)
end
end
@@ -41,20 +41,14 @@ RSpec.describe BulkImports::Pipeline do
BulkImports::MyPipeline.loader(klass, options)
BulkImports::MyPipeline.abort_on_failure!
- expect(BulkImports::MyPipeline.extractors)
- .to contain_exactly(
- { klass: BulkImports::Extractor, options: { foo: :bar } },
- { klass: klass, options: options })
+ expect(BulkImports::MyPipeline.get_extractor).to eq({ klass: klass, options: options })
expect(BulkImports::MyPipeline.transformers)
.to contain_exactly(
{ klass: BulkImports::Transformer, options: { foo: :bar } },
{ klass: klass, options: options })
- expect(BulkImports::MyPipeline.loaders)
- .to contain_exactly(
- { klass: BulkImports::Loader, options: { foo: :bar } },
- { klass: klass, options: options })
+ expect(BulkImports::MyPipeline.get_loader).to eq({ klass: klass, options: options })
expect(BulkImports::MyPipeline.abort_on_failure?).to eq(true)
end
diff --git a/spec/lib/constraints/admin_constrainer_spec.rb b/spec/lib/constraints/admin_constrainer_spec.rb
index 3efe683177c..ac6ad31120e 100644
--- a/spec/lib/constraints/admin_constrainer_spec.rb
+++ b/spec/lib/constraints/admin_constrainer_spec.rb
@@ -2,7 +2,7 @@
#
require 'spec_helper'
-RSpec.describe Constraints::AdminConstrainer, :do_not_mock_admin_mode do
+RSpec.describe Constraints::AdminConstrainer do
let(:user) { create(:user) }
let(:session) { {} }
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index 2c08fdc1e75..9d6f4db537d 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -26,7 +26,54 @@ RSpec.describe ContainerRegistry::Client do
}
end
- shared_examples '#repository_manifest' do |manifest_type|
+ let(:expected_faraday_headers) { { user_agent: "GitLab/#{Gitlab::VERSION}" } }
+ let(:expected_faraday_request_options) { Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS }
+
+ shared_examples 'handling timeouts' do
+ let(:retry_options) do
+ ContainerRegistry::Client::RETRY_OPTIONS.merge(
+ interval: 0.1,
+ interval_randomness: 0,
+ backoff_factor: 0
+ )
+ end
+
+ before do
+ stub_request(method, url).to_timeout
+ end
+
+ it 'handles network timeouts' do
+ actual_retries = 0
+ retry_options_with_block = retry_options.merge(
+ retry_block: -> (_, _, _, _) { actual_retries += 1 }
+ )
+
+ stub_const('ContainerRegistry::Client::RETRY_OPTIONS', retry_options_with_block)
+
+ expect { subject }.to raise_error(Faraday::ConnectionFailed)
+ expect(actual_retries).to eq(retry_options_with_block[:max])
+ end
+
+ it 'logs the error' do
+ stub_const('ContainerRegistry::Client::RETRY_OPTIONS', retry_options)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .exactly(retry_options[:max] + 1)
+ .times
+ .with(
+ an_instance_of(Faraday::ConnectionFailed),
+ class: described_class.name,
+ url: URI(url)
+ )
+
+ expect { subject }.to raise_error(Faraday::ConnectionFailed)
+ end
+ end
+
+ shared_examples 'handling repository manifest' do |manifest_type|
+ let(:method) { :get }
+ let(:url) { 'http://container-registry/v2/group/test/manifests/mytag' }
let(:manifest) do
{
"schemaVersion" => 2,
@@ -48,7 +95,7 @@ RSpec.describe ContainerRegistry::Client do
end
it 'GET /v2/:name/manifests/mytag' do
- stub_request(:get, "http://container-registry/v2/group/test/manifests/mytag")
+ stub_request(method, url)
.with(headers: {
'Accept' => 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json',
'Authorization' => "bearer #{token}",
@@ -56,14 +103,24 @@ RSpec.describe ContainerRegistry::Client do
})
.to_return(status: 200, body: manifest.to_json, headers: { content_type: manifest_type })
- expect(client.repository_manifest('group/test', 'mytag')).to eq(manifest)
+ expect_new_faraday
+
+ expect(subject).to eq(manifest)
end
+
+ it_behaves_like 'handling timeouts'
end
- it_behaves_like '#repository_manifest', described_class::DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE
- it_behaves_like '#repository_manifest', described_class::OCI_MANIFEST_V1_TYPE
+ describe '#repository_manifest' do
+ subject { client.repository_manifest('group/test', 'mytag') }
+
+ it_behaves_like 'handling repository manifest', described_class::DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE
+ it_behaves_like 'handling repository manifest', described_class::OCI_MANIFEST_V1_TYPE
+ end
describe '#blob' do
+ let(:method) { :get }
+ let(:url) { 'http://container-registry/v2/group/test/blobs/sha256:0123456789012345' }
let(:blob_headers) do
{
'Accept' => 'application/octet-stream',
@@ -78,16 +135,20 @@ RSpec.describe ContainerRegistry::Client do
}
end
+ subject { client.blob('group/test', 'sha256:0123456789012345') }
+
it 'GET /v2/:name/blobs/:digest' do
- stub_request(:get, "http://container-registry/v2/group/test/blobs/sha256:0123456789012345")
+ stub_request(method, url)
.with(headers: blob_headers)
.to_return(status: 200, body: "Blob")
- expect(client.blob('group/test', 'sha256:0123456789012345')).to eq('Blob')
+ expect_new_faraday
+
+ expect(subject).to eq('Blob')
end
it 'follows 307 redirect for GET /v2/:name/blobs/:digest' do
- stub_request(:get, "http://container-registry/v2/group/test/blobs/sha256:0123456789012345")
+ stub_request(method, url)
.with(headers: blob_headers)
.to_return(status: 307, body: '', headers: { Location: 'http://redirected' })
# We should probably use hash_excluding here, but that requires an update to WebMock:
@@ -98,10 +159,12 @@ RSpec.describe ContainerRegistry::Client do
end
.to_return(status: 200, body: "Successfully redirected")
- response = client.blob('group/test', 'sha256:0123456789012345')
+ expect_new_faraday(times: 2)
- expect(response).to eq('Successfully redirected')
+ expect(subject).to eq('Successfully redirected')
end
+
+ it_behaves_like 'handling timeouts'
end
describe '#upload_blob' do
@@ -111,6 +174,8 @@ RSpec.describe ContainerRegistry::Client do
it 'starts the upload and posts the blob' do
stub_upload('path', 'content', 'sha256:123')
+ expect_new_faraday(timeout: false)
+
expect(subject).to be_success
end
end
@@ -173,6 +238,8 @@ RSpec.describe ContainerRegistry::Client do
.with(body: "{\n \"foo\": \"bar\"\n}", headers: manifest_headers)
.to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:123' })
+ expect_new_faraday(timeout: false)
+
expect(subject).to eq 'sha256:123'
end
end
@@ -375,4 +442,17 @@ RSpec.describe ContainerRegistry::Client do
headers: { 'Allow' => 'DELETE' }
)
end
+
+ def expect_new_faraday(times: 1, timeout: true)
+ request_options = timeout ? expected_faraday_request_options : nil
+ expect(Faraday)
+ .to receive(:new)
+ .with(
+ 'http://container-registry',
+ headers: expected_faraday_headers,
+ request: request_options
+ ).and_call_original
+ .exactly(times)
+ .times
+ end
end
diff --git a/spec/lib/declarative_enum_spec.rb b/spec/lib/declarative_enum_spec.rb
new file mode 100644
index 00000000000..66cda9fc3a8
--- /dev/null
+++ b/spec/lib/declarative_enum_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DeclarativeEnum do
+ let(:enum_module) do
+ Module.new do
+ extend DeclarativeEnum
+
+ key :my_enum
+ name 'MyEnumName'
+
+ description "Enum description"
+
+ define do
+ foo value: 0, description: 'description of foo'
+ bar value: 1, description: 'description of bar'
+ end
+ end
+ end
+
+ let(:original_definition) do
+ {
+ foo: { description: 'description of foo', value: 0 },
+ bar: { description: 'description of bar', value: 1 }
+ }
+ end
+
+ describe '.key' do
+ subject(:key) { enum_module.key(new_key) }
+
+ context 'when the argument is set' do
+ let(:new_key) { :new_enum_key }
+
+ it 'changes the key' do
+ expect { key }.to change { enum_module.key }.from(:my_enum).to(:new_enum_key)
+ end
+ end
+
+ context 'when the argument is `nil`' do
+ let(:new_key) { nil }
+
+ it { is_expected.to eq(:my_enum) }
+ end
+ end
+
+ describe '.name' do
+ subject(:name) { enum_module.name(new_name) }
+
+ context 'when the argument is set' do
+ let(:new_name) { 'NewMyEnumName' }
+
+ it 'changes the name' do
+ expect { name }.to change { enum_module.name }.from('MyEnumName').to('NewMyEnumName')
+ end
+ end
+
+ context 'when the argument is `nil`' do
+ let(:new_name) { nil }
+
+ it { is_expected.to eq('MyEnumName') }
+ end
+ end
+
+ describe '.description' do
+ subject(:description) { enum_module.description(new_description) }
+
+ context 'when the argument is set' do
+ let(:new_description) { 'New enum description' }
+
+ it 'changes the description' do
+ expect { description }.to change { enum_module.description }.from('Enum description').to('New enum description')
+ end
+ end
+
+ context 'when the argument is `nil`' do
+ let(:new_description) { nil }
+
+ it { is_expected.to eq('Enum description') }
+ end
+ end
+
+ describe '.define' do
+ subject(:define) { enum_module.define(&block) }
+
+ context 'when there is a block given' do
+ context 'when the given block tries to register the same key' do
+ let(:block) do
+ proc do
+ foo value: 2, description: 'description of foo'
+ end
+ end
+
+ it 'raises a `KeyCollisionError`' do
+ expect { define }.to raise_error(DeclarativeEnum::Builder::KeyCollisionError)
+ end
+ end
+
+ context 'when the given block does not try to register the same key' do
+ let(:expected_new_definition) { original_definition.merge(zoo: { description: 'description of zoo', value: 0 }) }
+ let(:block) do
+ proc do
+ zoo value: 0, description: 'description of zoo'
+ end
+ end
+
+ it 'appends the new definition' do
+ expect { define }.to change { enum_module.definition }.from(original_definition).to(expected_new_definition)
+ end
+ end
+ end
+
+ context 'when there is no block given' do
+ let(:block) { nil }
+
+ it 'raises a LocalJumpError' do
+ expect { define }.to raise_error(LocalJumpError)
+ end
+ end
+ end
+
+ describe '.definition' do
+ subject { enum_module.definition }
+
+ it { is_expected.to eq(original_definition) }
+ end
+
+ describe 'extending the enum module' do
+ let(:extended_definition) { original_definition.merge(zoo: { value: 2, description: 'description of zoo' }) }
+ let(:new_enum_module) do
+ Module.new do
+ extend DeclarativeEnum
+
+ define do
+ zoo value: 2, description: 'description of zoo'
+ end
+ end
+ end
+
+ subject(:prepend_new_enum_module) { enum_module.prepend(new_enum_module) }
+
+ it 'extends the values of the base enum module' do
+ expect { prepend_new_enum_module }.to change { enum_module.definition }.from(original_definition)
+ .to(extended_definition)
+ end
+ end
+end
diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb
index a994b4b92a6..b603325cdb8 100644
--- a/spec/lib/expand_variables_spec.rb
+++ b/spec/lib/expand_variables_spec.rb
@@ -224,4 +224,41 @@ RSpec.describe ExpandVariables do
end
end
end
+
+ describe '#possible_var_reference?' do
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty value": {
+ value: '',
+ result: false
+ },
+ "normal value": {
+ value: 'some value',
+ result: false
+ },
+ "simple expansions": {
+ value: 'key$variable',
+ result: true
+ },
+ "complex expansions": {
+ value: 'key${variable}${variable2}',
+ result: true
+ },
+ "complex expansions for Windows": {
+ value: 'key%variable%%variable2%',
+ result: true
+ }
+ }
+ end
+
+ with_them do
+ subject { ExpandVariables.possible_var_reference?(value) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production_spec.rb
new file mode 100644
index 00000000000..93e588675d3
--- /dev/null
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/issue_deployed_to_production_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::IssueDeployedToProduction do
+ it_behaves_like 'value stream analytics event'
+end
diff --git a/spec/lib/gitlab/api_authentication/builder_spec.rb b/spec/lib/gitlab/api_authentication/builder_spec.rb
new file mode 100644
index 00000000000..e241aa77805
--- /dev/null
+++ b/spec/lib/gitlab/api_authentication/builder_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::APIAuthentication::Builder do
+ describe '#build' do
+ shared_examples 'builds the correct result' do |token_type:, sent_through:, builds:|
+ context "with #{token_type.size} token type(s) and #{sent_through.size} sent through(s)" do
+ it 'works when passed together' do
+ strategies = described_class.new.build { |allow| allow.token_types(*token_type).sent_through(*sent_through) }
+
+ expect(strategies).to eq(builds)
+ end
+
+ it 'works when token types are passed separately' do
+ strategies = described_class.new.build { |allow| token_type.each { |t| allow.token_types(t).sent_through(*sent_through) } }
+
+ expect(strategies).to eq(builds)
+ end
+
+ it 'works when sent throughs are passed separately' do
+ strategies = described_class.new.build { |allow| sent_through.each { |s| allow.token_types(*token_type).sent_through(s) } }
+
+ expect(strategies).to eq(builds)
+ end
+
+ it 'works when token types and sent throughs are passed separately' do
+ strategies = described_class.new.build { |allow| token_type.each { |t| sent_through.each { |s| allow.token_types(t).sent_through(s) } } }
+
+ expect(strategies).to eq(builds)
+ end
+ end
+ end
+
+ it_behaves_like 'builds the correct result',
+ token_type: [:pat],
+ sent_through: [:basic],
+ builds: { basic: [:pat] }
+
+ it_behaves_like 'builds the correct result',
+ token_type: [:pat],
+ sent_through: [:basic, :oauth],
+ builds: { basic: [:pat], oauth: [:pat] }
+
+ it_behaves_like 'builds the correct result',
+ token_type: [:pat, :job],
+ sent_through: [:basic],
+ builds: { basic: [:pat, :job] }
+
+ it_behaves_like 'builds the correct result',
+ token_type: [:pat, :job],
+ sent_through: [:basic, :oauth],
+ builds: { basic: [:pat, :job], oauth: [:pat, :job] }
+
+ context 'with a complex auth strategy' do
+ it 'builds the correct result' do
+ strategies = described_class.new.build do |allow|
+ allow.token_types(:pat, :job, :deploy).sent_through(:http_basic, :oauth)
+ allow.token_types(:pat).sent_through(:http_private, :query_private)
+ allow.token_types(:oauth2).sent_through(:http_bearer, :query_access)
+ end
+
+ expect(strategies).to eq({
+ http_basic: [:pat, :job, :deploy],
+ oauth: [:pat, :job, :deploy],
+
+ http_private: [:pat],
+ query_private: [:pat],
+
+ http_bearer: [:oauth2],
+ query_access: [:oauth2]
+ })
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/api_authentication/sent_through_builder_spec.rb b/spec/lib/gitlab/api_authentication/sent_through_builder_spec.rb
new file mode 100644
index 00000000000..845e317f3aa
--- /dev/null
+++ b/spec/lib/gitlab/api_authentication/sent_through_builder_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::APIAuthentication::SentThroughBuilder do
+ describe '#sent_through' do
+ let(:resolvers) { Array.new(3) { double } }
+ let(:locators) { Array.new(3) { double } }
+
+ it 'adds a strategy for each of locators x resolvers' do
+ strategies = locators.to_h { |l| [l, []] }
+ described_class.new(strategies, resolvers).sent_through(*locators)
+
+ expect(strategies).to eq(locators.to_h { |l| [l, resolvers] })
+ 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
new file mode 100644
index 00000000000..68ce48a70ea
--- /dev/null
+++ b/spec/lib/gitlab/api_authentication/token_locator_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::APIAuthentication::TokenLocator do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :public) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:ci_job) { create(:ci_build, project: project, user: user, status: :running) }
+ let_it_be(:ci_job_done) { create(:ci_build, project: project, user: user, status: :success) }
+ let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+
+ describe '.new' do
+ context 'with a valid type' do
+ it 'creates a new instance' do
+ expect(described_class.new(:http_basic_auth)).to be_a(described_class)
+ end
+ end
+
+ context 'with an invalid type' do
+ it 'raises ActiveModel::ValidationError' do
+ expect { described_class.new(:not_a_real_locator) }.to raise_error(ActiveModel::ValidationError)
+ end
+ end
+ end
+
+ describe '#extract' do
+ let(:locator) { described_class.new(type) }
+
+ subject { locator.extract(request) }
+
+ context 'with :http_basic_auth' do
+ let(:type) { :http_basic_auth }
+
+ context 'without credentials' do
+ let(:request) { double(authorization: nil) }
+
+ it 'returns nil' do
+ expect(subject).to be(nil)
+ end
+ end
+
+ context 'with credentials' do
+ let(:username) { 'foo' }
+ let(:password) { 'bar' }
+ let(:request) { double(authorization: "Basic #{::Base64.strict_encode64("#{username}:#{password}")}") }
+
+ it 'returns the credentials' do
+ expect(subject.username).to eq(username)
+ 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
new file mode 100644
index 00000000000..0028fb080ac
--- /dev/null
+++ b/spec/lib/gitlab/api_authentication/token_resolver_spec.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::APIAuthentication::TokenResolver do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :public) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:ci_job) { create(:ci_build, project: project, user: user, status: :running) }
+ let_it_be(:ci_job_done) { create(:ci_build, project: project, user: user, status: :success) }
+ let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+
+ shared_examples 'an authorized request' do
+ it 'returns the correct token' do
+ expect(subject).to eq(token)
+ end
+ end
+
+ shared_examples 'an unauthorized request' do
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ end
+ end
+
+ shared_examples 'an anoymous request' do
+ it 'returns nil' do
+ expect(subject).to eq(nil)
+ end
+ end
+
+ describe '.new' do
+ context 'with a valid type' do
+ it 'creates a new instance' do
+ expect(described_class.new(:personal_access_token)).to be_a(described_class)
+ end
+ end
+
+ context 'with an invalid type' do
+ it 'raises a validation error' do
+ expect { described_class.new(:not_a_real_locator) }.to raise_error(ActiveModel::ValidationError)
+ end
+ end
+ end
+
+ describe '#resolve' do
+ let(:resolver) { described_class.new(type) }
+
+ subject { resolver.resolve(raw) }
+
+ 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(user.username, token.token) }
+
+ it_behaves_like 'an authorized request'
+ end
+
+ context 'with an invalid username' do
+ let(:raw) { username_and_password("not-my-#{user.username}", token.token) }
+
+ it_behaves_like 'an unauthorized 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(Gitlab::Auth::CI_JOB_USER, token.token) }
+
+ it_behaves_like 'an authorized request'
+ end
+
+ context 'when the job is not running' do
+ let(:raw) { username_and_password(Gitlab::Auth::CI_JOB_USER, ci_job_done.token) }
+
+ it_behaves_like 'an unauthorized request'
+ end
+
+ context 'with the wrong username' do
+ let(:raw) { username_and_password("not-#{Gitlab::Auth::CI_JOB_USER}", nil) }
+
+ it_behaves_like 'an anoymous request'
+ end
+
+ context 'with an invalid job token' do
+ let(:raw) { username_and_password(Gitlab::Auth::CI_JOB_USER, "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(token.username, token.token) }
+
+ it_behaves_like 'an authorized request'
+ end
+
+ context 'with an invalid username' do
+ let(:raw) { username_and_password("not-my-#{token.username}", token.token) }
+
+ it_behaves_like 'an unauthorized request'
+ end
+ end
+ end
+
+ def username_and_password(username, password)
+ ::Gitlab::APIAuthentication::TokenLocator::UsernameAndPassword.new(username, password)
+ end
+end
diff --git a/spec/lib/gitlab/api_authentication/token_type_builder_spec.rb b/spec/lib/gitlab/api_authentication/token_type_builder_spec.rb
new file mode 100644
index 00000000000..fbca62c9a42
--- /dev/null
+++ b/spec/lib/gitlab/api_authentication/token_type_builder_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::APIAuthentication::TokenTypeBuilder do
+ describe '#token_types' do
+ it 'passes strategies and resolvers to SentThroughBuilder' do
+ strategies = double
+ resolvers = Array.new(3) { double }
+ retval = double
+ expect(Gitlab::APIAuthentication::SentThroughBuilder).to receive(:new).with(strategies, resolvers).and_return(retval)
+
+ expect(described_class.new(strategies).token_types(*resolvers)).to be(retval)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/asset_proxy_spec.rb b/spec/lib/gitlab/asset_proxy_spec.rb
index 73b101c0dd8..7d7952d5741 100644
--- a/spec/lib/gitlab/asset_proxy_spec.rb
+++ b/spec/lib/gitlab/asset_proxy_spec.rb
@@ -17,12 +17,12 @@ RSpec.describe Gitlab::AssetProxy do
context 'when asset proxy is enabled' do
before do
- stub_asset_proxy_setting(whitelist: %w(gitlab.com *.mydomain.com))
+ stub_asset_proxy_setting(allowlist: %w(gitlab.com *.mydomain.com))
stub_asset_proxy_setting(
enabled: true,
url: 'https://assets.example.com',
secret_key: 'shared-secret',
- domain_regexp: Banzai::Filter::AssetProxyFilter.compile_whitelist(Gitlab.config.asset_proxy.whitelist)
+ domain_regexp: Banzai::Filter::AssetProxyFilter.compile_allowlist(Gitlab.config.asset_proxy.allowlist)
)
end
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index f927d5912bb..775f8f056b5 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
include described_class
include HttpBasicAuthHelpers
- let(:user) { create(:user) }
+ # 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(:env) do
{
'rack.input' => ''
@@ -65,7 +66,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_bearer_token' do
- let(:job) { create(:ci_build, user: user) }
+ let_it_be_with_reload(:job) { create(:ci_build, user: user) }
subject { find_user_from_bearer_token }
@@ -91,7 +92,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'with a personal access token' do
- let(:pat) { create(:personal_access_token, user: user) }
+ let_it_be(:pat) { create(:personal_access_token, user: user) }
let(:token) { pat.token }
before do
@@ -148,7 +149,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
it 'returns nil if valid feed_token and disabled' do
- allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true)
+ stub_application_setting(disable_feed_token: true)
set_param(:feed_token, user.feed_token)
expect(find_user_from_feed_token(:rss)).to be_nil
@@ -166,7 +167,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'when rss_token param is provided' do
- it 'returns user if valid rssd_token' do
+ it 'returns user if valid rss_token' do
set_param(:rss_token, user.feed_token)
expect(find_user_from_feed_token(:rss)).to eq user
@@ -347,7 +348,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_access_token' do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
before do
set_header('SCRIPT_NAME', 'url.atom')
@@ -386,7 +387,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'when using a non-prefixed access token' do
- let(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) }
it 'returns user' do
set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}")
@@ -398,7 +399,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_web_access_token' do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ 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)
@@ -449,6 +450,22 @@ RSpec.describe Gitlab::Auth::AuthFinders do
expect(find_user_from_web_access_token(:api)).to be_nil
end
+ context 'when the token has read_api scope' do
+ before do
+ personal_access_token.update!(scopes: ['read_api'])
+
+ set_header('SCRIPT_NAME', '/api/endpoint')
+ end
+
+ it 'raises InsufficientScopeError by default' do
+ expect { find_user_from_web_access_token(:api) }.to raise_error(Gitlab::Auth::InsufficientScopeError)
+ end
+
+ it 'finds the user when the read_api scope is passed' do
+ expect(find_user_from_web_access_token(:api, scopes: [:api, :read_api])).to eq(user)
+ end
+ end
+
context 'when relative_url_root is set' do
before do
stub_config_setting(relative_url_root: '/relative_root')
@@ -464,7 +481,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_personal_access_token' do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
before do
set_header('SCRIPT_NAME', 'url.atom')
@@ -534,7 +551,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'access token is valid' do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ 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
@@ -555,7 +572,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'route_setting is not set' do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
it 'returns nil' do
auth_header_with(personal_access_token.token)
@@ -565,7 +582,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'route_setting is not correct' do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ 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
@@ -611,8 +628,9 @@ RSpec.describe Gitlab::Auth::AuthFinders do
context 'with CI username' do
let(:username) { ::Gitlab::Auth::CI_JOB_USER }
- let(:user) { create(:user) }
- let(:build) { create(:ci_build, user: user, status: :running) }
+
+ 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)
@@ -645,11 +663,11 @@ RSpec.describe Gitlab::Auth::AuthFinders do
describe '#validate_access_token!' do
subject { validate_access_token! }
- let(:personal_access_token) { create(:personal_access_token, user: user) }
+ 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 } }
- let(:job) { create(:ci_build, user: user, status: :running) }
before do
env['HTTP_AUTHORIZATION'] = "Bearer #{job.token}"
@@ -671,7 +689,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
it 'returns Gitlab::Auth::ExpiredError if token expired' do
- personal_access_token.expires_at = 1.day.ago
+ personal_access_token.update!(expires_at: 1.day.ago)
expect { validate_access_token! }.to raise_error(Gitlab::Auth::ExpiredError)
end
@@ -688,7 +706,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'with impersonation token' do
- let(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
context 'when impersonation is disabled' do
before do
@@ -704,7 +722,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_job_token' do
- let(:job) { create(:ci_build, user: user, status: :running) }
+ 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 }
@@ -866,7 +884,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_runner_from_token' do
- let(:runner) { create(:ci_runner) }
+ let_it_be(:runner) { create(:ci_runner) }
context 'with API requests' do
before do
diff --git a/spec/lib/gitlab/auth/current_user_mode_spec.rb b/spec/lib/gitlab/auth/current_user_mode_spec.rb
index ffd7813190a..a21f0931b78 100644
--- a/spec/lib/gitlab/auth/current_user_mode_spec.rb
+++ b/spec/lib/gitlab/auth/current_user_mode_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode, :request_store do
+RSpec.describe Gitlab::Auth::CurrentUserMode, :request_store do
let(:user) { build_stubbed(:user) }
subject { described_class.new(user) }
diff --git a/spec/lib/gitlab/auth/ldap/config_spec.rb b/spec/lib/gitlab/auth/ldap/config_spec.rb
index e4c87a54365..7a657cce597 100644
--- a/spec/lib/gitlab/auth/ldap/config_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/config_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Gitlab::Auth::Ldap::Config do
include LdapHelpers
+ before do
+ stub_ldap_setting(enabled: true)
+ end
+
let(:config) { described_class.new('ldapmain') }
def raw_cert
@@ -68,12 +72,28 @@ AtlErSqafbECNDSwS5BX8yDpu5yRBJ4xegO/rNlmb8ICRYkuJapD1xXicFOsmfUK
describe '.servers' do
it 'returns empty array if no server information is available' do
- allow(Gitlab.config).to receive(:ldap).and_return('enabled' => false)
+ stub_ldap_setting(servers: {})
expect(described_class.servers).to eq []
end
end
+ describe '.available_providers' do
+ before do
+ stub_licensed_features(multiple_ldap_servers: false)
+ stub_ldap_setting(
+ 'servers' => {
+ 'main' => { 'provider_name' => 'ldapmain' },
+ 'secondary' => { 'provider_name' => 'ldapsecondary' }
+ }
+ )
+ end
+
+ it 'returns one provider' do
+ expect(described_class.available_providers).to match_array(%w(ldapmain))
+ end
+ end
+
describe '#initialize' do
it 'requires a provider' do
expect { described_class.new }.to raise_error ArgumentError
diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb
index ef6b1d72712..93e9cb06786 100644
--- a/spec/lib/gitlab/auth/request_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb
@@ -47,7 +47,10 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
let!(:job_token_user) { build(:user) }
it 'returns access_token user first' do
- allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token).and_return(access_token_user)
+ allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token)
+ .with(anything, scopes: [:api, :read_api])
+ .and_return(access_token_user)
+
allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
expect(subject.find_sessionless_user(:api)).to eq access_token_user
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index dfd21983682..4e4bbd1bb60 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -372,6 +372,11 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
expect(gl_auth.find_for_git_client(project_bot_user.username, project_access_token.token, project: project, ip: 'ip'))
.to eq(Gitlab::Auth::Result.new(project_bot_user, nil, :personal_access_token, described_class.full_authentication_abilities))
end
+
+ it 'successfully authenticates the project bot with a nil project' do
+ expect(gl_auth.find_for_git_client(project_bot_user.username, project_access_token.token, project: nil, ip: 'ip'))
+ .to eq(Gitlab::Auth::Result.new(project_bot_user, nil, :personal_access_token, described_class.full_authentication_abilities))
+ end
end
context 'with invalid project access token' do
diff --git a/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb b/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb
new file mode 100644
index 00000000000..49fa7b41916
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillArtifactExpiryDate, :migration, schema: 20201111152859 do
+ subject(:perform) { migration.perform(1, 99) }
+
+ let(:migration) { described_class.new }
+ let(:artifact_outside_id_range) { create_artifact!(id: 100, created_at: 1.year.ago, expire_at: nil) }
+ let(:artifact_outside_date_range) { create_artifact!(id: 40, created_at: Time.current, expire_at: nil) }
+ let(:old_artifact) { create_artifact!(id: 10, created_at: 16.months.ago, expire_at: nil) }
+ let(:recent_artifact) { create_artifact!(id: 20, created_at: 1.year.ago, expire_at: nil) }
+ let(:artifact_with_expiry) { create_artifact!(id: 30, created_at: 1.year.ago, expire_at: Time.current + 1.day) }
+
+ before do
+ table(:namespaces).create!(id: 1, name: 'the-namespace', path: 'the-path')
+ table(:projects).create!(id: 1, name: 'the-project', namespace_id: 1)
+ table(:ci_builds).create!(id: 1, allow_failure: false)
+ end
+
+ context 'when current date is before the 22nd' do
+ before do
+ travel_to(Time.zone.local(2020, 1, 1, 0, 0, 0))
+ end
+
+ it 'backfills the expiry date for old artifacts' do
+ expect(old_artifact.reload.expire_at).to eq(nil)
+
+ perform
+
+ expect(old_artifact.reload.expire_at).to be_within(1.minute).of(Time.zone.local(2020, 4, 22, 0, 0, 0))
+ end
+
+ it 'backfills the expiry date for recent artifacts' do
+ expect(recent_artifact.reload.expire_at).to eq(nil)
+
+ perform
+
+ expect(recent_artifact.reload.expire_at).to be_within(1.minute).of(Time.zone.local(2021, 1, 22, 0, 0, 0))
+ end
+ end
+
+ context 'when current date is after the 22nd' do
+ before do
+ travel_to(Time.zone.local(2020, 1, 23, 0, 0, 0))
+ end
+
+ it 'backfills the expiry date for old artifacts' do
+ expect(old_artifact.reload.expire_at).to eq(nil)
+
+ perform
+
+ expect(old_artifact.reload.expire_at).to be_within(1.minute).of(Time.zone.local(2020, 5, 22, 0, 0, 0))
+ end
+
+ it 'backfills the expiry date for recent artifacts' do
+ expect(recent_artifact.reload.expire_at).to eq(nil)
+
+ perform
+
+ expect(recent_artifact.reload.expire_at).to be_within(1.minute).of(Time.zone.local(2021, 2, 22, 0, 0, 0))
+ end
+ end
+
+ it 'does not touch artifacts with expiry date' do
+ expect { perform }.not_to change { artifact_with_expiry.reload.expire_at }
+ end
+
+ it 'does not touch artifacts outside id range' do
+ expect { perform }.not_to change { artifact_outside_id_range.reload.expire_at }
+ end
+
+ it 'does not touch artifacts outside date range' do
+ expect { perform }.not_to change { artifact_outside_date_range.reload.expire_at }
+ end
+
+ private
+
+ def create_artifact!(**args)
+ table(:ci_job_artifacts).create!(**args, project_id: 1, job_id: 1, file_type: 1)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
new file mode 100644
index 00000000000..110a1ff8a08
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob do
+ let(:table_name) { :copy_primary_key_test }
+ let(:test_table) { table(table_name) }
+ let(:sub_batch_size) { 1000 }
+
+ before do
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ CREATE TABLE #{table_name}
+ (
+ id integer NOT NULL,
+ name character varying,
+ fk integer NOT NULL,
+ id_convert_to_bigint bigint DEFAULT 0 NOT NULL,
+ fk_convert_to_bigint bigint DEFAULT 0 NOT NULL,
+ name_convert_to_text text DEFAULT 'no name'
+ );
+ SQL
+
+ # Insert some data, it doesn't make a difference
+ test_table.create!(id: 11, name: 'test1', fk: 1)
+ test_table.create!(id: 12, name: 'test2', fk: 2)
+ test_table.create!(id: 15, name: nil, fk: 3)
+ test_table.create!(id: 19, name: 'test4', fk: 4)
+ end
+
+ after do
+ # Make sure that the temp table we created is dropped (it is not removed by the database_cleaner)
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ DROP TABLE IF EXISTS #{table_name};
+ SQL
+ end
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ let(:migration_class) { described_class.name }
+ let!(:job1) do
+ table(:background_migration_jobs).create!(
+ class_name: migration_class,
+ arguments: [1, 10, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size]
+ )
+ end
+
+ let!(:job2) do
+ table(:background_migration_jobs).create!(
+ class_name: migration_class,
+ arguments: [11, 20, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size]
+ )
+ end
+
+ it 'copies all primary keys in range' do
+ subject.perform(12, 15, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size)
+
+ expect(test_table.where('id = id_convert_to_bigint').pluck(:id)).to contain_exactly(12, 15)
+ expect(test_table.where(id_convert_to_bigint: 0).pluck(:id)).to contain_exactly(11, 19)
+ expect(test_table.all.count).to eq(4)
+ end
+
+ it 'copies all foreign keys in range' do
+ subject.perform(10, 14, table_name, 'id', 'fk', 'fk_convert_to_bigint', sub_batch_size)
+
+ expect(test_table.where('fk = fk_convert_to_bigint').pluck(:id)).to contain_exactly(11, 12)
+ expect(test_table.where(fk_convert_to_bigint: 0).pluck(:id)).to contain_exactly(15, 19)
+ expect(test_table.all.count).to eq(4)
+ end
+
+ it 'copies columns with NULLs' do
+ expect(test_table.where("name_convert_to_text = 'no name'").count).to eq(4)
+
+ subject.perform(10, 20, table_name, 'id', 'name', 'name_convert_to_text', sub_batch_size)
+
+ expect(test_table.where('name = name_convert_to_text').pluck(:id)).to contain_exactly(11, 12, 19)
+ expect(test_table.where('name is NULL and name_convert_to_text is NULL').pluck(:id)).to contain_exactly(15)
+ expect(test_table.where("name_convert_to_text = 'no name'").count).to eq(0)
+ end
+
+ it 'tracks completion with BackgroundMigrationJob' do
+ expect do
+ subject.perform(11, 20, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size)
+ end.to change { Gitlab::Database::BackgroundMigrationJob.succeeded.count }.from(0).to(1)
+
+ expect(job1.reload.status).to eq(0)
+ expect(job2.reload.status).to eq(1)
+ expect(test_table.where('id = id_convert_to_bigint').count).to eq(4)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
new file mode 100644
index 00000000000..8e74935e127
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20201211090634 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:users) { table(:users) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:identifiers) { table(:vulnerability_identifiers) }
+ let(:findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_feedback) { table(:vulnerability_feedback) }
+
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
+ let(:user) { users.create!(username: 'john.doe', projects_limit: 5) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') }
+ let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'baz') }
+ let(:sast_report) { 0 }
+ let(:dependency_scanning_report) { 1 }
+ let(:dast_report) { 3 }
+ let(:secret_detection_report) { 4 }
+ let(:project_fingerprint) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:location_fingerprint_1) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:location_fingerprint_2) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:location_fingerprint_3) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
+ let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) }
+ let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) }
+ let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) }
+ let(:uuid_1_components) { ['sast', identifier.fingerprint, location_fingerprint_1, project.id].join('-') }
+ let(:uuid_2_components) { ['dast', identifier.fingerprint, location_fingerprint_2, project.id].join('-') }
+ let(:uuid_3_components) { ['secret_detection', identifier.fingerprint, location_fingerprint_3, project.id].join('-') }
+ let(:expected_uuid_1) { Gitlab::UUID.v5(uuid_1_components) }
+ let(:expected_uuid_2) { Gitlab::UUID.v5(uuid_2_components) }
+ let(:expected_uuid_3) { Gitlab::UUID.v5(uuid_3_components) }
+ let(:finding_creator) do
+ -> (report_type, location_fingerprint) do
+ findings.create!(
+ project_id: project.id,
+ primary_identifier_id: identifier.id,
+ scanner_id: scanner.id,
+ report_type: report_type,
+ uuid: SecureRandom.uuid,
+ name: 'Foo',
+ location_fingerprint: Gitlab::Database::ShaAttribute.serialize(location_fingerprint),
+ project_fingerprint: Gitlab::Database::ShaAttribute.serialize(project_fingerprint),
+ metadata_version: '1',
+ severity: 0,
+ confidence: 5,
+ raw_metadata: '{}'
+ )
+ end
+ end
+
+ let(:feedback_creator) do
+ -> (category, project_fingerprint) do
+ vulnerability_feedback.create!(
+ project_id: project.id,
+ author_id: user.id,
+ feedback_type: 0,
+ category: category,
+ project_fingerprint: project_fingerprint
+ )
+ end
+ end
+
+ let!(:feedback_1) { feedback_creator.call(finding_1.report_type, project_fingerprint) }
+ let!(:feedback_2) { feedback_creator.call(finding_2.report_type, project_fingerprint) }
+ let!(:feedback_3) { feedback_creator.call(finding_3.report_type, project_fingerprint) }
+ let!(:feedback_4) { feedback_creator.call(finding_1.report_type, 'foo') }
+ let!(:feedback_5) { feedback_creator.call(dependency_scanning_report, project_fingerprint) }
+
+ subject(:populate_finding_uuids) { described_class.new.perform(feedback_1.id, feedback_5.id) }
+
+ before do
+ allow(Gitlab::BackgroundMigration::Logger).to receive(:info)
+ end
+
+ describe '#perform' do
+ it 'updates the `finding_uuid` attributes of the feedback records' do
+ expect { populate_finding_uuids }.to change { feedback_1.reload.finding_uuid }.from(nil).to(expected_uuid_1)
+ .and change { feedback_2.reload.finding_uuid }.from(nil).to(expected_uuid_2)
+ .and change { feedback_3.reload.finding_uuid }.from(nil).to(expected_uuid_3)
+ .and not_change { feedback_4.reload.finding_uuid }
+ .and not_change { feedback_5.reload.finding_uuid }
+
+ expect(Gitlab::BackgroundMigration::Logger).to have_received(:info).once
+ end
+
+ it 'preloads the finding and identifier records to prevent N+1 queries' do
+ # Load feedback records(1), load findings(2), load identifiers(3) and finally update feedback records one by one(6)
+ expect { populate_finding_uuids }.not_to exceed_query_limit(6)
+ end
+
+ context 'when setting the `finding_uuid` attribute of a feedback record fails' do
+ let(:expected_error) { RuntimeError.new }
+
+ before do
+ allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ allow_next_found_instance_of(described_class::VulnerabilityFeedback) do |feedback|
+ allow(feedback).to receive(:update_column).and_raise(expected_error)
+ end
+ end
+
+ it 'captures the errors and does not crash entirely' do
+ expect { populate_finding_uuids }.not_to raise_error
+
+ expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(expected_error).exactly(3).times
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb b/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb
new file mode 100644
index 00000000000..391b27b28e6
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateServices, :migration, schema: 20201207165956 do
+ let_it_be(:users) { table(:users) }
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:services) { table(:services) }
+
+ let_it_be(:alerts_service_data) { table(:alerts_service_data) }
+ let_it_be(:chat_names) { table(:chat_names) }
+ let_it_be(:issue_tracker_data) { table(:issue_tracker_data) }
+ let_it_be(:jira_tracker_data) { table(:jira_tracker_data) }
+ let_it_be(:open_project_tracker_data) { table(:open_project_tracker_data) }
+ let_it_be(:slack_integrations) { table(:slack_integrations) }
+ let_it_be(:web_hooks) { table(:web_hooks) }
+
+ let_it_be(:data_tables) do
+ [alerts_service_data, chat_names, issue_tracker_data, jira_tracker_data, open_project_tracker_data, slack_integrations, web_hooks]
+ end
+
+ let!(:user) { users.create!(id: 1, projects_limit: 100) }
+ let!(:namespace) { namespaces.create!(id: 1, name: 'group', path: 'group') }
+
+ # project without duplicate services
+ let!(:project1) { projects.create!(id: 1, namespace_id: namespace.id) }
+ let!(:service1) { services.create!(id: 1, project_id: project1.id, type: 'AsanaService') }
+ let!(:service2) { services.create!(id: 2, project_id: project1.id, type: 'JiraService') }
+ let!(:service3) { services.create!(id: 3, project_id: project1.id, type: 'SlackService') }
+
+ # project with duplicate services
+ let!(:project2) { projects.create!(id: 2, namespace_id: namespace.id) }
+ let!(:service4) { services.create!(id: 4, project_id: project2.id, type: 'AsanaService') }
+ let!(:service5) { services.create!(id: 5, project_id: project2.id, type: 'JiraService') }
+ let!(:service6) { services.create!(id: 6, project_id: project2.id, type: 'JiraService') }
+ let!(:service7) { services.create!(id: 7, project_id: project2.id, type: 'SlackService') }
+ let!(:service8) { services.create!(id: 8, project_id: project2.id, type: 'SlackService') }
+ let!(:service9) { services.create!(id: 9, project_id: project2.id, type: 'SlackService') }
+
+ # project with duplicate services and dependant records
+ let!(:project3) { projects.create!(id: 3, namespace_id: namespace.id) }
+ let!(:service10) { services.create!(id: 10, project_id: project3.id, type: 'AlertsService') }
+ let!(:service11) { services.create!(id: 11, project_id: project3.id, type: 'AlertsService') }
+ let!(:service12) { services.create!(id: 12, project_id: project3.id, type: 'SlashCommandsService') }
+ let!(:service13) { services.create!(id: 13, project_id: project3.id, type: 'SlashCommandsService') }
+ let!(:service14) { services.create!(id: 14, project_id: project3.id, type: 'IssueTrackerService') }
+ let!(:service15) { services.create!(id: 15, project_id: project3.id, type: 'IssueTrackerService') }
+ let!(:service16) { services.create!(id: 16, project_id: project3.id, type: 'JiraService') }
+ let!(:service17) { services.create!(id: 17, project_id: project3.id, type: 'JiraService') }
+ let!(:service18) { services.create!(id: 18, project_id: project3.id, type: 'OpenProjectService') }
+ let!(:service19) { services.create!(id: 19, project_id: project3.id, type: 'OpenProjectService') }
+ let!(:service20) { services.create!(id: 20, project_id: project3.id, type: 'SlackService') }
+ let!(:service21) { services.create!(id: 21, project_id: project3.id, type: 'SlackService') }
+ let!(:dependant_records) do
+ alerts_service_data.create!(id: 1, service_id: service10.id)
+ alerts_service_data.create!(id: 2, service_id: service11.id)
+ chat_names.create!(id: 1, service_id: service12.id, user_id: user.id, team_id: 'team1', chat_id: 'chat1')
+ chat_names.create!(id: 2, service_id: service13.id, user_id: user.id, team_id: 'team2', chat_id: 'chat2')
+ issue_tracker_data.create!(id: 1, service_id: service14.id)
+ issue_tracker_data.create!(id: 2, service_id: service15.id)
+ jira_tracker_data.create!(id: 1, service_id: service16.id)
+ jira_tracker_data.create!(id: 2, service_id: service17.id)
+ open_project_tracker_data.create!(id: 1, service_id: service18.id)
+ open_project_tracker_data.create!(id: 2, service_id: service19.id)
+ slack_integrations.create!(id: 1, service_id: service20.id, user_id: user.id, team_id: 'team1', team_name: 'team1', alias: 'alias1')
+ slack_integrations.create!(id: 2, service_id: service21.id, user_id: user.id, team_id: 'team2', team_name: 'team2', alias: 'alias2')
+ web_hooks.create!(id: 1, service_id: service20.id)
+ web_hooks.create!(id: 2, service_id: service21.id)
+ end
+
+ # project without services
+ let!(:project4) { projects.create!(id: 4, namespace_id: namespace.id) }
+
+ it 'removes duplicate services and dependant records' do
+ # Determine which services we expect to keep
+ expected_services = projects.pluck(:id).each_with_object({}) do |project_id, map|
+ project_services = services.where(project_id: project_id)
+ types = project_services.distinct.pluck(:type)
+
+ map[project_id] = types.map { |type| project_services.where(type: type).take!.id }
+ end
+
+ expect do
+ subject.perform(project2.id, project3.id)
+ end.to change { services.count }.from(21).to(12)
+
+ services1 = services.where(project_id: project1.id)
+ expect(services1.count).to be(3)
+ expect(services1.pluck(:type)).to contain_exactly('AsanaService', 'JiraService', 'SlackService')
+ expect(services1.pluck(:id)).to contain_exactly(*expected_services[project1.id])
+
+ services2 = services.where(project_id: project2.id)
+ expect(services2.count).to be(3)
+ expect(services2.pluck(:type)).to contain_exactly('AsanaService', 'JiraService', 'SlackService')
+ expect(services2.pluck(:id)).to contain_exactly(*expected_services[project2.id])
+
+ services3 = services.where(project_id: project3.id)
+ expect(services3.count).to be(6)
+ expect(services3.pluck(:type)).to contain_exactly('AlertsService', 'SlashCommandsService', 'IssueTrackerService', 'JiraService', 'OpenProjectService', 'SlackService')
+ expect(services3.pluck(:id)).to contain_exactly(*expected_services[project3.id])
+
+ kept_services = expected_services.values.flatten
+ data_tables.each do |table|
+ expect(table.count).to be(1)
+ expect(kept_services).to include(table.pluck(:service_id).first)
+ end
+ end
+
+ it 'does not delete services without duplicates' do
+ expect do
+ subject.perform(project1.id, project4.id)
+ end.not_to change { services.count }
+ end
+
+ it 'only deletes duplicate services for the current batch' do
+ expect do
+ subject.perform(project2.id)
+ end.to change { services.count }.by(-3)
+ end
+end
diff --git a/spec/lib/gitlab/checks/diff_check_spec.rb b/spec/lib/gitlab/checks/diff_check_spec.rb
index f4daafb1d0e..6b45b8d4628 100644
--- a/spec/lib/gitlab/checks/diff_check_spec.rb
+++ b/spec/lib/gitlab/checks/diff_check_spec.rb
@@ -6,96 +6,63 @@ RSpec.describe Gitlab::Checks::DiffCheck do
include_context 'change access checks context'
describe '#validate!' do
- let(:owner) { create(:user) }
-
- before do
- allow(project.repository).to receive(:new_commits).and_return(
- project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51')
- )
- end
-
- context 'with LFS not enabled' do
- before do
- allow(project).to receive(:lfs_enabled?).and_return(false)
- end
-
- it 'does not invoke :lfs_file_locks_validation' do
- expect(subject).not_to receive(:lfs_file_locks_validation)
+ context 'when commits is empty' do
+ it 'does not call find_changed_paths' do
+ expect(project.repository).not_to receive(:find_changed_paths)
subject.validate!
end
end
- context 'with LFS enabled' do
- let!(:lock) { create(:lfs_file_lock, user: owner, project: project, path: 'README') }
-
+ context 'when commits is not empty' do
before do
- allow(project).to receive(:lfs_enabled?).and_return(true)
+ allow(project.repository).to receive(:new_commits).and_return(
+ project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51')
+ )
end
- context 'when change is sent by a different user' do
- context 'when diff check with paths rpc feature flag is true' do
- it 'raises an error if the user is not allowed to update the file' do
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
- end
- end
+ context 'when deletion is true' do
+ let(:newrev) { Gitlab::Git::BLANK_SHA }
- context 'when diff check with paths rpc feature flag is false' do
- before do
- stub_feature_flags(diff_check_with_paths_changed_rpc: false)
- end
+ it 'does not call find_changed_paths' do
+ expect(project.repository).not_to receive(:find_changed_paths)
- it 'raises an error if the user is not allowed to update the file' do
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
- end
+ subject.validate!
end
end
- context 'when change is sent by the author of the lock' do
- let(:user) { owner }
-
- it "doesn't raise any error" do
- expect { subject.validate! }.not_to raise_error
+ context 'with LFS not enabled' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(false)
end
- end
- end
-
- context 'commit diff validations' do
- before do
- allow(subject).to receive(:validations_for_diff).and_return([lambda { |diff| return }])
-
- expect_any_instance_of(Commit).to receive(:raw_deltas).and_call_original
-
- stub_feature_flags(diff_check_with_paths_changed_rpc: false)
-
- subject.validate!
- end
- context 'when request store is inactive' do
- it 'are run for every commit' do
- expect_any_instance_of(Commit).to receive(:raw_deltas).and_call_original
+ it 'does not invoke :lfs_file_locks_validation' do
+ expect(subject).not_to receive(:lfs_file_locks_validation)
subject.validate!
end
end
- context 'when request store is active', :request_store do
- it 'are cached for every commit' do
- expect_any_instance_of(Commit).not_to receive(:raw_deltas)
+ context 'with LFS enabled' do
+ let(:owner) { create(:user) }
+ let!(:lock) { create(:lfs_file_lock, user: owner, project: project, path: 'README') }
- subject.validate!
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
end
- it 'are run for not cached commits' do
- allow(project.repository).to receive(:new_commits).and_return(
- project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', 'a5391128b0ef5d21df5dd23d98557f4ef12fae20')
- )
- change_access.instance_variable_set(:@commits, project.repository.new_commits)
+ context 'when change is sent by a different user' do
+ it 'raises an error if the user is not allowed to update the file' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
+ end
+ end
- expect(project.repository.new_commits.first).not_to receive(:raw_deltas).and_call_original
- expect(project.repository.new_commits.last).to receive(:raw_deltas).and_call_original
+ context 'when change is sent by the author of the lock' do
+ let(:user) { owner }
- subject.validate!
+ it "doesn't raise any error" do
+ expect { subject.validate! }.not_to raise_error
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
index 028dcd3e1e6..0e6d5b6c311 100644
--- a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
@@ -36,6 +36,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Artifacts do
expect(entry.value).to eq config
end
end
+
+ context "when value includes 'public' keyword" do
+ let(:config) { { paths: %w[results.txt], public: false } }
+
+ it 'returns general artifact and report-type artifacts configuration' do
+ expect(entry.value).to eq config
+ end
+ end
end
context 'when entry value is not correct' do
@@ -67,6 +75,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Artifacts do
end
end
+ context "when 'public' is not a boolean" do
+ let(:config) { { paths: %w[results.txt], public: 'false' } }
+
+ it 'reports error' do
+ expect(entry.errors)
+ .to include 'artifacts public should be a boolean value'
+ end
+ end
+
context "when 'expose_as' is not a string" do
let(:config) { { paths: %w[results.txt], expose_as: 1 } }
diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
index 426a38e2ef7..78d37e228df 100644
--- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Variables do
let(:metadata) { {} }
- subject { described_class.new(config, metadata) }
+ subject { described_class.new(config, **metadata) }
shared_examples 'valid config' do
describe '#value' do
diff --git a/spec/lib/gitlab/ci/config/external/file/local_spec.rb b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
index fdd29afe2d6..7e39fae7b9b 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do
project: project,
sha: sha,
user: user,
- parent_pipeline: parent_pipeline
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables
}
end
@@ -131,7 +132,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do
user: user,
project: project,
sha: sha,
- parent_pipeline: parent_pipeline)
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables)
end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
index a5e4e27df6f..0e8851ba915 100644
--- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
project: context_project,
sha: '12345',
user: context_user,
- parent_pipeline: parent_pipeline
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables
}
end
@@ -165,7 +166,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
user: user,
project: project,
sha: project.commit('master').id,
- parent_pipeline: parent_pipeline)
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables)
end
end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 7ad57827e30..4fdaaca8316 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
let(:local_file) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
let(:template_file) { 'Auto-DevOps.gitlab-ci.yml' }
- let(:context_params) { { project: project, sha: '123456', user: user } }
+ let(:context_params) { { project: project, sha: '123456', user: user, variables: project.predefined_variables.to_runner_variables } }
let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:file_content) do
@@ -124,17 +124,6 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
an_instance_of(Gitlab::Ci::Config::External::File::Project),
an_instance_of(Gitlab::Ci::Config::External::File::Project))
end
-
- context 'when FF ci_include_multiple_files_from_project is disabled' do
- before do
- stub_feature_flags(ci_include_multiple_files_from_project: false)
- end
-
- it 'returns a File instance' do
- expect(subject).to contain_exactly(
- an_instance_of(Gitlab::Ci::Config::External::File::Project))
- end
- end
end
end
@@ -236,5 +225,118 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
end
end
end
+
+ context "when 'include' section uses project variable" do
+ let(:full_local_file_path) { '$CI_PROJECT_PATH' + local_file }
+
+ context 'when local file is included as a single string' do
+ let(:values) do
+ { include: full_local_file_path }
+ end
+
+ it 'expands the variable', :aggregate_failures do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Local))
+ end
+ end
+
+ context 'when remote file is included as a single string' do
+ let(:remote_url) { "#{Gitlab.config.gitlab.url}/radio/.gitlab-ci.yml" }
+
+ let(:values) do
+ { include: '$CI_SERVER_URL/radio/.gitlab-ci.yml' }
+ end
+
+ it 'expands the variable', :aggregate_failures do
+ expect(subject[0].location).to eq(remote_url)
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Remote))
+ end
+ end
+
+ context 'defined as an array' do
+ let(:values) do
+ { include: [full_local_file_path, remote_url],
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject[1].location).to eq(remote_url)
+ end
+ end
+
+ context 'defined as an array of hashes' do
+ let(:values) do
+ { include: [{ local: full_local_file_path }, { remote: remote_url }],
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject[1].location).to eq(remote_url)
+ end
+ end
+
+ context 'local file hash' do
+ let(:values) do
+ { include: { 'local' => full_local_file_path } }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ end
+ end
+
+ context 'project name' do
+ let(:values) do
+ { include: { project: '$CI_PROJECT_PATH', file: local_file },
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable', :aggregate_failures do
+ expect(subject[0].project_name).to eq(project.full_path)
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Project))
+ end
+ end
+
+ context 'with multiple files' do
+ let(:values) do
+ { include: { project: project.full_path, file: [full_local_file_path, 'another_file_path.yml'] },
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject[1].location).to eq('another_file_path.yml')
+ end
+ end
+
+ context 'when include variable has an unsupported type for variable expansion' do
+ let(:values) do
+ { include: { project: project.id, file: local_file },
+ image: 'ruby:2.7' }
+ end
+
+ it 'does not invoke expansion for the variable', :aggregate_failures do
+ expect(ExpandVariables).not_to receive(:expand).with(project.id, context_params[:variables])
+
+ 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/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 150a2ec2929..d2d7116bb12 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -365,19 +365,6 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
output = processor.perform
expect(output.keys).to match_array([:image, :my_build, :my_test])
end
-
- context 'when FF ci_include_multiple_files_from_project is disabled' do
- before do
- stub_feature_flags(ci_include_multiple_files_from_project: false)
- end
-
- it 'raises an error' do
- expect { processor.perform }.to raise_error(
- described_class::IncludeError,
- 'Included file `["/templates/my-build.yml", "/templates/my-test.yml"]` needs to be a string'
- )
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index b5a0f0e3fd7..dc03d2f80fe 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -82,6 +82,30 @@ RSpec.describe Gitlab::Ci::Config do
end
end
+ describe '#included_templates' do
+ let(:yml) do
+ <<-EOS
+ include:
+ - template: Jobs/Deploy.gitlab-ci.yml
+ - template: Jobs/Build.gitlab-ci.yml
+ - remote: https://example.com/gitlab-ci.yml
+ EOS
+ end
+
+ before do
+ stub_request(:get, 'https://example.com/gitlab-ci.yml').to_return(status: 200, body: <<-EOS)
+ test:
+ script: [ 'echo hello world' ]
+ EOS
+ end
+
+ subject(:included_templates) do
+ config.included_templates
+ end
+
+ it { is_expected.to contain_exactly('Jobs/Deploy.gitlab-ci.yml', 'Jobs/Build.gitlab-ci.yml') }
+ end
+
context 'when using extendable hash' do
let(:yml) do
<<-EOS
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index c67f8464123..67324c09d86 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -247,7 +247,7 @@ RSpec.describe Gitlab::Ci::Lint do
include_context 'advanced validations' do
it 'runs advanced logical validations' do
expect(subject).not_to be_valid
- expect(subject.errors).to eq(["test: needs 'build'"])
+ expect(subject.errors).to eq(["'test' job needs 'build' job, but it was not added to the pipeline"])
end
end
diff --git a/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb b/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb
index 2313378d1e9..546de2bee5c 100644
--- a/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb
@@ -224,6 +224,12 @@ RSpec.describe Gitlab::Ci::Parsers::Coverage::Cobertura do
it_behaves_like 'ignoring sources, project_path, and worktree_paths'
end
+ context 'when there is an empty <sources>' do
+ let(:sources_xml) { '<sources />' }
+
+ it_behaves_like 'ignoring sources, project_path, and worktree_paths'
+ end
+
context 'when there is a <sources>' do
context 'and has a single source with a pattern for Go projects' do
let(:project_path) { 'local/go' } # Make sure we're not making false positives
diff --git a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
index 6da565a2bf6..20406acb658 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:user) { create(:user, developer_projects: [project]) }
let(:pipeline) { Ci::Pipeline.new }
@@ -29,29 +29,96 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
let(:step) { described_class.new(pipeline, command) }
- before do
- stub_ci_pipeline_yaml_file(gitlab_ci_yaml)
+ shared_examples 'builds pipeline' do
+ it 'builds a pipeline with the expected attributes' do
+ step.perform!
+
+ expect(pipeline.sha).not_to be_empty
+ expect(pipeline.sha).to eq project.commit.id
+ expect(pipeline.ref).to eq 'master'
+ expect(pipeline.tag).to be false
+ expect(pipeline.user).to eq user
+ expect(pipeline.project).to eq project
+ end
end
- it 'never breaks the chain' do
- step.perform!
+ shared_examples 'breaks the chain' do
+ it 'returns true' do
+ step.perform!
+
+ expect(step.break?).to be true
+ end
+ end
+
+ shared_examples 'does not break the chain' do
+ it 'returns false' do
+ step.perform!
+
+ expect(step.break?).to be false
+ end
+ end
- expect(step.break?).to be false
+ before do
+ stub_ci_pipeline_yaml_file(gitlab_ci_yaml)
end
- it 'fills pipeline object with data' do
+ it_behaves_like 'does not break the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'sets pipeline variables' do
step.perform!
- expect(pipeline.sha).not_to be_empty
- expect(pipeline.sha).to eq project.commit.id
- expect(pipeline.ref).to eq 'master'
- expect(pipeline.tag).to be false
- expect(pipeline.user).to eq user
- expect(pipeline.project).to eq project
expect(pipeline.variables.map { |var| var.slice(:key, :secret_value) })
.to eq variables_attributes.map(&:with_indifferent_access)
end
+ context 'when project setting restrict_user_defined_variables is enabled' do
+ before do
+ project.update!(restrict_user_defined_variables: true)
+ end
+
+ context 'when user is developer' do
+ it_behaves_like 'breaks the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'returns an error on variables_attributes', :aggregate_failures do
+ step.perform!
+
+ expect(pipeline.errors.full_messages).to eq(['Insufficient permissions to set pipeline variables'])
+ expect(pipeline.variables).to be_empty
+ end
+
+ context 'when variables_attributes is not specified' do
+ let(:variables_attributes) { nil }
+
+ it_behaves_like 'does not break the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'assigns empty variables' do
+ step.perform!
+
+ expect(pipeline.variables).to be_empty
+ end
+ end
+ end
+
+ context 'when user is maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'does not break the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'assigns variables_attributes' do
+ step.perform!
+
+ expect(pipeline.variables.map { |var| var.slice(:key, :secret_value) })
+ .to eq variables_attributes.map(&:with_indifferent_access)
+ end
+ end
+ end
+
it 'returns a valid pipeline' do
step.perform!
@@ -157,4 +224,25 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
expect(pipeline.target_sha).to eq(external_pull_request.target_sha)
end
end
+
+ context 'when keep_latest_artifact is set' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:keep_latest_artifact, :locking_result) do
+ true | 'artifacts_locked'
+ false | 'unlocked'
+ end
+
+ with_them do
+ before do
+ project.update!(ci_keep_latest_artifact: keep_latest_artifact)
+ end
+
+ it 'builds a pipeline with appropriate locked value' do
+ step.perform!
+
+ expect(pipeline.locked).to eq(locking_result)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index bc2012e83bd..9ca5aeeea58 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -295,4 +295,30 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
it { is_expected.to eq(false) }
end
end
+
+ describe '#creates_child_pipeline?' do
+ let(:command) { described_class.new(bridge: bridge) }
+
+ subject { command.creates_child_pipeline? }
+
+ context 'when bridge is present' do
+ context 'when bridge triggers a child pipeline' do
+ let(:bridge) { double(:bridge, triggers_child_pipeline?: true) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when bridge triggers a multi-project pipeline' do
+ let(:bridge) { double(:bridge, triggers_child_pipeline?: false) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when bridge is not present' do
+ let(:bridge) { nil }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
index 85c8e20767f..fabfbd779f3 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
@@ -51,18 +51,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::SeedBlock do
expect(pipeline.variables.size).to eq(1)
end
-
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'does not execute the block' do
- run_chain
-
- expect(pipeline.variables.size).to eq(0)
- end
- end
end
context 'when the seeds_block tries to save the pipelie' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index 0ce8b80902e..80013cab6ee 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
describe '#perform!' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
+ run_chain
end
let(:config) do
@@ -36,20 +37,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'allocates next IID' do
- run_chain
-
expect(pipeline.iid).to be_present
end
it 'ensures ci_ref' do
- run_chain
-
expect(pipeline.ci_ref).to be_present
end
it 'sets the seeds in the command object' do
- run_chain
-
expect(command.pipeline_seed).to be_a(Gitlab::Ci::Pipeline::Seed::Pipeline)
expect(command.pipeline_seed.size).to eq 1
end
@@ -64,8 +59,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'correctly fabricates stages and builds' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.stages.size).to eq 2
@@ -91,8 +84,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns pipeline seed with jobs only assigned to master' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -112,8 +103,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns pipeline seed with jobs only assigned to schedules' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -141,8 +130,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
let(:pipeline) { build(:ci_pipeline, project: project) }
it 'returns seeds for kubernetes dependent job' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 2
@@ -154,8 +141,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
context 'when kubernetes is not active' do
it 'does not return seeds for kubernetes dependent job' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -173,8 +158,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns stage seeds only when variables expression is truthy' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -187,24 +170,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
->(pipeline) { pipeline.variables.build(key: 'VAR', value: '123') }
end
- context 'when FF ci_seed_block_run_before_workflow_rules is enabled' do
- it 'does not execute the block' do
- run_chain
-
- expect(pipeline.variables.size).to eq(0)
- end
- end
-
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'executes the block' do
- run_chain
-
- expect(pipeline.variables.size).to eq(1)
- end
+ it 'does not execute the block' do
+ expect(pipeline.variables.size).to eq(0)
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
new file mode 100644
index 00000000000..3616461d94f
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::TemplateUsage do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ describe '#perform!' do
+ subject(:perform) { step.perform! }
+
+ it 'tracks the included templates' do
+ expect(command).to(
+ receive(:yaml_processor_result)
+ .and_return(
+ double(included_templates: %w(Template-1 Template-2))
+ )
+ )
+
+ %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)
+ )
+ end
+
+ perform
+ 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 bc10e94c81d..cf020fc343c 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -966,7 +966,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it "returns an error" do
expect(subject.errors).to contain_exactly(
- "rspec: needs 'build'")
+ "'rspec' job needs 'build' job, but it was not added to the pipeline")
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
index 1790388da03..860b07647bd 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
@@ -62,7 +62,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Pipeline do
needs_attributes: [{ name: 'non-existent', artifacts: true }]
}
- expect(seed.errors).to contain_exactly("invalid_job: needs 'non-existent'")
+ expect(seed.errors).to contain_exactly(
+ "'invalid_job' job needs 'non-existent' job, but it was not added to the pipeline")
end
end
end
diff --git a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
index 8df34eddffd..831bc5e9f37 100644
--- a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
@@ -28,18 +28,5 @@ RSpec.describe Gitlab::Ci::Reports::TestFailureHistory, :aggregate_failures do
expect(failed_rspec.recent_failures).to eq(count: 2, base_branch: 'master')
expect(failed_java.recent_failures).to eq(count: 1, base_branch: 'master')
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(test_failure_history: false)
- end
-
- it 'does not set recent failures' do
- load_history
-
- expect(failed_rspec.recent_failures).to be_nil
- expect(failed_java.recent_failures).to be_nil
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/status/group/factory_spec.rb b/spec/lib/gitlab/ci/status/group/factory_spec.rb
index 6267b26aa78..c67c7ff8271 100644
--- a/spec/lib/gitlab/ci/status/group/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/group/factory_spec.rb
@@ -12,4 +12,9 @@ RSpec.describe Gitlab::Ci::Status::Group::Factory do
expect(described_class.common_helpers)
.to eq Gitlab::Ci::Status::Group::Common
end
+
+ it 'exposes extended statuses' do
+ expect(described_class.extended_statuses)
+ .to eq([[Gitlab::Ci::Status::SuccessWarning]])
+ end
end
diff --git a/spec/lib/gitlab/ci/syntax_templates_spec.rb b/spec/lib/gitlab/ci/syntax_templates_spec.rb
new file mode 100644
index 00000000000..ce3169e17ec
--- /dev/null
+++ b/spec/lib/gitlab/ci/syntax_templates_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'ci/syntax_templates' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let(:lint) { Gitlab::Ci::Lint.new(project: project, current_user: user) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ subject(:lint_result) { lint.validate(content) }
+
+ Dir.glob('lib/gitlab/ci/syntax_templates/**/*.yml').each do |template|
+ describe template do
+ let(:content) { File.read(template) }
+
+ it 'validates the template' do
+ expect(lint_result).to be_valid, "got errors: #{lint_result.errors.join(', ')}"
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
new file mode 100644
index 00000000000..6bc8e261640
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe '5-Minute-Production-App.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('5-Minute-Production-App') }
+
+ describe 'the created pipeline' do
+ let_it_be(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+
+ let(:user) { project.owner }
+ let(:default_branch) { 'master' }
+ let(:pipeline_branch) { default_branch }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
+ let(:pipeline) { service.execute!(:push) }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ end
+
+ it 'creates only build job' do
+ expect(build_names).to match_array('build')
+ end
+
+ context 'when AWS variables are set' do
+ before do
+ create(:ci_variable, project: project, key: 'AWS_ACCESS_KEY_ID', value: 'AKIAIOSFODNN7EXAMPLE')
+ create(:ci_variable, project: project, key: 'AWS_SECRET_ACCESS_KEY', value: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY')
+ create(:ci_variable, project: project, key: 'AWS_DEFAULT_REGION', value: 'us-west-2')
+ end
+
+ it 'creates all jobs' do
+ expect(build_names).to match_array(%w(build terraform_apply deploy terraform_destroy))
+ end
+
+ context 'pipeline branch is protected' do
+ before do
+ create(:protected_branch, project: project, name: pipeline_branch)
+ project.reload
+ end
+
+ it 'does not create a destroy job' do
+ expect(build_names).to match_array(%w(build terraform_apply deploy))
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
index 4be92e8608e..653b3be0b2a 100644
--- a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('AWS/Deploy-ECS') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
index 4f8faa5ddb1..1f278048ad5 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Build') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
index e685ad3b46e..0a76de82421 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Code-Quality') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
index ea9bd5bd02c..25c88c161ea 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
@@ -27,8 +27,8 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
index f475785be98..b64959a9917 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Test') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
index 8df739d9245..0811c07e896 100644
--- a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe 'Terraform/Base.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Terraform/Base.latest') }
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
index 9711df55226..03fa45fe0a1 100644
--- a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
@@ -19,8 +19,8 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 793df55f45d..f9d6fe24e70 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') }
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
@@ -232,8 +232,8 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
end
with_them do
- let(:user) { create(:admin) }
let(:project) { create(:project, :custom_repo, files: files) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
let(:pipeline) { service.execute(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..4e5fe622648
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Flutter.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Flutter') }
+
+ describe 'the created pipeline' do
+ let(:pipeline_branch) { 'master' }
+ let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
+ let(:pipeline) { service.execute!(:push) }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ allow(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
+ end
+
+ it 'creates test and code_quality jobs' do
+ expect(build_names).to include('test', 'code_quality')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index 1f8e32ce019..b10e2b0e057 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -6,11 +6,10 @@ RSpec.describe 'npm.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm.latest') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:repo_files) { { 'package.json' => '{}', 'README.md' => '' } }
let(:modified_files) { %w[package.json] }
let(:project) { create(:project, :custom_repo, files: repo_files) }
+ let(:user) { project.owner }
let(:pipeline_branch) { project.default_branch }
let(:pipeline_tag) { 'v1.2.1' }
let(:pipeline_ref) { pipeline_branch }
diff --git a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
index 5eec021b9d7..4377f155d34 100644
--- a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
@@ -10,11 +10,10 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Terraform.latest') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb b/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
new file mode 100644
index 00000000000..d85bf29f77f
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
@@ -0,0 +1,251 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
+ describe '#errors' do
+ context 'when FF :variable_inside_variable is disabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: false)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: []
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ },
+ "complex expansion": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'key${variable}' }
+ ]
+ },
+ "complex expansions with missing variable for Windows": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'key%variable%%variable2%' }
+ ]
+ },
+ "out-of-order variable reference": {
+ variables: [
+ { key: 'variable2', value: 'key${variable}' },
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "array with cyclic dependency": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'does not report error' do
+ expect(subject.errors).to eq(nil)
+ end
+
+ it 'valid? reports true' do
+ expect(subject.valid?).to eq(true)
+ end
+ end
+ end
+ end
+
+ context 'when FF :variable_inside_variable is enabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: true)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: [],
+ validation_result: nil
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ validation_result: nil
+ },
+ "cyclic dependency": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ validation_result: 'circular variable reference detected: ["variable", "variable2", "variable3"]'
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'errors matches expected validation result' do
+ expect(subject.errors).to eq(validation_result)
+ end
+
+ it 'valid? matches expected validation result' do
+ expect(subject.valid?).to eq(validation_result.nil?)
+ end
+ end
+ end
+ end
+ end
+
+ describe '#sort' do
+ context 'when FF :variable_inside_variable is disabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: false)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: []
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ },
+ "complex expansion": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'key${variable}' }
+ ]
+ },
+ "complex expansions with missing variable for Windows": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'key%variable%%variable2%' }
+ ]
+ },
+ "out-of-order variable reference": {
+ variables: [
+ { key: 'variable2', value: 'key${variable}' },
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "array with cyclic dependency": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'does not expand variables' do
+ expect(subject.sort).to eq(variables)
+ end
+ end
+ end
+ end
+
+ context 'when FF :variable_inside_variable is enabled' do
+ before do
+ stub_licensed_features(group_saml_group_sync: true)
+ stub_feature_flags(saml_group_links: true)
+ stub_feature_flags(variable_inside_variable: true)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: [],
+ result: []
+ },
+ "simple expansions, no reordering needed": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ result: %w[variable variable2 variable3]
+ },
+ "complex expansion, reordering needed": {
+ variables: [
+ { key: 'variable2', value: 'key${variable}' },
+ { key: 'variable', value: 'value' }
+ ],
+ result: %w[variable variable2]
+ },
+ "unused variables": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable4', value: 'key$variable$variable3' },
+ { key: 'variable2', value: 'result2' },
+ { key: 'variable3', value: 'result3' }
+ ],
+ result: %w[variable variable3 variable4 variable2]
+ },
+ "missing variable": {
+ variables: [
+ { key: 'variable2', value: 'key$variable' }
+ ],
+ result: %w[variable2]
+ },
+ "complex expansions with missing variable": {
+ variables: [
+ { key: 'variable4', value: 'key${variable}${variable2}${variable3}' },
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'value3' }
+ ],
+ result: %w[variable variable3 variable4]
+ },
+ "cyclic dependency causes original array to be returned": {
+ variables: [
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' },
+ { key: 'variable', value: '$variable2' }
+ ],
+ result: %w[variable2 variable3 variable]
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'sort returns correctly sorted variables' do
+ expect(subject.sort.map { |var| var[:key] }).to eq(result)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 5ad1b3dd241..9498453852a 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -2711,40 +2711,6 @@ module Gitlab
end
end
- describe "#validation_message" do
- subject { Gitlab::Ci::YamlProcessor.validation_message(content) }
-
- context "when the YAML could not be parsed" do
- let(:content) { YAML.dump("invalid: yaml: test") }
-
- it { is_expected.to eq "Invalid configuration format" }
- end
-
- context "when the tags parameter is invalid" do
- let(:content) { YAML.dump({ rspec: { script: "test", tags: "mysql" } }) }
-
- it { is_expected.to eq "jobs:rspec:tags config should be an array of strings" }
- end
-
- context "when YAML content is empty" do
- let(:content) { '' }
-
- it { is_expected.to eq "Please provide content of .gitlab-ci.yml" }
- end
-
- context 'when the YAML contains an unknown alias' do
- let(:content) { 'steps: *bad_alias' }
-
- it { is_expected.to eq "Unknown alias: bad_alias" }
- end
-
- context "when the YAML is valid" do
- let(:content) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
-
- it { is_expected.to be_nil }
- end
- end
-
describe '#execute' do
subject { Gitlab::Ci::YamlProcessor.new(content).execute }
diff --git a/spec/lib/gitlab/composer/version_index_spec.rb b/spec/lib/gitlab/composer/version_index_spec.rb
new file mode 100644
index 00000000000..4c4742d9f59
--- /dev/null
+++ b/spec/lib/gitlab/composer/version_index_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Composer::VersionIndex 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: package_name, version: '2.0.0', json: json) }
+
+ let(:branch) { project.repository.find_branch('master') }
+
+ let(:packages) { [package1, package2] }
+
+ describe '#as_json' do
+ subject(:index) { described_class.new(packages).as_json }
+
+ def expected_json(package)
+ {
+ 'dist' => {
+ 'reference' => branch.target,
+ 'shasum' => '',
+ 'type' => 'zip',
+ 'url' => "http://localhost/api/v4/projects/#{project.id}/packages/composer/archives/#{package.name}.zip?sha=#{branch.target}"
+ },
+ 'name' => package.name,
+ 'uid' => package.id,
+ 'version' => package.version
+ }
+ end
+
+ it 'returns the packages json' do
+ packages = index['packages'][package_name]
+
+ expect(packages['1.0.0']).to eq(expected_json(package1))
+ expect(packages['2.0.0']).to eq(expected_json(package2))
+ end
+ end
+
+ describe '#sha' do
+ subject(:sha) { described_class.new(packages).sha }
+
+ it 'returns the json SHA' do
+ expect(sha).to match /^[A-Fa-f0-9]{64}$/
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/composable_hash_spec.rb b/spec/lib/gitlab/config/entry/composable_hash_spec.rb
index 15bbf2047c5..f64b39231a3 100644
--- a/spec/lib/gitlab/config/entry/composable_hash_spec.rb
+++ b/spec/lib/gitlab/config/entry/composable_hash_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::Config::Entry::ComposableHash, :aggregate_failures do
end
let(:entry) do
- parent_entry = composable_hash_parent_class.new(secrets: config)
+ parent_entry = composable_hash_parent_class.new({ secrets: config })
parent_entry.compose!
parent_entry[:secrets]
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index 0de944d3f8a..bb9bee763d8 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -97,19 +97,27 @@ RSpec.describe Gitlab::Conflict::File do
let(:diff_line_types) { conflict_file.diff_lines_for_serializer.map(&:type) }
it 'assigns conflict types to the diff lines' do
- expect(diff_line_types[4]).to eq('conflict_marker')
- expect(diff_line_types[5..10]).to eq(['conflict_marker_our'] * 6)
+ expect(diff_line_types[4]).to eq('conflict_marker_our')
+ expect(diff_line_types[5..10]).to eq(['conflict_our'] * 6)
expect(diff_line_types[11]).to eq('conflict_marker')
- expect(diff_line_types[12..17]).to eq(['conflict_marker_their'] * 6)
- expect(diff_line_types[18]).to eq('conflict_marker')
+ expect(diff_line_types[12..17]).to eq(['conflict_their'] * 6)
+ expect(diff_line_types[18]).to eq('conflict_marker_their')
expect(diff_line_types[19..24]).to eq([nil] * 6)
- expect(diff_line_types[25]).to eq('conflict_marker')
- expect(diff_line_types[26..27]).to eq(['conflict_marker_our'] * 2)
+ expect(diff_line_types[25]).to eq('conflict_marker_our')
+ expect(diff_line_types[26..27]).to eq(['conflict_our'] * 2)
expect(diff_line_types[28]).to eq('conflict_marker')
- expect(diff_line_types[29..30]).to eq(['conflict_marker_their'] * 2)
- expect(diff_line_types[31]).to eq('conflict_marker')
+ expect(diff_line_types[29..30]).to eq(['conflict_their'] * 2)
+ expect(diff_line_types[31]).to eq('conflict_marker_their')
+ end
+
+ # Swap the positions around due to conflicts/diffs display inconsistency
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/291989
+ it 'swaps the new and old positions around' do
+ lines = conflict_file.diff_lines_for_serializer
+ expect(lines.map(&:old_pos)[26..27]).to eq([21, 22])
+ expect(lines.map(&:new_pos)[29..30]).to eq([21, 22])
end
it 'does not add a match line to the end of the section' do
@@ -124,13 +132,13 @@ RSpec.describe Gitlab::Conflict::File do
expect(diff_line_types).to eq([
'match',
nil, nil, nil,
- "conflict_marker",
"conflict_marker_our",
+ "conflict_our",
"conflict_marker",
+ "conflict_their",
+ "conflict_their",
+ "conflict_their",
"conflict_marker_their",
- "conflict_marker_their",
- "conflict_marker_their",
- "conflict_marker",
nil, nil, nil,
"match"
])
diff --git a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
deleted file mode 100644
index 056c1b5bc9f..00000000000
--- a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::BaseEventFetcher do
- let(:max_events) { 2 }
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user, :admin) }
- let(:start_time_attrs) { Issue.arel_table[:created_at] }
- let(:end_time_attrs) { [Issue::Metrics.arel_table[:first_associated_with_milestone_at]] }
- let(:options) do
- { start_time_attrs: start_time_attrs,
- end_time_attrs: end_time_attrs,
- from: 30.days.ago,
- project: project }
- end
-
- subject do
- described_class.new(stage: :issue,
- options: options).fetch
- end
-
- before do
- allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return(Issue.all)
- allow_any_instance_of(described_class).to receive(:serialize) do |event|
- event
- end
- allow_any_instance_of(described_class)
- .to receive(:allowed_ids).and_return(nil)
-
- stub_const('Gitlab::CycleAnalytics::BaseEventFetcher::MAX_EVENTS', max_events)
-
- setup_events(count: 3)
- end
-
- it 'limits the rows to the max number' do
- expect(subject.count).to eq(max_events)
- end
-
- def setup_events(count:)
- count.times do
- issue = create(:issue, project: project, created_at: 2.days.ago)
- milestone = create(:milestone, project: project)
-
- issue.update(milestone: milestone)
- create_merge_request_closing_issue(user, project, issue)
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/code_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/code_event_fetcher_spec.rb
deleted file mode 100644
index a1a173abe57..00000000000
--- a/spec/lib/gitlab/cycle_analytics/code_event_fetcher_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::CodeEventFetcher do
- let(:stage_name) { :code }
-
- it_behaves_like 'default query config' do
- it 'has a default order' do
- expect(event.order).not_to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
deleted file mode 100644
index 17104715580..00000000000
--- a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::CodeStage do
- let(:stage_name) { :code }
-
- let(:project) { create(:project) }
- let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:mr_1) { create(:merge_request, source_project: project, created_at: 15.minutes.ago) }
- let(:mr_2) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'A') }
- let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
- let(:stage) { described_class.new(options: stage_options) }
-
- before do
- issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
- issue_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
- issue_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
- create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B')
- create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
- create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
- end
-
- it_behaves_like 'base stage'
-
- context 'when using the new query backend' do
- include_examples 'Gitlab::Analytics::CycleAnalytics::DataCollector backend examples' do
- let(:expected_record_count) { 2 }
- let(:expected_ordered_attribute_values) { [mr_2.title, mr_1.title] }
- end
- end
-
- describe '#project_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.project_median).to eq(ISSUES_MEDIAN)
- end
-
- include_examples 'calculate #median with date range'
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that closes issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
- end
- end
-
- context 'when group is given' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project_2) { create(:project, group: group) }
- let(:project_3) { create(:project, group: group) }
- let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
- let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
- let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
- let(:mr_2_1) { create(:merge_request, source_project: project_2, created_at: 15.minutes.ago) }
- let(:mr_2_2) { create(:merge_request, source_project: project_3, created_at: 10.minutes.ago, source_branch: 'A') }
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
-
- before do
- group.add_owner(user)
- issue_2_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
- issue_2_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
- issue_2_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
- create(:merge_requests_closing_issues, merge_request: mr_2_1, issue: issue_2_1)
- create(:merge_requests_closing_issues, merge_request: mr_2_2, issue: issue_2_2)
- end
-
- describe '#group_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.group_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(mr_2_1.title, mr_2_2.title)
- end
- end
-
- context 'when subgroup is given' do
- let(:subgroup) { create(:group, parent: group) }
- let(:project_4) { create(:project, group: subgroup) }
- let(:project_5) { create(:project, group: subgroup) }
- let(:issue_3_1) { create(:issue, project: project_4, created_at: 90.minutes.ago) }
- let(:issue_3_2) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
- let(:issue_3_3) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
- let(:mr_3_1) { create(:merge_request, source_project: project_4, created_at: 15.minutes.ago) }
- let(:mr_3_2) { create(:merge_request, source_project: project_5, created_at: 10.minutes.ago, source_branch: 'A') }
-
- before do
- issue_3_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
- issue_3_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
- issue_3_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
- create(:merge_requests_closing_issues, merge_request: mr_3_1, issue: issue_3_1)
- create(:merge_requests_closing_issues, merge_request: mr_3_2, issue: issue_3_2)
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(4)
- expect(subject.map { |event| event[:title] }).to contain_exactly(mr_2_1.title, mr_2_2.title, mr_3_1.title, mr_3_2.title)
- end
-
- it 'exposes merge requests that close issues with full path for subgroup' do
- expect(subject.count).to eq(4)
- expect(subject.find { |event| event[:title] == mr_3_1.title }[:url]).to include("#{subgroup.full_path}")
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb
deleted file mode 100644
index 553f33a66c4..00000000000
--- a/spec/lib/gitlab/cycle_analytics/events_spec.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'value stream analytics events', :aggregate_failures do
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:user, :admin) }
- let(:from_date) { 10.days.ago }
- let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
-
- let(:events) do
- CycleAnalytics::ProjectLevel
- .new(project, options: { from: from_date, current_user: user })[stage]
- .events
- end
-
- let(:event) { events.first }
-
- before do
- setup(context)
- end
-
- describe '#issue_events' do
- let(:stage) { :issue }
-
- it 'has correct attributes' do
- expect(event[:total_time]).not_to be_empty
- expect(event[:title]).to eq(context.title)
- expect(event[:url]).not_to be_nil
- expect(event[:iid]).to eq(context.iid.to_s)
- expect(event[:created_at]).to end_with('ago')
- expect(event[:author][:web_url]).not_to be_nil
- expect(event[:author][:avatar_url]).not_to be_nil
- expect(event[:author][:name]).to eq(context.author.name)
- end
- end
-
- describe '#plan_events' do
- let(:stage) { :plan }
-
- before do
- create_commit_referencing_issue(context)
-
- # Adding extra duration because the new VSA backend filters out 0 durations between these columns
- context.metrics.update!(first_mentioned_in_commit_at: context.metrics.first_associated_with_milestone_at + 1.day)
- end
-
- it 'has correct attributes' do
- expect(event[:total_time]).not_to be_empty
- expect(event[:title]).to eq(context.title)
- expect(event[:url]).not_to be_nil
- expect(event[:iid]).to eq(context.iid.to_s)
- expect(event[:created_at]).to end_with('ago')
- expect(event[:author][:web_url]).not_to be_nil
- expect(event[:author][:avatar_url]).not_to be_nil
- expect(event[:author][:name]).to eq(context.author.name)
- end
- end
-
- describe '#code_events' do
- let(:stage) { :code }
- let!(:merge_request) { MergeRequest.first }
-
- before do
- create_commit_referencing_issue(context)
- end
-
- it 'has correct attributes' do
- expect(event[:total_time]).not_to be_empty
- expect(event[:title]).to eq('Awesome merge_request')
- expect(event[:iid]).to eq(context.iid.to_s)
- expect(event[:created_at]).to end_with('ago')
- expect(event[:author][:web_url]).not_to be_nil
- expect(event[:author][:avatar_url]).not_to be_nil
- expect(event[:author][:name]).to eq(MergeRequest.first.author.name)
- end
- end
-
- describe '#test_events', :sidekiq_might_not_need_inline do
- let(:stage) { :test }
-
- let(:merge_request) { MergeRequest.first }
- let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
-
- let!(:pipeline) do
- create(:ci_pipeline,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha,
- project: project,
- head_pipeline_of: merge_request)
- end
-
- before do
- create(:ci_build, :success, pipeline: pipeline, author: user)
- create(:ci_build, :success, pipeline: pipeline, author: user)
-
- pipeline.run!
- pipeline.succeed!
- merge_merge_requests_closing_issue(user, project, context)
- end
-
- it 'has correct attributes' do
- expect(event[:name]).not_to be_nil
- expect(event[:id]).not_to be_nil
- expect(event[:url]).not_to be_nil
- expect(event[:branch]).not_to be_nil
- expect(event[:branch][:url]).not_to be_nil
- expect(event[:short_sha]).not_to be_nil
- expect(event[:commit_url]).not_to be_nil
- expect(event[:date]).not_to be_nil
- expect(event[:total_time]).not_to be_empty
- end
- end
-
- describe '#review_events' do
- let(:stage) { :review }
- let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
-
- before do
- merge_merge_requests_closing_issue(user, project, context)
- end
-
- it 'has correct attributes' do
- expect(event[:total_time]).not_to be_empty
- expect(event[:title]).to eq('Awesome merge_request')
- expect(event[:iid]).to eq(context.iid.to_s)
- expect(event[:url]).not_to be_nil
- expect(event[:state]).not_to be_nil
- expect(event[:created_at]).not_to be_nil
- expect(event[:author][:web_url]).not_to be_nil
- expect(event[:author][:avatar_url]).not_to be_nil
- expect(event[:author][:name]).to eq(MergeRequest.first.author.name)
- end
- end
-
- describe '#staging_events', :sidekiq_might_not_need_inline do
- let(:stage) { :staging }
- let(:merge_request) { MergeRequest.first }
-
- let!(:pipeline) do
- create(:ci_pipeline,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha,
- project: project,
- head_pipeline_of: merge_request)
- end
-
- before do
- create(:ci_build, :success, pipeline: pipeline, author: user)
- create(:ci_build, :success, pipeline: pipeline, author: user)
-
- pipeline.run!
- pipeline.succeed!
-
- merge_merge_requests_closing_issue(user, project, context)
- deploy_master(user, project)
- end
-
- it 'has correct attributes' do
- expect(event[:name]).not_to be_nil
- expect(event[:id]).not_to be_nil
- expect(event[:url]).not_to be_nil
- expect(event[:branch]).not_to be_nil
- expect(event[:branch][:url]).not_to be_nil
- expect(event[:short_sha]).not_to be_nil
- expect(event[:commit_url]).not_to be_nil
- expect(event[:date]).not_to be_nil
- expect(event[:total_time]).not_to be_empty
- expect(event[:author][:web_url]).not_to be_nil
- expect(event[:author][:avatar_url]).not_to be_nil
- expect(event[:author][:name]).to eq(MergeRequest.first.author.name)
- end
- end
-
- def setup(context)
- milestone = create(:milestone, project: project)
- context.update!(milestone: milestone)
- mr = create_merge_request_closing_issue(user, project, context, commit_message: "References #{context.to_reference}")
-
- ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash)
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb
deleted file mode 100644
index 7a49ee53e8f..00000000000
--- a/spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::IssueEventFetcher do
- let(:stage_name) { :issue }
-
- it_behaves_like 'default query config'
-end
diff --git a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
deleted file mode 100644
index c7ab2b9b84b..00000000000
--- a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::IssueStage do
- let(:stage_name) { :issue }
- let(:project) { create(:project) }
- let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
- let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
- let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
- let(:stage) { described_class.new(options: stage_options) }
-
- before do
- issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago )
- issue_2.metrics.update!(first_added_to_board_at: 30.minutes.ago)
- issue_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
- end
-
- it_behaves_like 'base stage'
-
- context 'when using the new query backend' do
- include_examples 'Gitlab::Analytics::CycleAnalytics::DataCollector backend examples' do
- let(:expected_record_count) { 3 }
- let(:expected_ordered_attribute_values) { [issue_3.title, issue_2.title, issue_1.title] }
- end
- end
-
- describe '#median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.project_median).to eq(ISSUES_MEDIAN)
- end
-
- include_examples 'calculate #median with date range'
- end
-
- describe '#events' do
- it 'exposes issues with metrics' do
- result = stage.events
-
- expect(result.count).to eq(3)
- expect(result.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title, issue_3.title)
- end
- end
- context 'when group is given' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project_2) { create(:project, group: group) }
- let(:project_3) { create(:project, group: group) }
- let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
- let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
- let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
-
- before do
- group.add_owner(user)
- issue_2_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago)
- issue_2_2.metrics.update!(first_added_to_board_at: 30.minutes.ago)
- end
-
- describe '#group_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.group_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title)
- end
- end
-
- context 'when only part of projects is chosen' do
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group, projects: [project_2.id] }) }
-
- describe '#group_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.group_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(1)
- expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title)
- end
- end
- end
-
- context 'when subgroup is given' do
- let(:subgroup) { create(:group, parent: group) }
- let(:project_4) { create(:project, group: subgroup) }
- let(:project_5) { create(:project, group: subgroup) }
- let(:issue_3_1) { create(:issue, project: project_4, created_at: 90.minutes.ago) }
- let(:issue_3_2) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
- let(:issue_3_3) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
-
- before do
- issue_3_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago)
- issue_3_2.metrics.update!(first_added_to_board_at: 30.minutes.ago)
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(4)
- expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title, issue_3_1.title, issue_3_2.title)
- end
-
- it 'exposes merge requests that close issues with full path for subgroup' do
- expect(subject.count).to eq(4)
- expect(subject.find { |event| event[:title] == issue_3_1.title }[:url]).to include("#{subgroup.full_path}")
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/plan_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_event_fetcher_spec.rb
deleted file mode 100644
index bc14a772d34..00000000000
--- a/spec/lib/gitlab/cycle_analytics/plan_event_fetcher_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::PlanEventFetcher do
- let(:stage_name) { :plan }
-
- it_behaves_like 'default query config' do
- context 'no commits' do
- it 'does not blow up if there are no commits' do
- allow(event).to receive(:event_result).and_return([{}])
-
- expect { event.fetch }.not_to raise_error
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
deleted file mode 100644
index 2547c05c025..00000000000
--- a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::PlanStage do
- let(:stage_name) { :plan }
- let(:project) { create(:project) }
- let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
- let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
- let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
- let(:stage) { described_class.new(options: stage_options) }
-
- before do
- issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
- issue_2.metrics.update!(first_added_to_board_at: 30.minutes.ago, first_mentioned_in_commit_at: 20.minutes.ago)
- issue_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
- end
-
- it_behaves_like 'base stage'
-
- context 'when using the new query backend' do
- include_examples 'Gitlab::Analytics::CycleAnalytics::DataCollector backend examples' do
- let(:expected_record_count) { 2 }
- let(:expected_ordered_attribute_values) { [issue_1.title, issue_2.title] }
- end
- end
-
- describe '#project_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.project_median).to eq(ISSUES_MEDIAN)
- end
-
- include_examples 'calculate #median with date range'
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes issues with metrics' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title)
- end
- end
-
- context 'when group is given' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project_2) { create(:project, group: group) }
- let(:project_3) { create(:project, group: group) }
- let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
- let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
- let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
-
- before do
- group.add_owner(user)
- issue_2_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
- issue_2_2.metrics.update!(first_added_to_board_at: 30.minutes.ago, first_mentioned_in_commit_at: 20.minutes.ago)
- issue_2_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
- end
-
- describe '#group_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.group_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title)
- end
- end
-
- context 'when subgroup is given' do
- let(:subgroup) { create(:group, parent: group) }
- let(:project_4) { create(:project, group: subgroup) }
- let(:project_5) { create(:project, group: subgroup) }
- let(:issue_3_1) { create(:issue, project: project_4, created_at: 90.minutes.ago) }
- let(:issue_3_2) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
- let(:issue_3_3) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
-
- before do
- issue_3_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
- issue_3_2.metrics.update!(first_added_to_board_at: 30.minutes.ago, first_mentioned_in_commit_at: 20.minutes.ago)
- issue_3_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(4)
- expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title, issue_3_1.title, issue_3_2.title)
- end
-
- it 'exposes merge requests that close issues with full path for subgroup' do
- expect(subject.count).to eq(4)
- expect(subject.find { |event| event[:title] == issue_3_1.title }[:url]).to include("#{subgroup.full_path}")
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/production_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/production_event_fetcher_spec.rb
deleted file mode 100644
index 86b07a95cbb..00000000000
--- a/spec/lib/gitlab/cycle_analytics/production_event_fetcher_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::ProductionEventFetcher do
- let(:stage_name) { :production }
-
- it_behaves_like 'default query config'
-end
diff --git a/spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb
deleted file mode 100644
index fe13cc6b065..00000000000
--- a/spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::ReviewEventFetcher do
- let(:stage_name) { :review }
-
- it_behaves_like 'default query config'
-end
diff --git a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
deleted file mode 100644
index 5593013740e..00000000000
--- a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::ReviewStage do
- let(:stage_name) { :review }
- let(:project) { create(:project) }
- let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
- let(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
- let(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
- let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') }
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
-
- before do
- mr_1.metrics.update!(merged_at: 30.minutes.ago)
- mr_2.metrics.update!(merged_at: 10.minutes.ago)
-
- create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
- create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
- create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3)
- end
-
- it_behaves_like 'base stage'
-
- describe '#project_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.project_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
- end
- end
-
- context 'when group is given' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project_2) { create(:project, group: group) }
- let(:project_3) { create(:project, group: group) }
- let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
- let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
- let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
- let(:mr_2_1) { create(:merge_request, :closed, source_project: project_2, created_at: 60.minutes.ago) }
- let(:mr_2_2) { create(:merge_request, :closed, source_project: project_3, created_at: 40.minutes.ago, source_branch: 'A') }
- let(:mr_2_3) { create(:merge_request, source_project: project_2, created_at: 10.minutes.ago, source_branch: 'B') }
- let!(:mr_2_4) { create(:merge_request, source_project: project_3, created_at: 10.minutes.ago, source_branch: 'C') }
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
-
- before do
- group.add_owner(user)
- mr_2_1.metrics.update!(merged_at: 30.minutes.ago)
- mr_2_2.metrics.update!(merged_at: 10.minutes.ago)
-
- create(:merge_requests_closing_issues, merge_request: mr_2_1, issue: issue_2_1)
- create(:merge_requests_closing_issues, merge_request: mr_2_2, issue: issue_2_2)
- create(:merge_requests_closing_issues, merge_request: mr_2_3, issue: issue_2_3)
- end
-
- describe '#group_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.group_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:title] }).to contain_exactly(mr_2_1.title, mr_2_2.title)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/staging_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_event_fetcher_spec.rb
deleted file mode 100644
index bdf1b99c4c9..00000000000
--- a/spec/lib/gitlab/cycle_analytics/staging_event_fetcher_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::StagingEventFetcher do
- let(:stage_name) { :staging }
-
- it_behaves_like 'default query config' do
- it 'has a default order' do
- expect(event.order).not_to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
deleted file mode 100644
index 852f7041dc6..00000000000
--- a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::StagingStage do
- let(:stage_name) { :staging }
-
- let(:project) { create(:project) }
- let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
- let(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
- let(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
- let(:build_1) { create(:ci_build, project: project) }
- let(:build_2) { create(:ci_build, project: project) }
-
- let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
- let(:stage) { described_class.new(options: stage_options) }
-
- before do
- mr_1.metrics.update!(merged_at: 80.minutes.ago, first_deployed_to_production_at: 50.minutes.ago, pipeline_id: build_1.commit_id)
- mr_2.metrics.update!(merged_at: 60.minutes.ago, first_deployed_to_production_at: 30.minutes.ago, pipeline_id: build_2.commit_id)
- mr_3.metrics.update!(merged_at: 10.minutes.ago, first_deployed_to_production_at: 3.days.ago, pipeline_id: create(:ci_build, project: project).commit_id)
-
- create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
- create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
- create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3)
- end
-
- it_behaves_like 'base stage'
-
- describe '#project_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.project_median).to eq(ISSUES_MEDIAN)
- end
-
- it_behaves_like 'calculate #median with date range'
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes builds connected to merge request' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:name] }).to contain_exactly(build_1.name, build_2.name)
- end
- end
-
- context 'when group is given' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project_2) { create(:project, group: group) }
- let(:project_3) { create(:project, group: group) }
- let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
- let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
- let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
- let(:mr_1) { create(:merge_request, :closed, source_project: project_2, created_at: 60.minutes.ago) }
- let(:mr_2) { create(:merge_request, :closed, source_project: project_3, created_at: 40.minutes.ago, source_branch: 'A') }
- let(:mr_3) { create(:merge_request, source_project: project_2, created_at: 10.minutes.ago, source_branch: 'B') }
- let(:build_1) { create(:ci_build, project: project_2) }
- let(:build_2) { create(:ci_build, project: project_3) }
- let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
-
- before do
- group.add_owner(user)
- mr_1.metrics.update!(merged_at: 80.minutes.ago, first_deployed_to_production_at: 50.minutes.ago, pipeline_id: build_1.commit_id)
- mr_2.metrics.update!(merged_at: 60.minutes.ago, first_deployed_to_production_at: 30.minutes.ago, pipeline_id: build_2.commit_id)
- mr_3.metrics.update!(merged_at: 10.minutes.ago, first_deployed_to_production_at: 3.days.ago, pipeline_id: create(:ci_build, project: project_2).commit_id)
-
- create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_2_1)
- create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2_2)
- create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_2_3)
- end
-
- describe '#group_median' do
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.group_median).to eq(ISSUES_MEDIAN)
- end
- end
-
- describe '#events' do
- subject { stage.events }
-
- it 'exposes merge requests that close issues' do
- expect(subject.count).to eq(2)
- expect(subject.map { |event| event[:name] }).to contain_exactly(build_1.name, build_2.name)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/test_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/test_event_fetcher_spec.rb
deleted file mode 100644
index 1277385d0b4..00000000000
--- a/spec/lib/gitlab/cycle_analytics/test_event_fetcher_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::TestEventFetcher do
- let(:stage_name) { :test }
-
- it_behaves_like 'default query config' do
- it 'has a default order' do
- expect(event.order).not_to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
deleted file mode 100644
index 49ee6624260..00000000000
--- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::TestStage do
- let(:stage_name) { :test }
- let(:project) { create(:project) }
- let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
- let(:stage) { described_class.new(options: stage_options) }
-
- it_behaves_like 'base stage'
-
- describe '#median' do
- let(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
- let(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
- let(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
- let(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') }
- let(:mr_5) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'D') }
- let(:ci_build1) { create(:ci_build, project: project) }
- let(:ci_build2) { create(:ci_build, project: project) }
-
- before do
- issue_1 = create(:issue, project: project, created_at: 90.minutes.ago)
- issue_2 = create(:issue, project: project, created_at: 60.minutes.ago)
- issue_3 = create(:issue, project: project, created_at: 60.minutes.ago)
- mr_1.metrics.update!(latest_build_started_at: 32.minutes.ago, latest_build_finished_at: 2.minutes.ago, pipeline_id: ci_build1.commit_id)
- mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minutes.ago, pipeline_id: ci_build2.commit_id)
- mr_3.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil)
- mr_4.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil)
- mr_5.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil)
-
- create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
- create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
- create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3)
- create(:merge_requests_closing_issues, merge_request: mr_4, issue: issue_3)
- create(:merge_requests_closing_issues, merge_request: mr_5, issue: issue_3)
- end
-
- around do |example|
- freeze_time { example.run }
- end
-
- it 'counts median from issues with metrics' do
- expect(stage.project_median).to eq(ISSUES_MEDIAN)
- end
-
- include_examples 'calculate #median with date range'
-
- context 'when using the new query backend' do
- include_examples 'Gitlab::Analytics::CycleAnalytics::DataCollector backend examples' do
- let(:expected_record_count) { 2 }
- let(:attribute_to_verify) { :id }
- let(:expected_ordered_attribute_values) { [mr_1.metrics.pipeline.builds.first.id, mr_2.metrics.pipeline.builds.first.id] }
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/base_linter_spec.rb b/spec/lib/gitlab/danger/base_linter_spec.rb
index bd0ceb5a125..0136a0278ae 100644
--- a/spec/lib/gitlab/danger/base_linter_spec.rb
+++ b/spec/lib/gitlab/danger/base_linter_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'rspec-parameterized'
require_relative 'danger_spec_helper'
require 'gitlab/danger/base_linter'
@@ -70,19 +71,57 @@ RSpec.describe Gitlab::Danger::BaseLinter do
end
end
- context 'when subject is a WIP' do
+ context 'when ignoring length issues for subject having not-ready wording' do
+ using RSpec::Parameterized::TableSyntax
+
let(:final_message) { 'A B C' }
- # commit message with prefix will be over max length. commit message without prefix will be of maximum size
- let(:commit_message) { described_class::WIP_PREFIX + final_message + 'D' * (described_class::MAX_LINE_LENGTH - final_message.size) }
- it 'does not have any problems' do
- commit_linter.lint_subject
+ 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
- expect(commit_linter.problems).to be_empty
+ 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 is too short and too long' do
+ 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
diff --git a/spec/lib/gitlab/danger/changelog_spec.rb b/spec/lib/gitlab/danger/changelog_spec.rb
index 2da60f4f8bd..04c515f1205 100644
--- a/spec/lib/gitlab/danger/changelog_spec.rb
+++ b/spec/lib/gitlab/danger/changelog_spec.rb
@@ -150,41 +150,80 @@ RSpec.describe Gitlab::Danger::Changelog do
end
describe '#modified_text' do
- let(:sanitize_mr_title) { 'Fake Title' }
let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
subject { changelog.modified_text }
- it 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"')
+ 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(:sanitize_mr_title) { 'Fake Title' }
let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
subject { changelog.required_text }
- it do
- expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).not_to include('--ee')
+ 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(:sanitize_mr_title) { 'Fake Title' }
+ describe '#optional_text' do
let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
subject { changelog.optional_text }
- it 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"')
+ 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/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
index a8f113a8cd1..bd5c746dd54 100644
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -351,33 +351,23 @@ RSpec.describe Gitlab::Danger::Helper do
end
context 'having specific changes' do
- it 'has database and backend categories' do
- changed_files = ['usage_data.rb', 'lib/gitlab/usage_data.rb', 'ee/lib/ee/gitlab/usage_data.rb']
-
- changed_files.each do |file|
- allow(fake_git).to receive(:diff_for_file).with(file) { double(:diff, patch: "+ count(User.active)") }
-
- expect(helper.categories_for_file(file)).to eq([:database, :backend])
- end
- end
-
- it 'has backend category' do
- allow(fake_git).to receive(:diff_for_file).with('usage_data.rb') { double(:diff, patch: "+ alt_usage_data(User.active)") }
-
- expect(helper.categories_for_file('usage_data.rb')).to eq([:backend])
- end
-
- it 'has backend category for changes outside usage_data files' do
- allow(fake_git).to receive(:diff_for_file).with('user.rb') { double(:diff, patch: "+ count(User.active)") }
-
- expect(helper.categories_for_file('user.rb')).to eq([:backend])
+ 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
- it 'has backend category for files that are not usage_data.rb' do
- changed_file = 'usage_data/topology.rb'
- allow(fake_git).to receive(:diff_for_file).with(changed_file) { double(:diff, patch: "+ count(User.active)") }
+ 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(changed_file)).to eq([:backend])
+ expect(helper.categories_for_file(file)).to eq(expected_categories)
+ end
+ end
end
end
end
@@ -412,24 +402,6 @@ RSpec.describe Gitlab::Danger::Helper do
end
end
- 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'
- end
-
- with_them do
- subject { helper.sanitize_mr_title(mr_title) }
-
- it { is_expected.to eq(expected_mr_title) }
- end
- end
-
describe '#security_mr?' do
it 'returns false when `gitlab_helper` is unavailable' do
expect(helper).to receive(:gitlab_helper).and_return(nil)
diff --git a/spec/lib/gitlab/danger/roulette_spec.rb b/spec/lib/gitlab/danger/roulette_spec.rb
index 561e108bf31..59ac3b12b6b 100644
--- a/spec/lib/gitlab/danger/roulette_spec.rb
+++ b/spec/lib/gitlab/danger/roulette_spec.rb
@@ -245,69 +245,6 @@ RSpec.describe Gitlab::Danger::Roulette do
end
end
end
-
- describe 'reviewer suggestion probability' do
- let(:reviewer) { teammate_with_capability('reviewer', 'reviewer backend') }
- let(:hungry_reviewer) { teammate_with_capability('hungry_reviewer', 'reviewer backend', hungry: true) }
- let(:traintainer) { teammate_with_capability('traintainer', 'trainee_maintainer backend') }
- let(:hungry_traintainer) { teammate_with_capability('hungry_traintainer', 'trainee_maintainer backend', hungry: true) }
- let(:teammates) do
- [
- reviewer.to_h,
- hungry_reviewer.to_h,
- traintainer.to_h,
- hungry_traintainer.to_h
- ]
- end
-
- let(:categories) { [:backend] }
-
- # This test is testing probability with inherent randomness.
- # The variance is inversely related to sample size
- # Given large enough sample size, the variance would be smaller,
- # but the test would take longer.
- # Given smaller sample size, the variance would be larger,
- # but the test would take less time.
- let!(:sample_size) { 500 }
- let!(:variance) { 0.1 }
-
- before do
- # This test needs actual randomness to simulate probabilities
- allow(subject).to receive(:new_random).and_return(Random.new)
- WebMock
- .stub_request(:get, described_class::ROULETTE_DATA_URL)
- .to_return(body: teammate_json)
- end
-
- it 'has 1:2:3:4 probability of picking reviewer, hungry_reviewer, traintainer, hungry_traintainer' do
- picks = Array.new(sample_size).map do
- spins = subject.spin(project, categories, timezone_experiment: timezone_experiment)
- spins.first.reviewer.name
- end
-
- expect(probability(picks, 'reviewer')).to be_within(variance).of(0.1)
- expect(probability(picks, 'hungry_reviewer')).to be_within(variance).of(0.2)
- expect(probability(picks, 'traintainer')).to be_within(variance).of(0.3)
- expect(probability(picks, 'hungry_traintainer')).to be_within(variance).of(0.4)
- end
-
- def probability(picks, role)
- picks.count(role).to_f / picks.length
- end
-
- def teammate_with_capability(name, capability, hungry: false)
- Gitlab::Danger::Teammate.new(
- {
- 'name' => name,
- 'projects' => {
- 'gitlab' => capability
- },
- 'available' => true,
- 'hungry' => hungry
- }
- )
- end
- end
end
RSpec::Matchers.define :match_teammates do |expected|
diff --git a/spec/lib/gitlab/danger/teammate_spec.rb b/spec/lib/gitlab/danger/teammate_spec.rb
index eebe14ed5e1..9c066ba4c1b 100644
--- a/spec/lib/gitlab/danger/teammate_spec.rb
+++ b/spec/lib/gitlab/danger/teammate_spec.rb
@@ -121,6 +121,14 @@ RSpec.describe Gitlab::Danger::Teammate do
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'] }
diff --git a/spec/lib/gitlab/danger/title_linting_spec.rb b/spec/lib/gitlab/danger/title_linting_spec.rb
new file mode 100644
index 00000000000..b48d2c5e53d
--- /dev/null
+++ b/spec/lib/gitlab/danger/title_linting_spec.rb
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 00000000000..066bb487fa2
--- /dev/null
+++ b/spec/lib/gitlab/danger/weightage/maintainers_spec.rb
@@ -0,0 +1,34 @@
+# 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
new file mode 100644
index 00000000000..cca81f4d9b5
--- /dev/null
+++ b/spec/lib/gitlab/danger/weightage/reviewers_spec.rb
@@ -0,0 +1,63 @@
+# 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 cfaaf849b09..2f74e766a11 100644
--- a/spec/lib/gitlab/data_builder/build_spec.rb
+++ b/spec/lib/gitlab/data_builder/build_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe Gitlab::DataBuilder::Build do
it {
expect(data[:user]).to eq(
{
+ id: user.id,
name: user.name,
username: user.username,
avatar_url: user.avatar_url(only_path: false),
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index e5dfff33a2a..297d87708d8 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -41,6 +41,7 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
expect(project_data).to eq(project.hook_attrs(backward: false))
expect(data[:merge_request]).to be_nil
expect(data[:user]).to eq({
+ id: user.id,
name: user.name,
username: user.username,
avatar_url: user.avatar_url(only_path: false),
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index a763dc08b73..6b709cba5b3 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::MigrationHelpers do
+ include Database::TableSchemaHelpers
+
let(:model) do
ActiveRecord::Migration.new.extend(described_class)
end
@@ -96,6 +98,131 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
end
+ describe '#create_table_with_constraints' do
+ let(:table_name) { :test_table }
+ let(:column_attributes) do
+ [
+ { name: 'id', sql_type: 'bigint', null: false, default: nil },
+ { name: 'created_at', sql_type: 'timestamp with time zone', null: false, default: nil },
+ { name: 'updated_at', sql_type: 'timestamp with time zone', null: false, default: nil },
+ { name: 'some_id', sql_type: 'integer', null: false, default: nil },
+ { name: 'active', sql_type: 'boolean', null: false, default: 'true' },
+ { name: 'name', sql_type: 'text', null: true, default: nil }
+ ]
+ end
+
+ before do
+ allow(model).to receive(:transaction_open?).and_return(true)
+ end
+
+ context 'when no check constraints are defined' do
+ it 'creates the table as expected' do
+ model.create_table_with_constraints table_name do |t|
+ t.timestamps_with_timezone
+ t.integer :some_id, null: false
+ t.boolean :active, null: false, default: true
+ t.text :name
+ end
+
+ expect_table_columns_to_match(column_attributes, table_name)
+ end
+ end
+
+ context 'when check constraints are defined' do
+ context 'when the text_limit is explicity named' do
+ it 'creates the table as expected' do
+ model.create_table_with_constraints table_name do |t|
+ t.timestamps_with_timezone
+ t.integer :some_id, null: false
+ t.boolean :active, null: false, default: true
+ t.text :name
+
+ t.text_limit :name, 255, name: 'check_name_length'
+ t.check_constraint :some_id_is_positive, 'some_id > 0'
+ end
+
+ expect_table_columns_to_match(column_attributes, table_name)
+
+ expect_check_constraint(table_name, 'check_name_length', 'char_length(name) <= 255')
+ expect_check_constraint(table_name, 'some_id_is_positive', 'some_id > 0')
+ end
+ end
+
+ context 'when the text_limit is not named' do
+ it 'creates the table as expected, naming the text limit' do
+ model.create_table_with_constraints table_name do |t|
+ t.timestamps_with_timezone
+ t.integer :some_id, null: false
+ t.boolean :active, null: false, default: true
+ t.text :name
+
+ t.text_limit :name, 255
+ t.check_constraint :some_id_is_positive, 'some_id > 0'
+ end
+
+ expect_table_columns_to_match(column_attributes, table_name)
+
+ expect_check_constraint(table_name, 'check_cda6f69506', 'char_length(name) <= 255')
+ expect_check_constraint(table_name, 'some_id_is_positive', 'some_id > 0')
+ end
+ end
+
+ it 'runs the change within a with_lock_retries' do
+ expect(model).to receive(:with_lock_retries).ordered.and_yield
+ expect(model).to receive(:create_table).ordered.and_call_original
+ expect(model).to receive(:execute).with(<<~SQL).ordered
+ ALTER TABLE "#{table_name}"\nADD CONSTRAINT "check_cda6f69506" CHECK (char_length("name") <= 255)
+ SQL
+
+ model.create_table_with_constraints table_name do |t|
+ t.text :name
+ t.text_limit :name, 255
+ end
+ end
+
+ context 'when constraints are given invalid names' do
+ let(:expected_max_length) { described_class::MAX_IDENTIFIER_NAME_LENGTH }
+ let(:expected_error_message) { "The maximum allowed constraint name is #{expected_max_length} characters" }
+
+ context 'when the explicit text limit name is not valid' do
+ it 'raises an error' do
+ too_long_length = expected_max_length + 1
+
+ expect do
+ model.create_table_with_constraints table_name do |t|
+ t.timestamps_with_timezone
+ t.integer :some_id, null: false
+ t.boolean :active, null: false, default: true
+ t.text :name
+
+ t.text_limit :name, 255, name: ('a' * too_long_length)
+ t.check_constraint :some_id_is_positive, 'some_id > 0'
+ end
+ end.to raise_error(expected_error_message)
+ end
+ end
+
+ context 'when a check constraint name is not valid' do
+ it 'raises an error' do
+ too_long_length = expected_max_length + 1
+
+ expect do
+ model.create_table_with_constraints table_name do |t|
+ t.timestamps_with_timezone
+ t.integer :some_id, null: false
+ t.boolean :active, null: false, default: true
+ t.text :name
+
+ t.text_limit :name, 255
+ t.check_constraint ('a' * too_long_length), 'some_id > 0'
+ end
+ end.to raise_error(expected_error_message)
+ end
+ end
+ end
+ end
+ end
+
describe '#add_concurrent_index' do
context 'outside a transaction' do
before do
@@ -1548,6 +1675,69 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
end
+ describe '#initialize_conversion_of_integer_to_bigint' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:issue) { create(:issue, project: project) }
+ let!(:event) do
+ create(:event, :created, project: project, target: issue, author: user)
+ end
+
+ context 'in a transaction' do
+ it 'raises RuntimeError' do
+ allow(model).to receive(:transaction_open?).and_return(true)
+
+ expect { model.initialize_conversion_of_integer_to_bigint(:events, :id) }
+ .to raise_error(RuntimeError)
+ end
+ end
+
+ context 'outside a transaction' do
+ before do
+ allow(model).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'creates a bigint column and starts backfilling it' do
+ expect(model)
+ .to receive(:add_column)
+ .with(
+ :events,
+ 'id_convert_to_bigint',
+ :bigint,
+ default: 0,
+ null: false
+ )
+
+ expect(model)
+ .to receive(:install_rename_triggers)
+ .with(:events, :id, 'id_convert_to_bigint')
+
+ expect(model).to receive(:queue_background_migration_jobs_by_range_at_intervals).and_call_original
+
+ expect(BackgroundMigrationWorker)
+ .to receive(:perform_in)
+ .ordered
+ .with(
+ 2.minutes,
+ 'CopyColumnUsingBackgroundMigrationJob',
+ [event.id, event.id, :events, :id, :id, 'id_convert_to_bigint', 100]
+ )
+
+ expect(Gitlab::BackgroundMigration)
+ .to receive(:steal)
+ .ordered
+ .with('CopyColumnUsingBackgroundMigrationJob')
+
+ model.initialize_conversion_of_integer_to_bigint(
+ :events,
+ :id,
+ batch_size: 300,
+ sub_batch_size: 100
+ )
+ end
+ end
+ end
+
describe '#index_exists_by_name?' do
it 'returns true if an index exists' do
ActiveRecord::Base.connection.execute(
diff --git a/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb b/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb
index 56399941662..ec89f2ed61c 100644
--- a/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Partitioning::PartitionCreator do
- include PartitioningHelpers
+ include Database::PartitioningHelpers
include ExclusiveLeaseHelpers
describe '.register' do
diff --git a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
index d47666eeffd..8e27797208c 100644
--- a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Partitioning::ReplaceTable, '#perform' do
- include TableSchemaHelpers
+ include Database::TableSchemaHelpers
subject(:replace_table) { described_class.new(original_table, replacement_table, archived_table, 'id').perform }
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
index 7d88c17c9b3..93dbd9d7c30 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::ForeignKeyHelpers do
- include TriggerHelpers
+ include Database::TriggerHelpers
let(:model) do
ActiveRecord::Migration.new.extend(described_class)
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
index 7f61ff759fc..603f3dc41af 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do
- include TableSchemaHelpers
+ include Database::TableSchemaHelpers
let(:migration) do
ActiveRecord::Migration.new.extend(described_class)
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 f10ff704c17..b50e02c7043 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
@@ -3,25 +3,36 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers do
- include PartitioningHelpers
- include TriggerHelpers
- include TableSchemaHelpers
+ include Database::PartitioningHelpers
+ include Database::TriggerHelpers
+ include Database::TableSchemaHelpers
let(:migration) do
ActiveRecord::Migration.new.extend(described_class)
end
let_it_be(:connection) { ActiveRecord::Base.connection }
- let(:source_table) { :audit_events }
+ let(:source_table) { :_test_original_table }
let(:partitioned_table) { '_test_migration_partitioned_table' }
let(:function_name) { '_test_migration_function_name' }
let(:trigger_name) { '_test_migration_trigger_name' }
let(:partition_column) { 'created_at' }
let(:min_date) { Date.new(2019, 12) }
let(:max_date) { Date.new(2020, 3) }
+ let(:source_model) { Class.new(ActiveRecord::Base) }
before do
allow(migration).to receive(:puts)
+
+ migration.create_table source_table do |t|
+ t.string :name, null: false
+ t.integer :age, null: false
+ t.datetime partition_column
+ t.datetime :updated_at
+ end
+
+ source_model.table_name = source_table
+
allow(migration).to receive(:transaction_open?).and_return(false)
allow(migration).to receive(:make_partitioned_table_name).and_return(partitioned_table)
allow(migration).to receive(:make_sync_function_name).and_return(function_name)
@@ -81,14 +92,11 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
context 'when the given table does not have a primary key' do
- let(:source_table) { :_partitioning_migration_helper_test_table }
- let(:partition_column) { :some_field }
-
it 'raises an error' do
- migration.create_table source_table, id: false do |t|
- t.integer :id
- t.datetime partition_column
- end
+ migration.execute(<<~SQL)
+ ALTER TABLE #{source_table}
+ DROP CONSTRAINT #{source_table}_pkey
+ SQL
expect do
migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
@@ -97,12 +105,12 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
context 'when an invalid partition column is given' do
- let(:partition_column) { :_this_is_not_real }
+ let(:invalid_column) { :_this_is_not_real }
it 'raises an error' do
expect do
- migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
- end.to raise_error(/partition column #{partition_column} does not exist/)
+ migration.partition_table_by_date source_table, invalid_column, min_date: min_date, max_date: max_date
+ end.to raise_error(/partition column #{invalid_column} does not exist/)
end
end
@@ -126,19 +134,19 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
context 'with a non-integer primary key datatype' do
before do
- connection.create_table :another_example, id: false do |t|
+ connection.create_table non_int_table, id: false do |t|
t.string :identifier, primary_key: true
t.timestamp :created_at
end
end
- let(:source_table) { :another_example }
+ let(:non_int_table) { :another_example }
let(:old_primary_key) { 'identifier' }
it 'does not change the primary key datatype' do
- migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
+ migration.partition_table_by_date non_int_table, partition_column, min_date: min_date, max_date: max_date
- original_pk_column = connection.columns(source_table).find { |c| c.name == old_primary_key }
+ original_pk_column = connection.columns(non_int_table).find { |c| c.name == old_primary_key }
pk_column = connection.columns(partitioned_table).find { |c| c.name == old_primary_key }
expect(pk_column).not_to be_nil
@@ -176,11 +184,9 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
context 'when min_date is not given' do
- let(:source_table) { :todos }
-
context 'with records present already' do
before do
- create(:todo, created_at: Date.parse('2019-11-05'))
+ source_model.create!(name: 'Test', age: 10, created_at: Date.parse('2019-11-05'))
end
it 'creates a partition spanning over each month from the first record' do
@@ -248,13 +254,12 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
describe 'keeping data in sync with the partitioned table' do
- let(:source_table) { :todos }
- let(:model) { Class.new(ActiveRecord::Base) }
+ let(:partitioned_model) { Class.new(ActiveRecord::Base) }
let(:timestamp) { Time.utc(2019, 12, 1, 12).round }
before do
- model.primary_key = :id
- model.table_name = partitioned_table
+ partitioned_model.primary_key = :id
+ partitioned_model.table_name = partitioned_table
end
it 'creates a trigger function on the original table' do
@@ -270,50 +275,50 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
it 'syncs inserts to the partitioned tables' do
migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
- expect(model.count).to eq(0)
+ expect(partitioned_model.count).to eq(0)
- first_todo = create(:todo, created_at: timestamp, updated_at: timestamp)
- second_todo = create(:todo, created_at: timestamp, updated_at: timestamp)
+ first_record = source_model.create!(name: 'Bob', age: 20, created_at: timestamp, updated_at: timestamp)
+ second_record = source_model.create!(name: 'Alice', age: 30, created_at: timestamp, updated_at: timestamp)
- expect(model.count).to eq(2)
- expect(model.find(first_todo.id).attributes).to eq(first_todo.attributes)
- expect(model.find(second_todo.id).attributes).to eq(second_todo.attributes)
+ expect(partitioned_model.count).to eq(2)
+ expect(partitioned_model.find(first_record.id).attributes).to eq(first_record.attributes)
+ expect(partitioned_model.find(second_record.id).attributes).to eq(second_record.attributes)
end
it 'syncs updates to the partitioned tables' do
migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
- first_todo = create(:todo, :pending, commit_id: nil, created_at: timestamp, updated_at: timestamp)
- second_todo = create(:todo, created_at: timestamp, updated_at: timestamp)
+ first_record = source_model.create!(name: 'Bob', age: 20, created_at: timestamp, updated_at: timestamp)
+ second_record = source_model.create!(name: 'Alice', age: 30, created_at: timestamp, updated_at: timestamp)
- expect(model.count).to eq(2)
+ expect(partitioned_model.count).to eq(2)
- first_copy = model.find(first_todo.id)
- second_copy = model.find(second_todo.id)
+ first_copy = partitioned_model.find(first_record.id)
+ second_copy = partitioned_model.find(second_record.id)
- expect(first_copy.attributes).to eq(first_todo.attributes)
- expect(second_copy.attributes).to eq(second_todo.attributes)
+ expect(first_copy.attributes).to eq(first_record.attributes)
+ expect(second_copy.attributes).to eq(second_record.attributes)
- first_todo.update(state_event: 'done', commit_id: 'abc123', updated_at: timestamp + 1.second)
+ first_record.update!(age: 21, updated_at: timestamp + 1.hour)
- expect(model.count).to eq(2)
- expect(first_copy.reload.attributes).to eq(first_todo.attributes)
- expect(second_copy.reload.attributes).to eq(second_todo.attributes)
+ expect(partitioned_model.count).to eq(2)
+ expect(first_copy.reload.attributes).to eq(first_record.attributes)
+ expect(second_copy.reload.attributes).to eq(second_record.attributes)
end
it 'syncs deletes to the partitioned tables' do
migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
- first_todo = create(:todo, created_at: timestamp, updated_at: timestamp)
- second_todo = create(:todo, created_at: timestamp, updated_at: timestamp)
+ first_record = source_model.create!(name: 'Bob', age: 20, created_at: timestamp, updated_at: timestamp)
+ second_record = source_model.create!(name: 'Alice', age: 30, created_at: timestamp, updated_at: timestamp)
- expect(model.count).to eq(2)
+ expect(partitioned_model.count).to eq(2)
- first_todo.destroy
+ first_record.destroy!
- expect(model.count).to eq(1)
- expect(model.find_by_id(first_todo.id)).to be_nil
- expect(model.find(second_todo.id).attributes).to eq(second_todo.attributes)
+ expect(partitioned_model.count).to eq(1)
+ expect(partitioned_model.find_by_id(first_record.id)).to be_nil
+ expect(partitioned_model.find(second_record.id).attributes).to eq(second_record.attributes)
end
end
end
@@ -388,13 +393,12 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
context 'when records exist in the source table' do
- let(:source_table) { 'todos' }
let(:migration_class) { '::Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable' }
let(:sub_batch_size) { described_class::SUB_BATCH_SIZE }
let(:pause_seconds) { described_class::PAUSE_SECONDS }
- let!(:first_id) { create(:todo).id }
- let!(:second_id) { create(:todo).id }
- let!(:third_id) { create(:todo).id }
+ let!(:first_id) { source_model.create!(name: 'Bob', age: 20).id }
+ let!(:second_id) { source_model.create!(name: 'Alice', age: 30).id }
+ let!(:third_id) { source_model.create!(name: 'Sam', age: 40).id }
before do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
@@ -410,10 +414,10 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- first_job_arguments = [first_id, second_id, source_table, partitioned_table, 'id']
+ first_job_arguments = [first_id, second_id, source_table.to_s, partitioned_table, 'id']
expect(BackgroundMigrationWorker.jobs[0]['args']).to eq([migration_class, first_job_arguments])
- second_job_arguments = [third_id, third_id, source_table, partitioned_table, 'id']
+ second_job_arguments = [third_id, third_id, source_table.to_s, partitioned_table, 'id']
expect(BackgroundMigrationWorker.jobs[1]['args']).to eq([migration_class, second_job_arguments])
end
end
@@ -482,7 +486,6 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
describe '#finalize_backfilling_partitioned_table' do
- let(:source_table) { 'todos' }
let(:source_column) { 'id' }
context 'when the table is not allowed' do
@@ -536,27 +539,27 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
context 'when there is missed data' do
let(:partitioned_model) { Class.new(ActiveRecord::Base) }
let(:timestamp) { Time.utc(2019, 12, 1, 12).round }
- let!(:todo1) { create(:todo, created_at: timestamp, updated_at: timestamp) }
- let!(:todo2) { create(:todo, created_at: timestamp, updated_at: timestamp) }
- let!(:todo3) { create(:todo, created_at: timestamp, updated_at: timestamp) }
- let!(:todo4) { create(:todo, created_at: timestamp, updated_at: timestamp) }
+ let!(:record1) { source_model.create!(name: 'Bob', age: 20, created_at: timestamp, updated_at: timestamp) }
+ let!(:record2) { source_model.create!(name: 'Alice', age: 30, created_at: timestamp, updated_at: timestamp) }
+ let!(:record3) { source_model.create!(name: 'Sam', age: 40, created_at: timestamp, updated_at: timestamp) }
+ let!(:record4) { source_model.create!(name: 'Sue', age: 50, created_at: timestamp, updated_at: timestamp) }
let!(:pending_job1) do
create(:background_migration_job,
class_name: described_class::MIGRATION_CLASS_NAME,
- arguments: [todo1.id, todo2.id, source_table, partitioned_table, source_column])
+ arguments: [record1.id, record2.id, source_table, partitioned_table, source_column])
end
let!(:pending_job2) do
create(:background_migration_job,
class_name: described_class::MIGRATION_CLASS_NAME,
- arguments: [todo3.id, todo3.id, source_table, partitioned_table, source_column])
+ arguments: [record3.id, record3.id, source_table, partitioned_table, source_column])
end
let!(:succeeded_job) do
create(:background_migration_job, :succeeded,
class_name: described_class::MIGRATION_CLASS_NAME,
- arguments: [todo4.id, todo4.id, source_table, partitioned_table, source_column])
+ arguments: [record4.id, record4.id, source_table, partitioned_table, source_column])
end
before do
@@ -575,17 +578,17 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
it 'idempotently cleans up after failed background migrations' do
expect(partitioned_model.count).to eq(0)
- partitioned_model.insert!(todo2.attributes)
+ partitioned_model.insert!(record2.attributes)
expect_next_instance_of(Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable) do |backfill|
allow(backfill).to receive(:transaction_open?).and_return(false)
expect(backfill).to receive(:perform)
- .with(todo1.id, todo2.id, source_table, partitioned_table, source_column)
+ .with(record1.id, record2.id, source_table, partitioned_table, source_column)
.and_call_original
expect(backfill).to receive(:perform)
- .with(todo3.id, todo3.id, source_table, partitioned_table, source_column)
+ .with(record3.id, record3.id, source_table, partitioned_table, source_column)
.and_call_original
end
@@ -593,12 +596,12 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
expect(partitioned_model.count).to eq(3)
- [todo1, todo2, todo3].each do |original|
+ [record1, record2, record3].each do |original|
copy = partitioned_model.find(original.id)
expect(copy.attributes).to eq(original.attributes)
end
- expect(partitioned_model.find_by_id(todo4.id)).to be_nil
+ expect(partitioned_model.find_by_id(record4.id)).to be_nil
[pending_job1, pending_job2].each do |job|
expect(job.reload).to be_succeeded
diff --git a/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb b/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb
index 934e2274358..2c550f14a08 100644
--- a/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb
+++ b/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb
@@ -24,107 +24,48 @@ RSpec.describe Gitlab::Database::PostgresHll::BatchDistinctCounter do
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(in_transaction)
end
- context 'different distribution of relation records' do
- [10, 100, 100_000].each do |spread|
- context "records are spread within #{spread}" do
- before do
- ids = (1..spread).to_a.sample(10)
- create_list(:issue, 10).each_with_index do |issue, i|
- issue.id = ids[i]
- end
- end
-
- it 'counts table' do
- expect(described_class.new(model).estimate_distinct_count).to be_within(error_rate).percent_of(10)
- end
- end
- end
- end
-
context 'unit test for different counting parameters' do
before_all do
create_list(:issue, 3, author: user)
create_list(:issue, 2, author: another_user)
end
- describe '#estimate_distinct_count' do
- it 'counts table' do
- expect(described_class.new(model).estimate_distinct_count).to be_within(error_rate).percent_of(5)
- end
-
- it 'counts with column field' do
- expect(described_class.new(model, column).estimate_distinct_count).to be_within(error_rate).percent_of(2)
- end
-
- it 'counts with :id field' do
- expect(described_class.new(model, :id).estimate_distinct_count).to be_within(error_rate).percent_of(5)
- end
-
- it 'counts with "id" field' do
- expect(described_class.new(model, "id").estimate_distinct_count).to be_within(error_rate).percent_of(5)
- end
-
- it 'counts with table.column field' do
- expect(described_class.new(model, "#{model.table_name}.#{column}").estimate_distinct_count).to be_within(error_rate).percent_of(2)
- end
-
- it 'counts with Arel column' do
- expect(described_class.new(model, model.arel_table[column]).estimate_distinct_count).to be_within(error_rate).percent_of(2)
- end
-
- it 'counts over joined relations' do
- expect(described_class.new(model.joins(:author), "users.email").estimate_distinct_count).to be_within(error_rate).percent_of(2)
- end
-
- it 'counts with :column field with batch_size of 50K' do
- expect(described_class.new(model, column).estimate_distinct_count(batch_size: 50_000)).to be_within(error_rate).percent_of(2)
- end
-
- it 'will not count table with a batch size less than allowed' do
- expect(described_class.new(model, column).estimate_distinct_count(batch_size: small_batch_size)).to eq(fallback)
- end
-
- it 'counts with different number of batches and aggregates total result' do
- stub_const('Gitlab::Database::PostgresHll::BatchDistinctCounter::MIN_REQUIRED_BATCH_SIZE', 0)
-
- [1, 2, 4, 5, 6].each { |i| expect(described_class.new(model).estimate_distinct_count(batch_size: i)).to be_within(error_rate).percent_of(5) }
- end
-
- it 'counts with a start and finish' do
- expect(described_class.new(model, column).estimate_distinct_count(start: model.minimum(:id), finish: model.maximum(:id))).to be_within(error_rate).percent_of(2)
+ describe '#execute' do
+ it 'builds hll buckets' do
+ expect(described_class.new(model).execute).to be_an_instance_of(Gitlab::Database::PostgresHll::Buckets)
end
- it "defaults the batch size to #{Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE}" do
+ it "defaults batch size to #{Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE}" do
min_id = model.minimum(:id)
batch_end_id = min_id + calculate_batch_size(Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE)
expect(model).to receive(:where).with("id" => min_id..batch_end_id).and_call_original
- described_class.new(model).estimate_distinct_count
+ described_class.new(model).execute
end
context 'when a transaction is open' do
let(:in_transaction) { true }
it 'raises an error' do
- expect { described_class.new(model, column).estimate_distinct_count }.to raise_error('BatchCount can not be run inside a transaction')
+ expect { described_class.new(model, column).execute }.to raise_error('BatchCount can not be run inside a transaction')
end
end
context 'disallowed configurations' do
let(:default_batch_size) { Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE }
- it 'returns fallback if start is bigger than finish' do
- expect(described_class.new(model, column).estimate_distinct_count(start: 1, finish: 0)).to eq(fallback)
+ it 'raises WRONG_CONFIGURATION_ERROR if start is bigger than finish' do
+ expect { described_class.new(model, column).execute(start: 1, finish: 0) }.to raise_error(described_class::WRONG_CONFIGURATION_ERROR)
end
- it 'returns fallback if data volume exceeds upper limit' do
+ it 'raises WRONG_CONFIGURATION_ERROR if data volume exceeds upper limit' do
large_finish = Gitlab::Database::PostgresHll::BatchDistinctCounter::MAX_DATA_VOLUME + 1
- expect(described_class.new(model, column).estimate_distinct_count(start: 1, finish: large_finish)).to eq(fallback)
+ expect { described_class.new(model, column).execute(start: 1, finish: large_finish) }.to raise_error(described_class::WRONG_CONFIGURATION_ERROR)
end
- it 'returns fallback if batch size is less than min required' do
- expect(described_class.new(model, column).estimate_distinct_count(batch_size: small_batch_size)).to eq(fallback)
+ it 'raises WRONG_CONFIGURATION_ERROR if batch size is less than min required' do
+ expect { described_class.new(model, column).execute(batch_size: small_batch_size) }.to raise_error(described_class::WRONG_CONFIGURATION_ERROR)
end
end
end
diff --git a/spec/lib/gitlab/database/postgres_hll/buckets_spec.rb b/spec/lib/gitlab/database/postgres_hll/buckets_spec.rb
new file mode 100644
index 00000000000..b4d8fd4a449
--- /dev/null
+++ b/spec/lib/gitlab/database/postgres_hll/buckets_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PostgresHll::Buckets do
+ let(:error_rate) { Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE } # HyperLogLog is a probabilistic algorithm, which provides estimated data, with given error margin
+ let(:buckets_hash_5) { { 121 => 2, 126 => 1, 141 => 1, 383 => 1, 56 => 1 } }
+ let(:buckets_hash_2) { { 141 => 1, 56 => 1 } }
+
+ describe '#estimated_distinct_count' do
+ it 'provides estimated cardinality', :aggregate_failures do
+ expect(described_class.new(buckets_hash_5).estimated_distinct_count).to be_within(error_rate).percent_of(5)
+ expect(described_class.new(buckets_hash_2).estimated_distinct_count).to be_within(error_rate).percent_of(2)
+ expect(described_class.new({}).estimated_distinct_count).to eq 0
+ expect(described_class.new.estimated_distinct_count).to eq 0
+ end
+ end
+
+ describe '#merge_hash!' do
+ let(:hash_a) { { 1 => 1, 2 => 3 } }
+ let(:hash_b) { { 1 => 2, 2 => 1 } }
+
+ it 'merges two hashes together into union of two sets' do
+ expect(described_class.new(hash_a).merge_hash!(hash_b).to_json).to eq described_class.new(1 => 2, 2 => 3).to_json
+ end
+ end
+
+ describe '#to_json' do
+ it 'serialize HyperLogLog buckets as hash' do
+ expect(described_class.new(1 => 5).to_json).to eq '{"1":5}'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/reindexing/coordinator_spec.rb b/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
index f45d959c0de..ae6362ba812 100644
--- a/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
@@ -3,65 +3,79 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Reindexing::Coordinator do
+ include Database::DatabaseHelpers
include ExclusiveLeaseHelpers
describe '.perform' do
- subject { described_class.new(indexes).perform }
+ subject { described_class.new(index, notifier).perform }
- let(:indexes) { [instance_double(Gitlab::Database::PostgresIndex), instance_double(Gitlab::Database::PostgresIndex)] }
- let(:reindexers) { [instance_double(Gitlab::Database::Reindexing::ConcurrentReindex), instance_double(Gitlab::Database::Reindexing::ConcurrentReindex)] }
+ before do
+ swapout_view_for_table(:postgres_indexes)
+
+ allow(Gitlab::Database::Reindexing::ConcurrentReindex).to receive(:new).with(index).and_return(reindexer)
+ allow(Gitlab::Database::Reindexing::ReindexAction).to receive(:create_for).with(index).and_return(action)
+ end
+
+ let(:index) { create(:postgres_index) }
+ let(:notifier) { instance_double(Gitlab::Database::Reindexing::GrafanaNotifier, notify_start: nil, notify_end: nil) }
+ let(:reindexer) { instance_double(Gitlab::Database::Reindexing::ConcurrentReindex, perform: nil) }
+ let(:action) { create(:reindex_action, index: index) }
let!(:lease) { stub_exclusive_lease(lease_key, uuid, timeout: lease_timeout) }
let(:lease_key) { 'gitlab/database/reindexing/coordinator' }
let(:lease_timeout) { 1.day }
let(:uuid) { 'uuid' }
- before do
- allow(Gitlab::Database::Reindexing::ReindexAction).to receive(:keep_track_of).and_yield
+ context 'locking' do
+ it 'acquires a lock while reindexing' do
+ expect(lease).to receive(:try_obtain).ordered.and_return(uuid)
- indexes.zip(reindexers).each do |index, reindexer|
- allow(Gitlab::Database::Reindexing::ConcurrentReindex).to receive(:new).with(index).and_return(reindexer)
- allow(reindexer).to receive(:perform)
- end
- end
+ expect(reindexer).to receive(:perform).ordered
- it 'performs concurrent reindexing for each index' do
- indexes.zip(reindexers).each do |index, reindexer|
- expect(Gitlab::Database::Reindexing::ConcurrentReindex).to receive(:new).with(index).ordered.and_return(reindexer)
- expect(reindexer).to receive(:perform)
+ expect(Gitlab::ExclusiveLease).to receive(:cancel).ordered.with(lease_key, uuid)
+
+ subject
end
- subject
+ it 'does not perform reindexing actions if lease is not granted' do
+ expect(lease).to receive(:try_obtain).ordered.and_return(false)
+ expect(Gitlab::Database::Reindexing::ConcurrentReindex).not_to receive(:new)
+
+ subject
+ end
end
- it 'keeps track of actions and creates ReindexAction records' do
- indexes.each do |index|
- expect(Gitlab::Database::Reindexing::ReindexAction).to receive(:keep_track_of).with(index).and_yield
+ context 'notifications' do
+ it 'sends #notify_start before reindexing' do
+ expect(notifier).to receive(:notify_start).with(action).ordered
+ expect(reindexer).to receive(:perform).ordered
+
+ subject
end
- subject
+ it 'sends #notify_end after reindexing and updating the action is done' do
+ expect(action).to receive(:finish).ordered
+ expect(notifier).to receive(:notify_end).with(action).ordered
+
+ subject
+ end
end
- context 'locking' do
- it 'acquires a lock while reindexing' do
- indexes.each do |index|
- expect(lease).to receive(:try_obtain).ordered.and_return(uuid)
- action = instance_double(Gitlab::Database::Reindexing::ConcurrentReindex)
- expect(Gitlab::Database::Reindexing::ConcurrentReindex).to receive(:new).ordered.with(index).and_return(action)
- expect(action).to receive(:perform).ordered
- expect(Gitlab::ExclusiveLease).to receive(:cancel).ordered.with(lease_key, uuid)
- end
+ context 'action tracking' do
+ it 'calls #finish on the action' do
+ expect(reindexer).to receive(:perform).ordered
+ expect(action).to receive(:finish).ordered
subject
end
- it 'does does not perform reindexing actions if lease is not granted' do
- indexes.each do |index|
- expect(lease).to receive(:try_obtain).ordered.and_return(false)
- expect(Gitlab::Database::Reindexing::ConcurrentReindex).not_to receive(:new)
- end
+ it 'upon error, it still calls finish and raises the error' do
+ expect(reindexer).to receive(:perform).ordered.and_raise('something went wrong')
+ expect(action).to receive(:finish).ordered
- subject
+ expect { subject }.to raise_error(/something went wrong/)
+
+ expect(action).to be_failed
end
end
end
diff --git a/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb b/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb
new file mode 100644
index 00000000000..e76718fe48a
--- /dev/null
+++ b/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Reindexing::GrafanaNotifier do
+ include Database::DatabaseHelpers
+
+ let(:api_key) { "foo" }
+ let(:api_url) { "http://bar"}
+ let(:additional_tag) { "some-tag" }
+
+ let(:action) { create(:reindex_action) }
+
+ before do
+ swapout_view_for_table(:postgres_indexes)
+ end
+
+ let(:headers) do
+ {
+ 'Content-Type': 'application/json',
+ 'Authorization': "Bearer #{api_key}"
+ }
+ end
+
+ let(:response) { double('response', success?: true) }
+
+ def expect_api_call(payload)
+ expect(Gitlab::HTTP).to receive(:post).with("#{api_url}/api/annotations", body: payload.to_json, headers: headers, allow_local_requests: true).and_return(response)
+ end
+
+ shared_examples_for 'interacting with Grafana annotations API' do
+ it 'POSTs a JSON payload' do
+ expect_api_call(payload)
+
+ expect(subject).to be_truthy
+ end
+
+ context 'on error' do
+ it 'does not raise the error and returns false' do
+ allow(Gitlab::HTTP).to receive(:post).and_raise('something went wrong')
+
+ expect(subject).to be_falsey
+ end
+
+ context 'when request was not successful' do
+ it 'returns false' do
+ expect_api_call(payload)
+ allow(response).to receive(:success?).and_return(false)
+
+ expect(subject).to be_falsey
+ end
+ end
+ end
+
+ context 'without api_key' do
+ let(:api_key) { '' }
+
+ it 'does not post anything' do
+ expect(Gitlab::HTTP).not_to receive(:post)
+
+ expect(subject).to be_falsey
+ end
+ end
+
+ context 'without api_url' do
+ let(:api_url) { '' }
+
+ it 'does not post anything' do
+ expect(Gitlab::HTTP).not_to receive(:post)
+
+ expect(subject).to be_falsey
+ end
+ end
+ end
+
+ describe '#notify_start' do
+ context 'additional tag is nil' do
+ subject { described_class.new(api_key, api_url, nil).notify_start(action) }
+
+ let(:payload) do
+ {
+ time: (action.action_start.utc.to_f * 1000).to_i,
+ tags: ['reindex', action.index.tablename, action.index.name],
+ text: "Started reindexing of #{action.index.name} on #{action.index.tablename}"
+ }
+ end
+
+ it_behaves_like 'interacting with Grafana annotations API'
+ end
+
+ context 'additional tag is not nil' do
+ subject { described_class.new(api_key, api_url, additional_tag).notify_start(action) }
+
+ let(:payload) do
+ {
+ time: (action.action_start.utc.to_f * 1000).to_i,
+ tags: ['reindex', additional_tag, action.index.tablename, action.index.name],
+ text: "Started reindexing of #{action.index.name} on #{action.index.tablename}"
+ }
+ end
+
+ it_behaves_like 'interacting with Grafana annotations API'
+ end
+ end
+
+ describe '#notify_end' do
+ context 'additional tag is nil' do
+ subject { described_class.new(api_key, api_url, nil).notify_end(action) }
+
+ let(:payload) do
+ {
+ time: (action.action_start.utc.to_f * 1000).to_i,
+ tags: ['reindex', action.index.tablename, action.index.name],
+ text: "Finished reindexing of #{action.index.name} on #{action.index.tablename} (#{action.state})",
+ timeEnd: (action.action_end.utc.to_f * 1000).to_i,
+ isRegion: true
+ }
+ end
+
+ it_behaves_like 'interacting with Grafana annotations API'
+ end
+
+ context 'additional tag is not nil' do
+ subject { described_class.new(api_key, api_url, additional_tag).notify_end(action) }
+
+ let(:payload) do
+ {
+ time: (action.action_start.utc.to_f * 1000).to_i,
+ tags: ['reindex', additional_tag, action.index.tablename, action.index.name],
+ text: "Finished reindexing of #{action.index.name} on #{action.index.tablename} (#{action.state})",
+ timeEnd: (action.action_end.utc.to_f * 1000).to_i,
+ isRegion: true
+ }
+ end
+
+ it_behaves_like 'interacting with Grafana annotations API'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/reindexing/index_selection_spec.rb b/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
index a5e2f368f40..4466679a099 100644
--- a/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Reindexing::IndexSelection do
- include DatabaseHelpers
+ include Database::DatabaseHelpers
subject { described_class.new(Gitlab::Database::PostgresIndex.all).to_a }
diff --git a/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb b/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb
index 225f23d2135..a8f196d8f0e 100644
--- a/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb
@@ -2,91 +2,83 @@
require 'spec_helper'
-RSpec.describe Gitlab::Database::Reindexing::ReindexAction, '.keep_track_of' do
- let(:index) { double('index', identifier: 'public.something', ondisk_size_bytes: 10240, reload: nil, bloat_size: 42) }
- let(:size_after) { 512 }
+RSpec.describe Gitlab::Database::Reindexing::ReindexAction do
+ include Database::DatabaseHelpers
- it 'yields to the caller' do
- expect { |b| described_class.keep_track_of(index, &b) }.to yield_control
- end
+ let(:index) { create(:postgres_index) }
- def find_record
- described_class.find_by(index_identifier: index.identifier)
+ before_all do
+ swapout_view_for_table(:postgres_indexes)
end
- it 'creates the record with a start time and updates its end time' do
- freeze_time do
- described_class.keep_track_of(index) do
- expect(find_record.action_start).to be_within(1.second).of(Time.zone.now)
+ describe '.create_for' do
+ subject { described_class.create_for(index) }
- travel(10.seconds)
- end
+ it 'creates a new record for the given index' do
+ freeze_time do
+ record = subject
- duration = find_record.action_end - find_record.action_start
+ expect(record.index_identifier).to eq(index.identifier)
+ expect(record.action_start).to eq(Time.zone.now)
+ expect(record.ondisk_size_bytes_start).to eq(index.ondisk_size_bytes)
+ expect(subject.bloat_estimate_bytes_start).to eq(index.bloat_size)
- expect(duration).to be_within(1.second).of(10.seconds)
+ expect(record).to be_persisted
+ end
end
end
- it 'creates the record with its status set to :started and updates its state to :finished' do
- described_class.keep_track_of(index) do
- expect(find_record).to be_started
- end
+ describe '#finish' do
+ subject { action.finish }
- expect(find_record).to be_finished
- end
+ let(:action) { build(:reindex_action, index: index) }
- it 'creates the record with the indexes start size and updates its end size' do
- described_class.keep_track_of(index) do
- expect(find_record.ondisk_size_bytes_start).to eq(index.ondisk_size_bytes)
+ it 'sets #action_end' do
+ freeze_time do
+ subject
- expect(index).to receive(:reload).once
- allow(index).to receive(:ondisk_size_bytes).and_return(size_after)
+ expect(action.action_end).to eq(Time.zone.now)
+ end
end
- expect(find_record.ondisk_size_bytes_end).to eq(size_after)
- end
+ it 'sets #ondisk_size_bytes_end after reloading the index record' do
+ new_size = 4711
+ expect(action.index).to receive(:reload).ordered
+ expect(action.index).to receive(:ondisk_size_bytes).and_return(new_size).ordered
+
+ subject
- it 'creates the record with the indexes bloat estimate' do
- described_class.keep_track_of(index) do
- expect(find_record.bloat_estimate_bytes_start).to eq(index.bloat_size)
+ expect(action.ondisk_size_bytes_end).to eq(new_size)
end
- end
- context 'in case of errors' do
- it 'sets the state to failed' do
- expect do
- described_class.keep_track_of(index) do
- raise 'something went wrong'
- end
- end.to raise_error(/something went wrong/)
+ context 'setting #state' do
+ it 'sets #state to finished if not given' do
+ action.state = nil
- expect(find_record).to be_failed
- end
+ subject
- it 'records the end time' do
- freeze_time do
- expect do
- described_class.keep_track_of(index) do
- raise 'something went wrong'
- end
- end.to raise_error(/something went wrong/)
+ expect(action).to be_finished
+ end
+
+ it 'sets #state to finished if not set to started' do
+ action.state = :started
- expect(find_record.action_end).to be_within(1.second).of(Time.zone.now)
+ subject
+
+ expect(action).to be_finished
end
- end
- it 'records the resulting index size' do
- expect(index).to receive(:reload).once
- allow(index).to receive(:ondisk_size_bytes).and_return(size_after)
+ it 'does not change state if set to failed' do
+ action.state = :failed
+
+ expect { subject }.not_to change { action.state }
+ end
+ end
- expect do
- described_class.keep_track_of(index) do
- raise 'something went wrong'
- end
- end.to raise_error(/something went wrong/)
+ it 'saves the record' do
+ expect(action).to receive(:save!)
- expect(find_record.ondisk_size_bytes_end).to eq(size_after)
+ subject
end
end
end
diff --git a/spec/lib/gitlab/database/reindexing_spec.rb b/spec/lib/gitlab/database/reindexing_spec.rb
index eb78a5fe8ea..b2f038e8b62 100644
--- a/spec/lib/gitlab/database/reindexing_spec.rb
+++ b/spec/lib/gitlab/database/reindexing_spec.rb
@@ -11,13 +11,16 @@ RSpec.describe Gitlab::Database::Reindexing do
let(:coordinator) { instance_double(Gitlab::Database::Reindexing::Coordinator) }
let(:index_selection) { instance_double(Gitlab::Database::Reindexing::IndexSelection) }
let(:candidate_indexes) { double }
- let(:indexes) { double }
+ let(:indexes) { [double, double] }
it 'delegates to Coordinator' do
expect(Gitlab::Database::Reindexing::IndexSelection).to receive(:new).with(candidate_indexes).and_return(index_selection)
expect(index_selection).to receive(:take).with(2).and_return(indexes)
- expect(Gitlab::Database::Reindexing::Coordinator).to receive(:new).with(indexes).and_return(coordinator)
- expect(coordinator).to receive(:perform)
+
+ indexes.each do |index|
+ expect(Gitlab::Database::Reindexing::Coordinator).to receive(:new).with(index).and_return(coordinator)
+ expect(coordinator).to receive(:perform)
+ end
subject
end
diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
index 4048fc69591..417bf3e363a 100644
--- a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
+++ b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
@@ -8,8 +8,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
let(:prometheus_settings) do
{
- enable: true,
- listen_address: 'localhost:9090'
+ enabled: true,
+ server_address: 'localhost:9090'
}
end
@@ -63,13 +63,13 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
application_setting.update(allow_local_requests_from_web_hooks_and_services: true)
end
- shared_examples 'has prometheus service' do |listen_address|
+ shared_examples 'has prometheus service' do |server_address|
it do
expect(result[:status]).to eq(:success)
prometheus = project.prometheus_service
expect(prometheus).not_to eq(nil)
- expect(prometheus.api_url).to eq(listen_address)
+ expect(prometheus.api_url).to eq(server_address)
expect(prometheus.active).to eq(true)
expect(prometheus.manual_configuration).to eq(true)
end
@@ -202,25 +202,25 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
end
context 'with non default prometheus address' do
- let(:listen_address) { 'https://localhost:9090' }
+ let(:server_address) { 'https://localhost:9090' }
let(:prometheus_settings) do
{
- enable: true,
- listen_address: listen_address
+ enabled: true,
+ server_address: server_address
}
end
it_behaves_like 'has prometheus service', 'https://localhost:9090'
context 'with :9090 symbol' do
- let(:listen_address) { :':9090' }
+ let(:server_address) { :':9090' }
it_behaves_like 'has prometheus service', 'http://localhost:9090'
end
context 'with 0.0.0.0:9090' do
- let(:listen_address) { '0.0.0.0:9090' }
+ let(:server_address) { '0.0.0.0:9090' }
it_behaves_like 'has prometheus service', 'http://localhost:9090'
end
@@ -251,8 +251,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
context 'when prometheus setting is disabled in gitlab.yml' do
let(:prometheus_settings) do
{
- enable: false,
- listen_address: 'http://localhost:9090'
+ enabled: false,
+ server_address: 'http://localhost:9090'
}
end
@@ -262,8 +262,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
end
end
- context 'when prometheus listen address is blank in gitlab.yml' do
- let(:prometheus_settings) { { enable: true, listen_address: '' } }
+ context 'when prometheus server address is blank in gitlab.yml' do
+ let(:prometheus_settings) { { enabled: true, server_address: '' } }
it 'does not configure prometheus' do
expect(result).to include(status: :success)
@@ -296,8 +296,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
context 'when prometheus manual configuration cannot be saved' do
let(:prometheus_settings) do
{
- enable: true,
- listen_address: 'httpinvalid://localhost:9090'
+ enabled: true,
+ server_address: 'httpinvalid://localhost:9090'
}
end
diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb
index a7f6ea0cbfb..c9a20f40462 100644
--- a/spec/lib/gitlab/diff/position_spec.rb
+++ b/spec/lib/gitlab/diff/position_spec.rb
@@ -752,4 +752,62 @@ RSpec.describe Gitlab::Diff::Position do
expect(subject.file_hash).to eq(Digest::SHA1.hexdigest(subject.file_path))
end
end
+
+ describe '#multiline?' do
+ let(:end_line_code) { "ab09011fa121d0a2bb9fa4ca76094f2482b902b7_#{end_old_line}_#{end_new_line}" }
+
+ let(:line_range) do
+ {
+ "start" => {
+ "line_code" => "ab09011fa121d0a2bb9fa4ca76094f2482b902b7_18_18",
+ "type" => nil,
+ "old_line" => 18,
+ "new_line" => 18
+ },
+ "end" => {
+ "line_code" => end_line_code,
+ "type" => nil,
+ "old_line" => end_old_line,
+ "new_line" => end_new_line
+ }
+ }
+ end
+
+ subject(:multiline) do
+ described_class.new(
+ line_range: line_range,
+ position_type: position_type
+ )
+ end
+
+ let(:end_old_line) { 20 }
+ let(:end_new_line) { 20 }
+
+ context 'when the position type is text' do
+ let(:position_type) { "text" }
+
+ context 'when the start lines equal the end lines' do
+ let(:end_old_line) { 18 }
+ let(:end_new_line) { 18 }
+
+ it "returns true" do
+ expect(subject.multiline?).to be_falsey
+ end
+ end
+
+ context 'when the start lines do not equal the end lines' do
+ it "returns true" do
+ expect(subject.multiline?).to be_truthy
+ end
+ end
+ end
+
+ context 'when the position type is not text' do
+ let(:position_type) { "image" }
+
+ it "returns false" do
+ expect(subject.multiline?).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
index ef448ee96a4..8872800069a 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -4,146 +4,50 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
include_context :email_shared_context
- let!(:sent_notification) do
- SentNotification.record_note(note, user.id, mail_key)
- end
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
let(:noteable) { note.noteable }
let(:note) { create(:diff_note_on_merge_request, project: project) }
- let(:user) { create(:user) }
- let(:project) { create(:project, :public, :repository) }
let(:email_raw) { fixture_file('emails/valid_reply.eml') }
+ let!(:sent_notification) do
+ SentNotification.record_note(note, user.id, mail_key)
+ end
it_behaves_like :reply_processing_shared_examples
+ it_behaves_like :note_handler_shared_examples do
+ let(:recipient) { sent_notification.recipient }
+
+ let(:update_commands_only) { fixture_file('emails/update_commands_only_reply.eml')}
+ let(:no_content) { fixture_file('emails/no_content_reply.eml') }
+ let(:commands_in_reply) { fixture_file('emails/commands_in_reply.eml') }
+ let(:with_quick_actions) { fixture_file('emails/valid_reply_with_quick_actions.eml') }
+ end
+
before do
stub_incoming_email_setting(enabled: true, address: "reply+%{key}@appmail.adventuretime.ooo")
stub_config_setting(host: 'localhost')
end
- context "when the recipient address doesn't include a mail key" do
- let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "") }
+ context 'when the recipient address does not include a mail key' do
+ let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, '') }
- it "raises a UnknownIncomingEmail" do
+ it 'raises a UnknownIncomingEmail' do
expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail)
end
end
- context "when no sent notification for the mail key could be found" do
+ context 'when no sent notification for the mail key could be found' do
let(:email_raw) { fixture_file('emails/wrong_mail_key.eml') }
- it "raises a SentNotificationNotFoundError" do
+ it 'raises a SentNotificationNotFoundError' do
expect { receiver.execute }.to raise_error(Gitlab::Email::SentNotificationNotFoundError)
end
end
- context "when the noteable could not be found" do
- before do
- noteable.destroy
- end
-
- it "raises a NoteableNotFoundError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::NoteableNotFoundError)
- end
- end
-
- context "when the note could not be saved" do
- before do
- allow_any_instance_of(Note).to receive(:persisted?).and_return(false)
- end
-
- it "raises an InvalidNoteError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
- end
-
- context 'because the note was update commands only' do
- let!(:email_raw) { fixture_file("emails/update_commands_only_reply.eml") }
-
- context 'and current user cannot update noteable' do
- it 'raises a CommandsOnlyNoteError' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
- end
- end
-
- context "and current user can update noteable" do
- before do
- project.add_developer(user)
- end
-
- it 'does not raise an error' do
- expect { receiver.execute }.to change { noteable.resource_state_events.count }.by(1)
-
- expect(noteable.reload).to be_closed
- end
- end
- end
- end
-
- context 'when the note contains quick actions' do
- let!(:email_raw) { fixture_file("emails/commands_in_reply.eml") }
-
- context 'and current user cannot update the noteable' do
- it 'only executes the commands that the user can perform' do
- expect { receiver.execute }
- .to change { noteable.notes.user.count }.by(1)
- .and change { user.todos_pending_count }.from(0).to(1)
-
- expect(noteable.reload).to be_open
- end
- end
-
- context 'and current user can update noteable' do
- before do
- project.add_developer(user)
- end
-
- it 'posts a note and updates the noteable' do
- expect(TodoService.new.todo_exist?(noteable, user)).to be_falsy
-
- expect { receiver.execute }
- .to change { noteable.notes.user.count }.by(1)
- .and change { user.todos_pending_count }.from(0).to(1)
-
- expect(noteable.reload).to be_closed
- end
- end
- end
-
- context "when the reply is blank" do
- let!(:email_raw) { fixture_file("emails/no_content_reply.eml") }
-
- it "raises an EmptyEmailError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::EmptyEmailError)
- end
- end
-
- shared_examples "checks permissions on noteable" do
- context "when user has access" do
- before do
- project.add_reporter(user)
- end
-
- it "creates a comment" do
- expect { receiver.execute }.to change { noteable.notes.count }.by(1)
- end
- end
-
- context "when user does not have access" do
- it "raises UserNotAuthorizedError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError)
- end
- end
- end
-
- context "when discussion is locked" do
- before do
- noteable.update_attribute(:discussion_locked, true)
- end
-
- it_behaves_like "checks permissions on noteable"
- end
-
- context "when issue is confidential" do
+ context 'when issue is confidential' do
let(:issue) { create(:issue, project: project) }
let(:note) { create(:note, noteable: issue, project: project) }
@@ -151,17 +55,17 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
issue.update_attribute(:confidential, true)
end
- it_behaves_like "checks permissions on noteable"
+ it_behaves_like :checks_permissions_on_noteable_examples
end
shared_examples 'a reply to existing comment' do
- it "creates a comment" do
+ it 'creates a comment' do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
new_note = noteable.notes.last
expect(new_note.author).to eq(sent_notification.recipient)
expect(new_note.position).to eq(note.position)
- expect(new_note.note).to include("I could not disagree more.")
+ expect(new_note.note).to include('I could not disagree more.')
expect(new_note.in_reply_to?(note)).to be_truthy
if note.part_of_discussion?
@@ -172,32 +76,14 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
- context "when everything is fine" do
+ # additional shared tests in :reply_processing_shared_examples
+ context 'when everything is fine' do
before do
setup_attachment
end
it_behaves_like 'a reply to existing comment'
- it "adds all attachments" do
- expect_next_instance_of(Gitlab::Email::AttachmentUploader) do |uploader|
- expect(uploader).to receive(:execute).with(upload_parent: project, uploader_class: FileUploader).and_return(
- [
- {
- url: "uploads/image.png",
- alt: "image",
- markdown: markdown
- }
- ]
- )
- end
-
- receiver.execute
-
- note = noteable.notes.last
- expect(note.note).to include(markdown)
- end
-
context 'when sub-addressing is not supported' do
before do
stub_incoming_email_setting(enabled: true, address: nil)
@@ -228,75 +114,9 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
- context "when note is not a discussion" do
+ context 'when note is not a discussion' do
let(:note) { create(:note_on_merge_request, project: project) }
it_behaves_like 'a reply to existing comment'
end
-
- context 'when the service desk' do
- let(:project) { create(:project, :public, service_desk_enabled: true) }
- let(:support_bot) { User.support_bot }
- let(:noteable) { create(:issue, project: project, author: support_bot, title: 'service desk issue') }
- let(:note) { create(:note, project: project, noteable: noteable) }
- let(:email_raw) { fixture_file('emails/valid_reply_with_quick_actions.eml') }
-
- let!(:sent_notification) do
- SentNotification.record_note(note, support_bot.id, mail_key)
- end
-
- context 'is enabled' do
- before do
- allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true)
- project.project_feature.update!(issues_access_level: issues_access_level)
- end
-
- context 'when issues are enabled for everyone' do
- let(:issues_access_level) { ProjectFeature::ENABLED }
-
- it 'creates a comment' do
- expect { receiver.execute }.to change { noteable.notes.count }.by(1)
- end
-
- context 'when quick actions are present' do
- it 'encloses quick actions with code span markdown' do
- receiver.execute
- noteable.reload
-
- note = Note.last
- expect(note.note).to include("Jake out\n\n`/close`\n`/title test`")
- expect(noteable.title).to eq('service desk issue')
- expect(noteable).to be_opened
- end
- end
- end
-
- context 'when issues are protected members only' do
- let(:issues_access_level) { ProjectFeature::PRIVATE }
-
- it 'creates a comment' do
- expect { receiver.execute }.to change { noteable.notes.count }.by(1)
- end
- end
-
- context 'when issues are disabled' do
- let(:issues_access_level) { ProjectFeature::DISABLED }
-
- it 'does not create a comment' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError)
- end
- end
- end
-
- context 'is disabled' do
- before do
- allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(false)
- allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(false)
- end
-
- it 'does not create a comment' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
- end
- end
- end
end
diff --git a/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb
new file mode 100644
index 00000000000..94f28d3399a
--- /dev/null
+++ b/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Email::Handler::CreateNoteOnIssuableHandler do
+ include_context :email_shared_context
+
+ let_it_be(:user) { create(:user, email: 'jake@adventuretime.ooo', incoming_email_token: 'auth_token') }
+ let_it_be(:namespace) { create(:namespace, path: 'gitlabhq') }
+ let_it_be(:project) { create(:project, :public, namespace: namespace, path: 'gitlabhq') }
+
+ let!(:noteable) { create(:issue, project: project) }
+ let(:email_raw) { email_fixture('emails/valid_note_on_issuable.eml') }
+
+ before do
+ stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo")
+ stub_config_setting(host: 'localhost')
+ end
+
+ it_behaves_like :reply_processing_shared_examples
+
+ it_behaves_like :note_handler_shared_examples, true do
+ let_it_be(:recipient) { user }
+
+ let(:update_commands_only) { email_reply_fixture('emails/update_commands_only_reply.eml') }
+ let(:no_content) { email_reply_fixture('emails/no_content_reply.eml') }
+ let(:commands_in_reply) { email_reply_fixture('emails/commands_in_reply.eml') }
+ let(:with_quick_actions) { email_reply_fixture('emails/valid_reply_with_quick_actions.eml') }
+ end
+
+ context 'when the recipient address does not include a mail key' do
+ let(:mail_key) { 'gitlabhq-gitlabhq-project_id-auth_token-issue-issue_iid' }
+ let(:email_raw) { fixture_file('emails/valid_note_on_issuable.eml').gsub(mail_key, '') }
+
+ it 'raises an UnknownIncomingEmail' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail)
+ end
+ end
+
+ context 'when issue is confidential' do
+ before do
+ noteable.update_attribute(:confidential, true)
+ end
+
+ it_behaves_like :checks_permissions_on_noteable_examples
+ end
+
+ def email_fixture(path)
+ fixture_file(path)
+ .gsub('project_id', project.project_id.to_s)
+ .gsub('issue_iid', noteable.iid.to_s)
+ end
+
+ def email_reply_fixture(path)
+ reply_address = 'reply+59d8df8370b7e95c5a49fbf86aeb2c93'
+ note_address = "incoming+#{project.full_path_slug}-#{project.project_id}-#{user.incoming_email_token}-issue-#{noteable.iid}"
+
+ fixture_file(path)
+ .gsub(reply_address, note_address)
+ end
+end
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 32b451f8329..b1ffbedc7bf 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -191,16 +191,6 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
end
end
-
- context 'when service_desk_custom_address feature is disabled' do
- before do
- stub_feature_flags(service_desk_custom_address: false)
- end
-
- it 'bounces the email' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
- end
- end
end
end
diff --git a/spec/lib/gitlab/email/handler_spec.rb b/spec/lib/gitlab/email/handler_spec.rb
index 2cd8c31e6b2..eff6fb63a5f 100644
--- a/spec/lib/gitlab/email/handler_spec.rb
+++ b/spec/lib/gitlab/email/handler_spec.rb
@@ -60,8 +60,9 @@ RSpec.describe Gitlab::Email::Handler do
describe 'regexps are set properly' do
let(:addresses) do
- %W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX} sent_notification_key path-to-project-123-user_email_token-merge-request) +
- %W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY} sent_notification_key path-to-project-123-user_email_token-issue) +
+ %W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX} sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY}) +
+ %w(sent_notification_key path-to-project-123-user_email_token-merge-request) +
+ %w(path-to-project-123-user_email_token-issue path-to-project-123-user_email_token-issue-123) +
%w(path/to/project+user_email_token path/to/project+merge-request+user_email_token some/project)
end
diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb
index 68a46b11487..764478ad1d7 100644
--- a/spec/lib/gitlab/error_tracking_spec.rb
+++ b/spec/lib/gitlab/error_tracking_spec.rb
@@ -236,7 +236,7 @@ RSpec.describe Gitlab::ErrorTracking do
context 'the exception implements :sentry_extra_data' do
let(:extra_info) { { event: 'explosion', size: :massive } }
- let(:exception) { double(message: 'bang!', sentry_extra_data: extra_info, backtrace: caller) }
+ let(:exception) { double(message: 'bang!', sentry_extra_data: extra_info, backtrace: caller, cause: nil) }
it 'includes the extra data from the exception in the tracking information' do
track_exception
@@ -247,7 +247,7 @@ RSpec.describe Gitlab::ErrorTracking do
end
context 'the exception implements :sentry_extra_data, which returns nil' do
- let(:exception) { double(message: 'bang!', sentry_extra_data: nil, backtrace: caller) }
+ let(:exception) { double(message: 'bang!', sentry_extra_data: nil, backtrace: caller, cause: nil) }
let(:extra) { { issue_url: issue_url } }
it 'just includes the other extra info' do
@@ -287,10 +287,23 @@ RSpec.describe Gitlab::ErrorTracking do
let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
it 'injects the normalized sql query into extra' do
+ allow(Raven.client.transport).to receive(:send_event) do |event|
+ expect(event.extra).to include(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ end
+
track_exception
+ end
+ end
- expect(Raven).to have_received(:capture_exception)
- .with(exception, a_hash_including(extra: a_hash_including(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')))
+ context 'when the `ActiveRecord::StatementInvalid` is wrapped in another exception' do
+ let(:exception) { RuntimeError.new(cause: ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1')) }
+
+ it 'injects the normalized sql query into extra' do
+ allow(Raven.client.transport).to receive(:send_event) do |event|
+ expect(event.extra).to include(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ end
+
+ track_exception
end
end
end
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
index 03cb89ee033..c47f71c207d 100644
--- a/spec/lib/gitlab/experimentation/controller_concern_spec.rb
+++ b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
@@ -156,6 +156,16 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
is_expected.to eq(true)
end
end
+
+ context 'Cookie parameter to force enable experiment' do
+ it 'returns true unconditionally' do
+ cookies[:force_experiment] = 'test_experiment,another_experiment'
+ get :index
+
+ expect(check_experiment(:test_experiment)).to eq(true)
+ expect(check_experiment(:another_experiment)).to eq(true)
+ end
+ end
end
describe '#track_experiment_event', :snowplow do
diff --git a/spec/lib/gitlab/experimentation/experiment_spec.rb b/spec/lib/gitlab/experimentation/experiment_spec.rb
index 7b1d1763010..008e6699597 100644
--- a/spec/lib/gitlab/experimentation/experiment_spec.rb
+++ b/spec/lib/gitlab/experimentation/experiment_spec.rb
@@ -14,8 +14,10 @@ RSpec.describe Gitlab::Experimentation::Experiment do
end
before do
- feature = double('FeatureFlag', percentage_of_time_value: percentage )
- expect(Feature).to receive(:get).with(:experiment_key_experiment_percentage).and_return(feature)
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+ feature = double('FeatureFlag', percentage_of_time_value: percentage, enabled?: true)
+ allow(Feature).to receive(:get).with(:experiment_key_experiment_percentage).and_return(feature)
end
subject(:experiment) { described_class.new(:experiment_key, **params) }
diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb
index a68c050d829..b503960b8c7 100644
--- a/spec/lib/gitlab/experimentation_spec.rb
+++ b/spec/lib/gitlab/experimentation_spec.rb
@@ -38,6 +38,8 @@ RSpec.describe Gitlab::Experimentation do
}
})
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
Feature.enable_percentage_of_time(:backwards_compatible_test_experiment_experiment_percentage, enabled_percentage)
Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
allow(Gitlab).to receive(:com?).and_return(true)
diff --git a/spec/lib/gitlab/faraday/error_callback_spec.rb b/spec/lib/gitlab/faraday/error_callback_spec.rb
new file mode 100644
index 00000000000..5da4b8adf6a
--- /dev/null
+++ b/spec/lib/gitlab/faraday/error_callback_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Faraday::ErrorCallback do
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app, {}) }
+
+ describe '#call' do
+ let(:env) { { url: 'http://target.url' } }
+
+ subject { middleware.call(env) }
+
+ context 'with no errors' do
+ before do
+ expect(app).to receive(:call).with(env).and_return('success')
+ end
+
+ it { is_expected.to eq('success') }
+ end
+
+ context 'with errors' do
+ before do
+ expect(app).to receive(:call).and_raise(ArgumentError, 'Kaboom!')
+ end
+
+ context 'with no callback' do
+ it 'uses the default callback' do
+ expect { subject }.to raise_error(ArgumentError, 'Kaboom!')
+ end
+ end
+
+ context 'with a custom callback' do
+ let(:options) { { callback: callback } }
+
+ it 'uses the custom callback' do
+ count = 0
+ target_url = nil
+ exception_class = nil
+
+ callback = proc do |env, exception|
+ count += 1
+ target_url = env[:url].to_s
+ exception_class = exception.class.name
+ end
+
+ options = { callback: callback }
+ middleware = described_class.new(app, options)
+
+ expect(callback).to receive(:call).and_call_original
+ expect { middleware.call(env) }.to raise_error(ArgumentError, 'Kaboom!')
+ expect(count).to eq(1)
+ expect(target_url).to eq('http://target.url')
+ expect(exception_class).to eq(ArgumentError.name)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/changed_path_spec.rb b/spec/lib/gitlab/git/changed_path_spec.rb
new file mode 100644
index 00000000000..93db107ad5c
--- /dev/null
+++ b/spec/lib/gitlab/git/changed_path_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Gitlab::Git::ChangedPath do
+ subject(:changed_path) { described_class.new(path: path, status: status) }
+
+ let(:path) { 'test_path' }
+
+ describe '#new_file?' do
+ subject(:new_file?) { changed_path.new_file? }
+
+ context 'when it is a new file' do
+ let(:status) { :ADDED }
+
+ it 'returns true' do
+ expect(new_file?).to eq(true)
+ end
+ end
+
+ context 'when it is not a new file' do
+ let(:status) { :MODIFIED }
+
+ it 'returns false' do
+ expect(new_file?).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index d4174a34433..783f0a9ccf7 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -58,7 +58,7 @@ EOT
context 'using a diff that is too large' do
it 'prunes the diff' do
- diff = described_class.new(diff: 'a' * 204800)
+ diff = described_class.new({ diff: 'a' * 204800 })
expect(diff.diff).to be_empty
expect(diff).to be_too_large
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index c917945499c..ef9b5a30c86 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -520,12 +520,13 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
forced: true,
no_tags: true,
timeout: described_class::GITLAB_PROJECTS_TIMEOUT,
- prune: false
+ prune: false,
+ check_tags_changed: false
}
expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts)
- repository.fetch_remote('remote-name', ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false)
+ repository.fetch_remote('remote-name', ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false, check_tags_changed: false)
end
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RepositoryService, :fetch_remote do
@@ -1191,25 +1192,25 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
let(:commit_3) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
let(:commit_1_files) do
[
- OpenStruct.new(status: :ADDED, path: "files/executables/ls"),
- OpenStruct.new(status: :ADDED, path: "files/executables/touch"),
- OpenStruct.new(status: :ADDED, path: "files/links/regex.rb"),
- OpenStruct.new(status: :ADDED, path: "files/links/ruby-style-guide.md"),
- OpenStruct.new(status: :ADDED, path: "files/links/touch"),
- OpenStruct.new(status: :MODIFIED, path: ".gitmodules"),
- OpenStruct.new(status: :ADDED, path: "deeper/nested/six"),
- OpenStruct.new(status: :ADDED, path: "nested/six")
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "files/executables/ls"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "files/executables/touch"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "files/links/regex.rb"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "files/links/ruby-style-guide.md"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "files/links/touch"),
+ Gitlab::Git::ChangedPath.new(status: :MODIFIED, path: ".gitmodules"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "deeper/nested/six"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "nested/six")
]
end
let(:commit_2_files) do
- [OpenStruct.new(status: :ADDED, path: "bin/executable")]
+ [Gitlab::Git::ChangedPath.new(status: :ADDED, path: "bin/executable")]
end
let(:commit_3_files) do
[
- OpenStruct.new(status: :MODIFIED, path: ".gitmodules"),
- OpenStruct.new(status: :ADDED, path: "gitlab-shell")
+ Gitlab::Git::ChangedPath.new(status: :MODIFIED, path: ".gitmodules"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "gitlab-shell")
]
end
@@ -1217,7 +1218,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
collection = repository.find_changed_paths([commit_1, commit_2, commit_3])
expect(collection).to be_a(Enumerable)
- expect(collection.to_a).to eq(commit_1_files + commit_2_files + commit_3_files)
+ expect(collection.as_json).to eq((commit_1_files + commit_2_files + commit_3_files).as_json)
end
it 'returns no paths when SHAs are invalid' do
@@ -1231,7 +1232,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
collection = repository.find_changed_paths([nil, commit_1])
expect(collection).to be_a(Enumerable)
- expect(collection.to_a).to eq(commit_1_files)
+ expect(collection.as_json).to eq(commit_1_files.as_json)
end
it 'returns no paths when the commits are nil' do
diff --git a/spec/lib/gitlab/git/wiki_page_version_spec.rb b/spec/lib/gitlab/git/wiki_page_version_spec.rb
new file mode 100644
index 00000000000..836fa2449ec
--- /dev/null
+++ b/spec/lib/gitlab/git/wiki_page_version_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Git::WikiPageVersion do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let(:user) { create(:user, username: 'someone') }
+
+ describe '#author_url' do
+ subject(:author_url) { described_class.new(commit, nil).author_url }
+
+ context 'user exists in gitlab' do
+ let(:commit) { create(:commit, project: project, author: user) }
+
+ it 'returns the profile link of the user' do
+ expect(author_url).to eq('http://localhost/someone')
+ end
+ end
+
+ context 'user does not exist in gitlab' do
+ let(:commit) { create(:commit, project: project, author_email: "someone@somewebsite.com") }
+
+ it 'returns a mailto: url' do
+ expect(author_url).to eq('mailto:someone@somewebsite.com')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb
index f5d8758a78a..777c94035d4 100644
--- a/spec/lib/gitlab/git_access_snippet_spec.rb
+++ b/spec/lib/gitlab/git_access_snippet_spec.rb
@@ -29,8 +29,17 @@ RSpec.describe Gitlab::GitAccessSnippet do
let(:actor) { build(:deploy_key) }
it 'does not allow push and pull access' do
- expect { push_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:authentication_mechanism])
- expect { pull_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:authentication_mechanism])
+ expect { push_access_check }.to raise_forbidden(:authentication_mechanism)
+ expect { pull_access_check }.to raise_forbidden(:authentication_mechanism)
+ end
+ end
+
+ describe 'when snippet repository is read-only' do
+ it 'does not allow push and allows pull access' do
+ allow(snippet).to receive(:repository_read_only?).and_return(true)
+
+ expect { push_access_check }.to raise_forbidden(:read_only)
+ expect { pull_access_check }.not_to raise_error
end
end
@@ -58,7 +67,7 @@ RSpec.describe Gitlab::GitAccessSnippet do
let(:snippet) { nil }
it 'blocks access with "not found"' do
- expect { pull_access_check }.to raise_snippet_not_found
+ expect { pull_access_check }.to raise_not_found(:snippet_not_found)
end
end
@@ -66,7 +75,7 @@ RSpec.describe Gitlab::GitAccessSnippet do
let(:snippet) { build_stubbed(:personal_snippet) }
it 'blocks access with "not found"' do
- expect { pull_access_check }.to raise_snippet_not_found
+ expect { pull_access_check }.to raise_not_found(:no_repo)
end
end
end
@@ -81,8 +90,8 @@ RSpec.describe Gitlab::GitAccessSnippet do
it 'blocks access when the user did not accept terms' do
message = /must accept the Terms of Service in order to perform this action/
- expect { push_access_check }.to raise_forbidden(message)
- expect { pull_access_check }.to raise_forbidden(message)
+ expect { push_access_check }.to raise_forbidden_with_message(message)
+ expect { pull_access_check }.to raise_forbidden_with_message(message)
end
it 'allows access when the user accepted the terms' do
@@ -149,8 +158,8 @@ RSpec.describe Gitlab::GitAccessSnippet do
let(:membership) { membership }
it 'respects accessibility' do
- expect { push_access_check }.to raise_snippet_not_found
- expect { pull_access_check }.to raise_snippet_not_found
+ expect { push_access_check }.to raise_not_found(:project_not_found)
+ expect { pull_access_check }.to raise_not_found(:project_not_found)
end
end
end
@@ -172,7 +181,7 @@ RSpec.describe Gitlab::GitAccessSnippet do
end
end
- [:guest, :reporter, :maintainer, :author, :admin].each do |membership|
+ [:guest, :reporter, :maintainer, :author].each do |membership|
context membership.to_s do
let(:membership) { membership }
@@ -183,6 +192,24 @@ RSpec.describe Gitlab::GitAccessSnippet do
end
end
+ context 'admin' do
+ let(:membership) { :admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'cannot perform git pushes' do
+ expect { push_access_check }.to raise_error(described_class::ForbiddenError)
+ expect { pull_access_check }.not_to raise_error
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'cannot perform git operations' do
+ expect { push_access_check }.to raise_error(described_class::ForbiddenError)
+ expect { pull_access_check }.to raise_error(described_class::ForbiddenError)
+ end
+ end
+ end
+
it_behaves_like 'actor is migration bot'
end
@@ -255,7 +282,7 @@ RSpec.describe Gitlab::GitAccessSnippet do
allow(check).to receive(:validate!).and_raise(Gitlab::GitAccess::ForbiddenError, 'foo')
end
- expect { push_access_check }.to raise_forbidden('foo')
+ expect { push_access_check }.to raise_forbidden_with_message('foo')
end
it 'sets the file count limit from Snippet class' do
@@ -372,17 +399,49 @@ RSpec.describe Gitlab::GitAccessSnippet do
end
end
+ describe 'HEAD realignment' do
+ let_it_be(:snippet) { create(:project_snippet, :private, :repository, project: project) }
+
+ shared_examples 'HEAD is updated to the snippet default branch' do
+ let(:actor) { snippet.author }
+
+ specify do
+ expect(snippet).to receive(:change_head_to_default_branch).and_call_original
+
+ subject
+ end
+
+ context 'when an error is raised' do
+ let(:actor) { nil }
+
+ it 'does not realign HEAD' do
+ expect(snippet).not_to receive(:change_head_to_default_branch).and_call_original
+
+ expect { subject }.to raise_error(described_class::ForbiddenError)
+ end
+ end
+ end
+
+ it_behaves_like 'HEAD is updated to the snippet default branch' do
+ subject { push_access_check }
+ end
+
+ it_behaves_like 'HEAD is updated to the snippet default branch' do
+ subject { pull_access_check }
+ end
+ end
+
private
- def raise_snippet_not_found
- raise_error(Gitlab::GitAccess::NotFoundError, Gitlab::GitAccess::ERROR_MESSAGES[:snippet_not_found])
+ def raise_not_found(message_key)
+ raise_error(described_class::NotFoundError, described_class.error_message(message_key))
end
- def raise_project_not_found
- raise_error(Gitlab::GitAccess::NotFoundError, Gitlab::GitAccess::ERROR_MESSAGES[:project_not_found])
+ def raise_forbidden(message_key)
+ raise_error(Gitlab::GitAccess::ForbiddenError, described_class.error_message(message_key))
end
- def raise_forbidden(message)
+ def raise_forbidden_with_message(message)
raise_error(Gitlab::GitAccess::ForbiddenError, message)
end
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 780f4329bcc..a0cafe3d763 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GitAccess do
include TermsHelper
include GitHelpers
+ include AdminModeHelper
let(:user) { create(:user) }
@@ -769,19 +770,39 @@ RSpec.describe Gitlab::GitAccess do
describe 'admin user' do
let(:user) { create(:admin) }
- context 'when member of the project' do
- before do
- project.add_reporter(user)
+ context 'when admin mode enabled', :enable_admin_mode do
+ context 'when member of the project' do
+ before do
+ project.add_reporter(user)
+ end
+
+ context 'pull code' do
+ it { expect { pull_access_check }.not_to raise_error }
+ end
end
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
+ context 'when is not member of the project' do
+ context 'pull code' do
+ it { expect { pull_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:download]) }
+ end
end
end
- context 'when is not member of the project' do
- context 'pull code' do
- it { expect { pull_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:download]) }
+ context 'when admin mode disabled' do
+ context 'when member of the project' do
+ before do
+ project.add_reporter(user)
+ end
+
+ context 'pull code' do
+ it { expect { pull_access_check }.not_to raise_error }
+ end
+ end
+
+ context 'when is not member of the project' do
+ context 'pull code' do
+ it { expect { pull_access_check }.to raise_not_found }
+ end
end
end
end
@@ -870,8 +891,13 @@ RSpec.describe Gitlab::GitAccess do
# Expectations are given a custom failure message proc so that it's
# easier to identify which check(s) failed.
it "has the correct permissions for #{role}s" do
- if role == :admin
+ if role == :admin_without_admin_mode
+ skip("All admins are allowed to perform actions https://gitlab.com/gitlab-org/gitlab/-/issues/296509")
+ end
+
+ if [:admin_with_admin_mode, :admin_without_admin_mode].include?(role)
user.update_attribute(:admin, true)
+ enable_admin_mode!(user) if role == :admin_with_admin_mode
project.add_guest(user)
else
project.add_role(user, role)
@@ -897,7 +923,7 @@ RSpec.describe Gitlab::GitAccess do
end
permissions_matrix = {
- admin: {
+ admin_with_admin_mode: {
any: true,
push_new_branch: true,
push_master: true,
@@ -909,6 +935,18 @@ RSpec.describe Gitlab::GitAccess do
merge_into_protected_branch: true
},
+ admin_without_admin_mode: {
+ any: false,
+ push_new_branch: false,
+ push_master: false,
+ push_protected_branch: false,
+ push_remove_protected_branch: false,
+ push_tag: false,
+ push_new_tag: false,
+ push_all: false,
+ merge_into_protected_branch: false
+ },
+
maintainer: {
any: true,
push_new_branch: true,
@@ -1009,7 +1047,7 @@ RSpec.describe Gitlab::GitAccess do
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
maintainer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
- admin: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false }))
+ admin_with_admin_mode: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false }))
end
end
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index 157c2393ce1..ac4c42d57ee 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -162,11 +162,9 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
.with(request, kind_of(Hash)).and_return([changed_paths_response])
returned_value = described_class.new(repository).find_changed_paths(commits)
+ mapped_expected_value = changed_paths_response.paths.map { |path| Gitlab::Git::ChangedPath.new(status: path.status, path: path.path) }
- mapped_returned_value = returned_value.map(&:to_h)
- mapped_expected_value = changed_paths_response.paths.map(&:to_h)
-
- expect(mapped_returned_value).to eq(mapped_expected_value)
+ expect(returned_value.as_json).to eq(mapped_expected_value.as_json)
end
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index f810a5c15a5..7a382df1248 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -131,7 +131,8 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
known_hosts: '',
force: false,
no_tags: false,
- no_prune: false
+ no_prune: false,
+ check_tags_changed: false
)
expect_any_instance_of(Gitaly::RepositoryService::Stub)
@@ -139,7 +140,7 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
.with(expected_request, kind_of(Hash))
.and_return(double(value: true))
- client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1)
+ client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false)
end
context 'SSH auth' do
diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
index 180c6d9e420..3839303b881 100644
--- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
@@ -205,7 +205,7 @@ RSpec.describe Gitlab::GithubImport::Importer::RepositoryImporter do
.with(project.import_url, refmap: Gitlab::GithubImport.refmap, forced: true, remote_name: 'github')
service = double
- expect(Projects::HousekeepingService)
+ expect(Repositories::HousekeepingService)
.to receive(:new).with(project, :gc).and_return(service)
expect(service).to receive(:execute)
diff --git a/spec/lib/gitlab/gitpod_spec.rb b/spec/lib/gitlab/gitpod_spec.rb
deleted file mode 100644
index 717e396f942..00000000000
--- a/spec/lib/gitlab/gitpod_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Gitpod do
- let_it_be(:user) { create(:user) }
-
- before do
- stub_feature_flags(gitpod: feature_scope)
- end
-
- describe '.feature_available?' do
- subject { described_class.feature_available? }
-
- context 'when feature has not been set' do
- let(:feature_scope) { nil }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is disabled' do
- let(:feature_scope) { false }
-
- it { is_expected.to be_falsey }
- end
-
- context 'when feature is enabled globally' do
- let(:feature_scope) { true }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is enabled only to a resource' do
- let(:feature_scope) { user }
-
- it { is_expected.to be_truthy }
- end
- end
-
- describe '.feature_enabled?' do
- let(:current_user) { nil }
-
- subject { described_class.feature_enabled?(current_user) }
-
- context 'when feature has not been set' do
- let(:feature_scope) { nil }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is enabled globally' do
- let(:feature_scope) { true }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is enabled only to a resource' do
- let(:feature_scope) { user }
-
- context 'for the same resource' do
- let(:current_user) { user }
-
- it { is_expected.to be_truthy }
- end
-
- context 'for a different resource' do
- let(:current_user) { create(:user) }
-
- it { is_expected.to be_falsey }
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/batch_key_spec.rb b/spec/lib/gitlab/graphql/batch_key_spec.rb
new file mode 100644
index 00000000000..881fba5c1be
--- /dev/null
+++ b/spec/lib/gitlab/graphql/batch_key_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'test_prof/recipes/rspec/let_it_be'
+
+RSpec.describe ::Gitlab::Graphql::BatchKey do
+ let_it_be(:rect) { Struct.new(:len, :width) }
+ let_it_be(:circle) { Struct.new(:radius) }
+ let(:lookahead) { nil }
+ let(:object) { rect.new(2, 3) }
+
+ subject { described_class.new(object, lookahead, object_name: :rect) }
+
+ it 'is equal to keys of the same object, regardless of lookahead or object name' do
+ expect(subject).to eq(described_class.new(rect.new(2, 3)))
+ expect(subject).to eq(described_class.new(rect.new(2, 3), :anything))
+ expect(subject).to eq(described_class.new(rect.new(2, 3), lookahead, object_name: :does_not_matter))
+ expect(subject).not_to eq(described_class.new(rect.new(2, 4)))
+ expect(subject).not_to eq(described_class.new(circle.new(10)))
+ end
+
+ it 'delegates attribute lookup methods to the inner object' do
+ other = rect.new(2, 3)
+
+ expect(subject.hash).to eq(other.hash)
+ expect(subject.len).to eq(other.len)
+ expect(subject.width).to eq(other.width)
+ end
+
+ it 'allows the object to be named more meaningfully' do
+ expect(subject.object).to eq(object)
+ expect(subject.object).to eq(subject.rect)
+ end
+
+ it 'works as a hash key' do
+ h = { subject => :foo }
+
+ expect(h[described_class.new(object)]).to eq(:foo)
+ end
+
+ describe '#requires?' do
+ it 'returns false if the lookahead was not provided' do
+ expect(subject.requires?([:foo])).to be(false)
+ end
+
+ context 'lookahead was provided' do
+ let(:lookahead) { double(:Lookahead) }
+
+ before do
+ allow(lookahead).to receive(:selection).with(Symbol).and_return(lookahead)
+ end
+
+ it 'returns false if the path is empty' do
+ expect(subject.requires?([])).to be(false)
+ end
+
+ context 'it selects the field' do
+ before do
+ allow(lookahead).to receive(:selects?).with(Symbol).once.and_return(true)
+ end
+
+ it 'returns true' do
+ expect(subject.requires?(%i[foo bar baz])).to be(true)
+ end
+ end
+
+ context 'it does not select the field' do
+ before do
+ allow(lookahead).to receive(:selects?).with(Symbol).once.and_return(false)
+ end
+
+ it 'returns false' do
+ expect(subject.requires?(%i[foo bar baz])).to be(false)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index 0ac54a20fcc..02e67488d3f 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -21,6 +21,47 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
Gitlab::Json.parse(Base64Bp.urlsafe_decode64(cursor))
end
+ # see: https://gitlab.com/gitlab-org/gitlab/-/issues/297358
+ context 'the relation has been preloaded' do
+ let(:projects) { Project.all.preload(:issues) }
+ let(:nodes) { projects.first.issues }
+
+ before do
+ project = create(:project)
+ create_list(:issue, 3, project: project)
+ end
+
+ it 'is loaded' do
+ expect(nodes).to be_loaded
+ end
+
+ it 'does not error when accessing pagination information' do
+ connection.first = 2
+
+ expect(connection).to have_attributes(
+ has_previous_page: false,
+ has_next_page: true
+ )
+ end
+
+ it 'can generate cursors' do
+ connection.send(:ordered_items) # necessary to generate the order-list
+
+ expect(connection.cursor_for(nodes.first)).to be_a(String)
+ end
+
+ it 'can read the next page' do
+ connection.send(:ordered_items) # necessary to generate the order-list
+ ordered = nodes.reorder(id: :desc)
+ next_page = described_class.new(nodes,
+ context: context,
+ max_page_size: 3,
+ after: connection.cursor_for(ordered.second))
+
+ expect(next_page.sliced_nodes).to contain_exactly(ordered.third)
+ end
+ end
+
it_behaves_like 'a connection with collection methods'
it_behaves_like 'a redactable connection' do
diff --git a/spec/lib/gitlab/graphql/queries_spec.rb b/spec/lib/gitlab/graphql/queries_spec.rb
new file mode 100644
index 00000000000..6e08a87523f
--- /dev/null
+++ b/spec/lib/gitlab/graphql/queries_spec.rb
@@ -0,0 +1,343 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require "test_prof/recipes/rspec/let_it_be"
+
+RSpec.describe Gitlab::Graphql::Queries do
+ shared_examples 'a valid GraphQL query for the blog schema' do
+ it 'is valid' do
+ expect(subject.validate(schema).second).to be_empty
+ end
+ end
+
+ shared_examples 'an invalid GraphQL query for the blog schema' do
+ it 'is invalid' do
+ expect(subject.validate(schema).second).to match errors
+ end
+ end
+
+ # Toy schema to validate queries against
+ let_it_be(:schema) do
+ author = Class.new(GraphQL::Schema::Object) do
+ graphql_name 'Author'
+ field :name, GraphQL::STRING_TYPE, null: true
+ field :handle, GraphQL::STRING_TYPE, null: false
+ field :verified, GraphQL::BOOLEAN_TYPE, null: false
+ end
+
+ post = Class.new(GraphQL::Schema::Object) do
+ graphql_name 'Post'
+ field :name, GraphQL::STRING_TYPE, null: false
+ field :title, GraphQL::STRING_TYPE, null: false
+ field :content, GraphQL::STRING_TYPE, null: true
+ field :author, author, null: false
+ end
+ author.field :posts, [post], null: false do
+ argument :blog_title, GraphQL::STRING_TYPE, required: false
+ end
+
+ blog = Class.new(GraphQL::Schema::Object) do
+ graphql_name 'Blog'
+ field :title, GraphQL::STRING_TYPE, null: false
+ field :description, GraphQL::STRING_TYPE, null: false
+ field :main_author, author, null: false
+ field :posts, [post], null: false
+ field :post, post, null: true do
+ argument :slug, GraphQL::STRING_TYPE, required: true
+ end
+ end
+
+ Class.new(GraphQL::Schema) do
+ query(Class.new(GraphQL::Schema::Object) do
+ graphql_name 'Query'
+ field :blog, blog, null: true do
+ argument :title, GraphQL::STRING_TYPE, required: true
+ end
+ field :post, post, null: true do
+ argument :slug, GraphQL::STRING_TYPE, required: true
+ end
+ end)
+ end
+ end
+
+ let(:root) do
+ Rails.root / 'fixtures/lib/gitlab/graphql/queries'
+ end
+
+ describe Gitlab::Graphql::Queries::Fragments do
+ subject { described_class.new(root) }
+
+ it 'has the right home' do
+ expect(subject.home).to eq (root / 'app/assets/javascripts').to_s
+ end
+
+ it 'has the right EE home' do
+ expect(subject.home_ee).to eq (root / 'ee/app/assets/javascripts').to_s
+ end
+
+ it 'caches query definitions' do
+ fragment = subject.get('foo')
+
+ expect(fragment).to be_a(::Gitlab::Graphql::Queries::Definition)
+ expect(subject.get('foo')).to be fragment
+ end
+ end
+
+ describe '.all' do
+ it 'is the combination of finding queries in CE and EE' do
+ expect(described_class)
+ .to receive(:find).with(Rails.root / 'app/assets/javascripts').and_return([:ce])
+ expect(described_class)
+ .to receive(:find).with(Rails.root / 'ee/app/assets/javascripts').and_return([:ee])
+
+ expect(described_class.all).to eq([:ce, :ee])
+ end
+ end
+
+ describe '.find' do
+ def definition_of(path)
+ be_a(::Gitlab::Graphql::Queries::Definition)
+ .and(have_attributes(file: path.to_s))
+ end
+
+ it 'find a single specific file' do
+ path = root / 'post_by_slug.graphql'
+
+ expect(described_class.find(path)).to contain_exactly(definition_of(path))
+ end
+
+ it 'ignores files that do not exist' do
+ path = root / 'not_there.graphql'
+
+ expect(described_class.find(path)).to be_empty
+ end
+
+ it 'ignores fragments' do
+ path = root / 'author.fragment.graphql'
+
+ expect(described_class.find(path)).to be_empty
+ end
+
+ it 'ignores typedefs' do
+ path = root / 'typedefs.graphql'
+
+ expect(described_class.find(path)).to be_empty
+ end
+
+ it 'finds all query definitions under a root directory' do
+ found = described_class.find(root)
+
+ expect(found).to include(
+ definition_of(root / 'post_by_slug.graphql'),
+ definition_of(root / 'post_by_slug.with_import.graphql'),
+ definition_of(root / 'post_by_slug.with_import.misspelled.graphql'),
+ definition_of(root / 'duplicate_imports.graphql'),
+ definition_of(root / 'deeply/nested/query.graphql')
+ )
+
+ expect(found).not_to include(
+ definition_of(root / 'typedefs.graphql'),
+ definition_of(root / 'author.fragment.graphql')
+ )
+ end
+ end
+
+ describe Gitlab::Graphql::Queries::Definition do
+ let(:fragments) { Gitlab::Graphql::Queries::Fragments.new(root, '.') }
+
+ subject { described_class.new(root / path, fragments) }
+
+ context 'a simple query' do
+ let(:path) { 'post_by_slug.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a query with an import' do
+ let(:path) { 'post_by_slug.with_import.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a query with duplicate imports' do
+ let(:path) { 'duplicate_imports.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a query importing from ee_else_ce' do
+ let(:path) { 'ee_else_ce.import.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+
+ it 'can resolve the ee fields' do
+ expect(subject.text(mode: :ce)).not_to include('verified')
+ expect(subject.text(mode: :ee)).to include('verified')
+ end
+ end
+
+ context 'a query refering to parent directories' do
+ let(:path) { 'deeply/nested/query.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a query refering to parent directories, incorrectly' do
+ let(:path) { 'deeply/nested/bad_import.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ be_a(::Gitlab::Graphql::Queries::FileNotFound)
+ .and(have_attributes(message: include('deeply/author.fragment.graphql')))
+ )
+ end
+ end
+ end
+
+ context 'a query with a broken import' do
+ let(:path) { 'post_by_slug.with_import.misspelled.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ be_a(::Gitlab::Graphql::Queries::FileNotFound)
+ .and(have_attributes(message: include('auther.fragment.graphql')))
+ )
+ end
+ end
+ end
+
+ context 'a query which imports a file with a broken import' do
+ let(:path) { 'transitive_bad_import.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ be_a(::Gitlab::Graphql::Queries::FileNotFound)
+ .and(have_attributes(message: include('does-not-exist.graphql')))
+ )
+ end
+ end
+ end
+
+ context 'a query containing a client directive' do
+ let(:path) { 'client.query.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+
+ it 'is tagged as a client query' do
+ expect(subject.validate(schema).first).to eq :client_query
+ end
+ end
+
+ context 'a mixed client query, valid' do
+ let(:path) { 'mixed_client.query.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+
+ it 'is not tagged as a client query' do
+ expect(subject.validate(schema).first).not_to eq :client_query
+ end
+ end
+
+ context 'a mixed client query, with skipped argument' do
+ let(:path) { 'mixed_client_skipped_argument.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a mixed client query, with unused fragment' do
+ let(:path) { 'mixed_client_unused_fragment.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a client query, with unused fragment' do
+ let(:path) { 'client_unused_fragment.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+
+ it 'is tagged as a client query' do
+ expect(subject.validate(schema).first).to eq :client_query
+ end
+ end
+
+ context 'a mixed client query, invalid' do
+ let(:path) { 'mixed_client_invalid.query.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(have_attributes(message: include('titlz')))
+ end
+ end
+ end
+
+ context 'a query containing a connection directive' do
+ let(:path) { 'connection.query.graphql' }
+
+ it_behaves_like 'a valid GraphQL query for the blog schema'
+ end
+
+ context 'a query which mentions an incorrect field' do
+ let(:path) { 'wrong_field.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ have_attributes(message: /'createdAt' doesn't exist/),
+ have_attributes(message: /'categories' doesn't exist/)
+ )
+ end
+ end
+ end
+
+ context 'a query which has a missing argument' do
+ let(:path) { 'missing_argument.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ have_attributes(message: include('blog'))
+ )
+ end
+ end
+ end
+
+ context 'a query which has a bad argument' do
+ let(:path) { 'bad_argument.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ have_attributes(message: include('Nullability mismatch on variable $bad'))
+ )
+ end
+ end
+ end
+
+ context 'a query which has a syntax error' do
+ let(:path) { 'syntax-error.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ have_attributes(message: include('Parse error'))
+ )
+ end
+ end
+ end
+
+ context 'a query which has an unused import' do
+ let(:path) { 'unused_import.graphql' }
+
+ it_behaves_like 'an invalid GraphQL query for the blog schema' do
+ let(:errors) do
+ contain_exactly(
+ have_attributes(message: include('AuthorF was defined, but not used'))
+ )
+ end
+ 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 fba32ae0673..825513bdfc5 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -87,6 +87,7 @@ label:
- merge_requests
- priorities
- epic_board_labels
+- epic_lists
milestone:
- group
- project
@@ -524,7 +525,6 @@ project:
- designs
- project_aliases
- external_pull_requests
-- alerts_service
- grafana_integration
- remove_source_branch_after_merge
- deleting_user
@@ -560,6 +560,7 @@ project:
- alert_management_http_integrations
- exported_protected_branches
- incident_management_oncall_schedules
+- debian_distributions
award_emoji:
- awardable
- user
@@ -722,6 +723,7 @@ epic:
- user_mentions
- note_authors
- boards_epic_user_preferences
+- epic_board_positions
epic_issue:
- epic
- issue
diff --git a/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb b/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb
index 3f5661d4ca6..0092c69d0bb 100644
--- a/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb
+++ b/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb
@@ -12,7 +12,8 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
ingress: ingress,
egress: egress,
labels: labels,
- resource_version: resource_version
+ resource_version: resource_version,
+ annotations: annotations
)
end
@@ -20,7 +21,7 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
::Kubeclient::Resource.new(
apiVersion: Gitlab::Kubernetes::CiliumNetworkPolicy::API_VERSION,
kind: Gitlab::Kubernetes::CiliumNetworkPolicy::KIND,
- metadata: { name: name, namespace: namespace, resourceVersion: resource_version },
+ metadata: { name: name, namespace: namespace, resourceVersion: resource_version, annotations: annotations },
spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: egress },
description: description
)
@@ -34,6 +35,7 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
let(:description) { 'example-description' }
let(:partial_class_name) { described_class.name.split('::').last }
let(:resource_version) { 101 }
+ let(:annotations) { { 'app.gitlab.com/alert': 'true' } }
let(:ingress) do
[
{
@@ -64,6 +66,8 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
name: example-name
namespace: example-namespace
resourceVersion: 101
+ annotations:
+ app.gitlab.com/alert: "true"
spec:
endpointSelector:
matchLabels:
@@ -157,7 +161,7 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
description: description,
metadata: {
name: name, namespace: namespace, creationTimestamp: '2020-04-14T00:08:30Z',
- labels: { app: 'foo' }, resourceVersion: resource_version
+ labels: { app: 'foo' }, resourceVersion: resource_version, annotations: annotations
},
spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil, labels: nil }
)
@@ -168,7 +172,7 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
apiVersion: Gitlab::Kubernetes::CiliumNetworkPolicy::API_VERSION,
kind: Gitlab::Kubernetes::CiliumNetworkPolicy::KIND,
description: description,
- metadata: { name: name, namespace: namespace, resourceVersion: resource_version, labels: { app: 'foo' } },
+ metadata: { name: name, namespace: namespace, resourceVersion: resource_version, labels: { app: 'foo' }, annotations: annotations },
spec: { endpointSelector: endpoint_selector, ingress: ingress }
)
end
@@ -211,7 +215,7 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
{
apiVersion: Gitlab::Kubernetes::CiliumNetworkPolicy::API_VERSION,
kind: Gitlab::Kubernetes::CiliumNetworkPolicy::KIND,
- metadata: { name: name, namespace: namespace, resourceVersion: resource_version },
+ metadata: { name: name, namespace: namespace, resourceVersion: resource_version, annotations: annotations },
spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: egress },
description: description
}
@@ -248,5 +252,15 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
it { is_expected.to eq(resource) }
end
+
+ context 'without annotations' do
+ let(:annotations) { nil }
+
+ before do
+ resource[:metadata].delete(:annotations)
+ end
+
+ it { is_expected.to eq(resource) }
+ end
end
end
diff --git a/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb b/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb
index e80bb3dfb07..2e373613269 100644
--- a/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb
@@ -56,9 +56,10 @@ RSpec.describe Gitlab::Kubernetes::KubectlCmd do
describe '.delete_crds_from_group' do
it 'constructs string properly' do
- expected_command = 'kubectl api-resources -o name --api-group foo | xargs kubectl delete --ignore-not-found crd'
+ command = 'kubectl api-resources -o name --api-group foo | xargs -r kubectl delete --ignore-not-found crd'
+ command_with_retries = "for i in $(seq 1 3); do #{command} && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
- expect(described_class.delete_crds_from_group("foo")).to eq expected_command
+ expect(described_class.delete_crds_from_group("foo")).to eq command_with_retries
end
end
end
diff --git a/spec/lib/gitlab/kubernetes/pod_cmd_spec.rb b/spec/lib/gitlab/kubernetes/pod_cmd_spec.rb
new file mode 100644
index 00000000000..51bdbf64741
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/pod_cmd_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Kubernetes::PodCmd do
+ describe '.retry_command' do
+ it 'constructs string properly' do
+ command = 'my command'
+ command_with_retries = "for i in $(seq 1 3); do #{command} && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
+
+ expect(described_class.retry_command(command)).to eq command_with_retries
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
index 7f05f35c941..f751416f4ec 100644
--- a/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
@@ -7,15 +7,7 @@ RSpec.describe Gitlab::Metrics::Samplers::ActionCableSampler do
subject { described_class.new(action_cable: action_cable) }
- describe '#interval' do
- it 'samples every five seconds by default' do
- expect(subject.interval).to eq(5)
- end
-
- it 'samples at other intervals if requested' do
- expect(described_class.new(11).interval).to eq(11)
- end
- end
+ it_behaves_like 'metrics sampler', 'ACTION_CABLE_SAMPLER'
describe '#sample' do
let(:pool) { instance_double(Concurrent::ThreadPoolExecutor) }
diff --git a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
index b94d19ff227..9572e9f50be 100644
--- a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
@@ -5,15 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::Samplers::DatabaseSampler do
subject { described_class.new }
- describe '#interval' do
- it 'samples every five seconds by default' do
- expect(subject.interval).to eq(5)
- end
-
- it 'samples at other intervals if requested' do
- expect(described_class.new(11).interval).to eq(11)
- end
- end
+ it_behaves_like 'metrics sampler', 'DATABASE_SAMPLER'
describe '#sample' do
before do
diff --git a/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb
index 214649d3e7e..2013435a074 100644
--- a/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb
@@ -11,15 +11,7 @@ RSpec.describe Gitlab::Metrics::Samplers::PumaSampler do
allow(Gitlab::Metrics::NullMetric).to receive(:instance).and_return(null_metric)
end
- describe '#interval' do
- it 'samples every five seconds by default' do
- expect(subject.interval).to eq(5)
- end
-
- it 'samples at other intervals if requested' do
- expect(described_class.new(11).interval).to eq(11)
- end
- end
+ it_behaves_like 'metrics sampler', 'PUMA_SAMPLER'
describe '#sample' do
before do
diff --git a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
index eb6c83096b9..6f1e0480197 100644
--- a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
@@ -10,6 +10,8 @@ RSpec.describe Gitlab::Metrics::Samplers::RubySampler do
allow(Gitlab::Metrics::NullMetric).to receive(:instance).and_return(null_metric)
end
+ it_behaves_like 'metrics sampler', 'RUBY_SAMPLER'
+
describe '#initialize' do
it 'sets process_start_time_seconds' do
freeze_time do
@@ -18,16 +20,6 @@ RSpec.describe Gitlab::Metrics::Samplers::RubySampler do
end
end
- describe '#interval' do
- it 'samples every sixty seconds by default' do
- expect(subject.interval).to eq(60)
- end
-
- it 'samples at other intervals if requested' do
- expect(described_class.new(11).interval).to eq(11)
- end
- end
-
describe '#sample' do
it 'adds a metric containing the process resident memory bytes' do
expect(Gitlab::Metrics::System).to receive(:memory_usage_rss).and_return(9000)
diff --git a/spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb
index 19477589289..5dabafb7c0b 100644
--- a/spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb
@@ -5,15 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::Samplers::ThreadsSampler do
subject { described_class.new }
- describe '#interval' do
- it 'samples every five seconds by default' do
- expect(subject.interval).to eq(5)
- end
-
- it 'samples at other intervals if requested' do
- expect(described_class.new(11).interval).to eq(11)
- end
- end
+ it_behaves_like 'metrics sampler', 'THREADS_SAMPLER'
describe '#sample' do
before do
diff --git a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
index 9f2180c4170..7971a7cabd5 100644
--- a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::Samplers::UnicornSampler do
subject { described_class.new(1.second) }
+ it_behaves_like 'metrics sampler', 'UNICORN_SAMPLER'
+
describe '#sample' do
let(:unicorn) { Module.new }
let(:raindrops) { double('raindrops') }
diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb
index 720bd5d79b3..732aa553737 100644
--- a/spec/lib/gitlab/metrics/system_spec.rb
+++ b/spec/lib/gitlab/metrics/system_spec.rb
@@ -96,6 +96,25 @@ RSpec.describe Gitlab::Metrics::System do
expect(described_class.memory_usage_uss_pss).to eq(uss: 475136, pss: 515072)
end
end
+
+ describe '.summary' do
+ it 'contains a selection of the available fields' do
+ stub_const('RUBY_DESCRIPTION', 'ruby-3.0-patch1')
+ mock_existing_proc_file('/proc/self/status', proc_status)
+ mock_existing_proc_file('/proc/self/smaps_rollup', proc_smaps_rollup)
+
+ summary = described_class.summary
+
+ expect(summary[:version]).to eq('ruby-3.0-patch1')
+ expect(summary[:gc_stat].keys).to eq(GC.stat.keys)
+ expect(summary[:memory_rss]).to eq(2527232)
+ expect(summary[:memory_uss]).to eq(475136)
+ expect(summary[:memory_pss]).to eq(515072)
+ expect(summary[:time_cputime]).to be_a(Float)
+ expect(summary[:time_realtime]).to be_a(Float)
+ expect(summary[:time_monotonic]).to be_a(Float)
+ end
+ end
end
context 'when /proc files do not exist' do
@@ -128,6 +147,21 @@ RSpec.describe Gitlab::Metrics::System do
expect(described_class.max_open_file_descriptors).to eq(0)
end
end
+
+ describe '.summary' do
+ it 'returns only available fields' do
+ summary = described_class.summary
+
+ expect(summary[:version]).to be_a(String)
+ expect(summary[:gc_stat].keys).to eq(GC.stat.keys)
+ expect(summary[:memory_rss]).to eq(0)
+ expect(summary[:memory_uss]).to eq(0)
+ expect(summary[:memory_pss]).to eq(0)
+ expect(summary[:time_cputime]).to be_a(Float)
+ expect(summary[:time_realtime]).to be_a(Float)
+ expect(summary[:time_monotonic]).to be_a(Float)
+ end
+ end
end
describe '.cpu_time' do
diff --git a/spec/lib/gitlab/middleware/multipart/handler_for_jwt_params_spec.rb b/spec/lib/gitlab/middleware/multipart/handler_for_jwt_params_spec.rb
deleted file mode 100644
index 59ec743f6ca..00000000000
--- a/spec/lib/gitlab/middleware/multipart/handler_for_jwt_params_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Middleware::Multipart::HandlerForJWTParams do
- using RSpec::Parameterized::TableSyntax
-
- let_it_be(:env) { Rack::MockRequest.env_for('/', method: 'post', params: {}) }
- let_it_be(:message) { { 'rewritten_fields' => {} } }
-
- describe '#allowed_paths' do
- let_it_be(:expected_allowed_paths) do
- [
- Dir.tmpdir,
- ::FileUploader.root,
- ::Gitlab.config.uploads.storage_path,
- ::JobArtifactUploader.workhorse_upload_path,
- ::LfsObjectUploader.workhorse_upload_path,
- File.join(Rails.root, 'public/uploads/tmp')
- ]
- end
-
- let_it_be(:expected_with_packages_path) { expected_allowed_paths + [::Packages::PackageFileUploader.workhorse_upload_path] }
-
- subject { described_class.new(env, message).send(:allowed_paths) }
-
- where(:package_features_enabled, :object_storage_enabled, :direct_upload_enabled, :expected_paths) do
- false | false | true | :expected_allowed_paths
- false | false | false | :expected_allowed_paths
- false | true | true | :expected_allowed_paths
- false | true | false | :expected_allowed_paths
- true | false | true | :expected_with_packages_path
- true | false | false | :expected_with_packages_path
- true | true | true | :expected_allowed_paths
- true | true | false | :expected_with_packages_path
- end
-
- with_them do
- before do
- stub_config(packages: {
- enabled: package_features_enabled,
- object_store: {
- enabled: object_storage_enabled,
- direct_upload: direct_upload_enabled
- },
- storage_path: '/any/dir'
- })
- end
-
- it { is_expected.to eq(send(expected_paths)) }
- end
- end
-end
diff --git a/spec/lib/gitlab/middleware/multipart_spec.rb b/spec/lib/gitlab/middleware/multipart_spec.rb
new file mode 100644
index 00000000000..65ec3535271
--- /dev/null
+++ b/spec/lib/gitlab/middleware/multipart_spec.rb
@@ -0,0 +1,198 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Middleware::Multipart do
+ include MultipartHelpers
+
+ describe '#call' do
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app) }
+ let(:secret) { Gitlab::Workhorse.secret }
+ let(:issuer) { 'gitlab-workhorse' }
+
+ subject do
+ env = post_env(
+ rewritten_fields: rewritten_fields,
+ params: params,
+ secret: secret,
+ issuer: issuer
+ )
+ middleware.call(env)
+ end
+
+ context 'remote file mode' do
+ let(:mode) { :remote }
+
+ it_behaves_like 'handling all upload parameters conditions'
+
+ context 'and a path set' do
+ include_context 'with one temporary file for multipart'
+
+ let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
+ let(:params) { upload_parameters_for(key: 'file', mode: mode, filename: filename, remote_id: remote_id).merge('file.path' => '/should/not/be/read') }
+
+ it 'builds an UploadedFile' do
+ expect_uploaded_files(original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file))
+
+ subject
+ end
+ end
+ end
+
+ context 'local file mode' do
+ let(:mode) { :local }
+
+ it_behaves_like 'handling all upload parameters conditions'
+
+ context 'when file is' do
+ include_context 'with one temporary file for multipart'
+
+ let(:allowed_paths) { [Dir.tmpdir] }
+
+ before do
+ expect_next_instance_of(::Gitlab::Middleware::Multipart::Handler) do |handler|
+ expect(handler).to receive(:allowed_paths).and_return(allowed_paths)
+ end
+ end
+
+ context 'in allowed paths' do
+ let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
+ let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', mode: mode, filename: filename) }
+
+ it 'builds an UploadedFile' do
+ expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, size: uploaded_file.size, params_path: %w(file))
+
+ subject
+ end
+ end
+
+ context 'not in allowed paths' do
+ let(:allowed_paths) { [] }
+
+ let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
+ let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', mode: mode) }
+
+ it 'returns an error' do
+ result = subject
+
+ expect(result[0]).to eq(400)
+ expect(result[2]).to include('insecure path used')
+ end
+ end
+ end
+ end
+
+ context 'with dummy params in remote mode' do
+ let(:rewritten_fields) { { 'file' => 'should/not/be/read' } }
+ let(:params) { upload_parameters_for(key: 'file', mode: mode) }
+ let(:mode) { :remote }
+
+ context 'with an invalid secret' do
+ let(:secret) { 'INVALID_SECRET' }
+
+ it { expect { subject }.to raise_error(JWT::VerificationError) }
+ end
+
+ context 'with an invalid issuer' do
+ let(:issuer) { 'INVALID_ISSUER' }
+
+ it { expect { subject }.to raise_error(JWT::InvalidIssuerError) }
+ end
+
+ context 'with invalid rewritten field key' do
+ invalid_keys = [
+ '[file]',
+ ';file',
+ 'file]',
+ ';file]',
+ 'file]]',
+ 'file;;'
+ ]
+
+ invalid_keys.each do |invalid_key|
+ context invalid_key do
+ let(:rewritten_fields) { { invalid_key => 'should/not/be/read' } }
+
+ it { expect { subject }.to raise_error(RuntimeError, "invalid field: \"#{invalid_key}\"") }
+ end
+ end
+ end
+
+ context 'with an invalid upload key' do
+ include_context 'with one temporary file for multipart'
+
+ RSpec.shared_examples 'rejecting the invalid key' do |key_in_header:, key_in_upload_params:, error_message:|
+ let(:rewritten_fields) { rewritten_fields_hash(key_in_header => uploaded_filepath) }
+ let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: key_in_upload_params, mode: mode, filename: filename, remote_id: remote_id) }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(RuntimeError, error_message)
+ end
+ end
+
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: 'file',
+ key_in_upload_params: 'wrong_key',
+ error_message: 'Empty JWT param: file.gitlab-workhorse-upload'
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: 'user[avatar',
+ key_in_upload_params: 'user[avatar]',
+ error_message: 'invalid field: "user[avatar"'
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: '[user]avatar',
+ key_in_upload_params: 'user[avatar]',
+ error_message: 'invalid field: "[user]avatar"'
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: 'user[]avatar',
+ key_in_upload_params: 'user[avatar]',
+ error_message: 'invalid field: "user[]avatar"'
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: 'user[avatar[image[url]]]',
+ key_in_upload_params: 'user[avatar]',
+ error_message: 'invalid field: "user[avatar[image[url]]]"'
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: '[]',
+ key_in_upload_params: 'user[avatar]',
+ error_message: 'invalid field: "[]"'
+ it_behaves_like 'rejecting the invalid key',
+ key_in_header: 'x' * 11000,
+ key_in_upload_params: 'user[avatar]',
+ error_message: "invalid field: \"#{'x' * 11000}\""
+ end
+
+ context 'with a modified JWT payload' do
+ include_context 'with one temporary file for multipart'
+
+ let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
+ let(:crafted_payload) { Base64.urlsafe_encode64({ 'path' => 'test' }.to_json) }
+ let(:params) do
+ upload_parameters_for(filepath: uploaded_filepath, key: 'file', mode: mode, filename: filename, remote_id: remote_id).tap do |params|
+ header, _, sig = params['file.gitlab-workhorse-upload'].split('.')
+ params['file.gitlab-workhorse-upload'] = [header, crafted_payload, sig].join('.')
+ end
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(JWT::VerificationError, 'Signature verification raised')
+ end
+ end
+
+ context 'with a modified JWT sig' do
+ include_context 'with one temporary file for multipart'
+
+ let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
+ let(:params) do
+ upload_parameters_for(filepath: uploaded_filepath, key: 'file', mode: mode, filename: filename, remote_id: remote_id).tap do |params|
+ header, payload, sig = params['file.gitlab-workhorse-upload'].split('.')
+ params['file.gitlab-workhorse-upload'] = [header, payload, "#{sig}modified"].join('.')
+ end
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(JWT::VerificationError, 'Signature verification raised')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/middleware/multipart_with_handler_for_jwt_params_spec.rb b/spec/lib/gitlab/middleware/multipart_with_handler_for_jwt_params_spec.rb
deleted file mode 100644
index a1e9ac6e425..00000000000
--- a/spec/lib/gitlab/middleware/multipart_with_handler_for_jwt_params_spec.rb
+++ /dev/null
@@ -1,202 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Middleware::Multipart do
- include MultipartHelpers
-
- describe '#call' do
- let(:app) { double(:app) }
- let(:middleware) { described_class.new(app) }
- let(:secret) { Gitlab::Workhorse.secret }
- let(:issuer) { 'gitlab-workhorse' }
-
- subject do
- env = post_env(
- rewritten_fields: rewritten_fields,
- params: params,
- secret: secret,
- issuer: issuer
- )
- middleware.call(env)
- end
-
- before do
- stub_feature_flags(upload_middleware_jwt_params_handler: true)
- end
-
- context 'remote file mode' do
- let(:mode) { :remote }
-
- it_behaves_like 'handling all upload parameters conditions'
-
- context 'and a path set' do
- include_context 'with one temporary file for multipart'
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(key: 'file', filename: filename, remote_id: remote_id).merge('file.path' => '/should/not/be/read') }
-
- it 'builds an UploadedFile' do
- expect_uploaded_files(original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file))
-
- subject
- end
- end
- end
-
- context 'local file mode' do
- let(:mode) { :local }
-
- it_behaves_like 'handling all upload parameters conditions'
-
- context 'when file is' do
- include_context 'with one temporary file for multipart'
-
- let(:allowed_paths) { [Dir.tmpdir] }
-
- before do
- expect_next_instance_of(::Gitlab::Middleware::Multipart::HandlerForJWTParams) do |handler|
- expect(handler).to receive(:allowed_paths).and_return(allowed_paths)
- end
- end
-
- context 'in allowed paths' do
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', filename: filename) }
-
- it 'builds an UploadedFile' do
- expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, size: uploaded_file.size, params_path: %w(file))
-
- subject
- end
- end
-
- context 'not in allowed paths' do
- let(:allowed_paths) { [] }
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file') }
-
- it 'returns an error' do
- result = subject
-
- expect(result[0]).to eq(400)
- expect(result[2]).to include('insecure path used')
- end
- end
- end
- end
-
- context 'with dummy params in remote mode' do
- let(:rewritten_fields) { { 'file' => 'should/not/be/read' } }
- let(:params) { upload_parameters_for(key: 'file') }
- let(:mode) { :remote }
-
- context 'with an invalid secret' do
- let(:secret) { 'INVALID_SECRET' }
-
- it { expect { subject }.to raise_error(JWT::VerificationError) }
- end
-
- context 'with an invalid issuer' do
- let(:issuer) { 'INVALID_ISSUER' }
-
- it { expect { subject }.to raise_error(JWT::InvalidIssuerError) }
- end
-
- context 'with invalid rewritten field key' do
- invalid_keys = [
- '[file]',
- ';file',
- 'file]',
- ';file]',
- 'file]]',
- 'file;;'
- ]
-
- invalid_keys.each do |invalid_key|
- context invalid_key do
- let(:rewritten_fields) { { invalid_key => 'should/not/be/read' } }
-
- it { expect { subject }.to raise_error(RuntimeError, "invalid field: \"#{invalid_key}\"") }
- end
- end
- end
-
- context 'with an invalid upload key' do
- include_context 'with one temporary file for multipart'
-
- RSpec.shared_examples 'rejecting the invalid key' do |key_in_header:, key_in_upload_params:, error_message:|
- let(:rewritten_fields) { rewritten_fields_hash(key_in_header => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: key_in_upload_params, filename: filename, remote_id: remote_id) }
-
- it 'raises an error' do
- expect { subject }.to raise_error(RuntimeError, error_message)
- end
- end
-
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'file',
- key_in_upload_params: 'wrong_key',
- error_message: 'Empty JWT param: file.gitlab-workhorse-upload'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'user[avatar',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "user[avatar"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: '[user]avatar',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "[user]avatar"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'user[]avatar',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "user[]avatar"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'user[avatar[image[url]]]',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "user[avatar[image[url]]]"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: '[]',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "[]"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'x' * 11000,
- key_in_upload_params: 'user[avatar]',
- error_message: "invalid field: \"#{'x' * 11000}\""
- end
-
- context 'with a modified JWT payload' do
- include_context 'with one temporary file for multipart'
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:crafted_payload) { Base64.urlsafe_encode64({ 'path' => 'test' }.to_json) }
- let(:params) do
- upload_parameters_for(filepath: uploaded_filepath, key: 'file', filename: filename, remote_id: remote_id).tap do |params|
- header, _, sig = params['file.gitlab-workhorse-upload'].split('.')
- params['file.gitlab-workhorse-upload'] = [header, crafted_payload, sig].join('.')
- end
- end
-
- it 'raises an error' do
- expect { subject }.to raise_error(JWT::VerificationError, 'Signature verification raised')
- end
- end
-
- context 'with a modified JWT sig' do
- include_context 'with one temporary file for multipart'
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) do
- upload_parameters_for(filepath: uploaded_filepath, key: 'file', filename: filename, remote_id: remote_id).tap do |params|
- header, payload, sig = params['file.gitlab-workhorse-upload'].split('.')
- params['file.gitlab-workhorse-upload'] = [header, payload, "#{sig}modified"].join('.')
- end
- end
-
- it 'raises an error' do
- expect { subject }.to raise_error(JWT::VerificationError, 'Signature verification raised')
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/middleware/multipart_with_handler_spec.rb b/spec/lib/gitlab/middleware/multipart_with_handler_spec.rb
deleted file mode 100644
index 8c2af775574..00000000000
--- a/spec/lib/gitlab/middleware/multipart_with_handler_spec.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Middleware::Multipart do
- include MultipartHelpers
-
- describe '#call' do
- let(:app) { double(:app) }
- let(:middleware) { described_class.new(app) }
- let(:secret) { Gitlab::Workhorse.secret }
- let(:issuer) { 'gitlab-workhorse' }
-
- subject do
- env = post_env(
- rewritten_fields: rewritten_fields,
- params: params,
- secret: secret,
- issuer: issuer
- )
- middleware.call(env)
- end
-
- before do
- stub_feature_flags(upload_middleware_jwt_params_handler: false)
- end
-
- context 'remote file mode' do
- let(:mode) { :remote }
-
- it_behaves_like 'handling all upload parameters conditions'
-
- context 'and a path set' do
- include_context 'with one temporary file for multipart'
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(key: 'file', filename: filename, remote_id: remote_id).merge('file.path' => '/should/not/be/read') }
-
- it 'builds an UploadedFile' do
- expect_uploaded_files(original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file))
-
- subject
- end
- end
- end
-
- context 'local file mode' do
- let(:mode) { :local }
-
- it_behaves_like 'handling all upload parameters conditions'
-
- context 'when file is' do
- include_context 'with one temporary file for multipart'
-
- let(:allowed_paths) { [Dir.tmpdir] }
-
- before do
- expect_next_instance_of(::Gitlab::Middleware::Multipart::Handler) do |handler|
- expect(handler).to receive(:allowed_paths).and_return(allowed_paths)
- end
- end
-
- context 'in allowed paths' do
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', filename: filename) }
-
- it 'builds an UploadedFile' do
- expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, size: uploaded_file.size, params_path: %w(file))
-
- subject
- end
- end
-
- context 'not in allowed paths' do
- let(:allowed_paths) { [] }
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file') }
-
- it 'returns an error' do
- result = subject
-
- expect(result[0]).to eq(400)
- expect(result[2]).to include('insecure path used')
- end
- end
- end
- end
-
- context 'with dummy params in remote mode' do
- let(:rewritten_fields) { { 'file' => 'should/not/be/read' } }
- let(:params) { upload_parameters_for(key: 'file') }
- let(:mode) { :remote }
-
- context 'with an invalid secret' do
- let(:secret) { 'INVALID_SECRET' }
-
- it { expect { subject }.to raise_error(JWT::VerificationError) }
- end
-
- context 'with an invalid issuer' do
- let(:issuer) { 'INVALID_ISSUER' }
-
- it { expect { subject }.to raise_error(JWT::InvalidIssuerError) }
- end
-
- context 'with invalid rewritten field key' do
- invalid_keys = [
- '[file]',
- ';file',
- 'file]',
- ';file]',
- 'file]]',
- 'file;;'
- ]
-
- invalid_keys.each do |invalid_key|
- context invalid_key do
- let(:rewritten_fields) { { invalid_key => 'should/not/be/read' } }
-
- it { expect { subject }.to raise_error(RuntimeError, "invalid field: \"#{invalid_key}\"") }
- end
- end
- end
-
- context 'with invalid key in parameters' do
- include_context 'with one temporary file for multipart'
-
- let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'wrong_key', filename: filename, remote_id: remote_id) }
-
- it 'builds no UploadedFile' do
- expect(app).to receive(:call) do |env|
- received_params = get_params(env)
- expect(received_params['file']).to be_nil
- expect(received_params['wrong_key']).to be_nil
- end
-
- subject
- end
- end
-
- context 'with invalid key in header' do
- include_context 'with one temporary file for multipart'
-
- RSpec.shared_examples 'rejecting the invalid key' do |key_in_header:, key_in_upload_params:, error_message:|
- let(:rewritten_fields) { rewritten_fields_hash(key_in_header => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: key_in_upload_params, filename: filename, remote_id: remote_id) }
-
- it 'raises an error' do
- expect { subject }.to raise_error(RuntimeError, error_message)
- end
- end
-
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'user[avatar',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "user[avatar"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: '[user]avatar',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "[user]avatar"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'user[]avatar',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "user[]avatar"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'user[avatar[image[url]]]',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "user[avatar[image[url]]]"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: '[]',
- key_in_upload_params: 'user[avatar]',
- error_message: 'invalid field: "[]"'
- it_behaves_like 'rejecting the invalid key',
- key_in_header: 'x' * 11000,
- key_in_upload_params: 'user[avatar]',
- error_message: "invalid field: \"#{'x' * 11000}\""
- end
-
- context 'with key with unbalanced brackets in header' do
- include_context 'with one temporary file for multipart'
-
- let(:invalid_key) { 'user[avatar' }
- let(:rewritten_fields) { rewritten_fields_hash( invalid_key => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'user[avatar]', filename: filename, remote_id: remote_id) }
-
- it 'builds no UploadedFile' do
- expect(app).not_to receive(:call)
-
- expect { subject }.to raise_error(RuntimeError, "invalid field: \"#{invalid_key}\"")
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index 8e9f7e372c5..cd89674af0f 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -102,6 +102,7 @@ RSpec.describe Gitlab::PathRegex do
.concat(files_in_public)
.concat(Array(API::API.prefix.to_s))
.concat(sitemap_words)
+ .concat(deprecated_routes)
.compact
.uniq
end
@@ -110,6 +111,11 @@ RSpec.describe Gitlab::PathRegex do
%w(sitemap sitemap.xml sitemap.xml.gz)
end
+ let(:deprecated_routes) do
+ # profile was deprecated in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51646
+ %w(profile)
+ end
+
let(:ee_top_level_words) do
%w(unsubscribes v2)
end
diff --git a/spec/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled_spec.rb b/spec/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled_spec.rb
index bbc8b0d67e0..05cdc5bb79b 100644
--- a/spec/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled_spec.rb
+++ b/spec/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe Gitlab::PerformanceBar::RedisAdapterWhenPeekEnabled do
expect_to_obtain_exclusive_lease(GitlabPerformanceBarStatsWorker::LEASE_KEY, uuid)
expect(GitlabPerformanceBarStatsWorker).to receive(:perform_in).with(GitlabPerformanceBarStatsWorker::WORKER_DELAY, uuid)
expect(client).to receive(:sadd).with(GitlabPerformanceBarStatsWorker::STATS_KEY, uuid)
+ expect(client).to receive(:expire).with(GitlabPerformanceBarStatsWorker::STATS_KEY, GitlabPerformanceBarStatsWorker::STATS_KEY_EXPIRE)
peek_adapter.new(client).save('foo')
end
diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb
index 98bd2efdbc6..4eb13e63b46 100644
--- a/spec/lib/gitlab/project_template_spec.rb
+++ b/spec/lib/gitlab/project_template_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Gitlab::ProjectTemplate do
hexo sse_middleman gitpod_spring_petclinic nfhugo
nfjekyll nfplainhtml nfgitbook nfhexo salesforcedx
serverless_framework jsonnet cluster_management
+ kotlin_native_linux
]
expect(described_class.all).to be_an(Array)
diff --git a/spec/lib/gitlab/prometheus/internal_spec.rb b/spec/lib/gitlab/prometheus/internal_spec.rb
index 7771d85222a..b08b8813470 100644
--- a/spec/lib/gitlab/prometheus/internal_spec.rb
+++ b/spec/lib/gitlab/prometheus/internal_spec.rb
@@ -3,12 +3,12 @@
require 'spec_helper'
RSpec.describe Gitlab::Prometheus::Internal do
- let(:listen_address) { 'localhost:9090' }
+ let(:server_address) { 'localhost:9090' }
let(:prometheus_settings) do
{
- enable: true,
- listen_address: listen_address
+ enabled: true,
+ server_address: server_address
}
end
@@ -27,25 +27,25 @@ RSpec.describe Gitlab::Prometheus::Internal do
it_behaves_like 'returns valid uri', 'http://localhost:9090'
context 'with non default prometheus address' do
- let(:listen_address) { 'https://localhost:9090' }
+ let(:server_address) { 'https://localhost:9090' }
it_behaves_like 'returns valid uri', 'https://localhost:9090'
context 'with :9090 symbol' do
- let(:listen_address) { :':9090' }
+ let(:server_address) { :':9090' }
it_behaves_like 'returns valid uri', 'http://localhost:9090'
end
context 'with 0.0.0.0:9090' do
- let(:listen_address) { '0.0.0.0:9090' }
+ let(:server_address) { '0.0.0.0:9090' }
it_behaves_like 'returns valid uri', 'http://localhost:9090'
end
end
- context 'when listen_address is nil' do
- let(:listen_address) { nil }
+ context 'when server_address is nil' do
+ let(:server_address) { nil }
it 'does not fail' do
expect(described_class.uri).to be_nil
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::Prometheus::Internal do
end
context 'when prometheus listen address is blank in gitlab.yml' do
- let(:listen_address) { '' }
+ let(:server_address) { '' }
it 'does not configure prometheus' do
expect(described_class.uri).to be_nil
@@ -61,26 +61,6 @@ RSpec.describe Gitlab::Prometheus::Internal do
end
end
- describe '.server_address' do
- context 'self.uri returns valid uri' do
- ['http://localhost:9090', 'https://localhost:9090 '].each do |valid_uri|
- it 'returns correct server address' do
- expect(described_class).to receive(:uri).and_return(valid_uri)
-
- expect(described_class.server_address).to eq('localhost:9090')
- end
- end
- end
-
- context 'self.uri returns nil' do
- it 'returns nil' do
- expect(described_class).to receive(:uri).and_return(nil)
-
- expect(described_class.server_address).to be_nil
- end
- end
- end
-
describe '.prometheus_enabled?' do
it 'returns correct value' do
expect(described_class.prometheus_enabled?).to eq(true)
@@ -89,8 +69,8 @@ RSpec.describe Gitlab::Prometheus::Internal do
context 'when prometheus setting is disabled in gitlab.yml' do
let(:prometheus_settings) do
{
- enable: false,
- listen_address: listen_address
+ enabled: false,
+ server_address: server_address
}
end
@@ -110,9 +90,9 @@ RSpec.describe Gitlab::Prometheus::Internal do
end
end
- describe '.listen_address' do
+ describe '.server_address' do
it 'returns correct value' do
- expect(described_class.listen_address).to eq(listen_address)
+ expect(described_class.server_address).to eq(server_address)
end
context 'when prometheus setting is not present in gitlab.yml' do
@@ -121,7 +101,7 @@ RSpec.describe Gitlab::Prometheus::Internal do
end
it 'does not fail' do
- expect(described_class.listen_address).to be_nil
+ expect(described_class.server_address).to be_nil
end
end
end
diff --git a/spec/lib/gitlab/rack_attack_spec.rb b/spec/lib/gitlab/rack_attack_spec.rb
index d72863b0103..5748e1e49e5 100644
--- a/spec/lib/gitlab/rack_attack_spec.rb
+++ b/spec/lib/gitlab/rack_attack_spec.rb
@@ -22,8 +22,7 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
stub_const("Rack::Attack", fake_rack_attack)
stub_const("Rack::Attack::Request", fake_rack_attack_request)
- # Expect rather than just allow, because this is actually fairly important functionality
- expect(fake_rack_attack).to receive(:throttled_response_retry_after_header=).with(true)
+ allow(fake_rack_attack).to receive(:throttled_response=)
allow(fake_rack_attack).to receive(:throttle)
allow(fake_rack_attack).to receive(:track)
allow(fake_rack_attack).to receive(:safelist)
@@ -36,6 +35,12 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
expect(fake_rack_attack_request).to include(described_class::Request)
end
+ it 'configures the throttle response' do
+ described_class.configure(fake_rack_attack)
+
+ expect(fake_rack_attack).to have_received(:throttled_response=).with(an_instance_of(Proc))
+ end
+
it 'configures the safelist' do
described_class.configure(fake_rack_attack)
@@ -93,4 +98,207 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
end
end
end
+
+ describe '.throttled_response_headers' do
+ where(:matched, :match_data, :headers) do
+ [
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 3600,
+ epoch_time: Time.utc(2021, 1, 5, 10, 29, 30).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '60',
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '1830'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 3600,
+ epoch_time: Time.utc(2021, 1, 5, 10, 59, 59).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '60',
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '1'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 3600,
+ epoch_time: Time.utc(2021, 1, 5, 10, 0, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '60',
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '3600'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 3600,
+ epoch_time: Time.utc(2021, 1, 5, 23, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '60',
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609891200', # Time.utc(2021, 1, 6, 0, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Wed, 06 Jan 2021 00:00:00 GMT', # Next day
+ 'Retry-After' => '1800'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 3400,
+ epoch_time: Time.utc(2021, 1, 5, 10, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '57', # 56.66 requests per minute
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '1800'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 3700,
+ epoch_time: Time.utc(2021, 1, 5, 10, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '62', # 61.66 requests per minute
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '1800'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 59,
+ epoch_time: Time.utc(2021, 1, 5, 10, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '1', # 0.9833 requests per minute
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '1800'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 1.hour,
+ limit: 61,
+ epoch_time: Time.utc(2021, 1, 5, 10, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '2', # 1.016 requests per minute
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609844400', # Time.utc(2021, 1, 5, 11, 0, 0).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 11:00:00 GMT',
+ 'Retry-After' => '1800'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 15.seconds,
+ limit: 10,
+ epoch_time: Time.utc(2021, 1, 5, 10, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '40',
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609842615', # Time.utc(2021, 1, 5, 10, 30, 15).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 10:30:15 GMT',
+ 'Retry-After' => '15'
+ }
+ ],
+ [
+ 'throttle_unauthenticated',
+ {
+ discriminator: '127.0.0.1',
+ count: 3700,
+ period: 27.seconds,
+ limit: 10,
+ epoch_time: Time.utc(2021, 1, 5, 10, 30, 0).to_i
+ },
+ {
+ 'RateLimit-Name' => 'throttle_unauthenticated',
+ 'RateLimit-Limit' => '23',
+ 'RateLimit-Observed' => '3700',
+ 'RateLimit-Remaining' => '0',
+ 'RateLimit-Reset' => '1609842627', # Time.utc(2021, 1, 5, 10, 30, 27).to_i.to_s
+ 'RateLimit-ResetTime' => 'Tue, 05 Jan 2021 10:30:27 GMT',
+ 'Retry-After' => '27'
+ }
+ ]
+ ]
+ end
+
+ with_them do
+ it 'generates accurate throttled headers' do
+ expect(described_class.throttled_response_headers(matched, match_data)).to eql(headers)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index 57be9e93af2..c437b6bcceb 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -342,17 +342,36 @@ RSpec.describe Gitlab::SearchResults do
expect(results.limited_issues_count).to eq 4
end
- it 'lists all issues for admin' do
- results = described_class.new(admin, query, limit_projects)
- issues = results.objects('issues')
+ context 'with admin user' do
+ context 'when admin mode enabled', :enable_admin_mode do
+ it 'lists all issues' do
+ results = described_class.new(admin, query, limit_projects)
+ issues = results.objects('issues')
+
+ expect(issues).to include issue
+ expect(issues).to include security_issue_1
+ expect(issues).to include security_issue_2
+ expect(issues).to include security_issue_3
+ expect(issues).to include security_issue_4
+ expect(issues).not_to include security_issue_5
+ expect(results.limited_issues_count).to eq 5
+ end
+ end
- expect(issues).to include issue
- expect(issues).to include security_issue_1
- expect(issues).to include security_issue_2
- expect(issues).to include security_issue_3
- expect(issues).to include security_issue_4
- expect(issues).not_to include security_issue_5
- expect(results.limited_issues_count).to eq 5
+ context 'when admin mode disabled' do
+ it 'does not list confidential issues' do
+ results = described_class.new(admin, query, limit_projects)
+ issues = results.objects('issues')
+
+ expect(issues).to include issue
+ expect(issues).not_to include security_issue_1
+ expect(issues).not_to include security_issue_2
+ expect(issues).not_to include security_issue_3
+ expect(issues).not_to include security_issue_4
+ expect(issues).not_to include security_issue_5
+ expect(results.limited_issues_count).to eq 1
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
index 3d9ffb11ae2..3ba08455d01 100644
--- a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Client, :do_not_mock_admin_mode, :request_store do
+RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Client, :request_store do
include AdminModeHelper
let(:worker) do
diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
index 20f1e88bcf4..e8322b11875 100644
--- a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Server, :do_not_mock_admin_mode, :request_store do
+RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Server, :request_store do
include AdminModeHelper
let(:worker) do
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 4ee9569a0cf..b632fc8bad2 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -100,7 +100,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
"subject",
"body"
],
- "_aj_symbol_keys" => ["args"]
+ ActiveJob::Arguments.const_get('RUBY2_KEYWORDS_KEY', false) => ["args"]
}
],
"executions" => 0,
diff --git a/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb b/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
index df949154d4c..a4d8e3957cf 100644
--- a/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
+++ b/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
@@ -3,15 +3,20 @@
require 'spec_helper'
RSpec.describe Gitlab::SlashCommands::Presenters::IssueMove do
- let_it_be(:admin) { create(:admin) }
+ let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:other_project) { create(:project) }
let_it_be(:old_issue, reload: true) { create(:issue, project: project) }
- let(:new_issue) { Issues::MoveService.new(project, admin).execute(old_issue, other_project) }
+ let(:new_issue) { Issues::MoveService.new(project, user).execute(old_issue, other_project) }
let(:attachment) { subject[:attachments].first }
subject { described_class.new(new_issue).present(old_issue) }
+ before do
+ project.add_developer(user)
+ other_project.add_developer(user)
+ end
+
it { is_expected.to be_a(Hash) }
it 'shows the new issue' do
diff --git a/spec/lib/gitlab/template/gitlab_ci_syntax_yml_template_spec.rb b/spec/lib/gitlab/template/gitlab_ci_syntax_yml_template_spec.rb
new file mode 100644
index 00000000000..d1024019a9f
--- /dev/null
+++ b/spec/lib/gitlab/template/gitlab_ci_syntax_yml_template_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Template::GitlabCiSyntaxYmlTemplate do
+ subject { described_class }
+
+ describe '#content' do
+ it 'loads the full file' do
+ template = subject.new(Rails.root.join('lib/gitlab/ci/syntax_templates/Artifacts example.gitlab-ci.yml'))
+
+ expect(template.content).to start_with('#')
+ end
+ end
+
+ it_behaves_like 'file template shared examples', 'Artifacts example', '.gitlab-ci.yml'
+end
diff --git a/spec/lib/gitlab/throttle_spec.rb b/spec/lib/gitlab/throttle_spec.rb
index 7462b2e1c38..50d723193ac 100644
--- a/spec/lib/gitlab/throttle_spec.rb
+++ b/spec/lib/gitlab/throttle_spec.rb
@@ -30,4 +30,32 @@ RSpec.describe Gitlab::Throttle do
end
end
end
+
+ describe '.rate_limiting_response_text' do
+ subject { described_class.rate_limiting_response_text }
+
+ context 'when the setting is not present' do
+ before do
+ stub_application_setting(rate_limiting_response_text: '')
+ end
+
+ it 'returns the default value with a trailing newline' do
+ expect(subject).to eq(described_class::DEFAULT_RATE_LIMITING_RESPONSE_TEXT + "\n")
+ end
+ end
+
+ context 'when the setting is present' do
+ let(:response_text) do
+ 'Rate limit exceeded; see https://docs.gitlab.com/ee/user/gitlab_com/#gitlabcom-specific-rate-limits for more details'
+ end
+
+ before do
+ stub_application_setting(rate_limiting_response_text: response_text)
+ end
+
+ it 'returns the default value with a trailing newline' do
+ expect(subject).to eq(response_text + "\n")
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
new file mode 100644
index 00000000000..acf7aeb303a
--- /dev/null
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Tracking::StandardContext do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:namespace) { create(:namespace) }
+
+ 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
+ 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')
+ end
+ end
+
+ context 'with namespace' do
+ subject { described_class.new(namespace: namespace) }
+
+ 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
+ end
+ end
+
+ context 'with project' do
+ subject { described_class.new(project: project) }
+
+ 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)
+ end
+ end
+
+ context 'with project and namespace' do
+ subject { described_class.new(namespace: namespace, project: project) }
+
+ 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)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index 57882de0974..8f1fd49f4c5 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -41,21 +41,42 @@ RSpec.describe Gitlab::Tracking do
allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
end
- it 'delegates to snowplow destination' do
- expect_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
- .to receive(:event)
- .with('category', 'action', label: 'label', property: 'property', value: 1.5, context: nil)
+ 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
- described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
- end
+ described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5,
+ standard_context: Gitlab::Tracking::StandardContext.new(foo: 'bar'))
+ end
+ end
- it 'delegates to ProductAnalytics destination' do
- expect_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics)
- .to receive(:event)
- .with('category', 'action', label: 'label', property: 'property', value: 1.5, context: nil)
+ 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
- described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
+ described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
+ end
+ end
end
+
+ include_examples 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
+ include_examples 'delegates to destination', Gitlab::Tracking::Destinations::ProductAnalytics
end
describe '.self_describing_event' do
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index c892f1f0410..6d055fe3643 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -18,6 +18,8 @@ RSpec.describe Gitlab::UrlBuilder do
where(:factory, :path_generator) do
:project | ->(project) { "/#{project.full_path}" }
+ :board | ->(board) { "/#{board.project.full_path}/-/boards/#{board.id}" }
+ :group_board | ->(board) { "/groups/#{board.group.full_path}/-/boards/#{board.id}" }
:commit | ->(commit) { "/#{commit.project.full_path}/-/commit/#{commit.id}" }
:issue | ->(issue) { "/#{issue.project.full_path}/-/issues/#{issue.iid}" }
:merge_request | ->(merge_request) { "/#{merge_request.project.full_path}/-/merge_requests/#{merge_request.iid}" }
diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb
new file mode 100644
index 00000000000..e101f837324
--- /dev/null
+++ b/spec/lib/gitlab/usage/metric_definition_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+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',
+ status: 'data_available',
+ default_generation: 'generation_1',
+ full_path: {
+ generation_1: 'uuid',
+ generation_2: 'license.uuid'
+ },
+ group: 'group::product analytics',
+ time_frame: 'none',
+ data_source: 'database',
+ distribution: %w(ee ce),
+ tier: %w(free starter premium ultimate bronze silver gold)
+ }
+ end
+
+ let(:path) { File.join('metrics', 'uuid.yml') }
+ let(:definition) { described_class.new(path, attributes) }
+ let(:yaml_content) { attributes.deep_stringify_keys.to_yaml }
+
+ it 'has all definitons valid' do
+ expect { described_class.definitions }.not_to raise_error(Gitlab::Usage::Metric::InvalidMetricError)
+ end
+
+ describe '#key' do
+ subject { definition.key }
+
+ it 'returns a symbol from name' do
+ is_expected.to eq('uuid')
+ end
+ end
+
+ describe '#validate' 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
+ :time_frame | nil
+ :time_frame | '29d'
+ :data_source | 'other'
+ :data_source | nil
+ :distribution | nil
+ :distribution | 'test'
+ :tier | %w(test ee)
+ end
+
+ with_them do
+ before do
+ attributes[attribute] = value
+ end
+
+ it 'raise exception' 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).validate!
+ end
+ end
+ end
+
+ describe '.load_all!' do
+ let(:metric1) { Dir.mktmpdir('metric1') }
+ let(:metric2) { Dir.mktmpdir('metric2') }
+ let(:definitions) { {} }
+
+ before do
+ allow(described_class).to receive(:paths).and_return(
+ [
+ File.join(metric1, '**', '*.yml'),
+ File.join(metric2, '**', '*.yml')
+ ]
+ )
+ end
+
+ subject { described_class.send(:load_all!) }
+
+ it 'has empty list when there are no definition files' do
+ is_expected.to be_empty
+ end
+
+ it 'has one metric when there is one file' do
+ write_metric(metric1, path, yaml_content)
+
+ is_expected.to be_one
+ end
+
+ it 'when the same meric is defined multiple times raises exception' do
+ write_metric(metric1, path, yaml_content)
+ write_metric(metric2, path, yaml_content)
+
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(instance_of(Gitlab::Usage::Metric::InvalidMetricError))
+
+ subject
+ end
+
+ after do
+ FileUtils.rm_rf(metric1)
+ FileUtils.rm_rf(metric2)
+ end
+
+ def write_metric(metric, path, content)
+ path = File.join(metric, path)
+ dir = File.dirname(path)
+ FileUtils.mkdir_p(dir)
+ File.write(path, content)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metric_spec.rb b/spec/lib/gitlab/usage/metric_spec.rb
new file mode 100644
index 00000000000..40671d980d6
--- /dev/null
+++ b/spec/lib/gitlab/usage/metric_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+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)
+ end
+ end
+
+ describe '#unflatten_default_path' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:default_generation_path, :value, :expected_hash) do
+ 'uuid' | nil | { uuid: nil }
+ 'uuid' | '1111' | { uuid: '1111' }
+ 'counts.issues' | nil | { counts: { issues: nil } }
+ 'counts.issues' | 100 | { counts: { issues: 100 } }
+ 'usage_activity_by_stage.verify.ci_builds' | 100 | { usage_activity_by_stage: { verify: { ci_builds: 100 } } }
+ end
+
+ with_them do
+ subject { described_class.new(default_generation_path: default_generation_path, value: value).unflatten_default_path }
+
+ it { is_expected.to eq(expected_hash) }
+ end
+ end
+end
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
new file mode 100644
index 00000000000..ba7bfe47bc9
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+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) }
+
+ let(:target_id) { "p_ci_templates_#{described_class::TEMPLATE_TO_EVENT[template]}" }
+ let(:expected_type) { instance_of(Integer) }
+ end
+ end
+ end
+
+ it 'does not track templates outside of TEMPLATE_TO_EVENT' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to(
+ receive(:track_event)
+ )
+ 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)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/guest_package_event_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/guest_package_event_counter_spec.rb
deleted file mode 100644
index d018100b041..00000000000
--- a/spec/lib/gitlab/usage_data_counters/guest_package_event_counter_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::UsageDataCounters::GuestPackageEventCounter, :clean_gitlab_redis_shared_state do
- shared_examples_for 'usage counter with totals' do |counter|
- it 'increments counter and returns total count' do
- expect(described_class.read(counter)).to eq(0)
-
- 2.times { described_class.count(counter) }
-
- expect(described_class.read(counter)).to eq(2)
- end
- end
-
- it 'includes the right events' do
- expect(described_class::KNOWN_EVENTS.size).to eq 33
- end
-
- described_class::KNOWN_EVENTS.each do |event|
- it_behaves_like 'usage counter with totals', event
- end
-
- describe '.fetch_supported_event' do
- subject { described_class.fetch_supported_event(event_name) }
-
- let(:event_name) { 'package_guest_i_package_composer_guest_push' }
-
- it { is_expected.to eq 'i_package_composer_guest_push' }
- 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 b6a60c09d3d..b8eddc0ca7f 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
@@ -24,6 +24,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.categories' do
it 'gets all unique category names' do
expect(described_class.categories).to contain_exactly(
+ 'deploy_token_packages',
+ 'user_packages',
'compliance',
'analytics',
'ide_edit',
@@ -34,18 +36,10 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'testing',
'issues_edit',
'ci_secrets_management',
- 'maven_packages',
- 'npm_packages',
- 'conan_packages',
- 'nuget_packages',
- 'pypi_packages',
- 'composer_packages',
- 'generic_packages',
- 'golang_packages',
- 'debian_packages',
- 'container_packages',
- 'tag_packages',
- 'snippets'
+ 'snippets',
+ 'code_review',
+ 'terraform',
+ 'ci_templates'
)
end
end
@@ -95,7 +89,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
it 'does not track the event' do
stub_application_setting(usage_ping_enabled: false)
- described_class.track_event(entity1, weekly_event, Date.current)
+ described_class.track_event(weekly_event, values: entity1, time: Date.current)
expect(Gitlab::Redis::HLL).not_to receive(:add)
end
@@ -109,20 +103,27 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
it 'tracks event when using symbol' do
expect(Gitlab::Redis::HLL).to receive(:add)
- described_class.track_event(entity1, :g_analytics_contribution)
+ described_class.track_event(:g_analytics_contribution, values: entity1)
+ end
+
+ it 'tracks events with multiple values' do
+ values = [entity1, entity2]
+ expect(Gitlab::Redis::HLL).to receive(:add).with(key: /g_{analytics}_contribution/, value: values, expiry: 84.days)
+
+ described_class.track_event(:g_analytics_contribution, values: values)
end
it "raise error if metrics don't have same aggregation" do
- expect { described_class.track_event(entity1, different_aggregation, Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownAggregation)
+ expect { described_class.track_event(different_aggregation, values: entity1, time: Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownAggregation)
end
it 'raise error if metrics of unknown aggregation' do
- expect { described_class.track_event(entity1, 'unknown', Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
+ expect { described_class.track_event('unknown', values: entity1, time: Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
end
context 'for weekly events' do
it 'sets the keys in Redis to expire automatically after the given expiry time' do
- described_class.track_event(entity1, "g_analytics_contribution")
+ described_class.track_event("g_analytics_contribution", values: entity1)
Gitlab::Redis::SharedState.with do |redis|
keys = redis.scan_each(match: "g_{analytics}_contribution-*").to_a
@@ -135,7 +136,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
it 'sets the keys in Redis to expire automatically after 6 weeks by default' do
- described_class.track_event(entity1, "g_compliance_dashboard")
+ described_class.track_event("g_compliance_dashboard", values: entity1)
Gitlab::Redis::SharedState.with do |redis|
keys = redis.scan_each(match: "g_{compliance}_dashboard-*").to_a
@@ -150,7 +151,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
context 'for daily events' do
it 'sets the keys in Redis to expire after the given expiry time' do
- described_class.track_event(entity1, "g_analytics_search")
+ described_class.track_event("g_analytics_search", values: entity1)
Gitlab::Redis::SharedState.with do |redis|
keys = redis.scan_each(match: "*-g_{analytics}_search").to_a
@@ -163,7 +164,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
it 'sets the keys in Redis to expire after 29 days by default' do
- described_class.track_event(entity1, "no_slot")
+ described_class.track_event("no_slot", values: entity1)
Gitlab::Redis::SharedState.with do |redis|
keys = redis.scan_each(match: "*-{no_slot}").to_a
@@ -180,12 +181,19 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.track_event_in_context' do
context 'with valid contex' do
- it 'increments conext event counte' do
+ it 'increments context event counter' do
expect(Gitlab::Redis::HLL).to receive(:add) do |kwargs|
expect(kwargs[:key]).to match(/^#{default_context}\_.*/)
end
- described_class.track_event_in_context(entity1, context_event, default_context)
+ described_class.track_event_in_context(context_event, values: entity1, context: default_context)
+ end
+
+ it 'tracks events with multiple values' do
+ values = [entity1, entity2]
+ expect(Gitlab::Redis::HLL).to receive(:add).with(key: /g_{analytics}_contribution/, value: values, expiry: 84.days)
+
+ described_class.track_event_in_context(:g_analytics_contribution, values: values, context: default_context)
end
end
@@ -193,7 +201,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
it 'does not increment a counter' do
expect(Gitlab::Redis::HLL).not_to receive(:add)
- described_class.track_event_in_context(entity1, context_event, '')
+ described_class.track_event_in_context(context_event, values: entity1, context: '')
end
end
@@ -201,7 +209,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
it 'does not increment a counter' do
expect(Gitlab::Redis::HLL).not_to receive(:add)
- described_class.track_event_in_context(entity1, context_event, invalid_context)
+ described_class.track_event_in_context(context_event, values: entity1, context: invalid_context)
end
end
end
@@ -209,35 +217,35 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.unique_events' do
before do
# events in current week, should not be counted as week is not complete
- described_class.track_event(entity1, weekly_event, Date.current)
- described_class.track_event(entity2, weekly_event, Date.current)
+ described_class.track_event(weekly_event, values: entity1, time: Date.current)
+ described_class.track_event(weekly_event, values: entity2, time: Date.current)
# Events last week
- described_class.track_event(entity1, weekly_event, 2.days.ago)
- described_class.track_event(entity1, weekly_event, 2.days.ago)
- described_class.track_event(entity1, no_slot, 2.days.ago)
+ described_class.track_event(weekly_event, values: entity1, time: 2.days.ago)
+ described_class.track_event(weekly_event, values: entity1, time: 2.days.ago)
+ described_class.track_event(no_slot, values: entity1, time: 2.days.ago)
# Events 2 weeks ago
- described_class.track_event(entity1, weekly_event, 2.weeks.ago)
+ described_class.track_event(weekly_event, values: entity1, time: 2.weeks.ago)
# Events 4 weeks ago
- described_class.track_event(entity3, weekly_event, 4.weeks.ago)
- described_class.track_event(entity4, weekly_event, 29.days.ago)
+ described_class.track_event(weekly_event, values: entity3, time: 4.weeks.ago)
+ described_class.track_event(weekly_event, values: entity4, time: 29.days.ago)
# events in current day should be counted in daily aggregation
- described_class.track_event(entity1, daily_event, Date.current)
- described_class.track_event(entity2, daily_event, Date.current)
+ described_class.track_event(daily_event, values: entity1, time: Date.current)
+ described_class.track_event(daily_event, values: entity2, time: Date.current)
# Events last week
- described_class.track_event(entity1, daily_event, 2.days.ago)
- described_class.track_event(entity1, daily_event, 2.days.ago)
+ described_class.track_event(daily_event, values: entity1, time: 2.days.ago)
+ described_class.track_event(daily_event, values: entity1, time: 2.days.ago)
# Events 2 weeks ago
- described_class.track_event(entity1, daily_event, 14.days.ago)
+ described_class.track_event(daily_event, values: entity1, time: 14.days.ago)
# Events 4 weeks ago
- described_class.track_event(entity3, daily_event, 28.days.ago)
- described_class.track_event(entity4, daily_event, 29.days.ago)
+ described_class.track_event(daily_event, values: entity3, time: 28.days.ago)
+ described_class.track_event(daily_event, values: entity4, time: 29.days.ago)
end
it 'raise error if metrics are not in the same slot' do
@@ -345,10 +353,10 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
allow(described_class).to receive(:known_events).and_return(known_events)
allow(described_class).to receive(:categories).and_return(%w(category1 category2))
- described_class.track_event_in_context([entity1, entity3], 'event_name_1', default_context, 2.days.ago)
- described_class.track_event_in_context(entity3, 'event_name_1', default_context, 2.days.ago)
- described_class.track_event_in_context(entity3, 'event_name_1', invalid_context, 2.days.ago)
- described_class.track_event_in_context([entity1, entity2], 'event_name_2', '', 2.weeks.ago)
+ described_class.track_event_in_context('event_name_1', values: [entity1, entity3], context: default_context, time: 2.days.ago)
+ described_class.track_event_in_context('event_name_1', values: entity3, context: default_context, time: 2.days.ago)
+ described_class.track_event_in_context('event_name_1', values: entity3, context: invalid_context, time: 2.days.ago)
+ described_class.track_event_in_context('event_name_2', values: [entity1, entity2], context: '', time: 2.weeks.ago)
end
subject(:unique_events) { described_class.unique_events(event_names: event_names, start_date: 4.weeks.ago, end_date: Date.current, context: context) }
@@ -386,13 +394,13 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
allow(described_class).to receive(:known_events).and_return(known_events)
allow(described_class).to receive(:categories).and_return(%w(category1 category2))
- described_class.track_event(entity1, 'event1_slot', 2.days.ago)
- described_class.track_event(entity2, 'event2_slot', 2.days.ago)
- described_class.track_event(entity3, 'event2_slot', 2.weeks.ago)
+ described_class.track_event('event1_slot', values: entity1, time: 2.days.ago)
+ described_class.track_event('event2_slot', values: entity2, time: 2.days.ago)
+ described_class.track_event('event2_slot', values: entity3, time: 2.weeks.ago)
# events in different slots
- described_class.track_event(entity2, 'event3', 2.days.ago)
- described_class.track_event(entity2, 'event4', 2.days.ago)
+ described_class.track_event('event3', values: entity2, time: 2.days.ago)
+ described_class.track_event('event4', values: entity2, time: 2.days.ago)
end
it 'returns the number of unique events for all known events' do
@@ -516,23 +524,23 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
subject(:aggregated_metrics_data) { described_class.aggregated_metrics_weekly_data }
before do
- described_class.track_event(entity1, 'event1_slot', 2.days.ago)
- described_class.track_event(entity2, 'event1_slot', 2.days.ago)
- described_class.track_event(entity3, 'event1_slot', 2.days.ago)
- described_class.track_event(entity1, 'event2_slot', 2.days.ago)
- described_class.track_event(entity2, 'event2_slot', 3.days.ago)
- described_class.track_event(entity3, 'event2_slot', 3.days.ago)
- described_class.track_event(entity1, 'event3_slot', 3.days.ago)
- described_class.track_event(entity2, 'event3_slot', 3.days.ago)
- described_class.track_event(entity2, 'event5_slot', 3.days.ago)
+ 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(entity3, 'event2_slot', 8.days.ago)
+ described_class.track_event('event2_slot', values: entity3, time: 8.days.ago)
# events in different slots
- described_class.track_event(entity1, 'event4', 2.days.ago)
- described_class.track_event(entity2, 'event4', 2.days.ago)
- described_class.track_event(entity4, 'event4', 2.days.ago)
+ 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'
@@ -543,23 +551,23 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
it_behaves_like 'aggregated_metrics_data' do
before do
- described_class.track_event(entity1, 'event1_slot', 2.days.ago)
- described_class.track_event(entity2, 'event1_slot', 2.days.ago)
- described_class.track_event(entity3, 'event1_slot', 2.days.ago)
- described_class.track_event(entity1, 'event2_slot', 2.days.ago)
- described_class.track_event(entity2, 'event2_slot', 3.days.ago)
- described_class.track_event(entity3, 'event2_slot', 3.days.ago)
- described_class.track_event(entity1, 'event3_slot', 3.days.ago)
- described_class.track_event(entity2, 'event3_slot', 10.days.ago)
- described_class.track_event(entity2, 'event5_slot', 4.weeks.ago.advance(days: 1))
+ 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(entity1, 'event5_slot', 4.weeks.ago.advance(days: -1))
+ described_class.track_event('event5_slot', values: entity1, time: 4.weeks.ago.advance(days: -1))
# events in different slots
- described_class.track_event(entity1, 'event4', 2.days.ago)
- described_class.track_event(entity2, 'event4', 2.days.ago)
- described_class.track_event(entity4, 'event4', 2.days.ago)
+ 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
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
new file mode 100644
index 00000000000..c7b208cfb31
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
@@ -0,0 +1,151 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :clean_gitlab_redis_shared_state do
+ let(:merge_request) { build(:merge_request, id: 1) }
+ let(:user) { build(:user, id: 1) }
+ let(:note) { build(:note, author: user) }
+
+ shared_examples_for 'a tracked merge request 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
+
+ describe '.track_mr_diffs_action' do
+ subject { described_class.track_mr_diffs_action(merge_request: merge_request) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_DIFFS_ACTION }
+ end
+ end
+
+ describe '.track_mr_diffs_single_file_action' do
+ subject { described_class.track_mr_diffs_single_file_action(merge_request: merge_request, user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_DIFFS_SINGLE_FILE_ACTION }
+ end
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_DIFFS_USER_SINGLE_FILE_ACTION }
+ end
+ end
+
+ describe '.track_create_mr_action' do
+ subject { described_class.track_create_mr_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_CREATE_ACTION }
+ end
+ end
+
+ describe '.track_close_mr_action' do
+ subject { described_class.track_close_mr_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_CLOSE_ACTION }
+ end
+ end
+
+ describe '.track_merge_mr_action' do
+ subject { described_class.track_merge_mr_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_MERGE_ACTION }
+ end
+ end
+
+ describe '.track_reopen_mr_action' do
+ subject { described_class.track_reopen_mr_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_REOPEN_ACTION }
+ end
+ end
+
+ describe '.track_create_comment_action' do
+ subject { described_class.track_create_comment_action(note: note) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_CREATE_COMMENT_ACTION }
+ end
+
+ context 'when the note is multiline diff note' do
+ let(:note) { build(:diff_note_on_merge_request, author: user) }
+
+ before do
+ allow(note).to receive(:multiline?).and_return(true)
+ end
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_CREATE_MULTILINE_COMMENT_ACTION }
+ end
+ end
+ end
+
+ describe '.track_edit_comment_action' do
+ subject { described_class.track_edit_comment_action(note: note) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_EDIT_COMMENT_ACTION }
+ end
+
+ context 'when the note is multiline diff note' do
+ let(:note) { build(:diff_note_on_merge_request, author: user) }
+
+ before do
+ allow(note).to receive(:multiline?).and_return(true)
+ end
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_EDIT_MULTILINE_COMMENT_ACTION }
+ end
+ end
+ end
+
+ describe '.track_remove_comment_action' do
+ subject { described_class.track_remove_comment_action(note: note) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_REMOVE_COMMENT_ACTION }
+ end
+
+ context 'when the note is multiline diff note' do
+ let(:note) { build(:diff_note_on_merge_request, author: user) }
+
+ before do
+ allow(note).to receive(:multiline?).and_return(true)
+ end
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_REMOVE_MULTILINE_COMMENT_ACTION }
+ end
+ end
+ end
+
+ describe '.track_create_review_note_action' do
+ subject { described_class.track_create_review_note_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_CREATE_REVIEW_NOTE_ACTION }
+ end
+ end
+
+ describe '.track_publish_review_action' do
+ subject { described_class.track_publish_review_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_PUBLISH_REVIEW_ACTION }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb
new file mode 100644
index 00000000000..7b5efb11034
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::PackageEventCounter, :clean_gitlab_redis_shared_state do
+ shared_examples_for 'usage counter with totals' do |counter|
+ it 'increments counter and returns total count' do
+ expect(described_class.read(counter)).to eq(0)
+
+ 2.times { described_class.count(counter) }
+
+ expect(described_class.read(counter)).to eq(2)
+ end
+ end
+
+ it 'includes the right events' do
+ expect(described_class::KNOWN_EVENTS.size).to eq 45
+ end
+
+ described_class::KNOWN_EVENTS.each do |event|
+ it_behaves_like 'usage counter with totals', event
+ end
+
+ describe '.fetch_supported_event' do
+ subject { described_class.fetch_supported_event(event_name) }
+
+ let(:event_name) { 'package_events_i_package_composer_push_package' }
+
+ it { is_expected.to eq 'i_package_composer_push_package' }
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 4d12bb6bd8c..fd02521622c 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -680,7 +680,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
it { is_expected.to include(:kubernetes_agent_gitops_sync) }
it { is_expected.to include(:static_site_editor_views) }
- it { is_expected.to include(:package_guest_i_package_composer_guest_pull) }
+ it { is_expected.to include(:package_events_i_package_pull_package) }
+ it { is_expected.to include(:package_events_i_package_delete_package_by_user) }
+ it { is_expected.to include(:package_events_i_package_conan_push_package) }
end
describe '.usage_data_counters' do
@@ -1260,7 +1262,7 @@ 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 testing ci_secrets_management incident_management_alerts snippets] }
+ let(:ineligible_total_categories) { %w[source_code ci_secrets_management incident_management_alerts snippets terraform] }
it 'has all known_events' do
expect(subject).to have_key(:redis_hll_counters)
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index 748a8336a25..97fff030906 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -45,10 +45,20 @@ RSpec.describe Gitlab::UserAccess do
let(:empty_project) { create(:project_empty_repo) }
let(:project_access) { described_class.new(user, container: empty_project) }
- it 'returns true for admins' do
- user.update!(admin: true)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns true for admins' do
+ user.update!(admin: true)
- expect(access.can_push_to_branch?('master')).to be_truthy
+ expect(access.can_push_to_branch?('master')).to be_truthy
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns false for admins' do
+ user.update!(admin: true)
+
+ expect(access.can_push_to_branch?('master')).to be_falsey
+ end
end
it 'returns true if user is maintainer' do
@@ -85,10 +95,20 @@ RSpec.describe Gitlab::UserAccess do
let(:branch) { create :protected_branch, project: project, name: "test" }
let(:not_existing_branch) { create :protected_branch, :developers_can_merge, project: project }
- it 'returns true for admins' do
- user.update!(admin: true)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns true for admins' do
+ user.update!(admin: true)
- expect(access.can_push_to_branch?(branch.name)).to be_truthy
+ expect(access.can_push_to_branch?(branch.name)).to be_truthy
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns false for admins' do
+ user.update!(admin: true)
+
+ expect(access.can_push_to_branch?(branch.name)).to be_falsey
+ end
end
it 'returns true if user is a maintainer' do
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index 521d6584a20..dfc381d0ef2 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -38,32 +38,116 @@ RSpec.describe Gitlab::Utils::UsageData do
end
describe '#estimate_batch_distinct_count' do
+ let(:error_rate) { Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE } # HyperLogLog is a probabilistic algorithm, which provides estimated data, with given error margin
let(:relation) { double(:relation) }
+ before do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ end
+
it 'delegates counting to counter class instance' do
+ buckets = instance_double(Gitlab::Database::PostgresHll::Buckets)
+
expect_next_instance_of(Gitlab::Database::PostgresHll::BatchDistinctCounter, relation, 'column') do |instance|
- expect(instance).to receive(:estimate_distinct_count)
+ expect(instance).to receive(:execute)
.with(batch_size: nil, start: nil, finish: nil)
- .and_return(5)
+ .and_return(buckets)
end
+ expect(buckets).to receive(:estimated_distinct_count).and_return(5)
expect(described_class.estimate_batch_distinct_count(relation, 'column')).to eq(5)
end
- it 'returns default fallback value when counting fails due to database error' do
- stub_const("Gitlab::Utils::UsageData::FALLBACK", 15)
- allow(Gitlab::Database::PostgresHll::BatchDistinctCounter).to receive(:new).and_raise(ActiveRecord::StatementInvalid.new(''))
+ 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
+ # estimations of unique values present in dataset, because of that its results
+ # are always off by some small factor from real value. However for given
+ # dataset it provide consistent and deterministic result. In the following context
+ # analyzed sets consist of values:
+ # build_needs set: ['1', '2', '3', '4', '5']
+ # ci_build set ['a', 'b']
+ # with them, current implementation is expected to consistently report
+ # 5.217656147118495 and 2.0809220082170614 values
+ # This test suite is expected to assure, that HyperLogLog implementation
+ # behaves consistently between changes made to other parts of codebase.
+ # In case of fine tuning or changes to HyperLogLog algorithm implementation
+ # one should run in depth analysis of accuracy with supplementary rake tasks
+ # currently under implementation at https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51118
+ # and adjust used values in this context accordingly.
+ let_it_be(:build) { create(:ci_build, name: 'a') }
+ let_it_be(:another_build) { create(:ci_build, name: 'b') }
+
+ let(:model) { Ci::BuildNeed }
+ let(:column) { :name }
+ let(:build_needs_estimated_cardinality) { 5.217656147118495 }
+ let(:ci_builds_estimated_cardinality) { 2.0809220082170614 }
+
+ context 'different counting parameters' do
+ before_all do
+ 1.upto(3) { |i| create(:ci_build_need, name: i, build: build) }
+ 4.upto(5) { |i| create(:ci_build_need, name: i, build: another_build) }
+ end
+
+ it 'counts with symbol passed in column argument' do
+ expect(described_class.estimate_batch_distinct_count(model, column)).to eq(build_needs_estimated_cardinality)
+ end
+
+ it 'counts with string passed in column argument' do
+ expect(described_class.estimate_batch_distinct_count(model, column.to_s)).to eq(build_needs_estimated_cardinality)
+ end
+
+ it 'counts with table.column passed in column argument' do
+ expect(described_class.estimate_batch_distinct_count(model, "#{model.table_name}.#{column}")).to eq(build_needs_estimated_cardinality)
+ end
+
+ it 'counts with Arel passed in column argument' do
+ expect(described_class.estimate_batch_distinct_count(model, model.arel_table[column])).to eq(build_needs_estimated_cardinality)
+ end
+
+ it 'counts over joined relations' do
+ expect(described_class.estimate_batch_distinct_count(model.joins(:build), "ci_builds.name")).to eq(ci_builds_estimated_cardinality)
+ end
- expect(described_class.estimate_batch_distinct_count(relation)).to eq(15)
+ it 'counts with :column field with batch_size of 50K' do
+ expect(described_class.estimate_batch_distinct_count(model, column, batch_size: 50_000)).to eq(build_needs_estimated_cardinality)
+ end
+
+ it 'counts with different number of batches and aggregates total result' do
+ stub_const('Gitlab::Database::PostgresHll::BatchDistinctCounter::MIN_REQUIRED_BATCH_SIZE', 0)
+
+ [1, 2, 4, 5, 6].each { |i| expect(described_class.estimate_batch_distinct_count(model, column, batch_size: i)).to eq(build_needs_estimated_cardinality) }
+ end
+
+ it 'counts with a start and finish' do
+ expect(described_class.estimate_batch_distinct_count(model, column, start: model.minimum(:id), finish: model.maximum(:id))).to eq(build_needs_estimated_cardinality)
+ end
+ end
end
- it 'logs error and returns DISTRIBUTED_HLL_FALLBACK value when counting raises any error', :aggregate_failures do
- error = StandardError.new('')
- stub_const("Gitlab::Utils::UsageData::DISTRIBUTED_HLL_FALLBACK", 15)
- allow(Gitlab::Database::PostgresHll::BatchDistinctCounter).to receive(:new).and_raise(error)
+ describe 'error handling' do
+ before do
+ stub_const("Gitlab::Utils::UsageData::FALLBACK", 3)
+ stub_const("Gitlab::Utils::UsageData::DISTRIBUTED_HLL_FALLBACK", 4)
+ end
+
+ it 'returns fallback if counter raises WRONG_CONFIGURATION_ERROR' do
+ expect(described_class.estimate_batch_distinct_count(relation, 'id', start: 1, finish: 0)).to eq 3
+ end
+
+ it 'returns default fallback value when counting fails due to database error' do
+ allow(Gitlab::Database::PostgresHll::BatchDistinctCounter).to receive(:new).and_raise(ActiveRecord::StatementInvalid.new(''))
- expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error)
- expect(described_class.estimate_batch_distinct_count(relation)).to eq(15)
+ expect(described_class.estimate_batch_distinct_count(relation)).to eq(3)
+ end
+
+ it 'logs error and returns DISTRIBUTED_HLL_FALLBACK value when counting raises any error', :aggregate_failures do
+ error = StandardError.new('')
+ allow(Gitlab::Database::PostgresHll::BatchDistinctCounter).to receive(:new).and_raise(error)
+
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error)
+ expect(described_class.estimate_batch_distinct_count(relation)).to eq(4)
+ end
end
end
@@ -193,7 +277,7 @@ RSpec.describe Gitlab::Utils::UsageData do
context 'when Prometheus server address is available from settings' do
before do
expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true)
- expect(Gitlab::Prometheus::Internal).to receive(:server_address).and_return('prom:9090')
+ expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090')
end
it_behaves_like 'try to query Prometheus with given address'
@@ -256,7 +340,7 @@ RSpec.describe Gitlab::Utils::UsageData do
end
it 'tracks redis hll event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(value, event_name)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
described_class.track_usage_event(event_name, value)
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 36257a0605b..1052d4cbacc 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -392,6 +392,23 @@ RSpec.describe Gitlab::Utils do
end
end
+ describe ".safe_downcase!" do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:str, :result) do
+ "test".freeze | "test"
+ "Test".freeze | "test"
+ "test" | "test"
+ "Test" | "test"
+ end
+
+ with_them do
+ it "downcases the string" do
+ expect(described_class.safe_downcase!(str)).to eq(result)
+ end
+ end
+ end
+
describe '.parse_url' do
it 'returns Addressable::URI object' do
expect(described_class.parse_url('http://gitlab.com')).to be_instance_of(Addressable::URI)
diff --git a/spec/lib/gitlab/uuid_spec.rb b/spec/lib/gitlab/uuid_spec.rb
index a2e28f5a24d..44c1d30fce0 100644
--- a/spec/lib/gitlab/uuid_spec.rb
+++ b/spec/lib/gitlab/uuid_spec.rb
@@ -49,4 +49,23 @@ RSpec.describe Gitlab::UUID do
it { is_expected.to eq(production_proper_uuid) }
end
end
+
+ describe 'v5?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:test_string, :is_uuid_v5) do
+ 'not even a uuid' | false
+ 'this-seems-like-a-uuid' | false
+ 'thislook-more-5lik-eava-liduuidbutno' | false
+ '9f470438-db0f-37b7-9ca9-1d47104c339a' | false
+ '9f470438-db0f-47b7-9ca9-1d47104c339a' | false
+ '9f470438-db0f-57b7-9ca9-1d47104c339a' | true
+ end
+
+ with_them do
+ subject { described_class.v5?(test_string) }
+
+ it { is_expected.to be(is_uuid_v5) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/visibility_level_spec.rb b/spec/lib/gitlab/visibility_level_spec.rb
index 2ac343cd1e7..63c31c82d59 100644
--- a/spec/lib/gitlab/visibility_level_spec.rb
+++ b/spec/lib/gitlab/visibility_level_spec.rb
@@ -22,13 +22,25 @@ RSpec.describe Gitlab::VisibilityLevel do
end
describe '.levels_for_user' do
- it 'returns all levels for an admin' do
- user = build(:user, :admin)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns all levels for an admin' do
+ user = build(:user, :admin)
+
+ expect(described_class.levels_for_user(user))
+ .to eq([Gitlab::VisibilityLevel::PRIVATE,
+ Gitlab::VisibilityLevel::INTERNAL,
+ Gitlab::VisibilityLevel::PUBLIC])
+ end
+ end
- expect(described_class.levels_for_user(user))
- .to eq([Gitlab::VisibilityLevel::PRIVATE,
- Gitlab::VisibilityLevel::INTERNAL,
- Gitlab::VisibilityLevel::PUBLIC])
+ context 'when admin mode is disabled' do
+ it 'returns INTERNAL and PUBLIC for an admin' do
+ user = build(:user, :admin)
+
+ expect(described_class.levels_for_user(user))
+ .to eq([Gitlab::VisibilityLevel::INTERNAL,
+ Gitlab::VisibilityLevel::PUBLIC])
+ end
end
it 'returns INTERNAL and PUBLIC for internal users' do
@@ -119,28 +131,4 @@ RSpec.describe Gitlab::VisibilityLevel do
end
end
end
-
- describe '#visibility_level_decreased?' do
- let(:project) { create(:project, :internal) }
-
- context 'when visibility level decreases' do
- before do
- project.update!(visibility_level: described_class::PRIVATE)
- end
-
- it 'returns true' do
- expect(project.visibility_level_decreased?).to be(true)
- end
- end
-
- context 'when visibility level does not decrease' do
- before do
- project.update!(visibility_level: described_class::PUBLIC)
- end
-
- it 'returns false' do
- expect(project.visibility_level_decreased?).to be(false)
- end
- end
- end
end
diff --git a/spec/lib/release_highlights/validator/entry_spec.rb b/spec/lib/release_highlights/validator/entry_spec.rb
new file mode 100644
index 00000000000..648356e63ba
--- /dev/null
+++ b/spec/lib/release_highlights/validator/entry_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ReleaseHighlights::Validator::Entry do
+ subject(:entry) { described_class.new(document.root.children.first) }
+
+ let(:document) { YAML.parse(File.read(yaml_path)) }
+ let(:yaml_path) { 'spec/fixtures/whats_new/blank.yml' }
+
+ describe 'validations' do
+ before do
+ allow(entry).to receive(:value_for).and_call_original
+ end
+
+ context 'with a valid entry' do
+ let(:yaml_path) { 'spec/fixtures/whats_new/valid.yml' }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'with an invalid entry' do
+ let(:yaml_path) { 'spec/fixtures/whats_new/invalid.yml' }
+
+ it 'returns line numbers in errors' do
+ subject.valid?
+
+ expect(entry.errors[:packages].first).to match('(line 6)')
+ end
+ end
+
+ context 'with a blank entry' do
+ it 'validate presence of title, body and stage' do
+ subject.valid?
+
+ expect(subject.errors[:title]).not_to be_empty
+ expect(subject.errors[:body]).not_to be_empty
+ expect(subject.errors[:stage]).not_to be_empty
+ expect(subject.errors[:packages]).not_to be_empty
+ end
+
+ it 'validates boolean value of "self-managed" and "gitlab-com"' do
+ allow(entry).to receive(:value_for).with('self-managed').and_return('nope')
+ allow(entry).to receive(:value_for).with('gitlab-com').and_return('yerp')
+
+ subject.valid?
+
+ expect(subject.errors[:'self-managed']).to include(/must be a boolean/)
+ expect(subject.errors[:'gitlab-com']).to include(/must be a boolean/)
+ end
+
+ it 'validates URI of "url" and "image_url"' do
+ allow(entry).to receive(:value_for).with('image_url').and_return('imgur/gitlab_feature.gif')
+ allow(entry).to receive(:value_for).with('url').and_return('gitlab/newest_release.html')
+
+ subject.valid?
+
+ expect(subject.errors[:url]).to include(/must be a URL/)
+ expect(subject.errors[:image_url]).to include(/must be a URL/)
+ end
+
+ it 'validates release is numerical' do
+ allow(entry).to receive(:value_for).with('release').and_return('one')
+
+ subject.valid?
+
+ expect(subject.errors[:release]).to include(/is not a number/)
+ end
+
+ it 'validates published_at is a date' do
+ allow(entry).to receive(:value_for).with('published_at').and_return('christmas day')
+
+ subject.valid?
+
+ expect(subject.errors[:published_at]).to include(/must be valid Date/)
+ end
+
+ it 'validates packages are included in list' do
+ allow(entry).to receive(:value_for).with('packages').and_return(['ALL'])
+
+ subject.valid?
+
+ expect(subject.errors[:packages].first).to include("must be one of", "Core", "Starter", "Premium", "Ultimate")
+ end
+ end
+ end
+end
diff --git a/spec/lib/release_highlights/validator_spec.rb b/spec/lib/release_highlights/validator_spec.rb
new file mode 100644
index 00000000000..e68d9145dcd
--- /dev/null
+++ b/spec/lib/release_highlights/validator_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ReleaseHighlights::Validator do
+ let(:validator) { described_class.new(file: yaml_path) }
+ let(:yaml_path) { 'spec/fixtures/whats_new/valid.yml' }
+ let(:invalid_yaml_path) { 'spec/fixtures/whats_new/invalid.yml' }
+
+ describe '#valid?' do
+ subject { validator.valid? }
+
+ context 'with a valid file' do
+ it 'passes entries to entry validator and returns true' do
+ expect(ReleaseHighlights::Validator::Entry).to receive(:new).exactly(:twice).and_call_original
+ expect(subject).to be true
+ expect(validator.errors).to be_empty
+ end
+ end
+
+ context 'with invalid file' do
+ let(:yaml_path) { invalid_yaml_path }
+
+ it 'returns false and has errors' do
+ expect(subject).to be false
+ expect(validator.errors).not_to be_empty
+ end
+ end
+ end
+
+ describe '.validate_all!' do
+ subject { described_class.validate_all! }
+
+ before do
+ allow(ReleaseHighlight).to receive(:file_paths).and_return(yaml_paths)
+ end
+
+ context 'with valid files' do
+ let(:yaml_paths) { [yaml_path, yaml_path] }
+
+ it { is_expected.to be true }
+ end
+
+ context 'with an invalid file' do
+ let(:yaml_paths) { [invalid_yaml_path, yaml_path] }
+
+ it { is_expected.to be false }
+ end
+ end
+
+ describe '.error_message' do
+ subject do
+ described_class.validate_all!
+ described_class.error_message
+ end
+
+ before do
+ allow(ReleaseHighlight).to receive(:file_paths).and_return([yaml_path])
+ end
+
+ context 'with a valid file' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'with an invalid file' do
+ let(:yaml_path) { invalid_yaml_path }
+
+ it 'returns a nice error message' do
+ expect(subject).to eq(<<-MESSAGE.strip_heredoc)
+ ---------------------------------------------------------
+ Validation failed for spec/fixtures/whats_new/invalid.yml
+ ---------------------------------------------------------
+ * Packages must be one of ["Core", "Starter", "Premium", "Ultimate"] (line 6)
+
+ MESSAGE
+ end
+ end
+ end
+
+ describe 'when validating all files' do
+ it 'they should have no errors' do
+ expect(described_class.validate_all!).to be_truthy, described_class.error_message
+ end
+ end
+end
diff --git a/spec/lib/uploaded_file_spec.rb b/spec/lib/uploaded_file_spec.rb
index 8425e1dbd46..ececc84bc93 100644
--- a/spec/lib/uploaded_file_spec.rb
+++ b/spec/lib/uploaded_file_spec.rb
@@ -27,12 +27,12 @@ RSpec.describe UploadedFile do
end
it 'handles a blank path' do
- params['file.path'] = ''
+ params['path'] = ''
# Not a real file, so can't determine size itself
- params['file.size'] = 1.byte
+ params['size'] = 1.byte
- expect { described_class.from_params(params, :file, upload_path) }
+ expect { described_class.from_params(params, upload_path) }
.not_to raise_error
end
end
@@ -50,7 +50,7 @@ RSpec.describe UploadedFile do
end
end
- describe '.from_params_without_field' do
+ describe '.from_params' do
let(:upload_path) { nil }
after do
@@ -58,7 +58,7 @@ RSpec.describe UploadedFile do
end
subject do
- described_class.from_params_without_field(params, [upload_path, Dir.tmpdir])
+ described_class.from_params(params, [upload_path, Dir.tmpdir])
end
context 'when valid file is specified' do
@@ -170,190 +170,6 @@ RSpec.describe UploadedFile do
end
end
end
-
- describe '.from_params' do
- let(:upload_path) { nil }
- let(:file_path_override) { nil }
-
- after do
- FileUtils.rm_r(upload_path) if upload_path
- end
-
- subject do
- described_class.from_params(params, :file, [upload_path, Dir.tmpdir], file_path_override)
- end
-
- RSpec.shared_context 'filepath override' do
- let(:temp_file_override) { Tempfile.new(%w[override override], temp_dir) }
- let(:file_path_override) { temp_file_override.path }
-
- before do
- FileUtils.touch(temp_file_override)
- end
-
- after do
- FileUtils.rm_f(temp_file_override)
- end
- end
-
- context 'when valid file is specified' do
- context 'only local path is specified' do
- let(:params) do
- { 'file.path' => temp_file.path }
- end
-
- it { is_expected.not_to be_nil }
-
- it "generates filename from path" do
- expect(subject.original_filename).to eq(::File.basename(temp_file.path))
- end
- end
-
- context 'all parameters are specified' do
- context 'with a filepath' do
- let(:params) do
- { 'file.path' => temp_file.path,
- 'file.name' => 'dir/my file&.txt',
- 'file.type' => 'my/type',
- 'file.sha256' => 'sha256' }
- end
-
- it_behaves_like 'using the file path',
- filename: 'my_file_.txt',
- content_type: 'my/type',
- sha256: 'sha256',
- path_suffix: 'test'
- end
-
- context 'with a filepath override' do
- include_context 'filepath override'
-
- let(:params) do
- { 'file.path' => temp_file.path,
- 'file.name' => 'dir/my file&.txt',
- 'file.type' => 'my/type',
- 'file.sha256' => 'sha256' }
- end
-
- it_behaves_like 'using the file path',
- filename: 'my_file_.txt',
- content_type: 'my/type',
- sha256: 'sha256',
- path_suffix: 'override'
- end
-
- context 'with a remote id' do
- let(:params) do
- {
- 'file.name' => 'dir/my file&.txt',
- 'file.sha256' => 'sha256',
- 'file.remote_url' => 'http://localhost/file',
- 'file.remote_id' => '1234567890',
- 'file.etag' => 'etag1234567890',
- 'file.size' => '123456'
- }
- end
-
- it_behaves_like 'using the remote id',
- filename: 'my_file_.txt',
- content_type: 'application/octet-stream',
- sha256: 'sha256',
- size: 123456,
- remote_id: '1234567890'
- end
-
- context 'with a path and a remote id' do
- let(:params) do
- {
- 'file.path' => temp_file.path,
- 'file.name' => 'dir/my file&.txt',
- 'file.sha256' => 'sha256',
- 'file.remote_url' => 'http://localhost/file',
- 'file.remote_id' => '1234567890',
- 'file.etag' => 'etag1234567890',
- 'file.size' => '123456'
- }
- end
-
- it_behaves_like 'using the remote id',
- filename: 'my_file_.txt',
- content_type: 'application/octet-stream',
- sha256: 'sha256',
- size: 123456,
- remote_id: '1234567890'
- end
-
- context 'with a path override and a remote id' do
- include_context 'filepath override'
-
- let(:params) do
- {
- 'file.name' => 'dir/my file&.txt',
- 'file.sha256' => 'sha256',
- 'file.remote_url' => 'http://localhost/file',
- 'file.remote_id' => '1234567890',
- 'file.etag' => 'etag1234567890',
- 'file.size' => '123456'
- }
- end
-
- it_behaves_like 'using the remote id',
- filename: 'my_file_.txt',
- content_type: 'application/octet-stream',
- sha256: 'sha256',
- size: 123456,
- remote_id: '1234567890'
- end
- end
- end
-
- context 'when no params are specified' do
- let(:params) do
- {}
- end
-
- it "does not return an object" do
- is_expected.to be_nil
- end
- end
-
- context 'when verifying allowed paths' do
- let(:params) do
- { 'file.path' => temp_file.path }
- end
-
- context 'when file is stored in system temporary folder' do
- let(:temp_dir) { Dir.tmpdir }
-
- it "succeeds" do
- is_expected.not_to be_nil
- end
- end
-
- context 'when file is stored in user provided upload path' do
- let(:upload_path) { Dir.mktmpdir }
- let(:temp_dir) { upload_path }
-
- it "succeeds" do
- is_expected.not_to be_nil
- end
- end
-
- context 'when file is stored outside of user provided upload path' do
- let!(:generated_dir) { Dir.mktmpdir }
- let!(:temp_dir) { Dir.mktmpdir }
-
- before do
- # We overwrite default temporary path
- allow(Dir).to receive(:tmpdir).and_return(generated_dir)
- end
-
- it "raises an error" do
- expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/)
- end
- end
- end
- end
end
describe '.initialize' do
diff --git a/spec/mailers/emails/merge_requests_spec.rb b/spec/mailers/emails/merge_requests_spec.rb
index 412cdff3aba..34665d943ab 100644
--- a/spec/mailers/emails/merge_requests_spec.rb
+++ b/spec/mailers/emails/merge_requests_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Emails::MergeRequests do
}
end
- it { expect(subject).to have_content('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB.') }
+ it { expect(subject).to have_content('attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15 MB.') }
end
end
end
diff --git a/spec/mailers/emails/pipelines_spec.rb b/spec/mailers/emails/pipelines_spec.rb
index f0f23fe2097..3ac68721357 100644
--- a/spec/mailers/emails/pipelines_spec.rb
+++ b/spec/mailers/emails/pipelines_spec.rb
@@ -11,8 +11,8 @@ RSpec.describe Emails::Pipelines do
shared_examples_for 'correct pipeline information' do
it 'has a correct information' do
expect(subject)
- .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \
- "#{status} for #{pipeline.source_ref} | " \
+ .to have_subject "#{status} pipeline for #{pipeline.source_ref} | " \
+ "#{project.name} | " \
"#{pipeline.short_sha}".to_s
expect(subject).to have_body_text pipeline.source_ref
@@ -29,8 +29,8 @@ RSpec.describe Emails::Pipelines do
it 'has correct information that there is no merge request link' do
expect(subject)
- .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \
- "#{status} for #{pipeline.source_ref} | " \
+ .to have_subject "#{status} pipeline for #{pipeline.source_ref} | " \
+ "#{project.name} | " \
"#{pipeline.short_sha}".to_s
expect(subject).to have_body_text pipeline.source_ref
@@ -49,9 +49,9 @@ RSpec.describe Emails::Pipelines do
it 'has correct information that there is a merge request link' do
expect(subject)
- .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \
- "#{status} for #{pipeline.source_ref} | " \
- "#{pipeline.short_sha} in !#{merge_request.iid}".to_s
+ .to have_subject "#{status} pipeline for #{pipeline.source_ref} | " \
+ "#{project.name} | " \
+ "#{pipeline.short_sha}".to_s
expect(subject).to have_body_text merge_request.to_reference
expect(subject).to have_body_text pipeline.source_ref
@@ -71,9 +71,9 @@ RSpec.describe Emails::Pipelines do
it 'has correct information that there is a merge request link' do
expect(subject)
- .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \
- "#{status} for #{pipeline.source_ref} | " \
- "#{pipeline.short_sha} in !#{merge_request.iid}".to_s
+ .to have_subject "#{status} pipeline for #{pipeline.source_ref} | " \
+ "#{project.name} | " \
+ "#{pipeline.short_sha}".to_s
expect(subject).to have_body_text merge_request.to_reference
expect(subject).to have_body_text pipeline.source_ref
@@ -89,8 +89,8 @@ RSpec.describe Emails::Pipelines do
let(:sha) { project.commit(ref).sha }
it_behaves_like 'correct pipeline information' do
- let(:status) { 'succeeded' }
- let(:status_text) { 'Your pipeline has passed.' }
+ let(:status) { 'Succesful' }
+ let(:status_text) { "Pipeline ##{pipeline.id} has passed!" }
end
end
@@ -102,8 +102,8 @@ RSpec.describe Emails::Pipelines do
let(:sha) { project.commit(ref).sha }
it_behaves_like 'correct pipeline information' do
- let(:status) { 'failed' }
- let(:status_text) { 'Your pipeline has failed.' }
+ let(:status) { 'Failed' }
+ let(:status_text) { "Pipeline ##{pipeline.id} has failed!" }
end
end
@@ -115,8 +115,8 @@ RSpec.describe Emails::Pipelines do
let(:sha) { project.commit(ref).sha }
it_behaves_like 'correct pipeline information' do
- let(:status) { 'been fixed' }
- let(:status_text) { 'Your pipeline has been fixed!' }
+ let(:status) { 'Fixed' }
+ let(:status_text) { "Pipeline has been fixed and ##{pipeline.id} has passed!" }
end
end
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 3ebc2fc1e36..53ce200eed5 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -224,6 +224,10 @@ RSpec.describe Notify do
let(:model) { issue }
end
+ it 'contains a link to the issue' do
+ is_expected.to have_body_text(issue.to_reference(full: false))
+ end
+
it_behaves_like 'it should show Gmail Actions View Issue link'
it_behaves_like 'an unsubscribeable thread'
it_behaves_like 'appearance header and footer enabled'
@@ -1611,6 +1615,88 @@ RSpec.describe Notify do
is_expected.to have_body_text group_member.invite_email
end
end
+
+ describe 'group expiration date updated' do
+ let_it_be(:group_member) { create(:group_member, group: group, expires_at: 1.day.from_now) }
+
+ context 'when expiration date is changed' do
+ subject { described_class.member_expiration_date_updated_email('group', group_member.id) }
+
+ it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
+ it_behaves_like 'a user cannot unsubscribe through footer link'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
+ context 'when expiration date is one day away' do
+ it 'contains all the useful information' do
+ is_expected.to have_subject 'Group membership expiration date changed'
+ is_expected.to have_body_text group_member.user.name
+ is_expected.to have_body_text group.name
+ is_expected.to have_body_text group.web_url
+ is_expected.to have_body_text group_group_members_url(group, search: group_member.user.username)
+ is_expected.to have_body_text 'day.'
+ is_expected.not_to have_body_text 'days.'
+ end
+ end
+
+ context 'when expiration date is more than one day away' do
+ before do
+ group_member.update!(expires_at: 20.days.from_now)
+ end
+
+ it 'contains all the useful information' do
+ is_expected.to have_subject 'Group membership expiration date changed'
+ is_expected.to have_body_text group_member.user.name
+ is_expected.to have_body_text group.name
+ is_expected.to have_body_text group.web_url
+ is_expected.to have_body_text group_group_members_url(group, search: group_member.user.username)
+ is_expected.to have_body_text 'days.'
+ is_expected.not_to have_body_text 'day.'
+ end
+ end
+
+ context 'when a group member is newly given an expiration date' do
+ let_it_be(:group_member) { create(:group_member, group: group) }
+
+ before do
+ group_member.update!(expires_at: 5.days.from_now)
+ end
+
+ subject { described_class.member_expiration_date_updated_email('group', group_member.id) }
+
+ it 'contains all the useful information' do
+ is_expected.to have_subject 'Group membership expiration date changed'
+ is_expected.to have_body_text group_member.user.name
+ is_expected.to have_body_text group.name
+ is_expected.to have_body_text group.web_url
+ is_expected.to have_body_text group_group_members_url(group, search: group_member.user.username)
+ is_expected.to have_body_text 'days.'
+ is_expected.not_to have_body_text 'day.'
+ end
+ end
+ end
+
+ context 'when expiration date is removed' do
+ before do
+ group_member.update!(expires_at: nil)
+ end
+
+ subject { described_class.member_expiration_date_updated_email('group', group_member.id) }
+
+ it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
+ it_behaves_like 'a user cannot unsubscribe through footer link'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
+ it 'contains all the useful information' do
+ is_expected.to have_subject 'Group membership expiration date removed'
+ is_expected.to have_body_text group_member.user.name
+ is_expected.to have_body_text group.name
+ end
+ end
+ end
end
describe 'confirmation if email changed' do
diff --git a/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb b/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
new file mode 100644
index 00000000000..9a57d9bf84d
--- /dev/null
+++ b/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210112143418_remove_duplicate_services2.rb')
+
+RSpec.describe RemoveDuplicateServices2 do
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:services) { table(:services) }
+
+ describe '#up' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ namespaces.create!(id: 1, name: 'group', path: 'group')
+
+ projects.create!(id: 1, namespace_id: 1) # duplicate services
+ projects.create!(id: 2, namespace_id: 1) # normal services
+ projects.create!(id: 3, namespace_id: 1) # no services
+ projects.create!(id: 4, namespace_id: 1) # duplicate services
+ projects.create!(id: 5, namespace_id: 1) # duplicate services
+
+ services.create!(id: 1, project_id: 1, type: 'JiraService')
+ services.create!(id: 2, project_id: 1, type: 'JiraService')
+ services.create!(id: 3, project_id: 2, type: 'JiraService')
+ services.create!(id: 4, project_id: 4, type: 'AsanaService')
+ services.create!(id: 5, project_id: 4, type: 'AsanaService')
+ services.create!(id: 6, project_id: 4, type: 'JiraService')
+ services.create!(id: 7, project_id: 4, type: 'JiraService')
+ services.create!(id: 8, project_id: 4, type: 'SlackService')
+ services.create!(id: 9, project_id: 4, type: 'SlackService')
+ services.create!(id: 10, project_id: 5, type: 'JiraService')
+ services.create!(id: 11, project_id: 5, type: 'JiraService')
+
+ # Services without a project_id should be ignored
+ services.create!(id: 12, type: 'JiraService')
+ services.create!(id: 13, type: 'JiraService')
+ end
+
+ it 'schedules background jobs for all projects with duplicate services' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 4)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 5)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/add_has_external_wiki_trigger_spec.rb b/spec/migrations/add_has_external_wiki_trigger_spec.rb
new file mode 100644
index 00000000000..10c6888c87e
--- /dev/null
+++ b/spec/migrations/add_has_external_wiki_trigger_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddHasExternalWikiTrigger 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_wiki` to true when active `ExternalWikiService` is inserted' do
+ expect do
+ services.create!(type: 'ExternalWikiService', active: true, project_id: @project.id)
+ end.to change { @project.reload.has_external_wiki }.to(true)
+ end
+
+ it 'does not set `has_external_wiki` to true when service is for a different project' do
+ different_project = projects.create!(namespace_id: @namespace.id)
+
+ expect do
+ services.create!(type: 'ExternalWikiService', active: true, project_id: different_project.id)
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+
+ it 'does not set `has_external_wiki` to true when inactive `ExternalWikiService` is inserted' do
+ expect do
+ services.create!(type: 'ExternalWikiService', active: false, project_id: @project.id)
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+
+ it 'does not set `has_external_wiki` to true when active other service is inserted' do
+ expect do
+ services.create!(type: 'MyService', active: true, project_id: @project.id)
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+ end
+
+ describe 'UPDATE trigger' do
+ it 'sets `has_external_wiki` to true when `ExternalWikiService` is made active' do
+ service = services.create!(type: 'ExternalWikiService', active: false, project_id: @project.id)
+
+ expect do
+ service.update!(active: true)
+ end.to change { @project.reload.has_external_wiki }.to(true)
+ end
+
+ it 'sets `has_external_wiki` to false when `ExternalWikiService` is made inactive' do
+ service = services.create!(type: 'ExternalWikiService', active: true, project_id: @project.id)
+
+ expect do
+ service.update!(active: false)
+ end.to change { @project.reload.has_external_wiki }.to(false)
+ end
+
+ it 'does not change `has_external_wiki` when service is for a different project' do
+ different_project = projects.create!(namespace_id: @namespace.id)
+ service = services.create!(type: 'ExternalWikiService', active: false, project_id: different_project.id)
+
+ expect do
+ service.update!(active: true)
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+ end
+
+ describe 'DELETE trigger' do
+ it 'sets `has_external_wiki` to false when `ExternalWikiService` is deleted' do
+ service = services.create!(type: 'ExternalWikiService', active: true, project_id: @project.id)
+
+ expect do
+ service.delete
+ end.to change { @project.reload.has_external_wiki }.to(false)
+ end
+
+ it 'does not change `has_external_wiki` when service is for a different project' do
+ different_project = projects.create!(namespace_id: @namespace.id)
+ service = services.create!(type: 'ExternalWikiService', active: true, project_id: different_project.id)
+
+ expect do
+ service.delete
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the INSERT trigger' do
+ expect do
+ services.create!(type: 'ExternalWikiService', active: true, project_id: @project.id)
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+
+ it 'drops the UPDATE trigger' do
+ service = services.create!(type: 'ExternalWikiService', active: false, project_id: @project.id)
+ @project.update!(has_external_wiki: false)
+
+ expect do
+ service.update!(active: true)
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+
+ it 'drops the DELETE trigger' do
+ service = services.create!(type: 'ExternalWikiService', active: true, project_id: @project.id)
+ @project.update!(has_external_wiki: true)
+
+ expect do
+ service.delete
+ end.not_to change { @project.reload.has_external_wiki }
+ end
+ end
+end
diff --git a/spec/migrations/remove_alerts_service_records_spec.rb b/spec/migrations/remove_alerts_service_records_spec.rb
new file mode 100644
index 00000000000..eaf9f90b445
--- /dev/null
+++ b/spec/migrations/remove_alerts_service_records_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210107194543_remove_alerts_service_records.rb')
+
+RSpec.describe RemoveAlertsServiceRecords do
+ let(:services) { table(:services) }
+ let(:alerts_service_data) { table(:alerts_service_data) }
+
+ before do
+ 5.times do
+ service = services.create!(type: 'AlertsService')
+ alerts_service_data.create!(service_id: service.id)
+ end
+
+ services.create!(type: 'SomeOtherType')
+ end
+
+ it 'removes services records of type AlertsService and corresponding data', :aggregate_failures do
+ expect(services.count).to eq(6)
+ expect(alerts_service_data.count).to eq(5)
+
+ migrate!
+
+ expect(services.count).to eq(1)
+ expect(services.first.type).to eq('SomeOtherType')
+ expect(services.where(type: 'AlertsService')).to be_empty
+ expect(alerts_service_data.all).to be_empty
+ end
+end
diff --git a/spec/migrations/remove_duplicate_labels_from_groups_spec.rb b/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
new file mode 100644
index 00000000000..eff2c6a37e4
--- /dev/null
+++ b/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
@@ -0,0 +1,227 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200716234259_remove_duplicate_labels_from_group.rb')
+
+RSpec.describe RemoveDuplicateLabelsFromGroup do
+ let(:labels_table) { table(:labels) }
+ let(:labels) { labels_table.all }
+ let(:projects_table) { table(:projects) }
+ let(:projects) { projects_table.all }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:namespaces) { namespaces_table.all }
+ let(:backup_labels_table) { table(:backup_labels) }
+ let(:backup_labels) { backup_labels_table.all }
+ # for those cases where we can't use the activerecord class because the `type` column
+ # makes it think it has polymorphism and should be/have a Label subclass
+ let(:sql_backup_labels) { ApplicationRecord.connection.execute('SELECT * from backup_labels') }
+
+ # all the possible tables with records that may have a relationship with a label
+ let(:analytics_cycle_analytics_group_stages_table) { table(:analytics_cycle_analytics_group_stages) }
+ let(:analytics_cycle_analytics_project_stages_table) { table(:analytics_cycle_analytics_project_stages) }
+ let(:board_labels_table) { table(:board_labels) }
+ let(:label_links_table) { table(:label_links) }
+ let(:label_priorities_table) { table(:label_priorities) }
+ let(:lists_table) { table(:lists) }
+ let(:resource_label_events_table) { table(:resource_label_events) }
+
+ let!(:group_one) { namespaces_table.create!(id: 1, type: 'Group', name: 'group', path: 'group') }
+ let!(:project_one) do
+ projects_table.create!(id: 1, name: 'project', path: 'project',
+ visibility_level: 0, namespace_id: group_one.id)
+ end
+
+ let(:label_title) { 'bug' }
+ let(:label_color) { 'red' }
+ let(:label_description) { 'nice label' }
+ let(:project_id) { project_one.id }
+ let(:group_id) { group_one.id }
+ let(:other_title) { 'feature' }
+
+ let(:group_label_attributes) do
+ {
+ title: label_title, color: label_color, group_id: group_id, type: 'GroupLabel', template: false, description: label_description
+ }
+ end
+
+ let(:migration) { described_class.new }
+
+ describe 'removing full duplicates' do
+ context 'when there are no duplicate labels' do
+ let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1, title: "a different label")) }
+ let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2, title: "a totally different label")) }
+
+ it 'does not remove anything' do
+ expect { migration.up }.not_to change { backup_labels_table.count }
+ end
+
+ it 'restores removed records when rolling back - no change' do
+ migration.up
+
+ expect { migration.down }.not_to change { labels_table.count }
+ end
+ end
+
+ context 'with duplicates with no relationships' do
+ let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1)) }
+ let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2)) }
+ let!(:third_label) { labels_table.create!(group_label_attributes.merge(id: 3, title: other_title)) }
+ let!(:fourth_label) { labels_table.create!(group_label_attributes.merge(id: 4, title: other_title)) }
+
+ it 'creates a backup record for each removed record' do
+ expect { migration.up }.to change { backup_labels_table.count }.from(0).to(2)
+ end
+
+ it 'creates the correct backup records with `create` restore_action' do
+ migration.up
+
+ expect(sql_backup_labels.find { |bl| bl["id"] == 2 }).to include(second_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
+ expect(sql_backup_labels.find { |bl| bl["id"] == 4 }).to include(fourth_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
+ end
+
+ it 'deletes all but one' do
+ migration.up
+
+ expect { second_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { fourth_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'restores removed records on rollback' do
+ second_label_attributes = modified_attributes(second_label)
+ fourth_label_attributes = modified_attributes(fourth_label)
+
+ migration.up
+
+ migration.down
+
+ expect(second_label.attributes).to include(second_label_attributes)
+ expect(fourth_label.attributes).to include(fourth_label_attributes)
+ end
+ end
+
+ context 'two duplicate records, one of which has a relationship' do
+ let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1)) }
+ let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2)) }
+ let!(:label_priority) { label_priorities_table.create!(label_id: second_label.id, project_id: project_id, priority: 1) }
+
+ it 'does not remove anything' do
+ expect { migration.up }.not_to change { labels_table.count }
+ end
+
+ it 'does not create a backup record with `create` restore_action' do
+ expect { migration.up }.not_to change { backup_labels_table.where(restore_action: described_class::CREATE).count }
+ end
+
+ it 'restores removed records when rolling back - no change' do
+ migration.up
+
+ expect { migration.down }.not_to change { labels_table.count }
+ end
+ end
+
+ context 'multiple duplicates, a subset of which have relationships' do
+ let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1)) }
+ let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2)) }
+ let!(:label_priority_for_second_label) { label_priorities_table.create!(label_id: second_label.id, project_id: project_id, priority: 1) }
+ let!(:third_label) { labels_table.create!(group_label_attributes.merge(id: 3)) }
+ let!(:fourth_label) { labels_table.create!(group_label_attributes.merge(id: 4)) }
+ let!(:label_priority_for_fourth_label) { label_priorities_table.create!(label_id: fourth_label.id, project_id: project_id, priority: 2) }
+
+ it 'creates a backup record with `create` restore_action for each removed record' do
+ expect { migration.up }.to change { backup_labels_table.where(restore_action: described_class::CREATE).count }.from(0).to(1)
+ end
+
+ it 'creates the correct backup records' do
+ migration.up
+
+ expect(sql_backup_labels.find { |bl| bl["id"] == 3 }).to include(third_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
+ end
+
+ it 'deletes the duplicate record' do
+ migration.up
+
+ expect { first_label.reload }.not_to raise_error
+ expect { second_label.reload }.not_to raise_error
+ expect { third_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'restores removed records on rollback' do
+ third_label_attributes = modified_attributes(third_label)
+
+ migration.up
+ migration.down
+
+ expect(third_label.attributes).to include(third_label_attributes)
+ end
+ end
+ end
+
+ describe 'renaming partial duplicates' do
+ # partial duplicates - only group_id and title match. Distinct colour prevents deletion.
+ context 'when there are no duplicate labels' do
+ let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1, title: "a unique label", color: 'green')) }
+ let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2, title: "a totally different, unique, label", color: 'blue')) }
+
+ it 'does not rename anything' do
+ expect { migration.up }.not_to change { backup_labels_table.count }
+ end
+ end
+
+ context 'with duplicates with no relationships' do
+ let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1, color: 'green')) }
+ let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2, color: 'blue')) }
+ let!(:third_label) { labels_table.create!(group_label_attributes.merge(id: 3, title: other_title, color: 'purple')) }
+ let!(:fourth_label) { labels_table.create!(group_label_attributes.merge(id: 4, title: other_title, color: 'yellow')) }
+
+ it 'creates a backup record for each renamed record' do
+ expect { migration.up }.to change { backup_labels_table.count }.from(0).to(2)
+ end
+
+ it 'creates the correct backup records with `rename` restore_action' do
+ migration.up
+
+ expect(sql_backup_labels.find { |bl| bl["id"] == 2 }).to include(second_label.attributes.merge("restore_action" => described_class::RENAME, "created_at" => anything, "updated_at" => anything))
+ expect(sql_backup_labels.find { |bl| bl["id"] == 4 }).to include(fourth_label.attributes.merge("restore_action" => described_class::RENAME, "created_at" => anything, "updated_at" => anything))
+ end
+
+ it 'modifies the titles of the partial duplicates' do
+ migration.up
+
+ expect(second_label.reload.title).to match(/#{label_title}_duplicate#{second_label.id}$/)
+ expect(fourth_label.reload.title).to match(/#{other_title}_duplicate#{fourth_label.id}$/)
+ end
+
+ it 'restores renamed records on rollback' do
+ second_label_attributes = modified_attributes(second_label)
+ fourth_label_attributes = modified_attributes(fourth_label)
+
+ migration.up
+
+ migration.down
+
+ expect(second_label.reload.attributes).to include(second_label_attributes)
+ expect(fourth_label.reload.attributes).to include(fourth_label_attributes)
+ end
+
+ context 'when the labels have a long title that might overflow' do
+ let(:long_title) { "a" * 255 }
+
+ before do
+ first_label.update_attribute(:title, long_title)
+ second_label.update_attribute(:title, long_title)
+ end
+
+ it 'keeps the length within the limit' do
+ migration.up
+
+ expect(second_label.reload.title).to eq("#{"a" * 244}_duplicate#{second_label.id}")
+ expect(second_label.title.length).to eq(255)
+ end
+ end
+ end
+ end
+
+ def modified_attributes(label)
+ label.attributes.except('created_at', 'updated_at')
+ end
+end
diff --git a/spec/migrations/schedule_populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/migrations/schedule_populate_finding_uuid_for_vulnerability_feedback_spec.rb
new file mode 100644
index 00000000000..d8bdefd5546
--- /dev/null
+++ b/spec/migrations/schedule_populate_finding_uuid_for_vulnerability_feedback_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe SchedulePopulateFindingUuidForVulnerabilityFeedback do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:users) { table(:users) }
+ let(:vulnerability_feedback) { table(:vulnerability_feedback) }
+
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
+ let(:user) { users.create!(username: 'john.doe', projects_limit: 1) }
+
+ let(:common_feedback_params) { { feedback_type: 0, category: 0, project_id: project.id, author_id: user.id } }
+ let!(:feedback_1) { vulnerability_feedback.create!(**common_feedback_params, project_fingerprint: 'foo') }
+ let!(:feedback_2) { vulnerability_feedback.create!(**common_feedback_params, project_fingerprint: 'bar') }
+ let!(:feedback_3) { vulnerability_feedback.create!(**common_feedback_params, project_fingerprint: 'zoo', finding_uuid: SecureRandom.uuid) }
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+ end
+
+ it 'schedules the background jobs', :aggregate_failures do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to be(3)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2.minutes, feedback_1.id, feedback_1.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(4.minutes, feedback_2.id, feedback_2.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(6.minutes, feedback_3.id, feedback_3.id)
+ end
+end
diff --git a/spec/models/alert_management/http_integration_spec.rb b/spec/models/alert_management/http_integration_spec.rb
index 910df51801a..ddd65e723eb 100644
--- a/spec/models/alert_management/http_integration_spec.rb
+++ b/spec/models/alert_management/http_integration_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe AlertManagement::HttpIntegration do
context 'with valid JSON schema' do
let(:attribute_mapping) do
{
- title: { path: %w(a b c), type: 'string' },
+ title: { path: %w(a b c), type: 'string', label: 'Title' },
description: { path: %w(a), type: 'string' }
}
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index ea03cbc3706..4755d700d72 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -72,6 +72,7 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:push_event_activities_limit) }
it { is_expected.to validate_numericality_of(:container_registry_delete_tags_service_timeout).only_integer.is_greater_than_or_equal_to(0) }
+ it { is_expected.to validate_numericality_of(:container_registry_cleanup_tags_service_max_list_size).only_integer.is_greater_than_or_equal_to(0) }
it { is_expected.to validate_numericality_of(:container_registry_expiration_policies_worker_capacity).only_integer.is_greater_than_or_equal_to(0) }
it { is_expected.to validate_numericality_of(:snippet_size_limit).only_integer.is_greater_than(0) }
@@ -313,7 +314,7 @@ RSpec.describe ApplicationSetting do
it { is_expected.to validate_presence_of(:max_attachment_size) }
- it do
+ specify do
is_expected.to validate_numericality_of(:max_attachment_size)
.only_integer
.is_greater_than(0)
@@ -321,13 +322,13 @@ RSpec.describe ApplicationSetting do
it { is_expected.to validate_presence_of(:max_import_size) }
- it do
+ specify do
is_expected.to validate_numericality_of(:max_import_size)
.only_integer
.is_greater_than_or_equal_to(0)
end
- it do
+ specify do
is_expected.to validate_numericality_of(:local_markdown_version)
.only_integer
.is_greater_than_or_equal_to(0)
@@ -472,7 +473,7 @@ RSpec.describe ApplicationSetting do
end
[:gitaly_timeout_default, :gitaly_timeout_medium, :gitaly_timeout_fast].each do |timeout_name|
- it do
+ specify do
is_expected.to validate_presence_of(timeout_name)
is_expected.to validate_numericality_of(timeout_name).only_integer
.is_greater_than_or_equal_to(0)
@@ -733,6 +734,27 @@ RSpec.describe ApplicationSetting do
is_expected.to be_invalid
end
end
+
+ context 'throttle_* settings' do
+ where(:throttle_setting) do
+ %i[
+ throttle_unauthenticated_requests_per_period
+ throttle_unauthenticated_period_in_seconds
+ throttle_authenticated_api_requests_per_period
+ throttle_authenticated_api_period_in_seconds
+ throttle_authenticated_web_requests_per_period
+ throttle_authenticated_web_period_in_seconds
+ ]
+ end
+
+ with_them do
+ it { is_expected.to allow_value(3).for(throttle_setting) }
+ it { is_expected.not_to allow_value(-3).for(throttle_setting) }
+ it { is_expected.not_to allow_value(0).for(throttle_setting) }
+ it { is_expected.not_to allow_value('three').for(throttle_setting) }
+ it { is_expected.not_to allow_value(nil).for(throttle_setting) }
+ end
+ end
end
context 'restrict creating duplicates' do
@@ -821,7 +843,7 @@ RSpec.describe ApplicationSetting do
context 'validations' do
it { is_expected.to validate_presence_of(:diff_max_patch_bytes) }
- it do
+ specify do
is_expected.to validate_numericality_of(:diff_max_patch_bytes)
.only_integer
.is_greater_than_or_equal_to(Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES)
@@ -850,12 +872,13 @@ RSpec.describe ApplicationSetting do
end
end
- describe '#instance_review_permitted?', :request_store do
+ describe '#instance_review_permitted?', :request_store, :use_clean_rails_memory_store_caching do
subject { setting.instance_review_permitted? }
before do
- RequestStore.store[:current_license] = nil
- expect(Rails.cache).to receive(:fetch).and_return(
+ allow(License).to receive(:current).and_return(nil) if Gitlab.ee?
+ allow(Rails.cache).to receive(:fetch).and_call_original
+ expect(Rails.cache).to receive(:fetch).with('limited_users_count', anything).and_return(
::ApplicationSetting::INSTANCE_REVIEW_MIN_USERS + users_over_minimum
)
end
diff --git a/spec/models/audit_event_archived_spec.rb b/spec/models/audit_event_archived_spec.rb
new file mode 100644
index 00000000000..43a2e8434b0
--- /dev/null
+++ b/spec/models/audit_event_archived_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuditEventArchived do
+ let(:source_table) { AuditEvent }
+ let(:destination_table) { described_class }
+
+ it 'has the same columns as the source table' do
+ column_names_from_source_table = column_names(source_table)
+ column_names_from_destination_table = column_names(destination_table)
+
+ expect(column_names_from_destination_table).to match_array(column_names_from_source_table)
+ end
+
+ it 'has the same null constraints as the source table' do
+ constraints_from_source_table = null_constraints(source_table)
+ constraints_from_destination_table = null_constraints(destination_table)
+
+ expect(constraints_from_destination_table.to_a).to match_array(constraints_from_source_table.to_a)
+ end
+
+ it 'inserts the same record as the one in the source table', :aggregate_failures do
+ expect { create(:audit_event) }.to change { destination_table.count }.by(1)
+
+ event_from_source_table = source_table.connection.select_one(
+ "SELECT * FROM #{source_table.table_name} ORDER BY created_at desc LIMIT 1"
+ )
+ event_from_destination_table = destination_table.connection.select_one(
+ "SELECT * FROM #{destination_table.table_name} ORDER BY created_at desc LIMIT 1"
+ )
+
+ expect(event_from_destination_table).to eq(event_from_source_table)
+ end
+
+ def column_names(table)
+ table.connection.select_all(<<~SQL)
+ SELECT c.column_name
+ FROM information_schema.columns c
+ WHERE c.table_name = '#{table.table_name}'
+ SQL
+ end
+
+ def null_constraints(table)
+ table.connection.select_all(<<~SQL)
+ SELECT c.column_name, c.is_nullable
+ FROM information_schema.columns c
+ WHERE c.table_name = '#{table.table_name}'
+ AND c.column_name != 'created_at'
+ SQL
+ end
+end
diff --git a/spec/models/audit_event_partitioned_spec.rb b/spec/models/audit_event_partitioned_spec.rb
deleted file mode 100644
index ab48e291f78..00000000000
--- a/spec/models/audit_event_partitioned_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AuditEventPartitioned do
- let(:source_table) { AuditEvent }
- let(:partitioned_table) { described_class }
-
- it 'has the same columns as the source table' do
- column_names_from_source_table = column_names(source_table)
- column_names_from_partioned_table = column_names(partitioned_table)
-
- expect(column_names_from_partioned_table).to match_array(column_names_from_source_table)
- end
-
- it 'has the same null constraints as the source table' do
- constraints_from_source_table = null_constraints(source_table)
- constraints_from_partitioned_table = null_constraints(partitioned_table)
-
- expect(constraints_from_partitioned_table.to_a).to match_array(constraints_from_source_table.to_a)
- end
-
- it 'inserts the same record as the one in the source table', :aggregate_failures do
- expect { create(:audit_event) }.to change { partitioned_table.count }.by(1)
-
- event_from_source_table = source_table.connection.select_one(
- "SELECT * FROM #{source_table.table_name} ORDER BY created_at desc LIMIT 1"
- )
- event_from_partitioned_table = partitioned_table.connection.select_one(
- "SELECT * FROM #{partitioned_table.table_name} ORDER BY created_at desc LIMIT 1"
- )
-
- expect(event_from_partitioned_table).to eq(event_from_source_table)
- end
-
- def column_names(table)
- table.connection.select_all(<<~SQL)
- SELECT c.column_name
- FROM information_schema.columns c
- WHERE c.table_name = '#{table.table_name}'
- SQL
- end
-
- def null_constraints(table)
- table.connection.select_all(<<~SQL)
- SELECT c.column_name, c.is_nullable
- FROM information_schema.columns c
- WHERE c.table_name = '#{table.table_name}'
- AND c.column_name != 'created_at'
- SQL
- end
-end
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 11dcecd50ca..4f09f6f1da4 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -356,14 +356,6 @@ RSpec.describe Ci::Bridge do
describe '#dependency_variables' do
subject { bridge.dependency_variables }
- shared_context 'when ci_bridge_dependency_variables is disabled' do
- before do
- stub_feature_flags(ci_bridge_dependency_variables: false)
- end
-
- it { is_expected.to be_empty }
- end
-
context 'when downloading from previous stages' do
let!(:prepare1) { create(:ci_build, name: 'prepare1', pipeline: pipeline, stage_idx: 0) }
let!(:bridge) { create(:ci_bridge, pipeline: pipeline, stage_idx: 1) }
@@ -374,8 +366,6 @@ RSpec.describe Ci::Bridge do
it 'inherits only dependent variables' do
expect(subject.to_hash).to eq(job_variable_1.key => job_variable_1.value)
end
-
- it_behaves_like 'when ci_bridge_dependency_variables is disabled'
end
context 'when using needs' do
@@ -397,8 +387,6 @@ RSpec.describe Ci::Bridge do
it 'inherits only needs with artifacts variables' do
expect(subject.to_hash).to eq(job_variable_1.key => job_variable_1.value)
end
-
- it_behaves_like 'when ci_bridge_dependency_variables is disabled'
end
end
end
diff --git a/spec/models/ci/build_need_spec.rb b/spec/models/ci/build_need_spec.rb
index 43cce073918..c2cf9027055 100644
--- a/spec/models/ci/build_need_spec.rb
+++ b/spec/models/ci/build_need_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Ci::BuildNeed, model: true do
let(:build_need) { build(:ci_build_need) }
- it { is_expected.to belong_to(:build) }
+ it { is_expected.to belong_to(:build).class_name('Ci::Processable') }
it { is_expected.to validate_presence_of(:build) }
it { is_expected.to validate_presence_of(:name) }
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 9f412d64d56..c2029b9240b 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -717,6 +717,22 @@ RSpec.describe Ci::Build do
end
end
+ describe '#artifacts_public?' do
+ subject { build.artifacts_public? }
+
+ context 'artifacts with defaults' do
+ let(:build) { create(:ci_build, :artifacts) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'non public artifacts' do
+ let(:build) { create(:ci_build, :artifacts, :non_public_artifacts) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
describe '#artifacts_expired?' do
subject { build.artifacts_expired? }
@@ -1149,26 +1165,12 @@ RSpec.describe Ci::Build do
end
context 'when transits to skipped' do
- context 'when cd_skipped_deployment_status is disabled' do
- before do
- stub_feature_flags(cd_skipped_deployment_status: false)
- build.skip!
- end
-
- it 'transits deployment status to canceled' do
- expect(deployment).to be_canceled
- end
+ before do
+ build.skip!
end
- context 'when cd_skipped_deployment_status is enabled' do
- before do
- stub_feature_flags(cd_skipped_deployment_status: project)
- build.skip!
- end
-
- it 'transits deployment status to skipped' do
- expect(deployment).to be_skipped
- end
+ it 'transits deployment status to skipped' do
+ expect(deployment).to be_skipped
end
end
@@ -2456,6 +2458,7 @@ RSpec.describe Ci::Build do
{ key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true, masked: false },
{ key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: project.repository_languages.map(&:name).join(',').downcase, public: true, masked: false },
{ key: 'CI_DEFAULT_BRANCH', value: project.default_branch, public: true, masked: false },
+ { key: 'CI_PROJECT_CONFIG_PATH', value: project.ci_config_path_or_default, public: true, masked: false },
{ key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true, masked: false },
{ key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
{ key: 'CI_DEPENDENCY_PROXY_SERVER', value: "#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}", public: true, masked: false },
@@ -2986,7 +2989,7 @@ RSpec.describe Ci::Build do
let(:ci_config_path) { { key: 'CI_CONFIG_PATH', value: 'custom', public: true, masked: false } }
before do
- expect_any_instance_of(Project).to receive(:ci_config_path) { 'custom' }
+ project.update!(ci_config_path: 'custom')
end
it { is_expected.to include(ci_config_path) }
@@ -4343,7 +4346,7 @@ RSpec.describe Ci::Build do
end
describe '#supported_runner?' do
- let_it_be(:build) { create(:ci_build) }
+ let_it_be_with_refind(:build) { create(:ci_build) }
subject { build.supported_runner?(runner_features) }
@@ -4408,6 +4411,41 @@ RSpec.describe Ci::Build do
it { is_expected.to be_falsey }
end
end
+
+ context 'when `return_exit_code` feature is required by build' do
+ let(:options) { { allow_failure_criteria: { exit_codes: [1] } } }
+
+ before do
+ build.update!(options: options)
+ end
+
+ context 'when runner provides given feature' do
+ let(:runner_features) { { return_exit_code: true } }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when runner does not provide given feature' do
+ let(:runner_features) { {} }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the runner does not provide all of the required features' do
+ let(:options) do
+ {
+ allow_failure_criteria: { exit_codes: [1] },
+ artifacts: { reports: { junit: "junit.xml" } }
+ }
+ end
+
+ let(:runner_features) { { return_exit_code: true } }
+
+ it 'requires `upload_multiple_artifacts` too' do
+ is_expected.to be_falsey
+ end
+ end
+ end
end
describe '#deployment_status' do
@@ -4737,22 +4775,6 @@ RSpec.describe Ci::Build do
describe '#debug_mode?' do
subject { build.debug_mode? }
- context 'when feature is disabled' do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- end
-
- it { is_expected.to eq false }
-
- context 'when in variables' do
- before do
- create(:ci_instance_variable, key: 'CI_DEBUG_TRACE', value: 'true')
- end
-
- it { is_expected.to eq false }
- end
- end
-
context 'when CI_DEBUG_TRACE=true is in variables' do
context 'when in instance variables' do
before do
@@ -4807,4 +4829,159 @@ RSpec.describe Ci::Build do
it { is_expected.to eq false }
end
end
+
+ describe '#drop_with_exit_code!' do
+ let(:exit_code) { 1 }
+ let(:options) { {} }
+
+ before do
+ build.options.merge!(options)
+ build.save!
+ end
+
+ subject(:drop_with_exit_code) do
+ build.drop_with_exit_code!(:unknown_failure, exit_code)
+ end
+
+ shared_examples 'drops the build without changing allow_failure' do
+ it 'does not change allow_failure' do
+ expect { drop_with_exit_code }
+ .not_to change { build.reload.allow_failure }
+ end
+
+ it 'drops the build' do
+ expect { drop_with_exit_code }
+ .to change { build.reload.failed? }
+ end
+ end
+
+ context 'when exit_codes are not defined' do
+ it_behaves_like 'drops the build without changing allow_failure'
+ end
+
+ context 'when allow_failure_criteria is nil' do
+ let(:options) { { allow_failure_criteria: nil } }
+
+ it_behaves_like 'drops the build without changing allow_failure'
+ end
+
+ context 'when exit_codes is nil' do
+ let(:options) do
+ {
+ allow_failure_criteria: {
+ exit_codes: nil
+ }
+ }
+ end
+
+ it_behaves_like 'drops the build without changing allow_failure'
+ end
+
+ context 'when exit_codes do not match' do
+ let(:options) do
+ {
+ allow_failure_criteria: {
+ exit_codes: [2, 3, 4]
+ }
+ }
+ end
+
+ it_behaves_like 'drops the build without changing allow_failure'
+ end
+
+ context 'with matching exit codes' do
+ let(:options) do
+ { allow_failure_criteria: { exit_codes: [1, 2, 3] } }
+ end
+
+ it 'changes allow_failure' do
+ expect { drop_with_exit_code }
+ .to change { build.reload.allow_failure }
+ end
+
+ it 'drops the build' do
+ expect { drop_with_exit_code }
+ .to change { build.reload.failed? }
+ end
+
+ it 'is executed inside a transaction' do
+ expect(build).to receive(:drop!)
+ .with(:unknown_failure)
+ .and_raise(ActiveRecord::Rollback)
+
+ expect(build).to receive(:conditionally_allow_failure!)
+ .with(1)
+ .and_call_original
+
+ expect { drop_with_exit_code }
+ .not_to change { build.reload.allow_failure }
+ end
+
+ context 'when exit_code is nil' do
+ let(:exit_code) {}
+
+ 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
+
+ describe '#exit_codes_defined?' do
+ let(:options) { {} }
+
+ before do
+ build.options.merge!(options)
+ end
+
+ subject(:exit_codes_defined) do
+ build.exit_codes_defined?
+ end
+
+ context 'without allow_failure_criteria' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when exit_codes is nil' do
+ let(:options) do
+ {
+ allow_failure_criteria: {
+ exit_codes: nil
+ }
+ }
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when exit_codes is an empty array' do
+ let(:options) do
+ {
+ allow_failure_criteria: {
+ exit_codes: []
+ }
+ }
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when exit_codes are defined' do
+ let(:options) do
+ {
+ allow_failure_criteria: {
+ exit_codes: [5, 6]
+ }
+ }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/models/ci/commit_with_pipeline_spec.rb b/spec/models/ci/commit_with_pipeline_spec.rb
new file mode 100644
index 00000000000..4dd288bde62
--- /dev/null
+++ b/spec/models/ci/commit_with_pipeline_spec.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CommitWithPipeline do
+ let(:project) { create(:project, :public, :repository) }
+ let(:commit) { described_class.new(project.commit) }
+
+ describe '#last_pipeline' do
+ let!(:first_pipeline) do
+ create(:ci_empty_pipeline,
+ project: project,
+ sha: commit.sha,
+ status: 'success')
+ end
+
+ let!(:second_pipeline) do
+ create(:ci_empty_pipeline,
+ project: project,
+ sha: commit.sha,
+ status: 'success')
+ end
+
+ it 'returns last pipeline' do
+ expect(commit.last_pipeline).to eq second_pipeline
+ end
+ end
+
+ describe '#latest_pipeline' do
+ let(:pipeline) { double }
+
+ shared_examples_for 'fetching latest pipeline' do |ref|
+ it 'returns the latest pipeline for the project' do
+ expect(commit)
+ .to receive(:latest_pipeline_for_project)
+ .with(ref, project)
+ .and_return(pipeline)
+
+ expect(result).to eq(pipeline)
+ end
+
+ it "returns the memoized pipeline for the key of #{ref}" do
+ commit.set_latest_pipeline_for_ref(ref, pipeline)
+
+ expect(commit)
+ .not_to receive(:latest_pipeline_for_project)
+
+ expect(result).to eq(pipeline)
+ end
+ end
+
+ context 'without ref argument' do
+ let(:result) { commit.latest_pipeline }
+
+ it_behaves_like 'fetching latest pipeline', nil
+ end
+
+ context 'when a particular ref is specified' do
+ let(:result) { commit.latest_pipeline('master') }
+
+ it_behaves_like 'fetching latest pipeline', 'master'
+ end
+ end
+
+ describe '#latest_pipeline_for_project' do
+ let(:project_pipelines) { double }
+ let(:pipeline_project) { double }
+ let(:pipeline) { double }
+ let(:ref) { 'master' }
+ let(:result) { commit.latest_pipeline_for_project(ref, pipeline_project) }
+
+ before do
+ allow(pipeline_project).to receive(:ci_pipelines).and_return(project_pipelines)
+ end
+
+ it 'returns the latest pipeline of the commit for the given ref and project' do
+ expect(project_pipelines)
+ .to receive(:latest_pipeline_per_commit)
+ .with(commit.id, ref)
+ .and_return(commit.id => pipeline)
+
+ expect(result).to eq(pipeline)
+ end
+ end
+
+ describe '#set_latest_pipeline_for_ref' do
+ let(:pipeline) { double }
+
+ it 'sets the latest pipeline for a given reference' do
+ commit.set_latest_pipeline_for_ref('master', pipeline)
+
+ expect(commit.latest_pipeline('master')).to eq(pipeline)
+ end
+ end
+
+ describe "#status" do
+ it 'returns the status of the latest pipeline for the given ref' do
+ expect(commit)
+ .to receive(:latest_pipeline)
+ .with('master')
+ .and_return(double(status: 'success'))
+
+ expect(commit.status('master')).to eq('success')
+ end
+
+ it 'returns nil when latest pipeline is not present for the given ref' do
+ expect(commit)
+ .to receive(:latest_pipeline)
+ .with('master')
+ .and_return(nil)
+
+ expect(commit.status('master')).to eq(nil)
+ end
+
+ it 'returns the status of the latest pipeline when no ref is given' do
+ expect(commit)
+ .to receive(:latest_pipeline)
+ .with(nil)
+ .and_return(double(status: 'success'))
+
+ expect(commit.status).to eq('success')
+ end
+ end
+end
diff --git a/spec/models/ci/group_spec.rb b/spec/models/ci/group_spec.rb
index c20b7e61044..6c96e659a34 100644
--- a/spec/models/ci/group_spec.rb
+++ b/spec/models/ci/group_spec.rb
@@ -54,6 +54,18 @@ RSpec.describe Ci::Group do
.to be_a(Gitlab::Ci::Status::Failed)
end
end
+
+ context 'when one of the commit statuses in the group is allowed to fail' do
+ let(:jobs) do
+ [create(:ci_build, :failed, :allowed_to_fail),
+ create(:ci_build, :success)]
+ end
+
+ it 'fabricates a new detailed status object' do
+ expect(subject.detailed_status(double(:user)))
+ .to be_a(Gitlab::Ci::Status::SuccessWarning)
+ end
+ end
end
describe '.fabricate' do
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index ef21ca8f100..796947be4c8 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -219,6 +219,39 @@ RSpec.describe Ci::JobArtifact do
end
end
+ describe '.unlocked' do
+ let_it_be(:job_artifact) { create(:ci_job_artifact) }
+
+ context 'with locked pipelines' do
+ before do
+ job_artifact.job.pipeline.artifacts_locked!
+ end
+
+ it 'returns an empty array' do
+ expect(described_class.unlocked).to be_empty
+ end
+ end
+
+ context 'with unlocked pipelines' do
+ before do
+ job_artifact.job.pipeline.unlocked!
+ end
+
+ it 'returns the artifact' do
+ expect(described_class.unlocked).to eq([job_artifact])
+ end
+ end
+ end
+
+ describe '.order_expired_desc' do
+ let_it_be(:first_artifact) { create(:ci_job_artifact, expire_at: 2.days.ago) }
+ let_it_be(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+
+ it 'returns ordered artifacts' do
+ expect(described_class.order_expired_desc).to eq([second_artifact, first_artifact])
+ end
+ end
+
describe 'callbacks' do
describe '#schedule_background_upload' do
subject { create(:ci_job_artifact, :archive) }
diff --git a/spec/models/ci/ref_spec.rb b/spec/models/ci/ref_spec.rb
index cb62646532c..0a9cd5ef2ec 100644
--- a/spec/models/ci/ref_spec.rb
+++ b/spec/models/ci/ref_spec.rb
@@ -16,35 +16,49 @@ RSpec.describe Ci::Ref do
stub_const('Ci::PipelineSuccessUnlockArtifactsWorker', unlock_artifacts_worker_spy)
end
- where(:initial_state, :action, :count) do
- :unknown | :succeed! | 1
- :unknown | :do_fail! | 0
- :success | :succeed! | 1
- :success | :do_fail! | 0
- :failed | :succeed! | 1
- :failed | :do_fail! | 0
- :fixed | :succeed! | 1
- :fixed | :do_fail! | 0
- :broken | :succeed! | 1
- :broken | :do_fail! | 0
- :still_failing | :succeed | 1
- :still_failing | :do_fail | 0
- end
+ context 'pipline is locked' do
+ let!(:pipeline) { create(:ci_pipeline, ci_ref_id: ci_ref.id, locked: :artifacts_locked) }
+
+ where(:initial_state, :action, :count) do
+ :unknown | :succeed! | 1
+ :unknown | :do_fail! | 0
+ :success | :succeed! | 1
+ :success | :do_fail! | 0
+ :failed | :succeed! | 1
+ :failed | :do_fail! | 0
+ :fixed | :succeed! | 1
+ :fixed | :do_fail! | 0
+ :broken | :succeed! | 1
+ :broken | :do_fail! | 0
+ :still_failing | :succeed | 1
+ :still_failing | :do_fail | 0
+ end
- with_them do
- context "when transitioning states" do
- before do
- status_value = Ci::Ref.state_machines[:status].states[initial_state].value
- ci_ref.update!(status: status_value)
- end
+ with_them do
+ context "when transitioning states" do
+ before do
+ status_value = Ci::Ref.state_machines[:status].states[initial_state].value
+ ci_ref.update!(status: status_value)
+ end
- it 'calls unlock artifacts service' do
- ci_ref.send(action)
+ it 'calls unlock artifacts service' do
+ ci_ref.send(action)
- expect(unlock_artifacts_worker_spy).to have_received(:perform_async).exactly(count).times
+ expect(unlock_artifacts_worker_spy).to have_received(:perform_async).exactly(count).times
+ end
end
end
end
+
+ context 'pipeline is unlocked' do
+ let!(:pipeline) { create(:ci_pipeline, ci_ref_id: ci_ref.id, locked: :unlocked) }
+
+ it 'does not call unlock artifacts service' do
+ ci_ref.succeed!
+
+ expect(unlock_artifacts_worker_spy).not_to have_received(:perform_async)
+ end
+ end
end
end
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index 41b4ec86233..d0e470bfa42 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -150,7 +150,7 @@ RSpec.describe Clusters::Applications::Knative do
subject { knative.install_command }
it 'is initialized with latest version' do
- expect(subject.version).to eq('0.9.0')
+ expect(subject.version).to eq('0.10.0')
end
it_behaves_like 'a command'
@@ -204,8 +204,8 @@ RSpec.describe Clusters::Applications::Knative do
expect(subject.postdelete).to include(*remove_knative_istio_leftovers_script)
expect(subject.postdelete.size).to eq(full_delete_commands_size)
- expect(subject.postdelete[2]).to eq("kubectl api-resources -o name --api-group #{api_groups[0]} | xargs kubectl delete --ignore-not-found crd")
- expect(subject.postdelete[3]).to eq("kubectl api-resources -o name --api-group #{api_groups[1]} | xargs kubectl delete --ignore-not-found crd")
+ expect(subject.postdelete[2]).to include("kubectl api-resources -o name --api-group #{api_groups[0]} | xargs -r kubectl delete --ignore-not-found crd")
+ expect(subject.postdelete[3]).to include("kubectl api-resources -o name --api-group #{api_groups[1]} | xargs -r kubectl delete --ignore-not-found crd")
end
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index cfa87b3e39e..acbabee9383 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -428,6 +428,19 @@ eos
allow(commit).to receive(:safe_message).and_return(message)
expect(commit.description).to eq(message)
end
+
+ it 'truncates html representation if more than 1Mib' do
+ # Commit message is over 2MiB
+ huge_commit_message = ['panic', ('panic ' * 350000), 'trailing text'].join("\n")
+
+ allow(commit).to receive(:safe_message).and_return(huge_commit_message)
+
+ commit.refresh_markdown_cache
+ description_html = commit.description_html
+
+ expect(description_html.bytesize).to be < 2.megabytes
+ expect(description_html).not_to include('trailing text')
+ end
end
describe "delegation" do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 9824eb91bc7..532f68c2f18 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -61,6 +61,22 @@ RSpec.describe CommitStatus do
expect(commit_status.started_at).to be_present
end
end
+
+ describe 'transitioning to created from skipped or manual' do
+ let(:commit_status) { create(:commit_status, :skipped) }
+
+ it 'does not update user without parameter' do
+ commit_status.process!
+
+ expect { commit_status.process }.not_to change { commit_status.reload.user }
+ end
+
+ it 'updates user with user parameter' do
+ new_user = create(:user)
+
+ expect { commit_status.process(new_user) }.to change { commit_status.reload.user }.to(new_user)
+ end
+ end
end
describe '#processed' do
@@ -503,6 +519,9 @@ RSpec.describe CommitStatus do
subject { commit_status.group_name }
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 test' | 'rspec:windows 0 test'
diff --git a/spec/models/commit_with_pipeline_spec.rb b/spec/models/commit_with_pipeline_spec.rb
deleted file mode 100644
index c4b6deebae0..00000000000
--- a/spec/models/commit_with_pipeline_spec.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe CommitWithPipeline do
- let(:project) { create(:project, :public, :repository) }
- let(:commit) { described_class.new(project.commit) }
-
- describe '#last_pipeline' do
- let!(:first_pipeline) do
- create(:ci_empty_pipeline,
- project: project,
- sha: commit.sha,
- status: 'success')
- end
-
- let!(:second_pipeline) do
- create(:ci_empty_pipeline,
- project: project,
- sha: commit.sha,
- status: 'success')
- end
-
- it 'returns last pipeline' do
- expect(commit.last_pipeline).to eq second_pipeline
- end
- end
-
- describe '#latest_pipeline' do
- let(:pipeline) { double }
-
- shared_examples_for 'fetching latest pipeline' do |ref|
- it 'returns the latest pipeline for the project' do
- expect(commit)
- .to receive(:latest_pipeline_for_project)
- .with(ref, project)
- .and_return(pipeline)
-
- expect(result).to eq(pipeline)
- end
-
- it "returns the memoized pipeline for the key of #{ref}" do
- commit.set_latest_pipeline_for_ref(ref, pipeline)
-
- expect(commit)
- .not_to receive(:latest_pipeline_for_project)
-
- expect(result).to eq(pipeline)
- end
- end
-
- context 'without ref argument' do
- let(:result) { commit.latest_pipeline }
-
- it_behaves_like 'fetching latest pipeline', nil
- end
-
- context 'when a particular ref is specified' do
- let(:result) { commit.latest_pipeline('master') }
-
- it_behaves_like 'fetching latest pipeline', 'master'
- end
- end
-
- describe '#latest_pipeline_for_project' do
- let(:project_pipelines) { double }
- let(:pipeline_project) { double }
- let(:pipeline) { double }
- let(:ref) { 'master' }
- let(:result) { commit.latest_pipeline_for_project(ref, pipeline_project) }
-
- before do
- allow(pipeline_project).to receive(:ci_pipelines).and_return(project_pipelines)
- end
-
- it 'returns the latest pipeline of the commit for the given ref and project' do
- expect(project_pipelines)
- .to receive(:latest_pipeline_per_commit)
- .with(commit.id, ref)
- .and_return(commit.id => pipeline)
-
- expect(result).to eq(pipeline)
- end
- end
-
- describe '#set_latest_pipeline_for_ref' do
- let(:pipeline) { double }
-
- it 'sets the latest pipeline for a given reference' do
- commit.set_latest_pipeline_for_ref('master', pipeline)
-
- expect(commit.latest_pipeline('master')).to eq(pipeline)
- end
- end
-
- describe "#status" do
- it 'returns the status of the latest pipeline for the given ref' do
- expect(commit)
- .to receive(:latest_pipeline)
- .with('master')
- .and_return(double(status: 'success'))
-
- expect(commit.status('master')).to eq('success')
- end
-
- it 'returns nil when latest pipeline is not present for the given ref' do
- expect(commit)
- .to receive(:latest_pipeline)
- .with('master')
- .and_return(nil)
-
- expect(commit.status('master')).to eq(nil)
- end
-
- it 'returns the status of the latest pipeline when no ref is given' do
- expect(commit)
- .to receive(:latest_pipeline)
- .with(nil)
- .and_return(double(status: 'success'))
-
- expect(commit.status).to eq('success')
- end
- end
-end
diff --git a/spec/models/concerns/ci/artifactable_spec.rb b/spec/models/concerns/ci/artifactable_spec.rb
index f05189abdd2..ebc838e86a6 100644
--- a/spec/models/concerns/ci/artifactable_spec.rb
+++ b/spec/models/concerns/ci/artifactable_spec.rb
@@ -54,4 +54,23 @@ RSpec.describe Ci::Artifactable do
end
end
end
+
+ context 'ActiveRecord scopes' do
+ let_it_be(:recently_expired_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+ let_it_be(:later_expired_artifact) { create(:ci_job_artifact, expire_at: 2.days.ago) }
+ let_it_be(:not_expired_artifact) { create(:ci_job_artifact, expire_at: 1.day.from_now) }
+
+ describe '.expired_before' do
+ it 'returns expired artifacts' do
+ expect(Ci::JobArtifact.expired_before(1.hour.ago))
+ .to match_array([recently_expired_artifact, later_expired_artifact])
+ end
+ end
+
+ describe '.expired' do
+ it 'returns a limited number of expired artifacts' do
+ expect(Ci::JobArtifact.expired(1).order_id_asc).to eq([recently_expired_artifact])
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/each_batch_spec.rb b/spec/models/concerns/each_batch_spec.rb
index 8b70753633c..5f4e5d4bd98 100644
--- a/spec/models/concerns/each_batch_spec.rb
+++ b/spec/models/concerns/each_batch_spec.rb
@@ -56,5 +56,21 @@ RSpec.describe EachBatch do
it_behaves_like 'each_batch handling', {}
it_behaves_like 'each_batch handling', { order_hint: :updated_at }
+
+ it 'orders ascending by default' do
+ ids = []
+
+ model.each_batch(of: 1) { |rel| ids.concat(rel.ids) }
+
+ expect(ids).to eq(ids.sort)
+ end
+
+ it 'accepts descending order' do
+ ids = []
+
+ model.each_batch(of: 1, order: :desc) { |rel| ids.concat(rel.ids) }
+
+ expect(ids).to eq(ids.sort.reverse)
+ end
end
end
diff --git a/spec/models/concerns/milestoneable_spec.rb b/spec/models/concerns/milestoneable_spec.rb
index c37582cb65d..5fb3b39f734 100644
--- a/spec/models/concerns/milestoneable_spec.rb
+++ b/spec/models/concerns/milestoneable_spec.rb
@@ -104,8 +104,8 @@ RSpec.describe Milestoneable do
context "for incidents" do
let(:incident) { build(:incident) }
- it 'returns false' do
- expect(incident.supports_milestone?).to be_falsy
+ it 'returns true' do
+ expect(incident.supports_milestone?).to be_truthy
end
end
end
diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb
index bb7374bf46c..a7117af81a2 100644
--- a/spec/models/concerns/noteable_spec.rb
+++ b/spec/models/concerns/noteable_spec.rb
@@ -25,8 +25,8 @@ RSpec.describe Noteable do
let(:active_position2) do
Gitlab::Diff::Position.new(
- old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
+ old_path: 'files/ruby/popen.rb',
+ new_path: 'files/ruby/popen.rb',
old_line: 16,
new_line: 22,
diff_refs: subject.diff_refs
@@ -35,11 +35,11 @@ RSpec.describe Noteable do
let(:outdated_position) do
Gitlab::Diff::Position.new(
- old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
+ old_path: 'files/ruby/popen.rb',
+ new_path: 'files/ruby/popen.rb',
old_line: nil,
new_line: 9,
- diff_refs: project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e").diff_refs
+ diff_refs: project.commit('874797c3a73b60d2187ed6e2fcabd289ff75171e').diff_refs
)
end
@@ -80,7 +80,7 @@ RSpec.describe Noteable do
describe '#grouped_diff_discussions' do
let(:grouped_diff_discussions) { subject.grouped_diff_discussions }
- it "includes active discussions" do
+ it 'includes active discussions' do
discussions = grouped_diff_discussions.values.flatten
expect(discussions.count).to eq(2)
@@ -91,17 +91,17 @@ RSpec.describe Noteable do
expect(discussions.last.notes).to eq([active_diff_note3])
end
- it "doesn't include outdated discussions" do
+ it 'does not include outdated discussions' do
expect(grouped_diff_discussions.values.flatten.map(&:id)).not_to include(outdated_diff_note1.discussion_id)
end
- it "groups the discussions by line code" do
+ it 'groups the discussions by line code' do
expect(grouped_diff_discussions[active_diff_note1.line_code].first.id).to eq(active_diff_note1.discussion_id)
expect(grouped_diff_discussions[active_diff_note3.line_code].first.id).to eq(active_diff_note3.discussion_id)
end
end
- context "discussion status" do
+ context 'discussion status' do
let(:first_discussion) { build_stubbed(:discussion_note_on_merge_request, noteable: subject, project: project).to_discussion }
let(:second_discussion) { build_stubbed(:discussion_note_on_merge_request, noteable: subject, project: project).to_discussion }
let(:third_discussion) { build_stubbed(:discussion_note_on_merge_request, noteable: subject, project: project).to_discussion }
@@ -110,56 +110,56 @@ RSpec.describe Noteable do
allow(subject).to receive(:resolvable_discussions).and_return([first_discussion, second_discussion, third_discussion])
end
- describe "#discussions_resolvable?" do
- context "when all discussions are unresolvable" do
+ describe '#discussions_resolvable?' do
+ context 'when all discussions are unresolvable' do
before do
allow(first_discussion).to receive(:resolvable?).and_return(false)
allow(second_discussion).to receive(:resolvable?).and_return(false)
allow(third_discussion).to receive(:resolvable?).and_return(false)
end
- it "returns false" do
+ it 'returns false' do
expect(subject.discussions_resolvable?).to be false
end
end
- context "when some discussions are unresolvable and some discussions are resolvable" do
+ context 'when some discussions are unresolvable and some discussions are resolvable' do
before do
allow(first_discussion).to receive(:resolvable?).and_return(true)
allow(second_discussion).to receive(:resolvable?).and_return(false)
allow(third_discussion).to receive(:resolvable?).and_return(true)
end
- it "returns true" do
+ it 'returns true' do
expect(subject.discussions_resolvable?).to be true
end
end
- context "when all discussions are resolvable" do
+ context 'when all discussions are resolvable' do
before do
allow(first_discussion).to receive(:resolvable?).and_return(true)
allow(second_discussion).to receive(:resolvable?).and_return(true)
allow(third_discussion).to receive(:resolvable?).and_return(true)
end
- it "returns true" do
+ it 'returns true' do
expect(subject.discussions_resolvable?).to be true
end
end
end
- describe "#discussions_resolved?" do
- context "when discussions are not resolvable" do
+ describe '#discussions_resolved?' do
+ context 'when discussions are not resolvable' do
before do
allow(subject).to receive(:discussions_resolvable?).and_return(false)
end
- it "returns false" do
+ it 'returns false' do
expect(subject.discussions_resolved?).to be false
end
end
- context "when discussions are resolvable" do
+ context 'when discussions are resolvable' do
before do
allow(subject).to receive(:discussions_resolvable?).and_return(true)
@@ -168,31 +168,31 @@ RSpec.describe Noteable do
allow(third_discussion).to receive(:resolvable?).and_return(true)
end
- context "when all resolvable discussions are resolved" do
+ context 'when all resolvable discussions are resolved' do
before do
allow(first_discussion).to receive(:resolved?).and_return(true)
allow(third_discussion).to receive(:resolved?).and_return(true)
end
- it "returns true" do
+ it 'returns true' do
expect(subject.discussions_resolved?).to be true
end
end
- context "when some resolvable discussions are not resolved" do
+ context 'when some resolvable discussions are not resolved' do
before do
allow(first_discussion).to receive(:resolved?).and_return(true)
allow(third_discussion).to receive(:resolved?).and_return(false)
end
- it "returns false" do
+ it 'returns false' do
expect(subject.discussions_resolved?).to be false
end
end
end
end
- describe "#discussions_to_be_resolved" do
+ describe '#discussions_to_be_resolved' do
before do
allow(first_discussion).to receive(:to_be_resolved?).and_return(true)
allow(second_discussion).to receive(:to_be_resolved?).and_return(false)
@@ -245,6 +245,12 @@ RSpec.describe Noteable do
end
end
+ describe '.email_creatable_types' do
+ it 'exposes the email creatable types' do
+ expect(described_class.email_creatable_types).to include('Issue')
+ end
+ end
+
describe '#capped_notes_count' do
context 'notes number < 10' do
it 'the number of notes is returned' do
@@ -263,13 +269,13 @@ RSpec.describe Noteable do
end
end
- describe "#has_any_diff_note_positions?" do
- let(:source_branch) { "compare-with-merge-head-source" }
- let(:target_branch) { "compare-with-merge-head-target" }
+ describe '#has_any_diff_note_positions?' do
+ let(:source_branch) { 'compare-with-merge-head-source' }
+ let(:target_branch) { 'compare-with-merge-head-target' }
let(:merge_request) { create(:merge_request, source_branch: source_branch, target_branch: target_branch) }
let!(:note) do
- path = "files/markdown/ruby-style-guide.md"
+ path = 'files/markdown/ruby-style-guide.md'
position = Gitlab::Diff::Position.new(
old_path: path,
@@ -286,20 +292,54 @@ RSpec.describe Noteable do
Discussions::CaptureDiffNotePositionsService.new(merge_request).execute
end
- it "returns true when it has diff note positions" do
+ it 'returns true when it has diff note positions' do
expect(merge_request.has_any_diff_note_positions?).to be(true)
end
- it "returns false when it has notes but no diff note positions" do
+ it 'returns false when it has notes but no diff note positions' do
DiffNotePosition.where(note: note).find_each(&:delete)
expect(merge_request.has_any_diff_note_positions?).to be(false)
end
- it "returns false when it has no notes" do
+ it 'returns false when it has no notes' do
merge_request.notes.find_each(&:destroy)
expect(merge_request.has_any_diff_note_positions?).to be(false)
end
end
+
+ describe '#creatable_note_email_address' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:source_branch) { 'compare-with-merge-head-source' }
+
+ let(:issue) { create(:issue, project: project) }
+ let(:snippet) { build(:snippet) }
+
+ context 'incoming email enabled' do
+ before do
+ stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
+ end
+
+ it 'returns the address to create a note' do
+ address = "p+#{project.full_path_slug}-#{project.project_id}-#{user.incoming_email_token}-issue-#{issue.iid}@gl.ab"
+
+ expect(issue.creatable_note_email_address(user)).to eq(address)
+ end
+
+ it 'returns nil for unsupported types' do
+ expect(snippet.creatable_note_email_address(user)).to be_nil
+ end
+ end
+
+ context 'incoming email disabled' do
+ before do
+ stub_incoming_email_setting(enabled: false)
+ end
+
+ it 'returns nil' do
+ expect(issue.creatable_note_email_address(user)).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb
deleted file mode 100644
index ca612cba654..00000000000
--- a/spec/models/cycle_analytics/code_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#code' do
- extend CycleAnalyticsHelpers::TestGeneration
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
- let_it_be(:project_level) { CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user }) }
-
- subject { project_level }
-
- context 'with deployment' do
- generate_cycle_analytics_spec(
- phase: :code,
- data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } },
- start_time_conditions: [["issue mentioned in a commit",
- -> (context, data) do
- context.create_commit_referencing_issue(data[:issue])
- end]],
- end_time_conditions: [["merge request that closes issue is created",
- -> (context, data) do
- context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
- end]],
- post_fn: -> (context, data) do
- end)
-
- context "when a regular merge request (that doesn't close the issue) is created" do
- it "returns nil" do
- issue = create(:issue, project: project)
-
- create_commit_referencing_issue(issue)
- create_merge_request_closing_issue(user, project, issue, message: "Closes nothing")
-
- merge_merge_requests_closing_issue(user, project, issue)
- deploy_master(user, project)
-
- expect(subject[:code].project_median).to be_nil
- end
- end
- end
-
- context 'without deployment' do
- generate_cycle_analytics_spec(
- phase: :code,
- data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } },
- start_time_conditions: [["issue mentioned in a commit",
- -> (context, data) do
- context.create_commit_referencing_issue(data[:issue])
- end]],
- end_time_conditions: [["merge request that closes issue is created",
- -> (context, data) do
- context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
- end]],
- post_fn: -> (context, data) do
- end)
-
- context "when a regular merge request (that doesn't close the issue) is created" do
- it "returns nil" do
- issue = create(:issue, project: project)
-
- create_commit_referencing_issue(issue)
- create_merge_request_closing_issue(user, project, issue, message: "Closes nothing")
-
- merge_merge_requests_closing_issue(user, project, issue)
-
- expect(subject[:code].project_median).to be_nil
- end
- end
- end
-end
diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb
deleted file mode 100644
index 66d21f6925f..00000000000
--- a/spec/models/cycle_analytics/issue_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#issue' do
- extend CycleAnalyticsHelpers::TestGeneration
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
- let_it_be(:project_level) { CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user }) }
-
- subject { project_level }
-
- generate_cycle_analytics_spec(
- phase: :issue,
- data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } },
- start_time_conditions: [["issue created", -> (context, data) { data[:issue].save! }]],
- end_time_conditions: [["issue associated with a milestone",
- -> (context, data) do
- if data[:issue].persisted?
- data[:issue].update!(milestone: context.create(:milestone, project: context.project))
- end
- end],
- ["list label added to issue",
- -> (context, data) do
- if data[:issue].persisted?
- data[:issue].update!(label_ids: [context.create(:list).label_id])
- end
- end]],
- post_fn: -> (context, data) do
- end)
-
- context "when a regular label (instead of a list label) is added to the issue" do
- it "returns nil" do
- regular_label = create(:label)
- issue = create(:issue, project: project)
- issue.update!(label_ids: [regular_label.id])
-
- create_merge_request_closing_issue(user, project, issue)
- merge_merge_requests_closing_issue(user, project, issue)
-
- expect(subject[:issue].project_median).to be_nil
- end
- end
-end
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
deleted file mode 100644
index acaf767db01..00000000000
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#plan' do
- extend CycleAnalyticsHelpers::TestGeneration
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
- let_it_be(:project_level) { CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user }) }
-
- subject { project_level }
-
- generate_cycle_analytics_spec(
- phase: :plan,
- data_fn: -> (context) do
- {
- issue: context.build(:issue, project: context.project),
- branch_name: context.generate(:branch)
- }
- end,
- start_time_conditions: [["issue associated with a milestone",
- -> (context, data) do
- data[:issue].update!(milestone: context.create(:milestone, project: context.project))
- end],
- ["list label added to issue",
- -> (context, data) do
- data[:issue].update!(label_ids: [context.create(:list).label_id])
- end]],
- end_time_conditions: [["issue mentioned in a commit",
- -> (context, data) do
- context.create_commit_referencing_issue(data[:issue], branch_name: data[:branch_name])
- end]],
- post_fn: -> (context, data) do
- end)
-
- context "when a regular label (instead of a list label) is added to the issue" do
- it "returns nil" do
- branch_name = generate(:branch)
- label = create(:label)
- issue = create(:issue, project: project)
- issue.update!(label_ids: [label.id])
- create_commit_referencing_issue(issue, branch_name: branch_name)
-
- create_merge_request_closing_issue(user, project, issue, source_branch: branch_name)
- merge_merge_requests_closing_issue(user, project, issue)
-
- expect(subject[:issue].project_median).to be_nil
- end
- end
-end
diff --git a/spec/models/cycle_analytics/project_level_spec.rb b/spec/models/cycle_analytics/project_level_spec.rb
deleted file mode 100644
index c2d421c03d8..00000000000
--- a/spec/models/cycle_analytics/project_level_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe CycleAnalytics::ProjectLevel do
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
- let_it_be(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
- let_it_be(:milestone) { create(:milestone, project: project) }
- let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") }
- let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr) }
-
- subject { described_class.new(project, options: { from: from_date }) }
-
- describe '#all_medians_by_stage' do
- before do
- allow_next_instance_of(Gitlab::ReferenceExtractor) do |instance|
- allow(instance).to receive(:issues).and_return([issue])
- end
-
- create_cycle(user, project, issue, mr, milestone, pipeline)
- deploy_master(user, project)
- end
-
- it 'returns every median for each stage for a specific project' do
- values = described_class::STAGES.each_with_object({}) do |stage_name, hsh|
- hsh[stage_name] = subject[stage_name].project_median.presence
- end
-
- expect(subject.all_medians_by_stage).to eq(values)
- end
- end
-end
diff --git a/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb b/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
new file mode 100644
index 00000000000..9bdee292938
--- /dev/null
+++ b/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CycleAnalytics::ProjectLevelStageAdapter, type: :model do
+ let_it_be(:stage_name) { :review } # pre-defined, default stage
+ let_it_be(:merge_request) do
+ create(:merge_request, created_at: 5.hours.ago).tap do |mr|
+ mr.metrics.update!(merged_at: mr.created_at + 1.hour)
+ end
+ end
+
+ let_it_be(:project) { merge_request.target_project }
+
+ let(:stage) do
+ params = Gitlab::Analytics::CycleAnalytics::DefaultStages.find_by_name!(stage_name).merge(project: project)
+ Analytics::CycleAnalytics::ProjectStage.new(params)
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ subject { described_class.new(stage, from: 1.month.ago, to: Time.zone.now, current_user: merge_request.author) }
+
+ it 'calculates median' do
+ expect(subject.median).to be_within(1.hour).of(0.5)
+ end
+
+ it 'lists events' do
+ expect(subject.events.size).to eq(1)
+ expect(subject.events.first[:title]).to eq(merge_request.title)
+ end
+
+ it 'presents the data as json' do
+ expect(subject.as_json).to include({ title: 'Review', value: 'about 1 hour' })
+ end
+end
diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb
deleted file mode 100644
index 06d9cfbf8c0..00000000000
--- a/spec/models/cycle_analytics/review_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#review' do
- extend CycleAnalyticsHelpers::TestGeneration
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
-
- subject { CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user }) }
-
- generate_cycle_analytics_spec(
- phase: :review,
- data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } },
- start_time_conditions: [["merge request that closes issue is created",
- -> (context, data) do
- context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
- end]],
- end_time_conditions: [["merge request that closes issue is merged",
- -> (context, data) do
- context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
- end]],
- post_fn: nil)
-
- context "when a regular merge request (that doesn't close the issue) is created and merged" do
- it "returns nil" do
- MergeRequests::MergeService.new(project, user).execute(create(:merge_request))
-
- expect(subject[:review].project_median).to be_nil
- end
- end
-end
diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb
deleted file mode 100644
index 50cb49d6309..00000000000
--- a/spec/models/cycle_analytics/staging_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#staging' do
- extend CycleAnalyticsHelpers::TestGeneration
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
- let_it_be(:project_level) { CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user }) }
-
- subject { project_level }
-
- generate_cycle_analytics_spec(
- phase: :staging,
- data_fn: lambda do |context|
- issue = context.create(:issue, project: context.project)
- { issue: issue, merge_request: context.create_merge_request_closing_issue(context.user, context.project, issue) }
- end,
- start_time_conditions: [["merge request that closes issue is merged",
- -> (context, data) do
- context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
- end]],
- end_time_conditions: [["merge request that closes issue is deployed to production",
- -> (context, data) do
- context.deploy_master(context.user, context.project)
- end],
- ["production deploy happens after merge request is merged (along with other changes)",
- lambda do |context, data|
- # Make other changes on master
- context.project.repository.commit("this_sha_apparently_does_not_matter")
- context.deploy_master(context.user, context.project)
- end]])
-
- context "when a regular merge request (that doesn't close the issue) is merged and deployed" do
- it "returns nil" do
- merge_request = create(:merge_request)
- MergeRequests::MergeService.new(project, user).execute(merge_request)
- deploy_master(user, project)
-
- expect(subject[:staging].project_median).to be_nil
- end
- end
-
- context "when the deployment happens to a non-production environment" do
- it "returns nil" do
- issue = create(:issue, project: project)
- merge_request = create_merge_request_closing_issue(user, project, issue)
- MergeRequests::MergeService.new(project, user).execute(merge_request)
- deploy_master(user, project, environment: 'staging')
-
- expect(subject[:staging].project_median).to be_nil
- end
- end
-end
diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb
deleted file mode 100644
index 8f65c047b15..00000000000
--- a/spec/models/cycle_analytics/test_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#test' do
- extend CycleAnalyticsHelpers::TestGeneration
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:from_date) { 10.days.ago }
- let_it_be(:user) { project.owner }
- let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:project_level) { CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user }) }
- let!(:merge_request) { create_merge_request_closing_issue(user, project, issue) }
-
- subject { project_level }
-
- generate_cycle_analytics_spec(
- phase: :test,
- data_fn: lambda do |context|
- issue = context.issue
- merge_request = context.create_merge_request_closing_issue(context.user, context.project, issue)
- pipeline = context.create(:ci_pipeline, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, project: context.project, head_pipeline_of: merge_request)
- { pipeline: pipeline, issue: issue }
- end,
- start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]],
- end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]],
- post_fn: -> (context, data) do
- end)
-
- context "when the pipeline is for a regular merge request (that doesn't close an issue)" do
- it "returns nil" do
- pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha)
-
- pipeline.run!
- pipeline.succeed!
-
- expect(subject[:test].project_median).to be_nil
- end
- end
-
- context "when the pipeline is not for a merge request" do
- it "returns nil" do
- pipeline = create(:ci_pipeline, ref: "refs/heads/master", sha: project.repository.commit('master').sha)
-
- pipeline.run!
- pipeline.succeed!
-
- expect(subject[:test].project_median).to be_nil
- end
- end
-
- context "when the pipeline is dropped (failed)" do
- it "returns nil" do
- pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha)
-
- pipeline.run!
- pipeline.drop!
-
- expect(subject[:test].project_median).to be_nil
- end
- end
-
- context "when the pipeline is cancelled" do
- it "returns nil" do
- pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha)
-
- pipeline.run!
- pipeline.cancel!
-
- expect(subject[:test].project_median).to be_nil
- end
- end
-end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index c962b012a4b..5bc61db6d21 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -227,6 +227,56 @@ RSpec.describe Deployment do
deployment.skip!
end
end
+
+ describe 'synching status to Jira' do
+ let(:deployment) { create(:deployment) }
+
+ let(:worker) { ::JiraConnect::SyncDeploymentsWorker }
+
+ it 'calls the worker on creation' do
+ expect(worker).to receive(:perform_async).with(Integer)
+
+ deployment
+ end
+
+ it 'does not call the worker for skipped deployments' do
+ expect(deployment).to be_present # warm-up, ignore the creation trigger
+
+ expect(worker).not_to receive(:perform_async)
+
+ deployment.skip!
+ end
+
+ %i[run! succeed! drop! cancel!].each do |event|
+ context "when we call pipeline.#{event}" do
+ it 'triggers a Jira synch worker' do
+ expect(worker).to receive(:perform_async).with(deployment.id)
+
+ 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
end
describe '#success?' do
diff --git a/spec/models/experiment_spec.rb b/spec/models/experiment_spec.rb
index 1bf7b8b4850..171bfd116d3 100644
--- a/spec/models/experiment_spec.rb
+++ b/spec/models/experiment_spec.rb
@@ -164,7 +164,7 @@ RSpec.describe Experiment do
context 'when an experiment_user already exists for the given user' do
before do
# Create an existing experiment_user for this experiment and the :control group
- experiment.record_user_and_group(user, :control, context)
+ experiment.record_user_and_group(user, :control)
end
it 'does not create a new experiment_user record' do
@@ -173,15 +173,65 @@ RSpec.describe Experiment do
context 'but the group_type and context has changed' do
let(:group) { :experimental }
- let(:context) { { b: 37 } }
it 'updates the existing experiment_user record with group_type' do
expect { record_user_and_group }.to change { ExperimentUser.last.group_type }
end
+ end
+ end
+
+ context 'when a context already exists' do
+ let_it_be(:context) { { a: 42, 'b' => 34, 'c': { c1: 100, c2: 'c2', e: :e }, d: [1, 3] } }
+ let_it_be(:initial_expected_context) { { 'a' => 42, 'b' => 34, 'c' => { 'c1' => 100, 'c2' => 'c2', 'e' => 'e' }, 'd' => [1, 3] } }
- it 'updates the existing experiment_user record with context' do
+ before do
+ record_user_and_group
+ experiment.record_user_and_group(user, :control, {})
+ end
+
+ it 'has an initial context with stringified keys' do
+ expect(ExperimentUser.last.context).to eq(initial_expected_context)
+ end
+
+ context 'when updated' do
+ before do
record_user_and_group
- expect(ExperimentUser.last.context).to eq({ 'b' => 37 })
+ experiment.record_user_and_group(user, :control, new_context)
+ end
+
+ context 'with an empty context' do
+ let_it_be(:new_context) { {} }
+
+ it 'keeps the initial context' do
+ expect(ExperimentUser.last.context).to eq(initial_expected_context)
+ end
+ end
+
+ context 'with string keys' do
+ let_it_be(:new_context) { { f: :some_symbol } }
+
+ it 'adds new symbols stringified' do
+ expected_context = initial_expected_context.merge('f' => 'some_symbol')
+ expect(ExperimentUser.last.context).to eq(expected_context)
+ end
+ end
+
+ context 'with atomic values or array values' do
+ let_it_be(:new_context) { { b: 97, d: [99] } }
+
+ it 'overrides the values' do
+ expected_context = { 'a' => 42, 'b' => 97, 'c' => { 'c1' => 100, 'c2' => 'c2', 'e' => 'e' }, 'd' => [99] }
+ expect(ExperimentUser.last.context).to eq(expected_context)
+ end
+ end
+
+ context 'with nested hashes' do
+ let_it_be(:new_context) { { c: { g: 107 } } }
+
+ it 'inserts nested additional values in the same keys' do
+ expected_context = initial_expected_context.deep_merge('c' => { 'g' => 107 })
+ expect(ExperimentUser.last.context).to eq(expected_context)
+ end
end
end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index cc8e744a15c..0acf2b96b74 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe Group do
it { is_expected.to have_one(:dependency_proxy_setting) }
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) }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -1751,4 +1752,23 @@ RSpec.describe Group do
it { is_expected.to eq(false) }
end
end
+
+ 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
+ end
end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index 37158584062..f0b1bc33e84 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe List do
it_behaves_like 'having unique enum values'
+ it_behaves_like 'boards listable model', :list
describe 'relationships' do
it { is_expected.to belong_to(:board) }
@@ -14,72 +15,6 @@ RSpec.describe List do
it { is_expected.to validate_presence_of(:board) }
it { is_expected.to validate_presence_of(:label) }
it { is_expected.to validate_presence_of(:list_type) }
- it { is_expected.to validate_presence_of(:position) }
- it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than_or_equal_to(0) }
-
- context 'when list_type is set to closed' do
- subject { described_class.new(list_type: :closed) }
-
- it { is_expected.not_to validate_presence_of(:label) }
- it { is_expected.not_to validate_presence_of(:position) }
- end
- end
-
- describe '#destroy' do
- it 'can be destroyed when list_type is set to label' do
- subject = create(:list)
-
- expect(subject.destroy).to be_truthy
- end
-
- it 'can not be destroyed when list_type is set to closed' do
- subject = create(:closed_list)
-
- expect(subject.destroy).to be_falsey
- end
- end
-
- describe '#destroyable?' do
- it 'returns true when list_type is set to label' do
- subject.list_type = :label
-
- expect(subject).to be_destroyable
- end
-
- it 'returns false when list_type is set to closed' do
- subject.list_type = :closed
-
- expect(subject).not_to be_destroyable
- end
- end
-
- describe '#movable?' do
- it 'returns true when list_type is set to label' do
- subject.list_type = :label
-
- expect(subject).to be_movable
- end
-
- it 'returns false when list_type is set to closed' do
- subject.list_type = :closed
-
- expect(subject).not_to be_movable
- end
- end
-
- describe '#title' do
- it 'returns label name when list_type is set to label' do
- subject.list_type = :label
- subject.label = Label.new(name: 'Development')
-
- expect(subject.title).to eq 'Development'
- end
-
- it 'returns Closed when list_type is set to closed' do
- subject.list_type = :closed
-
- expect(subject.title).to eq 'Closed'
- end
end
describe '#update_preferences_for' do
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index 2b24e2d6455..3d3ed6fc54a 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -123,4 +123,16 @@ RSpec.describe GroupMember do
end
end
end
+
+ context 'when group member expiration date is updated' do
+ let_it_be(:group_member) { create(:group_member) }
+
+ it 'emails the user that their group membership expiry has changed' do
+ expect_next_instance_of(NotificationService) do |notification|
+ allow(notification).to receive(:updated_group_member_expiration).with(group_member)
+ end
+
+ group_member.update!(expires_at: 5.days.from_now)
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 431a60a11a5..1cf197322f5 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -411,6 +411,48 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '.by_squash_commit_sha' do
+ subject { described_class.by_squash_commit_sha(sha) }
+
+ let(:sha) { '123abc' }
+ let(:merge_request) { create(:merge_request, :merged, squash_commit_sha: sha) }
+
+ it 'returns merge requests that match the given squash commit' do
+ is_expected.to eq([merge_request])
+ end
+ end
+
+ describe '.by_related_commit_sha' do
+ subject { described_class.by_related_commit_sha(sha) }
+
+ context 'when commit is a squash commit' do
+ let!(:merge_request) { create(:merge_request, :merged, squash_commit_sha: sha) }
+ let(:sha) { '123abc' }
+
+ it { is_expected.to eq([merge_request]) }
+ end
+
+ context 'when commit is a part of the merge request' do
+ let!(:merge_request) { create(:merge_request, :with_diffs) }
+ let(:sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
+
+ it { is_expected.to eq([merge_request]) }
+ end
+
+ context 'when commit is a merge commit' do
+ let!(:merge_request) { create(:merge_request, :merged, merge_commit_sha: sha) }
+ let(:sha) { '123abc' }
+
+ it { is_expected.to eq([merge_request]) }
+ end
+
+ context 'when commit is not found' do
+ let(:sha) { '0000' }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
describe '.by_cherry_pick_sha' do
it 'returns merge requests that match the given merge commit' do
note = create(:track_mr_picking_note, commit_id: '456abc')
@@ -3555,112 +3597,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- describe '#mergeable_with_quick_action?' do
- def create_pipeline(status)
- pipeline = create(:ci_pipeline,
- project: project,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha,
- status: status,
- head_pipeline_of: merge_request)
-
- pipeline
- end
-
- let_it_be(:project) { create(:project, :public, :repository, only_allow_merge_if_pipeline_succeeds: true) }
-
- let(:developer) { create(:user) }
- let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request, source_project: project) }
- let(:mr_sha) { merge_request.diff_head_sha }
-
- before do
- project.add_developer(developer)
- end
-
- context 'when autocomplete_precheck is set to true' do
- it 'is mergeable by developer' do
- expect(merge_request.mergeable_with_quick_action?(developer, autocomplete_precheck: true)).to be_truthy
- end
-
- it 'is not mergeable by normal user' do
- expect(merge_request.mergeable_with_quick_action?(user, autocomplete_precheck: true)).to be_falsey
- end
- end
-
- context 'when autocomplete_precheck is set to false' do
- it 'is mergeable by developer' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
- end
-
- it 'is not mergeable by normal user' do
- expect(merge_request.mergeable_with_quick_action?(user, last_diff_sha: mr_sha)).to be_falsey
- end
-
- context 'closed MR' do
- before do
- merge_request.update_attribute(:state_id, described_class.available_states[:closed])
- end
-
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
- end
- end
-
- context 'MR with WIP' do
- before do
- merge_request.update_attribute(:title, 'WIP: some MR')
- end
-
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
- end
- end
-
- context 'sha differs from the MR diff_head_sha' do
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: 'some other sha')).to be_falsey
- end
- end
-
- context 'sha is not provided' do
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer)).to be_falsey
- end
- end
-
- context 'with pipeline ok' do
- before do
- create_pipeline(:success)
- end
-
- it 'is mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
- end
- end
-
- context 'with failing pipeline' do
- before do
- create_pipeline(:failed)
- end
-
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
- end
- end
-
- context 'with running pipeline' do
- before do
- create_pipeline(:running)
- end
-
- it 'is mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
- end
- end
- end
- end
-
describe '#pipeline_coverage_delta' do
let!(:merge_request) { create(:merge_request) }
diff --git a/spec/models/namespace/package_setting_spec.rb b/spec/models/namespace/package_setting_spec.rb
new file mode 100644
index 00000000000..097cef8ef3b
--- /dev/null
+++ b/spec/models/namespace/package_setting_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespace::PackageSetting do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:namespace) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:namespace) }
+
+ describe '#maven_duplicates_allowed' do
+ it { is_expected.to allow_value(true).for(:maven_duplicates_allowed) }
+ it { is_expected.to allow_value(false).for(:maven_duplicates_allowed) }
+ it { is_expected.not_to allow_value(nil).for(:maven_duplicates_allowed) }
+ end
+
+ describe '#maven_duplicate_exception_regex' do
+ let_it_be(:package_settings) { create(:namespace_package_setting) }
+
+ subject { package_settings }
+
+ valid_regexps = %w[SNAPSHOT .* v.+ v10.1.* (?:v.+|SNAPSHOT|TEMP)]
+ invalid_regexps = ['[', '(?:v.+|SNAPSHOT|TEMP']
+
+ valid_regexps.each do |valid_regexp|
+ it { is_expected.to allow_value(valid_regexp).for(:maven_duplicate_exception_regex) }
+ end
+
+ invalid_regexps.each do |invalid_regexp|
+ it { is_expected.not_to allow_value(invalid_regexp).for(:maven_duplicate_exception_regex) }
+ end
+ end
+ end
+
+ describe '#duplicates_allowed?' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.duplicates_allowed?(package) }
+
+ context 'package types with package_settings' do
+ # As more package types gain settings they will be added to this list
+ [:maven_package].each do |format|
+ let_it_be(:package) { create(format) } # rubocop:disable Rails/SaveBang
+ let_it_be(:package_type) { package.package_type }
+ let_it_be(:package_setting) { package.project.namespace.package_settings }
+
+ where(:duplicates_allowed, :duplicate_exception_regex, :result) do
+ true | '' | true
+ false | '' | false
+ false | '.*' | true
+ end
+
+ with_them do
+ context "for #{format}" do
+ before do
+ package_setting.update!(
+ "#{package_type}_duplicates_allowed" => duplicates_allowed,
+ "#{package_type}_duplicate_exception_regex" => duplicate_exception_regex
+ )
+ end
+
+ it { is_expected.to be(result) }
+ end
+ end
+ end
+ end
+
+ context 'package types without package_settings' do
+ [:npm_package, :conan_package, :nuget_package, :pypi_package, :composer_package, :generic_package, :golang_package, :debian_package].each do |format|
+ let_it_be(:package) { create(format) } # rubocop:disable Rails/SaveBang
+ let_it_be(:package_setting) { package.project.namespace.package_settings }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Namespace::PackageSetting::PackageSettingNotImplemented)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/namespace_onboarding_action_spec.rb b/spec/models/namespace_onboarding_action_spec.rb
deleted file mode 100644
index 70dcb989b32..00000000000
--- a/spec/models/namespace_onboarding_action_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe NamespaceOnboardingAction do
- let(:namespace) { build(:namespace) }
-
- describe 'associations' do
- it { is_expected.to belong_to(:namespace).required }
- end
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:action) }
- end
-
- describe '.completed?' do
- let(:action) { :subscription_created }
-
- subject { described_class.completed?(namespace, action) }
-
- context 'action created for the namespace' do
- before do
- create(:namespace_onboarding_action, namespace: namespace, action: action)
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'action created for another namespace' do
- before do
- create(:namespace_onboarding_action, namespace: build(:namespace), action: action)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- describe '.create_action' do
- let(:action) { :subscription_created }
-
- subject(:create_action) { described_class.create_action(namespace, action) }
-
- it 'creates the action for the namespace just once' do
- expect { create_action }.to change { count_namespace_actions }.by(1)
-
- expect { create_action }.to change { count_namespace_actions }.by(0)
- end
-
- def count_namespace_actions
- described_class.where(namespace: namespace, action: action).count
- end
- end
-end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 0130618d004..a3c0a43115e 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -19,7 +19,8 @@ RSpec.describe Namespace do
it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_one :namespace_settings }
it { is_expected.to have_many :custom_emoji }
- it { is_expected.to have_many :namespace_onboarding_actions }
+ it { is_expected.to have_one :package_setting_relation }
+ it { is_expected.to have_one :onboarding_progress }
end
describe 'validations' do
@@ -1500,4 +1501,24 @@ RSpec.describe Namespace do
end
end
end
+
+ describe '#root?' do
+ subject { namespace.root? }
+
+ context 'when is subgroup' do
+ before do
+ namespace.parent = build(:group)
+ end
+
+ it 'returns false' do
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'when is root' do
+ it 'returns true' do
+ is_expected.to eq(true)
+ end
+ end
+ end
end
diff --git a/spec/models/onboarding_progress_spec.rb b/spec/models/onboarding_progress_spec.rb
new file mode 100644
index 00000000000..bd951846bb8
--- /dev/null
+++ b/spec/models/onboarding_progress_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe OnboardingProgress do
+ let(:namespace) { create(:namespace) }
+ let(:action) { :subscription_created }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:namespace).required }
+ end
+
+ describe 'validations' do
+ describe 'namespace_is_root_namespace' do
+ subject(:onboarding_progress) { build(:onboarding_progress, namespace: namespace)}
+
+ context 'when associated namespace is root' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'when associated namespace is not root' do
+ let(:namespace) { build(:group, :nested) }
+
+ it 'is invalid' do
+ expect(onboarding_progress).to be_invalid
+ expect(onboarding_progress.errors[:namespace]).to include('must be a root namespace')
+ end
+ end
+ end
+ end
+
+ describe '.onboard' do
+ subject(:onboard) { described_class.onboard(namespace) }
+
+ it 'adds a record for the namespace' do
+ expect { onboard }.to change(described_class, :count).from(0).to(1)
+ end
+
+ context 'when not given a namespace' do
+ let(:namespace) { nil }
+
+ it 'does not add a record for the namespace' do
+ expect { onboard }.not_to change(described_class, :count).from(0)
+ end
+ end
+
+ context 'when not given a root namespace' do
+ let(:namespace) { create(:namespace, parent: build(:namespace)) }
+
+ it 'does not add a record for the namespace' do
+ expect { onboard }.not_to change(described_class, :count).from(0)
+ end
+ end
+ end
+
+ describe '.register' do
+ subject(:register_action) { described_class.register(namespace, action) }
+
+ context 'when the namespace was onboarded' do
+ before do
+ described_class.onboard(namespace)
+ end
+
+ it 'registers the action for the namespace' do
+ expect { register_action }.to change { described_class.completed?(namespace, action) }.from(false).to(true)
+ end
+
+ context 'when the action does not exist' do
+ let(:action) { :foo }
+
+ it 'does not register the action for the namespace' do
+ expect { register_action }.not_to change { described_class.completed?(namespace, action) }.from(nil)
+ end
+ end
+ end
+
+ context 'when the namespace was not onboarded' do
+ it 'does not register the action for the namespace' do
+ expect { register_action }.not_to change { described_class.completed?(namespace, action) }.from(false)
+ end
+ end
+ end
+
+ describe '.completed?' do
+ subject { described_class.completed?(namespace, action) }
+
+ context 'when the namespace has not yet been onboarded' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when the namespace has been onboarded but not registered the action yet' do
+ before do
+ described_class.onboard(namespace)
+ end
+
+ it { is_expected.to eq(false) }
+
+ context 'when the action has been registered' do
+ before do
+ described_class.register(namespace, action)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
+end
diff --git a/spec/models/packages/debian/file_metadatum_spec.rb b/spec/models/packages/debian/file_metadatum_spec.rb
new file mode 100644
index 00000000000..1215adfa6a1
--- /dev/null
+++ b/spec/models/packages/debian/file_metadatum_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::FileMetadatum, type: :model do
+ RSpec.shared_context 'Debian file metadatum' do |factory, trait|
+ let_it_be_with_reload(:debian_package_file) { create(factory, trait) }
+ let(:debian_file_metadatum) { debian_package_file.debian_file_metadatum }
+
+ subject { debian_file_metadatum }
+ end
+
+ RSpec.shared_examples 'Test Debian file metadatum' do |has_component, has_architecture, has_fields, has_outdated|
+ describe 'relationships' do
+ it { is_expected.to belong_to(:package_file) }
+ end
+
+ describe 'validations' do
+ describe '#package_file' do
+ it { is_expected.to validate_presence_of(:package_file) }
+ end
+
+ describe '#file_type' do
+ it { is_expected.to validate_presence_of(:file_type) }
+ end
+
+ describe '#component' do
+ it "has_component=#{has_component}" do
+ if has_component
+ is_expected.to validate_presence_of(:component)
+ is_expected.to allow_value('main').for(:component)
+ is_expected.not_to allow_value('hé').for(:component)
+ else
+ is_expected.to validate_absence_of(:component)
+ end
+ end
+ end
+
+ describe '#architecture' do
+ it "has_architecture=#{has_architecture}" do
+ if has_architecture
+ is_expected.to validate_presence_of(:architecture)
+ is_expected.to allow_value('amd64').for(:architecture)
+ is_expected.not_to allow_value('-a').for(:architecture)
+ else
+ is_expected.to validate_absence_of(:architecture)
+ end
+ end
+ end
+
+ describe '#fields' do
+ if has_fields
+ it { is_expected.to validate_presence_of(:fields) }
+ it { is_expected.to allow_value({ 'a': 'b' }).for(:fields) }
+ it { is_expected.not_to allow_value({ 'a': { 'b': 'c' } }).for(:fields) }
+ else
+ it { is_expected.to validate_absence_of(:fields) }
+ end
+ end
+
+ describe '#debian_package_type' do
+ before do
+ debian_package_file.package.package_type = :pypi
+ end
+
+ it 'validates package of type debian' do
+ expect(debian_file_metadatum).not_to be_valid
+ expect(debian_file_metadatum.errors.to_a).to contain_exactly('Package file Package type must be Debian')
+ end
+ end
+ end
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:factory, :trait, :has_component, :has_architecture, :has_fields) do
+ :debian_package_file | :unknown | false | false | false
+ :debian_package_file | :source | true | false | false
+ :debian_package_file | :dsc | true | false | true
+ :debian_package_file | :deb | true | true | true
+ :debian_package_file | :udeb | true | true | true
+ :debian_package_file | :buildinfo | true | false | true
+ :debian_package_file | :changes | false | false | true
+ end
+
+ with_them do
+ include_context 'Debian file metadatum', params[:factory], params[:trait] do
+ it_behaves_like 'Test Debian file metadatum', params[:has_component], params[:has_architecture], params[:has_fields], params[:has_outdated]
+ end
+ end
+end
diff --git a/spec/models/packages/debian/group_architecture_spec.rb b/spec/models/packages/debian/group_architecture_spec.rb
new file mode 100644
index 00000000000..a6def6e56cd
--- /dev/null
+++ b/spec/models/packages/debian/group_architecture_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GroupArchitecture do
+ it_behaves_like 'Debian Distribution Architecture', :debian_group_architecture, :group, false
+end
diff --git a/spec/models/packages/debian/group_distribution_spec.rb b/spec/models/packages/debian/group_distribution_spec.rb
new file mode 100644
index 00000000000..90fb0d0e7d8
--- /dev/null
+++ b/spec/models/packages/debian/group_distribution_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GroupDistribution do
+ it_behaves_like 'Debian Distribution', :debian_group_distribution, :group, false
+end
diff --git a/spec/models/packages/debian/project_architecture_spec.rb b/spec/models/packages/debian/project_architecture_spec.rb
new file mode 100644
index 00000000000..b82ecabc4d4
--- /dev/null
+++ b/spec/models/packages/debian/project_architecture_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ProjectArchitecture do
+ it_behaves_like 'Debian Distribution Architecture', :debian_project_architecture, :project, true
+end
diff --git a/spec/models/packages/debian/project_distribution_spec.rb b/spec/models/packages/debian/project_distribution_spec.rb
new file mode 100644
index 00000000000..5f4041ad9fe
--- /dev/null
+++ b/spec/models/packages/debian/project_distribution_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ProjectDistribution do
+ it_behaves_like 'Debian Distribution', :debian_project_distribution, :project, true
+end
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index 82ac159b9cc..ebb10e991ad 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Packages::PackageFile, type: :model do
it { is_expected.to have_one(:conan_file_metadatum) }
it { is_expected.to have_many(:package_file_build_infos).inverse_of(:package_file) }
it { is_expected.to have_many(:pipelines).through(:package_file_build_infos) }
+ it { is_expected.to have_one(:debian_file_metadatum).inverse_of(:package_file).class_name('Packages::Debian::FileMetadatum') }
end
describe 'validations' do
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 16764673474..6645db33503 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -599,6 +599,20 @@ RSpec.describe Packages::Package, type: :model do
end
end
+ describe '.order_by_package_file' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:package1) { create(:maven_package, project: project) }
+ let_it_be(:package2) { create(:maven_package, project: project) }
+
+ it 'orders packages their associated package_file\'s created_at date', :aggregate_failures do
+ expect(project.packages.order_by_package_file).to match_array([package1, package1, package1, package2, package2, package2])
+
+ create(:package_file, :xml, package: package1)
+
+ expect(project.packages.order_by_package_file).to match_array([package1, package1, package1, package2, package2, package2, package1])
+ end
+ end
+
describe '#versions' do
let_it_be(:project) { create(:project) }
let_it_be(:package) { create(:maven_package, project: project) }
@@ -731,4 +745,14 @@ RSpec.describe Packages::Package, type: :model do
end
end
end
+
+ describe '#package_settings' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:package) { create(:maven_package, project: project) }
+
+ it 'returns the namespace package_settings' do
+ expect(package.package_settings).to eq(group.package_settings)
+ end
+ end
end
diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb
index 6a0402d43a8..843beb4ce23 100644
--- a/spec/models/project_import_state_spec.rb
+++ b/spec/models/project_import_state_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe ProjectImportState, type: :model do
allow(after_import_service)
.to receive(:execute) { housekeeping_service.execute }
- allow(Projects::HousekeepingService)
+ allow(Repositories::HousekeepingService)
.to receive(:new) { housekeeping_service }
end
diff --git a/spec/models/project_pages_metadatum_spec.rb b/spec/models/project_pages_metadatum_spec.rb
new file mode 100644
index 00000000000..31a533e0363
--- /dev/null
+++ b/spec/models/project_pages_metadatum_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProjectPagesMetadatum do
+ describe '.only_on_legacy_storage' do
+ it 'returns only deployed records without deployment' do
+ create(:project) # without pages deployed
+
+ legacy_storage_project = create(:project)
+ legacy_storage_project.mark_pages_as_deployed
+
+ project_with_deployment = create(:project)
+ deployment = create(:pages_deployment, project: project_with_deployment)
+ project_with_deployment.mark_pages_as_deployed
+ project_with_deployment.update_pages_deployment!(deployment)
+
+ expect(described_class.only_on_legacy_storage).to eq([legacy_storage_project.pages_metadatum])
+ end
+ end
+end
diff --git a/spec/models/project_services/alerts_service_spec.rb b/spec/models/project_services/alerts_service_spec.rb
index db25885c76a..75b91c29914 100644
--- a/spec/models/project_services/alerts_service_spec.rb
+++ b/spec/models/project_services/alerts_service_spec.rb
@@ -2,108 +2,38 @@
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) }
- let(:service_params) { { project: project, active: active } }
- let(:active) { true }
- let(:service) { described_class.new(service_params) }
+ subject(:service) { described_class.new(project: project) }
- shared_context 'when active' do
- let(:active) { true }
- end
-
- shared_context 'when inactive' do
- let(:active) { false }
- end
-
- shared_context 'when persisted' do
- before do
- service.save!
- service.reload
- end
- end
-
- describe '#url' do
- include Gitlab::Routing
-
- subject { service.url }
+ it { is_expected.to be_valid }
- it { is_expected.to eq(project_alerts_notify_url(project, format: :json)) }
- end
-
- describe '#json_fields' do
- subject { service.json_fields }
+ describe '#to_param' do
+ subject { service.to_param }
- it { is_expected.to eq(%w(active token)) }
+ it { is_expected.to eq('alerts') }
end
- describe '#as_json' do
- subject { service.as_json(only: service.json_fields) }
+ describe '#supported_events' do
+ subject { service.supported_events }
- it { is_expected.to eq('active' => true, 'token' => nil) }
+ it { is_expected.to be_empty }
end
- describe '#token' do
- shared_context 'reset token' do
- before do
- service.token = ''
- service.valid?
- end
- end
-
- shared_context 'assign token' do |token|
- before do
- service.token = token
- service.valid?
- end
- end
-
- shared_examples 'valid token' do
- it { is_expected.to match(/\A\h{32}\z/) }
- end
-
- shared_examples 'no token' do
- it { is_expected.to be_blank }
- end
-
- subject { service.token }
-
- context 'when active' do
- include_context 'when active'
-
- context 'when resetting' do
- let!(:previous_token) { service.token }
-
- include_context 'reset token'
-
- it_behaves_like 'valid token'
-
- it { is_expected.not_to eq(previous_token) }
- end
-
- context 'when assigning' do
- include_context 'assign token', 'random token'
-
- it_behaves_like 'valid token'
- end
- end
-
- context 'when inactive' do
- include_context 'when inactive'
-
- context 'when resetting' do
- let!(:previous_token) { service.token }
-
- include_context 'reset token'
-
- it_behaves_like 'no token'
- end
- 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')
+ )
- context 'when persisted' do
- include_context 'when persisted'
+ expect(service.save).to be_falsey
- it_behaves_like 'valid token'
+ 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/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index e7cd3d7f537..cd0873bddd2 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -5,12 +5,21 @@ require 'spec_helper'
RSpec.describe JiraService do
include AssetsHelpers
+ let_it_be(:project) { create(:project, :repository) }
let(:url) { 'http://jira.example.com' }
let(:api_url) { 'http://api-jira.example.com' }
let(:username) { 'jira-username' }
let(:password) { 'jira-password' }
let(:transition_id) { 'test27' }
let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
+ let(:jira_service) do
+ described_class.new(
+ project: project,
+ url: url,
+ username: username,
+ password: password
+ )
+ end
before do
WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json )
@@ -19,7 +28,7 @@ RSpec.describe JiraService do
describe '#options' do
let(:options) do
{
- project: create(:project),
+ project: project,
active: true,
username: 'username',
password: 'test',
@@ -108,7 +117,7 @@ RSpec.describe JiraService do
describe '#create' do
let(:params) do
{
- project: create(:project),
+ project: project,
url: url, api_url: api_url,
username: username, password: password,
jira_issue_transition_id: transition_id
@@ -434,10 +443,23 @@ RSpec.describe JiraService do
end
end
+ describe '#find_issue' do
+ let(:issue_key) { 'JIRA-123' }
+ let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
+
+ before do
+ stub_request(:get, issue_url).with(basic_auth: [username, password])
+ end
+
+ it 'call the Jira API to get the issue' do
+ jira_service.find_issue(issue_key)
+
+ expect(WebMock).to have_requested(:get, issue_url)
+ end
+ end
+
describe '#close_issue' do
let(:custom_base_url) { 'http://custom_url' }
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
shared_examples 'close_issue' do
before do
@@ -445,7 +467,6 @@ RSpec.describe JiraService do
allow(@jira_service).to receive_messages(
project_id: project.id,
project: project,
- service_hook: true,
url: 'http://jira.example.com',
username: 'gitlab_jira_username',
password: 'gitlab_jira_password',
@@ -657,17 +678,7 @@ RSpec.describe JiraService do
end
describe '#create_cross_reference_note' do
- let_it_be(:user) { build_stubbed(:user) }
- let_it_be(:project) { create(:project, :repository) }
- let(:jira_service) do
- described_class.new(
- project: project,
- url: url,
- username: username,
- password: password
- )
- end
-
+ let_it_be(:user) { build_stubbed(:user) }
let(:jira_issue) { ExternalIssue.new('JIRA-123', project) }
subject { jira_service.create_cross_reference_note(jira_issue, resource, user) }
@@ -732,15 +743,6 @@ RSpec.describe JiraService do
describe '#test' do
let(:server_info_results) { { 'url' => 'http://url', 'deploymentType' => 'Cloud' } }
- let_it_be(:project) { create(:project, :repository) }
- let(:jira_service) do
- described_class.new(
- url: url,
- project: project,
- username: username,
- password: password
- )
- end
def server_info
jira_service.test(nil)
@@ -790,7 +792,6 @@ RSpec.describe JiraService do
}
allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
- project = create(:project)
service = project.create_jira_service(active: true)
expect(service.url).to eq('http://jira.sample/projects/project_a')
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index 76fc5a826c9..8215fb5c336 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
service.api_url = 'http://localhost:9090'
stub_application_setting(self_monitoring_project_id: project.id)
- stub_config(prometheus: { enable: true, listen_address: 'localhost:9090' })
+ stub_config(prometheus: { enable: true, server_address: 'localhost:9090' })
end
it 'allows self-monitoring project to connect to internal Prometheus' do
@@ -242,7 +242,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
stub_config(prometheus: {
enable: true,
- listen_address: api_url
+ server_address: api_url
})
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a71b0eb842a..a2b51684d4d 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -127,6 +127,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_many(:reviews).inverse_of(:project) }
it { is_expected.to have_many(:packages).class_name('Packages::Package') }
it { is_expected.to have_many(:package_files).class_name('Packages::PackageFile') }
+ it { is_expected.to have_many(:debian_distributions).class_name('Packages::Debian::ProjectDistribution').dependent(:destroy) }
it { is_expected.to have_many(:pipeline_artifacts) }
it { is_expected.to have_many(:terraform_states).class_name('Terraform::State').inverse_of(:project) }
@@ -1066,36 +1067,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#cache_has_external_wiki' do
- let_it_be(:project) { create(:project, has_external_wiki: nil) }
-
- it 'stores true if there is any external_wikis' do
- services = double(:service, external_wikis: [ExternalWikiService.new])
- expect(project).to receive(:services).and_return(services)
-
- expect do
- project.cache_has_external_wiki
- end.to change { project.has_external_wiki}.to(true)
- end
-
- it 'stores false if there is no external_wikis' do
- services = double(:service, external_wikis: [])
- expect(project).to receive(:services).and_return(services)
-
- expect do
- project.cache_has_external_wiki
- end.to change { project.has_external_wiki}.to(false)
- end
-
- it 'does not cache data when in a read-only GitLab instance' do
- allow(Gitlab::Database).to receive(:read_only?) { true }
-
- expect do
- project.cache_has_external_wiki
- end.not_to change { project.has_external_wiki }
- end
- end
-
describe '#has_wiki?' do
let(:no_wiki_project) { create(:project, :wiki_disabled, has_external_wiki: false) }
let(:wiki_enabled_project) { create(:project) }
@@ -1135,52 +1106,64 @@ RSpec.describe Project, factory_default: :keep do
describe '#external_wiki' do
let_it_be(:project) { create(:project) }
- context 'with an active external wiki' do
- before do
- create(:service, project: project, type: 'ExternalWikiService', active: true)
- project.external_wiki
- end
+ def subject
+ project.reload.external_wiki
+ end
- it 'sets :has_external_wiki as true' do
- expect(project.has_external_wiki).to be(true)
- end
+ it 'returns an active external wiki' do
+ create(:service, project: project, type: 'ExternalWikiService', active: true)
- it 'sets :has_external_wiki as false if an external wiki service is destroyed later' do
- expect(project.has_external_wiki).to be(true)
+ is_expected.to be_kind_of(ExternalWikiService)
+ end
- project.services.external_wikis.first.destroy
+ it 'does not return an inactive external wiki' do
+ create(:service, project: project, type: 'ExternalWikiService', active: false)
- expect(project.has_external_wiki).to be(false)
- end
+ is_expected.to eq(nil)
end
- context 'with an inactive external wiki' do
- before do
- create(:service, project: project, type: 'ExternalWikiService', active: false)
- end
+ it 'sets Project#has_external_wiki when it is nil' do
+ create(:service, project: project, type: 'ExternalWikiService', active: true)
+ project.update_column(:has_external_wiki, nil)
- it 'sets :has_external_wiki as false' do
- expect(project.has_external_wiki).to be(false)
- end
+ expect { subject }.to change { project.has_external_wiki }.from(nil).to(true)
end
+ end
- context 'with no external wiki' do
- before do
- project.external_wiki
- end
+ describe '#has_external_wiki' do
+ let_it_be(:project) { create(:project) }
- it 'sets :has_external_wiki as false' do
- expect(project.has_external_wiki).to be(false)
- end
+ def subject
+ project.reload.has_external_wiki
+ end
- it 'sets :has_external_wiki as true if an external wiki service is created later' do
- expect(project.has_external_wiki).to be(false)
+ specify { is_expected.to eq(false) }
+ context 'when there is an active external wiki service' do
+ let!(:service) do
create(:service, project: project, type: 'ExternalWikiService', active: true)
+ end
+
+ specify { is_expected.to eq(true) }
+
+ it 'becomes false if the external wiki service is destroyed' do
+ expect do
+ Service.find(service.id).delete
+ end.to change { subject }.to(false)
+ end
- expect(project.has_external_wiki).to be(true)
+ it 'becomes false if the external wiki service becomes inactive' do
+ expect do
+ service.update_column(:active, false)
+ end.to change { subject }.to(false)
end
end
+
+ it 'is false when external wiki service is not active' do
+ create(:service, project: project, type: 'ExternalWikiService', active: false)
+
+ is_expected.to eq(false)
+ end
end
describe '#star_count' do
@@ -1516,63 +1499,13 @@ RSpec.describe Project, factory_default: :keep do
allow(::Gitlab::ServiceDeskEmail).to receive(:config).and_return(config)
end
- context 'when service_desk_custom_address flag is enabled' do
- before do
- stub_feature_flags(service_desk_custom_address: true)
- end
-
- it 'returns custom address when project_key is set' do
- create(:service_desk_setting, project: project, project_key: 'key1')
-
- expect(subject).to eq("foo+#{project.full_path_slug}-key1@bar.com")
- end
+ it 'returns custom address when project_key is set' do
+ create(:service_desk_setting, project: project, project_key: 'key1')
- it_behaves_like 'with incoming email address'
+ expect(subject).to eq("foo+#{project.full_path_slug}-key1@bar.com")
end
- context 'when service_desk_custom_address flag is disabled' do
- before do
- stub_feature_flags(service_desk_custom_address: false)
- end
-
- it_behaves_like 'with incoming email address'
- end
- end
- end
-
- describe '.service_desk_custom_address_enabled?' do
- let_it_be(:project) { create(:project, service_desk_enabled: true) }
-
- subject(:address_enabled) { project.service_desk_custom_address_enabled? }
-
- context 'when service_desk_email is enabled' do
- before do
- allow(::Gitlab::ServiceDeskEmail).to receive(:enabled?).and_return(true)
- end
-
- it 'returns true' do
- expect(address_enabled).to be_truthy
- end
-
- context 'when service_desk_custom_address flag is disabled' do
- before do
- stub_feature_flags(service_desk_custom_address: false)
- end
-
- it 'returns false' do
- expect(address_enabled).to be_falsey
- end
- end
- end
-
- context 'when service_desk_email is disabled' do
- before do
- allow(::Gitlab::ServiceDeskEmail).to receive(:enabled?).and_return(false)
- end
-
- it 'returns false when service_desk_email is disabled' do
- expect(address_enabled).to be_falsey
- end
+ it_behaves_like 'with incoming email address'
end
end
@@ -3044,56 +2977,9 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#pushes_since_gc' do
- let(:project) { build_stubbed(:project) }
-
- after do
- project.reset_pushes_since_gc
- end
-
- context 'without any pushes' do
- it 'returns 0' do
- expect(project.pushes_since_gc).to eq(0)
- end
- end
-
- context 'with a number of pushes' do
- it 'returns the number of pushes' do
- 3.times { project.increment_pushes_since_gc }
-
- expect(project.pushes_since_gc).to eq(3)
- end
- end
- end
-
- describe '#increment_pushes_since_gc' do
- let(:project) { build_stubbed(:project) }
-
- after do
- project.reset_pushes_since_gc
- end
-
- it 'increments the number of pushes since the last GC' do
- 3.times { project.increment_pushes_since_gc }
-
- expect(project.pushes_since_gc).to eq(3)
- end
- end
-
- describe '#reset_pushes_since_gc' do
- let(:project) { build_stubbed(:project) }
-
- after do
- project.reset_pushes_since_gc
- end
-
- it 'resets the number of pushes since the last GC' do
- 3.times { project.increment_pushes_since_gc }
-
- project.reset_pushes_since_gc
-
- expect(project.pushes_since_gc).to eq(0)
- end
+ it_behaves_like 'can housekeep repository' do
+ let(:resource) { build_stubbed(:project) }
+ let(:resource_key) { 'projects' }
end
describe '#deployment_variables' do
@@ -4548,6 +4434,24 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#predefined_project_variables' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ subject { project.predefined_project_variables.to_runner_variables }
+
+ specify do
+ expect(subject).to include({ key: 'CI_PROJECT_CONFIG_PATH', value: Ci::Pipeline::DEFAULT_CONFIG_PATH, public: true, masked: false })
+ end
+
+ context 'when ci config path is overridden' do
+ before do
+ project.update!(ci_config_path: 'random.yml')
+ end
+
+ it { expect(subject).to include({ key: 'CI_PROJECT_CONFIG_PATH', value: 'random.yml', public: true, masked: false }) }
+ end
+ end
+
describe '#auto_devops_enabled?' do
before do
Feature.enable_percentage_of_actors(:force_autodevops_on_by_default, 0)
@@ -6002,6 +5906,43 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#set_first_pages_deployment!' do
+ let(:project) { create(:project) }
+ let(:deployment) { create(:pages_deployment, project: project) }
+
+ it "creates new metadata record if none exists yet and sets deployment" do
+ project.pages_metadatum.destroy!
+ project.reload
+
+ project.set_first_pages_deployment!(deployment)
+
+ expect(project.pages_metadatum.reload.pages_deployment).to eq(deployment)
+ end
+
+ it "updates the existing metadara record with deployment" do
+ expect do
+ project.set_first_pages_deployment!(deployment)
+ end.to change { project.pages_metadatum.reload.pages_deployment }.from(nil).to(deployment)
+ end
+
+ it 'only updates metadata for this project' do
+ other_project = create(:project)
+
+ expect do
+ project.set_first_pages_deployment!(deployment)
+ end.not_to change { other_project.pages_metadatum.reload.pages_deployment }.from(nil)
+ end
+
+ it 'does nothing if metadata already references some deployment' do
+ existing_deployment = create(:pages_deployment, project: project)
+ project.set_first_pages_deployment!(existing_deployment)
+
+ expect do
+ project.set_first_pages_deployment!(deployment)
+ end.not_to change { project.pages_metadatum.reload.pages_deployment }.from(existing_deployment)
+ end
+ end
+
describe '#has_pool_repsitory?' do
it 'returns false when it does not have a pool repository' do
subject = create(:project, :repository)
@@ -6275,28 +6216,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#alerts_service_activated?' do
- let!(:project) { create(:project) }
-
- subject { project.alerts_service_activated? }
-
- context 'when project has an activated alerts service' do
- before do
- create(:alerts_service, project: project)
- end
-
- it { is_expected.to be_truthy }
- end
-
- context 'when project has an inactive alerts service' do
- before do
- create(:alerts_service, :inactive, project: project)
- end
-
- it { is_expected.to be_falsey }
- end
- end
-
describe '#prometheus_service_active?' do
let(:project) { create(:project) }
@@ -6456,6 +6375,25 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ 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
+ end
+
describe '#environments_for_scope' do
let_it_be(:project, reload: true) { create(:project) }
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 2e82fcf5511..8001d009901 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -42,4 +42,10 @@ RSpec.describe ProjectWiki do
end
end
end
+
+ it_behaves_like 'can housekeep repository' do
+ let_it_be(:resource) { create(:project_wiki) }
+
+ let(:resource_key) { 'project_wikis' }
+ end
end
diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb
index c51197234ca..918c3078405 100644
--- a/spec/models/protectable_dropdown_spec.rb
+++ b/spec/models/protectable_dropdown_spec.rb
@@ -14,21 +14,33 @@ RSpec.describe ProtectableDropdown do
end
describe '#protectable_ref_names' do
- before do
- project.protected_branches.create(name: 'master')
- end
+ context 'when project repository is not empty' do
+ before do
+ project.protected_branches.create(name: 'master')
+ end
+
+ it { expect(subject.protectable_ref_names).to include('feature') }
+ it { expect(subject.protectable_ref_names).not_to include('master') }
+
+ it "includes branches matching a protected branch wildcard" do
+ expect(subject.protectable_ref_names).to include('feature')
- it { expect(subject.protectable_ref_names).to include('feature') }
- it { expect(subject.protectable_ref_names).not_to include('master') }
+ create(:protected_branch, name: 'feat*', project: project)
- it "includes branches matching a protected branch wildcard" do
- expect(subject.protectable_ref_names).to include('feature')
+ subject = described_class.new(project.reload, :branches)
+
+ expect(subject.protectable_ref_names).to include('feature')
+ end
+ end
- create(:protected_branch, name: 'feat*', project: project)
+ context 'when project repository is empty' do
+ let(:project) { create(:project) }
- subject = described_class.new(project.reload, :branches)
+ it "returns empty list" do
+ subject = described_class.new(project, :branches)
- expect(subject.protectable_ref_names).to include('feature')
+ expect(subject.protectable_ref_names).to be_empty
+ end
end
end
end
diff --git a/spec/models/release_highlight_spec.rb b/spec/models/release_highlight_spec.rb
index ac252e6d6cf..749b9b8e1ab 100644
--- a/spec/models/release_highlight_spec.rb
+++ b/spec/models/release_highlight_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ReleaseHighlight do
- let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')) }
+ let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')).grep(/\d*\_(\d*\_\d*)\.yml$/) }
before do
allow(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index fea15ea00c8..b436c2e1088 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Release do
- let(:user) { create(:user) }
- let(:project) { create(:project, :public, :repository) }
- let(:release) { create(:release, project: project, author: user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:release) { create(:release, project: project, author: user) }
it { expect(release).to be_valid }
@@ -132,8 +132,10 @@ RSpec.describe Release do
end
describe '#milestone_titles' do
- let(:release) { create(:release, :with_milestones) }
+ let_it_be(:milestone_1) { create(:milestone, project: project, title: 'Milestone 1') }
+ let_it_be(:milestone_2) { create(:milestone, project: project, title: 'Milestone 2') }
+ let_it_be(:release) { create(:release, project: project, milestones: [milestone_1, milestone_2]) }
- it { expect(release.milestone_titles).to eq(release.milestones.map {|m| m.title }.sort.join(", "))}
+ it { expect(release.milestone_titles).to eq("#{milestone_1.title}, #{milestone_2.title}")}
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index c1f073e26d1..dd54a701282 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -123,7 +123,7 @@ RSpec.describe Repository do
options = { message: 'test tag message\n',
tagger: { name: 'John Smith', email: 'john@gmail.com' } }
- rugged_repo(repository).tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', options)
+ rugged_repo(repository).tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', **options)
double_first = double(committed_date: Time.current - 1.second)
double_last = double(committed_date: Time.current)
@@ -2028,6 +2028,22 @@ RSpec.describe Repository do
end
end
+ describe '#lookup' do
+ before do
+ allow(repository.raw_repository).to receive(:lookup).and_return('interesting_blob')
+ end
+
+ it 'uses the lookup cache' do
+ 2.times.each { repository.lookup('sha1') }
+
+ expect(repository.raw_repository).to have_received(:lookup).once
+ end
+
+ it 'returns the correct value' do
+ expect(repository.lookup('sha1')).to eq('interesting_blob')
+ end
+ end
+
describe '#after_create' do
it 'calls expire_status_cache' do
expect(repository).to receive(:expire_status_cache)
diff --git a/spec/models/snippet_repository_storage_move_spec.rb b/spec/models/snippet_repository_storage_move_spec.rb
index c9feff0c22f..357951f8859 100644
--- a/spec/models/snippet_repository_storage_move_spec.rb
+++ b/spec/models/snippet_repository_storage_move_spec.rb
@@ -8,6 +8,6 @@ RSpec.describe SnippetRepositoryStorageMove, type: :model do
let(:repository_storage_factory_key) { :snippet_repository_storage_move }
let(:error_key) { :snippet }
- let(:repository_storage_worker) { nil } # TODO set to SnippetUpdateRepositoryStorageWorker after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
+ let(:repository_storage_worker) { SnippetUpdateRepositoryStorageWorker }
end
end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index f87259ea048..68d183d5d55 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -796,4 +796,90 @@ RSpec.describe Snippet do
it_behaves_like 'can move repository storage' do
let_it_be(:container) { create(:snippet, :repository) }
end
+
+ describe '#change_head_to_default_branch' do
+ let(:head_path) { Rails.root.join(TestEnv.repos_path, "#{snippet.disk_path}.git", 'HEAD') }
+
+ subject { snippet.change_head_to_default_branch }
+
+ context 'when repository does not exist' do
+ let(:snippet) { create(:snippet) }
+
+ it 'does nothing' do
+ expect(snippet.repository_exists?).to eq false
+ expect(snippet.repository.raw_repository).not_to receive(:write_ref)
+
+ subject
+ end
+ end
+
+ context 'when repository is empty' do
+ let(:snippet) { create(:snippet, :empty_repo) }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return(default_branch)
+ end
+
+ context 'when default branch in settings is "master"' do
+ let(:default_branch) { 'master' }
+
+ it 'does nothing' do
+ expect(File.read(head_path).squish).to eq 'ref: refs/heads/master'
+
+ expect(snippet.repository.raw_repository).not_to receive(:write_ref)
+
+ subject
+ end
+ end
+
+ context 'when default branch in settings is different from "master"' do
+ let(:default_branch) { 'main' }
+
+ it 'changes the HEAD reference to the default branch' do
+ expect(File.read(head_path).squish).to eq 'ref: refs/heads/master'
+
+ subject
+
+ expect(File.read(head_path).squish).to eq "ref: refs/heads/#{default_branch}"
+ end
+ end
+ end
+
+ context 'when repository is not empty' do
+ let(:snippet) { create(:snippet, :empty_repo) }
+
+ before do
+ populate_snippet_repo
+ end
+
+ context 'when HEAD branch is empty' do
+ it 'changes HEAD to default branch' do
+ File.write(head_path, 'ref: refs/heads/non_existen_branch')
+ expect(File.read(head_path).squish).to eq 'ref: refs/heads/non_existen_branch'
+
+ subject
+
+ expect(File.read(head_path).squish).to eq 'ref: refs/heads/main'
+ expect(snippet.list_files('HEAD')).not_to be_empty
+ end
+ end
+
+ context 'when HEAD branch is not empty' do
+ it 'does nothing' do
+ File.write(head_path, 'ref: refs/heads/main')
+
+ expect(snippet.repository.raw_repository).not_to receive(:write_ref)
+
+ subject
+ end
+ end
+
+ def populate_snippet_repo
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('main')
+
+ data = [{ file_path: 'new_file_test', content: 'bar' }]
+ snippet.snippet_repository.multi_files_action(snippet.author, data, branch_name: 'main', message: 'foo')
+ end
+ end
+ end
end
diff --git a/spec/models/terraform/state_spec.rb b/spec/models/terraform/state_spec.rb
index ef91e4a5a71..ed311314086 100644
--- a/spec/models/terraform/state_spec.rb
+++ b/spec/models/terraform/state_spec.rb
@@ -27,6 +27,22 @@ RSpec.describe Terraform::State do
end
end
+ describe '#destroy' do
+ let(:terraform_state) { create(:terraform_state) }
+ let(:user) { terraform_state.project.creator }
+
+ it 'deletes when the state is unlocked' do
+ expect(terraform_state.destroy).to be_truthy
+ end
+
+ it 'fails to delete when the state is locked', :aggregate_failures do
+ terraform_state.update!(lock_xid: SecureRandom.uuid, locked_by_user: user, locked_at: Time.current)
+
+ expect(terraform_state.destroy).to be_falsey
+ expect(terraform_state.errors.full_messages).to eq(["You cannot remove the State file because it's locked. Unlock the State file first before removing it."])
+ end
+ end
+
describe '#latest_file' do
let(:terraform_state) { create(:terraform_state, :with_version) }
let(:latest_version) { terraform_state.latest_version }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index fb05c9e8052..0935d3576a4 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -4084,6 +4084,7 @@ RSpec.describe User do
cache_mock = double
expect(cache_mock).to receive(:delete).with(['users', user.id, 'assigned_open_merge_requests_count'])
+ expect(cache_mock).to receive(:delete).with(['users', user.id, 'review_requested_open_merge_requests_count'])
allow(Rails).to receive(:cache).and_return(cache_mock)
@@ -4163,6 +4164,20 @@ RSpec.describe User do
end
end
+ describe '#review_requested_open_merge_requests_count' do
+ it 'returns number of open merge requests from non-archived projects' do
+ user = create(:user)
+ project = create(:project, :public)
+ archived_project = create(:project, :public, :archived)
+
+ create(:merge_request, source_project: project, author: user, reviewers: [user])
+ create(:merge_request, :closed, source_project: project, author: user, reviewers: [user])
+ create(:merge_request, source_project: archived_project, author: user, reviewers: [user])
+
+ expect(user.review_requested_open_merge_requests_count(force: true)).to eq 1
+ end
+ end
+
describe '#assigned_open_issues_count' do
it 'returns number of open issues from non-archived projects' do
user = create(:user)
@@ -4265,7 +4280,7 @@ RSpec.describe User do
it 'adds the namespace errors to the user' do
user.update(username: new_username)
- expect(user.errors.full_messages.first).to eq('Username has already been taken')
+ expect(user.errors.full_messages.first).to eq('A user, alias, or group already exists with that username.')
end
end
end
@@ -5074,9 +5089,10 @@ RSpec.describe User do
end
describe '#hook_attrs' do
- it 'includes name, username, avatar_url, and email' do
+ it 'includes id, name, username, avatar_url, and email' do
user = create(:user)
user_attributes = {
+ id: user.id,
name: user.name,
username: user.username,
avatar_url: user.avatar_url(only_path: false),
diff --git a/spec/policies/group_member_policy_spec.rb b/spec/policies/group_member_policy_spec.rb
index 9e58ea81ef3..6099e4549b1 100644
--- a/spec/policies/group_member_policy_spec.rb
+++ b/spec/policies/group_member_policy_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe GroupMemberPolicy do
+ include DesignManagementTestHelpers
+
let(:guest) { create(:user) }
let(:owner) { create(:user) }
let(:group) { create(:group, :private) }
@@ -28,22 +30,64 @@ RSpec.describe GroupMemberPolicy do
permissions.each { |p| is_expected.not_to be_allowed(p) }
end
- context 'with guest user' do
- let(:current_user) { guest }
+ context 'with anonymous user' do
+ let(:group) { create(:group, :public) }
+ let(:current_user) { nil }
+ let(:membership) { guest.members.first }
it do
- expect_disallowed(:member_related_permissions)
+ expect_disallowed(:read_design_activity, *member_related_permissions)
+ expect_allowed(:read_group)
+ end
+
+ context 'design management is enabled' do
+ before do
+ create(:project, :public, group: group) # Necessary to enable design management
+ enable_design_management
+ end
+
+ specify do
+ expect_allowed(:read_design_activity)
+ end
+ end
+
+ context 'for a private group' do
+ let(:group) { create(:group, :private) }
+
+ specify do
+ expect_disallowed(:read_group, :read_design_activity, *member_related_permissions)
+ end
+ end
+
+ context 'for an internal group' do
+ let(:group) { create(:group, :internal) }
+
+ specify do
+ expect_disallowed(:read_group, :read_design_activity, *member_related_permissions)
+ end
end
end
+ context 'with guest user, for own membership' do
+ let(:current_user) { guest }
+
+ specify { expect_disallowed(:update_group_member) }
+ specify { expect_allowed(:read_group, :destroy_group_member) }
+ end
+
+ context 'with guest user, for other membership' do
+ let(:current_user) { guest }
+ let(:membership) { owner.members.first }
+
+ specify { expect_disallowed(:destroy_group_member, :update_group_member) }
+ specify { expect_allowed(:read_group) }
+ end
+
context 'with one owner' do
let(:current_user) { owner }
- it do
- expect_disallowed(:destroy_group_member)
- expect_disallowed(:update_group_member)
- expect_allowed(:read_group)
- end
+ specify { expect_disallowed(*member_related_permissions) }
+ specify { expect_allowed(:read_group) }
end
context 'with more than one owner' do
@@ -53,10 +97,7 @@ RSpec.describe GroupMemberPolicy do
group.add_owner(create(:user))
end
- it do
- expect_allowed(:destroy_group_member)
- expect_allowed(:update_group_member)
- end
+ specify { expect_allowed(*member_related_permissions) }
end
context 'with the group parent' do
diff --git a/spec/policies/namespace_policy_spec.rb b/spec/policies/namespace_policy_spec.rb
index 514d7303ad7..b9823273de8 100644
--- a/spec/policies/namespace_policy_spec.rb
+++ b/spec/policies/namespace_policy_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe NamespacePolicy do
let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, owner: owner) }
- let(:owner_permissions) { [:owner_access, :create_projects, :admin_namespace, :read_namespace, :read_statistics, :transfer_projects] }
+ let(:owner_permissions) { [:owner_access, :create_projects, :admin_namespace, :read_namespace, :read_statistics, :transfer_projects, :create_package_settings, :read_package_settings] }
subject { described_class.new(current_user, namespace) }
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index c21d3b0939f..e6650549f7f 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -401,6 +401,48 @@ RSpec.describe ProjectPolicy do
end
end
+ describe 'set_pipeline_variables' do
+ context 'when user is developer' do
+ let(:current_user) { developer }
+
+ context 'when project allows user defined variables' do
+ before do
+ project.update!(restrict_user_defined_variables: false)
+ end
+
+ it { is_expected.to be_allowed(:set_pipeline_variables) }
+ end
+
+ context 'when project restricts use of user defined variables' do
+ before do
+ project.update!(restrict_user_defined_variables: true)
+ end
+
+ it { is_expected.not_to be_allowed(:set_pipeline_variables) }
+ end
+ end
+
+ context 'when user is maintainer' do
+ let(:current_user) { maintainer }
+
+ context 'when project allows user defined variables' do
+ before do
+ project.update!(restrict_user_defined_variables: false)
+ end
+
+ it { is_expected.to be_allowed(:set_pipeline_variables) }
+ end
+
+ context 'when project restricts use of user defined variables' do
+ before do
+ project.update!(restrict_user_defined_variables: true)
+ end
+
+ it { is_expected.to be_allowed(:set_pipeline_variables) }
+ end
+ end
+ end
+
context 'support bot' do
let(:current_user) { User.support_bot }
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index ce4c5a2db7d..f78ad38f4e8 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -189,7 +189,21 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns the correct refspecs' do
is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}",
- "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ "+#{pipeline.sha}:refs/pipelines/#{pipeline.id}")
+ end
+
+ it 'uses a SHA in the persistent refspec' 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
@@ -197,7 +211,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns the correct refspecs' do
is_expected.to contain_exactly("+refs/tags/#{build.ref}:refs/tags/#{build.ref}",
- "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ "+#{pipeline.sha}:refs/pipelines/#{pipeline.id}")
end
context 'when GIT_DEPTH is zero' do
@@ -208,7 +222,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns the correct refspecs' do
is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
'+refs/heads/*:refs/remotes/origin/*',
- "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ "+#{pipeline.sha}:refs/pipelines/#{pipeline.id}")
end
end
end
@@ -224,7 +238,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns the correct refspecs' do
is_expected
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ .to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}")
end
context 'when GIT_DEPTH is zero' do
@@ -234,7 +248,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns the correct refspecs' do
is_expected
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ .to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
'+refs/heads/*:refs/remotes/origin/*',
'+refs/tags/*:refs/tags/*')
end
@@ -244,7 +258,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ is_expected.to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
"+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
end
end
@@ -262,7 +276,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'exposes the persistent pipeline ref' do
is_expected
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ .to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
"+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
end
end
diff --git a/spec/presenters/packages/nuget/service_index_presenter_spec.rb b/spec/presenters/packages/nuget/service_index_presenter_spec.rb
index 19ef890e19f..9c95fbc8fd2 100644
--- a/spec/presenters/packages/nuget/service_index_presenter_spec.rb
+++ b/spec/presenters/packages/nuget/service_index_presenter_spec.rb
@@ -4,25 +4,64 @@ require 'spec_helper'
RSpec.describe ::Packages::Nuget::ServiceIndexPresenter do
let_it_be(:project) { create(:project) }
- let_it_be(:presenter) { described_class.new(project) }
+ let_it_be(:group) { create(:group) }
+
+ let(:presenter) { described_class.new(target) }
describe '#version' do
subject { presenter.version }
- it { is_expected.to eq '3.0.0' }
+ context 'for a group' do
+ let(:target) { group }
+
+ it { is_expected.to eq '3.0.0' }
+ end
+
+ context 'for a project' do
+ let(:target) { project }
+
+ it { is_expected.to eq '3.0.0' }
+ end
end
describe '#resources' do
subject { presenter.resources }
- it 'has valid resources' do
- expect(subject.size).to eq 8
- subject.each do |resource|
- %i[@id @type comment].each do |field|
- expect(resource).to have_key(field)
- expect(resource[field]).to be_a(String)
+ shared_examples 'returning valid resources' do |resources_count: 8, include_publish_service: true|
+ it 'has valid resources' do
+ expect(subject.size).to eq resources_count
+ subject.each do |resource|
+ %i[@id @type comment].each do |field|
+ expect(resource).to have_key(field)
+ expect(resource[field]).to be_a(String)
+ end
+ end
+ end
+
+ it "does #{'not ' unless include_publish_service}return the publish resource" do
+ services_types = subject.map { |res| res[:@type] }
+
+ described_class::SERVICE_VERSIONS[:publish].each do |publish_service_version|
+ if include_publish_service
+ expect(services_types).to include(publish_service_version)
+ else
+ expect(services_types).not_to include(publish_service_version)
+ end
end
end
end
+
+ context 'for a group' do
+ let(:target) { group }
+
+ # at the group level we don't have the publish and download service
+ it_behaves_like 'returning valid resources', resources_count: 6, include_publish_service: false
+ end
+
+ context 'for a project' do
+ let(:target) { project }
+
+ it_behaves_like 'returning valid resources'
+ end
end
end
diff --git a/spec/rack_servers/puma_spec.rb b/spec/rack_servers/puma_spec.rb
index 80595b267fa..6729119fe92 100644
--- a/spec/rack_servers/puma_spec.rb
+++ b/spec/rack_servers/puma_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe 'Puma' do
end
after(:all) do
- WebMock.disable_net_connect!(allow_localhost: true)
+ webmock_enable!
Process.kill('TERM', @puma_master_pid)
rescue Errno::ESRCH
end
diff --git a/spec/rack_servers/unicorn_spec.rb b/spec/rack_servers/unicorn_spec.rb
index 5887b49d269..52d44b6e7e0 100644
--- a/spec/rack_servers/unicorn_spec.rb
+++ b/spec/rack_servers/unicorn_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'Unicorn' do
end
after(:all) do
- WebMock.disable_net_connect!(allow_localhost: true)
+ webmock_enable!
Process.kill('TERM', @unicorn_master_pid)
end
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 3cc8764de4a..9fd30213133 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -102,6 +102,7 @@ RSpec.describe API::API do
Labkit::Context.current.to_h.tap do |log_context|
expect(log_context).to match('correlation_id' => an_instance_of(String),
'meta.caller_id' => '/api/:version/projects/:id/issues',
+ 'meta.remote_ip' => an_instance_of(String),
'meta.project' => project.full_path,
'meta.root_namespace' => project.namespace.full_path,
'meta.user' => user.username,
@@ -117,6 +118,7 @@ RSpec.describe API::API do
Labkit::Context.current.to_h.tap do |log_context|
expect(log_context).to match('correlation_id' => an_instance_of(String),
'meta.caller_id' => '/api/:version/users',
+ 'meta.remote_ip' => an_instance_of(String),
'meta.feature_category' => 'users')
end
end
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index 36fc6101b84..ca6492396cd 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -53,17 +53,6 @@ RSpec.describe API::Boards do
end
end
- describe "PUT /projects/:id/boards/:board_id" do
- let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}" }
-
- it 'updates the issue board' do
- put api(url, user), params: { name: 'changed board name' }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('changed board name')
- end
- end
-
describe "DELETE /projects/:id/boards/:board_id" do
let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}" }
diff --git a/spec/requests/api/ci/runner/jobs_put_spec.rb b/spec/requests/api/ci/runner/jobs_put_spec.rb
index e9d793d5a22..f4c99307b1a 100644
--- a/spec/requests/api/ci/runner/jobs_put_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_put_spec.rb
@@ -78,6 +78,33 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when an exit_code is provided' do
+ context 'when the exit_codes are acceptable' do
+ before do
+ job.options[:allow_failure_criteria] = { exit_codes: [1] }
+ job.save!
+ end
+
+ it 'accepts an exit code' do
+ update_job(state: 'failed', exit_code: 1)
+
+ expect(job.reload).to be_failed
+ expect(job.allow_failure).to be_truthy
+ expect(job).to be_unknown_failure
+ end
+ end
+
+ context 'when the exit_codes are not defined' do
+ it 'ignore the exit code' do
+ update_job(state: 'failed', exit_code: 1)
+
+ expect(job.reload).to be_failed
+ expect(job.allow_failure).to be_falsy
+ expect(job).to be_unknown_failure
+ end
+ end
+ end
+
context 'when failure_reason is script_failure' do
before do
update_job(state: 'failed', failure_reason: 'script_failure')
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index 2dc92417892..74d8e3f7ae8 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -156,7 +156,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
'sha' => job.sha,
'before_sha' => job.before_sha,
'ref_type' => 'branch',
- 'refspecs' => ["+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ 'refspecs' => ["+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
"+refs/heads/#{job.ref}:refs/remotes/origin/#{job.ref}"],
'depth' => project.ci_default_git_depth }
end
@@ -284,7 +284,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:created)
expect(json_response['git_info']['refspecs'])
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ .to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
'+refs/tags/*:refs/tags/*',
'+refs/heads/*:refs/remotes/origin/*')
end
@@ -346,7 +346,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:created)
expect(json_response['git_info']['refspecs'])
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ .to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
'+refs/tags/*:refs/tags/*',
'+refs/heads/*:refs/remotes/origin/*')
end
diff --git a/spec/requests/api/debian_project_packages_spec.rb b/spec/requests/api/debian_project_packages_spec.rb
index d2f208d0079..663b69b1b76 100644
--- a/spec/requests/api/debian_project_packages_spec.rb
+++ b/spec/requests/api/debian_project_packages_spec.rb
@@ -42,5 +42,12 @@ RSpec.describe API::DebianProjectPackages do
it_behaves_like 'Debian project repository PUT endpoint', :created, nil
end
+
+ describe 'PUT projects/:id/-/packages/debian/incoming/:file_name/authorize' do
+ let(:method) { :put }
+ let(:url) { "/projects/#{project.id}/-/packages/debian/incoming/#{file_name}/authorize" }
+
+ it_behaves_like 'Debian project repository PUT endpoint', :created, nil, is_authorize: true
+ end
end
end
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index b8e79853486..d162d288129 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -3,8 +3,16 @@
require 'spec_helper'
RSpec.describe API::GenericPackages do
+ include HttpBasicAuthHelpers
+
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:deploy_token_rw) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:project_deploy_token_rw) { create(:project_deploy_token, deploy_token: deploy_token_rw, project: project) }
+ let_it_be(:deploy_token_ro) { create(:deploy_token, read_package_registry: true, write_package_registry: false) }
+ 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 }
@@ -22,6 +30,23 @@ RSpec.describe API::GenericPackages do
personal_access_token_header('wrong token')
when :invalid_job_token
job_token_header('wrong token')
+ when :user_basic_auth
+ user_basic_auth_header(user)
+ when :invalid_user_basic_auth
+ basic_auth_header('invalid user', 'invalid password')
+ end
+ end
+
+ def deploy_token_auth_header
+ case authenticate_with
+ when :deploy_token_rw
+ deploy_token_header(deploy_token_rw.token)
+ when :deploy_token_ro
+ deploy_token_header(deploy_token_ro.token)
+ when :deploy_token_wo
+ deploy_token_header(deploy_token_wo.token)
+ when :invalid_deploy_token
+ deploy_token_header('wrong token')
end
end
@@ -33,6 +58,10 @@ RSpec.describe API::GenericPackages do
{ Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER => value || ci_build.token }
end
+ def deploy_token_header(value)
+ { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => value }
+ end
+
shared_examples 'secure endpoint' do
before do
project.add_developer(user)
@@ -54,19 +83,35 @@ RSpec.describe API::GenericPackages do
'PUBLIC' | :guest | true | :personal_access_token | :forbidden
'PUBLIC' | :developer | true | :invalid_personal_access_token | :unauthorized
'PUBLIC' | :guest | true | :invalid_personal_access_token | :unauthorized
+ 'PUBLIC' | :developer | true | :user_basic_auth | :success
+ 'PUBLIC' | :guest | true | :user_basic_auth | :forbidden
+ 'PUBLIC' | :developer | true | :invalid_user_basic_auth | :unauthorized
+ 'PUBLIC' | :guest | true | :invalid_user_basic_auth | :unauthorized
'PUBLIC' | :developer | false | :personal_access_token | :forbidden
'PUBLIC' | :guest | false | :personal_access_token | :forbidden
'PUBLIC' | :developer | false | :invalid_personal_access_token | :unauthorized
'PUBLIC' | :guest | false | :invalid_personal_access_token | :unauthorized
+ 'PUBLIC' | :developer | false | :user_basic_auth | :forbidden
+ 'PUBLIC' | :guest | false | :user_basic_auth | :forbidden
+ 'PUBLIC' | :developer | false | :invalid_user_basic_auth | :unauthorized
+ 'PUBLIC' | :guest | false | :invalid_user_basic_auth | :unauthorized
'PUBLIC' | :anonymous | false | :none | :unauthorized
'PRIVATE' | :developer | true | :personal_access_token | :success
'PRIVATE' | :guest | true | :personal_access_token | :forbidden
'PRIVATE' | :developer | true | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | true | :invalid_personal_access_token | :unauthorized
+ 'PRIVATE' | :developer | true | :user_basic_auth | :success
+ 'PRIVATE' | :guest | true | :user_basic_auth | :forbidden
+ 'PRIVATE' | :developer | true | :invalid_user_basic_auth | :unauthorized
+ 'PRIVATE' | :guest | true | :invalid_user_basic_auth | :unauthorized
'PRIVATE' | :developer | false | :personal_access_token | :not_found
'PRIVATE' | :guest | false | :personal_access_token | :not_found
'PRIVATE' | :developer | false | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | false | :invalid_personal_access_token | :unauthorized
+ 'PRIVATE' | :developer | false | :user_basic_auth | :not_found
+ 'PRIVATE' | :guest | false | :user_basic_auth | :not_found
+ 'PRIVATE' | :developer | false | :invalid_user_basic_auth | :unauthorized
+ 'PRIVATE' | :guest | false | :invalid_user_basic_auth | :unauthorized
'PRIVATE' | :anonymous | false | :none | :unauthorized
'PUBLIC' | :developer | true | :job_token | :success
'PUBLIC' | :developer | true | :invalid_job_token | :unauthorized
@@ -90,6 +135,21 @@ RSpec.describe API::GenericPackages do
expect(response).to have_gitlab_http_status(expected_status)
end
end
+
+ where(:authenticate_with, :expected_status) do
+ :deploy_token_rw | :success
+ :deploy_token_wo | :success
+ :deploy_token_ro | :forbidden
+ :invalid_deploy_token | :unauthorized
+ end
+
+ with_them do
+ it "responds with #{params[:expected_status]}" do
+ authorize_upload_file(workhorse_header.merge(deploy_token_auth_header))
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ end
+ end
end
context 'application security' do
@@ -138,20 +198,34 @@ RSpec.describe API::GenericPackages do
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
'PUBLIC' | :developer | true | :invalid_personal_access_token | :unauthorized
'PUBLIC' | :guest | true | :invalid_personal_access_token | :unauthorized
+ 'PUBLIC' | :developer | true | :invalid_user_basic_auth | :unauthorized
+ 'PUBLIC' | :guest | true | :invalid_user_basic_auth | :unauthorized
'PUBLIC' | :developer | false | :personal_access_token | :forbidden
'PUBLIC' | :guest | false | :personal_access_token | :forbidden
+ 'PUBLIC' | :developer | false | :user_basic_auth | :forbidden
+ 'PUBLIC' | :guest | false | :user_basic_auth | :forbidden
'PUBLIC' | :developer | false | :invalid_personal_access_token | :unauthorized
'PUBLIC' | :guest | false | :invalid_personal_access_token | :unauthorized
+ 'PUBLIC' | :developer | false | :invalid_user_basic_auth | :unauthorized
+ 'PUBLIC' | :guest | false | :invalid_user_basic_auth | :unauthorized
'PUBLIC' | :anonymous | false | :none | :unauthorized
'PRIVATE' | :guest | true | :personal_access_token | :forbidden
+ 'PRIVATE' | :guest | true | :user_basic_auth | :forbidden
'PRIVATE' | :developer | true | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | true | :invalid_personal_access_token | :unauthorized
+ 'PRIVATE' | :developer | true | :invalid_user_basic_auth | :unauthorized
+ 'PRIVATE' | :guest | true | :invalid_user_basic_auth | :unauthorized
'PRIVATE' | :developer | false | :personal_access_token | :not_found
'PRIVATE' | :guest | false | :personal_access_token | :not_found
+ 'PRIVATE' | :developer | false | :user_basic_auth | :not_found
+ 'PRIVATE' | :guest | false | :user_basic_auth | :not_found
'PRIVATE' | :developer | false | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | false | :invalid_personal_access_token | :unauthorized
+ 'PRIVATE' | :developer | false | :invalid_user_basic_auth | :unauthorized
+ 'PRIVATE' | :guest | false | :invalid_user_basic_auth | :unauthorized
'PRIVATE' | :anonymous | false | :none | :unauthorized
'PUBLIC' | :developer | true | :invalid_job_token | :unauthorized
'PUBLIC' | :developer | false | :job_token | :forbidden
@@ -175,6 +249,21 @@ RSpec.describe API::GenericPackages do
expect(response).to have_gitlab_http_status(expected_status)
end
end
+
+ where(:authenticate_with, :expected_status) do
+ :deploy_token_ro | :forbidden
+ :invalid_deploy_token | :unauthorized
+ end
+
+ with_them do
+ it "responds with #{params[:expected_status]}" do
+ headers = workhorse_header.merge(deploy_token_auth_header)
+
+ upload_file(params, headers)
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ end
+ end
end
context 'when user can upload packages and has valid credentials' do
@@ -182,43 +271,58 @@ RSpec.describe API::GenericPackages do
project.add_developer(user)
end
- it 'creates package and package file when valid personal access token is used' do
- headers = workhorse_header.merge(personal_access_token_header)
+ shared_examples 'creates a package and package file' do
+ it 'creates a package and package file' do
+ headers = workhorse_header.merge(auth_header)
- expect { upload_file(params, headers) }
- .to change { project.packages.generic.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
+ expect { upload_file(params, headers) }
+ .to change { project.packages.generic.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
- aggregate_failures do
- expect(response).to have_gitlab_http_status(:created)
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:created)
- package = project.packages.generic.last
- expect(package.name).to eq('mypackage')
- expect(package.version).to eq('0.0.1')
- expect(package.original_build_info).to be_nil
+ package = project.packages.generic.last
+ expect(package.name).to eq('mypackage')
+ expect(package.version).to eq('0.0.1')
- package_file = package.package_files.last
- expect(package_file.file_name).to eq('myfile.tar.gz')
+ if should_set_build_info
+ expect(package.original_build_info.pipeline).to eq(ci_build.pipeline)
+ else
+ expect(package.original_build_info).to be_nil
+ end
+
+ package_file = package.package_files.last
+ expect(package_file.file_name).to eq('myfile.tar.gz')
+ end
end
end
- it 'creates package, package file, and package build info when valid job token is used' do
- headers = workhorse_header.merge(job_token_header)
-
- expect { upload_file(params, headers) }
- .to change { project.packages.generic.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
+ context 'when valid personal access token is used' do
+ it_behaves_like 'creates a package and package file' do
+ let(:auth_header) { personal_access_token_header }
+ let(:should_set_build_info) { false }
+ end
+ end
- aggregate_failures do
- expect(response).to have_gitlab_http_status(:created)
+ context 'when valid basic auth is used' do
+ it_behaves_like 'creates a package and package file' do
+ let(:auth_header) { user_basic_auth_header(user) }
+ let(:should_set_build_info) { false }
+ end
+ end
- package = project.packages.generic.last
- expect(package.name).to eq('mypackage')
- expect(package.version).to eq('0.0.1')
- expect(package.original_build_info.pipeline).to eq(ci_build.pipeline)
+ context 'when valid deploy token is used' do
+ it_behaves_like 'creates a package and package file' do
+ let(:auth_header) { deploy_token_header(deploy_token_wo.token) }
+ let(:should_set_build_info) { false }
+ end
+ end
- package_file = package.package_files.last
- expect(package_file.file_name).to eq('myfile.tar.gz')
+ context 'when valid job token is used' do
+ it_behaves_like 'creates a package and package file' do
+ let(:auth_header) { job_token_header }
+ let(:should_set_build_info) { true }
end
end
@@ -309,21 +413,37 @@ RSpec.describe API::GenericPackages do
where(:project_visibility, :user_role, :member?, :authenticate_with, :expected_status) do
'PUBLIC' | :developer | true | :personal_access_token | :success
'PUBLIC' | :guest | true | :personal_access_token | :success
+ 'PUBLIC' | :developer | true | :user_basic_auth | :success
+ 'PUBLIC' | :guest | true | :user_basic_auth | :success
'PUBLIC' | :developer | true | :invalid_personal_access_token | :unauthorized
'PUBLIC' | :guest | true | :invalid_personal_access_token | :unauthorized
+ 'PUBLIC' | :developer | true | :invalid_user_basic_auth | :unauthorized
+ 'PUBLIC' | :guest | true | :invalid_user_basic_auth | :unauthorized
'PUBLIC' | :developer | false | :personal_access_token | :success
'PUBLIC' | :guest | false | :personal_access_token | :success
+ 'PUBLIC' | :developer | false | :user_basic_auth | :success
+ 'PUBLIC' | :guest | false | :user_basic_auth | :success
'PUBLIC' | :developer | false | :invalid_personal_access_token | :unauthorized
'PUBLIC' | :guest | false | :invalid_personal_access_token | :unauthorized
+ 'PUBLIC' | :developer | false | :invalid_user_basic_auth | :unauthorized
+ 'PUBLIC' | :guest | false | :invalid_user_basic_auth | :unauthorized
'PUBLIC' | :anonymous | false | :none | :unauthorized
'PRIVATE' | :developer | true | :personal_access_token | :success
'PRIVATE' | :guest | true | :personal_access_token | :forbidden
+ 'PRIVATE' | :developer | true | :user_basic_auth | :success
+ 'PRIVATE' | :guest | true | :user_basic_auth | :forbidden
'PRIVATE' | :developer | true | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | true | :invalid_personal_access_token | :unauthorized
+ 'PRIVATE' | :developer | true | :invalid_user_basic_auth | :unauthorized
+ 'PRIVATE' | :guest | true | :invalid_user_basic_auth | :unauthorized
'PRIVATE' | :developer | false | :personal_access_token | :not_found
'PRIVATE' | :guest | false | :personal_access_token | :not_found
+ 'PRIVATE' | :developer | false | :user_basic_auth | :not_found
+ 'PRIVATE' | :guest | false | :user_basic_auth | :not_found
'PRIVATE' | :developer | false | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | false | :invalid_personal_access_token | :unauthorized
+ 'PRIVATE' | :developer | false | :invalid_user_basic_auth | :unauthorized
+ 'PRIVATE' | :guest | false | :invalid_user_basic_auth | :unauthorized
'PRIVATE' | :anonymous | false | :none | :unauthorized
'PUBLIC' | :developer | true | :job_token | :success
'PUBLIC' | :developer | true | :invalid_job_token | :unauthorized
@@ -347,6 +467,21 @@ RSpec.describe API::GenericPackages do
expect(response).to have_gitlab_http_status(expected_status)
end
end
+
+ where(:authenticate_with, :expected_status) do
+ :deploy_token_rw | :success
+ :deploy_token_wo | :success
+ :deploy_token_ro | :success
+ :invalid_deploy_token | :unauthorized
+ end
+
+ with_them do
+ it "responds with #{params[:expected_status]}" do
+ download_file(deploy_token_auth_header)
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ end
+ end
end
context 'event tracking' do
diff --git a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
index e086ce02942..db8a412e45c 100644
--- a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
+++ b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Getting Ci Cd Setting' do
let(:fields) do
<<~QUERY
- #{all_graphql_fields_for('ProjectCiCdSetting')}
+ #{all_graphql_fields_for('ProjectCiCdSetting', max_depth: 1)}
QUERY
end
@@ -43,8 +43,10 @@ RSpec.describe 'Getting Ci Cd Setting' do
it_behaves_like 'a working graphql query'
- specify { expect(settings_data['mergePipelinesEnabled']).to eql project.ci_cd_settings.merge_pipelines_enabled? }
- specify { expect(settings_data['mergeTrainsEnabled']).to eql project.ci_cd_settings.merge_trains_enabled? }
- specify { expect(settings_data['project']['id']).to eql "gid://gitlab/Project/#{project.id}" }
+ 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?
+ end
end
end
diff --git a/spec/requests/api/graphql/ci/config_spec.rb b/spec/requests/api/graphql/ci/config_spec.rb
index b682470e0a1..8ede6e1538c 100644
--- a/spec/requests/api/graphql/ci/config_spec.rb
+++ b/spec/requests/api/graphql/ci/config_spec.rb
@@ -7,7 +7,8 @@ RSpec.describe 'Query.ciConfig' do
subject(:post_graphql_query) { post_graphql(query, current_user: user) }
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
let_it_be(:content) do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_includes.yml'))
@@ -16,20 +17,41 @@ RSpec.describe 'Query.ciConfig' do
let(:query) do
%(
query {
- ciConfig(content: "#{content}") {
+ ciConfig(projectPath: "#{project.full_path}", content: "#{content}", dryRun: false) {
status
errors
stages {
- name
- groups {
+ nodes {
name
- size
- jobs {
- name
- groupName
- stage
- needs {
+ groups {
+ nodes {
name
+ size
+ jobs {
+ nodes {
+ name
+ groupName
+ stage
+ script
+ beforeScript
+ afterScript
+ allowFailure
+ only {
+ refs
+ }
+ when
+ except {
+ refs
+ }
+ environment
+ tags
+ needs {
+ nodes {
+ name
+ }
+ }
+ }
+ }
}
}
}
@@ -39,53 +61,259 @@ RSpec.describe 'Query.ciConfig' do
)
end
- before do
- post_graphql_query
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql_query
+ end
end
- it_behaves_like 'a working graphql query'
-
it 'returns the correct structure' do
+ post_graphql_query
+
expect(graphql_data['ciConfig']).to eq(
"status" => "VALID",
"errors" => [],
"stages" =>
- [
- {
- "name" => "build",
- "groups" =>
- [
+ {
+ "nodes" =>
+ [
+ {
+ "name" => "build",
+ "groups" =>
{
- "name" => "rspec",
- "size" => 2,
- "jobs" =>
+ "nodes" =>
[
- { "name" => "rspec 0 1", "groupName" => "rspec", "stage" => "build", "needs" => [] },
- { "name" => "rspec 0 2", "groupName" => "rspec", "stage" => "build", "needs" => [] }
+ {
+ "name" => "rspec",
+ "size" => 2,
+ "jobs" =>
+ {
+ "nodes" =>
+ [
+ {
+ "name" => "rspec 0 1",
+ "groupName" => "rspec",
+ "stage" => "build",
+ "script" => ["rake spec"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => false,
+ "only" => { "refs" => %w[branches master] },
+ "when" => "on_success",
+ "except" => nil,
+ "environment" => nil,
+ "tags" => %w[ruby postgres],
+ "needs" => { "nodes" => [] }
+ },
+ {
+ "name" => "rspec 0 2",
+ "groupName" => "rspec",
+ "stage" => "build",
+ "script" => ["rake spec"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => true,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "on_failure",
+ "except" => nil,
+ "environment" => nil,
+ "tags" => [],
+ "needs" => { "nodes" => [] }
+ }
+ ]
+ }
+ },
+ {
+ "name" => "spinach", "size" => 1, "jobs" =>
+ {
+ "nodes" =>
+ [
+ {
+ "name" => "spinach",
+ "groupName" => "spinach",
+ "stage" => "build",
+ "script" => ["rake spinach"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => false,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "on_success",
+ "except" => { "refs" => ["tags"] },
+ "environment" => nil,
+ "tags" => [],
+ "needs" => { "nodes" => [] }
+ }
+ ]
+ }
+ }
]
- },
+ }
+ },
+ {
+ "name" => "test",
+ "groups" =>
{
- "name" => "spinach", "size" => 1, "jobs" =>
+ "nodes" =>
[
- { "name" => "spinach", "groupName" => "spinach", "stage" => "build", "needs" => [] }
+ {
+ "name" => "docker",
+ "size" => 1,
+ "jobs" =>
+ {
+ "nodes" => [
+ {
+ "name" => "docker",
+ "groupName" => "docker",
+ "stage" => "test",
+ "script" => ["curl http://dockerhub/URL"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => true,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "manual",
+ "except" => { "refs" => ["branches"] },
+ "environment" => nil,
+ "tags" => [],
+ "needs" => { "nodes" => [{ "name" => "spinach" }, { "name" => "rspec 0 1" }] }
+ }
+ ]
+ }
+ }
]
}
- ]
- },
+ },
+ {
+ "name" => "deploy",
+ "groups" =>
+ {
+ "nodes" =>
+ [
+ {
+ "name" => "deploy_job",
+ "size" => 1,
+ "jobs" =>
+ {
+ "nodes" => [
+ {
+ "name" => "deploy_job",
+ "groupName" => "deploy_job",
+ "stage" => "deploy",
+ "script" => ["echo 'done'"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => false,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "on_success",
+ "except" => nil,
+ "environment" => "production",
+ "tags" => [],
+ "needs" => { "nodes" => [] }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ )
+ end
+
+ context 'when the config file includes other files' do
+ let_it_be(:content) do
+ YAML.dump(
+ include: 'other_file.yml',
+ rspec: {
+ script: 'rspec'
+ }
+ )
+ end
+
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:blob_data_at).with(an_instance_of(String), 'other_file.yml') do
+ YAML.dump(
+ build: {
+ script: 'build'
+ }
+ )
+ end
+ end
+
+ post_graphql_query
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns the correct structure with included files' do
+ expect(graphql_data['ciConfig']).to eq(
+ "status" => "VALID",
+ "errors" => [],
+ "stages" =>
{
- "name" => "test",
- "groups" =>
+ "nodes" =>
[
{
- "name" => "docker",
- "size" => 1,
- "jobs" => [
- { "name" => "docker", "groupName" => "docker", "stage" => "test", "needs" => [{ "name" => "spinach" }, { "name" => "rspec 0 1" }] }
- ]
+ "name" => "test",
+ "groups" =>
+ {
+ "nodes" =>
+ [
+ {
+ "name" => "build",
+ "size" => 1,
+ "jobs" =>
+ {
+ "nodes" =>
+ [
+ {
+ "name" => "build",
+ "stage" => "test",
+ "groupName" => "build",
+ "script" => ["build"],
+ "afterScript" => [],
+ "beforeScript" => [],
+ "allowFailure" => false,
+ "environment" => nil,
+ "except" => nil,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "on_success",
+ "tags" => [],
+ "needs" => { "nodes" => [] }
+}
+ ]
+ }
+ },
+ {
+ "name" => "rspec",
+ "size" => 1,
+ "jobs" =>
+ {
+ "nodes" =>
+ [
+ { "name" => "rspec",
+ "stage" => "test",
+ "groupName" => "rspec",
+ "script" => ["rspec"],
+ "afterScript" => [],
+ "beforeScript" => [],
+ "allowFailure" => false,
+ "environment" => nil,
+ "except" => nil,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "on_success",
+ "tags" => [],
+ "needs" => { "nodes" => [] } }
+ ]
+ }
+ }
+ ]
+ }
}
]
}
- ]
- )
+ )
+ end
end
end
diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb
index 19954c4e52f..3fb89d6e815 100644
--- a/spec/requests/api/graphql/ci/jobs_spec.rb
+++ b/spec/requests/api/graphql/ci/jobs_spec.rb
@@ -7,48 +7,74 @@ RSpec.describe 'Query.project.pipeline' do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:user) { create(:user) }
- def first(field)
- [field.pluralize, 'nodes', 0]
+ def all(*fields)
+ fields.flat_map { |f| [f, :nodes] }
end
describe '.stages.groups.jobs' do
let(:pipeline) do
pipeline = create(:ci_pipeline, project: project, user: user)
- stage = create(:ci_stage_entity, pipeline: pipeline, name: 'first')
- create(:commit_status, stage_id: stage.id, pipeline: pipeline, name: 'my test job')
+ stage = create(:ci_stage_entity, project: project, pipeline: pipeline, name: 'first')
+ create(:ci_build, stage_id: stage.id, pipeline: pipeline, name: 'my test job')
pipeline
end
- let(:jobs_graphql_data) { graphql_data.dig(*%w[project pipeline], *first('stage'), *first('group'), 'jobs', 'nodes') }
+ let(:jobs_graphql_data) { graphql_data_at(:project, :pipeline, *all(:stages, :groups, :jobs)) }
+
+ let(:first_n) { var('Int') }
let(:query) do
- %(
- query {
- project(fullPath: "#{project.full_path}") {
- pipeline(iid: "#{pipeline.iid}") {
- stages {
- nodes {
- name
- groups {
- nodes {
- name
- jobs {
- nodes {
- name
- pipeline {
- id
- }
- }
- }
- }
- }
+ with_signature([first_n], wrap_fields(query_graphql_path([
+ [:project, { full_path: project.full_path }],
+ [:pipeline, { iid: pipeline.iid.to_s }],
+ [:stages, { first: first_n }]
+ ], stage_fields)))
+ end
+
+ let(:stage_fields) do
+ <<~FIELDS
+ nodes {
+ name
+ groups {
+ nodes {
+ name
+ jobs {
+ nodes {
+ name
+ needs {
+ nodes { #{all_graphql_fields_for('CiBuildNeed')} }
+ }
+ pipeline {
+ id
}
}
}
}
}
- )
+ }
+ FIELDS
+ end
+
+ context 'when there are build needs' do
+ before do
+ pipeline.statuses.each do |build|
+ create_list(:ci_build_need, 2, build: build)
+ end
+ end
+
+ it 'reports the build needs' do
+ post_graphql(query, current_user: user)
+
+ expect(jobs_graphql_data).to contain_exactly a_hash_including(
+ 'needs' => a_hash_including(
+ 'nodes' => contain_exactly(
+ a_hash_including('name' => String),
+ a_hash_including('name' => String)
+ )
+ )
+ )
+ end
end
it 'returns the jobs of a pipeline stage' do
@@ -57,60 +83,43 @@ RSpec.describe 'Query.project.pipeline' do
expect(jobs_graphql_data).to contain_exactly(a_hash_including('name' => 'my test job'))
end
- it 'avoids N+1 queries', :aggregate_failures do
- control_count = ActiveRecord::QueryRecorder.new do
- post_graphql(query, current_user: user)
+ describe 'performance' do
+ before do
+ build_stage = create(:ci_stage_entity, position: 2, name: 'build', project: project, pipeline: pipeline)
+ test_stage = create(:ci_stage_entity, position: 3, name: 'test', project: project, pipeline: pipeline)
+ create(:commit_status, pipeline: pipeline, stage_id: build_stage.id, name: 'docker 1 2')
+ create(:commit_status, pipeline: pipeline, stage_id: build_stage.id, name: 'docker 2 2')
+ create(:commit_status, pipeline: pipeline, stage_id: test_stage.id, name: 'rspec 1 2')
+ create(:commit_status, pipeline: pipeline, stage_id: test_stage.id, name: 'rspec 2 2')
end
- build_stage = create(:ci_stage_entity, name: 'build', pipeline: pipeline)
- test_stage = create(:ci_stage_entity, name: 'test', pipeline: pipeline)
- create(:commit_status, pipeline: pipeline, stage_id: build_stage.id, name: 'docker 1 2')
- create(:commit_status, pipeline: pipeline, stage_id: build_stage.id, name: 'docker 2 2')
- create(:commit_status, pipeline: pipeline, stage_id: test_stage.id, name: 'rspec 1 2')
- create(:commit_status, pipeline: pipeline, stage_id: test_stage.id, name: 'rspec 2 2')
+ it 'can find the first stage' do
+ post_graphql(query, current_user: user, variables: first_n.with(1))
- expect do
- post_graphql(query, current_user: user)
- end.not_to exceed_query_limit(control_count)
+ expect(jobs_graphql_data).to contain_exactly(a_hash_including('name' => 'my test job'))
+ end
- expect(response).to have_gitlab_http_status(:ok)
+ it 'can find all stages' do
+ post_graphql(query, current_user: user, variables: first_n.with(3))
- build_stage = graphql_data.dig('project', 'pipeline', 'stages', 'nodes').find do |stage|
- stage['name'] == 'build'
+ expect(jobs_graphql_data).to contain_exactly(
+ a_hash_including('name' => 'my test job'),
+ a_hash_including('name' => 'docker 1 2'),
+ a_hash_including('name' => 'docker 2 2'),
+ a_hash_including('name' => 'rspec 1 2'),
+ a_hash_including('name' => 'rspec 2 2')
+ )
end
- test_stage = graphql_data.dig('project', 'pipeline', 'stages', 'nodes').find do |stage|
- stage['name'] == 'test'
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: user, variables: first_n.with(1))
+ end
+
+ expect do
+ post_graphql(query, current_user: user, variables: first_n.with(3))
+ end.not_to exceed_query_limit(control_count)
end
- docker_group = build_stage.dig('groups', 'nodes').first
- rspec_group = test_stage.dig('groups', 'nodes').first
-
- expect(docker_group['name']).to eq('docker')
- expect(rspec_group['name']).to eq('rspec')
-
- docker_jobs = docker_group.dig('jobs', 'nodes')
- rspec_jobs = rspec_group.dig('jobs', 'nodes')
-
- expect(docker_jobs).to eq([
- {
- 'name' => 'docker 1 2',
- 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
- },
- {
- 'name' => 'docker 2 2',
- 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
- }
- ])
-
- expect(rspec_jobs).to eq([
- {
- 'name' => 'rspec 1 2',
- 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
- },
- {
- 'name' => 'rspec 2 2',
- 'pipeline' => { 'id' => pipeline.to_global_id.to_s }
- }
- ])
end
end
diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb
index 414ddabbac9..7933251b8e9 100644
--- a/spec/requests/api/graphql/ci/pipelines_spec.rb
+++ b/spec/requests/api/graphql/ci/pipelines_spec.rb
@@ -6,53 +6,59 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository, :public) }
- let_it_be(:first_user) { create(:user) }
- let_it_be(:second_user) { create(:user) }
+ let_it_be(:user) { create(:user) }
describe '.jobs' do
- let_it_be(:query) do
- %(
- query {
- project(fullPath: "#{project.full_path}") {
- pipelines {
- nodes {
- jobs {
- nodes {
- name
- }
- }
- }
- }
- }
- }
- )
+ let(:first_n) { var('Int') }
+ let(:query_path) do
+ [
+ [:project, { full_path: project.full_path }],
+ [:pipelines, { first: first_n }],
+ [:nodes],
+ [:jobs],
+ [:nodes]
+ ]
end
- it 'fetches the jobs without an N+1' do
+ let(:query) do
+ with_signature([first_n], wrap_fields(query_graphql_path(query_path, :name)))
+ end
+
+ before_all do
pipeline = create(:ci_pipeline, project: project)
create(:ci_build, pipeline: pipeline, name: 'Job 1')
-
- control_count = ActiveRecord::QueryRecorder.new do
- post_graphql(query, current_user: first_user)
- end
-
pipeline = create(:ci_pipeline, project: project)
create(:ci_build, pipeline: pipeline, name: 'Job 2')
+ end
- expect do
- post_graphql(query, current_user: second_user)
- end.not_to exceed_query_limit(control_count)
+ it 'limits the results' do
+ post_graphql(query, current_user: user, variables: first_n.with(1))
- expect(response).to have_gitlab_http_status(:ok)
+ expect(graphql_data_at(*query_path.map(&:first))).to contain_exactly a_hash_including(
+ 'name' => 'Job 2'
+ )
+ end
- pipelines_data = graphql_data.dig('project', 'pipelines', 'nodes')
+ it 'fetches all results' do
+ post_graphql(query, current_user: user)
- job_names = pipelines_data.map do |pipeline_data|
- jobs_data = pipeline_data.dig('jobs', 'nodes')
- jobs_data.map { |job_data| job_data['name'] }
- end.flatten
+ expect(graphql_data_at(*query_path.map(&:first))).to contain_exactly(
+ a_hash_including('name' => 'Job 1'),
+ a_hash_including('name' => 'Job 2')
+ )
+ end
+
+ it 'fetches the jobs without an N+1' do
+ first_user = create(:personal_access_token).user
+ second_user = create(:personal_access_token).user
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: first_user, variables: first_n.with(1))
+ end
- expect(job_names).to contain_exactly('Job 1', 'Job 2')
+ expect do
+ post_graphql(query, current_user: second_user)
+ end.not_to exceed_query_limit(control_count)
end
end
@@ -80,7 +86,7 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
create(:ci_build, :dast, name: 'DAST Job 1', pipeline: pipeline)
create(:ci_build, :sast, name: 'SAST Job 1', pipeline: pipeline)
- post_graphql(query, current_user: first_user)
+ post_graphql(query, current_user: user)
expect(response).to have_gitlab_http_status(:ok)
@@ -96,9 +102,9 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
end
describe 'upstream' do
- let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: first_user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
let_it_be(:upstream_project) { create(:project, :repository, :public) }
- let_it_be(:upstream_pipeline) { create(:ci_pipeline, project: upstream_project, user: first_user) }
+ let_it_be(:upstream_pipeline) { create(:ci_pipeline, project: upstream_project, user: user) }
let(:upstream_pipelines_graphql_data) { graphql_data.dig(*%w[project pipelines nodes]).first['upstream'] }
let(:query) do
@@ -120,7 +126,7 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
before do
create(:ci_sources_pipeline, source_pipeline: upstream_pipeline, pipeline: pipeline )
- post_graphql(query, current_user: first_user)
+ post_graphql(query, current_user: user)
end
it_behaves_like 'a working graphql query'
@@ -131,15 +137,18 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
context 'when fetching the upstream pipeline from the pipeline' do
it 'avoids N+1 queries' do
+ first_user = create(:user)
+ second_user = create(:user)
+
control_count = ActiveRecord::QueryRecorder.new do
post_graphql(query, current_user: first_user)
end
- pipeline_2 = create(:ci_pipeline, project: project, user: first_user)
- upstream_pipeline_2 = create(:ci_pipeline, project: upstream_project, user: first_user)
+ pipeline_2 = create(:ci_pipeline, project: project, user: user)
+ upstream_pipeline_2 = create(:ci_pipeline, project: upstream_project, user: user)
create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_2, pipeline: pipeline_2 )
- pipeline_3 = create(:ci_pipeline, project: project, user: first_user)
- upstream_pipeline_3 = create(:ci_pipeline, project: upstream_project, user: first_user)
+ pipeline_3 = create(:ci_pipeline, project: project, user: user)
+ upstream_pipeline_3 = create(:ci_pipeline, project: upstream_project, user: user)
create(:ci_sources_pipeline, source_pipeline: upstream_pipeline_3, pipeline: pipeline_3 )
expect do
@@ -152,12 +161,12 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
end
describe 'downstream' do
- let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: first_user) }
- let(:pipeline_2) { create(:ci_pipeline, project: project, user: first_user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+ let(:pipeline_2) { create(:ci_pipeline, project: project, user: user) }
let_it_be(:downstream_project) { create(:project, :repository, :public) }
- let_it_be(:downstream_pipeline_a) { create(:ci_pipeline, project: downstream_project, user: first_user) }
- let_it_be(:downstream_pipeline_b) { create(:ci_pipeline, project: downstream_project, user: first_user) }
+ let_it_be(:downstream_pipeline_a) { create(:ci_pipeline, project: downstream_project, user: user) }
+ let_it_be(:downstream_pipeline_b) { create(:ci_pipeline, project: downstream_project, user: user) }
let(:pipelines_graphql_data) { graphql_data.dig(*%w[project pipelines nodes]) }
@@ -183,7 +192,7 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
create(:ci_sources_pipeline, source_pipeline: pipeline, pipeline: downstream_pipeline_a)
create(:ci_sources_pipeline, source_pipeline: pipeline_2, pipeline: downstream_pipeline_b)
- post_graphql(query, current_user: first_user)
+ post_graphql(query, current_user: user)
end
it_behaves_like 'a working graphql query'
@@ -198,16 +207,19 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
context 'when fetching the downstream pipelines from the pipeline' do
it 'avoids N+1 queries' do
+ first_user = create(:user)
+ second_user = create(:user)
+
control_count = ActiveRecord::QueryRecorder.new do
post_graphql(query, current_user: first_user)
end
- downstream_pipeline_2a = create(:ci_pipeline, project: downstream_project, user: first_user)
+ downstream_pipeline_2a = create(:ci_pipeline, project: downstream_project, user: user)
create(:ci_sources_pipeline, source_pipeline: pipeline, pipeline: downstream_pipeline_2a)
- downsteam_pipeline_3a = create(:ci_pipeline, project: downstream_project, user: first_user)
+ downsteam_pipeline_3a = create(:ci_pipeline, project: downstream_project, user: user)
create(:ci_sources_pipeline, source_pipeline: pipeline, pipeline: downsteam_pipeline_3a)
- downstream_pipeline_2b = create(:ci_pipeline, project: downstream_project, user: first_user)
+ downstream_pipeline_2b = create(:ci_pipeline, project: downstream_project, user: user)
create(:ci_sources_pipeline, source_pipeline: pipeline_2, pipeline: downstream_pipeline_2b)
downsteam_pipeline_3b = create(:ci_pipeline, project: downstream_project, user: first_user)
create(:ci_sources_pipeline, source_pipeline: pipeline_2, pipeline: downsteam_pipeline_3b)
diff --git a/spec/requests/api/graphql/group/group_members_spec.rb b/spec/requests/api/graphql/group/group_members_spec.rb
index 3554e22cdf2..452610ab18f 100644
--- a/spec/requests/api/graphql/group/group_members_spec.rb
+++ b/spec/requests/api/graphql/group/group_members_spec.rb
@@ -10,15 +10,13 @@ RSpec.describe 'getting group members information' do
let_it_be(:user_1) { create(:user, username: 'user') }
let_it_be(:user_2) { create(:user, username: 'test') }
- let(:member_data) { graphql_data['group']['groupMembers']['edges'] }
-
before_all do
[user_1, user_2].each { |user| parent_group.add_guest(user) }
end
context 'when the request is correct' do
it_behaves_like 'a working graphql query' do
- before_all do
+ before do
fetch_members
end
end
@@ -80,12 +78,10 @@ RSpec.describe 'getting group members information' do
end
context 'when unauthenticated' do
- it 'returns nothing' do
+ it 'returns visible members' do
fetch_members(current_user: nil)
- expect(graphql_errors).to be_nil
- expect(response).to have_gitlab_http_status(:success)
- expect(member_data).to be_empty
+ expect_array_response(user_1, user_2)
end
end
@@ -112,8 +108,8 @@ RSpec.describe 'getting group members information' do
def expect_array_response(*items)
expect(response).to have_gitlab_http_status(:success)
- expect(member_data).to be_an Array
- expect(member_data.map { |node| node["node"]["user"]["id"] })
- .to match_array(items.map { |u| global_id_of(u) })
+ member_gids = graphql_data_at(:group, :group_members, :edges, :node, :user, :id)
+
+ expect(member_gids).to match_array(items.map { |u| global_id_of(u) })
end
end
diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb
index e5803f50474..cd423d7764a 100644
--- a/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb
@@ -42,6 +42,8 @@ RSpec.describe 'Creating a todo for the alert' do
context 'todo already exists' do
before do
+ stub_feature_flags(multiple_todos: false)
+
create(:todo, :pending, project: project, user: user, target: alert)
end
diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb
index a285cebc805..e594d67aab4 100644
--- a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb
@@ -39,21 +39,7 @@ RSpec.describe 'Creating a new HTTP Integration' do
project.add_maintainer(current_user)
end
- it 'creates a new integration' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- new_integration = ::AlertManagement::HttpIntegration.last!
- integration_response = mutation_response['integration']
-
- expect(response).to have_gitlab_http_status(:success)
- expect(integration_response['id']).to eq(GitlabSchema.id_from_object(new_integration).to_s)
- expect(integration_response['type']).to eq('HTTP')
- expect(integration_response['name']).to eq(new_integration.name)
- expect(integration_response['active']).to eq(new_integration.active)
- expect(integration_response['token']).to eq(new_integration.token)
- expect(integration_response['url']).to eq(new_integration.url)
- expect(integration_response['apiUrl']).to eq(nil)
- end
+ it_behaves_like 'creating a new HTTP integration'
[:project_path, :active, :name].each do |argument|
context "without required argument #{argument}" do
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
new file mode 100644
index 00000000000..283badeaf33
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'CiCdSettingsUpdate' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, ci_keep_latest_artifact: true) }
+ let(:variables) { { full_path: project.full_path, keep_latest_artifact: false } }
+ let(:mutation) { graphql_mutation(:ci_cd_settings_update, variables) }
+
+ context 'when unauthorized' do
+ let(:user) { create(:user) }
+
+ shared_examples 'unauthorized' do
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).not_to be_empty
+ end
+ end
+
+ context 'when not a project member' do
+ it_behaves_like 'unauthorized'
+ end
+
+ context 'when a non-admin project member' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'unauthorized'
+ end
+ end
+
+ context 'when authorized' do
+ let_it_be(:user) { project.owner }
+
+ it 'updates ci cd settings' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(project.ci_keep_latest_artifact).to eq(false)
+ end
+
+ context 'when bad arguments are provided' do
+ let(:variables) { { full_path: '', keep_latest_artifact: false } }
+
+ it 'returns the errors' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).not_to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
new file mode 100644
index 00000000000..749373e7b8d
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Updating the package settings' do
+ include GraphqlHelpers
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+
+ let(:params) do
+ {
+ namespace_path: namespace.full_path,
+ maven_duplicates_allowed: false,
+ maven_duplicate_exception_regex: 'foo-.*'
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(:update_namespace_package_settings, params) do
+ <<~QL
+ packageSettings {
+ mavenDuplicatesAllowed
+ mavenDuplicateExceptionRegex
+ }
+ errors
+ QL
+ end
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:update_namespace_package_settings) }
+ let(:package_settings_response) { mutation_response['packageSettings'] }
+
+ RSpec.shared_examples 'returning a success' do
+ it_behaves_like 'returning response status', :success
+
+ it 'returns the updated package settings', :aggregate_failures do
+ subject
+
+ expect(mutation_response['errors']).to be_empty
+ expect(package_settings_response['mavenDuplicatesAllowed']).to eq(params[:maven_duplicates_allowed])
+ expect(package_settings_response['mavenDuplicateExceptionRegex']).to eq(params[:maven_duplicate_exception_regex])
+ end
+ end
+
+ RSpec.shared_examples 'rejecting invalid regex' do
+ context "for field mavenDuplicateExceptionRegex" do
+ let_it_be(:invalid_regex) { '][' }
+
+ let(:params) do
+ {
+ :namespace_path => namespace.full_path,
+ 'mavenDuplicateExceptionRegex' => invalid_regex
+ }
+ end
+
+ it_behaves_like 'returning response status', :success
+
+ it_behaves_like 'not creating the namespace package setting'
+
+ it 'returns an error', :aggregate_failures do
+ subject
+
+ expect(graphql_errors.size).to eq(1)
+ expect(graphql_errors.first['message']).to include("#{invalid_regex} is an invalid regexp")
+ end
+ end
+ end
+
+ RSpec.shared_examples 'accepting the mutation request updating the package settings' do
+ it_behaves_like 'updating the namespace package setting attributes',
+ from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT' },
+ to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'foo-.*' }
+
+ it_behaves_like 'returning a success'
+ it_behaves_like 'rejecting invalid regex'
+ end
+
+ RSpec.shared_examples 'accepting the mutation request creating the package settings' do
+ it_behaves_like 'creating the namespace package setting'
+ it_behaves_like 'returning a success'
+ it_behaves_like 'rejecting invalid regex'
+ end
+
+ RSpec.shared_examples 'denying the mutation request' do
+ it_behaves_like 'not creating the namespace package setting'
+
+ it_behaves_like 'returning response status', :success
+
+ it 'returns no response' do
+ subject
+
+ expect(mutation_response).to be_nil
+ end
+ end
+
+ describe 'post graphql mutation' do
+ subject { post_graphql_mutation(mutation, current_user: user) }
+
+ context 'with existing package settings' do
+ let_it_be(:package_settings, reload: true) { create(:namespace_package_setting, :group) }
+ let_it_be(:namespace, reload: true) { package_settings.namespace }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'accepting the mutation request updating the package settings'
+ :developer | 'accepting the mutation request updating the package settings'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :anonymous | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ namespace.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+
+ context 'without existing package settings' do
+ let_it_be(:namespace, reload: true) { create(:group) }
+ let(:package_settings) { namespace.package_settings }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'accepting the mutation request creating the package settings'
+ :developer | 'accepting the mutation request creating the package settings'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :anonymous | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ namespace.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
index d745eb3083d..79bdcec7944 100644
--- a/spec/requests/api/graphql/mutations/releases/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -116,11 +116,9 @@ RSpec.describe 'Creation of a new release' do
context 'when all available mutation arguments are provided' do
it_behaves_like 'no errors'
- # rubocop: disable CodeReuse/ActiveRecord
it 'returns the new release data' do
create_release
- release = mutation_response[:release]
expected_direct_asset_url = Gitlab::Routing.url_helpers.project_release_url(project, Release.find_by(tag: tag_name)) << "/downloads#{asset_link[:directAssetPath]}"
expected_attributes = {
@@ -139,21 +137,17 @@ RSpec.describe 'Creation of a new release' do
directAssetUrl: expected_direct_asset_url
}]
}
+ },
+ milestones: {
+ nodes: [
+ { title: '12.3' },
+ { title: '12.4' }
+ ]
}
- }
-
- expect(release).to include(expected_attributes)
+ }.with_indifferent_access
- # Right now the milestones are returned in a non-deterministic order.
- # This `milestones` test should be moved up into the expect(release)
- # above (and `.to include` updated to `.to eq`) once
- # https://gitlab.com/gitlab-org/gitlab/-/issues/259012 is addressed.
- expect(release['milestones']['nodes']).to match_array([
- { 'title' => '12.4' },
- { 'title' => '12.3' }
- ])
+ expect(mutation_response[:release]).to eq(expected_attributes)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
context 'when only the required mutation arguments are provided' do
diff --git a/spec/requests/api/graphql/mutations/releases/update_spec.rb b/spec/requests/api/graphql/mutations/releases/update_spec.rb
index 19320c3393c..c9a6c3abd57 100644
--- a/spec/requests/api/graphql/mutations/releases/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/update_spec.rb
@@ -116,15 +116,7 @@ RSpec.describe 'Updating an existing release' do
it 'updates the correct field and returns the release' do
update_release
- expect(mutation_response[:release]).to include(expected_attributes.merge(updates).except(:milestones))
-
- # Right now the milestones are returned in a non-deterministic order.
- # Because of this, we need to test milestones separately to allow
- # for them to be returned in any order.
- # Once https://gitlab.com/gitlab-org/gitlab/-/issues/259012 has been
- # fixed, this special milestone handling can be removed.
- expected_milestones = expected_attributes.merge(updates)[:milestones]
- expect(mutation_response[:release][:milestones][:nodes]).to match_array(expected_milestones[:nodes])
+ expect(mutation_response[:release]).to eq(expected_attributes.merge(updates))
end
end
diff --git a/spec/requests/api/graphql/namespace/package_settings_spec.rb b/spec/requests/api/graphql/namespace/package_settings_spec.rb
new file mode 100644
index 00000000000..6af098e902f
--- /dev/null
+++ b/spec/requests/api/graphql/namespace/package_settings_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting namespace package settings in a namespace' do
+ include GraphqlHelpers
+
+ let_it_be(:package_settings) { create(:namespace_package_setting) }
+ let_it_be(:namespace) { package_settings.namespace }
+ let_it_be(:current_user) { namespace.owner }
+ let(:package_settings_response) { graphql_data.dig('namespace', 'packageSettings') }
+ let(:fields) { all_graphql_fields_for('PackageSettings') }
+
+ let(:query) do
+ graphql_query_for(
+ 'namespace',
+ { 'fullPath' => namespace.full_path },
+ query_graphql_field('package_settings', {}, fields)
+ )
+ end
+
+ subject { post_graphql(query, current_user: current_user) }
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ subject
+ end
+
+ it 'matches the JSON schema' do
+ expect(package_settings_response).to match_schema('graphql/namespace/package_settings')
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/packages/package_composer_details_spec.rb b/spec/requests/api/graphql/packages/package_composer_details_spec.rb
new file mode 100644
index 00000000000..1a2cf4a972a
--- /dev/null
+++ b/spec/requests/api/graphql/packages/package_composer_details_spec.rb
@@ -0,0 +1,39 @@
+# 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/project/alert_management/alert/assignees_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb
index dd001a73349..9ab94f1d749 100644
--- a/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb
@@ -60,19 +60,35 @@ RSpec.describe 'getting Alert Management Alert Assignees' do
expect(second_assignees).to be_empty
end
- it 'avoids N+1 queries' do
- base_count = ActiveRecord::QueryRecorder.new do
- post_graphql(query, current_user: current_user)
+ describe 'performance' do
+ let(:first_n) { var('Int') }
+ let(:params) { { first: first_n } }
+ let(:limited_query) { with_signature([first_n], query) }
+
+ before do
+ create(:alert_management_alert, project: project, assignees: [current_user])
+ end
+
+ it 'can limit results' do
+ post_graphql(limited_query, current_user: current_user, variables: first_n.with(1))
+
+ expect(alerts.size).to eq 1
+ expect(alerts).not_to include(a_hash_including('iid' => first_alert.iid.to_s))
end
- # An N+1 would mean a new alert would increase the query count
- third_alert = create(:alert_management_alert, project: project, assignees: [current_user])
+ it 'can include all results' do
+ post_graphql(limited_query, current_user: current_user)
- expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(base_count)
+ expect(alerts.size).to be > 1
+ expect(alerts).to include(a_hash_including('iid' => first_alert.iid.to_s))
+ end
- third_assignees = assignees[third_alert.iid.to_s]
+ it 'avoids N+1 queries' do
+ base_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(limited_query, current_user: current_user, variables: first_n.with(1))
+ end
- expect(third_assignees.length).to eq(1)
- expect(third_assignees.first).to include('username' => current_user.username)
+ expect { post_graphql(limited_query, current_user: current_user) }.not_to exceed_query_limit(base_count)
+ end
end
end
diff --git a/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb
index 1350cba119b..5d46f370756 100644
--- a/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb
@@ -65,16 +65,28 @@ RSpec.describe 'getting Alert Management Alert Notes' do
expect(second_notes_result).to be_empty
end
- it 'avoids N+1 queries' do
- base_count = ActiveRecord::QueryRecorder.new do
- post_graphql(query, current_user: current_user)
+ describe 'performance' do
+ let(:first_n) { var('Int') }
+ let(:params) { { first: first_n } }
+
+ before do
+ # An N+1 would mean a new alert would increase the query count
+ create(:alert_management_alert, project: project)
end
- # An N+1 would mean a new alert would increase the query count
- create(:alert_management_alert, project: project)
+ it 'avoids N+1 queries' do
+ q = with_signature([first_n], query)
- expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(base_count)
- expect(alerts_result.length).to eq(3)
+ base_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(q, current_user: current_user, variables: first_n.with(1))
+ expect(alerts_result.length).to eq(1)
+ end
+
+ expect do
+ post_graphql(q, current_user: current_user, variables: first_n.with(3))
+ expect(alerts_result.length).to eq(3)
+ end.not_to exceed_query_limit(base_count)
+ end
end
context 'for non-system notes' do
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index fae52fe814d..e1b867ad097 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -9,12 +9,13 @@ RSpec.describe 'getting merge request information nested in a project' do
let(:current_user) { create(:user) }
let(:merge_request_graphql_data) { graphql_data['project']['mergeRequest'] }
let!(:merge_request) { create(:merge_request, source_project: project) }
+ let(:mr_fields) { all_graphql_fields_for('MergeRequest') }
let(:query) do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
- query_graphql_field('mergeRequest', iid: merge_request.iid.to_s)
+ query_graphql_field('mergeRequest', { iid: merge_request.iid.to_s }, mr_fields)
)
end
@@ -43,6 +44,38 @@ RSpec.describe 'getting merge request information nested in a project' do
expect(merge_request_graphql_data['author']['username']).to eq(merge_request.author.username)
end
+ context 'the merge_request has reviewers' do
+ let(:mr_fields) do
+ <<~SELECT
+ reviewers { nodes { id username } }
+ participants { nodes { id username } }
+ SELECT
+ end
+
+ before do
+ merge_request.reviewers << create_list(:user, 2)
+ end
+
+ it 'includes reviewers' do
+ expected = merge_request.reviewers.map do |r|
+ a_hash_including('id' => global_id_of(r), 'username' => r.username)
+ end
+
+ post_graphql(query, current_user: current_user)
+
+ 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
be_natural = an_instance_of(Integer).and(be >= 0)
@@ -219,4 +252,41 @@ RSpec.describe 'getting merge request information nested in a project' do
expect(merge_request_graphql_data['mergeStatus']).to eq('checking')
end
end
+
+ # see: https://gitlab.com/gitlab-org/gitlab/-/issues/297358
+ context 'when the notes have been preloaded (by participants)' do
+ let(:query) do
+ <<~GQL
+ query($path: ID!) {
+ project(fullPath: $path) {
+ mrs: mergeRequests(first: 1) {
+ nodes {
+ participants { nodes { id } }
+ notes(first: 1) {
+ pageInfo { endCursor hasPreviousPage hasNextPage }
+ nodes { id }
+ }
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ before do
+ create_list(:note_on_merge_request, 3, project: project, noteable: merge_request)
+ end
+
+ it 'does not error' do
+ post_graphql(query,
+ current_user: current_user,
+ variables: { path: project.full_path })
+
+ expect(graphql_data_at(:project, :mrs, :nodes, :notes, :pageInfo)).to contain_exactly a_hash_including(
+ 'endCursor' => String,
+ 'hasNextPage' => true,
+ 'hasPreviousPage' => false
+ )
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index c05a620bb62..c85cb8b2ffe 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -23,9 +23,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
graphql_query_for(
:project,
{ full_path: project.full_path },
- query_graphql_field(:merge_requests, search_params, [
- query_graphql_field(:nodes, nil, fields)
- ])
+ query_nodes(:merge_requests, fields, args: search_params)
)
end
@@ -50,24 +48,22 @@ RSpec.describe 'getting merge request listings nested in a project' do
project.repository.expire_branches_cache
end
+ let(:graphql_data) do
+ GitlabSchema.execute(query, context: { current_user: current_user }).to_h['data']
+ end
+
context 'selecting any single scalar field' do
where(:field) do
scalar_fields_of('MergeRequest').map { |name| [name] }
end
with_them do
- it_behaves_like 'a working graphql query' do
- let(:query) do
- query_merge_requests([:iid, field].uniq)
- end
-
- before do
- post_graphql(query, current_user: current_user)
- end
-
- it 'selects the correct MR' do
- expect(results).to contain_exactly(a_hash_including('iid' => fresh_mr.iid.to_s))
- end
+ let(:query) do
+ query_merge_requests([:iid, field].uniq)
+ end
+
+ it 'selects the correct MR' do
+ expect(results).to contain_exactly(a_hash_including('iid' => fresh_mr.iid.to_s))
end
end
end
@@ -87,19 +83,13 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
with_them do
- it_behaves_like 'a working graphql query' do
- let(:query) do
- fld = is_connection ? query_graphql_field(:nodes, nil, [subfield]) : subfield
- query_merge_requests([:iid, query_graphql_field(field, nil, [fld])])
- end
-
- before do
- post_graphql(query, current_user: current_user)
- end
-
- it 'selects the correct MR' do
- expect(results).to contain_exactly(a_hash_including('iid' => fresh_mr.iid.to_s))
- end
+ let(:query) do
+ fld = is_connection ? query_graphql_field(:nodes, nil, [subfield]) : subfield
+ query_merge_requests([:iid, query_graphql_field(field, nil, [fld])])
+ end
+
+ it 'selects the correct MR' do
+ expect(results).to contain_exactly(a_hash_including('iid' => fresh_mr.iid.to_s))
end
end
end
@@ -254,6 +244,115 @@ RSpec.describe 'getting merge request listings nested in a project' do
include_examples 'N+1 query check'
end
+
+ context 'when requesting reviewers' do
+ let(:requested_fields) { ['reviewers { nodes { username } }'] }
+
+ before do
+ merge_request_a.reviewers << create(:user)
+ merge_request_a.reviewers << create(:user)
+ merge_request_c.reviewers << create(:user)
+ end
+
+ it 'returns the reviewers' do
+ execute_query
+
+ expect(results).to include a_hash_including('reviewers' => {
+ 'nodes' => match_array(merge_request_a.reviewers.map do |r|
+ a_hash_including('username' => r.username)
+ end)
+ })
+ 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
+
+ describe 'performance' do
+ let(:mr_fields) do
+ <<~SELECT
+ assignees { nodes { username } }
+ reviewers { nodes { username } }
+ participants { nodes { username } }
+ headPipeline { status }
+ SELECT
+ end
+
+ let(:query) do
+ <<~GQL
+ query($first: Int) {
+ project(fullPath: "#{project.full_path}") {
+ mergeRequests(first: $first) {
+ nodes { #{mr_fields} }
+ }
+ }
+ }
+ GQL
+ end
+
+ before_all do
+ project.add_developer(current_user)
+ mrs = create_list(:merge_request, 10, :closed, :with_head_pipeline,
+ source_project: project,
+ author: current_user)
+ mrs.each do |mr|
+ mr.assignees << create(:user)
+ mr.assignees << current_user
+ mr.reviewers << create(:user)
+ mr.reviewers << current_user
+ end
+ end
+
+ before do
+ # Confounding factor: makes DB calls in EE
+ allow(Gitlab::Database).to receive(:read_only?).and_return(false)
+ end
+
+ def run_query(number)
+ # Ensure that we have a fresh request store and batch-context between runs
+ result = run_with_clean_state(query,
+ context: { current_user: current_user },
+ variables: { first: number }
+ )
+
+ graphql_dig_at(result.to_h, :data, :project, :merge_requests, :nodes)
+ end
+
+ def user_collection
+ { 'nodes' => all(match(a_hash_including('username' => be_present))) }
+ end
+
+ it 'returns appropriate results' do
+ mrs = run_query(2)
+
+ expect(mrs.size).to eq(2)
+ expect(mrs).to all(
+ match(
+ a_hash_including(
+ 'assignees' => user_collection,
+ 'reviewers' => user_collection,
+ 'participants' => user_collection,
+ 'headPipeline' => { 'status' => be_present }
+ )))
+ end
+
+ it 'can lookahead to eliminate N+1 queries' do
+ baseline = ActiveRecord::QueryRecorder.new { run_query(1) }
+
+ expect { run_query(10) }.not_to exceed_query_limit(baseline)
+ end
end
describe 'sorting and pagination' do
diff --git a/spec/requests/api/graphql/project/project_members_spec.rb b/spec/requests/api/graphql/project/project_members_spec.rb
index cb937432ef7..984a0adb8c6 100644
--- a/spec/requests/api/graphql/project/project_members_spec.rb
+++ b/spec/requests/api/graphql/project/project_members_spec.rb
@@ -11,15 +11,13 @@ RSpec.describe 'getting project members information' do
let_it_be(:user_1) { create(:user, username: 'user') }
let_it_be(:user_2) { create(:user, username: 'test') }
- let(:member_data) { graphql_data['project']['projectMembers']['edges'] }
-
before_all do
[user_1, user_2].each { |user| parent_group.add_guest(user) }
end
context 'when the request is correct' do
it_behaves_like 'a working graphql query' do
- before_all do
+ before do
fetch_members(project: parent_project)
end
end
@@ -114,8 +112,7 @@ RSpec.describe 'getting project members information' do
def expect_array_response(*items)
expect(response).to have_gitlab_http_status(:success)
- expect(member_data).to be_an Array
- expect(member_data.map { |node| node['node']['user']['id'] })
- .to match_array(items.map { |u| global_id_of(u) })
+ member_gids = graphql_data_at(:project, :project_members, :edges, :node, :user, :id)
+ expect(member_gids).to match_array(items.map { |u| global_id_of(u) })
end
end
diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb
index 99b15ff00b1..ccc2825da25 100644
--- a/spec/requests/api/graphql/project/release_spec.rb
+++ b/spec/requests/api/graphql/project/release_spec.rb
@@ -76,11 +76,11 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
it 'finds all milestones associated to a release' do
post_query
- expected = release.milestones.map do |milestone|
+ expected = release.milestones.order_by_dates_and_title.map do |milestone|
{ 'id' => global_id_of(milestone), 'title' => milestone.title }
end
- expect(data).to match_array(expected)
+ expect(data).to eq(expected)
end
end
@@ -427,4 +427,33 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
end
end
end
+
+ describe 'milestone order' do
+ let(:path) { path_prefix }
+ let(:current_user) { stranger }
+ let_it_be(:project) { create(:project, :public) }
+ 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
+ post_query
+
+ data.dig('milestones', 'nodes').map { |m| m['title'] }
+ end
+
+ before do
+ release.update!(milestones: [milestone_2, milestone_1])
+ end
+
+ it_behaves_like 'correct release milestone order'
+ end
end
diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb
index b29f9ae913f..2cdd7273b18 100644
--- a/spec/requests/api/graphql/project_query_spec.rb
+++ b/spec/requests/api/graphql/project_query_spec.rb
@@ -6,26 +6,21 @@ RSpec.describe 'getting project information' do
include GraphqlHelpers
let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, :repository, group: group) }
+ let_it_be(:project, reload: true) { create(:project, :repository, group: group) }
let_it_be(:current_user) { create(:user) }
- let(:fields) { all_graphql_fields_for(Project, max_depth: 2, excluded: %w(jiraImports services)) }
+ let(:project_fields) { all_graphql_fields_for('project'.to_s.classify, max_depth: 1) }
let(:query) do
- graphql_query_for(:project, { full_path: project.full_path }, fields)
+ graphql_query_for(:project, { full_path: project.full_path }, project_fields)
end
context 'when the user has full access to the project' do
- let(:full_access_query) do
- graphql_query_for(:project, { full_path: project.full_path },
- all_graphql_fields_for('Project', max_depth: 2))
- end
-
before do
project.add_maintainer(current_user)
end
it 'includes the project', :use_clean_rails_memory_store_caching, :request_store do
- post_graphql(full_access_query, current_user: current_user)
+ post_graphql(query, current_user: current_user)
expect(graphql_data['project']).not_to be_nil
end
@@ -49,12 +44,12 @@ RSpec.describe 'getting project information' do
end
context 'when there are pipelines present' do
+ let(:project_fields) { query_nodes(:pipelines) }
+
before do
create(:ci_pipeline, project: project)
end
- let(:fields) { query_nodes(:pipelines) }
-
it 'is included in the pipelines connection' do
post_graphql(query, current_user: current_user)
@@ -108,55 +103,6 @@ RSpec.describe 'getting project information' do
end
end
- describe 'performance' do
- before_all do
- project.add_developer(current_user)
- mrs = create_list(:merge_request, 10, :closed, :with_head_pipeline,
- source_project: project,
- author: current_user)
- mrs.each do |mr|
- mr.assignees << create(:user)
- mr.assignees << current_user
- end
- end
-
- def run_query(number)
- q = <<~GQL
- query {
- project(fullPath: "#{project.full_path}") {
- mergeRequests(first: #{number}) {
- nodes {
- assignees { nodes { username } }
- headPipeline { status }
- }
- }
- }
- }
- GQL
-
- post_graphql(q, current_user: current_user)
- end
-
- it 'returns appropriate results' do
- run_query(2)
-
- mrs = graphql_data.dig('project', 'mergeRequests', 'nodes')
-
- expect(mrs.size).to eq(2)
- expect(mrs).to all(
- match(
- a_hash_including(
- 'assignees' => { 'nodes' => all(match(a_hash_including('username' => be_present))) },
- 'headPipeline' => { 'status' => be_present }
- )))
- end
-
- it 'can lookahead to eliminate N+1 queries' do
- baseline = ActiveRecord::QueryRecorder.new { run_query(1) }
- expect { run_query(10) }.not_to exceed_query_limit(baseline)
- end
- end
-
context 'when the user does not have access to the project' do
it 'returns an empty field' do
post_graphql(query, current_user: current_user)
diff --git a/spec/requests/api/graphql/user/starred_projects_query_spec.rb b/spec/requests/api/graphql/user/starred_projects_query_spec.rb
index b098058a735..6cb02068f2a 100644
--- a/spec/requests/api/graphql/user/starred_projects_query_spec.rb
+++ b/spec/requests/api/graphql/user/starred_projects_query_spec.rb
@@ -17,7 +17,13 @@ RSpec.describe 'Getting starredProjects of the user' do
let_it_be(:user, reload: true) { create(:user) }
let(:user_fields) { 'starredProjects { nodes { id } }' }
- let(:starred_projects) { graphql_data_at(:user, :starred_projects, :nodes) }
+ let(:current_user) { nil }
+
+ let(:starred_projects) do
+ post_graphql(query, current_user: current_user)
+
+ graphql_data_at(:user, :starred_projects, :nodes)
+ end
before do
project_b.add_reporter(user)
@@ -26,11 +32,13 @@ RSpec.describe 'Getting starredProjects of the user' do
user.toggle_star(project_a)
user.toggle_star(project_b)
user.toggle_star(project_c)
-
- post_graphql(query)
end
- it_behaves_like 'a working graphql query'
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query)
+ end
+ end
it 'found only public project' do
expect(starred_projects).to contain_exactly(
@@ -41,10 +49,6 @@ RSpec.describe 'Getting starredProjects of the user' do
context 'the current user is the user' do
let(:current_user) { user }
- before do
- post_graphql(query, current_user: current_user)
- end
-
it 'found all projects' do
expect(starred_projects).to contain_exactly(
a_hash_including('id' => global_id_of(project_a)),
@@ -56,11 +60,10 @@ RSpec.describe 'Getting starredProjects of the user' do
context 'the current user is a member of a private project the user starred' do
let_it_be(:other_user) { create(:user) }
+ let(:current_user) { other_user }
before do
project_b.add_reporter(other_user)
-
- post_graphql(query, current_user: other_user)
end
it 'finds public and member projects' do
@@ -74,7 +77,6 @@ RSpec.describe 'Getting starredProjects of the user' do
context 'the user has a private profile' do
before do
user.update!(private_profile: true)
- post_graphql(query, current_user: current_user)
end
context 'the current user does not have access to view the private profile of the user' do
diff --git a/spec/requests/api/graphql/users_spec.rb b/spec/requests/api/graphql/users_spec.rb
index 72d86c10df1..22b68fbc9bb 100644
--- a/spec/requests/api/graphql/users_spec.rb
+++ b/spec/requests/api/graphql/users_spec.rb
@@ -54,6 +54,52 @@ RSpec.describe 'Users' do
)
end
end
+
+ context 'when admins is true' do
+ let_it_be(:admin) { create(:user, :admin) }
+ let_it_be(:another_admin) { create(:user, :admin) }
+
+ let(:query) { graphql_query_for(:users, { admins: true }, 'nodes { id }') }
+
+ context 'current user is not an admin' do
+ let(:post_query) { post_graphql(query, current_user: current_user) }
+
+ it_behaves_like 'a working users query'
+
+ it 'includes all non-admin users', :aggregate_failures do
+ post_graphql(query)
+
+ expect(graphql_data.dig('users', 'nodes')).to include(
+ { "id" => user1.to_global_id.to_s },
+ { "id" => user2.to_global_id.to_s },
+ { "id" => user3.to_global_id.to_s },
+ { "id" => current_user.to_global_id.to_s },
+ { "id" => admin.to_global_id.to_s },
+ { "id" => another_admin.to_global_id.to_s }
+ )
+ end
+ end
+
+ context 'when current user is an admin' do
+ it_behaves_like 'a working users query'
+
+ it 'includes only admins', :aggregate_failures do
+ post_graphql(query, current_user: admin)
+
+ expect(graphql_data.dig('users', 'nodes')).to include(
+ { "id" => another_admin.to_global_id.to_s },
+ { "id" => admin.to_global_id.to_s }
+ )
+
+ expect(graphql_data.dig('users', 'nodes')).not_to include(
+ { "id" => user1.to_global_id.to_s },
+ { "id" => user2.to_global_id.to_s },
+ { "id" => user3.to_global_id.to_s },
+ { "id" => current_user.to_global_id.to_s }
+ )
+ end
+ end
+ end
end
describe 'sorting and pagination' do
diff --git a/spec/requests/api/group_packages_spec.rb b/spec/requests/api/group_packages_spec.rb
index 72ba25c59af..26895e473de 100644
--- a/spec/requests/api/group_packages_spec.rb
+++ b/spec/requests/api/group_packages_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe API::GroupPackages do
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, namespace: group, name: 'project A') }
let_it_be(:user) { create(:user) }
+ let(:params) { {} }
- subject { get api(url) }
+ subject { get api(url), params: params }
describe 'GET /groups/:id/packages' do
let(:url) { "/groups/#{group.id}/packages" }
@@ -142,6 +143,7 @@ RSpec.describe API::GroupPackages do
it_behaves_like 'returning response status', :bad_request
end
+ it_behaves_like 'with versionless packages'
it_behaves_like 'does not cause n^2 queries'
end
end
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index aeb8e3642ed..2ea237469b1 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -30,6 +30,10 @@ RSpec.describe API::Invitations do
api("/#{source.model_name.plural}/#{source.id}/invitations", user)
end
+ def invite_member_by_email(source, source_type, email, created_by)
+ create(:"#{source_type}_member", invite_token: '123', invite_email: email, source: source, user: nil, created_by: created_by)
+ end
+
shared_examples 'POST /:source_type/:id/invitations' do |source_type|
context "with :source_type == #{source_type.pluralize}" do
it_behaves_like 'a 404 response when source is private' do
@@ -280,10 +284,6 @@ RSpec.describe API::Invitations do
expect(json_response.first['created_by_name']).to eq(developer.name)
expect(json_response.first['user_name']).to eq(nil)
end
-
- def invite_member_by_email(source, source_type, email, created_by)
- create(:"#{source_type}_member", invite_token: '123', invite_email: email, source: source, user: nil, created_by: created_by)
- end
end
end
@@ -298,4 +298,80 @@ RSpec.describe API::Invitations do
let(:source) { group }
end
end
+
+ shared_examples 'DELETE /:source_type/:id/invitations/:email' do |source_type|
+ def invite_api(source, user, email)
+ api("/#{source.model_name.plural}/#{source.id}/invitations/#{email}", user)
+ end
+
+ context "with :source_type == #{source_type.pluralize}" do
+ let!(:invite) { invite_member_by_email(source, source_type, developer.email, developer) }
+
+ it_behaves_like 'a 404 response when source is private' do
+ let(:route) { delete api("/#{source_type.pluralize}/#{source.id}/invitations/#{invite.invite_email}", stranger) }
+ end
+
+ context 'when authenticated as a non-member or member with insufficient rights' do
+ %i[access_requester stranger].each do |type|
+ context "as a #{type}" do
+ it 'returns 403' do
+ user = public_send(type)
+
+ delete invite_api(source, user, invite.invite_email)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ context 'when authenticated as a member and deleting themself' do
+ it 'does not delete the member' do
+ expect do
+ delete invite_api(source, developer, invite.invite_email)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end.not_to change { source.members.count }
+ end
+ end
+
+ context 'when authenticated as a maintainer/owner' do
+ it 'deletes the member and returns 204 with no content' do
+ expect do
+ delete invite_api(source, maintainer, invite.invite_email)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end.to change { source.members.count }.by(-1)
+ end
+ end
+
+ it 'returns 404 if member does not exist' do
+ delete invite_api(source, maintainer, non_existing_record_id)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns 422 for a valid request if the resource was not destroyed' do
+ allow_next_instance_of(::Members::DestroyService) do |instance|
+ allow(instance).to receive(:execute).with(invite).and_return(invite)
+ end
+
+ delete invite_api(source, maintainer, invite.invite_email)
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/inviations/:email' do
+ it_behaves_like 'DELETE /:source_type/:id/invitations/:email', 'project' do
+ let(:source) { project }
+ end
+ end
+
+ describe 'DELETE /groups/:id/inviations/:email' do
+ it_behaves_like 'DELETE /:source_type/:id/invitations/:email', 'group' do
+ let(:source) { group }
+ end
+ end
end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index f8521818845..6f854a28cec 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -260,6 +260,36 @@ RSpec.describe API::Jobs do
end
end
+ context 'when project is public with artifacts that are non public' do
+ let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
+
+ it 'rejects access to artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ it 'allows access to artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
context 'when project is public with builds access disabled' do
it 'rejects access to artifacts' do
project.update_column(:visibility_level,
@@ -396,6 +426,33 @@ RSpec.describe API::Jobs do
end
end
+ context 'when public project guest and artifacts are non public' do
+ let(:api_user) { guest }
+ let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
+
+ before do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ it 'rejects access and hides existence of artifacts' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ it 'allows access to artifacts' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
it 'does not return job artifacts if not uploaded' do
get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
@@ -580,6 +637,33 @@ RSpec.describe API::Jobs do
end
end
+ context 'when project is public with non public artifacts' do
+ let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline, user: api_user) }
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:public_builds) { true }
+
+ it 'rejects access and hides existence of artifacts', :sidekiq_might_not_need_inline do
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response).to have_key('message')
+ expect(response.headers.to_h)
+ .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ it 'allows access to artifacts', :sidekiq_might_not_need_inline do
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
context 'when project is private' do
let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
let(:public_builds) { true }
@@ -743,32 +827,6 @@ RSpec.describe API::Jobs do
expect(response).to have_gitlab_http_status(expected_status)
end
end
-
- context 'with restrict_access_to_build_debug_mode feature disabled' do
- before do
- stub_feature_flags(restrict_access_to_build_debug_mode: false)
- end
-
- where(:public_builds, :user_project_role, :expected_status) do
- true | 'developer' | :ok
- true | 'guest' | :ok
- false | 'developer' | :ok
- false | 'guest' | :forbidden
- end
-
- with_them do
- before do
- project.update!(public_builds: public_builds)
- project.add_role(user, user_project_role)
-
- get api("/projects/#{project.id}/jobs/#{job.id}/trace", api_user)
- end
-
- it 'renders trace to authorized users' do
- expect(response).to have_gitlab_http_status(expected_status)
- end
- end
- end
end
end
@@ -923,15 +981,32 @@ RSpec.describe API::Jobs do
post api("/projects/#{project.id}/jobs/#{job.id}/play", api_user)
end
- context 'on an playable job' do
- let(:job) { create(:ci_build, :manual, project: project, pipeline: pipeline) }
+ context 'on a playable job' do
+ let_it_be(:job) { create(:ci_bridge, :playable, pipeline: pipeline, downstream: project) }
+
+ before do
+ project.add_developer(user)
+ end
context 'when user is authorized to trigger a manual action' do
- it 'plays the job' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['user']['id']).to eq(user.id)
- expect(json_response['id']).to eq(job.id)
- expect(job.reload).to be_pending
+ context 'that is a bridge' do
+ it 'plays the job' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['user']['id']).to eq(user.id)
+ expect(json_response['id']).to eq(job.id)
+ expect(job.reload).to be_pending
+ end
+ end
+
+ context 'that is a build' do
+ let_it_be(:job) { create(:ci_build, :manual, project: project, pipeline: pipeline) }
+
+ it 'plays the job' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['user']['id']).to eq(user.id)
+ expect(json_response['id']).to eq(job.id)
+ expect(job.reload).to be_pending
+ end
end
end
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index b368f6e329c..6db6de4b533 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -520,14 +520,29 @@ RSpec.describe API::Labels do
expect(json_response['color']).to eq(label1.color)
end
- it 'returns 200 if group label already exists' do
- create(:group_label, title: label1.name, group: group)
+ context 'if group label already exists' do
+ let!(:group_label) { create(:group_label, title: label1.name, group: group) }
- expect { put api("/projects/#{project.id}/labels/promote", user), params: { name: label1.name } }
- .to change(project.labels, :count).by(-1)
- .and change(group.labels, :count).by(0)
+ it 'returns a status of 200' do
+ put api("/projects/#{project.id}/labels/promote", user), params: { name: label1.name }
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'does not change the group label count' do
+ expect { put api("/projects/#{project.id}/labels/promote", user), params: { name: label1.name } }
+ .not_to change(group.labels, :count)
+ end
+
+ it 'does not change the group label max (reuses the same ID)' do
+ expect { put api("/projects/#{project.id}/labels/promote", user), params: { name: label1.name } }
+ .not_to change(group.labels, :max)
+ end
+
+ it 'changes the project label count' do
+ expect { put api("/projects/#{project.id}/labels/promote", user), params: { name: label1.name } }
+ .to change(project.labels, :count).by(-1)
+ end
end
it 'returns 403 if guest promotes label' do
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index aecbcfb5b5a..2653653c896 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe API::Lint do
end
context 'with invalid configuration' do
- let(:yaml_content) { '{ image: "ruby:2.7", services: ["postgres"] }' }
+ let(:yaml_content) { '{ image: "ruby:2.7", services: ["postgres"], invalid }' }
it 'responds with errors about invalid configuration' do
post api('/ci/lint'), params: { content: yaml_content }
@@ -71,7 +71,7 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['status']).to eq('invalid')
expect(json_response['warnings']).to eq([])
- expect(json_response['errors']).to eq(['jobs config should contain at least one visible job'])
+ expect(json_response['errors']).to eq(['jobs invalid config should implement a script: or a trigger: keyword', 'jobs config should contain at least one visible job'])
end
it 'outputs expanded yaml content' do
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index f9ba819c9aa..e5d11fb1218 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe API::MavenPackages do
include WorkhorseHelpers
- let_it_be(:group) { create(:group) }
+ 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) }
let_it_be(:project, reload: true) { create(:project, :public, namespace: group) }
let_it_be(:package, reload: true) { create(:maven_package, project: project, name: project.full_path) }
@@ -18,6 +19,7 @@ RSpec.describe API::MavenPackages do
let_it_be(:deploy_token_for_group) { create(:deploy_token, :group, read_package_registry: true, write_package_registry: true) }
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
+ let(: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_with_token) { headers.merge('Private-Token' => personal_access_token.token) }
@@ -669,6 +671,50 @@ RSpec.describe API::MavenPackages do
end
end
+ context 'when package duplicates are not allowed' do
+ let(:package_name) { package.name }
+ let(:version) { package.version }
+
+ before do
+ package_settings.update!(maven_duplicates_allowed: false)
+ end
+
+ shared_examples 'storing the package file' do
+ it 'stores the file', :aggregate_failures do
+ expect { upload_file_with_token(params: params) }.to change { package.package_files.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(jar_file.file_name).to eq(file_upload.original_filename)
+ end
+ end
+
+ it 'rejects the request', :aggregate_failures do
+ expect { upload_file_with_token(params: params) }.not_to change { package.package_files.count }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to include('Duplicate package is not allowed')
+ end
+
+ context 'when uploading different non-duplicate files to the same package' do
+ let!(:package) { create(:maven_package, project: project, name: project.full_path) }
+
+ before do
+ package_file = package.package_files.find_by(file_name: 'my-app-1.0-20180724.124855-1.jar')
+ package_file.destroy!
+ end
+
+ it_behaves_like 'storing the package file'
+ end
+
+ context 'when the package name matches the exception regex' do
+ before do
+ package_settings.update!(maven_duplicate_exception_regex: '.*')
+ end
+
+ it_behaves_like 'storing the package file'
+ end
+ end
+
context 'for sha1 file' do
let(:dummy_package) { double(Packages::Package) }
@@ -698,7 +744,7 @@ RSpec.describe API::MavenPackages do
end
def upload_file(params: {}, request_headers: headers, file_extension: 'jar')
- url = "/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/my-app-1.0-20180724.124855-1.#{file_extension}"
+ url = "/projects/#{project.id}/packages/maven/#{package_name}/#{version}/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 4339f1dd830..3a3eae73932 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -440,6 +440,7 @@ RSpec.describe API::MergeRequests do
milestone: milestone,
author: user,
assignees: [user],
+ reviewers: [user2],
source_project: project,
target_project: project,
source_branch: 'what',
@@ -498,6 +499,71 @@ RSpec.describe API::MergeRequests do
expect(mr['assignee']['id']).not_to eq(user2.id)
end
end
+
+ context 'filter by reviewer' do
+ context 'with reviewer_id' do
+ context 'with an id' do
+ let(:params) { { not: { reviewer_id: user2.id } } }
+
+ it 'returns merge requests that do not have the given reviewer' do
+ get api(endpoint_path, user), params: { not: { reviewer_id: user2.id } }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(4)
+ expect(json_response.map { |mr| mr['id'] }).not_to include(merge_request2)
+ end
+ end
+
+ context 'with Any' do
+ let(:params) { { not: { reviewer_id: 'Any' } } }
+
+ it 'returns a 400' do
+ # Any is not supported for negated filter
+ get api(endpoint_path, user), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('not[reviewer_id] is invalid')
+ end
+ end
+
+ context 'with None' do
+ let(:params) { { not: { reviewer_id: 'None' } } }
+
+ it 'returns a 400' do
+ # None is not supported for negated filter
+ get api(endpoint_path, user), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('not[reviewer_id] is invalid')
+ end
+ end
+ end
+
+ context 'with reviewer_username' do
+ let(:params) { { not: { reviewer_username: user2.username } } }
+
+ it 'returns merge requests that do not have the given reviewer' do
+ get api(endpoint_path, user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(4)
+ expect(json_response.map { |mr| mr['id'] }).not_to include(merge_request2)
+ end
+ end
+
+ context 'when both reviewer_id and reviewer_username' do
+ let(:params) { { not: { reviewer_id: user2.id, reviewer_username: user2.username } } }
+
+ it 'returns a 400' do
+ get api('/merge_requests', user), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('not[reviewer_id], not[reviewer_username] are mutually exclusive')
+ end
+ end
+ end
end
context 'source_branch param' do
@@ -666,6 +732,79 @@ RSpec.describe API::MergeRequests do
end
end
+ context 'filter by reviewer' do
+ let_it_be(:review_requested_mr1) do
+ create(:merge_request, :unique_branches, author: user, reviewers: [user2], source_project: project2, target_project: project2)
+ end
+
+ let_it_be(:review_requested_mr2) do
+ create(:merge_request, :unique_branches, author: user2, reviewers: [user], source_project: project2, target_project: project2)
+ end
+
+ let(:params) { { scope: :all } }
+
+ context 'with reviewer_id' do
+ let(:params) { super().merge(reviewer_id: reviewer_id) }
+
+ context 'with an id' do
+ let(:reviewer_id) { user2.id }
+
+ it 'returns review requested merge requests for the given user' do
+ get api('/merge_requests', user), params: params
+
+ expect_response_contain_exactly(review_requested_mr1.id)
+ end
+ end
+
+ context 'with Any' do
+ let(:reviewer_id) { 'Any' }
+
+ it 'returns review requested merge requests for any user' do
+ get api('/merge_requests', user), params: params
+
+ expect_response_contain_exactly(review_requested_mr1.id, review_requested_mr2.id)
+ end
+ end
+
+ context 'with None' do
+ let(:reviewer_id) { 'None' }
+
+ it 'returns merge requests that has no assigned reviewers' do
+ get api('/merge_requests', user), params: params
+
+ expect_response_contain_exactly(
+ merge_request.id,
+ merge_request_closed.id,
+ merge_request_merged.id,
+ merge_request_locked.id,
+ merge_request2.id
+ )
+ end
+ end
+ end
+
+ context 'with reviewer_username' do
+ let(:params) { super().merge(reviewer_username: user2.username) }
+
+ it 'returns review requested merge requests for the given user' do
+ get api('/merge_requests', user), params: params
+
+ expect_response_contain_exactly(review_requested_mr1.id)
+ end
+ end
+
+ context 'with both reviewer_id and reviewer_username' do
+ let(:params) { super().merge(reviewer_id: user2.id, reviewer_username: user2.username) }
+
+ it 'returns a 400' do
+ get api('/merge_requests', user), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('reviewer_id, reviewer_username are mutually exclusive')
+ end
+ end
+ end
+
it 'returns an array of merge requests assigned to the given user' do
merge_request3 = create(:merge_request, :simple, author: user, assignees: [user2], source_project: project2, target_project: project2, source_branch: 'other-branch')
diff --git a/spec/requests/api/nuget_group_packages_spec.rb b/spec/requests/api/nuget_group_packages_spec.rb
new file mode 100644
index 00000000000..f7e81494660
--- /dev/null
+++ b/spec/requests/api/nuget_group_packages_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe API::NugetGroupPackages do
+ include_context 'nuget api setup'
+
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+ let_it_be_with_reload(:project) { create(:project, namespace: subgroup) }
+ let_it_be(:deploy_token) { create(:deploy_token, :group, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token, group: group) }
+
+ let(:target_type) { 'groups' }
+
+ shared_examples 'handling all endpoints' do
+ describe 'GET /api/v4/groups/:id/-/packages/nuget' do
+ it_behaves_like 'handling nuget service requests', anonymous_requests_example_name: 'rejects nuget packages access', anonymous_requests_status: :unauthorized do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/index.json" }
+ end
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/metadata/*package_name/index' do
+ it_behaves_like 'handling nuget metadata requests with package name', anonymous_requests_example_name: 'rejects nuget packages access', anonymous_requests_status: :unauthorized do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/metadata/#{package_name}/index.json" }
+ end
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/metadata/*package_name/*package_version' do
+ it_behaves_like 'handling nuget metadata requests with package name and package version', anonymous_requests_example_name: 'rejects nuget packages access', anonymous_requests_status: :unauthorized do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/metadata/#{package_name}/#{package.version}.json" }
+ end
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/query' do
+ it_behaves_like 'handling nuget search requests', anonymous_requests_example_name: 'rejects nuget packages access', anonymous_requests_status: :unauthorized do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/query?#{query_parameters.to_query}" }
+ end
+ end
+ end
+
+ context 'with a subgroup' do
+ # Bug: deploy tokens at parent group will not see the subgroup.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/285495
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token, group: subgroup) }
+
+ let(:target) { subgroup }
+
+ it_behaves_like 'handling all endpoints'
+
+ def update_visibility_to(visibility)
+ project.update!(visibility_level: visibility)
+ subgroup.update!(visibility_level: visibility)
+ end
+ end
+
+ context 'a group' do
+ let(:target) { group }
+
+ it_behaves_like 'handling all endpoints'
+
+ context 'with dummy packages and anonymous request' do
+ let_it_be(:package_name) { 'Dummy.Package' }
+ let_it_be(:packages) { create_list(:nuget_package, 5, :with_metadatum, name: package_name, project: project) }
+ let_it_be(:tags) { packages.each { |pkg| create(:packages_tag, package: pkg, name: 'test') } }
+
+ let(:search_term) { 'umm' }
+ let(:take) { 26 }
+ let(:skip) { 0 }
+ let(:include_prereleases) { true }
+ let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases } }
+
+ subject { get api(url), headers: {}}
+
+ shared_examples 'handling mixed visibilities' do
+ where(:group_visibility, :subgroup_visibility, :expected_status) do
+ 'PUBLIC' | 'PUBLIC' | :unauthorized
+ 'PUBLIC' | 'INTERNAL' | :unauthorized
+ 'PUBLIC' | 'PRIVATE' | :unauthorized
+ 'INTERNAL' | 'INTERNAL' | :unauthorized
+ 'INTERNAL' | 'PRIVATE' | :unauthorized
+ 'PRIVATE' | 'PRIVATE' | :unauthorized
+ end
+
+ with_them do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like 'returning response status', params[:expected_status]
+ end
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/metadata/*package_name/index' do
+ it_behaves_like 'handling mixed visibilities' do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/metadata/#{package_name}/index.json" }
+ end
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/metadata/*package_name/*package_version' do
+ it_behaves_like 'handling mixed visibilities' do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/metadata/#{package_name}/#{packages.first.version}.json" }
+ end
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/query' do
+ it_behaves_like 'handling mixed visibilities' do
+ let(:url) { "/groups/#{target.id}/-/packages/nuget/query?#{query_parameters.to_query}" }
+ end
+ end
+ end
+
+ def update_visibility_to(visibility)
+ project.update!(visibility_level: visibility)
+ subgroup.update!(visibility_level: visibility)
+ group.update!(visibility_level: visibility)
+ end
+ end
+end
diff --git a/spec/requests/api/nuget_project_packages_spec.rb b/spec/requests/api/nuget_project_packages_spec.rb
index df1daf39144..813ebc35ede 100644
--- a/spec/requests/api/nuget_project_packages_spec.rb
+++ b/spec/requests/api/nuget_project_packages_spec.rb
@@ -2,99 +2,202 @@
require 'spec_helper'
RSpec.describe API::NugetProjectPackages do
- include WorkhorseHelpers
- include PackagesManagerApiSpecHelpers
- include HttpBasicAuthHelpers
+ include_context 'nuget api setup'
- let_it_be(:user) { create(:user) }
- let_it_be(:project, reload: true) { create(:project, :public) }
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:project) { create(:project, :public) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
+ let(:target) { project }
+ let(:target_type) { 'projects' }
+
describe 'GET /api/v4/projects/:id/packages/nuget' do
it_behaves_like 'handling nuget service requests' do
- let(:url) { "/projects/#{project.id}/packages/nuget/index.json" }
+ let(:url) { "/projects/#{target.id}/packages/nuget/index.json" }
end
end
describe 'GET /api/v4/projects/:id/packages/nuget/metadata/*package_name/index' do
it_behaves_like 'handling nuget metadata requests with package name' do
- let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/index.json" }
+ let(:url) { "/projects/#{target.id}/packages/nuget/metadata/#{package_name}/index.json" }
end
end
describe 'GET /api/v4/projects/:id/packages/nuget/metadata/*package_name/*package_version' do
it_behaves_like 'handling nuget metadata requests with package name and package version' do
- let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/#{package.version}.json" }
+ let(:url) { "/projects/#{target.id}/packages/nuget/metadata/#{package_name}/#{package.version}.json" }
end
end
describe 'GET /api/v4/projects/:id/packages/nuget/query' do
it_behaves_like 'handling nuget search requests' do
- let(:url) { "/projects/#{project.id}/packages/nuget/query?#{query_parameters.to_query}" }
+ let(:url) { "/projects/#{target.id}/packages/nuget/query?#{query_parameters.to_query}" }
end
end
+ describe 'GET /api/v4/projects/:id/packages/nuget/download/*package_name/index' do
+ let_it_be(:package_name) { 'Dummy.Package' }
+ let_it_be(:packages) { create_list(:nuget_package, 5, name: package_name, project: project) }
+
+ let(:url) { "/projects/#{target.id}/packages/nuget/download/#{package_name}/index.json" }
+
+ subject { get api(url) }
+
+ context 'with valid target' do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'process nuget download versions request' | :success
+ 'PUBLIC' | :guest | true | true | 'process nuget download versions request' | :success
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'process nuget download versions request' | :success
+ 'PUBLIC' | :guest | false | true | 'process nuget download versions request' | :success
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | 'process nuget download versions request' | :success
+ 'PRIVATE' | :developer | true | true | 'process nuget download versions request' | :success
+ 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
+ end
+
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+
+ subject { get api(url), headers: headers }
+
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
+ end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ end
+ end
+
+ it_behaves_like 'deploy token for package GET requests'
+
+ it_behaves_like 'rejects nuget access with unknown target id'
+
+ it_behaves_like 'rejects nuget access with invalid target id'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/nuget/download/*package_name/*package_version/*package_filename' do
+ let_it_be(:package_name) { 'Dummy.Package' }
+ let_it_be(:package) { create(:nuget_package, project: project, name: package_name) }
+
+ let(:url) { "/projects/#{target.id}/packages/nuget/download/#{package.name}/#{package.version}/#{package.name}.#{package.version}.nupkg" }
+
+ subject { get api(url) }
+
+ context 'with valid target' do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'process nuget download content request' | :success
+ 'PUBLIC' | :guest | true | true | 'process nuget download content request' | :success
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'process nuget download content request' | :success
+ 'PUBLIC' | :guest | false | true | 'process nuget download content request' | :success
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | 'process nuget download content request' | :success
+ 'PRIVATE' | :developer | true | true | 'process nuget download content request' | :success
+ 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
+ end
+
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+
+ subject { get api(url), headers: headers }
+
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
+ end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ end
+ end
+
+ it_behaves_like 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
+
+ it_behaves_like 'rejects nuget access with unknown target id'
+
+ it_behaves_like 'rejects nuget access with invalid target id'
+ 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 } }
- let(:url) { "/projects/#{project.id}/packages/nuget/authorize" }
+ let(:url) { "/projects/#{target.id}/packages/nuget/authorize" }
let(:headers) { {} }
subject { put api(url), headers: headers }
- context 'without the need for a license' do
- 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 nuget workhorse authorization' | :success
- 'PUBLIC' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :developer | false | true | 'rejects nuget packages access' | :forbidden
- 'PUBLIC' | :guest | false | true | 'rejects nuget packages access' | :forbidden
- 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | true | true | 'process nuget workhorse authorization' | :success
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
- end
-
- 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) }
+ context 'with valid project' do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'process nuget workhorse authorization' | :success
+ 'PUBLIC' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'rejects nuget packages access' | :forbidden
+ 'PUBLIC' | :guest | false | true | 'rejects nuget packages access' | :forbidden
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | true | true | 'process nuget workhorse authorization' | :success
+ 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
+ end
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
+ 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) }
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
+ end
- it_behaves_like 'deploy token for package uploads'
+ it_behaves_like 'deploy token for package uploads'
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
- end
+ it_behaves_like 'rejects nuget access with invalid target id'
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 } }
let_it_be(:file_name) { 'package.nupkg' }
- let(:url) { "/projects/#{project.id}/packages/nuget" }
+ let(:url) { "/projects/#{target.id}/packages/nuget" }
let(:headers) { {} }
let(:params) { { package: temp_file(file_name) } }
let(:file_key) { :package }
@@ -111,170 +214,61 @@ RSpec.describe API::NugetProjectPackages do
)
end
- context 'without the need for a license' do
- 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 nuget upload' | :created
- 'PUBLIC' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :developer | false | true | 'rejects nuget packages access' | :forbidden
- 'PUBLIC' | :guest | false | true | 'rejects nuget packages access' | :forbidden
- 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | true | true | 'process nuget upload' | :created
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
- end
-
- 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) }
-
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
-
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
- end
+ context 'with valid project' do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'process nuget upload' | :created
+ 'PUBLIC' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'rejects nuget packages access' | :forbidden
+ 'PUBLIC' | :guest | false | true | 'rejects nuget packages access' | :forbidden
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | true | true | 'process nuget upload' | :created
+ 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
- it_behaves_like 'deploy token for package uploads'
-
- it_behaves_like 'rejects nuget access with unknown project id'
-
- it_behaves_like 'rejects nuget access with invalid project id'
-
- context 'file size above maximum limit' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ 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) }
before do
- allow_next_instance_of(UploadedFile) do |uploaded_file|
- allow(uploaded_file).to receive(:size).and_return(project.actual_limits.nuget_max_file_size + 1)
- end
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
- it_behaves_like 'returning response status', :bad_request
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
- end
-
- describe 'GET /api/v4/projects/:id/packages/nuget/download/*package_name/index' do
- let_it_be(:package_name) { 'Dummy.Package' }
- let_it_be(:packages) { create_list(:nuget_package, 5, name: package_name, project: project) }
- let(:url) { "/projects/#{project.id}/packages/nuget/download/#{package_name}/index.json" }
-
- subject { get api(url) }
- context 'without the need for a license' do
- 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 nuget download versions request' | :success
- 'PUBLIC' | :guest | true | true | 'process nuget download versions request' | :success
- 'PUBLIC' | :developer | true | false | 'process nuget download versions request' | :success
- 'PUBLIC' | :guest | true | false | 'process nuget download versions request' | :success
- 'PUBLIC' | :developer | false | true | 'process nuget download versions request' | :success
- 'PUBLIC' | :guest | false | true | 'process nuget download versions request' | :success
- 'PUBLIC' | :developer | false | false | 'process nuget download versions request' | :success
- 'PUBLIC' | :guest | false | false | 'process nuget download versions request' | :success
- 'PUBLIC' | :anonymous | false | true | 'process nuget download versions request' | :success
- 'PRIVATE' | :developer | true | true | 'process nuget download versions request' | :success
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
- end
+ it_behaves_like 'deploy token for package uploads'
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+ it_behaves_like 'rejects nuget access with unknown target id'
- subject { get api(url), headers: headers }
+ it_behaves_like 'rejects nuget access with invalid target id'
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
+ context 'file size above maximum limit' do
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ before do
+ allow_next_instance_of(UploadedFile) do |uploaded_file|
+ allow(uploaded_file).to receive(:size).and_return(project.actual_limits.nuget_max_file_size + 1)
end
end
- it_behaves_like 'deploy token for package GET requests'
-
- it_behaves_like 'rejects nuget access with unknown project id'
-
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'returning response status', :bad_request
end
end
- describe 'GET /api/v4/projects/:id/packages/nuget/download/*package_name/*package_version/*package_filename' do
- let_it_be(:package_name) { 'Dummy.Package' }
- let_it_be(:package) { create(:nuget_package, project: project, name: package_name) }
-
- let(:url) { "/projects/#{project.id}/packages/nuget/download/#{package.name}/#{package.version}/#{package.name}.#{package.version}.nupkg" }
-
- subject { get api(url) }
-
- context 'without the need for a license' do
- 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 nuget download content request' | :success
- 'PUBLIC' | :guest | true | true | 'process nuget download content request' | :success
- 'PUBLIC' | :developer | true | false | 'process nuget download content request' | :success
- 'PUBLIC' | :guest | true | false | 'process nuget download content request' | :success
- 'PUBLIC' | :developer | false | true | 'process nuget download content request' | :success
- 'PUBLIC' | :guest | false | true | 'process nuget download content request' | :success
- 'PUBLIC' | :developer | false | false | 'process nuget download content request' | :success
- 'PUBLIC' | :guest | false | false | 'process nuget download content request' | :success
- 'PUBLIC' | :anonymous | false | true | 'process nuget download content request' | :success
- 'PRIVATE' | :developer | true | true | 'process nuget download content request' | :success
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
- end
-
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
-
- subject { get api(url), headers: headers }
-
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
-
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
- end
- end
-
- it_behaves_like 'deploy token for package GET requests'
-
- it_behaves_like 'rejects nuget access with unknown project id'
-
- it_behaves_like 'rejects nuget access with invalid project id'
- end
+ def update_visibility_to(visibility)
+ project.update!(visibility_level: visibility)
end
end
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index 4c8599d1a20..eb86df36dbb 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -11,12 +11,13 @@ RSpec.describe API::ProjectPackages do
let!(:another_package) { create(:npm_package) }
let(:no_package_url) { "/projects/#{project.id}/packages/0" }
let(:wrong_package_url) { "/projects/#{project.id}/packages/#{another_package.id}" }
+ let(:params) { {} }
describe 'GET /projects/:id/packages' do
let(:url) { "/projects/#{project.id}/packages" }
let(:package_schema) { 'public_api/v4/packages/packages' }
- subject { get api(url) }
+ subject { get api(url), params: params }
context 'without the need for a license' do
context 'project is public' do
@@ -118,6 +119,7 @@ RSpec.describe API::ProjectPackages do
end
end
+ it_behaves_like 'with versionless packages'
it_behaves_like 'does not cause n^2 queries'
end
end
diff --git a/spec/requests/api/project_repository_storage_moves_spec.rb b/spec/requests/api/project_repository_storage_moves_spec.rb
index 15e69c2aa16..5e200312d1f 100644
--- a/spec/requests/api/project_repository_storage_moves_spec.rb
+++ b/spec/requests/api/project_repository_storage_moves_spec.rb
@@ -3,220 +3,10 @@
require 'spec_helper'
RSpec.describe API::ProjectRepositoryStorageMoves do
- include AccessMatchersForRequest
-
- let_it_be(:user) { create(:admin) }
- let_it_be(:project) { create(:project, :repository).tap { |project| project.track_project_repository } }
- let_it_be(:storage_move) { create(:project_repository_storage_move, :scheduled, container: project) }
-
- shared_examples 'get single project repository storage move' do
- let(:project_repository_storage_move_id) { storage_move.id }
-
- def get_project_repository_storage_move
- get api(url, user)
- end
-
- it 'returns a project repository storage move' do
- get_project_repository_storage_move
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/project_repository_storage_move')
- expect(json_response['id']).to eq(storage_move.id)
- expect(json_response['state']).to eq(storage_move.human_state_name)
- end
-
- context 'non-existent project repository storage move' do
- let(:project_repository_storage_move_id) { non_existing_record_id }
-
- it 'returns not found' do
- get_project_repository_storage_move
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- describe 'permissions' do
- it { expect { get_project_repository_storage_move }.to be_allowed_for(:admin) }
- it { expect { get_project_repository_storage_move }.to be_denied_for(:user) }
- end
- end
-
- shared_examples 'get project repository storage move list' do
- def get_project_repository_storage_moves
- get api(url, user)
- end
-
- it 'returns project repository storage moves' do
- get_project_repository_storage_moves
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(response).to match_response_schema('public_api/v4/project_repository_storage_moves')
- expect(json_response.size).to eq(1)
- expect(json_response.first['id']).to eq(storage_move.id)
- expect(json_response.first['state']).to eq(storage_move.human_state_name)
- end
-
- it 'avoids N+1 queries', :request_store do
- # prevent `let` from polluting the control
- get_project_repository_storage_moves
-
- control = ActiveRecord::QueryRecorder.new { get_project_repository_storage_moves }
-
- create(:project_repository_storage_move, :scheduled, container: project)
-
- expect { get_project_repository_storage_moves }.not_to exceed_query_limit(control)
- end
-
- it 'returns the most recently created first' do
- storage_move_oldest = create(:project_repository_storage_move, :scheduled, container: project, created_at: 2.days.ago)
- storage_move_middle = create(:project_repository_storage_move, :scheduled, container: project, created_at: 1.day.ago)
-
- get_project_repository_storage_moves
-
- json_ids = json_response.map {|storage_move| storage_move['id'] }
- expect(json_ids).to eq([
- storage_move.id,
- storage_move_middle.id,
- storage_move_oldest.id
- ])
- end
-
- describe 'permissions' do
- it { expect { get_project_repository_storage_moves }.to be_allowed_for(:admin) }
- it { expect { get_project_repository_storage_moves }.to be_denied_for(:user) }
- end
- end
-
- describe 'GET /project_repository_storage_moves' do
- it_behaves_like 'get project repository storage move list' do
- let(:url) { '/project_repository_storage_moves' }
- end
- end
-
- describe 'GET /project_repository_storage_moves/:repository_storage_move_id' do
- it_behaves_like 'get single project repository storage move' do
- let(:url) { "/project_repository_storage_moves/#{project_repository_storage_move_id}" }
- end
- end
-
- describe 'GET /projects/:id/repository_storage_moves' do
- it_behaves_like 'get project repository storage move list' do
- let(:url) { "/projects/#{project.id}/repository_storage_moves" }
- end
- end
-
- describe 'GET /projects/:id/repository_storage_moves/:repository_storage_move_id' do
- it_behaves_like 'get single project repository storage move' do
- let(:url) { "/projects/#{project.id}/repository_storage_moves/#{project_repository_storage_move_id}" }
- end
- end
-
- describe 'POST /projects/:id/repository_storage_moves' do
- let(:url) { "/projects/#{project.id}/repository_storage_moves" }
- let(:destination_storage_name) { 'test_second_storage' }
-
- def create_project_repository_storage_move
- post api(url, user), params: { destination_storage_name: destination_storage_name }
- end
-
- before do
- stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
- end
-
- it 'schedules a project repository storage move' do
- create_project_repository_storage_move
-
- storage_move = project.repository_storage_moves.last
-
- expect(response).to have_gitlab_http_status(:created)
- expect(response).to match_response_schema('public_api/v4/project_repository_storage_move')
- expect(json_response['id']).to eq(storage_move.id)
- expect(json_response['state']).to eq('scheduled')
- expect(json_response['source_storage_name']).to eq('default')
- expect(json_response['destination_storage_name']).to eq(destination_storage_name)
- end
-
- describe 'permissions' do
- it { expect { create_project_repository_storage_move }.to be_allowed_for(:admin) }
- it { expect { create_project_repository_storage_move }.to be_denied_for(:user) }
- end
-
- context 'destination_storage_name is missing' do
- let(:destination_storage_name) { nil }
-
- it 'schedules a project repository storage move' do
- create_project_repository_storage_move
-
- storage_move = project.repository_storage_moves.last
-
- expect(response).to have_gitlab_http_status(:created)
- expect(response).to match_response_schema('public_api/v4/project_repository_storage_move')
- expect(json_response['id']).to eq(storage_move.id)
- expect(json_response['state']).to eq('scheduled')
- expect(json_response['source_storage_name']).to eq('default')
- expect(json_response['destination_storage_name']).to be_present
- end
- end
- end
-
- describe 'POST /project_repository_storage_moves' do
- let(:source_storage_name) { 'default' }
- let(:destination_storage_name) { 'test_second_storage' }
-
- def create_project_repository_storage_moves
- post api('/project_repository_storage_moves', user), params: {
- source_storage_name: source_storage_name,
- destination_storage_name: destination_storage_name
- }
- end
-
- before do
- stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
- end
-
- it 'schedules the worker' do
- expect(ProjectScheduleBulkRepositoryShardMovesWorker).to receive(:perform_async).with(source_storage_name, destination_storage_name)
-
- create_project_repository_storage_moves
-
- expect(response).to have_gitlab_http_status(:accepted)
- end
-
- context 'source_storage_name is invalid' do
- let(:destination_storage_name) { 'not-a-real-storage' }
-
- it 'gives an error' do
- create_project_repository_storage_moves
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
-
- context 'destination_storage_name is missing' do
- let(:destination_storage_name) { nil }
-
- it 'schedules the worker' do
- expect(ProjectScheduleBulkRepositoryShardMovesWorker).to receive(:perform_async).with(source_storage_name, destination_storage_name)
-
- create_project_repository_storage_moves
-
- expect(response).to have_gitlab_http_status(:accepted)
- end
- end
-
- context 'destination_storage_name is invalid' do
- let(:destination_storage_name) { 'not-a-real-storage' }
-
- it 'gives an error' do
- create_project_repository_storage_moves
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
-
- describe 'normal user' do
- it { expect { create_project_repository_storage_moves }.to be_denied_for(:user) }
- end
+ it_behaves_like 'repository_storage_moves API', 'projects' do
+ let_it_be(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
+ let_it_be(:storage_move) { create(:project_repository_storage_move, :scheduled, container: container) }
+ let(:repository_storage_move_factory) { :project_repository_storage_move }
+ let(:bulk_worker_klass) { ProjectScheduleBulkRepositoryShardMovesWorker }
end
end
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
index d242d49fc1b..fc1035fc17d 100644
--- a/spec/requests/api/project_templates_spec.rb
+++ b/spec/requests/api/project_templates_spec.rb
@@ -53,6 +53,15 @@ RSpec.describe API::ProjectTemplates do
expect(json_response).to satisfy_one { |template| template['key'] == 'Android' }
end
+ it 'returns gitlab_ci_syntax_ymls' do
+ get api("/projects/#{public_project.id}/templates/gitlab_ci_syntax_ymls")
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ expect(json_response).to satisfy_one { |template| template['key'] == 'Artifacts example' }
+ end
+
it 'returns licenses' do
get api("/projects/#{public_project.id}/templates/licenses")
@@ -163,6 +172,14 @@ RSpec.describe API::ProjectTemplates do
expect(json_response['name']).to eq('Android')
end
+ it 'returns a specific gitlab_ci_syntax_yml' do
+ get api("/projects/#{public_project.id}/templates/gitlab_ci_syntax_ymls/Artifacts%20example")
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/template')
+ expect(json_response['name']).to eq('Artifacts example')
+ end
+
it 'returns a specific metrics_dashboard_yml' do
get api("/projects/#{public_project.id}/templates/metrics_dashboard_ymls/Default")
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index ad5468fb54c..4acd0eea448 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1583,6 +1583,7 @@ RSpec.describe API::Projects do
expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
expect(json_response['allow_merge_on_skipped_pipeline']).to eq(project.allow_merge_on_skipped_pipeline)
+ expect(json_response['restrict_user_defined_variables']).to eq(project.restrict_user_defined_variables?)
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
@@ -1654,6 +1655,7 @@ RSpec.describe API::Projects do
expect(json_response['shared_with_groups'][0]).to have_key('expires_at')
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
expect(json_response['allow_merge_on_skipped_pipeline']).to eq(project.allow_merge_on_skipped_pipeline)
+ expect(json_response['restrict_user_defined_variables']).to eq(project.restrict_user_defined_variables?)
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['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['ci_forward_deployment_enabled']).to eq(project.ci_forward_deployment_enabled)
@@ -2597,6 +2599,18 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:bad_request)
end
+ it 'updates restrict_user_defined_variables', :aggregate_failures do
+ project_param = { restrict_user_defined_variables: true }
+
+ put api("/projects/#{project3.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ project_param.each_pair do |k, v|
+ expect(json_response[k.to_s]).to eq(v)
+ end
+ end
+
it 'updates avatar' do
project_param = {
avatar: fixture_file_upload('spec/fixtures/banana_sample.gif',
@@ -2711,6 +2725,22 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['container_expiration_policy.name_regex_keep']).to contain_exactly('not valid RE2 syntax: missing ]: [')
end
+
+ it "doesn't update container_expiration_policy with invalid keep_n" do
+ project_param = {
+ container_expiration_policy_attributes: {
+ cadence: '1month',
+ enabled: true,
+ keep_n: 'not_int',
+ name_regex_keep: 'foo.*'
+ }
+ }
+
+ put api("/projects/#{project3.id}", user4), params: project_param
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('container_expiration_policy_attributes[keep_n] is invalid')
+ end
end
context 'when authenticated as project developer' do
@@ -3364,10 +3394,10 @@ RSpec.describe API::Projects do
end
describe 'POST /projects/:id/housekeeping' do
- let(:housekeeping) { Projects::HousekeepingService.new(project) }
+ let(:housekeeping) { Repositories::HousekeepingService.new(project) }
before do
- allow(Projects::HousekeepingService).to receive(:new).with(project, :gc).and_return(housekeeping)
+ allow(Repositories::HousekeepingService).to receive(:new).with(project, :gc).and_return(housekeeping)
end
context 'when authenticated as owner' do
@@ -3381,12 +3411,12 @@ RSpec.describe API::Projects do
context 'when housekeeping lease is taken' do
it 'returns conflict' do
- expect(housekeeping).to receive(:execute).once.and_raise(Projects::HousekeepingService::LeaseTaken)
+ expect(housekeeping).to receive(:execute).once.and_raise(Repositories::HousekeepingService::LeaseTaken)
post api("/projects/#{project.id}/housekeeping", user)
expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to match(/Somebody already triggered housekeeping for this project/)
+ expect(json_response['message']).to match(/Somebody already triggered housekeeping for this resource/)
end
end
end
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index 58b321a255e..70de2e5330b 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -16,9 +16,6 @@ RSpec.describe API::Releases do
project.add_reporter(reporter)
project.add_guest(guest)
project.add_developer(developer)
-
- project.repository.add_tag(maintainer, 'v0.1', commit.id)
- project.repository.add_tag(maintainer, 'v0.2', commit.id)
end
describe 'GET /projects/:id/releases' do
@@ -294,6 +291,25 @@ RSpec.describe API::Releases do
end
end
+ context 'when release is associated to mutiple milestones' do
+ context 'milestones order' do
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be_with_reload(:release_with_milestones) { create(:release, tag: 'v3.14', project: project) }
+
+ let(:actual_milestone_title_order) do
+ get api("/projects/#{project.id}/releases/#{release_with_milestones.tag}", non_project_member)
+
+ json_response['milestones'].map { |m| m['title'] }
+ end
+
+ before do
+ release_with_milestones.update!(milestones: [milestone_2, milestone_1])
+ end
+
+ it_behaves_like 'correct release milestone order'
+ end
+ end
+
context 'when release has link asset' do
let!(:link) do
create(:release_link,
@@ -461,6 +477,10 @@ RSpec.describe API::Releases do
}
end
+ before do
+ initialize_tags
+ end
+
it 'accepts the request' do
post api("/projects/#{project.id}/releases", maintainer), params: params
@@ -858,6 +878,10 @@ RSpec.describe API::Releases do
description: 'Super nice release')
end
+ before do
+ initialize_tags
+ end
+
it 'accepts the request' do
put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
@@ -1108,4 +1132,9 @@ RSpec.describe API::Releases do
end
end
end
+
+ def initialize_tags
+ project.repository.add_tag(maintainer, 'v0.1', commit.id)
+ project.repository.add_tag(maintainer, 'v0.2', commit.id)
+ end
end
diff --git a/spec/requests/api/snippet_repository_storage_moves_spec.rb b/spec/requests/api/snippet_repository_storage_moves_spec.rb
new file mode 100644
index 00000000000..edb92569823
--- /dev/null
+++ b/spec/requests/api/snippet_repository_storage_moves_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::SnippetRepositoryStorageMoves do
+ it_behaves_like 'repository_storage_moves API', 'snippets' do
+ let_it_be(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
+ let_it_be(:storage_move) { create(:snippet_repository_storage_move, :scheduled, container: container) }
+ let(:repository_storage_move_factory) { :snippet_repository_storage_move }
+ let(:bulk_worker_klass) { SnippetScheduleBulkRepositoryShardMovesWorker }
+ end
+end
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index 0fa088a641e..bfdb5458fd1 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -21,9 +21,36 @@ RSpec.describe API::Terraform::State do
stub_terraform_state_object_storage
end
+ shared_examples 'endpoint with unique user tracking' do
+ context 'without authentication' do
+ let(:auth_header) { basic_auth_header('bad', 'token') }
+
+ before do
+ stub_feature_flags(usage_data_p_terraform_state_api_unique_users: false)
+ end
+
+ it 'does not track unique event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ request
+ end
+ end
+
+ 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
+ let(:target_id) { 'p_terraform_state_api_unique_users' }
+ let(:expected_type) { instance_of(Integer) }
+ end
+ end
+ end
+
describe 'GET /projects/:id/terraform/state/:name' do
subject(:request) { get api(state_path), headers: auth_header }
+ it_behaves_like 'endpoint with unique user tracking'
+
context 'without authentication' do
let(:auth_header) { basic_auth_header('bad', 'token') }
@@ -117,6 +144,8 @@ RSpec.describe API::Terraform::State do
subject(:request) { post api(state_path), headers: auth_header, as: :json, params: params }
+ it_behaves_like 'endpoint with unique user tracking'
+
context 'when terraform state with a given name is already present' do
context 'with maintainer permissions' do
let(:current_user) { maintainer }
@@ -219,6 +248,8 @@ RSpec.describe API::Terraform::State do
describe 'DELETE /projects/:id/terraform/state/:name' do
subject(:request) { delete api(state_path), headers: auth_header }
+ it_behaves_like 'endpoint with unique user tracking'
+
context 'with maintainer permissions' do
let(:current_user) { maintainer }
@@ -256,6 +287,8 @@ RSpec.describe API::Terraform::State do
subject(:request) { post api("#{state_path}/lock"), headers: auth_header, params: params }
+ it_behaves_like 'endpoint with unique user tracking'
+
it 'locks the terraform state' do
request
@@ -305,6 +338,10 @@ RSpec.describe API::Terraform::State do
subject(:request) { delete api("#{state_path}/lock"), headers: auth_header, params: params }
+ it_behaves_like 'endpoint with unique user tracking' do
+ let(:lock_id) { 'irrelevant to this test, just needs to be present' }
+ end
+
context 'with the correct lock id' do
let(:lock_id) { '123-456' }
diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb
index bc315c5b3c6..eaffa49fc9d 100644
--- a/spec/requests/api/todos_spec.rb
+++ b/spec/requests/api/todos_spec.rb
@@ -302,6 +302,8 @@ RSpec.describe API::Todos do
end
it 'returns 304 there already exist a todo on that issuable' do
+ stub_feature_flags(multiple_todos: false)
+
create(:todo, project: project_1, author: author_1, user: john_doe, target: issuable)
post api("/projects/#{project_1.id}/#{issuable_type}/#{issuable.iid}/todo", john_doe)
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 2cd1483f486..94fba451860 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -368,6 +368,16 @@ RSpec.describe API::Users do
expect(json_response.map { |u| u['id'] }).not_to include(internal_user.id)
end
end
+
+ context 'admins param' do
+ it 'returns all users' do
+ get api("/users?admins=true", user)
+
+ expect(response).to match_response_schema('public_api/v4/user/basics')
+ expect(json_response.size).to eq(2)
+ expect(json_response.map { |u| u['id'] }).to include(user.id, admin.id)
+ end
+ end
end
context "when admin" do
@@ -487,6 +497,16 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:bad_request)
end
end
+
+ context 'admins param' do
+ it 'returns only admins' do
+ get api("/users?admins=true", admin)
+
+ expect(response).to match_response_schema('public_api/v4/user/basics')
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['id']).to eq(admin.id)
+ end
+ end
end
describe "GET /users/:id" do
@@ -2368,7 +2388,7 @@ RSpec.describe API::Users do
activate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - A blocked user must be unblocked to be activated')
+ expect(json_response['message']).to eq('403 Forbidden - A blocked user must be unblocked to be activated')
expect(user.reload.state).to eq('blocked')
end
end
@@ -2382,7 +2402,7 @@ RSpec.describe API::Users do
activate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - A blocked user must be unblocked to be activated')
+ expect(json_response['message']).to eq('403 Forbidden - A blocked user must be unblocked to be activated')
expect(user.reload.state).to eq('ldap_blocked')
end
end
@@ -2439,7 +2459,7 @@ RSpec.describe API::Users do
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq("403 Forbidden - The user you are trying to deactivate has been active in the past #{::User::MINIMUM_INACTIVE_DAYS} days and cannot be deactivated")
+ expect(json_response['message']).to eq("403 Forbidden - The user you are trying to deactivate has been active in the past #{::User::MINIMUM_INACTIVE_DAYS} days and cannot be deactivated")
expect(user.reload.state).to eq('active')
end
end
@@ -2467,7 +2487,7 @@ RSpec.describe API::Users do
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
+ expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
expect(user.reload.state).to eq('blocked')
end
end
@@ -2481,7 +2501,7 @@ RSpec.describe API::Users do
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
+ expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
expect(user.reload.state).to eq('ldap_blocked')
end
end
@@ -2493,7 +2513,7 @@ RSpec.describe API::Users do
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - An internal user cannot be deactivated by the API')
+ expect(json_response['message']).to eq('403 Forbidden - An internal user cannot be deactivated by the API')
end
end
@@ -2853,115 +2873,91 @@ RSpec.describe API::Users do
let(:expires_at) { 3.days.from_now.to_date.to_s }
let(:scopes) { %w(api read_user) }
- context 'when feature flag is enabled' do
- before do
- stub_feature_flags(pat_creation_api_for_admin: true)
- end
-
- it 'returns error if required attributes are missing' do
- post api("/users/#{user.id}/personal_access_tokens", admin)
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('name is missing, scopes is missing, scopes does not have a valid value')
- end
-
- it 'returns a 404 error if user not found' do
- post api("/users/#{non_existing_record_id}/personal_access_tokens", admin),
- params: {
- name: name,
- scopes: scopes,
- expires_at: expires_at
- }
+ it 'returns error if required attributes are missing' do
+ post api("/users/#{user.id}/personal_access_tokens", admin)
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('404 User Not Found')
- end
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('name is missing, scopes is missing, scopes does not have a valid value')
+ end
- it 'returns a 401 error when not authenticated' do
- post api("/users/#{user.id}/personal_access_tokens"),
- params: {
- name: name,
- scopes: scopes,
- expires_at: expires_at
- }
+ it 'returns a 404 error if user not found' do
+ post api("/users/#{non_existing_record_id}/personal_access_tokens", admin),
+ params: {
+ name: name,
+ scopes: scopes,
+ expires_at: expires_at
+ }
- expect(response).to have_gitlab_http_status(:unauthorized)
- expect(json_response['message']).to eq('401 Unauthorized')
- end
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
- it 'returns a 403 error when authenticated as normal user' do
- post api("/users/#{user.id}/personal_access_tokens", user),
- params: {
- name: name,
- scopes: scopes,
- expires_at: expires_at
- }
+ it 'returns a 401 error when not authenticated' do
+ post api("/users/#{user.id}/personal_access_tokens"),
+ params: {
+ name: name,
+ scopes: scopes,
+ expires_at: expires_at
+ }
- expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden')
- end
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(json_response['message']).to eq('401 Unauthorized')
+ end
- it 'creates a personal access token when authenticated as admin' do
- post api("/users/#{user.id}/personal_access_tokens", admin),
- params: {
- name: name,
- expires_at: expires_at,
- scopes: scopes
- }
+ it 'returns a 403 error when authenticated as normal user' do
+ post api("/users/#{user.id}/personal_access_tokens", user),
+ params: {
+ name: name,
+ scopes: scopes,
+ expires_at: expires_at
+ }
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq(name)
- expect(json_response['scopes']).to eq(scopes)
- expect(json_response['expires_at']).to eq(expires_at)
- expect(json_response['id']).to be_present
- expect(json_response['created_at']).to be_present
- expect(json_response['active']).to be_truthy
- expect(json_response['revoked']).to be_falsey
- expect(json_response['token']).to be_present
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response['message']).to eq('403 Forbidden')
+ end
- context 'when an error is thrown by the model' do
- let!(:admin_personal_access_token) { create(:personal_access_token, user: admin) }
- let(:error_message) { 'error message' }
+ it 'creates a personal access token when authenticated as admin' do
+ post api("/users/#{user.id}/personal_access_tokens", admin),
+ params: {
+ name: name,
+ expires_at: expires_at,
+ scopes: scopes
+ }
- before do
- allow_next_instance_of(PersonalAccessToken) do |personal_access_token|
- allow(personal_access_token).to receive_message_chain(:errors, :full_messages)
- .and_return([error_message])
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq(name)
+ expect(json_response['scopes']).to eq(scopes)
+ expect(json_response['expires_at']).to eq(expires_at)
+ expect(json_response['id']).to be_present
+ expect(json_response['created_at']).to be_present
+ expect(json_response['active']).to be_truthy
+ expect(json_response['revoked']).to be_falsey
+ expect(json_response['token']).to be_present
+ end
- allow(personal_access_token).to receive(:save).and_return(false)
- end
- end
+ context 'when an error is thrown by the model' do
+ let!(:admin_personal_access_token) { create(:personal_access_token, user: admin) }
+ let(:error_message) { 'error message' }
- it 'returns the error' do
- post api("/users/#{user.id}/personal_access_tokens", personal_access_token: admin_personal_access_token),
- params: {
- name: name,
- expires_at: expires_at,
- scopes: scopes
- }
+ before do
+ allow_next_instance_of(PersonalAccessToken) do |personal_access_token|
+ allow(personal_access_token).to receive_message_chain(:errors, :full_messages)
+ .and_return([error_message])
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response['message']).to eq(error_message)
+ allow(personal_access_token).to receive(:save).and_return(false)
end
end
- end
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(pat_creation_api_for_admin: false)
- end
-
- it 'returns a 404' do
- post api("/users/#{user.id}/personal_access_tokens", admin),
+ it 'returns the error' do
+ post api("/users/#{user.id}/personal_access_tokens", personal_access_token: admin_personal_access_token),
params: {
name: name,
expires_at: expires_at,
scopes: scopes
}
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('404 Not Found')
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq(error_message)
end
end
end
diff --git a/spec/requests/jwks_controller_spec.rb b/spec/requests/jwks_controller_spec.rb
new file mode 100644
index 00000000000..5eda1979027
--- /dev/null
+++ b/spec/requests/jwks_controller_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JwksController do
+ describe 'GET /-/jwks' do
+ let(:ci_jwt_signing_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:ci_jwk) { ci_jwt_signing_key.to_jwk }
+ let(:oidc_jwk) { OpenSSL::PKey::RSA.new(Rails.application.secrets.openid_connect_signing_key).to_jwk }
+
+ before do
+ stub_application_setting(ci_jwt_signing_key: ci_jwt_signing_key.to_s)
+ end
+
+ it 'returns signing keys used to sign CI_JOB_JWT' do
+ get jwks_url
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ ids = json_response['keys'].map { |jwk| jwk['kid'] }
+ expect(ids).to contain_exactly(ci_jwk['kid'], oidc_jwk['kid'])
+ end
+
+ it 'does not leak private key data' do
+ get jwks_url
+
+ aggregate_failures do
+ json_response['keys'].each do |jwk|
+ expect(jwk.keys).to contain_exactly('kty', 'kid', 'e', 'n', 'use', 'alg')
+ expect(jwk['use']).to eq('sig')
+ expect(jwk['alg']).to eq('RS256')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 535d511a459..aeec18aee2b 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -193,10 +193,8 @@ RSpec.describe 'Git LFS API and storage' do
subject(:request) { post_lfs_json batch_url(project), body, headers }
let(:response) { request && super() }
- let(:lfs_chunked_encoding) { true }
before do
- stub_feature_flags(lfs_chunked_encoding: lfs_chunked_encoding)
project.lfs_objects << lfs_object
end
@@ -480,20 +478,6 @@ RSpec.describe 'Git LFS API and storage' do
expect(headers['Transfer-Encoding']).to eq('chunked')
end
- context 'when lfs_chunked_encoding feature is disabled' do
- let(:lfs_chunked_encoding) { false }
-
- it 'responds with upload hypermedia link' do
- expect(json_response['objects']).to be_kind_of(Array)
- expect(json_response['objects'].first).to include(sample_object)
- expect(json_response['objects'].first['actions']['upload']['href']).to eq(objects_url(project, sample_oid, sample_size))
-
- headers = json_response['objects'].first['actions']['upload']['header']
- expect(headers['Content-Type']).to eq('application/octet-stream')
- expect(headers['Transfer-Encoding']).to be_nil
- end
- end
-
it_behaves_like 'process authorization header', renew_authorization: renew_authorization
end
diff --git a/spec/requests/profiles/notifications_controller_spec.rb b/spec/requests/profiles/notifications_controller_spec.rb
index 87669b3594c..d7dfb1c675d 100644
--- a/spec/requests/profiles/notifications_controller_spec.rb
+++ b/spec/requests/profiles/notifications_controller_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'view user notifications' do
get profile_notifications_path
end
- describe 'GET /profile/notifications' do
+ describe 'GET /-/profile/notifications' do
it 'does not have an N+1 due to an additional groups (with no parent group)' do
get_profile_notifications
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index f8fa9459467..565576f3091 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -7,113 +7,95 @@ RSpec.describe 'value stream analytics events' do
let(:project) { create(:project, :repository, public_builds: false) }
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
- shared_examples 'value stream analytics events examples' do
- describe 'GET /:namespace/:project/value_stream_analytics/events/issues' do
- before do
- project.add_developer(user)
+ describe 'GET /:namespace/:project/value_stream_analytics/events/issues' do
+ before do
+ project.add_developer(user)
- 3.times do |count|
- travel_to(Time.now + count.days) do
- create_cycle
- end
+ 3.times do |count|
+ travel_to(Time.now + count.days) do
+ create_cycle
end
-
- deploy_master(user, project)
-
- login_as(user)
end
- it 'lists the issue events' do
- get project_cycle_analytics_issue_path(project, format: :json)
+ deploy_master(user, project)
- first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
+ login_as(user)
+ end
- expect(json_response['events']).not_to be_empty
- expect(json_response['events'].first['iid']).to eq(first_issue_iid)
- end
+ it 'lists the issue events' do
+ get project_cycle_analytics_issue_path(project, format: :json)
- it 'lists the plan events' do
- get project_cycle_analytics_plan_path(project, format: :json)
+ first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
- first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
+ expect(json_response['events']).not_to be_empty
+ expect(json_response['events'].first['iid']).to eq(first_issue_iid)
+ end
- expect(json_response['events']).not_to be_empty
- expect(json_response['events'].first['iid']).to eq(first_issue_iid)
- end
+ it 'lists the plan events' do
+ get project_cycle_analytics_plan_path(project, format: :json)
- it 'lists the code events' do
- get project_cycle_analytics_code_path(project, format: :json)
+ first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
- expect(json_response['events']).not_to be_empty
+ expect(json_response['events']).not_to be_empty
+ expect(json_response['events'].first['iid']).to eq(first_issue_iid)
+ end
- first_mr_iid = project.merge_requests.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
+ it 'lists the code events' do
+ get project_cycle_analytics_code_path(project, format: :json)
- expect(json_response['events'].first['iid']).to eq(first_mr_iid)
- end
+ expect(json_response['events']).not_to be_empty
- it 'lists the test events', :sidekiq_inline do
- get project_cycle_analytics_test_path(project, format: :json)
+ first_mr_iid = project.merge_requests.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
- expect(json_response['events']).not_to be_empty
- expect(json_response['events'].first['date']).not_to be_empty
- end
+ expect(json_response['events'].first['iid']).to eq(first_mr_iid)
+ end
- it 'lists the review events' do
- get project_cycle_analytics_review_path(project, format: :json)
+ it 'lists the test events', :sidekiq_inline do
+ get project_cycle_analytics_test_path(project, format: :json)
- first_mr_iid = project.merge_requests.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
+ expect(json_response['events']).not_to be_empty
+ expect(json_response['events'].first['date']).not_to be_empty
+ end
- expect(json_response['events']).not_to be_empty
- expect(json_response['events'].first['iid']).to eq(first_mr_iid)
- end
+ it 'lists the review events' do
+ get project_cycle_analytics_review_path(project, format: :json)
- it 'lists the staging events', :sidekiq_inline do
- get project_cycle_analytics_staging_path(project, format: :json)
+ first_mr_iid = project.merge_requests.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
- expect(json_response['events']).not_to be_empty
- expect(json_response['events'].first['date']).not_to be_empty
- end
+ expect(json_response['events']).not_to be_empty
+ expect(json_response['events'].first['iid']).to eq(first_mr_iid)
+ end
- context 'with private project and builds' do
- before do
- project.members.last.update(access_level: Gitlab::Access::GUEST)
- end
+ it 'lists the staging events', :sidekiq_inline do
+ get project_cycle_analytics_staging_path(project, format: :json)
- it 'does not list the test events' do
- get project_cycle_analytics_test_path(project, format: :json)
+ expect(json_response['events']).not_to be_empty
+ expect(json_response['events'].first['date']).not_to be_empty
+ end
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ context 'with private project and builds' do
+ before do
+ project.members.last.update(access_level: Gitlab::Access::GUEST)
+ end
- it 'does not list the staging events' do
- get project_cycle_analytics_staging_path(project, format: :json)
+ it 'does not list the test events' do
+ get project_cycle_analytics_test_path(project, format: :json)
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
- it 'lists the issue events' do
- get project_cycle_analytics_issue_path(project, format: :json)
+ it 'does not list the staging events' do
+ get project_cycle_analytics_staging_path(project, format: :json)
- expect(response).to have_gitlab_http_status(:ok)
- end
+ expect(response).to have_gitlab_http_status(:not_found)
end
- end
- end
- describe 'when new_project_level_vsa_backend feature flag is off' do
- before do
- stub_feature_flags(new_project_level_vsa_backend: false, thing: project)
- end
-
- it_behaves_like 'value stream analytics events examples'
- end
+ it 'lists the issue events' do
+ get project_cycle_analytics_issue_path(project, format: :json)
- describe 'when new_project_level_vsa_backend feature flag is on' do
- before do
- stub_feature_flags(new_project_level_vsa_backend: true, thing: project)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
-
- it_behaves_like 'value stream analytics events examples'
end
def create_cycle
diff --git a/spec/requests/projects/incident_management/pagerduty_incidents_spec.rb b/spec/requests/projects/incident_management/pagerduty_incidents_spec.rb
index b18bffdb110..32434435475 100644
--- a/spec/requests/projects/incident_management/pagerduty_incidents_spec.rb
+++ b/spec/requests/projects/incident_management/pagerduty_incidents_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'PagerDuty webhook' do
it 'calls PagerDuty webhook processor with correct parameters' do
make_request
- expect(webhook_processor_class).to have_received(:new).with(project, nil, payload)
+ expect(webhook_processor_class).to have_received(:new).with(project, payload)
expect(webhook_processor).to have_received(:execute).with('VALID-TOKEN')
end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index c2e68df2c40..34f34c0b850 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -60,6 +60,24 @@ RSpec.describe 'Rack Attack global throttles' do
expect_rejection { get url_that_does_not_require_authentication }
end
+ context 'with custom response text' do
+ before do
+ stub_application_setting(rate_limiting_response_text: 'Custom response')
+ end
+
+ it 'rejects requests over the rate limit' do
+ # At first, allow requests under the rate limit.
+ requests_per_period.times do
+ get url_that_does_not_require_authentication
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ # the last straw
+ expect_rejection { get url_that_does_not_require_authentication }
+ expect(response.body).to eq("Custom response\n")
+ end
+ end
+
it 'allows requests after throttling and then waiting for the next period' do
requests_per_period.times do
get url_that_does_not_require_authentication
@@ -170,16 +188,16 @@ RSpec.describe 'Rack Attack global throttles' do
end
describe 'API requests authenticated with personal access token', :api do
- let(:user) { create(:user) }
- let(:token) { create(:personal_access_token, user: user) }
- let(:other_user) { create(:user) }
- let(:other_user_token) { create(:personal_access_token, user: other_user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:token) { create(:personal_access_token, user: user) }
+ let_it_be(:other_user) { create(:user) }
+ let_it_be(:other_user_token) { create(:personal_access_token, user: other_user) }
let(:throttle_setting_prefix) { 'throttle_authenticated_api' }
let(:api_partial_url) { '/todos' }
context 'with the token in the query string' do
- let(:request_args) { [api(api_partial_url, personal_access_token: token)] }
- let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, personal_access_token: token), {}] }
+ let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token), {}] }
it_behaves_like 'rate-limited token-authenticated requests'
end
@@ -190,6 +208,41 @@ RSpec.describe 'Rack Attack global throttles' do
it_behaves_like 'rate-limited token-authenticated requests'
end
+
+ context 'with the token in the OAuth headers' do
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
+
+ context 'with the token in basic auth' do
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, basic_auth_headers(user, token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, basic_auth_headers(other_user, other_user_token)) }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
+
+ context 'with a read_api scope' do
+ before do
+ token.update!(scopes: ['read_api'])
+ other_user_token.update!(scopes: ['read_api'])
+ end
+
+ context 'with the token in the headers' do
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
+
+ context 'with the token in the OAuth headers' do
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
+ end
end
describe 'API requests authenticated with OAuth token', :api do
@@ -205,8 +258,8 @@ RSpec.describe 'Rack Attack global throttles' do
let(:api_partial_url) { '/todos' }
context 'with the token in the query string' do
- let(:request_args) { [api(api_partial_url, oauth_access_token: token)] }
- let(:other_user_request_args) { [api(api_partial_url, oauth_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, oauth_access_token: token), {}] }
+ let(:other_user_request_args) { [api(api_partial_url, oauth_access_token: other_user_token), {}] }
it_behaves_like 'rate-limited token-authenticated requests'
end
@@ -217,6 +270,15 @@ RSpec.describe 'Rack Attack global throttles' do
it_behaves_like 'rate-limited token-authenticated requests'
end
+
+ context 'with a read_api scope' do
+ let(:read_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "read_api") }
+ let(:other_user_read_token) { Doorkeeper::AccessToken.create!(application_id: other_user_application.id, resource_owner_id: other_user.id, scopes: "read_api") }
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(read_token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_read_token)) }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
end
describe '"web" (non-API) requests authenticated with RSS token' do
@@ -314,8 +376,8 @@ RSpec.describe 'Rack Attack global throttles' do
end
context 'with the token in the query string' do
- let(:request_args) { [api(api_partial_url, personal_access_token: token)] }
- let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+ let(:request_args) { [api(api_partial_url, personal_access_token: token), {}] }
+ let(:other_user_request_args) { [api(api_partial_url, personal_access_token: other_user_token), {}] }
it_behaves_like 'rate-limited token-authenticated requests'
end
diff --git a/spec/requests/runner_setup_controller_spec.rb b/spec/requests/runner_setup_controller_spec.rb
new file mode 100644
index 00000000000..665c896e30d
--- /dev/null
+++ b/spec/requests/runner_setup_controller_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe RunnerSetupController do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET /-/runner_setup/platforms' do
+ it 'renders the platforms' do
+ get runner_setup_platforms_url
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to have_key("windows")
+ expect(json_response).to have_key("kubernetes")
+ end
+ end
+end
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
new file mode 100644
index 00000000000..b224ef87229
--- /dev/null
+++ b/spec/requests/users_controller_spec.rb
@@ -0,0 +1,833 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe UsersController do
+ # This user should have the same e-mail address associated with the GPG key prepared for tests
+ let(:user) { create(:user, email: GpgHelpers::User1.emails[0]) }
+ let(:private_user) { create(:user, private_profile: true) }
+ let(:public_user) { create(:user) }
+
+ describe 'GET #show' do
+ shared_examples_for 'renders the show template' do
+ it 'renders the show template' do
+ get user_url user.username
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('show')
+ end
+ end
+
+ context 'when the user exists and has public visibility' do
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders the show template'
+ end
+
+ context 'when logged out' do
+ it_behaves_like 'renders the show template'
+ end
+ end
+
+ context 'when public visibility level is restricted' do
+ before do
+ stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
+ end
+
+ context 'when logged out' do
+ it 'redirects to login page' do
+ get user_url user.username
+
+ expect(response).to redirect_to new_user_session_path
+ end
+ end
+
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders the show template'
+ end
+ end
+
+ context 'when a user by that username does not exist' do
+ context 'when logged out' do
+ it 'redirects to login page' do
+ get user_url 'nonexistent'
+
+ expect(response).to redirect_to new_user_session_path
+ end
+ end
+
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders 404' do
+ get user_url 'nonexistent'
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'requested in json format' do
+ let(:project) { create(:project) }
+
+ before do
+ project.add_developer(user)
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+
+ sign_in(user)
+ end
+
+ it 'returns 404 with deprecation message' do
+ # Requesting "/username?format=json" instead of "/username.json"
+ get user_url user.username, params: { format: :json }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.media_type).to eq('application/json')
+ expect(Gitlab::Json.parse(response.body)['message']).to include('This endpoint is deprecated.')
+ end
+ end
+ end
+
+ describe 'GET /users/:username (deprecated user top)' do
+ it 'redirects to /user1' do
+ get '/users/user1'
+
+ expect(response).to redirect_to user_path('user1')
+ end
+ end
+
+ describe 'GET #activity' do
+ shared_examples_for 'renders the show template' do
+ it 'renders the show template' do
+ get user_activity_url user.username
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('show')
+ end
+ end
+
+ context 'when the user exists and has public visibility' do
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders the show template'
+ end
+
+ context 'when logged out' do
+ it_behaves_like 'renders the show template'
+ end
+ end
+
+ context 'when public visibility level is restricted' do
+ before do
+ stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
+ end
+
+ context 'when logged out' do
+ it 'redirects to login page' do
+ get user_activity_url user.username
+
+ expect(response).to redirect_to new_user_session_path
+ end
+ end
+
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders the show template'
+ end
+ end
+
+ context 'when a user by that username does not exist' do
+ context 'when logged out' do
+ it 'redirects to login page' do
+ get user_activity_url 'nonexistent'
+
+ expect(response).to redirect_to new_user_session_path
+ end
+ end
+
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders 404' do
+ get user_activity_url 'nonexistent'
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'requested in json format' do
+ let(:project) { create(:project) }
+
+ before do
+ project.add_developer(user)
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+
+ sign_in(user)
+ end
+
+ it 'loads events' do
+ get user_activity_url user.username, format: :json
+
+ expect(response.media_type).to eq('application/json')
+ expect(Gitlab::Json.parse(response.body)['count']).to eq(1)
+ end
+
+ it 'hides events if the user cannot read cross project' do
+ allow(Ability).to receive(:allowed?).and_call_original
+ expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
+
+ get user_activity_url user.username, format: :json
+
+ expect(response.media_type).to eq('application/json')
+ expect(Gitlab::Json.parse(response.body)['count']).to eq(0)
+ end
+
+ it 'hides events if the user has a private profile' do
+ Gitlab::DataBuilder::Push.build_sample(project, private_user)
+
+ get user_activity_url private_user.username, format: :json
+
+ expect(response.media_type).to eq('application/json')
+ expect(Gitlab::Json.parse(response.body)['count']).to eq(0)
+ end
+ end
+ end
+
+ describe 'GET #ssh_keys' do
+ context 'non existent user' do
+ it 'does not generally work' do
+ get '/not-existent.keys'
+
+ expect(response).not_to be_successful
+ end
+ end
+
+ context 'user with no keys' do
+ it 'responds the empty body with text/plain content type' do
+ get "/#{user.username}.keys"
+
+ expect(response).to be_successful
+ expect(response.media_type).to eq("text/plain")
+ expect(response.body).to eq("")
+ end
+ end
+
+ context 'user with keys' do
+ let!(:key) { create(:key, user: user) }
+ let!(:another_key) { create(:another_key, user: user) }
+ let!(:deploy_key) { create(:deploy_key, user: user) }
+
+ shared_examples_for 'renders all public keys' do
+ it 'renders all non-deploy keys separated with a new line with text/plain content type without the comment key' do
+ get "/#{user.username}.keys"
+
+ expect(response).to be_successful
+ expect(response.media_type).to eq("text/plain")
+
+ expect(response.body).not_to eq('')
+ expect(response.body).to eq(user.all_ssh_keys.join("\n"))
+
+ expect(response.body).to include(key.key.sub(' dummy@gitlab.com', ''))
+ expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', ''))
+
+ expect(response.body).not_to match(/dummy@gitlab.com/)
+
+ expect(response.body).not_to include(deploy_key.key)
+ end
+ end
+
+ context 'while signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders all public keys'
+ end
+
+ context 'when logged out' do
+ before do
+ sign_out(user)
+ end
+
+ it_behaves_like 'renders all public keys'
+ end
+ end
+ end
+
+ describe 'GET #gpg_keys' do
+ context 'non existent user' do
+ it 'does not generally work' do
+ get '/not-existent.keys'
+
+ expect(response).not_to be_successful
+ end
+ end
+
+ context 'user with no keys' do
+ it 'responds the empty body with text/plain content type' do
+ get "/#{user.username}.gpg"
+
+ expect(response).to be_successful
+ expect(response.media_type).to eq("text/plain")
+ expect(response.body).to eq("")
+ end
+ end
+
+ context 'user with keys' do
+ let!(:gpg_key) { create(:gpg_key, user: user) }
+ let!(:another_gpg_key) { create(:another_gpg_key, user: user) }
+
+ shared_examples_for 'renders all verified GPG keys' do
+ it 'renders all verified keys separated with a new line with text/plain content type' do
+ get "/#{user.username}.gpg"
+
+ expect(response).to be_successful
+
+ expect(response.media_type).to eq("text/plain")
+
+ expect(response.body).not_to eq('')
+ expect(response.body).to eq(user.gpg_keys.select(&:verified?).map(&:key).join("\n"))
+
+ expect(response.body).to include(gpg_key.key)
+ expect(response.body).to include(another_gpg_key.key)
+ end
+ end
+
+ context 'while signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders all verified GPG keys'
+ end
+
+ context 'when logged out' do
+ before do
+ sign_out(user)
+ end
+
+ it_behaves_like 'renders all verified GPG keys'
+ end
+
+ context 'when revoked' do
+ shared_examples_for 'doesn\'t render revoked keys' do
+ it 'doesn\'t render revoked keys' do
+ get "/#{user.username}.gpg"
+
+ expect(response.body).not_to eq('')
+
+ expect(response.body).to include(gpg_key.key)
+ expect(response.body).not_to include(another_gpg_key.key)
+ end
+ end
+
+ before do
+ sign_in(user)
+ another_gpg_key.revoke
+ end
+
+ context 'while signed in' do
+ it_behaves_like 'doesn\'t render revoked keys'
+ end
+
+ context 'when logged out' do
+ before do
+ sign_out(user)
+ end
+
+ it_behaves_like 'doesn\'t render revoked keys'
+ end
+ end
+ end
+ end
+
+ describe 'GET #calendar' do
+ context 'for user' do
+ let(:project) { create(:project) }
+
+ before do
+ sign_in(user)
+ project.add_developer(user)
+ end
+
+ context 'with public profile' do
+ it 'renders calendar' do
+ push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user)
+ EventCreateService.new.push(project, public_user, push_data)
+
+ get user_calendar_url public_user.username, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'with private profile' do
+ it 'does not render calendar' do
+ push_data = Gitlab::DataBuilder::Push.build_sample(project, private_user)
+ EventCreateService.new.push(project, private_user, push_data)
+
+ get user_calendar_url private_user.username, format: :json
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'forked project' do
+ let(:project) { create(:project) }
+ let(:forked_project) { Projects::ForkService.new(project, user).execute }
+
+ before do
+ sign_in(user)
+ project.add_developer(user)
+
+ push_data = Gitlab::DataBuilder::Push.build_sample(project, user)
+
+ fork_push_data = Gitlab::DataBuilder::Push
+ .build_sample(forked_project, user)
+
+ EventCreateService.new.push(project, user, push_data)
+ EventCreateService.new.push(forked_project, user, fork_push_data)
+ end
+
+ it 'includes forked projects' do
+ get user_calendar_url user.username
+
+ expect(assigns(:contributions_calendar).projects.count).to eq(2)
+ end
+ end
+ end
+
+ describe 'GET #calendar_activities' do
+ let!(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ allow_next_instance_of(User) do |instance|
+ allow(instance).to receive(:contributed_projects_ids).and_return([project.id])
+ end
+
+ sign_in(user)
+ project.add_developer(user)
+ end
+
+ it 'renders activities on the specified day' do
+ get user_calendar_activities_url user.username, date: '2014-07-31'
+
+ expect(response.media_type).to eq('text/html')
+ expect(response.body).to include('Jul 31, 2014')
+ end
+
+ context 'for user' do
+ context 'with public profile' do
+ let(:issue) { create(:issue, project: project, author: user) }
+ let(:note) { create(:note, noteable: issue, author: user, project: project) }
+
+ before do
+ create_push_event
+ create_note_event
+ end
+
+ it 'renders calendar_activities' do
+ get user_calendar_activities_url public_user.username
+
+ expect(response.body).not_to be_empty
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ get user_calendar_activities_url public_user.username
+
+ control = ActiveRecord::QueryRecorder.new { get user_calendar_activities_url public_user.username }
+
+ create_push_event
+ create_note_event
+
+ expect { get user_calendar_activities_url public_user.username }.not_to exceed_query_limit(control)
+ end
+ end
+
+ context 'with private profile' do
+ it 'does not render calendar_activities' do
+ push_data = Gitlab::DataBuilder::Push.build_sample(project, private_user)
+ EventCreateService.new.push(project, private_user, push_data)
+
+ get user_calendar_activities_url private_user.username
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'external authorization' do
+ subject { get user_calendar_activities_url user.username }
+
+ it_behaves_like 'disabled when using an external authorization service'
+ end
+
+ def create_push_event
+ push_data = Gitlab::DataBuilder::Push.build_sample(project, public_user)
+ EventCreateService.new.push(project, public_user, push_data)
+ end
+
+ def create_note_event
+ EventCreateService.new.leave_note(note, public_user)
+ end
+ end
+ end
+
+ describe 'GET #contributed' do
+ let(:project) { create(:project, :public) }
+
+ subject do
+ get user_contributed_projects_url author.username, format: format
+ end
+
+ before do
+ sign_in(user)
+
+ project.add_developer(public_user)
+ project.add_developer(private_user)
+ create(:push_event, project: project, author: author)
+
+ subject
+ end
+
+ shared_examples_for 'renders contributed projects' do
+ it 'renders contributed projects' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).not_to be_empty
+ end
+ end
+
+ %i(html json).each do |format|
+ context "format: #{format}" do
+ let(:format) { format }
+
+ context 'with public profile' do
+ let(:author) { public_user }
+
+ it_behaves_like 'renders contributed projects'
+ end
+
+ context 'with private profile' do
+ let(:author) { private_user }
+
+ it 'returns 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'with a user that has the ability to read private profiles', :enable_admin_mode do
+ let(:user) { create(:admin) }
+
+ it_behaves_like 'renders contributed projects'
+ end
+ end
+ end
+ end
+ end
+
+ describe 'GET #starred' do
+ let(:project) { create(:project, :public) }
+
+ subject do
+ get user_starred_projects_url author.username, format: format
+ end
+
+ before do
+ author.toggle_star(project)
+
+ sign_in(user)
+ subject
+ end
+
+ shared_examples_for 'renders starred projects' do
+ it 'renders starred projects' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).not_to be_empty
+ end
+ end
+
+ %i(html json).each do |format|
+ context "format: #{format}" do
+ let(:format) { format }
+
+ context 'with public profile' do
+ let(:author) { public_user }
+
+ it_behaves_like 'renders starred projects'
+ end
+
+ context 'with private profile' do
+ let(:author) { private_user }
+
+ it 'returns 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'with a user that has the ability to read private profiles', :enable_admin_mode do
+ let(:user) { create(:admin) }
+
+ it_behaves_like 'renders starred projects'
+ end
+ end
+ end
+ end
+ end
+
+ describe 'GET #snippets' do
+ before do
+ sign_in(user)
+ end
+
+ context 'format html' do
+ it 'renders snippets page' do
+ get user_snippets_url user.username
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('show')
+ end
+ end
+
+ context 'format json' do
+ it 'response with snippets json data' do
+ get user_snippets_url user.username, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to have_key('html')
+ end
+ end
+
+ context 'external authorization' do
+ subject { get user_snippets_url user.username }
+
+ it_behaves_like 'disabled when using an external authorization service'
+ end
+ end
+
+ describe 'GET #exists' do
+ before do
+ sign_in(user)
+ end
+
+ context 'when user exists' do
+ it 'returns JSON indicating the user exists' do
+ get user_exists_url user.username
+
+ expected_json = { exists: true }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+
+ context 'when the casing is different' do
+ let(:user) { create(:user, username: 'CamelCaseUser') }
+
+ it 'returns JSON indicating the user exists' do
+ get user_exists_url user.username.downcase
+
+ expected_json = { exists: true }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'returns JSON indicating the user does not exist' do
+ get user_exists_url 'foo'
+
+ expected_json = { exists: false }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+
+ context 'when a user changed their username' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
+
+ it 'returns JSON indicating a user by that username does not exist' do
+ get user_exists_url 'old-username'
+
+ expected_json = { exists: false }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+ end
+ end
+ end
+
+ describe 'GET #suggests' do
+ context 'when user exists' do
+ it 'returns JSON indicating the user exists and a suggestion' do
+ get user_suggests_url user.username
+
+ expected_json = { exists: true, suggests: ["#{user.username}1"] }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+
+ context 'when the casing is different' do
+ let(:user) { create(:user, username: 'CamelCaseUser') }
+
+ it 'returns JSON indicating the user exists and a suggestion' do
+ get user_suggests_url user.username.downcase
+
+ expected_json = { exists: true, suggests: ["#{user.username.downcase}1"] }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'returns JSON indicating the user does not exist' do
+ get user_suggests_url 'foo'
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+
+ context 'when a user changed their username' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
+
+ it 'returns JSON indicating a user by that username does not exist' do
+ get user_suggests_url 'old-username'
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response.body).to eq(expected_json)
+ end
+ end
+ end
+ end
+
+ describe '#ensure_canonical_path' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a GET request' do
+ context 'when requesting users at the root path' do
+ context 'when requesting the canonical path' do
+ let(:user) { create(:user, username: 'CamelCaseUser') }
+
+ context 'with exactly matching casing' do
+ it 'responds with success' do
+ get user_url user.username
+
+ expect(response).to be_successful
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get user_url user.username.downcase
+
+ expect(response).to redirect_to(user)
+ expect(flash[:notice]).to be_nil
+ end
+ end
+ end
+
+ shared_examples_for 'redirects to the canonical path' do
+ it 'redirects to the canonical path' do
+ get user_url redirect_route.path
+
+ expect(response).to redirect_to(user)
+ expect(flash[:notice]).to eq(user_moved_message(redirect_route, user))
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
+
+ it_behaves_like 'redirects to the canonical path'
+
+ context 'when the old path is a substring of the scheme or host' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
+
+ # it does not modify the requested host and ...
+ it_behaves_like 'redirects to the canonical path'
+ end
+
+ context 'when the old path is substring of users' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
+
+ it_behaves_like 'redirects to the canonical path'
+ end
+ end
+ end
+
+ context 'when requesting users under the /users path' do
+ context 'when requesting the canonical path' do
+ let(:user) { create(:user, username: 'CamelCaseUser') }
+
+ context 'with exactly matching casing' do
+ it 'responds with success' do
+ get user_projects_url user.username
+
+ expect(response).to be_successful
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get user_projects_url user.username.downcase
+
+ expect(response).to redirect_to(user_projects_path(user))
+ expect(flash[:notice]).to be_nil
+ end
+ end
+ end
+
+ shared_examples_for 'redirects to the canonical path' do
+ it 'redirects to the canonical path' do
+ get user_projects_url redirect_route.path
+
+ expect(response).to redirect_to(user_projects_path(user))
+ expect(flash[:notice]).to eq(user_moved_message(redirect_route, user))
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
+
+ it_behaves_like 'redirects to the canonical path'
+
+ context 'when the old path is a substring of the scheme or host' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
+
+ # it does not modify the requested host and ...
+ it_behaves_like 'redirects to the canonical path'
+ end
+
+ context 'when the old path is substring of users' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
+
+ # it does not modify the /users part of the path
+ # (i.e. /users/ser should not become /ufoos/ser) and ...
+ it_behaves_like 'redirects to the canonical path'
+ end
+ end
+ end
+ end
+ end
+
+ context 'token authentication' do
+ let(:url) { user_url(user.username, format: :atom) }
+
+ it_behaves_like 'authenticates sessionless user for the request spec', public: true
+ end
+
+ def user_moved_message(redirect_route, user)
+ "User '#{redirect_route.path}' was moved to '#{user.full_path}'. Please update any links and bookmarks that may still have the old path."
+ end
+end
diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb
index 007e8ff4816..d66aa7f219f 100644
--- a/spec/routing/notifications_routing_spec.rb
+++ b/spec/routing/notifications_routing_spec.rb
@@ -4,15 +4,15 @@ require "spec_helper"
RSpec.describe "notifications routing" do
it "routes to #show" do
- expect(get("/profile/notifications")).to route_to("profiles/notifications#show")
+ expect(get("/-/profile/notifications")).to route_to("profiles/notifications#show")
end
it "routes to #update" do
- expect(put("/profile/notifications")).to route_to("profiles/notifications#update")
+ expect(put("/-/profile/notifications")).to route_to("profiles/notifications#update")
end
it 'routes to group #update' do
- expect(put("/profile/notifications/groups/gitlab-org")).to route_to("profiles/groups#update", id: 'gitlab-org')
- expect(put("/profile/notifications/groups/gitlab.org")).to route_to("profiles/groups#update", id: 'gitlab.org')
+ expect(put("/-/profile/notifications/groups/gitlab-org")).to route_to("profiles/groups#update", id: 'gitlab-org')
+ expect(put("/-/profile/notifications/groups/gitlab.org")).to route_to("profiles/groups#update", id: 'gitlab.org')
end
end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index a683dc28f4f..29e5c1b4bae 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -106,8 +106,8 @@ RSpec.describe 'project routing' do
let(:base_path) { '/gitlab/gitlabhq/-/wikis' }
end
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/wikis", "/gitlab/gitlabhq/-/wikis"
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/wikis/home/edit", "/gitlab/gitlabhq/-/wikis/home/edit"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/wikis", "/gitlab/gitlabhq/-/wikis"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/wikis/home/edit", "/gitlab/gitlabhq/-/wikis/home/edit"
end
# branches_project_repository GET /:project_id/repository/branches(.:format) projects/repositories#branches
@@ -171,7 +171,7 @@ RSpec.describe 'project routing' do
expect(delete('/gitlab/gitlabhq/-/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
end
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/tags", "/gitlab/gitlabhq/-/tags"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/tags", "/gitlab/gitlabhq/-/tags"
end
# project_deploy_keys GET /:project_id/deploy_keys(.:format) deploy_keys#index
@@ -259,8 +259,8 @@ RSpec.describe 'project routing' do
let(:base_path) { '/gitlab/gitlabhq/-/merge_requests' }
end
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/merge_requests", "/gitlab/gitlabhq/-/merge_requests"
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/merge_requests/1/diffs", "/gitlab/gitlabhq/-/merge_requests/1/diffs"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/merge_requests", "/gitlab/gitlabhq/-/merge_requests"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/merge_requests/1/diffs", "/gitlab/gitlabhq/-/merge_requests/1/diffs"
end
describe Projects::MergeRequests::CreationsController, 'routing' do
@@ -290,7 +290,7 @@ RSpec.describe 'project routing' do
expect(get('/gitlab/gitlabhq/-/merge_requests/new/diffs.json')).to route_to('projects/merge_requests/creations#diffs', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'json')
end
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/merge_requests/new", "/gitlab/gitlabhq/-/merge_requests/new"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/merge_requests/new", "/gitlab/gitlabhq/-/merge_requests/new"
end
describe Projects::MergeRequests::DiffsController, 'routing' do
@@ -454,8 +454,8 @@ RSpec.describe 'project routing' do
let(:base_path) { '/gitlab/gitlabhq/-/issues' }
end
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/issues", "/gitlab/gitlabhq/-/issues"
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/issues/1/edit", "/gitlab/gitlabhq/-/issues/1/edit"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/issues", "/gitlab/gitlabhq/-/issues"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/issues/1/edit", "/gitlab/gitlabhq/-/issues/1/edit"
end
# project_noteable_notes GET /:project_id/noteable/:target_type/:target_id/notes notes#index
@@ -769,25 +769,25 @@ RSpec.describe 'project routing' do
describe Projects::EnvironmentsController, 'routing' do
describe 'legacy routing' do
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/environments", "/gitlab/gitlabhq/-/environments"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/environments", "/gitlab/gitlabhq/-/environments"
end
end
describe Projects::ClustersController, 'routing' do
describe 'legacy routing' do
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/clusters", "/gitlab/gitlabhq/-/clusters"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/clusters", "/gitlab/gitlabhq/-/clusters"
end
end
describe Projects::ErrorTrackingController, 'routing' do
describe 'legacy routing' do
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/error_tracking", "/gitlab/gitlabhq/-/error_tracking"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/error_tracking", "/gitlab/gitlabhq/-/error_tracking"
end
end
describe Projects::Serverless, 'routing' do
describe 'legacy routing' do
- it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/serverless", "/gitlab/gitlabhq/-/serverless"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/serverless", "/gitlab/gitlabhq/-/serverless"
end
end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 26ad1f14786..7b9ba783885 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -122,111 +122,115 @@ RSpec.describe HelpController, "routing" do
end
end
-# profile_account GET /profile/account(.:format) profile#account
-# profile_history GET /profile/history(.:format) profile#history
-# profile_password PUT /profile/password(.:format) profile#password_update
-# profile_token GET /profile/token(.:format) profile#token
-# profile GET /profile(.:format) profile#show
-# profile_update PUT /profile/update(.:format) profile#update
+# profile_account GET /-/profile/account(.:format) profile#account
+# profile_history GET /-/profile/history(.:format) profile#history
+# profile_password PUT /-/profile/password(.:format) profile#password_update
+# profile_token GET /-/profile/token(.:format) profile#token
+# profile GET /-/profile(.:format) profile#show
+# profile_update PUT /-/profile/update(.:format) profile#update
RSpec.describe ProfilesController, "routing" do
it "to #account" do
- expect(get("/profile/account")).to route_to('profiles/accounts#show')
+ expect(get("/-/profile/account")).to route_to('profiles/accounts#show')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/account', '/-/profile/account'
it "to #audit_log" do
- expect(get("/profile/audit_log")).to route_to('profiles#audit_log')
+ expect(get("/-/profile/audit_log")).to route_to('profiles#audit_log')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/audit_log', '/-/profile/audit_log'
it "to #reset_feed_token" do
- expect(put("/profile/reset_feed_token")).to route_to('profiles#reset_feed_token')
+ expect(put("/-/profile/reset_feed_token")).to route_to('profiles#reset_feed_token')
end
it "to #show" do
- expect(get("/profile")).to route_to('profiles#show')
- end
-
- it 'to #show from scope routing' do
expect(get("/-/profile")).to route_to('profiles#show')
end
+ it_behaves_like 'redirecting a legacy path', '/profile', '/-/profile'
end
-# profile_preferences GET /profile/preferences(.:format) profiles/preferences#show
-# PATCH /profile/preferences(.:format) profiles/preferences#update
-# PUT /profile/preferences(.:format) profiles/preferences#update
+# profile_preferences GET /-/profile/preferences(.:format) profiles/preferences#show
+# PATCH /-/profile/preferences(.:format) profiles/preferences#update
+# PUT /-/profile/preferences(.:format) profiles/preferences#update
RSpec.describe Profiles::PreferencesController, 'routing' do
it 'to #show' do
- expect(get('/profile/preferences')).to route_to('profiles/preferences#show')
+ expect(get('/-/profile/preferences')).to route_to('profiles/preferences#show')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/preferences', '/-/profile/preferences'
it 'to #update' do
- expect(put('/profile/preferences')).to route_to('profiles/preferences#update')
- expect(patch('/profile/preferences')).to route_to('profiles/preferences#update')
+ expect(put('/-/profile/preferences')).to route_to('profiles/preferences#update')
+ expect(patch('/-/profile/preferences')).to route_to('profiles/preferences#update')
end
end
-# keys GET /keys(.:format) keys#index
-# POST /keys(.:format) keys#create
-# edit_key GET /keys/:id/edit(.:format) keys#edit
-# key GET /keys/:id(.:format) keys#show
-# PUT /keys/:id(.:format) keys#update
-# DELETE /keys/:id(.:format) keys#destroy
+# keys GET /-/profile/keys(.:format) keys#index
+# POST /-/profile/keys(.:format) keys#create
+# edit_key GET /-/profile/keys/:id/edit(.:format) keys#edit
+# key GET /-/profile/keys/:id(.:format) keys#show
+# PUT /-/profile/keys/:id(.:format) keys#update
+# DELETE /-/profile/keys/:id(.:format) keys#destroy
RSpec.describe Profiles::KeysController, "routing" do
it "to #index" do
- expect(get("/profile/keys")).to route_to('profiles/keys#index')
+ expect(get("/-/profile/keys")).to route_to('profiles/keys#index')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/keys', '/-/profile/keys'
it "to #create" do
- expect(post("/profile/keys")).to route_to('profiles/keys#create')
+ expect(post("/-/profile/keys")).to route_to('profiles/keys#create')
end
it "to #show" do
- expect(get("/profile/keys/1")).to route_to('profiles/keys#show', id: '1')
+ expect(get("/-/profile/keys/1")).to route_to('profiles/keys#show', id: '1')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/keys/1', '/-/profile/keys/1'
it "to #destroy" do
- expect(delete("/profile/keys/1")).to route_to('profiles/keys#destroy', id: '1')
+ expect(delete("/-/profile/keys/1")).to route_to('profiles/keys#destroy', id: '1')
end
end
-# keys GET /gpg_keys gpg_keys#index
-# key POST /gpg_keys gpg_keys#create
-# PUT /gpg_keys/:id gpg_keys#revoke
-# DELETE /gpg_keys/:id gpg_keys#desroy
+# keys GET /-/profile/gpg_keys gpg_keys#index
+# key POST /-/profile/gpg_keys gpg_keys#create
+# PUT /-/profile/gpg_keys/:id gpg_keys#revoke
+# DELETE /-/profile/gpg_keys/:id gpg_keys#desroy
RSpec.describe Profiles::GpgKeysController, "routing" do
it "to #index" do
- expect(get("/profile/gpg_keys")).to route_to('profiles/gpg_keys#index')
+ expect(get("/-/profile/gpg_keys")).to route_to('profiles/gpg_keys#index')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/gpg_keys', '/-/profile/gpg_keys'
it "to #create" do
- expect(post("/profile/gpg_keys")).to route_to('profiles/gpg_keys#create')
+ expect(post("/-/profile/gpg_keys")).to route_to('profiles/gpg_keys#create')
end
it "to #destroy" do
- expect(delete("/profile/gpg_keys/1")).to route_to('profiles/gpg_keys#destroy', id: '1')
+ expect(delete("/-/profile/gpg_keys/1")).to route_to('profiles/gpg_keys#destroy', id: '1')
end
end
-# emails GET /emails(.:format) emails#index
-# POST /keys(.:format) emails#create
-# DELETE /keys/:id(.:format) keys#destroy
+# emails GET /-/profile/emails(.:format) emails#index
+# POST /-/profile/emails(.:format) emails#create
+# DELETE /-/profile/emails/:id(.:format) keys#destroy
RSpec.describe Profiles::EmailsController, "routing" do
it "to #index" do
- expect(get("/profile/emails")).to route_to('profiles/emails#index')
+ expect(get("/-/profile/emails")).to route_to('profiles/emails#index')
end
+ it_behaves_like 'redirecting a legacy path', '/profile/emails', '/-/profile/emails'
it "to #create" do
- expect(post("/profile/emails")).to route_to('profiles/emails#create')
+ expect(post("/-/profile/emails")).to route_to('profiles/emails#create')
end
it "to #destroy" do
- expect(delete("/profile/emails/1")).to route_to('profiles/emails#destroy', id: '1')
+ expect(delete("/-/profile/emails/1")).to route_to('profiles/emails#destroy', id: '1')
end
end
-# profile_avatar DELETE /profile/avatar(.:format) profiles/avatars#destroy
+# profile_avatar DELETE /-/profile/avatar(.:format) profiles/avatars#destroy
RSpec.describe Profiles::AvatarsController, "routing" do
it "to #destroy" do
- expect(delete("/profile/avatar")).to route_to('profiles/avatars#destroy')
+ expect(delete("/-/profile/avatar")).to route_to('profiles/avatars#destroy')
end
end
diff --git a/spec/rubocop/cop/active_record_association_reload_spec.rb b/spec/rubocop/cop/active_record_association_reload_spec.rb
index e8d46064b49..8dbe6daeeca 100644
--- a/spec/rubocop/cop/active_record_association_reload_spec.rb
+++ b/spec/rubocop/cop/active_record_association_reload_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../rubocop/cop/active_record_association_reload'
-RSpec.describe RuboCop::Cop::ActiveRecordAssociationReload, type: :rubocop do
+RSpec.describe RuboCop::Cop::ActiveRecordAssociationReload do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/api/base_spec.rb b/spec/rubocop/cop/api/base_spec.rb
index 893bcf49627..de05ab93874 100644
--- a/spec/rubocop/cop/api/base_spec.rb
+++ b/spec/rubocop/cop/api/base_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/api/base'
-RSpec.describe RuboCop::Cop::API::Base, type: :rubocop do
+RSpec.describe RuboCop::Cop::API::Base do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/avoid_becomes_spec.rb b/spec/rubocop/cop/avoid_becomes_spec.rb
index 3e3e3abc27d..07cf374faf5 100644
--- a/spec/rubocop/cop/avoid_becomes_spec.rb
+++ b/spec/rubocop/cop/avoid_becomes_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/avoid_becomes'
-RSpec.describe RuboCop::Cop::AvoidBecomes, type: :rubocop do
+RSpec.describe RuboCop::Cop::AvoidBecomes do
include CopHelper
subject(:cop) { described_class.new }
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 4fb47e758bb..3c3aa5b7b5c 100644
--- a/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
+++ b/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../rubocop/cop/avoid_break_from_strong_memoize'
-RSpec.describe RuboCop::Cop::AvoidBreakFromStrongMemoize, type: :rubocop do
+RSpec.describe RuboCop::Cop::AvoidBreakFromStrongMemoize do
include CopHelper
subject(:cop) { described_class.new }
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 851493e004e..1e1fe851840 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
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers'
-RSpec.describe RuboCop::Cop::AvoidKeywordArgumentsInSidekiqWorkers, type: :rubocop do
+RSpec.describe RuboCop::Cop::AvoidKeywordArgumentsInSidekiqWorkers do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/avoid_return_from_blocks_spec.rb b/spec/rubocop/cop/avoid_return_from_blocks_spec.rb
index a157183646c..71311b9df7f 100644
--- a/spec/rubocop/cop/avoid_return_from_blocks_spec.rb
+++ b/spec/rubocop/cop/avoid_return_from_blocks_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../rubocop/cop/avoid_return_from_blocks'
-RSpec.describe RuboCop::Cop::AvoidReturnFromBlocks, type: :rubocop do
+RSpec.describe RuboCop::Cop::AvoidReturnFromBlocks do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/avoid_route_redirect_leading_slash_spec.rb b/spec/rubocop/cop/avoid_route_redirect_leading_slash_spec.rb
index 78bc859beda..9e13a5278e3 100644
--- a/spec/rubocop/cop/avoid_route_redirect_leading_slash_spec.rb
+++ b/spec/rubocop/cop/avoid_route_redirect_leading_slash_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../rubocop/cop/avoid_route_redirect_leading_slash'
-RSpec.describe RuboCop::Cop::AvoidRouteRedirectLeadingSlash, type: :rubocop do
+RSpec.describe RuboCop::Cop::AvoidRouteRedirectLeadingSlash do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/ban_catch_throw_spec.rb b/spec/rubocop/cop/ban_catch_throw_spec.rb
index 1d0ccb6d262..4f669bad4af 100644
--- a/spec/rubocop/cop/ban_catch_throw_spec.rb
+++ b/spec/rubocop/cop/ban_catch_throw_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/ban_catch_throw'
-RSpec.describe RuboCop::Cop::BanCatchThrow, type: :rubocop do
+RSpec.describe RuboCop::Cop::BanCatchThrow do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/code_reuse/finder_spec.rb b/spec/rubocop/cop/code_reuse/finder_spec.rb
index 1935d825b19..6f04d5e0d60 100644
--- a/spec/rubocop/cop/code_reuse/finder_spec.rb
+++ b/spec/rubocop/cop/code_reuse/finder_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/finder'
-RSpec.describe RuboCop::Cop::CodeReuse::Finder, type: :rubocop do
+RSpec.describe RuboCop::Cop::CodeReuse::Finder do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/code_reuse/presenter_spec.rb b/spec/rubocop/cop/code_reuse/presenter_spec.rb
index 1366018ec12..8efd4da8aa1 100644
--- a/spec/rubocop/cop/code_reuse/presenter_spec.rb
+++ b/spec/rubocop/cop/code_reuse/presenter_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/presenter'
-RSpec.describe RuboCop::Cop::CodeReuse::Presenter, type: :rubocop do
+RSpec.describe RuboCop::Cop::CodeReuse::Presenter do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/code_reuse/serializer_spec.rb b/spec/rubocop/cop/code_reuse/serializer_spec.rb
index d4341cc0367..74999df5859 100644
--- a/spec/rubocop/cop/code_reuse/serializer_spec.rb
+++ b/spec/rubocop/cop/code_reuse/serializer_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/serializer'
-RSpec.describe RuboCop::Cop::CodeReuse::Serializer, type: :rubocop do
+RSpec.describe RuboCop::Cop::CodeReuse::Serializer do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/code_reuse/service_class_spec.rb b/spec/rubocop/cop/code_reuse/service_class_spec.rb
index b018e743230..4870daf72dc 100644
--- a/spec/rubocop/cop/code_reuse/service_class_spec.rb
+++ b/spec/rubocop/cop/code_reuse/service_class_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/service_class'
-RSpec.describe RuboCop::Cop::CodeReuse::ServiceClass, type: :rubocop do
+RSpec.describe RuboCop::Cop::CodeReuse::ServiceClass do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/code_reuse/worker_spec.rb b/spec/rubocop/cop/code_reuse/worker_spec.rb
index 1f502e554c4..9e015f286d8 100644
--- a/spec/rubocop/cop/code_reuse/worker_spec.rb
+++ b/spec/rubocop/cop/code_reuse/worker_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/worker'
-RSpec.describe RuboCop::Cop::CodeReuse::Worker, type: :rubocop do
+RSpec.describe RuboCop::Cop::CodeReuse::Worker do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/default_scope_spec.rb b/spec/rubocop/cop/default_scope_spec.rb
index 617a7f63497..fee1895603c 100644
--- a/spec/rubocop/cop/default_scope_spec.rb
+++ b/spec/rubocop/cop/default_scope_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/default_scope'
-RSpec.describe RuboCop::Cop::DefaultScope, type: :rubocop do
+RSpec.describe RuboCop::Cop::DefaultScope do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/destroy_all_spec.rb b/spec/rubocop/cop/destroy_all_spec.rb
index 3220d44ea2b..df664724a91 100644
--- a/spec/rubocop/cop/destroy_all_spec.rb
+++ b/spec/rubocop/cop/destroy_all_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/destroy_all'
-RSpec.describe RuboCop::Cop::DestroyAll, type: :rubocop do
+RSpec.describe RuboCop::Cop::DestroyAll do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/filename_length_spec.rb b/spec/rubocop/cop/filename_length_spec.rb
index 381218c61ed..2411c8dbc7b 100644
--- a/spec/rubocop/cop/filename_length_spec.rb
+++ b/spec/rubocop/cop/filename_length_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/filename_length'
-RSpec.describe RuboCop::Cop::FilenameLength, type: :rubocop do
+RSpec.describe RuboCop::Cop::FilenameLength do
subject(:cop) { described_class.new }
it 'does not flag files with names 100 characters long' do
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 8341b0cab3a..2db03898e01 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
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/avoid_uploaded_file_from_params'
-RSpec.describe RuboCop::Cop::Gitlab::AvoidUploadedFileFromParams, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::AvoidUploadedFileFromParams do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
index d1236865897..ad7e685e505 100644
--- a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
+++ b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/bulk_insert'
-RSpec.describe RuboCop::Cop::Gitlab::BulkInsert, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::BulkInsert do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/change_timezone_spec.rb b/spec/rubocop/cop/gitlab/change_timezone_spec.rb
index 1ec5f28e811..6abbc06bb1a 100644
--- a/spec/rubocop/cop/gitlab/change_timezone_spec.rb
+++ b/spec/rubocop/cop/gitlab/change_timezone_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/change_timzone'
-RSpec.describe RuboCop::Cop::Gitlab::ChangeTimezone, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::ChangeTimezone do
include CopHelper
subject(:cop) { described_class.new }
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 97ed6b743f9..bed06ab2b17 100644
--- a/spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb
+++ b/spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/const_get_inherit_false'
-RSpec.describe RuboCop::Cop::Gitlab::ConstGetInheritFalse, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::ConstGetInheritFalse do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb b/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
index 1ed21e44290..5804b03b641 100644
--- a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
+++ b/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/gitlab/duplicate_spec_location'
-RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/except_spec.rb b/spec/rubocop/cop/gitlab/except_spec.rb
index 50277d15a57..173e5943da5 100644
--- a/spec/rubocop/cop/gitlab/except_spec.rb
+++ b/spec/rubocop/cop/gitlab/except_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/except'
-RSpec.describe RuboCop::Cop::Gitlab::Except, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::Except do
include CopHelper
subject(:cop) { described_class.new }
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 a47625d5dc1..db3bcf1dfdb 100644
--- a/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
+++ b/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/finder_with_find_by'
-RSpec.describe RuboCop::Cop::Gitlab::FinderWithFindBy, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::FinderWithFindBy do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/httparty_spec.rb b/spec/rubocop/cop/gitlab/httparty_spec.rb
index 379365096ba..b112ac84bff 100644
--- a/spec/rubocop/cop/gitlab/httparty_spec.rb
+++ b/spec/rubocop/cop/gitlab/httparty_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/httparty'
-RSpec.describe RuboCop::Cop::Gitlab::HTTParty, type: :rubocop do # rubocop:disable RSpec/FilePath
+RSpec.describe RuboCop::Cop::Gitlab::HTTParty do # rubocop:disable RSpec/FilePath
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/intersect_spec.rb b/spec/rubocop/cop/gitlab/intersect_spec.rb
index 351033d0ed2..e724f47029c 100644
--- a/spec/rubocop/cop/gitlab/intersect_spec.rb
+++ b/spec/rubocop/cop/gitlab/intersect_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/intersect'
-RSpec.describe RuboCop::Cop::Gitlab::Intersect, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::Intersect do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/json_spec.rb b/spec/rubocop/cop/gitlab/json_spec.rb
index 6f5ec07ffb1..fc25f69a244 100644
--- a/spec/rubocop/cop/gitlab/json_spec.rb
+++ b/spec/rubocop/cop/gitlab/json_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/json'
-RSpec.describe RuboCop::Cop::Gitlab::Json, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::Json do
include CopHelper
subject(:cop) { described_class.new }
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 3d22201c92e..1d09c720bf7 100644
--- a/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
+++ b/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/module_with_instance_variables'
-RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb b/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb
index 6221d038512..e6fb9ab9d57 100644
--- a/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb
+++ b/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/policy_rule_boolean'
-RSpec.describe RuboCop::Cop::Gitlab::PolicyRuleBoolean, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::PolicyRuleBoolean do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb b/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
index ebe984b189d..322c7c82968 100644
--- a/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
+++ b/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/predicate_memoization'
-RSpec.describe RuboCop::Cop::Gitlab::PredicateMemoization, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::PredicateMemoization do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/rails_logger_spec.rb b/spec/rubocop/cop/gitlab/rails_logger_spec.rb
index 70d208b31ec..768da243b02 100644
--- a/spec/rubocop/cop/gitlab/rails_logger_spec.rb
+++ b/spec/rubocop/cop/gitlab/rails_logger_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/rails_logger'
-RSpec.describe RuboCop::Cop::Gitlab::RailsLogger, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::RailsLogger do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/gitlab/union_spec.rb b/spec/rubocop/cop/gitlab/union_spec.rb
index 571dcc4eeb4..20364b1b901 100644
--- a/spec/rubocop/cop/gitlab/union_spec.rb
+++ b/spec/rubocop/cop/gitlab/union_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/union'
-RSpec.describe RuboCop::Cop::Gitlab::Union, type: :rubocop do
+RSpec.describe RuboCop::Cop::Gitlab::Union do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/graphql/authorize_types_spec.rb b/spec/rubocop/cop/graphql/authorize_types_spec.rb
index df637a26ec5..a1b7a3f3a9b 100644
--- a/spec/rubocop/cop/graphql/authorize_types_spec.rb
+++ b/spec/rubocop/cop/graphql/authorize_types_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/authorize_types'
-RSpec.describe RuboCop::Cop::Graphql::AuthorizeTypes, type: :rubocop do
+RSpec.describe RuboCop::Cop::Graphql::AuthorizeTypes do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/graphql/descriptions_spec.rb b/spec/rubocop/cop/graphql/descriptions_spec.rb
index f4693057bcb..b44205b0920 100644
--- a/spec/rubocop/cop/graphql/descriptions_spec.rb
+++ b/spec/rubocop/cop/graphql/descriptions_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/descriptions'
-RSpec.describe RuboCop::Cop::Graphql::Descriptions, type: :rubocop do
+RSpec.describe RuboCop::Cop::Graphql::Descriptions do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/graphql/gid_expected_type_spec.rb b/spec/rubocop/cop/graphql/gid_expected_type_spec.rb
index a81af2aea5d..8fd7ae03748 100644
--- a/spec/rubocop/cop/graphql/gid_expected_type_spec.rb
+++ b/spec/rubocop/cop/graphql/gid_expected_type_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/gid_expected_type'
-RSpec.describe RuboCop::Cop::Graphql::GIDExpectedType, type: :rubocop do
+RSpec.describe RuboCop::Cop::Graphql::GIDExpectedType do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/graphql/id_type_spec.rb b/spec/rubocop/cop/graphql/id_type_spec.rb
index 8767412e282..6135c9fef43 100644
--- a/spec/rubocop/cop/graphql/id_type_spec.rb
+++ b/spec/rubocop/cop/graphql/id_type_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/id_type'
-RSpec.describe RuboCop::Cop::Graphql::IDType, type: :rubocop do
+RSpec.describe RuboCop::Cop::Graphql::IDType do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/graphql/json_type_spec.rb b/spec/rubocop/cop/graphql/json_type_spec.rb
index ac25e0feb69..6d9f86e44d2 100644
--- a/spec/rubocop/cop/graphql/json_type_spec.rb
+++ b/spec/rubocop/cop/graphql/json_type_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/json_type'
-RSpec.describe RuboCop::Cop::Graphql::JSONType, type: :rubocop do
+RSpec.describe RuboCop::Cop::Graphql::JSONType do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/graphql/resolver_type_spec.rb b/spec/rubocop/cop/graphql/resolver_type_spec.rb
index 4807d66396a..25213e30528 100644
--- a/spec/rubocop/cop/graphql/resolver_type_spec.rb
+++ b/spec/rubocop/cop/graphql/resolver_type_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/resolver_type'
-RSpec.describe RuboCop::Cop::Graphql::ResolverType, type: :rubocop do
+RSpec.describe RuboCop::Cop::Graphql::ResolverType do
include CopHelper
subject(:cop) { described_class.new }
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 4e725deaafd..ac6c481a7c3 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
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/group_public_or_visible_to_user'
-RSpec.describe RuboCop::Cop::GroupPublicOrVisibleToUser, type: :rubocop do
+RSpec.describe RuboCop::Cop::GroupPublicOrVisibleToUser do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/ignored_columns_spec.rb b/spec/rubocop/cop/ignored_columns_spec.rb
index ec5499bbdff..38b4ac0bc1a 100644
--- a/spec/rubocop/cop/ignored_columns_spec.rb
+++ b/spec/rubocop/cop/ignored_columns_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/ignored_columns'
-RSpec.describe RuboCop::Cop::IgnoredColumns, type: :rubocop do
+RSpec.describe RuboCop::Cop::IgnoredColumns do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/include_sidekiq_worker_spec.rb b/spec/rubocop/cop/include_sidekiq_worker_spec.rb
index 33737babee5..f12652a1a58 100644
--- a/spec/rubocop/cop/include_sidekiq_worker_spec.rb
+++ b/spec/rubocop/cop/include_sidekiq_worker_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/include_sidekiq_worker'
-RSpec.describe RuboCop::Cop::IncludeSidekiqWorker, type: :rubocop do
+RSpec.describe RuboCop::Cop::IncludeSidekiqWorker do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
index 767ed994542..47247006e42 100644
--- a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
+++ b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/inject_enterprise_edition_module'
-RSpec.describe RuboCop::Cop::InjectEnterpriseEditionModule, type: :rubocop do
+RSpec.describe RuboCop::Cop::InjectEnterpriseEditionModule do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/lint/last_keyword_argument_spec.rb b/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
index 5822bf74e8d..826c681a880 100644
--- a/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
+++ b/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/lint/last_keyword_argument'
-RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument, type: :rubocop do
+RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument do
include CopHelper
subject(:cop) { described_class.new }
@@ -38,6 +38,8 @@ RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument, type: :rubocop do
- |
DEPRECATION WARNING: /Users/tkuah/code/ee-gdk/gitlab/create_service.rb:1: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/Users/tkuah/code/ee-gdk/gitlab/user.rb:17: warning: The called method `call' is defined here
+ - |
+ DEPRECATION WARNING: /Users/tkuah/code/ee-gdk/gitlab/other_warning_type.rb:1: warning: Some other warning type
YAML
end
@@ -62,7 +64,7 @@ RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument, type: :rubocop do
allow(File).to receive(:read).and_return(create_spec_yaml, projects_spec_yaml)
end
- it 'registers an offense' do
+ it 'registers an offense for last keyword warning' do
expect_offense(<<~SOURCE, 'create_service.rb')
users.call(params)
^^^^^^ Using the last argument as keyword parameters is deprecated
@@ -73,6 +75,12 @@ RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument, type: :rubocop do
SOURCE
end
+ it 'does not register an offense for other warning types' do
+ expect_no_offenses(<<~SOURCE, 'other_warning_type.rb')
+ users.call(params)
+ SOURCE
+ end
+
it 'registers an offense for the new method call' do
expect_offense(<<~SOURCE, 'projects_spec.rb')
Project.new(params)
@@ -95,6 +103,23 @@ RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument, type: :rubocop do
SOURCE
end
+ it 'registers an offense on the last non-block argument' do
+ expect_offense(<<~SOURCE, 'create_service.rb')
+ users.call(id, params, &block)
+ ^^^^^^ Using the last argument as keyword parameters is deprecated
+ SOURCE
+
+ expect_correction(<<~SOURCE)
+ users.call(id, **params, &block)
+ SOURCE
+ end
+
+ it 'does not register an offense if the only argument is a block argument' do
+ expect_no_offenses(<<~SOURCE, 'create_service.rb')
+ users.call(&block)
+ SOURCE
+ end
+
it 'registers an offense and corrects by converting splat to double splat' do
expect_offense(<<~SOURCE, 'create_service.rb')
users.call(id, *params)
diff --git a/spec/rubocop/cop/migration/add_column_with_default_spec.rb b/spec/rubocop/cop/migration/add_column_with_default_spec.rb
index 6deb092f235..cf476ae55d6 100644
--- a/spec/rubocop/cop/migration/add_column_with_default_spec.rb
+++ b/spec/rubocop/cop/migration/add_column_with_default_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_column_with_default'
-RSpec.describe RuboCop::Cop::Migration::AddColumnWithDefault, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddColumnWithDefault do
include CopHelper
let(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb b/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb
index 6ae4fb21126..92863c45b1a 100644
--- a/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb
+++ b/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_columns_to_wide_tables'
-RSpec.describe RuboCop::Cop::Migration::AddColumnsToWideTables, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddColumnsToWideTables do
include CopHelper
let(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb b/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb
index aaf191a1b6b..25350ad1ecb 100644
--- a/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb
+++ b/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_concurrent_foreign_key'
-RSpec.describe RuboCop::Cop::Migration::AddConcurrentForeignKey, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddConcurrentForeignKey do
include CopHelper
let(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/add_concurrent_index_spec.rb b/spec/rubocop/cop/migration/add_concurrent_index_spec.rb
index cef5295830c..351283a230a 100644
--- a/spec/rubocop/cop/migration/add_concurrent_index_spec.rb
+++ b/spec/rubocop/cop/migration/add_concurrent_index_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_concurrent_index'
-RSpec.describe RuboCop::Cop::Migration::AddConcurrentIndex, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddConcurrentIndex do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/add_index_spec.rb b/spec/rubocop/cop/migration/add_index_spec.rb
index 6bb78a7f3c7..1d083e9f2d2 100644
--- a/spec/rubocop/cop/migration/add_index_spec.rb
+++ b/spec/rubocop/cop/migration/add_index_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_index'
-RSpec.describe RuboCop::Cop::Migration::AddIndex, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddIndex do
include CopHelper
subject(:cop) { described_class.new }
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 0bea7bd7a0c..97b9d0d1ee2 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
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_limit_to_text_columns'
-RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/add_reference_spec.rb b/spec/rubocop/cop/migration/add_reference_spec.rb
index fab70d74b55..6e229d3eefc 100644
--- a/spec/rubocop/cop/migration/add_reference_spec.rb
+++ b/spec/rubocop/cop/migration/add_reference_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_reference'
-RSpec.describe RuboCop::Cop::Migration::AddReference, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddReference do
include CopHelper
let(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/add_timestamps_spec.rb b/spec/rubocop/cop/migration/add_timestamps_spec.rb
index c18b6b06ded..83570711ab9 100644
--- a/spec/rubocop/cop/migration/add_timestamps_spec.rb
+++ b/spec/rubocop/cop/migration/add_timestamps_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/add_timestamps'
-RSpec.describe RuboCop::Cop::Migration::AddTimestamps, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::AddTimestamps do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
index b769109057e..38ccf546b7c 100644
--- a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
+++ b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/complex_indexes_require_name'
-RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb b/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
index eaaa50b8190..2159bad1490 100644
--- a/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
+++ b/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/create_table_with_foreign_keys'
-RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys do
include CopHelper
let(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/datetime_spec.rb b/spec/rubocop/cop/migration/datetime_spec.rb
index c5f6fd503ec..a3cccae21e0 100644
--- a/spec/rubocop/cop/migration/datetime_spec.rb
+++ b/spec/rubocop/cop/migration/datetime_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/datetime'
-RSpec.describe RuboCop::Cop::Migration::Datetime, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::Datetime do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/drop_table_spec.rb b/spec/rubocop/cop/migration/drop_table_spec.rb
index 9ce5ee45b08..d783cb56203 100644
--- a/spec/rubocop/cop/migration/drop_table_spec.rb
+++ b/spec/rubocop/cop/migration/drop_table_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/drop_table'
-RSpec.describe RuboCop::Cop::Migration::DropTable, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::DropTable do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/hash_index_spec.rb b/spec/rubocop/cop/migration/hash_index_spec.rb
index 3d26ea41d08..15f68eb990f 100644
--- a/spec/rubocop/cop/migration/hash_index_spec.rb
+++ b/spec/rubocop/cop/migration/hash_index_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/hash_index'
-RSpec.describe RuboCop::Cop::Migration::HashIndex, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::HashIndex do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/prevent_strings_spec.rb b/spec/rubocop/cop/migration/prevent_strings_spec.rb
index 6882dca1926..560a485017a 100644
--- a/spec/rubocop/cop/migration/prevent_strings_spec.rb
+++ b/spec/rubocop/cop/migration/prevent_strings_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/prevent_strings'
-RSpec.describe RuboCop::Cop::Migration::PreventStrings, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::PreventStrings do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb b/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
index 76554d7446c..a25328a56a8 100644
--- a/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
+++ b/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/refer_to_index_by_name'
-RSpec.describe RuboCop::Cop::Migration::ReferToIndexByName, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::ReferToIndexByName do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/remove_column_spec.rb b/spec/rubocop/cop/migration/remove_column_spec.rb
index 7ef5556d8d7..4768093b10d 100644
--- a/spec/rubocop/cop/migration/remove_column_spec.rb
+++ b/spec/rubocop/cop/migration/remove_column_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/remove_column'
-RSpec.describe RuboCop::Cop::Migration::RemoveColumn, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::RemoveColumn do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb b/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb
index f70febb571d..8da368d588c 100644
--- a/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb
+++ b/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/remove_concurrent_index'
-RSpec.describe RuboCop::Cop::Migration::RemoveConcurrentIndex, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::RemoveConcurrentIndex do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/remove_index_spec.rb b/spec/rubocop/cop/migration/remove_index_spec.rb
index cc82306a0f5..274c907ac41 100644
--- a/spec/rubocop/cop/migration/remove_index_spec.rb
+++ b/spec/rubocop/cop/migration/remove_index_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/remove_index'
-RSpec.describe RuboCop::Cop::Migration::RemoveIndex, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::RemoveIndex do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/safer_boolean_column_spec.rb b/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
index 72b817fde12..aa7bb58ab45 100644
--- a/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
+++ b/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/safer_boolean_column'
-RSpec.describe RuboCop::Cop::Migration::SaferBooleanColumn, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::SaferBooleanColumn do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/timestamps_spec.rb b/spec/rubocop/cop/migration/timestamps_spec.rb
index 14b3cb36cf8..2f4154907d2 100644
--- a/spec/rubocop/cop/migration/timestamps_spec.rb
+++ b/spec/rubocop/cop/migration/timestamps_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/timestamps'
-RSpec.describe RuboCop::Cop::Migration::Timestamps, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::Timestamps do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
index 1d50d8c675e..8049cba12d0 100644
--- a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
+++ b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/migration/update_column_in_batches'
-RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches do
let(:cop) { described_class.new }
let(:tmp_rails_root) { rails_root_join('tmp', 'rails_root') }
let(:migration_code) do
diff --git a/spec/rubocop/cop/migration/with_lock_retries_disallowed_method_spec.rb b/spec/rubocop/cop/migration/with_lock_retries_disallowed_method_spec.rb
index 607daf0c9f0..814d87ea24b 100644
--- a/spec/rubocop/cop/migration/with_lock_retries_disallowed_method_spec.rb
+++ b/spec/rubocop/cop/migration/with_lock_retries_disallowed_method_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/with_lock_retries_disallowed_method'
-RSpec.describe RuboCop::Cop::Migration::WithLockRetriesDisallowedMethod, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::WithLockRetriesDisallowedMethod do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/migration/with_lock_retries_with_change_spec.rb b/spec/rubocop/cop/migration/with_lock_retries_with_change_spec.rb
index 93b96f3a20e..f0be14c8ee9 100644
--- a/spec/rubocop/cop/migration/with_lock_retries_with_change_spec.rb
+++ b/spec/rubocop/cop/migration/with_lock_retries_with_change_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/migration/with_lock_retries_with_change'
-RSpec.describe RuboCop::Cop::Migration::WithLockRetriesWithChange, type: :rubocop do
+RSpec.describe RuboCop::Cop::Migration::WithLockRetriesWithChange do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/performance/ar_count_each_spec.rb b/spec/rubocop/cop/performance/ar_count_each_spec.rb
index 33b667dd52f..6242c7a4c5e 100644
--- a/spec/rubocop/cop/performance/ar_count_each_spec.rb
+++ b/spec/rubocop/cop/performance/ar_count_each_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/performance/ar_count_each.rb'
-RSpec.describe RuboCop::Cop::Performance::ARCountEach, type: :rubocop do
+RSpec.describe RuboCop::Cop::Performance::ARCountEach do
include CopHelper
subject(:cop) { described_class.new }
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 972f3c52153..3321d400ae1 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
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/performance/ar_exists_and_present_blank.rb'
-RSpec.describe RuboCop::Cop::Performance::ARExistsAndPresentBlank, type: :rubocop do
+RSpec.describe RuboCop::Cop::Performance::ARExistsAndPresentBlank do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/performance/readlines_each_spec.rb b/spec/rubocop/cop/performance/readlines_each_spec.rb
index 2f222f1dc00..c19426606f6 100644
--- a/spec/rubocop/cop/performance/readlines_each_spec.rb
+++ b/spec/rubocop/cop/performance/readlines_each_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/performance/readlines_each'
-RSpec.describe RuboCop::Cop::Performance::ReadlinesEach, type: :rubocop do
+RSpec.describe RuboCop::Cop::Performance::ReadlinesEach do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/prefer_class_methods_over_module_spec.rb b/spec/rubocop/cop/prefer_class_methods_over_module_spec.rb
index bed8d331209..dc665f9dd25 100644
--- a/spec/rubocop/cop/prefer_class_methods_over_module_spec.rb
+++ b/spec/rubocop/cop/prefer_class_methods_over_module_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/prefer_class_methods_over_module'
-RSpec.describe RuboCop::Cop::PreferClassMethodsOverModule, type: :rubocop do
+RSpec.describe RuboCop::Cop::PreferClassMethodsOverModule do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/project_path_helper_spec.rb b/spec/rubocop/cop/project_path_helper_spec.rb
index 0e5b0b10ae6..78a590b89f6 100644
--- a/spec/rubocop/cop/project_path_helper_spec.rb
+++ b/spec/rubocop/cop/project_path_helper_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/project_path_helper'
-RSpec.describe RuboCop::Cop::ProjectPathHelper, type: :rubocop do
+RSpec.describe RuboCop::Cop::ProjectPathHelper do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/put_group_routes_under_scope_spec.rb b/spec/rubocop/cop/put_group_routes_under_scope_spec.rb
index 888d1b6a2ba..46b50d7690b 100644
--- a/spec/rubocop/cop/put_group_routes_under_scope_spec.rb
+++ b/spec/rubocop/cop/put_group_routes_under_scope_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../rubocop/cop/put_group_routes_under_scope'
-RSpec.describe RuboCop::Cop::PutGroupRoutesUnderScope, type: :rubocop do
+RSpec.describe RuboCop::Cop::PutGroupRoutesUnderScope do
include CopHelper
subject(:cop) { described_class.new }
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 eebb7f3eb61..b0627af0e8b 100644
--- a/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
+++ b/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../rubocop/cop/put_project_routes_under_scope'
-RSpec.describe RuboCop::Cop::PutProjectRoutesUnderScope, type: :rubocop do
+RSpec.describe RuboCop::Cop::PutProjectRoutesUnderScope do
include CopHelper
subject(:cop) { described_class.new }
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 484b5fad473..4876fcd5050 100644
--- a/spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb
+++ b/spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/qa/ambiguous_page_object_name'
-RSpec.describe RuboCop::Cop::QA::AmbiguousPageObjectName, type: :rubocop do
+RSpec.describe RuboCop::Cop::QA::AmbiguousPageObjectName do
include CopHelper
let(:source_file) { 'qa/page.rb' }
diff --git a/spec/rubocop/cop/qa/element_with_pattern_spec.rb b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
index 0e599701531..6289b1a7c97 100644
--- a/spec/rubocop/cop/qa/element_with_pattern_spec.rb
+++ b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/qa/element_with_pattern'
-RSpec.describe RuboCop::Cop::QA::ElementWithPattern, type: :rubocop do
+RSpec.describe RuboCop::Cop::QA::ElementWithPattern do
include CopHelper
let(:source_file) { 'qa/page.rb' }
diff --git a/spec/rubocop/cop/rspec/any_instance_of_spec.rb b/spec/rubocop/cop/rspec/any_instance_of_spec.rb
index 971e28853a3..42bb7d196a1 100644
--- a/spec/rubocop/cop/rspec/any_instance_of_spec.rb
+++ b/spec/rubocop/cop/rspec/any_instance_of_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/rspec/any_instance_of'
-RSpec.describe RuboCop::Cop::RSpec::AnyInstanceOf, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::AnyInstanceOf do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/rspec/be_success_matcher_spec.rb b/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
index b14cf39cbde..d49507c89b1 100644
--- a/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
+++ b/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/be_success_matcher'
-RSpec.describe RuboCop::Cop::RSpec::BeSuccessMatcher, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::BeSuccessMatcher do
include CopHelper
let(:source_file) { 'spec/foo_spec.rb' }
diff --git a/spec/rubocop/cop/rspec/env_assignment_spec.rb b/spec/rubocop/cop/rspec/env_assignment_spec.rb
index 72ad584dd6f..07afd30fc90 100644
--- a/spec/rubocop/cop/rspec/env_assignment_spec.rb
+++ b/spec/rubocop/cop/rspec/env_assignment_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/rspec/env_assignment'
-RSpec.describe RuboCop::Cop::RSpec::EnvAssignment, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::EnvAssignment do
include CopHelper
offense_call_single_quotes_key = %(ENV['FOO'] = 'bar').freeze
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 1bb93402a5b..fe9cea47a43 100644
--- a/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
+++ b/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/rspec/factories_in_migration_specs'
-RSpec.describe RuboCop::Cop::RSpec::FactoriesInMigrationSpecs, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::FactoriesInMigrationSpecs do
include CopHelper
subject(:cop) { described_class.new }
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 70dbe086127..33fdaaee3c7 100644
--- a/spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb
+++ b/spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb
@@ -6,7 +6,7 @@ require 'rubocop'
require_relative '../../../../../rubocop/cop/rspec/factory_bot/inline_association'
-RSpec.describe RuboCop::Cop::RSpec::FactoryBot::InlineAssociation, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::FactoryBot::InlineAssociation do
include CopHelper
subject(:cop) { described_class.new }
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 8c3703a488a..6e9e436602c 100644
--- a/spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb
+++ b/spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/rspec/httparty_basic_auth'
-RSpec.describe RuboCop::Cop::RSpec::HTTPartyBasicAuth, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::HTTPartyBasicAuth do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb b/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb
index ca47bba4264..d9e3ca5741c 100644
--- a/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb
+++ b/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/modify_sidekiq_middleware'
-RSpec.describe RuboCop::Cop::RSpec::ModifySidekiqMiddleware, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::ModifySidekiqMiddleware do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/rspec/timecop_freeze_spec.rb b/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
index 3809431a2fc..b1cf82492e4 100644
--- a/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
+++ b/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/rspec/timecop_freeze'
-RSpec.describe RuboCop::Cop::RSpec::TimecopFreeze, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::TimecopFreeze do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/rspec/timecop_travel_spec.rb b/spec/rubocop/cop/rspec/timecop_travel_spec.rb
index 25a8127d40e..2ee8bfe9ad7 100644
--- a/spec/rubocop/cop/rspec/timecop_travel_spec.rb
+++ b/spec/rubocop/cop/rspec/timecop_travel_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/rspec/timecop_travel'
-RSpec.describe RuboCop::Cop::RSpec::TimecopTravel, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::TimecopTravel do
include CopHelper
subject(:cop) { described_class.new }
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 92a76bde243..4936936836d 100644
--- a/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
+++ b/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/top_level_describe_path'
-RSpec.describe RuboCop::Cop::RSpec::TopLevelDescribePath, type: :rubocop do
+RSpec.describe RuboCop::Cop::RSpec::TopLevelDescribePath do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/rspec/web_mock_enable_spec.rb b/spec/rubocop/cop/rspec/web_mock_enable_spec.rb
new file mode 100644
index 00000000000..61a85064a61
--- /dev/null
+++ b/spec/rubocop/cop/rspec/web_mock_enable_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/rspec/web_mock_enable'
+
+RSpec.describe RuboCop::Cop::RSpec::WebMockEnable do
+ subject(:cop) { described_class.new }
+
+ context 'when calling WebMock.disable_net_connect!' do
+ it 'registers an offence and autocorrects it' do
+ expect_offense(<<~RUBY)
+ WebMock.disable_net_connect!(allow_localhost: true)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use webmock_enable! instead of calling WebMock.disable_net_connect! directly.
+ RUBY
+
+ expect_correction(<<~RUBY)
+ webmock_enable!
+ RUBY
+ end
+ end
+end
diff --git a/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb b/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb
index 938ddc7fb6a..a6a44b3fa68 100644
--- a/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb
+++ b/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb
@@ -9,7 +9,7 @@ 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, type: :rubocop do
+RSpec.describe RuboCop::Cop::RubyInterpolationInTranslation do
subject(:cop) { described_class.new }
it 'does not add an offence for a regular messages' do
diff --git a/spec/rubocop/cop/safe_params_spec.rb b/spec/rubocop/cop/safe_params_spec.rb
index c4f683a41bf..c8f6768c4bb 100644
--- a/spec/rubocop/cop/safe_params_spec.rb
+++ b/spec/rubocop/cop/safe_params_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/safe_params'
-RSpec.describe RuboCop::Cop::SafeParams, type: :rubocop do
+RSpec.describe RuboCop::Cop::SafeParams do
include CopHelper
subject(:cop) { described_class.new }
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 48964ab76e0..6e526f7ad8f 100644
--- a/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
+++ b/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/bulk_perform_with_context'
-RSpec.describe RuboCop::Cop::Scalability::BulkPerformWithContext, type: :rubocop do
+RSpec.describe RuboCop::Cop::Scalability::BulkPerformWithContext do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/scalability/cron_worker_context_spec.rb b/spec/rubocop/cop/scalability/cron_worker_context_spec.rb
index 4b4ee7258f1..4699e06e9cf 100644
--- a/spec/rubocop/cop/scalability/cron_worker_context_spec.rb
+++ b/spec/rubocop/cop/scalability/cron_worker_context_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/cron_worker_context'
-RSpec.describe RuboCop::Cop::Scalability::CronWorkerContext, type: :rubocop do
+RSpec.describe RuboCop::Cop::Scalability::CronWorkerContext do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/scalability/file_uploads_spec.rb b/spec/rubocop/cop/scalability/file_uploads_spec.rb
index ed826728681..78ff7fea55c 100644
--- a/spec/rubocop/cop/scalability/file_uploads_spec.rb
+++ b/spec/rubocop/cop/scalability/file_uploads_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/file_uploads'
-RSpec.describe RuboCop::Cop::Scalability::FileUploads, type: :rubocop do
+RSpec.describe RuboCop::Cop::Scalability::FileUploads do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/scalability/idempotent_worker_spec.rb b/spec/rubocop/cop/scalability/idempotent_worker_spec.rb
index 9197cc954f5..666122a9de4 100644
--- a/spec/rubocop/cop/scalability/idempotent_worker_spec.rb
+++ b/spec/rubocop/cop/scalability/idempotent_worker_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/idempotent_worker'
-RSpec.describe RuboCop::Cop::Scalability::IdempotentWorker, type: :rubocop do
+RSpec.describe RuboCop::Cop::Scalability::IdempotentWorker do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/sidekiq_options_queue_spec.rb b/spec/rubocop/cop/sidekiq_options_queue_spec.rb
index e76265d426c..306cbcf62b5 100644
--- a/spec/rubocop/cop/sidekiq_options_queue_spec.rb
+++ b/spec/rubocop/cop/sidekiq_options_queue_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/sidekiq_options_queue'
-RSpec.describe RuboCop::Cop::SidekiqOptionsQueue, type: :rubocop do
+RSpec.describe RuboCop::Cop::SidekiqOptionsQueue do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/static_translation_definition_spec.rb b/spec/rubocop/cop/static_translation_definition_spec.rb
index f3185def3d7..8a38a318999 100644
--- a/spec/rubocop/cop/static_translation_definition_spec.rb
+++ b/spec/rubocop/cop/static_translation_definition_spec.rb
@@ -7,7 +7,7 @@ require 'rspec-parameterized'
require_relative '../../../rubocop/cop/static_translation_definition'
-RSpec.describe RuboCop::Cop::StaticTranslationDefinition, type: :rubocop do
+RSpec.describe RuboCop::Cop::StaticTranslationDefinition do
include CopHelper
using RSpec::Parameterized::TableSyntax
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 8b6a2eac349..1c90df798a5 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
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/usage_data/distinct_count_by_large_foreign_key'
-RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :rubocop do
+RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey do
include CopHelper
let(:allowed_foreign_keys) { [:author_id, :user_id, :'merge_requests.target_project_id'] }
diff --git a/spec/rubocop/cop/usage_data/large_table_spec.rb b/spec/rubocop/cop/usage_data/large_table_spec.rb
index de6fb9c17e2..638e8c67dc8 100644
--- a/spec/rubocop/cop/usage_data/large_table_spec.rb
+++ b/spec/rubocop/cop/usage_data/large_table_spec.rb
@@ -7,7 +7,7 @@ require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/usage_data/large_table'
-RSpec.describe RuboCop::Cop::UsageData::LargeTable, type: :rubocop do
+RSpec.describe RuboCop::Cop::UsageData::LargeTable do
include CopHelper
let(:large_tables) { %i[Rails Time] }
diff --git a/spec/rubocop/qa_helpers_spec.rb b/spec/rubocop/qa_helpers_spec.rb
index 786b9c78952..051817903a8 100644
--- a/spec/rubocop/qa_helpers_spec.rb
+++ b/spec/rubocop/qa_helpers_spec.rb
@@ -5,7 +5,7 @@ require 'rubocop'
require 'parser/current'
require_relative '../../rubocop/qa_helpers'
-RSpec.describe RuboCop::QAHelpers, type: :rubocop do
+RSpec.describe RuboCop::QAHelpers do
def parse_source(source, path = 'foo.rb')
buffer = Parser::Source::Buffer.new(path)
buffer.source = source
diff --git a/spec/serializers/analytics_stage_serializer_spec.rb b/spec/serializers/analytics_stage_serializer_spec.rb
deleted file mode 100644
index 0f2de262188..00000000000
--- a/spec/serializers/analytics_stage_serializer_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AnalyticsStageSerializer do
- subject do
- described_class.new.represent(resource)
- end
-
- let(:resource) do
- Gitlab::CycleAnalytics::CodeStage.new(options: { project: double })
- end
-
- before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(1.12)
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseEventFetcher).to receive(:event_result).and_return({})
- end
-
- it 'generates payload for single object' do
- expect(subject).to be_kind_of Hash
- end
-
- it 'contains important elements of AnalyticsStage' do
- expect(subject).to include(:title, :description, :value)
- end
-
- context 'when median is equal 0' do
- before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(0)
- end
-
- it 'sets the value to nil' do
- expect(subject.fetch(:value)).to be_nil
- end
- end
-
- context 'when median is below 1' do
- before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(0.12)
- end
-
- it 'sets the value to equal to median' do
- expect(subject.fetch(:value)).to eq('less than a minute')
- end
- end
-
- context 'when median is above 1' do
- before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(60.12)
- end
-
- it 'sets the value to equal to median' do
- expect(subject.fetch(:value)).to eq('1 minute')
- end
- end
-end
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index 5d29452e91c..4a58f341658 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -5,14 +5,13 @@ require 'spec_helper'
RSpec.describe BuildDetailsEntity do
include ProjectForksHelper
- let_it_be(:user) { create(:admin) }
-
it 'inherits from JobEntity' do
expect(described_class).to be < JobEntity
end
describe '#as_json' do
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, :failed, pipeline: pipeline) }
let(:request) { double('request', project: project) }
@@ -66,6 +65,7 @@ RSpec.describe BuildDetailsEntity do
before do
allow(build).to receive(:merge_request).and_return(merge_request)
+ forked_project.add_developer(user)
end
let(:merge_request) do
@@ -186,7 +186,7 @@ RSpec.describe BuildDetailsEntity do
end
context 'when the build has expired artifacts' do
- let!(:build) { create(:ci_build, :artifacts, artifacts_expire_at: 7.days.ago) }
+ let!(:build) { create(:ci_build, :artifacts, pipeline: pipeline, artifacts_expire_at: 7.days.ago) }
context 'when pipeline is unlocked' do
before do
@@ -218,12 +218,43 @@ RSpec.describe BuildDetailsEntity do
end
context 'when the build has archive type artifacts' do
- let!(:build) { create(:ci_build, :artifacts, artifacts_expire_at: 7.days.from_now) }
+ let!(:build) { create(:ci_build, :artifacts, pipeline: pipeline, artifacts_expire_at: 7.days.from_now) }
let!(:report) { create(:ci_job_artifact, :codequality, job: build) }
it 'exposes artifact details' do
expect(subject[:artifact].keys).to include(:download_path, :browse_path, :keep_path, :expire_at, :expired, :locked)
end
end
+
+ context 'when the project is public and the user is a guest' do
+ let(:project) { create(:project, :repository, :public) }
+ let(:user) { create(:project_member, :guest, project: project).user }
+
+ context 'when the build has public archive type artifacts' do
+ let(:build) { create(:ci_build, :artifacts) }
+
+ it 'exposes public artifact details' do
+ expect(subject[:artifact].keys).to include(:download_path, :browse_path, :locked)
+ end
+ end
+
+ context 'when the build has non public archive type artifacts' do
+ let(:build) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
+
+ it 'does not expose non public artifacts' do
+ expect(subject.keys).not_to include(:artifact)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ it 'exposes artifact details' do
+ expect(subject[:artifact].keys).to include(:download_path, :browse_path, :locked)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/serializers/deploy_key_entity_spec.rb b/spec/serializers/deploy_key_entity_spec.rb
index 3404d27a23c..e8d9701be67 100644
--- a/spec/serializers/deploy_key_entity_spec.rb
+++ b/spec/serializers/deploy_key_entity_spec.rb
@@ -52,7 +52,13 @@ RSpec.describe DeployKeyEntity do
context 'user is an admin' do
let(:user) { create(:user, :admin) }
- it { expect(entity.as_json).to include(can_edit: true) }
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { expect(entity.as_json).to include(can_edit: true) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { expect(entity.as_json).not_to include(can_edit: true) }
+ end
end
context 'user is a project maintainer' do
diff --git a/spec/serializers/diffs_metadata_entity_spec.rb b/spec/serializers/diffs_metadata_entity_spec.rb
index e8cbc2076d7..f6993d4652e 100644
--- a/spec/serializers/diffs_metadata_entity_spec.rb
+++ b/spec/serializers/diffs_metadata_entity_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe DiffsMetadataEntity do
:merge_request_diffs, :context_commits,
:definition_path_prefix, :source_branch_exists,
:can_merge, :conflict_resolution_path, :has_conflicts,
+ :project_name, :project_path, :user_full_name, :username,
# Attributes
:diff_files
)
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index 5b83507b4ec..a6101f825e9 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe EnvironmentEntity do
+ include KubernetesHelpers
include Gitlab::Routing.url_helpers
- let(:request) { double('request') }
+ let(:request) { double('request', current_user: user, project: project) }
let(:entity) do
described_class.new(environment, request: request)
end
@@ -167,4 +168,23 @@ RSpec.describe EnvironmentEntity do
end
end
end
+
+ context 'with deployment service ready' do
+ before do
+ allow(environment).to receive(:has_terminals?).and_return(true)
+ allow(environment).to receive(:rollout_status).and_return(kube_deployment_rollout_status)
+ end
+
+ it 'exposes rollout_status' do
+ expect(subject).to include(:rollout_status)
+ end
+ end
+
+ context 'with deployment service not ready' do
+ let(:user) { create(:user) }
+
+ it 'does not expose rollout_status' do
+ expect(subject).not_to include(:rollout_status)
+ end
+ end
end
diff --git a/spec/serializers/member_entity_spec.rb b/spec/serializers/member_entity_spec.rb
new file mode 100644
index 00000000000..f34434188c1
--- /dev/null
+++ b/spec/serializers/member_entity_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+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_hash) { entity.as_json }
+
+ shared_examples 'member.json' do
+ it 'matches json schema' do
+ expect(entity.to_json).to match_schema('entities/member')
+ end
+
+ it 'correctly exposes `can_update`' do
+ allow(member).to receive(:can_update?).and_return(true)
+
+ expect(entity_hash[:can_update]).to be(true)
+ end
+
+ it 'correctly exposes `can_remove`' do
+ allow(member).to receive(:can_remove?).and_return(true)
+
+ expect(entity_hash[:can_remove]).to be(true)
+ end
+ end
+
+ shared_examples 'invite' do
+ it 'correctly exposes `invite.avatar_url`' do
+ avatar_url = 'https://www.gravatar.com/avatar/c4637cb869d5f94c3193bde4f23d4cdc?s=80&d=identicon'
+ allow(entity).to receive(:avatar_icon_for_email).with(member.invite_email, Member::AVATAR_SIZE).and_return(avatar_url)
+
+ expect(entity_hash[:invite][:avatar_url]).to match(avatar_url)
+ end
+
+ it 'correctly exposes `invite.can_resend`' do
+ allow(member).to receive(:can_resend_invite?).and_return(true)
+
+ expect(entity_hash[:invite][:can_resend]).to be(true)
+ end
+ end
+
+ context 'group member' do
+ let(:group) { create(:group) }
+ let(:member) { GroupMemberPresenter.new(create(:group_member, group: group), current_user: current_user) }
+
+ it_behaves_like 'member.json'
+
+ context 'invite' do
+ let(:member) { GroupMemberPresenter.new(create(:group_member, :invited, group: group), current_user: current_user) }
+
+ it_behaves_like 'member.json'
+ it_behaves_like 'invite'
+ end
+ end
+
+ context 'project member' do
+ let(:project) { create(:project) }
+ let(:group) { project.group }
+ let(:member) { ProjectMemberPresenter.new(create(:project_member, project: project), current_user: current_user) }
+
+ it_behaves_like 'member.json'
+
+ context 'invite' do
+ let(:member) { ProjectMemberPresenter.new(create(:project_member, :invited, project: project), current_user: current_user) }
+
+ it_behaves_like 'member.json'
+ it_behaves_like 'invite'
+ end
+ end
+end
diff --git a/spec/serializers/member_serializer_spec.rb b/spec/serializers/member_serializer_spec.rb
new file mode 100644
index 00000000000..d3ec45fe9c4
--- /dev/null
+++ b/spec/serializers/member_serializer_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MemberSerializer do
+ include MembersPresentation
+
+ let_it_be(:current_user) { create(:user) }
+
+ subject { described_class.new.represent(members, { current_user: current_user, group: group }) }
+
+ shared_examples 'members.json' do
+ it 'matches json schema' do
+ expect(subject.to_json).to match_schema('members')
+ end
+ end
+
+ context 'group member' do
+ let(:group) { create(:group) }
+ let(:members) { present_members(create_list(:group_member, 1, group: group)) }
+
+ it_behaves_like 'members.json'
+ end
+
+ context 'project member' do
+ let(:project) { create(:project) }
+ let(:group) { project.group }
+ let(:members) { present_members(create_list(:project_member, 1, project: project)) }
+
+ it_behaves_like 'members.json'
+ end
+end
diff --git a/spec/serializers/member_user_entity_spec.rb b/spec/serializers/member_user_entity_spec.rb
new file mode 100644
index 00000000000..1c000c06bb6
--- /dev/null
+++ b/spec/serializers/member_user_entity_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MemberUserEntity do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:emoji) { 'slight_smile' }
+ let_it_be(:user_status) { create(:user_status, user: user, emoji: emoji) }
+ let(:entity) { described_class.new(user) }
+ let(:entity_hash) { entity.as_json }
+
+ it 'matches json schema' do
+ expect(entity.to_json).to match_schema('entities/member_user')
+ end
+
+ it 'correctly exposes `avatar_url`' do
+ avatar_url = 'https://www.gravatar.com/avatar/c4637cb869d5f94c3193bde4f23d4cdc?s=80&d=identicon'
+ allow(user).to receive(:avatar_url).and_return(avatar_url)
+
+ expect(entity_hash[:avatar_url]).to match(avatar_url)
+ end
+
+ it 'correctly exposes `blocked`' do
+ allow(user).to receive(:blocked?).and_return(true)
+
+ expect(entity_hash[:blocked]).to be(true)
+ end
+
+ it 'correctly exposes `two_factor_enabled`' do
+ allow(user).to receive(:two_factor_enabled?).and_return(true)
+
+ expect(entity_hash[:two_factor_enabled]).to be(true)
+ end
+
+ it 'correctly exposes `status.emoji`' do
+ expect(entity_hash[:status][:emoji]).to match(emoji)
+ end
+end
diff --git a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
index 031dc729a79..8c72430ff5c 100644
--- a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
let_it_be(:project, refind: true) { create :project, :repository }
let_it_be(:resource, refind: true) { create(:merge_request, source_project: project, target_project: project) }
let_it_be(:user) { create(:user) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:request) { double('request', current_user: user, project: project) }
@@ -25,6 +26,17 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
expect(subject[:merge_status]).to eq 'checking'
end
+ it 'has blob path data' do
+ allow(resource).to receive_messages(
+ base_pipeline: pipeline,
+ head_pipeline: pipeline
+ )
+
+ expect(subject).to include(:blob_path)
+ expect(subject[:blob_path]).to include(:base_path)
+ expect(subject[:blob_path]).to include(:head_path)
+ end
+
describe 'diverged_commits_count' do
context 'when MR open and its diverging' do
it 'returns diverged commits count' do
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 9f734c08ef4..42d843af596 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -76,17 +76,6 @@ RSpec.describe MergeRequestWidgetEntity do
.to eq("/#{resource.project.full_path}/-/merge_requests/#{resource.iid}.diff")
end
- it 'has blob path data' do
- allow(resource).to receive_messages(
- base_pipeline: pipeline,
- head_pipeline: pipeline
- )
-
- expect(subject).to include(:blob_path)
- expect(subject[:blob_path]).to include(:base_path)
- expect(subject[:blob_path]).to include(:head_path)
- end
-
describe 'codequality report artifacts', :request_store do
let(:merge_base_pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
diff --git a/spec/serializers/merge_requests/pipeline_entity_spec.rb b/spec/serializers/merge_requests/pipeline_entity_spec.rb
index 8685d4bb846..b91d5e7679f 100644
--- a/spec/serializers/merge_requests/pipeline_entity_spec.rb
+++ b/spec/serializers/merge_requests/pipeline_entity_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe MergeRequests::PipelineEntity do
)
expect(subject[:commit]).to include(:short_id, :commit_path)
expect(subject[:ref]).to include(:branch)
- expect(subject[:details]).to include(:name, :status, :stages)
+ expect(subject[:details]).to include(:artifacts, :name, :status, :stages)
expect(subject[:details][:status]).to include(:icon, :favicon, :text, :label, :tooltip)
expect(subject[:flags]).to include(:merge_request_pipeline)
end
@@ -42,4 +42,6 @@ RSpec.describe MergeRequests::PipelineEntity do
expect(entity.as_json).not_to include(:coverage)
end
end
+
+ it_behaves_like 'public artifacts'
end
diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb
index 1357836cb89..74e91cc9cdd 100644
--- a/spec/serializers/pipeline_details_entity_spec.rb
+++ b/spec/serializers/pipeline_details_entity_spec.rb
@@ -183,5 +183,7 @@ RSpec.describe PipelineDetailsEntity do
expect(source_jobs[child_pipeline.id][:name]).to eq('child')
end
end
+
+ it_behaves_like 'public artifacts'
end
end
diff --git a/spec/serializers/runner_entity_spec.rb b/spec/serializers/runner_entity_spec.rb
index 84c7d1720e2..e864b52c0f2 100644
--- a/spec/serializers/runner_entity_spec.rb
+++ b/spec/serializers/runner_entity_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe RunnerEntity do
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:entity) { described_class.new(runner, request: request, current_user: user) }
let(:request) { double('request') }
- let(:user) { create(:admin) }
+ let(:user) { project.owner }
before do
allow(request).to receive(:current_user).and_return(user)
diff --git a/spec/services/alert_management/alerts/todo/create_service_spec.rb b/spec/services/alert_management/alerts/todo/create_service_spec.rb
index e3d9de8b4df..fa4fd8ed0b2 100644
--- a/spec/services/alert_management/alerts/todo/create_service_spec.rb
+++ b/spec/services/alert_management/alerts/todo/create_service_spec.rb
@@ -58,6 +58,10 @@ RSpec.describe AlertManagement::Alerts::Todo::CreateService do
create(:todo, :pending, **todo_params)
end
+ before do
+ stub_feature_flags(multiple_todos: false)
+ end
+
it 'does not create a todo' do
expect { result }.not_to change { Todo.count }
end
diff --git a/spec/services/alert_management/sync_alert_service_data_service_spec.rb b/spec/services/alert_management/sync_alert_service_data_service_spec.rb
deleted file mode 100644
index ecec60011db..00000000000
--- a/spec/services/alert_management/sync_alert_service_data_service_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AlertManagement::SyncAlertServiceDataService do
- let_it_be(:alerts_service) do
- AlertsService.skip_callback(:save, :after, :update_http_integration)
- service = create(:alerts_service, :active)
- AlertsService.set_callback(:save, :after, :update_http_integration)
-
- service
- end
-
- describe '#execute' do
- subject(:execute) { described_class.new(alerts_service).execute }
-
- context 'without http integration' do
- it 'creates the integration' do
- expect { execute }
- .to change { AlertManagement::HttpIntegration.count }.by(1)
- end
-
- it 'returns a success' do
- expect(subject.success?).to eq(true)
- end
- end
-
- context 'existing legacy http integration' do
- let_it_be(:integration) { create(:alert_management_http_integration, :legacy, project: alerts_service.project) }
-
- it 'updates the integration' do
- expect { execute }
- .to change { integration.reload.encrypted_token }.to(alerts_service.data.encrypted_token)
- .and change { integration.encrypted_token_iv }.to(alerts_service.data.encrypted_token_iv)
- end
-
- it 'returns a success' do
- expect(subject.success?).to eq(true)
- end
- end
-
- context 'existing other http integration' do
- let_it_be(:integration) { create(:alert_management_http_integration, project: alerts_service.project) }
-
- it 'creates the integration' do
- expect { execute }
- .to change { AlertManagement::HttpIntegration.count }.by(1)
- end
-
- it 'returns a success' do
- expect(subject.success?).to eq(true)
- end
- end
- end
-end
diff --git a/spec/services/ci/build_report_result_service_spec.rb b/spec/services/ci/build_report_result_service_spec.rb
index 244ffbf4bbd..7c2702af086 100644
--- a/spec/services/ci/build_report_result_service_spec.rb
+++ b/spec/services/ci/build_report_result_service_spec.rb
@@ -6,12 +6,6 @@ RSpec.describe Ci::BuildReportResultService do
describe '#execute', :clean_gitlab_redis_shared_state do
subject(:build_report_result) { described_class.new.execute(build) }
- around do |example|
- travel_to(DateTime.parse('2020-07-01')) do
- example.run
- end
- end
-
context 'when build is finished' do
let(:build) { create(:ci_build, :success, :test_reports) }
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 03cea4074bf..860932d4fde 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -371,6 +371,26 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
expect { service.execute(bridge) }.to change { Ci::Pipeline.count }.by(1)
end
end
+
+ context 'when downstream project does not allow user-defined variables for child pipelines' do
+ before do
+ bridge.yaml_variables = [{ key: 'BRIDGE', value: '$PIPELINE_VARIABLE-var', public: true }]
+
+ upstream_pipeline.project.update!(restrict_user_defined_variables: true)
+ end
+
+ it 'creates a new pipeline allowing variables to be passed downstream' do
+ expect { service.execute(bridge) }.to change { Ci::Pipeline.count }.by(1)
+ end
+
+ it 'passes variables downstream from the bridge' do
+ pipeline = service.execute(bridge)
+
+ pipeline.variables.map(&:key).tap do |variables|
+ expect(variables).to include 'BRIDGE'
+ end
+ end
+ end
end
end
@@ -460,6 +480,33 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
expect(variable.value).to eq 'my-value-var'
end
end
+
+ context 'when downstream project does not allow user-defined variables for multi-project pipelines' do
+ before do
+ downstream_project.update!(restrict_user_defined_variables: true)
+ end
+
+ it 'does not create a new pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+ end
+
+ it 'ignores variables passed downstream from the bridge' do
+ pipeline = service.execute(bridge)
+
+ pipeline.variables.map(&:key).tap do |variables|
+ expect(variables).not_to include 'BRIDGE'
+ end
+ end
+
+ it 'sets errors', :aggregate_failures do
+ service.execute(bridge)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
+ expect(bridge.options[:downstream_errors]).to eq(['Insufficient permissions to set pipeline variables'])
+ end
+ end
end
end
diff --git a/spec/services/ci/create_pipeline_service/dry_run_spec.rb b/spec/services/ci/create_pipeline_service/dry_run_spec.rb
index 60c56ed0f67..c21a4ef0917 100644
--- a/spec/services/ci/create_pipeline_service/dry_run_spec.rb
+++ b/spec/services/ci/create_pipeline_service/dry_run_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe Ci::CreatePipelineService do
it_behaves_like 'returns a non persisted pipeline'
it 'returns a pipeline with errors', :aggregate_failures do
- error_message = "test: needs 'build'"
+ error_message = "'test' job needs 'build' job, but it was not added to the pipeline"
expect(subject.error_messages.map(&:content)).to eq([error_message])
expect(subject.errors).not_to be_empty
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index f9015752644..e1f1bdc41a1 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -91,6 +91,23 @@ RSpec.describe Ci::CreatePipelineService do
.with({ source: 'push' }, 5)
end
+ it 'tracks included template usage' do
+ expect_next_instance_of(Gitlab::Ci::Pipeline::Chain::TemplateUsage) do |instance|
+ expect(instance).to receive(:perform!)
+ end
+
+ execute_service
+ end
+
+ 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
+ end
+
context 'when merge requests already exist for this source branch' do
let(:merge_request_1) do
create(:merge_request, source_branch: 'feature', target_branch: "master", source_project: project)
@@ -481,6 +498,7 @@ RSpec.describe Ci::CreatePipelineService do
expect(execute_service).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
+ expect(Namespaces::OnboardingPipelineCreatedWorker).not_to receive(:perform_async)
end
shared_examples 'a failed pipeline' do
@@ -1418,6 +1436,13 @@ RSpec.describe Ci::CreatePipelineService do
pipeline
end
+ it 'schedules a namespace onboarding create action worker' do
+ expect(Namespaces::OnboardingPipelineCreatedWorker)
+ .to receive(:perform_async).with(project.namespace_id)
+
+ pipeline
+ end
+
context 'when target sha is specified' do
let(:target_sha) { merge_request.target_branch_sha }
@@ -1688,9 +1713,11 @@ RSpec.describe Ci::CreatePipelineService do
shared_examples 'has errors' do
it 'contains the expected errors' do
expect(pipeline.builds).to be_empty
- expect(pipeline.yaml_errors).to eq("test_a: needs 'build_a'")
- expect(pipeline.error_messages.map(&:content)).to contain_exactly("test_a: needs 'build_a'")
- expect(pipeline.errors[:base]).to contain_exactly("test_a: needs 'build_a'")
+
+ error_message = "'test_a' job needs 'build_a' job, but it was not added to the pipeline"
+ expect(pipeline.yaml_errors).to eq(error_message)
+ expect(pipeline.error_messages.map(&:content)).to contain_exactly(error_message)
+ expect(pipeline.errors[:base]).to contain_exactly(error_message)
end
end
@@ -2385,16 +2412,6 @@ RSpec.describe Ci::CreatePipelineService do
expect(build_names).to contain_exactly('regular-job')
end
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'does not a pipeline' do
- expect(pipeline).not_to be_persisted
- end
- end
-
context 'when a job requires the same variable' do
let(:config) do
<<-EOY
@@ -2423,16 +2440,6 @@ RSpec.describe Ci::CreatePipelineService do
expect(pipeline).to be_persisted
expect(build_names).to contain_exactly('build', 'test1', 'test2')
end
-
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'does not a pipeline' do
- expect(pipeline).not_to be_persisted
- end
- end
end
end
@@ -2443,16 +2450,6 @@ RSpec.describe Ci::CreatePipelineService do
expect(pipeline).not_to be_persisted
end
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'does not create a pipeline' do
- expect(pipeline).not_to be_persisted
- end
- end
-
context 'when a job requires the same variable' do
let(:config) do
<<-EOY
@@ -2480,16 +2477,6 @@ RSpec.describe Ci::CreatePipelineService do
it 'does not create a pipeline' do
expect(pipeline).not_to be_persisted
end
-
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'does not create a pipeline' do
- expect(pipeline).not_to be_persisted
- end
- end
end
end
end
diff --git a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
index c8d426ee657..1edcef2977b 100644
--- a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
+++ b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
describe '.execute' do
subject { service.execute }
- let_it_be(:artifact, reload: true) do
+ let_it_be(:artifact, refind: true) do
create(:ci_job_artifact, expire_at: 1.day.ago)
end
@@ -30,14 +30,16 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
it 'performs the smallest number of queries for job_artifacts' do
log = ActiveRecord::QueryRecorder.new { subject }
- # SELECT expired ci_job_artifacts
+ # SELECT expired ci_job_artifacts - 3 queries from each_batch
# PRELOAD projects, routes, project_statistics
# BEGIN
# INSERT into ci_deleted_objects
# DELETE loaded ci_job_artifacts
# DELETE security_findings -- for EE
# COMMIT
- expect(log.count).to be_within(1).of(8)
+ # SELECT next expired ci_job_artifacts
+
+ expect(log.count).to be_within(1).of(11)
end
end
@@ -162,13 +164,21 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
end
context 'when timeout happens' do
+ let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+
before do
- stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_TIMEOUT', 1.second)
- allow_any_instance_of(described_class).to receive(:destroy_artifacts_batch) { true }
+ stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_TIMEOUT', 0.seconds)
+ stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
+
+ second_artifact.job.pipeline.unlocked!
+ end
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
end
- it 'returns false and does not continue destroying' do
- is_expected.to be_falsy
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
end
end
@@ -182,13 +192,13 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
- it 'raises an error and does not continue destroying' do
- is_expected.to be_falsy
- end
-
it 'destroys one artifact' do
expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
+ end
end
context 'when there are no artifacts' do
@@ -199,6 +209,10 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
it 'does not raise error' do
expect { subject }.not_to raise_error
end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(0)
+ end
end
context 'when there are artifacts more than batch sizes' do
@@ -213,33 +227,9 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
it 'destroys all expired artifacts' do
expect { subject }.to change { Ci::JobArtifact.count }.by(-2)
end
- end
-
- context 'when artifact is a pipeline artifact' do
- context 'when artifacts are expired' do
- let!(:pipeline_artifact_1) { create(:ci_pipeline_artifact, expire_at: 1.week.ago) }
- let!(:pipeline_artifact_2) { create(:ci_pipeline_artifact, expire_at: 1.week.ago) }
- before do
- [pipeline_artifact_1, pipeline_artifact_2].each { |pipeline_artifact| pipeline_artifact.pipeline.unlocked! }
- end
-
- it 'destroys pipeline artifacts' do
- expect { subject }.to change { Ci::PipelineArtifact.count }.by(-2)
- end
- end
-
- context 'when artifacts are not expired' do
- let!(:pipeline_artifact_1) { create(:ci_pipeline_artifact, expire_at: 2.days.from_now) }
- let!(:pipeline_artifact_2) { create(:ci_pipeline_artifact, expire_at: 2.days.from_now) }
-
- before do
- [pipeline_artifact_1, pipeline_artifact_2].each { |pipeline_artifact| pipeline_artifact.pipeline.unlocked! }
- end
-
- it 'does not destroy pipeline artifacts' do
- expect { subject }.not_to change { Ci::PipelineArtifact.count }
- end
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(2)
end
end
@@ -255,16 +245,4 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
end
end
end
-
- describe '.destroy_job_artifacts_batch' do
- it 'returns a falsy value without artifacts' do
- expect(service.send(:destroy_job_artifacts_batch)).to be_falsy
- end
- end
-
- describe '.destroy_pipeline_artifacts_batch' do
- it 'returns a falsy value without artifacts' do
- expect(service.send(:destroy_pipeline_artifacts_batch)).to be_falsy
- end
- end
end
diff --git a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb
new file mode 100644
index 00000000000..b48ea70aa4c
--- /dev/null
+++ b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::PipelineArtifacts::CoverageReportService do
+ describe '#execute' do
+ subject { described_class.new.execute(pipeline) }
+
+ context 'when pipeline has coverage reports' do
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_pipeline, :with_coverage_reports, project: project) }
+
+ context 'when pipeline is finished' do
+ it 'creates a pipeline artifact' do
+ subject
+
+ expect(Ci::PipelineArtifact.count).to eq(1)
+ end
+
+ it 'persists the default file name' do
+ subject
+
+ file = Ci::PipelineArtifact.first.file
+
+ expect(file.filename).to eq('code_coverage.json')
+ end
+
+ it 'sets expire_at to 1 week' do
+ freeze_time do
+ subject
+
+ pipeline_artifact = Ci::PipelineArtifact.first
+
+ expect(pipeline_artifact.expire_at).to eq(1.week.from_now)
+ end
+ end
+ end
+
+ context 'when pipeline artifact has already been created' do
+ it 'do not raise an error and do not persist the same artifact twice' do
+ expect { 2.times { described_class.new.execute(pipeline) } }.not_to raise_error(ActiveRecord::RecordNotUnique)
+
+ expect(Ci::PipelineArtifact.count).to eq(1)
+ end
+ end
+ end
+
+ context 'when pipeline is running and coverage report does not exist' do
+ let(:pipeline) { create(:ci_pipeline, :running) }
+
+ it 'does not persist data' do
+ subject
+
+ expect(Ci::PipelineArtifact.count).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb b/spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb
new file mode 100644
index 00000000000..ac1a590face
--- /dev/null
+++ b/spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineArtifacts::DestroyExpiredArtifactsService do
+ let(:service) { described_class.new }
+
+ describe '.execute' do
+ subject { service.execute }
+
+ context 'when timeout happens' do
+ before do
+ stub_const('Ci::PipelineArtifacts::DestroyExpiredArtifactsService::LOOP_TIMEOUT', 0.1.seconds)
+ allow(service).to receive(:destroy_artifacts_batch) { true }
+ end
+
+ it 'returns 0 and does not continue destroying' do
+ is_expected.to eq(0)
+ end
+ end
+
+ context 'when there are no artifacts' do
+ it 'does not raise error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when the loop limit is reached' do
+ before do
+ stub_const('::Ci::PipelineArtifacts::DestroyExpiredArtifactsService::LOOP_LIMIT', 1)
+ stub_const('::Ci::PipelineArtifacts::DestroyExpiredArtifactsService::BATCH_SIZE', 1)
+
+ create_list(:ci_pipeline_artifact, 2, expire_at: 1.week.ago)
+ end
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::PipelineArtifact.count }.by(-1)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when there are artifacts more than batch sizes' do
+ before do
+ stub_const('Ci::PipelineArtifacts::DestroyExpiredArtifactsService::BATCH_SIZE', 1)
+
+ create_list(:ci_pipeline_artifact, 2, expire_at: 1.week.ago)
+ end
+
+ it 'destroys all expired artifacts' do
+ expect { subject }.to change { Ci::PipelineArtifact.count }.by(-2)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(2)
+ end
+ end
+
+ context 'when artifacts are not expired' do
+ before do
+ create(:ci_pipeline_artifact, expire_at: 2.days.from_now)
+ end
+
+ it 'does not destroy pipeline artifacts' do
+ expect { subject }.not_to change { Ci::PipelineArtifact.count }
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(0)
+ end
+ end
+ end
+
+ describe '.destroy_artifacts_batch' do
+ it 'returns a falsy value without artifacts' do
+ expect(service.send(:destroy_artifacts_batch)).to be_falsy
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_delayed_and_needs_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_delayed_and_needs_test.yml
new file mode 100644
index 00000000000..b729efaeab2
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_delayed_and_needs_test.yml
@@ -0,0 +1,41 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ when: delayed
+ start_in: 5 seconds
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_manual_and_needs_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_manual_and_needs_test.yml
new file mode 100644
index 00000000000..479fc8fd72d
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_is_manual_and_needs_test.yml
@@ -0,0 +1,40 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ when: manual
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_trigger_service_spec.rb b/spec/services/ci/pipeline_trigger_service_spec.rb
index ac077e3c30e..0cc66e67b91 100644
--- a/spec/services/ci/pipeline_trigger_service_spec.rb
+++ b/spec/services/ci/pipeline_trigger_service_spec.rb
@@ -3,14 +3,16 @@
require 'spec_helper'
RSpec.describe Ci::PipelineTriggerService do
- let(:project) { create(:project, :repository) }
+ include AfterNextHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
before do
stub_ci_pipeline_to_return_yaml_file
end
describe '#execute' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
let(:result) { described_class.new(project, user, params).execute }
before do
@@ -29,8 +31,8 @@ RSpec.describe Ci::PipelineTriggerService do
end
end
- context 'when params have an existsed trigger token' do
- context 'when params have an existsed ref' do
+ context 'when params have an existing trigger token' do
+ context 'when params have an existing ref' do
let(:params) { { token: trigger.token, ref: 'master', variables: nil } }
it 'triggers a pipeline' do
@@ -45,9 +47,7 @@ RSpec.describe Ci::PipelineTriggerService do
context 'when commit message has [ci skip]' do
before do
- allow_next_instance_of(Ci::Pipeline) do |instance|
- allow(instance).to receive(:git_commit_message) { '[ci skip]' }
- end
+ allow_next(Ci::Pipeline).to receive(:git_commit_message) { '[ci skip]' }
end
it 'ignores [ci skip] and create as general' do
diff --git a/spec/services/ci/pipelines/create_artifact_service_spec.rb b/spec/services/ci/pipelines/create_artifact_service_spec.rb
deleted file mode 100644
index 4e9248d9d1a..00000000000
--- a/spec/services/ci/pipelines/create_artifact_service_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Ci::Pipelines::CreateArtifactService do
- describe '#execute' do
- subject { described_class.new.execute(pipeline) }
-
- context 'when pipeline has coverage reports' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_pipeline, :with_coverage_reports, project: project) }
-
- context 'when pipeline is finished' do
- it 'creates a pipeline artifact' do
- subject
-
- expect(Ci::PipelineArtifact.count).to eq(1)
- end
-
- it 'persists the default file name' do
- subject
-
- file = Ci::PipelineArtifact.first.file
-
- expect(file.filename).to eq('code_coverage.json')
- end
-
- it 'sets expire_at to 1 week' do
- freeze_time do
- subject
-
- pipeline_artifact = Ci::PipelineArtifact.first
-
- expect(pipeline_artifact.expire_at).to eq(1.week.from_now)
- end
- end
- end
-
- context 'when pipeline artifact has already been created' do
- it 'do not raise an error and do not persist the same artifact twice' do
- expect { 2.times { described_class.new.execute(pipeline) } }.not_to raise_error(ActiveRecord::RecordNotUnique)
-
- expect(Ci::PipelineArtifact.count).to eq(1)
- end
- end
- end
-
- context 'when pipeline is running and coverage report does not exist' do
- let(:pipeline) { create(:ci_pipeline, :running) }
-
- it 'does not persist data' do
- subject
-
- expect(Ci::PipelineArtifact.count).to eq(0)
- end
- end
- end
-end
diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb
index c9ecbad3167..00c6de7681d 100644
--- a/spec/services/ci/play_build_service_spec.rb
+++ b/spec/services/ci/play_build_service_spec.rb
@@ -72,6 +72,31 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second')
end
+
+ context 'when user defined variables are restricted' do
+ before do
+ project.update!(restrict_user_defined_variables: true)
+ end
+
+ context 'when user is maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'assigns the variables to the build' do
+ service.execute(build, job_variables)
+
+ expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second')
+ end
+ end
+
+ context 'when user is developer' do
+ it 'raises an error' do
+ expect { service.execute(build, job_variables) }
+ .to raise_error Gitlab::Access::AccessDeniedError
+ end
+ end
+ end
end
end
diff --git a/spec/services/ci/process_build_service_spec.rb b/spec/services/ci/process_build_service_spec.rb
index a6e8732f5ff..6d2af81a6e8 100644
--- a/spec/services/ci/process_build_service_spec.rb
+++ b/spec/services/ci/process_build_service_spec.rb
@@ -124,24 +124,46 @@ RSpec.describe Ci::ProcessBuildService, '#execute' do
end
context 'when build is scheduled with DAG' do
+ using RSpec::Parameterized::TableSyntax
+
let(:pipeline) { create(:ci_pipeline, ref: 'master', project: project) }
- let!(:build) { create(:ci_build, :created, when: :on_success, pipeline: pipeline, scheduling_type: :dag) }
+ let!(:build) { create(:ci_build, :created, when: build_when, pipeline: pipeline, scheduling_type: :dag) }
let!(:other_build) { create(:ci_build, :created, when: :on_success, pipeline: pipeline) }
let!(:build_on_other_build) { create(:ci_build_need, build: build, name: other_build.name) }
- context 'when current status is success' do
- let(:current_status) { 'success' }
+ where(:build_when, :current_status, :after_status) do
+ :on_success | 'success' | 'pending'
+ :on_success | 'skipped' | 'skipped'
+ :manual | 'success' | 'manual'
+ :manual | 'skipped' | 'skipped'
+ :delayed | 'success' | 'manual'
+ :delayed | 'skipped' | 'skipped'
+ end
- it 'enqueues the build' do
- expect { subject }.to change { build.status }.to('pending')
+ with_them do
+ it 'proceeds the build' do
+ expect { subject }.to change { build.status }.to(after_status)
end
end
- context 'when current status is skipped' do
- let(:current_status) { 'skipped' }
+ context 'when FF skip_dag_manual_and_delayed_jobs is disabled' do
+ before do
+ stub_feature_flags(skip_dag_manual_and_delayed_jobs: false)
+ end
- it 'skips the build' do
- expect { subject }.to change { build.status }.to('skipped')
+ where(:build_when, :current_status, :after_status) do
+ :on_success | 'success' | 'pending'
+ :on_success | 'skipped' | 'skipped'
+ :manual | 'success' | 'manual'
+ :manual | 'skipped' | 'manual'
+ :delayed | 'success' | 'manual'
+ :delayed | 'skipped' | 'manual'
+ end
+
+ with_them do
+ it 'proceeds the build' do
+ expect { subject }.to change { build.status }.to(after_status)
+ end
end
end
end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 81d56a0e42a..bdf60bb3fdc 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -206,6 +206,22 @@ RSpec.describe Ci::RetryBuildService do
expect(subsequent_build.reload).to be_created
expect(subsequent_bridge.reload).to be_created
end
+
+ it 'updates ownership for subsequent builds' do
+ expect { service.execute(build) }.to change { subsequent_build.reload.user }.to(user)
+ end
+
+ it 'updates ownership for subsequent bridges' do
+ expect { service.execute(build) }.to change { subsequent_bridge.reload.user }.to(user)
+ end
+
+ it 'does not cause n+1 when updaing build ownership' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { service.execute(build) }.count
+
+ create_list(:ci_build, 2, :skipped, stage_idx: build.stage_idx + 1, pipeline: pipeline, stage: 'deploy')
+
+ expect { service.execute(build) }.not_to exceed_all_query_limit(control_count)
+ end
end
context 'when pipeline has other builds' do
diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb
index 526c2f39b46..3c6a99efbf8 100644
--- a/spec/services/ci/retry_pipeline_service_spec.rb
+++ b/spec/services/ci/retry_pipeline_service_spec.rb
@@ -64,6 +64,18 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
expect(build('spinach 1')).to be_created
expect(pipeline.reload).to be_running
end
+
+ it 'changes ownership of subsequent builds' do
+ expect(build('rspec 2').user).not_to eq(user)
+ expect(build('rspec 3').user).not_to eq(user)
+ expect(build('spinach 1').user).not_to eq(user)
+
+ service.execute(pipeline)
+
+ expect(build('rspec 2').user).to eq(user)
+ expect(build('rspec 3').user).to eq(user)
+ expect(build('spinach 1').user).to eq(user)
+ end
end
context 'when there is failed build present which was run on failure' do
@@ -161,6 +173,16 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
expect(build('rspec 2')).to be_created
expect(pipeline.reload).to be_running
end
+
+ it 'changes ownership of subsequent builds' do
+ expect(build('staging').user).not_to eq(user)
+ expect(build('rspec 2').user).not_to eq(user)
+
+ service.execute(pipeline)
+
+ expect(build('staging').user).to eq(user)
+ expect(build('rspec 2').user).to eq(user)
+ end
end
end
diff --git a/spec/services/ci/test_failure_history_service_spec.rb b/spec/services/ci/test_failure_history_service_spec.rb
index e858c85490d..d9c1c8dc3fa 100644
--- a/spec/services/ci/test_failure_history_service_spec.rb
+++ b/spec/services/ci/test_failure_history_service_spec.rb
@@ -22,19 +22,6 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
expect(Ci::TestCaseFailure.count).to eq(2)
end
- context 'when feature flag for test failure history is disabled' do
- before do
- stub_feature_flags(test_failure_history: false)
- end
-
- it 'does not persist data' do
- execute_service
-
- expect(Ci::TestCase.count).to eq(0)
- expect(Ci::TestCaseFailure.count).to eq(0)
- end
- end
-
context 'when pipeline is not for the default branch' do
before do
pipeline.update_column(:ref, 'new-feature')
@@ -136,14 +123,6 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
it { is_expected.to eq(true) }
end
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(test_failure_history: false)
- end
-
- it { is_expected.to eq(false) }
- end
-
context 'when pipeline is not equal to the project default branch' do
before do
pipeline.update_column(:ref, 'some-other-branch')
diff --git a/spec/services/ci/update_build_state_service_spec.rb b/spec/services/ci/update_build_state_service_spec.rb
index 3112e5dda1b..63190cc5d49 100644
--- a/spec/services/ci/update_build_state_service_spec.rb
+++ b/spec/services/ci/update_build_state_service_spec.rb
@@ -82,8 +82,9 @@ RSpec.describe Ci::UpdateBuildStateService do
let(:params) do
{
output: { checksum: 'crc32:12345678', bytesize: 123 },
+ state: 'failed',
failure_reason: 'script_failure',
- state: 'failed'
+ exit_code: 42
}
end
@@ -95,6 +96,15 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(result.status).to eq 200
end
+ it 'updates the allow_failure flag' do
+ expect(build)
+ .to receive(:drop_with_exit_code!)
+ .with('script_failure', 42)
+ .and_call_original
+
+ subject.execute
+ end
+
it 'does not increment invalid trace metric' do
execute_with_stubbed_metrics!
@@ -115,6 +125,15 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(build).to be_failed
end
+ it 'updates the allow_failure flag' do
+ expect(build)
+ .to receive(:drop_with_exit_code!)
+ .with('script_failure', 42)
+ .and_call_original
+
+ subject.execute
+ end
+
it 'responds with 200 OK status' do
result = subject.execute
diff --git a/spec/services/container_expiration_policies/cleanup_service_spec.rb b/spec/services/container_expiration_policies/cleanup_service_spec.rb
index 8438073ceb0..34f69d24141 100644
--- a/spec/services/container_expiration_policies/cleanup_service_spec.rb
+++ b/spec/services/container_expiration_policies/cleanup_service_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
it 'completely clean up the repository' do
expect(Projects::ContainerRepository::CleanupTagsService)
- .to receive(:new).with(project, nil, cleanup_tags_service_params).and_return(cleanup_tags_service)
+ .to receive(:new).with(project, nil, cleanup_tags_service_params).and_return(cleanup_tags_service)
expect(cleanup_tags_service).to receive(:execute).with(repository).and_return(status: :success)
response = subject
@@ -34,10 +34,14 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
end
context 'without a successful cleanup tags service execution' do
- it 'partially clean up the repository' do
+ let(:cleanup_tags_service_response) { { status: :error, message: 'timeout' } }
+
+ before do
expect(Projects::ContainerRepository::CleanupTagsService)
- .to receive(:new).and_return(double(execute: { status: :error, message: 'timeout' }))
+ .to receive(:new).and_return(double(execute: cleanup_tags_service_response))
+ end
+ it 'partially clean up the repository' do
response = subject
aggregate_failures "checking the response and container repositories" do
@@ -49,6 +53,39 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
expect(repository.expiration_policy_completed_at).to eq(nil)
end
end
+
+ context 'with a truncated cleanup tags service response' do
+ let(:cleanup_tags_service_response) do
+ {
+ status: :error,
+ original_size: 1000,
+ before_truncate_size: 800,
+ after_truncate_size: 200,
+ before_delete_size: 100
+ }
+ end
+
+ it 'partially clean up the repository' do
+ response = subject
+
+ aggregate_failures "checking the response and container repositories" do
+ expect(response.success?).to eq(true)
+ expect(response.payload)
+ .to include(
+ cleanup_status: :unfinished,
+ container_repository_id: repository.id,
+ cleanup_tags_service_original_size: 1000,
+ cleanup_tags_service_before_truncate_size: 800,
+ cleanup_tags_service_after_truncate_size: 200,
+ cleanup_tags_service_before_delete_size: 100
+ )
+ 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
context 'with no repository' do
diff --git a/spec/services/draft_notes/create_service_spec.rb b/spec/services/draft_notes/create_service_spec.rb
index f0291067777..9e084dbed1c 100644
--- a/spec/services/draft_notes/create_service_spec.rb
+++ b/spec/services/draft_notes/create_service_spec.rb
@@ -20,6 +20,23 @@ RSpec.describe DraftNotes::CreateService do
expect(draft.discussion_id).to be_nil
end
+ it 'tracks the start event when the draft is persisted' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_create_review_note_action)
+ .with(user: user)
+
+ draft = create_draft(note: 'This is a test')
+ expect(draft).to be_persisted
+ end
+
+ it 'does not track the start event when the draft is not persisted' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_create_review_note_action)
+
+ draft = create_draft(note: 'Not a reply!', resolve_discussion: true)
+ expect(draft).not_to be_persisted
+ end
+
it 'cannot resolve when there is nothing to resolve' do
draft = create_draft(note: 'Not a reply!', resolve_discussion: true)
diff --git a/spec/services/draft_notes/publish_service_spec.rb b/spec/services/draft_notes/publish_service_spec.rb
index ae0c8113904..f83e91b683f 100644
--- a/spec/services/draft_notes/publish_service_spec.rb
+++ b/spec/services/draft_notes/publish_service_spec.rb
@@ -43,6 +43,13 @@ RSpec.describe DraftNotes::PublishService do
expect(result[:status]).to eq(:success)
end
+ it 'does not track the publish event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_publish_review_action)
+
+ publish(draft: drafts.first)
+ end
+
context 'commit_id is set' do
let(:commit_id) { commit.id }
@@ -74,6 +81,13 @@ RSpec.describe DraftNotes::PublishService do
expect { publish }.not_to change { DraftNote.count }
end
+ it 'does not track the publish event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_publish_review_action)
+
+ publish
+ end
+
it 'returns an error' do
result = publish
@@ -105,6 +119,14 @@ RSpec.describe DraftNotes::PublishService do
publish
end
+ it 'tracks the publish event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_publish_review_action)
+ .with(user: user)
+
+ publish
+ end
+
context 'commit_id is set' do
let(:commit_id) { commit.id }
diff --git a/spec/services/feature_flags/create_service_spec.rb b/spec/services/feature_flags/create_service_spec.rb
index 2cd19000f99..e115d8098c9 100644
--- a/spec/services/feature_flags/create_service_spec.rb
+++ b/spec/services/feature_flags/create_service_spec.rb
@@ -34,6 +34,12 @@ RSpec.describe FeatureFlags::CreateService do
it 'does not create audit log' do
expect { subject }.not_to change { AuditEvent.count }
end
+
+ it 'does not sync the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).not_to receive(:perform_async)
+
+ subject
+ end
end
context 'when feature flag is saved correctly' do
@@ -54,6 +60,24 @@ RSpec.describe FeatureFlags::CreateService do
expect { subject }.to change { Operations::FeatureFlag.count }.by(1)
end
+ it 'syncs the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).to receive(:perform_async).with(Integer, Integer)
+
+ 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 66a75a2c24e..8c4055ddd9e 100644
--- a/spec/services/feature_flags/update_service_spec.rb
+++ b/spec/services/feature_flags/update_service_spec.rb
@@ -26,6 +26,24 @@ 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)
+
+ subject
+ end
+
it 'creates audit event with correct message' do
name_was = feature_flag.name
@@ -52,6 +70,12 @@ RSpec.describe FeatureFlags::UpdateService do
it 'does not create audit event' do
expect { subject }.not_to change { AuditEvent.count }
end
+
+ it 'does not sync the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).not_to receive(:perform_async)
+
+ subject
+ end
end
context 'when user is reporter' do
diff --git a/spec/services/git/branch_push_service_spec.rb b/spec/services/git/branch_push_service_spec.rb
index c7bf006dab0..cc3ba21f002 100644
--- a/spec/services/git/branch_push_service_spec.rb
+++ b/spec/services/git/branch_push_service_spec.rb
@@ -554,7 +554,7 @@ RSpec.describe Git::BranchPushService, services: true do
end
describe "housekeeping" do
- let(:housekeeping) { Projects::HousekeepingService.new(project) }
+ let(:housekeeping) { Repositories::HousekeepingService.new(project) }
before do
# Flush any raw key-value data stored by the housekeeping code.
@@ -562,7 +562,7 @@ RSpec.describe Git::BranchPushService, services: true do
Gitlab::Redis::Queues.with { |conn| conn.flushall }
Gitlab::Redis::SharedState.with { |conn| conn.flushall }
- allow(Projects::HousekeepingService).to receive(:new).and_return(housekeeping)
+ allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping)
end
after do
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index 4f5bc3a3d5a..f0cd42c1948 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -63,6 +63,10 @@ RSpec.describe Groups::CreateService, '#execute' do
end
it { is_expected.to be_persisted }
+
+ it 'adds an onboarding progress record' do
+ expect { subject }.to change(OnboardingProgress, :count).from(0).to(1)
+ end
end
context 'when user can not create a group' do
@@ -84,6 +88,10 @@ RSpec.describe Groups::CreateService, '#execute' do
end
it { is_expected.to be_persisted }
+
+ it 'does not add an onboarding progress record' do
+ expect { subject }.not_to change(OnboardingProgress, :count).from(0)
+ end
end
context 'as guest' do
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index e06f09d0463..2f9bb72939a 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -135,51 +135,120 @@ RSpec.describe Groups::DestroyService do
end
describe 'authorization updates', :sidekiq_inline do
- context 'shared groups' do
+ context 'for solo groups' do
+ context 'group is deleted' do
+ it 'updates project authorization' do
+ expect { destroy_group(group, user, false) }.to(
+ change { user.can?(:read_project, project) }.from(true).to(false))
+ end
+
+ it 'does not make use of a specific service to update project_authorizations records' do
+ expect(UserProjectAccessChangedService)
+ .not_to receive(:new).with(group.user_ids_for_project_authorizations)
+
+ destroy_group(group, user, false)
+ end
+ end
+ end
+
+ context 'for shared groups within different hierarchies' do
+ let(:shared_with_group) { group }
let!(:shared_group) { create(:group, :private) }
let!(:shared_group_child) { create(:group, :private, parent: shared_group) }
+ let!(:shared_group_user) { create(:user) }
let!(:project) { create(:project, group: shared_group) }
let!(:project_child) { create(:project, group: shared_group_child) }
before do
- create(:group_group_link, shared_group: shared_group, shared_with_group: group)
- group.refresh_members_authorized_projects
+ shared_group.add_user(shared_group_user, Gitlab::Access::OWNER)
+
+ create(:group_group_link, shared_group: shared_group, shared_with_group: shared_with_group)
+ shared_with_group.refresh_members_authorized_projects
+ end
+
+ context 'the shared group is deleted' do
+ it 'updates project authorization' do
+ expect(shared_group_user.can?(:read_project, project)).to eq(true)
+ expect(shared_group_user.can?(:read_project, project_child)).to eq(true)
+
+ destroy_group(shared_group, shared_group_user, false)
+
+ expect(shared_group_user.can?(:read_project, project)).to eq(false)
+ expect(shared_group_user.can?(:read_project, project_child)).to eq(false)
+ end
+
+ it 'does not make use of specific service to update project_authorizations records' do
+ expect(UserProjectAccessChangedService)
+ .not_to receive(:new).with(shared_group.user_ids_for_project_authorizations).and_call_original
+
+ destroy_group(shared_group, shared_group_user, false)
+ end
end
- it 'updates project authorization' do
- expect(user.can?(:read_project, project)).to eq(true)
- expect(user.can?(:read_project, project_child)).to eq(true)
+ context 'the shared_with group is deleted' do
+ it 'updates project authorization' do
+ expect(user.can?(:read_project, project)).to eq(true)
+ expect(user.can?(:read_project, project_child)).to eq(true)
- destroy_group(group, user, false)
+ destroy_group(shared_with_group, user, false)
- expect(user.can?(:read_project, project)).to eq(false)
- expect(user.can?(:read_project, project_child)).to eq(false)
+ expect(user.can?(:read_project, project)).to eq(false)
+ expect(user.can?(:read_project, project_child)).to eq(false)
+ end
+
+ it 'makes use of a specific service to update project_authorizations records' do
+ expect(UserProjectAccessChangedService)
+ .to receive(:new).with(shared_with_group.user_ids_for_project_authorizations).and_call_original
+
+ destroy_group(shared_with_group, user, false)
+ end
end
end
- context 'shared groups in the same group hierarchy' do
- let!(:subgroup) { create(:group, :private, parent: group) }
- let!(:subgroup_user) { create(:user) }
+ context 'for shared groups in the same group hierarchy' do
+ let(:shared_group) { group }
+ let(:shared_with_group) { nested_group }
+ let!(:shared_with_group_user) { create(:user) }
before do
- subgroup.add_user(subgroup_user, Gitlab::Access::MAINTAINER)
+ shared_with_group.add_user(shared_with_group_user, Gitlab::Access::MAINTAINER)
- create(:group_group_link, shared_group: group, shared_with_group: subgroup)
- subgroup.refresh_members_authorized_projects
+ create(:group_group_link, shared_group: shared_group, shared_with_group: shared_with_group)
+ shared_with_group.refresh_members_authorized_projects
end
- context 'group is deleted' do
+ context 'the shared group is deleted' do
it 'updates project authorization' do
- expect { destroy_group(group, user, false) }.to(
- change { subgroup_user.can?(:read_project, project) }.from(true).to(false))
+ expect { destroy_group(shared_group, user, false) }.to(
+ change { shared_with_group_user.can?(:read_project, project) }.from(true).to(false))
+ end
+
+ it 'does not make use of a specific service to update project authorizations' do
+ # Due to the recursive nature of `Groups::DestroyService`, `UserProjectAccessChangedService`
+ # will still be executed for the nested group as they fall under the same hierarchy
+ # and hence we need to account for this scenario.
+ expect(UserProjectAccessChangedService)
+ .to receive(:new).with(shared_with_group.user_ids_for_project_authorizations).and_call_original
+
+ expect(UserProjectAccessChangedService)
+ .not_to receive(:new).with(shared_group.user_ids_for_project_authorizations)
+
+ destroy_group(shared_group, user, false)
end
end
- context 'subgroup is deleted' do
+ context 'the shared_with group is deleted' do
it 'updates project authorization' do
- expect { destroy_group(subgroup, user, false) }.to(
- change { subgroup_user.can?(:read_project, project) }.from(true).to(false))
+ expect { destroy_group(shared_with_group, user, false) }.to(
+ change { shared_with_group_user.can?(:read_project, project) }.from(true).to(false))
+ end
+
+ it 'makes use of a specific service to update project authorizations' do
+ expect(UserProjectAccessChangedService)
+ .to receive(:new).with(shared_with_group.user_ids_for_project_authorizations).and_call_original
+
+ destroy_group(shared_with_group, user, false)
end
end
end
diff --git a/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb b/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
index 4c8aebe5fe2..0caffb16f42 100644
--- a/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
+++ b/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe IncidentManagement::PagerDuty::ProcessWebhookService do
let(:webhook_payload) { Gitlab::Json.parse(fixture_file('pager_duty/webhook_incident_trigger.json')) }
let(:token) { nil }
- subject(:execute) { described_class.new(project, nil, webhook_payload).execute(token) }
+ subject(:execute) { described_class.new(project, webhook_payload).execute(token) }
context 'when PagerDuty webhook setting is active' do
let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb
index f2bc4f717af..79543fe9f5d 100644
--- a/spec/services/issuable/bulk_update_service_spec.rb
+++ b/spec/services/issuable/bulk_update_service_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Issuable::BulkUpdateService do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
def bulk_update(issuables, extra_params = {})
bulk_update_params = extra_params
@@ -31,6 +31,23 @@ RSpec.describe Issuable::BulkUpdateService do
end
end
+ shared_examples 'updates iterations' do
+ it 'succeeds' do
+ result = bulk_update(issuables, sprint_id: iteration.id)
+
+ expect(result.success?).to be_truthy
+ expect(result.payload[:count]).to eq(issuables.count)
+ end
+
+ it 'updates the issuables iteration' do
+ bulk_update(issuables, sprint_id: iteration.id)
+
+ issuables.each do |issuable|
+ expect(issuable.reload.iteration).to eq(iteration)
+ end
+ end
+ end
+
shared_examples 'updating labels' do
def create_issue_with_labels(labels)
create(:labeled_issue, project: project, labels: labels)
@@ -233,6 +250,21 @@ RSpec.describe Issuable::BulkUpdateService do
it_behaves_like 'updates milestones'
end
+ describe 'updating iterations' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:issuables) { [create(:issue, project: project)] }
+ let_it_be(:iteration) { create(:iteration, group: group) }
+
+ let(:parent) { project }
+
+ before do
+ group.add_reporter(user)
+ end
+
+ it_behaves_like 'updates iterations'
+ end
+
describe 'updating labels' do
let(:bug) { create(:label, project: project) }
let(:regression) { create(:label, project: project) }
@@ -283,7 +315,7 @@ RSpec.describe Issuable::BulkUpdateService do
end
context 'with issuables at a group level' do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
let(:parent) { group }
before do
@@ -315,6 +347,19 @@ RSpec.describe Issuable::BulkUpdateService do
end
end
+ describe 'updating iterations' do
+ let_it_be(:iteration) { create(:iteration, group: group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
+
+ context 'when issues' do
+ let_it_be(:issue1) { create(:issue, project: project) }
+ let_it_be(:issue2) { create(:issue, project: project) }
+ let_it_be(:issuables) { [issue1, issue2] }
+
+ it_behaves_like 'updates iterations'
+ end
+ end
+
describe 'updating labels' do
let(:project) { create(:project, :repository, group: group) }
let(:bug) { create(:group_label, group: group) }
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index 9076fb11c9b..dc545f57d23 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -112,10 +112,14 @@ RSpec.describe Issues::CloseService do
end
context "closed by a merge request", :sidekiq_might_not_need_inline do
- it 'mentions closure via a merge request' do
+ subject(:close_issue) do
perform_enqueued_jobs do
described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request)
end
+ end
+
+ it 'mentions closure via a merge request' do
+ close_issue
email = ActionMailer::Base.deliveries.last
@@ -124,12 +128,15 @@ RSpec.describe Issues::CloseService do
expect(email.body.parts.map(&:body)).to all(include(closing_merge_request.to_reference))
end
+ it_behaves_like 'records an onboarding progress action', :issue_auto_closed do
+ let(:namespace) { project.namespace }
+ end
+
context 'when user cannot read merge request' do
it 'does not mention merge request' do
project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
- perform_enqueued_jobs do
- described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request)
- end
+
+ close_issue
email = ActionMailer::Base.deliveries.last
body_text = email.body.parts.map(&:body).join(" ")
@@ -141,13 +148,11 @@ RSpec.describe Issues::CloseService do
end
context 'updating `metrics.first_mentioned_in_commit_at`' do
- subject { described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request) }
-
context 'when `metrics.first_mentioned_in_commit_at` is not set' do
it 'uses the first commit authored timestamp' do
expected = closing_merge_request.commits.first.authored_date
- subject
+ close_issue
expect(issue.metrics.first_mentioned_in_commit_at).to eq(expected)
end
@@ -159,7 +164,7 @@ RSpec.describe Issues::CloseService do
end
it 'does not update the metrics' do
- expect { subject }.not_to change { issue.metrics.first_mentioned_in_commit_at }
+ expect { close_issue }.not_to change { issue.metrics.first_mentioned_in_commit_at }
end
end
@@ -167,7 +172,7 @@ RSpec.describe Issues::CloseService do
let(:closing_merge_request) { create(:merge_request, :without_diffs, source_project: project) }
it 'does not update the metrics' do
- subject
+ close_issue
expect(issue.metrics.first_mentioned_in_commit_at).to be_nil
end
@@ -206,7 +211,7 @@ RSpec.describe Issues::CloseService do
end
context "valid params" do
- def close_issue
+ subject(:close_issue) do
perform_enqueued_jobs do
described_class.new(project, user).close_issue(issue)
end
@@ -290,6 +295,8 @@ RSpec.describe Issues::CloseService do
close_issue
end
+
+ it_behaves_like 'does not record an onboarding progress action'
end
context 'when issue is not confidential' do
diff --git a/spec/services/issues/export_csv_service_spec.rb b/spec/services/issues/export_csv_service_spec.rb
index 8072b7a478e..fd1bcf82ccd 100644
--- a/spec/services/issues/export_csv_service_spec.rb
+++ b/spec/services/issues/export_csv_service_spec.rb
@@ -20,7 +20,9 @@ RSpec.describe Issues::ExportCsvService do
end
it 'renders with a target filesize' do
- expect(subject.csv_builder).to receive(:render).with(described_class::TARGET_FILESIZE)
+ expect_next_instance_of(CsvBuilder) do |csv_builder|
+ expect(csv_builder).to receive(:render).with(described_class::TARGET_FILESIZE).once
+ end
subject.email(user)
end
diff --git a/spec/services/jira_connect/sync_service_spec.rb b/spec/services/jira_connect/sync_service_spec.rb
index 4b434348146..edd0bad70f5 100644
--- a/spec/services/jira_connect/sync_service_spec.rb
+++ b/spec/services/jira_connect/sync_service_spec.rb
@@ -45,11 +45,11 @@ RSpec.describe JiraConnect::SyncService do
it 'logs the response as an error' do
expect_next(client).to store_info([
{ 'errorMessages' => ['some error message'] },
- { 'rejectedBuilds' => ['x'] }
+ { 'errorMessages' => ['x'] }
])
expect_log(:error, { 'errorMessages' => ['some error message'] })
- expect_log(:error, { 'rejectedBuilds' => ['x'] })
+ expect_log(:error, { 'errorMessages' => ['x'] })
subject
end
diff --git a/spec/services/jira_connect_subscriptions/create_service_spec.rb b/spec/services/jira_connect_subscriptions/create_service_spec.rb
index 9750c671fa2..5f467a07a78 100644
--- a/spec/services/jira_connect_subscriptions/create_service_spec.rb
+++ b/spec/services/jira_connect_subscriptions/create_service_spec.rb
@@ -49,18 +49,6 @@ RSpec.describe JiraConnectSubscriptions::CreateService do
subject
end
-
- context 'when the jira_connect_full_namespace_sync feature flag is disabled' do
- before do
- stub_feature_flags(jira_connect_full_namespace_sync: false)
- end
-
- specify do
- expect(JiraConnect::SyncProjectWorker).not_to receive(:bulk_perform_in_with_contexts)
-
- subject
- end
- end
end
end
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index e8a4a798b20..50efee9f43c 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -2,26 +2,41 @@
require 'spec_helper'
-RSpec.describe Members::CreateService do
- let_it_be(:project) { create(:project) }
+RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sidekiq_inline do
+ let_it_be(:source) { create(:project) }
let_it_be(:user) { create(:user) }
- let_it_be(:project_user) { create(:user) }
- let_it_be(:user_ids) { project_user.id.to_s }
+ let_it_be(:member) { create(:user) }
+ let_it_be(:user_ids) { member.id.to_s }
let_it_be(:access_level) { Gitlab::Access::GUEST }
let(:params) { { user_ids: user_ids, access_level: access_level } }
- subject(:execute_service) { described_class.new(user, params).execute(project) }
+ subject(:execute_service) { described_class.new(user, params).execute(source) }
before do
- project.add_maintainer(user)
- allow(Namespaces::OnboardingUserAddedWorker).to receive(:idempotent?).and_return(false)
+ if source.is_a?(Project)
+ source.add_maintainer(user)
+ OnboardingProgress.onboard(source.namespace)
+ else
+ source.add_owner(user)
+ OnboardingProgress.onboard(source)
+ end
end
context 'when passing valid parameters' do
it 'adds a user to members' do
expect(execute_service[:status]).to eq(:success)
- expect(project.users).to include project_user
- expect(Namespaces::OnboardingUserAddedWorker.jobs.last['args'][0]).to eq(project.id)
+ expect(source.users).to include member
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(true)
+ end
+
+ context 'when executing on a group' do
+ let_it_be(:source) { create(:group) }
+
+ it 'adds a user to members' do
+ expect(execute_service[:status]).to eq(:success)
+ expect(source.users).to include member
+ expect(OnboardingProgress.completed?(source, :user_added)).to be(true)
+ end
end
end
@@ -31,8 +46,8 @@ RSpec.describe Members::CreateService do
it 'does not add a member' do
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to be_present
- expect(project.users).not_to include project_user
- expect(Namespaces::OnboardingUserAddedWorker.jobs.size).to eq(0)
+ expect(source.users).not_to include member
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
@@ -42,8 +57,8 @@ RSpec.describe Members::CreateService do
it 'limits the number of users to 100' do
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to be_present
- expect(project.users).not_to include project_user
- expect(Namespaces::OnboardingUserAddedWorker.jobs.size).to eq(0)
+ expect(source.users).not_to include member
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
@@ -52,19 +67,19 @@ RSpec.describe Members::CreateService do
it 'does not add a member' do
expect(execute_service[:status]).to eq(:error)
- expect(execute_service[:message]).to include("#{project_user.username}: Access level is not included in the list")
- expect(project.users).not_to include project_user
- expect(Namespaces::OnboardingUserAddedWorker.jobs.size).to eq(0)
+ expect(execute_service[:message]).to include("#{member.username}: Access level is not included in the list")
+ expect(source.users).not_to include member
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
context 'when passing an existing invite user id' do
- let(:user_ids) { create(:project_member, :invited, project: project).invite_email }
+ let(:user_ids) { create(:project_member, :invited, project: source).invite_email }
it 'does not add a member' do
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to eq('Invite email has already been taken')
- expect(Namespaces::OnboardingUserAddedWorker.jobs.size).to eq(0)
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
end
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index 69bab3b1ea4..9ae310d8cee 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe MergeRequests::AfterCreateService do
+ include AfterNextHelpers
+
let_it_be(:merge_request) { create(:merge_request) }
subject(:after_create_service) do
@@ -27,6 +29,14 @@ RSpec.describe MergeRequests::AfterCreateService do
execute_service
end
+ it 'calls the merge request activity counter' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_create_mr_action)
+ .with(user: merge_request.author)
+
+ execute_service
+ end
+
it 'creates a new merge request notification' do
expect(notification_service)
.to receive(:new_merge_request).with(merge_request, merge_request.author)
@@ -56,11 +66,15 @@ RSpec.describe MergeRequests::AfterCreateService do
execute_service
end
- it 'records a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(merge_request.target_project.namespace, :merge_request_created).and_call_original
+ 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 { execute_service }.to change(NamespaceOnboardingAction, :count).by(1)
+ expect(OnboardingProgress.completed?(merge_request.target_project.namespace, :merge_request_created)).to be(true)
end
end
end
diff --git a/spec/services/merge_requests/cleanup_refs_service_spec.rb b/spec/services/merge_requests/cleanup_refs_service_spec.rb
index 38c0e204e54..a1822a4d5ba 100644
--- a/spec/services/merge_requests/cleanup_refs_service_spec.rb
+++ b/spec/services/merge_requests/cleanup_refs_service_spec.rb
@@ -91,6 +91,26 @@ RSpec.describe MergeRequests::CleanupRefsService do
it_behaves_like 'service that does not clean up merge request refs'
end
+ context 'when a git error is raised' do
+ context 'Gitlab::Git::Repository::GitError' do
+ before do
+ allow(merge_request.project.repository).to receive(:delete_refs).and_raise(Gitlab::Git::Repository::GitError)
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+
+ context 'Gitlab::Git::CommandError' do
+ before do
+ allow_next_instance_of(Gitlab::Git::KeepAround) do |keep_around|
+ expect(keep_around).to receive(:kept_around?).and_raise(Gitlab::Git::CommandError)
+ end
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+ end
+
context 'when cleanup schedule fails to update' do
before do
allow(merge_request.cleanup_schedule).to receive(:update).and_return(false)
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index 67fb4eaade5..48f56b3ec68 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe MergeRequests::CloseService do
describe '#execute' do
it_behaves_like 'cache counters invalidator'
+ it_behaves_like 'merge request reviewers cache counters invalidator'
context 'valid params' do
let(:service) { described_class.new(project, user, {}) }
@@ -75,6 +76,14 @@ RSpec.describe MergeRequests::CloseService do
described_class.new(project, user, {}).execute(merge_request)
end
+ it 'calls the merge request activity counter' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_close_mr_action)
+ .with(user: user)
+
+ described_class.new(project, user, {}).execute(merge_request)
+ end
+
it 'refreshes the number of open merge requests for a valid MR', :use_clean_rails_memory_store_caching do
service = described_class.new(project, user, {})
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 86e49fe601c..be8c41bc4a1 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -66,10 +66,11 @@ RSpec.describe MergeRequests::CreateFromIssueService do
expect { service.execute }.to change(target_project.merge_requests, :count).by(1)
end
- it 'sets the merge request author to current user', :sidekiq_might_not_need_inline do
+ it 'sets the merge request author to current user and assigns them', :sidekiq_might_not_need_inline do
result = service.execute
expect(result[:merge_request].author).to eq(user)
+ expect(result[:merge_request].assignees).to eq([user])
end
it 'sets the merge request source branch to the new issue branch', :sidekiq_might_not_need_inline do
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index d042b318d02..4f47a22b07c 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -155,6 +155,12 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
expect(Todo.where(attributes).count).to eq 1
end
+
+ it 'invalidates counter cache for reviewers', :use_clean_rails_memory_store_caching do
+ expect { merge_request }
+ .to change { user2.review_requested_open_merge_requests_count }
+ .by(1)
+ end
end
context 'when head pipelines already exist for merge request source branch', :sidekiq_inline do
diff --git a/spec/services/merge_requests/export_csv_service_spec.rb b/spec/services/merge_requests/export_csv_service_spec.rb
index ecb17b3fe77..4ce032c396e 100644
--- a/spec/services/merge_requests/export_csv_service_spec.rb
+++ b/spec/services/merge_requests/export_csv_service_spec.rb
@@ -27,11 +27,11 @@ RSpec.describe MergeRequests::ExportCsvService do
let_it_be(:merge_request) { create(:merge_request, assignees: create_list(:user, 2)) }
it 'contains the names of assignees' do
- expect(csv['Assignees']).to eq(merge_request.assignees.map(&:name).join(', '))
+ expect(csv['Assignees'].split(', ')).to match_array(merge_request.assignees.map(&:name))
end
it 'contains the usernames of assignees' do
- expect(csv['Assignee Usernames']).to eq(merge_request.assignees.map(&:username).join(', '))
+ expect(csv['Assignee Usernames'].split(', ')).to match_array(merge_request.assignees.map(&:username))
end
end
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index d0e3102f157..dd37d87e3f5 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -37,6 +37,10 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request.in_progress_merge_commit_sha).to be_nil
end
+ it 'does not update squash_commit_sha if it is not a squash' do
+ expect(merge_request.squash_commit_sha).to be_nil
+ end
+
it 'sends email to user2 about merge of new merge_request' do
email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email)
@@ -76,6 +80,12 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_commit.message).to eq('Merge commit message')
expect(squash_commit.message).to eq("Squash commit message\n")
end
+
+ it 'persists squash_commit_sha' do
+ squash_commit = merge_request.merge_commit.parents.last
+
+ expect(merge_request.squash_commit_sha).to eq(squash_commit.id)
+ end
end
end
@@ -361,6 +371,7 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.squash_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))
end
@@ -381,6 +392,7 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.squash_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))
end
@@ -395,10 +407,27 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.squash_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))
end
+ it 'logs and saves error if there is an PreReceiveError exception' do
+ error_message = 'error message'
+
+ allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, "GitLab: #{error_message}")
+ allow(service).to receive(:execute_hooks)
+ merge_request.update!(squash: true)
+
+ service.execute(merge_request)
+
+ expect(merge_request).to be_open
+ expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.squash_commit_sha).to be_nil
+ expect(merge_request.merge_error).to include('Something went wrong during merge pre-receive hook')
+ expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ end
+
context 'when fast-forward merge is not allowed' do
before do
allow_any_instance_of(Repository).to receive(:ancestor?).and_return(nil)
@@ -415,6 +444,7 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
+ expect(merge_request.squash_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))
end
diff --git a/spec/services/merge_requests/mergeability_check_service_spec.rb b/spec/services/merge_requests/mergeability_check_service_spec.rb
index 725fc16fa7c..17bfa9d7368 100644
--- a/spec/services/merge_requests/mergeability_check_service_spec.rb
+++ b/spec/services/merge_requests/mergeability_check_service_spec.rb
@@ -124,14 +124,6 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
it_behaves_like 'mergeable merge request'
- context 'when lock is disabled' do
- before do
- stub_feature_flags(merge_ref_auto_sync_lock: false)
- end
-
- it_behaves_like 'mergeable merge request'
- end
-
context 'when concurrent calls' do
it 'waits first lock and returns "cached" result in subsequent calls' do
threads = execute_within_threads(amount: 3)
@@ -167,25 +159,6 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
end
end
- context 'disabled merge ref sync feature flag' do
- before do
- stub_feature_flags(merge_ref_auto_sync: false)
- end
-
- it 'returns error and no payload' do
- result = subject
-
- expect(result).to be_a(ServiceResponse)
- expect(result.error?).to be(true)
- expect(result.message).to eq('Merge ref is outdated due to disabled feature')
- expect(result.payload).to be_empty
- end
-
- it 'ignores merge-ref and updates merge status' do
- expect { subject }.to change(merge_request, :merge_status).from('unchecked').to('can_be_merged')
- end
- end
-
context 'when broken' do
before do
expect(merge_request).to receive(:broken?) { true }
@@ -305,28 +278,6 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
context 'recheck enforced' do
subject { described_class.new(merge_request).execute(recheck: true) }
- context 'when MR is mergeable and merge-ref auto-sync is disabled' do
- before do
- stub_feature_flags(merge_ref_auto_sync: false)
- merge_request.mark_as_mergeable!
- end
-
- it 'returns ServiceResponse.error' do
- result = subject
-
- expect(result).to be_a(ServiceResponse)
- expect(result.error?).to be(true)
- expect(result.message).to eq('Merge ref is outdated due to disabled feature')
- expect(result.payload).to be_empty
- end
-
- it 'merge status is not changed' do
- subject
-
- expect(merge_request.merge_status).to eq('can_be_merged')
- end
- end
-
context 'when MR is marked as mergeable, but repo is not mergeable and MR is not opened' do
before do
# Making sure that we don't touch the merge-status after
diff --git a/spec/services/merge_requests/post_merge_service_spec.rb b/spec/services/merge_requests/post_merge_service_spec.rb
index 402f753c0af..6523b5a158c 100644
--- a/spec/services/merge_requests/post_merge_service_spec.rb
+++ b/spec/services/merge_requests/post_merge_service_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe MergeRequests::PostMergeService do
describe '#execute' do
it_behaves_like 'cache counters invalidator'
+ it_behaves_like 'merge request reviewers cache counters invalidator'
it 'refreshes the number of open merge requests for a valid MR', :use_clean_rails_memory_store_caching do
# Cache the counter before the MR changed state.
@@ -37,6 +38,14 @@ RSpec.describe MergeRequests::PostMergeService do
subject
end
+ it 'calls the merge request activity counter' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_merge_mr_action)
+ .with(user: user)
+
+ subject
+ end
+
it 'deletes non-latest diffs' do
diff_removal_service = instance_double(MergeRequests::DeleteNonLatestDiffsService, execute: nil)
diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb
index 2bd83dc36a8..8541d597581 100644
--- a/spec/services/merge_requests/reopen_service_spec.rb
+++ b/spec/services/merge_requests/reopen_service_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe MergeRequests::ReopenService do
describe '#execute' do
it_behaves_like 'cache counters invalidator'
+ it_behaves_like 'merge request reviewers cache counters invalidator'
context 'valid params' do
let(:service) { described_class.new(project, user, {}) }
@@ -80,6 +81,14 @@ RSpec.describe MergeRequests::ReopenService do
described_class.new(project, user, {}).execute(merge_request)
end
+ it 'calls the merge request activity counter' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_reopen_mr_action)
+ .with(user: user)
+
+ described_class.new(project, user, {}).execute(merge_request)
+ end
+
it 'refreshes the number of open merge requests for a valid MR' do
service = described_class.new(project, user, {})
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index ed8872b71f7..9eb82dcd0ad 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -431,14 +431,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
describe 'merge' do
it_behaves_like 'correct merge behavior'
-
- context 'when merge_orchestration_service feature flag is disabled' do
- before do
- stub_feature_flags(merge_orchestration_service: false)
- end
-
- it_behaves_like 'correct merge behavior'
- end
end
context 'todos' do
@@ -529,6 +521,19 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
should_email(user2)
should_email(user3)
end
+
+ it 'updates open merge request counter for reviewers', :use_clean_rails_memory_store_caching do
+ merge_request.reviewers = [user3]
+
+ # Cache them to ensure the cache gets invalidated on update
+ expect(user2.review_requested_open_merge_requests_count).to eq(0)
+ expect(user3.review_requested_open_merge_requests_count).to eq(1)
+
+ update_merge_request(reviewer_ids: [user2.id])
+
+ expect(user2.review_requested_open_merge_requests_count).to eq(1)
+ expect(user3.review_requested_open_merge_requests_count).to eq(0)
+ end
end
context 'when the milestone is removed' do
@@ -837,20 +842,20 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
it 'does not allow a maintainer of the target project to set `allow_collaboration`' do
target_project.add_developer(user)
- update_merge_request(allow_collaboration: true, title: 'Updated title')
+ update_merge_request(allow_collaboration: false, title: 'Updated title')
expect(merge_request.title).to eq('Updated title')
- expect(merge_request.allow_collaboration).to be_falsy
+ expect(merge_request.allow_collaboration).to be_truthy
end
it 'is allowed by a user that can push to the source and can update the merge request' do
merge_request.update!(assignees: [user])
source_project.add_developer(user)
- update_merge_request(allow_collaboration: true, title: 'Updated title')
+ update_merge_request(allow_collaboration: false, title: 'Updated title')
expect(merge_request.title).to eq('Updated title')
- expect(merge_request.allow_collaboration).to be_truthy
+ expect(merge_request.allow_collaboration).to be_falsy
end
end
diff --git a/spec/services/namespaces/package_settings/update_service_spec.rb b/spec/services/namespaces/package_settings/update_service_spec.rb
new file mode 100644
index 00000000000..fa0c58e4c9b
--- /dev/null
+++ b/spec/services/namespaces/package_settings/update_service_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Namespaces::PackageSettings::UpdateService do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:namespace) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:params) { {} }
+
+ describe '#execute' do
+ subject { described_class.new(container: namespace, current_user: user, params: params).execute }
+
+ shared_examples 'returning a success' do
+ it 'returns a success' do
+ result = subject
+
+ expect(result.payload[:package_settings]).to be_present
+ expect(result.success?).to be_truthy
+ end
+ end
+
+ shared_examples 'returning an error' do |message, http_status|
+ it 'returns an error' do
+ result = subject
+
+ expect(result.message).to eq(message)
+ expect(result.status).to eq(:error)
+ expect(result.http_status).to eq(http_status)
+ end
+ end
+
+ shared_examples 'updating the namespace package setting' do
+ it_behaves_like 'updating the namespace package setting attributes', from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' }
+
+ it_behaves_like 'returning a success'
+
+ context 'with invalid params' do
+ let_it_be(:params) { { maven_duplicates_allowed: nil } }
+
+ it_behaves_like 'not creating the namespace package setting'
+
+ it "doesn't update the maven_duplicates_allowed" do
+ expect { subject }
+ .not_to change { package_settings.reload.maven_duplicates_allowed }
+ end
+
+ it_behaves_like 'returning an error', 'Maven duplicates allowed is not included in the list', 400
+ end
+ end
+
+ shared_examples 'denying access to namespace package setting' do
+ context 'with existing namespace package setting' do
+ it_behaves_like 'not creating the namespace package setting'
+
+ it_behaves_like 'returning an error', 'Access Denied', 403
+ end
+ end
+
+ context 'with existing namespace package setting' do
+ let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) }
+ let_it_be(:params) { { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' } }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'updating the namespace package setting'
+ :developer | 'updating the namespace package setting'
+ :reporter | 'denying access to namespace package setting'
+ :guest | 'denying access to namespace package setting'
+ :anonymous | 'denying access to namespace package setting'
+ end
+
+ with_them do
+ before do
+ namespace.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+
+ context 'without existing namespace package setting' do
+ let_it_be(:package_settings) { namespace.package_settings }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'creating the namespace package setting'
+ :developer | 'creating the namespace package setting'
+ :reporter | 'denying access to namespace package setting'
+ :guest | 'denying access to namespace package setting'
+ :anonymous | 'denying access to namespace package setting'
+ end
+
+ with_them do
+ before do
+ namespace.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+ end
+end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 3118956951e..20f06619e02 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -78,6 +78,12 @@ RSpec.describe Notes::CreateService do
end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
end
+ it 'does not track merge request usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).not_to receive(:track_create_comment_action)
+
+ described_class.new(project, user, opts).execute
+ end
+
context 'in a merge request' do
let_it_be(:project_with_repo) { create(:project, :repository) }
let_it_be(:merge_request) do
@@ -85,18 +91,6 @@ RSpec.describe Notes::CreateService do
target_project: project_with_repo)
end
- context 'issue comment usage data' do
- let(:opts) do
- { note: 'Awesome comment', noteable_type: 'MergeRequest', noteable_id: merge_request.id }
- end
-
- it 'does not track' do
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_added_action)
-
- described_class.new(project, user, opts).execute
- end
- end
-
context 'noteable highlight cache clearing' do
let(:position) do
Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
@@ -119,6 +113,18 @@ RSpec.describe Notes::CreateService do
.to receive(:unfolded_diff?) { true }
end
+ it 'does not track issue comment usage data' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_added_action)
+
+ described_class.new(project_with_repo, user, new_opts).execute
+ end
+
+ it 'tracks merge request usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).to receive(:track_create_comment_action).with(note: kind_of(Note))
+
+ described_class.new(project_with_repo, user, new_opts).execute
+ end
+
it 'clears noteable diff cache when it was unfolded for the note position' do
expect_any_instance_of(Gitlab::Diff::HighlightCache).to receive(:clear)
diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb
index 0859c28cbe7..eebbdcc33b8 100644
--- a/spec/services/notes/destroy_service_spec.rb
+++ b/spec/services/notes/destroy_service_spec.rb
@@ -35,6 +35,14 @@ RSpec.describe Notes::DestroyService do
end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
end
+ it 'tracks merge request usage data' do
+ mr = create(:merge_request, source_project: project)
+ note = create(:note, project: project, noteable: mr)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).to receive(:track_remove_comment_action).with(note: note)
+
+ described_class.new(project, user).execute(note)
+ end
+
context 'in a merge request' do
let_it_be(:repo_project) { create(:project, :repository) }
let_it_be(:merge_request) do
diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb
index 64aa845841b..c098500b78a 100644
--- a/spec/services/notes/quick_actions_service_spec.rb
+++ b/spec/services/notes/quick_actions_service_spec.rb
@@ -153,8 +153,8 @@ RSpec.describe Notes::QuickActionsService do
expect(execute(note)).to be_empty
end
- it 'does not assign the milestone' do
- expect { execute(note) }.not_to change { issue.reload.milestone }
+ it 'assigns the milestone' do
+ expect { execute(note) }.to change { issue.reload.milestone }.from(nil).to(milestone)
end
end
@@ -195,8 +195,8 @@ RSpec.describe Notes::QuickActionsService do
expect(execute(note)).to be_empty
end
- it 'does not remove the milestone' do
- expect { execute(note) }.not_to change { issue.reload.milestone }
+ it 'removes the milestone' do
+ expect { execute(note) }.to change { issue.reload.milestone }.from(milestone).to(nil)
end
end
diff --git a/spec/services/notes/update_service_spec.rb b/spec/services/notes/update_service_spec.rb
index e2f51c9af67..902fd9958f8 100644
--- a/spec/services/notes/update_service_spec.rb
+++ b/spec/services/notes/update_service_spec.rb
@@ -49,11 +49,12 @@ RSpec.describe Notes::UpdateService do
it 'does not track usage data when params is blank' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_edited_action)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).not_to receive(:track_edit_comment_action)
update_note({})
end
- it 'tracks usage data', :clean_gitlab_redis_shared_state do
+ it 'tracks issue usage data', :clean_gitlab_redis_shared_state do
event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_EDITED
counter = Gitlab::UsageDataCounters::HLLRedisCounter
@@ -63,6 +64,17 @@ RSpec.describe Notes::UpdateService do
end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
end
+ context 'when the notable is a merge request' do
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:note) { create(:note, project: project, noteable: merge_request, author: user, note: "Old note #{user2.to_reference}") }
+
+ it 'tracks merge request usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).to receive(:track_edit_comment_action).with(note: note)
+
+ update_note(note: 'new text')
+ end
+ end
+
context 'with system note' do
before do
note.update_column(:system, true)
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 9431c023850..85234077b1f 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -2455,6 +2455,18 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { group.add_guest(added_user) }
end
end
+
+ describe '#updated_group_member_expiration' do
+ let_it_be(:group_member) { create(:group_member) }
+
+ it 'emails the user that their group membership expiry has changed' do
+ expect_next_instance_of(NotificationService) do |notification|
+ allow(notification).to receive(:updated_group_member_expiration).with(group_member)
+ end
+
+ group_member.update!(expires_at: 5.days.from_now)
+ end
+ end
end
describe 'ProjectMember', :deliver_mails_inline do
diff --git a/spec/services/onboarding_progress_service_spec.rb b/spec/services/onboarding_progress_service_spec.rb
index 59b6083d38a..340face4ae8 100644
--- a/spec/services/onboarding_progress_service_spec.rb
+++ b/spec/services/onboarding_progress_service_spec.rb
@@ -5,28 +5,44 @@ require 'spec_helper'
RSpec.describe OnboardingProgressService do
describe '#execute' do
let(:namespace) { create(:namespace, parent: root_namespace) }
+ let(:root_namespace) { nil }
+ let(:action) { :namespace_action }
subject(:execute_service) { described_class.new(namespace).execute(action: :subscription_created) }
context 'when the namespace is a root' do
- let(:root_namespace) { nil }
+ before do
+ OnboardingProgress.onboard(namespace)
+ end
- it 'records a namespace onboarding progress action for the given namespace' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(namespace, :subscription_created).and_call_original
+ it 'registers a namespace onboarding progress action for the given namespace' do
+ execute_service
- expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1)
+ expect(OnboardingProgress.completed?(namespace, :subscription_created)).to eq(true)
end
end
context 'when the namespace is not the root' do
- let_it_be(:root_namespace) { build(:namespace) }
+ let(:root_namespace) { build(:namespace) }
+
+ before do
+ OnboardingProgress.onboard(root_namespace)
+ end
+
+ it 'registers a namespace onboarding progress action for the root namespace' do
+ execute_service
+
+ expect(OnboardingProgress.completed?(root_namespace, :subscription_created)).to eq(true)
+ end
+ end
+
+ context 'when no namespace is passed' do
+ let(:namespace) { nil }
- it 'records a namespace onboarding progress action for the root namespace' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(root_namespace, :subscription_created).and_call_original
+ it 'does not register a namespace onboarding progress action' do
+ execute_service
- expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1)
+ expect(OnboardingProgress.completed?(root_namespace, :subscription_created)).to be(nil)
end
end
end
diff --git a/spec/services/packages/create_event_service_spec.rb b/spec/services/packages/create_event_service_spec.rb
index f581d704087..f7bab0e5a9f 100644
--- a/spec/services/packages/create_event_service_spec.rb
+++ b/spec/services/packages/create_event_service_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe Packages::CreateEventService do
end
end
- shared_examples 'redis package event creation' do |originator_type, expected_scope|
+ shared_examples 'redis package unique event creation' do |originator_type, expected_scope|
context 'with feature flag disable' do
before do
stub_feature_flags(collect_package_events_redis: false)
@@ -70,29 +70,27 @@ RSpec.describe Packages::CreateEventService do
end
it 'tracks the event' do
- expect(::Gitlab::UsageDataCounters::GuestPackageEventCounter).not_to receive(:count)
- expect(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(user.id, Packages::Event.allowed_event_name(expected_scope, event_name, originator_type))
+ expect(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(/package/, values: user.id)
subject
end
end
- shared_examples 'redis package guest event creation' do |originator_type, expected_scope|
+ shared_examples 'redis package count event creation' do |originator_type, expected_scope|
context 'with feature flag disabled' do
before do
stub_feature_flags(collect_package_events_redis: false)
end
it 'does not track the event' do
- expect(::Gitlab::UsageDataCounters::GuestPackageEventCounter).not_to receive(:count)
+ expect(::Gitlab::UsageDataCounters::PackageEventCounter).not_to receive(:count)
subject
end
end
it 'tracks the event' do
- expect(::Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
- expect(::Gitlab::UsageDataCounters::GuestPackageEventCounter).to receive(:count).with(Packages::Event.allowed_event_name(expected_scope, event_name, originator_type))
+ expect(::Gitlab::UsageDataCounters::PackageEventCounter).to receive(:count).at_least(:once)
subject
end
@@ -102,21 +100,23 @@ RSpec.describe Packages::CreateEventService do
let(:user) { create(:user) }
it_behaves_like 'db package event creation', 'user', 'container'
- it_behaves_like 'redis package event creation', 'user', 'container'
+ it_behaves_like 'redis package unique event creation', 'user', 'container'
+ it_behaves_like 'redis package count event creation', 'user', 'container'
end
context 'with a deploy token' do
let(:user) { create(:deploy_token) }
it_behaves_like 'db package event creation', 'deploy_token', 'container'
- it_behaves_like 'redis package event creation', 'deploy_token', 'container'
+ it_behaves_like 'redis package unique event creation', 'deploy_token', 'container'
+ it_behaves_like 'redis package count event creation', 'deploy_token', 'container'
end
context 'with no user' do
let(:user) { nil }
it_behaves_like 'db package event creation', 'guest', 'container'
- it_behaves_like 'redis package guest event creation', 'guest', 'container'
+ it_behaves_like 'redis package count event creation', 'guest', 'container'
end
context 'with a package as scope' do
@@ -126,14 +126,15 @@ RSpec.describe Packages::CreateEventService do
let(:user) { nil }
it_behaves_like 'db package event creation', 'guest', 'npm'
- it_behaves_like 'redis package guest event creation', 'guest', 'npm'
+ it_behaves_like 'redis package count event creation', 'guest', 'npm'
end
context 'with user' do
let(:user) { create(:user) }
it_behaves_like 'db package event creation', 'user', 'npm'
- it_behaves_like 'redis package event creation', 'user', 'npm'
+ it_behaves_like 'redis package unique event creation', 'user', 'npm'
+ it_behaves_like 'redis package count event creation', 'user', 'npm'
end
end
end
diff --git a/spec/services/packages/debian/create_package_file_service_spec.rb b/spec/services/packages/debian/create_package_file_service_spec.rb
new file mode 100644
index 00000000000..74b97a4f941
--- /dev/null
+++ b/spec/services/packages/debian/create_package_file_service_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::CreatePackageFileService do
+ include WorkhorseHelpers
+
+ let_it_be(:package) { create(:debian_incoming, without_package_files: true) }
+
+ describe '#execute' do
+ let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
+ let(:fixture_path) { "spec/fixtures/packages/debian/#{file_name}" }
+
+ let(:params) do
+ {
+ file: file,
+ file_name: file_name,
+ file_sha1: '54321',
+ file_md5: '12345'
+ }.with_indifferent_access
+ end
+
+ let(:service) { described_class.new(package, params) }
+
+ subject(:package_file) { service.execute }
+
+ shared_examples 'a valid deb' do
+ it 'creates a new package file', :aggregate_failures do
+ expect(package_file).to be_valid
+ expect(package_file.file.read).to start_with('!<arch>')
+ expect(package_file.size).to eq(1124)
+ expect(package_file.file_name).to eq(file_name)
+ expect(package_file.file_sha1).to eq('54321')
+ expect(package_file.file_sha256).to eq('543212345')
+ expect(package_file.file_md5).to eq('12345')
+ expect(package_file.debian_file_metadatum).to be_valid
+ expect(package_file.debian_file_metadatum.file_type).to eq('unknown')
+ expect(package_file.debian_file_metadatum.architecture).to be_nil
+ expect(package_file.debian_file_metadatum.fields).to be_nil
+ end
+ end
+
+ context 'with temp file' do
+ let!(:file) do
+ upload_path = ::Packages::PackageFileUploader.workhorse_local_upload_path
+ file_path = upload_path + '/' + file_name
+
+ FileUtils.mkdir_p(upload_path)
+ File.write(file_path, File.read(fixture_path))
+
+ UploadedFile.new(file_path, filename: File.basename(file_path), sha256: '543212345')
+ end
+
+ it_behaves_like 'a valid deb'
+ end
+
+ context 'with remote file' do
+ let!(:fog_connection) do
+ stub_package_file_object_storage(direct_upload: true)
+ end
+
+ before do
+ allow_next_instance_of(UploadedFile) do |uploaded_file|
+ allow(uploaded_file).to receive(:sha256).and_return('543212345')
+ end
+ end
+
+ let(:tmp_object) do
+ fog_connection.directories.new(key: 'packages').files.create( # rubocop:disable Rails/SaveBang
+ key: "tmp/uploads/#{file_name}",
+ body: File.read(fixture_path)
+ )
+ end
+
+ let!(:file) { fog_to_uploaded_file(tmp_object) }
+
+ it_behaves_like 'a valid deb'
+ end
+
+ context 'package is missing' do
+ let(:package) { nil }
+ let(:params) { {} }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(ArgumentError, 'Invalid package')
+ end
+ end
+
+ context 'params is empty' do
+ let(:params) { {} }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
+ context 'file is missing' do
+ let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
+ let(:file) { nil }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/debian/extract_metadata_service_spec.rb b/spec/services/packages/debian/extract_metadata_service_spec.rb
new file mode 100644
index 00000000000..0aa9a67b263
--- /dev/null
+++ b/spec/services/packages/debian/extract_metadata_service_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ExtractMetadataService do
+ let(:service) { described_class.new(package_file) }
+
+ subject { service.execute }
+
+ RSpec.shared_context 'Debian ExtractMetadata Service' do |trait|
+ let(:package_file) { create(:debian_package_file, trait) }
+ end
+
+ RSpec.shared_examples 'Test Debian ExtractMetadata Service' do |expected_file_type, expected_architecture, expected_fields|
+ it "returns file_type #{expected_file_type.inspect}" do
+ expect(subject[:file_type]).to eq(expected_file_type)
+ end
+
+ it "returns architecture #{expected_architecture.inspect}" do
+ expect(subject[:architecture]).to eq(expected_architecture)
+ end
+
+ it "returns fields #{expected_fields.nil? ? '' : 'including '}#{expected_fields.inspect}" do
+ if expected_fields.nil?
+ expect(subject[:fields]).to be_nil
+ else
+ expect(subject[:fields]).to include(**expected_fields)
+ end
+ end
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:case_name, :trait, :expected_file_type, :expected_architecture, :expected_fields) do
+ 'with invalid' | :invalid | :unknown | nil | nil
+ 'with source' | :source | :source | nil | nil
+ 'with dsc' | :dsc | :dsc | nil | { 'Binary': 'sample-dev, libsample0, sample-udeb' }
+ 'with deb' | :deb | :deb | 'amd64' | { 'Multi-Arch': 'same' }
+ 'with udeb' | :udeb | :udeb | 'amd64' | { 'Package': 'sample-udeb' }
+ 'with buildinfo' | :buildinfo | :buildinfo | nil | { 'Architecture': 'amd64 source', 'Build-Architecture': 'amd64' }
+ 'with changes' | :changes | :changes | nil | { 'Architecture': 'source amd64', 'Binary': 'libsample0 sample-dev sample-udeb' }
+ end
+
+ with_them do
+ include_context 'Debian ExtractMetadata Service', params[:trait] do
+ it_behaves_like 'Test Debian ExtractMetadata Service',
+ params[:expected_file_type],
+ params[:expected_architecture],
+ params[:expected_fields]
+ end
+ end
+
+ context 'with invalid package file' do
+ let(:package_file) { create(:conan_package_file) }
+
+ it 'raise error' do
+ expect { subject }.to raise_error(described_class::ExtractionError, 'invalid package file')
+ end
+ end
+end
diff --git a/spec/services/packages/debian/get_or_create_incoming_service_spec.rb b/spec/services/packages/debian/get_or_create_incoming_service_spec.rb
new file mode 100644
index 00000000000..ab99b091246
--- /dev/null
+++ b/spec/services/packages/debian/get_or_create_incoming_service_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GetOrCreateIncomingService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ subject(:service) { described_class.new(project, user) }
+
+ describe '#execute' do
+ subject(:package) { service.execute }
+
+ context 'run once' do
+ it 'creates a new package', :aggregate_failures do
+ expect(package).to be_valid
+ expect(package.project_id).to eq(project.id)
+ expect(package.creator_id).to eq(user.id)
+ expect(package.name).to eq('incoming')
+ expect(package.version).to be_nil
+ expect(package.package_type).to eq('debian')
+ expect(package.debian_incoming?).to be_truthy
+ end
+
+ it_behaves_like 'assigns the package creator'
+ end
+
+ context 'run twice' do
+ let!(:package2) { service.execute }
+
+ it 'returns the same object' do
+ expect(package2.id).to eq(package.id)
+ end
+ end
+ 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 2eaad7db445..82dffeefcde 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
@@ -11,29 +11,36 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
let(:file_name) { 'test.jar' }
let(:param_path) { "#{path}/#{version}" }
let(:params) { { path: param_path, file_name: file_name } }
+ let(:service) { described_class.new(project, user, params) }
describe '#execute' do
using RSpec::Parameterized::TableSyntax
- subject { described_class.new(project, user, params).execute }
+ subject { service.execute }
- RSpec.shared_examples 'reuse existing package' do
- it { expect { subject}.not_to change { Packages::Package.count } }
+ shared_examples 'reuse existing package' do
+ it { expect { subject }.not_to change { Packages::Package.count } }
- it { is_expected.to eq(existing_package) }
+ it 'returns the existing package' do
+ expect(subject.payload).to eq(package: existing_package)
+ end
end
- RSpec.shared_examples 'create package' do
+ shared_examples 'create package' do
it { expect { subject }.to change { Packages::Package.count }.by(1) }
- it 'sets the proper name and version' do
- pkg = subject
+ it 'sets the proper name and version', :aggregate_failures do
+ pkg = subject.payload[:package]
expect(pkg.name).to eq(path)
expect(pkg.version).to eq(version)
end
- it_behaves_like 'assigns build to package'
+ context 'with a build' do
+ subject { service.execute.payload[:package] }
+
+ it_behaves_like 'assigns build to package'
+ end
end
context 'path with version' do
@@ -90,5 +97,36 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
expect { subject }.to change { Packages::BuildInfo.count }.by(1)
end
end
+
+ context 'when package duplicates are not allowed' do
+ let_it_be_with_refind(:package_settings) { create(:namespace_package_setting, :group, maven_duplicates_allowed: false) }
+ let_it_be_with_refind(:group) { package_settings.namespace }
+ let_it_be_with_refind(:project) { create(:project, group: group) }
+ let!(:existing_package) { create(:maven_package, name: path, version: version, project: project) }
+
+ it { expect { subject }.not_to change { project.package_files.count } }
+
+ it 'returns an error', :aggregate_failures do
+ expect(subject.payload).to be_empty
+ expect(subject.errors).to include('Duplicate package is not allowed')
+ 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')
+ package_file.destroy!
+ end
+
+ it_behaves_like 'reuse existing package'
+ end
+
+ context 'when the package name matches the exception regex' do
+ before do
+ package_settings.update!(maven_duplicate_exception_regex: '.*')
+ end
+
+ it_behaves_like 'reuse existing package'
+ end
+ end
end
end
diff --git a/spec/services/packages/nuget/search_service_spec.rb b/spec/services/packages/nuget/search_service_spec.rb
index d163e7087e4..db758dc6672 100644
--- a/spec/services/packages/nuget/search_service_spec.rb
+++ b/spec/services/packages/nuget/search_service_spec.rb
@@ -1,8 +1,12 @@
# frozen_string_literal: true
+
require 'spec_helper'
RSpec.describe Packages::Nuget::SearchService do
- let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project) { create(:project, namespace: subgroup) }
let_it_be(:package_a) { create(:nuget_package, project: project, name: 'DummyPackageA') }
let_it_be(:packages_b) { create_list(:nuget_package, 5, project: project, name: 'DummyPackageB') }
let_it_be(:packages_c) { create_list(:nuget_package, 5, project: project, name: 'DummyPackageC') }
@@ -16,94 +20,126 @@ RSpec.describe Packages::Nuget::SearchService do
let(:options) { { include_prerelease_versions: include_prerelease_versions, per_page: per_page, padding: padding } }
describe '#execute' do
- subject { described_class.new(project, search_term, options).execute }
+ subject { described_class.new(user, target, search_term, options).execute }
- it { expect_search_results 3, package_a, packages_b, packages_c }
+ shared_examples 'handling all the conditions' do
+ it { expect_search_results 3, package_a, packages_b, packages_c }
- context 'with a smaller per page count' do
- let(:per_page) { 2 }
+ context 'with a smaller per page count' do
+ let(:per_page) { 2 }
- it { expect_search_results 3, package_a, packages_b }
- end
+ it { expect_search_results 3, package_a, packages_b }
+ end
- context 'with 0 per page count' do
- let(:per_page) { 0 }
+ context 'with 0 per page count' do
+ let(:per_page) { 0 }
- it { expect_search_results 3, [] }
- end
+ it { expect_search_results 3, [] }
+ end
- context 'with a negative per page count' do
- let(:per_page) { -1 }
+ context 'with a negative per page count' do
+ let(:per_page) { -1 }
- it { expect { subject }.to raise_error(ArgumentError, 'negative per_page') }
- end
+ it { expect { subject }.to raise_error(ArgumentError, 'negative per_page') }
+ end
- context 'with a padding' do
- let(:padding) { 2 }
+ context 'with a padding' do
+ let(:padding) { 2 }
- it { expect_search_results 3, packages_c }
- end
+ it { expect_search_results 3, packages_c }
+ end
- context 'with a too big padding' do
- let(:padding) { 5 }
+ context 'with a too big padding' do
+ let(:padding) { 5 }
- it { expect_search_results 3, [] }
- end
+ it { expect_search_results 3, [] }
+ end
- context 'with a negative padding' do
- let(:padding) { -1 }
+ context 'with a negative padding' do
+ let(:padding) { -1 }
- it { expect { subject }.to raise_error(ArgumentError, 'negative padding') }
- end
+ it { expect { subject }.to raise_error(ArgumentError, 'negative padding') }
+ end
- context 'with search term' do
- let(:search_term) { 'umm' }
+ context 'with search term' do
+ let(:search_term) { 'umm' }
- it { expect_search_results 3, package_a, packages_b, packages_c }
- end
+ it { expect_search_results 3, package_a, packages_b, packages_c }
+ end
- context 'with nil search term' do
- let(:search_term) { nil }
+ context 'with nil search term' do
+ let(:search_term) { nil }
- it { expect_search_results 4, package_a, packages_b, packages_c, package_d }
- end
+ it { expect_search_results 4, package_a, packages_b, packages_c, package_d }
+ end
- context 'with empty search term' do
- let(:search_term) { '' }
+ context 'with empty search term' do
+ let(:search_term) { '' }
- it { expect_search_results 4, package_a, packages_b, packages_c, package_d }
- end
+ it { expect_search_results 4, package_a, packages_b, packages_c, package_d }
+ end
- context 'with prefix search term' do
- let(:search_term) { 'dummy' }
+ context 'with prefix search term' do
+ let(:search_term) { 'dummy' }
- it { expect_search_results 3, package_a, packages_b, packages_c }
- end
+ it { expect_search_results 3, package_a, packages_b, packages_c }
+ end
+
+ context 'with suffix search term' do
+ let(:search_term) { 'packagec' }
+
+ it { expect_search_results 1, packages_c }
+ end
+
+ context 'with pre release packages' do
+ let_it_be(:package_e) { create(:nuget_package, project: project, name: 'DummyPackageE', version: '3.2.1-alpha') }
+
+ context 'including them' do
+ it { expect_search_results 4, package_a, packages_b, packages_c, package_e }
+ end
+
+ context 'excluding them' do
+ let(:include_prerelease_versions) { false }
- context 'with suffix search term' do
- let(:search_term) { 'packagec' }
+ it { expect_search_results 3, package_a, packages_b, packages_c }
- it { expect_search_results 1, packages_c }
+ context 'when mixed with release versions' do
+ let_it_be(:package_e_release) { create(:nuget_package, project: project, name: 'DummyPackageE', version: '3.2.1') }
+
+ it { expect_search_results 4, package_a, packages_b, packages_c, package_e_release }
+ end
+ end
+ end
end
- context 'with pre release packages' do
- let_it_be(:package_e) { create(:nuget_package, project: project, name: 'DummyPackageE', version: '3.2.1-alpha') }
+ context 'with project' do
+ let(:target) { project }
- context 'including them' do
- it { expect_search_results 4, package_a, packages_b, packages_c, package_e }
+ before do
+ project.add_developer(user)
end
- context 'excluding them' do
- let(:include_prerelease_versions) { false }
+ it_behaves_like 'handling all the conditions'
+ end
- it { expect_search_results 3, package_a, packages_b, packages_c }
+ context 'with subgroup' do
+ let(:target) { subgroup }
- context 'when mixed with release versions' do
- let_it_be(:package_e_release) { create(:nuget_package, project: project, name: 'DummyPackageE', version: '3.2.1') }
+ before do
+ subgroup.add_developer(user)
+ end
- it { expect_search_results 4, package_a, packages_b, packages_c, package_e_release }
- end
+ it_behaves_like 'handling all the conditions'
+ end
+
+ context 'with group' do
+ let(:target) { group }
+
+ before do
+ group.add_developer(user)
end
+
+ it_behaves_like 'handling all the conditions'
end
def expect_search_results(total_count, *results)
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
new file mode 100644
index 00000000000..29023621413
--- /dev/null
+++ b/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Pages::MigrateLegacyStorageToDeploymentService do
+ let(:project) { create(:project, :repository) }
+ let(:service) { described_class.new(project) }
+
+ it 'marks pages as not deployed if public directory is absent' do
+ project.mark_pages_as_deployed
+
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+
+ expect(service.execute).to(
+ eq(status: :error,
+ message: "Can't create zip archive: Can not find valid public dir in #{project.pages_path}")
+ )
+
+ expect(project.pages_metadatum.reload.deployed).to eq(false)
+ end
+
+ it 'does not mark pages as not deployed if public directory is absent but pages_deployment exists' do
+ deployment = create(:pages_deployment, project: project)
+ project.update_pages_deployment!(deployment)
+ project.mark_pages_as_deployed
+
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+
+ expect(service.execute).to(
+ eq(status: :error,
+ message: "Can't create zip archive: Can not find valid public dir in #{project.pages_path}")
+ )
+
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+ end
+
+ it 'does not mark pages as not deployed if public directory is absent but feature is disabled' do
+ stub_feature_flags(pages_migration_mark_as_not_deployed: false)
+
+ project.mark_pages_as_deployed
+
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+
+ expect(service.execute).to(
+ eq(status: :error,
+ message: "Can't create zip archive: Can not find valid public dir in #{project.pages_path}")
+ )
+
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+ end
+
+ it 'removes pages archive when can not save deployment' do
+ archive = fixture_file_upload("spec/fixtures/pages.zip")
+ expect_next_instance_of(::Pages::ZipDirectoryService) do |zip_service|
+ expect(zip_service).to receive(:execute).and_return(status: :success,
+ archive_path: archive.path,
+ entries_count: 3)
+ end
+
+ expect_next_instance_of(PagesDeployment) do |deployment|
+ expect(deployment).to receive(:save!).and_raise("Something")
+ end
+
+ expect do
+ service.execute
+ end.to raise_error("Something")
+
+ expect(File.exist?(archive.path)).to eq(false)
+ end
+
+ context 'when pages site is deployed to legacy storage' 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 'creates pages deployment' do
+ expect do
+ expect(described_class.new(project).execute).to eq(status: :success)
+ end.to change { project.reload.pages_deployments.count }.by(1)
+
+ deployment = project.pages_metadatum.pages_deployment
+
+ Zip::File.open(deployment.file.path) do |zip_file|
+ expect(zip_file.glob("public").first.ftype).to eq(:directory)
+ expect(zip_file.glob("public/index.html").first.get_input_stream.read).to eq("Hello!")
+ end
+
+ expect(deployment.file_count).to eq(2)
+ expect(deployment.file_sha256).to eq(Digest::SHA256.file(deployment.file.path).hexdigest)
+ end
+
+ it 'removes tmp pages archive' do
+ described_class.new(project).execute
+
+ expect(File.exist?(File.join(project.pages_path, '@migrated.zip'))).to eq(false)
+ end
+
+ it 'does not change pages deployment if it is set' do
+ old_deployment = create(:pages_deployment, project: project)
+ project.update_pages_deployment!(old_deployment)
+
+ expect do
+ described_class.new(project).execute
+ end.not_to change { project.pages_metadatum.reload.pages_deployment_id }.from(old_deployment.id)
+ end
+
+ it 'raises exception if exclusive lease is taken' do
+ described_class.new(project).try_obtain_lease do
+ expect do
+ described_class.new(project).execute
+ end.to raise_error(described_class::ExclusiveLeaseTakenError)
+ end
+ end
+ end
+end
diff --git a/spec/services/pages/zip_directory_service_spec.rb b/spec/services/pages/zip_directory_service_spec.rb
index 1568103d102..dcab6b2dada 100644
--- a/spec/services/pages/zip_directory_service_spec.rb
+++ b/spec/services/pages/zip_directory_service_spec.rb
@@ -14,19 +14,35 @@ RSpec.describe Pages::ZipDirectoryService do
described_class.new(@work_dir).execute
end
- let(:archive) { result.first }
- let(:entries_count) { result.second }
+ let(:status) { result[:status] }
+ let(:message) { result[:message] }
+ let(:archive) { result[:archive_path] }
+ let(:entries_count) { result[:entries_count] }
+
+ it 'returns error if project pages dir does not exist' do
+ 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")
+ end
+
+ it 'returns nils if there is no public directory and does not leave archive' do
+ expect(status).to eq(:error)
+ expect(message).to eq("Can not find valid public dir in #{@work_dir}")
+ expect(archive).to eq(nil)
+ expect(entries_count).to eq(nil)
- it 'raises error if there is no public directory' do
- expect { archive }.to raise_error(described_class::InvalidArchiveError)
+ expect(File.exist?(File.join(@work_dir, '@migrated.zip'))).to eq(false)
end
- it 'raises error if public directory is a symlink' do
+ it 'returns nils if public directory is a symlink' do
create_dir('target')
create_file('./target/index.html', 'hello')
create_link("public", "./target")
- expect { archive }.to raise_error(described_class::InvalidArchiveError)
+ expect(status).to eq(:error)
+ expect(message).to eq("Can not find valid public dir in #{@work_dir}")
+ expect(archive).to eq(nil)
+ expect(entries_count).to eq(nil)
end
context 'when there is a public directory' do
diff --git a/spec/services/post_receive_service_spec.rb b/spec/services/post_receive_service_spec.rb
index 4e303bfc20a..6e2cd7edf04 100644
--- a/spec/services/post_receive_service_spec.rb
+++ b/spec/services/post_receive_service_spec.rb
@@ -4,6 +4,7 @@ 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) }
@@ -46,8 +47,8 @@ RSpec.describe PostReceiveService do
expect(subject).to be_empty
end
- it 'does not record a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).not_to receive(:create_action)
+ it 'does not record an onboarding progress action' do
+ expect_next(OnboardingProgressService).not_to receive(:execute)
subject
end
@@ -87,9 +88,9 @@ RSpec.describe PostReceiveService do
expect(response.reference_counter_decreased).to be(true)
end
- it 'records a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(project.namespace, :git_write)
+ it 'records an onboarding progress action' do
+ expect_next(OnboardingProgressService, project.namespace)
+ .to receive(:execute).with(action: :git_write)
subject
end
diff --git a/spec/services/projects/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb
index a109348ea19..a16aec891a9 100644
--- a/spec/services/projects/after_import_service_spec.rb
+++ b/spec/services/projects/after_import_service_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Projects::AfterImportService do
describe '#execute' do
before do
- allow(Projects::HousekeepingService)
+ allow(Repositories::HousekeepingService)
.to receive(:new).with(project).and_return(housekeeping_service)
allow(housekeeping_service)
@@ -73,10 +73,10 @@ RSpec.describe Projects::AfterImportService do
end
context 'when housekeeping service lease is taken' do
- let(:exception) { Projects::HousekeepingService::LeaseTaken.new }
+ let(:exception) { Repositories::HousekeepingService::LeaseTaken.new }
it 'logs the error message' do
- allow_next_instance_of(Projects::HousekeepingService) do |instance|
+ allow_next_instance_of(Repositories::HousekeepingService) do |instance|
expect(instance).to receive(:execute).and_raise(exception)
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 8ddcb8ce660..17c2f0f6c17 100644
--- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -3,11 +3,14 @@
require 'spec_helper'
RSpec.describe Projects::ContainerRepository::CleanupTagsService do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :private) }
let_it_be(:repository) { create(:container_repository, :root, project: project) }
let(:service) { described_class.new(project, user, params) }
+ let(:tags) { %w[latest A Ba Bb C D E] }
before do
project.add_maintainer(user)
@@ -16,7 +19,8 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
stub_container_registry_tags(
repository: repository.path,
- tags: %w(latest A Ba Bb C D E))
+ tags: tags
+ )
stub_tag_digest('latest', 'sha256:configA')
stub_tag_digest('A', 'sha256:configA')
@@ -30,6 +34,8 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
stub_digest_config('sha256:configB', 5.days.ago)
stub_digest_config('sha256:configC', 1.month.ago)
stub_digest_config('sha256:configD', nil)
+
+ stub_feature_flags(container_registry_expiration_policies_throttling: false)
end
describe '#execute' do
@@ -42,7 +48,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
expect_any_instance_of(Projects::ContainerRepository::DeleteTagsService)
.not_to receive(:execute)
- is_expected.to include(status: :success, deleted: [])
+ is_expected.to eq(expected_service_response(before_truncate_size: 0, after_truncate_size: 0, before_delete_size: 0))
end
end
@@ -51,7 +57,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does remove all tags except latest' do
expect_delete(%w(A Ba Bb C D E))
- is_expected.to include(status: :success, deleted: %w(A Ba Bb C D E))
+ is_expected.to eq(expected_service_response(deleted: %w(A Ba Bb C D E)))
end
end
@@ -78,12 +84,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
subject
end
- it 'returns an error' do
- response = subject
-
- expect(response[:status]).to eq(:error)
- expect(response[:message]).to eq('invalid regex')
- end
+ it { is_expected.to eq(status: :error, message: 'invalid regex') }
it 'calls error tracking service' do
expect(Gitlab::ErrorTracking).to receive(:log_exception).and_call_original
@@ -119,7 +120,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does remove C and D' do
expect_delete(%w(C D))
- is_expected.to include(status: :success, deleted: %w(C D))
+ is_expected.to eq(expected_service_response(deleted: %w(C D), before_truncate_size: 2, after_truncate_size: 2, before_delete_size: 2))
end
context 'with overriding allow regex' do
@@ -131,7 +132,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does not remove C' do
expect_delete(%w(D))
- is_expected.to include(status: :success, deleted: %w(D))
+ is_expected.to eq(expected_service_response(deleted: %w(D), before_truncate_size: 1, after_truncate_size: 1, before_delete_size: 1))
end
end
@@ -144,7 +145,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does not remove C' do
expect_delete(%w(D))
- is_expected.to include(status: :success, deleted: %w(D))
+ is_expected.to eq(expected_service_response(deleted: %w(D), before_truncate_size: 1, after_truncate_size: 1, before_delete_size: 1))
end
end
end
@@ -158,7 +159,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does not remove B*' do
expect_delete(%w(A C D E))
- is_expected.to include(status: :success, deleted: %w(A C D E))
+ is_expected.to eq(expected_service_response(deleted: %w(A C D E), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 4))
end
end
@@ -173,7 +174,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
expect(service).to receive(:order_by_date).and_call_original
- is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 3))
end
end
@@ -187,7 +188,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
expect(service).not_to receive(:order_by_date)
- is_expected.to include(status: :success, deleted: %w(A Ba Bb C))
+ is_expected.to eq(expected_service_response(deleted: %w(A Ba Bb C), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 4))
end
end
@@ -200,7 +201,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does remove B* and C as they are the oldest' do
expect_delete(%w(Bb Ba C))
- is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
end
end
@@ -213,7 +214,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does remove B* and C as they are older than 1 day' do
expect_delete(%w(Ba Bb C))
- is_expected.to include(status: :success, deleted: %w(Ba Bb C))
+ is_expected.to eq(expected_service_response(deleted: %w(Ba Bb C), before_delete_size: 3))
end
end
@@ -227,7 +228,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'does remove B* and C' do
expect_delete(%w(Bb Ba C))
- is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
end
end
@@ -245,7 +246,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
it 'succeeds without a user' do
expect_delete(%w(Bb Ba C), container_expiration_policy: true)
- is_expected.to include(status: :success, deleted: %w(Bb Ba C))
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
end
end
@@ -257,10 +258,73 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
end
it 'fails' do
- is_expected.to include(status: :error, message: 'access denied')
+ is_expected.to eq(status: :error, message: 'access denied')
end
end
end
+
+ context 'truncating the tags list' do
+ let(:params) do
+ {
+ 'name_regex_delete' => '.*',
+ 'keep_n' => 1
+ }
+ end
+
+ shared_examples 'returning the response' do |status:, original_size:, before_truncate_size:, after_truncate_size:, before_delete_size:|
+ it 'returns the response' do
+ result = subject
+
+ service_response = expected_service_response(
+ status: status,
+ original_size: original_size,
+ before_truncate_size: before_truncate_size,
+ after_truncate_size: after_truncate_size,
+ before_delete_size: before_delete_size,
+ deleted: nil
+ )
+
+ expect(result).to eq(service_response.compact)
+ end
+ end
+
+ where(:feature_flag_enabled, :max_list_size, :delete_tags_service_status, :expected_status, :expected_truncated) do
+ false | 10 | :success | :success | false
+ false | 10 | :error | :error | false
+ false | 3 | :success | :success | false
+ false | 3 | :error | :error | false
+ false | 0 | :success | :success | false
+ false | 0 | :error | :error | false
+ true | 10 | :success | :success | false
+ true | 10 | :error | :error | false
+ true | 3 | :success | :error | true
+ true | 3 | :error | :error | true
+ true | 0 | :success | :success | false
+ true | 0 | :error | :error | false
+ end
+
+ with_them do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
+ stub_application_setting(container_registry_cleanup_tags_service_max_list_size: max_list_size)
+ allow_next_instance_of(Projects::ContainerRepository::DeleteTagsService) do |service|
+ expect(service).to receive(:execute).and_return(status: delete_tags_service_status)
+ end
+ end
+
+ original_size = 7
+ keep_n = 1
+
+ it_behaves_like(
+ 'returning the response',
+ status: params[:expected_status],
+ original_size: original_size,
+ before_truncate_size: original_size - keep_n,
+ after_truncate_size: params[:expected_truncated] ? params[:max_list_size] + keep_n : original_size - keep_n,
+ before_delete_size: params[:expected_truncated] ? params[:max_list_size] : original_size - keep_n - 1 # one tag is filtered out with older_than filter
+ )
+ end
+ end
end
private
@@ -295,4 +359,16 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
.to receive(:execute)
.with(repository) { { status: :success, deleted: tags } }
end
+
+ # all those -1 because the default tags on L13 have a "latest" that will be filtered out
+ def expected_service_response(status: :success, deleted: [], original_size: tags.size, before_truncate_size: tags.size - 1, after_truncate_size: tags.size - 1, before_delete_size: tags.size - 1)
+ {
+ status: status,
+ deleted: deleted,
+ original_size: original_size,
+ before_truncate_size: before_truncate_size,
+ after_truncate_size: after_truncate_size,
+ before_delete_size: before_delete_size
+ }.compact
+ end
end
diff --git a/spec/services/projects/container_repository/delete_tags_service_spec.rb b/spec/services/projects/container_repository/delete_tags_service_spec.rb
index 4da416d9698..94037d6de1e 100644
--- a/spec/services/projects/container_repository/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb
@@ -119,9 +119,9 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
+ it { is_expected.to include(status: :error, message: 'error while deleting tags') }
- it_behaves_like 'logging an error response', message: 'timeout while deleting tags', extra_log: { deleted_tags_count: 0 }
+ it_behaves_like 'logging an error response', message: 'error while deleting tags', extra_log: { deleted_tags_count: 0 }
end
end
end
diff --git a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
index 988971171fc..74f782538c5 100644
--- a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do
stub_delete_reference_requests('A' => 200)
end
- it { is_expected.to eq(status: :error, message: 'timeout while deleting tags', deleted: ['A']) }
+ it { is_expected.to eq(status: :error, message: 'error while deleting tags', deleted: ['A'], exception_class_name: Projects::ContainerRepository::Gitlab::DeleteTagsService::TimeoutError.name) }
it 'tracks the exception' do
expect(::Gitlab::ErrorTracking)
@@ -89,6 +89,21 @@ RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do
it_behaves_like 'deleting tags'
end
end
+
+ context 'with a network error' do
+ before do
+ expect(service).to receive(:delete_tags).and_raise(::Faraday::TimeoutError)
+ end
+
+ it { is_expected.to eq(status: :error, message: 'error while deleting tags', deleted: [], exception_class_name: ::Faraday::TimeoutError.name) }
+
+ it 'tracks the exception' do
+ expect(::Gitlab::ErrorTracking)
+ .to receive(:track_exception).with(::Faraday::TimeoutError, tags_count: tags.size, container_repository_id: repository.id)
+
+ subject
+ end
+ end
end
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 60dfee820ca..a11f16573f5 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -116,6 +116,24 @@ RSpec.describe Projects::ForkService do
expect(to_project.fork_network_member.forked_from_project).to eq(from_forked_project)
end
+ context 'when the forked project has higher visibility than the root project' do
+ let(:root_project) { create(:project, :public) }
+
+ it 'successfully creates a fork of the fork with correct visibility' do
+ forked_project = fork_project(root_project, @to_user, using_service: true)
+
+ root_project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+
+ # Forked project visibility is not affected by root project visibility change
+ expect(forked_project).to have_attributes(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+
+ fork_of_the_fork = fork_project(forked_project, @to_user, namespace: other_namespace, using_service: true)
+
+ expect(fork_of_the_fork).to be_valid
+ expect(fork_of_the_fork).to have_attributes(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
+
it_behaves_like 'forks count cache refresh' do
let(:from_project) { from_forked_project }
let(:to_user) { @to_user }
diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb
index 18871f010f8..0aa4a1cd312 100644
--- a/spec/services/projects/housekeeping_service_spec.rb
+++ b/spec/services/projects/housekeeping_service_spec.rb
@@ -2,127 +2,19 @@
require 'spec_helper'
+# This is a compatibility class to avoid calling a non-existent
+# class from sidekiq during deployment.
+#
+# We're deploying the name of the referenced class in 13.9. Nevertheless,
+# we cannot remove the class entirely because there can be jobs
+# referencing it. We still need this specs to ensure that the old
+# class still has the old behavior.
+#
+# We can get rid of this class in 13.10
+# https://gitlab.com/gitlab-org/gitlab/-/issues/297580
+#
RSpec.describe Projects::HousekeepingService do
- subject { described_class.new(project) }
-
- let_it_be(:project) { create(:project, :repository) }
-
- before do
- project.reset_pushes_since_gc
- end
-
- after do
- project.reset_pushes_since_gc
- end
-
- 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(project.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)
- end
- end
-
- it 'yields the block if given' do
- expect do |block|
- subject.execute(&block)
- end.to yield_with_no_args
- end
-
- it 'resets counter after execution' do
- expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
- allow(subject).to receive(:gc_period).and_return(1)
- project.increment_pushes_since_gc
-
- perform_enqueued_jobs do
- expect { subject.execute }.to change { project.pushes_since_gc }.to(0)
- end
- end
-
- context 'when no lease can be obtained' do
- before do
- expect(subject).to receive(:try_obtain_lease).and_return(false)
- end
-
- it 'does not enqueue a job' do
- expect(GitGarbageCollectWorker).not_to receive(:perform_async)
-
- expect { subject.execute }.to raise_error(Projects::HousekeepingService::LeaseTaken)
- end
-
- it 'does not reset pushes_since_gc' do
- expect do
- expect { subject.execute }.to raise_error(Projects::HousekeepingService::LeaseTaken)
- end.not_to change { project.pushes_since_gc }
- end
-
- it 'does not yield' do
- expect do |block|
- expect { subject.execute(&block) }
- .to raise_error(Projects::HousekeepingService::LeaseTaken)
- end.not_to yield_with_no_args
- end
- end
-
- context 'task type' do
- it 'goes through all three housekeeping tasks, executing only the highest task when there is overlap' do
- allow(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
- allow(subject).to receive(:lease_key).and_return(:the_lease_key)
-
- # At push 200
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :the_lease_key, :the_uuid)
- .once
- # At push 50, 100, 150
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.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(project.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(project.id, :pack_refs, :the_lease_key, :the_uuid)
- .exactly(27).times
-
- 201.times do
- subject.increment!
- subject.execute if subject.needed?
- end
-
- expect(project.pushes_since_gc).to eq(1)
- end
- end
-
- it 'runs the task specifically requested' do
- housekeeping = described_class.new(project, :gc)
-
- 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(project.id, :gc, :gc_lease_key, :gc_uuid).twice
-
- 2.times do
- housekeeping.execute
- end
- end
- end
-
- describe '#needed?' do
- it 'when the count is low enough' do
- expect(subject.needed?).to eq(false)
- end
-
- it 'when the count is high enough' do
- allow(project).to receive(:pushes_since_gc).and_return(10)
- expect(subject.needed?).to eq(true)
- end
- end
-
- describe '#increment!' do
- it 'increments the pushes_since_gc counter' do
- expect { subject.increment! }.to change { project.pushes_since_gc }.by(1)
- end
+ it_behaves_like 'housekeeps repository' do
+ let_it_be(:resource) { create(:project, :repository) }
end
end
diff --git a/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb b/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb
index 5b76386bfab..15c9d1e5925 100644
--- a/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb
+++ b/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb
@@ -3,45 +3,10 @@
require 'spec_helper'
RSpec.describe Projects::ScheduleBulkRepositoryShardMovesService do
- before do
- stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
- end
-
- let!(:project) { create(:project, :repository).tap { |project| project.track_project_repository } }
- let(:source_storage_name) { 'default' }
- let(:destination_storage_name) { 'test_second_storage' }
-
- describe '#execute' do
- it 'schedules project repository storage moves' do
- expect { subject.execute(source_storage_name, destination_storage_name) }
- .to change(ProjectRepositoryStorageMove, :count).by(1)
-
- storage_move = project.repository_storage_moves.last!
-
- expect(storage_move).to have_attributes(
- source_storage_name: source_storage_name,
- destination_storage_name: destination_storage_name,
- state_name: :scheduled
- )
- end
-
- context 'read-only repository' do
- let!(:project) { create(:project, :repository, :read_only).tap { |project| project.track_project_repository } }
-
- it 'does not get scheduled' do
- expect(subject).to receive(:log_info)
- .with("Project #{project.full_path} (#{project.id}) was skipped: Project is read only")
- expect { subject.execute(source_storage_name, destination_storage_name) }
- .to change(ProjectRepositoryStorageMove, :count).by(0)
- end
- end
- end
-
- describe '.enqueue' do
- it 'defers to the worker' do
- expect(::ProjectScheduleBulkRepositoryShardMovesWorker).to receive(:perform_async).with(source_storage_name, destination_storage_name)
+ it_behaves_like 'moves repository shard in bulk' do
+ let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
- described_class.enqueue(source_storage_name, destination_storage_name)
- end
+ let(:move_service_klass) { ProjectRepositoryStorageMove }
+ let(:bulk_worker_klass) { ::ProjectScheduleBulkRepositoryShardMovesWorker }
end
end
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index a15f6bdbe2c..a6730c5de52 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -79,6 +79,19 @@ RSpec.describe Projects::UpdatePagesService do
end
end
+ it 'fails if sha on branch was updated before deployment was uploaded' do
+ expect(subject).to receive(:create_pages_deployment).and_wrap_original do |m, *args|
+ build.update!(ref: 'feature')
+ m.call(*args)
+ end
+
+ expect(execute).not_to eq(:success)
+ expect(project.pages_metadatum).not_to be_deployed
+
+ expect(deploy_status).to be_failed
+ expect(deploy_status.description).to eq('build SHA is outdated for this ref')
+ end
+
it 'does not fail if pages_metadata is absent' do
project.pages_metadatum.destroy!
project.reload
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 760cd85bf71..a59b6adf346 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -15,13 +15,6 @@ RSpec.describe Projects::UpdateService do
let(:admin) { create(:admin) }
context 'when changing visibility level' do
- def expect_to_call_unlink_fork_service
- service = Projects::UnlinkForkService.new(project, user)
-
- expect(Projects::UnlinkForkService).to receive(:new).with(project, user).and_return(service)
- expect(service).to receive(:execute).and_call_original
- end
-
context 'when visibility_level changes to INTERNAL' do
it 'updates the project to internal' do
expect(TodosDestroyer::ProjectPrivateWorker).not_to receive(:perform_in)
@@ -31,18 +24,6 @@ RSpec.describe Projects::UpdateService do
expect(result).to eq({ status: :success })
expect(project).to be_internal
end
-
- context 'and project is PUBLIC' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'unlinks project from fork network' do
- expect_to_call_unlink_fork_service
-
- update_project(project, user, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
- end
end
context 'when visibility_level changes to PUBLIC' do
@@ -78,30 +59,6 @@ RSpec.describe Projects::UpdateService do
expect(result).to eq({ status: :success })
expect(project).to be_private
end
-
- context 'and project is PUBLIC' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- end
-
- it 'unlinks project from fork network' do
- expect_to_call_unlink_fork_service
-
- update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
- end
-
- context 'and project is INTERNAL' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it 'unlinks project from fork network' do
- expect_to_call_unlink_fork_service
-
- update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
- end
end
context 'when visibility levels are restricted to PUBLIC only' do
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index e6d1d0e90a7..21e294418a1 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe QuickActions::InterpretService do
let_it_be(:project) { public_project }
let_it_be(:developer) { create(:user) }
let_it_be(:developer2) { create(:user) }
+ let_it_be(:developer3) { create(:user) }
let_it_be_with_reload(:issue) { create(:issue, project: project) }
let(:milestone) { create(:milestone, project: project, title: '9.10') }
let(:commit) { create(:commit, project: project) }
@@ -23,6 +24,7 @@ RSpec.describe QuickActions::InterpretService do
before do
stub_licensed_features(multiple_issue_assignees: false,
+ multiple_merge_request_reviewers: false,
multiple_merge_request_assignees: false)
end
@@ -665,6 +667,24 @@ RSpec.describe QuickActions::InterpretService do
end
end
+ shared_examples 'assign_reviewer command' do
+ it 'assigns a reviewer to a single user' do
+ _, updates, message = service.execute(content, issuable)
+
+ expect(updates).to eq(reviewer_ids: [developer.id])
+ expect(message).to eq("Assigned #{developer.to_reference} as reviewer.")
+ end
+ end
+
+ shared_examples 'unassign_reviewer command' do
+ it 'removes a single reviewer' do
+ _, updates, message = service.execute(content, issuable)
+
+ expect(updates).to eq(reviewer_ids: [])
+ expect(message).to eq("Removed reviewer #{developer.to_reference}.")
+ end
+ end
+
it_behaves_like 'reopen command' do
let(:content) { '/reopen' }
let(:issuable) { issue }
@@ -779,6 +799,11 @@ RSpec.describe QuickActions::InterpretService do
it_behaves_like 'assign command' do
let(:content) { "/assign @#{developer.username}" }
+ let(:issuable) { create(:incident, project: project) }
+ end
+
+ it_behaves_like 'assign command' do
+ let(:content) { "/assign @#{developer.username}" }
let(:issuable) { merge_request }
end
end
@@ -789,12 +814,32 @@ RSpec.describe QuickActions::InterpretService do
project.add_developer(developer2)
end
- it_behaves_like 'assign command' do
+ # 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.
+ shared_examples 'assigns to one of the two users' do
+ let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
+
+ it 'assigns to a single user' do
+ _, updates, message = service.execute(content, issuable)
+
+ expect(updates[:assignee_ids].count).to eq(1)
+ assignee = updates[:assignee_ids].first
+ expect([developer.id, developer2.id]).to include(assignee)
+
+ user = assignee == developer.id ? developer : developer2
+
+ expect(message).to match("Assigned #{user.to_reference}.")
+ end
+ end
+
+ it_behaves_like 'assigns to one of the two users' do
let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
let(:issuable) { issue }
end
- it_behaves_like 'assign command', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/27989' do
+ it_behaves_like 'assigns to one of the two users' do
let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
let(:issuable) { merge_request }
end
@@ -834,6 +879,142 @@ 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 }
+
+ 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 }
+
+ 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
+
+ # 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)
+
+ 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
+
+ expect(message).to match("Assigned #{user.to_reference} as reviewer.")
+ end
+ end
+ end
+
+ context 'with "me" alias' do
+ let(:content) { '/assign_reviewer me' }
+
+ it_behaves_like 'assign_reviewer command'
+ end
+
+ context 'with an alias and whitespace' do
+ let(:content) { '/assign_reviewer me ' }
+
+ it_behaves_like 'assign_reviewer command'
+ end
+
+ 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
+
+ context 'with the "reviewer" alias' do
+ let(:content) { "/reviewer @#{developer.username}" }
+
+ it_behaves_like 'assign_reviewer command'
+ end
+
+ context 'with no user' do
+ let(:content) { '/assign_reviewer' }
+
+ it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
+ end
+
+ context 'includes only the user reference with extra text' do
+ let(:content) { "/assign_reviewer @#{developer.username} do it!" }
+
+ it_behaves_like 'assign_reviewer command'
+ end
+ 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 '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
+
+ context 'with anything after the command' do
+ let(:content) { '/unassign_reviewer supercalifragilisticexpialidocious' }
+
+ it_behaves_like 'unassign_reviewer command'
+ end
+
+ context 'with the "remove_reviewer" alias' do
+ let(:content) { "/remove_reviewer @#{developer.username}" }
+
+ it_behaves_like 'unassign_reviewer command'
+ end
+
+ context 'with no user' do
+ let(:content) { '/unassign_reviewer' }
+
+ it_behaves_like 'unassign_reviewer command'
+ end
+ end
+ end
+
+ context 'when the merge_request_reviewers flag is disabled' do
+ before do
+ stub_feature_flags(merge_request_reviewers: false)
+ end
+
+ describe 'assign_reviewer command' do
+ it_behaves_like 'empty command' do
+ let(:content) { "/assign_reviewer @#{developer.username}" }
+ let(:issuable) { merge_request }
+ end
+ end
+
+ describe 'unassign_reviewer command' do
+ it_behaves_like 'empty command' do
+ let(:content) { "/unassign_reviewer @#{developer.username}" }
+ let(:issuable) { merge_request }
+ end
+ end
+ end
+
context 'unassign command' do
let(:content) { '/unassign' }
@@ -1117,6 +1298,11 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
+ it_behaves_like 'confidential command' do
+ let(:content) { '/confidential' }
+ let(:issuable) { create(:incident, project: project) }
+ end
+
it_behaves_like 'lock command' do
let(:content) { '/lock' }
let(:issuable) { issue }
@@ -1819,6 +2005,28 @@ RSpec.describe QuickActions::InterpretService do
end
end
+ describe 'unassign_reviewer command' do
+ let(:content) { '/unassign_reviewer' }
+ let(:merge_request) { create(:merge_request, source_project: project, reviewers: [developer]) }
+
+ it 'includes current assignee reference' do
+ _, explanations = service.explain(content, merge_request)
+
+ expect(explanations).to eq(["Removes reviewer @#{developer.username}."])
+ end
+ end
+
+ describe 'assign_reviewer command' do
+ let(:content) { "/assign_reviewer #{developer.to_reference}" }
+ let(:merge_request) { create(:merge_request, source_project: project, assignees: [developer]) }
+
+ it 'includes only the user reference' do
+ _, explanations = service.explain(content, merge_request)
+
+ expect(explanations).to eq(["Assigns #{developer.to_reference} as reviewer."])
+ end
+ end
+
describe 'milestone command' do
let(:content) { '/milestone %wrong-milestone' }
let!(:milestone) { create(:milestone, project: project, title: '9.10') }
diff --git a/spec/services/repositories/housekeeping_service_spec.rb b/spec/services/repositories/housekeeping_service_spec.rb
new file mode 100644
index 00000000000..fbd9affb33c
--- /dev/null
+++ b/spec/services/repositories/housekeeping_service_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::HousekeepingService do
+ it_behaves_like 'housekeeps repository' do
+ let_it_be(:resource) { create(:project, :repository) }
+ end
+
+ it_behaves_like 'housekeeps repository' do
+ let_it_be(:project) { create(:project, :wiki_repo) }
+ let_it_be(:resource) { project.wiki }
+ end
+end
diff --git a/spec/services/resource_events/change_state_service_spec.rb b/spec/services/resource_events/change_state_service_spec.rb
index 5b5379b241b..255ee9eca57 100644
--- a/spec/services/resource_events/change_state_service_spec.rb
+++ b/spec/services/resource_events/change_state_service_spec.rb
@@ -30,6 +30,15 @@ RSpec.describe ResourceEvents::ChangeStateService do
expect_event_source(event, source)
end
+
+ it "sets the created_at timestamp from the system_note_timestamp" do
+ resource.system_note_timestamp = Time.at(43).utc
+
+ described_class.new(user: user, resource: resource).execute(status: state, mentionable_source: source)
+ event = resource.resource_state_events.last
+
+ expect(event.created_at).to eq(Time.at(43).utc)
+ end
end
end
diff --git a/spec/services/service_desk_settings/update_service_spec.rb b/spec/services/service_desk_settings/update_service_spec.rb
index fbef587365d..72134af1369 100644
--- a/spec/services/service_desk_settings/update_service_spec.rb
+++ b/spec/services/service_desk_settings/update_service_spec.rb
@@ -16,19 +16,6 @@ RSpec.describe ServiceDeskSettings::UpdateService do
expect(settings.reload.outgoing_name).to eq 'some name'
expect(settings.reload.project_key).to eq 'foo'
end
-
- context 'when service_desk_custom_address is disabled' do
- before do
- stub_feature_flags(service_desk_custom_address: false)
- end
-
- it 'ignores project_key parameter' do
- result = described_class.new(settings.project, user, params).execute
-
- expect(result[:status]).to eq :success
- expect(settings.reload.project_key).to be_nil
- end
- end
end
context 'when project_key is an empty string' do
diff --git a/spec/services/snippets/schedule_bulk_repository_shard_moves_service_spec.rb b/spec/services/snippets/schedule_bulk_repository_shard_moves_service_spec.rb
new file mode 100644
index 00000000000..764c7f94a46
--- /dev/null
+++ b/spec/services/snippets/schedule_bulk_repository_shard_moves_service_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Snippets::ScheduleBulkRepositoryShardMovesService do
+ it_behaves_like 'moves repository shard in bulk' do
+ let_it_be_with_reload(:container) { create(:snippet, :repository) }
+
+ let(:move_service_klass) { SnippetRepositoryStorageMove }
+ let(:bulk_worker_klass) { ::SnippetScheduleBulkRepositoryShardMovesWorker }
+ end
+end
diff --git a/spec/services/snippets/update_repository_storage_service_spec.rb b/spec/services/snippets/update_repository_storage_service_spec.rb
new file mode 100644
index 00000000000..b2bcd620d76
--- /dev/null
+++ b/spec/services/snippets/update_repository_storage_service_spec.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Snippets::UpdateRepositoryStorageService do
+ include Gitlab::ShellAdapter
+
+ subject { described_class.new(repository_storage_move) }
+
+ describe "#execute" do
+ let_it_be_with_reload(:snippet) { create(:snippet, :repository) }
+ let_it_be(:destination) { 'test_second_storage' }
+ let_it_be(:checksum) { snippet.repository.checksum }
+
+ let(:repository_storage_move_state) { :scheduled }
+ let(:repository_storage_move) { create(:snippet_repository_storage_move, repository_storage_move_state, container: snippet, destination_storage_name: destination) }
+ let(:snippet_repository_double) { double(:repository) }
+ let(:original_snippet_repository_double) { double(:repository) }
+
+ before do
+ allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage])
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with(destination).and_return(SecureRandom.uuid)
+ allow(Gitlab::Git::Repository).to receive(:new).and_call_original
+ allow(Gitlab::Git::Repository).to receive(:new)
+ .with(destination, snippet.repository.raw.relative_path, snippet.repository.gl_repository, snippet.repository.full_path)
+ .and_return(snippet_repository_double)
+ allow(Gitlab::Git::Repository).to receive(:new)
+ .with('default', snippet.repository.raw.relative_path, nil, nil)
+ .and_return(original_snippet_repository_double)
+ end
+
+ context 'when the move succeeds' do
+ it 'moves the repository to the new storage and unmarks the repository as read only' do
+ old_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ snippet.repository.path_to_repo
+ end
+
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ expect(snippet_repository_double).to receive(:checksum)
+ .and_return(checksum)
+ expect(original_snippet_repository_double).to receive(:remove)
+
+ result = subject.execute
+ snippet.reload
+
+ expect(result).to be_success
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq(destination)
+ expect(gitlab_shell.repository_exists?('default', old_path)).to be(false)
+ expect(snippet.snippet_repository.shard_name).to eq(destination)
+ end
+ end
+
+ context 'when the filesystems are the same' do
+ let(:destination) { snippet.repository_storage }
+
+ it 'bails out and does nothing' do
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(result.message).to match(/SameFilesystemError/)
+ end
+ end
+
+ context 'when the move fails' do
+ it 'unmarks the repository as read-only without updating the repository storage' do
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ .and_raise(Gitlab::Git::CommandError)
+
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq('default')
+ expect(repository_storage_move).to be_failed
+ end
+ end
+
+ context 'when the cleanup fails' do
+ it 'sets the correct state' do
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ expect(snippet_repository_double).to receive(:checksum)
+ .and_return(checksum)
+ expect(original_snippet_repository_double).to receive(:remove)
+ .and_raise(Gitlab::Git::CommandError)
+
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(repository_storage_move).to be_cleanup_failed
+ end
+ end
+
+ context 'when the checksum does not match' do
+ it 'unmarks the repository as read-only without updating the repository storage' do
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ expect(snippet_repository_double).to receive(:checksum)
+ .and_return('not matching checksum')
+
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq('default')
+ end
+ end
+
+ context 'when the repository move is finished' do
+ let(:repository_storage_move_state) { :finished }
+
+ it 'is idempotent' do
+ expect do
+ result = subject.execute
+
+ expect(result).to be_success
+ end.not_to change(repository_storage_move, :state)
+ end
+ end
+
+ context 'when the repository move is failed' do
+ let(:repository_storage_move_state) { :failed }
+
+ it 'is idempotent' do
+ expect do
+ result = subject.execute
+
+ expect(result).to be_success
+ end.not_to change(repository_storage_move, :state)
+ end
+ end
+ end
+end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 90325c564bc..83d233a8112 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -100,17 +100,18 @@ RSpec.describe TodoService do
end
describe 'Issues' do
- let(:issue) { create(:issue, project: project, assignees: [john_doe], author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
- let(:addressed_issue) { create(:issue, project: project, assignees: [john_doe], author: author, description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
+ let(:issue) { create(:issue, project: project, author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
+ let(:addressed_issue) { create(:issue, project: project, author: author, description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
+ let(:assigned_issue) { create(:issue, project: project, assignees: [john_doe]) }
let(:unassigned_issue) { create(:issue, project: project, assignees: []) }
let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignees: [assignee], description: mentions) }
let(:addressed_confident_issue) { create(:issue, :confidential, project: project, author: author, assignees: [assignee], description: directly_addressed) }
describe '#new_issue' do
it 'creates a todo if assigned' do
- service.new_issue(issue, author)
+ service.new_issue(assigned_issue, author)
- should_create_todo(user: john_doe, target: issue, action: Todo::ASSIGNED)
+ should_create_todo(user: john_doe, target: assigned_issue, action: Todo::ASSIGNED)
end
it 'does not create a todo if unassigned' do
@@ -130,7 +131,7 @@ RSpec.describe TodoService do
should_create_todo(user: member, target: issue, action: Todo::MENTIONED)
should_create_todo(user: guest, target: issue, action: Todo::MENTIONED)
should_create_todo(user: author, target: issue, action: Todo::MENTIONED)
- should_not_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED)
+ should_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED)
should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED)
end
@@ -140,7 +141,7 @@ RSpec.describe TodoService do
should_create_todo(user: member, target: addressed_issue, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: guest, target: addressed_issue, action: Todo::DIRECTLY_ADDRESSED)
should_create_todo(user: author, target: addressed_issue, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: john_doe, target: addressed_issue, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: john_doe, target: addressed_issue, action: Todo::DIRECTLY_ADDRESSED)
should_not_create_todo(user: non_member, target: addressed_issue, action: Todo::DIRECTLY_ADDRESSED)
end
@@ -244,6 +245,8 @@ RSpec.describe TodoService do
end
it 'does not create a todo if user was already mentioned and todo is pending' do
+ stub_feature_flags(multiple_todos: false)
+
create(:todo, :mentioned, user: member, project: project, target: issue, author: author)
expect { service.update_issue(issue, author, skip_users) }.not_to change(member.todos, :count)
@@ -256,6 +259,8 @@ RSpec.describe TodoService do
end
it 'does not create a directly addressed todo if user was already mentioned or addressed and todo is pending' do
+ stub_feature_flags(multiple_todos: false)
+
create(:todo, :directly_addressed, user: member, project: project, target: addressed_issue, author: author)
expect { service.update_issue(addressed_issue, author, skip_users) }.not_to change(member.todos, :count)
@@ -622,6 +627,26 @@ RSpec.describe TodoService do
expect(service.todo_exist?(unassigned_issue, author)).to be_truthy
end
end
+
+ context 'when multiple_todos are enabled' do
+ before do
+ stub_feature_flags(multiple_todos: true)
+ end
+
+ it 'creates a todo even if user already has a pending todo' do
+ create(:todo, :mentioned, user: member, project: project, target: issue, author: author)
+
+ expect { service.update_issue(issue, author) }.to change(member.todos, :count)
+ end
+
+ it 'creates multiple todos if a user is assigned and mentioned in a new issue' do
+ assigned_issue.description = mentions
+ service.new_issue(assigned_issue, author)
+
+ should_create_todo(user: john_doe, target: assigned_issue, action: Todo::ASSIGNED)
+ should_create_todo(user: john_doe, target: assigned_issue, action: Todo::MENTIONED)
+ end
+ end
end
describe '#reassigned_assignable' do
@@ -664,154 +689,161 @@ RSpec.describe TodoService do
end
describe 'Merge Requests' do
- let(:mr_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
- let(:addressed_mr_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
- let(:mr_unassigned) { create(:merge_request, source_project: project, author: author, assignees: []) }
+ let(:mentioned_mr) { create(:merge_request, source_project: project, author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
+ let(:addressed_mr) { create(:merge_request, source_project: project, author: author, description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
+ let(:assigned_mr) { create(:merge_request, source_project: project, author: author, assignees: [john_doe]) }
+ let(:unassigned_mr) { create(:merge_request, source_project: project, author: author, assignees: []) }
describe '#new_merge_request' do
it 'creates a pending todo if assigned' do
- service.new_merge_request(mr_assigned, author)
+ service.new_merge_request(assigned_mr, author)
- should_create_todo(user: john_doe, target: mr_assigned, action: Todo::ASSIGNED)
+ should_create_todo(user: john_doe, target: assigned_mr, action: Todo::ASSIGNED)
end
it 'does not create a todo if unassigned' do
- should_not_create_any_todo { service.new_merge_request(mr_unassigned, author) }
+ should_not_create_any_todo { service.new_merge_request(unassigned_mr, author) }
end
- it 'does not create a todo if assignee is the current user' do
- should_not_create_any_todo { service.new_merge_request(mr_unassigned, john_doe) }
+ it 'creates a todo if assignee is the current user' do
+ service.new_merge_request(assigned_mr, john_doe)
+
+ should_create_todo(user: john_doe, target: assigned_mr, author: john_doe, action: Todo::ASSIGNED)
end
it 'creates a todo for each valid mentioned user' do
- service.new_merge_request(mr_assigned, author)
+ service.new_merge_request(mentioned_mr, author)
- should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
- should_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED)
+ should_create_todo(user: member, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: guest, target: mentioned_mr, action: Todo::MENTIONED)
+ should_create_todo(user: author, target: mentioned_mr, action: Todo::MENTIONED)
+ should_create_todo(user: john_doe, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: non_member, target: mentioned_mr, action: Todo::MENTIONED)
end
it 'creates a todo for each valid user based on the type of mention' do
- mr_assigned.update!(description: directly_addressed_and_mentioned)
+ mentioned_mr.update!(description: directly_addressed_and_mentioned)
- service.new_merge_request(mr_assigned, author)
+ service.new_merge_request(mentioned_mr, author)
- should_create_todo(user: member, target: mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
+ should_create_todo(user: member, target: mentioned_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: admin, target: mentioned_mr, action: Todo::MENTIONED)
end
it 'creates a directly addressed todo for each valid addressed user' do
- service.new_merge_request(addressed_mr_assigned, author)
+ service.new_merge_request(addressed_mr, author)
- should_create_todo(user: member, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: guest, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: author, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: john_doe, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: non_member, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: member, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: guest, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: author, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: john_doe, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: non_member, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
end
end
describe '#update_merge_request' do
it 'creates a todo for each valid mentioned user not included in skip_users' do
- service.update_merge_request(mr_assigned, author, skip_users)
+ service.update_merge_request(mentioned_mr, author, skip_users)
- should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
- should_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED)
- should_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: skipped, target: mr_assigned, action: Todo::MENTIONED)
+ should_create_todo(user: member, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: guest, target: mentioned_mr, action: Todo::MENTIONED)
+ should_create_todo(user: john_doe, target: mentioned_mr, action: Todo::MENTIONED)
+ should_create_todo(user: author, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: non_member, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: skipped, target: mentioned_mr, action: Todo::MENTIONED)
end
it 'creates a todo for each valid user not included in skip_users based on the type of mention' do
- mr_assigned.update!(description: directly_addressed_and_mentioned)
+ mentioned_mr.update!(description: directly_addressed_and_mentioned)
- service.update_merge_request(mr_assigned, author, skip_users)
+ service.update_merge_request(mentioned_mr, author, skip_users)
- should_create_todo(user: member, target: mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: skipped, target: mr_assigned)
+ should_create_todo(user: member, target: mentioned_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: admin, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: skipped, target: mentioned_mr)
end
it 'creates a directly addressed todo for each valid addressed user not included in skip_users' do
- service.update_merge_request(addressed_mr_assigned, author, skip_users)
+ service.update_merge_request(addressed_mr, author, skip_users)
- should_create_todo(user: member, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: guest, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: john_doe, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_create_todo(user: author, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: non_member, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: skipped, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: member, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: guest, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: john_doe, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_create_todo(user: author, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: non_member, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: skipped, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
end
it 'does not create a todo if user was already mentioned and todo is pending' do
- create(:todo, :mentioned, user: member, project: project, target: mr_assigned, author: author)
+ stub_feature_flags(multiple_todos: false)
+
+ create(:todo, :mentioned, user: member, project: project, target: mentioned_mr, author: author)
- expect { service.update_merge_request(mr_assigned, author) }.not_to change(member.todos, :count)
+ expect { service.update_merge_request(mentioned_mr, author) }.not_to change(member.todos, :count)
end
it 'does not create a todo if user was already mentioned and todo is done' do
- create(:todo, :mentioned, :done, user: skipped, project: project, target: mr_assigned, author: author)
+ create(:todo, :mentioned, :done, user: skipped, project: project, target: mentioned_mr, author: author)
- expect { service.update_merge_request(mr_assigned, author, skip_users) }.not_to change(skipped.todos, :count)
+ expect { service.update_merge_request(mentioned_mr, author, skip_users) }.not_to change(skipped.todos, :count)
end
it 'does not create a directly addressed todo if user was already mentioned or addressed and todo is pending' do
- create(:todo, :directly_addressed, user: member, project: project, target: addressed_mr_assigned, author: author)
+ stub_feature_flags(multiple_todos: false)
+
+ create(:todo, :directly_addressed, user: member, project: project, target: addressed_mr, author: author)
- expect { service.update_merge_request(addressed_mr_assigned, author) }.not_to change(member.todos, :count)
+ expect { service.update_merge_request(addressed_mr, author) }.not_to change(member.todos, :count)
end
it 'does not create a directly addressed todo if user was already mentioned or addressed and todo is done' do
- create(:todo, :directly_addressed, user: skipped, project: project, target: addressed_mr_assigned, author: author)
+ create(:todo, :directly_addressed, user: skipped, project: project, target: addressed_mr, author: author)
- expect { service.update_merge_request(addressed_mr_assigned, author, skip_users) }.not_to change(skipped.todos, :count)
+ expect { service.update_merge_request(addressed_mr, author, skip_users) }.not_to change(skipped.todos, :count)
end
context 'with a task list' do
it 'does not create todo when tasks are marked as completed' do
- mr_assigned.update!(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
+ mentioned_mr.update!(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
- service.update_merge_request(mr_assigned, author)
+ service.update_merge_request(mentioned_mr, author)
- should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: assignee, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED)
- should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
+ should_not_create_todo(user: admin, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: assignee, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: author, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: john_doe, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: member, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: non_member, target: mentioned_mr, action: Todo::MENTIONED)
+ should_not_create_todo(user: guest, target: mentioned_mr, action: Todo::MENTIONED)
end
it 'does not create directly addressed todo when tasks are marked as completed' do
- addressed_mr_assigned.update!(description: "#{directly_addressed}\n- [x] Task 1\n- [X] Task 2")
+ addressed_mr.update!(description: "#{directly_addressed}\n- [x] Task 1\n- [X] Task 2")
- service.update_merge_request(addressed_mr_assigned, author)
+ service.update_merge_request(addressed_mr, author)
- should_not_create_todo(user: admin, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: assignee, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: author, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: john_doe, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: member, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: non_member, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
- should_not_create_todo(user: guest, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: admin, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: assignee, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: author, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: john_doe, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: member, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: non_member, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
+ should_not_create_todo(user: guest, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
end
it 'does not raise an error when description not change' do
- mr_assigned.update!(title: 'Sample')
+ mentioned_mr.update!(title: 'Sample')
- expect { service.update_merge_request(mr_assigned, author) }.not_to raise_error
+ expect { service.update_merge_request(mentioned_mr, author) }.not_to raise_error
end
end
end
describe '#close_merge_request' do
it 'marks related pending todos to the target for the user as done' do
- first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
- second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
- service.close_merge_request(mr_assigned, john_doe)
+ first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mentioned_mr, author: author)
+ second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mentioned_mr, author: author)
+ service.close_merge_request(mentioned_mr, john_doe)
expect(first_todo.reload).to be_done
expect(second_todo.reload).to be_done
@@ -820,55 +852,55 @@ RSpec.describe TodoService do
describe '#merge_merge_request' do
it 'marks related pending todos to the target for the user as done' do
- first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
- second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
- service.merge_merge_request(mr_assigned, john_doe)
+ first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mentioned_mr, author: author)
+ second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mentioned_mr, author: author)
+ service.merge_merge_request(mentioned_mr, john_doe)
expect(first_todo.reload).to be_done
expect(second_todo.reload).to be_done
end
it 'does not create todo for guests' do
- service.merge_merge_request(mr_assigned, john_doe)
- should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
+ service.merge_merge_request(mentioned_mr, john_doe)
+ should_not_create_todo(user: guest, target: mentioned_mr, action: Todo::MENTIONED)
end
it 'does not create directly addressed todo for guests' do
- service.merge_merge_request(addressed_mr_assigned, john_doe)
- should_not_create_todo(user: guest, target: addressed_mr_assigned, action: Todo::DIRECTLY_ADDRESSED)
+ service.merge_merge_request(addressed_mr, john_doe)
+ should_not_create_todo(user: guest, target: addressed_mr, action: Todo::DIRECTLY_ADDRESSED)
end
end
describe '#new_award_emoji' do
it 'marks related pending todos to the target for the user as done' do
- todo = create(:todo, user: john_doe, project: project, target: mr_assigned, author: author)
- service.new_award_emoji(mr_assigned, john_doe)
+ todo = create(:todo, user: john_doe, project: project, target: mentioned_mr, author: author)
+ service.new_award_emoji(mentioned_mr, john_doe)
expect(todo.reload).to be_done
end
end
describe '#merge_request_build_failed' do
- let(:merge_participants) { [mr_unassigned.author, admin] }
+ let(:merge_participants) { [unassigned_mr.author, admin] }
before do
- allow(mr_unassigned).to receive(:merge_participants).and_return(merge_participants)
+ allow(unassigned_mr).to receive(:merge_participants).and_return(merge_participants)
end
it 'creates a pending todo for each merge_participant' do
- service.merge_request_build_failed(mr_unassigned)
+ service.merge_request_build_failed(unassigned_mr)
merge_participants.each do |participant|
- should_create_todo(user: participant, author: participant, target: mr_unassigned, action: Todo::BUILD_FAILED)
+ should_create_todo(user: participant, author: participant, target: unassigned_mr, action: Todo::BUILD_FAILED)
end
end
end
describe '#merge_request_push' do
it 'marks related pending todos to the target for the user as done' do
- first_todo = create(:todo, :build_failed, user: author, project: project, target: mr_assigned, author: john_doe)
- second_todo = create(:todo, :build_failed, user: john_doe, project: project, target: mr_assigned, author: john_doe)
- service.merge_request_push(mr_assigned, author)
+ first_todo = create(:todo, :build_failed, user: author, project: project, target: mentioned_mr, author: john_doe)
+ second_todo = create(:todo, :build_failed, user: john_doe, project: project, target: mentioned_mr, author: john_doe)
+ service.merge_request_push(mentioned_mr, author)
expect(first_todo.reload).to be_done
expect(second_todo.reload).not_to be_done
@@ -879,24 +911,24 @@ RSpec.describe TodoService do
let(:merge_participants) { [admin, create(:user)] }
before do
- allow(mr_unassigned).to receive(:merge_participants).and_return(merge_participants)
+ allow(unassigned_mr).to receive(:merge_participants).and_return(merge_participants)
end
it 'creates a pending todo for each merge_participant' do
- mr_unassigned.update!(merge_when_pipeline_succeeds: true, merge_user: admin)
- service.merge_request_became_unmergeable(mr_unassigned)
+ unassigned_mr.update!(merge_when_pipeline_succeeds: true, merge_user: admin)
+ service.merge_request_became_unmergeable(unassigned_mr)
merge_participants.each do |participant|
- should_create_todo(user: participant, author: participant, target: mr_unassigned, action: Todo::UNMERGEABLE)
+ should_create_todo(user: participant, author: participant, target: unassigned_mr, action: Todo::UNMERGEABLE)
end
end
end
describe '#mark_todo' do
it 'creates a todo from a merge request' do
- service.mark_todo(mr_unassigned, author)
+ service.mark_todo(unassigned_mr, author)
- should_create_todo(user: author, target: mr_unassigned, action: Todo::MARKED)
+ should_create_todo(user: author, target: unassigned_mr, action: Todo::MARKED)
end
end
@@ -913,33 +945,33 @@ RSpec.describe TodoService do
end
let(:mention) { john_doe.to_reference }
- let(:diff_note_on_merge_request) { create(:diff_note_on_merge_request, project: project, noteable: mr_unassigned, author: author, note: "Hey #{mention}") }
- let(:addressed_diff_note_on_merge_request) { create(:diff_note_on_merge_request, project: project, noteable: mr_unassigned, author: author, note: "#{mention}, hey!") }
- let(:legacy_diff_note_on_merge_request) { create(:legacy_diff_note_on_merge_request, project: project, noteable: mr_unassigned, author: author, note: "Hey #{mention}") }
+ let(:diff_note_on_merge_request) { create(:diff_note_on_merge_request, project: project, noteable: unassigned_mr, author: author, note: "Hey #{mention}") }
+ let(:addressed_diff_note_on_merge_request) { create(:diff_note_on_merge_request, project: project, noteable: unassigned_mr, author: author, note: "#{mention}, hey!") }
+ let(:legacy_diff_note_on_merge_request) { create(:legacy_diff_note_on_merge_request, project: project, noteable: unassigned_mr, author: author, note: "Hey #{mention}") }
it 'creates a todo for mentioned user on new diff note' do
service.new_note(diff_note_on_merge_request, author)
- should_create_todo(user: john_doe, target: mr_unassigned, author: author, action: Todo::MENTIONED, note: diff_note_on_merge_request)
+ should_create_todo(user: john_doe, target: unassigned_mr, author: author, action: Todo::MENTIONED, note: diff_note_on_merge_request)
end
it 'creates a directly addressed todo for addressed user on new diff note' do
service.new_note(addressed_diff_note_on_merge_request, author)
- should_create_todo(user: john_doe, target: mr_unassigned, author: author, action: Todo::DIRECTLY_ADDRESSED, note: addressed_diff_note_on_merge_request)
+ should_create_todo(user: john_doe, target: unassigned_mr, author: author, action: Todo::DIRECTLY_ADDRESSED, note: addressed_diff_note_on_merge_request)
end
it 'creates a todo for mentioned user on legacy diff note' do
service.new_note(legacy_diff_note_on_merge_request, author)
- should_create_todo(user: john_doe, target: mr_unassigned, author: author, action: Todo::MENTIONED, note: legacy_diff_note_on_merge_request)
+ should_create_todo(user: john_doe, target: unassigned_mr, author: author, action: Todo::MENTIONED, note: legacy_diff_note_on_merge_request)
end
it 'does not create todo for guests' do
- note_on_merge_request = create :note_on_merge_request, project: project, noteable: mr_assigned, note: mentions
+ note_on_merge_request = create :note_on_merge_request, project: project, noteable: mentioned_mr, note: mentions
service.new_note(note_on_merge_request, author)
- should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
+ should_not_create_todo(user: guest, target: mentioned_mr, action: Todo::MENTIONED)
end
end
end
@@ -1013,6 +1045,8 @@ RSpec.describe TodoService do
end
it 'does not create a todo if user was already mentioned and todo is pending' do
+ stub_feature_flags(multiple_todos: false)
+
create(:todo, :mentioned, user: member, project: project, target: noteable, author: author)
expect { service.update_note(note, author, skip_users) }.not_to change(member.todos, :count)
@@ -1025,6 +1059,8 @@ RSpec.describe TodoService do
end
it 'does not create a directly addressed todo if user was already mentioned or addressed and todo is pending' do
+ stub_feature_flags(multiple_todos: false)
+
create(:todo, :directly_addressed, user: member, project: project, target: noteable, author: author)
expect { service.update_note(addressed_note, author, skip_users) }.not_to change(member.todos, :count)
@@ -1038,7 +1074,7 @@ RSpec.describe TodoService do
end
it 'updates cached counts when a todo is created' do
- issue = create(:issue, project: project, assignees: [john_doe], author: author, description: mentions)
+ issue = create(:issue, project: project, assignees: [john_doe], author: author)
expect(john_doe.todos_pending_count).to eq(0)
expect(john_doe).to receive(:update_todos_count_cache).and_call_original
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index 274c44394f3..b30b7e6eb56 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Users::UpdateService do
result = update_user(user, { username: 'taken' })
end.not_to change { user.reload.username }
expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('Username has already been taken')
+ expect(result[:message]).to eq('A user, alias, or group already exists with that username.')
end
it 'updates the status if status params were given' do
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index a607a6734b0..2fe72ab31c2 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -131,6 +131,15 @@ RSpec.describe WebHookService do
end
end
+ context 'when url is not encoded' do
+ let(:project_hook) { create(:project_hook, url: 'http://server.com/my path/') }
+
+ it 'handles exceptions' do
+ expect(service_instance.execute).to eq(status: :error, message: 'bad URI(is not URI?): "http://server.com/my path/"')
+ expect { service_instance.execute }.not_to raise_error
+ end
+ end
+
context 'when request body size is too big' do
it 'does not perform the request' do
stub_const("#{described_class}::REQUEST_BODY_SIZE_LIMIT", 10.bytes)
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c19c26f9a0b..9fac6c8e192 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -272,41 +272,6 @@ RSpec.configure do |config|
Sidekiq::Worker.clear_all
- # Temporary patch to force admin mode to be active by default in tests when
- # using the feature flag :user_mode_in_session, since this will require
- # modifying a significant number of specs to test both states for admin
- # mode enabled / disabled.
- #
- # This will only be applied to specs below dirs in `admin_mode_mock_dirs`
- #
- # See ongoing migration: https://gitlab.com/gitlab-org/gitlab/-/issues/31511
- #
- # Until the migration is finished, if it is required to have the real
- # behaviour in any of the mocked dirs specs that an admin is signed in
- # with normal user mode and needs to switch to admin mode, it is possible to
- # mark such tests with the `do_not_mock_admin_mode` metadata tag, e.g:
- #
- # context 'some test in mocked dir', :do_not_mock_admin_mode do ... end
- admin_mode_mock_dirs = %w(
- ./ee/spec/elastic_integration
- ./ee/spec/finders
- ./ee/spec/lib
- ./ee/spec/serializers
- ./ee/spec/support/shared_examples/finders/geo
- ./ee/spec/support/shared_examples/graphql/geo
- ./spec/finders
- ./spec/lib
- ./spec/serializers
- ./spec/support/shared_examples/lib/gitlab
- ./spec/workers
- )
-
- if !example.metadata[:do_not_mock_admin_mode] && example.metadata[:file_path].start_with?(*admin_mode_mock_dirs)
- allow_any_instance_of(Gitlab::Auth::CurrentUserMode).to receive(:admin_mode?) do |current_user_mode|
- current_user_mode.send(:user)&.admin?
- end
- end
-
# Administrators have to re-authenticate in order to access administrative
# functionality when feature flag :user_mode_in_session is active. Any spec
# that requires administrative access can use the tag :enable_admin_mode
@@ -314,6 +279,10 @@ RSpec.configure do |config|
#
# context 'some test that requires admin mode', :enable_admin_mode do ... end
#
+ # Some specs do get admin mode enabled automatically (e.g. `spec/controllers/admin`).
+ # In this case, specs that need to test both admin mode states can use the
+ # :do_not_mock_admin_mode tag to disable auto admin mode.
+ #
# See also spec/support/helpers/admin_mode_helpers.rb
if example.metadata[:enable_admin_mode] && !example.metadata[:do_not_mock_admin_mode]
allow_any_instance_of(Gitlab::Auth::CurrentUserMode).to receive(:admin_mode?) do |current_user_mode|
@@ -400,8 +369,5 @@ end
# Prevent Rugged from picking up local developer gitconfig.
Rugged::Settings['search_path_global'] = Rails.root.join('tmp/tests').to_s
-# Disable timestamp checks for invisible_captcha
-InvisibleCaptcha.timestamp_enabled = false
-
# Initialize FactoryDefault to use create_default helper
TestProf::FactoryDefault.init
diff --git a/spec/support/atlassian/jira_connect/schemata.rb b/spec/support/atlassian/jira_connect/schemata.rb
index 91f8fe0bb41..d056c7cacf3 100644
--- a/spec/support/atlassian/jira_connect/schemata.rb
+++ b/spec/support/atlassian/jira_connect/schemata.rb
@@ -2,82 +2,291 @@
module Atlassian
module Schemata
- def self.build_info
- {
- 'type' => 'object',
- 'required' => %w(schemaVersion pipelineId buildNumber updateSequenceNumber displayName url state issueKeys testInfo references),
- 'properties' => {
- 'schemaVersion' => { 'type' => 'string', 'pattern' => '1.0' },
- 'pipelineId' => { 'type' => 'string' },
- 'buildNumber' => { 'type' => 'integer' },
- 'updateSequenceNumber' => { 'type' => 'integer' },
- 'displayName' => { 'type' => 'string' },
- 'url' => { 'type' => 'string' },
- 'state' => {
- 'type' => 'string',
- 'pattern' => '(pending|in_progress|successful|failed|cancelled)'
- },
- 'issueKeys' => {
- 'type' => 'array',
- 'items' => { 'type' => 'string' },
- 'minItems' => 1
- },
- 'testInfo' => {
- 'type' => 'object',
- 'required' => %w(totalNumber numberPassed numberFailed numberSkipped),
- 'properties' => {
- 'totalNumber' => { 'type' => 'integer' },
- 'numberFailed' => { 'type' => 'integer' },
- 'numberPassed' => { 'type' => 'integer' },
- 'numberSkipped' => { 'type' => 'integer' }
- }
- },
- 'references' => {
- 'type' => 'array',
- 'items' => {
+ class << self
+ def build_info
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(
+ schemaVersion pipelineId buildNumber updateSequenceNumber
+ displayName url state issueKeys testInfo references
+ lastUpdated
+ ),
+ 'properties' => {
+ 'schemaVersion' => schema_version_type,
+ 'pipelineId' => { 'type' => 'string' },
+ 'buildNumber' => { 'type' => 'integer' },
+ 'updateSequenceNumber' => { 'type' => 'integer' },
+ 'displayName' => { 'type' => 'string' },
+ 'lastUpdated' => iso8601_type,
+ 'url' => { 'type' => 'string' },
+ 'state' => state_type,
+ 'issueKeys' => issue_keys_type,
+ 'testInfo' => {
'type' => 'object',
- 'required' => %w(commit ref),
+ 'required' => %w(totalNumber numberPassed numberFailed numberSkipped),
'properties' => {
- 'commit' => {
- 'type' => 'object',
- 'required' => %w(id repositoryUri),
- 'properties' => {
- 'id' => { 'type' => 'string' },
- 'repositoryUri' => { 'type' => 'string' }
+ 'totalNumber' => { 'type' => 'integer' },
+ 'numberFailed' => { 'type' => 'integer' },
+ 'numberPassed' => { 'type' => 'integer' },
+ 'numberSkipped' => { 'type' => 'integer' }
+ }
+ },
+ 'references' => {
+ 'type' => 'array',
+ 'items' => {
+ 'type' => 'object',
+ 'required' => %w(commit ref),
+ 'properties' => {
+ 'commit' => {
+ 'type' => 'object',
+ 'required' => %w(id repositoryUri),
+ 'properties' => {
+ 'id' => { 'type' => 'string' },
+ 'repositoryUri' => { 'type' => 'string' }
+ }
+ },
+ 'ref' => {
+ 'type' => 'object',
+ 'required' => %w(name uri),
+ 'properties' => {
+ 'name' => { 'type' => 'string' },
+ 'uri' => { 'type' => 'string' }
+ }
}
- },
- 'ref' => {
- 'type' => 'object',
- 'required' => %w(name uri),
- 'properties' => {
- 'name' => { 'type' => 'string' },
- 'uri' => { 'type' => 'string' }
+ }
+ }
+ }
+ }
+ }
+ end
+
+ def deployment_info
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(
+ deploymentSequenceNumber updateSequenceNumber
+ associations displayName url description lastUpdated
+ state pipeline environment
+ ),
+ 'properties' => {
+ 'deploymentSequenceNumber' => { 'type' => 'integer' },
+ 'updateSequenceNumber' => { 'type' => 'integer' },
+ 'associations' => {
+ 'type' => 'array',
+ 'items' => association_type,
+ 'minItems' => 1
+ },
+ 'displayName' => { 'type' => 'string' },
+ 'description' => { 'type' => 'string' },
+ 'label' => { 'type' => 'string' },
+ 'url' => { 'type' => 'string' },
+ 'lastUpdated' => iso8601_type,
+ 'state' => state_type,
+ 'pipeline' => pipeline_type,
+ 'environment' => environment_type,
+ 'schemaVersion' => schema_version_type
+ }
+ }
+ end
+
+ def feature_flag_info
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(
+ updateSequenceId id key issueKeys summary details
+ ),
+ 'properties' => {
+ 'id' => { 'type' => 'string' },
+ 'key' => { 'type' => 'string' },
+ 'displayName' => { 'type' => 'string' },
+ 'issueKeys' => issue_keys_type,
+ 'summary' => summary_type,
+ 'details' => details_type,
+ 'updateSequenceId' => { 'type' => 'integer' },
+ 'schemaVersion' => schema_version_type
+ }
+ }
+ end
+
+ def details_type
+ {
+ 'type' => 'array',
+ 'items' => combine(summary_type, {
+ 'required' => ['environment'],
+ 'properties' => {
+ 'environment' => {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(name),
+ 'properties' => {
+ 'name' => { 'type' => 'string' },
+ 'type' => {
+ 'type' => 'string',
+ 'pattern' => '^(development|testing|staging|production)$'
}
}
}
}
+ })
+ }
+ end
+
+ def combine(map_a, map_b)
+ map_a.merge(map_b) do |k, a, b|
+ a.respond_to?(:merge) ? a.merge(b) : a + b
+ end
+ end
+
+ def summary_type
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(url status lastUpdated),
+ 'properties' => {
+ 'lastUpdated' => iso8601_type,
+ 'url' => { 'type' => 'string' },
+ 'status' => feature_status_type
}
}
- }
- end
+ end
- def self.build_info_payload
- {
- 'type' => 'object',
- 'required' => %w(providerMetadata builds),
- 'properties' => {
- 'providerMetadata' => provider_metadata,
- 'builds' => { 'type' => 'array', 'items' => build_info }
+ def feature_status_type
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(enabled),
+ 'properties' => {
+ 'enabled' => { 'type' => 'boolean' },
+ 'defaultValue' => { 'type' => 'string' },
+ 'rollout' => rollout_type
+ }
}
- }
- end
+ end
+
+ def rollout_type
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'properties' => {
+ 'percentage' => { 'type' => 'number' },
+ 'text' => { 'type' => 'string' },
+ 'rules' => { 'type' => 'number' }
+ }
+ }
+ end
- def self.provider_metadata
- {
- 'type' => 'object',
- 'required' => %w(product),
- 'properties' => { 'product' => { 'type' => 'string' } }
- }
+ def environment_type
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(id displayName type),
+ 'properties' => {
+ 'id' => { 'type' => 'string', 'maxLength' => 255 },
+ 'displayName' => { 'type' => 'string', 'maxLength' => 255 },
+ 'type' => {
+ 'type' => 'string',
+ 'pattern' => '(unmapped|development|testing|staging|production)'
+ }
+ }
+ }
+ end
+
+ def pipeline_type
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(id displayName url),
+ 'properties' => {
+ 'id' => { 'type' => 'string', 'maxLength' => 255 },
+ 'displayName' => { 'type' => 'string', 'maxLength' => 255 },
+ 'url' => { 'type' => 'string', 'maxLength' => 2000 }
+ }
+ }
+ end
+
+ def schema_version_type
+ { 'type' => 'string', 'pattern' => '1.0' }
+ end
+
+ def state_type
+ {
+ 'type' => 'string',
+ 'pattern' => '(pending|in_progress|successful|failed|cancelled)'
+ }
+ end
+
+ def association_type
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => %w(associationType values),
+ 'properties' => {
+ 'associationType' => {
+ 'type' => 'string',
+ 'pattern' => '(issueKeys|issueIdOrKeys)'
+ },
+ 'values' => issue_keys_type
+ }
+ }
+ end
+
+ def issue_keys_type
+ {
+ 'type' => 'array',
+ 'items' => { 'type' => 'string' },
+ 'minItems' => 1,
+ 'maxItems' => 100
+ }
+ end
+
+ def deploy_info_payload
+ payload('deployments', deployment_info)
+ end
+
+ def build_info_payload
+ payload('builds', build_info)
+ end
+
+ def ff_info_payload
+ pl = payload('flags', feature_flag_info)
+ pl['properties']['properties'] = {
+ 'type' => 'object',
+ 'additionalProperties' => { 'type' => 'string' },
+ 'maxProperties' => 5,
+ 'propertyNames' => { 'pattern' => '^[^_][^:]+$' }
+ }
+ pl
+ end
+
+ def payload(key, schema)
+ {
+ 'type' => 'object',
+ 'additionalProperties' => false,
+ 'required' => ['providerMetadata', key],
+ 'properties' => {
+ 'providerMetadata' => provider_metadata,
+ key => { 'type' => 'array', 'items' => schema }
+ }
+ }
+ end
+
+ def provider_metadata
+ {
+ 'type' => 'object',
+ 'required' => %w(product),
+ 'properties' => { 'product' => { 'type' => 'string' } }
+ }
+ end
+
+ def iso8601_type
+ {
+ 'type' => 'string',
+ 'pattern' => '^-?([1-9][0-9]*)?[0-9]{4}-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$'
+ }
+ end
end
end
end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index ab55cf97ab4..db198ac9808 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -33,7 +33,7 @@ Capybara.register_server :puma_via_workhorse do |app, port, host, **options|
socket_path = file.path
file.close! # We just want the filename
- TestEnv.with_workhorse(TestEnv.workhorse_dir, host, port, socket_path) do
+ TestEnv.with_workhorse(host, port, socket_path) do
Capybara.servers[:puma].call(app, nil, socket_path, **options)
end
end
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
index c4f3c3aace2..d20078c8904 100644
--- a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
@@ -4,7 +4,8 @@ include:
variables:
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
SAST_EXCLUDED_PATHS: "spec, executables"
- SAST_DEFAULT_ANALYZERS: "bandit, gosec"
+ SAST_DEFAULT_ANALYZERS: "bandit, brakeman"
+ SAST_EXCLUDED_ANALYZERS: "brakeman"
stages:
- our_custom_security_stage
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml
new file mode 100644
index 00000000000..c4f3c3aace2
--- /dev/null
+++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml
@@ -0,0 +1,15 @@
+include:
+ - template: SAST.gitlab-ci.yml
+
+variables:
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
+ SAST_EXCLUDED_PATHS: "spec, executables"
+ SAST_DEFAULT_ANALYZERS: "bandit, gosec"
+
+stages:
+ - our_custom_security_stage
+sast:
+ stage: our_custom_security_stage
+ variables:
+ SEARCH_MAX_DEPTH: 8
+ SAST_BRAKEMAN_LEVEL: 2
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast_excluded_analyzers.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast_excluded_analyzers.yml
new file mode 100644
index 00000000000..b665de5f982
--- /dev/null
+++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast_excluded_analyzers.yml
@@ -0,0 +1,14 @@
+include:
+ - template: SAST.gitlab-ci.yml
+
+variables:
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
+ SAST_EXCLUDED_PATHS: "spec, executables"
+ SAST_EXCLUDED_ANALYZERS: "brakeman"
+
+stages:
+ - our_custom_security_stage
+sast:
+ stage: our_custom_security_stage
+ variables:
+ SEARCH_MAX_DEPTH: 8
diff --git a/spec/support/gitlab_stubs/gitlab_ci_includes.yml b/spec/support/gitlab_stubs/gitlab_ci_includes.yml
index e74773ce23e..1029fa1ea86 100644
--- a/spec/support/gitlab_stubs/gitlab_ci_includes.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci_includes.yml
@@ -1,19 +1,45 @@
+before_script:
+ - bundle install
+ - bundle exec rake db:create
+
rspec 0 1:
stage: build
script: 'rake spec'
needs: []
+ tags:
+ - ruby
+ - postgres
+ only:
+ - branches
+ - master
rspec 0 2:
stage: build
+ allow_failure: true
script: 'rake spec'
+ when: on_failure
needs: []
spinach:
stage: build
script: 'rake spinach'
needs: []
+ except:
+ - tags
+deploy_job:
+ stage: deploy
+ script:
+ - echo 'done'
+ environment:
+ name: production
docker:
stage: test
script: 'curl http://dockerhub/URL'
needs: [spinach, rspec 0 1]
+ when: manual
+ except:
+ - branches
+
+after_script:
+ - echo 'run this after'
diff --git a/spec/support/helpers/database/database_helpers.rb b/spec/support/helpers/database/database_helpers.rb
new file mode 100644
index 00000000000..b8d7ea3662f
--- /dev/null
+++ b/spec/support/helpers/database/database_helpers.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Database
+ module DatabaseHelpers
+ # In order to directly work with views using factories,
+ # we can swapout the view for a table of identical structure.
+ def swapout_view_for_table(view)
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ CREATE TABLE #{view}_copy (LIKE #{view});
+ DROP VIEW #{view};
+ ALTER TABLE #{view}_copy RENAME TO #{view};
+ SQL
+ end
+ end
+end
diff --git a/spec/support/helpers/database/partitioning_helpers.rb b/spec/support/helpers/database/partitioning_helpers.rb
new file mode 100644
index 00000000000..80b31fe0603
--- /dev/null
+++ b/spec/support/helpers/database/partitioning_helpers.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+module Database
+ module PartitioningHelpers
+ def expect_table_partitioned_by(table, columns, part_type: :range)
+ columns_with_part_type = columns.map { |c| [part_type.to_s, c] }
+ actual_columns = find_partitioned_columns(table)
+
+ expect(columns_with_part_type).to match_array(actual_columns)
+ end
+
+ def expect_range_partition_of(partition_name, table_name, min_value, max_value)
+ definition = find_partition_definition(partition_name, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+
+ expect(definition).not_to be_nil
+ expect(definition['base_table']).to eq(table_name.to_s)
+ expect(definition['condition']).to eq("FOR VALUES FROM (#{min_value}) TO (#{max_value})")
+ end
+
+ def expect_total_partitions(table_name, count, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+ partitions = find_partitions(table_name, schema: schema)
+
+ expect(partitions.size).to eq(count)
+ end
+
+ def expect_range_partitions_for(table_name, partitions)
+ partitions.each do |suffix, (min_value, max_value)|
+ partition_name = "#{table_name}_#{suffix}"
+ expect_range_partition_of(partition_name, table_name, min_value, max_value)
+ end
+
+ expect_total_partitions(table_name, partitions.size, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+ end
+
+ def expect_hash_partition_of(partition_name, table_name, modulus, remainder)
+ definition = find_partition_definition(partition_name, schema: Gitlab::Database::STATIC_PARTITIONS_SCHEMA)
+
+ expect(definition).not_to be_nil
+ expect(definition['base_table']).to eq(table_name.to_s)
+ expect(definition['condition']).to eq("FOR VALUES WITH (modulus #{modulus}, remainder #{remainder})")
+ end
+
+ private
+
+ def find_partitioned_columns(table)
+ connection.select_rows(<<~SQL)
+ select
+ case partstrat
+ when 'l' then 'list'
+ when 'r' then 'range'
+ when 'h' then 'hash'
+ end as partstrat,
+ cols.column_name
+ from (
+ select partrelid, partstrat, unnest(partattrs) as col_pos
+ from pg_partitioned_table
+ ) pg_part
+ inner join pg_class
+ on pg_part.partrelid = pg_class.oid
+ inner join information_schema.columns cols
+ on cols.table_name = pg_class.relname
+ and cols.ordinal_position = pg_part.col_pos
+ where pg_class.relname = '#{table}';
+ SQL
+ end
+
+ def find_partition_definition(partition, schema: )
+ connection.select_one(<<~SQL)
+ select
+ parent_class.relname as base_table,
+ pg_get_expr(pg_class.relpartbound, inhrelid) as condition
+ from pg_class
+ inner join pg_inherits i on pg_class.oid = inhrelid
+ inner join pg_class parent_class on parent_class.oid = inhparent
+ inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
+ where pg_namespace.nspname = '#{schema}'
+ and pg_class.relname = '#{partition}'
+ and pg_class.relispartition
+ SQL
+ end
+
+ def find_partitions(partition, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+ connection.select_rows(<<~SQL)
+ select
+ pg_class.relname
+ from pg_class
+ inner join pg_inherits i on pg_class.oid = inhrelid
+ inner join pg_class parent_class on parent_class.oid = inhparent
+ inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
+ where pg_namespace.nspname = '#{schema}'
+ and parent_class.relname = '#{partition}'
+ and pg_class.relispartition
+ SQL
+ end
+ end
+end
diff --git a/spec/support/helpers/database/table_schema_helpers.rb b/spec/support/helpers/database/table_schema_helpers.rb
new file mode 100644
index 00000000000..48d33442110
--- /dev/null
+++ b/spec/support/helpers/database/table_schema_helpers.rb
@@ -0,0 +1,149 @@
+# frozen_string_literal: true
+
+module Database
+ module TableSchemaHelpers
+ def connection
+ ActiveRecord::Base.connection
+ end
+
+ def expect_table_to_be_replaced(original_table:, replacement_table:, archived_table:)
+ original_oid = table_oid(original_table)
+ replacement_oid = table_oid(replacement_table)
+
+ yield
+
+ expect(table_oid(original_table)).to eq(replacement_oid)
+ expect(table_oid(archived_table)).to eq(original_oid)
+ expect(table_oid(replacement_table)).to be_nil
+ end
+
+ def expect_table_columns_to_match(expected_column_attributes, table_name)
+ expect(connection.table_exists?(table_name)).to eq(true)
+
+ actual_columns = connection.columns(table_name)
+ expect(actual_columns.size).to eq(column_attributes.size)
+
+ column_attributes.each_with_index do |attributes, i|
+ actual_column = actual_columns[i]
+
+ attributes.each do |name, value|
+ actual_value = actual_column.public_send(name)
+ message = "expected #{actual_column.name}.#{name} to be #{value}, but got #{actual_value}"
+
+ expect(actual_value).to eq(value), message
+ end
+ end
+ end
+
+ def expect_index_to_exist(name, schema: nil)
+ expect(index_exists_by_name(name, schema: schema)).to eq(true)
+ end
+
+ def expect_index_not_to_exist(name, schema: nil)
+ expect(index_exists_by_name(name, schema: schema)).to be_nil
+ end
+
+ def expect_check_constraint(table_name, name, definition, schema: nil)
+ expect(check_constraint_definition(table_name, name, schema: schema)).to eq("CHECK ((#{definition}))")
+ end
+
+ def expect_primary_keys_after_tables(tables, schema: nil)
+ tables.each do |table|
+ primary_key = primary_key_constraint_name(table, schema: schema)
+
+ expect(primary_key).to eq("#{table}_pkey")
+ end
+ end
+
+ def table_oid(name)
+ connection.select_value(<<~SQL)
+ SELECT oid
+ FROM pg_catalog.pg_class
+ WHERE relname = '#{name}'
+ SQL
+ end
+
+ def table_type(name)
+ connection.select_value(<<~SQL)
+ SELECT
+ CASE class.relkind
+ WHEN 'r' THEN 'normal'
+ WHEN 'p' THEN 'partitioned'
+ ELSE 'other'
+ END as table_type
+ FROM pg_catalog.pg_class class
+ WHERE class.relname = '#{name}'
+ SQL
+ end
+
+ def sequence_owned_by(table_name, column_name)
+ connection.select_value(<<~SQL)
+ SELECT
+ sequence.relname as name
+ FROM pg_catalog.pg_class as sequence
+ INNER JOIN pg_catalog.pg_depend depend
+ ON depend.objid = sequence.oid
+ INNER JOIN pg_catalog.pg_class class
+ ON class.oid = depend.refobjid
+ INNER JOIN pg_catalog.pg_attribute attribute
+ ON attribute.attnum = depend.refobjsubid
+ AND attribute.attrelid = depend.refobjid
+ WHERE class.relname = '#{table_name}'
+ AND attribute.attname = '#{column_name}'
+ SQL
+ end
+
+ def default_expression_for(table_name, column_name)
+ connection.select_value(<<~SQL)
+ SELECT
+ pg_get_expr(attrdef.adbin, attrdef.adrelid) AS default_value
+ FROM pg_catalog.pg_attribute attribute
+ INNER JOIN pg_catalog.pg_attrdef attrdef
+ ON attribute.attrelid = attrdef.adrelid
+ AND attribute.attnum = attrdef.adnum
+ WHERE attribute.attrelid = '#{table_name}'::regclass
+ AND attribute.attname = '#{column_name}'
+ SQL
+ end
+
+ def primary_key_constraint_name(table_name, schema: nil)
+ table_name = schema ? "#{schema}.#{table_name}" : table_name
+
+ connection.select_value(<<~SQL)
+ SELECT
+ conname AS constraint_name
+ FROM pg_catalog.pg_constraint
+ WHERE pg_constraint.conrelid = '#{table_name}'::regclass
+ AND pg_constraint.contype = 'p'
+ SQL
+ end
+
+ def index_exists_by_name(index, schema: nil)
+ schema = schema ? "'#{schema}'" : 'current_schema'
+
+ connection.select_value(<<~SQL)
+ SELECT true
+ FROM pg_catalog.pg_index i
+ INNER JOIN pg_catalog.pg_class c
+ ON c.oid = i.indexrelid
+ INNER JOIN pg_catalog.pg_namespace n
+ ON c.relnamespace = n.oid
+ WHERE c.relname = '#{index}'
+ AND n.nspname = #{schema}
+ SQL
+ end
+
+ def check_constraint_definition(table_name, constraint_name, schema: nil)
+ table_name = schema ? "#{schema}.#{table_name}" : table_name
+
+ connection.select_value(<<~SQL)
+ SELECT
+ pg_get_constraintdef(oid) AS constraint_definition
+ FROM pg_catalog.pg_constraint
+ WHERE pg_constraint.conrelid = '#{table_name}'::regclass
+ AND pg_constraint.contype = 'c'
+ AND pg_constraint.conname = '#{constraint_name}'
+ SQL
+ end
+ end
+end
diff --git a/spec/support/helpers/database/trigger_helpers.rb b/spec/support/helpers/database/trigger_helpers.rb
new file mode 100644
index 00000000000..9ec03e68413
--- /dev/null
+++ b/spec/support/helpers/database/trigger_helpers.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Database
+ module TriggerHelpers
+ def expect_function_to_exist(name)
+ expect(find_function_def(name)).not_to be_nil
+ end
+
+ def expect_function_not_to_exist(name)
+ expect(find_function_def(name)).to be_nil
+ end
+
+ def expect_function_to_contain(name, *statements)
+ return_stmt, *body_stmts = parsed_function_statements(name).reverse
+
+ expect(return_stmt).to eq('return old')
+ expect(body_stmts).to contain_exactly(*statements)
+ end
+
+ def expect_trigger_not_to_exist(table_name, name)
+ expect(find_trigger_def(table_name, name)).to be_nil
+ end
+
+ def expect_valid_function_trigger(table_name, name, fn_name, fires_on)
+ events, timing, definition = cleaned_trigger_def(table_name, name)
+
+ events = events&.split(',')
+ expected_timing, expected_events = fires_on.first
+ expect(timing).to eq(expected_timing.to_s)
+ expect(events).to match_array(Array.wrap(expected_events))
+
+ expect(definition).to match(%r{execute (?:procedure|function) #{fn_name}()})
+ end
+
+ private
+
+ def parsed_function_statements(name)
+ cleaned_definition = find_function_def(name)['body'].downcase.gsub(/\s+/, ' ')
+ statements = cleaned_definition.sub(/\A\s*begin\s*(.*)\s*end\s*\Z/, "\\1")
+ statements.split(';').map! { |stmt| stmt.strip.presence }.compact!
+ end
+
+ def find_function_def(name)
+ connection.select_one(<<~SQL)
+ SELECT prosrc AS body
+ FROM pg_proc
+ WHERE proname = '#{name}'
+ SQL
+ end
+
+ def cleaned_trigger_def(table_name, name)
+ find_trigger_def(table_name, name).values_at('event', 'action_timing', 'action_statement').map!(&:downcase)
+ end
+
+ def find_trigger_def(table_name, name)
+ connection.select_one(<<~SQL)
+ SELECT
+ string_agg(event_manipulation, ',') AS event,
+ action_timing,
+ action_statement
+ FROM information_schema.triggers
+ WHERE event_object_table = '#{table_name}'
+ AND trigger_name = '#{name}'
+ GROUP BY 2, 3
+ SQL
+ end
+ end
+end
diff --git a/spec/support/helpers/database_helpers.rb b/spec/support/helpers/database_helpers.rb
deleted file mode 100644
index e9f0a74a8d1..00000000000
--- a/spec/support/helpers/database_helpers.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module DatabaseHelpers
- # In order to directly work with views using factories,
- # we can swapout the view for a table of identical structure.
- def swapout_view_for_table(view)
- ActiveRecord::Base.connection.execute(<<~SQL)
- CREATE TABLE #{view}_copy (LIKE #{view});
- DROP VIEW #{view};
- ALTER TABLE #{view}_copy RENAME TO #{view};
- SQL
- end
-end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index b20801bd3c4..35c298a4d48 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -67,14 +67,16 @@ module GraphqlHelpers
end
end
+ def with_clean_batchloader_executor(&block)
+ BatchLoader::Executor.ensure_current
+ yield
+ ensure
+ BatchLoader::Executor.clear_current
+ end
+
# Runs a block inside a BatchLoader::Executor wrapper
def batch(max_queries: nil, &blk)
- wrapper = proc do
- BatchLoader::Executor.ensure_current
- yield
- ensure
- BatchLoader::Executor.clear_current
- end
+ wrapper = -> { with_clean_batchloader_executor(&blk) }
if max_queries
result = nil
@@ -85,6 +87,32 @@ module GraphqlHelpers
end
end
+ # Use this when writing N+1 tests.
+ #
+ # It does not use the controller, so it avoids confounding factors due to
+ # authentication (token set-up, license checks)
+ # It clears the request store, rails cache, and BatchLoader Executor between runs.
+ def run_with_clean_state(query, **args)
+ ::Gitlab::WithRequestStore.with_request_store do
+ with_clean_rails_cache do
+ with_clean_batchloader_executor do
+ ::GitlabSchema.execute(query, **args)
+ end
+ end
+ end
+ end
+
+ # Basically a combination of use_sql_query_cache and use_clean_rails_memory_store_caching,
+ # but more fine-grained, suitable for comparing two runs in the same example.
+ def with_clean_rails_cache(&blk)
+ caching_store = Rails.cache
+ Rails.cache = ActiveSupport::Cache::MemoryStore.new
+
+ ActiveRecord::Base.cache(&blk)
+ ensure
+ Rails.cache = caching_store
+ end
+
# BatchLoader::GraphQL returns a wrapper, so we need to :sync in order
# to get the actual values
def batch_sync(max_queries: nil, &blk)
@@ -245,7 +273,7 @@ module GraphqlHelpers
return if max_depth <= 0
allow_unlimited_graphql_complexity
- allow_unlimited_graphql_depth
+ allow_unlimited_graphql_depth if max_depth > 1
allow_high_graphql_recursion
allow_high_graphql_transaction_threshold
diff --git a/spec/support/helpers/multipart_helpers.rb b/spec/support/helpers/multipart_helpers.rb
index bcb184f84c5..8438a83aa8a 100644
--- a/spec/support/helpers/multipart_helpers.rb
+++ b/spec/support/helpers/multipart_helpers.rb
@@ -13,29 +13,23 @@ module MultipartHelpers
)
end
- # This function assumes a `mode` variable to be set
- def upload_parameters_for(filepath: nil, key: nil, filename: 'filename', remote_id: 'remote_id')
+ def upload_parameters_for(filepath: nil, key: nil, mode: nil, filename: 'filename', remote_id: 'remote_id')
result = {
- "#{key}.name" => filename,
- "#{key}.type" => "application/octet-stream",
- "#{key}.sha256" => "1234567890"
+ "name" => filename,
+ "type" => "application/octet-stream",
+ "sha256" => "1234567890"
}
case mode
when :local
- result["#{key}.path"] = filepath
+ result["path"] = filepath
when :remote
- result["#{key}.remote_id"] = remote_id
- result["#{key}.size"] = 3.megabytes
+ result["remote_id"] = remote_id
+ result["size"] = 3.megabytes
else
raise ArgumentError, "can't handle #{mode} mode"
end
- return result if ::Feature.disabled?(:upload_middleware_jwt_params_handler, default_enabled: true)
-
- # the HandlerForJWTParams expects a jwt token with the upload parameters
- # *without* the "#{key}." prefix
- result.deep_transform_keys! { |k| k.remove("#{key}.") }
{
"#{key}.gitlab-workhorse-upload" => jwt_token(data: { 'upload' => result })
}
diff --git a/spec/support/helpers/partitioning_helpers.rb b/spec/support/helpers/partitioning_helpers.rb
deleted file mode 100644
index 8981fea04d5..00000000000
--- a/spec/support/helpers/partitioning_helpers.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-module PartitioningHelpers
- def expect_table_partitioned_by(table, columns, part_type: :range)
- columns_with_part_type = columns.map { |c| [part_type.to_s, c] }
- actual_columns = find_partitioned_columns(table)
-
- expect(columns_with_part_type).to match_array(actual_columns)
- end
-
- def expect_range_partition_of(partition_name, table_name, min_value, max_value)
- definition = find_partition_definition(partition_name, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
-
- expect(definition).not_to be_nil
- expect(definition['base_table']).to eq(table_name.to_s)
- expect(definition['condition']).to eq("FOR VALUES FROM (#{min_value}) TO (#{max_value})")
- end
-
- def expect_total_partitions(table_name, count, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
- partitions = find_partitions(table_name, schema: schema)
-
- expect(partitions.size).to eq(count)
- end
-
- def expect_range_partitions_for(table_name, partitions)
- partitions.each do |suffix, (min_value, max_value)|
- partition_name = "#{table_name}_#{suffix}"
- expect_range_partition_of(partition_name, table_name, min_value, max_value)
- end
-
- expect_total_partitions(table_name, partitions.size, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
- end
-
- def expect_hash_partition_of(partition_name, table_name, modulus, remainder)
- definition = find_partition_definition(partition_name, schema: Gitlab::Database::STATIC_PARTITIONS_SCHEMA)
-
- expect(definition).not_to be_nil
- expect(definition['base_table']).to eq(table_name.to_s)
- expect(definition['condition']).to eq("FOR VALUES WITH (modulus #{modulus}, remainder #{remainder})")
- end
-
- private
-
- def find_partitioned_columns(table)
- connection.select_rows(<<~SQL)
- select
- case partstrat
- when 'l' then 'list'
- when 'r' then 'range'
- when 'h' then 'hash'
- end as partstrat,
- cols.column_name
- from (
- select partrelid, partstrat, unnest(partattrs) as col_pos
- from pg_partitioned_table
- ) pg_part
- inner join pg_class
- on pg_part.partrelid = pg_class.oid
- inner join information_schema.columns cols
- on cols.table_name = pg_class.relname
- and cols.ordinal_position = pg_part.col_pos
- where pg_class.relname = '#{table}';
- SQL
- end
-
- def find_partition_definition(partition, schema: )
- connection.select_one(<<~SQL)
- select
- parent_class.relname as base_table,
- pg_get_expr(pg_class.relpartbound, inhrelid) as condition
- from pg_class
- inner join pg_inherits i on pg_class.oid = inhrelid
- inner join pg_class parent_class on parent_class.oid = inhparent
- inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
- where pg_namespace.nspname = '#{schema}'
- and pg_class.relname = '#{partition}'
- and pg_class.relispartition
- SQL
- end
-
- def find_partitions(partition, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
- connection.select_rows(<<~SQL)
- select
- pg_class.relname
- from pg_class
- inner join pg_inherits i on pg_class.oid = inhrelid
- inner join pg_class parent_class on parent_class.oid = inhparent
- inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
- where pg_namespace.nspname = '#{schema}'
- and parent_class.relname = '#{partition}'
- and pg_class.relispartition
- SQL
- end
-end
diff --git a/spec/support/helpers/rack_attack_spec_helpers.rb b/spec/support/helpers/rack_attack_spec_helpers.rb
index a8ae69885d8..d50a6382a40 100644
--- a/spec/support/helpers/rack_attack_spec_helpers.rb
+++ b/spec/support/helpers/rack_attack_spec_helpers.rb
@@ -21,10 +21,31 @@ module RackAttackSpecHelpers
{ 'AUTHORIZATION' => "Bearer #{oauth_access_token.token}" }
end
+ def basic_auth_headers(user, personal_access_token)
+ encoded_login = ["#{user.username}:#{personal_access_token.token}"].pack('m0')
+ { 'AUTHORIZATION' => "Basic #{encoded_login}" }
+ end
+
def expect_rejection(&block)
yield
expect(response).to have_gitlab_http_status(:too_many_requests)
+
+ expect(response.headers.to_h).to include(
+ 'RateLimit-Limit' => a_string_matching(/^\d+$/),
+ 'RateLimit-Name' => a_string_matching(/^throttle_.*$/),
+ 'RateLimit-Observed' => a_string_matching(/^\d+$/),
+ 'RateLimit-Remaining' => a_string_matching(/^\d+$/),
+ 'Retry-After' => a_string_matching(/^\d+$/)
+ )
+ expect(response).to have_header('RateLimit-Reset')
+ expect do
+ DateTime.strptime(response.headers['RateLimit-Reset'], '%s')
+ end.not_to raise_error
+ expect(response).to have_header('RateLimit-ResetTime')
+ expect do
+ Time.httpdate(response.headers['RateLimit-ResetTime'])
+ end.not_to raise_error
end
def expect_ok(&block)
diff --git a/spec/support/helpers/stub_experiments.rb b/spec/support/helpers/stub_experiments.rb
index 247692d83ee..408d16a7c08 100644
--- a/spec/support/helpers/stub_experiments.rb
+++ b/spec/support/helpers/stub_experiments.rb
@@ -11,6 +11,7 @@ module StubExperiments
allow(Gitlab::Experimentation).to receive(:active?).and_call_original
experiments.each do |experiment_key, enabled|
+ Feature.persist_used!("#{experiment_key}#{feature_flag_suffix}")
allow(Gitlab::Experimentation).to receive(:active?).with(experiment_key) { enabled }
end
end
@@ -25,7 +26,14 @@ module StubExperiments
allow(Gitlab::Experimentation).to receive(:in_experiment_group?).and_call_original
experiments.each do |experiment_key, enabled|
+ Feature.persist_used!("#{experiment_key}#{feature_flag_suffix}")
allow(Gitlab::Experimentation).to receive(:in_experiment_group?).with(experiment_key, anything) { enabled }
end
end
+
+ private
+
+ def feature_flag_suffix
+ Gitlab::Experimentation::Experiment::FEATURE_FLAG_SUFFIX
+ end
end
diff --git a/spec/support/helpers/stub_feature_flags.rb b/spec/support/helpers/stub_feature_flags.rb
index 7f30a2a70cd..77f31169ecb 100644
--- a/spec/support/helpers/stub_feature_flags.rb
+++ b/spec/support/helpers/stub_feature_flags.rb
@@ -66,4 +66,8 @@ module StubFeatureFlags
def skip_feature_flags_yaml_validation
allow(Feature::Definition).to receive(:valid_usage!)
end
+
+ def skip_default_enabled_yaml_check
+ allow(Feature::Definition).to receive(:default_enabled?).and_return(false)
+ end
end
diff --git a/spec/support/helpers/table_schema_helpers.rb b/spec/support/helpers/table_schema_helpers.rb
deleted file mode 100644
index 28794211190..00000000000
--- a/spec/support/helpers/table_schema_helpers.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-# frozen_string_literal: true
-
-module TableSchemaHelpers
- def connection
- ActiveRecord::Base.connection
- end
-
- def expect_table_to_be_replaced(original_table:, replacement_table:, archived_table:)
- original_oid = table_oid(original_table)
- replacement_oid = table_oid(replacement_table)
-
- yield
-
- expect(table_oid(original_table)).to eq(replacement_oid)
- expect(table_oid(archived_table)).to eq(original_oid)
- expect(table_oid(replacement_table)).to be_nil
- end
-
- def expect_index_to_exist(name, schema: nil)
- expect(index_exists_by_name(name, schema: schema)).to eq(true)
- end
-
- def expect_index_not_to_exist(name, schema: nil)
- expect(index_exists_by_name(name, schema: schema)).to be_nil
- end
-
- def expect_primary_keys_after_tables(tables, schema: nil)
- tables.each do |table|
- primary_key = primary_key_constraint_name(table, schema: schema)
-
- expect(primary_key).to eq("#{table}_pkey")
- end
- end
-
- def table_oid(name)
- connection.select_value(<<~SQL)
- SELECT oid
- FROM pg_catalog.pg_class
- WHERE relname = '#{name}'
- SQL
- end
-
- def table_type(name)
- connection.select_value(<<~SQL)
- SELECT
- CASE class.relkind
- WHEN 'r' THEN 'normal'
- WHEN 'p' THEN 'partitioned'
- ELSE 'other'
- END as table_type
- FROM pg_catalog.pg_class class
- WHERE class.relname = '#{name}'
- SQL
- end
-
- def sequence_owned_by(table_name, column_name)
- connection.select_value(<<~SQL)
- SELECT
- sequence.relname as name
- FROM pg_catalog.pg_class as sequence
- INNER JOIN pg_catalog.pg_depend depend
- ON depend.objid = sequence.oid
- INNER JOIN pg_catalog.pg_class class
- ON class.oid = depend.refobjid
- INNER JOIN pg_catalog.pg_attribute attribute
- ON attribute.attnum = depend.refobjsubid
- AND attribute.attrelid = depend.refobjid
- WHERE class.relname = '#{table_name}'
- AND attribute.attname = '#{column_name}'
- SQL
- end
-
- def default_expression_for(table_name, column_name)
- connection.select_value(<<~SQL)
- SELECT
- pg_get_expr(attrdef.adbin, attrdef.adrelid) AS default_value
- FROM pg_catalog.pg_attribute attribute
- INNER JOIN pg_catalog.pg_attrdef attrdef
- ON attribute.attrelid = attrdef.adrelid
- AND attribute.attnum = attrdef.adnum
- WHERE attribute.attrelid = '#{table_name}'::regclass
- AND attribute.attname = '#{column_name}'
- SQL
- end
-
- def primary_key_constraint_name(table_name, schema: nil)
- table_name = schema ? "#{schema}.#{table_name}" : table_name
-
- connection.select_value(<<~SQL)
- SELECT
- conname AS constraint_name
- FROM pg_catalog.pg_constraint
- WHERE pg_constraint.conrelid = '#{table_name}'::regclass
- AND pg_constraint.contype = 'p'
- SQL
- end
-
- def index_exists_by_name(index, schema: nil)
- schema = schema ? "'#{schema}'" : 'current_schema'
-
- connection.select_value(<<~SQL)
- SELECT true
- FROM pg_catalog.pg_index i
- INNER JOIN pg_catalog.pg_class c
- ON c.oid = i.indexrelid
- INNER JOIN pg_catalog.pg_namespace n
- ON c.relnamespace = n.oid
- WHERE c.relname = '#{index}'
- AND n.nspname = #{schema}
- SQL
- end
-end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 01571277a1d..cb25f5f9429 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -203,10 +203,13 @@ module TestEnv
end
gitaly_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly.pid')))
+ gitaly2_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly2.pid')))
praefect_pid = Integer(File.read(TMP_TEST_PATH.join('praefect.pid')))
- Kernel.at_exit { stop(gitaly_pid) }
- Kernel.at_exit { stop(praefect_pid) }
+ Kernel.at_exit do
+ pids = [gitaly_pid, gitaly2_pid, praefect_pid]
+ pids.each { |pid| stop(pid) }
+ end
wait('gitaly')
wait('praefect')
@@ -284,7 +287,7 @@ module TestEnv
@workhorse_path ||= File.join('tmp', 'tests', 'gitlab-workhorse')
end
- def with_workhorse(workhorse_dir, host, port, upstream, &blk)
+ def with_workhorse(host, port, upstream, &blk)
host = "[#{host}]" if host.include?(':')
listen_addr = [host, port].join(':')
diff --git a/spec/support/helpers/trigger_helpers.rb b/spec/support/helpers/trigger_helpers.rb
deleted file mode 100644
index dd6d8ff5bb5..00000000000
--- a/spec/support/helpers/trigger_helpers.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-module TriggerHelpers
- def expect_function_to_exist(name)
- expect(find_function_def(name)).not_to be_nil
- end
-
- def expect_function_not_to_exist(name)
- expect(find_function_def(name)).to be_nil
- end
-
- def expect_function_to_contain(name, *statements)
- return_stmt, *body_stmts = parsed_function_statements(name).reverse
-
- expect(return_stmt).to eq('return old')
- expect(body_stmts).to contain_exactly(*statements)
- end
-
- def expect_trigger_not_to_exist(table_name, name)
- expect(find_trigger_def(table_name, name)).to be_nil
- end
-
- def expect_valid_function_trigger(table_name, name, fn_name, fires_on)
- events, timing, definition = cleaned_trigger_def(table_name, name)
-
- events = events&.split(',')
- expected_timing, expected_events = fires_on.first
- expect(timing).to eq(expected_timing.to_s)
- expect(events).to match_array(Array.wrap(expected_events))
-
- expect(definition).to match(%r{execute (?:procedure|function) #{fn_name}()})
- end
-
- private
-
- def parsed_function_statements(name)
- cleaned_definition = find_function_def(name)['body'].downcase.gsub(/\s+/, ' ')
- statements = cleaned_definition.sub(/\A\s*begin\s*(.*)\s*end\s*\Z/, "\\1")
- statements.split(';').map! { |stmt| stmt.strip.presence }.compact!
- end
-
- def find_function_def(name)
- connection.select_one(<<~SQL)
- SELECT prosrc AS body
- FROM pg_proc
- WHERE proname = '#{name}'
- SQL
- end
-
- def cleaned_trigger_def(table_name, name)
- find_trigger_def(table_name, name).values_at('event', 'action_timing', 'action_statement').map!(&:downcase)
- end
-
- def find_trigger_def(table_name, name)
- connection.select_one(<<~SQL)
- SELECT
- string_agg(event_manipulation, ',') AS event,
- action_timing,
- action_statement
- FROM information_schema.triggers
- WHERE event_object_table = '#{table_name}'
- AND trigger_name = '#{name}'
- GROUP BY 2, 3
- SQL
- end
-end
diff --git a/spec/support/matchers/be_sorted.rb b/spec/support/matchers/be_sorted.rb
index 1455060fe71..b0ab93efbb2 100644
--- a/spec/support/matchers/be_sorted.rb
+++ b/spec/support/matchers/be_sorted.rb
@@ -4,18 +4,75 @@
#
# By default, this checks that the collection is sorted ascending
# but you can check order by specific field and order by passing
-# them, eg:
+# them, either as arguments, or using the fluent interface, eg:
#
# ```
+# # Usage examples:
+# expect(collection).to be_sorted
+# expect(collection).to be_sorted(:field)
# expect(collection).to be_sorted(:field, :desc)
+# expect(collection).to be_sorted.asc
+# expect(collection).to be_sorted.desc.by(&:field)
+# expect(collection).to be_sorted.by(&:field).desc
+# expect(collection).to be_sorted.by { |x| [x.foo, x.bar] }
# ```
-RSpec::Matchers.define :be_sorted do |by, order = :asc|
+RSpec::Matchers.define :be_sorted do |on = :itself, order = :asc|
+ def by(&block)
+ @comparator = block
+ self
+ end
+
+ def asc
+ @direction = :asc
+ self
+ end
+
+ def desc
+ @direction = :desc
+ self
+ end
+
+ def format_with(proc)
+ @format_with = proc
+ self
+ end
+
+ define_method :comparator do
+ @comparator || on
+ end
+
+ define_method :descending? do
+ (@direction || order.to_sym) == :desc
+ end
+
+ def order(items)
+ descending? ? items.reverse : items
+ end
+
+ def sort(items)
+ items.sort_by(&comparator)
+ end
+
match do |actual|
- next true unless actual.present? # emtpy collection is sorted
+ next true unless actual.present? # empty collection is sorted
+
+ actual = actual.to_a if actual.respond_to?(:to_a) && !actual.respond_to?(:sort_by)
+
+ @got = actual
+ @expected = order(sort(actual))
+
+ @expected == actual
+ end
+
+ def failure_message
+ "Expected #{show(@expected)}, got #{show(@got)}"
+ end
- actual
- .then { |collection| by ? collection.sort_by(&by) : collection.sort }
- .then { |sorted_collection| order.to_sym == :desc ? sorted_collection.reverse : sorted_collection }
- .then { |sorted_collection| sorted_collection == actual }
+ def show(things)
+ if @format_with
+ things.map(&@format_with)
+ else
+ things
+ end
end
end
diff --git a/spec/support/matchers/be_valid_json.rb b/spec/support/matchers/be_valid_json.rb
index f46c35c7198..228c1fc986e 100644
--- a/spec/support/matchers/be_valid_json.rb
+++ b/spec/support/matchers/be_valid_json.rb
@@ -1,20 +1,8 @@
# frozen_string_literal: true
RSpec::Matchers.define :be_valid_json do
- def according_to_schema(schema)
- @schema = schema
- self
- end
-
match do |actual|
- data = Gitlab::Json.parse(actual)
-
- if @schema.present?
- @validation_errors = JSON::Validator.fully_validate(@schema, data)
- @validation_errors.empty?
- else
- data.present?
- end
+ Gitlab::Json.parse(actual).present?
rescue JSON::ParserError => e
@error = e
false
@@ -23,8 +11,6 @@ RSpec::Matchers.define :be_valid_json do
def failure_message
if @error
"Parse failed with error: #{@error}"
- elsif @validation_errors.present?
- "Validation failed because #{@validation_errors.join(', and ')}"
else
"Parsing did not return any data"
end
diff --git a/spec/support/matchers/schema_matcher.rb b/spec/support/matchers/schema_matcher.rb
index ebbd57c8115..f0e7a52c51e 100644
--- a/spec/support/matchers/schema_matcher.rb
+++ b/spec/support/matchers/schema_matcher.rb
@@ -2,6 +2,8 @@
module SchemaPath
def self.expand(schema, dir = nil)
+ return schema unless schema.is_a?(String)
+
if Gitlab.ee? && dir.nil?
ee_path = expand(schema, 'ee')
@@ -35,7 +37,13 @@ RSpec::Matchers.define :match_schema do |schema, dir: nil, **options|
end
failure_message do |response|
- "didn't match the schema defined by #{SchemaPath.expand(schema, dir)}" \
+ "didn't match the schema defined by #{schema_name(schema, dir)}" \
" The validation errors were:\n#{@errors.join("\n")}"
end
+
+ def schema_name(schema, dir)
+ return 'provided schema' unless schema.is_a?(String)
+
+ SchemaPath.expand(schema, dir)
+ end
end
diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb
index 32f738faa9b..00b9aac7bf4 100644
--- a/spec/support/rspec.rb
+++ b/spec/support/rspec.rb
@@ -25,4 +25,8 @@ RSpec.configure do |config|
config.include FastRailsRoot
config.include RuboCop::RSpec::ExpectOffense, type: :rubocop
+
+ config.define_derived_metadata(file_path: %r{spec/rubocop}) do |metadata|
+ metadata[:type] = :rubocop
+ end
end
diff --git a/spec/support/shared_contexts/email_shared_context.rb b/spec/support/shared_contexts/email_shared_context.rb
index 298e03162c4..9dffea7c94e 100644
--- a/spec/support/shared_contexts/email_shared_context.rb
+++ b/spec/support/shared_contexts/email_shared_context.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
RSpec.shared_context :email_shared_context do
- let(:mail_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" }
+ let(:mail_key) { '59d8df8370b7e95c5a49fbf86aeb2c93' }
let(:receiver) { Gitlab::Email::Receiver.new(email_raw) }
- let(:markdown) { "![image](uploads/image.png)" }
+ let(:markdown) { '![image](uploads/image.png)' }
def setup_attachment
allow_any_instance_of(Gitlab::Email::AttachmentUploader).to receive(:execute).and_return(
[
{
- url: "uploads/image.png",
- alt: "image",
+ url: 'uploads/image.png',
+ alt: 'image',
markdown: markdown
}
]
@@ -19,23 +19,252 @@ RSpec.shared_context :email_shared_context do
end
RSpec.shared_examples :reply_processing_shared_examples do
- context "when the user could not be found" do
+ context 'when the user could not be found' do
before do
user.destroy!
end
- it "raises a UserNotFoundError" do
+ it 'raises a UserNotFoundError' do
expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
end
end
- context "when the user is not authorized to the project" do
+ context 'when the user is not authorized to the project' do
before do
project.update_attribute(:visibility_level, Project::PRIVATE)
end
- it "raises a ProjectNotFound" do
+ it 'raises a ProjectNotFound' do
expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
end
end
end
+
+RSpec.shared_examples :checks_permissions_on_noteable_examples do
+ context 'when user has access' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'creates a comment' do
+ expect { receiver.execute }.to change { noteable.notes.count }.by(1)
+ end
+ end
+
+ context 'when user does not have access' do
+ it 'raises UserNotAuthorizedError' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError)
+ end
+ end
+end
+
+RSpec.shared_examples :note_handler_shared_examples do |forwardable|
+ context 'when the noteable could not be found' do
+ before do
+ noteable.destroy!
+ end
+
+ it 'raises a NoteableNotFoundError' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::NoteableNotFoundError)
+ end
+ end
+
+ context 'when the note could not be saved' do
+ before do
+ allow_any_instance_of(Note).to receive(:persisted?).and_return(false)
+ end
+
+ it 'raises an InvalidNoteError' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
+ end
+
+ context 'because the note was update commands only' do
+ let!(:email_raw) { update_commands_only }
+
+ context 'and current user cannot update noteable' do
+ it 'raises a CommandsOnlyNoteError' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
+ end
+ end
+
+ context 'and current user can update noteable' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'does not raise an error', unless: forwardable do
+ expect { receiver.execute }.to change { noteable.resource_state_events.count }.by(1)
+
+ expect(noteable.reload).to be_closed
+ end
+
+ it 'raises an InvalidNoteError', if: forwardable do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
+ end
+ end
+ end
+ end
+
+ context 'when the note contains quick actions' do
+ let!(:email_raw) { commands_in_reply }
+
+ context 'and current user cannot update the noteable' do
+ it 'only executes the commands that the user can perform' do
+ expect { receiver.execute }
+ .to change { noteable.notes.user.count }.by(1)
+ .and change { user.todos_pending_count }.from(0).to(1)
+
+ expect(noteable.reload).to be_open
+ end
+ end
+
+ context 'and current user can update noteable' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'posts a note and updates the noteable' do
+ expect(TodoService.new.todo_exist?(noteable, user)).to be_falsy
+
+ expect { receiver.execute }
+ .to change { noteable.notes.user.count }.by(1)
+ .and change { user.todos_pending_count }.from(0).to(1)
+
+ expect(noteable.reload).to be_closed
+ end
+ end
+ end
+
+ context 'when the reply is blank' do
+ let!(:email_raw) { no_content }
+
+ it 'raises an EmptyEmailError', unless: forwardable do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::EmptyEmailError)
+ end
+
+ it 'allows email to only have quoted text', if: forwardable do
+ expect { receiver.execute }.not_to raise_error(Gitlab::Email::EmptyEmailError)
+ end
+ end
+
+ context 'when discussion is locked' do
+ before do
+ noteable.update_attribute(:discussion_locked, true)
+ end
+
+ it_behaves_like :checks_permissions_on_noteable_examples
+ end
+
+ context 'when everything is fine' do
+ before do
+ setup_attachment
+ end
+
+ it 'adds all attachments' do
+ expect_next_instance_of(Gitlab::Email::AttachmentUploader) do |uploader|
+ expect(uploader).to receive(:execute).with(upload_parent: project, uploader_class: FileUploader).and_return(
+ [
+ {
+ url: 'uploads/image.png',
+ alt: 'image',
+ markdown: markdown
+ }
+ ]
+ )
+ end
+
+ receiver.execute
+
+ note = noteable.notes.last
+ expect(note.note).to include(markdown)
+ expect(note.note).to include('Jake out')
+ end
+ end
+
+ context 'when the service desk' do
+ let(:project) { create(:project, :public, service_desk_enabled: true) }
+ let(:support_bot) { User.support_bot }
+ let(:noteable) { create(:issue, project: project, author: support_bot, title: 'service desk issue') }
+ let!(:note) { create(:note, project: project, noteable: noteable) }
+ let(:email_raw) { with_quick_actions }
+
+ let!(:sent_notification) do
+ SentNotification.record_note(note, support_bot.id, mail_key)
+ end
+
+ context 'is enabled' do
+ before do
+ allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true)
+ project.project_feature.update!(issues_access_level: issues_access_level)
+ end
+
+ context 'when issues are enabled for everyone' do
+ let(:issues_access_level) { ProjectFeature::ENABLED }
+
+ it 'creates a comment' do
+ expect { receiver.execute }.to change { noteable.notes.count }.by(1)
+ end
+
+ context 'when quick actions are present' do
+ before do
+ receiver.execute
+ noteable.reload
+ end
+
+ context 'when author is a support_bot', unless: forwardable do
+ it 'encloses quick actions with code span markdown' do
+ note = Note.last
+ expect(note.note).to include("Jake out\n\n`/close`\n`/title test`")
+ expect(noteable.title).to eq('service desk issue')
+ expect(noteable).to be_opened
+ end
+ end
+
+ context 'when author is a normal user', if: forwardable do
+ it 'extracted the quick actions' do
+ note = Note.last
+ expect(note.note).to include('Jake out')
+ expect(note.note).not_to include("`/close`\n`/title test`")
+ end
+ end
+ end
+ end
+
+ context 'when issues are protected members only' do
+ let(:issues_access_level) { ProjectFeature::PRIVATE }
+
+ before do
+ if recipient.support_bot?
+ @changed_by = 1
+ else
+ @changed_by = 2
+ project.add_developer(recipient)
+ end
+ end
+
+ it 'creates a comment' do
+ expect { receiver.execute }.to change { noteable.notes.count }.by(@changed_by)
+ end
+ end
+
+ context 'when issues are disabled' do
+ let(:issues_access_level) { ProjectFeature::DISABLED }
+
+ it 'does not create a comment' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError)
+ end
+ end
+ end
+
+ context 'is disabled', unless: forwardable do
+ before do
+ allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(false)
+ allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(false)
+ end
+
+ it 'does not create a comment' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb
index 9ffde54c84a..d9cbea58406 100644
--- a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb
@@ -8,13 +8,53 @@ RSpec.shared_context 'IssuesFinder context' do
let_it_be(:project1, reload: true) { create(:project, group: group) }
let_it_be(:project2, reload: true) { create(:project) }
let_it_be(:project3, reload: true) { create(:project, group: subgroup) }
- let_it_be(:milestone) { create(:milestone, project: project1) }
+ let_it_be(:release) { create(:release, project: project1, tag: 'v1.0.0') }
+ let_it_be(:milestone) { create(:milestone, project: project1, releases: [release]) }
let_it_be(:label) { create(:label, project: project2) }
let_it_be(:label2) { create(:label, project: project2) }
- let_it_be(:issue1, reload: true) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) }
- let_it_be(:issue2, reload: true) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) }
- let_it_be(:issue3, reload: true) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) }
+ let_it_be(:issue1, reload: true) do
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project1,
+ milestone: milestone,
+ title: 'gitlab',
+ created_at: 1.week.ago,
+ updated_at: 1.week.ago)
+ end
+
+ let_it_be(:issue2, reload: true) do
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project2,
+ description: 'gitlab',
+ created_at: 1.week.from_now,
+ updated_at: 1.week.from_now)
+ end
+
+ let_it_be(:issue3, reload: true) do
+ create(:issue,
+ author: user2,
+ assignees: [user2],
+ project: project2,
+ title: 'tanuki',
+ description: 'tanuki',
+ created_at: 2.weeks.from_now,
+ updated_at: 2.weeks.from_now)
+ end
+
let_it_be(:issue4, reload: true) { create(:issue, project: project3) }
+ let_it_be(:issue5, reload: true) do
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project1,
+ title: 'wotnot',
+ created_at: 3.days.ago,
+ updated_at: 3.days.ago)
+ end
+
let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) }
let_it_be(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) }
let_it_be(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) }
diff --git a/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb
index 54022aeb494..6a09497a497 100644
--- a/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb
@@ -2,6 +2,7 @@
RSpec.shared_context 'UsersFinder#execute filter by project context' do
let_it_be(:normal_user) { create(:user, username: 'johndoe') }
+ let_it_be(:admin_user) { create(:user, :admin, username: 'iamadmin') }
let_it_be(:blocked_user) { create(:user, :blocked, username: 'notsorandom') }
let_it_be(:external_user) { create(:user, :external) }
let_it_be(:omniauth_user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 549dc1cff1d..57d8320b76a 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -137,6 +137,7 @@ RSpec.shared_context 'group navbar structure' do
_('Projects'),
_('Repository'),
_('CI / CD'),
+ _('Packages & Registries'),
_('Webhooks')
]
}
diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
index e0e2a18cdd2..e7bc1450601 100644
--- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -19,8 +19,29 @@ RSpec.shared_context 'GroupPolicy context' do
end
let(:read_group_permissions) { %i[read_label read_list read_milestone read_board] }
- let(:reporter_permissions) { %i[admin_label read_container_image read_metrics_dashboard_annotation read_prometheus] }
- let(:developer_permissions) { %i[admin_milestone create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation] }
+
+ let(:reporter_permissions) do
+ %i[
+ admin_label
+ admin_board
+ read_container_image
+ read_metrics_dashboard_annotation
+ read_prometheus
+ read_package_settings
+ ]
+ end
+
+ let(:developer_permissions) do
+ %i[
+ admin_milestone
+ create_metrics_dashboard_annotation
+ delete_metrics_dashboard_annotation
+ update_metrics_dashboard_annotation
+ create_custom_emoji
+ create_package_settings
+ ]
+ end
+
let(:maintainer_permissions) do
%i[
create_projects
diff --git a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
index f8f33e2a745..04c50171766 100644
--- a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
+++ b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
@@ -5,5 +5,13 @@ RSpec.shared_context 'read ci configuration for sast enabled project' do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast.yml'))
end
+ let_it_be(:gitlab_ci_yml_default_analyzers_content) do
+ File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml'))
+ end
+
+ let_it_be(:gitlab_ci_yml_excluded_analyzers_content) do
+ File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast_excluded_analyzers.yml'))
+ end
+
let_it_be(:project) { create(:project, :repository) }
end
diff --git a/spec/support/shared_contexts/requests/api/nuget_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/nuget_packages_shared_context.rb
new file mode 100644
index 00000000000..f877d6299bd
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/nuget_packages_shared_context.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'nuget api setup' do
+ include WorkhorseHelpers
+ include PackagesManagerApiSpecHelpers
+ include HttpBasicAuthHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+end
diff --git a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
index 9b738a4b002..00a0fb7e4c5 100644
--- a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
@@ -77,30 +77,6 @@ RSpec.shared_examples Repositories::GitHttpController do
end
end
end
-
- context 'with exceptions' do
- before do
- allow(controller).to receive(:authenticate_user).and_return(true)
- allow(controller).to receive(:verify_workhorse_api!).and_return(true)
- end
-
- it 'returns 503 with GRPC Unavailable' do
- allow(controller).to receive(:access_check).and_raise(GRPC::Unavailable)
-
- get :info_refs, params: params
-
- expect(response).to have_gitlab_http_status(:service_unavailable)
- end
-
- it 'returns 503 with timeout error' do
- allow(controller).to receive(:access_check).and_raise(Gitlab::GitAccess::TimeoutError)
-
- get :info_refs, params: params
-
- expect(response).to have_gitlab_http_status(:service_unavailable)
- expect(response.body).to eq 'Gitlab::GitAccess::TimeoutError'
- end
- end
end
describe 'POST #git_upload_pack' do
diff --git a/spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb b/spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb
index b67eb0d99fd..041695d8111 100644
--- a/spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb
@@ -1,5 +1,9 @@
# frozen_string_literal: true
+# This controller shared examples will be migrated to
+# spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb
+# See also https://gitlab.com/groups/gitlab-org/-/epics/5076
+
RSpec.shared_examples 'authenticates sessionless user' do |path, format, params|
params ||= {}
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 cf7ee17ea13..c5d65743810 100644
--- a/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
+++ b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
@@ -7,7 +7,7 @@
RSpec.shared_examples 'tracking unique hll events' do |feature_flag|
it 'tracks unique event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(expected_type, target_id)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(target_id, values: expected_type)
request
end
diff --git a/spec/support/shared_examples/features/file_uploads_shared_examples.rb b/spec/support/shared_examples/features/file_uploads_shared_examples.rb
index ea8c8d44501..d586bf03b59 100644
--- a/spec/support/shared_examples/features/file_uploads_shared_examples.rb
+++ b/spec/support/shared_examples/features/file_uploads_shared_examples.rb
@@ -2,28 +2,6 @@
RSpec.shared_examples 'handling file uploads' do |shared_examples_name|
context 'with object storage disabled' do
- context 'with upload_middleware_jwt_params_handler disabled' do
- before do
- stub_feature_flags(upload_middleware_jwt_params_handler: false)
-
- expect_next_instance_of(Gitlab::Middleware::Multipart::Handler) do |handler|
- expect(handler).to receive(:with_open_files).and_call_original
- end
- end
-
- it_behaves_like shared_examples_name
- end
-
- context 'with upload_middleware_jwt_params_handler enabled' do
- before do
- stub_feature_flags(upload_middleware_jwt_params_handler: true)
-
- expect_next_instance_of(Gitlab::Middleware::Multipart::HandlerForJWTParams) do |handler|
- expect(handler).to receive(:with_open_files).and_call_original
- end
- end
-
- it_behaves_like shared_examples_name
- end
+ it_behaves_like shared_examples_name
end
end
diff --git a/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb b/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
index 1dbaace1c89..c2dc87b0fb0 100644
--- a/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
+++ b/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
@@ -12,9 +12,7 @@ RSpec.shared_examples 'Maintainer manages access requests' do
sign_in(maintainer)
visit members_page_path
- if has_tabs
- click_on 'Access requests'
- end
+ click_on 'Access requests'
end
it 'maintainer can see access requests', :js do
@@ -48,11 +46,7 @@ RSpec.shared_examples 'Maintainer manages access requests' do
end
def expect_visible_access_request(entity, user)
- if has_tabs
- expect(page).to have_content "Access requests 1"
- else
- expect(page).to have_content "Users requesting access to #{entity.name} 1"
- end
+ expect(page).to have_content "Access requests 1"
expect(page).to have_content user.name
end
diff --git a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
index 44d82d2e753..2f8ebd0d264 100644
--- a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
@@ -20,15 +20,25 @@ RSpec.shared_examples 'User creates wiki page' do
click_link "Create your first page"
end
- it "shows validation error message" do
+ it "shows validation error message if the form is force submitted", :js do
page.within(".wiki-form") do
fill_in(:wiki_content, with: "")
- click_on("Create page")
+ page.execute_script("window.onbeforeunload = null")
+ page.execute_script("document.querySelector('.wiki-form').submit()")
end
expect(page).to have_content("The form contains the following error:").and have_content("Content can't be blank")
+ end
+
+ it "disables the submit button", :js do
+ page.within(".wiki-form") do
+ fill_in(:wiki_content, with: "")
+ expect(page).to have_button('Create page', disabled: true)
+ end
+ end
+ it "makes sure links to unknown pages work correctly", :js do
page.within(".wiki-form") do
fill_in(:wiki_content, with: "[link test](test)")
@@ -42,7 +52,7 @@ RSpec.shared_examples 'User creates wiki page' do
expect(page).to have_content("Create New Page")
end
- it "shows non-escaped link in the pages list" do
+ it "shows non-escaped link in the pages list", :js do
fill_in(:wiki_title, with: "one/two/three-test")
page.within(".wiki-form") do
@@ -61,7 +71,7 @@ RSpec.shared_examples 'User creates wiki page' do
expect(page).to have_field("wiki[message]", with: "Create home")
end
- it "creates a page from the home page" do
+ it "creates a page from the home page", :js do
fill_in(:wiki_content, with: "[test](test)\n[GitLab API doc](api)\n[Rake tasks](raketasks)\n# Wiki header\n")
fill_in(:wiki_message, with: "Adding links to wiki")
@@ -79,7 +89,7 @@ RSpec.shared_examples 'User creates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, "test"))
- page.within(:css, ".nav-text") do
+ page.within(:css, ".wiki-page-header") do
expect(page).to have_content("Create New Page")
end
@@ -91,7 +101,7 @@ RSpec.shared_examples 'User creates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, "api"))
- page.within(:css, ".nav-text") do
+ page.within(:css, ".wiki-page-header") do
expect(page).to have_content("Create")
end
@@ -103,7 +113,7 @@ RSpec.shared_examples 'User creates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, "raketasks"))
- page.within(:css, ".nav-text") do
+ page.within(:css, ".wiki-page-header") do
expect(page).to have_content("Create")
end
end
@@ -142,7 +152,7 @@ RSpec.shared_examples 'User creates wiki page' do
end
end
- it 'creates a wiki page with Org markup', :aggregate_failures do
+ it 'creates a wiki page with Org markup', :aggregate_failures, :js do
org_content = <<~ORG
* Heading
** Subheading
@@ -170,7 +180,7 @@ RSpec.shared_examples 'User creates wiki page' do
visit wiki_path(wiki)
end
- context "via the `new wiki page` page" do
+ context "via the `new wiki page` page", :js do
it "creates a page with a single word" do
click_link("New page")
@@ -189,7 +199,7 @@ RSpec.shared_examples 'User creates wiki page' do
.and have_content("My awesome wiki!")
end
- it "creates a page with spaces in the name" do
+ it "creates a page with spaces in the name", :js do
click_link("New page")
page.within(".wiki-form") do
@@ -207,7 +217,7 @@ RSpec.shared_examples 'User creates wiki page' do
.and have_content("My awesome wiki!")
end
- it "creates a page with hyphens in the name" do
+ it "creates a page with hyphens in the name", :js do
click_link("New page")
page.within(".wiki-form") do
diff --git a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
index 3350e54a8a7..1e325535e81 100644
--- a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
@@ -90,9 +90,11 @@ RSpec.shared_examples 'User updates wiki page' do
expect(page).to have_field('wiki[message]', with: 'Update Wiki title')
end
- it 'shows a validation error message' do
+ it 'shows a validation error message if the form is force submitted', :js do
fill_in(:wiki_content, with: '')
- click_button('Save changes')
+
+ page.execute_script("window.onbeforeunload = null")
+ page.execute_script("document.querySelector('.wiki-form').submit()")
expect(page).to have_selector('.wiki-form')
expect(page).to have_content('Edit Page')
@@ -101,6 +103,13 @@ RSpec.shared_examples 'User updates wiki page' do
expect(find('textarea#wiki_content').value).to eq('')
end
+ it "disables the submit button", :js do
+ page.within(".wiki-form") do
+ fill_in(:wiki_content, with: "")
+ expect(page).to have_button('Save changes', disabled: true)
+ end
+ end
+
it 'shows the emoji autocompletion dropdown', :js do
find('#wiki_content').native.send_keys('')
fill_in(:wiki_content, with: ':')
@@ -108,7 +117,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(page).to have_selector('.atwho-view')
end
- it 'shows the error message' do
+ it 'shows the error message', :js do
wiki_page.update(content: 'Update') # rubocop:disable Rails/SaveBang
click_button('Save changes')
@@ -116,13 +125,17 @@ RSpec.shared_examples 'User updates wiki page' do
expect(page).to have_content('Someone edited the page the same time you did.')
end
- it 'updates a page' do
+ it 'updates a page', :js do
fill_in('Content', with: 'Updated Wiki Content')
click_on('Save changes')
expect(page).to have_content('Updated Wiki Content')
end
+ it 'focuses on the content field', :js do
+ expect(page).to have_selector '.note-textarea:focus'
+ end
+
it 'cancels editing of a page' do
page.within(:css, '.wiki-form .form-actions') do
click_on('Cancel')
@@ -143,7 +156,7 @@ RSpec.shared_examples 'User updates wiki page' do
visit wiki_page_path(wiki, wiki_page, action: :edit)
end
- it 'moves the page to the root folder' do
+ it 'moves the page to the root folder', :js do
fill_in(:wiki_title, with: "/#{page_name}")
click_button('Save changes')
@@ -151,7 +164,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, page_name))
end
- it 'moves the page to other dir' do
+ it 'moves the page to other dir', :js do
new_page_dir = "foo1/bar1/#{page_name}"
fill_in(:wiki_title, with: new_page_dir)
@@ -161,7 +174,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, new_page_dir))
end
- it 'remains in the same place if title has not changed' do
+ it 'remains in the same place if title has not changed', :js do
original_path = wiki_page_path(wiki, wiki_page)
fill_in(:wiki_title, with: page_name)
@@ -171,7 +184,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(current_path).to eq(original_path)
end
- it 'can be moved to a different dir with a different name' do
+ it 'can be moved to a different dir with a different name', :js do
new_page_dir = "foo1/bar1/new_page_name"
fill_in(:wiki_title, with: new_page_dir)
@@ -181,7 +194,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, new_page_dir))
end
- it 'can be renamed and moved to the root folder' do
+ it 'can be renamed and moved to the root folder', :js do
new_name = 'new_page_name'
fill_in(:wiki_title, with: "/#{new_name}")
@@ -191,7 +204,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(current_path).to eq(wiki_page_path(wiki, new_name))
end
- it 'squishes the title before creating the page' do
+ it 'squishes the title before creating the page', :js do
new_page_dir = " foo1 / bar1 / #{page_name} "
fill_in(:wiki_title, with: new_page_dir)
@@ -220,7 +233,7 @@ RSpec.shared_examples 'User updates wiki page' do
expect(page).to have_content('Wiki page was successfully updated.')
end
- it 'shows a validation error when trying to change the content' do
+ it 'shows a validation error when trying to change the content', :js do
fill_in 'Content', with: 'new content'
click_on 'Save changes'
diff --git a/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb
index 759cfaf6b1f..857d923785f 100644
--- a/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb
@@ -15,6 +15,6 @@ RSpec.shared_examples 'User uses wiki shortcuts' do
it 'visit edit wiki page using "e" keyboard shortcut', :js do
find('body').native.send_key('e')
- expect(find('.wiki-page-title')).to have_content('Edit Page')
+ expect(find('.page-title')).to have_content('Edit Page')
end
end
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb
index d7f5b485a82..14180d503df 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb
@@ -53,7 +53,7 @@ RSpec.shared_examples 'User views empty wiki' do
if writable
element.click_link 'Create your first page'
- expect(page).to have_button('Create page')
+ expect(page).to have_button('Create page', disabled: true)
else
expect(element).not_to have_link('Create your first page')
end
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
index af769be6d4b..61feeff57bb 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
@@ -44,7 +44,7 @@ RSpec.shared_examples 'User views a wiki page' do
expect(current_path).to include('one/two/three-test')
- page.within(:css, '.nav-text') do
+ page.within(:css, '.wiki-page-header') do
expect(page).to have_content('History')
end
end
@@ -69,7 +69,7 @@ RSpec.shared_examples 'User views a wiki page' do
click_on('Page history')
- within('.nav-text') do
+ within('.wiki-page-header') do
expect(page).to have_content('History')
end
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb
index a7ba7a8ad07..639eb3f2b99 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb
@@ -17,23 +17,55 @@ RSpec.shared_examples 'User views wiki sidebar' do
create(:wiki_page, wiki: wiki, title: 'another', content: 'another')
end
- it 'renders a default sidebar when there is no customized sidebar' do
- visit wiki_path(wiki)
+ context 'when there is no custom sidebar' do
+ before do
+ visit wiki_path(wiki)
+ end
- expect(page).to have_content('another')
- expect(page).not_to have_link('View All Pages')
+ it 'renders a default sidebar' do
+ within('.right-sidebar') do
+ expect(page).to have_content('another')
+ expect(page).not_to have_link('View All Pages')
+ end
+ end
+
+ it 'can create a custom sidebar', :js do
+ click_on 'Edit sidebar'
+ fill_in :wiki_content, with: 'My custom sidebar'
+ click_on 'Create page'
+
+ within('.right-sidebar') do
+ expect(page).to have_content('My custom sidebar')
+ expect(page).not_to have_content('another')
+ end
+ end
end
- context 'when there is a customized sidebar' do
+ context 'when there is a custom sidebar' do
before do
- create(:wiki_page, wiki: wiki, title: '_sidebar', content: 'My customized sidebar')
- end
+ create(:wiki_page, wiki: wiki, title: '_sidebar', content: 'My custom sidebar')
- it 'renders my customized sidebar instead of the default one' do
visit wiki_path(wiki)
+ end
+
+ it 'renders the custom sidebar instead of the default one' do
+ within('.right-sidebar') do
+ expect(page).to have_content('My custom sidebar')
+ expect(page).not_to have_content('another')
+ end
+ end
+
+ it 'can edit the custom sidebar', :js do
+ click_on 'Edit sidebar'
+
+ expect(page).to have_field(:wiki_content, with: 'My custom sidebar')
+
+ fill_in :wiki_content, with: 'My other custom sidebar'
+ click_on 'Save changes'
- expect(page).to have_content('My customized sidebar')
- expect(page).not_to have_content('Another')
+ within('.right-sidebar') do
+ expect(page).to have_content('My other custom sidebar')
+ end
end
end
end
diff --git a/spec/support/shared_examples/finders/packages/debian/distributions_finder_shared_examples.rb b/spec/support/shared_examples/finders/packages/debian/distributions_finder_shared_examples.rb
new file mode 100644
index 00000000000..2700d29bf0e
--- /dev/null
+++ b/spec/support/shared_examples/finders/packages/debian/distributions_finder_shared_examples.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Distributions Finder' do |factory, can_freeze|
+ let_it_be(:distribution_with_suite, freeze: can_freeze) { create(factory, suite: 'mysuite') }
+ let_it_be(:container) { distribution_with_suite.container }
+ let_it_be(:distribution_with_same_container, freeze: can_freeze) { create(factory, container: container ) }
+ let_it_be(:distribution_with_same_codename, freeze: can_freeze) { create(factory, codename: distribution_with_suite.codename ) }
+ let_it_be(:distribution_with_same_suite, freeze: can_freeze) { create(factory, suite: distribution_with_suite.suite ) }
+ let_it_be(:distribution_with_codename_and_suite_flipped, freeze: can_freeze) { create(factory, codename: distribution_with_suite.suite, suite: distribution_with_suite.codename) }
+
+ let(:params) { {} }
+ let(:service) { described_class.new(container, params) }
+
+ subject { service.execute.to_a }
+
+ context 'by codename' do
+ context 'with existing codename' do
+ let(:params) { { codename: distribution_with_suite.codename } }
+
+ it 'finds distributions by codename' do
+ is_expected.to contain_exactly(distribution_with_suite)
+ end
+ end
+
+ context 'with non-existing codename' do
+ let(:params) { { codename: 'does_not_exists' } }
+
+ it 'finds nothing' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ context 'by suite' do
+ context 'with existing suite' do
+ let(:params) { { suite: 'mysuite' } }
+
+ it 'finds distribution by suite' do
+ is_expected.to contain_exactly(distribution_with_suite)
+ end
+ end
+
+ context 'with non-existing suite' do
+ let(:params) { { suite: 'does_not_exists' } }
+
+ it 'finds nothing' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ context 'by codename_or_suite' do
+ context 'with existing codename' do
+ let(:params) { { codename_or_suite: distribution_with_suite.codename } }
+
+ it 'finds distribution by codename' do
+ is_expected.to contain_exactly(distribution_with_suite)
+ end
+ end
+
+ context 'with existing suite' do
+ let(:params) { { codename_or_suite: 'mysuite' } }
+
+ it 'finds distribution by suite' do
+ is_expected.to contain_exactly(distribution_with_suite)
+ end
+ end
+
+ context 'with non-existing suite' do
+ let(:params) { { codename_or_suite: 'does_not_exists' } }
+
+ it 'finds nothing' do
+ is_expected.to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/finders/packages_shared_examples.rb b/spec/support/shared_examples/finders/packages_shared_examples.rb
new file mode 100644
index 00000000000..52976565b21
--- /dev/null
+++ b/spec/support/shared_examples/finders/packages_shared_examples.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'concerning versionless param' do
+ let_it_be(:versionless_package) { create(:maven_package, project: project, version: nil) }
+
+ it { is_expected.not_to include(versionless_package) }
+
+ context 'with valid include_versionless param' do
+ let(:params) { { include_versionless: true } }
+
+ it { is_expected.to include(versionless_package) }
+ end
+
+ context 'with empty include_versionless param' do
+ let(:params) { { include_versionless: '' } }
+
+ it { is_expected.not_to include(versionless_package) }
+ 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
new file mode 100644
index 00000000000..0338eb43f8d
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'creating a new HTTP integration' do
+ it 'creates a new integration' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ new_integration = ::AlertManagement::HttpIntegration.last!
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(new_integration).to_s)
+ expect(integration_response['type']).to eq('HTTP')
+ expect(integration_response['name']).to eq(new_integration.name)
+ expect(integration_response['active']).to eq(new_integration.active)
+ expect(integration_response['token']).to eq(new_integration.token)
+ expect(integration_response['url']).to eq(new_integration.url)
+ expect(integration_response['apiUrl']).to eq(nil)
+ end
+end
diff --git a/spec/support/shared_examples/graphql/projects/merge_request_n_plus_one_query_examples.rb b/spec/support/shared_examples/graphql/projects/merge_request_n_plus_one_query_examples.rb
index 397e22ace28..738edd43c92 100644
--- a/spec/support/shared_examples/graphql/projects/merge_request_n_plus_one_query_examples.rb
+++ b/spec/support/shared_examples/graphql/projects/merge_request_n_plus_one_query_examples.rb
@@ -2,10 +2,12 @@
shared_examples 'N+1 query check' do
it 'prevents N+1 queries' do
execute_query # "warm up" to prevent undeterministic counts
+ expect(graphql_errors).to be_blank # Sanity check - ex falso quodlibet!
- control_count = ActiveRecord::QueryRecorder.new { execute_query }.count
+ control = ActiveRecord::QueryRecorder.new { execute_query }
+ expect(control.count).to be > 0
search_params[:iids] << extra_iid_for_second_query
- expect { execute_query }.not_to exceed_query_limit(control_count)
+ expect { execute_query }.not_to exceed_query_limit(control)
end
end
diff --git a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb
index 134e38833cf..b5c07f45d59 100644
--- a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb
+++ b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-RSpec.shared_examples 'default whitelist' do
- it 'sanitizes tags that are not whitelisted' do
+RSpec.shared_examples 'default allowlist' do
+ it 'sanitizes tags that are not allowed' do
act = %q{<textarea>no inputs</textarea> and <blink>no blinks</blink>}
exp = 'no inputs and no blinks'
expect(filter(act).to_html).to eq exp
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/base_stage_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/base_stage_shared_examples.rb
deleted file mode 100644
index d76089d56dd..00000000000
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/base_stage_shared_examples.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-ISSUES_MEDIAN = 30.minutes.to_i
-
-RSpec.shared_examples 'base stage' do
- let(:stage) { described_class.new(options: { project: double }) }
-
- before do
- allow(stage).to receive(:project_median).and_return(1.12)
- allow_next_instance_of(Gitlab::CycleAnalytics::BaseEventFetcher) do |instance|
- allow(instance).to receive(:event_result).and_return({})
- end
- end
-
- it 'has the median data value' do
- expect(stage.as_json[:value]).not_to be_nil
- end
-
- it 'has the median data stage' do
- expect(stage.as_json[:title]).not_to be_nil
- end
-
- it 'has the median data description' do
- expect(stage.as_json[:description]).not_to be_nil
- end
-
- it 'has the title' do
- expect(stage.title).to eq(stage_name.to_s.capitalize)
- end
-
- it 'has the events' do
- expect(stage.events).not_to be_nil
- end
-end
-
-RSpec.shared_examples 'calculate #median with date range' do
- context 'when valid date range is given' do
- before do
- stage_options[:from] = 5.days.ago
- stage_options[:to] = 5.days.from_now
- end
-
- it { expect(stage.project_median).to eq(ISSUES_MEDIAN) }
- end
-
- context 'when records are out of the date range' do
- before do
- stage_options[:from] = 2.years.ago
- stage_options[:to] = 1.year.ago
- end
-
- it { expect(stage.project_median).to eq(nil) }
- end
-end
-
-RSpec.shared_examples 'Gitlab::Analytics::CycleAnalytics::DataCollector backend examples' do
- let(:stage_params) { Gitlab::Analytics::CycleAnalytics::DefaultStages.send("params_for_#{stage_name}_stage").merge(project: project) }
- let(:stage) { Analytics::CycleAnalytics::ProjectStage.new(stage_params) }
- let(:data_collector) { Gitlab::Analytics::CycleAnalytics::DataCollector.new(stage: stage, params: { from: stage_options[:from], current_user: project.creator }) }
- let(:attribute_to_verify) { :title }
-
- context 'provides the same results as the old implementation' do
- it 'for the median' do
- expect(data_collector.median.seconds).to be_within(0.5).of(ISSUES_MEDIAN)
- end
-
- it 'for the list of event records' do
- records = data_collector.records_fetcher.serialized_records
- expect(records.map { |event| event[attribute_to_verify] }).to eq(expected_ordered_attribute_values)
- end
- end
-end
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/default_query_config_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/default_query_config_shared_examples.rb
deleted file mode 100644
index 4f648b27ea2..00000000000
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/default_query_config_shared_examples.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.shared_examples 'default query config' do
- let(:project) { create(:project) }
- let(:event) { described_class.new(stage: stage_name, options: { from: 1.day.ago, project: project }) }
-
- it 'has the stage attribute' do
- expect(event.stage).not_to be_nil
- end
-
- it 'has the projection attributes' do
- expect(event.projections).not_to be_nil
- end
-end
diff --git a/spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb
index 6327367fcc2..40deaa27955 100644
--- a/spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb
@@ -5,7 +5,7 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
include_context 'with one temporary file for multipart'
let(:rewritten_fields) { rewritten_fields_hash('file' => uploaded_filepath) }
- let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', filename: filename, remote_id: remote_id) }
+ let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', mode: mode, filename: filename, remote_id: remote_id) }
it 'builds an UploadedFile' do
expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file))
@@ -19,8 +19,8 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
let(:rewritten_fields) { rewritten_fields_hash('file1' => uploaded_filepath, 'file2' => uploaded_filepath2) }
let(:params) do
- upload_parameters_for(filepath: uploaded_filepath, key: 'file1', filename: filename, remote_id: remote_id).merge(
- upload_parameters_for(filepath: uploaded_filepath2, key: 'file2', filename: filename2, remote_id: remote_id2)
+ upload_parameters_for(filepath: uploaded_filepath, key: 'file1', mode: mode, filename: filename, remote_id: remote_id).merge(
+ upload_parameters_for(filepath: uploaded_filepath2, key: 'file2', mode: mode, filename: filename2, remote_id: remote_id2)
)
end
@@ -38,7 +38,7 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
include_context 'with one temporary file for multipart'
let(:rewritten_fields) { rewritten_fields_hash('user[avatar]' => uploaded_filepath) }
- let(:params) { { 'user' => { 'avatar' => upload_parameters_for(filepath: uploaded_filepath, filename: filename, remote_id: remote_id) } } }
+ let(:params) { { 'user' => { 'avatar' => upload_parameters_for(filepath: uploaded_filepath, mode: mode, filename: filename, remote_id: remote_id) } } }
it 'builds an UploadedFile' do
expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar))
@@ -54,8 +54,8 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
let(:params) do
{
'user' => {
- 'avatar' => upload_parameters_for(filepath: uploaded_filepath, filename: filename, remote_id: remote_id),
- 'screenshot' => upload_parameters_for(filepath: uploaded_filepath2, filename: filename2, remote_id: remote_id2)
+ 'avatar' => upload_parameters_for(filepath: uploaded_filepath, mode: mode, filename: filename, remote_id: remote_id),
+ 'screenshot' => upload_parameters_for(filepath: uploaded_filepath2, mode: mode, filename: filename2, remote_id: remote_id2)
}
}
end
@@ -74,7 +74,7 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
include_context 'with one temporary file for multipart'
let(:rewritten_fields) { rewritten_fields_hash('user[avatar][bananas]' => uploaded_filepath) }
- let(:params) { { 'user' => { 'avatar' => { 'bananas' => upload_parameters_for(filepath: uploaded_filepath, filename: filename, remote_id: remote_id) } } } }
+ let(:params) { { 'user' => { 'avatar' => { 'bananas' => upload_parameters_for(filepath: uploaded_filepath, mode: mode, filename: filename, remote_id: remote_id) } } } }
it 'builds an UploadedFile' do
expect_uploaded_files(filepath: uploaded_file, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar bananas))
@@ -91,10 +91,10 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
{
'user' => {
'avatar' => {
- 'bananas' => upload_parameters_for(filepath: uploaded_filepath, filename: filename, remote_id: remote_id)
+ 'bananas' => upload_parameters_for(filepath: uploaded_filepath, mode: mode, filename: filename, remote_id: remote_id)
},
'friend' => {
- 'ananas' => upload_parameters_for(filepath: uploaded_filepath2, filename: filename2, remote_id: remote_id2)
+ 'ananas' => upload_parameters_for(filepath: uploaded_filepath2, mode: mode, filename: filename2, remote_id: remote_id2)
}
}
}
@@ -122,11 +122,11 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
end
let(:params) do
- upload_parameters_for(filepath: uploaded_filepath, filename: filename, key: 'file', remote_id: remote_id).merge(
+ upload_parameters_for(filepath: uploaded_filepath, filename: filename, key: 'file', mode: mode, remote_id: remote_id).merge(
'user' => {
- 'avatar' => upload_parameters_for(filepath: uploaded_filepath2, filename: filename2, remote_id: remote_id2),
+ 'avatar' => upload_parameters_for(filepath: uploaded_filepath2, mode: mode, filename: filename2, remote_id: remote_id2),
'friend' => {
- 'avatar' => upload_parameters_for(filepath: uploaded_filepath3, filename: filename3, remote_id: remote_id3)
+ 'avatar' => upload_parameters_for(filepath: uploaded_filepath3, mode: mode, filename: filename3, remote_id: remote_id3)
}
}
)
diff --git a/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
index 94ef41ce5a5..f83fecee4ea 100644
--- a/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
@@ -54,7 +54,7 @@ RSpec.shared_examples 'access restricted confidential issues' do
end
end
- context 'when the user is a developper' do
+ context 'when the user is a developer' do
let(:user) do
create(:user) { |user| project.add_developer(user) }
end
@@ -70,10 +70,19 @@ RSpec.shared_examples 'access restricted confidential issues' do
context 'when the user is admin', :request_store do
let(:user) { create(:user, admin: true) }
- it 'lists all project issues' do
- expect(objects).to contain_exactly(issue,
- security_issue_1,
- security_issue_2)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'lists all project issues' do
+ expect(objects).to contain_exactly(issue,
+ security_issue_1,
+ security_issue_2)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'does not list project confidential issues' do
+ expect(objects).to contain_exactly(issue)
+ expect(results.limited_issues_count).to eq 1
+ end
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb
index 788c35dd5bf..88bc8e8d0c1 100644
--- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb
@@ -13,7 +13,7 @@ RSpec.shared_examples 'an incident management tracked event' do |event|
expect(Gitlab::UsageDataCounters::HLLRedisCounter)
.to receive(:track_event)
- .with(current_user.id, event.to_s)
+ .with(event.to_s, values: current_user.id)
.and_call_original
expect { subject }
diff --git a/spec/support/shared_examples/metrics/sampler_shared_examples.rb b/spec/support/shared_examples/metrics/sampler_shared_examples.rb
new file mode 100644
index 00000000000..ebf199c3a8d
--- /dev/null
+++ b/spec/support/shared_examples/metrics/sampler_shared_examples.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'metrics sampler' do |env_prefix|
+ context 'when sampling interval is passed explicitly' do
+ subject { described_class.new(42) }
+
+ specify { expect(subject.interval).to eq(42) }
+ end
+
+ context 'when sampling interval is passed through the environment' do
+ subject { described_class.new }
+
+ before do
+ stub_env("#{env_prefix}_INTERVAL_SECONDS", '42')
+ end
+
+ specify { expect(subject.interval).to eq(42) }
+ end
+
+ context 'when no sampling interval is passed anywhere' do
+ subject { described_class.new }
+
+ it 'uses the hardcoded default' do
+ expect(subject.interval).to eq(described_class::DEFAULT_SAMPLING_INTERVAL_SECONDS)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/boards/listable_shared_examples.rb b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
new file mode 100644
index 00000000000..e733a5488fb
--- /dev/null
+++ b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'boards listable model' do |list_factory|
+ subject { build(list_factory) }
+
+ describe 'associations' do
+ it { is_expected.to validate_presence_of(:position) }
+ it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than_or_equal_to(0) }
+
+ context 'when list_type is set to closed' do
+ subject { build(list_factory, list_type: :closed) }
+
+ it { is_expected.not_to validate_presence_of(:label) }
+ it { is_expected.not_to validate_presence_of(:position) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.ordered' do
+ it 'returns lists ordered by type and position' do
+ # rubocop:disable Rails/SaveBang
+ lists = [
+ create(list_factory, list_type: :backlog),
+ create(list_factory, list_type: :closed),
+ create(list_factory, position: 1),
+ create(list_factory, position: 2)
+ ]
+ # rubocop:enable Rails/SaveBang
+
+ expect(described_class.where(id: lists).ordered).to eq([lists[0], lists[2], lists[3], lists[1]])
+ end
+ end
+ end
+
+ describe '#destroyable?' do
+ it 'returns true when list_type is set to label' do
+ subject.list_type = :label
+
+ expect(subject).to be_destroyable
+ end
+
+ it 'returns false when list_type is set to closed' do
+ subject.list_type = :closed
+
+ expect(subject).not_to be_destroyable
+ end
+ end
+
+ describe '#movable?' do
+ it 'returns true when list_type is set to label' do
+ subject.list_type = :label
+
+ expect(subject).to be_movable
+ end
+
+ it 'returns false when list_type is set to closed' do
+ subject.list_type = :closed
+
+ expect(subject).not_to be_movable
+ end
+ end
+
+ describe '#title' do
+ it 'returns label name when list_type is set to label' do
+ subject.list_type = :label
+ subject.label = Label.new(name: 'Development')
+
+ expect(subject.title).to eq 'Development'
+ end
+
+ it 'returns Open when list_type is set to backlog' do
+ subject.list_type = :backlog
+
+ expect(subject.title).to eq 'Open'
+ end
+
+ it 'returns Closed when list_type is set to closed' do
+ subject.list_type = :closed
+
+ expect(subject.title).to eq 'Closed'
+ end
+ end
+
+ describe '#destroy' do
+ it 'can be destroyed when list_type is set to label' do
+ subject = create(list_factory) # rubocop:disable Rails/SaveBang
+
+ expect(subject.destroy).to be_truthy
+ end
+
+ it 'can not be destroyed when list_type is set to closed' do
+ subject = create(list_factory, list_type: :closed) # rubocop:disable Rails/SaveBang
+
+ expect(subject.destroy).to be_falsey
+ end
+ end
+end
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
new file mode 100644
index 00000000000..2f0b95427d2
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb
@@ -0,0 +1,45 @@
+# 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/repositories/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
new file mode 100644
index 00000000000..2f0b95427d2
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
@@ -0,0 +1,45 @@
+# 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/repository_storage_movable_shared_examples.rb b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
index 5a8388d01df..4c617f3ba46 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
@@ -63,7 +63,6 @@ RSpec.shared_examples 'handles repository moves' do
context 'and transits to scheduled' do
it 'triggers the corresponding repository storage worker' do
- skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id)
storage_move.schedule!
@@ -72,8 +71,7 @@ RSpec.shared_examples 'handles repository moves' do
end
context 'when the transition fails' do
- it 'does not trigger ProjectUpdateRepositoryStorageWorker and adds an error' do
- skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
+ it 'does not trigger the corresponding repository storage worker and adds an error' do
allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar')
expect(repository_storage_worker).not_to receive(:perform_async)
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
new file mode 100644
index 00000000000..38983f752f4
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Distribution Architecture' do |factory, container, can_freeze|
+ let_it_be_with_refind(:architecture) { create(factory) } # rubocop:disable Rails/SaveBang
+ let_it_be(:architecture_same_distribution, freeze: can_freeze) { create(factory, distribution: architecture.distribution) }
+ let_it_be(:architecture_same_name, freeze: can_freeze) { create(factory, name: architecture.name) }
+
+ subject { architecture }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:architectures) }
+ 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('amd64').for(:name) }
+ it { is_expected.to allow_value('kfreebsd-i386').for(:name) }
+ it { is_expected.not_to allow_value('-a').for(:name) }
+ it { is_expected.not_to allow_value('AMD64').for(:name) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.with_distribution' do
+ subject { described_class.with_distribution(architecture.distribution) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([architecture, architecture_same_distribution])
+ end
+ end
+
+ describe '.with_name' do
+ subject { described_class.with_name(architecture.name) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([architecture, architecture_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
new file mode 100644
index 00000000000..af87d30099f
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -0,0 +1,225 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
+ let_it_be(:distribution_with_suite, freeze: can_freeze) { create(factory, suite: 'mysuite') }
+ let_it_be(:distribution_with_same_container, freeze: can_freeze) { create(factory, container: distribution_with_suite.container ) }
+ let_it_be(:distribution_with_same_codename, freeze: can_freeze) { create(factory, codename: distribution_with_suite.codename ) }
+ let_it_be(:distribution_with_same_suite, freeze: can_freeze) { create(factory, suite: distribution_with_suite.suite ) }
+ let_it_be(:distribution_with_codename_and_suite_flipped, freeze: can_freeze) { create(factory, codename: distribution_with_suite.suite, suite: distribution_with_suite.codename) }
+
+ let_it_be_with_refind(:distribution) { create(factory, container: distribution_with_suite.container ) }
+
+ subject { distribution }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(container) }
+ it { is_expected.to belong_to(:creator).class_name('User') }
+
+ it { is_expected.to have_many(:architectures).class_name("Packages::Debian::#{container.capitalize}Architecture").inverse_of(:distribution) }
+ end
+
+ describe 'validations' do
+ describe "##{container}" do
+ it { is_expected.to validate_presence_of(container) }
+ end
+
+ describe "#creator" do
+ it { is_expected.not_to validate_presence_of(:creator) }
+ end
+
+ describe '#codename' do
+ it { is_expected.to validate_presence_of(:codename) }
+
+ it { is_expected.to allow_value('buster').for(:codename) }
+ it { is_expected.to allow_value('buster-updates').for(:codename) }
+ it { is_expected.to allow_value('Debian10.5').for(:codename) }
+ it { is_expected.not_to allow_value('jessie/updates').for(:codename) }
+ it { is_expected.not_to allow_value('hé').for(:codename) }
+ end
+
+ describe '#suite' do
+ it { is_expected.to allow_value(nil).for(:suite) }
+ it { is_expected.to allow_value('testing').for(:suite) }
+ it { is_expected.not_to allow_value('hé').for(:suite) }
+ end
+
+ describe '#unique_debian_suite_and_codename' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:with_existing_suite, :suite, :codename, :errors) do
+ false | nil | :keep | nil
+ false | 'testing' | :keep | nil
+ false | nil | :codename | ["Codename has already been taken"]
+ false | :codename | :keep | ["Suite has already been taken as Codename"]
+ false | :codename | :codename | ["Codename has already been taken", "Suite has already been taken as Codename"]
+ true | nil | :keep | nil
+ true | 'testing' | :keep | nil
+ true | nil | :codename | ["Codename has already been taken"]
+ true | :codename | :keep | ["Suite has already been taken as Codename"]
+ true | :codename | :codename | ["Codename has already been taken", "Suite has already been taken as Codename"]
+ true | nil | :suite | ["Codename has already been taken as Suite"]
+ true | :suite | :keep | ["Suite has already been taken"]
+ true | :suite | :suite | ["Suite has already been taken", "Codename has already been taken as Suite"]
+ end
+
+ with_them do
+ context factory do
+ let(:new_distribution) { build(factory, container: distribution.container) }
+
+ before do
+ distribution.update_column(:suite, 'suite-' + distribution.codename) if with_existing_suite
+
+ if suite.is_a?(Symbol)
+ new_distribution.suite = distribution.send suite unless suite == :keep
+ else
+ new_distribution.suite = suite
+ end
+
+ if codename.is_a?(Symbol)
+ new_distribution.codename = distribution.send codename unless codename == :keep
+ else
+ new_distribution.codename = codename
+ end
+ end
+
+ it do
+ if errors
+ expect(new_distribution).not_to be_valid
+ expect(new_distribution.errors.to_a).to eq(errors)
+ else
+ expect(new_distribution).to be_valid
+ end
+ end
+ end
+ end
+ end
+
+ describe '#origin' do
+ it { is_expected.to allow_value(nil).for(:origin) }
+ it { is_expected.to allow_value('Debian').for(:origin) }
+ it { is_expected.not_to allow_value('hé').for(:origin) }
+ end
+
+ describe '#label' do
+ it { is_expected.to allow_value(nil).for(:label) }
+ it { is_expected.to allow_value('Debian').for(:label) }
+ it { is_expected.not_to allow_value('hé').for(:label) }
+ end
+
+ describe '#version' do
+ it { is_expected.to allow_value(nil).for(:version) }
+ it { is_expected.to allow_value('10.6').for(:version) }
+ it { is_expected.not_to allow_value('hé').for(:version) }
+ end
+
+ describe '#description' do
+ it { is_expected.to allow_value(nil).for(:description) }
+ it { is_expected.to allow_value('Debian 10.6 Released 26 September 2020').for(:description) }
+ it { is_expected.to allow_value('Hé !').for(:description) }
+ end
+
+ describe '#valid_time_duration_seconds' do
+ it { is_expected.to allow_value(nil).for(:valid_time_duration_seconds) }
+ it { is_expected.to allow_value(24.hours.to_i).for(:valid_time_duration_seconds) }
+ it { is_expected.not_to allow_value(12.hours.to_i).for(:valid_time_duration_seconds) }
+ end
+
+ describe '#signing_keys' do
+ it { is_expected.to validate_absence_of(:signing_keys) }
+ end
+
+ describe '#file' do
+ it { is_expected.not_to validate_presence_of(:file) }
+ end
+
+ describe '#file_store' do
+ it { is_expected.to validate_presence_of(:file_store) }
+ end
+
+ describe '#file_signature' do
+ it { is_expected.to validate_absence_of(:file_signature) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.with_container' do
+ subject { described_class.with_container(distribution_with_suite.container) }
+
+ it 'does not return other distributions' do
+ expect(subject).to match_array([distribution_with_suite, distribution, distribution_with_same_container])
+ end
+ end
+
+ describe '.with_codename' do
+ subject { described_class.with_codename(distribution_with_suite.codename) }
+
+ it 'does not return other distributions' do
+ expect(subject).to match_array([distribution_with_suite, distribution_with_same_codename])
+ end
+ end
+
+ describe '.with_suite' do
+ subject { described_class.with_suite(distribution_with_suite.suite) }
+
+ it 'does not return other distributions' do
+ expect(subject).to match_array([distribution_with_suite, distribution_with_same_suite])
+ end
+ end
+
+ describe '.with_codename_or_suite' do
+ describe 'passing codename' do
+ subject { described_class.with_codename_or_suite(distribution_with_suite.codename) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([distribution_with_suite, distribution_with_same_codename, distribution_with_codename_and_suite_flipped])
+ end
+ end
+
+ describe 'passing suite' do
+ subject { described_class.with_codename_or_suite(distribution_with_suite.suite) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([distribution_with_suite, distribution_with_same_suite, distribution_with_codename_and_suite_flipped])
+ end
+ end
+ end
+ end
+
+ describe '#needs_update?' do
+ subject { distribution.needs_update? }
+
+ context 'with new distribution' do
+ let(:distribution) { create(factory, container: distribution_with_suite.container) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with file' do
+ context 'without valid_time_duration_seconds' do
+ let(:distribution) { create(factory, :with_file, container: distribution_with_suite.container) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'with valid_time_duration_seconds' do
+ let(:distribution) { create(factory, :with_file, container: distribution_with_suite.container, valid_time_duration_seconds: 2.days.to_i) }
+
+ context 'when not yet expired' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when expired' do
+ it do
+ distribution
+
+ travel_to(4.days.from_now) do
+ is_expected.to be_truthy
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..28decb4011d
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/merge_request/rebase_quick_action_shared_examples.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'rebase quick action' do
+ context 'when updating the description' do
+ before do
+ sign_in(user)
+ visit edit_project_merge_request_path(project, merge_request)
+ end
+
+ it 'rebases the MR', :sidekiq_inline do
+ fill_in('Description', with: '/rebase')
+ click_button('Save changes')
+
+ expect(page).not_to have_content('commit behind the target branch')
+ expect(merge_request.reload).not_to be_merged
+ end
+
+ it 'ignores /merge if /rebase is specified', :sidekiq_inline do
+ fill_in('Description', with: "/merge\n/rebase")
+ click_button('Save changes')
+
+ expect(page).not_to have_content('commit behind the target branch')
+ expect(merge_request.reload).not_to be_merged
+ end
+ end
+
+ context 'when creating a new note' do
+ context 'when the current user can rebase the MR' do
+ before do
+ sign_in(user)
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'rebase the MR', :sidekiq_inline do
+ add_note("/rebase")
+
+ expect(page).to have_content "Scheduled a rebase of branch #{merge_request.source_branch}."
+ end
+
+ context 'when the merge request is closed' do
+ before do
+ merge_request.close!
+ end
+
+ it 'does not rebase the MR', :sidekiq_inline do
+ add_note("/rebase")
+
+ expect(page).not_to have_content 'Scheduled a rebase'
+ end
+ end
+
+ context 'when a rebase is in progress', :sidekiq_inline, :clean_gitlab_redis_shared_state do
+ before do
+ jid = SecureRandom.hex
+ merge_request.update!(rebase_jid: jid)
+ Gitlab::SidekiqStatus.set(jid)
+ end
+
+ it 'tells the user a rebase is in progress' do
+ add_note('/rebase')
+
+ expect(page).to have_content 'A rebase is already in progress.'
+ expect(page).not_to have_content 'Scheduled a rebase'
+ end
+ end
+
+ context 'when there are conflicts in the merge request' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, source_branch: 'conflict-missing-side', target_branch: 'conflict-start', merge_status: :cannot_be_merged) }
+
+ it 'does not rebase the MR' do
+ add_note("/rebase")
+
+ expect(page).to have_content 'This merge request cannot be rebased while there are conflicts.'
+ end
+ end
+ end
+
+ context 'when the current user cannot rebase the MR' do
+ before do
+ project.add_guest(guest)
+ sign_in(guest)
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'does not rebase the MR' do
+ add_note("/rebase")
+
+ expect(page).not_to have_content 'Scheduled a rebase'
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/boards_shared_examples.rb b/spec/support/shared_examples/requests/api/boards_shared_examples.rb
index 0096aab55e3..8e8edd61ef9 100644
--- a/spec/support/shared_examples/requests/api/boards_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/boards_shared_examples.rb
@@ -44,16 +44,35 @@ RSpec.shared_examples 'group and project boards' do |route_definition, ee = fals
expect_schema_match_for(response, 'public_api/v4/boards', ee)
end
+ end
+ end
- describe "GET #{route_definition}/:board_id" do
- let(:url) { "#{root_url}/#{board.id}" }
+ describe "GET #{route_definition}/:board_id" do
+ let(:url) { "#{root_url}/#{board.id}" }
- it 'get a single board by id' do
- get api(url, user)
+ it 'get a single board by id' do
+ get api(url, user)
- expect_schema_match_for(response, 'public_api/v4/board', ee)
- end
- end
+ expect_schema_match_for(response, 'public_api/v4/board', ee)
+ end
+ end
+
+ describe "PUT #{route_definition}/:board_id" do
+ let(:url) { "#{root_url}/#{board.id}" }
+
+ it 'updates the board name' do
+ put api(url, user), params: { name: 'changed board name' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('changed board name')
+ end
+
+ it 'updates the issue board booleans' do
+ put api(url, user), params: { hide_backlog_list: true, hide_closed_list: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['hide_backlog_list']).to eq(true)
+ expect(json_response['hide_closed_list']).to eq(true)
end
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 f55043fe64f..83ba72c12aa 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
@@ -37,9 +37,9 @@ 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
if method == :put
- workhorse_token = JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256')
{ 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token }
else
{}
@@ -117,12 +117,13 @@ RSpec.shared_examples 'Debian project repository PUT request' do |user_role, add
and_body = body.nil? ? '' : ' and expected body'
if status == :created
- it 'creates package files' do
+ it 'creates package files', :aggregate_failures do
pending "Debian package creation not implemented"
expect { subject }
.to change { project.packages.debian.count }.by(1)
expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('text/plain')
unless body.nil?
expect(response.body).to eq(body)
@@ -130,7 +131,59 @@ RSpec.shared_examples 'Debian project repository PUT request' do |user_role, add
end
it_behaves_like 'a package tracking event', described_class.name, 'push_package'
else
- it "returns #{status}#{and_body}" do
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to eq(body)
+ end
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian project repository PUT authorize request' do |user_role, add_member, status, body, is_authorize|
+ context "for user type #{user_role}" do
+ before do
+ project.send("add_#{user_role}", user) if add_member && user_role != :anonymous
+ end
+
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :created
+ it 'authorizes package file upload', :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ expect(json_response['TempPath']).to eq(Packages::PackageFileUploader.workhorse_local_upload_path)
+ expect(json_response['RemoteObject']).to be_nil
+ expect(json_response['MaximumSize']).to be_nil
+ end
+
+ context 'without a valid token' do
+ let(:workhorse_token) { 'invalid' }
+
+ it 'rejects request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'bypassing gitlab-workhorse' do
+ let(:workhorse_headers) { {} }
+
+ it 'rejects request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(status)
@@ -194,7 +247,7 @@ RSpec.shared_examples 'Debian project repository GET endpoint' do |success_statu
it_behaves_like 'rejects Debian access with unknown project id'
end
-RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_status, success_body|
+RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_status, success_body, is_authorize = false|
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
@@ -221,7 +274,13 @@ RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_statu
with_them do
include_context 'Debian repository project access', params[:project_visibility_level], params[:user_role], params[:user_token], :basic do
- it_behaves_like 'Debian project repository PUT request', params[:user_role], params[:member], params[:expected_status], params[:expected_body]
+ desired_behavior = if is_authorize
+ 'Debian project repository PUT authorize request'
+ else
+ 'Debian project repository PUT request'
+ end
+
+ it_behaves_like desired_behavior, params[:user_role], params[:member], params[:expected_status], params[:expected_body]
end
end
end
diff --git a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
index f808d12baf4..7b7d2a33e8c 100644
--- a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
@@ -1,31 +1,31 @@
# frozen_string_literal: true
-RSpec.shared_examples 'handling nuget service requests' do
+RSpec.shared_examples 'handling nuget service requests' do |anonymous_requests_example_name: 'process nuget service index request', anonymous_requests_status: :success|
subject { get api(url) }
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
context 'personal token' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
- 'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
- 'PUBLIC' | :developer | true | false | 'process nuget service index request' | :success
- 'PUBLIC' | :guest | true | false | 'process nuget service index request' | :success
- 'PUBLIC' | :developer | false | true | 'process nuget service index request' | :success
- 'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
- 'PUBLIC' | :developer | false | false | 'process nuget service index request' | :success
- 'PUBLIC' | :guest | false | false | 'process nuget service index request' | :success
- 'PUBLIC' | :anonymous | false | true | 'process nuget service index request' | :success
- 'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
- 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
- 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
+ 'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'process nuget service index request' | :success
+ 'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
+ 'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
+ 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
+ 'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
@@ -35,7 +35,7 @@ RSpec.shared_examples 'handling nuget service requests' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
@@ -43,7 +43,7 @@ RSpec.shared_examples 'handling nuget service requests' do
end
context 'with job token' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
@@ -52,7 +52,7 @@ RSpec.shared_examples 'handling nuget service requests' do
'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'process nuget service index request' | :success
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
@@ -71,7 +71,7 @@ RSpec.shared_examples 'handling nuget service requests' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
@@ -79,14 +79,18 @@ RSpec.shared_examples 'handling nuget service requests' do
end
end
- it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'rejects nuget access with invalid target id'
end
-RSpec.shared_examples 'handling nuget metadata requests with package name' do
+RSpec.shared_examples 'handling nuget metadata requests with package name' do |anonymous_requests_example_name: 'process nuget metadata request at package name level', anonymous_requests_status: :success|
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
@@ -99,19 +103,19 @@ RSpec.shared_examples 'handling nuget metadata requests with package name' do
packages.each { |pkg| create_dependencies_for(pkg) }
end
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | true | true | 'process nuget metadata request at package name level' | :success
- 'PUBLIC' | :developer | true | false | 'process nuget metadata request at package name level' | :success
- 'PUBLIC' | :guest | true | false | 'process nuget metadata request at package name level' | :success
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :developer | false | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | false | true | 'process nuget metadata request at package name level' | :success
- 'PUBLIC' | :developer | false | false | 'process nuget metadata request at package name level' | :success
- 'PUBLIC' | :guest | false | false | 'process nuget metadata request at package name level' | :success
- 'PUBLIC' | :anonymous | false | true | 'process nuget metadata request at package name level' | :success
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name level' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
@@ -130,21 +134,25 @@ RSpec.shared_examples 'handling nuget metadata requests with package name' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
- it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'rejects nuget access with invalid target id'
end
end
-RSpec.shared_examples 'handling nuget metadata requests with package name and package version' do
+RSpec.shared_examples 'handling nuget metadata requests with package name and package version' do |anonymous_requests_example_name: 'process nuget metadata request at package name and package version level', anonymous_requests_status: :success|
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
@@ -157,19 +165,19 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
create_dependencies_for(package)
end
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | true | true | 'process nuget metadata request at package name and package version level' | :success
- 'PUBLIC' | :developer | true | false | 'process nuget metadata request at package name and package version level' | :success
- 'PUBLIC' | :guest | true | false | 'process nuget metadata request at package name and package version level' | :success
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :developer | false | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | false | true | 'process nuget metadata request at package name and package version level' | :success
- 'PUBLIC' | :developer | false | false | 'process nuget metadata request at package name and package version level' | :success
- 'PUBLIC' | :guest | false | false | 'process nuget metadata request at package name and package version level' | :success
- 'PUBLIC' | :anonymous | false | true | 'process nuget metadata request at package name and package version level' | :success
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
@@ -188,23 +196,25 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
- it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- context 'with invalid package name' do
- let_it_be(:package_name) { 'Unkown' }
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget packages access', :developer, :not_found
- end
+ it_behaves_like 'rejects nuget access with invalid target id'
end
-RSpec.shared_examples 'handling nuget search requests' do
+RSpec.shared_examples 'handling nuget search requests' do |anonymous_requests_example_name: 'process nuget search request', anonymous_requests_status: :success|
let_it_be(:package_a) { create(:nuget_package, :with_metadatum, name: 'Dummy.PackageA', project: project) }
let_it_be(:tag) { create(:packages_tag, package: package_a, name: 'test') }
let_it_be(:packages_b) { create_list(:nuget_package, 5, name: 'Dummy.PackageB', project: project) }
@@ -219,19 +229,19 @@ RSpec.shared_examples 'handling nuget search requests' do
subject { get api(url) }
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget search request' | :success
'PUBLIC' | :guest | true | true | 'process nuget search request' | :success
- 'PUBLIC' | :developer | true | false | 'process nuget search request' | :success
- 'PUBLIC' | :guest | true | false | 'process nuget search request' | :success
+ 'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :developer | false | true | 'process nuget search request' | :success
'PUBLIC' | :guest | false | true | 'process nuget search request' | :success
- 'PUBLIC' | :developer | false | false | 'process nuget search request' | :success
- 'PUBLIC' | :guest | false | false | 'process nuget search request' | :success
- 'PUBLIC' | :anonymous | false | true | 'process nuget search request' | :success
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget search request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
@@ -250,16 +260,20 @@ RSpec.shared_examples 'handling nuget search requests' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
- it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'rejects nuget access with invalid target id'
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 dc6ac5f0371..8b60857cdaf 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
@@ -3,7 +3,7 @@
RSpec.shared_examples 'rejects nuget packages access' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -21,7 +21,7 @@ end
RSpec.shared_examples 'process nuget service index request' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -37,7 +37,7 @@ RSpec.shared_examples 'process nuget service index request' do |user_type, statu
end
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/index.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/index.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -57,7 +57,7 @@ end
RSpec.shared_examples 'process nuget metadata request at package name level' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -65,7 +65,7 @@ RSpec.shared_examples 'process nuget metadata request at package name level' do
it_behaves_like 'returning nuget metadata json response with json schema', 'public_api/v4/packages/nuget/packages_metadata'
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/index.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/metadata/#{package_name}/index.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -83,7 +83,7 @@ end
RSpec.shared_examples 'process nuget metadata request at package name and package version level' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -91,7 +91,7 @@ RSpec.shared_examples 'process nuget metadata request at package name and packag
it_behaves_like 'returning nuget metadata json response with json schema', 'public_api/v4/packages/nuget/package_metadata'
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/#{package.version}.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/metadata/#{package_name}/#{package.version}.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -109,7 +109,7 @@ end
RSpec.shared_examples 'process nuget workhorse authorization' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -128,7 +128,7 @@ RSpec.shared_examples 'process nuget workhorse authorization' do |user_type, sta
end
before do
- project.add_maintainer(user)
+ target.add_maintainer(user)
end
it_behaves_like 'returning response status', :forbidden
@@ -141,18 +141,18 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member =
it 'creates package files' do
expect(::Packages::Nuget::ExtractionWorker).to receive(:perform_async).once
expect { subject }
- .to change { project.packages.count }.by(1)
+ .to change { target.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
expect(response).to have_gitlab_http_status(status)
- package_file = project.packages.last.package_files.reload.last
+ package_file = target.packages.last.package_files.reload.last
expect(package_file.file_name).to eq('package.nupkg')
end
end
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
context 'with object storage disabled' do
@@ -206,7 +206,7 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member =
context 'with crafted package.path param' do
let(:crafted_file) { Tempfile.new('nuget.crafted.package.path') }
- let(:url) { "/projects/#{project.id}/packages/nuget?package.path=#{crafted_file.path}" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget?package.path=#{crafted_file.path}" }
let(:params) { { file: temp_file(file_name) } }
let(:file_key) { :file }
@@ -255,7 +255,7 @@ RSpec.shared_examples 'process nuget download versions request' do |user_type, s
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -263,7 +263,7 @@ RSpec.shared_examples 'process nuget download versions request' do |user_type, s
it_behaves_like 'returns a valid nuget download versions json response'
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/download/#{package_name}/index.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/download/#{package_name}/index.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -281,7 +281,7 @@ end
RSpec.shared_examples 'process nuget download content request' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -295,7 +295,7 @@ RSpec.shared_examples 'process nuget download content request' do |user_type, st
end
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/download/#{package.name}/#{package.version}/#{package.name}.#{package.version}.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/download/#{package.name}/#{package.version}/#{package.name}.#{package.version}.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -331,7 +331,7 @@ RSpec.shared_examples 'process nuget search request' do |user_type, status, add_
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returns a valid json search response', status, 4, [1, 5, 5, 1]
@@ -370,20 +370,20 @@ RSpec.shared_examples 'process nuget search request' do |user_type, status, add_
end
end
-RSpec.shared_examples 'rejects nuget access with invalid project id' do
- context 'with a project id with invalid integers' do
+RSpec.shared_examples 'rejects nuget access with invalid target id' do
+ context 'with a target id with invalid integers' do
using RSpec::Parameterized::TableSyntax
- let(:project) { OpenStruct.new(id: id) }
+ let(:target) { OpenStruct.new(id: id) }
where(:id, :status) do
- '/../' | :unauthorized
+ '/../' | :bad_request
'' | :not_found
- '%20' | :unauthorized
- '%2e%2e%2f' | :unauthorized
- 'NaN' | :unauthorized
+ '%20' | :bad_request
+ '%2e%2e%2f' | :bad_request
+ 'NaN' | :bad_request
00002345 | :unauthorized
- 'anything25' | :unauthorized
+ 'anything25' | :bad_request
end
with_them do
@@ -392,9 +392,9 @@ RSpec.shared_examples 'rejects nuget access with invalid project id' do
end
end
-RSpec.shared_examples 'rejects nuget access with unknown project id' do
- context 'with an unknown project' do
- let(:project) { OpenStruct.new(id: 1234567890) }
+RSpec.shared_examples 'rejects nuget access with unknown target id' do
+ context 'with an unknown target' do
+ let(:target) { OpenStruct.new(id: 1234567890) }
context 'as anonymous' do
it_behaves_like 'rejects nuget packages access', :anonymous, :unauthorized
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
new file mode 100644
index 00000000000..b2970fd265d
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
@@ -0,0 +1,219 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'repository_storage_moves API' do |container_type|
+ include AccessMatchersForRequest
+
+ let_it_be(:user) { create(:admin) }
+
+ shared_examples 'get single container repository storage move' do
+ let(:repository_storage_move_id) { storage_move.id }
+
+ def get_container_repository_storage_move
+ get api(url, user)
+ end
+
+ it 'returns a container repository storage move', :aggregate_failures do
+ get_container_repository_storage_move
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_move")
+ expect(json_response['id']).to eq(storage_move.id)
+ expect(json_response['state']).to eq(storage_move.human_state_name)
+ end
+
+ context 'non-existent container repository storage move' do
+ let(:repository_storage_move_id) { non_existing_record_id }
+
+ it 'returns not found' do
+ get_container_repository_storage_move
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ describe 'permissions' do
+ it { expect { get_container_repository_storage_move }.to be_allowed_for(:admin) }
+ it { expect { get_container_repository_storage_move }.to be_denied_for(:user) }
+ end
+ end
+
+ shared_examples 'get container repository storage move list' do
+ def get_container_repository_storage_moves
+ get api(url, user)
+ end
+
+ it 'returns container repository storage moves', :aggregate_failures do
+ get_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_moves")
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['id']).to eq(storage_move.id)
+ expect(json_response.first['state']).to eq(storage_move.human_state_name)
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ # prevent `let` from polluting the control
+ get_container_repository_storage_moves
+
+ control = ActiveRecord::QueryRecorder.new { get_container_repository_storage_moves }
+
+ create(repository_storage_move_factory, :scheduled, container: container)
+
+ expect { get_container_repository_storage_moves }.not_to exceed_query_limit(control)
+ end
+
+ it 'returns the most recently created first' do
+ storage_move_oldest = create(repository_storage_move_factory, :scheduled, container: container, created_at: 2.days.ago)
+ storage_move_middle = create(repository_storage_move_factory, :scheduled, container: container, created_at: 1.day.ago)
+
+ get_container_repository_storage_moves
+
+ json_ids = json_response.map {|storage_move| storage_move['id'] }
+ expect(json_ids).to eq([
+ storage_move.id,
+ storage_move_middle.id,
+ storage_move_oldest.id
+ ])
+ end
+
+ describe 'permissions' do
+ it { expect { get_container_repository_storage_moves }.to be_allowed_for(:admin) }
+ it { expect { get_container_repository_storage_moves }.to be_denied_for(:user) }
+ end
+ 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" }
+ 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}" }
+ end
+ end
+
+ describe "GET /#{container_type.singularize}_repository_storage_moves" do
+ it_behaves_like 'get container repository storage move list' do
+ let(:url) { "/#{container_type.singularize}_repository_storage_moves" }
+ end
+ end
+
+ describe "GET /#{container_type.singularize}_repository_storage_moves/:repository_storage_move_id" do
+ it_behaves_like 'get single container repository storage move' do
+ let(:url) { "/#{container_type.singularize}_repository_storage_moves/#{repository_storage_move_id}" }
+ end
+ end
+
+ describe "POST /#{container_type}/:id/repository_storage_moves" do
+ let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves" }
+ let(:destination_storage_name) { 'test_second_storage' }
+
+ def create_container_repository_storage_move
+ post api(url, user), params: { destination_storage_name: destination_storage_name }
+ end
+
+ before do
+ stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
+ end
+
+ it 'schedules a container repository storage move', :aggregate_failures do
+ create_container_repository_storage_move
+
+ storage_move = container.repository_storage_moves.last
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_move")
+ expect(json_response['id']).to eq(storage_move.id)
+ expect(json_response['state']).to eq('scheduled')
+ expect(json_response['source_storage_name']).to eq('default')
+ expect(json_response['destination_storage_name']).to eq(destination_storage_name)
+ end
+
+ describe 'permissions' do
+ it { expect { create_container_repository_storage_move }.to be_allowed_for(:admin) }
+ it { expect { create_container_repository_storage_move }.to be_denied_for(:user) }
+ end
+
+ context 'destination_storage_name is missing', :aggregate_failures do
+ let(:destination_storage_name) { nil }
+
+ it 'schedules a container repository storage move' do
+ create_container_repository_storage_move
+
+ storage_move = container.repository_storage_moves.last
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_move")
+ expect(json_response['id']).to eq(storage_move.id)
+ expect(json_response['state']).to eq('scheduled')
+ expect(json_response['source_storage_name']).to eq('default')
+ expect(json_response['destination_storage_name']).to be_present
+ end
+ end
+ end
+
+ describe "POST /#{container_type.singularize}_repository_storage_moves" do
+ let(:url) { "/#{container_type.singularize}_repository_storage_moves" }
+ let(:source_storage_name) { 'default' }
+ let(:destination_storage_name) { 'test_second_storage' }
+
+ def create_container_repository_storage_moves
+ post api(url, user), params: {
+ source_storage_name: source_storage_name,
+ destination_storage_name: destination_storage_name
+ }
+ end
+
+ before do
+ stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
+ end
+
+ it 'schedules the worker' do
+ expect(bulk_worker_klass).to receive(:perform_async).with(source_storage_name, destination_storage_name)
+
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+
+ context 'source_storage_name is invalid' do
+ let(:destination_storage_name) { 'not-a-real-storage' }
+
+ it 'gives an error' do
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'destination_storage_name is missing' do
+ let(:destination_storage_name) { nil }
+
+ it 'schedules the worker' do
+ expect(bulk_worker_klass).to receive(:perform_async).with(source_storage_name, destination_storage_name)
+
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+ end
+
+ context 'destination_storage_name is invalid' do
+ let(:destination_storage_name) { 'not-a-real-storage' }
+
+ it 'gives an error' do
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ describe 'normal user' do
+ it { expect { create_container_repository_storage_moves }.to be_denied_for(:user) }
+ end
+ end
+end
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 5748e873fd4..460e8d57a2b 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
@@ -9,6 +9,7 @@ RSpec.shared_examples 'resolvable discussions API' do |parent_type, noteable_typ
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['notes'].size).to eq(1)
expect(json_response['notes'][0]['resolved']).to eq(true)
+ expect(Time.parse(json_response['notes'][0]['resolved_at'])).to be_like_time(note.reload.resolved_at)
end
it "unresolves discussion if resolved is false" do
@@ -18,6 +19,7 @@ RSpec.shared_examples 'resolvable discussions API' do |parent_type, noteable_typ
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['notes'].size).to eq(1)
expect(json_response['notes'][0]['resolved']).to eq(false)
+ expect(json_response['notes'][0]['resolved_at']).to be_nil
end
it "returns a 400 bad request error if resolved parameter is not passed" do
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 5d300d38e4a..3b039049ca9 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -154,10 +154,11 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
end
def make_request(args)
+ path, options = args
if request_method == 'POST'
- post(*args)
+ post(path, **options)
else
- get(*args)
+ get(path, **options)
end
end
end
diff --git a/spec/support/shared_examples/requests/releases_shared_examples.rb b/spec/support/shared_examples/requests/releases_shared_examples.rb
new file mode 100644
index 00000000000..b835947e497
--- /dev/null
+++ b/spec/support/shared_examples/requests/releases_shared_examples.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'correct release milestone order' do
+ let_it_be_with_reload(:milestone_1) { create(:milestone, project: project) }
+ let_it_be_with_reload(:milestone_2) { create(:milestone, project: project) }
+
+ shared_examples 'correct sort order' do
+ it 'sorts milestonee_1 before milestone_2' do
+ freeze_time do
+ expect(actual_milestone_title_order).to eq([milestone_1.title, milestone_2.title])
+ end
+ end
+ end
+
+ context 'due_date' do
+ before do
+ milestone_1.update!(due_date: Time.zone.now, start_date: 1.day.ago, title: 'z')
+ milestone_2.update!(due_date: 1.day.from_now, start_date: 2.days.ago, title: 'a')
+ end
+
+ context 'when both milestones have a due_date' do
+ it_behaves_like 'correct sort order'
+ end
+
+ context 'when one milestone does not have a due_date' do
+ before do
+ milestone_2.update!(due_date: nil)
+ end
+
+ it_behaves_like 'correct sort order'
+ end
+ end
+
+ context 'start_date' do
+ before do
+ milestone_1.update!(due_date: 1.day.from_now, start_date: 1.day.ago, title: 'z' )
+ milestone_2.update!(due_date: 1.day.from_now, start_date: milestone_2_start_date, title: 'a' )
+ end
+
+ context 'when both milestones have a start_date' do
+ let(:milestone_2_start_date) { Time.zone.now }
+
+ it_behaves_like 'correct sort order'
+ end
+
+ context 'when one milestone does not have a start_date' do
+ let(:milestone_2_start_date) { nil }
+
+ it_behaves_like 'correct sort order'
+ end
+ end
+
+ context 'title' do
+ before do
+ milestone_1.update!(due_date: 1.day.from_now, start_date: Time.zone.now, title: 'a' )
+ milestone_2.update!(due_date: 1.day.from_now, start_date: Time.zone.now, title: 'z' )
+ end
+
+ it_behaves_like 'correct sort order'
+ end
+end
diff --git a/spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb b/spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb
new file mode 100644
index 00000000000..d82da1b01e1
--- /dev/null
+++ b/spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'authenticates sessionless user for the request spec' do |params|
+ params ||= {}
+
+ before do
+ stub_authentication_activity_metrics(debug: false)
+ end
+
+ let(:user) { create(:user) }
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+ let(:default_params) { params.except(:public) || {} }
+
+ context "when the 'personal_access_token' param is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ get url, params: default_params.merge(private_token: personal_access_token.token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(controller.current_user).to eq(user)
+ end
+
+ it 'does not log the user in if page is public', if: params[:public] do
+ get url, params: default_params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(controller.current_user).to be_nil
+ end
+ end
+
+ context 'when the personal access token has no api scope', unless: params[:public] do
+ it 'does not log the user in' do
+ # Several instances of where these specs are shared route the request
+ # through ApplicationController#route_not_found which does not involve
+ # the usual auth code from Devise, so does not increment the
+ # :user_unauthenticated_counter
+ #
+ unless params[:ignore_incrementing]
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+ end
+
+ personal_access_token.update!(scopes: [:read_user])
+
+ get url, params: default_params.merge(private_token: personal_access_token.token)
+
+ expect(response).not_to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context "when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ headers = { 'PRIVATE-TOKEN': personal_access_token.token }
+ get url, params: default_params, headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it "doesn't log the user in otherwise", unless: params[:public] do
+ # Several instances of where these specs are shared route the request
+ # through ApplicationController#route_not_found which does not involve
+ # the usual auth code from Devise, so does not increment the
+ # :user_unauthenticated_counter
+ #
+ unless params[:ignore_incrementing]
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+ end
+
+ get url, params: default_params.merge(private_token: 'token')
+
+ expect(response).not_to have_gitlab_http_status(:ok)
+ end
+end
diff --git a/spec/support/shared_examples/routing/legacy_path_redirect_shared_examples.rb b/spec/support/shared_examples/routing/legacy_path_redirect_shared_examples.rb
index 808336db7b1..ae3f6425b5e 100644
--- a/spec/support/shared_examples/routing/legacy_path_redirect_shared_examples.rb
+++ b/spec/support/shared_examples/routing/legacy_path_redirect_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'redirecting a legacy project path' do |source, target|
+RSpec.shared_examples 'redirecting a legacy path' do |source, target|
include RSpec::Rails::RequestExampleGroup
it "redirects #{source} to #{target}" do
diff --git a/spec/support/shared_examples/serializers/pipeline_artifacts_shared_example.rb b/spec/support/shared_examples/serializers/pipeline_artifacts_shared_example.rb
new file mode 100644
index 00000000000..d5ffd5e7510
--- /dev/null
+++ b/spec/support/shared_examples/serializers/pipeline_artifacts_shared_example.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+RSpec.shared_examples 'public artifacts' do
+ let_it_be(:project) { create(:project, :public) }
+ let(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) }
+
+ context 'that has artifacts' do
+ let!(:build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
+
+ it 'contains information about artifacts' do
+ expect(subject[:details][:artifacts].length).to eq(1)
+ end
+ end
+
+ context 'that has non public artifacts' do
+ let!(:build) { create(:ci_build, :success, :artifacts, :non_public_artifacts, pipeline: pipeline) }
+
+ it 'does not contain information about artifacts' do
+ expect(subject[:details][:artifacts].length).to eq(0)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
index 06e2b715e6d..197b0694741 100644
--- a/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
@@ -19,78 +19,12 @@ RSpec.shared_examples 'issues list service' do
end
end
- it 'avoids N+1' do
- params = { board_id: board.id }
- control = ActiveRecord::QueryRecorder.new { described_class.new(parent, user, params).execute }
-
- create(:list, board: board)
-
- expect { described_class.new(parent, user, params).execute }.not_to exceed_query_limit(control)
- end
-
- context 'issues are ordered by priority' do
- it 'returns opened issues when list_id is missing' do
- params = { board_id: board.id }
-
- issues = described_class.new(parent, user, params).execute
-
- expect(issues).to eq [opened_issue2, reopened_issue1, opened_issue1]
- end
-
- it 'returns opened issues when listing issues from Backlog' do
- params = { board_id: board.id, id: backlog.id }
-
- issues = described_class.new(parent, user, params).execute
-
- expect(issues).to eq [opened_issue2, reopened_issue1, opened_issue1]
- end
-
- it 'returns opened issues that have label list applied when listing issues from a label list' do
- params = { board_id: board.id, id: list1.id }
-
- issues = described_class.new(parent, user, params).execute
-
- expect(issues).to eq [list1_issue3, list1_issue1, list1_issue2]
- end
- end
-
- context 'issues are ordered by date of closing' do
- it 'returns closed issues when listing issues from Closed' do
- params = { board_id: board.id, id: closed.id }
-
- issues = described_class.new(parent, user, params).execute
-
- expect(issues).to eq [closed_issue1, closed_issue2, closed_issue3, closed_issue4, closed_issue5]
- end
- end
-
- context 'with list that does not belong to the board' do
- it 'raises an error' do
- list = create(:list)
- service = described_class.new(parent, user, board_id: board.id, id: list.id)
-
- expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'with invalid list id' do
- it 'raises an error' do
- service = described_class.new(parent, user, board_id: board.id, id: nil)
-
- expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'when :all_lists is used' do
- it 'returns issues from all lists' do
- params = { board_id: board.id, all_lists: true }
-
- issues = described_class.new(parent, user, params).execute
-
- expected = [opened_issue2, reopened_issue1, opened_issue1, list1_issue1,
- list1_issue2, list1_issue3, list2_issue1, closed_issue1,
- closed_issue2, closed_issue3, closed_issue4, closed_issue5]
- expect(issues).to match_array(expected)
- end
+ it_behaves_like 'items list service' do
+ let(:backlog_items) { [opened_issue2, reopened_issue1, opened_issue1] }
+ let(:list1_items) { [list1_issue3, list1_issue1, list1_issue2] }
+ let(:closed_items) { [closed_issue1, closed_issue2, closed_issue3, closed_issue4, closed_issue5] }
+ let(:all_items) { backlog_items + list1_items + closed_items + [list2_issue1] }
+ let(:list_factory) { :list }
+ let(:new_list) { create(:list, board: board) }
end
end
diff --git a/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb
new file mode 100644
index 00000000000..9a3a0cc9cc8
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'items list service' do
+ it 'avoids N+1' do
+ params = { board_id: board.id }
+ control = ActiveRecord::QueryRecorder.new { described_class.new(parent, user, params).execute }
+
+ new_list
+
+ expect { described_class.new(parent, user, params).execute }.not_to exceed_query_limit(control)
+ end
+
+ it 'returns opened items when list_id is missing' do
+ params = { board_id: board.id }
+
+ items = described_class.new(parent, user, params).execute
+
+ expect(items).to match_array(backlog_items)
+ end
+
+ it 'returns opened items when listing items from Backlog' do
+ params = { board_id: board.id, id: backlog.id }
+
+ items = described_class.new(parent, user, params).execute
+
+ expect(items).to match_array(backlog_items)
+ end
+
+ it 'returns opened items that have label list applied when listing items from a label list' do
+ params = { board_id: board.id, id: list1.id }
+
+ items = described_class.new(parent, user, params).execute
+
+ expect(items).to match_array(list1_items)
+ end
+
+ it 'returns closed items when listing items from Closed sorted by closed_at in descending order' do
+ params = { board_id: board.id, id: closed.id }
+
+ items = described_class.new(parent, user, params).execute
+
+ expect(items).to eq(closed_items)
+ end
+
+ it 'raises an error if the list does not belong to the board' do
+ list = create(list_factory) # rubocop:disable Rails/SaveBang
+ service = described_class.new(parent, user, board_id: board.id, id: list.id)
+
+ expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'raises an error if list id is invalid' do
+ service = described_class.new(parent, user, board_id: board.id, id: nil)
+
+ expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'returns items from all lists if :all_list is used' do
+ params = { board_id: board.id, all_lists: true }
+
+ items = described_class.new(parent, user, params).execute
+
+ expect(items).to match_array(all_items)
+ end
+end
diff --git a/spec/support/shared_examples/services/merge_request_shared_examples.rb b/spec/support/shared_examples/services/merge_request_shared_examples.rb
index 2bd06ac3e9c..56179b6cd00 100644
--- a/spec/support/shared_examples/services/merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/services/merge_request_shared_examples.rb
@@ -58,3 +58,18 @@ RSpec.shared_examples 'reviewer_ids filter' do
end
end
end
+
+RSpec.shared_examples 'merge request reviewers cache counters invalidator' do
+ let(:reviewer_1) { create(:user) }
+ let(:reviewer_2) { create(:user) }
+
+ before do
+ merge_request.update!(reviewers: [reviewer_1, reviewer_2])
+ end
+
+ it 'invalidates counter cache for reviewers' do
+ expect(merge_request.reviewers).to all(receive(:invalidate_merge_request_cache_counts))
+
+ described_class.new(project, user, {}).execute(merge_request)
+ end
+end
diff --git a/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb b/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb
new file mode 100644
index 00000000000..8398dd3c453
--- /dev/null
+++ b/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'updating the namespace package setting attributes' do |from: {}, to:|
+ it_behaves_like 'not creating the namespace package setting'
+
+ it 'updates the namespace package setting' do
+ expect { subject }
+ .to change { namespace.package_settings.reload.maven_duplicates_allowed }.from(from[:maven_duplicates_allowed]).to(to[:maven_duplicates_allowed])
+ .and change { namespace.package_settings.reload.maven_duplicate_exception_regex }.from(from[:maven_duplicate_exception_regex]).to(to[:maven_duplicate_exception_regex])
+ end
+end
+
+RSpec.shared_examples 'not creating the namespace package setting' do
+ it "doesn't create the namespace package setting" do
+ expect { subject }.not_to change { Namespace::PackageSetting.count }
+ end
+end
+
+RSpec.shared_examples 'creating the namespace package setting' do
+ it 'creates a new package setting' do
+ expect { subject }.to change { Namespace::PackageSetting.count }.by(1)
+ end
+
+ it 'saves the settings', :aggregate_failures do
+ subject
+
+ expect(namespace.package_setting_relation.maven_duplicates_allowed).to eq(package_settings[:maven_duplicates_allowed])
+ expect(namespace.package_setting_relation.maven_duplicate_exception_regex).to eq(package_settings[:maven_duplicate_exception_regex])
+ end
+
+ it_behaves_like 'returning a success'
+end
diff --git a/spec/support/shared_examples/services/onboarding_progress_shared_examples.rb b/spec/support/shared_examples/services/onboarding_progress_shared_examples.rb
new file mode 100644
index 00000000000..8c6c2271af3
--- /dev/null
+++ b/spec/support/shared_examples/services/onboarding_progress_shared_examples.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'records an onboarding progress action' do |action|
+ include AfterNextHelpers
+
+ it do
+ expect_next(OnboardingProgressService, namespace)
+ .to receive(:execute).with(action: action).and_call_original
+
+ subject
+ end
+end
+
+RSpec.shared_examples 'does not record an onboarding progress action' do
+ it do
+ expect(OnboardingProgressService).not_to receive(:new)
+
+ subject
+ end
+end
diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb
index 70d29b4bc99..fa307d2a9a6 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -220,3 +220,45 @@ RSpec.shared_examples 'package workhorse uploads' do
end
end
end
+
+RSpec.shared_examples 'with versionless packages' do
+ context 'with versionless package' do
+ let!(:versionless_package) { create(:maven_package, project: project, version: nil) }
+
+ shared_examples 'not including the package' do
+ it 'does not return the package' do
+ subject
+
+ expect(json_response.map { |package| package['id'] }).not_to include(versionless_package.id)
+ end
+ end
+
+ it_behaves_like 'not including the package'
+
+ context 'with include_versionless param' do
+ context 'with true include_versionless param' do
+ [true, 'true', 1, '1'].each do |param|
+ context "for param #{param}" do
+ let(:params) { super().merge(include_versionless: param) }
+
+ it 'returns the package' do
+ subject
+
+ expect(json_response.map { |package| package['id'] }).to include(versionless_package.id)
+ end
+ end
+ end
+ end
+
+ context 'with falsy include_versionless param' do
+ [false, '', nil, 'false', 0, '0'].each do |param|
+ context "for param #{param}" do
+ let(:params) { super().merge(include_versionless: param) }
+
+ it_behaves_like 'not including the package'
+ end
+ end
+ end
+ end
+ 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
new file mode 100644
index 00000000000..a174ae94b75
--- /dev/null
+++ b/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'housekeeps repository' do
+ subject { described_class.new(resource) }
+
+ context 'with a clean redis state', :clean_gitlab_redis_shared_state 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
+
+ Sidekiq::Testing.fake! do
+ expect { subject.execute }.to change(GitGarbageCollectWorker.jobs, :size).by(1)
+ end
+ end
+
+ it 'yields the block if given' do
+ expect do |block|
+ subject.execute(&block)
+ end.to yield_with_no_args
+ end
+
+ it 'resets counter after execution' do
+ expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
+ allow(subject).to receive(:gc_period).and_return(1)
+ resource.increment_pushes_since_gc
+
+ perform_enqueued_jobs do
+ expect { subject.execute }.to change { resource.pushes_since_gc }.to(0)
+ end
+ end
+
+ context 'when no lease can be obtained' do
+ before do
+ expect(subject).to receive(:try_obtain_lease).and_return(false)
+ end
+
+ it 'does not enqueue a job' do
+ expect(GitGarbageCollectWorker).not_to receive(:perform_async)
+
+ expect { subject.execute }.to raise_error(Repositories::HousekeepingService::LeaseTaken)
+ end
+
+ it 'does not reset pushes_since_gc' do
+ expect do
+ expect { subject.execute }.to raise_error(Repositories::HousekeepingService::LeaseTaken)
+ end.not_to change { resource.pushes_since_gc }
+ end
+
+ it 'does not yield' do
+ expect do |block|
+ expect { subject.execute(&block) }
+ .to raise_error(Repositories::HousekeepingService::LeaseTaken)
+ end.not_to yield_with_no_args
+ end
+ end
+
+ context 'task type' do
+ it 'goes through all three housekeeping tasks, executing only the highest task when there is overlap' do
+ allow(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
+ 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)
+ .once
+ # At push 50, 100, 150
+ expect(GitGarbageCollectWorker).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)
+ .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)
+ .exactly(27).times
+
+ 201.times do
+ subject.increment!
+ subject.execute if subject.needed?
+ end
+
+ expect(resource.pushes_since_gc).to eq(1)
+ end
+ end
+
+ it 'runs the task specifically requested' do
+ housekeeping = described_class.new(resource, :gc)
+
+ 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
+
+ 2.times do
+ housekeeping.execute
+ end
+ end
+ end
+
+ describe '#needed?' do
+ it 'when the count is low enough' do
+ expect(subject.needed?).to eq(false)
+ end
+
+ it 'when the count is high enough' do
+ allow(resource).to receive(:pushes_since_gc).and_return(10)
+ expect(subject.needed?).to eq(true)
+ end
+ end
+
+ describe '#increment!' do
+ it 'increments the pushes_since_gc counter' do
+ expect { subject.increment! }.to change { resource.pushes_since_gc }.by(1)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/schedule_bulk_repository_shard_moves_shared_examples.rb b/spec/support/shared_examples/services/schedule_bulk_repository_shard_moves_shared_examples.rb
new file mode 100644
index 00000000000..e67fc4ab04a
--- /dev/null
+++ b/spec/support/shared_examples/services/schedule_bulk_repository_shard_moves_shared_examples.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'moves repository shard in bulk' do
+ let(:source_storage_name) { 'default' }
+ let(:destination_storage_name) { 'test_second_storage' }
+
+ before do
+ stub_storage_settings(destination_storage_name => { 'path' => 'tmp/tests/extra_storage' })
+ end
+
+ describe '#execute' do
+ it 'schedules container repository storage moves' do
+ expect { subject.execute(source_storage_name, destination_storage_name) }
+ .to change(move_service_klass, :count).by(1)
+
+ storage_move = container.repository_storage_moves.last!
+
+ expect(storage_move).to have_attributes(
+ source_storage_name: source_storage_name,
+ destination_storage_name: destination_storage_name,
+ state_name: :scheduled
+ )
+ end
+
+ context 'read-only repository' do
+ it 'does not get scheduled' do
+ container.set_repository_read_only!
+
+ expect(subject).to receive(:log_info)
+ .with(/Container #{container.full_path} \(#{container.id}\) was skipped: #{container.class} is read only/)
+ expect { subject.execute(source_storage_name, destination_storage_name) }
+ .to change(move_service_klass, :count).by(0)
+ end
+ end
+ end
+
+ describe '.enqueue' do
+ it 'defers to the worker' do
+ expect(bulk_worker_klass).to receive(:perform_async).with(source_storage_name, destination_storage_name)
+
+ described_class.enqueue(source_storage_name, destination_storage_name)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/workers/schedule_bulk_repository_shard_moves_shared_examples.rb b/spec/support/shared_examples/workers/schedule_bulk_repository_shard_moves_shared_examples.rb
new file mode 100644
index 00000000000..465aca63148
--- /dev/null
+++ b/spec/support/shared_examples/workers/schedule_bulk_repository_shard_moves_shared_examples.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'schedules bulk repository shard moves' do
+ let(:source_storage_name) { 'default' }
+ let(:destination_storage_name) { 'test_second_storage' }
+
+ describe "#perform" do
+ before do
+ stub_storage_settings(destination_storage_name => { 'path' => 'tmp/tests/extra_storage' })
+
+ allow(worker_klass).to receive(:perform_async)
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [source_storage_name, destination_storage_name] }
+
+ it 'schedules container repository storage moves' do
+ expect { subject }.to change(move_service_klass, :count).by(1)
+
+ storage_move = container.repository_storage_moves.last!
+
+ expect(storage_move).to have_attributes(
+ source_storage_name: source_storage_name,
+ destination_storage_name: destination_storage_name,
+ state_name: :scheduled
+ )
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/workers/update_repository_move_shared_examples.rb b/spec/support/shared_examples/workers/update_repository_move_shared_examples.rb
new file mode 100644
index 00000000000..babd7cfbbeb
--- /dev/null
+++ b/spec/support/shared_examples/workers/update_repository_move_shared_examples.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'an update storage move worker' do
+ describe '#perform' do
+ let(:service) { double(:update_repository_storage_service) }
+
+ before do
+ allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage])
+ end
+
+ context 'without repository storage move' do
+ it 'calls the update repository storage service' do
+ expect(service_klass).to receive(:new).and_return(service)
+ expect(service).to receive(:execute)
+
+ expect do
+ subject.perform(container.id, 'test_second_storage')
+ end.to change(repository_storage_move_klass, :count).by(1)
+
+ storage_move = container.repository_storage_moves.last
+ expect(storage_move).to have_attributes(
+ source_storage_name: 'default',
+ destination_storage_name: 'test_second_storage'
+ )
+ end
+ end
+
+ context 'with repository storage move' do
+ it 'calls the update repository storage service' do
+ expect(service_klass).to receive(:new).and_return(service)
+ expect(service).to receive(:execute)
+
+ expect do
+ subject.perform(nil, nil, repository_storage_move.id)
+ end.not_to change(repository_storage_move_klass, :count)
+ end
+ end
+ end
+end
diff --git a/spec/support_specs/matchers/be_sorted_spec.rb b/spec/support_specs/matchers/be_sorted_spec.rb
new file mode 100644
index 00000000000..e62bc9b36b3
--- /dev/null
+++ b/spec/support_specs/matchers/be_sorted_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+load File.expand_path('../../../spec/support/matchers/be_sorted.rb', __dir__)
+
+RSpec.describe 'be_sorted' do
+ it 'matches empty collections, regardless of arguments' do
+ expect([])
+ .to be_sorted
+ .and be_sorted.asc
+ .and be_sorted.desc
+ .and be_sorted(:foo)
+ .and be_sorted(:bar)
+
+ expect([].to_set).to be_sorted
+ expect({}).to be_sorted
+ end
+
+ it 'matches in both directions' do
+ expect([1, 2, 3]).to be_sorted.asc
+ expect([3, 2, 1]).to be_sorted.desc
+ end
+
+ it 'can match on a projection' do
+ xs = [['a', 10], ['b', 7], ['c', 4]]
+
+ expect(xs).to be_sorted.asc.by(&:first)
+ expect(xs).to be_sorted(:first, :asc)
+ expect(xs).to be_sorted.desc.by(&:second)
+ expect(xs).to be_sorted(:second, :desc)
+ end
+end
diff --git a/spec/tasks/gitlab/git_rake_spec.rb b/spec/tasks/gitlab/git_rake_spec.rb
index 4bc1b460d9b..4d89b126c9e 100644
--- a/spec/tasks/gitlab/git_rake_spec.rb
+++ b/spec/tasks/gitlab/git_rake_spec.rb
@@ -19,4 +19,38 @@ RSpec.describe 'gitlab:git rake tasks' do
expect { run_rake_task('gitlab:git:fsck') }.to output(/Performed integrity check for/).to_stdout
end
end
+
+ describe 'checksum_projects' do
+ it 'outputs the checksum for a repo' do
+ expected = /#{project.id},#{project.repository.checksum}/
+
+ expect { run_rake_task('gitlab:git:checksum_projects') }.to output(expected).to_stdout
+ end
+
+ it 'outputs blank checksum for no repo' do
+ no_repo = create(:project)
+
+ expected = /#{no_repo.id},$/
+
+ expect { run_rake_task('gitlab:git:checksum_projects') }.to output(expected).to_stdout
+ end
+
+ it 'outputs zeroes for empty repo' do
+ empty_repo = create(:project, :empty_repo)
+
+ expected = /#{empty_repo.id},0000000000000000000000000000000000000000/
+
+ expect { run_rake_task('gitlab:git:checksum_projects') }.to output(expected).to_stdout
+ end
+
+ it 'outputs errors' do
+ allow_next_found_instance_of(Project) do |project|
+ allow(project).to receive(:repo_exists?).and_raise('foo')
+ end
+
+ expected = /#{project.id},Ignored error: foo/
+
+ expect { run_rake_task('gitlab:git:checksum_projects') }.to output(expected).to_stdout
+ end
+ end
end
diff --git a/spec/tasks/gitlab/packages/events_rake_spec.rb b/spec/tasks/gitlab/packages/events_rake_spec.rb
index a485dc2ce58..d6aa6deac1e 100644
--- a/spec/tasks/gitlab/packages/events_rake_spec.rb
+++ b/spec/tasks/gitlab/packages/events_rake_spec.rb
@@ -38,8 +38,8 @@ RSpec.describe 'gitlab:packages:events namespace rake task' do
end
end
- describe 'generate_guest' do
- let(:task) { 'generate_guest' }
+ describe 'generate_counts' do
+ let(:task) { 'generate_counts' }
Packages::Event::EVENT_SCOPES.keys.each do |event_scope|
it "includes `#{event_scope}` scope" do
diff --git a/spec/tasks/gitlab/pages_rake_spec.rb b/spec/tasks/gitlab/pages_rake_spec.rb
new file mode 100644
index 00000000000..76808f52890
--- /dev/null
+++ b/spec/tasks/gitlab/pages_rake_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:pages:migrate_legacy_storagerake task' do
+ before(:context) do
+ Rake.application.rake_require 'tasks/gitlab/pages'
+ end
+
+ subject { run_rake_task('gitlab:pages:migrate_legacy_storage') }
+
+ let(:project) { create(:project) }
+
+ it 'does not try to migrate pages if pages are not deployed' do
+ expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+
+ subject
+ end
+
+ context 'when pages are marked as deployed' do
+ 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) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ subject
+ 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) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect do
+ subject
+ 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)
+
+ subject
+ end
+ 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 fdd56aa0189..2511295206c 100644
--- a/spec/tooling/lib/tooling/kubernetes_client_spec.rb
+++ b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
@@ -17,84 +17,111 @@ RSpec.describe Tooling::KubernetesClient do
end
end
- describe '#cleanup' do
+ describe '#cleanup_by_release' do
before do
allow(subject).to receive(:raw_resource_names).and_return(raw_resource_names)
end
+ shared_examples 'a kubectl command to delete resources' do
+ let(:wait) { true }
+ let(:release_names_in_command) { release_name.respond_to?(:join) ? %(-l 'release in (#{release_name.join(', ')})') : %(-l release="#{release_name}") }
+
+ 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})])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(kubectl delete --namespace "#{namespace}" --ignore-not-found #{pod_for_release})])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+
+ # We're not verifying the output here, just silencing it
+ expect { subject.cleanup_by_release(release_name: release_name) }.to output.to_stdout
+ end
+ end
+
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}")])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
- expect { subject.cleanup(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
+ expect { subject.cleanup_by_release(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
end
- it 'calls kubectl with the correct arguments' 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}")])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+ it_behaves_like 'a kubectl command to delete resources'
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(kubectl delete --namespace "#{namespace}" --ignore-not-found #{pod_for_release})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+ context 'with multiple releases' do
+ let(:release_name) { %w[my-release my-release-2] }
- # We're not verifying the output here, just silencing it
- expect { subject.cleanup(release_name: release_name) }.to output.to_stdout
+ it_behaves_like 'a kubectl command to delete resources'
end
- context 'with multiple releases' do
- let(:release_name) { %w[my-release my-release-2] }
+ context 'with `wait: false`' do
+ let(:wait) { false }
- 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 in (#{release_name.join(', ')})')])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
+ it_behaves_like 'a kubectl command to delete resources'
+ end
+ end
- expect { subject.cleanup(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
- end
+ describe '#cleanup_by_created_at' do
+ let(:two_days_ago) { Time.now - 3600 * 24 * 2 }
+ let(:resource_type) { 'pvc' }
+ let(:resource_names) { [pod_for_release] }
- it 'calls kubectl with the correct arguments' 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 in (#{release_name.join(', ')})')])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+ before do
+ allow(subject).to receive(:resource_names_created_before).with(resource_type: resource_type, created_before: two_days_ago).and_return(resource_names)
+ end
+
+ shared_examples 'a kubectl command to delete resources by older than given creation time' do
+ let(:wait) { true }
+ let(:release_names_in_command) { resource_names.join(' ') }
+ specify do
expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(kubectl delete --namespace "#{namespace}" --ignore-not-found #{pod_for_release})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+ .with(["kubectl delete #{resource_type} ".squeeze(' ') +
+ %(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --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
- expect { subject.cleanup(release_name: release_name) }.to output.to_stdout
+ expect { subject.cleanup_by_created_at(resource_type: resource_type, created_before: two_days_ago) }.to output.to_stdout
end
end
+ 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})])
+ .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)
+ end
+
+ it_behaves_like 'a kubectl command to delete resources by older than given creation time'
+
+ context 'with multiple resource names' do
+ let(:resource_names) { %w[pod-1 pod-2] }
+
+ it_behaves_like 'a kubectl command to delete resources by older than given creation time'
+ end
+
context 'with `wait: false`' 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=false -l release="#{release_name}")])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
+ let(:wait) { false }
- expect { subject.cleanup(release_name: release_name, wait: false) }.to raise_error(described_class::CommandFailedError)
- end
+ it_behaves_like 'a kubectl command to delete resources by older than given creation time'
+ end
- it 'calls kubectl with the correct arguments' 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=false -l release="#{release_name}")])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+ context 'with no resource_type given' do
+ let(:resource_type) { nil }
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(kubectl delete --namespace "#{namespace}" --ignore-not-found #{pod_for_release})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+ it_behaves_like 'a kubectl command to delete resources by older than given creation time'
+ end
- # We're not verifying the output here, just silencing it
- expect { subject.cleanup(release_name: release_name, wait: false) }.to output.to_stdout
- end
+ context 'with multiple resource_type given' do
+ let(:resource_type) { 'pvc,service' }
+
+ it_behaves_like 'a kubectl command to delete resources by older than given creation time'
end
end
@@ -108,4 +135,59 @@ RSpec.describe Tooling::KubernetesClient do
expect(subject.__send__(:raw_resource_names)).to eq(raw_resource_names)
end
end
+
+ describe '#resource_names_created_before' do
+ let(:three_days_ago) { Time.now - 3600 * 24 * 3 }
+ let(:two_days_ago) { Time.now - 3600 * 24 * 2 }
+ let(:pvc_created_three_days_ago) { 'pvc-created-three-days-ago' }
+ let(:resource_type) { 'pvc' }
+ let(:raw_resources) do
+ {
+ items: [
+ {
+ apiVersion: "v1",
+ kind: "PersistentVolumeClaim",
+ metadata: {
+ creationTimestamp: three_days_ago,
+ name: pvc_created_three_days_ago
+ }
+ },
+ {
+ apiVersion: "v1",
+ kind: "PersistentVolumeClaim",
+ metadata: {
+ creationTimestamp: Time.now,
+ name: 'another-pvc'
+ }
+ }
+ ]
+ }.to_json
+ end
+
+ shared_examples 'a kubectl command to retrieve resource names sorted by creationTimestamp' do
+ specify do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with(["kubectl get #{resource_type} ".squeeze(' ') +
+ %(--namespace "#{namespace}" ) +
+ "--sort-by='{.metadata.creationTimestamp}' -o json"])
+ .and_return(Gitlab::Popen::Result.new([], raw_resources, '', double(success?: true)))
+
+ expect(subject.__send__(:resource_names_created_before, resource_type: resource_type, created_before: two_days_ago)).to contain_exactly(pvc_created_three_days_ago)
+ end
+ end
+
+ it_behaves_like 'a kubectl command to retrieve resource names sorted by creationTimestamp'
+
+ context 'with no resource_type given' do
+ let(:resource_type) { nil }
+
+ it_behaves_like 'a kubectl command to retrieve resource names sorted by creationTimestamp'
+ end
+
+ context 'with multiple resource_type given' do
+ let(:resource_type) { 'pvc,service' }
+
+ it_behaves_like 'a kubectl command to retrieve resource names sorted by creationTimestamp'
+ end
+ end
end
diff --git a/spec/tooling/lib/tooling/test_file_finder_spec.rb b/spec/tooling/lib/tooling/test_file_finder_spec.rb
deleted file mode 100644
index 683bc647b8a..00000000000
--- a/spec/tooling/lib/tooling/test_file_finder_spec.rb
+++ /dev/null
@@ -1,175 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../../../tooling/lib/tooling/test_file_finder'
-
-RSpec.describe Tooling::TestFileFinder do
- subject { described_class.new(file) }
-
- describe '#test_files' do
- context 'when given non .rb files' do
- let(:file) { 'app/assets/images/emoji.png' }
-
- it 'does not return a test file' do
- expect(subject.test_files).to be_empty
- end
- end
-
- context 'when given file in app/' do
- let(:file) { 'app/finders/admin/projects_finder.rb' }
-
- it 'returns the matching app spec file' do
- expect(subject.test_files).to contain_exactly('spec/finders/admin/projects_finder_spec.rb')
- end
- end
-
- context 'when given file in lib/' do
- let(:file) { 'lib/banzai/color_parser.rb' }
-
- it 'returns the matching app spec file' do
- expect(subject.test_files).to contain_exactly('spec/lib/banzai/color_parser_spec.rb')
- end
- end
-
- context 'when given a file in tooling/' do
- let(:file) { 'tooling/lib/tooling/test_file_finder.rb' }
-
- it 'returns the matching tooling test' do
- expect(subject.test_files).to contain_exactly('spec/tooling/lib/tooling/test_file_finder_spec.rb')
- end
- end
-
- context 'when given a test file' do
- let(:file) { 'spec/lib/banzai/color_parser_spec.rb' }
-
- it 'returns the matching test file itself' do
- expect(subject.test_files).to contain_exactly('spec/lib/banzai/color_parser_spec.rb')
- end
- end
-
- context 'when given an app file in ee/' do
- let(:file) { 'ee/app/models/analytics/cycle_analytics/group_level.rb' }
-
- it 'returns the matching ee/ test file' do
- expect(subject.test_files).to contain_exactly('ee/spec/models/analytics/cycle_analytics/group_level_spec.rb')
- end
- end
-
- context 'when given an ee extension module file' do
- let(:file) { 'ee/app/models/ee/user.rb' }
-
- it 'returns the matching ee/ class test file, ee extension module test file and the foss class test file' do
- test_files = ['ee/spec/models/user_spec.rb', 'ee/spec/models/ee/user_spec.rb', 'spec/app/models/user_spec.rb']
- expect(subject.test_files).to contain_exactly(*test_files)
- end
- end
-
- context 'when given a test file in ee/' do
- let(:file) { 'ee/spec/models/container_registry/event_spec.rb' }
-
- it 'returns the test file itself' do
- expect(subject.test_files).to contain_exactly('ee/spec/models/container_registry/event_spec.rb')
- end
- end
-
- context 'when given a module test file in ee/' do
- let(:file) { 'ee/spec/models/ee/appearance_spec.rb' }
-
- it 'returns the matching module test file itself and the corresponding spec model test file' do
- test_files = ['ee/spec/models/ee/appearance_spec.rb', 'spec/models/appearance_spec.rb']
- expect(subject.test_files).to contain_exactly(*test_files)
- end
- end
-
- context 'when given a factory file' do
- let(:file) { 'spec/factories/users.rb' }
-
- it 'returns spec/factories_spec.rb file' do
- expect(subject.test_files).to contain_exactly('spec/factories_spec.rb')
- end
- end
-
- context 'when given an ee factory file' do
- let(:file) { 'ee/spec/factories/users.rb' }
-
- it 'returns spec/factories_spec.rb file' do
- expect(subject.test_files).to contain_exactly('spec/factories_spec.rb')
- end
- end
-
- context 'when given db/structure.sql' do
- let(:file) { 'db/structure.sql' }
-
- it 'returns spec/db/schema_spec.rb' do
- expect(subject.test_files).to contain_exactly('spec/db/schema_spec.rb')
- end
- end
-
- context 'when given an initializer' do
- let(:file) { 'config/initializers/action_mailer_hooks.rb' }
-
- it 'returns the matching initializer spec' do
- expect(subject.test_files).to contain_exactly('spec/initializers/action_mailer_hooks_spec.rb')
- end
- end
-
- context 'when given a haml view' do
- let(:file) { 'app/views/admin/users/_user.html.haml' }
-
- it 'returns the matching view spec' do
- expect(subject.test_files).to contain_exactly('spec/views/admin/users/_user.html.haml_spec.rb')
- end
- end
-
- context 'when given a haml view in ee/' do
- let(:file) { 'ee/app/views/admin/users/_user.html.haml' }
-
- it 'returns the matching view spec' do
- expect(subject.test_files).to contain_exactly('ee/spec/views/admin/users/_user.html.haml_spec.rb')
- end
- end
-
- context 'when given a migration file' do
- let(:file) { 'db/migrate/20191023152913_add_default_and_free_plans.rb' }
-
- it 'returns the matching migration spec' do
- test_files = %w[
- spec/migrations/add_default_and_free_plans_spec.rb
- spec/migrations/20191023152913_add_default_and_free_plans_spec.rb
- ]
- expect(subject.test_files).to contain_exactly(*test_files)
- end
- end
-
- context 'when given a post-migration file' do
- let(:file) { 'db/post_migrate/20200608072931_backfill_imported_snippet_repositories.rb' }
-
- it 'returns the matching migration spec' do
- test_files = %w[
- spec/migrations/backfill_imported_snippet_repositories_spec.rb
- spec/migrations/20200608072931_backfill_imported_snippet_repositories_spec.rb
- ]
- expect(subject.test_files).to contain_exactly(*test_files)
- end
- end
-
- context 'with foss_test_only: true' do
- subject { Tooling::TestFileFinder.new(file, foss_test_only: true) }
-
- context 'when given a module file in ee/' do
- let(:file) { 'ee/app/models/ee/user.rb' }
-
- it 'returns only the corresponding spec model test file in foss' do
- expect(subject.test_files).to contain_exactly('spec/app/models/user_spec.rb')
- end
- end
-
- context 'when given an app file in ee/' do
- let(:file) { 'ee/app/models/approval.rb' }
-
- it 'returns no test file in foss' do
- expect(subject.test_files).to be_empty
- end
- end
- end
- end
-end
diff --git a/spec/uploaders/packages/debian/distribution_release_file_uploader_spec.rb b/spec/uploaders/packages/debian/distribution_release_file_uploader_spec.rb
new file mode 100644
index 00000000000..d36bfac4de8
--- /dev/null
+++ b/spec/uploaders/packages/debian/distribution_release_file_uploader_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::DistributionReleaseFileUploader do
+ [:project, :group].each do |container_type|
+ context "Packages::Debian::#{container_type.capitalize}Distribution" do
+ let(:factory) { "debian_#{container_type}_distribution" }
+ let(:distribution) { create(factory, :with_file) }
+ let(:uploader) { described_class.new(distribution, :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}_distribution/\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}_distribution/\d+$],
+ cache_dir: %r[/packages/tmp/cache$],
+ work_dir: %r[/packages/tmp/work$]
+ end
+
+ describe 'remote file' do
+ let(:distribution) { create(factory, :with_file, :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)
+
+ distribution
+
+ expect(distribution.file_store).to eq(described_class::Store::REMOTE)
+ expect(distribution.file.path).not_to be_blank
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/uploaders/packages/package_file_uploader_spec.rb b/spec/uploaders/packages/package_file_uploader_spec.rb
index f4e72892c8f..e8f4cae7b04 100644
--- a/spec/uploaders/packages/package_file_uploader_spec.rb
+++ b/spec/uploaders/packages/package_file_uploader_spec.rb
@@ -2,43 +2,50 @@
require 'spec_helper'
RSpec.describe Packages::PackageFileUploader do
- let(:package_file) { create(:package_file, :xml) }
- let(:uploader) { described_class.new(package_file, :file) }
- let(:path) { Gitlab.config.packages.storage_path }
-
- subject { uploader }
-
- it_behaves_like "builds correct paths",
- store_dir: %r[\h{2}/\h{2}],
- 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}]
- end
+ {
+ package_file: %r[^\h{2}/\h{2}/\h{64}/packages/\d+/files/\d+$],
+ debian_package_file: %r[^\h{2}/\h{2}/\h{64}/packages/debian/files/\d+$]
+ }.each do |factory, store_dir_regex|
+ context factory.to_s do
+ let(:package_file) { create(factory) } # rubocop:disable Rails/SaveBang
+ let(:uploader) { described_class.new(package_file, :file) }
+ let(:path) { Gitlab.config.packages.storage_path }
+
+ subject { uploader }
+
+ it_behaves_like "builds correct paths",
+ store_dir: store_dir_regex,
+ 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: store_dir_regex
+ end
- describe 'remote file' do
- let(:package_file) { create(:package_file, :object_storage, :xml) }
+ describe 'remote file' do
+ let(:package_file) { create(factory, :object_storage) }
- context 'with object storage enabled' do
- before do
- stub_package_file_object_storage
- end
+ 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)
+ it 'can store file remotely' do
+ allow(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async)
- package_file
+ package_file
- expect(package_file.file_store).to eq(described_class::Store::REMOTE)
- expect(package_file.file.path).not_to be_blank
+ expect(package_file.file_store).to eq(described_class::Store::REMOTE)
+ expect(package_file.file.path).not_to be_blank
+ 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 d8748873f64..15fdfaaaa65 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe 'layouts/_head' do
render
- expect(rendered).to match('<link rel="stylesheet" media="all" href="/stylesheets/highlight/themes/solarised-light.css" />')
+ expect(rendered).to match('<link rel="stylesheet" media="print" href="/stylesheets/highlight/themes/solarised-light.css" />')
end
context 'when an asset_host is set and snowplow url is set' do
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index cf33ec9884b..01892e72c97 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -3,10 +3,42 @@
require 'spec_helper'
RSpec.describe 'layouts/header/_new_dropdown' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+
+ shared_examples_for 'invite member quick link' do
+ context 'when an experiment is active' 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)
+ end
+
+ context 'with ability to invite members' do
+ it { is_expected.to have_link('Invite members', href: href) }
+
+ it 'records the experiment' 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)
+ end
+ end
+
+ context 'without ability to invite members' do
+ let(:invite_member) { false }
+
+ it { is_expected.not_to have_link('Invite members') }
+ end
+ end
+
+ context 'when experiment is not active' do
+ it { is_expected.not_to have_link('Invite members') }
+ end
+ end
context 'group-specific links' do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
before do
stub_current_user(user)
@@ -22,25 +54,39 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has a "New project" link' do
render
- expect(rendered).to have_link(
- 'New project',
- href: new_project_path(namespace_id: group.id)
- )
+ expect(rendered).to have_link('New project', href: new_project_path(namespace_id: group.id))
end
it 'has a "New subgroup" link' do
render
- expect(rendered).to have_link(
- 'New subgroup',
- href: new_group_path(parent_id: group.id)
- )
+ expect(rendered).to have_link('New subgroup', href: new_group_path(parent_id: group.id))
end
end
+
+ describe 'invite members quick link' do
+ let(:href) { group_group_members_path(group) }
+ let(:invite_member) { true }
+
+ before do
+ allow(view).to receive(:can?).with(user, :create_projects, group).and_return(true)
+ allow(view).to receive(:can?).with(user, :admin_group_member, group).and_return(invite_member)
+ allow(view).to receive(:can_import_members?).and_return(invite_member)
+ allow(view).to receive(:experiment_enabled?)
+ end
+
+ subject do
+ render
+
+ rendered
+ end
+
+ it_behaves_like 'invite member quick link'
+ end
end
context 'project-specific links' do
- let(:project) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:project) { create(:project, creator: user, namespace: user.namespace) }
before do
assign(:project, project)
@@ -54,33 +100,24 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has a "New issue" link' do
render
- expect(rendered).to have_link(
- 'New issue',
- href: new_project_issue_path(project)
- )
+ expect(rendered).to have_link('New issue', href: new_project_issue_path(project))
end
it 'has a "New merge request" link' do
render
- expect(rendered).to have_link(
- 'New merge request',
- href: project_new_merge_request_path(project)
- )
+ expect(rendered).to have_link('New merge request', href: project_new_merge_request_path(project))
end
it 'has a "New snippet" link' do
render
- expect(rendered).to have_link(
- 'New snippet',
- href: new_project_snippet_path(project)
- )
+ expect(rendered).to have_link('New snippet', href: new_project_snippet_path(project))
end
end
context 'as a Project guest' do
- let(:guest) { create(:user) }
+ let_it_be(:guest) { create(:user) }
before do
stub_current_user(guest)
@@ -96,12 +133,28 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has no "New snippet" link' do
render
- expect(rendered).not_to have_link(
- 'New snippet',
- href: new_project_snippet_path(project)
- )
+ expect(rendered).not_to have_link('New snippet', href: new_project_snippet_path(project))
end
end
+
+ describe 'invite members quick link' do
+ let(:invite_member) { true }
+ let(:href) { project_project_members_path(project) }
+
+ before do
+ allow(view).to receive(:can_import_members?).and_return(invite_member)
+ stub_current_user(user)
+ allow(view).to receive(:experiment_enabled?)
+ end
+
+ subject do
+ render
+
+ rendered
+ end
+
+ it_behaves_like 'invite member quick link'
+ end
end
context 'global links' do
@@ -128,7 +181,7 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
context 'when the user is not allowed to create snippets' do
- let(:user) { create(:user, :external)}
+ let(:user) { create(:user, :external) }
it 'has no "New snippet" link' do
render
diff --git a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
index b41933f9c36..defd8190eda 100644
--- a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'notify/pipeline_failed_email.html.haml' do
it_behaves_like 'pipeline status changes email' do
- let(:title) { 'Your pipeline has failed' }
+ let(:title) { "Pipeline ##{pipeline.id} has failed!" }
let(:status) { :failed }
end
end
diff --git a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
index a5c31632b0d..dd637af5137 100644
--- a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'notify/pipeline_failed_email.text.erb' do
it 'renders the email correctly' do
render
- expect(rendered).to have_content('Your pipeline has failed')
+ expect(rendered).to have_content("Pipeline ##{pipeline.id} has failed!")
expect(rendered).to have_content(pipeline.project.name)
expect(rendered).to have_content(pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' '))
expect(rendered).to have_content(pipeline.commit.author_name)
diff --git a/spec/views/notify/pipeline_fixed_email.html.haml_spec.rb b/spec/views/notify/pipeline_fixed_email.html.haml_spec.rb
index 2b3b08f8e8c..bdfc8fb5f6b 100644
--- a/spec/views/notify/pipeline_fixed_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_fixed_email.html.haml_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'notify/pipeline_fixed_email.html.haml' do
it_behaves_like 'pipeline status changes email' do
- let(:title) { 'Your pipeline has been fixed!' }
+ let(:title) { "Pipeline has been fixed and ##{pipeline.id} has passed!" }
let(:status) { :success }
end
end
diff --git a/spec/views/notify/pipeline_fixed_email.text.erb_spec.rb b/spec/views/notify/pipeline_fixed_email.text.erb_spec.rb
index 8640998acaa..d0bc110f95c 100644
--- a/spec/views/notify/pipeline_fixed_email.text.erb_spec.rb
+++ b/spec/views/notify/pipeline_fixed_email.text.erb_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'notify/pipeline_fixed_email.text.erb' do
it_behaves_like 'pipeline status changes email' do
- let(:title) { 'Your pipeline has been fixed!' }
+ let(:title) { "Pipeline has been fixed and ##{pipeline.id} has passed!" }
let(:status) { :success }
end
end
diff --git a/spec/views/notify/pipeline_success_email.html.haml_spec.rb b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
index 51ea7ef5066..ce03f672700 100644
--- a/spec/views/notify/pipeline_success_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'notify/pipeline_success_email.html.haml' do
it_behaves_like 'pipeline status changes email' do
- let(:title) { 'Your pipeline has passed' }
+ let(:title) { "Pipeline ##{pipeline.id} has passed!" }
let(:status) { :success }
end
end
diff --git a/spec/views/notify/pipeline_success_email.text.erb_spec.rb b/spec/views/notify/pipeline_success_email.text.erb_spec.rb
index 3acf4dd3e26..02334a48fa3 100644
--- a/spec/views/notify/pipeline_success_email.text.erb_spec.rb
+++ b/spec/views/notify/pipeline_success_email.text.erb_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'notify/pipeline_success_email.text.erb' do
it_behaves_like 'pipeline status changes email' do
- let(:title) { 'Your pipeline has passed' }
+ let(:title) { "Pipeline ##{pipeline.id} has passed!" }
let(:status) { :success }
end
end
diff --git a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
index b3f59a59ac8..95c51be9867 100644
--- a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
+++ b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'projects/settings/ci_cd/_autodevops_form' do
it 'shows a warning message about Kubernetes cluster' do
render
- expect(rendered).to have_text('Add a Kubernetes cluster integration with a domain or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable')
+ expect(rendered).to have_text('Add a Kubernetes cluster integration with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable.')
end
context 'when the project has an available kubernetes cluster' do
@@ -28,7 +28,7 @@ RSpec.describe 'projects/settings/ci_cd/_autodevops_form' do
it 'shows a warning message about base domain' do
render
- expect(rendered).to have_text('You must add a base domain to your Kubernetes cluster in order for your deployment strategy to work.')
+ expect(rendered).to have_text('Add a base domain to your Kubernetes cluster for your deployment strategy to work.')
end
end
end
diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb
index facb4e2016d..a22853d40d8 100644
--- a/spec/views/projects/settings/operations/show.html.haml_spec.rb
+++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb
@@ -15,14 +15,6 @@ RSpec.describe 'projects/settings/operations/show' do
end
let_it_be(:prometheus_service) { create(:prometheus_service, project: project) }
- let_it_be(:alerts_service) { create(:alerts_service, project: project) }
-
- let(:operations_show_locals) do
- {
- prometheus_service: prometheus_service,
- alerts_service: alerts_service
- }
- end
before_all do
project.add_maintainer(user)
@@ -35,13 +27,24 @@ RSpec.describe 'projects/settings/operations/show' do
.and_return(error_tracking_setting)
allow(view).to receive(:tracing_setting)
.and_return(tracing_setting)
+ allow(view).to receive(:prometheus_service)
+ .and_return(prometheus_service)
allow(view).to receive(:current_user).and_return(user)
end
+ describe 'Operations > Alerts' do
+ it 'renders the Operations Settings page' do
+ render
+
+ expect(rendered).to have_content _('Alerts')
+ expect(rendered).to have_content _('Display alerts from all your monitoring tools directly within GitLab.')
+ end
+ end
+
describe 'Operations > Error Tracking' do
context 'Settings page ' do
it 'renders the Operations Settings page' do
- render template: 'projects/settings/operations/show', locals: operations_show_locals
+ render
expect(rendered).to have_content _('Error tracking')
expect(rendered).to have_content _('To link Sentry to GitLab, enter your Sentry URL and Auth Token')
@@ -49,10 +52,34 @@ RSpec.describe 'projects/settings/operations/show' do
end
end
+ describe 'Operations > Prometheus' do
+ context 'when settings_operations_prometheus_service flag is enabled' do
+ it 'renders the Operations Settings page' do
+ render
+
+ expect(rendered).to have_content _('Prometheus')
+ expect(rendered).to have_content _('Link Prometheus monitoring to GitLab.')
+ expect(rendered).to have_content _('To enable the installation of Prometheus on your clusters, deactivate the manual configuration below')
+ end
+ end
+
+ context 'when settings_operations_prometheus_service is disabled' do
+ before do
+ stub_feature_flags(settings_operations_prometheus_service: false)
+ end
+
+ it 'renders the Operations Settings page' do
+ render
+
+ expect(rendered).not_to have_content _('Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used.')
+ end
+ end
+ end
+
describe 'Operations > Tracing' do
context 'with project.tracing_external_url' do
it 'links to project.tracing_external_url' do
- render template: 'projects/settings/operations/show', locals: operations_show_locals
+ render
expect(rendered).to have_link('Tracing', href: tracing_setting.external_url)
end
@@ -66,7 +93,7 @@ RSpec.describe 'projects/settings/operations/show' do
end
it 'sanitizes external_url' do
- render template: 'projects/settings/operations/show', locals: operations_show_locals
+ render
expect(tracing_setting.external_url).to eq(malicious_tracing_url)
expect(rendered).to have_link('Tracing', href: cleaned_url)
@@ -82,7 +109,7 @@ RSpec.describe 'projects/settings/operations/show' do
end
it 'links to Tracing page' do
- render template: 'projects/settings/operations/show', locals: operations_show_locals
+ render
expect(rendered).to have_link('Tracing', href: project_tracing_path(project))
end
diff --git a/spec/views/shared/wikis/_sidebar.html.haml_spec.rb b/spec/views/shared/wikis/_sidebar.html.haml_spec.rb
index 3e691862937..70991369506 100644
--- a/spec/views/shared/wikis/_sidebar.html.haml_spec.rb
+++ b/spec/views/shared/wikis/_sidebar.html.haml_spec.rb
@@ -80,4 +80,28 @@ RSpec.describe 'shared/wikis/_sidebar.html.haml' do
end
end
end
+
+ describe 'link to edit the sidebar' do
+ before do
+ allow(view).to receive(:can?).with(anything, :create_wiki, anything).and_return(can_edit)
+
+ render
+ end
+
+ context 'when the user has edit permission' do
+ let(:can_edit) { true }
+
+ it 'renders the link' do
+ expect(rendered).to have_link('Edit sidebar', href: wiki_page_path(wiki, Wiki::SIDEBAR, action: :edit))
+ end
+ end
+
+ context 'when the user does not have edit permission' do
+ let(:can_edit) { false }
+
+ it 'does not render the link' do
+ expect(rendered).not_to have_link('Edit sidebar')
+ end
+ end
+ end
end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index 12783f40528..d3a4144d606 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -4,13 +4,74 @@ require 'spec_helper'
RSpec.describe BulkImportWorker do
describe '#perform' do
- it 'executes Group Importer' do
- bulk_import_id = 1
+ before do
+ stub_const("#{described_class}::DEFAULT_BATCH_SIZE", 1)
+ end
+
+ context 'when no bulk import is found' do
+ it 'does nothing' do
+ expect(described_class).not_to receive(:perform_in)
+
+ subject.perform(non_existing_record_id)
+ end
+ end
+
+ context 'when bulk import is finished' do
+ it 'does nothing' do
+ bulk_import = create(:bulk_import, :finished)
+
+ expect(described_class).not_to receive(:perform_in)
+
+ subject.perform(bulk_import.id)
+ end
+ end
+
+ context 'when all entities are processed' do
+ it 'marks bulk import as finished' do
+ bulk_import = create(:bulk_import, :started)
+ create(:bulk_import_entity, :finished, bulk_import: bulk_import)
+ create(:bulk_import_entity, :failed, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(bulk_import.reload.finished?).to eq(true)
+ end
+ end
+
+ context 'when maximum allowed number of import entities in progress' do
+ it 'reenqueues itself' do
+ bulk_import = create(:bulk_import, :started)
+ (described_class::DEFAULT_BATCH_SIZE + 1).times { |_| create(:bulk_import_entity, :started, bulk_import: bulk_import) }
+
+ expect(described_class).to receive(:perform_in).with(described_class::PERFORM_DELAY, bulk_import.id)
+
+ subject.perform(bulk_import.id)
+ end
+ end
+
+ context 'when bulk import is created' do
+ it 'marks bulk import as started' do
+ bulk_import = create(:bulk_import, :created)
+ create(:bulk_import_entity, :created, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(bulk_import.reload.started?).to eq(true)
+ end
+
+ context 'when there are created entities to process' do
+ it 'marks a batch of entities as started, enqueues BulkImports::EntityWorker and reenqueues' do
+ bulk_import = create(:bulk_import, :created)
+ (described_class::DEFAULT_BATCH_SIZE + 1).times { |_| create(:bulk_import_entity, :created, bulk_import: bulk_import) }
+
+ expect(described_class).to receive(:perform_in).with(described_class::PERFORM_DELAY, bulk_import.id)
+ expect(BulkImports::EntityWorker).to receive(:perform_async)
- expect(BulkImports::Importers::GroupsImporter)
- .to receive(:new).with(bulk_import_id).and_return(double(execute: true))
+ subject.perform(bulk_import.id)
- described_class.new.perform(bulk_import_id)
+ expect(bulk_import.entities.map(&:status_name)).to contain_exactly(:created, :started)
+ 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
new file mode 100644
index 00000000000..31515b31947
--- /dev/null
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::EntityWorker do
+ describe '#execute' do
+ let(:bulk_import) { create(:bulk_import) }
+
+ context 'when started entity exists' do
+ let(:entity) { create(:bulk_import_entity, :started, bulk_import: bulk_import) }
+
+ it 'executes BulkImports::Importers::GroupImporter' do
+ expect(BulkImports::Importers::GroupImporter).to receive(:new).with(entity).and_call_original
+
+ subject.perform(entity.id)
+ end
+
+ it 'sets jid' do
+ jid = 'jid'
+
+ allow(subject).to receive(:jid).and_return(jid)
+
+ subject.perform(entity.id)
+
+ expect(entity.reload.jid).to eq(jid)
+ end
+ end
+
+ context 'when started entity does not exist' do
+ it 'does not execute BulkImports::Importers::GroupImporter' do
+ entity = create(:bulk_import_entity, bulk_import: bulk_import)
+
+ expect(BulkImports::Importers::GroupImporter).not_to receive(:new)
+
+ subject.perform(entity.id)
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/pipeline_artifacts/coverage_report_worker_spec.rb b/spec/workers/ci/pipeline_artifacts/coverage_report_worker_spec.rb
new file mode 100644
index 00000000000..000eda055af
--- /dev/null
+++ b/spec/workers/ci/pipeline_artifacts/coverage_report_worker_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::PipelineArtifacts::CoverageReportWorker do
+ describe '#perform' do
+ subject { described_class.new.perform(pipeline_id) }
+
+ context 'when pipeline exists' do
+ let(:pipeline) { create(:ci_pipeline) }
+ let(:pipeline_id) { pipeline.id }
+
+ it 'calls pipeline report result service' do
+ expect_next_instance_of(::Ci::PipelineArtifacts::CoverageReportService) do |create_artifact_service|
+ expect(create_artifact_service).to receive(:execute)
+ end
+
+ subject
+ end
+ end
+
+ context 'when pipeline does not exist' do
+ let(:pipeline_id) { non_existing_record_id }
+
+ it 'does not call pipeline create artifact service' do
+ expect(Ci::PipelineArtifacts::CoverageReportService).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
new file mode 100644
index 00000000000..9e9aa962b63
--- /dev/null
+++ b/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineArtifacts::ExpireArtifactsWorker do
+ let(:worker) { described_class.new }
+
+ describe '#perform' do
+ let_it_be(:pipeline_artifact) do
+ create(:ci_pipeline_artifact, expire_at: 1.week.ago)
+ end
+
+ it 'executes a service' do
+ expect_next_instance_of(::Ci::PipelineArtifacts::DestroyExpiredArtifactsService) do |instance|
+ expect(instance).to receive(:execute)
+ end
+
+ worker.perform
+ end
+
+ include_examples 'an idempotent worker' do
+ subject do
+ perform_multiple(worker: worker)
+ end
+
+ it 'removes the artifact only once' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:destroyed_pipeline_artifacts_count, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:destroyed_pipeline_artifacts_count, 0)
+
+ subject
+
+ expect { pipeline_artifact.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/pipelines/create_artifact_worker_spec.rb b/spec/workers/ci/pipelines/create_artifact_worker_spec.rb
deleted file mode 100644
index 31d2c4e9559..00000000000
--- a/spec/workers/ci/pipelines/create_artifact_worker_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Ci::Pipelines::CreateArtifactWorker do
- describe '#perform' do
- subject { described_class.new.perform(pipeline_id) }
-
- context 'when pipeline exists' do
- let(:pipeline) { create(:ci_pipeline) }
- let(:pipeline_id) { pipeline.id }
-
- it 'calls pipeline report result service' do
- expect_next_instance_of(::Ci::Pipelines::CreateArtifactService) do |create_artifact_service|
- expect(create_artifact_service).to receive(:execute)
- end
-
- subject
- end
- end
-
- context 'when pipeline does not exist' do
- let(:pipeline_id) { non_existing_record_id }
-
- it 'does not call pipeline create artifact service' do
- expect(Ci::Pipelines::CreateArtifactService).not_to receive(:execute)
-
- subject
- end
- end
- end
-end
diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
index d98ea1b6ab2..e6592f7f204 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
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:repository, reload: true) { create(:container_repository, :cleanup_scheduled) }
let_it_be(:project) { repository.project }
let_it_be(:policy) { project.container_expiration_policy }
@@ -19,23 +21,55 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
RSpec.shared_examples 'handling all repository conditions' do
it 'sends the repository for cleaning' do
+ service_response = cleanup_service_response(repository: repository)
expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(repository: repository)))
- expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :finished)
- expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response)
subject
end
context 'with unfinished cleanup' do
it 'logs an unfinished cleanup' do
+ service_response = cleanup_service_response(status: :unfinished, repository: repository)
expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(status: :unfinished, repository: repository)))
- expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :unfinished)
- expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished)
subject
end
+
+ context 'with a truncated list of tags to delete' do
+ it 'logs an unfinished cleanup' do
+ service_response = cleanup_service_response(status: :unfinished, repository: repository, cleanup_tags_service_after_truncate_size: 10, cleanup_tags_service_before_delete_size: 5)
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished, truncated: true)
+
+ subject
+ end
+ end
+
+ context 'the truncated log field' do
+ where(:before_truncate_size, :after_truncate_size, :truncated) do
+ 100 | 100 | false
+ 100 | 80 | true
+ nil | 100 | false
+ 100 | nil | false
+ nil | nil | false
+ end
+
+ with_them do
+ it 'is logged properly' do
+ service_response = cleanup_service_response(status: :unfinished, repository: repository, cleanup_tags_service_after_truncate_size: after_truncate_size, cleanup_tags_service_before_truncate_size: before_truncate_size)
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished, truncated: truncated)
+
+ subject
+ end
+ end
+ end
end
context 'with policy running shortly' do
@@ -87,10 +121,10 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
let_it_be(:another_repository) { create(:container_repository, :cleanup_unfinished) }
it 'process the cleanup scheduled repository first' do
+ service_response = cleanup_service_response(repository: repository)
expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(repository: repository)))
- expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :finished)
- expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response)
subject
end
@@ -105,10 +139,10 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end
it 'process the repository with the oldest expiration_policy_started_at' do
+ service_response = cleanup_service_response(repository: repository)
expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: cleanup_service_response(repository: repository)))
- expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :finished)
- expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response)
subject
end
@@ -164,8 +198,28 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end
end
- def cleanup_service_response(status: :finished, repository:)
- ServiceResponse.success(message: "cleanup #{status}", payload: { cleanup_status: status, container_repository_id: repository.id })
+ 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)
+ ServiceResponse.success(
+ message: "cleanup #{status}",
+ payload: {
+ cleanup_status: status,
+ container_repository_id: repository.id,
+ cleanup_tags_service_original_size: cleanup_tags_service_original_size,
+ cleanup_tags_service_before_truncate_size: cleanup_tags_service_before_truncate_size,
+ cleanup_tags_service_after_truncate_size: cleanup_tags_service_after_truncate_size,
+ cleanup_tags_service_before_delete_size: cleanup_tags_service_before_delete_size
+ }.compact
+ )
+ 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|
+ 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)
end
end
diff --git a/spec/workers/experiments/record_conversion_event_worker_spec.rb b/spec/workers/experiments/record_conversion_event_worker_spec.rb
new file mode 100644
index 00000000000..05e4ebc13ba
--- /dev/null
+++ b/spec/workers/experiments/record_conversion_event_worker_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Experiments::RecordConversionEventWorker, '#perform' do
+ subject(:perform) { described_class.new.perform(:experiment_key, 1234) }
+
+ before do
+ stub_experiment(experiment_key: experiment_active)
+ end
+
+ context 'when the experiment is active' do
+ let(:experiment_active) { true }
+
+ include_examples 'an idempotent worker' do
+ subject { perform }
+
+ it 'records the event' do
+ expect(Experiment).to receive(:record_conversion_event).with(:experiment_key, 1234)
+
+ perform
+ end
+ end
+ end
+
+ context 'when the experiment is not active' do
+ let(:experiment_active) { false }
+
+ it 'records the event' do
+ expect(Experiment).not_to receive(:record_conversion_event)
+
+ perform
+ end
+ end
+end
diff --git a/spec/workers/expire_build_artifacts_worker_spec.rb b/spec/workers/expire_build_artifacts_worker_spec.rb
index 995f37daf17..6d73d715d21 100644
--- a/spec/workers/expire_build_artifacts_worker_spec.rb
+++ b/spec/workers/expire_build_artifacts_worker_spec.rb
@@ -8,9 +8,11 @@ RSpec.describe ExpireBuildArtifactsWorker do
describe '#perform' do
it 'executes a service' do
expect_next_instance_of(Ci::DestroyExpiredJobArtifactsService) do |instance|
- expect(instance).to receive(:execute)
+ expect(instance).to receive(:execute).and_call_original
end
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:destroyed_job_artifacts_count, 0)
+
worker.perform
end
end
diff --git a/spec/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker_spec.rb
index 7acf1a338d3..75d4d2dff2e 100644
--- a/spec/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker_spec.rb
@@ -9,23 +9,7 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportPullRequestsReviewsWorker do
let(:client) { double(:client) }
describe '#import' do
- it 'does not import with the feature disabled' do
- stub_feature_flags(github_import_pull_request_reviews: false)
-
- expect(Gitlab::JobWaiter)
- .to receive(:new)
- .and_return(double(key: '123', jobs_remaining: 0))
-
- expect(Gitlab::GithubImport::AdvanceStageWorker)
- .to receive(:perform_async)
- .with(project.id, { '123' => 0 }, :issues_and_diff_notes)
-
- worker.import(client, project)
- end
-
it 'imports all the pull request reviews' do
- stub_feature_flags(github_import_pull_request_reviews: true)
-
importer = double(:importer)
waiter = Gitlab::JobWaiter.new(2, '123')
diff --git a/spec/workers/gitlab_performance_bar_stats_worker_spec.rb b/spec/workers/gitlab_performance_bar_stats_worker_spec.rb
index 367003dd1ad..3638add1524 100644
--- a/spec/workers/gitlab_performance_bar_stats_worker_spec.rb
+++ b/spec/workers/gitlab_performance_bar_stats_worker_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe GitlabPerformanceBarStatsWorker do
let(:uuid) { 1 }
before do
- expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
+ expect(Gitlab::Redis::Cache).to receive(:with).and_yield(redis)
expect_to_cancel_exclusive_lease(GitlabPerformanceBarStatsWorker::LEASE_KEY, uuid)
end
diff --git a/spec/workers/group_destroy_worker_spec.rb b/spec/workers/group_destroy_worker_spec.rb
index ab3dd19dec1..82ae9010a24 100644
--- a/spec/workers/group_destroy_worker_spec.rb
+++ b/spec/workers/group_destroy_worker_spec.rb
@@ -4,8 +4,12 @@ require 'spec_helper'
RSpec.describe GroupDestroyWorker do
let(:group) { create(:group) }
- let(:user) { create(:admin) }
let!(:project) { create(:project, namespace: group) }
+ let(:user) { create(:user) }
+
+ before do
+ group.add_owner(user)
+ end
subject { described_class.new }
diff --git a/spec/workers/jira_connect/sync_branch_worker_spec.rb b/spec/workers/jira_connect/sync_branch_worker_spec.rb
index c8453064b0d..7c715f36fb4 100644
--- a/spec/workers/jira_connect/sync_branch_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_branch_worker_spec.rb
@@ -13,82 +13,67 @@ RSpec.describe JiraConnect::SyncBranchWorker do
let(:project_id) { project.id }
let(:branch_name) { 'master' }
let(:commit_shas) { %w(b83d6e3 5a62481) }
-
- subject { described_class.new.perform(project_id, branch_name, commit_shas) }
+ let(:update_sequence_id) { 1 }
def expect_jira_sync_service_execute(args)
- expect_next_instance_of(JiraConnect::SyncService) do |instance|
- expect(instance).to receive(:execute).with(args.merge(update_sequence_id: nil))
+ expect_next_instances_of(JiraConnect::SyncService, IdempotentWorkerHelper::WORKER_EXEC_TIMES) do |instance|
+ expect(instance).to receive(:execute).with(args)
end
end
- it 'calls JiraConnect::SyncService#execute' do
- expect_jira_sync_service_execute(
- branches: [instance_of(Gitlab::Git::Branch)],
- commits: project.commits_by(oids: commit_shas)
- )
-
- subject
- end
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [project_id, branch_name, commit_shas, update_sequence_id] }
- context 'without branch name' do
- let(:branch_name) { nil }
-
- it 'calls JiraConnect::SyncService#execute' do
- expect_jira_sync_service_execute(
- branches: nil,
- commits: project.commits_by(oids: commit_shas)
- )
-
- subject
+ before do
+ stub_request(:post, 'https://sample.atlassian.net/rest/devinfo/0.10/bulk').to_return(status: 200, body: '', headers: {})
end
- end
-
- context 'without commits' do
- let(:commit_shas) { nil }
it 'calls JiraConnect::SyncService#execute' do
expect_jira_sync_service_execute(
branches: [instance_of(Gitlab::Git::Branch)],
- commits: nil
+ commits: project.commits_by(oids: commit_shas),
+ update_sequence_id: update_sequence_id
)
subject
end
- end
- context 'when project no longer exists' do
- let(:project_id) { non_existing_record_id }
+ context 'without branch name' do
+ let(:branch_name) { nil }
- it 'does not call JiraConnect::SyncService' do
- expect(JiraConnect::SyncService).not_to receive(:new)
+ it 'calls JiraConnect::SyncService#execute' do
+ expect_jira_sync_service_execute(
+ branches: nil,
+ commits: project.commits_by(oids: commit_shas),
+ update_sequence_id: update_sequence_id
+ )
- subject
+ subject
+ end
end
- end
- context 'with update_sequence_id' do
- let(:update_sequence_id) { 1 }
- let(:request_path) { '/rest/devinfo/0.10/bulk' }
- let(:request_body) do
- {
- repositories: [
- Atlassian::JiraConnect::Serializers::RepositoryEntity.represent(
- project,
- commits: project.commits_by(oids: commit_shas),
- branches: [project.repository.find_branch(branch_name)],
- update_sequence_id: update_sequence_id
- )
- ]
- }
+ context 'without commits' do
+ let(:commit_shas) { nil }
+
+ it 'calls JiraConnect::SyncService#execute' do
+ expect_jira_sync_service_execute(
+ branches: [instance_of(Gitlab::Git::Branch)],
+ commits: nil,
+ update_sequence_id: update_sequence_id
+ )
+
+ subject
+ end
end
- subject { described_class.new.perform(project_id, branch_name, commit_shas, update_sequence_id) }
+ context 'when project no longer exists' do
+ let(:project_id) { non_existing_record_id }
- it 'sends the reqeust with custom update_sequence_id' do
- expect_next(Atlassian::JiraConnect::Client).to receive(:post).with(request_path, request_body)
+ it 'does not call JiraConnect::SyncService' do
+ expect(JiraConnect::SyncService).not_to receive(:new)
- subject
+ 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
new file mode 100644
index 00000000000..9485f4cd3a7
--- /dev/null
+++ b/spec/workers/jira_connect/sync_deployments_worker_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::JiraConnect::SyncDeploymentsWorker do
+ include AfterNextHelpers
+ include ServicesHelper
+
+ describe '#perform' do
+ let_it_be(:deployment) { create(:deployment) }
+
+ let(:sequence_id) { Random.random_number(1..10_000) }
+ let(:object_id) { deployment.id }
+
+ subject { described_class.new.perform(object_id, sequence_id) }
+
+ context 'when the object exists' do
+ it 'calls the Jira sync service' do
+ expect_next(::JiraConnect::SyncService, deployment.project)
+ .to receive(:execute).with(deployments: contain_exactly(deployment), update_sequence_id: sequence_id)
+
+ subject
+ end
+ end
+
+ context 'when the object does not exist' do
+ let(:object_id) { non_existing_record_id }
+
+ 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 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
new file mode 100644
index 00000000000..035f4ebdd3c
--- /dev/null
+++ b/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::JiraConnect::SyncFeatureFlagsWorker do
+ include AfterNextHelpers
+ include ServicesHelper
+
+ describe '#perform' do
+ let_it_be(:feature_flag) { create(:operations_feature_flag) }
+
+ let(:sequence_id) { Random.random_number(1..10_000) }
+ let(:feature_flag_id) { feature_flag.id }
+
+ subject { described_class.new.perform(feature_flag_id, sequence_id) }
+
+ context 'when object exists' do
+ it 'calls the Jira sync service' do
+ expect_next(::JiraConnect::SyncService, feature_flag.project)
+ .to receive(:execute).with(feature_flags: contain_exactly(feature_flag), update_sequence_id: sequence_id)
+
+ subject
+ end
+ end
+
+ context 'when object does not exist' do
+ let(:feature_flag_id) { non_existing_record_id }
+
+ 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 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/jira_connect/sync_merge_request_worker_spec.rb b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
index 1a40aa2b3ad..6a0a0744f6f 100644
--- a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
@@ -12,48 +12,31 @@ RSpec.describe JiraConnect::SyncMergeRequestWorker do
let_it_be(:merge_request) { create(:merge_request, source_project: project) }
let(:merge_request_id) { merge_request.id }
+ let(:update_sequence_id) { 1 }
- subject { described_class.new.perform(merge_request_id) }
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [merge_request_id, update_sequence_id] }
- it 'calls JiraConnect::SyncService#execute' do
- expect_next_instance_of(JiraConnect::SyncService) do |service|
- expect(service).to receive(:execute).with(merge_requests: [merge_request], update_sequence_id: nil)
+ before do
+ stub_request(:post, 'https://sample.atlassian.net/rest/devinfo/0.10/bulk').to_return(status: 200, body: '', headers: {})
end
- subject
- end
-
- context 'when MR no longer exists' do
- let(:merge_request_id) { non_existing_record_id }
-
- it 'does not call JiraConnect::SyncService' do
- expect(JiraConnect::SyncService).not_to receive(:new)
+ it 'calls JiraConnect::SyncService#execute' do
+ expect_next_instances_of(JiraConnect::SyncService, IdempotentWorkerHelper::WORKER_EXEC_TIMES) do |service|
+ expect(service).to receive(:execute).with(merge_requests: [merge_request], update_sequence_id: update_sequence_id)
+ end
subject
end
- end
- context 'with update_sequence_id' do
- let(:update_sequence_id) { 1 }
- let(:request_path) { '/rest/devinfo/0.10/bulk' }
- let(:request_body) do
- {
- repositories: [
- Atlassian::JiraConnect::Serializers::RepositoryEntity.represent(
- project,
- merge_requests: [merge_request],
- update_sequence_id: update_sequence_id
- )
- ]
- }
- end
-
- subject { described_class.new.perform(merge_request_id, update_sequence_id) }
+ context 'when MR no longer exists' do
+ let(:merge_request_id) { non_existing_record_id }
- it 'sends the request with custom update_sequence_id' do
- expect_next(Atlassian::JiraConnect::Client).to receive(:post).with(request_path, request_body)
+ it 'does not call JiraConnect::SyncService' do
+ expect(JiraConnect::SyncService).not_to receive(:new)
- subject
+ subject
+ end
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
new file mode 100644
index 00000000000..f1789fa8fbd
--- /dev/null
+++ b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+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
+
+ subject.perform(ci_pipeline.project.namespace_id)
+
+ expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(true)
+ 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
+ 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 03c668259f8..a773e160fab 100644
--- a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
+++ b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
@@ -7,10 +7,16 @@ RSpec.describe Namespaces::OnboardingUserAddedWorker, '#perform' do
let_it_be(:group) { create(:group) }
- it 'records the event' do
+ 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
- expect { subject.perform(group.id) }.to change(NamespaceOnboardingAction, :count).by(1)
+ subject.perform(group.id)
+
+ expect(OnboardingProgress.completed?(group, :user_added)).to be(true)
end
end
diff --git a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
index aadfae51906..fb762593d75 100644
--- a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
+++ b/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
@@ -3,31 +3,10 @@
require 'spec_helper'
RSpec.describe ProjectScheduleBulkRepositoryShardMovesWorker do
- describe "#perform" do
- before do
- stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
+ it_behaves_like 'schedules bulk repository shard moves' do
+ let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
- allow(ProjectUpdateRepositoryStorageWorker).to receive(:perform_async)
- end
-
- let!(:project) { create(:project, :repository).tap { |project| project.track_project_repository } }
- let(:source_storage_name) { 'default' }
- let(:destination_storage_name) { 'test_second_storage' }
-
- include_examples 'an idempotent worker' do
- let(:job_args) { [source_storage_name, destination_storage_name] }
-
- it 'schedules project repository storage moves' do
- expect { subject }.to change(ProjectRepositoryStorageMove, :count).by(1)
-
- storage_move = project.repository_storage_moves.last!
-
- expect(storage_move).to have_attributes(
- source_storage_name: source_storage_name,
- destination_storage_name: destination_storage_name,
- state_name: :scheduled
- )
- end
- end
+ let(:move_service_klass) { ProjectRepositoryStorageMove }
+ let(:worker_klass) { ProjectUpdateRepositoryStorageWorker }
end
end
diff --git a/spec/workers/project_update_repository_storage_worker_spec.rb b/spec/workers/project_update_repository_storage_worker_spec.rb
index f75bb3d1642..490f1f5a2ad 100644
--- a/spec/workers/project_update_repository_storage_worker_spec.rb
+++ b/spec/workers/project_update_repository_storage_worker_spec.rb
@@ -3,45 +3,13 @@
require 'spec_helper'
RSpec.describe ProjectUpdateRepositoryStorageWorker do
- let(:project) { create(:project, :repository) }
-
subject { described_class.new }
- describe "#perform" do
- let(:service) { double(:update_repository_storage_service) }
-
- before do
- allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage])
- end
-
- context 'without repository storage move' do
- it "calls the update repository storage service" do
- expect(Projects::UpdateRepositoryStorageService).to receive(:new).and_return(service)
- expect(service).to receive(:execute)
-
- expect do
- subject.perform(project.id, 'test_second_storage')
- end.to change(ProjectRepositoryStorageMove, :count).by(1)
-
- storage_move = project.repository_storage_moves.last
- expect(storage_move).to have_attributes(
- source_storage_name: "default",
- destination_storage_name: "test_second_storage"
- )
- end
- end
-
- context 'with repository storage move' do
- let!(:repository_storage_move) { create(:project_repository_storage_move) }
-
- it "calls the update repository storage service" do
- expect(Projects::UpdateRepositoryStorageService).to receive(:new).and_return(service)
- expect(service).to receive(:execute)
+ it_behaves_like 'an update storage move worker' do
+ let_it_be_with_refind(:container) { create(:project, :repository) }
+ let_it_be(:repository_storage_move) { create(:project_repository_storage_move) }
- expect do
- subject.perform(nil, nil, repository_storage_move.id)
- end.not_to change(ProjectRepositoryStorageMove, :count)
- end
- end
+ let(:service_klass) { Projects::UpdateRepositoryStorageService }
+ let(:repository_storage_move_klass) { ProjectRepositoryStorageMove }
end
end
diff --git a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb
new file mode 100644
index 00000000000..3a09b6ce449
--- /dev/null
+++ b/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SnippetScheduleBulkRepositoryShardMovesWorker do
+ it_behaves_like 'schedules bulk repository shard moves' do
+ let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
+
+ let(:move_service_klass) { SnippetRepositoryStorageMove }
+ let(:worker_klass) { SnippetUpdateRepositoryStorageWorker }
+ end
+end
diff --git a/spec/workers/snippet_update_repository_storage_worker_spec.rb b/spec/workers/snippet_update_repository_storage_worker_spec.rb
new file mode 100644
index 00000000000..a48abe4abf7
--- /dev/null
+++ b/spec/workers/snippet_update_repository_storage_worker_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SnippetUpdateRepositoryStorageWorker do
+ subject { described_class.new }
+
+ it_behaves_like 'an update storage move worker' do
+ let_it_be_with_refind(:container) { create(:snippet, :repository) }
+ let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) }
+
+ let(:service_klass) { Snippets::UpdateRepositoryStorageService }
+ let(:repository_storage_move_klass) { SnippetRepositoryStorageMove }
+ end
+end
diff --git a/tmp/.gitignore b/tmp/.gitignore
index a383b23fb78..450053eb4f3 100644
--- a/tmp/.gitignore
+++ b/tmp/.gitignore
@@ -1,5 +1,10 @@
*
-!*/
!.gitignore
!.gitkeep
+
+# explicitly list ignored sub directories to speed up performance
+/cache/
+/capybara/
+/letter_opener/
+/rubocop_cache/
/tests/
diff --git a/tooling/lib/tooling/helm3_client.rb b/tooling/lib/tooling/helm3_client.rb
index d6671688794..3743138f27e 100644
--- a/tooling/lib/tooling/helm3_client.rb
+++ b/tooling/lib/tooling/helm3_client.rb
@@ -66,13 +66,15 @@ module Tooling
%(--output json),
*args
]
- releases = JSON.parse(run_command(command)) # rubocop:disable Gitlab/Json
+
+ response = run_command(command)
+ releases = JSON.parse(response) # rubocop:disable Gitlab/Json
releases.map do |release|
Release.new(*release.values_at(*RELEASE_JSON_ATTRIBUTES))
end
rescue ::JSON::ParserError => ex
- puts "Ignoring this JSON parsing error: #{ex}" # rubocop:disable Rails/Output
+ puts "Ignoring this JSON parsing error: #{ex}\n\nResponse was:\n#{response}" # rubocop:disable Rails/Output
[]
end
diff --git a/tooling/lib/tooling/kubernetes_client.rb b/tooling/lib/tooling/kubernetes_client.rb
index 14b96addf87..f7abc5ac4cf 100644
--- a/tooling/lib/tooling/kubernetes_client.rb
+++ b/tooling/lib/tooling/kubernetes_client.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
+require 'json'
+require 'time'
require_relative '../../../lib/gitlab/popen' unless defined?(Gitlab::Popen)
-require_relative '../../../lib/gitlab/json' unless defined?(Gitlab::JSON)
module Tooling
class KubernetesClient
@@ -14,11 +15,16 @@ module Tooling
@namespace = namespace
end
- def cleanup(release_name:, wait: true)
+ def cleanup_by_release(release_name:, wait: true)
delete_by_selector(release_name: release_name, wait: wait)
delete_by_matching_name(release_name: release_name)
end
+ def cleanup_by_created_at(resource_type:, created_before:, wait: true)
+ resource_names = resource_names_created_before(resource_type: resource_type, created_before: created_before)
+ delete_by_exact_names(resource_type: resource_type, resource_names: resource_names, wait: wait)
+ end
+
private
def delete_by_selector(release_name:, wait:)
@@ -45,6 +51,21 @@ module Tooling
run_command(command)
end
+ def delete_by_exact_names(resource_names:, wait:, resource_type: nil)
+ command = [
+ 'delete',
+ resource_type,
+ %(--namespace "#{namespace}"),
+ '--now',
+ '--ignore-not-found',
+ '--include-uninitialized',
+ %(--wait=#{wait}),
+ resource_names.join(' ')
+ ]
+
+ run_command(command)
+ end
+
def delete_by_matching_name(release_name:)
resource_names = raw_resource_names
command = [
@@ -70,8 +91,26 @@ module Tooling
run_command(command).lines.map(&:strip)
end
+ def resource_names_created_before(resource_type:, created_before:)
+ command = [
+ 'get',
+ resource_type,
+ %(--namespace "#{namespace}"),
+ "--sort-by='{.metadata.creationTimestamp}'",
+ '-o json'
+ ]
+
+ response = run_command(command)
+ JSON.parse(response)['items'] # rubocop:disable Gitlab/Json
+ .map { |resource| resource.dig('metadata', 'name') if Time.parse(resource.dig('metadata', 'creationTimestamp')) < created_before }
+ .compact
+ rescue ::JSON::ParserError => ex
+ puts "Ignoring this JSON parsing error: #{ex}\n\nResponse was:\n#{response}" # rubocop:disable Rails/Output
+ []
+ end
+
def run_command(command)
- final_command = ['kubectl', *command].join(' ')
+ final_command = ['kubectl', *command.compact].join(' ')
puts "Running command: `#{final_command}`" # rubocop:disable Rails/Output
result = Gitlab::Popen.popen_with_detail([final_command])
diff --git a/tooling/lib/tooling/test_file_finder.rb b/tooling/lib/tooling/test_file_finder.rb
deleted file mode 100644
index cf5de190c4a..00000000000
--- a/tooling/lib/tooling/test_file_finder.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-require 'set'
-
-module Tooling
- class TestFileFinder
- EE_PREFIX = 'ee/'
-
- def initialize(file, foss_test_only: false)
- @file = file
- @foss_test_only = foss_test_only
- end
-
- def test_files
- impacted_tests = ee_impact | non_ee_impact | either_impact
- impacted_tests.impact(@file)
- end
-
- private
-
- attr_reader :file, :foss_test_only, :result
-
- class ImpactedTestFile
- attr_reader :pattern_matchers
-
- def initialize(prefix: nil)
- @pattern_matchers = {}
- @prefix = prefix
-
- yield self if block_given?
- end
-
- def associate(pattern, &block)
- @pattern_matchers[%r{^#{@prefix}#{pattern}}] = block
- end
-
- def impact(file)
- @pattern_matchers.each_with_object(Set.new) do |(pattern, block), result|
- if (match = pattern.match(file))
- test_files = block.call(match)
- result.merge(Array(test_files))
- end
- end.to_a
- end
-
- def |(other)
- self.class.new do |combined_matcher|
- self.pattern_matchers.each do |pattern, block|
- combined_matcher.associate(pattern, &block)
- end
- other.pattern_matchers.each do |pattern, block|
- combined_matcher.associate(pattern, &block)
- end
- end
- end
- end
-
- def ee_impact
- ImpactedTestFile.new(prefix: EE_PREFIX) do |impact|
- unless foss_test_only
- impact.associate(%r{app/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/#{match[1]}_spec.rb" }
- impact.associate(%r{app/(.*/)ee/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/#{match[1]}#{match[2]}_spec.rb" }
- impact.associate(%r{lib/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/lib/#{match[1]}_spec.rb" }
- end
-
- impact.associate(%r{(?!spec)(.*/)ee/(.+)\.rb$}) { |match| "spec/#{match[1]}#{match[2]}_spec.rb" }
- impact.associate(%r{spec/(.*/)ee/(.+)\.rb$}) { |match| "spec/#{match[1]}#{match[2]}.rb" }
- end
- end
-
- def non_ee_impact
- ImpactedTestFile.new do |impact|
- impact.associate(%r{app/(.+)\.rb$}) { |match| "spec/#{match[1]}_spec.rb" }
- impact.associate(%r{(tooling/)?lib/(.+)\.rb$}) { |match| "spec/#{match[1]}lib/#{match[2]}_spec.rb" }
- impact.associate(%r{config/initializers/(.+)\.rb$}) { |match| "spec/initializers/#{match[1]}_spec.rb" }
- impact.associate('db/structure.sql') { 'spec/db/schema_spec.rb' }
- impact.associate(%r{db/(?:post_)?migrate/([0-9]+)_(.+)\.rb$}) do |match|
- [
- "spec/migrations/#{match[2]}_spec.rb",
- "spec/migrations/#{match[1]}_#{match[2]}_spec.rb"
- ]
- end
- end
- end
-
- def either_impact
- ImpactedTestFile.new(prefix: %r{^(?<prefix>#{EE_PREFIX})?}) do |impact|
- impact.associate(%r{app/views/(?<view>.+)\.haml$}) { |match| "#{match[:prefix]}spec/views/#{match[:view]}.haml_spec.rb" }
- impact.associate(%r{spec/(.+)_spec\.rb$}) { |match| match[0] }
- impact.associate(%r{spec/factories/.+\.rb$}) { 'spec/factories_spec.rb' }
- end
- end
- end
-end
diff --git a/tooling/overcommit/Gemfile b/tooling/overcommit/Gemfile
index 52e8dcaa497..6d2c5bce29a 100644
--- a/tooling/overcommit/Gemfile
+++ b/tooling/overcommit/Gemfile
@@ -4,6 +4,6 @@
source 'https://rubygems.org'
gem 'overcommit'
-gem 'gitlab-styles', '~> 5.3.0', require: false
+gem 'gitlab-styles', '~> 5.4.0', require: false
gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.34.0', require: false
diff --git a/tooling/overcommit/Gemfile.lock b/tooling/overcommit/Gemfile.lock
index b46229ac9f8..f1d701b3e4b 100644
--- a/tooling/overcommit/Gemfile.lock
+++ b/tooling/overcommit/Gemfile.lock
@@ -11,7 +11,7 @@ GEM
childprocess (3.0.0)
concurrent-ruby (1.1.7)
ffi (1.12.2)
- gitlab-styles (5.3.0)
+ gitlab-styles (5.4.0)
rubocop (~> 0.89.1)
rubocop-gitlab-security (~> 0.1.0)
rubocop-performance (~> 1.8.1)
@@ -88,7 +88,7 @@ PLATFORMS
ruby
DEPENDENCIES
- gitlab-styles (~> 5.3.0)
+ gitlab-styles (~> 5.4.0)
haml_lint (~> 0.34.0)
overcommit
scss_lint (~> 0.56.0)
diff --git a/vendor/assets/javascripts/jquery.scrollTo.js b/vendor/assets/javascripts/jquery.scrollTo.js
deleted file mode 100644
index 7ba17766b70..00000000000
--- a/vendor/assets/javascripts/jquery.scrollTo.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/*!
- * jQuery.scrollTo
- * Copyright (c) 2007-2015 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
- * Licensed under MIT
- * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
- * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery
- * @author Ariel Flesler
- * @version 2.1.2
- */
-;(function(factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- // AMD
- define(['jquery'], factory);
- } else if (typeof module !== 'undefined' && module.exports) {
- // CommonJS
- module.exports = factory(require('jquery'));
- } else {
- // Global
- factory(jQuery);
- }
-})(function($) {
- 'use strict';
-
- var $scrollTo = $.scrollTo = function(target, duration, settings) {
- return $(window).scrollTo(target, duration, settings);
- };
-
- $scrollTo.defaults = {
- axis:'xy',
- duration: 0,
- limit:true
- };
-
- function isWin(elem) {
- return !elem.nodeName ||
- $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;
- }
-
- $.fn.scrollTo = function(target, duration, settings) {
- if (typeof duration === 'object') {
- settings = duration;
- duration = 0;
- }
- if (typeof settings === 'function') {
- settings = { onAfter:settings };
- }
- if (target === 'max') {
- target = 9e9;
- }
-
- settings = $.extend({}, $scrollTo.defaults, settings);
- // Speed is still recognized for backwards compatibility
- duration = duration || settings.duration;
- // Make sure the settings are given right
- var queue = settings.queue && settings.axis.length > 1;
- if (queue) {
- // Let's keep the overall duration
- duration /= 2;
- }
- settings.offset = both(settings.offset);
- settings.over = both(settings.over);
-
- return this.each(function() {
- // Null target yields nothing, just like jQuery does
- if (target === null) return;
-
- var win = isWin(this),
- elem = win ? this.contentWindow || window : this,
- $elem = $(elem),
- targ = target,
- attr = {},
- toff;
-
- switch (typeof targ) {
- // A number will pass the regex
- case 'number':
- case 'string':
- if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {
- targ = both(targ);
- // We are done
- break;
- }
- // Relative/Absolute selector
- targ = win ? $(targ) : $(targ, elem);
- /* falls through */
- case 'object':
- if (targ.length === 0) return;
- // DOMElement / jQuery
- if (targ.is || targ.style) {
- // Get the real position of the target
- toff = (targ = $(targ)).offset();
- }
- }
-
- var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;
-
- $.each(settings.axis.split(''), function(i, axis) {
- var Pos = axis === 'x' ? 'Left' : 'Top',
- pos = Pos.toLowerCase(),
- key = 'scroll' + Pos,
- prev = $elem[key](),
- max = $scrollTo.max(elem, axis);
-
- if (toff) {// jQuery / DOMElement
- attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);
-
- // If it's a dom element, reduce the margin
- if (settings.margin) {
- attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;
- attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;
- }
-
- attr[key] += offset[pos] || 0;
-
- if (settings.over[pos]) {
- // Scroll to a fraction of its width/height
- attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];
- }
- } else {
- var val = targ[pos];
- // Handle percentage values
- attr[key] = val.slice && val.slice(-1) === '%' ?
- parseFloat(val) / 100 * max
- : val;
- }
-
- // Number or 'number'
- if (settings.limit && /^\d+$/.test(attr[key])) {
- // Check the limits
- attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);
- }
-
- // Don't waste time animating, if there's no need.
- if (!i && settings.axis.length > 1) {
- if (prev === attr[key]) {
- // No animation needed
- attr = {};
- } else if (queue) {
- // Intermediate animation
- animate(settings.onAfterFirst);
- // Don't animate this axis again in the next iteration.
- attr = {};
- }
- }
- });
-
- animate(settings.onAfter);
-
- function animate(callback) {
- var opts = $.extend({}, settings, {
- // The queue setting conflicts with animate()
- // Force it to always be true
- queue: true,
- duration: duration,
- complete: callback && function() {
- callback.call(elem, targ, settings);
- }
- });
- $elem.animate(attr, opts);
- }
- });
- };
-
- // Max scrolling position, works on quirks mode
- // It only fails (not too badly) on IE, quirks mode.
- $scrollTo.max = function(elem, axis) {
- var Dim = axis === 'x' ? 'Width' : 'Height',
- scroll = 'scroll'+Dim;
-
- if (!isWin(elem))
- return elem[scroll] - $(elem)[Dim.toLowerCase()]();
-
- var size = 'client' + Dim,
- doc = elem.ownerDocument || elem.document,
- html = doc.documentElement,
- body = doc.body;
-
- return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);
- };
-
- function both(val) {
- return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };
- }
-
- // Add special hooks so that window scroll properties can be animated
- $.Tween.propHooks.scrollLeft =
- $.Tween.propHooks.scrollTop = {
- get: function(t) {
- return $(t.elem)[t.prop]();
- },
- set: function(t) {
- var curr = this.get(t);
- // If interrupt is true and user scrolled, stop animating
- if (t.options.interrupt && t._last && t._last !== curr) {
- return $(t.elem).stop();
- }
- var next = Math.round(t.now);
- // Don't waste CPU
- // Browsers don't render floating point scroll
- if (curr !== next) {
- $(t.elem)[t.prop](next);
- t._last = this.get(t);
- }
- }
- };
-
- // AMD requirement
- return $scrollTo;
-});
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 259148fa18f..259148fa18f 100755..100644
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
diff --git a/vendor/gitignore/Clojure.gitignore b/vendor/gitignore/Clojure.gitignore
index 7657a270c45..a4cb69a32cc 120000..100644
--- a/vendor/gitignore/Clojure.gitignore
+++ b/vendor/gitignore/Clojure.gitignore
@@ -1 +1,14 @@
-Leiningen.gitignore \ No newline at end of file
+pom.xml
+pom.xml.asc
+*.jar
+*.class
+/lib/
+/classes/
+/target/
+/checkouts/
+.lein-deps-sum
+.lein-repl-history
+.lein-plugins/
+.lein-failures
+.nrepl-port
+.cpcache/
diff --git a/vendor/gitignore/Fortran.gitignore b/vendor/gitignore/Fortran.gitignore
index 5daba98a3e6..259148fa18f 120000..100644
--- a/vendor/gitignore/Fortran.gitignore
+++ b/vendor/gitignore/Fortran.gitignore
@@ -1 +1,32 @@
-C++.gitignore \ No newline at end of file
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
diff --git a/vendor/gitignore/Java.gitignore b/vendor/gitignore/Java.gitignore
index a1c2a238a96..a1c2a238a96 100755..100644
--- a/vendor/gitignore/Java.gitignore
+++ b/vendor/gitignore/Java.gitignore
diff --git a/vendor/gitignore/Kotlin.gitignore b/vendor/gitignore/Kotlin.gitignore
index c48376eebcf..a1c2a238a96 120000..100644
--- a/vendor/gitignore/Kotlin.gitignore
+++ b/vendor/gitignore/Kotlin.gitignore
@@ -1 +1,23 @@
-Java.gitignore \ No newline at end of file
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
diff --git a/vendor/project_templates/dotnetcore.tar.gz b/vendor/project_templates/dotnetcore.tar.gz
index 078ea91bbe4..402153aa88d 100644
--- a/vendor/project_templates/dotnetcore.tar.gz
+++ b/vendor/project_templates/dotnetcore.tar.gz
Binary files differ
diff --git a/vendor/project_templates/express.tar.gz b/vendor/project_templates/express.tar.gz
index 619e8a69695..f9a52fde41b 100644
--- a/vendor/project_templates/express.tar.gz
+++ b/vendor/project_templates/express.tar.gz
Binary files differ
diff --git a/vendor/project_templates/rails.tar.gz b/vendor/project_templates/rails.tar.gz
index 6bb51bcd7a1..5ead9bd8459 100644
--- a/vendor/project_templates/rails.tar.gz
+++ b/vendor/project_templates/rails.tar.gz
Binary files differ
diff --git a/workhorse/.gitlab-ci.yml b/workhorse/.gitlab-ci.yml
index b3377c894e0..69f25fde968 100644
--- a/workhorse/.gitlab-ci.yml
+++ b/workhorse/.gitlab-ci.yml
@@ -49,6 +49,10 @@ test using go 1.14:
extends: .test
image: golang:1.14
+test using go 1.15:
+ extends: .test
+ image: golang:1.15
+
test:release:
rules:
- if: '$CI_COMMIT_TAG'
diff --git a/workhorse/CHANGELOG b/workhorse/CHANGELOG
index 271928845c1..42c13465ba9 100644
--- a/workhorse/CHANGELOG
+++ b/workhorse/CHANGELOG
@@ -1,12 +1,14 @@
# Changelog for gitlab-workhorse
-## v8.58.2
+## v8.59.0
-### Security
-- Allow DELETE HTTP method
- https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/
+### Fixed
+- Image scaling: strip out iCCP chunks in PNG files
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/673
-## v8.58.1
+### Other
+- Extract logging concerns into a separate module
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/
### Security
- Reject unknown http methods
diff --git a/workhorse/Makefile b/workhorse/Makefile
index 7a8503512df..5661468149b 100644
--- a/workhorse/Makefile
+++ b/workhorse/Makefile
@@ -22,8 +22,6 @@ export PATH := $(GOBIN):$(PATH)
export GOPROXY ?= https://proxy.golang.org
export GO111MODULE=on
-LOCAL_GO_FILES = $(shell find . -type f -name '*.go' | grep -v -e /_ -e /testdata/ -e '^\./\.')
-
define message
@echo "### $(1)"
endef
@@ -40,19 +38,23 @@ $(TARGET_SETUP):
mkdir -p "$(TARGET_DIR)"
touch "$(TARGET_SETUP)"
-gitlab-resize-image: $(TARGET_SETUP) $(shell find cmd/gitlab-resize-image/ -name '*.go')
+.PHONY: gitlab-resize-image
+gitlab-resize-image: $(TARGET_SETUP)
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
-gitlab-zip-cat: $(TARGET_SETUP) $(shell find cmd/gitlab-zip-cat/ -name '*.go')
+.PHONY: gitlab-zip-cat
+gitlab-zip-cat: $(TARGET_SETUP)
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
-gitlab-zip-metadata: $(TARGET_SETUP) $(shell find cmd/gitlab-zip-metadata/ -name '*.go')
+.PHONY: gitlab-zip-metadata
+gitlab-zip-metadata: $(TARGET_SETUP)
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
-gitlab-workhorse: $(TARGET_SETUP) $(shell find . -name '*.go' | grep -v '^\./_')
+.PHONY: gitlab-workhorse
+gitlab-workhorse: $(TARGET_SETUP)
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
@@ -142,7 +144,7 @@ detect-assert:
.PHONY: check-formatting
check-formatting: $(TARGET_SETUP) install-goimports
$(call message,Verify: $@)
- @_support/validate-formatting.sh $(LOCAL_GO_FILES)
+ @_support/fmt.sh check
# Megacheck will tailor some responses given a minimum Go version, so pass that through the CLI
# Additionally, megacheck will not return failure exit codes unless explicitly told to via the
@@ -158,7 +160,7 @@ staticcheck: $(TARGET_SETUP)
.PHONY: fmt
fmt: $(TARGET_SETUP) install-goimports
$(call message,$@)
- @goimports -w -local $(PKG) -l $(LOCAL_GO_FILES)
+ @_support/fmt.sh
.PHONY: goimports
install-goimports: $(TARGET_SETUP)
diff --git a/workhorse/PROCESS.md b/workhorse/PROCESS.md
index 07f553dd387..797de59d47e 100644
--- a/workhorse/PROCESS.md
+++ b/workhorse/PROCESS.md
@@ -42,6 +42,7 @@ maintainers. The release process is:
- the new version will only be deployed to `gitlab.com` if [`GITLAB_WORKHORSE_VERSION`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_WORKHORSE_VERSION) is updated accordingly;
if applicable, please remind the person who originally asked for a new release to make this change
(the MR should include a link back to the [version tag](https://gitlab.com/gitlab-org/gitlab-workhorse/-/tags) and a copy of the changelog)
+- the person who updates GITLAB_WORKHORSE_VERSION should also run `scripts/update-workhorse` after commiting the new GITLAB_WORKHORSE_VERSION. If they forget they will be reminded by CI.
## Security releases
diff --git a/workhorse/VERSION b/workhorse/VERSION
index 8aa8b5f68bd..8c20f999400 100644
--- a/workhorse/VERSION
+++ b/workhorse/VERSION
@@ -1 +1 @@
-8.58.2
+8.59.0
diff --git a/workhorse/_support/fmt.sh b/workhorse/_support/fmt.sh
new file mode 100755
index 00000000000..b319ac7e328
--- /dev/null
+++ b/workhorse/_support/fmt.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+FLAG=-w
+if [ "x$1" = xcheck ]; then
+ FLAG=-e
+fi
+
+IMPORT_RESULT=$(
+ goimports $FLAG -local "gitlab.com/gitlab-org/gitlab-workhorse" -l $(
+ find . -type f -name '*.go' | grep -v -e /_ -e /testdata/ -e '^\./\.'
+ )
+)
+
+case "x$1" in
+ xcheck)
+ if [ -n "${IMPORT_RESULT}" ]; then
+ echo >&2 "Formatting or imports need fixing: 'make fmt'"
+ echo "${IMPORT_RESULT}"
+ exit 1
+ fi
+ ;;
+ x)
+ echo "${IMPORT_RESULT}"
+ ;;
+esac
diff --git a/workhorse/_support/validate-formatting.sh b/workhorse/_support/validate-formatting.sh
deleted file mode 100755
index 190f646f8df..00000000000
--- a/workhorse/_support/validate-formatting.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-IMPORT_RESULT=$(goimports -e -local "gitlab.com/gitlab-org/gitlab-workhorse" -l "$@")
-
-if [ -n "${IMPORT_RESULT}" ]; then
- echo >&2 "Formatting or imports need fixing: 'make fmt'"
- echo "${IMPORT_RESULT}"
- exit 1
-fi
diff --git a/workhorse/cmd/gitlab-resize-image/main.go b/workhorse/cmd/gitlab-resize-image/main.go
index 662efd7306d..81288c645eb 100644
--- a/workhorse/cmd/gitlab-resize-image/main.go
+++ b/workhorse/cmd/gitlab-resize-image/main.go
@@ -7,6 +7,8 @@ import (
"strconv"
"github.com/disintegration/imaging"
+
+ "gitlab.com/gitlab-org/gitlab-workhorse/cmd/gitlab-resize-image/png"
)
func main() {
@@ -23,7 +25,12 @@ func _main() error {
return fmt.Errorf("GL_RESIZE_IMAGE_WIDTH: %w", err)
}
- src, formatName, err := image.Decode(os.Stdin)
+ pngReader, err := png.NewReader(os.Stdin)
+ if err != nil {
+ return fmt.Errorf("construct PNG reader: %w", err)
+ }
+
+ src, formatName, err := image.Decode(pngReader)
if err != nil {
return fmt.Errorf("decode: %w", err)
}
diff --git a/workhorse/cmd/gitlab-resize-image/png/reader.go b/workhorse/cmd/gitlab-resize-image/png/reader.go
new file mode 100644
index 00000000000..8229454ee3b
--- /dev/null
+++ b/workhorse/cmd/gitlab-resize-image/png/reader.go
@@ -0,0 +1,86 @@
+package png
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+)
+
+const (
+ pngMagicLen = 8
+ pngMagic = "\x89PNG\r\n\x1a\n"
+)
+
+// Reader is an io.Reader decorator that skips certain PNG chunks known to cause problems.
+// If the image stream is not a PNG, it will yield all bytes unchanged to the underlying
+// reader.
+// See also https://gitlab.com/gitlab-org/gitlab/-/issues/287614
+type Reader struct {
+ underlying io.Reader
+ chunk io.Reader
+ bytesRemaining int64
+}
+
+func NewReader(r io.Reader) (io.Reader, error) {
+ magicBytes, err := readMagic(r)
+ if err != nil {
+ return nil, err
+ }
+
+ if string(magicBytes) != pngMagic {
+ debug("Not a PNG - read file unchanged")
+ return io.MultiReader(bytes.NewReader(magicBytes), r), nil
+ }
+
+ return io.MultiReader(bytes.NewReader(magicBytes), &Reader{underlying: r}), nil
+}
+
+func (r *Reader) Read(p []byte) (int, error) {
+ for r.bytesRemaining == 0 {
+ const (
+ headerLen = 8
+ crcLen = 4
+ )
+ var header [headerLen]byte
+ _, err := io.ReadFull(r.underlying, header[:])
+ if err != nil {
+ return 0, err
+ }
+
+ chunkLen := int64(binary.BigEndian.Uint32(header[:4]))
+ if chunkType := string(header[4:]); chunkType == "iCCP" {
+ debug("!! iCCP chunk found; skipping")
+ if _, err := io.CopyN(ioutil.Discard, r.underlying, chunkLen+crcLen); err != nil {
+ return 0, err
+ }
+ continue
+ }
+
+ r.bytesRemaining = headerLen + chunkLen + crcLen
+ r.chunk = io.MultiReader(bytes.NewReader(header[:]), io.LimitReader(r.underlying, r.bytesRemaining-headerLen))
+ }
+
+ n, err := r.chunk.Read(p)
+ r.bytesRemaining -= int64(n)
+ return n, err
+}
+
+func debug(args ...interface{}) {
+ if os.Getenv("DEBUG") == "1" {
+ fmt.Fprintln(os.Stderr, args...)
+ }
+}
+
+// Consume PNG magic and proceed to reading the IHDR chunk.
+func readMagic(r io.Reader) ([]byte, error) {
+ var magicBytes []byte = make([]byte, pngMagicLen)
+ _, err := io.ReadFull(r, magicBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ return magicBytes, nil
+}
diff --git a/workhorse/cmd/gitlab-resize-image/png/reader_test.go b/workhorse/cmd/gitlab-resize-image/png/reader_test.go
new file mode 100644
index 00000000000..2b2d5df24e9
--- /dev/null
+++ b/workhorse/cmd/gitlab-resize-image/png/reader_test.go
@@ -0,0 +1,97 @@
+package png
+
+import (
+ "bytes"
+ "hash/crc64"
+ "image"
+ "io"
+ "io/ioutil"
+ "os"
+ "testing"
+
+ _ "image/jpeg" // registers JPEG format for image.Decode
+ "image/png" // registers PNG format for image.Decode
+
+ "github.com/stretchr/testify/require"
+)
+
+const (
+ goodPNG = "../../../testdata/image.png"
+ badPNG = "../../../testdata/image_bad_iccp.png"
+ strippedPNG = "../../../testdata/image_stripped_iccp.png"
+ jpg = "../../../testdata/image.jpg"
+)
+
+func TestReadImageUnchanged(t *testing.T) {
+ testCases := []struct {
+ desc string
+ imagePath string
+ imageType string
+ }{
+ {
+ desc: "image is not a PNG",
+ imagePath: jpg,
+ imageType: "jpeg",
+ },
+ {
+ desc: "image is PNG without iCCP chunk",
+ imagePath: goodPNG,
+ imageType: "png",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ requireValidImage(t, pngReader(t, tc.imagePath), tc.imageType)
+ requireStreamUnchanged(t, pngReader(t, tc.imagePath), rawImageReader(t, tc.imagePath))
+ })
+ }
+}
+
+func TestReadPNGWithBadICCPChunkDecodesAndReEncodesSuccessfully(t *testing.T) {
+ badPNGBytes, fmt, err := image.Decode(pngReader(t, badPNG))
+ require.NoError(t, err)
+ require.Equal(t, "png", fmt)
+
+ strippedPNGBytes, fmt, err := image.Decode(pngReader(t, strippedPNG))
+ require.NoError(t, err)
+ require.Equal(t, "png", fmt)
+
+ buf1 := new(bytes.Buffer)
+ buf2 := new(bytes.Buffer)
+
+ require.NoError(t, png.Encode(buf1, badPNGBytes))
+ require.NoError(t, png.Encode(buf2, strippedPNGBytes))
+
+ requireStreamUnchanged(t, buf1, buf2)
+}
+
+func pngReader(t *testing.T, path string) io.Reader {
+ r, err := NewReader(rawImageReader(t, path))
+ require.NoError(t, err)
+ return r
+}
+
+func rawImageReader(t *testing.T, path string) io.Reader {
+ f, err := os.Open(path)
+ require.NoError(t, err)
+ return f
+}
+
+func requireValidImage(t *testing.T, r io.Reader, expected string) {
+ _, fmt, err := image.Decode(r)
+ require.NoError(t, err)
+ require.Equal(t, expected, fmt)
+}
+
+func requireStreamUnchanged(t *testing.T, actual io.Reader, expected io.Reader) {
+ actualBytes, err := ioutil.ReadAll(actual)
+ require.NoError(t, err)
+ expectedBytes, err := ioutil.ReadAll(expected)
+ require.NoError(t, err)
+
+ table := crc64.MakeTable(crc64.ISO)
+ sumActual := crc64.Checksum(actualBytes, table)
+ sumExpected := crc64.Checksum(expectedBytes, table)
+ require.Equal(t, sumExpected, sumActual)
+}
diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go
index 17fea398029..988bb73f256 100644
--- a/workhorse/internal/api/api.go
+++ b/workhorse/internal/api/api.go
@@ -18,6 +18,8 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/config"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
+
"gitlab.com/gitlab-org/gitlab-workhorse/internal/secret"
)
@@ -322,7 +324,7 @@ func passResponseBack(httpResponse *http.Response, w http.ResponseWriter, r *htt
}
w.WriteHeader(httpResponse.StatusCode)
if _, err := io.Copy(w, responseBody); err != nil {
- helper.LogError(r, err)
+ log.WithRequest(r).WithError(err).Error()
}
}
diff --git a/workhorse/internal/badgateway/roundtripper.go b/workhorse/internal/badgateway/roundtripper.go
index a36cc9f4a9a..71bee12ead7 100644
--- a/workhorse/internal/badgateway/roundtripper.go
+++ b/workhorse/internal/badgateway/roundtripper.go
@@ -9,9 +9,7 @@ import (
"strings"
"time"
- "gitlab.com/gitlab-org/labkit/log"
-
- "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
)
// Error is a custom error for pretty Sentry 'issues'
@@ -42,11 +40,7 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
// instead of 500s we catch the RoundTrip error here and inject a
// 502 response.
fields := log.Fields{"duration_ms": int64(time.Since(start).Seconds() * 1000)}
- helper.LogErrorWithFields(
- r,
- &sentryError{fmt.Errorf("badgateway: failed to receive response: %v", err)},
- fields,
- )
+ log.WithRequest(r).WithFields(fields).WithError(&sentryError{fmt.Errorf("badgateway: failed to receive response: %v", err)}).Error()
injectedResponse := &http.Response{
StatusCode: http.StatusBadGateway,
diff --git a/workhorse/internal/git/archive.go b/workhorse/internal/git/archive.go
index b7575be2c02..361e1d00c0b 100644
--- a/workhorse/internal/git/archive.go
+++ b/workhorse/internal/git/archive.go
@@ -24,6 +24,7 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/senddata"
)
@@ -116,14 +117,14 @@ func (a *archive) Inject(w http.ResponseWriter, r *http.Request, sendData string
setArchiveHeaders(w, format, archiveFilename)
w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just return
if _, err := io.Copy(w, reader); err != nil {
- helper.LogError(r, &copyError{fmt.Errorf("SendArchive: copy 'git archive' output: %v", err)})
+ log.WithRequest(r).WithError(&copyError{fmt.Errorf("SendArchive: copy 'git archive' output: %v", err)}).Error()
return
}
if cacheEnabled {
err := finalizeCachedArchive(tempFile, params.ArchivePath)
if err != nil {
- helper.LogError(r, fmt.Errorf("SendArchive: finalize cached archive: %v", err))
+ log.WithRequest(r).WithError(fmt.Errorf("SendArchive: finalize cached archive: %v", err)).Error()
return
}
}
diff --git a/workhorse/internal/git/diff.go b/workhorse/internal/git/diff.go
index b1a1c17a650..51cadeecb65 100644
--- a/workhorse/internal/git/diff.go
+++ b/workhorse/internal/git/diff.go
@@ -8,6 +8,7 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/senddata"
)
@@ -39,10 +40,7 @@ func (d *diff) Inject(w http.ResponseWriter, r *http.Request, sendData string) {
}
if err := diffClient.SendRawDiff(ctx, w, request); err != nil {
- helper.LogError(
- r,
- &copyError{fmt.Errorf("diff.RawDiff: request=%v, err=%v", request, err)},
- )
+ log.WithRequest(r).WithError(&copyError{fmt.Errorf("diff.RawDiff: %v", err)}).Error()
return
}
}
diff --git a/workhorse/internal/git/format-patch.go b/workhorse/internal/git/format-patch.go
index db96029b07e..3a65fc2a7a2 100644
--- a/workhorse/internal/git/format-patch.go
+++ b/workhorse/internal/git/format-patch.go
@@ -8,6 +8,7 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/senddata"
)
@@ -39,10 +40,7 @@ func (p *patch) Inject(w http.ResponseWriter, r *http.Request, sendData string)
}
if err := diffClient.SendRawPatch(ctx, w, request); err != nil {
- helper.LogError(
- r,
- &copyError{fmt.Errorf("diff.RawPatch: request=%v, err=%v", request, err)},
- )
+ log.WithRequest(r).WithError(&copyError{fmt.Errorf("diff.RawPatch: %v", err)}).Error()
return
}
}
diff --git a/workhorse/internal/git/git-http.go b/workhorse/internal/git/git-http.go
index 5df20a68bb7..8115d833bb1 100644
--- a/workhorse/internal/git/git-http.go
+++ b/workhorse/internal/git/git-http.go
@@ -12,7 +12,7 @@ import (
"sync"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
- "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
)
const (
@@ -54,7 +54,7 @@ func postRPCHandler(a *api.API, name string, handler func(*HttpResponseWriter, *
// no-op. It never reaches net/http because GitHttpResponseWriter calls
// WriteHeader on its underlying ResponseWriter at most once.
w.WriteHeader(500)
- helper.LogError(r, fmt.Errorf("%s: %v", name, err))
+ log.WithRequest(r).WithError(fmt.Errorf("%s: %v", name, err)).Error()
}
})
}
diff --git a/workhorse/internal/git/snapshot.go b/workhorse/internal/git/snapshot.go
index eb38becbd06..bd9405a28d0 100644
--- a/workhorse/internal/git/snapshot.go
+++ b/workhorse/internal/git/snapshot.go
@@ -9,6 +9,7 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/senddata"
)
@@ -59,6 +60,6 @@ func (s *snapshot) Inject(w http.ResponseWriter, r *http.Request, sendData strin
w.WriteHeader(http.StatusOK) // Errors aren't detectable beyond this point
if _, err := io.Copy(w, reader); err != nil {
- helper.LogError(r, fmt.Errorf("SendSnapshot: copy gitaly output: %v", err))
+ log.WithRequest(r).WithError(fmt.Errorf("SendSnapshot: copy gitaly output: %v", err)).Error()
}
}
diff --git a/workhorse/internal/helper/helpers.go b/workhorse/internal/helper/helpers.go
index 5f1e5fc51b3..f9b46181579 100644
--- a/workhorse/internal/helper/helpers.go
+++ b/workhorse/internal/helper/helpers.go
@@ -20,13 +20,9 @@ import (
const NginxResponseBufferHeader = "X-Accel-Buffering"
-func LogError(r *http.Request, err error) {
- LogErrorWithFields(r, err, nil)
-}
-
-func LogErrorWithFields(r *http.Request, err error, fields log.Fields) {
+func logErrorWithFields(r *http.Request, err error, fields log.Fields) {
if err != nil {
- captureRavenError(r, err, fields)
+ CaptureRavenError(r, err, fields)
}
printError(r, err, fields)
@@ -34,12 +30,7 @@ func LogErrorWithFields(r *http.Request, err error, fields log.Fields) {
func CaptureAndFail(w http.ResponseWriter, r *http.Request, err error, msg string, code int) {
http.Error(w, msg, code)
- LogError(r, err)
-}
-
-func CaptureAndFailWithFields(w http.ResponseWriter, r *http.Request, err error, msg string, code int, fields log.Fields) {
- http.Error(w, msg, code)
- LogErrorWithFields(r, err, fields)
+ logErrorWithFields(r, err, nil)
}
func Fail500(w http.ResponseWriter, r *http.Request, err error) {
@@ -47,7 +38,8 @@ func Fail500(w http.ResponseWriter, r *http.Request, err error) {
}
func Fail500WithFields(w http.ResponseWriter, r *http.Request, err error, fields log.Fields) {
- CaptureAndFailWithFields(w, r, err, "Internal server error", http.StatusInternalServerError, fields)
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ logErrorWithFields(r, err, fields)
}
func RequestEntityTooLarge(w http.ResponseWriter, r *http.Request, err error) {
@@ -60,7 +52,7 @@ func printError(r *http.Request, err error, fields log.Fields) {
"method": r.Method,
"uri": mask.URL(r.RequestURI),
})
- entry.WithFields(fields).WithError(err).Error("error")
+ entry.WithFields(fields).WithError(err).Error()
} else {
log.WithFields(fields).WithError(err).Error("unknown error")
}
diff --git a/workhorse/internal/helper/helpers_test.go b/workhorse/internal/helper/helpers_test.go
index 6a895aded03..93d1ee33d59 100644
--- a/workhorse/internal/helper/helpers_test.go
+++ b/workhorse/internal/helper/helpers_test.go
@@ -2,13 +2,11 @@ package helper
import (
"bytes"
- "fmt"
"io"
"net/http"
"net/http/httptest"
"testing"
- "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
)
@@ -142,117 +140,3 @@ func TestFail500WorksWithNils(t *testing.T) {
require.Equal(t, http.StatusInternalServerError, w.Code)
require.Equal(t, "Internal server error\n", body.String())
}
-
-func TestLogError(t *testing.T) {
- tests := []struct {
- name string
- method string
- uri string
- err error
- logMatchers []string
- }{
- {
- name: "nil_request",
- err: fmt.Errorf("crash"),
- logMatchers: []string{
- `level=error msg="unknown error" error=crash`,
- },
- },
- {
- name: "nil_request_nil_error",
- err: nil,
- logMatchers: []string{
- `level=error msg="unknown error" error="<nil>"`,
- },
- },
- {
- name: "basic_url",
- method: "GET",
- uri: "http://localhost:3000/",
- err: fmt.Errorf("error"),
- logMatchers: []string{
- `level=error msg=error correlation_id= error=error method=GET uri="http://localhost:3000/"`,
- },
- },
- {
- name: "secret_url",
- method: "GET",
- uri: "http://localhost:3000/path?certificate=123&sharedSecret=123&import_url=the_url&my_password_string=password",
- err: fmt.Errorf("error"),
- logMatchers: []string{
- `level=error msg=error correlation_id= error=error method=GET uri="http://localhost:3000/path\?certificate=\[FILTERED\]&sharedSecret=\[FILTERED\]&import_url=\[FILTERED\]&my_password_string=\[FILTERED\]"`,
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- buf := &bytes.Buffer{}
-
- oldOut := logrus.StandardLogger().Out
- logrus.StandardLogger().Out = buf
- defer func() {
- logrus.StandardLogger().Out = oldOut
- }()
-
- var r *http.Request
- if tt.uri != "" {
- r = httptest.NewRequest(tt.method, tt.uri, nil)
- }
-
- LogError(r, tt.err)
-
- logString := buf.String()
- for _, v := range tt.logMatchers {
- require.Regexp(t, v, logString)
- }
- })
- }
-}
-
-func TestLogErrorWithFields(t *testing.T) {
- tests := []struct {
- name string
- request *http.Request
- err error
- fields map[string]interface{}
- logMatcher string
- }{
- {
- name: "nil_request",
- err: fmt.Errorf("crash"),
- fields: map[string]interface{}{"extra_one": 123},
- logMatcher: `level=error msg="unknown error" error=crash extra_one=123`,
- },
- {
- name: "nil_request_nil_error",
- err: nil,
- fields: map[string]interface{}{"extra_one": 123, "extra_two": "test"},
- logMatcher: `level=error msg="unknown error" error="<nil>" extra_one=123 extra_two=test`,
- },
- {
- name: "basic_url",
- request: httptest.NewRequest("GET", "http://localhost:3000/", nil),
- err: fmt.Errorf("error"),
- fields: map[string]interface{}{"extra_one": 123, "extra_two": "test"},
- logMatcher: `level=error msg=error correlation_id= error=error extra_one=123 extra_two=test method=GET uri="http://localhost:3000/`,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- buf := &bytes.Buffer{}
-
- oldOut := logrus.StandardLogger().Out
- logrus.StandardLogger().Out = buf
- defer func() {
- logrus.StandardLogger().Out = oldOut
- }()
-
- LogErrorWithFields(tt.request, tt.err, tt.fields)
-
- logString := buf.String()
- require.Contains(t, logString, tt.logMatcher)
- })
- }
-}
diff --git a/workhorse/internal/helper/raven.go b/workhorse/internal/helper/raven.go
index ea1d0e1f6cc..898e8ec85f8 100644
--- a/workhorse/internal/helper/raven.go
+++ b/workhorse/internal/helper/raven.go
@@ -17,7 +17,7 @@ var ravenHeaderBlacklist = []string{
"Private-Token",
}
-func captureRavenError(r *http.Request, err error, fields log.Fields) {
+func CaptureRavenError(r *http.Request, err error, fields log.Fields) {
client := raven.DefaultClient
extra := raven.Extra{}
diff --git a/workhorse/internal/imageresizer/image_resizer.go b/workhorse/internal/imageresizer/image_resizer.go
index 77318ed1c46..69e9496aec2 100644
--- a/workhorse/internal/imageresizer/image_resizer.go
+++ b/workhorse/internal/imageresizer/image_resizer.go
@@ -19,12 +19,11 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"gitlab.com/gitlab-org/labkit/correlation"
- "gitlab.com/gitlab-org/labkit/log"
- "gitlab.com/gitlab-org/labkit/mask"
"gitlab.com/gitlab-org/labkit/tracing"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/config"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/senddata"
)
@@ -203,7 +202,7 @@ func (r *Resizer) Inject(w http.ResponseWriter, req *http.Request, paramsData st
if err != nil {
// Something failed, but we can still write out the original image, so don't return early.
// We need to log this separately since the subsequent steps might add other failures.
- helper.LogErrorWithFields(req, err, *logFields(start, params, &outcome))
+ log.WithRequest(req).WithFields(logFields(start, params, &outcome)).WithError(err).Error()
}
defer helper.CleanUpProcessGroup(resizeCmd)
@@ -410,13 +409,13 @@ func (o *resizeOutcome) error(err error) {
o.err = err
}
-func logFields(startTime time.Time, params *resizeParams, outcome *resizeOutcome) *log.Fields {
+func logFields(startTime time.Time, params *resizeParams, outcome *resizeOutcome) log.Fields {
var targetWidth, contentType string
if params != nil {
targetWidth = fmt.Sprint(params.Width)
contentType = fmt.Sprint(params.ContentType)
}
- return &log.Fields{
+ return log.Fields{
"subsystem": logSystem,
"written_bytes": outcome.bytesWritten,
"duration_s": time.Since(startTime).Seconds(),
@@ -428,22 +427,17 @@ func logFields(startTime time.Time, params *resizeParams, outcome *resizeOutcome
}
func handleOutcome(w http.ResponseWriter, req *http.Request, startTime time.Time, params *resizeParams, outcome *resizeOutcome) {
- logger := log.ContextLogger(req.Context())
- fields := *logFields(startTime, params, outcome)
+ fields := logFields(startTime, params, outcome)
+ log := log.WithRequest(req).WithFields(fields)
switch outcome.status {
case statusRequestFailure:
if outcome.bytesWritten <= 0 {
helper.Fail500WithFields(w, req, outcome.err, fields)
} else {
- helper.LogErrorWithFields(req, outcome.err, fields)
+ log.WithError(outcome.err).Error(outcome.status)
}
default:
- logger.WithFields(fields).WithFields(
- log.Fields{
- "method": req.Method,
- "uri": mask.URL(req.RequestURI),
- },
- ).Printf(outcome.status)
+ log.Info(outcome.status)
}
}
diff --git a/workhorse/internal/log/logging.go b/workhorse/internal/log/logging.go
new file mode 100644
index 00000000000..c65ec07743a
--- /dev/null
+++ b/workhorse/internal/log/logging.go
@@ -0,0 +1,88 @@
+package log
+
+import (
+ "net/http"
+
+ "github.com/sirupsen/logrus"
+ "gitlab.com/gitlab-org/labkit/log"
+ "gitlab.com/gitlab-org/labkit/mask"
+ "golang.org/x/net/context"
+
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+)
+
+type Fields = log.Fields
+
+type Builder struct {
+ entry *logrus.Entry
+ fields log.Fields
+ req *http.Request
+ err error
+}
+
+func NewBuilder() *Builder {
+ return &Builder{entry: log.WithFields(nil)}
+}
+
+func WithRequest(r *http.Request) *Builder {
+ return NewBuilder().WithRequest(r)
+}
+
+func (b *Builder) WithRequest(r *http.Request) *Builder {
+ if r == nil {
+ return b
+ }
+
+ b.req = r
+ b.WithFields(log.ContextFields(r.Context())).WithFields(
+ Fields{
+ "method": r.Method,
+ "uri": mask.URL(r.RequestURI),
+ },
+ )
+ return b
+}
+
+func WithFields(fields Fields) *Builder {
+ return NewBuilder().WithFields(fields)
+}
+
+func (b *Builder) WithFields(fields Fields) *Builder {
+ b.fields = fields
+ b.entry = b.entry.WithFields(fields)
+ return b
+}
+
+func WithContextFields(ctx context.Context, fields Fields) *Builder {
+ return WithFields(log.ContextFields(ctx)).WithFields(fields)
+}
+
+func WithError(err error) *Builder {
+ return NewBuilder().WithError(err)
+}
+
+func (b *Builder) WithError(err error) *Builder {
+ b.err = err
+ b.entry = b.entry.WithError(err)
+ return b
+}
+
+func Info(args ...interface{}) {
+ NewBuilder().Info(args...)
+}
+
+func (b *Builder) Info(args ...interface{}) {
+ b.entry.Info(args...)
+}
+
+func Error(args ...interface{}) {
+ NewBuilder().Error(args...)
+}
+
+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)
+ }
+}
diff --git a/workhorse/internal/log/logging_test.go b/workhorse/internal/log/logging_test.go
new file mode 100644
index 00000000000..1cb6438532e
--- /dev/null
+++ b/workhorse/internal/log/logging_test.go
@@ -0,0 +1,157 @@
+package log
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func captureLogs(b *Builder, testFn func()) string {
+ buf := &bytes.Buffer{}
+
+ logger := b.entry.Logger
+ oldOut := logger.Out
+ logger.Out = buf
+ defer func() {
+ logger.Out = oldOut
+ }()
+
+ testFn()
+
+ return buf.String()
+}
+
+func TestLogInfo(t *testing.T) {
+ b := NewBuilder()
+ logLine := captureLogs(b, func() {
+ b.Info("an observation")
+ })
+
+ require.Regexp(t, `level=info msg="an observation"`, logLine)
+}
+
+func TestLogError(t *testing.T) {
+ b := NewBuilder()
+ logLine := captureLogs(b, func() {
+ b.WithError(fmt.Errorf("the error")).Error()
+ })
+
+ require.Regexp(t, `level=error error="the error"`, logLine)
+}
+
+func TestLogErrorWithMessage(t *testing.T) {
+ b := NewBuilder()
+ logLine := captureLogs(b, func() {
+ b.WithError(fmt.Errorf("the error")).Error("an error occurred")
+ })
+
+ require.Regexp(t, `level=error msg="an error occurred" error="the error"`, logLine)
+}
+
+func TestLogErrorWithRequest(t *testing.T) {
+ tests := []struct {
+ name string
+ method string
+ uri string
+ err error
+ logMatchers []string
+ }{
+ {
+ name: "nil_request",
+ err: fmt.Errorf("cause"),
+ logMatchers: []string{
+ `level=error error=cause`,
+ },
+ },
+ {
+ name: "nil_request_nil_error",
+ err: nil,
+ logMatchers: []string{
+ `level=error error="<nil>"`,
+ },
+ },
+ {
+ name: "basic_url",
+ method: "GET",
+ uri: "http://localhost:3000/",
+ err: fmt.Errorf("cause"),
+ logMatchers: []string{
+ `level=error correlation_id= error=cause method=GET uri="http://localhost:3000/"`,
+ },
+ },
+ {
+ name: "secret_url",
+ method: "GET",
+ uri: "http://localhost:3000/path?certificate=123&sharedSecret=123&import_url=the_url&my_password_string=password",
+ err: fmt.Errorf("cause"),
+ logMatchers: []string{
+ `level=error correlation_id= error=cause method=GET uri="http://localhost:3000/path\?certificate=\[FILTERED\]&sharedSecret=\[FILTERED\]&import_url=\[FILTERED\]&my_password_string=\[FILTERED\]"`,
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ b := NewBuilder()
+
+ var r *http.Request
+ if tt.uri != "" {
+ r = httptest.NewRequest(tt.method, tt.uri, nil)
+ }
+
+ logLine := captureLogs(b, func() {
+ b.WithRequest(r).WithError(tt.err).Error()
+ })
+
+ for _, v := range tt.logMatchers {
+ require.Regexp(t, v, logLine)
+ }
+ })
+ }
+}
+
+func TestLogErrorWithFields(t *testing.T) {
+ tests := []struct {
+ name string
+ request *http.Request
+ err error
+ fields map[string]interface{}
+ logMatcher string
+ }{
+ {
+ name: "nil_request",
+ err: fmt.Errorf("cause"),
+ fields: map[string]interface{}{"extra_one": 123},
+ logMatcher: `level=error error=cause extra_one=123`,
+ },
+ {
+ name: "nil_request_nil_error",
+ err: nil,
+ fields: map[string]interface{}{"extra_one": 123, "extra_two": "test"},
+ logMatcher: `level=error error="<nil>" extra_one=123 extra_two=test`,
+ },
+ {
+ name: "basic_url",
+ request: httptest.NewRequest("GET", "http://localhost:3000/", nil),
+ err: fmt.Errorf("cause"),
+ fields: map[string]interface{}{"extra_one": 123, "extra_two": "test"},
+ logMatcher: `level=error correlation_id= error=cause extra_one=123 extra_two=test method=GET uri="http://localhost:3000/`,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ b := NewBuilder()
+
+ logLine := captureLogs(b, func() {
+ b.WithRequest(tt.request).WithFields(tt.fields).WithError(tt.err).Error()
+ })
+
+ require.Contains(t, logLine, tt.logMatcher)
+ })
+ }
+}
diff --git a/workhorse/internal/redis/keywatcher.go b/workhorse/internal/redis/keywatcher.go
index 96e33a64b85..8f3e61b5e9f 100644
--- a/workhorse/internal/redis/keywatcher.go
+++ b/workhorse/internal/redis/keywatcher.go
@@ -10,9 +10,8 @@ import (
"github.com/jpillora/backoff"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "gitlab.com/gitlab-org/labkit/log"
- "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
)
var (
@@ -64,13 +63,13 @@ func processInner(conn redis.Conn) error {
dataStr := string(v.Data)
msg := strings.SplitN(dataStr, "=", 2)
if len(msg) != 2 {
- helper.LogError(nil, fmt.Errorf("keywatcher: invalid notification: %q", dataStr))
+ log.WithError(fmt.Errorf("keywatcher: invalid notification: %q", dataStr)).Error()
continue
}
key, value := msg[0], msg[1]
notifyChanWatchers(key, value)
case error:
- helper.LogError(nil, fmt.Errorf("keywatcher: pubsub receive: %v", v))
+ log.WithError(fmt.Errorf("keywatcher: pubsub receive: %v", v)).Error()
// Intermittent error, return nil so that it doesn't wait before reconnect
return nil
}
@@ -101,14 +100,14 @@ func Process() {
for {
conn, err := dialPubSub(workerDialFunc)
if err != nil {
- helper.LogError(nil, fmt.Errorf("keywatcher: %v", err))
+ log.WithError(fmt.Errorf("keywatcher: %v", err)).Error()
time.Sleep(redisReconnectTimeout.Duration())
continue
}
redisReconnectTimeout.Reset()
if err = processInner(conn); err != nil {
- helper.LogError(nil, fmt.Errorf("keywatcher: process loop: %v", err))
+ log.WithError(fmt.Errorf("keywatcher: process loop: %v", err)).Error()
}
}
}
diff --git a/workhorse/internal/rejectmethods/middleware_test.go b/workhorse/internal/rejectmethods/middleware_test.go
index 2921975aeef..ee5a3eb0ade 100644
--- a/workhorse/internal/rejectmethods/middleware_test.go
+++ b/workhorse/internal/rejectmethods/middleware_test.go
@@ -16,7 +16,7 @@ func TestNewMiddleware(t *testing.T) {
middleware := NewMiddleware(handler)
- acceptedMethods := []string{"GET", "HEAD", "POST", "PUT", "PATCH", "CONNECT", "OPTIONS", "TRACE"}
+ acceptedMethods := []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "CONNECT", "OPTIONS", "TRACE"}
for _, method := range acceptedMethods {
t.Run(method, func(t *testing.T) {
tmpRequest, _ := http.NewRequest(method, "/", nil)
diff --git a/workhorse/internal/sendurl/sendurl.go b/workhorse/internal/sendurl/sendurl.go
index cf3d14a2bf0..8eef6f76ff1 100644
--- a/workhorse/internal/sendurl/sendurl.go
+++ b/workhorse/internal/sendurl/sendurl.go
@@ -11,11 +11,11 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"gitlab.com/gitlab-org/labkit/correlation"
- "gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/labkit/mask"
"gitlab.com/gitlab-org/labkit/tracing"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/senddata"
)
@@ -159,7 +159,7 @@ func (e *entry) Inject(w http.ResponseWriter, r *http.Request, sendData string)
if err != nil {
sendURLRequestsRequestFailed.Inc()
- helper.LogError(r, fmt.Errorf("SendURL: Copy response: %v", err))
+ log.WithRequest(r).WithError(fmt.Errorf("SendURL: Copy response: %v", err)).Error()
return
}
diff --git a/workhorse/testdata/image_bad_iccp.png b/workhorse/testdata/image_bad_iccp.png
new file mode 100644
index 00000000000..a276dd9ee68
--- /dev/null
+++ b/workhorse/testdata/image_bad_iccp.png
Binary files differ
diff --git a/workhorse/testdata/image_stripped_iccp.png b/workhorse/testdata/image_stripped_iccp.png
new file mode 100644
index 00000000000..6ed6aee4c30
--- /dev/null
+++ b/workhorse/testdata/image_stripped_iccp.png
Binary files differ
diff --git a/yarn.lock b/yarn.lock
index 58e3a393196..e21ccf83cc9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -845,10 +845,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.5.tgz#5f6bfe6baaef360daa9b038fa78798d7a6a916b4"
integrity sha512-282Dn3SPVsUHVDhMsXgfnv+Rzog0uxecjttxGRQvxh25es1+xvkGQFsvJfkSKJ3X1kHVkSjKf+Tt5Rra+Jhp9g==
-"@gitlab/eslint-plugin@5.0.0":
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-5.0.0.tgz#502eb2bccb55d65d6310ce9ef2da76035b6fc319"
- integrity sha512-zd4pa6D2OUuhPUD2QmyhfpZh7vuXKsNHaCHJdbTb2ld+mHel5IDqdidAzAshCI9On3e6o9XieD6l7rBTpN6H/g==
+"@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==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.0.0"
@@ -858,29 +858,34 @@
eslint-plugin-import "^2.20.1"
eslint-plugin-jest "^23.8.2"
eslint-plugin-promise "^4.2.1"
- eslint-plugin-vue "^6.2.1"
+ eslint-plugin-vue "^7.4.1"
vue-eslint-parser "^7.0.0"
-"@gitlab/svgs@1.177.0":
- version "1.177.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.177.0.tgz#e481ed327a11d3834c8b1668d7485b9eefef97f5"
- integrity sha512-L7DggusgkbubNFCRIYtCuYiLx+t5Hp8y/XIxJ3RM5mqAfxkTR1KxALNLDP9CT7xWieHDhNvgcXAdamGoi0ofDQ==
+"@gitlab/favicon-overlay@2.0.0":
+ version "2.0.0"
+ 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/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@24.8.1":
- version "24.8.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-24.8.1.tgz#eb674d19aedf9c91b9a14aa7a66397d54b199fb7"
- integrity sha512-tiK1toaa8VqiGGLQCTiOJRemODusm773yVDZjWT5RtmfhsnwFXpBu6wuV3YJjPbeptuzCsX3q2a+thEswZkAZQ==
+"@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==
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.3"
+ dompurify "^2.2.6"
echarts "^4.2.1"
highlight.js "^9.13.1"
js-beautify "^1.8.8"
@@ -1124,15 +1129,15 @@
consola "^2.10.1"
node-fetch "^2.6.0"
-"@rails/actioncable@^6.0.3-3":
- version "6.0.3-3"
- resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.0.3-3.tgz#fb1a46d3d353512764d5fa3cea2f492391601b7a"
- integrity sha512-+DEbtzvD2ITPKOGBAV0lLdUvImCsHtUYfxwW7TDKOrGNEFqgbVJij7aO6ZE8a3aDPQ7NnO/MlyrPwLVeiIZRSw==
+"@rails/actioncable@^6.0.3-4":
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.0.tgz#f336f25450b1bc43b99bc60557a70b6e6bb1d3d2"
+ integrity sha512-eDgy+vcKN9RIzxmMBfSAe77rTj2cp6kJALiVQyKrW2O9EK2MdostOmP+99At/Dit3ur5+77NVnruxD7y14ZYFA==
-"@rails/ujs@^6.0.3-2":
- version "6.0.3-2"
- resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.0.3-2.tgz#e14c1f29086858215ce7ccd9ad6d8888c458b4a3"
- integrity sha512-WcpIEftNCfGDEgk6KerOugiet75Mir5q/HT1yt3dDhpBI91BaZ15lfSQIsZwMw2nyeDz9A9QBz8dAFAd4gXIzg==
+"@rails/ujs@^6.0.3-4":
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.0.tgz#9a48df6511cb2b472c9f596c1f37dc0af022e751"
+ integrity sha512-kQNKyM4ePAc4u9eR1c4OqrbAHH+3SJXt++8izIjeaZeg+P7yBtgoF/dogMD/JPPowNC74ACFpM/4op0Ggp/fPw==
"@sindresorhus/is@^0.14.0":
version "0.14.0"
@@ -1304,10 +1309,10 @@
jest-diff "^25.2.1"
pretty-format "^25.2.1"
-"@types/json-schema@^7.0.3":
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
- integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
+"@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/minimatch@*":
version "3.0.3"
@@ -1423,10 +1428,10 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
-"@vue/test-utils@1.0.0-beta.30":
- version "1.0.0-beta.30"
- resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.30.tgz#d5f26d1e2411fdb7fa7fdedb61b4b4ea4194c49d"
- integrity sha512-Wyvcha9fNk8+kzTDwb3xWGjPkCPzHSYSwKP6MplrPTG/auhqoad7JqUEceZLc6u7AU4km2pPQ8/m9s0RgCZ0NA==
+"@vue/test-utils@1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.1.2.tgz#fdb487448dceefeaf3d01d465f7c836a3d666dbc"
+ integrity sha512-utbIL7zn9c+SjhybPwh48lpWCiluFCbP1yyRNAy1fQsw/6hiNFioaWy05FoVAFIZXC5WwBf+5r4ypfM1j/nI4A==
dependencies:
dom-event-types "^1.0.0"
lodash "^4.17.15"
@@ -1634,10 +1639,10 @@ acorn-globals@^6.0.0:
acorn "^7.1.1"
acorn-walk "^7.1.1"
-acorn-jsx@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384"
- integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==
+acorn-jsx@^5.2.0:
+ 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"
@@ -1654,7 +1659,7 @@ acorn@^6.0.7, acorn@^6.2.1, acorn@^6.3.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e"
integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==
-acorn@^7.1.0, acorn@^7.1.1:
+acorn@^7.1.1:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
@@ -1684,15 +1689,15 @@ ajv-errors@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59"
integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=
-ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
- version "3.4.1"
- resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
- integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
+ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3:
- version "6.12.5"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da"
- integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
@@ -3057,7 +3062,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@2, commander@^2.10.0, commander@^2.16.0, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@~2.20.0:
+commander@2, commander@^2.10.0, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@~2.20.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
@@ -4186,10 +4191,10 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"
-dompurify@^2.2.3, dompurify@^2.2.4:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.4.tgz#a98cd182b729bdd8715c3eb7a8bf8eafb2ff7410"
- integrity sha512-jE21SelIgWrGKoXGfGPA524Zt1IJFBnktwfFMHDlEYRx5FZOdc+4eEH9mkA6PuhExrq3HVpJnY8hMYUzAMl0OA==
+dompurify@^2.2.6:
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.6.tgz#54945dc5c0b45ce5ae228705777e8e59d7b2edc4"
+ integrity sha512-7b7ZArhhH0SP6W2R9cqK6RjaU82FZ2UPM7RO8qN1b1wyvC/NY1FNWcX1Pu00fFOAnzEORtwXe4bPaClg6pUybQ==
domutils@^1.5.1:
version "1.6.2"
@@ -4626,14 +4631,15 @@ eslint-plugin-promise@^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@^6.2.1:
- version "6.2.2"
- resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-6.2.2.tgz#27fecd9a3a24789b0f111ecdd540a9e56198e0fe"
- integrity sha512-Nhc+oVAHm0uz/PkJAWscwIT4ijTrK5fqNqz9QB1D35SbbuMG1uB6Yr5AJpvPSWg+WOw7nYNswerYh0kOk64gqQ==
+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==
dependencies:
+ eslint-utils "^2.1.0"
natural-compare "^1.4.0"
- semver "^5.6.0"
- vue-eslint-parser "^7.0.0"
+ semver "^7.3.2"
+ vue-eslint-parser "^7.3.0"
eslint-rule-composer@^0.3.0:
version "0.3.0"
@@ -4663,10 +4669,10 @@ eslint-utils@^1.4.3:
dependencies:
eslint-visitor-keys "^1.1.0"
-eslint-utils@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd"
- integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==
+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"
+ integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
dependencies:
eslint-visitor-keys "^1.1.0"
@@ -4718,13 +4724,13 @@ eslint@^6.8.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-espree@^6.1.2:
- version "6.1.2"
- resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d"
- integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==
+espree@^6.1.2, 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==
dependencies:
- acorn "^7.1.0"
- acorn-jsx "^5.1.0"
+ acorn "^7.1.1"
+ acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.1.0"
esprima@^4.0.0, esprima@^4.0.1:
@@ -5009,6 +5015,11 @@ fast-levenshtein@~2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+fast-mersenne-twister@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/fast-mersenne-twister/-/fast-mersenne-twister-1.0.2.tgz#5ead7caf3ace592a5789d11767732bd81cbaaa56"
+ integrity sha512-IaClPxsoBu3MxGpcURyjV8otT5Bj4ARoK0KBCJGnEVnD1A/qclL5eIeYiUuwG/WWJPxL1jlK61HTm2T6SBmvBQ==
+
fault@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa"
@@ -7476,11 +7487,11 @@ karma@^4.2.0:
useragent "2.3.0"
katex@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/katex/-/katex-0.10.0.tgz#da562e5d0d5cc3aa602e27af8a9b8710bfbce765"
- integrity sha512-/WRvx+L1eVBrLwX7QzKU1dQuaGnE7E8hDvx3VWfZh9HbMiCfsKWJNnYZ0S8ZMDAfAyDSofdyXIrH/hujF1fYXg==
+ version "0.10.2"
+ resolved "https://registry.yarnpkg.com/katex/-/katex-0.10.2.tgz#39973edbb65eda5b6f9e7f41648781e557dd4932"
+ integrity sha512-cQOmyIRoMloCoSIOZ1+gEwsksdJZ1EW4SWm3QzxSza/QsnZr6D4U1V9S4q+B/OLm2OQ8TCBecQ8MaIfnScI7cw==
dependencies:
- commander "^2.16.0"
+ commander "^2.19.0"
keyv@^3.0.0:
version "3.1.0"
@@ -7654,6 +7665,15 @@ loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2
emojis-list "^3.0.0"
json5 "^1.0.1"
+loader-utils@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
+ integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^3.0.0"
+ json5 "^2.1.2"
+
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -8045,6 +8065,11 @@ marked@^0.3.12, marked@~0.3.6:
resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790"
integrity sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==
+mathjax@3:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-3.1.2.tgz#95c0d45ce2330ef7b6a815cebe7d61ecc26bbabd"
+ integrity sha512-BojKspBv4nNWzO1wC6VEI+g9gHDOhkaGHGgLxXkasdU4pwjdO5AXD5M/wcLPkXYPjZ/N+6sU8rjQTlyvN2cWiQ==
+
mathml-tag-names@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc"
@@ -8176,11 +8201,6 @@ mermaid@^8.5.2:
moment-mini "^2.22.1"
scope-css "^1.2.1"
-mersenne-twister@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a"
- integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o=
-
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
@@ -9546,16 +9566,21 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
-prettier@1.18.2, prettier@^1.18.2:
- version "1.18.2"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
- integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
-
prettier@2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
+prettier@2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
+ integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
+
+prettier@^1.18.2:
+ version "1.18.2"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
+ integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
+
pretty-format@^25.2.1, pretty-format@^25.5.0:
version "25.5.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a"
@@ -10528,13 +10553,14 @@ 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.6.4:
- version "2.6.4"
- resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53"
- integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==
+schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.1, 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==
dependencies:
- ajv "^6.10.2"
- ajv-keywords "^3.4.1"
+ "@types/json-schema" "^7.0.5"
+ ajv "^6.12.4"
+ ajv-keywords "^3.5.2"
scope-css@^1.2.1:
version "1.2.1"
@@ -11299,13 +11325,13 @@ strip-json-comments@~2.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-style-loader@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.3.tgz#9e826e69c683c4d9bf9db924f85e9abb30d5e200"
- integrity sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw==
+style-loader@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e"
+ integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==
dependencies:
- loader-utils "^1.2.3"
- schema-utils "^2.6.4"
+ loader-utils "^2.0.0"
+ schema-utils "^2.7.0"
style-search@^0.1.0:
version "0.1.0"
@@ -12377,15 +12403,15 @@ vue-apollo@^3.0.3:
serialize-javascript "^2.1.0"
throttle-debounce "^2.1.0"
-vue-eslint-parser@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.0.0.tgz#a4ed2669f87179dedd06afdd8736acbb3a3864d6"
- integrity sha512-yR0dLxsTT7JfD2YQo9BhnQ6bUTLsZouuzt9SKRP7XNaZJV459gvlsJo4vT2nhZ/2dH9j3c53bIx9dnqU2prM9g==
+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==
dependencies:
debug "^4.1.1"
eslint-scope "^5.0.0"
eslint-visitor-keys "^1.1.0"
- espree "^6.1.2"
+ espree "^6.2.1"
esquery "^1.0.1"
lodash "^4.17.15"
@@ -12411,10 +12437,10 @@ vue-jest@4.0.0-rc.0:
source-map "0.5.6"
ts-jest "26.x"
-vue-loader@^15.9.5:
- version "15.9.5"
- resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.5.tgz#7a960dc420a3439deaacdda038fdcdbf7c432706"
- integrity sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==
+vue-loader@^15.9.6:
+ version "15.9.6"
+ resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
+ integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==
dependencies:
"@vue/component-compiler-utils" "^3.1.0"
hash-sum "^1.0.2"